diff options
| author | Amlal <amlal@el-mahrouss-logic.com> | 2024-09-22 17:46:11 +0200 |
|---|---|---|
| committer | Amlal <amlal@el-mahrouss-logic.com> | 2024-09-22 17:46:11 +0200 |
| commit | 8719b4570a2d10dd49a0d3a47e24f5c55bdda85e (patch) | |
| tree | ba095740888f3768e08b2ea058b0ea6da2d0403d /dev/zka/KernelKit | |
| parent | 45944b3d2dab04b763fcc6d10164fe8069e60b08 (diff) | |
:boom: A big refactor on the filesystem structure.
Signed-off-by: Amlal <amlal@el-mahrouss-logic.com>
Diffstat (limited to 'dev/zka/KernelKit')
35 files changed, 3113 insertions, 0 deletions
diff --git a/dev/zka/KernelKit/CodeMgr.hxx b/dev/zka/KernelKit/CodeMgr.hxx new file mode 100644 index 00000000..c8f9cca9 --- /dev/null +++ b/dev/zka/KernelKit/CodeMgr.hxx @@ -0,0 +1,31 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + + File: CodeMgr.hpp + Purpose: Code Mgr and Shared Objects. + + Revision History: + + 30/01/24: Added file (amlel) + 3/8/24: Add UPP struct. + +------------------------------------------- */ + +#pragma once + +#include <KernelKit/PECodeMgr.hxx> +#include <KernelKit/PEFCodeMgr.hxx> +#include <KernelKit/IPEFDLLObject.hxx> + +namespace Kernel +{ + /// @brief Main process entrypoint. + typedef void (*MainKind)(void); + + /// @brief Executes a new process from a function. Kernel code only. + /// @note This sets up a new stack, anything on the main function that calls the Kernel will not be accessible. + /// @param main the start of the process. + /// @return if the process was started or not. + bool sched_execute_thread(MainKind main, const Char* process_name) noexcept; +} // namespace Kernel diff --git a/dev/zka/KernelKit/DebugOutput.hxx b/dev/zka/KernelKit/DebugOutput.hxx new file mode 100644 index 00000000..162e2ed4 --- /dev/null +++ b/dev/zka/KernelKit/DebugOutput.hxx @@ -0,0 +1,196 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include <KernelKit/DeviceMgr.hxx> +#include <CompilerKit/CompilerKit.hxx> +#include <NewKit/OwnPtr.hxx> +#include <NewKit/Stream.hxx> + +#define kDebugMaxPorts 16 + +#define kDebugUnboundPort 0x0FEED + +#define kDebugMag0 'N' +#define kDebugMag1 'D' +#define kDebugMag2 'B' +#define kDebugMag3 'G' + +#define kDebugSourceFile 0 +#define kDebugLine 33 +#define kDebugTeam 43 +#define kDebugEOP 49 + +namespace Kernel +{ + class TerminalDevice; + + inline TerminalDevice end_line(); + inline TerminalDevice number(const Long& x); + inline TerminalDevice hex_number(const Long& x); + + // @brief Emulates a VT100 terminal. + class TerminalDevice final : public DeviceInterface<const Char*> + { + public: + TerminalDevice(void (*print)(const Char*), void (*get)(const Char*)) + : DeviceInterface<const Char*>(print, get) + { + } + + virtual ~TerminalDevice() = default; + + /// @brief returns device name (terminal name) + /// @return string type (const Char*) + virtual const Char* Name() const override + { + return ("TerminalDevice"); + } + + ZKA_COPY_DEFAULT(TerminalDevice); + + STATIC TerminalDevice The() noexcept; + }; + + inline TerminalDevice end_line() + { + TerminalDevice selfTerm = TerminalDevice::The(); + + selfTerm.operator<<("\r"); + return selfTerm; + } + + inline TerminalDevice carriage_return() + { + TerminalDevice selfTerm = TerminalDevice::The(); + + selfTerm.operator<<("\r"); + return selfTerm; + } + + inline TerminalDevice tabulate() + { + TerminalDevice selfTerm = TerminalDevice::The(); + + selfTerm.operator<<("\t"); + return selfTerm; + } + + /// @brief emulate a terminal bell, like the VT100 does. + inline TerminalDevice bell() + { + TerminalDevice selfTerm = TerminalDevice::The(); + + selfTerm.operator<<("\a"); + return selfTerm; + } + + namespace Detail + { + inline TerminalDevice _write_number(const Long& x, TerminalDevice& term) + { + UInt64 y = (x > 0 ? x : -x) / 10; + UInt64 h = (x > 0 ? x : -x) % 10; + + if (y) + _write_number(y, term); + + /* fail if the number is not base-10 */ + if (h > 10) + { + _write_number('?', term); + return term; + } + + if (y < 0) + y = -y; + + const Char cNumbers[11] = "0123456789"; + + Char buf[2]; + buf[0] = cNumbers[h]; + buf[1] = 0; + + term.operator<<(buf); + return term; + } + + inline TerminalDevice _write_number_hex(const Long& x, TerminalDevice& term) + { + UInt64 y = (x > 0 ? x : -x) / 16; + UInt64 h = (x > 0 ? x : -x) % 16; + + if (y) + _write_number_hex(y, term); + + /* fail if the hex number is not base-16 */ + if (h > 15) + { + _write_number_hex('?', term); + return term; + } + + if (y < 0) + y = -y; + + const Char cNumbers[17] = "0123456789ABCDEF"; + + Char buf[2]; + buf[0] = cNumbers[h]; + buf[1] = 0; + + term.operator<<(buf); + return term; + } + } // namespace Detail + + inline TerminalDevice hex_number(const Long& x) + { + TerminalDevice selfTerm = TerminalDevice::The(); + + Detail::_write_number_hex(x, selfTerm); + selfTerm.operator<<("h"); + + return selfTerm; + } + + inline TerminalDevice number(const Long& x) + { + TerminalDevice selfTerm = TerminalDevice::The(); + + Detail::_write_number(x, selfTerm); + + return selfTerm; + } + + inline TerminalDevice get_console_in(Char* buf) + { + TerminalDevice selfTerm = TerminalDevice::The(); + + selfTerm >> buf; + + return selfTerm; + } + + typedef Char rt_debug_type[255]; + + class DebuggerPortHeader final + { + public: + Int16 fPort[kDebugMaxPorts]; + Int16 fBoundCnt; + }; +} // namespace Kernel + +#ifdef kcout +#undef kcout +#endif // ifdef kcout + +#define kcout \ + (Kernel::TerminalDevice::The() << "\e[0;31m [ " << __FILE__ << ": LINE: " << Kernel::number(__LINE__)); \ + (Kernel::TerminalDevice::The() << " ] \e[0m" << ": ") +#define endl Kernel::TerminalDevice::The() << Kernel::end_line() diff --git a/dev/zka/KernelKit/Defines.hxx b/dev/zka/KernelKit/Defines.hxx new file mode 100644 index 00000000..e76b1b2f --- /dev/null +++ b/dev/zka/KernelKit/Defines.hxx @@ -0,0 +1,11 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include <NewKit/Defines.hxx> + +#define KERNELKIT_VERSION "1.02" diff --git a/dev/zka/KernelKit/DeviceMgr.hxx b/dev/zka/KernelKit/DeviceMgr.hxx new file mode 100644 index 00000000..473af601 --- /dev/null +++ b/dev/zka/KernelKit/DeviceMgr.hxx @@ -0,0 +1,132 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +/* ------------------------------------------- + + Revision History: + + 31/01/24: Add kDeviceCnt (amlel) + + ------------------------------------------- */ + +#pragma once + +/* Device manager. */ +/* @file KernelKit/DeviceMgr.hpp */ +/* @brief Device abstraction and I/O buffer. */ + +#include <NewKit/ErrorOr.hxx> +#include <NewKit/Ref.hxx> + +#define cDevicePath "\\Mount\\" + +// Last Rev +// Wed, Apr 3, 2024 9:09:41 AM + +namespace Kernel +{ + template <typename T> + class DeviceInterface; + + template <typename T> + class DeviceInterface + { + public: + explicit DeviceInterface(void (*Out)(T), void (*In)(T)) + : fOut(Out), fIn(In) + { + } + + virtual ~DeviceInterface() = default; + + public: + DeviceInterface& operator=(const DeviceInterface<T>&) = default; + DeviceInterface(const DeviceInterface<T>&) = default; + + public: + virtual DeviceInterface<T>& operator<<(T Data) + { + fOut(Data); + return *this; + } + + virtual DeviceInterface<T>& operator>>(T Data) + { + fIn(Data); + return *this; + } + + virtual const char* Name() const + { + return "DeviceInterface"; + } + + operator bool() + { + return fOut && fIn; + } + + Bool operator!() + { + return !fOut || !fIn; + } + + private: + Void (*fOut)(T Data) = {nullptr}; + Void (*fIn)(T Data) = {nullptr}; + }; + + /// + /// @brief Input Output Buffer + /// Used mainly to communicate between hardware. + /// + template <typename T> + class IOBuf final + { + public: + explicit IOBuf(T Dat) + : fData(Dat) + { + // at least pass something valid when instancating this struct. + MUST_PASS(Dat); + } + + IOBuf& operator=(const IOBuf<T>&) = default; + IOBuf(const IOBuf<T>&) = default; + + ~IOBuf() = default; + + public: + template <typename R> + R operator->() const + { + return fData; + } + + template <typename R> + R& operator[](Size index) const + { + return fData[index]; + } + + private: + T fData; + }; + + ///! @brief Device enum types. + enum + { + kDeviceTypeIDE, + kDeviceTypeEthernet, + kDeviceTypeWiFi, + kDeviceTypeRS232, + kDeviceTypeSCSI, + kDeviceTypeSHCI, + kDeviceTypeUSB, + kDeviceTypeMedia, + kDeviceTypeCount, + }; +} // namespace Kernel diff --git a/dev/zka/KernelKit/DriveMgr.hxx b/dev/zka/KernelKit/DriveMgr.hxx new file mode 100644 index 00000000..e2e0bc3a --- /dev/null +++ b/dev/zka/KernelKit/DriveMgr.hxx @@ -0,0 +1,152 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef __INC_DRIVE_MANAGER_HXX__ +#define __INC_DRIVE_MANAGER_HXX__ + +#include <KernelKit/UserProcessScheduler.hxx> +#include <CompilerKit/CompilerKit.hxx> +#include <KernelKit/DebugOutput.hxx> +#include <KernelKit/DeviceMgr.hxx> +#include <KernelKit/LPC.hxx> +#include <NewKit/Defines.hxx> +#include <NewKit/String.hxx> + +#define kDriveMgrCount (4U) + +#define kDriveInvalidID (-1) +#define kDriveNameLen (32) + +#define DrvSectorCnt(SIZE, SECTOR_SZ) (((SIZE) + (SECTOR_SZ)) / (SECTOR_SZ)) + +namespace Kernel +{ + enum + { + kInvalidDrive = -1, + kBlockDevice = 0xAD, + kMassStorage = 0xDA, + kFloppyDisc = 0xCD, + kOpticalDisc = 0xDC, // CD-ROM/DVD-ROM/Blu-Ray + /// combine with below. + kReadOnly = 0x10, // Read only drive + kEPMDrive = 0x11, // Explicit Partition Map. + kEPTDrive = 0x12, // ESP w/ EPM partition. + kMBRDrive = 0x13, // IBM PC classic partition scheme + kDriveCnt = 9, + }; + + typedef Int64 rt_drive_id_type; + + /// @brief Media drive trait type. + struct DriveTrait final + { + Char fName[kDriveNameLen]; // /System, /Boot, //./Devices/USB... + Int32 fKind; // fMassStorage, fFloppy, fOpticalDisc. + rt_drive_id_type fId; // Drive id. + Int32 fFlags; // fReadOnly, fXPMDrive, fXPTDrive + + /// @brief Packet drive (StorageKit compilant.) + struct DrivePacket final + { + VoidPtr fPacketContent; //! packet body. + Char fPacketMime[kDriveNameLen]; //! identify what we're sending. + SizeT fPacketSize; //! packet size + UInt32 fPacketCRC32; //! sanity crc, in case if good is set to false + Boolean fPacketGood; + Lba fLba; + } fPacket; + + Void (*fInput)(DrivePacket* packetPtr); + Void (*fOutput)(DrivePacket* packetPtr); + Void (*fVerify)(DrivePacket* packetPtr); + Void (*fInit)(DrivePacket* packetPtr); + const Char* (*fDriveKind)(Void); + }; + + ///! drive as a device. + typedef DriveTrait* DriveTraitPtr; + + /** + * @brief Mounted drives interface. + * @note This class has all of it's drive set to nullptr, allocate them using + * GetAddressOf(index). + */ + class MountpointInterface final + { + public: + explicit MountpointInterface() = default; + ~MountpointInterface() = default; + + ZKA_COPY_DEFAULT(MountpointInterface); + + public: + DriveTrait& A() + { + return mA; + } + DriveTrait& B() + { + return mB; + } + DriveTrait& C() + { + return mC; + } + DriveTrait& D() + { + return mD; + } + + DriveTraitPtr GetAddressOf(Int32 index) + { + ErrLocal() = kErrorSuccess; + + switch (index) + { + case 0: + return &mA; + case 1: + return &mB; + case 2: + return &mC; + case 3: + return &mD; + default: { + ErrLocal() = kErrorNoSuchDisk; + kcout << "No such disk.\n"; + + break; + } + } + + return nullptr; + } + + private: + DriveTrait mA, mB, mC, mD; + }; + + /// @brief Unimplemented drive. + /// @param pckt + /// @return + Void io_drv_unimplemented(DriveTrait::DrivePacket* pckt); + + /// @brief Gets the drive kind (ATA, SCSI, AHCI...) + /// @param + /// @return the drive kind (ATA, Flash, NVM) + const Char* io_drive_kind(Void); + + /// @brief Makes a new drive. + /// @return the new drive as a trait. + DriveTrait io_construct_drive(void) noexcept; + + /// @brief Fetches the main drive. + /// @return the new drive as a trait. + DriveTrait io_construct_main_drive(void) noexcept; +} // namespace Kernel + +#endif /* ifndef __INC_DRIVE_MANAGER_HXX__ */ diff --git a/dev/zka/KernelKit/FileMgr.hxx b/dev/zka/KernelKit/FileMgr.hxx new file mode 100644 index 00000000..cd557485 --- /dev/null +++ b/dev/zka/KernelKit/FileMgr.hxx @@ -0,0 +1,420 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + + File: FileMgr.hxx + Purpose: Kernel file manager. + +------------------------------------------- */ + +/* ------------------------------------------- + + Revision History: + + 31/01/24: Update documentation (amlel) + 05/07/24: NeFS support, and fork support, updated constants and specs + as well. + + ------------------------------------------- */ + +#pragma once + +#ifdef __FSKIT_USE_NEFS__ +#include <FSKit/NeFS.hxx> +#endif // __FSKIT_USE_NEFS__ + +#include <CompilerKit/CompilerKit.hxx> +#include <HintKit/CompilerHint.hxx> +#include <KernelKit/LPC.hxx> +#include <KernelKit/DebugOutput.hxx> +#include <NewKit/Stream.hxx> +#include <NewKit/ErrorOr.hxx> +#include <KernelKit/Heap.hxx> +#include <NewKit/Ref.hxx> + +/// @brief Filesystem manager, abstraction over mounted filesystem. +/// Works like the VFS or IFS. + +#define cRestrictR "r" +#define cRestrictRB "rb" +#define cRestrictW "w" +#define cRestrictWB "rw" +#define cRestrictRWB "rwb" + +#define cRestrictMax 5 + +#define node_cast(PTR) reinterpret_cast<Kernel::NodePtr>(PTR) + +/** + @note Refer to first enum. +*/ +#define cFileOpsCount 4 +#define cFileMimeGeneric "n-application-kind/all" + +/** @brief invalid position. (n-pos) */ +#define kNPos (SizeT)(-1); + +namespace Kernel +{ + enum + { + cFileWriteAll = 100, + cFileReadAll = 101, + cFileReadChunk = 102, + cFileWriteChunk = 103, + cFileIOCnt = (cFileWriteChunk - cFileWriteAll) + 1, + // file flags + cFileFlagRsrc = 104, + cFileFlagData = 105, + }; + + typedef VoidPtr NodePtr; + + /** + @brief Filesystem Mgr Interface class + @brief Used to provide common I/O for a specific filesystem. +*/ + class IFilesystemMgr + { + public: + explicit IFilesystemMgr() = default; + virtual ~IFilesystemMgr() = default; + + public: + ZKA_COPY_DEFAULT(IFilesystemMgr); + + public: + /// @brief Mounts a new filesystem into an active state. + /// @param interface the filesystem interface + /// @return + static bool Mount(IFilesystemMgr* interface); + + /// @brief Unmounts the active filesystem + /// @return + static IFilesystemMgr* Unmount(); + + /// @brief Getter, gets the active filesystem. + /// @return + static IFilesystemMgr* GetMounted(); + + public: + virtual NodePtr Create(_Input const Char* path) = 0; + virtual NodePtr CreateAlias(_Input const Char* path) = 0; + virtual NodePtr CreateDirectory(_Input const Char* path) = 0; + virtual NodePtr CreateSwapFile(const Char* path) = 0; + + public: + virtual bool Remove(_Input const Char* path) = 0; + + public: + virtual NodePtr Open(_Input const Char* path, _Input const Char* r) = 0; + + public: + virtual Void Write(_Input NodePtr node, _Input VoidPtr data, _Input Int32 flags, _Input SizeT size) = 0; + + virtual _Output VoidPtr Read(_Input NodePtr node, + _Input Int32 flags, + _Input SizeT sz) = 0; + + virtual Void Write(_Input const Char* name, + _Input NodePtr node, + _Input VoidPtr data, + _Input Int32 flags, + _Input SizeT size) = 0; + + virtual _Output VoidPtr Read(_Input const Char* name, + _Input NodePtr node, + _Input Int32 flags, + _Input SizeT sz) = 0; + + public: + virtual bool Seek(_Input NodePtr node, _Input SizeT off) = 0; + + public: + virtual SizeT Tell(_Input NodePtr node) = 0; + virtual bool Rewind(_Input NodePtr node) = 0; + }; + +#ifdef __FSKIT_USE_NEFS__ + /** + * @brief Based of IFilesystemMgr, takes care of managing NeFS + * disks. + */ + class NeFileSystemMgr final : public IFilesystemMgr + { + public: + explicit NeFileSystemMgr(); + ~NeFileSystemMgr() override; + + public: + ZKA_COPY_DEFAULT(NeFileSystemMgr); + + public: + NodePtr Create(const Char* path) override; + NodePtr CreateAlias(const Char* path) override; + NodePtr CreateDirectory(const Char* path) override; + NodePtr CreateSwapFile(const Char* path) override; + + public: + bool Remove(_Input const Char* path) override; + NodePtr Open(_Input const Char* path, _Input const Char* r) override; + Void Write(_Input NodePtr node, _Input VoidPtr data, _Input Int32 flags, _Input SizeT sz) override; + VoidPtr Read(_Input NodePtr node, _Input Int32 flags, _Input SizeT sz) override; + bool Seek(_Input NodePtr node, _Input SizeT off) override; + SizeT Tell(_Input NodePtr node) override; + bool Rewind(_Input NodePtr node) override; + + Void Write(_Input const Char* name, + _Input NodePtr node, + _Input VoidPtr data, + _Input Int32 flags, + _Input SizeT size) override; + + _Output VoidPtr Read(_Input const Char* name, + _Input NodePtr node, + _Input Int32 flags, + _Input SizeT sz) override; + + public: + /// @brief Get NeFS parser class. + /// @return The filesystem parser class. + NeFSParser* GetParser() noexcept; + + private: + NeFSParser* fImpl{nullptr}; + }; + +#endif // ifdef __FSKIT_USE_NEFS__ + + /** + * Usable FileStream + * @tparam Encoding file encoding (char, wchar_t...) + * @tparam FSClass Filesystem contract who takes care of it. + */ + template <typename Encoding = Char, + typename FSClass = IFilesystemMgr> + class FileStream final + { + public: + explicit FileStream(const Encoding* path, const Encoding* restrict_type); + ~FileStream(); + + public: + FileStream& operator=(const FileStream&); + FileStream(const FileStream&); + + public: + ErrorOr<Int64> WriteAll(const VoidPtr data) noexcept + { + if (this->fFileRestrict != eRestrictReadWrite && + this->fFileRestrict != eRestrictReadWriteBinary && + this->fFileRestrict != eRestrictWrite && + this->fFileRestrict != eRestrictWriteBinary) + return ErrorOr<Int64>(kErrorInvalidData); + + if (data == nullptr) + return ErrorOr<Int64>(kErrorInvalidData); + + auto man = FSClass::GetMounted(); + + if (man) + { + man->Write(fFile, data, cFileWriteAll); + return ErrorOr<Int64>(0); + } + + return ErrorOr<Int64>(kErrorInvalidData); + } + + VoidPtr ReadAll() noexcept + { + if (this->fFileRestrict != eRestrictReadWrite && + this->fFileRestrict != eRestrictReadWriteBinary && + this->fFileRestrict != eRestrictRead && + this->fFileRestrict != eRestrictReadBinary) + return nullptr; + + auto man = FSClass::GetMounted(); + + if (man) + { + VoidPtr ret = man->Read(fFile, cFileReadAll, 0); + return ret; + } + + return nullptr; + } + + ErrorOr<Int64> WriteAll(const Char* fName, const VoidPtr data) noexcept + { + if (this->fFileRestrict != eRestrictReadWrite && + this->fFileRestrict != eRestrictReadWriteBinary && + this->fFileRestrict != eRestrictWrite && + this->fFileRestrict != eRestrictWriteBinary) + return ErrorOr<Int64>(kErrorInvalidData); + + if (data == nullptr) + return ErrorOr<Int64>(kErrorInvalidData); + + auto man = FSClass::GetMounted(); + + if (man) + { + man->Write(fName, fFile, data, cFileWriteAll); + return ErrorOr<Int64>(0); + } + + return ErrorOr<Int64>(kErrorInvalidData); + } + + VoidPtr Read(const Char* fName) noexcept + { + if (this->fFileRestrict != eRestrictReadWrite && + this->fFileRestrict != eRestrictReadWriteBinary && + this->fFileRestrict != eRestrictRead && + this->fFileRestrict != eRestrictReadBinary) + return nullptr; + + auto man = FSClass::GetMounted(); + + if (man) + { + VoidPtr ret = man->Read(fName, fFile, cFileReadAll, 0); + return ret; + } + + return nullptr; + } + + VoidPtr Read(SizeT offset, SizeT sz) + { + if (this->fFileRestrict != eRestrictReadWrite && + this->fFileRestrict != eRestrictReadWriteBinary && + this->fFileRestrict != eRestrictRead && + this->fFileRestrict != eRestrictReadBinary) + return nullptr; + + auto man = FSClass::GetMounted(); + + if (man) + { + man->Seek(fFile, offset); + auto ret = man->Read(fFile, cFileReadChunk, sz); + + return ret; + } + + return nullptr; + } + + Void Write(SizeT offset, voidPtr data, SizeT sz) + { + if (this->fFileRestrict != eRestrictReadWrite && + this->fFileRestrict != eRestrictReadWriteBinary && + this->fFileRestrict != eRestrictWrite && + this->fFileRestrict != eRestrictWriteBinary) + return; + + auto man = FSClass::GetMounted(); + + if (man) + { + man->Seek(fFile, offset); + man->Write(fFile, data, sz, cFileReadChunk); + } + } + + public: + /// @brief Leak node pointer. + /// @return The node pointer. + NodePtr Leak() + { + return fFile; + } + + /// @brief Leak MIME. + /// @return The MIME. + Char* MIME() noexcept + { + return const_cast<char*>(fMime); + } + + enum + { + eRestrictRead, + eRestrictReadBinary, + eRestrictWrite, + eRestrictWriteBinary, + eRestrictReadWrite, + eRestrictReadWriteBinary, + }; + + private: + NodePtr fFile{nullptr}; + Int32 fFileRestrict{}; + const Char* fMime{cFileMimeGeneric}; + }; + + using FileStreamUTF8 = FileStream<Char>; + using FileStreamUTF16 = FileStream<WideChar>; + + typedef UInt64 CursorType; + + /// @brief constructor + template <typename Encoding, typename Class> + FileStream<Encoding, Class>::FileStream(const Encoding* path, + const Encoding* restrict_type) + : fFile(Class::GetMounted()->Open(path, restrict_type)) + { + static const auto cLength = 255; + + /// @brief restrict information about the file descriptor. + struct RESTRICT_MAP final + { + Char fRestrict[cLength]; + Int32 fMappedTo; + }; + + const SizeT cRestrictCount = cRestrictMax; + const RESTRICT_MAP cRestrictList[] = { + { + .fRestrict = cRestrictR, + .fMappedTo = eRestrictRead, + }, + { + .fRestrict = cRestrictRB, + .fMappedTo = eRestrictReadBinary, + }, + { + .fRestrict = cRestrictRWB, + .fMappedTo = eRestrictReadWriteBinary, + }, + { + .fRestrict = cRestrictW, + .fMappedTo = eRestrictWrite, + }, + { + .fRestrict = cRestrictWB, + .fMappedTo = eRestrictReadWrite, + }}; + + for (SizeT index = 0; index < cRestrictCount; ++index) + { + if (rt_string_cmp(restrict_type, cRestrictList[index].fRestrict, + rt_string_len(cRestrictList[index].fRestrict)) == 0) + { + fFileRestrict = cRestrictList[index].fMappedTo; + break; + } + } + + kcout << "new file: " << path << ".\r"; + } + + /// @brief destructor + template <typename Encoding, typename Class> + FileStream<Encoding, Class>::~FileStream() + { + mm_delete_heap(fFile); + } +} // namespace Kernel diff --git a/dev/zka/KernelKit/Framebuffer.hxx b/dev/zka/KernelKit/Framebuffer.hxx new file mode 100644 index 00000000..dac9b514 --- /dev/null +++ b/dev/zka/KernelKit/Framebuffer.hxx @@ -0,0 +1,85 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + + File: Framebuffer.hpp + Purpose: Framebuffer object. + +------------------------------------------- */ + +#ifndef __INC_FB_HPP__ +#define __INC_FB_HPP__ + +#include <NewKit/Defines.hxx> +#include <NewKit/Ref.hxx> + +namespace Kernel +{ + enum class FramebufferColorKind : UChar + { + RGB32, + RGB16, + RGB8, + INVALID, + }; + + class FramebufferContext final + { + public: + UIntPtr fBase; + UIntPtr fBpp; + UInt fWidth; + UInt fHeight; + }; + + class Framebuffer final + { + public: + explicit Framebuffer(Ref<FramebufferContext*>& addr); + ~Framebuffer() = default; + + Framebuffer& operator=(const Framebuffer&) = delete; + Framebuffer(const Framebuffer&) = default; + + volatile UIntPtr* operator[](const UIntPtr& pos); + + operator bool(); + + const FramebufferColorKind& Color( + const FramebufferColorKind& colour = FramebufferColorKind::INVALID); + + Ref<FramebufferContext*>& Leak(); + + /// @brief Draws a rectangle inside the fb. + /// @param width the width of it + /// @param height the height of it + /// @param x its x coord. + /// @param y its y coord. + /// @param color the color of it. + /// @return the framebuffer object. + Framebuffer& DrawRect(SizeT width, SizeT height, SizeT x, SizeT y, UInt32 color); + + /// @brief Puts a pixel on the screen. + /// @param x where in X + /// @param y where in Y + /// @param color the color of it. + /// @return the framebuffer object. + Framebuffer& PutPixel(SizeT x, SizeT y, UInt32 color); + + private: + Ref<FramebufferContext*> fFrameBufferAddr; + FramebufferColorKind fColour; + }; + + /***********************************************************************************/ + /// Some common colors. + /***********************************************************************************/ + + extern const UInt32 kRgbRed; + extern const UInt32 kRgbGreen; + extern const UInt32 kRgbBlue; + extern const UInt32 kRgbBlack; + extern const UInt32 kRgbWhite; +} // namespace Kernel + +#endif /* ifndef __INC_FB_HPP__ */ diff --git a/dev/zka/KernelKit/HardwareThreadScheduler.hxx b/dev/zka/KernelKit/HardwareThreadScheduler.hxx new file mode 100644 index 00000000..83f6ebd9 --- /dev/null +++ b/dev/zka/KernelKit/HardwareThreadScheduler.hxx @@ -0,0 +1,147 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef __INC_MP_MANAGER_HPP__ +#define __INC_MP_MANAGER_HPP__ + +#include <ArchKit/ArchKit.hxx> +#include <CompilerKit/CompilerKit.hxx> +#include <NewKit/Ref.hxx> + +/// @note Last Rev Sun 28 Jul CET 2024 +/// @note Last Rev Thu, Aug 1, 2024 9:07:38 AM + +#define cMaxHWThreads (8U) + +namespace Kernel +{ + class HardwareThread; + class HardwareThreadScheduler; + + using ThreadID = UInt32; + + enum ThreadKind + { + kHartSystemReserved, // System reserved thread, well user can't use it + kHartStandard, // user thread, cannot be used by Kernel + kHartFallback, // fallback thread, cannot be used by user if not clear or + // used by Kernel. + kHartBoot, // The core we booted from, the mama. + kInvalidHart, + kHartCount, + }; + + typedef enum ThreadKind ThreadKind; + typedef ThreadID ThreadID; + + /// + /// \name HardwareThread + /// \brief Abstraction over the CPU's core, used to run processes or threads. + /// + + class HardwareThread final + { + public: + explicit HardwareThread(); + ~HardwareThread(); + + public: + ZKA_COPY_DEFAULT(HardwareThread) + + public: + operator bool(); + + public: + void Wake(const bool wakeup = false) noexcept; + void Busy(const bool busy = false) noexcept; + + public: + bool Switch(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr frame); + bool IsWakeup() noexcept; + + public: + HAL::StackFramePtr StackFrame() noexcept; + const ThreadKind& Kind() noexcept; + bool IsBusy() noexcept; + const ThreadID& ID() noexcept; + + private: + HAL::StackFramePtr fStack{nullptr}; + ThreadKind fKind{ThreadKind::kHartStandard}; + ThreadID fID{0}; + ProcessID fSourcePID{-1}; + Bool fWakeup{false}; + Bool fBusy{false}; + UInt64 fPTime{0}; + + private: + friend class HardwareThreadScheduler; + friend class UserProcessHelper; + }; + + /// + /// \name HardwareThreadScheduler + /// \brief Class to manage the thread scheduling. + /// + + class HardwareThreadScheduler final : public ISchedulerObject + { + private: + friend class UserProcessHelper; + + public: + explicit HardwareThreadScheduler(); + ~HardwareThreadScheduler(); + ZKA_COPY_DEFAULT(HardwareThreadScheduler); + + public: + HAL::StackFramePtr Leak() noexcept; + + public: + Ref<HardwareThread*> operator[](const SizeT& idx); + bool operator!() noexcept; + operator bool() noexcept; + + const Bool IsUser() override + { + return Yes; + } + + const Bool IsKernel() override + { + return No; + } + + const Bool HasMP() override + { + return kHandoverHeader->f_HardwareTables.f_MultiProcessingEnabled; + } + + public: + /// @brief Shared instance of the MP Mgr. + /// @return the reference to the mp manager class. + STATIC HardwareThreadScheduler& The(); + + public: + /// @brief Returns the amount of threads present in the system. + /// @returns SizeT the amount of cores present. + SizeT Count() noexcept; + + private: + Array<HardwareThread, cMaxHWThreads> fThreadList; + ThreadID fCurrentThread{0}; + }; + + /// @brief wakes up thread. + /// wakes up thread from hang. + Void mp_wakeup_thread(HAL::StackFramePtr stack); + + /// @brief makes thread sleep. + /// hooks and hangs thread to prevent code from executing. + Void mp_hang_thread(HAL::StackFramePtr stack); +} // namespace Kernel + +#endif // !__INC_MP_MANAGER_HPP__ diff --git a/dev/zka/KernelKit/Heap.hxx b/dev/zka/KernelKit/Heap.hxx new file mode 100644 index 00000000..cb8da37d --- /dev/null +++ b/dev/zka/KernelKit/Heap.hxx @@ -0,0 +1,71 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef _INC_KERNEL_HEAP_HXX_ +#define _INC_KERNEL_HEAP_HXX_ + +// last-rev 30/01/24 +// file: KernelHeap.hxx +// description: heap allocation for the Kernel. + +#include <NewKit/Defines.hxx> + +namespace Kernel +{ + /// @brief Declare pointer as free. + /// @param heap_ptr the pointer. + /// @return + Int32 mm_delete_heap(VoidPtr heap_ptr); + + /// @brief Declare a new size for heap_ptr. + /// @param heap_ptr the pointer. + /// @return + VoidPtr mm_realloc_heap(VoidPtr heap_ptr, SizeT new_sz); + + /// @brief Check if pointer is a valid Kernel pointer. + /// @param heap_ptr the pointer + /// @return if it exists. + Boolean mm_is_valid_heap(VoidPtr heap_ptr); + + /// @brief Allocate chunk of memory. + /// @param sz Size of pointer + /// @param rw Read Write bit. + /// @param user User enable bit. + /// @return The newly allocated pointer. + VoidPtr mm_new_heap(const SizeT sz, const Bool rw, const Bool user); + + /// @brief Protect the heap with a CRC value. + /// @param heap_ptr pointer. + /// @return if it valid: point has crc now., otherwise fail. + Boolean mm_protect_heap(VoidPtr heap_ptr); + + /// @brief Makes a Kernel page. + /// @param heap_ptr the page pointer. + /// @return status code + Int32 mm_make_ke_page(VoidPtr heap_ptr); + + template <typename T, typename... Args> + inline T* mm_new_class(Args&&... args) + { + T* cls = (T*)mm_new_heap(sizeof(T), No, No); + MUST_PASS(cls); + + *cls = T(move(args)...); + + return cls; + } + + template <typename T> + inline Void mm_delete_class(T* cls) + { + cls->~T(); + mm_delete_heap((VoidPtr)cls); + + cls = nullptr; + } +} // namespace Kernel + +#endif // !_INC_KERNEL_HEAP_HXX_ diff --git a/dev/zka/KernelKit/IDLLObject.hxx b/dev/zka/KernelKit/IDLLObject.hxx new file mode 100644 index 00000000..21c2848a --- /dev/null +++ b/dev/zka/KernelKit/IDLLObject.hxx @@ -0,0 +1,44 @@ +/* + * ======================================================== + * + * Kernel + * Copyright ZKA Technologies., all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include <NewKit/Defines.hxx> + +namespace Kernel +{ + class IDLLObject + { + public: + explicit IDLLObject() = default; + virtual ~IDLLObject() = default; + + struct DLL_TRAITS final + { + VoidPtr fImageObject{nullptr}; + VoidPtr fImageEntrypointOffset{nullptr}; + + Bool IsValid() + { + return fImageObject && fImageEntrypointOffset; + } + }; + + ZKA_COPY_DEFAULT(IDLLObject); + + virtual DLL_TRAITS** GetAddressOf() = 0; + virtual DLL_TRAITS* Get() = 0; + + virtual Void Mount(DLL_TRAITS* to_mount) = 0; + virtual Void Unmount() = 0; + }; + + /// @brief Pure implementation, missing method/function handler. + EXTERN_C void __zka_pure_call(void); +} // namespace Kernel diff --git a/dev/zka/KernelKit/IPEFDLLObject.hxx b/dev/zka/KernelKit/IPEFDLLObject.hxx new file mode 100644 index 00000000..c41d3365 --- /dev/null +++ b/dev/zka/KernelKit/IPEFDLLObject.hxx @@ -0,0 +1,105 @@ +/* + * ======================================================== + * + * Kernel + * Copyright ZKA Technologies., all rights reserved. + * + * ======================================================== + */ + +#ifndef __KERNELKIT_SHARED_OBJECT_HXX__ +#define __KERNELKIT_SHARED_OBJECT_HXX__ + +#include <KernelKit/PEF.hxx> +#include <NewKit/Defines.hxx> +#include <KernelKit/PEFCodeMgr.hxx> +#include <KernelKit/IDLLObject.hxx> + +namespace Kernel +{ + /** + * @brief Shared Library class + * Load library from this class + */ + class IPEFDLLObject final : public IDLLObject + { + public: + explicit IPEFDLLObject() = default; + ~IPEFDLLObject() = default; + + public: + ZKA_COPY_DEFAULT(IPEFDLLObject); + + private: + DLL_TRAITS* fMounted{nullptr}; + + public: + DLL_TRAITS** GetAddressOf() + { + return &fMounted; + } + + DLL_TRAITS* Get() + { + return fMounted; + } + + public: + void Mount(DLL_TRAITS* to_mount) + { + if (!to_mount || !to_mount->fImageObject) + return; + + fMounted = to_mount; + + if (fLoader && to_mount) + { + delete fLoader; + fLoader = nullptr; + } + + if (!fLoader) + { + fLoader = new PEFLoader(fMounted->fImageObject); + } + } + + void Unmount() + { + if (fMounted) + fMounted = nullptr; + }; + + template <typename SymbolType> + SymbolType Load(const Char* symbol_name, SizeT len, Int32 kind) + { + if (symbol_name == nullptr || *symbol_name == 0) + return nullptr; + if (len > kPathLen || len < 1) + return nullptr; + + auto ret = + reinterpret_cast<SymbolType>(fLoader->FindSymbol(symbol_name, kind)); + + if (!ret) + { + if (kind == kPefCode) + return (VoidPtr)&__zka_pure_call; + + return nullptr; + } + + return ret; + } + + private: + PEFLoader* fLoader{nullptr}; + }; + + typedef IPEFDLLObject* IDLL; + + EXTERN_C IDLL rtl_init_dll(UserProcess* header); + EXTERN_C Void rtl_fini_dll(UserProcess* header, IDLL lib, Bool* successful); +} // namespace Kernel + +#endif /* ifndef __KERNELKIT_SHARED_OBJECT_HXX__ */ diff --git a/dev/zka/KernelKit/LPC.hxx b/dev/zka/KernelKit/LPC.hxx new file mode 100644 index 00000000..9a14c798 --- /dev/null +++ b/dev/zka/KernelKit/LPC.hxx @@ -0,0 +1,61 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include <NewKit/Defines.hxx> + +/// @file LPC.hxx +/// @brief Local Process Codes. + +#define ErrLocalIsOk() (Kernel::UserProcessScheduler::The().CurrentProcess().Leak().GetLocalCode() == Kernel::kErrorSuccess) +#define ErrLocalFailed() (Kernel::UserProcessScheduler::The().CurrentProcess().Leak().GetLocalCode() != Kernel::kErrorSuccess) +#define ErrLocal() Kernel::UserProcessScheduler::The().CurrentProcess().Leak().GetLocalCode() + +namespace Kernel +{ + typedef Int32 HError; + + inline constexpr HError kErrorSuccess = 0; + inline constexpr HError kErrorExecutable = 33; + inline constexpr HError kErrorExecutableLib = 34; + inline constexpr HError kErrorFileNotFound = 35; + inline constexpr HError kErrorDirectoryNotFound = 36; + inline constexpr HError kErrorDiskReadOnly = 37; + inline constexpr HError kErrorDiskIsFull = 38; + inline constexpr HError kErrorProcessFault = 39; + inline constexpr HError kErrorSocketHangUp = 40; + inline constexpr HError kErrorThreadLocalStorage = 41; + inline constexpr HError kErrorMath = 42; + inline constexpr HError kErrorNoNetwork = 43; + inline constexpr HError kErrorHeapOutOfMemory = 44; + inline constexpr HError kErrorNoSuchDisk = 45; + inline constexpr HError kErrorFileExists = 46; + inline constexpr HError kErrorFormatFailed = 47; + inline constexpr HError kErrorNetworkTimeout = 48; + inline constexpr HError kErrorInternal = 49; + inline constexpr HError kErrorForkAlreadyExists = 50; + inline constexpr HError kErrorOutOfTeamSlot = 51; + inline constexpr HError kErrorHeapNotPresent = 52; + inline constexpr HError kErrorNoEntrypoint = 53; + inline constexpr HError kErrorDiskIsCorrupted = 54; + inline constexpr HError kErrorDisk = 55; + inline constexpr HError kErrorInvalidData = 56; + inline constexpr HError kErrorAsync = 57; + inline constexpr HError kErrorNonBlocking = 58; + inline constexpr HError kErrorIPC = 59; + inline constexpr HError kErrorSign = 60; + inline constexpr HError kErrorInvalidCreds = 61; + inline constexpr HError kErrorUnimplemented = 0; + + /// @brief Reports a bug to system check. + Void err_bug_check_raise(void) noexcept; + + /// @brief Does a system wide bug check. + /// @param void no params. + /// @return if error-free: false, otherwise true. + Boolean err_bug_check(void) noexcept; +} // namespace Kernel diff --git a/dev/zka/KernelKit/LoaderInterface.hxx b/dev/zka/KernelKit/LoaderInterface.hxx new file mode 100644 index 00000000..ab251bec --- /dev/null +++ b/dev/zka/KernelKit/LoaderInterface.hxx @@ -0,0 +1,33 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include <CompilerKit/CompilerKit.hxx> +#include <HintKit/CompilerHint.hxx> +#include <NewKit/Defines.hxx> +#include <NewKit/ErrorOr.hxx> + +namespace Kernel +{ + /// @brief This interface is used to make loader contracts (MSCOFF, PEF). + /// @author @Amlal-El-Mahrouss + class LoaderInterface + { + public: + explicit LoaderInterface() = default; + virtual ~LoaderInterface() = default; + + ZKA_COPY_DEFAULT(LoaderInterface); + + public: + virtual _Output const Char* AsString() = 0; + virtual _Output const Char* MIME() = 0; + virtual _Output const Char* Path() = 0; + virtual _Output ErrorOr<VoidPtr> FindStart() = 0; + virtual _Output VoidPtr FindSymbol(_Input const Char* name, _Input Int32 kind) = 0; + }; +} // namespace Kernel diff --git a/dev/zka/KernelKit/LockDelegate.hxx b/dev/zka/KernelKit/LockDelegate.hxx new file mode 100644 index 00000000..d678e3d4 --- /dev/null +++ b/dev/zka/KernelKit/LockDelegate.hxx @@ -0,0 +1,67 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include <NewKit/Atom.hxx> +#include <NewKit/Defines.hxx> + +namespace Kernel +{ + enum + { + kLockDone = 200, + kLockTimedOut, + }; + + /// @brief Lock condition pointer. + typedef Boolean* LockPtr; + + /// @brief Locking delegate class, hangs until limit. + /// @tparam N the amount of cycles to wait. + template <SizeT N> + class LockDelegate final + { + public: + LockDelegate() = delete; + + public: + explicit LockDelegate(LockPtr expr) + { + auto spin = 0U; + + while (spin != N) + { + if (*expr) + { + fLockStatus | kLockDone; + break; + } + } + + if (spin == N) + fLockStatus | kLockTimedOut; + } + + ~LockDelegate() = default; + + LockDelegate& operator=(const LockDelegate&) = delete; + LockDelegate(const LockDelegate&) = delete; + + bool Done() + { + return fLockStatus[kLockDone] == kLockDone; + } + + bool HasTimedOut() + { + return fLockStatus[kLockTimedOut] != kLockTimedOut; + } + + private: + Atom<UInt> fLockStatus; + }; +} // namespace Kernel diff --git a/dev/zka/KernelKit/MSDOS.hxx b/dev/zka/KernelKit/MSDOS.hxx new file mode 100644 index 00000000..6ce11cbd --- /dev/null +++ b/dev/zka/KernelKit/MSDOS.hxx @@ -0,0 +1,52 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + + File: MSDOS.hpp + Purpose: MS-DOS header for Kernel. + + Revision History: + + 30/01/24: Added file (amlel) + +------------------------------------------- */ + +#ifndef __MSDOS_EXEC__ +#define __MSDOS_EXEC__ + +#include <KernelKit/PE.hxx> +#include <NewKit/Defines.hxx> + +// Last Rev +// Sat Feb 24 CET 2024 + +#define kMagMz0 'M' +#define kMagMz1 'Z' + +typedef Kernel::UInt32 DosWord; +typedef Kernel::Long DosLong; + +typedef struct _DosHeader +{ + Kernel::UInt8 eMagic[2]; + DosWord eMagLen; + DosWord ePagesCount; + DosWord eCrlc; + DosWord eCParHdr; + DosWord eMinAlloc; + DosWord eMaxAlloc; + DosWord eStackSeg; + DosWord eStackPtr; + DosWord eChksum; + DosWord eIp; + DosWord eCs; + DosWord eLfarlc; + DosWord eOvno; + DosWord eRes[4]; + DosWord eOemid; + DosWord eOeminfo; + DosWord eRes2[10]; + DosLong eLfanew; +} DosHeader, *DosHeaderPtr; + +#endif /* ifndef __MSDOS_EXEC__ */ diff --git a/dev/zka/KernelKit/PCI/Database.hxx b/dev/zka/KernelKit/PCI/Database.hxx new file mode 100644 index 00000000..c5f3c953 --- /dev/null +++ b/dev/zka/KernelKit/PCI/Database.hxx @@ -0,0 +1,38 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ +#pragma once + +#include <KernelKit/PCI/Device.hxx> +#include <NewKit/Defines.hxx> + +namespace Kernel +{ + namespace Types + { + // https://wiki.osdev.org/PCI + enum class PciDeviceKind : UChar + { + MassStorageController = 0x1, + NetworkController = 0x2, + DisplayController = 0x3, + MultimediaController = 0x4, + MemoryController = 0x5, + Bridge = 0x6, + CommunicationController = 0x7, + GenericSystemPeripheral = 0x8, + InputDeviceController = 0x9, + DockingStation = 0xa, + Processor = 0xb, + SerialBusController = 0xc, + WirelessController = 0xd, + IntelligentController = 0xe, + SatelliteCommunicationsController = 0xf, + CoProcessor = 0x40, + Unassgined = 0xf, + Invalid = Unassgined, + }; + } // namespace Types +} // namespace Kernel diff --git a/dev/zka/KernelKit/PCI/Device.hxx b/dev/zka/KernelKit/PCI/Device.hxx new file mode 100644 index 00000000..b1c011e9 --- /dev/null +++ b/dev/zka/KernelKit/PCI/Device.hxx @@ -0,0 +1,80 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ +#pragma once + +#include <NewKit/Defines.hxx> + +namespace Kernel::PCI +{ + enum class PciConfigKind : UShort + { + ConfigAddress = 0xCF8, + ConfigData = 0xCFC, + Invalid = 0xFFF + }; + + class Device final + { + public: + Device() = default; + + public: + explicit Device(UShort bus, UShort device, UShort function, UInt32 bar); + + Device& operator=(const Device&) = default; + + Device(const Device&) = default; + + ~Device(); + + public: + UInt Read(UInt bar, Size szData); + void Write(UInt bar, UIntPtr data, Size szData); + + public: + operator bool(); + + public: + template <typename T> + UInt Read(UInt bar) + { + static_assert(sizeof(T) <= 4, "64-bit PCI addressing is unsupported"); + return Read(bar, sizeof(T)); + } + + template <typename T> + void Write(UInt bar, UIntPtr data) + { + static_assert(sizeof(T) <= 4, "64-bit PCI addressing is unsupported"); + Write(bar, data, sizeof(T)); + } + + public: + UShort DeviceId(); + UShort VendorId(); + UShort InterfaceId(); + UChar Class(); + UChar Subclass(); + UChar ProgIf(); + UChar HeaderType(); + UInt32 Bar(); + + public: + void EnableMmio(); + void BecomeBusMaster(); // for PCI-DMA, PC-DMA does not need that. + + UShort Vendor(); + + private: + UShort fBus; + UShort fDevice; + UShort fFunction; + UInt32 fBar; + }; +} // namespace Kernel::PCI + +EXTERN_C void NewOSPCISetCfgTarget(Kernel::UInt bar); +EXTERN_C Kernel::UInt NewOSPCIReadRaw(Kernel::UInt bar); diff --git a/dev/zka/KernelKit/PCI/Dma.hxx b/dev/zka/KernelKit/PCI/Dma.hxx new file mode 100644 index 00000000..b265f738 --- /dev/null +++ b/dev/zka/KernelKit/PCI/Dma.hxx @@ -0,0 +1,81 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include <KernelKit/DeviceMgr.hxx> +#include <KernelKit/PCI/Device.hxx> +#include <NewKit/Array.hxx> +#include <NewKit/OwnPtr.hxx> +#include <NewKit/Ref.hxx> + +namespace Kernel +{ + enum class DmaKind + { + PCI, // Bus mastering is required to be turned on. Basiaclly a request + // control system. 64-Bit access depends on the PAE bit and the device + // (if Double Address Cycle is available) + ISA, // Four DMA channels 0-3; 8 bit transfers and only a megabyte of RAM. + Invalid, + }; + + class DMAWrapper final + { + public: + explicit DMAWrapper() = delete; + + public: + explicit DMAWrapper(nullPtr) = delete; + explicit DMAWrapper(voidPtr Ptr, DmaKind Kind = DmaKind::PCI) + : fAddress(Ptr), fKind(Kind) + { + } + + public: + DMAWrapper& operator=(voidPtr Ptr); + + public: + DMAWrapper& operator=(const DMAWrapper&) = default; + DMAWrapper(const DMAWrapper&) = default; + + public: + ~DMAWrapper() = default; + + template <class T> + T* operator->(); + + template <class T> + T* Get(const UIntPtr off = 0); + + public: + operator bool(); + bool operator!(); + + public: + bool Write(const UIntPtr& bit, const UIntPtr& offset); + UIntPtr Read(const UIntPtr& offset); + Boolean Check(UIntPtr offset) const; + + public: + UIntPtr operator[](const UIntPtr& offset); + + private: + voidPtr fAddress{nullptr}; + DmaKind fKind{DmaKind::Invalid}; + + private: + friend class DMAFactory; + }; + + class DMAFactory final + { + public: + static OwnPtr<IOBuf<Char*>> Construct(OwnPtr<DMAWrapper>& dma); + }; +} // namespace Kernel + +#include <KernelKit/PCI/Dma.inl> diff --git a/dev/zka/KernelKit/PCI/Dma.inl b/dev/zka/KernelKit/PCI/Dma.inl new file mode 100644 index 00000000..1c164af8 --- /dev/null +++ b/dev/zka/KernelKit/PCI/Dma.inl @@ -0,0 +1,20 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +namespace Kernel +{ + template <class T> + T* DMAWrapper::operator->() + { + return fAddress; + } + + template <class T> + T* DMAWrapper::Get(const UIntPtr offset) + { + return reinterpret_cast<T*>((UIntPtr)fAddress + offset); + } +} // namespace Kernel diff --git a/dev/zka/KernelKit/PCI/Express.hxx b/dev/zka/KernelKit/PCI/Express.hxx new file mode 100644 index 00000000..1d6a86d0 --- /dev/null +++ b/dev/zka/KernelKit/PCI/Express.hxx @@ -0,0 +1,11 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include <NewKit/Defines.hxx> + +#define PCI_EXPRESS_BUS_COUNT (4096) diff --git a/dev/zka/KernelKit/PCI/IO-Impl-AMD64.inl b/dev/zka/KernelKit/PCI/IO-Impl-AMD64.inl new file mode 100644 index 00000000..84c24620 --- /dev/null +++ b/dev/zka/KernelKit/PCI/IO-Impl-AMD64.inl @@ -0,0 +1,54 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + + File: IO-Impl-AMD64.hpp + Purpose: I/O for AMD64. + + Revision History: + + 30/01/24: Add file. (amlel) + 02/02/24: Update I/O routines. (amlel) + +------------------------------------------- */ + +namespace Kernel +{ + template <SizeT Sz> + template <typename T> + T IOArray<Sz>::In(SizeT index) + { + switch (sizeof(T)) + { +#ifdef __ZKA_AMD64__ + case 4: + return HAL::In32(fPorts[index].Leak()); + case 2: + return HAL::In16(fPorts[index].Leak()); + case 1: + return HAL::In8(fPorts[index].Leak()); +#endif + default: + return 0xFFFF; + } + } + + template <SizeT Sz> + template <typename T> + void IOArray<Sz>::Out(SizeT index, T value) + { + switch (sizeof(T)) + { +#ifdef __ZKA_AMD64__ + case 4: + HAL::Out32(fPorts[index].Leak(), value); + case 2: + HAL::Out16(fPorts[index].Leak(), value); + case 1: + HAL::Out8(fPorts[index].Leak(), value); +#endif + default: + break; + } + } +} // namespace Kernel diff --git a/dev/zka/KernelKit/PCI/IO.hxx b/dev/zka/KernelKit/PCI/IO.hxx new file mode 100644 index 00000000..a86bcc52 --- /dev/null +++ b/dev/zka/KernelKit/PCI/IO.hxx @@ -0,0 +1,59 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include <ArchKit/ArchKit.hxx> +#include <NewKit/Array.hxx> +#include <NewKit/Defines.hxx> +#include <NewKit/Ref.hxx> + +namespace Kernel +{ + template <SizeT Sz> + class IOArray final + { + public: + IOArray() = delete; + + IOArray(nullPtr) = delete; + + explicit IOArray(Array<UShort, Sz>& ports) + : fPorts(ports) + { + } + ~IOArray() + { + } + + IOArray& operator=(const IOArray&) = default; + + IOArray(const IOArray&) = default; + + operator bool() + { + return !fPorts.Empty(); + } + + public: + template <typename T> + T In(SizeT index); + + template <typename T> + void Out(SizeT index, T value); + + private: + Array<UShort, Sz> fPorts; + }; + + using IOArray16 = IOArray<16>; +} // namespace Kernel + +#ifdef __x86_64__ +#include <KernelKit/PCI/IO-Impl-AMD64.inl> +#else +#error Please provide platform specific code for the I/O +#endif // ifdef __x86_64__ diff --git a/dev/zka/KernelKit/PCI/Iterator.hxx b/dev/zka/KernelKit/PCI/Iterator.hxx new file mode 100644 index 00000000..24c6e610 --- /dev/null +++ b/dev/zka/KernelKit/PCI/Iterator.hxx @@ -0,0 +1,43 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef __PCI_ITERATOR_HPP__ +#define __PCI_ITERATOR_HPP__ + +#include <KernelKit/PCI/Database.hxx> +#include <KernelKit/PCI/Device.hxx> +#include <NewKit/Array.hxx> +#include <NewKit/Defines.hxx> +#include <NewKit/Ref.hxx> + +#define ZKA_BUS_COUNT (256) +#define ZKA_DEVICE_COUNT (33) +#define ZKA_FUNCTION_COUNT (8) + +namespace Kernel::PCI +{ + class Iterator final + { + public: + Iterator() = delete; + + public: + explicit Iterator(const Types::PciDeviceKind& deviceType); + + Iterator& operator=(const Iterator&) = default; + Iterator(const Iterator&) = default; + + ~Iterator(); + + public: + Ref<PCI::Device> operator[](const Size& sz); + + private: + Array<PCI::Device, ZKA_BUS_COUNT> fDevices; + }; +} // namespace Kernel::PCI + +#endif // __PCI_ITERATOR_HPP__ diff --git a/dev/zka/KernelKit/PCI/PCI.hxx b/dev/zka/KernelKit/PCI/PCI.hxx new file mode 100644 index 00000000..3289db04 --- /dev/null +++ b/dev/zka/KernelKit/PCI/PCI.hxx @@ -0,0 +1,59 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include <NewKit/Defines.hxx> + +#define cPCIConfigAddressPort (0xCF8) +#define cPCIConfigDataPort (0xCFC) + +#define cPCIDeviceCount (32) +#define cPCIFuncCount (8) +#define cPCIBusCount (255) + +namespace Kernel::PCI +{ + // model + struct DeviceHeader + { + UInt16 VendorId; + UInt16 DeviceId; + UInt8 Command; + UInt8 Status; + UInt8 RevisionId; + UInt8 ProgIf; + UInt8 SubClass; + UInt8 Class; + UInt8 CacheLineSz; + UInt8 LatencyTimer; + UInt8 HeaderType; + UInt8 Bist; + UInt8 Bus; + UInt8 Device; + UInt8 Function; + }; + + namespace Detail + { + class BAR + { + public: + UIntPtr BAR; + SizeT Size; + }; + } // namespace Detail + + class BAR + { + public: + Detail::BAR BAR1; + Detail::BAR BAR2; + Detail::BAR BAR3; + Detail::BAR BAR4; + Detail::BAR BAR5; + }; +} // namespace Kernel::PCI diff --git a/dev/zka/KernelKit/PE.hxx b/dev/zka/KernelKit/PE.hxx new file mode 100644 index 00000000..bab723ef --- /dev/null +++ b/dev/zka/KernelKit/PE.hxx @@ -0,0 +1,143 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + + File: PE.hxx + Purpose: Portable Executable for Kernel. + + Revision History: + + 30/01/24: Added file (amlel) + +------------------------------------------- */ + +#ifndef __KERNELKIT_INC_PE_HXX__ +#define __KERNELKIT_INC_PE_HXX__ + +#include <NewKit/Defines.hxx> + +#define kPeMagic 0x00004550 + +#define kPeDLLBase 0x4000000 +#define kPeEXEBase 0x1000000 + +#define kMagPE32 0x010b +#define kMagPE64 0x020b + +#define kPeMachineAMD64 0x8664 +#define kPeMachineARM64 0xaa64 + +typedef struct LDR_EXEC_HEADER final +{ + Kernel::UInt32 mSignature; + Kernel::UInt16 mMachine; + Kernel::UInt16 mNumberOfSections; + Kernel::UInt32 mTimeDateStamp; + Kernel::UInt32 mPointerToSymbolTable; + Kernel::UInt32 mNumberOfSymbols; + Kernel::UInt16 mSizeOfOptionalHeader; + Kernel::UInt16 mCharacteristics; +} LDR_EXEC_HEADER, *LDR_EXEC_HEADER_PTR; + +typedef struct LDR_OPTIONAL_HEADER final +{ + Kernel::UInt16 mMagic; // 0x010b - PE32, 0x020b - PE32+ (64 bit) + Kernel::UInt8 mMajorLinkerVersion; + Kernel::UInt8 mMinorLinkerVersion; + Kernel::UInt32 mSizeOfCode; + Kernel::UInt32 mSizeOfInitializedData; + Kernel::UInt32 mSizeOfUninitializedData; + Kernel::UInt32 mAddressOfEntryPoint; + Kernel::UInt32 mBaseOfCode; + Kernel::UInt32 mBaseOfData; + Kernel::UInt32 mImageBase; + Kernel::UInt32 mSectionAlignment; + Kernel::UInt32 mFileAlignment; + Kernel::UInt16 mMajorOperatingSystemVersion; + Kernel::UInt16 mMinorOperatingSystemVersion; + Kernel::UInt16 mMajorImageVersion; + Kernel::UInt16 mMinorImageVersion; + Kernel::UInt16 mMajorSubsystemVersion; + Kernel::UInt16 mMinorSubsystemVersion; + Kernel::UInt32 mWin32VersionValue; + Kernel::UInt32 mSizeOfImage; + Kernel::UInt32 mSizeOfHeaders; + Kernel::UInt32 mCheckSum; + Kernel::UInt16 mSubsystem; + Kernel::UInt16 mDllCharacteristics; + Kernel::UInt32 mSizeOfStackReserve; + Kernel::UInt32 mSizeOfStackCommit; + Kernel::UInt32 mSizeOfHeapReserve; + Kernel::UInt32 mSizeOfHeapCommit; + Kernel::UInt32 mLoaderFlags; + Kernel::UInt32 mNumberOfRvaAndSizes; +} LDR_OPTIONAL_HEADER, *LDR_OPTIONAL_HEADER_PTR; + +typedef struct LDR_SECTION_HEADER final +{ + Kernel::Char mName[8]; + Kernel::UInt32 mVirtualSize; + Kernel::UInt32 mVirtualAddress; + Kernel::UInt32 mSizeOfRawData; + Kernel::UInt32 mPointerToRawData; + Kernel::UInt32 mPointerToRelocations; + Kernel::UInt32 mPointerToLineNumbers; + Kernel::UInt16 mNumberOfRelocations; + Kernel::UInt16 mNumberOfLinenumbers; + Kernel::UInt32 mCharacteristics; +} LDR_SECTION_HEADER, *LDR_SECTION_HEADER_PTR; + +enum kExecDataDirParams +{ + kExecExport, + kExecImport, + kExecInvalid, + kExecCount, +}; + +typedef struct LDR_EXPORT_DIRECTORY +{ + Kernel::UInt32 mCharacteristics; + Kernel::UInt32 mTimeDateStamp; + Kernel::UInt16 mMajorVersion; + Kernel::UInt16 mMinorVersion; + Kernel::UInt32 mName; + Kernel::UInt32 mBase; + Kernel::UInt32 mNumberOfFunctions; + Kernel::UInt32 mNumberOfNames; + Kernel::UInt32 mAddressOfFunctions; // export table rva + Kernel::UInt32 mAddressOfNames; + Kernel::UInt32 mAddressOfNameOrdinal; // ordinal table rva +} LDR_EXPORT_DIRECTORY, *LDR_EXPORT_DIRECTORY_PTR; + +typedef struct LDR_IMPORT_DIRECTORY +{ + union { + Kernel::UInt32 mCharacteristics; + Kernel::UInt32 mOriginalFirstThunk; + }; + Kernel::UInt32 mTimeDateStamp; + Kernel::UInt32 mForwarderChain; + Kernel::UInt32 mNameRva; + Kernel::UInt32 mThunkTableRva; +} LDR_IMPORT_DIRECTORY, *LDR_IMPORT_DIRECTORY_PTR; + +typedef struct LDR_DATA_DIRECTORY +{ + Kernel::UInt32 VirtualAddress; + Kernel::UInt32 Size; +} LDR_DATA_DIRECTORY, *LDR_DATA_DIRECTORY_PTR; + +typedef struct LDR_IMAGE_HEADER +{ + LDR_EXEC_HEADER mHeader; + LDR_OPTIONAL_HEADER mOptHdr; +} LDR_IMAGE_HEADER, *LDR_IMAGE_HEADER_PTR; + +enum +{ + eUserSection = 0x00000020, + cPEResourceId = 0xFFaadd00, +}; + +#endif /* ifndef __KERNELKIT_INC_PE_HXX__ */ diff --git a/dev/zka/KernelKit/PECodeMgr.hxx b/dev/zka/KernelKit/PECodeMgr.hxx new file mode 100644 index 00000000..7b84fbc1 --- /dev/null +++ b/dev/zka/KernelKit/PECodeMgr.hxx @@ -0,0 +1,24 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + + File: PECodeMgr.hxx + Purpose: PE32+ Code Mgr and Shared Objects. + + Revision History: + + 12/02/24: Added file (amlel) + +------------------------------------------- */ + +#pragma once + +//////////////////////////////////////////////////// + +// LAST REV: Mon Feb 12 13:52:01 CET 2024 + +//////////////////////////////////////////////////// + +#include <KernelKit/PE.hxx> +#include <NewKit/ErrorOr.hxx> +#include <NewKit/String.hxx> diff --git a/dev/zka/KernelKit/PEF.hxx b/dev/zka/KernelKit/PEF.hxx new file mode 100644 index 00000000..e8066cf5 --- /dev/null +++ b/dev/zka/KernelKit/PEF.hxx @@ -0,0 +1,116 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + + File: PEF.hxx + Purpose: Preferred Executable Format for Kernel. + + Revision History: + + ?/?/23: Added file (amlel) + +------------------------------------------- */ + +#ifndef __KERNELKIT_INC_PEF_HXX__ +#define __KERNELKIT_INC_PEF_HXX__ + +#include <CompilerKit/CompilerKit.hxx> +#include <KernelKit/LoaderInterface.hxx> +#include <NewKit/Defines.hxx> + +#define kPefMagic "Joy!" +#define kPefMagicFat "yoJ!" + +#define kPefMagicLen 5 + +#define kPefVersion 3 +#define kPefNameLen 255 + +namespace Kernel +{ + enum + { + kPefArchIntel86S, + kPefArchAMD64, + kPefArchRISCV, + kPefArch64x0, /* 64x0. ISA */ + kPefArch32x0, /* 32x0. ISA */ + kPefArchPowerPC, + kPefArchARM64, + kPefArchCount = (kPefArchPowerPC - kPefArchIntel86S) + 1, + kPefArchInvalid = 0xFF, + }; + + enum + { + kPefSubArchAMD, + kPefSubArchIntel, + kPefSubArchGeneric, + kPefSubArchIBM, + }; + + enum + { + kPefKindExec = 1, /* .exe */ + kPefKindSharedObject = 2, /* .lib */ + kPefKindObject = 4, /* .obj */ + kPefKindDebug = 5, /* .dbg */ + kPefKindDriver = 6, + kPefKindCount, + }; + + typedef struct PEFContainer final + { + Char Magic[kPefMagicLen]; + UInt32 Linker; + UInt32 Version; + UInt32 Kind; + UInt32 Abi; + UInt32 Cpu; + UInt32 SubCpu; /* Cpu specific information */ + UIntPtr Start; + SizeT HdrSz; /* Size of header */ + SizeT Count; /* container header count */ + } PACKED PEFContainer; + + /* First PEFCommandHeader starts after PEFContainer */ + + typedef struct PEFCommandHeader final + { + Char Name[kPefNameLen]; /* container name */ + UInt32 Cpu; /* container cpu */ + UInt32 SubCpu; /* container sub-cpu */ + UInt32 Flags; /* container flags */ + UInt16 Kind; /* container kind */ + UIntPtr Offset; /* content offset */ + SizeT Size; /* content Size */ + } PACKED PEFCommandHeader; + + enum + { + kPefCode = 0xC, + kPefData = 0xD, + kPefZero = 0xE, + kPefLinkerID = 0x1, + }; +} // namespace Kernel + +/* not mandatory, only for non fork based filesystems */ +#define kPefExt ".exe" +#define kPefDylibExt ".dll" +#define kPefLibExt ".lib" +#define kPefObjectExt ".obj" +#define kPefDebugExt ".dbg" +#define kPefDriverExt ".sys" + +// Kernel System Binary Interface. +#define kPefAbi (0x5046) + +#define kPefBaseOrigin (0x40000000) + +#define kPefStart "__ImageStart" + +#define kPefForkKind kPefMagic +#define kPefForkKindFAT kPefMagicFat + +#endif /* ifndef __KERNELKIT_INC_PEF_HXX__ */ diff --git a/dev/zka/KernelKit/PEFCodeMgr.hxx b/dev/zka/KernelKit/PEFCodeMgr.hxx new file mode 100644 index 00000000..2b07e4f8 --- /dev/null +++ b/dev/zka/KernelKit/PEFCodeMgr.hxx @@ -0,0 +1,67 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef _INC_CODE_MANAGER_PEF_HXX_ +#define _INC_CODE_MANAGER_PEF_HXX_ + +#include <KernelKit/PEF.hxx> +#include <NewKit/ErrorOr.hxx> +#include <NewKit/String.hxx> +#include <KernelKit/FileMgr.hxx> + +#define kPefApplicationMime "application/vnd-zka-executable" + +namespace Kernel +{ + /// + /// \name PEFLoader + /// \brief PEF loader class. + /// + class PEFLoader : public LoaderInterface + { + private: + explicit PEFLoader() = delete; + + public: + explicit PEFLoader(const VoidPtr blob); + explicit PEFLoader(const Char* path); + ~PEFLoader() override; + + public: + ZKA_COPY_DEFAULT(PEFLoader); + + public: + const Char* Path() override; + const Char* AsString() override; + const Char* MIME() override; + + public: + ErrorOr<VoidPtr> FindStart() override; + VoidPtr FindSymbol(const Char* name, Int32 kind) override; + + public: + bool IsLoaded() noexcept; + + private: +#ifdef __FSKIT_USE_NEFS__ + OwnPtr<FileStream<Char, NeFileSystemMgr>> fFile; +#else + OwnPtr<FileStream<Char>> fFile; +#endif // __FSKIT_USE_NEFS__ + + Ref<StringView> fPath; + VoidPtr fCachedBlob; + bool fFatBinary; + bool fBad; + }; + + namespace Utils + { + bool execute_from_image(PEFLoader& exec, const Int32& procKind) noexcept; + } // namespace Utils +} // namespace Kernel + +#endif // ifndef _INC_CODE_MANAGER_PEF_HXX_ diff --git a/dev/zka/KernelKit/Semaphore.hxx b/dev/zka/KernelKit/Semaphore.hxx new file mode 100644 index 00000000..74c5f8da --- /dev/null +++ b/dev/zka/KernelKit/Semaphore.hxx @@ -0,0 +1,43 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include <NewKit/Defines.hxx> +#include <KernelKit/Timer.hxx> +#include <CompilerKit/CompilerKit.hxx> + +namespace Kernel +{ + class UserProcess; + + typedef UserProcess* UserProcessPtr; + + /// @brief Access control class, which locks a task until one is done. + class Semaphore final + { + public: + explicit Semaphore() = default; + ~Semaphore() = default; + + public: + bool IsLocked() const; + bool Unlock() noexcept; + + public: + void WaitForProcess() noexcept; + + public: + bool Lock(UserProcess* process); + bool LockOrWait(UserProcess* process, TimerInterface* timer); + + public: + ZKA_COPY_DEFAULT(Semaphore); + + private: + UserProcessPtr fLockingProcess{nullptr}; + }; +} // namespace Kernel diff --git a/dev/zka/KernelKit/ThreadLocalStorage.hxx b/dev/zka/KernelKit/ThreadLocalStorage.hxx new file mode 100644 index 00000000..a25d8926 --- /dev/null +++ b/dev/zka/KernelKit/ThreadLocalStorage.hxx @@ -0,0 +1,54 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef _KERNELKIT_TLS_HPP +#define _KERNELKIT_TLS_HPP + +#include <NewKit/Defines.hxx> + +///! @brief Thread Local Storage for newoskrnl. + +#define kCookieMag0 'Z' +#define kCookieMag1 'K' +#define kCookieMag2 'A' + +#define kTLSCookieLen (3U) + +struct THREAD_INFORMATION_BLOCK; + +/// @brief Thread Information Block. +/// Located in GS on AMD64, other architectures have their own stuff. (64x0, 32x0, ARM64) +struct PACKED THREAD_INFORMATION_BLOCK final +{ + Kernel::Char f_Cookie[kTLSCookieLen]{0}; //! Thread magic number. + Kernel::VoidPtr f_ThreadRecord{nullptr}; //! Thread information record. +}; + +///! @brief Cookie Sanity check. +Kernel::Boolean tls_check_tib(THREAD_INFORMATION_BLOCK* the_tib); + +///! @brief new ptr syscall. +template <typename T> +T* tls_new_ptr(void) noexcept; + +///! @brief delete ptr syscall. +template <typename T> +Kernel::Boolean tls_delete_ptr(T* ptr) noexcept; + +template <typename T, typename... Args> +T* tls_new_class(Args&&... args); + +/// @brief TLS install TIB and PIB. (syscall) +EXTERN_C Kernel::Void rt_install_tib(THREAD_INFORMATION_BLOCK* TIB, THREAD_INFORMATION_BLOCK* PIB); + +/// @brief TLS check (syscall) +EXTERN_C Kernel::Bool tls_check_syscall_impl(Kernel::VoidPtr TIB) noexcept; + +#include <KernelKit/ThreadLocalStorage.inl> + +// last rev 7/7/24 + +#endif /* ifndef _KERNELKIT_TLS_HPP */ diff --git a/dev/zka/KernelKit/ThreadLocalStorage.inl b/dev/zka/KernelKit/ThreadLocalStorage.inl new file mode 100644 index 00000000..7a1ef247 --- /dev/null +++ b/dev/zka/KernelKit/ThreadLocalStorage.inl @@ -0,0 +1,74 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +//! @file ThreadLocalStorage.inl +//! @brief Allocate resources from the process's heap storage. + +#ifndef _INC_PROCESS_SCHEDULER_HXX_ +#include <KernelKit/UserProcessScheduler.hxx> +#endif + +template <typename T> +inline T* tls_new_ptr(void) noexcept +{ + using namespace Kernel; + + auto ref_process = UserProcessScheduler::The().CurrentProcess(); + MUST_PASS(ref_process); + + T* pointer = (T*)ref_process.Leak().New(sizeof(T)); + return pointer; +} + +//! @brief TLS delete implementation. +template <typename T> +inline Kernel::Bool tls_delete_ptr(T* ptr) noexcept +{ + if (!ptr) + return false; + + using namespace Kernel; + + auto ref_process = UserProcessScheduler::The().CurrentProcess(); + MUST_PASS(ref_process); + + return ref_process.Leak().Delete(ptr, sizeof(T)); +} + +/// @brief Allocate a C++ class, and then call the constructor of it. +/// @tparam T +/// @tparam ...Args +/// @param ...args +/// @return +template <typename T, typename... Args> +T* tls_new_class(Args&&... args) +{ + T* ptr = tls_new_ptr<T>(); + + using namespace Kernel; + + if (ptr) + { + *ptr = T(forward(args)...); + return ptr; + } + + return nullptr; +} + +/// @brief Delete a C++ class (call constructor first.) +/// @tparam T +/// @param ptr +/// @return +template <typename T> +inline Kernel::Bool tls_delete_class(T* ptr) +{ + if (!ptr) + return false; + + ptr->~T(); + return tls_delete_ptr(ptr); +} diff --git a/dev/zka/KernelKit/Timer.hxx b/dev/zka/KernelKit/Timer.hxx new file mode 100644 index 00000000..3d997848 --- /dev/null +++ b/dev/zka/KernelKit/Timer.hxx @@ -0,0 +1,82 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include <ArchKit/ArchKit.hxx> +#include <CompilerKit/CompilerKit.hxx> +#include <KernelKit/LPC.hxx> + +namespace Kernel +{ + class SoftwareTimer; + class TimerInterface; + + class TimerInterface + { + public: + /// @brief Default constructor + explicit TimerInterface() = default; + virtual ~TimerInterface() = default; + + public: + ZKA_COPY_DEFAULT(TimerInterface); + + public: + virtual Int32 Wait() noexcept; + }; + + class SoftwareTimer final : public TimerInterface + { + public: + explicit SoftwareTimer(Int64 seconds); + ~SoftwareTimer() override; + + public: + ZKA_COPY_DEFAULT(SoftwareTimer); + + public: + Int32 Wait() noexcept override; + + private: + IntPtr* fDigitalTimer{nullptr}; + Int64 fWaitFor{0}; + }; + + class HardwareTimer final : public TimerInterface + { + public: + explicit HardwareTimer(Int64 seconds); + ~HardwareTimer() override; + + public: + ZKA_COPY_DEFAULT(HardwareTimer); + + public: + Int32 Wait() noexcept override; + + private: + IntPtr* fDigitalTimer{nullptr}; + Int64 fWaitFor{0}; + }; + + inline Int64 Milliseconds(Int64 time) + { + if (time < 0) + return 0; + + // TODO: nanoseconds maybe? + return 1000 * 1000 * time; + } + + inline Int64 Seconds(Int64 time) + { + if (time < 0) + return 0; + + return 1000 * Milliseconds(time); + } +} // namespace Kernel diff --git a/dev/zka/KernelKit/User.hxx b/dev/zka/KernelKit/User.hxx new file mode 100644 index 00000000..ce16576b --- /dev/null +++ b/dev/zka/KernelKit/User.hxx @@ -0,0 +1,76 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef _INC_USER_HXX_ +#define _INC_USER_HXX_ + +#include <CompilerKit/CompilerKit.hxx> +#include <KernelKit/LPC.hxx> +#include <NewKit/String.hxx> +#include <NewKit/Defines.hxx> + +// user mode users. +#define kSuperUser "ZKA USER\\SUPER" +#define kGuestUser "ZKA USER\\GUEST" + +#define kUsersFile "\\Users\\$UsrRcrd" +#define kUsersDir "\\Users\\" + +#define kMaxUserNameLen (255) +#define kMaxUserTokenLen (255) + +namespace Kernel +{ + class User; + + enum class RingKind + { + kRingStdUser = 1, + kRingSuperUser = 2, + kRingGuestUser = 5, + kRingCount = 3, + }; + + class User final + { + public: + explicit User() = delete; + + User(const Int32& sel, const Char* userName); + User(const RingKind& kind, const Char* userName); + + ~User(); + + public: + ZKA_COPY_DEFAULT(User) + + public: + bool operator==(const User& lhs); + bool operator!=(const User& lhs); + + public: + /// @brief Get software ring + const RingKind& Ring() noexcept; + + /// @brief Get user name + Char* Name() noexcept; + + /// @brief Is he a standard user? + Bool IsStdUser() noexcept; + + /// @brief Is she a super user? + Bool IsSuperUser() noexcept; + + Bool TrySave(const Char* password) noexcept; + + private: + RingKind fRing{RingKind::kRingStdUser}; + Char fUserName[kMaxUserNameLen] = {0}; + Char fUserToken[kMaxUserTokenLen] = {0}; + }; +} // namespace Kernel + +#endif /* ifndef _INC_USER_HXX_ */ diff --git a/dev/zka/KernelKit/UserProcessScheduler.hxx b/dev/zka/KernelKit/UserProcessScheduler.hxx new file mode 100644 index 00000000..3a6f03a1 --- /dev/null +++ b/dev/zka/KernelKit/UserProcessScheduler.hxx @@ -0,0 +1,331 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef _INC_PROCESS_SCHEDULER_HXX_ +#define _INC_PROCESS_SCHEDULER_HXX_ + +#include <ArchKit/ArchKit.hxx> +#include <KernelKit/LockDelegate.hxx> +#include <KernelKit/User.hxx> +#include <NewKit/MutableArray.hxx> + +#define kSchedMinMicroTime (AffinityKind::kStandard) +#define kSchedInvalidPID (-1) +#define kSchedProcessLimitPerTeam (16U) + +//////////////////////////////////////////////////// + +// LAST REV: Mon Feb 12 13:52:01 CET 2024 + +//////////////////////////////////////////////////// + +namespace Kernel +{ + //! @note Forward declarations. + + class UserProcess; + class IPEFDLLObject; + class UserProcessTeam; + class UserProcessScheduler; + class UserProcessHelper; + + //! @brief UserProcess identifier. + typedef Int64 ProcessID; + + //! @brief UserProcess name length. + inline constexpr SizeT kProcessLen = 256U; + + //! @brief UserProcess status enum. + enum class ProcessStatusKind : Int32 + { + kStarting, + kRunning, + kKilled, + kFrozen, + kDead + }; + + //! @brief Affinity is the amount of nano-seconds this process is going + //! to run. + enum class AffinityKind : Int32 + { + kRealTime = 500, + kVeryHigh = 250, + kHigh = 200, + kStandard = 1000, + kLowUsage = 1500, + kVeryLowUsage = 2000, + }; + + // operator overloading. + + inline bool operator<(AffinityKind lhs, AffinityKind rhs) + { + Int32 lhs_int = static_cast<Int>(lhs); + Int32 rhs_int = static_cast<Int>(rhs); + + return lhs_int < rhs_int; + } + + inline bool operator>(AffinityKind lhs, AffinityKind rhs) + { + Int32 lhs_int = static_cast<Int>(lhs); + Int32 rhs_int = static_cast<Int>(rhs); + + return lhs_int > rhs_int; + } + + inline bool operator<=(AffinityKind lhs, AffinityKind rhs) + { + Int32 lhs_int = static_cast<Int>(lhs); + Int32 rhs_int = static_cast<Int>(rhs); + + return lhs_int <= rhs_int; + } + + inline bool operator>=(AffinityKind lhs, AffinityKind rhs) + { + Int32 lhs_int = static_cast<Int>(lhs); + Int32 rhs_int = static_cast<Int>(rhs); + + return lhs_int >= rhs_int; + } + + // end of operator overloading. + + enum ProcessSubsystemEnum + { + eProcessSubsystemSecurity, + eProcessSubsystemNative, + eProcessSubsystemInvalid, + eProcessSubsystemCount, + }; + + using ProcessSubsystem = ProcessSubsystemEnum; + using ProcessTime = UInt64; + using PID = Int64; + + // for permission manager, tells where we run the code. + enum class ProcessLevelRing : Int32 + { + kRingStdUser = 1, + kRingSuperUser = 2, + kRingGuestUser = 5, + kRingCount = 5, + }; + + // Helper types. + using ImagePtr = VoidPtr; + using HeapPtrKind = VoidPtr; + + /// @name UserProcess + /// @brief User process block. + /// Holds information about the running process/thread. + struct UserProcess final + { + public: + explicit UserProcess(VoidPtr startImage = nullptr) + : Image(startImage) + { + } + + ~UserProcess() = default; + + ZKA_COPY_DEFAULT(UserProcess) + + public: + Void SetImageStart(VoidPtr imageStart) noexcept; + const UInt32& GetExitCode() noexcept; + + public: + Char Name[kProcessLen] = {"PROCESS #0 (TEAM 0)"}; + ProcessSubsystem SubSystem{ProcessSubsystem::eProcessSubsystemInvalid}; + User* Owner{nullptr}; + HAL::StackFramePtr StackFrame{nullptr}; + AffinityKind Affinity{AffinityKind::kStandard}; + ProcessStatusKind Status{ProcessStatusKind::kDead}; + UInt8* StackReserve{nullptr}; + + // Memory, images pointers. + ImagePtr Image{nullptr}; + + SizeT StackSize{mib_cast(8)}; + + //! @brief Shared library handle, reserved for kDLLKind types of executables only. + IPEFDLLObject* DLLPtr{nullptr}; + + /// @brief Parent process, reserved for threads only. + UserProcess* Parent{nullptr}; + + // Memory usage. + SizeT MemoryCursor{0}; + SizeT MemoryLimit{gib_cast(128)}; + + struct PROCESS_MEMORY_ENTRY + { + VoidPtr MemoryEntry; + + struct PROCESS_MEMORY_ENTRY* MemoryPrev; + struct PROCESS_MEMORY_ENTRY* MemoryNext; + }* MemoryEntryList{nullptr}; + + SizeT MemoryPD{0}; + + enum + { + kExeKind = 1, + kDLLKind = 2, + kKindCount, + }; + + ProcessTime PTime{0}; + PID ProcessId{kSchedInvalidPID}; + Int32 Kind{kExeKind}; + + public: + //! @brief boolean operator, check status. + operator bool() + { + return Status != ProcessStatusKind::kDead; + } + + ///! @brief Crashes the app, exits with code ~0. + Void Crash(); + + ///! @brief Exits the app. + Void Exit(const Int32& exit_code = 0); + + ///! @brief TLS allocate. + ///! @param sz size of new ptr. + VoidPtr New(const SizeT& sz); + + ///! @brief TLS free. + ///! @param ptr the pointer to free. + ///! @param sz the size of it. + Boolean Delete(VoidPtr ptr, const SizeT& sz); + + ///! @brief Wakes up threads. + Void Wake(const bool wakeup = false); + + // UserProcess getters. + public: + ///! @brief Get the process's name + ///! @example 'C Runtime Library' + const Char* GetProcessName() noexcept; + + //! @brief return local error code of process. + //! @return Int32 local error code. + Int32& GetLocalCode() noexcept; + + const User* GetOwner() noexcept; + const ProcessStatusKind& GetStatus() noexcept; + const AffinityKind& GetAffinity() noexcept; + + private: + UInt32 fLastExitCode{0}; + Int32 fLocalCode{0}; + + friend UserProcessScheduler; + friend UserProcessHelper; + }; + + /// \brief Processs Team (contains multiple processes inside it.) + /// Equivalent to a process batch + class UserProcessTeam final + { + public: + explicit UserProcessTeam() = default; + ~UserProcessTeam() = default; + + ZKA_COPY_DEFAULT(UserProcessTeam); + + Array<UserProcess, kSchedProcessLimitPerTeam>& AsArray(); + Ref<UserProcess>& AsRef(); + ProcessID& Id() noexcept; + + public: + Array<UserProcess, kSchedProcessLimitPerTeam> mProcessList; + Ref<UserProcess> mCurrentProcess; + SizeT mProcessAmount{0}; + ProcessID mTeamId{0}; + }; + + using UserProcessPtr = UserProcess*; + + /// @brief UserProcess scheduler class. + /// The main class which you call to schedule processes. + class UserProcessScheduler final : public ISchedulerObject + { + friend class UserProcessHelper; + + public: + explicit UserProcessScheduler() = default; + + ~UserProcessScheduler() = default; + + ZKA_COPY_DEFAULT(UserProcessScheduler) + + operator bool(); + bool operator!(); + + public: + UserProcessTeam& CurrentTeam(); + + public: + SizeT Add(UserProcess processRef); + Bool Remove(ProcessID processSlot); + + const Bool IsUser() override + { + return Yes; + } + + const Bool IsKernel() override + { + return No; + } + + const Bool HasMP() override + { + return kHandoverHeader->f_HardwareTables.f_MultiProcessingEnabled; + } + + public: + Ref<UserProcess>& CurrentProcess(); + SizeT Run() noexcept; + + public: + STATIC UserProcessScheduler& The(); + + private: + UserProcessTeam mTeam; + }; + + /* + * \brief UserProcess helper class, which contains needed utilities for the scheduler. + */ + + class UserProcessHelper final + { + public: + STATIC bool Switch(VoidPtr image_ptr, UInt8* stack_ptr, HAL::StackFramePtr frame_ptr, const PID& new_pid); + STATIC bool CanBeScheduled(const UserProcess& process); + STATIC PID& TheCurrentPID(); + STATIC SizeT StartScheduling(); + }; + + const UInt32& sched_get_exit_code(void) noexcept; +} // namespace Kernel + +#include <KernelKit/ThreadLocalStorage.hxx> + +//////////////////////////////////////////////////// + +// END + +//////////////////////////////////////////////////// + +#endif /* ifndef _INC_PROCESS_SCHEDULER_HXX_ */ diff --git a/dev/zka/KernelKit/XCOFF.hxx b/dev/zka/KernelKit/XCOFF.hxx new file mode 100644 index 00000000..82c6dd35 --- /dev/null +++ b/dev/zka/KernelKit/XCOFF.hxx @@ -0,0 +1,51 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + + File: XCOFF.hpp + Purpose: XCOFF for Kernel. + + Revision History: + + 04/07/24: Added file (amlel) + +------------------------------------------- */ + +#ifndef __INC_XCOFF_HXX__ +#define __INC_XCOFF_HXX__ + +#include <NewKit/Defines.hxx> + +#define cXCOFF64Magic (0x01F7) + +#define cXCOFFRelFlg (0x0001) +#define cXCOFFExecutable (0x0002) +#define cXCOFFLnno (0x0004) +#define cXCOFFLSyms (0x0008) + +struct XCoffFileHeader; +struct XCoffForkHeader; + +/// @brief XCoff file header, meant for POWER apps. +typedef struct XCoffFileHeader +{ + Kernel::UInt16 fMagic; + Kernel::UInt16 fTarget; + Kernel::UInt16 fNumSecs; + Kernel::UInt32 fTimeDat; + Kernel::UIntPtr fSymPtr; + Kernel::UInt32 fNumSyms; + Kernel::UInt16 fOptHdr; // ?: Number of bytes in optional header +} XCoffFileHeader32, XCoffFileHeader64; + +#define cForkNameLen (255) + +/// @brief This the executable manifest fork. +typedef struct XCoffForkHeader +{ + Kernel::Char fPropertiesXMLFork[cForkNameLen]; + Kernel::Char fDynamicLoaderFork[cForkNameLen]; + Kernel::Char fCodeSignFork[cForkNameLen]; +} XCoffForkHeader; + +#endif // ifndef __INC_XCOFF_HXX__ |
