From f3d931aa7cfaf96baef8383b59a8938779541ee7 Mon Sep 17 00:00:00 2001 From: Amlal EL Mahrouss Date: Thu, 15 Aug 2024 18:35:34 +0200 Subject: [IMP] Moved source code into dev/ folder. Signed-off-by: Amlal EL Mahrouss --- dev/Kernel/KernelKit/CodeManager.hxx | 31 ++ dev/Kernel/KernelKit/DebugOutput.hxx | 190 +++++++++++++ dev/Kernel/KernelKit/Defines.hxx | 11 + dev/Kernel/KernelKit/DeviceManager.hxx | 129 +++++++++ dev/Kernel/KernelKit/DriveManager.hxx | 149 ++++++++++ dev/Kernel/KernelKit/FileManager.hxx | 419 ++++++++++++++++++++++++++++ dev/Kernel/KernelKit/Framebuffer.hxx | 85 ++++++ dev/Kernel/KernelKit/Heap.hxx | 51 ++++ dev/Kernel/KernelKit/LPC.hxx | 56 ++++ dev/Kernel/KernelKit/LoaderInterface.hxx | 33 +++ dev/Kernel/KernelKit/LockDelegate.hxx | 67 +++++ dev/Kernel/KernelKit/MP.hxx | 130 +++++++++ dev/Kernel/KernelKit/MSDOS.hxx | 52 ++++ dev/Kernel/KernelKit/PCI/Database.hxx | 38 +++ dev/Kernel/KernelKit/PCI/Device.hxx | 79 ++++++ dev/Kernel/KernelKit/PCI/Dma.hxx | 81 ++++++ dev/Kernel/KernelKit/PCI/Dma.inl | 20 ++ dev/Kernel/KernelKit/PCI/Express.hxx | 11 + dev/Kernel/KernelKit/PCI/IO-Impl-AMD64.inl | 54 ++++ dev/Kernel/KernelKit/PCI/IO.hxx | 59 ++++ dev/Kernel/KernelKit/PCI/Iterator.hxx | 43 +++ dev/Kernel/KernelKit/PCI/PCI.hxx | 59 ++++ dev/Kernel/KernelKit/PE.hxx | 137 +++++++++ dev/Kernel/KernelKit/PECodeManager.hxx | 24 ++ dev/Kernel/KernelKit/PEF.hxx | 115 ++++++++ dev/Kernel/KernelKit/PEFCodeManager.hxx | 62 ++++ dev/Kernel/KernelKit/PEFSharedObject.hxx | 118 ++++++++ dev/Kernel/KernelKit/ProcessHeap.hxx | 44 +++ dev/Kernel/KernelKit/ProcessScheduler.hxx | 302 ++++++++++++++++++++ dev/Kernel/KernelKit/RLE.hxx | 15 + dev/Kernel/KernelKit/Semaphore.hxx | 43 +++ dev/Kernel/KernelKit/ThreadLocalStorage.hxx | 59 ++++ dev/Kernel/KernelKit/ThreadLocalStorage.inl | 74 +++++ dev/Kernel/KernelKit/Timer.hxx | 64 +++++ dev/Kernel/KernelKit/User.hxx | 101 +++++++ dev/Kernel/KernelKit/XCOFF.hxx | 51 ++++ dev/Kernel/KernelKit/compile_flags.txt | 6 + 37 files changed, 3062 insertions(+) create mode 100644 dev/Kernel/KernelKit/CodeManager.hxx create mode 100644 dev/Kernel/KernelKit/DebugOutput.hxx create mode 100644 dev/Kernel/KernelKit/Defines.hxx create mode 100644 dev/Kernel/KernelKit/DeviceManager.hxx create mode 100644 dev/Kernel/KernelKit/DriveManager.hxx create mode 100644 dev/Kernel/KernelKit/FileManager.hxx create mode 100644 dev/Kernel/KernelKit/Framebuffer.hxx create mode 100644 dev/Kernel/KernelKit/Heap.hxx create mode 100644 dev/Kernel/KernelKit/LPC.hxx create mode 100644 dev/Kernel/KernelKit/LoaderInterface.hxx create mode 100644 dev/Kernel/KernelKit/LockDelegate.hxx create mode 100644 dev/Kernel/KernelKit/MP.hxx create mode 100644 dev/Kernel/KernelKit/MSDOS.hxx create mode 100644 dev/Kernel/KernelKit/PCI/Database.hxx create mode 100644 dev/Kernel/KernelKit/PCI/Device.hxx create mode 100644 dev/Kernel/KernelKit/PCI/Dma.hxx create mode 100644 dev/Kernel/KernelKit/PCI/Dma.inl create mode 100644 dev/Kernel/KernelKit/PCI/Express.hxx create mode 100644 dev/Kernel/KernelKit/PCI/IO-Impl-AMD64.inl create mode 100644 dev/Kernel/KernelKit/PCI/IO.hxx create mode 100644 dev/Kernel/KernelKit/PCI/Iterator.hxx create mode 100644 dev/Kernel/KernelKit/PCI/PCI.hxx create mode 100644 dev/Kernel/KernelKit/PE.hxx create mode 100644 dev/Kernel/KernelKit/PECodeManager.hxx create mode 100644 dev/Kernel/KernelKit/PEF.hxx create mode 100644 dev/Kernel/KernelKit/PEFCodeManager.hxx create mode 100644 dev/Kernel/KernelKit/PEFSharedObject.hxx create mode 100644 dev/Kernel/KernelKit/ProcessHeap.hxx create mode 100644 dev/Kernel/KernelKit/ProcessScheduler.hxx create mode 100644 dev/Kernel/KernelKit/RLE.hxx create mode 100644 dev/Kernel/KernelKit/Semaphore.hxx create mode 100644 dev/Kernel/KernelKit/ThreadLocalStorage.hxx create mode 100644 dev/Kernel/KernelKit/ThreadLocalStorage.inl create mode 100644 dev/Kernel/KernelKit/Timer.hxx create mode 100644 dev/Kernel/KernelKit/User.hxx create mode 100644 dev/Kernel/KernelKit/XCOFF.hxx create mode 100644 dev/Kernel/KernelKit/compile_flags.txt (limited to 'dev/Kernel/KernelKit') diff --git a/dev/Kernel/KernelKit/CodeManager.hxx b/dev/Kernel/KernelKit/CodeManager.hxx new file mode 100644 index 00000000..08e97e60 --- /dev/null +++ b/dev/Kernel/KernelKit/CodeManager.hxx @@ -0,0 +1,31 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + + File: CodeManager.hpp + Purpose: Code Manager and Shared Objects. + + Revision History: + + 30/01/24: Added file (amlel) + 3/8/24: Add UPP struct. + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +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 execute_from_image(MainKind main, const char* processName) noexcept; +} // namespace Kernel \ No newline at end of file diff --git a/dev/Kernel/KernelKit/DebugOutput.hxx b/dev/Kernel/KernelKit/DebugOutput.hxx new file mode 100644 index 00000000..2205acfe --- /dev/null +++ b/dev/Kernel/KernelKit/DebugOutput.hxx @@ -0,0 +1,190 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include + +#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 + { + public: + TerminalDevice(void (*print)(const Char*), void (*get)(const Char*)) + : DeviceInterface(print, get) + { + } + + virtual ~TerminalDevice() = default; + + /// @brief returns device name (terminal name) + /// @return string type (const char*) + virtual const char* Name() const override + { + return ("TerminalDevice"); + } + + NEWOS_COPY_DEFAULT(TerminalDevice); + + STATIC TerminalDevice The() noexcept; + }; + + inline TerminalDevice end_line() + { + TerminalDevice selfTerm = TerminalDevice::The(); + selfTerm << "\r"; + return selfTerm; + } + + inline TerminalDevice carriage_return() + { + TerminalDevice selfTerm = TerminalDevice::The(); + selfTerm << "\r"; + return selfTerm; + } + + inline TerminalDevice tabulate() + { + TerminalDevice selfTerm = TerminalDevice::The(); + selfTerm << "\t"; + return selfTerm; + } + + /// @brief emulate a terminal bell, like the VT100 does. + inline TerminalDevice bell() + { + TerminalDevice selfTerm = TerminalDevice::The(); + selfTerm << "\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 << 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 << buf; + return term; + } + } // namespace Detail + + inline TerminalDevice hex_number(const Long& x) + { + TerminalDevice selfTerm = TerminalDevice::The(); + + selfTerm << "0x"; + Detail::_write_number_hex(x, selfTerm); + + 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 TerminalDevice::The() +#define endl kcout << Kernel::end_line() diff --git a/dev/Kernel/KernelKit/Defines.hxx b/dev/Kernel/KernelKit/Defines.hxx new file mode 100644 index 00000000..e76b1b2f --- /dev/null +++ b/dev/Kernel/KernelKit/Defines.hxx @@ -0,0 +1,11 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include + +#define KERNELKIT_VERSION "1.02" diff --git a/dev/Kernel/KernelKit/DeviceManager.hxx b/dev/Kernel/KernelKit/DeviceManager.hxx new file mode 100644 index 00000000..d9497da8 --- /dev/null +++ b/dev/Kernel/KernelKit/DeviceManager.hxx @@ -0,0 +1,129 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +/* ------------------------------------------- + + Revision History: + + 31/01/24: Add kDeviceCnt (amlel) + + ------------------------------------------- */ + +#pragma once + +/* Kernel device interface manager. */ +/* @file KernelKit/DeviceManager.hpp */ +/* @brief Device abstraction and I/O buffer. */ + +#include +#include + +// Last Rev +// Wed, Apr 3, 2024 9:09:41 AM + +namespace Kernel +{ + template + class DeviceInterface; + + template + class DeviceInterface + { + public: + explicit DeviceInterface(void (*Out)(T), void (*In)(T)) + : fOut(Out), fIn(In) + { + } + + virtual ~DeviceInterface() = default; + + public: + DeviceInterface& operator=(const DeviceInterface&) = default; + DeviceInterface(const DeviceInterface&) = default; + + public: + virtual DeviceInterface& operator<<(T Data) + { + fOut(Data); + return *this; + } + + virtual DeviceInterface& 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 + 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&) = default; + IOBuf(const IOBuf&) = default; + + ~IOBuf() = default; + + public: + template + R operator->() const + { + return fData; + } + + template + 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/Kernel/KernelKit/DriveManager.hxx b/dev/Kernel/KernelKit/DriveManager.hxx new file mode 100644 index 00000000..6485f995 --- /dev/null +++ b/dev/Kernel/KernelKit/DriveManager.hxx @@ -0,0 +1,149 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef __INC_DRIVE_MANAGER_HXX__ +#define __INC_DRIVE_MANAGER_HXX__ + +#include +#include +#include +#include +#include +#include +#include + +#define kDriveManagerCount (4U) + +#define kDriveInvalidID (-1) +#define kDriveNameLen (32) + +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); + 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; + + NEWOS_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 << "newoskrnl: 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/Kernel/KernelKit/FileManager.hxx b/dev/Kernel/KernelKit/FileManager.hxx new file mode 100644 index 00000000..68fa1eb5 --- /dev/null +++ b/dev/Kernel/KernelKit/FileManager.hxx @@ -0,0 +1,419 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +/* ------------------------------------------- + + Revision History: + + 31/01/24: Update documentation (amlel) + 05/07/24: NewFS support, and fork support, updated constants and specs + as well. + + ------------------------------------------- */ + +#pragma once + +#ifdef __FSKIT_USE_NEWFS__ +#include +#endif // __FSKIT_USE_NEWFS__ + +#include +#include +#include +#include +#include +#include +#include + +/// @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(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, + }; + + /// @brief filesystem node generic type. + struct PACKED FMNode final + { + VoidPtr _Unused; + }; + + typedef FMNode* NodePtr; + + /** + @brief Filesystem Manager Interface class + @brief Used to provide common I/O for a specific filesystem. +*/ + class FilesystemManagerInterface + { + public: + explicit FilesystemManagerInterface() = default; + virtual ~FilesystemManagerInterface() = default; + + public: + NEWOS_COPY_DEFAULT(FilesystemManagerInterface); + + public: + /// @brief Mounts a new filesystem into an active state. + /// @param interface the filesystem interface + /// @return + static bool Mount(FilesystemManagerInterface* interface); + + /// @brief Unmounts the active filesystem + /// @return + static FilesystemManagerInterface* Unmount(); + + /// @brief Getter, gets the active filesystem. + /// @return + static FilesystemManagerInterface* 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; + + 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_NEWFS__ + /** + * @brief Based of FilesystemManagerInterface, takes care of managing NewFS + * disks. + */ + class NewFilesystemManager final : public FilesystemManagerInterface + { + public: + explicit NewFilesystemManager(); + ~NewFilesystemManager() override; + + public: + NEWOS_COPY_DEFAULT(NewFilesystemManager); + + public: + NodePtr Create(const Char* path) override; + NodePtr CreateAlias(const Char* path) override; + NodePtr CreateDirectory(const Char* path) override; + + public: + bool Remove(const Char* path) override; + NodePtr Open(const Char* path, const Char* r) override; + Void Write(NodePtr node, VoidPtr data, Int32 flags, SizeT sz) override; + VoidPtr Read(NodePtr node, Int32 flags, SizeT sz) override; + bool Seek(NodePtr node, SizeT off) override; + SizeT Tell(NodePtr node) override; + bool Rewind(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: + void SetResourceFork(const char* forkName); + void SetDataFork(const char* forkName); + + /// @brief Get internal parser. + /// @return + NewFSParser* GetParser() noexcept; + + private: + NewFSParser* fImpl{nullptr}; + }; + +#endif // ifdef __FSKIT_USE_NEWFS__ + + /** + * Usable FileStream + * @tparam Encoding file encoding (char, wchar_t...) + * @tparam FSClass Filesystem contract who takes care of it. + */ + template + class FileStream final + { + public: + explicit FileStream(const Encoding* path, const Encoding* restrict_type); + ~FileStream(); + + public: + FileStream& operator=(const FileStream&); + FileStream(const FileStream&); + + public: + ErrorOr WriteAll(const VoidPtr data) noexcept + { + if (this->fFileRestrict != eRestrictReadWrite && + this->fFileRestrict != eRestrictReadWriteBinary && + this->fFileRestrict != eRestrictWrite && + this->fFileRestrict != eRestrictWriteBinary) + return ErrorOr(kErrorInvalidData); + + if (data == nullptr) + return ErrorOr(kErrorInvalidData); + + auto man = FSClass::GetMounted(); + + if (man) + { + man->Write(fFile, data, cFileWriteAll); + return ErrorOr(0); + } + + return ErrorOr(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 WriteAll(const char* fName, const VoidPtr data) noexcept + { + if (this->fFileRestrict != eRestrictReadWrite && + this->fFileRestrict != eRestrictReadWriteBinary && + this->fFileRestrict != eRestrictWrite && + this->fFileRestrict != eRestrictWriteBinary) + return ErrorOr(kErrorInvalidData); + + if (data == nullptr) + return ErrorOr(kErrorInvalidData); + + auto man = FSClass::GetMounted(); + + if (man) + { + man->Write(fName, fFile, data, cFileWriteAll); + return ErrorOr(0); + } + + return ErrorOr(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(fMime); + } + + enum + { + eRestrictRead, + eRestrictReadBinary, + eRestrictWrite, + eRestrictWriteBinary, + eRestrictReadWrite, + eRestrictReadWriteBinary, + }; + + private: + NodePtr fFile{nullptr}; + Int32 fFileRestrict{}; + const Char* fMime{cFileMimeGeneric}; + }; + + using FileStreamUTF8 = FileStream; + using FileStreamUTF16 = FileStream; + + typedef UInt64 CursorType; + + /// @brief constructor + template + FileStream::FileStream(const Encoding* path, + const Encoding* restrict_type) + : fFile(Class::GetMounted()->Open(path, restrict_type)) + { + static const auto cLength = 255; + + struct StringMap final + { + Char fRestrict[cLength]; + Int32 fMappedTo; + }; + + const SizeT cRestrictCount = cRestrictMax; + const StringMap 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 << "newoskrnl: new file: " << path << ".\r"; + } + + /// @brief destructor + template + FileStream::~FileStream() + { + delete fFile; + } +} // namespace Kernel diff --git a/dev/Kernel/KernelKit/Framebuffer.hxx b/dev/Kernel/KernelKit/Framebuffer.hxx new file mode 100644 index 00000000..dac9b514 --- /dev/null +++ b/dev/Kernel/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 +#include + +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& 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& 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 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/Kernel/KernelKit/Heap.hxx b/dev/Kernel/KernelKit/Heap.hxx new file mode 100644 index 00000000..0046fc58 --- /dev/null +++ b/dev/Kernel/KernelKit/Heap.hxx @@ -0,0 +1,51 @@ +/* ------------------------------------------- + + 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 + +namespace Kernel +{ + /// @brief Declare pointer as free. + /// @param allocatedPtr the pointer. + /// @return + Int32 mm_delete_ke_heap(voidPtr allocatedPtr); + + /// @brief Declare a new size for allocatedPtr. + /// @param allocatedPtr the pointer. + /// @return + voidPtr mm_realloc_ke_heap(voidPtr allocatedPtr, SizeT newSz); + + /// @brief Check if pointer is a valid kernel pointer. + /// @param allocatedPtr the pointer + /// @return if it exists. + Boolean mm_is_valid_heap(VoidPtr allocatedPtr); + + /// @brief allocate chunk of memory. + /// @param sz size of pointer + /// @param rw read write (true to enable it) + /// @param user is it accesible by user processes? + /// @return The newly allocated pointer. + voidPtr mm_new_ke_heap(const SizeT sz, const Bool rw, const Bool user); + + /// @brief Protect the heap with a CRC value. + /// @param allocatedPtr pointer. + /// @return if it valid: point has crc now., otherwise fail. + Boolean mm_protect_ke_heap(VoidPtr allocatedPtr); + + /// @brief Makes a kernel heap page. + /// @param allocatedPtr the page pointer. + /// @return + Int32 mm_make_ke_page(VoidPtr allocatedPtr); +} // namespace Kernel + +#endif // !_INC_KERNEL_HEAP_HXX_ diff --git a/dev/Kernel/KernelKit/LPC.hxx b/dev/Kernel/KernelKit/LPC.hxx new file mode 100644 index 00000000..fec1d637 --- /dev/null +++ b/dev/Kernel/KernelKit/LPC.hxx @@ -0,0 +1,56 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include + +/// @file LPC.hxx +/// @brief Local Process Codes. + +#define ErrLocalIsOk() (Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().GetLocalCode() == Kernel::kErrorSuccess) +#define ErrLocalFailed() (Kernel::ProcessScheduler::The().Leak().TheCurrent().Leak().GetLocalCode() != Kernel::kErrorSuccess) +#define ErrLocal() Kernel::ProcessScheduler::The().Leak().TheCurrent().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; + + Void err_bug_check_raise(void) noexcept; + Boolean err_bug_check(void) noexcept; +} // namespace Kernel diff --git a/dev/Kernel/KernelKit/LoaderInterface.hxx b/dev/Kernel/KernelKit/LoaderInterface.hxx new file mode 100644 index 00000000..7dcf41d4 --- /dev/null +++ b/dev/Kernel/KernelKit/LoaderInterface.hxx @@ -0,0 +1,33 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include + +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; + + NEWOS_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 FindStart() = 0; + virtual _Output VoidPtr FindSymbol(_Input const char* name, _Input Int32 kind) = 0; + }; +} // namespace Kernel diff --git a/dev/Kernel/KernelKit/LockDelegate.hxx b/dev/Kernel/KernelKit/LockDelegate.hxx new file mode 100644 index 00000000..d678e3d4 --- /dev/null +++ b/dev/Kernel/KernelKit/LockDelegate.hxx @@ -0,0 +1,67 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include +#include + +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 + 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 fLockStatus; + }; +} // namespace Kernel diff --git a/dev/Kernel/KernelKit/MP.hxx b/dev/Kernel/KernelKit/MP.hxx new file mode 100644 index 00000000..bc94102e --- /dev/null +++ b/dev/Kernel/KernelKit/MP.hxx @@ -0,0 +1,130 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef __INC_MP_MANAGER_HPP__ +#define __INC_MP_MANAGER_HPP__ + +#include +#include +#include + +/// @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 SmThreadKind; + typedef ThreadID SmThreadID; + + /// + /// \name HardwareThread + /// \brief Abstraction over the CPU's core, used to run processes or threads. + /// + + class HardwareThread final + { + public: + explicit HardwareThread(); + ~HardwareThread(); + + public: + NEWOS_COPY_DEFAULT(HardwareThread) + + public: + operator bool(); + + public: + void Wake(const bool wakeup = false) noexcept; + void Busy(const bool busy = false) noexcept; + + public: + bool Switch(HAL::StackFrame* stack); + bool IsWakeup() noexcept; + + public: + HAL::StackFrame* StackFrame() noexcept; + const ThreadKind& Kind() noexcept; + bool IsBusy() noexcept; + const ThreadID& ID() noexcept; + + private: + HAL::StackFrame* fStack{nullptr}; + ThreadKind fKind{ThreadKind::kInvalidHart}; + ThreadID fID{0}; + ProcessID fSourcePID{-1}; + bool fWakeup{false}; + bool fBusy{false}; + + private: + friend class HardwareThreadScheduler; + }; + + /// + /// \name HardwareThreadScheduler + /// \brief Class to manage the thread scheduling. + /// + + class HardwareThreadScheduler final + { + private: + explicit HardwareThreadScheduler(); + + public: + ~HardwareThreadScheduler(); + NEWOS_COPY_DEFAULT(HardwareThreadScheduler); + + public: + bool Switch(HAL::StackFramePtr the); + HAL::StackFramePtr Leak() noexcept; + + public: + Ref operator[](const SizeT& idx); + bool operator!() noexcept; + operator bool() noexcept; + + public: + /// @brief Shared instance of the MP Manager. + /// @return the reference to the mp manager class. + static Ref The(); + + public: + /// @brief Returns the amount of threads present in the system. + /// @returns SizeT the amount of cores present. + SizeT Count() noexcept; + + private: + Array 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/Kernel/KernelKit/MSDOS.hxx b/dev/Kernel/KernelKit/MSDOS.hxx new file mode 100644 index 00000000..6ce11cbd --- /dev/null +++ b/dev/Kernel/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 +#include + +// 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/Kernel/KernelKit/PCI/Database.hxx b/dev/Kernel/KernelKit/PCI/Database.hxx new file mode 100644 index 00000000..c5f3c953 --- /dev/null +++ b/dev/Kernel/KernelKit/PCI/Database.hxx @@ -0,0 +1,38 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ +#pragma once + +#include +#include + +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/Kernel/KernelKit/PCI/Device.hxx b/dev/Kernel/KernelKit/PCI/Device.hxx new file mode 100644 index 00000000..a562219a --- /dev/null +++ b/dev/Kernel/KernelKit/PCI/Device.hxx @@ -0,0 +1,79 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ +#pragma once + +#include + +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, UShort 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 + UInt Read(UInt bar) + { + static_assert(sizeof(T) <= 4, "64-bit PCI addressing is unsupported"); + return Read(bar, sizeof(T)); + } + + template + 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(); + + public: + void EnableMmio(); + void BecomeBusMaster(); // for PCI-DMA, PC-DMA does not need that. + + UShort Vendor(); + + private: + UShort fBus; + UShort fDevice; + UShort fFunction; + UShort fBar; + }; +} // namespace Kernel::PCI + +EXTERN_C void NewOSPCISetCfgTarget(Kernel::UInt bar); +EXTERN_C Kernel::UInt NewOSPCIReadRaw(Kernel::UInt bar); diff --git a/dev/Kernel/KernelKit/PCI/Dma.hxx b/dev/Kernel/KernelKit/PCI/Dma.hxx new file mode 100644 index 00000000..70292c19 --- /dev/null +++ b/dev/Kernel/KernelKit/PCI/Dma.hxx @@ -0,0 +1,81 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include +#include + +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 + T* operator->(); + + template + 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> Construct(OwnPtr& dma); + }; +} // namespace Kernel + +#include diff --git a/dev/Kernel/KernelKit/PCI/Dma.inl b/dev/Kernel/KernelKit/PCI/Dma.inl new file mode 100644 index 00000000..1c164af8 --- /dev/null +++ b/dev/Kernel/KernelKit/PCI/Dma.inl @@ -0,0 +1,20 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +namespace Kernel +{ + template + T* DMAWrapper::operator->() + { + return fAddress; + } + + template + T* DMAWrapper::Get(const UIntPtr offset) + { + return reinterpret_cast((UIntPtr)fAddress + offset); + } +} // namespace Kernel diff --git a/dev/Kernel/KernelKit/PCI/Express.hxx b/dev/Kernel/KernelKit/PCI/Express.hxx new file mode 100644 index 00000000..1d6a86d0 --- /dev/null +++ b/dev/Kernel/KernelKit/PCI/Express.hxx @@ -0,0 +1,11 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include + +#define PCI_EXPRESS_BUS_COUNT (4096) diff --git a/dev/Kernel/KernelKit/PCI/IO-Impl-AMD64.inl b/dev/Kernel/KernelKit/PCI/IO-Impl-AMD64.inl new file mode 100644 index 00000000..b0252e63 --- /dev/null +++ b/dev/Kernel/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 + template + T IOArray::In(SizeT index) + { + switch (sizeof(T)) + { +#ifdef __NEWOS_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 + template + void IOArray::Out(SizeT index, T value) + { + switch (sizeof(T)) + { +#ifdef __NEWOS_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/Kernel/KernelKit/PCI/IO.hxx b/dev/Kernel/KernelKit/PCI/IO.hxx new file mode 100644 index 00000000..a86bcc52 --- /dev/null +++ b/dev/Kernel/KernelKit/PCI/IO.hxx @@ -0,0 +1,59 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include + +namespace Kernel +{ + template + class IOArray final + { + public: + IOArray() = delete; + + IOArray(nullPtr) = delete; + + explicit IOArray(Array& ports) + : fPorts(ports) + { + } + ~IOArray() + { + } + + IOArray& operator=(const IOArray&) = default; + + IOArray(const IOArray&) = default; + + operator bool() + { + return !fPorts.Empty(); + } + + public: + template + T In(SizeT index); + + template + void Out(SizeT index, T value); + + private: + Array fPorts; + }; + + using IOArray16 = IOArray<16>; +} // namespace Kernel + +#ifdef __x86_64__ +#include +#else +#error Please provide platform specific code for the I/O +#endif // ifdef __x86_64__ diff --git a/dev/Kernel/KernelKit/PCI/Iterator.hxx b/dev/Kernel/KernelKit/PCI/Iterator.hxx new file mode 100644 index 00000000..5f2ca089 --- /dev/null +++ b/dev/Kernel/KernelKit/PCI/Iterator.hxx @@ -0,0 +1,43 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef __PCI_ITERATOR_HPP__ +#define __PCI_ITERATOR_HPP__ + +#include +#include +#include +#include +#include + +#define NEWOS_BUS_COUNT (256) +#define NEWOS_DEVICE_COUNT (33) +#define NEWOS_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 operator[](const Size& sz); + + private: + Array fDevices; + }; +} // namespace Kernel::PCI + +#endif // __PCI_ITERATOR_HPP__ diff --git a/dev/Kernel/KernelKit/PCI/PCI.hxx b/dev/Kernel/KernelKit/PCI/PCI.hxx new file mode 100644 index 00000000..8654defa --- /dev/null +++ b/dev/Kernel/KernelKit/PCI/PCI.hxx @@ -0,0 +1,59 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include + +#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/Kernel/KernelKit/PE.hxx b/dev/Kernel/KernelKit/PE.hxx new file mode 100644 index 00000000..11cc564e --- /dev/null +++ b/dev/Kernel/KernelKit/PE.hxx @@ -0,0 +1,137 @@ +/* ------------------------------------------- + + 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 + +#define kPeMagic 0x00004550 + +#define kMagPE32 0x010b +#define kMagPE64 0x020b + +#define kPeMachineAMD64 0x8664 +#define kPeMachineARM64 0xaa64 + +typedef struct ExecHeader 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; +} ExecHeader, *ExecHeaderPtr; + +typedef struct ExecOptionalHeader 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; +} ExecOptionalHeader, *ExecOptionalHeaderPtr; + +typedef struct ExecSectionHeader 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; +} ExecSectionHeader, *ExecSectionHeaderPtr; + +enum kExecDataDirParams +{ + kExecExport, + kExecImport, + kExecInvalid, + kExecCount, +}; + +typedef struct ExecExportDirectory +{ + 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 +} ExecExportDirectory, *ExecExportDirectoryPtr; + +typedef struct ExecImportDirectory +{ + union { + Kernel::UInt32 mCharacteristics; + Kernel::UInt32 mOriginalFirstThunk; + }; + Kernel::UInt32 mTimeDateStamp; + Kernel::UInt32 mForwarderChain; + Kernel::UInt32 mNameRva; + Kernel::UInt32 mThunkTableRva; +} ExecImportDirectory, *ExecImportDirectoryPtr; + +typedef struct ExecDataDirectory { + Kernel::UInt32 VirtualAddress; + Kernel::UInt32 Size; +} ExecDataDirectory, *ExecDataDirectoryPtr; + +typedef struct ExecImageHeader { + ExecHeader mHeader; + ExecOptionalHeader mOptHdr; +} ExecImageHeader, *ExecImageHeaderPtr; + +enum +{ + eUserSection = 0x00000020, +}; + +#endif /* ifndef __KERNELKIT_INC_PE_HXX__ */ diff --git a/dev/Kernel/KernelKit/PECodeManager.hxx b/dev/Kernel/KernelKit/PECodeManager.hxx new file mode 100644 index 00000000..f42c7c21 --- /dev/null +++ b/dev/Kernel/KernelKit/PECodeManager.hxx @@ -0,0 +1,24 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + + File: PECodeManager.hxx + Purpose: PE32+ Code Manager and Shared Objects. + + Revision History: + + 12/02/24: Added file (amlel) + +------------------------------------------- */ + +#pragma once + +//////////////////////////////////////////////////// + +// LAST REV: Mon Feb 12 13:52:01 CET 2024 + +//////////////////////////////////////////////////// + +#include +#include +#include diff --git a/dev/Kernel/KernelKit/PEF.hxx b/dev/Kernel/KernelKit/PEF.hxx new file mode 100644 index 00000000..d02cd4f9 --- /dev/null +++ b/dev/Kernel/KernelKit/PEF.hxx @@ -0,0 +1,115 @@ +/* ------------------------------------------- + + 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 +#include +#include + +#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" + +// 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/Kernel/KernelKit/PEFCodeManager.hxx b/dev/Kernel/KernelKit/PEFCodeManager.hxx new file mode 100644 index 00000000..325ca9a3 --- /dev/null +++ b/dev/Kernel/KernelKit/PEFCodeManager.hxx @@ -0,0 +1,62 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef _INC_CODE_MANAGER_PEF_HXX_ +#define _INC_CODE_MANAGER_PEF_HXX_ + +#include +#include +#include +#include + +#define kPefApplicationMime "application/x-newos-exec" + +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: + NEWOS_COPY_DEFAULT(PEFLoader); + + public: + const char* Path() override; + const char* AsString() override; + const char* MIME() override; + + public: + ErrorOr FindStart() override; + VoidPtr FindSymbol(const char* name, Int32 kind) override; + + public: + bool IsLoaded() noexcept; + + private: + OwnPtr> fFile; + Ref 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/Kernel/KernelKit/PEFSharedObject.hxx b/dev/Kernel/KernelKit/PEFSharedObject.hxx new file mode 100644 index 00000000..2ce87c1d --- /dev/null +++ b/dev/Kernel/KernelKit/PEFSharedObject.hxx @@ -0,0 +1,118 @@ +/* + * ======================================================== + * + * Kernel + * Copyright ZKA Technologies., all rights reserved. + * + * ======================================================== + */ + +#ifndef __KERNELKIT_SHARED_OBJECT_HXX__ +#define __KERNELKIT_SHARED_OBJECT_HXX__ + +#include +#include +#include +#include + +namespace Kernel +{ + /// @brief Pure implementation, missing method/function handler. + extern "C" void __mh_purecall(void); + + /** + * @brief Shared Library class + * Load library from this class + */ + class PEFSharedObjectInterface final + { + public: + struct PEF_SHARED_OBJECT_TRAITS final + { + VoidPtr fImageObject{nullptr}; + VoidPtr fImageEntrypointOffset{nullptr}; + + Bool IsValid() { return fImageObject && fImageEntrypointOffset; } + }; + + public: + explicit PEFSharedObjectInterface() = default; + ~PEFSharedObjectInterface() = default; + + public: + NEWOS_COPY_DEFAULT(PEFSharedObjectInterface); + + private: + PEF_SHARED_OBJECT_TRAITS* fMounted{nullptr}; + + public: + PEF_SHARED_OBJECT_TRAITS** GetAddressOf() + { + return &fMounted; + } + + PEF_SHARED_OBJECT_TRAITS* Get() + { + return fMounted; + } + + public: + void Mount(PEF_SHARED_OBJECT_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 + 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(fLoader->FindSymbol(symbol_name, kind)); + + if (!ret) + { + if (kind == kPefCode) + return (VoidPtr)__mh_purecall; + + return nullptr; + } + + return ret; + } + + private: + PEFLoader* fLoader{nullptr}; + }; + + typedef PEFSharedObjectInterface* SharedObjectPtr; + + EXTERN_C SharedObjectPtr rtl_init_shared_object(PROCESS_HEADER_BLOCK* header); + EXTERN_C Void rtl_fini_shared_object(PROCESS_HEADER_BLOCK* header, SharedObjectPtr lib, Bool* successful); +} // namespace Kernel + +#endif /* ifndef __KERNELKIT_SHARED_OBJECT_HXX__ */ + diff --git a/dev/Kernel/KernelKit/ProcessHeap.hxx b/dev/Kernel/KernelKit/ProcessHeap.hxx new file mode 100644 index 00000000..b6b6352c --- /dev/null +++ b/dev/Kernel/KernelKit/ProcessHeap.hxx @@ -0,0 +1,44 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +/// @version 5/11/23 +/// @file ProcessHeap.hxx +/// @brief Process heap allocator. + +#define kProcessHeapMag (0xFAF0FEF0) + +namespace Kernel +{ + typedef enum + { + /// @brief Shared heap. + kProcessHeapShared = 0x4, + /// @brief User and private heap. + kProcessHeapUser = 0x6, + /// @brief Read and Write heap. + kProcessHeapRw = 0x8, + } UserHeapFlags; + + /// @brief Allocate a process heap, no zero out is done here. + /// @param flags the heap's flags. + /// @param len_in_gib the heap in GB. + /// @return The process's heap. + VoidPtr sched_new_heap(Int32 flags, SizeT len_in_gib); + + /// @brief Frees the process heap. + /// @param pointer The process heap pointer. + /// @return status code of the freeing. + Int32 sched_free_heap(voidPtr pointer); +} // namespace Kernel diff --git a/dev/Kernel/KernelKit/ProcessScheduler.hxx b/dev/Kernel/KernelKit/ProcessScheduler.hxx new file mode 100644 index 00000000..277334cc --- /dev/null +++ b/dev/Kernel/KernelKit/ProcessScheduler.hxx @@ -0,0 +1,302 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef _INC_PROCESS_SCHEDULER_HXX_ +#define _INC_PROCESS_SCHEDULER_HXX_ + +#include +#include +#include +#include +#include + +#define kSchedMinMicroTime (AffinityKind::kStandard) +#define kSchedInvalidPID (-1) + +#define kSchedProcessLimitPerTeam (16U) + +//////////////////////////////////////////////////// + +// LAST REV: Mon Feb 12 13:52:01 CET 2024 + +//////////////////////////////////////////////////// + +namespace Kernel +{ + //! @brief Forward declarations. + struct PROCESS_HEADER_BLOCK; + + class PEFSharedObjectInterface; + class ProcessTeam; + class ProcessScheduler; + class ProcessHelper; + + //! @brief Process identifier. + typedef Int64 ProcessID; + + //! @brief Process name length. + inline constexpr SizeT kProcessLen = 256U; + + + //! @brief Process status enum. + enum class ProcessStatus : Int32 + { + kStarting, + kRunning, + kKilled, + kFrozen, + kDead + }; + + //! @brief Affinity is the amount of nano-seconds this process is going + //! to run. + enum class AffinityKind : Int32 + { + kInvalid = 300, + kVeryHigh = 250, + kHigh = 200, + kStandard = 150, + kLowUsage = 100, + kVeryLowUsage = 50, + }; + + // operator overloading. + + inline bool operator<(AffinityKind lhs, AffinityKind rhs) + { + Int32 lhs_int = static_cast(lhs); + Int32 rhs_int = static_cast(rhs); + + return lhs_int < rhs_int; + } + + inline bool operator>(AffinityKind lhs, AffinityKind rhs) + { + Int32 lhs_int = static_cast(lhs); + Int32 rhs_int = static_cast(rhs); + + return lhs_int > rhs_int; + } + + inline bool operator<=(AffinityKind lhs, AffinityKind rhs) + { + Int32 lhs_int = static_cast(lhs); + Int32 rhs_int = static_cast(rhs); + + return lhs_int <= rhs_int; + } + + inline bool operator>=(AffinityKind lhs, AffinityKind rhs) + { + Int32 lhs_int = static_cast(lhs); + Int32 rhs_int = static_cast(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 PROCESS_HEADER_BLOCK + /// @brief Process Header (PHB). Holds information about the running process. Thread execution the THREAD_INFORMATION_BLOCK. + struct PROCESS_HEADER_BLOCK final + { + public: + explicit PROCESS_HEADER_BLOCK(VoidPtr startImage = nullptr) + : Image(startImage) + { + } + + ~PROCESS_HEADER_BLOCK() = default; + + NEWOS_COPY_DEFAULT(PROCESS_HEADER_BLOCK) + + public: + void SetEntrypoint(UIntPtr& imageStart) noexcept; + const Int32& GetExitCode() noexcept; + + public: + Char Name[kProcessLen] = {"PROCESS"}; + ProcessSubsystem SubSystem{ProcessSubsystem::eProcessSubsystemInvalid}; + ProcessLevelRing Selector{ProcessLevelRing::kRingStdUser}; + HAL::StackFramePtr StackFrame{nullptr}; + AffinityKind Affinity{AffinityKind::kStandard}; + ProcessStatus Status{ProcessStatus::kDead}; + + // Memory, images pointers. + HeapPtrKind HeapCursor{nullptr}; + ImagePtr Image{nullptr}; + HeapPtrKind HeapPtr{nullptr}; + + // shared library handle, reserved for kSharedObjectKind types of executables only. + PEFSharedObjectInterface* DLLPtr{nullptr}; + + // Memory usage. + SizeT UsedMemory{0}; + SizeT FreeMemory{0}; + SizeT SizeMemory{gib_cast(4)}; + + enum + { + kAppKind = 1, + kSharedObjectKind = 2, + kKindCount, + }; + + ProcessTime PTime{0}; + PID ProcessId{kSchedInvalidPID}; + Int32 Kind{kAppKind}; + + public: + //! @brief boolean operator, check status. + operator bool() + { + return Status != ProcessStatus::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); + + // PROCESS_HEADER_BLOCK 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 ProcessLevelRing& GetLevelRing() noexcept; + const ProcessStatus& GetStatus() noexcept; + const AffinityKind& GetAffinity() noexcept; + + private: + Int32 fLastExitCode{0}; + Int32 fLocalCode{0}; + + friend ProcessScheduler; + friend ProcessHelper; + }; + + /// \brief Processs Team (contains multiple processes inside it.) + /// Equivalent to a process batch + class ProcessTeam final + { + public: + explicit ProcessTeam() = default; + ~ProcessTeam() = default; + + NEWOS_COPY_DEFAULT(ProcessTeam); + + MutableArray>& AsArray(); + Ref& AsRef(); + UInt64& Id() noexcept; + + public: + MutableArray> mProcessList; + Ref mCurrentProcess; + UInt64 mTeamId{0}; + }; + + using ProcessHeaderRef = PROCESS_HEADER_BLOCK*; + + /// @brief PROCESS_HEADER_BLOCK manager class. + /// The main class which you call to schedule an app. + class ProcessScheduler final + { + explicit ProcessScheduler() = default; + + public: + ~ProcessScheduler() = default; + + NEWOS_COPY_DEFAULT(ProcessScheduler) + + operator bool(); + bool operator!(); + + public: + ProcessTeam& CurrentTeam(); + + public: + SizeT Add(Ref& processRef); + Bool Remove(SizeT processSlot); + + public: + Ref& TheCurrent(); + SizeT Run() noexcept; + + public: + STATIC Ref& The(); + + private: + ProcessTeam mTeam; + }; + + /* + * Just a helper class, which contains some utilities for the scheduler. + */ + + class ProcessHelper final + { + public: + STATIC bool Switch(HAL::StackFrame* newStack, const PID& newPid); + STATIC bool CanBeScheduled(Ref& process); + STATIC PID& TheCurrentPID(); + STATIC SizeT StartScheduling(); + }; + + const Int32& sched_get_exit_code(void) noexcept; +} // namespace Kernel + +#include + +//////////////////////////////////////////////////// + +// END + +//////////////////////////////////////////////////// + +#endif /* ifndef _INC_PROCESS_SCHEDULER_HXX_ */ diff --git a/dev/Kernel/KernelKit/RLE.hxx b/dev/Kernel/KernelKit/RLE.hxx new file mode 100644 index 00000000..31e37619 --- /dev/null +++ b/dev/Kernel/KernelKit/RLE.hxx @@ -0,0 +1,15 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef __KERNELKIT_RLE_HXX__ +#define __KERNELKIT_RLE_HXX__ + +#include + +EXTERN_C void rle_compress(void* data, long sz, void* out, long out_sz); +EXTERN_C void rle_decompress(void* data, long sz, void* out, long out_sz); + +#endif // !ifndef __KERNELKIT_RLE_HXX__ diff --git a/dev/Kernel/KernelKit/Semaphore.hxx b/dev/Kernel/KernelKit/Semaphore.hxx new file mode 100644 index 00000000..33dfe651 --- /dev/null +++ b/dev/Kernel/KernelKit/Semaphore.hxx @@ -0,0 +1,43 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace Kernel +{ + class PROCESS_HEADER_BLOCK; + + typedef PROCESS_HEADER_BLOCK* ProcessHeaderRef; + + /// @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(PROCESS_HEADER_BLOCK* process); + bool LockOrWait(PROCESS_HEADER_BLOCK* process, HardwareTimerInterface* timer); + + public: + NEWOS_COPY_DEFAULT(Semaphore); + + private: + ProcessHeaderRef fLockingProcess{nullptr}; + }; +} // namespace Kernel diff --git a/dev/Kernel/KernelKit/ThreadLocalStorage.hxx b/dev/Kernel/KernelKit/ThreadLocalStorage.hxx new file mode 100644 index 00000000..afc4940f --- /dev/null +++ b/dev/Kernel/KernelKit/ThreadLocalStorage.hxx @@ -0,0 +1,59 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef _KERNELKIT_TLS_HPP +#define _KERNELKIT_TLS_HPP + +#include + +//! @brief TLS implementation in C++ + +#define kCookieMag0 'H' +#define kCookieMag1 'C' +#define kCookieMag2 'R' + +#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]; // Process cookie. + Kernel::UIntPtr f_Code; // Start address (Instruction Pointer) + Kernel::UIntPtr f_Data; // Allocated Heap for process. + Kernel::UIntPtr f_Stack; // Application Stack pointer. + Kernel::Int32 f_ID; // Thread execution ID. + Kernel::Int64 f_UsedHeapPercent; // used heap in percent. + Kernel::Int64 f_FreeHeapPercent; // heap free in percent. +}; + +///! @brief Cookie Sanity check. +Kernel::Boolean tls_check_tib(THREAD_INFORMATION_BLOCK* the_tib); + +///! @brief new ptr syscall. +template +T* tls_new_ptr(void); + +///! @brief delete ptr syscall. +template +Kernel::Boolean tls_delete_ptr(T* ptr); + +template +T* tls_new_class(Args&&... args); + +/// @brief TLS install TIB and PIB. (syscall) +EXTERN_C 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 + +// last rev 7/7/24 + +#endif /* ifndef _KERNELKIT_TLS_HPP */ diff --git a/dev/Kernel/KernelKit/ThreadLocalStorage.inl b/dev/Kernel/KernelKit/ThreadLocalStorage.inl new file mode 100644 index 00000000..a5bb1adb --- /dev/null +++ b/dev/Kernel/KernelKit/ThreadLocalStorage.inl @@ -0,0 +1,74 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +//! @brief Allocates a pointer from the process's tls. + +#ifndef _INC_PROCESS_SCHEDULER_HXX_ +#include +#endif + +template +inline T* tls_new_ptr(void) +{ + using namespace Kernel; + + MUST_PASS(ProcessScheduler::The().Leak().TheCurrent()); + + auto ref_process = ProcessScheduler::The().Leak().TheCurrent(); + + T* pointer = (T*)ref_process.Leak().New(sizeof(T)); + return pointer; +} + +//! @brief TLS delete implementation. +template +inline Kernel::Bool tls_delete_ptr(T* ptr) +{ + if (!ptr) + return false; + + using namespace Kernel; + + MUST_PASS(ProcessScheduler::The().Leak().TheCurrent()); + + auto ref_process = ProcessScheduler::The().Leak().TheCurrent(); + 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 +T* tls_new_class(Args&&... args) +{ + T* ptr = tls_new_ptr(); + + 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 +inline Kernel::Bool tls_delete_class(T* ptr) +{ + if (!ptr) + return false; + + ptr->~T(); + return tls_delete_ptr(ptr); +} diff --git a/dev/Kernel/KernelKit/Timer.hxx b/dev/Kernel/KernelKit/Timer.hxx new file mode 100644 index 00000000..e6ef5d03 --- /dev/null +++ b/dev/Kernel/KernelKit/Timer.hxx @@ -0,0 +1,64 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#pragma once + +#include +#include +#include + +namespace Kernel +{ + class HardwareTimer; + class HardwareTimerInterface; + + class HardwareTimerInterface + { + public: + /// @brief Default constructor + explicit HardwareTimerInterface() = default; + virtual ~HardwareTimerInterface() = default; + + public: + NEWOS_COPY_DEFAULT(HardwareTimerInterface); + + public: + virtual Int32 Wait() noexcept; + }; + + class HardwareTimer final : public HardwareTimerInterface + { + public: + explicit HardwareTimer(Int64 seconds); + ~HardwareTimer() override; + + public: + NEWOS_COPY_DEFAULT(HardwareTimer); + + public: + Int32 Wait() noexcept override; + + public: + IntPtr* fDigitalTimer{nullptr}; + Int64 fWaitFor{0}; + }; + + inline Int64 Seconds(Int64 time) + { + if (time < 0) + return 0; + + return 1000 / time; + } + + inline Int64 Milliseconds(Int64 time) + { + if (time < 0) + return 0; + + return 1000 / Seconds(time); + } +} // namespace Kernel diff --git a/dev/Kernel/KernelKit/User.hxx b/dev/Kernel/KernelKit/User.hxx new file mode 100644 index 00000000..56014c9b --- /dev/null +++ b/dev/Kernel/KernelKit/User.hxx @@ -0,0 +1,101 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef _INC_PERMISSION_SEL_HXX_ +#define _INC_PERMISSION_SEL_HXX_ + +#include +#include +#include +#include + +// user mode users. +#define kSuperUser "\\Local\\Super" +#define kGuestUser "\\Local\\Guest" + +#define kUsersFile "\\Users\\$MANIFEST" + +#define kMaxUserNameLen (255) +#define kMaxUserTokenLen (4096) + +// hash 'password' -> base64+md5 encoded data +// use this data to then fetch specific data of the user.. + +namespace Kernel +{ + class UserManager; + class User; + + enum class RingKind + { + kRingStdUser = 1, + kRingSuperUser = 2, + kRingGuestUser = 5, + kRingCount = 5, + }; + + class User final + { + public: + explicit User() = delete; + + User(const Int32& sel, const Char* userName); + User(const RingKind& kind, const Char* userName); + + ~User(); + + public: + NEWOS_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 + StringView& 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}; + StringView fUserName; + VoidPtr fUserToken{nullptr}; + + friend UserManager; + }; + + class UserManager final + { + UserManager() = default; + ~UserManager() = default; + + User* fCurrentUser = nullptr; + User* fLastLoggedOffUser = nullptr; + + public: + User* fRootUser = nullptr; + + public: + NEWOS_COPY_DELETE(UserManager); + + STATIC UserManager* The() noexcept; + Bool TryLogIn(User* user, const Char* password) noexcept; + User* GetCurrent() noexcept; + Void TryLogOff() noexcept; + }; +} // namespace Kernel + +#endif /* ifndef _INC_PERMISSION_SEL_HXX_ */ diff --git a/dev/Kernel/KernelKit/XCOFF.hxx b/dev/Kernel/KernelKit/XCOFF.hxx new file mode 100644 index 00000000..82c6dd35 --- /dev/null +++ b/dev/Kernel/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 + +#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__ diff --git a/dev/Kernel/KernelKit/compile_flags.txt b/dev/Kernel/KernelKit/compile_flags.txt new file mode 100644 index 00000000..39b236a9 --- /dev/null +++ b/dev/Kernel/KernelKit/compile_flags.txt @@ -0,0 +1,6 @@ +-nostdlib +-ffreestanding +-std=c++20 +-I./ +-I../ +-D__ED__ -- cgit v1.2.3