From af8a516fc22865abd80d6e26f1541fa3d6bebfdc Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Thu, 9 May 2024 00:42:44 +0200 Subject: MHR-23: :boom:, refactors. - Move NewBoot to /Boot, thus making Kernel directory only containing the kernel. Signed-off-by: Amlal El Mahrouss --- Kernel/Source/AppMain.cxx | 193 ++++++ Kernel/Source/Array.cxx | 7 + Kernel/Source/ArrayList.cxx | 7 + Kernel/Source/Atom.cxx | 10 + Kernel/Source/CodeManager.cxx | 29 + Kernel/Source/Crc32.cxx | 74 ++ Kernel/Source/CxxAbi.cxx | 87 +++ Kernel/Source/Defines.cxx | 7 + Kernel/Source/DeviceManager.cxx | 7 + Kernel/Source/DriveManager.cxx | 149 ++++ Kernel/Source/ErrorOr.cxx | 12 + Kernel/Source/FS/NewFS.cxx | 938 ++++++++++++++++++++++++++ Kernel/Source/FileManager.cxx | 183 +++++ Kernel/Source/Framebuffer.cxx | 96 +++ Kernel/Source/GUIDWizard.cxx | 65 ++ Kernel/Source/GUIDWrapper.cxx | 11 + Kernel/Source/HError.cxx | 18 + Kernel/Source/IndexableProperty.cxx | 57 ++ Kernel/Source/Json.cxx | 12 + Kernel/Source/KernelCheck.cxx | 109 +++ Kernel/Source/KernelHeap.cxx | 169 +++++ Kernel/Source/LockDelegate.cxx | 12 + Kernel/Source/MutableArray.cxx | 7 + Kernel/Source/Network/IP.cxx | 126 ++++ Kernel/Source/Network/IPCEP.cxx | 7 + Kernel/Source/Network/NetworkDevice.cxx | 15 + Kernel/Source/New+Delete.cxx | 50 ++ Kernel/Source/NewFS+FileManager.cxx | 89 +++ Kernel/Source/NewFS+IO.cxx | 101 +++ Kernel/Source/NewFS+Journal.cxx | 22 + Kernel/Source/OwnPtr.cxx | 7 + Kernel/Source/PEFCodeManager.cxx | 226 +++++++ Kernel/Source/PEFSharedObjectRT.cxx | 107 +++ Kernel/Source/PRDT.cxx | 22 + Kernel/Source/PageAllocator.cxx | 52 ++ Kernel/Source/PageManager.cxx | 118 ++++ Kernel/Source/PermissionSelector.cxx | 47 ++ Kernel/Source/Pmm.cxx | 85 +++ Kernel/Source/ProcessScheduler.cxx | 392 +++++++++++ Kernel/Source/ProcessTeam.cxx | 31 + Kernel/Source/Property.cxx | 20 + Kernel/Source/Ref.cxx | 7 + Kernel/Source/SMPManager.cxx | 217 ++++++ Kernel/Source/Semaphore.cxx | 53 ++ Kernel/Source/Storage/AHCIDeviceInterface.cxx | 35 + Kernel/Source/Storage/ATADeviceInterface.cxx | 88 +++ Kernel/Source/Storage/NVMEDeviceInterface.cxx | 15 + Kernel/Source/Storage/SCSIDeviceInterface.cxx | 11 + Kernel/Source/Stream.cxx | 12 + Kernel/Source/String.cxx | 248 +++++++ Kernel/Source/ThreadLocalStorage.cxx | 58 ++ Kernel/Source/Timer.cxx | 41 ++ Kernel/Source/URL.cxx | 96 +++ Kernel/Source/UserHeap.cxx | 252 +++++++ Kernel/Source/Utils.cxx | 253 +++++++ Kernel/Source/Variant.cxx | 29 + Kernel/Source/compile_flags.txt | 7 + 57 files changed, 5198 insertions(+) create mode 100644 Kernel/Source/AppMain.cxx create mode 100644 Kernel/Source/Array.cxx create mode 100644 Kernel/Source/ArrayList.cxx create mode 100644 Kernel/Source/Atom.cxx create mode 100644 Kernel/Source/CodeManager.cxx create mode 100644 Kernel/Source/Crc32.cxx create mode 100644 Kernel/Source/CxxAbi.cxx create mode 100644 Kernel/Source/Defines.cxx create mode 100644 Kernel/Source/DeviceManager.cxx create mode 100644 Kernel/Source/DriveManager.cxx create mode 100644 Kernel/Source/ErrorOr.cxx create mode 100644 Kernel/Source/FS/NewFS.cxx create mode 100644 Kernel/Source/FileManager.cxx create mode 100644 Kernel/Source/Framebuffer.cxx create mode 100644 Kernel/Source/GUIDWizard.cxx create mode 100644 Kernel/Source/GUIDWrapper.cxx create mode 100644 Kernel/Source/HError.cxx create mode 100644 Kernel/Source/IndexableProperty.cxx create mode 100644 Kernel/Source/Json.cxx create mode 100644 Kernel/Source/KernelCheck.cxx create mode 100644 Kernel/Source/KernelHeap.cxx create mode 100644 Kernel/Source/LockDelegate.cxx create mode 100644 Kernel/Source/MutableArray.cxx create mode 100644 Kernel/Source/Network/IP.cxx create mode 100644 Kernel/Source/Network/IPCEP.cxx create mode 100644 Kernel/Source/Network/NetworkDevice.cxx create mode 100644 Kernel/Source/New+Delete.cxx create mode 100644 Kernel/Source/NewFS+FileManager.cxx create mode 100644 Kernel/Source/NewFS+IO.cxx create mode 100644 Kernel/Source/NewFS+Journal.cxx create mode 100644 Kernel/Source/OwnPtr.cxx create mode 100644 Kernel/Source/PEFCodeManager.cxx create mode 100644 Kernel/Source/PEFSharedObjectRT.cxx create mode 100644 Kernel/Source/PRDT.cxx create mode 100644 Kernel/Source/PageAllocator.cxx create mode 100644 Kernel/Source/PageManager.cxx create mode 100644 Kernel/Source/PermissionSelector.cxx create mode 100644 Kernel/Source/Pmm.cxx create mode 100644 Kernel/Source/ProcessScheduler.cxx create mode 100644 Kernel/Source/ProcessTeam.cxx create mode 100644 Kernel/Source/Property.cxx create mode 100644 Kernel/Source/Ref.cxx create mode 100644 Kernel/Source/SMPManager.cxx create mode 100644 Kernel/Source/Semaphore.cxx create mode 100644 Kernel/Source/Storage/AHCIDeviceInterface.cxx create mode 100644 Kernel/Source/Storage/ATADeviceInterface.cxx create mode 100644 Kernel/Source/Storage/NVMEDeviceInterface.cxx create mode 100644 Kernel/Source/Storage/SCSIDeviceInterface.cxx create mode 100644 Kernel/Source/Stream.cxx create mode 100644 Kernel/Source/String.cxx create mode 100644 Kernel/Source/ThreadLocalStorage.cxx create mode 100644 Kernel/Source/Timer.cxx create mode 100644 Kernel/Source/URL.cxx create mode 100644 Kernel/Source/UserHeap.cxx create mode 100644 Kernel/Source/Utils.cxx create mode 100644 Kernel/Source/Variant.cxx create mode 100644 Kernel/Source/compile_flags.txt (limited to 'Kernel/Source') diff --git a/Kernel/Source/AppMain.cxx b/Kernel/Source/AppMain.cxx new file mode 100644 index 00000000..b91d6082 --- /dev/null +++ b/Kernel/Source/AppMain.cxx @@ -0,0 +1,193 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: AppMain.cxx + Purpose: Kernel main loop. + +------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Detail +{ + /// @brief Filesystem auto mounter, additional checks are also done by the + /// class. + class FilesystemWizard final + { + NewOS::NewFilesystemManager* fNewFS{nullptr}; + + public: + explicit FilesystemWizard() + { + if (NewOS::FilesystemManagerInterface::GetMounted()) + { + /// Mounted partition, cool! + NewOS::kcout + << "New OS: No need to create for a NewFS partition here...\r"; + } + else + { + /// Not mounted partition, auto-mount. + ///! Mounts a NewFS block. + fNewFS = new NewOS::NewFilesystemManager(); + + NewOS::FilesystemManagerInterface::Mount(fNewFS); + + if (fNewFS->GetImpl()) + { + constexpr auto cFolderInfo = "Metadata"; + const auto cDirCount = 8; + const char* cDirStr[cDirCount] = { + "/Boot/", "/System/", "/Support/", "/Applications/", + "/Users/", "/Library/", "/Mount/", "/Assistants/"}; + + for (NewOS::SizeT dirIndx = 0UL; dirIndx < cDirCount; ++dirIndx) + { + auto catalogDir = fNewFS->GetImpl()->GetCatalog(cDirStr[dirIndx]); + + if (catalogDir) + { + delete catalogDir; + continue; + } + + catalogDir = fNewFS->GetImpl()->CreateCatalog(cDirStr[dirIndx], 0, + kNewFSCatalogKindDir); + + NewFork theFork{0}; + + const NewOS::Char* cSrcName = cFolderInfo; + + NewOS::rt_copy_memory((NewOS::VoidPtr)(cSrcName), theFork.ForkName, + NewOS::rt_string_len(cSrcName)); + + NewOS::rt_copy_memory((NewOS::VoidPtr)(catalogDir->Name), + theFork.CatalogName, + NewOS::rt_string_len(catalogDir->Name)); + + delete catalogDir; + + theFork.DataSize = kNewFSForkSize; + theFork.ResourceId = 0; + theFork.ResourceKind = NewOS::kNewFSRsrcForkKind; + theFork.Kind = NewOS::kNewFSDataForkKind; + + NewOS::StringView metadataFolder(kNewFSSectorSz); + + metadataFolder += + "

Kind: folder

\r

Created by: system

\r

Edited by: " + "system

\r

Volume Type: New OS Standard

\r"; + + metadataFolder += "

File name: "; + metadataFolder += cDirStr[dirIndx]; + metadataFolder += "

\r"; + + const NewOS::SizeT metadataSz = kNewFSSectorSz; + + auto catalogSystem = fNewFS->GetImpl()->GetCatalog(cDirStr[dirIndx]); + + fNewFS->GetImpl()->CreateFork(catalogSystem, theFork); + + fNewFS->GetImpl()->WriteCatalog( + catalogSystem, (NewOS::VoidPtr)(metadataFolder.CData()), + metadataSz, cFolderInfo); + + delete catalogSystem; + } + } + + NewCatalog* catalogDisk = + this->fNewFS->GetImpl()->GetCatalog("/Mount/This Disk"); + + const NewOS::Char* cSrcName = "DiskInfo"; + + if (catalogDisk) + { + auto bufferInfoDisk = (NewOS::Char*)this->fNewFS->GetImpl()->ReadCatalog(catalogDisk, kNewFSSectorSz, cSrcName); + NewOS::kcout << bufferInfoDisk << NewOS::end_line(); + + delete bufferInfoDisk; + delete catalogDisk; + } + else + { + catalogDisk = + (NewCatalog*)this->Leak()->CreateAlias("/Mount/This Disk"); + + NewOS::StringView diskFolder(kNewFSSectorSz); + + diskFolder += + "

Kind: alias to disk

\r

Created by: system

\r

Edited " + "by: " + "system

\r

Volume Type: New OS Standard

\r"; + + diskFolder += "

Original Path: "; + diskFolder += NewOS::NewFilesystemHelper::Root(); + diskFolder += "

\r"; + + NewFork theDiskFork{0}; + + NewOS::rt_copy_memory((NewOS::VoidPtr)(cSrcName), theDiskFork.ForkName, + NewOS::rt_string_len(cSrcName)); + + NewOS::rt_copy_memory((NewOS::VoidPtr)(catalogDisk->Name), + theDiskFork.CatalogName, + NewOS::rt_string_len(catalogDisk->Name)); + + theDiskFork.DataSize = kNewFSForkSize; + theDiskFork.ResourceId = 0; + theDiskFork.ResourceKind = NewOS::kNewFSRsrcForkKind; + theDiskFork.Kind = NewOS::kNewFSDataForkKind; + + fNewFS->GetImpl()->CreateFork(catalogDisk, theDiskFork); + fNewFS->GetImpl()->WriteCatalog(catalogDisk, + (NewOS::VoidPtr)diskFolder.CData(), + kNewFSSectorSz, cSrcName); + + delete catalogDisk; + } + } + } + + ~FilesystemWizard() + { + delete fNewFS; + } + + NEWOS_COPY_DEFAULT(FilesystemWizard); + + /// Grab the disk's NewFS reference. + NewOS::NewFilesystemManager* Leak() + { + return fNewFS; + } + }; +} // namespace Detail + +/// @file Main microkernel entrypoint. + +EXTERN_C NewOS::Void AppMain(NewOS::Void) +{ + /// Now run kernel loop, until no process are running. + Detail::FilesystemWizard wizard; // automatic. + + while (NewOS::ProcessScheduler::Shared().Leak().Run() > 0) + { + ; + } +} diff --git a/Kernel/Source/Array.cxx b/Kernel/Source/Array.cxx new file mode 100644 index 00000000..618ba9f6 --- /dev/null +++ b/Kernel/Source/Array.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/ArrayList.cxx b/Kernel/Source/ArrayList.cxx new file mode 100644 index 00000000..0f3a1b3a --- /dev/null +++ b/Kernel/Source/ArrayList.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/Atom.cxx b/Kernel/Source/Atom.cxx new file mode 100644 index 00000000..f7ae9416 --- /dev/null +++ b/Kernel/Source/Atom.cxx @@ -0,0 +1,10 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +// @file Atom.cpp +// @brief Atomic primitives diff --git a/Kernel/Source/CodeManager.cxx b/Kernel/Source/CodeManager.cxx new file mode 100644 index 00000000..39917163 --- /dev/null +++ b/Kernel/Source/CodeManager.cxx @@ -0,0 +1,29 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +using namespace NewOS; + +/// @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 +{ + if (!main) + return false; + + ProcessHeader proc((VoidPtr)main); + proc.Kind = ProcessHeader::kDriverKind; + rt_copy_memory((VoidPtr)processName, proc.Name, rt_string_len(proc.Name)); + + Ref refProc = proc; + + return ProcessScheduler::Shared().Leak().Add(refProc); +} \ No newline at end of file diff --git a/Kernel/Source/Crc32.cxx b/Kernel/Source/Crc32.cxx new file mode 100644 index 00000000..6ddb5642 --- /dev/null +++ b/Kernel/Source/Crc32.cxx @@ -0,0 +1,74 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +// @file CRC32.cpp +// @brief Check sequence implementation. + +namespace NewOS +{ + /// @brief The CRC32 table. + UInt kCrcTbl[kCrcCnt] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, + 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, + 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, + 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, + 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, + 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, + 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, + 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, + 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, + 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, + 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, + 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, + 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, + 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, + 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, + 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, + 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, + 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, + 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, + 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, + 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, + 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, + 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, + 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, + 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, + 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, + 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, + 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, + 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, + 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, + 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, + 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, + 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, + 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, + 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d}; + + /// @brief Calculate CRC32 of p + /// @param p the data to compute. + /// @param len the length of the data. + /// @return the CRC32. + UInt ke_calculate_crc32(const Char* p, UInt len) noexcept + { + UInt crc = 0xffffffff; + + while (len-- != 0) + crc = kCrcTbl[((UInt8)crc ^ *(p++))] ^ (crc >> 8); + + // return (~crc); also works, does the same thing. + return (crc ^ 0xffffffff); + } +} // namespace NewOS diff --git a/Kernel/Source/CxxAbi.cxx b/Kernel/Source/CxxAbi.cxx new file mode 100644 index 00000000..2f9ae6a2 --- /dev/null +++ b/Kernel/Source/CxxAbi.cxx @@ -0,0 +1,87 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +atexit_func_entry_t __atexit_funcs[kDSOMaxObjects]; + +uarch_t __atexit_func_count; + +extern "C" void __cxa_pure_virtual() +{ + NewOS::kcout << "New OS: C++ placeholder method.\n"; +} + +extern "C" void ___chkstk_ms() +{ + while (1) + { + asm("cli"); + asm("hlt"); + } +} + +extern "C" int atexit(void (*f)(void*), void* arg, void* dso) +{ + if (__atexit_func_count >= kDSOMaxObjects) + return -1; + + __atexit_funcs[__atexit_func_count].destructor_func = f; + __atexit_funcs[__atexit_func_count].obj_ptr = arg; + __atexit_funcs[__atexit_func_count].dso_handle = dso; + + __atexit_func_count++; + + return 0; +} + +extern "C" void __cxa_finalize(void* f) +{ + uarch_t i = __atexit_func_count; + if (!f) + { + while (i--) + { + if (__atexit_funcs[i].destructor_func) + { + (*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr); + }; + } + + return; + } + + while (i--) + { + if (__atexit_funcs[i].destructor_func) + { + (*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr); + __atexit_funcs[i].destructor_func = 0; + }; + } +} + +namespace cxxabiv1 +{ + extern "C" int __cxa_guard_acquire(__guard* g) + { + (void)g; + return 0; + } + + extern "C" int __cxa_guard_release(__guard* g) + { + *(char*)g = 1; + return 0; + } + + extern "C" void __cxa_guard_abort(__guard* g) + { + (void)g; + } +} // namespace cxxabiv1 diff --git a/Kernel/Source/Defines.cxx b/Kernel/Source/Defines.cxx new file mode 100644 index 00000000..02327f07 --- /dev/null +++ b/Kernel/Source/Defines.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/DeviceManager.cxx b/Kernel/Source/DeviceManager.cxx new file mode 100644 index 00000000..6e45e9da --- /dev/null +++ b/Kernel/Source/DeviceManager.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/DriveManager.cxx b/Kernel/Source/DriveManager.cxx new file mode 100644 index 00000000..c60b2079 --- /dev/null +++ b/Kernel/Source/DriveManager.cxx @@ -0,0 +1,149 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include +#include +#include + +/// @file DriveManager.cxx +/// @brief Kernel drive manager. + +namespace NewOS +{ + static UInt16 kATAIO = 0U; + static UInt8 kATAMaster = 0U; + + /// @brief reads from an ATA drive. + /// @param pckt + /// @return + Void ke_drv_input(DriveTrait::DrivePacket* pckt) + { + if (!pckt) + { + return; + } + + pckt->fPacketGood = false; + +#ifdef __AHCI__ + drv_std_read(pckt->fLba, (Char*)pckt->fPacketContent, kAHCISectorSize, pckt->fPacketSize); +#elif defined(__ATA_PIO__) || defined(__ATA_DMA__) + drv_std_read(pckt->fLba, kATAIO, kATAMaster, (Char*)pckt->fPacketContent, kATASectorSize, pckt->fPacketSize); +#endif + + pckt->fPacketGood = true; + } + + /// @brief Writes to an ATA drive. + /// @param pckt + /// @return + Void ke_drv_output(DriveTrait::DrivePacket* pckt) + { + if (!pckt) + { + return; + } + + pckt->fPacketGood = false; + +#ifdef __AHCI__ + drv_std_write(pckt->fLba, (Char*)pckt->fPacketContent, kATASectorSize, pckt->fPacketSize); +#elif defined(__ATA_PIO__) || defined(__ATA_DMA__) + drv_std_write(pckt->fLba, kATAIO, kATAMaster, (Char*)pckt->fPacketContent, kATASectorSize, pckt->fPacketSize); +#endif + + pckt->fPacketGood = true; + } + + /// @brief Executes a disk check on the ATA drive. + /// @param pckt + /// @return + Void ke_drv_check_disk(DriveTrait::DrivePacket* pckt) + { + if (!pckt) + { + return; + } + + pckt->fPacketGood = false; + +#if defined(__ATA_PIO__) || defined(__ATA_DMA__) + kATAMaster = true; + kATAIO = ATA_PRIMARY_IO; + + MUST_PASS(drv_std_init(kATAIO, kATAMaster, kATAIO, kATAMaster)); +#endif // if defined(__ATA_PIO__) || defined (__ATA_DMA__) + + pckt->fPacketGood = true; + } + +/// @brief Gets the drive kind (ATA, SCSI, AHCI...) +/// @param +/// @return +#ifdef __ATA_PIO__ + const Char* ke_drive_kind(Void) + { + return "ATA-PIO"; + } +#endif + +#ifdef __ATA_DMA__ + const Char* ke_drive_kind(Void) + { + return "ATA-DMA"; + } +#endif + +#ifdef __AHCI__ + const Char* ke_drive_kind(Void) + { + return "AHCI"; + } +#endif + + /// @brief Unimplemented drive. + /// @param pckt + /// @return + Void ke_drv_unimplemented(DriveTrait::DrivePacket* pckt) + { + } + + /// @brief Makes a new drive. + /// @return the new drive. + DriveTrait construct_drive() noexcept + { + DriveTrait trait; + + rt_copy_memory((VoidPtr) "/Mount/Null", trait.fName, rt_string_len("/Mount/Null")); + trait.fKind = kInvalidDrive; + + trait.fInput = ke_drv_unimplemented; + trait.fOutput = ke_drv_unimplemented; + trait.fVerify = ke_drv_unimplemented; + trait.fDriveKind = ke_drive_kind; + + return trait; + } + + /// @brief Fetches the main drive. + /// @return the new drive. + DriveTrait construct_main_drive() noexcept + { + DriveTrait trait; + + rt_copy_memory((VoidPtr) "/Mount/MainDisk/", trait.fName, rt_string_len("/Mount/MainDisk/")); + trait.fKind = kMassStorage | kEPMDrive; + + trait.fInput = ke_drv_input; + trait.fOutput = ke_drv_output; + trait.fVerify = ke_drv_check_disk; + trait.fDriveKind = ke_drive_kind; + + return trait; + } +} // namespace NewOS diff --git a/Kernel/Source/ErrorOr.cxx b/Kernel/Source/ErrorOr.cxx new file mode 100644 index 00000000..7cef9afb --- /dev/null +++ b/Kernel/Source/ErrorOr.cxx @@ -0,0 +1,12 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +/***********************************************************************************/ +/// @file ErrorOr.cxx /// +/// @brief Error Or Value class. /// +/***********************************************************************************/ diff --git a/Kernel/Source/FS/NewFS.cxx b/Kernel/Source/FS/NewFS.cxx new file mode 100644 index 00000000..41869fcd --- /dev/null +++ b/Kernel/Source/FS/NewFS.cxx @@ -0,0 +1,938 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#ifdef __FSKIT_NEWFS__ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace NewOS; + +///! BUGS: 0 + +/***********************************************************************************/ +/* This file implements the New File System. +/***********************************************************************************/ + +STATIC MountpointInterface sMountpointInterface; + +/// @brief Creates a new fork inside the New filesystem partition. +/// @param catalog it's catalog +/// @param theFork the fork itself. +/// @return the fork +_Output NewFork* NewFSParser::CreateFork(_Input NewCatalog* catalog, + _Input NewFork& theFork) +{ + if (!sMountpointInterface.GetAddressOf(this->fDriveIndex)) + return nullptr; + + if (catalog && theFork.ForkName[0] != 0 && + theFork.DataSize == kNewFSForkSize) + { + Lba lba = (theFork.Kind == kNewFSDataForkKind) ? catalog->DataFork + : catalog->ResourceFork; + + kcout << "Fork Lba: " << hex_number(lba) << endl; + + if (lba <= kNewFSCatalogStartAddress) + return nullptr; + + auto drv = sMountpointInterface.GetAddressOf(this->fDriveIndex); + + /// special treatment. + rt_copy_memory((VoidPtr) "fs/newfs-packet", drv->fPacket.fPacketMime, + rt_string_len("fs/newfs-packet")); + + NewFork curFork{0}; + NewFork prevFork{0}; + Lba lbaOfPreviousFork = lba; + + /// do not check for anything. Loop until we get what we want, that is a free fork zone. + while (true) + { + if (lba <= kNewFSCatalogStartAddress) + break; + + drv->fPacket.fLba = lba; + drv->fPacket.fPacketSize = sizeof(NewFork); + drv->fPacket.fPacketContent = &curFork; + + drv->fInput(&drv->fPacket); + + kcout << "New OS: Next-Fork: " << hex_number(curFork.NextSibling) << endl; + + if (curFork.Flags == kNewFSFlagCreated) + { + kcout << "New OS: Fork already exists.\r"; + + /// sanity check. + if (StringBuilder::Equals(curFork.ForkName, theFork.ForkName) && + StringBuilder::Equals(curFork.CatalogName, catalog->Name)) + return nullptr; + + kcout << "Next-Fork: " << hex_number(curFork.NextSibling) << endl; + + lbaOfPreviousFork = lba; + lba = curFork.NextSibling; + + prevFork = curFork; + } + else + { + /// This is a check that we have, in order to link the previous fork + /// entry. + if (lba >= kNewFSCatalogStartAddress) + { + drv->fPacket.fLba = lbaOfPreviousFork; + drv->fPacket.fPacketSize = sizeof(NewFork); + drv->fPacket.fPacketContent = &prevFork; + + prevFork.NextSibling = lba; + + /// write to disk. + drv->fOutput(&drv->fPacket); + } + + break; + } + } + + constexpr auto cForkPadding = + 4; /// this value gives us space for the data offset. + + theFork.Flags = kNewFSFlagCreated; + theFork.DataOffset = lba - sizeof(NewFork) * cForkPadding; + theFork.PreviousSibling = lbaOfPreviousFork; + theFork.NextSibling = theFork.DataOffset - theFork.DataSize; + + drv->fPacket.fLba = lba; + drv->fPacket.fPacketSize = sizeof(NewFork); + drv->fPacket.fPacketContent = &theFork; + + drv->fOutput(&drv->fPacket); + + /// log what we have now. + kcout << "New OS: Wrote fork data at: " << hex_number(theFork.DataOffset) + << endl; + + kcout << "New OS: Wrote fork at: " << hex_number(lba) << endl; + + return &theFork; + } + + return nullptr; +} + +/// @brief Find fork inside New filesystem. +/// @param catalog the catalog. +/// @param name the fork name. +/// @return the fork. +_Output NewFork* NewFSParser::FindFork(_Input NewCatalog* catalog, + _Input const Char* name, + Boolean isDataFork) +{ + auto drv = sMountpointInterface.GetAddressOf(this->fDriveIndex); + NewFork* theFork = nullptr; + + Lba lba = isDataFork ? catalog->DataFork : catalog->ResourceFork; + + while (lba != 0) + { + drv->fPacket.fLba = lba; + drv->fPacket.fPacketSize = sizeof(NewFork); + drv->fPacket.fPacketContent = (VoidPtr)theFork; + + rt_copy_memory((VoidPtr) "fs/newfs-packet", drv->fPacket.fPacketMime, 16); + + if (auto res = + fs_newfs_read(&sMountpointInterface, *drv, this->fDriveIndex); + res) + { + switch (res) + { + case 1: + DbgLastError() = kErrorDiskReadOnly; + break; + case 2: + DbgLastError() = kErrorDiskIsFull; + break; + DbgLastError() = kErrorNoSuchDisk; + break; + + default: + break; + } + return nullptr; + } + + if (StringBuilder::Equals(theFork->ForkName, name)) + { + break; + } + + lba = theFork->NextSibling; + } + + return theFork; +} + +/// @brief Simpler factory to create a catalog (assumes you want to create a +/// file.) +/// @param name +/// @return catalog pointer. +_Output NewCatalog* NewFSParser::CreateCatalog(_Input const char* name) +{ + return this->CreateCatalog(name, 0, kNewFSCatalogKindFile); +} + +/// @brief Creates a new catalog into the disk. +/// @param name the catalog name. +/// @param flags the flags of the catalog. +/// @param kind the catalog kind. +/// @return catalog pointer. +_Output NewCatalog* NewFSParser::CreateCatalog(_Input const char* name, + _Input const Int32& flags, + _Input const Int32& kind) +{ + if (!sMountpointInterface.GetAddressOf(this->fDriveIndex)) + return nullptr; + + Lba outLba = 0UL; + + /// a directory should have a slash in the end. + if (kind == kNewFSCatalogKindDir && + name[rt_string_len(name) - 1] != NewFilesystemHelper::Separator()) + return nullptr; + + /// a file shouldn't have a slash in the end. + if (kind != kNewFSCatalogKindDir && + name[rt_string_len(name) - 1] == NewFilesystemHelper::Separator()) + return nullptr; + + NewCatalog* checkForCpy = this->FindCatalog(name, outLba); + + if (checkForCpy) + { + return checkForCpy; + } + + char parentName[kNewFSNodeNameLen] = {0}; + + for (SizeT indexName = 0UL; indexName < rt_string_len(name); ++indexName) + { + parentName[indexName] = name[indexName]; + } + + if (*parentName == 0) + { + DbgLastError() = kErrorFileNotFound; + return nullptr; + } + + /// Locate parent catalog, to then allocate right after it. + + for (SizeT indexFill = 0; indexFill < rt_string_len(name); ++indexFill) + { + parentName[indexFill] = name[indexFill]; + } + + SizeT indexReverseCopy = rt_string_len(parentName); + + // zero character. + parentName[--indexReverseCopy] = 0; + + // mandatory / character. + parentName[--indexReverseCopy] = 0; + + while (parentName[indexReverseCopy] != NewFilesystemHelper::Separator()) + { + parentName[indexReverseCopy] = 0; + --indexReverseCopy; + } + + NewCatalog* catalog = this->FindCatalog(parentName, outLba); + + if (catalog && catalog->Kind == kNewFSCatalogKindFile) + { + delete catalog; + return nullptr; + } + else if (!catalog) + { + outLba = kNewFSCatalogStartAddress; + } + + constexpr SizeT cDefaultForkSize = kNewFSForkSize; + + NewCatalog* catalogChild = new NewCatalog(); + + catalogChild->ResourceForkSize = cDefaultForkSize; + catalogChild->DataForkSize = cDefaultForkSize; + + catalogChild->NextSibling = outLba; + catalogChild->PrevSibling = outLba; + catalogChild->Kind = kind; + catalogChild->Flags = kNewFSFlagCreated; + + rt_copy_memory((VoidPtr)name, (VoidPtr)catalogChild->Name, + rt_string_len(name)); + + UInt16 catalogBuf[kNewFSSectorSz] = {0}; + + auto drive = sMountpointInterface.GetAddressOf(this->fDriveIndex); + + Lba startFree = outLba; + + rt_copy_memory((VoidPtr) "fs/newfs-packet", drive->fPacket.fPacketMime, + rt_string_len("fs/newfs-packet")); + + drive->fPacket.fPacketContent = catalogBuf; + drive->fPacket.fPacketSize = kNewFSSectorSz; + drive->fPacket.fLba = startFree; + + drive->fInput(&drive->fPacket); + + NewCatalog* nextSibling = (NewCatalog*)catalogBuf; + + startFree = nextSibling->NextSibling; + + catalogChild->PrevSibling = outLba; + + drive->fPacket.fLba = startFree; + drive->fInput(&drive->fPacket); + + while (drive->fPacket.fPacketGood) + { + nextSibling = (NewCatalog*)catalogBuf; + + if (startFree <= kNewFSAddressAsLba) + { + delete catalogChild; + delete catalog; + + return nullptr; + } + + /// allocation or reallocation or catalog... + if (nextSibling->Flags != kNewFSFlagCreated) + { + Char sectorBufPartBlock[kNewFSSectorSz] = {0}; + + drive->fPacket.fPacketContent = sectorBufPartBlock; + drive->fPacket.fPacketSize = kNewFSSectorSz; + drive->fPacket.fLba = kNewFSAddressAsLba; + + drive->fInput(&drive->fPacket); + + constexpr auto cNewFSCatalogPadding = 4; + + NewPartitionBlock* partBlock = (NewPartitionBlock*)sectorBufPartBlock; + + if (partBlock->FreeCatalog < 1) + { + delete catalogChild; + return nullptr; + } + + catalogChild->DataFork = partBlock->DiskSize - partBlock->StartCatalog; + + catalogChild->ResourceFork = catalogChild->DataFork; + + catalogChild->NextSibling = + startFree + (sizeof(NewCatalog) * cNewFSCatalogPadding); + + drive->fPacket.fPacketContent = catalogChild; + drive->fPacket.fPacketSize = sizeof(NewCatalog); + drive->fPacket.fLba = startFree; + + drive->fOutput(&drive->fPacket); + + drive->fPacket.fPacketContent = catalogBuf; + drive->fPacket.fPacketSize = kNewFSSectorSz; + drive->fPacket.fLba = + startFree - (sizeof(NewCatalog) * cNewFSCatalogPadding); + + drive->fInput(&drive->fPacket); + + nextSibling->NextSibling = startFree; + + drive->fOutput(&drive->fPacket); + + kcout << "New OS: Create new catalog, status: " + << hex_number(catalogChild->Flags) << endl; + kcout << "New OS: Create new catalog, status: " << catalogChild->Name + << endl; + + drive->fPacket.fPacketContent = sectorBufPartBlock; + drive->fPacket.fPacketSize = kNewFSSectorSz; + drive->fPacket.fLba = kNewFSAddressAsLba; + + drive->fInput(&drive->fPacket); + + partBlock->SectorCount -= 1; + partBlock->CatalogCount += 1; + partBlock->FreeCatalog -= 1; + partBlock->FreeCatalog = catalogChild->NextSibling; + + drive->fOutput(&drive->fPacket); + + delete catalog; + return catalogChild; + } + + constexpr auto cNewFSCatalogPadding = 4; + + //// @note that's how we find the next catalog in the partition block. + startFree = startFree + (sizeof(NewCatalog) * cNewFSCatalogPadding); + + drive->fPacket.fPacketContent = catalogBuf; + drive->fPacket.fPacketSize = kNewFSSectorSz; + drive->fPacket.fLba = startFree; + + drive->fInput(&drive->fPacket); + } + + delete catalog; + return nullptr; +} + +/// @brief Make a EPM+NewFS drive out of the disk. +/// @param drive The drive to write on. +/// @return If it was sucessful, see DbgLastError(). +bool NewFSParser::Format(_Input _Output DriveTrait* drive) +{ + /// verify disk. + drive->fVerify(&drive->fPacket); + + rt_copy_memory((VoidPtr) "fs/newfs-packet", drive->fPacket.fPacketMime, + rt_string_len("fs/newfs-packet")); + + /// if disk isn't good, then error out. + if (false == drive->fPacket.fPacketGood) + { + DbgLastError() = kErrorDiskIsCorrupted; + return false; + } + + Char sectorBuf[kNewFSSectorSz] = {0}; + + drive->fPacket.fPacketContent = sectorBuf; + drive->fPacket.fPacketSize = kNewFSSectorSz; + drive->fPacket.fLba = kNewFSAddressAsLba; + + drive->fInput(&drive->fPacket); + + /// disk isnt faulty and data has been fetched. + if (drive->fPacket.fPacketGood) + { + NewPartitionBlock* partBlock = (NewPartitionBlock*)sectorBuf; + + /// check for an empty partition here. + if (partBlock->PartitionName[0] == 0 && + rt_string_cmp(partBlock->Ident, kNewFSIdent, kNewFSIdentLen)) + { + /// partition is free and valid. + + partBlock->Version = kNewFSVersionInteger; + + const auto cUntitledHD = "New OS HD\0"; + + rt_copy_memory((VoidPtr)kNewFSIdent, (VoidPtr)partBlock->Ident, + kNewFSIdentLen); + + rt_copy_memory((VoidPtr)cUntitledHD, (VoidPtr)partBlock->PartitionName, + rt_string_len(cUntitledHD)); + + SizeT catalogCount = 0; + SizeT sectorCount = drv_std_get_sector_count(); + SizeT diskSize = drv_std_get_drv_size(); + + partBlock->Kind = kNewFSPartitionTypeStandard; + partBlock->StartCatalog = kNewFSCatalogStartAddress; + partBlock->Flags = kNewFSPartitionTypeStandard; + partBlock->CatalogCount = sectorCount / sizeof(NewCatalog); + partBlock->SectorCount = sectorCount; + partBlock->DiskSize = diskSize; + partBlock->FreeCatalog = sectorCount / sizeof(NewCatalog); + + drive->fPacket.fPacketContent = sectorBuf; + drive->fPacket.fPacketSize = kNewFSSectorSz; + drive->fPacket.fLba = kNewFSAddressAsLba; + + drive->fOutput(&drive->fPacket); + + kcout << "Drive-Kind: " << drive->fDriveKind() << endl; + + kcout << "Partition-Name: " << partBlock->PartitionName << endl; + kcout << "Start-Catalog: " << hex_number(partBlock->StartCatalog) << endl; + kcout << "Catalog-Count: " << hex_number(partBlock->CatalogCount) << endl; + kcout << "Free-Catalog: " << hex_number(partBlock->FreeCatalog) << endl; + kcout << "Free-Sectors: " << hex_number(partBlock->FreeSectors) << endl; + kcout << "Sector-Size: " << hex_number(partBlock->SectorSize) << endl; + + /// write the root catalog. + this->CreateCatalog(kNewFSRoot, 0, kNewFSCatalogKindDir); + + return true; + } + + kcout << "New OS: PartitionBlock already exists.\r"; + + /// return success as well, do not ignore that partition. + return true; + } + + return false; +} + +/// @brief Writes the data fork into a specific catalog. +/// @param catalog the catalog itself +/// @param data the data. +/// @return if the catalog w rote the contents successfully. +bool NewFSParser::WriteCatalog(_Input _Output NewCatalog* catalog, voidPtr data, SizeT sizeOfData, _Input const char* forkName) +{ + if (sizeOfData > catalog->DataForkSize) + return false; + if (!sMountpointInterface.GetAddressOf(this->fDriveIndex)) + return false; + + NewFork* forkData = new NewFork(); + rt_set_memory(forkData, 0, sizeof(NewFork)); + + auto drive = sMountpointInterface.GetAddressOf(this->fDriveIndex); + + rt_copy_memory((VoidPtr) "fs/newfs-packet", drive->fPacket.fPacketMime, + rt_string_len("fs/newfs-packet")); + + auto startFork = catalog->DataFork; + + rt_copy_memory(catalog->Name, forkData->CatalogName, kNewFSNodeNameLen); + + /// sanity check of the fork position as the condition to run the loop. + while (startFork >= kNewFSCatalogStartAddress) + { + drive->fPacket.fPacketContent = forkData; + drive->fPacket.fPacketSize = sizeof(NewFork); + drive->fPacket.fLba = startFork; + + drive->fInput(&drive->fPacket); + + kcout << "Fork-Name: " << forkData->ForkName << endl; + + /// sanity check the fork. + if (forkData->DataOffset <= kNewFSCatalogStartAddress) + { + DbgLastError() = kErrorDiskIsCorrupted; + + kcout << "New OS: Invalid fork offset.\r"; + + delete forkData; + return false; + } + + if (forkData->Flags != kNewFSFlagUnallocated && + forkData->Flags != kNewFSFlagDeleted && + StringBuilder::Equals(forkData->ForkName, forkName) && + StringBuilder::Equals(forkData->CatalogName, catalog->Name)) + { + drive->fPacket.fPacketContent = data; + drive->fPacket.fPacketSize = sizeOfData; + drive->fPacket.fLba = forkData->DataOffset; + kcout << "Fork-Offset: " << hex_number(forkData->DataOffset) << endl; + + drive->fOutput(&drive->fPacket); + + delete forkData; + return true; + } + else if (auto catalog = this->GetCatalog(forkData->CatalogName); + catalog == nullptr) + { + delete catalog; + drive->fPacket.fPacketContent = data; + drive->fPacket.fPacketSize = sizeOfData; + drive->fPacket.fLba = forkData->DataOffset; + kcout << "Fork-Offset: " << hex_number(forkData->DataOffset) << endl; + + drive->fOutput(&drive->fPacket); + + delete forkData; + return true; + } + + startFork = forkData->NextSibling; + } + + delete forkData; + return false; +} + +/// @brief +/// @param catalogName the catalog name. +/// @return the newly found catalog. +_Output NewCatalog* NewFSParser::FindCatalog(_Input const char* catalogName, + Lba& outLba) +{ + if (!sMountpointInterface.GetAddressOf(this->fDriveIndex)) + return nullptr; + + Char* sectorBuf = new Char[sizeof(NewPartitionBlock)]; + auto drive = sMountpointInterface.GetAddressOf(this->fDriveIndex); + + rt_copy_memory((VoidPtr) "fs/newfs-packet", drive->fPacket.fPacketMime, + rt_string_len("fs/newfs-packet")); + + drive->fPacket.fPacketContent = sectorBuf; + drive->fPacket.fPacketSize = sizeof(NewPartitionBlock); + drive->fPacket.fLba = kNewFSAddressAsLba; + + drive->fInput(&drive->fPacket); + + NewPartitionBlock* part = (NewPartitionBlock*)sectorBuf; + + auto startCatalogList = part->StartCatalog; + const auto cCtartCatalogList = part->StartCatalog; + + auto localSearchFirst = false; + + drive->fPacket.fLba = startCatalogList; + drive->fPacket.fPacketContent = sectorBuf; + drive->fPacket.fPacketSize = sizeof(NewCatalog); + + drive->fInput(&drive->fPacket); + + if (!StringBuilder::Equals(catalogName, NewFilesystemHelper::Root())) + { + Char parentName[kNewFSNodeNameLen] = {0}; + + for (SizeT indexFill = 0; indexFill < rt_string_len(catalogName); ++indexFill) + { + parentName[indexFill] = catalogName[indexFill]; + } + + SizeT indexReverseCopy = rt_string_len(parentName); + + // zero character. + parentName[--indexReverseCopy] = 0; + + // mandatory '/' character. + parentName[--indexReverseCopy] = 0; + + while (parentName[indexReverseCopy] != NewFilesystemHelper::Separator()) + { + parentName[indexReverseCopy] = 0; + --indexReverseCopy; + } + + NewCatalog* parentCatalog = this->FindCatalog(parentName, outLba); + + if (parentCatalog && + !StringBuilder::Equals(parentName, NewFilesystemHelper::Root())) + { + startCatalogList = outLba; + delete parentCatalog; + + localSearchFirst = true; + } + else if (parentCatalog) + { + delete parentCatalog; + } + } + +_NewFSSearchThroughCatalogList: + while (drive->fPacket.fPacketGood) + { + NewCatalog* catalog = (NewCatalog*)sectorBuf; + + if (StringBuilder::Equals(catalogName, catalog->Name)) + { + /// ignore unallocated catalog, break + if (catalog->Flags != kNewFSFlagCreated) + { + goto _NewFSContinueSearch; + } + + NewCatalog* catalogPtr = new NewCatalog(); + rt_copy_memory(catalog, catalogPtr, sizeof(NewCatalog)); + + kcout << "New OS: Found catalog at: " << hex_number(startCatalogList) << endl; + + outLba = startCatalogList; + delete[] sectorBuf; + return catalogPtr; + } + + _NewFSContinueSearch: + startCatalogList = catalog->NextSibling; + + if (startCatalogList <= kNewFSAddressAsLba) + break; + + drive->fPacket.fLba = startCatalogList; + drive->fPacket.fPacketContent = sectorBuf; + drive->fPacket.fPacketSize = sizeof(NewCatalog); + + drive->fInput(&drive->fPacket); + } + + if (localSearchFirst) + { + localSearchFirst = false; + startCatalogList = cCtartCatalogList; + + goto _NewFSSearchThroughCatalogList; + } + + outLba = 0UL; + delete[] sectorBuf; + + return nullptr; +} + +/// @brief +/// @param name +/// @return +_Output NewCatalog* NewFSParser::GetCatalog(_Input const char* name) +{ + Lba unused = 0; + return this->FindCatalog(name, unused); +} + +/// @brief +/// @param catalog +/// @return +Boolean NewFSParser::CloseCatalog(_Input _Output NewCatalog* catalog) +{ + if (!catalog) + return false; + + delete catalog; + catalog = nullptr; + + return true; +} + +/// @brief Mark catalog as removed. +/// @param catalog The catalog structure. +/// @return if the catalog was removed or not. +Boolean NewFSParser::RemoveCatalog(_Input const Char* catalogName) +{ + if (!catalogName || + StringBuilder::Equals(catalogName, NewFilesystemHelper::Root())) + { + DbgLastError() = kErrorInternal; + return false; + } + + Lba outLba = 0; + auto catalog = this->FindCatalog(catalogName, outLba); + + if (outLba >= kNewFSCatalogStartAddress || + catalog->Flags == kNewFSFlagCreated) + { + catalog->Flags = kNewFSFlagDeleted; + + auto drive = sMountpointInterface.GetAddressOf(this->fDriveIndex); + + rt_copy_memory((VoidPtr) "fs/newfs-packet", drive->fPacket.fPacketMime, + rt_string_len("fs/newfs-packet")); + + drive->fPacket.fLba = outLba; // the catalog position. + drive->fPacket.fPacketSize = + sizeof(NewCatalog); // size of catalog. roughly the sector size. + drive->fPacket.fPacketContent = catalog; // the catalog itself. + + drive->fOutput(&drive->fPacket); // send packet. + + Char partitionBlockBuf[sizeof(NewPartitionBlock)] = {0}; + + drive->fPacket.fLba = kNewFSAddressAsLba; + drive->fPacket.fPacketContent = partitionBlockBuf; + drive->fPacket.fPacketSize = sizeof(NewPartitionBlock); + + drive->fInput(&drive->fPacket); + + NewPartitionBlock* partBlock = + reinterpret_cast(partitionBlockBuf); + + ++partBlock->FreeCatalog; + --partBlock->CatalogCount; + + drive->fOutput(&drive->fPacket); + + return true; + } + + delete catalog; + return false; +} + +/// ***************************************************************** /// +/// Reading,Seek,Tell are unimplemented on catalogs, refer to forks I/O instead. +/// ***************************************************************** /// + +/***********************************************************************************/ +/// @brief Read the catalog data fork. +/// @param catalog +/// @param dataSz +/// @return +/***********************************************************************************/ + +VoidPtr NewFSParser::ReadCatalog(_Input _Output NewCatalog* catalog, + _Input SizeT dataSz, + _Input const char* forkName) +{ + if (!catalog) + { + DbgLastError() = kErrorFileNotFound; + return nullptr; + } + + if (!sMountpointInterface.GetAddressOf(this->fDriveIndex)) + return nullptr; + + Lba dataForkLba = catalog->DataFork; + Size dataForkSize = catalog->DataForkSize; + + kcout << "Found-Catalog: " << catalog->Name + << ", Data-Fork: " << hex_number(dataForkLba) << endl; + + Char* sectorBuf = new Char[sizeof(NewFork)]; + auto drive = sMountpointInterface.GetAddressOf(this->fDriveIndex); + + rt_copy_memory((VoidPtr) "fs/newfs-packet", drive->fPacket.fPacketMime, + rt_string_len("fs/newfs-packet")); + + NewFork* forkData = nullptr; + + while (dataForkLba >= kNewFSCatalogStartAddress) + { + drive->fPacket.fLba = dataForkLba; + drive->fPacket.fPacketSize = sizeof(NewFork); + drive->fPacket.fPacketContent = sectorBuf; + + drive->fInput(&drive->fPacket); + + forkData = (NewFork*)sectorBuf; + + kcout << "Fork-Name: " << forkData->ForkName << endl; + + if (forkData->DataOffset <= kNewFSCatalogStartAddress) + { + delete[] sectorBuf; + + kcout << "Fail-Data-Offset: " << hex_number(forkData->DataOffset) << endl; + + return nullptr; + } + + if (StringBuilder::Equals(forkName, forkData->ForkName) && + StringBuilder::Equals(catalog->Name, forkData->CatalogName)) + break; + + dataForkLba = forkData->NextSibling; + } + + if (dataForkLba <= kNewFSCatalogStartAddress) + { + delete[] sectorBuf; + return nullptr; + } + + Char* forkBuf = new Char[dataSz]; + + drive->fPacket.fLba = forkData->DataOffset; + drive->fPacket.fPacketSize = dataSz; + drive->fPacket.fPacketContent = forkBuf; + + drive->fInput(&drive->fPacket); + + delete[] sectorBuf; + return forkBuf; +} + +/***********************************************************************************/ +/// @brief Seek in the data fork. +/// @param catalog the catalog offset. +/// @param off where to seek. +/// @return if the seeking was successful. +/***********************************************************************************/ + +bool NewFSParser::Seek(_Input _Output NewCatalog* catalog, SizeT off) +{ + if (!catalog) + { + DbgLastError() = kErrorFileNotFound; + return false; + } + + DbgLastError() = kErrorUnimplemented; + return false; +} + +/***********************************************************************************/ +/// @brief Tell where we are inside the data fork. +/// @param catalog +/// @return The position on the file. +/***********************************************************************************/ + +SizeT NewFSParser::Tell(_Input _Output NewCatalog* catalog) +{ + if (!catalog) + { + DbgLastError() = kErrorFileNotFound; + return 0; + } + + DbgLastError() = kErrorUnimplemented; + return 0; +} + +namespace NewOS::Detail +{ + /***********************************************************************************/ + /// @brief Construct NewFS drives. + /***********************************************************************************/ + Boolean fs_init_newfs(Void) noexcept + { + sMountpointInterface.A() = construct_main_drive(); + sMountpointInterface.B() = construct_drive(); + sMountpointInterface.C() = construct_drive(); + sMountpointInterface.D() = construct_drive(); + + sMountpointInterface.A().fVerify(&sMountpointInterface.A().fPacket); + + Char partitionBlockBuf[sizeof(NewPartitionBlock)] = {0}; + + sMountpointInterface.A().fPacket.fLba = kNewFSAddressAsLba; + sMountpointInterface.A().fPacket.fPacketContent = partitionBlockBuf; + sMountpointInterface.A().fPacket.fPacketSize = sizeof(NewPartitionBlock); + + sMountpointInterface.A().fInput(&sMountpointInterface.A().fPacket); + + NewPartitionBlock* partBlock = + reinterpret_cast(partitionBlockBuf); + + if (!StringBuilder::Equals(partBlock->Ident, kNewFSIdent)) + { + kcout << "New OS: New FS Partition is corrupt.\r"; + return false; + } + + kcout << "New OS: Read partition: " << partBlock->PartitionName << ", with success!\r"; + + return true; + } +} // namespace NewOS::Detail + +#endif // ifdef __FSKIT_NEWFS__ diff --git a/Kernel/Source/FileManager.cxx b/Kernel/Source/FileManager.cxx new file mode 100644 index 00000000..72ea15a1 --- /dev/null +++ b/Kernel/Source/FileManager.cxx @@ -0,0 +1,183 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +/// BUGS: 0 +//! @brief File manager for NewOS. + +namespace NewOS +{ + static FilesystemManagerInterface* kMounted = nullptr; + + /// @brief FilesystemManager getter. + /// @return The mounted filesystem. + FilesystemManagerInterface* FilesystemManagerInterface::GetMounted() + { + return kMounted; + } + + /// @brief Unmount filesystem. + /// @return The unmounted filesystem. + FilesystemManagerInterface* FilesystemManagerInterface::Unmount() + { + if (kMounted) + { + auto mount = kMounted; + kMounted = nullptr; + + return mount; + } + + return nullptr; + } + + /// @brief Mount filesystem. + /// @param mountPtr The filesystem to mount. + /// @return if it succeeded true, otherwise false. + bool FilesystemManagerInterface::Mount(FilesystemManagerInterface* mountPtr) + { + if (kMounted == nullptr) + { + kMounted = mountPtr; + return true; + } + + return false; + } + +#ifdef __FSKIT_NEWFS__ + /// @brief Opens a new file. + /// @param path + /// @param r + /// @return + NodePtr NewFilesystemManager::Open(const char* path, const char* r) + { + if (!path || *path == 0) + return nullptr; + + if (!r || *r == 0) + return nullptr; + + auto catalog = fImpl->GetCatalog(path); + + if (catalog->Kind != kNewFSCatalogKindFile) + { + fImpl->CloseCatalog(catalog); + return nullptr; + } + + return node_cast(catalog); + } + + /// @brief Writes to a catalog's fork. + /// @param node the node ptr. + /// @param data the data. + /// @param flags the size. + /// @return + Void NewFilesystemManager::Write(NodePtr node, VoidPtr data, Int32 flags, SizeT size) + { + if (!size || + size > kNewFSForkSize) + return; + + if (!data) + return; + + NEWOS_UNUSED(flags); + + const char* cReadAllFork = fDataFork; + + if ((reinterpret_cast(node))->Kind == kNewFSCatalogKindFile) + fImpl->WriteCatalog(reinterpret_cast(node), data, size, + cReadAllFork); + } + + /// @brief Read from filesystem fork. + /// @param node the catalog node. + /// @param flags the flags with it. + /// @param sz the size to read. + /// @return + VoidPtr NewFilesystemManager::Read(NodePtr node, Int32 flags, SizeT sz) + { + if (sz > kNewFSForkSize) + return nullptr; + + if (!sz) + return nullptr; + + NEWOS_UNUSED(flags); + + const char* cReadAllFork = fDataFork; + + if ((reinterpret_cast(node))->Kind == kNewFSCatalogKindFile) + return fImpl->ReadCatalog(reinterpret_cast(node), sz, + cReadAllFork); + + return nullptr; + } + + /// @brief Seek from Catalog. + /// @param node + /// @param off + /// @retval true always returns false, this is unimplemented. + /// @retval false always returns this, it is unimplemented. + + bool NewFilesystemManager::Seek(NodePtr node, SizeT off) + { + if (!node || off == 0) + return false; + + return fImpl->Seek(reinterpret_cast(node), off); + } + + /// @brief Tell where the catalog is. + /// @param node + /// @retval true always returns false, this is unimplemented. + /// @retval false always returns this, it is unimplemented. + + SizeT NewFilesystemManager::Tell(NodePtr node) + { + if (!node) + return kNPos; + + return fImpl->Tell(reinterpret_cast(node)); + } + + /// @brief Rewinds the catalog. + /// @param node + /// @retval true always returns false, this is unimplemented. + /// @retval false always returns this, it is unimplemented. + + bool NewFilesystemManager::Rewind(NodePtr node) + { + if (!node) + return false; + + return this->Seek(node, 0); + } + + /// @brief Returns the filesystem parser. + /// @return the Filesystem parser class. + NewFSParser* NewFilesystemManager::GetImpl() noexcept + { + return fImpl; + } + + void NewFilesystemManager::SetResourceFork(const char* forkName) + { + if (!forkName) return; + rt_copy_memory((VoidPtr)forkName, (VoidPtr)fRsrcFork, rt_string_len(forkName)); + } + + void NewFilesystemManager::SetDataFork(const char* forkName) + { + if (!forkName) return; + rt_copy_memory((VoidPtr)forkName, (VoidPtr)fDataFork, rt_string_len(forkName)); + } +#endif // __FSKIT_NEWFS__ +} // namespace NewOS diff --git a/Kernel/Source/Framebuffer.cxx b/Kernel/Source/Framebuffer.cxx new file mode 100644 index 00000000..7d36c722 --- /dev/null +++ b/Kernel/Source/Framebuffer.cxx @@ -0,0 +1,96 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: Framebuffer.cxx + Purpose: Framebuffer object + + Revision History: + + 01/02/24: Added file (amlel) + 02/02/24: Add documentation (amlel) + +------------------------------------------- */ + +#include + +/** + * @brief Framebuffer object implementation. + * + */ + +using namespace NewOS; + +namespace NewOS +{ + const UInt32 kRgbRed = 0x000000FF; + const UInt32 kRgbGreen = 0x0000FF00; + const UInt32 kRgbBlue = 0x00FF0000; + const UInt32 kRgbBlack = 0x00000000; + const UInt32 kRgbWhite = 0xFFFFFFFF; +} // namespace NewOS + +/** + * @brief Get Pixel at + * + * @param pos position of pixel. + * @return volatile* + */ +volatile UIntPtr* Framebuffer::operator[](const UIntPtr& pos) +{ + return (UIntPtr*)(fFrameBufferAddr->fBase * pos); +} + +/// @brief Boolean operator. +Framebuffer::operator bool() +{ + return fFrameBufferAddr.Leak()->fBase != 0 && + fColour != FramebufferColorKind::INVALID && + fFrameBufferAddr.Leak()->fBase != kBadPtr; +} + +/// @brief Set color kind of framebuffer. +/// @param colour +/// @return +const FramebufferColorKind& Framebuffer::Color( + const FramebufferColorKind& colour) +{ + if (fColour != FramebufferColorKind::INVALID && + colour != FramebufferColorKind::INVALID) + { + fColour = colour; + } + + return fColour; +} + +/// @brief Leak framebuffer context. +/// @return The reference of the framebuffer context. +Ref& Framebuffer::Leak() +{ + return this->fFrameBufferAddr; +} + +Framebuffer& Framebuffer::DrawRect(SizeT width, SizeT height, SizeT x, SizeT y, UInt32 color) +{ + for (NewOS::SizeT i = x; i < width + x; ++i) + { + for (NewOS::SizeT u = y; u < height + y; ++u) + { + *(((volatile NewOS::UInt32*)(fFrameBufferAddr.Leak()->fBase + + 4 * fFrameBufferAddr.Leak()->fBpp * i + + 4 * u))) = color; + } + } + + return *this; +} + +Framebuffer& Framebuffer::PutPixel(SizeT x, SizeT y, UInt32 color) +{ + *(((volatile NewOS::UInt32*)(fFrameBufferAddr.Leak()->fBase + + 4 * fFrameBufferAddr.Leak()->fBpp * x + + 4 * y))) = color; + + return *this; +} \ No newline at end of file diff --git a/Kernel/Source/GUIDWizard.cxx b/Kernel/Source/GUIDWizard.cxx new file mode 100644 index 00000000..2e4ffafa --- /dev/null +++ b/Kernel/Source/GUIDWizard.cxx @@ -0,0 +1,65 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: GUIDWizard.cxx + Purpose: GUID helper code + + Revision History: + +------------------------------------------- */ + +#include +#include + +// begin of ascii 'readable' characters. (A, C, C, 1, 2) +#define kAsciiBegin 47 +// @brief Size of UUID. +#define kUUIDSize 37 + +namespace NewOS::XRN::Version1 +{ + auto make_sequence(const ArrayList& uuidSeq) -> Ref + { + GUIDSequence* seq = new GUIDSequence(); + MUST_PASS(seq); + + Ref sequenceReference{seq, true}; + + sequenceReference->fMs1 |= uuidSeq[0]; + sequenceReference->fMs2 |= uuidSeq[1]; + sequenceReference->fMs3 |= uuidSeq[2]; + sequenceReference->fMs3 |= uuidSeq[3]; + + return sequenceReference; + } + + // @brief Tries to make a guid out of a string. + // This function is not complete for now + auto try_guid_to_string(Ref& seq) -> ErrorOr> + { + Char buf[kUUIDSize]; + + for (SizeT index = 0; index < 16; ++index) + { + buf[index] = seq->u8[index] + kAsciiBegin; + } + + for (SizeT index = 16; index < 24; ++index) + { + buf[index] = seq->u16[index] + kAsciiBegin; + } + + for (SizeT index = 24; index < 28; ++index) + { + buf[index] = seq->u32[index] + kAsciiBegin; + } + + auto view = StringBuilder::Construct(buf); + + if (view) + return ErrorOr>{view.Leak()}; + + return ErrorOr>{-1}; + } +} // namespace NewOS::XRN::Version1 diff --git a/Kernel/Source/GUIDWrapper.cxx b/Kernel/Source/GUIDWrapper.cxx new file mode 100644 index 00000000..d8ed28e0 --- /dev/null +++ b/Kernel/Source/GUIDWrapper.cxx @@ -0,0 +1,11 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS::XRN +{ +} diff --git a/Kernel/Source/HError.cxx b/Kernel/Source/HError.cxx new file mode 100644 index 00000000..bee5a467 --- /dev/null +++ b/Kernel/Source/HError.cxx @@ -0,0 +1,18 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ + /// @brief Doea a system wide bug check. + /// @param void no params. + /// @return if error-free: true, otherwise false. + Boolean ke_bug_check(void) noexcept + { + return true; + } +} // namespace NewOS diff --git a/Kernel/Source/IndexableProperty.cxx b/Kernel/Source/IndexableProperty.cxx new file mode 100644 index 00000000..305d0988 --- /dev/null +++ b/Kernel/Source/IndexableProperty.cxx @@ -0,0 +1,57 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +//! @brief Filesystem Indexer. + +#include +#include +#include +#include + +/// @brief File Indexer. +/// BUGS: 0 + +#define kMaxLenIndexer 256 + +namespace NewOS +{ + namespace Indexer + { + IndexProperty& IndexableProperty::LeakProperty() noexcept + { + return fIndex; + } + + void IndexableProperty::AddFlag(Int16 flag) + { + fFlags |= flag; + } + void IndexableProperty::RemoveFlag(Int16 flag) + { + fFlags &= flag; + } + Int16 IndexableProperty::HasFlag(Int16 flag) + { + return fFlags & flag; + } + + /// @brief Index a file into the indexer instance. + /// @param filename path + /// @param filenameLen used bytes in path. + /// @param indexer the filesystem indexer. + /// @return none. + Void fs_index_file(const Char* filename, SizeT filenameLen, IndexableProperty& indexer) + { + if (!indexer.HasFlag(kIndexerClaimed)) + { + indexer.AddFlag(kIndexerClaimed); + rt_copy_memory((VoidPtr)indexer.LeakProperty().Path, (VoidPtr)filename, filenameLen); + + kcout << "New OS: FSKit: index new file: " << filename << endl; + } + } + } // namespace Indexer +} // namespace NewOS diff --git a/Kernel/Source/Json.cxx b/Kernel/Source/Json.cxx new file mode 100644 index 00000000..672c1b39 --- /dev/null +++ b/Kernel/Source/Json.cxx @@ -0,0 +1,12 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +using namespace NewOS; + +/// @brief Undefined object, is null in length. +INIT(NewOS::JsonType::kUndefined, NewOS::JsonType); diff --git a/Kernel/Source/KernelCheck.cxx b/Kernel/Source/KernelCheck.cxx new file mode 100644 index 00000000..e7c43650 --- /dev/null +++ b/Kernel/Source/KernelCheck.cxx @@ -0,0 +1,109 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include +#include + +extern "C" [[noreturn]] void ke_wait_for_debugger() +{ + while (true) + { + NewOS::HAL::rt_cli(); + NewOS::HAL::rt_halt(); + } +} + +/* Each error code is attributed with an ID, which will prompt a string onto the + * screen. Wait for debugger... */ + +namespace NewOS +{ + void ke_stop(const NewOS::Int& id) + { + kcout << "*** STOP *** \r"; + kcout << "*** NewKernel.exe has trigerred a runtime stop. *** \r"; + + switch (id) + { + case RUNTIME_CHECK_PROCESS: { + kcout << "*** CAUSE: RUNTIME_CHECK_PROCESS *** \r"; + kcout << "*** WHAT: BAD DRIVER. *** \r"; + break; + } + case RUNTIME_CHECK_ACPI: { + kcout << "*** CAUSE: RUNTIME_CHECK_ACPI *** \r"; + kcout << "*** WHAT: ACPI ERROR, UNSTABLE STATE. *** \r"; + break; + } + case RUNTIME_CHECK_POINTER: { + kcout << "*** CAUSE: RUNTIME_CHECK_POINTER *** \r"; + kcout << "*** WHAT: HEAP CRC32 ERROR, UNSTABLE STATE. *** \r"; + break; + } + case RUNTIME_CHECK_BAD_BEHAVIOR: { + kcout << "*** CAUSE: RUNTIME_CHECK_BAD_BEHAVIOR *** \r"; + kcout << "*** WHAT: KERNEL BECAME UNSTABLE. *** \r"; + break; + } + case RUNTIME_CHECK_BOOTSTRAP: { + kcout << "*** CAUSE: RUNTIME_CHECK_BOOTSTRAP *** \r"; + kcout << "*** WHAT: INVALID BOOT SEQUENCE. *** \r"; + break; + } + case RUNTIME_CHECK_HANDSHAKE: { + kcout << "*** CAUSE: RUNTIME_CHECK_HANDSHAKE *** \r"; + kcout << "*** WHAT: BAD HANDSHAKE. *** \r"; + break; + } + case RUNTIME_CHECK_IPC: { + kcout << "*** CAUSE: RUNTIME_CHECK_IPC *** \r"; + kcout << "*** WHAT: RICH CALL VIOLATION. *** \r"; + break; + } + case RUNTIME_CHECK_INVALID_PRIVILEGE: { + kcout << "*** CAUSE: RUNTIME_CHECK_INVALID_PRIVILEGE *** \r"; + kcout << "*** WHAT: HYPERVISOR POLICY VIOLATION. *** \r"; + break; + case RUNTIME_CHECK_UNEXCPECTED: { + kcout << "*** CAUSE: RUNTIME_CHECK_UNEXCPECTED *** \r"; + kcout << "*** WHAT: CATASROPHIC FAILURE! *** \r"; + break; + } + case RUNTIME_CHECK_FAILED: { + kcout << "*** CAUSE: RUNTIME_CHECK_FAILED *** \r"; + kcout << "*** WHAT: ASSERTION FAILED! *** \r"; + break; + } + default: { + kcout << "*** CAUSE: RUNTIME_CHECK_GENERIC *** \r"; + break; + } + } + }; + + DumpManager::Dump(); + +#ifdef __DEBUG__ + ke_wait_for_debugger(); +#endif // ifdef __DEBUG__ + } + + void ke_runtime_check(bool expr, const char* file, const char* line) + { + if (!expr) + { +#ifdef __DEBUG__ + kcout << "New Kernel: File: " << file << "\r"; + kcout << "New Kernel: Line: " << line << "\r"; + +#endif // __DEBUG__ + + NewOS::ke_stop(RUNTIME_CHECK_FAILED); // Runtime Check failed + } + } +} // namespace NewOS diff --git a/Kernel/Source/KernelHeap.cxx b/Kernel/Source/KernelHeap.cxx new file mode 100644 index 00000000..d0037ec3 --- /dev/null +++ b/Kernel/Source/KernelHeap.cxx @@ -0,0 +1,169 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include +#include +#include + +//! @file KernelHeap.cxx +//! @brief Kernel allocator. + +#define kKernelHeapMagic (0xD4D7D5) +#define kKernelHeapHeaderPaddingSz (16U) + +namespace NewOS +{ + STATIC SizeT kHeapCount = 0UL; + STATIC PageManager kHeapPageManager; + + namespace Detail + { + /// @brief Kernel heap information block. + /// Located before the address bytes. + /// | HIB | ADDRESS | + struct PACKED HeapInformationBlock final + { + ///! @brief 32-bit value which contains the magic number of the executable. + UInt32 fMagic; + ///! @brief Boolean value which tells if the pointer is allocated. + Boolean fPresent; + ///! @brief 32-bit CRC checksum + UInt32 fCRC32; + /// @brief 64-bit pointer size. + SizeT fTargetPtrSize; + /// @brief 64-bit target pointer. + UIntPtr fTargetPtr; + UInt8 fPadding[kKernelHeapHeaderPaddingSz]; + }; + + typedef HeapInformationBlock* HeapInformationBlockPtr; + } // namespace Detail + + /// @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 pointer + VoidPtr ke_new_ke_heap(SizeT sz, const bool rw, const bool user) + { + if (sz == 0) + ++sz; + + auto wrapper = kHeapPageManager.Request(rw, user, false, sz); + + Detail::HeapInformationBlockPtr heapInfo = + reinterpret_cast( + wrapper.VirtualAddress()); + + heapInfo->fTargetPtrSize = sz; + heapInfo->fMagic = kKernelHeapMagic; + heapInfo->fCRC32 = 0; // dont fill it for now. + heapInfo->fTargetPtr = wrapper.VirtualAddress(); + + ++kHeapCount; + + return reinterpret_cast(wrapper.VirtualAddress() + + sizeof(Detail::HeapInformationBlock)); + } + + /// @brief Declare pointer as free. + /// @param heapPtr the pointer. + /// @return + Int32 ke_delete_ke_heap(VoidPtr heapPtr) + { + if (kHeapCount < 1) + return -kErrorInternal; + if (((IntPtr)heapPtr - sizeof(Detail::HeapInformationBlock)) <= 0) + return -kErrorInternal; + if (((IntPtr)heapPtr - kBadPtr) < 0) + return -kErrorInternal; + + Detail::HeapInformationBlockPtr virtualAddress = + reinterpret_cast( + (UIntPtr)heapPtr - sizeof(Detail::HeapInformationBlock)); + + if (virtualAddress && virtualAddress->fMagic == kKernelHeapMagic) + { + if (!virtualAddress->fPresent) + { + return -kErrorHeapNotPresent; + } + + if (virtualAddress->fCRC32 != 0) + { + if (virtualAddress->fCRC32 != + ke_calculate_crc32((Char*)virtualAddress->fTargetPtr, + virtualAddress->fTargetPtrSize)) + { + ke_stop(RUNTIME_CHECK_POINTER); + } + } + + virtualAddress->fTargetPtrSize = 0UL; + virtualAddress->fPresent = false; + virtualAddress->fTargetPtr = 0; + virtualAddress->fCRC32 = 0; + virtualAddress->fMagic = 0; + + PTEWrapper pageWrapper(false, false, false, (UIntPtr)virtualAddress); + Ref pteAddress{&pageWrapper}; + + kHeapPageManager.Free(pteAddress); + + --kHeapCount; + return 0; + } + + return -kErrorInternal; + } + + /// @brief Check if pointer is a valid kernel pointer. + /// @param heapPtr the pointer + /// @return if it exists. + Boolean ke_is_valid_heap(VoidPtr heapPtr) + { + if (kHeapCount < 1) + return false; + + if (heapPtr) + { + Detail::HeapInformationBlockPtr virtualAddress = + reinterpret_cast( + (UIntPtr)heapPtr - sizeof(Detail::HeapInformationBlock)); + + if (virtualAddress->fPresent && virtualAddress->fMagic == kKernelHeapMagic) + { + return true; + } + } + + return false; + } + + /// @brief Protect the heap with a CRC value. + /// @param heapPtr HIB pointer. + /// @return if it valid: point has crc now., otherwise fail. + Boolean ke_protect_ke_heap(VoidPtr heapPtr) + { + if (heapPtr) + { + Detail::HeapInformationBlockPtr virtualAddress = + reinterpret_cast( + (UIntPtr)heapPtr - sizeof(Detail::HeapInformationBlock)); + + if (virtualAddress->fPresent && kKernelHeapMagic == virtualAddress->fMagic) + { + virtualAddress->fCRC32 = + ke_calculate_crc32((Char*)heapPtr, virtualAddress->fTargetPtrSize); + return true; + } + } + + return false; + } +} // namespace NewOS diff --git a/Kernel/Source/LockDelegate.cxx b/Kernel/Source/LockDelegate.cxx new file mode 100644 index 00000000..70e421f7 --- /dev/null +++ b/Kernel/Source/LockDelegate.cxx @@ -0,0 +1,12 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ + /// Leave it empty for now. +} // namespace NewOS \ No newline at end of file diff --git a/Kernel/Source/MutableArray.cxx b/Kernel/Source/MutableArray.cxx new file mode 100644 index 00000000..047a4455 --- /dev/null +++ b/Kernel/Source/MutableArray.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/Network/IP.cxx b/Kernel/Source/Network/IP.cxx new file mode 100644 index 00000000..224f7b2a --- /dev/null +++ b/Kernel/Source/Network/IP.cxx @@ -0,0 +1,126 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +namespace NewOS +{ + char* RawIPAddress::Address() + { + return fAddr; + } + + RawIPAddress::RawIPAddress(char bytes[4]) + { + rt_copy_memory(bytes, fAddr, 4); + } + + bool RawIPAddress::operator==(const RawIPAddress& ipv4) + { + for (Size index = 0; index < 4; ++index) + { + if (ipv4.fAddr[index] != fAddr[index]) + return false; + } + + return true; + } + + bool RawIPAddress::operator!=(const RawIPAddress& ipv4) + { + for (Size index = 0; index < 4; ++index) + { + if (ipv4.fAddr[index] == fAddr[index]) + return false; + } + + return true; + } + + char& RawIPAddress::operator[](const Size& index) + { + kcout << "[RawIPAddress::operator[]] Fetching Index...\r"; + + static char IP_PLACEHOLDER = '0'; + if (index > 4) + return IP_PLACEHOLDER; + + return fAddr[index]; + } + + RawIPAddress6::RawIPAddress6(char bytes[8]) + { + rt_copy_memory(bytes, fAddr, 8); + } + + char& RawIPAddress6::operator[](const Size& index) + { + kcout << "[RawIPAddress6::operator[]] Fetching Index...\r"; + + static char IP_PLACEHOLDER = '0'; + if (index > 8) + return IP_PLACEHOLDER; + + return fAddr[index]; + } + + bool RawIPAddress6::operator==(const RawIPAddress6& ipv6) + { + for (SizeT index = 0; index < 8; ++index) + { + if (ipv6.fAddr[index] != fAddr[index]) + return false; + } + + return true; + } + + bool RawIPAddress6::operator!=(const RawIPAddress6& ipv6) + { + for (SizeT index = 0; index < 8; ++index) + { + if (ipv6.fAddr[index] == fAddr[index]) + return false; + } + + return true; + } + + ErrorOr IPFactory::ToStringView(Ref ipv6) + { + auto str = StringBuilder::Construct(ipv6.Leak().Address()); + return str; + } + + ErrorOr IPFactory::ToStringView(Ref ipv4) + { + auto str = StringBuilder::Construct(ipv4.Leak().Address()); + return str; + } + + bool IPFactory::IpCheckVersion4(const char* ip) + { + int cnter = 0; + + for (Size base = 0; base < rt_string_len(ip); ++base) + { + if (ip[base] == '.') + { + cnter = 0; + } + else + { + if (cnter == 3) + return false; + + ++cnter; + } + } + + return true; + } +} // namespace NewOS diff --git a/Kernel/Source/Network/IPCEP.cxx b/Kernel/Source/Network/IPCEP.cxx new file mode 100644 index 00000000..39f3ea33 --- /dev/null +++ b/Kernel/Source/Network/IPCEP.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/Network/NetworkDevice.cxx b/Kernel/Source/Network/NetworkDevice.cxx new file mode 100644 index 00000000..a2c25782 --- /dev/null +++ b/Kernel/Source/Network/NetworkDevice.cxx @@ -0,0 +1,15 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ + const char* NetworkDevice::Name() const + { + return "NetworkDevice"; + } +} // namespace NewOS diff --git a/Kernel/Source/New+Delete.cxx b/Kernel/Source/New+Delete.cxx new file mode 100644 index 00000000..84e3a72d --- /dev/null +++ b/Kernel/Source/New+Delete.cxx @@ -0,0 +1,50 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +void* operator new[](size_t sz) +{ + if (sz == 0) + ++sz; + + return NewOS::ke_new_ke_heap(sz, true, false); +} + +void* operator new(size_t sz) +{ + if (sz == 0) + ++sz; + + return NewOS::ke_new_ke_heap(sz, true, false); +} + +void operator delete[](void* ptr) +{ + if (ptr == nullptr) + return; + + NewOS::ke_delete_ke_heap(ptr); +} + +void operator delete(void* ptr) +{ + if (ptr == nullptr) + return; + + NewOS::ke_delete_ke_heap(ptr); +} + +void operator delete(void* ptr, size_t sz) +{ + if (ptr == nullptr) + return; + + NEWOS_UNUSED(sz); + + NewOS::ke_delete_ke_heap(ptr); +} diff --git a/Kernel/Source/NewFS+FileManager.cxx b/Kernel/Source/NewFS+FileManager.cxx new file mode 100644 index 00000000..bcfc0443 --- /dev/null +++ b/Kernel/Source/NewFS+FileManager.cxx @@ -0,0 +1,89 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +#ifdef __FSKIT_NEWFS__ + +/// @brief NewFS File manager. +/// BUGS: 0 + +namespace NewOS +{ + /// @brief C++ constructor + NewFilesystemManager::NewFilesystemManager() + { + MUST_PASS(Detail::fs_init_newfs()); + fImpl = new NewFSParser(); + } + + NewFilesystemManager::~NewFilesystemManager() + { + if (fImpl) + { + delete fImpl; + } + } + + /// @brief Removes a node from the filesystem. + /// @param fileName The filename + /// @return If it was deleted or not. + bool NewFilesystemManager::Remove(const char* fileName) + { + if (fileName == nullptr || *fileName == 0) + return false; + + return fImpl->RemoveCatalog(fileName); + } + + /// @brief Creates a node with the specified. + /// @param path The filename path. + /// @return The Node pointer. + NodePtr NewFilesystemManager::Create(const char* path) + { + return node_cast(fImpl->CreateCatalog(path, 0, kNewFSCatalogKindFile)); + } + + /// @brief Creates a node with is a directory. + /// @param path The filename path. + /// @return The Node pointer. + NodePtr NewFilesystemManager::CreateDirectory(const char* path) + { + return node_cast(fImpl->CreateCatalog(path, 0, kNewFSCatalogKindDir)); + } + + /// @brief Creates a node with is a alias. + /// @param path The filename path. + /// @return The Node pointer. + NodePtr NewFilesystemManager::CreateAlias(const char* path) + { + return node_cast(fImpl->CreateCatalog(path, 0, kNewFSCatalogKindAlias)); + } + + /// @brief Gets the root directory. + /// @return + const char* NewFilesystemHelper::Root() + { + return kNewFSRoot; + } + + /// @brief Gets the up-dir directory. + /// @return + const char* NewFilesystemHelper::UpDir() + { + return kNewFSUpDir; + } + + /// @brief Gets the separator character. + /// @return + const char NewFilesystemHelper::Separator() + { + return kNewFSSeparator; + } +} // namespace NewOS + +#endif // ifdef __FSKIT_NEWFS__ diff --git a/Kernel/Source/NewFS+IO.cxx b/Kernel/Source/NewFS+IO.cxx new file mode 100644 index 00000000..3235c080 --- /dev/null +++ b/Kernel/Source/NewFS+IO.cxx @@ -0,0 +1,101 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +/************************************************************* + * + * File: NewFS+IO.cxx + * Purpose: Filesystem to mountpoint interface. + * Date: 3/26/24 + * + * Copyright SoftwareLabs, all rights reserved. + * + *************************************************************/ + +#ifdef __FSKIT_NEWFS__ + +#include + +/// Useful macros. + +#define NEWFS_WRITE(DRV, TRAITS, MP) (MP->DRV()).fOutput(&TRAITS) +#define NEWFS_READ(DRV, TRAITS, MP) (MP->DRV()).fInput(&TRAITS) + +using namespace NewOS; + +/// @brief Read from newfs disk. +/// @param Mnt mounted interface. +/// @param DrvTrait drive info +/// @param DrvIndex drive index. +/// @return +Int32 fs_newfs_read(MountpointInterface* Mnt, DriveTrait& DrvTrait, Int32 DrvIndex) +{ + if (!Mnt) + return -1; + + DrvTrait.fPacket.fPacketGood = false; + + switch (DrvIndex) + { + case kNewFSSubDriveA: { + NEWFS_READ(A, DrvTrait.fPacket, Mnt); + break; + } + case kNewFSSubDriveB: { + NEWFS_READ(B, DrvTrait.fPacket, Mnt); + break; + } + case kNewFSSubDriveC: { + NEWFS_READ(C, DrvTrait.fPacket, Mnt); + break; + } + case kNewFSSubDriveD: { + NEWFS_READ(D, DrvTrait.fPacket, Mnt); + break; + } + } + + return DrvTrait.fPacket.fPacketGood; +} + +/// @brief Write to newfs disk. +/// @param Mnt mounted interface. +/// @param DrvTrait drive info +/// @param DrvIndex drive index. +/// @return +Int32 fs_newfs_write(MountpointInterface* Mnt, DriveTrait& DrvTrait, Int32 DrvIndex) +{ + if (!Mnt) + return -1; + + DrvTrait.fPacket.fPacketGood = false; + + switch (DrvIndex) + { + case kNewFSSubDriveA: { + NEWFS_WRITE(A, DrvTrait.fPacket, Mnt); + break; + } + case kNewFSSubDriveB: { + NEWFS_WRITE(B, DrvTrait.fPacket, Mnt); + break; + } + case kNewFSSubDriveC: { + NEWFS_WRITE(C, DrvTrait.fPacket, Mnt); + break; + } + case kNewFSSubDriveD: { + NEWFS_WRITE(D, DrvTrait.fPacket, Mnt); + break; + } + } + + return DrvTrait.fPacket.fPacketGood; +} + +#endif // ifdef __FSKIT_NEWFS__ diff --git a/Kernel/Source/NewFS+Journal.cxx b/Kernel/Source/NewFS+Journal.cxx new file mode 100644 index 00000000..23f42f89 --- /dev/null +++ b/Kernel/Source/NewFS+Journal.cxx @@ -0,0 +1,22 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +#ifdef __FSKIT_NEWFS__ + +///! BUGS: 0 +///! @file NewFS+Journal.cxx +///! @brief Journaling for NewFS. + +namespace NewOS::Journal +{ +} // namespace NewOS::Journal + +using namespace NewOS; + +#endif // ifdef __FSKIT_NEWFS__ diff --git a/Kernel/Source/OwnPtr.cxx b/Kernel/Source/OwnPtr.cxx new file mode 100644 index 00000000..909eacef --- /dev/null +++ b/Kernel/Source/OwnPtr.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/PEFCodeManager.cxx b/Kernel/Source/PEFCodeManager.cxx new file mode 100644 index 00000000..0bab5373 --- /dev/null +++ b/Kernel/Source/PEFCodeManager.cxx @@ -0,0 +1,226 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace NewOS +{ + namespace Detail + { + /// @brief Get the PEF platform signature according to the compiled backebnd + UInt32 rt_get_pef_platform(void) noexcept + { +#ifdef __32x0__ + return kPefArch32x0; +#elif defined(__64x0__) + return kPefArch64x0; +#elif defined(__x86_64__) + return kPefArchAMD64; +#elif defined(__powerpc64__) + return kPefArchPowerPC; +#else + return kPefArchInvalid; +#endif // __32x0__ || __64x0__ || __x86_64__ + } + } // namespace Detail + + /// @brief PEF loader constructor w/ blob. + /// @param blob + PEFLoader::PEFLoader(const VoidPtr blob) + : fCachedBlob(blob) + { + MUST_PASS(fCachedBlob); + fBad = false; + } + + /// @brief PEF loader constructor. + /// @param path the filesystem path. + PEFLoader::PEFLoader(const Char* path) + : fCachedBlob(nullptr), fBad(false), fFatBinary(false) + { + OwnPtr> file; + + file.New(const_cast(path), kRestrictRB); + + if (StringBuilder::Equals(file->MIME(), this->MIME())) + { + fPath = StringBuilder::Construct(path).Leak(); + + fCachedBlob = file->Read(); + + PEFContainer* container = reinterpret_cast(fCachedBlob); + + if (container->Cpu == Detail::rt_get_pef_platform() && + container->Magic[0] == kPefMagic[0] && + container->Magic[1] == kPefMagic[1] && + container->Magic[2] == kPefMagic[2] && + container->Magic[3] == kPefMagic[3] && + container->Magic[4] == kPefMagic[4] && container->Abi == kPefAbi) + { + return; + } + else if (container->Magic[4] == kPefMagic[0] && + container->Magic[3] == kPefMagic[1] && + container->Magic[2] == kPefMagic[2] && + container->Magic[1] == kPefMagic[3] && + container->Magic[0] == kPefMagic[0] && container->Abi == kPefAbi) + { + /// This is a fat binary. + this->fFatBinary = true; + return; + } + + kcout << "CodeManager: Warning: Executable format error!\n"; + fBad = true; + + ke_delete_ke_heap(fCachedBlob); + + fCachedBlob = nullptr; + } + } + + /// @brief PEF destructor. + PEFLoader::~PEFLoader() + { + if (fCachedBlob) + ke_delete_ke_heap(fCachedBlob); + } + + VoidPtr PEFLoader::FindSymbol(const char* name, Int32 kind) + { + if (!fCachedBlob || fBad) + return nullptr; + + PEFContainer* container = reinterpret_cast(fCachedBlob); + + PEFCommandHeader* container_header = reinterpret_cast( + (UIntPtr)fCachedBlob + sizeof(PEFContainer)); + + constexpr auto cMangleCharacter = '$'; + const char* cContainerKinds[] = {".code64", ".data64", ".zero64", nullptr}; + + ErrorOr errOrSym; + + switch (kind) + { + case kPefCode: { + errOrSym = StringBuilder::Construct(cContainerKinds[0]); // code symbol. + break; + } + case kPefData: { + errOrSym = StringBuilder::Construct(cContainerKinds[1]); // data symbol. + break; + } + case kPefZero: { + errOrSym = StringBuilder::Construct(cContainerKinds[2]); // block starting symbol. + break; + } + default: + return nullptr; + } + + char* unconstSymbol = const_cast(name); + + for (SizeT i = 0UL; i < rt_string_len(unconstSymbol, kPefNameLen); ++i) + { + if (unconstSymbol[i] == ' ') + { + unconstSymbol[i] = cMangleCharacter; + } + } + + errOrSym.Leak().Leak() += name; + + for (SizeT index = 0; index < container->Count; ++index) + { + if (StringBuilder::Equals(container_header->Name, + errOrSym.Leak().Leak().CData())) + { + if (container_header->Kind == kind) + { + if (container_header->Cpu != Detail::rt_get_pef_platform()) + { + if (!this->fFatBinary) + return nullptr; + } + + return (VoidPtr)(static_cast(fCachedBlob) + + container_header->Offset); + } + } + } + + return nullptr; + } + + /// @brief Finds the executable entrypoint. + /// @return + ErrorOr PEFLoader::FindStart() + { + if (auto sym = this->FindSymbol(kPefStart, kPefCode); sym) + return ErrorOr(sym); + + return ErrorOr(kErrorExecutable); + } + + /// @brief Tells if the executable is loaded or not. + /// @return + bool PEFLoader::IsLoaded() noexcept + { + return !fBad && fCachedBlob; + } + + namespace Utils + { + bool execute_from_image(PEFLoader& exec, const Int32& procKind) noexcept + { + auto errOrStart = exec.FindStart(); + + if (errOrStart.Error() != 0) + return false; + + ProcessHeader proc(errOrStart.Leak().Leak()); + Ref refProc = proc; + + proc.Kind = procKind; + + return ProcessScheduler::Shared().Leak().Add(refProc); + } + } // namespace Utils + + const char* PEFLoader::Path() + { + return fPath.Leak().CData(); + } + + const char* PEFLoader::FormatAsString() + { +#ifdef __32x0__ + return "32x0 PEF."; +#elif defined(__64x0__) + return "64x0 PEF."; +#elif defined(__x86_64__) + return "x86_64 PEF."; +#elif defined(__powerpc64__) + return "POWER PEF."; +#else + return "Unknown PEF."; +#endif // __32x0__ || __64x0__ || __x86_64__ || __powerpc64__ + } + + const char* PEFLoader::MIME() + { + return kPefApplicationMime; + } +} // namespace NewOS diff --git a/Kernel/Source/PEFSharedObjectRT.cxx b/Kernel/Source/PEFSharedObjectRT.cxx new file mode 100644 index 00000000..810f0480 --- /dev/null +++ b/Kernel/Source/PEFSharedObjectRT.cxx @@ -0,0 +1,107 @@ +/* + * ======================================================== + * + * NewOS + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#include +#include +#include +#include +#include +#include + +/* ------------------------------------------- + + Revision History: + + 01/02/24: Rework shared library ABI, except a rt_library_init and + rt_library_free (amlel) 15/02/24: Breaking changes, changed the name of the + routines. (amlel) + + ------------------------------------------- */ + +using namespace NewOS; + +/***********************************************************************************/ +/// @file SharedObjectRT.cxx +/// @brief Shared Object runtime. +/***********************************************************************************/ + +/***********************************************************************************/ +/* @brief Library runtime initializer. */ +/***********************************************************************************/ + +EXTERN_C SharedObjectPtr rt_library_init(void) +{ + SharedObjectPtr library = tls_new_class(); + + if (!library) + { + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); + + return nullptr; + } + + library->Mount(tls_new_class()); + + if (!library->Get()) + { + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); + + return nullptr; + } + + library->Get()->fImageObject = + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Image; + + if (!library->Get()->fImageObject) + { + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); + + return nullptr; + } + + library->Get()->fImageEntrypointOffset = + library->Load(kPefStart, rt_string_len(kPefStart, 0), kPefCode); + + return library; +} + +/***********************************************************************************/ +/* @brief Ends the library. */ +/* @note Please check if the lib got freed! */ +/* @param SharedObjectPtr the library to free. */ +/***********************************************************************************/ + +EXTERN_C Void rt_library_free(SharedObjectPtr lib, bool* successful) +{ + MUST_PASS(successful); + + // sanity check (will also trigger a bug check if this fails) + if (lib == nullptr) + { + *successful = false; + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); + } + + delete lib->Get(); + delete lib; + + lib = nullptr; + + *successful = true; +} + +/***********************************************************************************/ + +/// @brief Unimplemented function (crashes by default) +/// @param +EXTERN_C void __mh_purecall(void) +{ + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); + return; +} diff --git a/Kernel/Source/PRDT.cxx b/Kernel/Source/PRDT.cxx new file mode 100644 index 00000000..3f454409 --- /dev/null +++ b/Kernel/Source/PRDT.cxx @@ -0,0 +1,22 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +namespace NewOS +{ + /// @brief constructs a new PRD. + /// @param prd PRD reference. + /// @note This doesnt construct a valid, please fill it by yourself. + void construct_prdt(Ref& prd) + { + prd.Leak().fPhysAddress = 0x0; + prd.Leak().fSectorCount = 0x0; + prd.Leak().fEndBit = 0x0; + } +} // namespace NewOS diff --git a/Kernel/Source/PageAllocator.cxx b/Kernel/Source/PageAllocator.cxx new file mode 100644 index 00000000..bafa5a7e --- /dev/null +++ b/Kernel/Source/PageAllocator.cxx @@ -0,0 +1,52 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +/// @brief Internal namespace, used internally by kernel. +namespace NewOS::Detail +{ + VoidPtr create_page_wrapper(Boolean rw, Boolean user, SizeT pageSz) + { + auto addr = HAL::hal_alloc_page(rw, user, pageSz); + + if (addr == kBadAddress) + { + kcout << "[create_page_wrapper] kBadAddress returned\n"; + ke_stop(RUNTIME_CHECK_POINTER); + } + + return addr; + } + + void exec_disable(UIntPtr VirtualAddr) + { + PTE* VirtualAddrTable = reinterpret_cast(VirtualAddr); + MUST_PASS(!VirtualAddrTable->Accessed); + VirtualAddrTable->ExecDisable = true; + + hal_flush_tlb(); + } + + bool page_disable(UIntPtr VirtualAddr) + { + if (VirtualAddr) + { + auto VirtualAddrTable = (PTE*)(VirtualAddr); + MUST_PASS(!VirtualAddrTable->Accessed); + + VirtualAddrTable->Present = false; + + hal_flush_tlb(); + + return true; + } + + return false; + } +} // namespace NewOS::Detail diff --git a/Kernel/Source/PageManager.cxx b/Kernel/Source/PageManager.cxx new file mode 100644 index 00000000..e1cfdeea --- /dev/null +++ b/Kernel/Source/PageManager.cxx @@ -0,0 +1,118 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +#ifdef __x86_64__ +#include +#endif // ifdef __x86_64__ + +//! null deref will throw (Page Zero detected, aborting app!) +#define kProtectedRegionEnd (512) + +namespace NewOS +{ + PTEWrapper::PTEWrapper(Boolean Rw, Boolean User, Boolean ExecDisable, UIntPtr VirtAddr) + : fRw(Rw), + fUser(User), + fExecDisable(ExecDisable), + fVirtAddr(VirtAddr), + fCache(false), + fShareable(false), + fWt(false), + fPresent(true), + fAccessed(false) + { + } + + PTEWrapper::~PTEWrapper() + { + } + + /// @brief Flush virtual address. + /// @param VirtAddr + void PageManager::FlushTLB(UIntPtr VirtAddr) + { + if (VirtAddr == kBadAddress) + return; + + hal_flush_tlb(); + } + + /// @brief Reclaim freed page. + /// @return + bool PTEWrapper::Reclaim() + { + if (!this->fPresent) + { + this->fPresent = true; + return true; + } + + return false; + } + + /// @brief Request a PTE. + /// @param Rw r/w? + /// @param User user mode? + /// @param ExecDisable disable execution on page? + /// @return + PTEWrapper PageManager::Request(Boolean Rw, Boolean User, Boolean ExecDisable, SizeT Sz) + { + // Store PTE wrapper right after PTE. + VoidPtr ptr = NewOS::HAL::hal_alloc_page(Rw, User, Sz); + + return PTEWrapper{Rw, User, ExecDisable, reinterpret_cast(ptr)}; + } + + /// @brief Disable PTE. + /// @param wrapper the wrapper. + /// @return + bool PageManager::Free(Ref& wrapper) + { + if (wrapper) + { + if (!Detail::page_disable(wrapper->VirtualAddress())) + return false; + return true; + } + + return false; + } + + /// @brief Virtual PTE address. + /// @return The virtual address of the page. + const UIntPtr PTEWrapper::VirtualAddress() + { + return (fVirtAddr); + } + + bool PTEWrapper::Shareable() + { + return fShareable; + } + + bool PTEWrapper::Present() + { + return fPresent; + } + + bool PTEWrapper::Access() + { + return fAccessed; + } + + void PTEWrapper::NoExecute(const bool enable) + { + this->fExecDisable = enable; + } + + const bool& PTEWrapper::NoExecute() + { + return this->fExecDisable; + } +} // namespace NewOS diff --git a/Kernel/Source/PermissionSelector.cxx b/Kernel/Source/PermissionSelector.cxx new file mode 100644 index 00000000..cb44b237 --- /dev/null +++ b/Kernel/Source/PermissionSelector.cxx @@ -0,0 +1,47 @@ +/* + * ======================================================== + * + * NewOS + * Copyright SoftwareLabs, all rights reserved. + * + * File: PermissionSelector.cpp + * Purpose: Permission selectors. + * + * ======================================================== + */ + +#include +#include + +/// bugs 0 + +namespace NewOS +{ + PermissionSelector::PermissionSelector(const Int32& sel) + : fRing((RingKind)sel) + { + MUST_PASS(sel > 0); + } + + PermissionSelector::PermissionSelector(const RingKind& ringKind) + : fRing(ringKind) + { + } + + PermissionSelector::~PermissionSelector() = default; + + bool PermissionSelector::operator==(const PermissionSelector& lhs) + { + return lhs.fRing == this->fRing; + } + + bool PermissionSelector::operator!=(const PermissionSelector& lhs) + { + return lhs.fRing != this->fRing; + } + + const RingKind& PermissionSelector::Ring() noexcept + { + return this->fRing; + } +} // namespace NewOS diff --git a/Kernel/Source/Pmm.cxx b/Kernel/Source/Pmm.cxx new file mode 100644 index 00000000..f60f5b23 --- /dev/null +++ b/Kernel/Source/Pmm.cxx @@ -0,0 +1,85 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include + +namespace NewOS +{ + Pmm::Pmm() + : fPageManager() + { + kcout << "[PMM] Allocate PageMemoryManager"; + } + + Pmm::~Pmm() = default; + + /* If this returns Null pointer, enter emergency mode */ + Ref Pmm::RequestPage(Boolean user, Boolean readWrite) + { + PTEWrapper pt = fPageManager.Leak().Request(user, readWrite, false, kPTESize); + + if (pt.fPresent) + { + kcout << "[PMM]: Allocation was successful."; + return Ref(pt); + } + + kcout << "[PMM]: Allocation failure."; + + return {}; + } + + Boolean Pmm::FreePage(Ref PageRef) + { + if (!PageRef) + return false; + + PageRef.Leak().fPresent = false; + + return true; + } + + Boolean Pmm::TogglePresent(Ref PageRef, Boolean Enable) + { + if (!PageRef) + return false; + + PageRef.Leak().fPresent = Enable; + + return true; + } + + Boolean Pmm::ToggleUser(Ref PageRef, Boolean Enable) + { + if (!PageRef) + return false; + + PageRef.Leak().fRw = Enable; + + return true; + } + + Boolean Pmm::ToggleRw(Ref PageRef, Boolean Enable) + { + if (!PageRef) + return false; + + PageRef.Leak().fRw = Enable; + + return true; + } + + Boolean Pmm::ToggleShare(Ref PageRef, Boolean Enable) + { + if (!PageRef) + return false; + + PageRef.Leak().fShareable = Enable; + + return true; + } +} // namespace NewOS diff --git a/Kernel/Source/ProcessScheduler.cxx b/Kernel/Source/ProcessScheduler.cxx new file mode 100644 index 00000000..859ce657 --- /dev/null +++ b/Kernel/Source/ProcessScheduler.cxx @@ -0,0 +1,392 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +/***********************************************************************************/ +/// @file ProcessScheduler.cxx +/// @brief MicroKernel process scheduler. +/***********************************************************************************/ + +#include +#include +#include +#include +#include + +///! BUGS: 0 + +/***********************************************************************************/ +/* This file handles the process scheduling. +/***********************************************************************************/ + +namespace NewOS +{ + /***********************************************************************************/ + /// @brief Exit Code global + /***********************************************************************************/ + + STATIC Int32 kLastExitCode = 0U; + + /// @brief Gets the latest exit code. + /// @note Not thread-safe. + const Int32& rt_get_exit_code() noexcept + { + return kLastExitCode; + } + + /***********************************************************************************/ + /// @brief crash current process. + /***********************************************************************************/ + + void ProcessHeader::Crash() + { + kcout << this->Name << ": crashed. (id = " << number(39); + kcout << ")\r"; + + if (this->Ring != kRingUserKind) + { + MUST_PASS(ke_bug_check()); + } + + this->Exit(kErrorProcessFault); + } + + void ProcessHeader::Wake(const bool should_wakeup) + { + this->Status = + should_wakeup ? ProcessStatus::kRunning : ProcessStatus::kFrozen; + } + + /***********************************************************************************/ + + VoidPtr ProcessHeader::New(const SizeT& sz) + { + if (this->FreeMemory < 1) + { + DbgLastError() = kErrorHeapOutOfMemory; + this->Crash(); /// out of memory. + + return nullptr; + } + + if (this->HeapCursor) + { + VoidPtr ptr = this->HeapCursor; + this->HeapCursor = (VoidPtr)((UIntPtr)this->HeapCursor + (sizeof(sz))); + + ++this->UsedMemory; + --this->FreeMemory; + + return ptr; + } + + return nullptr; + } + + /***********************************************************************************/ + + /* @brief checks if runtime pointer is in region. */ + bool rt_is_in_pool(VoidPtr pool_ptr, VoidPtr pool, const SizeT& sz) + { + UIntPtr* _pool_ptr = (UIntPtr*)pool_ptr; + UIntPtr* _pool = (UIntPtr*)pool; + + for (SizeT index = sz; _pool[sz] != kUserHeapMag; --index) + { + if (&_pool[index] > &_pool_ptr[sz]) + continue; + + if (_pool[index] == _pool_ptr[index]) + return true; + } + + return false; + } + + /* @brief free pointer from usage. */ + Boolean ProcessHeader::Delete(VoidPtr ptr, const SizeT& sz) + { + if (sz < 1 || this->HeapCursor == this->HeapPtr) + return false; + + // also check for the amount of allocations we've done so far. + if (this->UsedMemory < 1) + return false; + + if (rt_is_in_pool(ptr, this->HeapCursor, this->UsedMemory)) + { + this->HeapCursor = (VoidPtr)((UIntPtr)this->HeapCursor - (sizeof(sz))); + rt_zero_memory(ptr, sz); + + ++this->FreeMemory; + --this->UsedMemory; + + return true; + } + + return false; + } + + /// @brief process name getter. + const Char* ProcessHeader::GetName() + { + return this->Name; + } + + /// @brief process selector getter. + const ProcessSelector& ProcessHeader::GetSelector() + { + return this->Selector; + } + + /// @brief process status getter. + const ProcessStatus& ProcessHeader::GetStatus() + { + return this->Status; + } + + /***********************************************************************************/ + + /** +@brief Affinity is the time slot allowed for the process. +*/ + const AffinityKind& ProcessHeader::GetAffinity() + { + return this->Affinity; + } + + /** +@brief Standard exit proc. +*/ + void ProcessHeader::Exit(Int32 exit_code) + { + if (this->ProcessId != + ProcessScheduler::Shared().Leak().GetCurrent().Leak().ProcessId) + ke_stop(RUNTIME_CHECK_PROCESS); + + if (this->Ring == (Int32)ProcessSelector::kRingKernel && + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Ring > 0) + ke_stop(RUNTIME_CHECK_PROCESS); + + kLastExitCode = exit_code; + + if (this->Ring != (Int32)ProcessSelector::kRingDriver) + { + if (this->HeapPtr) + rt_free_heap(this->HeapPtr); + + this->HeapPtr = nullptr; + this->HeapCursor = nullptr; + + this->FreeMemory = 0UL; + this->UsedMemory = 0UL; + } + + //! Delete image if not done already. + if (this->Image) + ke_delete_ke_heap(this->Image); + if (this->StackFrame) + ke_delete_ke_heap((VoidPtr)this->StackFrame); + + this->Image = nullptr; + this->StackFrame = nullptr; + + ProcessScheduler::Shared().Leak().Remove(this->ProcessId); + } + + SizeT ProcessScheduler::Add(Ref& process) + { + if (!process) + return -1; + + if (!process.Leak().Image) + { + if (process.Leak().Kind != ProcessHeader::kLibKind) + { + return -kErrorNoEntrypoint; + } + } + + if (!mTeam.AsArray().Count() > kSchedProcessLimitPerTeam) + return -kErrorOutOfTeamSlot; + + if (process.Leak().Ring != (Int32)ProcessSelector::kRingKernel) + return -1; + + kcout << "ProcessScheduler::Add(Ref& process)\r"; + + /// Create heap according to type of process. + if (process.Leak().Kind == ProcessHeader::kUserKind) + process.Leak().HeapPtr = rt_new_heap(kUserHeapUser | kUserHeapRw); + else if (process.Leak().Kind == ProcessHeader::kLibKind) + process.Leak().HeapPtr = rt_new_heap(kUserHeapUser | kUserHeapRw | kUserHeapShared); + else + process.Leak().HeapPtr = rt_new_heap(kUserHeapDriver | kUserHeapRw); + + process.Leak().StackFrame = reinterpret_cast( + ke_new_ke_heap(sizeof(HAL::StackFrame), true, false)); + + MUST_PASS(process.Leak().StackFrame); + + mTeam.AsArray().Add(process); + + process.Leak().ProcessId = mTeam.AsArray().Count() - 1; + process.Leak().HeapCursor = process.Leak().HeapPtr; + + return mTeam.AsArray().Count() - 1; + } + + bool ProcessScheduler::Remove(SizeT process) + { + if (process > mTeam.AsArray().Count()) + return false; + + kcout << "ProcessScheduler::Remove(SizeT process)\r"; + + return mTeam.AsArray().Remove(process); + } + + SizeT ProcessScheduler::Run() noexcept + { + SizeT processIndex = 0; //! we store this guy to tell the scheduler how many + //! things we have scheduled. + + for (; processIndex < mTeam.AsArray().Count(); ++processIndex) + { + auto process = mTeam.AsArray()[processIndex]; + + MUST_PASS(process); //! no need for a MUST_PASS(process.Leak());, it is + //! recursive because of the nature of the class; + + //! run any process needed to be scheduled. + if (ProcessHelper::CanBeScheduled(process.Leak())) + { + auto unwrapped_process = *process.Leak(); + + unwrapped_process.PTime = 0; + + // set the current process. + mTeam.AsRef() = unwrapped_process; + + // tell helper to find a core to schedule on. + ProcessHelper::Switch(mTeam.AsRef().Leak().StackFrame, + mTeam.AsRef().Leak().ProcessId); + } + else + { + // otherwise increment the P-time. + ++mTeam.AsRef().Leak().PTime; + } + } + + return processIndex; + } + + Ref ProcessScheduler::Shared() + { + static ProcessScheduler ref; + return {ref}; + } + + /// @brief Gets current running process. + /// @return + Ref& ProcessScheduler::GetCurrent() + { + return mTeam.AsRef(); + } + + PID& ProcessHelper::GetCurrentPID() + { + kcout << "ProcessHelper::GetCurrentPID: Leaking ProcessId...\r"; + return ProcessScheduler::Shared().Leak().GetCurrent().Leak().ProcessId; + } + + bool ProcessHelper::CanBeScheduled(Ref& process) + { + if (process.Leak().Status == ProcessStatus::kFrozen || + process.Leak().Status == ProcessStatus::kDead) + return false; + + if (process.Leak().GetStatus() == ProcessStatus::kStarting) + { + if (process.Leak().PTime < static_cast(kSchedMinMicroTime)) + { + process.Leak().Status = ProcessStatus::kRunning; + process.Leak().Affinity = AffinityKind::kHartStandard; + + return true; + } + + ++process.Leak().PTime; + } + + return process.Leak().PTime > static_cast(kSchedMinMicroTime); + } + + /** + * @brief Spin scheduler class. + */ + bool ProcessHelper::StartScheduling() + { + if (ProcessHelper::CanBeScheduled( + ProcessScheduler::Shared().Leak().GetCurrent())) + { + --ProcessScheduler::Shared().Leak().GetCurrent().Leak().PTime; + return false; + } + + auto processRef = ProcessScheduler::Shared().Leak(); + + if (!processRef) + return false; // we have nothing to schedule. simply return. + + SizeT ret = processRef.Run(); + + kcout << StringBuilder::FromInt( + "ProcessHelper::StartScheduling() Iterated over {%} jobs inside team.\r", ret); + + return true; + } + + /** + * \brief Does a context switch in a CPU. + * \param the_stack the stackframe of the running app. + * \param new_pid the process's PID. +*/ + + bool ProcessHelper::Switch(HAL::StackFrame* the_stack, const PID& new_pid) + { + if (!the_stack || new_pid < 0) + return false; + + for (SizeT index = 0UL; index < SMPManager::Shared().Leak().Count(); ++index) + { + if (SMPManager::Shared().Leak()[index].Leak().Kind() == kInvalidHart) + continue; + + if (SMPManager::Shared().Leak()[index].Leak().StackFrame() == the_stack) + { + SMPManager::Shared().Leak()[index].Leak().Busy(false); + continue; + } + + if (SMPManager::Shared().Leak()[index].Leak().IsBusy()) + continue; + + if (SMPManager::Shared().Leak()[index].Leak().Kind() != + ThreadKind::kHartBoot && + SMPManager::Shared().Leak()[index].Leak().Kind() != + ThreadKind::kHartSystemReserved) + { + SMPManager::Shared().Leak()[index].Leak().Busy(true); + ProcessHelper::GetCurrentPID() = new_pid; + + return SMPManager::Shared().Leak()[index].Leak().Switch(the_stack); + } + } + + return false; + } +} // namespace NewOS diff --git a/Kernel/Source/ProcessTeam.cxx b/Kernel/Source/ProcessTeam.cxx new file mode 100644 index 00000000..959402f4 --- /dev/null +++ b/Kernel/Source/ProcessTeam.cxx @@ -0,0 +1,31 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +/***********************************************************************************/ +/// @file ProcessTeam.cxx +/// @brief Process teams implementation. +/***********************************************************************************/ + +#include + +namespace NewOS +{ + /// @brief Process list array getter. + /// @return The list of process to schedule. + MutableArray>& ProcessTeam::AsArray() + { + return mProcessList; + } + + /// @brief Current process getter. + /// @return The current process header. + Ref& ProcessTeam::AsRef() + { + return mCurrentProcess; + } +} // namespace NewOS + +// last rev 05-03-24 diff --git a/Kernel/Source/Property.cxx b/Kernel/Source/Property.cxx new file mode 100644 index 00000000..ab4f7bf5 --- /dev/null +++ b/Kernel/Source/Property.cxx @@ -0,0 +1,20 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ + bool Property::StringEquals(StringView& name) + { + return fName && this->fName == name; + } + + const PropertyId& Property::GetPropertyById() + { + return fAction; + } +} // namespace NewOS diff --git a/Kernel/Source/Ref.cxx b/Kernel/Source/Ref.cxx new file mode 100644 index 00000000..60f02b69 --- /dev/null +++ b/Kernel/Source/Ref.cxx @@ -0,0 +1,7 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/SMPManager.cxx b/Kernel/Source/SMPManager.cxx new file mode 100644 index 00000000..d9aac48e --- /dev/null +++ b/Kernel/Source/SMPManager.cxx @@ -0,0 +1,217 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +///! BUGS: 0 + +///! @file SMPManager.cxx +///! @brief This file handles multi processing in NewOS. +///! @brief Multi processing is needed for multi-tasking operations. + +namespace NewOS +{ + ///! A HardwareThread class takes care of it's owned hardware thread. + ///! It has a stack for it's core. + + ///! @brief constructor + HardwareThread::HardwareThread() = default; + + ///! @brief destructor + HardwareThread::~HardwareThread() = default; + + //! @brief returns the id + + const ThreadID& HardwareThread::ID() noexcept + { + return fID; + } + + //! @brief returns the kind + + const ThreadKind& HardwareThread::Kind() noexcept + { + return fKind; + } + + //! @brief is the core busy? + + bool HardwareThread::IsBusy() noexcept + { + return fBusy; + } + + /// @brief Get processor stack frame. + + HAL::StackFramePtr HardwareThread::StackFrame() noexcept + { + MUST_PASS(fStack); + return fStack; + } + + void HardwareThread::Busy(const bool busy) noexcept + { + fBusy = busy; + } + + HardwareThread::operator bool() + { + return fStack; + } + + /// @brief Wakeup the processor. + + void HardwareThread::Wake(const bool wakeup) noexcept + { + fWakeup = wakeup; + + if (!fWakeup) + rt_hang_thread(fStack); + else + rt_wakeup_thread(fStack); + } + + extern bool rt_check_stack(HAL::StackFramePtr stackPtr); + + bool HardwareThread::Switch(HAL::StackFramePtr stack) + { + if (!rt_check_stack(stack)) + return false; + + fStack = stack; + + rt_do_context_switch(fStack); + return true; + } + + ///! @brief Tells if processor is waked up. + bool HardwareThread::IsWakeup() noexcept + { + return fWakeup; + } + + //! @brief Constructor and destructor + + ///! @brief Default constructor. + SMPManager::SMPManager() = default; + + ///! @brief Default destructor. + SMPManager::~SMPManager() = default; + + /// @brief Shared singleton function + Ref SMPManager::Shared() + { + static SMPManager manager; + return {manager}; + } + + /// @brief Get Stack Frame of Core + HAL::StackFramePtr SMPManager::GetStackFrame() noexcept + { + if (fThreadList[fCurrentThread].Leak() && + ProcessHelper::GetCurrentPID() == + fThreadList[fCurrentThread].Leak().Leak().fPID) + return fThreadList[fCurrentThread].Leak().Leak().fStack; + + return nullptr; + } + + /// @brief Finds and switch to a free core. + bool SMPManager::Switch(HAL::StackFramePtr stack) + { + if (stack == nullptr) + return false; + + for (SizeT idx = 0; idx < kMaxHarts; ++idx) + { + // stack != nullptr -> if core is used, then continue. + if (!fThreadList[idx].Leak() || + !fThreadList[idx].Leak().Leak().IsWakeup() || + fThreadList[idx].Leak().Leak().IsBusy()) + continue; + + // to avoid any null deref. + if (!fThreadList[idx].Leak().Leak().fStack) + continue; + if (fThreadList[idx].Leak().Leak().fStack->Rsp == 0) + continue; + if (fThreadList[idx].Leak().Leak().fStack->Rbp == 0) + continue; + + fThreadList[idx].Leak().Leak().Busy(true); + + fThreadList[idx].Leak().Leak().fID = idx; + + /// I figured out this: + /// Allocate stack + /// Set APIC base to stack + /// Do stuff and relocate stack based on this code. + /// - Amlel + rt_copy_memory(stack, fThreadList[idx].Leak().Leak().fStack, + sizeof(HAL::StackFrame)); + + fThreadList[idx].Leak().Leak().fPID = ProcessHelper::GetCurrentPID(); + + fThreadList[idx].Leak().Leak().Busy(false); + + return true; + } + + return false; + } + + /** + * Index Hardware thread + * @param idx the index + * @return the reference to the hardware thread. + */ + Ref SMPManager::operator[](const SizeT& idx) + { + if (idx == 0) + { + if (fThreadList[idx].Leak().Leak().Kind() != kHartSystemReserved) + { + fThreadList[idx].Leak().Leak().fKind = kHartBoot; + } + } + else if (idx >= kMaxHarts) + { + HardwareThread fakeThread; + fakeThread.fKind = kInvalidHart; + + return {fakeThread}; + } + + return fThreadList[idx].Leak(); + } + + /** + * Check if thread pool isn't empty. + * @return + */ + SMPManager::operator bool() noexcept + { + return !fThreadList.Empty(); + } + + /** + * Reverse operator bool + * @return + */ + bool SMPManager::operator!() noexcept + { + return fThreadList.Empty(); + } + + /// @brief Returns the amount of core present. + /// @return the number of cores. + SizeT SMPManager::Count() noexcept + { + return fThreadList.Count(); + } +} // namespace NewOS diff --git a/Kernel/Source/Semaphore.cxx b/Kernel/Source/Semaphore.cxx new file mode 100644 index 00000000..eebdd210 --- /dev/null +++ b/Kernel/Source/Semaphore.cxx @@ -0,0 +1,53 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +namespace NewOS +{ + bool Semaphore::Unlock() noexcept + { + if (fLockingProcess) + fLockingProcess = nullptr; + + return fLockingProcess == nullptr; + } + + bool Semaphore::Lock(ProcessHeader* process) + { + if (!process || fLockingProcess) + return false; + + fLockingProcess = process; + + return true; + } + + bool Semaphore::IsLocked() const + { + return fLockingProcess; + } + + bool Semaphore::LockOrWait(ProcessHeader* process, const Int64& seconds) + { + if (process == nullptr) + return false; + + HardwareTimer timer(Seconds(seconds)); + timer.Wait(); + + return this->Lock(process); + } + + void Semaphore::Sync() noexcept + { + while (fLockingProcess) + { + } + } +} // namespace NewOS diff --git a/Kernel/Source/Storage/AHCIDeviceInterface.cxx b/Kernel/Source/Storage/AHCIDeviceInterface.cxx new file mode 100644 index 00000000..da25c05d --- /dev/null +++ b/Kernel/Source/Storage/AHCIDeviceInterface.cxx @@ -0,0 +1,35 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +using namespace NewOS; + +/// @brief Class constructor +/// @param Out Disk output +/// @param In Disk input +/// @param Cleanup Disk cleanup. +AHCIDeviceInterface::AHCIDeviceInterface(void (*Out)(MountpointInterface* outpacket), + void (*In)(MountpointInterface* inpacket), + void (*Cleanup)(void)) + : DeviceInterface(Out, In), fCleanup(Cleanup) +{ +} + +/// @brief Class desctructor +AHCIDeviceInterface::~AHCIDeviceInterface() +{ + MUST_PASS(fCleanup); + if (fCleanup) + fCleanup(); +} + +/// @brief Returns the name of the device interface. +/// @return it's name as a string. +const char* AHCIDeviceInterface::Name() const +{ + return "AHCIDeviceInterface"; +} diff --git a/Kernel/Source/Storage/ATADeviceInterface.cxx b/Kernel/Source/Storage/ATADeviceInterface.cxx new file mode 100644 index 00000000..5624dddb --- /dev/null +++ b/Kernel/Source/Storage/ATADeviceInterface.cxx @@ -0,0 +1,88 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +using namespace NewOS; + +/// @brief Class constructor +/// @param Out Disk output +/// @param In Disk input +/// @param Cleanup Disk cleanup. +ATADeviceInterface::ATADeviceInterface( + void (*Out)(MountpointInterface* outpacket), + void (*In)(MountpointInterface* inpacket), + void (*Cleanup)(void)) + : DeviceInterface(Out, In), fCleanup(Cleanup) +{ +} + +/// @brief Class desctructor +ATADeviceInterface::~ATADeviceInterface() +{ + MUST_PASS(fCleanup); + if (fCleanup) + fCleanup(); +} + +/// @brief Returns the name of the device interface. +/// @return it's name as a string. +const char* ATADeviceInterface::Name() const +{ + return "ATADeviceInterface"; +} + +/// @brief Output operator. +/// @param Data +/// @return +ATADeviceInterface& ATADeviceInterface::operator<<(MountpointInterface* Data) +{ + if (!Data) + return *this; + + for (SizeT driveCount = 0; driveCount < kDriveManagerCount; ++driveCount) + { + auto interface = Data->GetAddressOf(driveCount); + if ((interface) && rt_string_cmp((interface)->fDriveKind(), "ATA-", 5) == 0) + { + continue; + } + else if ((interface) && + rt_string_cmp((interface)->fDriveKind(), "ATA-", 5) != 0) + { + return *this; + } + } + + return (ATADeviceInterface&)DeviceInterface::operator<<( + Data); +} + +/// @brief Input operator. +/// @param Data +/// @return +ATADeviceInterface& ATADeviceInterface::operator>>(MountpointInterface* Data) +{ + if (!Data) + return *this; + + for (SizeT driveCount = 0; driveCount < kDriveManagerCount; ++driveCount) + { + auto interface = Data->GetAddressOf(driveCount); + if ((interface) && rt_string_cmp((interface)->fDriveKind(), "ATA-", 5) == 0) + { + continue; + } + else if ((interface) && + rt_string_cmp((interface)->fDriveKind(), "ATA-", 5) != 0) + { + return *this; + } + } + + return (ATADeviceInterface&)DeviceInterface::operator>>( + Data); +} diff --git a/Kernel/Source/Storage/NVMEDeviceInterface.cxx b/Kernel/Source/Storage/NVMEDeviceInterface.cxx new file mode 100644 index 00000000..aaaa3eb0 --- /dev/null +++ b/Kernel/Source/Storage/NVMEDeviceInterface.cxx @@ -0,0 +1,15 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ + const char* NVMEDeviceInterface::Name() const + { + return ("NVMEDeviceInterface"); + } +} // namespace NewOS diff --git a/Kernel/Source/Storage/SCSIDeviceInterface.cxx b/Kernel/Source/Storage/SCSIDeviceInterface.cxx new file mode 100644 index 00000000..16105547 --- /dev/null +++ b/Kernel/Source/Storage/SCSIDeviceInterface.cxx @@ -0,0 +1,11 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +///! @brief ATAPI SCSI packet. +const scsi_packet_type kCDRomPacketTemplate = {0x43, 0, 1, 0, 0, 0, + 0, 12, 0x40, 0, 0}; diff --git a/Kernel/Source/Stream.cxx b/Kernel/Source/Stream.cxx new file mode 100644 index 00000000..134ec586 --- /dev/null +++ b/Kernel/Source/Stream.cxx @@ -0,0 +1,12 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + + File: Stream.cxx + Purpose: Stream object + + Revision History: + +------------------------------------------- */ + +#include diff --git a/Kernel/Source/String.cxx b/Kernel/Source/String.cxx new file mode 100644 index 00000000..764ab0d9 --- /dev/null +++ b/Kernel/Source/String.cxx @@ -0,0 +1,248 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +namespace NewOS +{ + Char* StringView::Data() + { + return fData; + } + + const Char* StringView::CData() + { + return fData; + } + + Size StringView::Length() const + { + return rt_string_len(fData); + } + + bool StringView::operator==(const StringView& rhs) const + { + if (rhs.Length() != this->Length()) + return false; + + for (Size index = 0; index < this->Length(); ++index) + { + if (rhs.fData[index] != fData[index]) + return false; + } + + return true; + } + + bool StringView::operator==(const Char* rhs) const + { + if (rt_string_len(rhs) != this->Length()) + return false; + + for (Size index = 0; index < rt_string_len(rhs); ++index) + { + if (rhs[index] != fData[index]) + return false; + } + + return true; + } + + bool StringView::operator!=(const StringView& rhs) const + { + if (rhs.Length() != this->Length()) + return false; + + for (Size index = 0; index < rhs.Length(); ++index) + { + if (rhs.fData[index] == fData[index]) + return false; + } + + return true; + } + + bool StringView::operator!=(const Char* rhs) const + { + if (rt_string_len(rhs) != this->Length()) + return false; + + for (Size index = 0; index < rt_string_len(rhs); ++index) + { + if (rhs[index] == fData[index]) + return false; + } + + return true; + } + + ErrorOr StringBuilder::Construct(const Char* data) + { + if (!data || *data == 0) + return {}; + + StringView view(rt_string_len(data)); + + view += data; + + return ErrorOr(view); + } + + const char* StringBuilder::FromInt(const char* fmt, int i) + { + if (!fmt) + return ("-1"); + + char* ret = (char*)Alloca(sizeof(char) * 8 + rt_string_len(fmt)); + + if (!ret) + return ("-1"); + + Char result[8]; + + if (!rt_to_string(result, sizeof(int), i)) + { + return ("-1"); + } + + const auto fmt_len = rt_string_len(fmt); + const auto res_len = rt_string_len(result); + + for (Size idx = 0; idx < fmt_len; ++idx) + { + if (fmt[idx] == '%') + { + SizeT result_cnt = idx; + + for (auto y_idx = idx; y_idx < res_len; ++y_idx) + { + ret[result_cnt] = result[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; /* Copy that ret into a buffer, Alloca allocates to the stack */ + } + + const char* StringBuilder::FromBool(const char* fmt, bool i) + { + if (!fmt) + return ("?"); + + const char* boolean_expr = i ? "true" : "false"; + char* ret = (char*)Alloca((sizeof(char) * i) ? 4 : 5 + rt_string_len(fmt)); + + if (!ret) + return ("?"); + + const auto fmt_len = rt_string_len(fmt); + const auto res_len = rt_string_len(boolean_expr); + + for (Size idx = 0; idx < fmt_len; ++idx) + { + if (fmt[idx] == '%') + { + SizeT result_cnt = idx; + + for (auto y_idx = idx; y_idx < res_len; ++y_idx) + { + ret[result_cnt] = boolean_expr[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; + } + + bool StringBuilder::Equals(const char* lhs, const char* rhs) + { + if (rt_string_len(rhs) != rt_string_len(lhs)) + return false; + + for (Size index = 0; index < rt_string_len(rhs); ++index) + { + if (rhs[index] != lhs[index]) + return false; + } + + return true; + } + + const char* StringBuilder::Format(const char* fmt, const char* fmt2) + { + if (!fmt || !fmt2) + return ("?"); + + char* ret = + (char*)Alloca(sizeof(char) * rt_string_len(fmt2) + rt_string_len(fmt2)); + + if (!ret) + return ("?"); + + for (Size idx = 0; idx < rt_string_len(fmt); ++idx) + { + if (fmt[idx] == '%') + { + Size result_cnt = idx; + for (Size y_idx = 0; y_idx < rt_string_len(fmt2); ++y_idx) + { + ret[result_cnt] = fmt2[y_idx]; + ++result_cnt; + } + + break; + } + + ret[idx] = fmt[idx]; + } + + return ret; + } + + static void string_append(char* lhs, char* rhs, int cur) + { + if (lhs && rhs) + { + SizeT sz_rhs = rt_string_len(rhs); + + if (sz_rhs == 0) + return; + + rt_copy_memory(rhs, lhs + cur, sz_rhs); + } + } + + StringView& StringView::operator+=(const Char* rhs) + { + string_append(this->fData, const_cast(rhs), this->fCur); + this->fCur += rt_string_len(rhs); + + return *this; + } + + StringView& StringView::operator+=(const StringView& rhs) + { + if (rt_string_len(rhs.fData) > rt_string_len(this->fData)) + return *this; + + string_append(this->fData, const_cast(rhs.fData), this->fCur); + this->fCur += rt_string_len(const_cast(rhs.fData)); + + return *this; + } +} // namespace NewOS diff --git a/Kernel/Source/ThreadLocalStorage.cxx b/Kernel/Source/ThreadLocalStorage.cxx new file mode 100644 index 00000000..c31ae1c2 --- /dev/null +++ b/Kernel/Source/ThreadLocalStorage.cxx @@ -0,0 +1,58 @@ +/* + * ======================================================== + * + * NewOS + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#include +#include + +///! BUGS: 0 + +/***********************************************************************************/ +/// @file ThreadLocalStorage.cxx +/// @brief TLS implementation in kernel. +/***********************************************************************************/ + +using namespace NewOS; + +/** + * @brief Check for cookie inside TIB. + * @param tib the TIB to check. + * @return if the cookie is enabled. + */ + +Boolean tls_check_tib(ThreadInformationBlock* tib) +{ + if (!tib) + return false; + + Encoder encoder; + const char* tibAsBytes = encoder.AsBytes(tib); + + kcout << "New OS: Checking for a valid cookie...\r"; + + return tibAsBytes[0] == kCookieMag0 && tibAsBytes[1] == kCookieMag1 && + tibAsBytes[2] == kCookieMag2; +} + +/** + * @brief System call implementation of the TLS check. + * @param stackPtr The call frame. + * @return + */ +EXTERN_C Void tls_check_syscall_impl(NewOS::HAL::StackFramePtr stackPtr) noexcept +{ + ThreadInformationBlock* tib = (ThreadInformationBlock*)stackPtr->Gs; + + if (!tls_check_tib(tib)) + { + kcout << "New OS: Verification failed, Crashing...\r"; + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); + } + + kcout << "New OS: Verification succeeded! Keeping on...\r"; +} diff --git a/Kernel/Source/Timer.cxx b/Kernel/Source/Timer.cxx new file mode 100644 index 00000000..3e705c38 --- /dev/null +++ b/Kernel/Source/Timer.cxx @@ -0,0 +1,41 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +///! BUGS: 0 +///! @file Timer.cxx + +using namespace NewOS; + +/// @brief Unimplemented as it is an interface. +Int32 HardwareTimerInterface::Wait() noexcept +{ + return kErrorUnimplemented; +} + +/// @brief HardwareTimer class, meant to be generic. + +HardwareTimer::HardwareTimer(Int64 seconds) + : fWaitFor(seconds) +{ +} +HardwareTimer::~HardwareTimer() +{ + fWaitFor = 0; +} + +Int32 HardwareTimer::Wait() noexcept +{ + if (fWaitFor < 1) + return -1; + + while (*fDigitalTimer < (*fDigitalTimer + fWaitFor)) + { + } + + return 0; +} diff --git a/Kernel/Source/URL.cxx b/Kernel/Source/URL.cxx new file mode 100644 index 00000000..8c11ca55 --- /dev/null +++ b/Kernel/Source/URL.cxx @@ -0,0 +1,96 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +/// BUGS: 0 + +namespace NewOS +{ + URL::URL(StringView& strUrl) + : fUrlView(strUrl, false) + { + } + + URL::~URL() = default; + + /// @brief internal and reserved protocols by kernel. + constexpr const char* kURLProtocols[] = { + "file", // Filesystem protocol + "mup", // Mahrouss update protocol + "param", // Mahrouss parameter protocol. + }; + + constexpr const int kUrlOutSz = 1; //! such as: :// + constexpr const int kProtosCount = 3; + constexpr const int kRangeSz = 4096; + + ErrorOr url_extract_location(const char* url) + { + if (!url || *url == 0 || rt_string_len(url, kRangeSz) > kRangeSz) + return ErrorOr{-1}; + + StringView view(rt_string_len(url)); + + SizeT i = 0; + bool scheme_found = false; + + for (; i < rt_string_len(url); ++i) + { + if (!scheme_found) + { + for (int y = 0; kProtosCount; ++y) + { + if (rt_string_in_string(view.CData(), kURLProtocols[y])) + { + i += rt_string_len(kURLProtocols[y]) + kUrlOutSz; + scheme_found = true; + + break; + } + } + } + + view.Data()[i] = url[i]; + } + + return ErrorOr(view); + } + + ErrorOr url_extract_protocol(const char* url) + { + if (!url || *url == 0 || rt_string_len(url, kRangeSz) > kRangeSz) + return ErrorOr{-1}; + + ErrorOr view{-1}; + + return view; + } + + Ref> URL::Location() noexcept + { + const char* src = fUrlView.Leak().CData(); + auto loc = url_extract_location(src); + + if (!loc) + return {}; + + return Ref>(loc); + } + + Ref> URL::Protocol() noexcept + { + const char* src = fUrlView.Leak().CData(); + auto loc = url_extract_protocol(src); + + if (!loc) + return {}; + + return Ref>(loc); + } +} // namespace NewOS diff --git a/Kernel/Source/UserHeap.cxx b/Kernel/Source/UserHeap.cxx new file mode 100644 index 00000000..9d9cd627 --- /dev/null +++ b/Kernel/Source/UserHeap.cxx @@ -0,0 +1,252 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +#define kHeapHeaderPaddingSz (16U) + +/// @file UserHeap.cxx +/// @brief User Heap Manager, Process heap allocator. +/// @note if you want to look at the kernel allocator, please look for +/// KernelHeap.cxx +/// BUGS: 0 + +namespace NewOS +{ + /** + * @brief Process Heap Header + * @note Allocated per process, it denotes the user's heap. + */ + struct UserHeapHeader final + { + UInt32 fMagic; + Int32 fFlags; + Boolean fFree; + UInt8 fPadding[kHeapHeaderPaddingSz]; + }; + + /** + * @brief User Heap Manager class, takes care of allocating the process pools. + * @note This rely on Virtual Memory! Consider adding good vmem support when + * @note porting to a new arch. + */ + class UserHeapManager final + { + public: + UserHeapManager() = delete; + ~UserHeapManager() = default; + + public: + STATIC SizeT& Count() + { + return s_NumPools; + } + STATIC Ref& Leak() + { + return s_Pmm; + } + STATIC Boolean& IsEnabled() + { + return s_PoolsAreEnabled; + } + STATIC MutableArray>& The() + { + return s_Pool; + } + + private: + STATIC Size s_NumPools; + STATIC Ref s_Pmm; + + private: + STATIC Boolean s_PoolsAreEnabled; + STATIC MutableArray> s_Pool; + }; + + //! declare fields + + SizeT UserHeapManager::s_NumPools = 0UL; + Ref UserHeapManager::s_Pmm; + Boolean UserHeapManager::s_PoolsAreEnabled = true; + MutableArray> UserHeapManager::s_Pool; + + STATIC VoidPtr ke_find_unused_heap(Int32 flags); + STATIC Void ke_free_heap_internal(VoidPtr vaddr); + STATIC VoidPtr ke_make_heap_internal(VoidPtr vaddr, Int32 flags); + STATIC Boolean ke_check_and_free_heap(const SizeT& index, VoidPtr ptr); + + /// @brief Find an unused heap header to allocate on. + /// @param flags the flags to use. + /// @return VoidPtr the heap pointer. + STATIC VoidPtr ke_find_unused_heap(Int32 flags) + { + for (SizeT index = 0; index < kUserHeapMaxSz; ++index) + { + if (UserHeapManager::The()[index] && + !UserHeapManager::The()[index].Leak().Leak().Present()) + { + UserHeapManager::Leak().Leak().TogglePresent( + UserHeapManager::The()[index].Leak().Leak(), true); + kcout << "[ke_find_unused_heap] Done, trying to make a pool now...\r"; + + return ke_make_heap_internal( + (VoidPtr)UserHeapManager::The()[index].Leak().Leak().VirtualAddress(), + flags); + } + } + + return nullptr; + } + + /// @brief Makes a new heap for the process to use. + /// @param virtualAddress the virtual address of the process. + /// @param flags the flags. + /// @return + STATIC VoidPtr ke_make_heap_internal(VoidPtr virtualAddress, Int32 flags) + { + if (virtualAddress) + { + UserHeapHeader* poolHdr = reinterpret_cast(virtualAddress); + + if (!poolHdr->fFree) + { + kcout + << "[ke_make_heap_internal] poolHdr->fFree, HeapPtr already exists\n"; + return nullptr; + } + + poolHdr->fFlags = flags; + poolHdr->fMagic = kUserHeapMag; + poolHdr->fFree = false; + + kcout << "[ke_make_heap_internal] New allocation has been done.\n"; + return reinterpret_cast( + (reinterpret_cast(virtualAddress) + sizeof(UserHeapHeader))); + } + + kcout << "[ke_make_heap_internal] Address is invalid"; + return nullptr; + } + + /// @brief Internally makrs the heap as free. + /// This is done by setting the fFree bit to true + /// @param virtualAddress + /// @return + STATIC Void ke_free_heap_internal(VoidPtr virtualAddress) + { + UserHeapHeader* poolHdr = reinterpret_cast( + reinterpret_cast(virtualAddress) - sizeof(UserHeapHeader)); + + if (poolHdr->fMagic == kUserHeapMag) + { + if (!poolHdr->fFree) + { + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash(); + return; + } + + poolHdr->fFree = true; + poolHdr->fFlags = 0; + + kcout << "[ke_free_heap_internal] Successfully marked header as free!\r"; + } + } + + /** + * @brief Check for the ptr and frees it. + * + * @param index Where to look at. + * @param ptr The ptr to check. + * @return Boolean true if successful. + */ + STATIC Boolean ke_check_and_free_heap(const SizeT& index, VoidPtr ptr) + { + if (UserHeapManager::The()[index]) + { + // ErrorOr<>::operator Boolean + /// if (address matches) + /// -> Free heap. + if (UserHeapManager::The()[index].Leak().Leak().VirtualAddress() == + (UIntPtr)ptr) + { + UserHeapManager::Leak().Leak().FreePage( + UserHeapManager::The()[index].Leak().Leak()); + + --UserHeapManager::Count(); + + ke_free_heap_internal(ptr); + ptr = nullptr; + + return true; + } + } + + return false; + } + + /// @brief Creates a new pool pointer. + /// @param flags the flags attached to it. + /// @return a pool pointer with selected permissions. + VoidPtr rt_new_heap(Int32 flags) + { + if (!UserHeapManager::IsEnabled()) + return nullptr; + + if (UserHeapManager::Count() > kUserHeapMaxSz) + return nullptr; + + if (VoidPtr ret = ke_find_unused_heap(flags)) + return ret; + + // this wasn't set to true + auto ref_page = UserHeapManager::Leak().Leak().RequestPage( + ((flags & kUserHeapUser)), (flags & kUserHeapRw)); + + if (ref_page) + { + ///! reserve page. + UserHeapManager::The()[UserHeapManager::Count()].Leak() = ref_page; + auto& ref = UserHeapManager::Count(); + + ++ref; // increment the number of addresses we have now. + + // finally make the pool address. + return ke_make_heap_internal( + reinterpret_cast(ref_page.Leak().VirtualAddress()), flags); + } + + return nullptr; + } + + /// @brief free a pool pointer. + /// @param ptr The pool pointer to free. + /// @return status code + Int32 rt_free_heap(VoidPtr ptr) + { + if (!UserHeapManager::IsEnabled()) + return -1; + + if (ptr) + { + SizeT base = UserHeapManager::Count(); + + if (ke_check_and_free_heap(base, ptr)) + return 0; + + for (SizeT index = 0; index < kUserHeapMaxSz; ++index) + { + if (ke_check_and_free_heap(index, ptr)) + return 0; + + --base; + } + } + + return -1; + } +} // namespace NewOS diff --git a/Kernel/Source/Utils.cxx b/Kernel/Source/Utils.cxx new file mode 100644 index 00000000..f621594d --- /dev/null +++ b/Kernel/Source/Utils.cxx @@ -0,0 +1,253 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include +#include +#include + +namespace NewOS +{ + Int rt_string_cmp(const Char* src, const Char* cmp, Size size) + { + Int32 counter = 0; + + for (Size index = 0; index < size; ++index) + { + if (src[index] != cmp[index]) + ++counter; + } + + return counter; + } + + void rt_zero_memory(voidPtr pointer, Size len) + { + rt_set_memory(pointer, 0, len); + } + + Size rt_string_len(const Char* str, SizeT _len) + { + if (*str == '\0') + return 0; + + Size len{0}; + while (str[len] != '\0') + { + if (len > _len) + { + break; + } + + ++len; + } + + return len; + } + + Size rt_string_len(const Char* ptr) + { + if (!ptr) + return 0; + + SizeT cnt = 0; + + while (*ptr != (Char)0) + { + ++ptr; + ++cnt; + } + + return cnt; + } + + voidPtr rt_set_memory(voidPtr src, char value, Size len) + { + if (!src || len < 1) + return nullptr; + char* start = reinterpret_cast(src); + + while (len) + { + *start = value; + ++start; + --len; + } + + return (voidPtr)start; + } + + Int rt_move_memory(const voidPtr src, voidPtr dst, Size len) + { + if (len < 1) + return -2; + if (!src || !dst) + return -1; + + char* srcChr = reinterpret_cast(src); + char* dstChar = reinterpret_cast(dst); + Size index = 0; + + while (index < len) + { + dstChar[index] = srcChr[index]; + srcChr[index] = 0; + + ++index; + } + + return 0; + } + + Int rt_copy_memory(const voidPtr src, voidPtr dst, Size len) + { + if (len < 1) + return -2; + + char* srcChr = reinterpret_cast(src); + char* dstChar = reinterpret_cast(dst); + Size index = 0; + + while (index < len) + { + dstChar[index] = srcChr[index]; + ++index; + } + + return index; + } + + const Char* alloc_string(const Char* text) + { + if (!text) + return nullptr; + + const Char* string = new Char[rt_string_len(text)]; + if (!string) + return nullptr; + + voidPtr vText = reinterpret_cast(const_cast(text)); + voidPtr vStr = reinterpret_cast(const_cast(string)); + rt_copy_memory(vText, vStr, rt_string_len(text)); + + return string; + } + + Int rt_to_uppercase(Int character) + { + if (character >= 'a' && character <= 'z') + return character - 0x20; + + return character; + } + + Int rt_to_lower(Int character) + { + if (character >= 'A' && character <= 'Z') + return character + 0x20; + + return character; + } + + bool rt_to_string(Char* str, Int limit, Int base) + { + if (limit == 0) + return false; + + Int copy_limit = limit; + Int cnt = 0; + Int ret = base; + + while (limit != 1) + { + ret = ret % 10; + str[cnt] = ret; + + ++cnt; + --limit; + --ret; + } + + str[copy_limit] = '\0'; + return true; + } + + Boolean is_space(Char chr) + { + return chr == ' '; + } + + Boolean is_newln(Char chr) + { + return chr == '\n'; + } + + voidPtr rt_string_in_string(const char* in, const char* needle) + { + for (size_t i = 0; i < rt_string_len(in); ++i) + { + if (rt_string_cmp(in + i, needle, rt_string_len(needle)) == 0) + return reinterpret_cast(const_cast(in + i)); + } + + return nullptr; + } + + // @brief Checks for a string start at the character. + + char* rt_string_has_char(char* str, const char chr) + { + while (*str != chr) + { + ++str; + + if (*str == 0) + return nullptr; + } + + return str; + } +} // namespace NewOS + +//////////////////////////////////////////////////////////////////////////////////////// +/// Exported C functions +//////////////////////////////////////////////////////////////////////////////////////// + +/// @brief memset in C++ +EXTERN_C void memset(void* dst, char src, size_t len) +{ + NewOS::rt_set_memory(dst, src, len); +} + +/// @brief memcpy in C++ +EXTERN_C void memcpy(void* dst, void* src, size_t len) +{ + NewOS::rt_copy_memory(src, dst, len); +} + +/// @brief memmove in C++ +EXTERN_C void* memmove(void* dst, void* src, size_t len) +{ + NewOS::rt_copy_memory(src, dst, len); + return dst; +} + +/// @brief strlen definition in C++. +EXTERN_C size_t strlen(const char* whatToCheck) +{ + return NewOS::rt_string_len(whatToCheck); +} + +/// @brief memcmp in C++ +EXTERN_C NewOS::SizeT memcmp(void* dst, void* src, size_t len) +{ + return NewOS::rt_string_cmp((char*)src, (char*)dst, len); +} + +/// @brief strcmp in C++ +EXTERN_C NewOS::SizeT strcmp(char* dst, char* src, size_t len) +{ + return NewOS::rt_string_cmp(src, dst, len); +} diff --git a/Kernel/Source/Variant.cxx b/Kernel/Source/Variant.cxx new file mode 100644 index 00000000..afe66624 --- /dev/null +++ b/Kernel/Source/Variant.cxx @@ -0,0 +1,29 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#include + +namespace NewOS +{ + const Char* Variant::ToString() + { + if (fPtr == nullptr) + { + return ("Memory:{Nullptr}"); + } + + switch (fKind) + { + case VariantKind::kString: + return ("Class:{String}"); + case VariantKind::kPointer: + return ("Memory:{Pointer}"); + default: + return ("Memory:{Undefined}"); + } + } + +} // namespace NewOS diff --git a/Kernel/Source/compile_flags.txt b/Kernel/Source/compile_flags.txt new file mode 100644 index 00000000..1f54e6fb --- /dev/null +++ b/Kernel/Source/compile_flags.txt @@ -0,0 +1,7 @@ +-nostdlib +-ffreestanding +-std=c++20 +-I../ +-I$(HOME)/ +-D__FSKIT_NEWFS__ +-D__NEWOS_AMD64__ -- cgit v1.2.3 From 915c14eb3b717bbd168d069e296a4246c6aef117 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Thu, 9 May 2024 19:23:04 +0200 Subject: MHR-23: Starting to implement SMP for AMD64. Signed-off-by: Amlal El Mahrouss --- Boot/Source/HEL/AMD64/BootMain.cxx | 3 +- Kernel/HALKit/64x0/ReadMe.md | 4 +++ Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx | 11 ++++--- .../HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp | 33 ++++++++++--------- Kernel/HALKit/AMD64/HalHardwareMP.cpp | 4 +-- Kernel/HALKit/AMD64/HalInterruptAPI.asm | 20 ++++++------ Kernel/HALKit/AMD64/ReadMe.md | 4 +++ Kernel/HALKit/ARM64/ReadMe.md | 4 +++ Kernel/HALKit/POWER/ReadMe.md | 4 +++ Kernel/HALKit/RISCV/ReadMe.md | 4 +++ Kernel/KernelKit/DebugOutput.hpp | 28 +++++++++++++++- Kernel/Source/AppMain.cxx | 10 ++++++ Kernel/Source/CodeManager.cxx | 37 +++++++++++----------- 13 files changed, 115 insertions(+), 51 deletions(-) create mode 100644 Kernel/HALKit/64x0/ReadMe.md create mode 100644 Kernel/HALKit/AMD64/ReadMe.md create mode 100644 Kernel/HALKit/ARM64/ReadMe.md create mode 100644 Kernel/HALKit/POWER/ReadMe.md create mode 100644 Kernel/HALKit/RISCV/ReadMe.md (limited to 'Kernel/Source') diff --git a/Boot/Source/HEL/AMD64/BootMain.cxx b/Boot/Source/HEL/AMD64/BootMain.cxx index f422b661..649596b4 100644 --- a/Boot/Source/HEL/AMD64/BootMain.cxx +++ b/Boot/Source/HEL/AMD64/BootMain.cxx @@ -90,7 +90,7 @@ EFI_EXTERN_C EFI_API Int Main(EfiHandlePtr ImageHandle, for (SizeT indexVT = 0; indexVT < SystemTable->NumberOfTableEntries; ++indexVT) { - volatile Char* vendorTable = reinterpret_cast( + Char* vendorTable = reinterpret_cast( SystemTable->ConfigurationTable[indexVT].VendorTable); /// ACPI's 'RSD PTR', which contains hardware tables (MADT, FACP...) @@ -99,6 +99,7 @@ EFI_EXTERN_C EFI_API Int Main(EfiHandlePtr ImageHandle, vendorTable[4] == 'P' && vendorTable[5] == 'T' && vendorTable[6] == 'R' && vendorTable[7] == ' ') { + writer.Write(L"New Boot: Found ACPI RSD PTR!\r"); handoverHdrPtr->f_HardwareTables.f_RsdPtr = (VoidPtr)vendorTable; break; diff --git a/Kernel/HALKit/64x0/ReadMe.md b/Kernel/HALKit/64x0/ReadMe.md new file mode 100644 index 00000000..6744f602 --- /dev/null +++ b/Kernel/HALKit/64x0/ReadMe.md @@ -0,0 +1,4 @@ +64x0 Hardware Abstraction Layer + +- Supported CPU: SoftwareLabs 64x0 +- Supported Firmware: CoreBoot \ No newline at end of file diff --git a/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx b/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx index 3609165f..f4c9226e 100644 --- a/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx +++ b/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx @@ -75,7 +75,7 @@ namespace NewOS SDT* xsdt = (SDT*)(rsdPtr->XsdtAddress >> (rsdPtr->XsdtAddress & 0xFFF)); - SizeT num = xsdt->Length + sizeof(SDT) / 8; + SizeT num = (xsdt->Length + sizeof(SDT)) / 8; this->fEntries = num; @@ -83,10 +83,11 @@ namespace NewOS kcout << "ACPI: Address of XSDT: " << hex_number((UIntPtr)xsdt) << endl; constexpr short ACPI_SIGNATURE_LENGTH = 4; + SizeT offsetToAdd = 0UL; for (Size index = 0; index < num; ++index) { - SDT* sdt = (SDT*)*((UInt64*)(UInt64)xsdt + sizeof(SDT) + (index * 8)); + SDT* sdt = &(xsdt[index]) + offsetToAdd; for (int signature_index = 0; signature_index < 4; signature_index++) { @@ -94,11 +95,13 @@ namespace NewOS break; if (signature_index == 3) - return ErrorOr(reinterpret_cast((SDT*)sdt)); + return ErrorOr(reinterpret_cast(sdt)); } + + offsetToAdd = sdt->Length; } - return ErrorOr{-1}; + return ErrorOr{nullptr}; } /*** diff --git a/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp b/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp index 2129d790..ec6d47da 100644 --- a/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp +++ b/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp @@ -23,12 +23,12 @@ namespace NewOS::HAL constexpr Int32 kThreadBoot = 4; /* - * - * this is used to store info about the current running thread - * we use this struct to determine if we can use it, or mark it as used or on - * sleep. - * - */ + * + * this is used to store info about the current running thread + * we use this struct to determine if we can use it, or mark it as used or on + * sleep. + * + */ struct ProcessorInfoAMD64 final { @@ -51,12 +51,12 @@ namespace NewOS::HAL { struct MadtAddress final { + UInt32 fAddress; UInt32 fFlags; // 1 = Dual Legacy PICs installed - UInt32 fPhysicalAddress; Char fType; Char fRecLen; // record length - } Madt[]; + } fMadt[]; }; struct MadtProcessorLocalApic final @@ -104,20 +104,23 @@ namespace NewOS::HAL void hal_system_get_cores(voidPtr rsdPtr) { - kcout << "New OS: Constructing ACPIFactoryInterface...\r"; - auto acpi = ACPIFactoryInterface(rsdPtr); kApicMadt = acpi.Find(kApicSignature).Leak().Leak(); if (kApicMadt) { - kcout << "New OS: Successfuly fetched the MADT!\r"; + kcout << "New OS: Successfuly fetched the cores!\r"; kApicInfoBlock = (MadtType*)kApicMadt; + + kcout << "New OS: Revision: "; + kcout.HexNumber(kApicInfoBlock->Revision).EndLine(); + + ke_stop(RUNTIME_CHECK_BOOTSTRAP); } - else - { - MUST_PASS(false); - } + else + { + ke_stop(RUNTIME_CHECK_BOOTSTRAP); + } } } // namespace NewOS::HAL diff --git a/Kernel/HALKit/AMD64/HalHardwareMP.cpp b/Kernel/HALKit/AMD64/HalHardwareMP.cpp index 2ebf45fd..83e99ef8 100644 --- a/Kernel/HALKit/AMD64/HalHardwareMP.cpp +++ b/Kernel/HALKit/AMD64/HalHardwareMP.cpp @@ -16,7 +16,7 @@ namespace NewOS { HAL::rt_cli(); - stack->Rcx = 0; + HAL::rt_sti(); } @@ -27,7 +27,7 @@ namespace NewOS { HAL::rt_cli(); - stack->Rcx = 1; + HAL::rt_sti(); } diff --git a/Kernel/HALKit/AMD64/HalInterruptAPI.asm b/Kernel/HALKit/AMD64/HalInterruptAPI.asm index e4063388..875a1abc 100644 --- a/Kernel/HALKit/AMD64/HalInterruptAPI.asm +++ b/Kernel/HALKit/AMD64/HalInterruptAPI.asm @@ -14,16 +14,16 @@ %define kInterruptId 0x21 %macro IntExp 1 -global __HCR_INT_%1 -__HCR_INT_%1: +global __NEW_INT_%1 +__NEW_INT_%1: cld iretq %endmacro %macro IntNormal 1 -global __HCR_INT_%1 -__HCR_INT_%1: +global __NEW_INT_%1 +__NEW_INT_%1: cld iretq @@ -54,7 +54,7 @@ IntNormal 4 IntNormal 5 ;; Invalid opcode interrupt -__HCR_INT_6: +__NEW_INT_6: cli push rax @@ -75,7 +75,7 @@ IntExp 11 IntExp 12 -__HCR_INT_13: +__NEW_INT_13: cli push rax @@ -88,7 +88,7 @@ __HCR_INT_13: sti iretq -__HCR_INT_14: +__NEW_INT_14: cli push rax @@ -135,7 +135,7 @@ IntNormal 41 IntNormal 42 IntNormal 43 -__HCR_INT_44: +__NEW_INT_44: cli ;; TODO: CoreEvents dispatch routine. @@ -153,7 +153,7 @@ IntNormal 47 IntNormal 48 IntNormal 49 -__HCR_INT_50: +__NEW_INT_50: cli ;; todo handle system calls. @@ -217,6 +217,6 @@ section .data kInterruptVectorTable: %assign i 0 %rep 256 - dq __HCR_INT_%+i + dq __NEW_INT_%+i %assign i i+1 %endrep diff --git a/Kernel/HALKit/AMD64/ReadMe.md b/Kernel/HALKit/AMD64/ReadMe.md new file mode 100644 index 00000000..0be48c77 --- /dev/null +++ b/Kernel/HALKit/AMD64/ReadMe.md @@ -0,0 +1,4 @@ +AMD64 Hardware Abstraction Layer + +- Supported CPU: AMD64 CPU +- Supported Firmware: EDK 2 \ No newline at end of file diff --git a/Kernel/HALKit/ARM64/ReadMe.md b/Kernel/HALKit/ARM64/ReadMe.md new file mode 100644 index 00000000..89679e18 --- /dev/null +++ b/Kernel/HALKit/ARM64/ReadMe.md @@ -0,0 +1,4 @@ +ARM64 Hardware Abstraction Layer + +- Supported CPU: Qualcomm CPU +- Supported Firmware: EDK 2 \ No newline at end of file diff --git a/Kernel/HALKit/POWER/ReadMe.md b/Kernel/HALKit/POWER/ReadMe.md new file mode 100644 index 00000000..a9751581 --- /dev/null +++ b/Kernel/HALKit/POWER/ReadMe.md @@ -0,0 +1,4 @@ +POWER Hardware Abstraction Layer + +- Supported CPU: POWER +- Supported Firmware: CoreBoot \ No newline at end of file diff --git a/Kernel/HALKit/RISCV/ReadMe.md b/Kernel/HALKit/RISCV/ReadMe.md new file mode 100644 index 00000000..b099aa31 --- /dev/null +++ b/Kernel/HALKit/RISCV/ReadMe.md @@ -0,0 +1,4 @@ +RISCV64 Hardware Abstraction Layer + +- Supported CPU: RISCV64 +- Supported Firmware: CoreBoot \ No newline at end of file diff --git a/Kernel/KernelKit/DebugOutput.hpp b/Kernel/KernelKit/DebugOutput.hpp index 7fde69aa..656fe7a9 100644 --- a/Kernel/KernelKit/DebugOutput.hpp +++ b/Kernel/KernelKit/DebugOutput.hpp @@ -15,7 +15,7 @@ #define kDebugUnboundPort 0x0FEED -#define kDebugMag0 'H' +#define kDebugMag0 'N' #define kDebugMag1 'D' #define kDebugMag2 'B' #define kDebugMag3 'G' @@ -27,6 +27,12 @@ namespace NewOS { + 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 { @@ -34,10 +40,30 @@ namespace NewOS TerminalDevice(void (*print)(const Char*), void (*get)(const Char*)) : DeviceInterface(print, get) { + } virtual ~TerminalDevice() { + + } + + TerminalDevice& Number(const Long Data) noexcept + { + number(Data); + return *this; + } + + TerminalDevice& HexNumber(const Long Data) noexcept + { + number(Data); + return *this; + } + + TerminalDevice& EndLine() noexcept + { + end_line(); + return *this; } /// @brief returns device name (terminal name) diff --git a/Kernel/Source/AppMain.cxx b/Kernel/Source/AppMain.cxx index b91d6082..4f5de11f 100644 --- a/Kernel/Source/AppMain.cxx +++ b/Kernel/Source/AppMain.cxx @@ -22,6 +22,7 @@ #include #include #include +#include namespace Detail { @@ -177,6 +178,12 @@ namespace Detail return fNewFS; } }; + + STATIC NewOS::Void AppWatchdogThread(NewOS::Void) + { + NewOS::kcout << "SystemSanityThread: Exiting process..."; + NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().Exit(0); + } } // namespace Detail /// @file Main microkernel entrypoint. @@ -186,6 +193,9 @@ EXTERN_C NewOS::Void AppMain(NewOS::Void) /// Now run kernel loop, until no process are running. Detail::FilesystemWizard wizard; // automatic. + auto cWatchdogThreadName = "SystemSanityThread"; + NewOS::execute_from_image((NewOS::MainKind)Detail::AppWatchdogThread, cWatchdogThreadName); + while (NewOS::ProcessScheduler::Shared().Leak().Run() > 0) { ; diff --git a/Kernel/Source/CodeManager.cxx b/Kernel/Source/CodeManager.cxx index 39917163..001795ce 100644 --- a/Kernel/Source/CodeManager.cxx +++ b/Kernel/Source/CodeManager.cxx @@ -8,22 +8,23 @@ #include #include -using namespace NewOS; - -/// @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 NewOS { - if (!main) - return false; - - ProcessHeader proc((VoidPtr)main); - proc.Kind = ProcessHeader::kDriverKind; - rt_copy_memory((VoidPtr)processName, proc.Name, rt_string_len(proc.Name)); - - Ref refProc = proc; - - return ProcessScheduler::Shared().Leak().Add(refProc); -} \ No newline at end of file + /// @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 + { + if (!main) + return false; + + ProcessHeader proc((VoidPtr)main); + proc.Kind = ProcessHeader::kDriverKind; + rt_copy_memory((VoidPtr)processName, proc.Name, rt_string_len(proc.Name)); + + Ref refProc = proc; + + return ProcessScheduler::Shared().Leak().Add(refProc); + } +} // namespace NewOS \ No newline at end of file -- cgit v1.2.3 From 84b0e780dfd9272b177c32cc3bb99f37bb88304d Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Fri, 10 May 2024 07:06:43 +0200 Subject: MHR-23: Getting SMP to work... Signed-off-by: Amlal El Mahrouss --- Boot/NetBoot/Module.cxx | 5 +- Boot/NetBoot/NetBoot.hxx | 12 +++ Boot/Source/BootloaderRsrc.rsrc | 2 +- Boot/Source/makefile | 106 -------------------- Boot/makefile | 110 +++++++++++++++++++++ Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx | 19 ++-- .../HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp | 58 +++++------ Kernel/HALKit/AXP/README.TXT | 2 +- Kernel/KernelKit/DebugOutput.hpp | 2 +- Kernel/KernelKit/FileManager.hpp | 2 - Kernel/KernelKit/ProcessScheduler.hpp | 4 +- Kernel/KernelRsrc.rsrc | 2 +- Kernel/Linker/16x0.json | 2 +- Kernel/Linker/32x0.json | 2 +- Kernel/Linker/64x0.json | 2 +- Kernel/NewKit/Application.hxx | 31 ------ Kernel/NewKit/ApplicationInterface.hxx | 31 ++++++ Kernel/Source/AppMain.cxx | 39 ++++++-- Kernel/Source/FileManager.cxx | 22 +---- Kernel/Source/KernelCheck.cxx | 2 +- Kernel/Source/ProcessScheduler.cxx | 2 +- Kernel/Source/Variant.cxx | 5 - Kernel/makefile | 5 +- 23 files changed, 240 insertions(+), 227 deletions(-) create mode 100644 Boot/NetBoot/NetBoot.hxx delete mode 100644 Boot/Source/makefile create mode 100644 Boot/makefile delete mode 100644 Kernel/NewKit/Application.hxx create mode 100644 Kernel/NewKit/ApplicationInterface.hxx (limited to 'Kernel/Source') diff --git a/Boot/NetBoot/Module.cxx b/Boot/NetBoot/Module.cxx index c296903b..57841904 100644 --- a/Boot/NetBoot/Module.cxx +++ b/Boot/NetBoot/Module.cxx @@ -8,10 +8,11 @@ */ #include +#include -EXTERN_C Int32 EfiMain(Void) +EXTERN_C Int32 ModuleMain(Void) { - /// - Find a network drive called "/OnlineBoot" + /// - Find a network drive called "/Remote/NewOSKrnl" /// - Download our image /// - Boot from it. diff --git a/Boot/NetBoot/NetBoot.hxx b/Boot/NetBoot/NetBoot.hxx new file mode 100644 index 00000000..d45f1de1 --- /dev/null +++ b/Boot/NetBoot/NetBoot.hxx @@ -0,0 +1,12 @@ +/* + * ======================================================== + * + * NetBoot + * Copyright SoftwareLabs, all rights reserved. + * + * ======================================================== + */ + +#pragma once + +#include diff --git a/Boot/Source/BootloaderRsrc.rsrc b/Boot/Source/BootloaderRsrc.rsrc index d79211e7..0282192b 100644 --- a/Boot/Source/BootloaderRsrc.rsrc +++ b/Boot/Source/BootloaderRsrc.rsrc @@ -15,7 +15,7 @@ BEGIN VALUE "FileVersion", BOOTLOADER_VERSION VALUE "InternalName", "NewBoot" VALUE "LegalCopyright", "Copyright SoftwareLabs, all rights reserved." - VALUE "OriginalFilename", "NewBoot.exe" + VALUE "OriginalFilename", "NewOSLdr.exe" VALUE "ProductName", "NewBoot" VALUE "ProductVersion", BOOTLOADER_VERSION END diff --git a/Boot/Source/makefile b/Boot/Source/makefile deleted file mode 100644 index 70fa7232..00000000 --- a/Boot/Source/makefile +++ /dev/null @@ -1,106 +0,0 @@ -################################################## -# (C) SoftwareLabs, all rights reserved. -# This is the bootloader makefile. -################################################## - -CC_GNU=x86_64-w64-mingw32-g++ -LD_GNU=x86_64-w64-mingw32-ld - -WINDRES=x86_64-w64-mingw32-windres - -ADD_FILE=touch -COPY=cp -HTTP_GET=wget - -ifeq ($(shell uname), Windows_NT) -EMU=qemu-system-x86_64w -else -EMU=qemu-system-x86_64 -endif - -ifeq ($(NEWS_MODEL), ) -NEWOS_MODEL=-DkMachineModel="\"Generic NeWS HD\"" -endif - -IMG=epm.img -IMG_2=epm-slave.img - -EMU_FLAGS=-net none -smp 4 -m 8G -M q35 \ - -bios OVMF.fd -device piix3-ide,id=ide \ - -drive id=disk,file=$(IMG),format=raw,if=none \ - -device ide-hd,drive=disk,bus=ide.0 -drive \ - file=fat:rw:Root,index=2,format=raw -d int -hdd epm-slave.img - -LD_FLAGS=-e Main --subsystem=10 - -ifeq ($(NEWS_STANDLONE), ) -OBJ=*.o ../../Kernel/Objects/*.obj -else -RESCMD=$(WINDRES) BootloaderRsrc.rsrc -O coff -o BootloaderRsrc.o -STANDALONE_MACRO=-D__STANDALONE__ -OBJ=*.o -endif - -REM=rm -REM_FLAG=-f - -FLAG_ASM=-f win64 -FLAG_GNU=-fshort-wchar -D__EFI_x86_64__ -mno-red-zone -D__KERNEL__ -D__NEWBOOT__ \ - -DEFI_FUNCTION_WRAPPER -I../ -I../../Kernel -I./ -c -nostdlib -fno-rtti -fno-exceptions \ - -std=c++20 -D__HAVE_MAHROUSS_APIS__ -D__MAHROUSS__ -D__BOOTLOADER__ -I./ - -BOOT_LOADER=NewBoot.exe -KERNEL=NewKernel.exe - -.PHONY: invalid-recipe -invalid-recipe: - @echo "invalid-recipe: Use make compile- instead." - -.PHONY: all -all: compile-amd64 - mkdir -p Root/EFI/BOOT - $(LD_GNU) $(OBJ) $(LD_FLAGS) -o $(BOOT_LOADER) - $(COPY) $(BOOT_LOADER) Root/EFI/BOOT/BOOTX64.EFI - $(COPY) $(BOOT_LOADER) Root/EFI/BOOT/NEWBOOT.EFI - $(COPY) ../../Kernel/$(KERNEL) Root/$(KERNEL) - -ifneq ($(DEBUG_SUPPORT), ) -DEBUG = -D__DEBUG__ -endif - -.PHONY: compile-amd64 -compile-amd64: - $(RESCMD) - $(CC_GNU) $(NEWOS_MODEL) $(STANDALONE_MACRO) $(FLAG_GNU) $(DEBUG) $(wildcard HEL/AMD64/*.cxx) $(wildcard HEL/AMD64/*.S) $(wildcard *.cxx) - -.PHONY: run-efi-amd64 -run-efi-amd64: - $(EMU) $(EMU_FLAGS) - -# img_2 is the rescue disk. img is the bootable disk, as provided by the NeWS. -.PHONY: epm-img -epm-img: - qemu-img create -f raw $(IMG) 10G - qemu-img create -f raw $(IMG_2) 512M - -.PHONY: download-edk -download-edk: - $(HTTP_GET) https://retrage.github.io/edk2-nightly/bin/DEBUGX64_OVMF.fd -O OVMF.fd - -BINS=*.bin -EXECUTABLES=NewBoot.exe NewKernel.exe OVMF.fd - -TARGETS=$(REM_FLAG) $(OBJ) $(BIN) $(IMG) $(IMG_2) $(EXECUTABLES) - -.PHONY: clean -clean: - $(REM) $(TARGETS) - -.PHONY: help -help: - @echo "=== HELP ===" - @echo "epm-img: Format a disk using the Explicit Partition Map." - @echo "gpt-img: Format a disk using the Explicit Partition Map." - @echo "clean: clean bootloader." - @echo "bootloader-amd64: Build bootloader. (PC AMD64)" - @echo "run-efi-amd64: Run bootloader. (PC AMD64)" diff --git a/Boot/makefile b/Boot/makefile new file mode 100644 index 00000000..878cee2a --- /dev/null +++ b/Boot/makefile @@ -0,0 +1,110 @@ +################################################## +# (C) SoftwareLabs, all rights reserved. +# This is the bootloader makefile. +################################################## + +CC_GNU=x86_64-w64-mingw32-g++ +LD_GNU=x86_64-w64-mingw32-ld + +WINDRES=x86_64-w64-mingw32-windres + +ADD_FILE=touch +COPY=cp +HTTP_GET=wget + +ifeq ($(shell uname), Windows_NT) +EMU=qemu-system-x86_64w +else +EMU=qemu-system-x86_64 +endif + +ifeq ($(NEWS_MODEL), ) +NEWOS_MODEL=-DkMachineModel="\"Generic NeWS HD\"" +endif + +BIOS=OVMF.fd +IMG=epm.img +IMG_2=epm-slave.img + +EMU_FLAGS=-net none -smp 4,sockets=1,cores=4,threads=1 -m 8G -M q35 \ + -bios Source/$(BIOS) -device piix3-ide,id=ide \ + -drive id=disk,file=Source/$(IMG),format=raw,if=none \ + -device ide-hd,drive=disk,bus=ide.0 -drive \ + file=fat:rw:Source/Root,index=2,format=raw -d int -hdd Source/$(IMG_2) + +LD_FLAGS=-e Main --subsystem=10 + +ifeq ($(NEWS_STANDLONE), ) +OBJ=*.o ../Kernel/Objects/*.obj +else +RESCMD=$(WINDRES) BootloaderRsrc.rsrc -O coff -o BootloaderRsrc.o +STANDALONE_MACRO=-D__STANDALONE__ +OBJ=*.o +endif + +REM=rm +REM_FLAG=-f + +FLAG_ASM=-f win64 +FLAG_GNU=-fshort-wchar -D__EFI_x86_64__ -mno-red-zone -D__KERNEL__ -D__NEWBOOT__ \ + -DEFI_FUNCTION_WRAPPER -I./ -I../Kernel -I./ -c -nostdlib -fno-rtti -fno-exceptions \ + -std=c++20 -D__HAVE_MAHROUSS_APIS__ -D__MAHROUSS__ -D__BOOTLOADER__ -I./ + +BOOT_LOADER=NewOSLdr.exe +KERNEL=NewOSKrnl.exe + +.PHONY: invalid-recipe +invalid-recipe: + @echo "invalid-recipe: Use make compile- instead." + +.PHONY: all +all: compile-amd64 + mkdir -p Root/EFI/BOOT + $(LD_GNU) $(OBJ) $(LD_FLAGS) -o Source/$(BOOT_LOADER) + $(COPY) Source/$(BOOT_LOADER) Source/Root/EFI/BOOT/BOOTX64.EFI + $(COPY) Source/$(BOOT_LOADER) Source/Root/EFI/BOOT/NEWBOOT.EFI + $(COPY) ../Kernel/$(KERNEL) Source/Root/$(KERNEL) + +ifneq ($(DEBUG_SUPPORT), ) +DEBUG = -D__DEBUG__ +endif + +.PHONY: compile-amd64 +compile-amd64: + $(RESCMD) + $(CC_GNU) $(NEWOS_MODEL) $(STANDALONE_MACRO) $(FLAG_GNU) $(DEBUG) \ + $(wildcard Source/HEL/AMD64/*.cxx) \ + $(wildcard Source/HEL/AMD64/*.S) + $(wildcard Source/*.cxx) + +.PHONY: run-efi-amd64 +run-efi-amd64: + $(EMU) $(EMU_FLAGS) + +# img_2 is the rescue disk. img is the bootable disk, as provided by the NeWS. +.PHONY: epm-img +epm-img: + qemu-img create -f raw $(IMG) 10G + qemu-img create -f raw $(IMG_2) 512M + +.PHONY: download-edk +download-edk: + $(HTTP_GET) https://retrage.github.io/edk2-nightly/bin/DEBUGX64_OVMF.fd -O OVMF.fd + +BINS=*.bin +EXECUTABLES=NewOSLdr.exe NewOSKrnl.exe OVMF.fd + +TARGETS=$(REM_FLAG) $(OBJ) $(BIN) $(IMG) $(IMG_2) $(EXECUTABLES) + +.PHONY: clean +clean: + $(REM) $(TARGETS) + +.PHONY: help +help: + @echo "=== HELP ===" + @echo "epm-img: Format a disk using the Explicit Partition Map." + @echo "gpt-img: Format a disk using the Explicit Partition Map." + @echo "clean: clean bootloader." + @echo "bootloader-amd64: Build bootloader. (PC AMD64)" + @echo "run-efi-amd64: Run bootloader. (PC AMD64)" diff --git a/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx b/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx index f4c9226e..db82616e 100644 --- a/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx +++ b/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx @@ -75,7 +75,7 @@ namespace NewOS SDT* xsdt = (SDT*)(rsdPtr->XsdtAddress >> (rsdPtr->XsdtAddress & 0xFFF)); - SizeT num = (xsdt->Length + sizeof(SDT)) / 8; + SizeT num = -(xsdt->Length - sizeof(SDT)) / 8; this->fEntries = num; @@ -83,22 +83,19 @@ namespace NewOS kcout << "ACPI: Address of XSDT: " << hex_number((UIntPtr)xsdt) << endl; constexpr short ACPI_SIGNATURE_LENGTH = 4; - SizeT offsetToAdd = 0UL; - - for (Size index = 0; index < num; ++index) + + for (Size index = 0; index < this->fEntries; ++index) { - SDT* sdt = &(xsdt[index]) + offsetToAdd; + SDT &sdt = xsdt[index]; - for (int signature_index = 0; signature_index < 4; signature_index++) + for (short signature_index = 0; signature_index < ACPI_SIGNATURE_LENGTH; ++signature_index) { - if (sdt->Signature[signature_index] != signature[signature_index]) + if (sdt.Signature[signature_index] != signature[signature_index]) break; - if (signature_index == 3) - return ErrorOr(reinterpret_cast(sdt)); + if (signature_index == 4) + return ErrorOr(reinterpret_cast(&sdt)); } - - offsetToAdd = sdt->Length; } return ErrorOr{nullptr}; diff --git a/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp b/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp index ec6d47da..470a3286 100644 --- a/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp +++ b/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp @@ -46,54 +46,54 @@ namespace NewOS::HAL STATIC voidPtr kApicMadt = nullptr; STATIC const char* kApicSignature = "APIC"; - /// @brief Multiple APIC descriptor table. + /// @brief Multiple APIC Descriptor Table. struct MadtType final : public SDT { struct MadtAddress final { - UInt32 fAddress; - UInt32 fFlags; // 1 = Dual Legacy PICs installed - - Char fType; - Char fRecLen; // record length - } fMadt[]; + Char RecordType; + Char RecordLen; // record length + + UInt32 Address; + UInt32 Flags; // 1 = Dual Legacy PICs installed + } MadtRecords[]; }; struct MadtProcessorLocalApic final { - Char fProcessorId; - Char fApicId; - UInt32 fFlags; + Char AcpiProcessorId; + Char Reserved; + UInt32 Flags; }; struct MadtIOApic final { - Char fApicId; - Char fReserved; - UInt32 fAddress; - UInt32 fSystemInterruptBase; + Char ApicId; + Char Reserved; + UInt32 Address; + UInt32 SystemInterruptBase; }; struct MadtInterruptSource final { - Char fBusSource; - Char fIrqSource; - UInt32 fGSI; - UInt16 fFlags; + Char BusSource; + Char IrqSource; + UInt32 GSI; + UInt16 Flags; }; struct MadtInterruptNmi final { - Char fNmiSource; - Char fReserved; - UInt16 fFlags; - UInt32 fGSI; + Char NmiSource; + Char Reserved; + UInt16 Flags; + UInt32 GSI; }; struct MadtLocalApicAddressOverride final { - UInt16 fResvered; - UIntPtr fAddress; + UInt16 Resvered; + UIntPtr Address; }; /////////////////////////////////////////////////////////////////////////////////////// @@ -109,17 +109,13 @@ namespace NewOS::HAL if (kApicMadt) { - kcout << "New OS: Successfuly fetched the cores!\r"; + kcout << "New OS: APIC is present...\r"; kApicInfoBlock = (MadtType*)kApicMadt; - - kcout << "New OS: Revision: "; - kcout.HexNumber(kApicInfoBlock->Revision).EndLine(); - - ke_stop(RUNTIME_CHECK_BOOTSTRAP); } else { - ke_stop(RUNTIME_CHECK_BOOTSTRAP); + kcout << "New OS: APIC is not present! it is a vital component.\r"; + ke_stop(RUNTIME_CHECK_FAILED); } } } // namespace NewOS::HAL diff --git a/Kernel/HALKit/AXP/README.TXT b/Kernel/HALKit/AXP/README.TXT index 03c2b816..d4ef257d 100644 --- a/Kernel/HALKit/AXP/README.TXT +++ b/Kernel/HALKit/AXP/README.TXT @@ -1 +1 @@ -A Toy HAL to test the Kernel portability. +An toy HAL to test the kernel portability. diff --git a/Kernel/KernelKit/DebugOutput.hpp b/Kernel/KernelKit/DebugOutput.hpp index 656fe7a9..c6eb4485 100644 --- a/Kernel/KernelKit/DebugOutput.hpp +++ b/Kernel/KernelKit/DebugOutput.hpp @@ -56,7 +56,7 @@ namespace NewOS TerminalDevice& HexNumber(const Long Data) noexcept { - number(Data); + hex_number(Data); return *this; } diff --git a/Kernel/KernelKit/FileManager.hpp b/Kernel/KernelKit/FileManager.hpp index d0843a5e..a5ac6a93 100644 --- a/Kernel/KernelKit/FileManager.hpp +++ b/Kernel/KernelKit/FileManager.hpp @@ -136,8 +136,6 @@ namespace NewOS NewFSParser* GetImpl() noexcept; private: - Char fDataFork[kNewFSForkNameLen] = {0}; - Char fRsrcFork[kNewFSForkNameLen] = {0}; NewFSParser* fImpl{nullptr}; }; diff --git a/Kernel/KernelKit/ProcessScheduler.hpp b/Kernel/KernelKit/ProcessScheduler.hpp index ba34f9cb..243857ae 100644 --- a/Kernel/KernelKit/ProcessScheduler.hpp +++ b/Kernel/KernelKit/ProcessScheduler.hpp @@ -163,7 +163,7 @@ namespace NewOS enum { - kUserKind = 3, + kAppKind = 3, kLibKind = 3, kDriverKind = 0, kKindCount, @@ -178,7 +178,7 @@ namespace NewOS ProcessTime PTime; PID ProcessId{kSchedInvalidPID}; Int32 Ring{kRingDriverKind}; - Int32 Kind{kUserKind}; + Int32 Kind{kAppKind}; public: //! @brief boolean operator, check status. diff --git a/Kernel/KernelRsrc.rsrc b/Kernel/KernelRsrc.rsrc index d8fc6473..6689d10c 100644 --- a/Kernel/KernelRsrc.rsrc +++ b/Kernel/KernelRsrc.rsrc @@ -15,7 +15,7 @@ BEGIN VALUE "FileVersion", KERNEL_VERSION VALUE "InternalName", "NewKernel" VALUE "LegalCopyright", "SoftwareLabs" - VALUE "OriginalFilename", "NewKernel.exe" + VALUE "OriginalFilename", "NewOSKrnl.exe" VALUE "ProductName", "NewKernel" VALUE "ProductVersion", KERNEL_VERSION END diff --git a/Kernel/Linker/16x0.json b/Kernel/Linker/16x0.json index 5851a2d3..40cee7c9 100644 --- a/Kernel/Linker/16x0.json +++ b/Kernel/Linker/16x0.json @@ -1,6 +1,6 @@ { "executable_type": "kernel", - "output_name": "NewKernel.exe", + "output_name": "NewOSKrnl.exe", "start_proc": "__ImageStart", "format": "PEF" } diff --git a/Kernel/Linker/32x0.json b/Kernel/Linker/32x0.json index 5851a2d3..40cee7c9 100644 --- a/Kernel/Linker/32x0.json +++ b/Kernel/Linker/32x0.json @@ -1,6 +1,6 @@ { "executable_type": "kernel", - "output_name": "NewKernel.exe", + "output_name": "NewOSKrnl.exe", "start_proc": "__ImageStart", "format": "PEF" } diff --git a/Kernel/Linker/64x0.json b/Kernel/Linker/64x0.json index 5851a2d3..40cee7c9 100644 --- a/Kernel/Linker/64x0.json +++ b/Kernel/Linker/64x0.json @@ -1,6 +1,6 @@ { "executable_type": "kernel", - "output_name": "NewKernel.exe", + "output_name": "NewOSKrnl.exe", "start_proc": "__ImageStart", "format": "PEF" } diff --git a/Kernel/NewKit/Application.hxx b/Kernel/NewKit/Application.hxx deleted file mode 100644 index 19a892d6..00000000 --- a/Kernel/NewKit/Application.hxx +++ /dev/null @@ -1,31 +0,0 @@ -/* ------------------------------------------- - - Copyright SoftwareLabs - -------------------------------------------- */ - -#pragma once - -/// -/// @brief Application object, given by the OS to the process. interact with the OS. -/// @file Application.hxx -/// @author Amlal EL Mahrouss -/// - -#include -#include - -/// \brief Application Interface. -/// \author Amlal El Mahrouss -typedef struct _ApplicationInterface final -{ - /// @brief Releases the object exit the process on main object. - NewOS::Void (*Release)(struct _Application* Self, NewOS::Int32 ExitCode); - /// @brief Invoke a function from the application object. - NewOS::IntPtr (*Invoke)(struct _Application* Self, NewOS::Int32 Sel, ...); - /// @brief Query a new application object from a GUID. - /// @note this doesn't query a process, it query a registered object withtin that app. - NewOS::Void (*Query)(struct _Application* Self, NewOS::VoidPtr* Dst, NewOS::SizeT SzDst, NewOS::XRN::GUIDSequence GuidOf); -} ApplicationInterface, *ApplicationInterfaceRef; - -#define app_cast reinterpret_cast diff --git a/Kernel/NewKit/ApplicationInterface.hxx b/Kernel/NewKit/ApplicationInterface.hxx new file mode 100644 index 00000000..09d2c901 --- /dev/null +++ b/Kernel/NewKit/ApplicationInterface.hxx @@ -0,0 +1,31 @@ +/* ------------------------------------------- + + Copyright SoftwareLabs + +------------------------------------------- */ + +#pragma once + +/// +/// @brief Application object, given by the OS to the process. interact with the OS. +/// @file ApplicationInterface.hxx +/// @author Amlal EL Mahrouss +/// + +#include +#include + +/// \brief Application Interface. +/// \author Amlal El Mahrouss +typedef struct _ApplicationInterface final +{ + /// @brief Releases the object exit the process on main object. + NewOS::Void (*Release)(struct _Application* Self, NewOS::Int32 ExitCode); + /// @brief Invoke a function from the application object. + NewOS::IntPtr (*Invoke)(struct _Application* Self, NewOS::Int32 Sel, ...); + /// @brief Query a new application object from a GUID. + /// @note this doesn't query a process, it query a registered object withtin that app. + NewOS::Void (*Query)(struct _Application* Self, NewOS::VoidPtr* Dst, NewOS::SizeT SzDst, NewOS::XRN::GUIDSequence GuidOf); +} ApplicationInterface, *ApplicationInterfaceRef; + +#define app_cast reinterpret_cast diff --git a/Kernel/Source/AppMain.cxx b/Kernel/Source/AppMain.cxx index 4f5de11f..028e70e5 100644 --- a/Kernel/Source/AppMain.cxx +++ b/Kernel/Source/AppMain.cxx @@ -179,25 +179,50 @@ namespace Detail } }; - STATIC NewOS::Void AppWatchdogThread(NewOS::Void) + /// @brief System loader entrypoint. + /// @param void no parameters. + /// @return void no return value. + STATIC NewOS::Void AppSystemLoader(NewOS::Void) { - NewOS::kcout << "SystemSanityThread: Exiting process..."; + NewOS::PEFLoader coreGraphicsShLib("/System/CoreGraphics"); + + if (!coreGraphicsShLib.IsLoaded()) + { + NewOS::ke_stop(RUNTIME_CHECK_FAILED); + } + + NewOS::Utils::execute_from_image(coreGraphicsShLib, + NewOS::ProcessHeader::kLibKind); + + NewOS::PEFLoader logonService("/System/Login"); + + if (!logonService.IsLoaded()) + { + NewOS::ke_stop(RUNTIME_CHECK_FAILED); + } + + NewOS::Utils::execute_from_image(logonService, + NewOS::ProcessHeader::kAppKind); + + NewOS::kcout << "SystemLoader: Exiting process, we're done initializing stuff..."; + NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().Exit(0); } } // namespace Detail -/// @file Main microkernel entrypoint. - +/// @brief Application entrypoint. +/// @param Void +/// @return Void EXTERN_C NewOS::Void AppMain(NewOS::Void) { /// Now run kernel loop, until no process are running. Detail::FilesystemWizard wizard; // automatic. - auto cWatchdogThreadName = "SystemSanityThread"; - NewOS::execute_from_image((NewOS::MainKind)Detail::AppWatchdogThread, cWatchdogThreadName); + auto cLoaderName = "SystemLoader"; + NewOS::execute_from_image(Detail::AppSystemLoader, cLoaderName); while (NewOS::ProcessScheduler::Shared().Leak().Run() > 0) { - ; + NewOS::kcout << "New OS: sleeping...\r"; } } diff --git a/Kernel/Source/FileManager.cxx b/Kernel/Source/FileManager.cxx index 72ea15a1..ed90dab8 100644 --- a/Kernel/Source/FileManager.cxx +++ b/Kernel/Source/FileManager.cxx @@ -90,11 +90,11 @@ namespace NewOS NEWOS_UNUSED(flags); - const char* cReadAllFork = fDataFork; - + auto dataForkName = "FileData"; + if ((reinterpret_cast(node))->Kind == kNewFSCatalogKindFile) fImpl->WriteCatalog(reinterpret_cast(node), data, size, - cReadAllFork); + dataForkName); } /// @brief Read from filesystem fork. @@ -112,11 +112,11 @@ namespace NewOS NEWOS_UNUSED(flags); - const char* cReadAllFork = fDataFork; + auto dataForkName = "FileData"; if ((reinterpret_cast(node))->Kind == kNewFSCatalogKindFile) return fImpl->ReadCatalog(reinterpret_cast(node), sz, - cReadAllFork); + dataForkName); return nullptr; } @@ -167,17 +167,5 @@ namespace NewOS { return fImpl; } - - void NewFilesystemManager::SetResourceFork(const char* forkName) - { - if (!forkName) return; - rt_copy_memory((VoidPtr)forkName, (VoidPtr)fRsrcFork, rt_string_len(forkName)); - } - - void NewFilesystemManager::SetDataFork(const char* forkName) - { - if (!forkName) return; - rt_copy_memory((VoidPtr)forkName, (VoidPtr)fDataFork, rt_string_len(forkName)); - } #endif // __FSKIT_NEWFS__ } // namespace NewOS diff --git a/Kernel/Source/KernelCheck.cxx b/Kernel/Source/KernelCheck.cxx index e7c43650..5df52248 100644 --- a/Kernel/Source/KernelCheck.cxx +++ b/Kernel/Source/KernelCheck.cxx @@ -26,7 +26,7 @@ namespace NewOS void ke_stop(const NewOS::Int& id) { kcout << "*** STOP *** \r"; - kcout << "*** NewKernel.exe has trigerred a runtime stop. *** \r"; + kcout << "*** Kernel has trigerred a runtime stop. *** \r"; switch (id) { diff --git a/Kernel/Source/ProcessScheduler.cxx b/Kernel/Source/ProcessScheduler.cxx index 859ce657..555dfe07 100644 --- a/Kernel/Source/ProcessScheduler.cxx +++ b/Kernel/Source/ProcessScheduler.cxx @@ -218,7 +218,7 @@ namespace NewOS kcout << "ProcessScheduler::Add(Ref& process)\r"; /// Create heap according to type of process. - if (process.Leak().Kind == ProcessHeader::kUserKind) + if (process.Leak().Kind == ProcessHeader::kAppKind) process.Leak().HeapPtr = rt_new_heap(kUserHeapUser | kUserHeapRw); else if (process.Leak().Kind == ProcessHeader::kLibKind) process.Leak().HeapPtr = rt_new_heap(kUserHeapUser | kUserHeapRw | kUserHeapShared); diff --git a/Kernel/Source/Variant.cxx b/Kernel/Source/Variant.cxx index afe66624..1a09718b 100644 --- a/Kernel/Source/Variant.cxx +++ b/Kernel/Source/Variant.cxx @@ -10,11 +10,6 @@ namespace NewOS { const Char* Variant::ToString() { - if (fPtr == nullptr) - { - return ("Memory:{Nullptr}"); - } - switch (fKind) { case VariantKind::kString: diff --git a/Kernel/makefile b/Kernel/makefile index 61eb9dfe..74365a60 100644 --- a/Kernel/makefile +++ b/Kernel/makefile @@ -37,10 +37,7 @@ LDFLAGS = -e __ImageStart --subsystem=17 LDOBJ = Objects/*.obj # This file is the kernel, responsible of task management and memory. -KERNEL = NewKernel.exe - -# The kernel entrypoint -SCRIPT = --script=Linker/Platforms/PC.lds +KERNEL = NewOSKrnl.exe .PHONY: error error: -- cgit v1.2.3