From 83d870e58457a1d335a1d9b9966a6a1887cc297b Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Mon, 24 Nov 2025 03:02:43 +0100 Subject: feat! breaking changes on kernel sources. Signed-off-by: Amlal El Mahrouss --- dev/kernel/src/ACPIFactoryInterface.cc | 88 -- dev/kernel/src/Array.cc | 7 - dev/kernel/src/ArrayList.cc | 7 - dev/kernel/src/AsciiUtils.cc | 161 --- dev/kernel/src/Atom.cc | 10 - dev/kernel/src/BinaryMutex.cc | 70 -- dev/kernel/src/BitMapMgr.cc | 206 ---- dev/kernel/src/CRuntimeOverrides.cc | 27 - dev/kernel/src/CodeMgr.cc | 35 - dev/kernel/src/Crc32.cc | 65 - dev/kernel/src/Defines.cc | 7 - dev/kernel/src/DeviceMgr.cc | 9 - dev/kernel/src/DriveMgr.cc | 254 ---- dev/kernel/src/ErrorOr.cc | 12 - dev/kernel/src/FS/Ext2+IFS.cc | 1555 ------------------------ dev/kernel/src/FS/NeFS+FileMgr.cc | 276 ----- dev/kernel/src/FS/NeFS+FileSystemParser.cc | 870 ------------- dev/kernel/src/FS/OpenHeFS+FileMgr.cc | 191 --- dev/kernel/src/FS/OpenHeFS+FileSystemParser.cc | 1160 ------------------ dev/kernel/src/FileMgr.cc | 49 - dev/kernel/src/GUIDWizard.cc | 67 - dev/kernel/src/GUIDWrapper.cc | 9 - dev/kernel/src/Gfx/FBDeviceInterface.cc | 50 - dev/kernel/src/HardwareThreadScheduler.cc | 184 --- dev/kernel/src/HeapMgr.cc | 260 ---- dev/kernel/src/IDylibObject.cc | 13 - dev/kernel/src/IFS.cc | 89 -- dev/kernel/src/IPEFDylibObject.cc | 109 -- dev/kernel/src/IndexableProperty.cc | 45 - dev/kernel/src/Json.cc | 9 - dev/kernel/src/KPC.cc | 39 - dev/kernel/src/KernelTaskScheduler.cc | 37 - dev/kernel/src/LockDelegate.cc | 11 - dev/kernel/src/MutableArray.cc | 7 - dev/kernel/src/Network/IPAddress.cc | 113 -- dev/kernel/src/Network/IPCAddress.cc | 27 - dev/kernel/src/Network/IPCMessage.cc | 129 -- dev/kernel/src/Network/MACAddressGetter.cc | 13 - dev/kernel/src/Network/NetworkDevice.cc | 29 - dev/kernel/src/New+Delete.cc | 48 - dev/kernel/src/OwnPtr.cc | 7 - dev/kernel/src/PE32CodeMgr.cc | 258 ---- dev/kernel/src/PEFCodeMgr.cc | 335 ----- dev/kernel/src/PRDT.cc | 22 - dev/kernel/src/PageMgr.cc | 95 -- dev/kernel/src/Pmm.cc | 83 -- dev/kernel/src/Property.cc | 41 - dev/kernel/src/Ref.cc | 7 - dev/kernel/src/Semaphore.cc | 7 - dev/kernel/src/SoftwareTimer.cc | 36 - dev/kernel/src/Storage/AHCIDeviceInterface.cc | 87 -- dev/kernel/src/Storage/ATADeviceInterface.cc | 96 -- dev/kernel/src/Storage/NVMEDeviceInterface.cc | 22 - dev/kernel/src/Storage/SCSIDeviceInterface.cc | 9 - dev/kernel/src/Stream.cc | 12 - dev/kernel/src/Swap/DiskSwap.cc | 64 - dev/kernel/src/ThreadLocalStorage.cc | 52 - dev/kernel/src/Timer.cc | 19 - dev/kernel/src/UserMgr.cc | 131 -- dev/kernel/src/UserProcessScheduler.cc | 690 ----------- dev/kernel/src/UserProcessTeam.cc | 57 - dev/kernel/src/UtfUtils.cc | 62 - dev/kernel/src/Variant.cc | 38 - dev/kernel/src/ZXD.cc | 7 - 64 files changed, 8584 deletions(-) delete mode 100644 dev/kernel/src/ACPIFactoryInterface.cc delete mode 100644 dev/kernel/src/Array.cc delete mode 100644 dev/kernel/src/ArrayList.cc delete mode 100644 dev/kernel/src/AsciiUtils.cc delete mode 100644 dev/kernel/src/Atom.cc delete mode 100644 dev/kernel/src/BinaryMutex.cc delete mode 100644 dev/kernel/src/BitMapMgr.cc delete mode 100644 dev/kernel/src/CRuntimeOverrides.cc delete mode 100644 dev/kernel/src/CodeMgr.cc delete mode 100644 dev/kernel/src/Crc32.cc delete mode 100644 dev/kernel/src/Defines.cc delete mode 100644 dev/kernel/src/DeviceMgr.cc delete mode 100644 dev/kernel/src/DriveMgr.cc delete mode 100644 dev/kernel/src/ErrorOr.cc delete mode 100644 dev/kernel/src/FS/Ext2+IFS.cc delete mode 100644 dev/kernel/src/FS/NeFS+FileMgr.cc delete mode 100644 dev/kernel/src/FS/NeFS+FileSystemParser.cc delete mode 100644 dev/kernel/src/FS/OpenHeFS+FileMgr.cc delete mode 100644 dev/kernel/src/FS/OpenHeFS+FileSystemParser.cc delete mode 100644 dev/kernel/src/FileMgr.cc delete mode 100644 dev/kernel/src/GUIDWizard.cc delete mode 100644 dev/kernel/src/GUIDWrapper.cc delete mode 100644 dev/kernel/src/Gfx/FBDeviceInterface.cc delete mode 100644 dev/kernel/src/HardwareThreadScheduler.cc delete mode 100644 dev/kernel/src/HeapMgr.cc delete mode 100644 dev/kernel/src/IDylibObject.cc delete mode 100644 dev/kernel/src/IFS.cc delete mode 100644 dev/kernel/src/IPEFDylibObject.cc delete mode 100644 dev/kernel/src/IndexableProperty.cc delete mode 100644 dev/kernel/src/Json.cc delete mode 100644 dev/kernel/src/KPC.cc delete mode 100644 dev/kernel/src/KernelTaskScheduler.cc delete mode 100644 dev/kernel/src/LockDelegate.cc delete mode 100644 dev/kernel/src/MutableArray.cc delete mode 100644 dev/kernel/src/Network/IPAddress.cc delete mode 100644 dev/kernel/src/Network/IPCAddress.cc delete mode 100644 dev/kernel/src/Network/IPCMessage.cc delete mode 100644 dev/kernel/src/Network/MACAddressGetter.cc delete mode 100644 dev/kernel/src/Network/NetworkDevice.cc delete mode 100644 dev/kernel/src/New+Delete.cc delete mode 100644 dev/kernel/src/OwnPtr.cc delete mode 100644 dev/kernel/src/PE32CodeMgr.cc delete mode 100644 dev/kernel/src/PEFCodeMgr.cc delete mode 100644 dev/kernel/src/PRDT.cc delete mode 100644 dev/kernel/src/PageMgr.cc delete mode 100644 dev/kernel/src/Pmm.cc delete mode 100644 dev/kernel/src/Property.cc delete mode 100644 dev/kernel/src/Ref.cc delete mode 100644 dev/kernel/src/Semaphore.cc delete mode 100644 dev/kernel/src/SoftwareTimer.cc delete mode 100644 dev/kernel/src/Storage/AHCIDeviceInterface.cc delete mode 100644 dev/kernel/src/Storage/ATADeviceInterface.cc delete mode 100644 dev/kernel/src/Storage/NVMEDeviceInterface.cc delete mode 100644 dev/kernel/src/Storage/SCSIDeviceInterface.cc delete mode 100644 dev/kernel/src/Stream.cc delete mode 100644 dev/kernel/src/Swap/DiskSwap.cc delete mode 100644 dev/kernel/src/ThreadLocalStorage.cc delete mode 100644 dev/kernel/src/Timer.cc delete mode 100644 dev/kernel/src/UserMgr.cc delete mode 100644 dev/kernel/src/UserProcessScheduler.cc delete mode 100644 dev/kernel/src/UserProcessTeam.cc delete mode 100644 dev/kernel/src/UtfUtils.cc delete mode 100644 dev/kernel/src/Variant.cc delete mode 100644 dev/kernel/src/ZXD.cc (limited to 'dev/kernel/src') diff --git a/dev/kernel/src/ACPIFactoryInterface.cc b/dev/kernel/src/ACPIFactoryInterface.cc deleted file mode 100644 index 42819b7e..00000000 --- a/dev/kernel/src/ACPIFactoryInterface.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include -#include -#include - -namespace Kernel { -constexpr STATIC const auto kMinACPIVer = 1U; - -/// @brief Finds a descriptor table inside ACPI XSDT. -ErrorOr ACPIFactoryInterface::Find(const Char* signature) { - if (this->fRsdp) return ErrorOr{-kErrorInvalidData}; - if (!signature) return ErrorOr{-kErrorInvalidData}; - if (*signature == 0) return ErrorOr{-kErrorInvalidData}; - - RSDP* rsp_ptr = reinterpret_cast(this->fRsdp); - - if (rsp_ptr->Revision < kMinACPIVer) return ErrorOr{-kErrorInvalidData}; - - RSDT* xsdt = reinterpret_cast(rsp_ptr->RsdtAddress); - - Int64 num = (xsdt->Length - sizeof(SDT)) / sizeof(Int64); - - /*** - crucial to avoid underflows. - */ - if (num < 1) { - /// stop here, we should have entries... - ke_panic(RUNTIME_CHECK_ACPI); - return ErrorOr{-kErrorInvalidData}; - } - - this->fEntries = num; - - (Void)(kout << "ACPI: Number of entries: " << number(this->fEntries) << kendl); - (Void)(kout << "ACPI: Revision: " << number(xsdt->Revision) << kendl); - (Void)(kout << "ACPI: Signature: " << xsdt->Signature << kendl); - (Void)(kout << "ACPI: Address of XSDT: " << hex_number((UIntPtr) xsdt) << kendl); - - static constexpr const UInt16 cAcpiSignatureLength = 4U; - - for (Size index = 0; index < this->fEntries; ++index) { - SDT* sdt = reinterpret_cast(xsdt->AddressArr[index]); - - (Void)(kout << "ACPI: Checksum: " << number(sdt->Checksum) << kendl); - (Void)(kout << "ACPI: Revision: " << number(sdt->Revision) << kendl); - - for (UInt16 signature_index = 0; signature_index < cAcpiSignatureLength; ++signature_index) { - if (sdt->Signature[signature_index] != signature[signature_index]) break; - - if (signature_index == (cAcpiSignatureLength - 1)) { - (Void)(kout << "ACPI: SDT Signature: " << sdt->Signature << kendl); - (Void)(kout << "ACPI: SDT OEM ID: " << sdt->OemId << kendl); - return ErrorOr(reinterpret_cast(xsdt->AddressArr[index])); - } - } - } - - return ErrorOr{-kErrorInvalidData}; -} - -/*** -@brief Checksum on SDT header. -@param checksum the header to checksum -@param len the length of it. -*/ -bool ACPIFactoryInterface::Checksum(const Char* checksum, SSizeT len) { - if (len == 0 || !checksum) return NO; - - Char chr = 0; - - for (SSizeT index = 0L; index < len; ++index) { - chr += checksum[index]; - } - - return chr == 0; -} - -ErrorOr ACPIFactoryInterface::operator[](const Char* signature) { - if (!signature) return ErrorOr{-kErrorInvalidData}; - return this->Find(signature); -} -} // namespace Kernel diff --git a/dev/kernel/src/Array.cc b/dev/kernel/src/Array.cc deleted file mode 100644 index c792ef93..00000000 --- a/dev/kernel/src/Array.cc +++ /dev/null @@ -1,7 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include diff --git a/dev/kernel/src/ArrayList.cc b/dev/kernel/src/ArrayList.cc deleted file mode 100644 index 37042320..00000000 --- a/dev/kernel/src/ArrayList.cc +++ /dev/null @@ -1,7 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include diff --git a/dev/kernel/src/AsciiUtils.cc b/dev/kernel/src/AsciiUtils.cc deleted file mode 100644 index 1f1ab0f6..00000000 --- a/dev/kernel/src/AsciiUtils.cc +++ /dev/null @@ -1,161 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -namespace Kernel { -Int32 rt_string_cmp(const Char* src, const Char* cmp, Size size) { - for (Size i = 0; i < size; ++i) { - if (src[i] != cmp[i]) return static_cast(src[i]) - static_cast(cmp[i]); - } - return 0; -} - -SizeT rt_string_len(const Char* str, SizeT max_len) { - SizeT len = 0; - while (len < max_len && str[len] != '\0') ++len; - return len; -} - -Size rt_string_len(const Char* ptr) { - Size cnt = 0; - while (ptr[cnt] != '\0') ++cnt; - return cnt; -} - -const Char* rt_alloc_string(const Char* src) { - SizeT slen = rt_string_len(src); - Char* buffer = new Char[slen + 1]; - if (!buffer) return nullptr; - - if (rt_copy_memory_safe(reinterpret_cast(const_cast(src)), - reinterpret_cast(buffer), slen, slen + 1) < 0) { - delete[] buffer; - return nullptr; - } - - buffer[slen] = '\0'; - return buffer; -} - -Int32 rt_copy_memory_safe(const voidPtr src, voidPtr dst, Size len, Size dst_size) { - if (!src || !dst || len > dst_size) { - if (dst && dst_size) { - rt_set_memory_safe(dst, 0, dst_size, dst_size); - } - return -1; - } - - auto s = reinterpret_cast(src); - auto d = reinterpret_cast(dst); - - for (Size i = 0; i < len; ++i) d[i] = s[i]; - - return static_cast(len); -} - -voidPtr rt_set_memory_safe(voidPtr dst, UInt32 value, Size len, Size dst_size) { - if (!dst || len > dst_size) return nullptr; - auto p = reinterpret_cast(dst); - UInt8 v = static_cast(value & 0xFF); - for (Size i = 0; i < len; ++i) p[i] = v; - return dst; -} - -Void rt_zero_memory(voidPtr pointer, Size len) { - rt_set_memory_safe(pointer, 0, len, len); -} - -#ifdef __NE_ENFORCE_DEPRECATED_WARNINGS -[[deprecated("Use rt_set_memory_safe instead")]] -#endif -voidPtr -rt_set_memory(voidPtr src, UInt32 value, Size len) { - if (!src) return nullptr; - auto p = reinterpret_cast(src); - UInt8 v = static_cast(value & 0xFF); - for (Size i = 0; i < len; ++i) p[i] = v; - return src; -} - -#ifdef __NE_ENFORCE_DEPRECATED_WARNINGS -[[deprecated("Use rt_copy_memory_safe instead")]] -#endif -Int32 rt_copy_memory(const voidPtr src, voidPtr dst, Size len) { - if (!src || !dst) return -1; - auto s = reinterpret_cast(src); - auto d = reinterpret_cast(dst); - - for (Size i = 0; i < len; ++i) d[i] = s[i]; - - return static_cast(len); -} - -Int32 rt_to_uppercase(Int ch) { - return (ch >= 'a' && ch <= 'z') ? ch - 0x20 : ch; -} - -Int32 rt_to_lower(Int ch) { - return (ch >= 'A' && ch <= 'Z') ? ch + 0x20 : ch; -} - -Int32 rt_is_alnum(Int ch) { - return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'); -} - -Boolean rt_is_space(Int ch) { - return ch == ' '; -} - -Boolean rt_is_newln(Int ch) { - return ch == '\n'; -} - -Char rt_to_char(UInt64 value, Int32 base) { - static constexpr Char kDigits[] = "0123456789ABCDEF"; - return kDigits[value % base]; -} - -Bool rt_to_string(Char* str, UInt64 value, Int32 base) { - if (!str || base < 2 || base > 16) return NO; - - Int i = 0; - do { - str[i++] = rt_to_char(value, base); - value /= base; - } while (value); - str[i] = '\0'; - // in-place - for (Int j = 0; j < i / 2; ++j) { - Char tmp = str[j]; - str[j] = str[i - j - 1]; - str[i - j - 1] = tmp; - } - - return YES; -} - -VoidPtr rt_string_in_string(const Char* haystack, const Char* needle) { - if (!haystack || !needle) return nullptr; - - SizeT needle_len = rt_string_len(needle); - SizeT hay_len = rt_string_len(haystack); - - if (needle_len > hay_len) return nullptr; - for (SizeT i = 0; i <= hay_len - needle_len; ++i) { - if (rt_string_cmp(haystack + i, needle, needle_len) == 0) { - return reinterpret_cast(const_cast(haystack + i)); - } - } - return nullptr; -} - -Char* rt_string_has_char(Char* str, Char ch) { - if (!str) return nullptr; - while (*str && *str != ch) ++str; - return (*str == ch) ? str : nullptr; -} -} // namespace Kernel diff --git a/dev/kernel/src/Atom.cc b/dev/kernel/src/Atom.cc deleted file mode 100644 index c6c1dd40..00000000 --- a/dev/kernel/src/Atom.cc +++ /dev/null @@ -1,10 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -// @file Atom.cc -// @brief Atomic primitives diff --git a/dev/kernel/src/BinaryMutex.cc b/dev/kernel/src/BinaryMutex.cc deleted file mode 100644 index 3c332b33..00000000 --- a/dev/kernel/src/BinaryMutex.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include - -namespace Kernel { -/***********************************************************************************/ -/// @brief Unlocks the binary mutex. -/***********************************************************************************/ - -Bool BinaryMutex::Unlock() noexcept { - if (fLockingProcess->Status == ProcessStatusKind::kRunning) { - fLockingProcess = nullptr; - - return Yes; - } - - return No; -} - -/***********************************************************************************/ -/// @brief Locks process in the binary mutex. -/***********************************************************************************/ - -Bool BinaryMutex::Lock(USER_PROCESS* process) { - if (!process || this->IsLocked()) return No; - - this->fLockingProcess = process; - - return Yes; -} - -/***********************************************************************************/ -/// @brief Checks if process is locked. -/***********************************************************************************/ - -Bool BinaryMutex::IsLocked() const { - return this->fLockingProcess->Status == ProcessStatusKind::kRunning; -} - -/***********************************************************************************/ -/// @brief Try lock or wait. -/***********************************************************************************/ - -Bool BinaryMutex::LockAndWait(USER_PROCESS* process, TimerInterface* timer) { - if (timer == nullptr) return No; - - this->Lock(process); - - timer->Wait(); - - return this->Lock(process); -} - -/***********************************************************************************/ -/// @brief Wait for process **sec** until we check if it's free. -/// @param sec seconds. -/***********************************************************************************/ - -BOOL BinaryMutex::WaitForProcess(const UInt32& sec) noexcept { - HardwareTimer hw_timer(rtl_milliseconds(sec)); - hw_timer.Wait(); - - return !this->IsLocked(); -} -} // namespace Kernel diff --git a/dev/kernel/src/BitMapMgr.cc b/dev/kernel/src/BitMapMgr.cc deleted file mode 100644 index d7ecb810..00000000 --- a/dev/kernel/src/BitMapMgr.cc +++ /dev/null @@ -1,206 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#ifdef __NE_AMD64__ -#include -#elif defined(__NE_ARM64__) -#include -#endif - -#include -#include - -#define kBitMapMagic (0x10210U) - -#define kBitMapMagIdx (0U) -#define kBitMapSizeIdx (1U) -#define kBitMapUsedIdx (2U) - -///! @author Amlal El Mahrouss (amlal@nekernel.org) - -namespace Kernel { -namespace HAL { - namespace Detail { - /***********************************************************************************/ - /// \brief Proxy Interface to manage a bitmap allocator. - /***********************************************************************************/ - class IBitMapProxy final { - public: - explicit IBitMapProxy() = default; - ~IBitMapProxy() = default; - - NE_COPY_DELETE(IBitMapProxy) - - auto IsBitMap(VoidPtr page_ptr) -> Bool { - if (!page_ptr) return No; - - UIntPtr* ptr_bit_set = reinterpret_cast(page_ptr); - - if (!ptr_bit_set[kBitMapMagIdx] || ptr_bit_set[kBitMapMagIdx] != kBitMapMagic) return No; - - return Yes; - } - - auto FreeBitMap(VoidPtr page_ptr) -> Bool { - if (this->IsBitMap(page_ptr) == No) return No; - - UIntPtr* ptr_bit_set = reinterpret_cast(page_ptr); - - kBitMapCursor += ptr_bit_set[kBitMapSizeIdx]; - - ptr_bit_set[kBitMapMagIdx] = kBitMapMagic; - ptr_bit_set[kBitMapUsedIdx] = No; - - this->GetBitMapStatus(ptr_bit_set); - - return Yes; - } - - UInt32 MakeMMFlags(Bool wr, Bool user) { - UInt32 flags = kMMFlagsPresent; - - if (wr) flags |= kMMFlagsWr; - if (user) flags |= kMMFlagsUser; - - return flags; - } - - /***********************************************************************************/ - /// @brief Iterate over availables bitmap, until we find a free entry. - /// @param base_ptr base pointer to look on. - /// @param size the size of the requested data structure. - /// @param wr is writable flag? - /// @param user is user flag? - /// @param pad additional padding added to **size** - /// @return The new free address, or nullptr. - /***********************************************************************************/ - auto FindBitMap(VoidPtr base_ptr, SizeT size, Bool wr, Bool user, SizeT pad) -> VoidPtr { - if (!size) return nullptr; - - if (kBitMapCursor > kKernelBitMpSize) { - err_global_get() = kErrorOutOfBitMapMemory; - - (Void)(kout << "Bitmap limit reached, can't allocate more bitmaps." << kendl); - return nullptr; - } - - VoidPtr base = reinterpret_cast((UIntPtr) base_ptr); - MUST_PASS(base); - - if (!base) return nullptr; - - STATIC SizeT biggest = 0UL; - - while (YES) { - UIntPtr* ptr_bit_set = reinterpret_cast(base); - - if (ptr_bit_set[kBitMapMagIdx] == kBitMapMagic && - ptr_bit_set[kBitMapSizeIdx] == (size + pad)) { - if (ptr_bit_set[kBitMapUsedIdx] == No) { - ptr_bit_set[kBitMapSizeIdx] = size + pad; - ptr_bit_set[kBitMapUsedIdx] = Yes; - - this->GetBitMapStatus(ptr_bit_set); - - UInt32 flags = this->MakeMMFlags(wr, user); - mm_map_page(ptr_bit_set, (VoidPtr)mm_get_page_addr(ptr_bit_set), flags); - - if (biggest < (size + pad)) biggest = size + pad; - - kBitMapCursor += size + pad; - - return (VoidPtr) ptr_bit_set; - } - } else if (ptr_bit_set[kBitMapMagIdx] != kBitMapMagic) { - ptr_bit_set[kBitMapMagIdx] = kBitMapMagic; - ptr_bit_set[kBitMapSizeIdx] = (size + pad); - ptr_bit_set[kBitMapUsedIdx] = Yes; - - this->GetBitMapStatus(ptr_bit_set); - - UInt32 flags = this->MakeMMFlags(wr, user); - mm_map_page(ptr_bit_set, (VoidPtr)mm_get_page_addr(ptr_bit_set), flags); - - if (biggest < (size + pad)) biggest = (size + pad); - - kBitMapCursor += size + pad; - - return (VoidPtr) ptr_bit_set; - } - - UIntPtr raw_base = reinterpret_cast(base); - UIntPtr offset = (ptr_bit_set[kBitMapMagIdx] != kBitMapMagic) - ? (size + pad) - : ptr_bit_set[kBitMapSizeIdx]; - - base = reinterpret_cast(raw_base + offset); - if (base == nullptr) return nullptr; - } - - return nullptr; - } - - /// @brief Print Bitmap status - auto GetBitMapStatus(UIntPtr* ptr_bit_set) -> Void { - if (!this->IsBitMap(ptr_bit_set)) { - (Void)(kout << "Not a BitMap: " << hex_number((UIntPtr) ptr_bit_set) << kendl); - return; - } - - (Void)(kout << "Magic: " << hex_number(ptr_bit_set[kBitMapMagIdx]) << kendl); - (Void)(kout << "Is Allocated? " << (ptr_bit_set[kBitMapUsedIdx] ? "YES" : "NO") << kendl); - (Void)(kout << "Size of BitMap (B): " << number(ptr_bit_set[kBitMapSizeIdx]) << kendl); - (Void)(kout << "Size of BitMap (KIB): " << number(KIB(ptr_bit_set[kBitMapSizeIdx])) - << kendl); - (Void)(kout << "Size of BitMap (MIB): " << number(MIB(ptr_bit_set[kBitMapSizeIdx])) - << kendl); - (Void)(kout << "Size of BitMap (GIB): " << number(GIB(ptr_bit_set[kBitMapSizeIdx])) - << kendl); - (Void)(kout << "Size of BitMap (TIB): " << number(TIB(ptr_bit_set[kBitMapSizeIdx])) - << kendl); - (Void)(kout << "BitMap Address: " << hex_number((UIntPtr) ptr_bit_set) << kendl); - } - }; - } // namespace Detail - - STATIC Detail::IBitMapProxy kBitMapMgr; - - auto mm_is_bitmap(VoidPtr ptr) -> BOOL { - return kBitMapMgr.IsBitMap(ptr); - } - - /***********************************************************************************/ - /// @brief Allocate a new page to be used by the OS. - /// @param wr read/write bit. - /// @param user user bit. - /// @return a new bitmap allocated pointer. - /***********************************************************************************/ - auto mm_alloc_bitmap(Boolean wr, Boolean user, SizeT size, Bool is_page, SizeT pad) -> VoidPtr { - VoidPtr ptr_new = nullptr; - if (is_page) return nullptr; - - ptr_new = kBitMapMgr.FindBitMap(kKernelBitMpStart, size, wr, user, pad); - - if (!ptr_new) { - ke_panic(RUNTIME_CHECK_VIRTUAL_OUT_OF_MEM, "Out of memory bitmap"); - return nullptr; - } - - return ptr_new; - } - - /***********************************************************************************/ - /// @brief Free Bitmap, and mark it as absent. - /// @param ptr the pointer to free. - /***********************************************************************************/ - auto mm_free_bitmap(VoidPtr ptr) -> Bool { - if (!ptr) return No; - - Bool ret = kBitMapMgr.FreeBitMap(ptr); - return ret; - } -} // namespace HAL -} // namespace Kernel diff --git a/dev/kernel/src/CRuntimeOverrides.cc b/dev/kernel/src/CRuntimeOverrides.cc deleted file mode 100644 index a773d4f9..00000000 --- a/dev/kernel/src/CRuntimeOverrides.cc +++ /dev/null @@ -1,27 +0,0 @@ -/* ======================================== - - Copyright (C) 2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -using namespace Kernel; - -/// =========================================================== /// -/// @brief C Standard Library overrides. /// -/// =========================================================== /// - -EXTERN_C void* memset(void* dst, int c, long long unsigned int len) { - return Kernel::rt_set_memory_safe(dst, c, static_cast(len), static_cast(len)); -} - -EXTERN_C void* memcpy(void* dst, const void* src, long long unsigned int len) { - Kernel::rt_copy_memory_safe(const_cast(src), dst, static_cast(len), - static_cast(len)); - return dst; -} - -EXTERN_C Int32 strcmp(const char* a, const char* b) { - return Kernel::rt_string_cmp(a, b, rt_string_len(a)); -} diff --git a/dev/kernel/src/CodeMgr.cc b/dev/kernel/src/CodeMgr.cc deleted file mode 100644 index 7b7add6d..00000000 --- a/dev/kernel/src/CodeMgr.cc +++ /dev/null @@ -1,35 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include -#include - -namespace Kernel { - -/// @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 The team's process id. -BOOL rtl_create_kernel_task(HAL::StackFramePtr task, const KID kid) noexcept { - if (!kid || task == nullptr) return FALSE; - return KernelTaskHelper::Add(task, kid); -} - -/***********************************************************************************/ -/// @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. -/***********************************************************************************/ - -ProcessID rtl_create_user_process(rtl_main_kind main, const Char* process_name) noexcept { - if (!process_name || *process_name == 0) return kSchedInvalidPID; - return UserProcessScheduler::The().Spawn(process_name, reinterpret_cast(main), nullptr); -} -} // namespace Kernel diff --git a/dev/kernel/src/Crc32.cc b/dev/kernel/src/Crc32.cc deleted file mode 100644 index 88a9b73a..00000000 --- a/dev/kernel/src/Crc32.cc +++ /dev/null @@ -1,65 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -#define kCrcCnt (256) - -// @file CRC32.cc -// @brief Check sequence implementation. - -namespace Kernel { -/// @brief The CRC32 seed table. -UInt32 kChecksumPolys[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 in the data to compute. -/// @param len the length of the data. -/// @return CRC32 of **in**. -UInt32 ke_calculate_crc32(const VoidPtr inp, Int32 len) noexcept { - if (!inp) return ~0; - - UInt32 crc = 0xffffffff; - - Char* in = static_cast(inp); - - while ((len--) > 0) crc = (crc >> 8) ^ kChecksumPolys[(crc ^ *(in++)) & 0xFF]; - - return ~crc; -} -} // namespace Kernel diff --git a/dev/kernel/src/Defines.cc b/dev/kernel/src/Defines.cc deleted file mode 100644 index 1ae6f12f..00000000 --- a/dev/kernel/src/Defines.cc +++ /dev/null @@ -1,7 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include diff --git a/dev/kernel/src/DeviceMgr.cc b/dev/kernel/src/DeviceMgr.cc deleted file mode 100644 index b392a4ee..00000000 --- a/dev/kernel/src/DeviceMgr.cc +++ /dev/null @@ -1,9 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -namespace Kernel {} // namespace Kernel diff --git a/dev/kernel/src/DriveMgr.cc b/dev/kernel/src/DriveMgr.cc deleted file mode 100644 index 8f2611a4..00000000 --- a/dev/kernel/src/DriveMgr.cc +++ /dev/null @@ -1,254 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/***********************************************************************************/ -/// @file DriveMgr.cc -/// @brief Drive Manager of NeKernel. -///! @author Amlal El Mahrouss (amlal@nekernel.org) -/***********************************************************************************/ - -namespace Kernel { -#if defined(__ATA_PIO__) || defined(__ATA_DMA__) -STATIC UInt16 kATAIO = 0U; -STATIC UInt8 kATAMaster = 0U; -#endif - -#if defined(__AHCI__) -STATIC UInt16 kAHCIPortsImplemented [[maybe_unused]] = 0UL; -#endif - -/// @brief reads from an ATA drive. -/// @param pckt Packet structure (fPacketContent must be non null) -/// @return -Void io_drv_input(DriveTrait::DrivePacket& pckt) { -#ifdef __AHCI__ - drv_std_read(pckt.fPacketLba, (Char*) pckt.fPacketContent, kAHCISectorSize, pckt.fPacketSize); - - if (err_global_get() != kErrorSuccess) pckt.fPacketGood = NO; -#elif defined(__ATA_PIO__) || defined(__ATA_DMA__) - drv_std_read(pckt.fPacketLba, kATAIO, kATAMaster, (Char*) pckt.fPacketContent, kATASectorSize, - pckt.fPacketSize); -#endif -} - -/// @brief Writes to an ATA drive. -/// @param pckt the packet to write. -/// @return -Void io_drv_output(DriveTrait::DrivePacket& pckt) { - if (pckt.fPacketReadOnly) { - pckt.fPacketGood = NO; - return; - } - - // nothing starts before 512 anyways, even an EPM partition. - if (!pckt.fPacketReadOnly && pckt.fPacketLba == 0) { - pckt.fPacketGood = NO; - return; - } - -#ifdef __AHCI__ - drv_std_write(pckt.fPacketLba, (Char*) pckt.fPacketContent, kAHCISectorSize, pckt.fPacketSize); - - if (err_global_get() != kErrorSuccess) pckt.fPacketGood = NO; -#elif defined(__ATA_PIO__) || defined(__ATA_DMA__) - drv_std_write(pckt.fPacketLba, kATAIO, kATAMaster, (Char*) pckt.fPacketContent, kATASectorSize, - pckt.fPacketSize); -#endif -} - -/// @brief Executes a disk check on the ATA drive. -/// @param pckt the packet to read. -/// @return -Void io_drv_init(DriveTrait::DrivePacket& pckt) { -#if defined(__ATA_PIO__) || defined(__ATA_DMA__) - kATAMaster = 0; - kATAIO = 0; - - kATAMaster = YES; - kATAIO = ATA_PRIMARY_IO; - - if (drv_std_init(kATAIO, kATAMaster, kATAIO, kATAMaster)) { - pckt.fPacketGood = YES; - return; - } - - kATAMaster = NO; - kATAIO = ATA_SECONDARY_IO; - - if (!drv_std_init(kATAIO, kATAMaster, kATAIO, kATAMaster)) { - pckt.fPacketGood = YES; - return; - } - - pckt.fPacketGood = YES; -#elif defined(__AHCI__) - kAHCIPortsImplemented = 0; - drv_std_init(kAHCIPortsImplemented); - - pckt.fPacketGood = kAHCIPortsImplemented > 0; -#endif // if defined(__ATA_PIO__) || defined (__ATA_DMA__) -} - -/// @brief Gets the drive kind (ATA, SCSI, AHCI...) -/// @param void no arguments. -/// @return no arguments. -#ifdef __ATA_PIO__ -const Char* io_drv_kind(Void) { - return "ATA-PIO"; -} -#elif defined(__ATA_DMA__) -const Char* io_drv_kind(Void) { - return "ATA-DMA"; -} -#elif defined(__AHCI__) -const Char* io_drv_kind(Void) { - return "AHCI"; -} -#else -const Char* io_drv_kind(Void) { - return "null"; -} -#endif - -/// @brief Unimplemented drive function. -/// @param pckt the packet to read. -Void io_drv_unimplemented(DriveTrait::DrivePacket& pckt) noexcept { - NE_UNUSED(pckt); -} - -/// @brief Makes a new drive. -/// @return the new blank drive. -DriveTrait io_construct_blank_drive() noexcept { - DriveTrait trait; - - constexpr auto kBlankDrive = "/media/blank/"; - - rt_copy_memory((VoidPtr) kBlankDrive, trait.fName, rt_string_len(kBlankDrive)); - trait.fKind = kInvalidDrive; - - trait.fInput = io_drv_unimplemented; - trait.fOutput = io_drv_unimplemented; - trait.fVerify = io_drv_unimplemented; - trait.fInit = io_drv_unimplemented; - trait.fProtocol = io_drv_kind; - - kout << "DriveMgr: Construct: " << trait.fName << "\r"; - - return trait; -} - -namespace Probe { - Void io_detect_drive(DriveTrait& trait) { - trait.fInit(trait.fPacket); - - EPM_PART_BLOCK block_struct; - - trait.fPacket.fPacketLba = kEPMBootBlockLba; - trait.fPacket.fPacketSize = sizeof(EPM_PART_BLOCK); - trait.fPacket.fPacketContent = &block_struct; - - rt_copy_memory((VoidPtr) "fs/detect-packet", trait.fPacket.fPacketMime, - rt_string_len("fs/detect-packet")); - - trait.fInput(trait.fPacket); - - if (rt_string_cmp(block_struct.Magic, kEPMMagic, kEPMMagicLength) == 0) { - trait.fPacket.fPacketReadOnly = NO; - trait.fKind = kMassStorageDrive | kEPMDrive; - - kout << "DriveMgr: Disk is EPM formatted.\r"; - - trait.fSectorSz = block_struct.SectorSz; - trait.fLbaEnd = block_struct.LbaEnd; - trait.fLbaStart = block_struct.LbaStart; - } else { - GPT_PARTITION_TABLE gpt_struct; - - trait.fPacket.fPacketLba = kEPMBootBlockLba; - trait.fPacket.fPacketSize = sizeof(GPT_PARTITION_TABLE); - trait.fPacket.fPacketContent = &gpt_struct; - - rt_copy_memory((VoidPtr) "fs/detect-packet", trait.fPacket.fPacketMime, - rt_string_len("fs/detect-packet")); - - trait.fInput(trait.fPacket); - - if (rt_string_cmp(gpt_struct.Signature, kMagicGPT, kMagicLenGPT) == 0) { - trait.fPacket.fPacketReadOnly = NO; - trait.fKind = kMassStorageDrive | kGPTDrive; - - kout << "DriveMgr: Disk is GPT formatted.\r"; - - trait.fSectorSz = gpt_struct.SizeOfEntries; - trait.fLbaEnd = gpt_struct.LastGPTEntry; - trait.fLbaStart = gpt_struct.FirstGPTEntry; - } else { - kout << "DriveMgr: Disk is unformatted.\r"; - - trait.fPacket.fPacketReadOnly = YES; - trait.fKind = kMassStorageDrive | kUnformattedDrive | kReadOnlyDrive; - - trait.fSectorSz = 512; - trait.fLbaEnd = drv_std_get_sector_count() - 1; - trait.fLbaStart = 0x400; - } - } - - rt_copy_memory((VoidPtr) "*/*", trait.fPacket.fPacketMime, rt_string_len("*/*")); - - trait.fPacket.fPacketLba = 0; - trait.fPacket.fPacketSize = 0UL; - trait.fPacket.fPacketContent = nullptr; - } -} // namespace Probe - -/// @brief Fetches the main drive. -/// @return the new drive. (returns kEPMDrive if EPM formatted) -DriveTrait io_construct_main_drive() noexcept { - constexpr auto kMainDrive = "/media/main/"; - - DriveTrait trait; - - rt_copy_memory((VoidPtr) kMainDrive, trait.fName, rt_string_len(kMainDrive)); - MUST_PASS(trait.fName[0] != 0); - - trait.fVerify = io_drv_unimplemented; - trait.fOutput = io_drv_output; - trait.fInput = io_drv_input; - trait.fInit = io_drv_init; - trait.fProtocol = io_drv_kind; - - Probe::io_detect_drive(trait); - - return trait; -} - -/// @brief Replacement for io_construct_main_drive that works with IMountpoint. -/// @return the new drive. (returns kEPMDrive if EPM formatted) -Void io_construct_main_drive(DriveTrait& trait) noexcept { - constexpr auto kMainDrive = "/media/main/"; - - rt_copy_memory((VoidPtr) kMainDrive, trait.fName, rt_string_len(kMainDrive)); - MUST_PASS(trait.fName[0] != 0); - - trait.fVerify = io_drv_unimplemented; - trait.fOutput = io_drv_output; - trait.fInput = io_drv_input; - trait.fInit = io_drv_init; - trait.fProtocol = io_drv_kind; - - Probe::io_detect_drive(trait); -} -} // namespace Kernel diff --git a/dev/kernel/src/ErrorOr.cc b/dev/kernel/src/ErrorOr.cc deleted file mode 100644 index 9f1b550b..00000000 --- a/dev/kernel/src/ErrorOr.cc +++ /dev/null @@ -1,12 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -/***********************************************************************************/ -/// @file ErrorOr.cc /// -/// @brief ErrorOr container class. /// -/***********************************************************************************/ diff --git a/dev/kernel/src/FS/Ext2+IFS.cc b/dev/kernel/src/FS/Ext2+IFS.cc deleted file mode 100644 index 106229f7..00000000 --- a/dev/kernel/src/FS/Ext2+IFS.cc +++ /dev/null @@ -1,1555 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#ifndef __NE_MINIMAL_OS__ -#ifdef __FSKIT_INCLUDES_EXT2__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -constexpr static UInt32 EXT2_DIRECT_BLOCKS = 12; -constexpr static UInt32 EXT2_SINGLE_INDIRECT_INDEX = 12; -constexpr static UInt32 EXT2_DOUBLE_INDIRECT_INDEX = 13; -constexpr ATTRIBUTE(unused) static UInt32 EXT2_TRIPLE_INDIRECT_INDEX = 14; -constexpr static UInt32 EXT2_ROOT_INODE = 2; -constexpr ATTRIBUTE(unused) static UInt32 EXT2_SUPERBLOCK_BLOCK = 1; -constexpr static UInt32 EXT2_GROUP_DESC_BLOCK_SMALL = 2; -constexpr static UInt32 EXT2_GROUP_DESC_BLOCK_LARGE = 1; - -static inline SizeT ext2_min(SizeT a, SizeT b) { - return a < b ? a : b; -} - -struct Ext2GroupInfo { - EXT2_GROUP_DESCRIPTOR* groupDesc; - UInt32 groupDescriptorBlock; - UInt32 offsetInGroupDescBlock; - UInt8* blockBuffer; -}; - -// Convert EXT2 block number -> LBA (sector index) for Drive I/O. -static inline UInt32 ext2_block_to_lba(Ext2Context* ctx, UInt32 blockNumber) { - if (!ctx || !ctx->drive) return 0; - UInt32 blockSize = ctx->BlockSize(); - UInt32 sectorSize = ctx->drive->fSectorSz; - UInt32 sectorsPerBlock = blockSize / sectorSize; - return blockNumber * sectorsPerBlock; -} - -// Read a block and return a pointer to its content -static ErrorOr ext2_read_block_ptr(Ext2Context* ctx, UInt32 blockNumber) { - if (!ctx || !ctx->drive || !ctx->superblock) return ErrorOr(kErrorInvalidData); - - UInt32 blockSize = ctx->BlockSize(); - auto buf = (UInt32*) mm_alloc_ptr(blockSize, true, false); - if (!buf) return ErrorOr(kErrorHeapOutOfMemory); - - UInt32 lba = ext2_block_to_lba(ctx, blockNumber); - if (!ext2_read_block(ctx->drive, lba, buf, blockSize)) { - mm_free_ptr(buf); - return ErrorOr(kErrorDisk); - } - return ErrorOr(buf); -} - -// Get the block address for a given logical block index -static ErrorOr ext2_get_block_address(Ext2Context* ctx, Ext2Node* node, - UInt32 logicalIndex) { - if (!ctx || !node || !ctx->drive) return ErrorOr(kErrorInvalidData); - - UInt32 blockSize = ctx->BlockSize(); - UInt32 pointersPerBlock = blockSize / sizeof(UInt32); - - // Direct blocks - if (logicalIndex < EXT2_DIRECT_BLOCKS) { - UInt32 bn = node->inode.fBlock[logicalIndex]; - if (bn == 0) return ErrorOr(kErrorInvalidData); - return ErrorOr(bn); - } - - // Single indirect blocks - if (logicalIndex < (EXT2_DIRECT_BLOCKS + pointersPerBlock)) { - UInt32 iblock = node->inode.fBlock[EXT2_SINGLE_INDIRECT_INDEX]; - if (iblock == 0) return ErrorOr(kErrorInvalidData); - - auto res = ext2_read_block_ptr(ctx, iblock); - if (!res) return ErrorOr(res.Error()); - - // Using dereference operator - UInt32* ptr = *res.Leak(); // operator* returns T (UInt32*) - - UInt32 val = ptr[logicalIndex - EXT2_DIRECT_BLOCKS]; - mm_free_ptr(ptr); - - if (val == 0) return ErrorOr(kErrorInvalidData); - return ErrorOr(val); - } - - // Double indirect blocks - UInt32 doubleStart = EXT2_DIRECT_BLOCKS + pointersPerBlock; - UInt32 doubleSpan = pointersPerBlock * pointersPerBlock; - if (logicalIndex < (doubleStart + doubleSpan)) { - UInt32 db = node->inode.fBlock[EXT2_DOUBLE_INDIRECT_INDEX]; - if (db == 0) return ErrorOr(kErrorInvalidData); - - auto dblRes = ext2_read_block_ptr(ctx, db); - if (!dblRes) return ErrorOr(dblRes.Error()); - - UInt32* dblPtr = *dblRes.Leak(); - - UInt32 idxWithin = logicalIndex - doubleStart; - UInt32 firstIdx = idxWithin / pointersPerBlock; - UInt32 secondIdx = idxWithin % pointersPerBlock; - UInt32 singleBlockNum = dblPtr[firstIdx]; - - mm_free_ptr(dblPtr); - if (singleBlockNum == 0) return ErrorOr(kErrorInvalidData); - - auto singleRes = ext2_read_block_ptr(ctx, singleBlockNum); - if (!singleRes) return ErrorOr(singleRes.Error()); - - UInt32* singlePtr = *singleRes.Leak(); - UInt32 val = singlePtr[secondIdx]; - mm_free_ptr(singlePtr); - - if (val == 0) return ErrorOr(kErrorInvalidData); - return ErrorOr(val); - } - - return ErrorOr(kErrorUnimplemented); -} - -static ErrorOr ext2_read_inode_data(Ext2Context* ctx, Ext2Node* node, SizeT size) { - if (!ctx || !ctx->drive || !node || size == 0) return ErrorOr(1); - - auto blockSize = ctx->BlockSize(); - SizeT available = (node->inode.fSize > node->cursor) ? (node->inode.fSize - node->cursor) : 0; - SizeT bytesToRead = (size < available) ? size : available; - if (bytesToRead == 0) return ErrorOr(2); // nothing to read - - auto buffer = mm_alloc_ptr(bytesToRead, true, false); - if (!buffer) return ErrorOr(3); // allocation failed - - UInt32 currentOffset = node->cursor; - SizeT remaining = bytesToRead; - UInt8* dest = reinterpret_cast(buffer); - - while (remaining > 0) { - UInt32 logicalIndex = currentOffset / blockSize; - UInt32 offsetInBlock = currentOffset % blockSize; - - auto phys = ext2_get_block_address(ctx, node, logicalIndex); - if (phys.HasError()) { - mm_free_ptr(buffer); - return ErrorOr(phys.Error()); - } - - auto blockNumber = phys.Value(); - UInt32 lba = ext2_block_to_lba(ctx, blockNumber); - - auto blockBuf = mm_alloc_ptr(blockSize, true, false); - if (!blockBuf) { - mm_free_ptr(buffer); - return ErrorOr(4); // block buffer allocation failed - } - - if (!ext2_read_block(ctx->drive, lba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - mm_free_ptr(buffer); - return ErrorOr(5); // block read failed - } - - SizeT chunk = ext2_min(remaining, blockSize - offsetInBlock); - rt_copy_memory_safe(static_cast(static_cast(blockBuf) + offsetInBlock), - static_cast(dest), chunk, chunk); - - mm_free_ptr(blockBuf); - - currentOffset += static_cast(chunk); - dest += chunk; - remaining -= chunk; - } - - node->cursor += static_cast(bytesToRead); - return ErrorOr(buffer); -} - -// Get group descriptor information for a given block/inode number -static ErrorOr ext2_get_group_descriptor_info(Ext2Context* ctx, - UInt32 targetBlockOrInode) { - if (!ctx || !ctx->superblock || !ctx->drive) return ErrorOr(kErrorInvalidData); - - UInt32 blockSize = ctx->BlockSize(); - UInt32 blocksPerGroup = ctx->superblock->fBlocksPerGroup; - UInt32 inodesPerGroup = ctx->superblock->fInodesPerGroup; - UInt32 totalBlocks = ctx->superblock->fBlockCount; - UInt32 totalInodes = ctx->superblock->fInodeCount; - - if (blocksPerGroup == 0 || inodesPerGroup == 0) return ErrorOr(kErrorInvalidData); - - // block group index - UInt32 groupIndex = 0; - if (targetBlockOrInode == 0) { - groupIndex = 0; - } else if (targetBlockOrInode <= totalInodes) { - // 1-based - groupIndex = (targetBlockOrInode - 1) / inodesPerGroup; - } else { - // EXT2 block number - if (targetBlockOrInode < ctx->superblock->fFirstDataBlock) { - groupIndex = 0; - } else { - groupIndex = (targetBlockOrInode - ctx->superblock->fFirstDataBlock) / blocksPerGroup; - } - } - - // Calculate number of block groups - UInt32 groupsCount = static_cast((totalBlocks + blocksPerGroup - 1) / blocksPerGroup); - if (groupIndex >= groupsCount) return ErrorOr(kErrorInvalidData); - - // Determine GDT start block - UInt32 gdtStartBlock = - (blockSize == 1024) ? EXT2_GROUP_DESC_BLOCK_SMALL : EXT2_GROUP_DESC_BLOCK_LARGE; - - // Compute byte offset of descriptor within the GDT - const UInt32 descSize = sizeof(EXT2_GROUP_DESCRIPTOR); - UInt64 descByteOffset = static_cast(groupIndex) * descSize; - - // Which EXT2 block contains that descriptor? - UInt32 blockOffsetWithinGdt = static_cast(descByteOffset / blockSize); - UInt32 offsetInGroupDescBlock = static_cast(descByteOffset % blockSize); - UInt32 groupDescriptorBlock = gdtStartBlock + blockOffsetWithinGdt; - - // Allocate buffer and read the block containing the descriptor - auto blockBuffer = mm_alloc_ptr(blockSize, true, false); - if (!blockBuffer) return ErrorOr(kErrorHeapOutOfMemory); - - UInt32 groupDescriptorLba = ext2_block_to_lba(ctx, groupDescriptorBlock); - if (!ext2_read_block(ctx->drive, groupDescriptorLba, blockBuffer, blockSize)) { - mm_free_ptr(blockBuffer); - return ErrorOr(kErrorDisk); - } - - auto groupInfo = (Ext2GroupInfo*) mm_alloc_ptr(sizeof(Ext2GroupInfo), true, false); - if (!groupInfo) { - mm_free_ptr(blockBuffer); - return ErrorOr(kErrorHeapOutOfMemory); - } - - groupInfo->groupDesc = reinterpret_cast( - reinterpret_cast(blockBuffer) + offsetInGroupDescBlock); - groupInfo->groupDescriptorBlock = groupDescriptorBlock; - groupInfo->offsetInGroupDescBlock = offsetInGroupDescBlock; - groupInfo->blockBuffer = reinterpret_cast(blockBuffer); - - return ErrorOr(groupInfo); -} - -// Allocate a new block -inline ErrorOr ext2_alloc_block(Ext2Context* ctx, EXT2_GROUP_DESCRIPTOR* groupDesc) { - if (!ctx || !ctx->superblock || !groupDesc) return ErrorOr(kErrorInvalidData); - - UInt32 blockSize = ctx->BlockSize(); - - // for the bitmap - auto bitmap = mm_alloc_ptr(blockSize, true, false); - if (!bitmap) return ErrorOr(kErrorHeapOutOfMemory); - - // Read block bitmap - if (!ext2_read_block(ctx->drive, groupDesc->fBlockBitmap, bitmap, blockSize)) { - mm_free_ptr(bitmap); - return ErrorOr(kErrorDisk); - } - - // bit = 0 - for (UInt32 byteIdx = 0; byteIdx < blockSize; ++byteIdx) { - auto byte = reinterpret_cast(bitmap)[byteIdx]; - if (byte != 0xFF) { - for (int bit = 0; bit < 8; ++bit) { - if (!(byte & (1 << bit))) { - // Mark bit as used - reinterpret_cast(bitmap)[byteIdx] |= (1 << bit); - - // Compute block number - UInt32 blockNumber = byteIdx * 8 + bit; - - // Write bitmap back - if (!ext2_write_block(ctx->drive, groupDesc->fBlockBitmap, bitmap, blockSize)) { - mm_free_ptr(bitmap); - return ErrorOr(kErrorDisk); - } - - // Update group descriptor free count - groupDesc->fFreeBlocksCount--; - mm_free_ptr(bitmap); - return ErrorOr(blockNumber); - } - } - } - } - - mm_free_ptr(bitmap); - return ErrorOr(kErrorDiskIsFull); -} - -// Indirect blocks -static ErrorOr ext2_set_block_address(Ext2Context* ctx, Ext2Node* node, - UInt32 logicalBlockIndex, UInt32 physicalBlockNumber) { - using namespace Kernel; - - if (!ctx || !ctx->drive || !node) return ErrorOr(kErrorInvalidData); - - auto blockSize = ctx->BlockSize(); - UInt32 blocksPerPointerBlock = blockSize / sizeof(UInt32); - - // Direct blocks - if (logicalBlockIndex < EXT2_DIRECT_BLOCKS) { - node->inode.fBlock[logicalBlockIndex] = physicalBlockNumber; - return ErrorOr(nullptr); - } - - // Single indirect blocks - if (logicalBlockIndex < EXT2_DIRECT_BLOCKS + blocksPerPointerBlock) { - if (node->inode.fBlock[EXT2_SINGLE_INDIRECT_INDEX] == 0) { - auto groupInfoRes = ext2_get_group_descriptor_info(ctx, node->inodeNumber); - if (groupInfoRes.HasError()) return ErrorOr(groupInfoRes.Error()); - - auto groupInfo = groupInfoRes.Leak().Leak(); // Ref - auto newBlockRes = ext2_alloc_block(ctx, groupInfo->groupDesc); - if (newBlockRes.HasError()) { - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr(newBlockRes.Error()); - } - - node->inode.fBlock[EXT2_SINGLE_INDIRECT_INDEX] = newBlockRes.Leak(); - - UInt32 gdtLba = ext2_block_to_lba(ctx, groupInfo->groupDescriptorBlock); - if (!ext2_write_block(ctx->drive, gdtLba, groupInfo->blockBuffer, blockSize)) { - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr(kErrorDisk); - } - - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - // Zero out new indirect block - auto zeroBuf = mm_alloc_ptr(blockSize, true, false); - if (!zeroBuf) return ErrorOr(kErrorHeapOutOfMemory); - - rt_zero_memory(zeroBuf, blockSize); - UInt32 indirectLba = ext2_block_to_lba(ctx, node->inode.fBlock[EXT2_SINGLE_INDIRECT_INDEX]); - if (!ext2_write_block(ctx->drive, indirectLba, zeroBuf, blockSize)) { - mm_free_ptr(zeroBuf); - return ErrorOr(kErrorDisk); - } - - mm_free_ptr(zeroBuf); - } - - // Read, modify, and write single indirect block - auto indirectRes = ext2_read_block_ptr(ctx, node->inode.fBlock[EXT2_SINGLE_INDIRECT_INDEX]); - if (indirectRes.HasError()) return ErrorOr(indirectRes.Error()); - - UInt32* indirectPtr = indirectRes.Leak().Leak(); // Ref - indirectPtr[logicalBlockIndex - EXT2_DIRECT_BLOCKS] = physicalBlockNumber; - - UInt32 indirectLba = ext2_block_to_lba(ctx, node->inode.fBlock[EXT2_SINGLE_INDIRECT_INDEX]); - if (!ext2_write_block(ctx->drive, indirectLba, indirectPtr, blockSize)) { - mm_free_ptr(indirectPtr); - return ErrorOr(kErrorDisk); - } - - mm_free_ptr(indirectPtr); - return ErrorOr(nullptr); - } - - // Double - UInt32 doubleStart = EXT2_DIRECT_BLOCKS + blocksPerPointerBlock; - UInt32 doubleSpan = blocksPerPointerBlock * blocksPerPointerBlock; - if (logicalBlockIndex < doubleStart + doubleSpan) { - if (node->inode.fBlock[EXT2_DOUBLE_INDIRECT_INDEX] == 0) { - auto groupInfoRes = ext2_get_group_descriptor_info(ctx, node->inodeNumber); - if (groupInfoRes.HasError()) return ErrorOr(groupInfoRes.Error()); - - auto groupInfo = groupInfoRes.Leak().Leak(); - auto newBlockRes = ext2_alloc_block(ctx, groupInfo->groupDesc); - if (newBlockRes.HasError()) { - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr(newBlockRes.Error()); - } - - node->inode.fBlock[EXT2_DOUBLE_INDIRECT_INDEX] = newBlockRes.Leak(); - - UInt32 gdtLba = ext2_block_to_lba(ctx, groupInfo->groupDescriptorBlock); - if (!ext2_write_block(ctx->drive, gdtLba, groupInfo->blockBuffer, blockSize)) { - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr(kErrorDisk); - } - - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - // Zero new double-indirect block - auto zeroBuf = mm_alloc_ptr(blockSize, true, false); - if (!zeroBuf) return ErrorOr(kErrorHeapOutOfMemory); - - rt_zero_memory(zeroBuf, blockSize); - UInt32 dblLba = ext2_block_to_lba(ctx, node->inode.fBlock[EXT2_DOUBLE_INDIRECT_INDEX]); - if (!ext2_write_block(ctx->drive, dblLba, zeroBuf, blockSize)) { - mm_free_ptr(zeroBuf); - return ErrorOr(kErrorDisk); - } - - mm_free_ptr(zeroBuf); - } - - // Compute indices - UInt32 idxWithin = logicalBlockIndex - doubleStart; - UInt32 firstIdx = idxWithin / blocksPerPointerBlock; - UInt32 secondIdx = idxWithin % blocksPerPointerBlock; - - auto doubleRes = ext2_read_block_ptr(ctx, node->inode.fBlock[EXT2_DOUBLE_INDIRECT_INDEX]); - if (doubleRes.HasError()) return ErrorOr(doubleRes.Error()); - - UInt32* doublePtr = doubleRes.Leak().Leak(); - UInt32 singleIndirectBlock = doublePtr[firstIdx]; - - // Allocate single-indirect if missing - if (singleIndirectBlock == 0) { - auto groupInfoRes = ext2_get_group_descriptor_info(ctx, node->inodeNumber); - if (groupInfoRes.HasError()) { - mm_free_ptr(doublePtr); - return ErrorOr(groupInfoRes.Error()); - } - - auto groupInfo = groupInfoRes.Leak().Leak(); - auto newBlockRes = ext2_alloc_block(ctx, groupInfo->groupDesc); - if (newBlockRes.HasError()) { - mm_free_ptr(doublePtr); - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr(newBlockRes.Error()); - } - - singleIndirectBlock = newBlockRes.Leak(); - doublePtr[firstIdx] = singleIndirectBlock; - - // Write back GDT - UInt32 gdtLba = ext2_block_to_lba(ctx, groupInfo->groupDescriptorBlock); - if (!ext2_write_block(ctx->drive, gdtLba, groupInfo->blockBuffer, blockSize)) { - mm_free_ptr(doublePtr); - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr(kErrorDisk); - } - - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - // Zero single-indirect block - auto zeroBuf = mm_alloc_ptr(blockSize, true, false); - if (!zeroBuf) { - mm_free_ptr(doublePtr); - return ErrorOr(kErrorHeapOutOfMemory); - } - - rt_zero_memory(zeroBuf, blockSize); - UInt32 singleLba = ext2_block_to_lba(ctx, singleIndirectBlock); - if (!ext2_write_block(ctx->drive, singleLba, zeroBuf, blockSize)) { - mm_free_ptr(zeroBuf); - mm_free_ptr(doublePtr); - return ErrorOr(kErrorDisk); - } - - mm_free_ptr(zeroBuf); - - // Write double-indirect back to disk - UInt32 dblLba = ext2_block_to_lba(ctx, node->inode.fBlock[EXT2_DOUBLE_INDIRECT_INDEX]); - if (!ext2_write_block(ctx->drive, dblLba, doublePtr, blockSize)) { - mm_free_ptr(doublePtr); - return ErrorOr(kErrorDisk); - } - } - - mm_free_ptr(doublePtr); - - // Write to single-indirect block - auto singleRes = ext2_read_block_ptr(ctx, singleIndirectBlock); - if (singleRes.HasError()) return ErrorOr(singleRes.Error()); - - UInt32* singlePtr = singleRes.Leak().Leak(); - singlePtr[secondIdx] = physicalBlockNumber; - - UInt32 singleLba = ext2_block_to_lba(ctx, singleIndirectBlock); - if (!ext2_write_block(ctx->drive, singleLba, singlePtr, blockSize)) { - mm_free_ptr(singlePtr); - return ErrorOr(kErrorDisk); - } - - mm_free_ptr(singlePtr); - return ErrorOr(nullptr); - } - - // Triple indirect blocks not implemented - return ErrorOr(kErrorUnimplemented); -} - -// Find a directory entry by name within a directory inode -static ErrorOr ext2_find_dir_entry(Ext2Context* ctx, Ext2Node* dirNode, - const char* name) { - if (!ctx || !ctx->drive || !dirNode || !name) return ErrorOr(kErrorInvalidData); - - // Check directory type - auto type = (dirNode->inode.fMode >> 12) & 0xF; - if (type != kExt2FileTypeDirectory) return ErrorOr(kErrorInvalidData); - - UInt32 blockSize = ctx->BlockSize(); - auto blockBuf = mm_alloc_ptr(blockSize, true, false); - if (!blockBuf) return ErrorOr(kErrorHeapOutOfMemory); - - SizeT nameLen = rt_string_len(name); - for (UInt32 i = 0; i < EXT2_DIRECT_BLOCKS; ++i) { - UInt32 blockNum = dirNode->inode.fBlock[i]; - if (blockNum == 0) continue; - - UInt32 lba = ext2_block_to_lba(ctx, blockNum); - if (!ext2_read_block(ctx->drive, lba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - return ErrorOr(kErrorDisk); - } - - UInt32 offset = 0; - while (offset + sizeof(UInt32) + sizeof(UInt16) <= blockSize) { - auto onDiskEntry = reinterpret_cast((UInt8*) blockBuf + offset); - if (onDiskEntry->fRecordLength == 0) break; // corrupted - - if (onDiskEntry->fInode != 0 && onDiskEntry->fNameLength == nameLen) { - // Compare names - if (rt_string_cmp(name, onDiskEntry->fName, nameLen) == 0) { - // Allocate a result sized to hold the name + metadata - SizeT recSize = sizeof(EXT2_DIR_ENTRY); - auto found = (EXT2_DIR_ENTRY*) mm_alloc_ptr(recSize, true, false); - if (!found) { - mm_free_ptr(blockBuf); - return ErrorOr(kErrorHeapOutOfMemory); - } - - // Copy only record-length bytes - rt_copy_memory_safe(onDiskEntry, found, onDiskEntry->fRecordLength, recSize); - mm_free_ptr(blockBuf); - return ErrorOr(found); - } - } - offset += onDiskEntry->fRecordLength; - } - } - - mm_free_ptr(blockBuf); - return ErrorOr(kErrorFileNotFound); -} - -// Compute ideal record length for a directory name -static inline UInt16 ext2_dir_entry_ideal_len(UInt8 nameLen) { - UInt16 raw = - static_cast(8 + nameLen); // 8 = inode(4)+rec_len(2)+name_len(1)+file_type(1) - return static_cast((raw + 3) & ~3u); // align up to 4 -} - -static ErrorOr ext2_add_dir_entry(Ext2Context* ctx, Ext2Node* parentDirNode, - const char* name, UInt32 inodeNumber, UInt8 fileType) { - using namespace Kernel; - - if (!ctx || !ctx->drive || !parentDirNode || !name) return ErrorOr(kErrorInvalidData); - - UInt32 blockSize = ctx->BlockSize(); - SizeT nameLen = rt_string_len(name); - if (nameLen == 0 || nameLen > 255) return ErrorOr(kErrorInvalidData); - - UInt16 newRecIdeal = ext2_dir_entry_ideal_len(static_cast(nameLen)); - - auto blockBuf = mm_alloc_ptr(blockSize, true, false); - if (!blockBuf) return ErrorOr(kErrorHeapOutOfMemory); - - for (UInt32 bi = 0; bi < EXT2_DIRECT_BLOCKS; ++bi) { - UInt32 blockNum = parentDirNode->inode.fBlock[bi]; - - if (blockNum == 0) { - // Allocate new block - auto groupInfoRes = ext2_get_group_descriptor_info(ctx, parentDirNode->inodeNumber); - if (!groupInfoRes) { - mm_free_ptr(blockBuf); - return ErrorOr(groupInfoRes.Error()); - } - - auto groupInfo = *groupInfoRes.Leak(); // Dereference to get Ext2GroupInfo* - auto allocBlockRes = ext2_alloc_block(ctx, groupInfo->groupDesc); - if (!allocBlockRes) { - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - mm_free_ptr(blockBuf); - return ErrorOr(allocBlockRes.Error()); - } - - UInt32 newBlock = *allocBlockRes.Leak(); // Dereference to get UInt32 - UInt32 gdtLba = ext2_block_to_lba(ctx, groupInfo->groupDescriptorBlock); - - if (!ext2_write_block(ctx->drive, gdtLba, groupInfo->blockBuffer, blockSize)) { - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - mm_free_ptr(blockBuf); - return ErrorOr(kErrorDisk); - } - - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - // Zero block & insert entry - rt_zero_memory(blockBuf, blockSize); - auto entry = reinterpret_cast(blockBuf); - entry->fInode = inodeNumber; - entry->fNameLength = static_cast(nameLen); - entry->fFileType = fileType; - entry->fRecordLength = static_cast(blockSize); - rt_copy_memory_safe(const_cast(name), entry->fName, nameLen, blockSize); - - UInt32 blockLba = ext2_block_to_lba(ctx, newBlock); - if (!ext2_write_block(ctx->drive, blockLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - return ErrorOr(kErrorDisk); - } - - auto setRes = ext2_set_block_address(ctx, parentDirNode, bi, newBlock); - if (!setRes) { - mm_free_ptr(blockBuf); - return ErrorOr(setRes.Error()); - } - - mm_free_ptr(blockBuf); - return ErrorOr(nullptr); - } - - // read it - UInt32 blockLba = ext2_block_to_lba(ctx, blockNum); - if (!ext2_read_block(ctx->drive, blockLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - return ErrorOr(kErrorDisk); - } - - UInt32 offset = 0; - EXT2_DIR_ENTRY* lastEntry = nullptr; - UInt32 lastOffset = 0; - - while (offset < blockSize) { - if (offset + 8 > blockSize) break; - auto e = reinterpret_cast((UInt8*) blockBuf + offset); - if (e->fRecordLength == 0) break; - lastEntry = e; - lastOffset = offset; - offset += e->fRecordLength; - } - - if (!lastEntry) continue; - - UInt16 lastIdeal = ext2_dir_entry_ideal_len(lastEntry->fNameLength); - - if (lastEntry->fRecordLength >= (UInt16) (lastIdeal + newRecIdeal)) { - UInt16 origRec = lastEntry->fRecordLength; - lastEntry->fRecordLength = lastIdeal; - - UInt32 newOffset = lastOffset + lastIdeal; - auto newEntry = reinterpret_cast((UInt8*) blockBuf + newOffset); - newEntry->fInode = inodeNumber; - newEntry->fNameLength = static_cast(nameLen); - newEntry->fFileType = fileType; - newEntry->fRecordLength = static_cast(origRec - lastIdeal); - rt_copy_memory_safe(const_cast(name), newEntry->fName, nameLen, - newEntry->fRecordLength); - - if (!ext2_write_block(ctx->drive, blockLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - return ErrorOr(kErrorDisk); - } - - mm_free_ptr(blockBuf); - return ErrorOr(nullptr); - } - } - - // No space in direct blocks -> allocate new block - int targetIndex = -1; - for (UInt32 i = 0; i < EXT2_DIRECT_BLOCKS; ++i) { - if (parentDirNode->inode.fBlock[i] == 0) { - targetIndex = i; - break; - } - } - if (targetIndex == -1) { - mm_free_ptr(blockBuf); - return ErrorOr(kErrorUnimplemented); - } - - auto groupInfoResult = ext2_get_group_descriptor_info(ctx, parentDirNode->inodeNumber); - if (!groupInfoResult) { - mm_free_ptr(blockBuf); - return ErrorOr(groupInfoResult.Error()); - } - - auto groupInfo = *groupInfoResult.Leak(); // Dereference to get Ext2GroupInfo* - auto newBlockRes = ext2_alloc_block(ctx, groupInfo->groupDesc); - if (!newBlockRes) { - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - mm_free_ptr(blockBuf); - return ErrorOr(newBlockRes.Error()); - } - - UInt32 newBlockNum = *newBlockRes.Leak(); // Dereference to get UInt32 - UInt32 gdtLba = ext2_block_to_lba(ctx, groupInfo->groupDescriptorBlock); - if (!ext2_write_block(ctx->drive, gdtLba, groupInfo->blockBuffer, blockSize)) { - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - mm_free_ptr(blockBuf); - return ErrorOr(kErrorDisk); - } - - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - rt_zero_memory(blockBuf, blockSize); - auto entry = reinterpret_cast(blockBuf); - entry->fInode = inodeNumber; - entry->fNameLength = static_cast(nameLen); - entry->fFileType = fileType; - entry->fRecordLength = static_cast(blockSize); - rt_copy_memory_safe(const_cast(name), entry->fName, nameLen, blockSize); - - UInt32 newBlockLba = ext2_block_to_lba(ctx, newBlockNum); - if (!ext2_write_block(ctx->drive, newBlockLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - return ErrorOr(kErrorDisk); - } - - auto setRes = ext2_set_block_address(ctx, parentDirNode, targetIndex, newBlockNum); - if (!setRes) { - mm_free_ptr(blockBuf); - return ErrorOr(setRes.Error()); - } - - mm_free_ptr(blockBuf); - return ErrorOr(nullptr); -} - -// Soon -static ErrorOr ext2_alloc_inode(Ext2Context* ctx, EXT2_GROUP_DESCRIPTOR* groupDesc) { - if (!ctx || !ctx->superblock || !groupDesc) return ErrorOr(kErrorInvalidData); - - UInt32 blockSize = ctx->BlockSize(); - - // buffer for the inode bitmap - auto bitmap = mm_alloc_ptr(blockSize, true, false); - if (!bitmap) return ErrorOr(kErrorHeapOutOfMemory); - - // Read inode bitmap - if (!ext2_read_block(ctx->drive, groupDesc->fInodeBitmap, bitmap, blockSize)) { - mm_free_ptr(bitmap); - return ErrorOr(kErrorDisk); - } - - // Find first free inode (bit = 0) - for (UInt32 byteIdx = 0; byteIdx < blockSize; ++byteIdx) { - auto byte = reinterpret_cast(bitmap)[byteIdx]; - if (byte != 0xFF) { - for (int bit = 0; bit < 8; ++bit) { - if (!(byte & (1 << bit))) { - // Mark bit as used - reinterpret_cast(bitmap)[byteIdx] |= (1 << bit); - - // Compute inode number - UInt32 inodeNumber = byteIdx * 8 + bit + 1; // Inodes are 1-based - - // Write bitmap back - if (!ext2_write_block(ctx->drive, groupDesc->fInodeBitmap, bitmap, blockSize)) { - mm_free_ptr(bitmap); - return ErrorOr(kErrorDisk); - } - - // Update group descriptor free count - groupDesc->fFreeInodesCount--; - mm_free_ptr(bitmap); - return ErrorOr(inodeNumber); - } - } - } - } - - mm_free_ptr(bitmap); - return ErrorOr(kErrorDiskIsFull); -} - -// to write an inode to its correct location on disk -static ErrorOr ext2_write_inode(Ext2Context* ctx, Ext2Node* node) { - using namespace Kernel; - - if (!ctx || !ctx->superblock || !ctx->drive || !node) return ErrorOr(kErrorInvalidData); - - auto blockSize = ctx->BlockSize(); - UInt32 inodesPerGroup = ctx->superblock->fInodesPerGroup; - - if (inodesPerGroup == 0) return ErrorOr(kErrorInvalidData); - - // Calculate which group this inode belongs to - UInt32 groupIndex = (node->inodeNumber - 1) / inodesPerGroup; - NE_UNUSED(groupIndex); - UInt32 inodeIndexInGroup = (node->inodeNumber - 1) % inodesPerGroup; - - // Get group descriptor - auto groupInfoResult = ext2_get_group_descriptor_info(ctx, node->inodeNumber); - if (!groupInfoResult) return ErrorOr(groupInfoResult.Error()); - - auto groupInfo = *groupInfoResult.Leak(); // Dereference to get Ext2GroupInfo* - - // Calculate inode table position - UInt32 inodeTableBlock = groupInfo->groupDesc->fInodeTable; - UInt32 inodeSize = ctx->superblock->fInodeSize; - UInt32 inodesPerBlock = blockSize / inodeSize; - - UInt32 blockOffset = inodeIndexInGroup / inodesPerBlock; - UInt32 offsetInBlock = (inodeIndexInGroup % inodesPerBlock) * inodeSize; - - UInt32 inodeBlock = inodeTableBlock + blockOffset; - UInt32 inodeLba = ext2_block_to_lba(ctx, inodeBlock); - - // Read the block containing the inode - auto blockBuf = mm_alloc_ptr(blockSize, true, false); - if (!blockBuf) { - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr(kErrorHeapOutOfMemory); - } - - if (!ext2_read_block(ctx->drive, inodeLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr(kErrorDisk); - } - - // Copy the updated inode into the block buffer - rt_copy_memory_safe(&node->inode, static_cast((UInt8*) blockBuf + offsetInBlock), - sizeof(EXT2_INODE), blockSize - offsetInBlock); - - // Write the block back - if (!ext2_write_block(ctx->drive, inodeLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return ErrorOr(kErrorDisk); - } - - mm_free_ptr(blockBuf); - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - return ErrorOr(nullptr); -} - -namespace { -// new -struct PathComponents { - const char** components; - int count; - Char* buffer; - - PathComponents(const char* path) : components(nullptr), count(0), buffer(nullptr) { - if (!path || *path == '\0') return; - - SizeT pathLen = rt_string_len(path); - buffer = (Char*) mm_alloc_ptr(pathLen + 1, true, false); - if (!buffer) return; - - rt_copy_memory_safe((void*) path, buffer, pathLen, pathLen + 1); - buffer[pathLen] = '\0'; - - // temp array - const char** temp = (const char**) mm_alloc_ptr(sizeof(char*) * (pathLen + 1), true, false); - if (!temp) { - mm_free_ptr(buffer); - buffer = nullptr; - return; - } - - UInt32 compCount = 0; - Char* p = buffer; - - while (*p != '\0') { - // skip slashes - while (*p == '/') p++; - if (*p == '\0') break; - - Char* start = p; - while (*p != '/' && *p != '\0') p++; - Char saved = *p; - *p = '\0'; - - // handle ".", "..", or normal - if (rt_string_cmp(start, ".", 1) == 0) { - // ignore - } else if (rt_string_cmp(start, "..", 2) == 0) { - if (compCount > 0) compCount--; // go up one level - } else { - temp[compCount++] = start; - } - - *p = saved; - } - - if (compCount == 0) { - mm_free_ptr(temp); - return; - } - - components = (const char**) mm_alloc_ptr(sizeof(char*) * compCount, true, false); - if (!components) { - mm_free_ptr(temp); - return; - } - - for (UInt32 i = 0; i < compCount; i++) components[i] = temp[i]; - count = compCount; - - mm_free_ptr(temp); - } - - ~PathComponents() { - if (components) mm_free_ptr(components); - if (buffer) mm_free_ptr(buffer); - } -}; -} // anonymous namespace - -// The Ext2FileSystemParser (not manager!) -Ext2FileSystemParser::Ext2FileSystemParser(DriveTrait* drive) : fCtx(drive) { - MUST_PASS(fCtx); -} - -NodePtr Ext2FileSystemParser::Open(const char* path, const char* restrict_type) { - NE_UNUSED(restrict_type); - if (!path || *path == '\0' || !this->fCtx.drive) { - return nullptr; - } - - // Root ("/") - if (rt_string_len(path) == 1 && rt_string_cmp(path, "/", 1) == 0) { - auto inodeResult = ext2_load_inode(&this->fCtx, EXT2_ROOT_INODE); - if (!inodeResult) { - return nullptr; - } - - auto heapNode = (Ext2Node*) mm_alloc_ptr(sizeof(Ext2Node), true, false); - if (!heapNode) return nullptr; - - *heapNode = *inodeResult.Leak().Leak(); - heapNode->cursor = 0; - return reinterpret_cast(heapNode); - } - - PathComponents pathComponents(path); - if (pathComponents.count == 0) { - return nullptr; - } - - UInt32 currentInodeNumber = EXT2_ROOT_INODE; - Ext2Node* currentDirNode = nullptr; - - for (UInt32 i = 0; i < (UInt32) pathComponents.count; ++i) { - auto inodeResult = ext2_load_inode(&this->fCtx, currentInodeNumber); - if (!inodeResult) { - if (currentDirNode) mm_free_ptr(currentDirNode); - return nullptr; - } - - if (currentDirNode) { - mm_free_ptr(currentDirNode); - currentDirNode = nullptr; - } - - currentDirNode = (Ext2Node*) mm_alloc_ptr(sizeof(Ext2Node), true, false); - if (!currentDirNode) { - return nullptr; - } - - *currentDirNode = *inodeResult.Leak().Leak(); - currentDirNode->cursor = 0; - - if (i < pathComponents.count - 1U) { - UInt32 type = (currentDirNode->inode.fMode >> 12) & 0xF; - if (type != kExt2FileTypeDirectory) { - mm_free_ptr(currentDirNode); - return nullptr; - } - } - - auto dirEntryResult = - ext2_find_dir_entry(&this->fCtx, currentDirNode, pathComponents.components[i]); - if (!dirEntryResult) { - mm_free_ptr(currentDirNode); - return nullptr; - } - - EXT2_DIR_ENTRY* entryPtr = *dirEntryResult.Leak(); - currentInodeNumber = entryPtr->fInode; - mm_free_ptr(entryPtr); - } - - auto finalInodeResult = ext2_load_inode(&this->fCtx, currentInodeNumber); - if (!finalInodeResult) { - if (currentDirNode) mm_free_ptr(currentDirNode); - return nullptr; - } - - if (currentDirNode) { - mm_free_ptr(currentDirNode); - } - - auto resultNode = (Ext2Node*) mm_alloc_ptr(sizeof(Ext2Node), true, false); - if (!resultNode) { - return nullptr; - } - - *resultNode = *finalInodeResult.Leak().Leak(); - resultNode->cursor = 0; - return reinterpret_cast(resultNode); -} - -void* Ext2FileSystemParser::Read(NodePtr node, Int32 flags, SizeT size) { - if (!node) return nullptr; - - NE_UNUSED(flags); - - auto extNode = reinterpret_cast(node); - auto dataResult = ext2_read_inode_data(&this->fCtx, extNode, size); - - if (!dataResult) { - return nullptr; // error, nothing to return - } - - void* data = *dataResult.Leak(); - if (data) { - extNode->cursor += static_cast(size); - } - - return data; -} - -void Ext2FileSystemParser::Write(NodePtr node, void* data, Int32 flags, SizeT size) { - if (!node || !data || size == 0) return; - - NE_UNUSED(flags); - - auto extNode = reinterpret_cast(node); - auto blockSize = this->fCtx.BlockSize(); - SizeT bytesWritten = 0; - - UInt32 currentOffset = extNode->cursor; - UInt8* src = reinterpret_cast(data); - - while (bytesWritten < size) { - UInt32 logicalBlockIndex = currentOffset / blockSize; - UInt32 offsetInBlock = currentOffset % blockSize; - - auto physBlockResult = ext2_get_block_address(&this->fCtx, extNode, logicalBlockIndex); - UInt32 physicalBlock = 0; - - if (!physBlockResult) { - auto err = physBlockResult.Error(); - if (err == kErrorInvalidData || err == kErrorUnimplemented) { - auto groupInfoResult = ext2_get_group_descriptor_info(&this->fCtx, extNode->inodeNumber); - if (!groupInfoResult) { - return; - } - - auto groupInfo = *groupInfoResult.Leak(); - auto allocResult = ext2_alloc_block(&this->fCtx, groupInfo->groupDesc); - if (!allocResult) { - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return; - } - - physicalBlock = *allocResult.Leak(); - - auto setRes = - ext2_set_block_address(&this->fCtx, extNode, logicalBlockIndex, physicalBlock); - if (!setRes) { - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return; - } - - UInt32 gdtLba = ext2_block_to_lba(&this->fCtx, groupInfo->groupDescriptorBlock); - if (!ext2_write_block(this->fCtx.drive, gdtLba, groupInfo->blockBuffer, blockSize)) { - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - return; - } - - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - } else { - return; - } - } else { - physicalBlock = physBlockResult.Value(); - } - - UInt32 physicalLba = ext2_block_to_lba(&this->fCtx, physicalBlock); - - auto blockBuf = mm_alloc_ptr(blockSize, true, false); - if (!blockBuf) return; - - if (offsetInBlock > 0 || (size - bytesWritten) < blockSize) { - if (!ext2_read_block(this->fCtx.drive, physicalLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - return; - } - } else { - rt_zero_memory(blockBuf, blockSize); - } - - UInt32 bytesInCurrentBlock = - static_cast(ext2_min(size - bytesWritten, blockSize - offsetInBlock)); - rt_copy_memory_safe(src, static_cast((UInt8*) blockBuf + offsetInBlock), - bytesInCurrentBlock, blockSize - offsetInBlock); - - if (!ext2_write_block(this->fCtx.drive, physicalLba, blockBuf, blockSize)) { - mm_free_ptr(blockBuf); - return; - } - - mm_free_ptr(blockBuf); - - currentOffset += bytesInCurrentBlock; - src += bytesInCurrentBlock; - bytesWritten += bytesInCurrentBlock; - } - - if (currentOffset > extNode->inode.fSize) { - extNode->inode.fSize = currentOffset; - } - - extNode->inode.fBlocks = (extNode->inode.fSize + blockSize - 1) / blockSize; - extNode->inode.fModifyTime = 0; - - auto writeInodeRes = ext2_write_inode(&this->fCtx, extNode); - if (!writeInodeRes) { - // Failed to persist inode - } - - extNode->cursor = currentOffset; -} - -bool Ext2FileSystemParser::Seek(NodePtr node, SizeT offset) { - if (!node) return false; - auto extNode = reinterpret_cast(node); - extNode->cursor = static_cast(offset); - return true; -} - -SizeT Ext2FileSystemParser::Tell(NodePtr node) { - if (!node) return 0; - auto extNode = reinterpret_cast(node); - return extNode->cursor; -} - -bool Ext2FileSystemParser::Rewind(NodePtr node) { - if (!node) return false; - auto extNode = reinterpret_cast(node); - extNode->cursor = 0; - return true; -} - -void* Ext2FileSystemParser::Read(const char* name, NodePtr node, Int32 flags, SizeT size) { - NE_UNUSED(name); - return Read(node, flags, size); -} - -void Ext2FileSystemParser::Write(const char* name, NodePtr node, void* data, Int32 flags, - SizeT size) { - NE_UNUSED(name); - Write(node, data, flags, size); -} - -NodePtr Ext2FileSystemParser::Create(const char* path) { - if (!path || *path == '\0') return nullptr; - - PathComponents pathComponents(path); - if (pathComponents.count == 0) return nullptr; - - const char* filename = pathComponents.components[pathComponents.count - 1]; - if (rt_string_len(filename) > kExt2FSMaxFileNameLen) return nullptr; - - // Build parent path - Char parentPathBuf[256] = {0}; - SizeT currentPathLen = 0; - for (UInt32 i = 0; (i < pathComponents.count - 1U); ++i) { - SizeT componentLen = rt_string_len(pathComponents.components[i]); - if (currentPathLen + componentLen + 1 >= sizeof(parentPathBuf)) return nullptr; - if (i > 0) parentPathBuf[currentPathLen++] = '/'; - rt_copy_memory_safe(const_cast(pathComponents.components[i]), - parentPathBuf + currentPathLen, componentLen, - sizeof(parentPathBuf) - currentPathLen); - currentPathLen += componentLen; - } - parentPathBuf[currentPathLen] = '\0'; - - // Open parent directory - NodePtr parentDirNodePtr = nullptr; - if (currentPathLen == 0) { - // root - auto inodeRes = ext2_load_inode(&this->fCtx, EXT2_ROOT_INODE); - if (!inodeRes) return nullptr; - parentDirNodePtr = mm_alloc_ptr(sizeof(Ext2Node), true, false); - if (!parentDirNodePtr) return nullptr; - *reinterpret_cast(parentDirNodePtr) = *inodeRes.Leak().Leak(); - reinterpret_cast(parentDirNodePtr)->cursor = 0; - } else { - parentDirNodePtr = Open(parentPathBuf, "r"); - } - - if (!parentDirNodePtr) return nullptr; - - auto parentDirNode = reinterpret_cast(parentDirNodePtr); - - // Ensure parent is a directory - UInt32 type = (parentDirNode->inode.fMode >> 12) & 0xF; - if (type != kExt2FileTypeDirectory) { - mm_free_ptr(parentDirNode); - return nullptr; - } - - // Get group info for allocation - auto groupInfoResult = ext2_get_group_descriptor_info(&this->fCtx, parentDirNode->inodeNumber); - if (!groupInfoResult) { - mm_free_ptr(parentDirNode); - return nullptr; - } - auto groupInfo = *groupInfoResult.Leak(); - - // Allocate new inode - auto newInodeRes = ext2_alloc_inode(&this->fCtx, groupInfo->groupDesc); - if (!newInodeRes) { - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); // so this works - mm_free_ptr(parentDirNode); - return nullptr; - } - UInt32 newInodeNumber = newInodeRes.Value(); - - UInt32 gdtLba = ext2_block_to_lba(&this->fCtx, groupInfo->groupDescriptorBlock); - if (!ext2_write_block(this->fCtx.drive, gdtLba, groupInfo->blockBuffer, this->fCtx.BlockSize())) { - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - mm_free_ptr(parentDirNode); - return nullptr; - } - - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - // Create new Ext2Node - Ext2Node* newFileNode = reinterpret_cast(mm_alloc_ptr(sizeof(Ext2Node), true, false)); - if (!newFileNode) { - mm_free_ptr(parentDirNode); - return nullptr; - } - - newFileNode->inodeNumber = newInodeNumber; - rt_zero_memory(&newFileNode->inode, sizeof(EXT2_INODE)); - - newFileNode->inode.fMode = (kExt2FileTypeRegular << 12); - newFileNode->inode.fUID = 0; - newFileNode->inode.fGID = 0; - newFileNode->inode.fLinksCount = 1; - newFileNode->inode.fSize = 0; - newFileNode->inode.fBlocks = 0; - newFileNode->inode.fCreateTime = 0; - newFileNode->inode.fModifyTime = 0; - - // Persist new inode - auto writeInodeRes = ext2_write_inode(&this->fCtx, newFileNode); - if (!writeInodeRes) { - mm_free_ptr(parentDirNode); - mm_free_ptr(newFileNode); - return nullptr; - } - - // Add directory entry - auto addRes = ext2_add_dir_entry(&this->fCtx, parentDirNode, filename, newInodeNumber, - kExt2FileTypeRegular); - if (!addRes) { - mm_free_ptr(parentDirNode); - mm_free_ptr(newFileNode); - return nullptr; - } - - // Update parent inode - auto parentWriteRes = ext2_write_inode(&this->fCtx, parentDirNode); - // ignore failure - - NE_UNUSED(parentWriteRes); - - mm_free_ptr(parentDirNode); - return reinterpret_cast(newFileNode); -} - -NodePtr Ext2FileSystemParser::CreateDirectory(const char* path) { - if (!path || *path == '\0') return nullptr; - - PathComponents pathComponents(path); - if (pathComponents.count == 0) { - kout << "EXT2: Failed to parse path for CreateDirectory.\n"; - return nullptr; - } - - const char* dirname = pathComponents.components[pathComponents.count - 1]; - if (rt_string_len(dirname) > kExt2FSMaxFileNameLen) { - kout << "EXT2: Directory name too long: " << dirname << ".\n"; - return nullptr; - } - - // Build parent path - Char parentPathBuf[256]; - SizeT currentPathLen = 0; - for (UInt32 i = 0; (i < pathComponents.count - 1U); ++i) { - SizeT componentLen = rt_string_len(pathComponents.components[i]); - if (currentPathLen + componentLen + 1 >= sizeof(parentPathBuf)) { - kout << "EXT2: Parent path too long for CreateDirectory.\n"; - return nullptr; - } - - if (i > 0) parentPathBuf[currentPathLen++] = '/'; - - rt_copy_memory_safe(static_cast(const_cast(pathComponents.components[i])), - static_cast(parentPathBuf + currentPathLen), componentLen, - sizeof(parentPathBuf) - currentPathLen); - currentPathLen += componentLen; - } - - parentPathBuf[currentPathLen] = '\0'; - - // Open parent directory node - NodePtr parentDirNodePtr = nullptr; - if (currentPathLen == 0) { - auto inodeRes = ext2_load_inode(&this->fCtx, EXT2_ROOT_INODE); - if (!inodeRes) { - return nullptr; - } - - parentDirNodePtr = reinterpret_cast(mm_alloc_ptr(sizeof(Ext2Node), true, false)); - if (!parentDirNodePtr) return nullptr; - - *reinterpret_cast(parentDirNodePtr) = *inodeRes.Leak().Leak(); - reinterpret_cast(parentDirNodePtr)->cursor = 0; - } else { - parentDirNodePtr = Open(parentPathBuf, "r"); - } - - if (!parentDirNodePtr) { - kout << "EXT2: Failed to open parent directory for CreateDirectory: " << parentPathBuf << ".\n"; - return nullptr; - } - - auto parentDirNode = reinterpret_cast(parentDirNodePtr); - - // Check parent is a directory - UInt32 parentType = (parentDirNode->inode.fMode >> 12) & 0xF; - if (parentType != kExt2FileTypeDirectory) { - kout << "EXT2: Parent is not a directory: " << parentPathBuf << ".\n"; - mm_free_ptr(parentDirNode); - return nullptr; - } - - // Allocate inode - auto groupInfoResult = ext2_get_group_descriptor_info(&this->fCtx, parentDirNode->inodeNumber); - if (!groupInfoResult) { - kout << "EXT2: Failed to get group descriptor info for new dir inode.\n"; - mm_free_ptr(parentDirNode); - return nullptr; - } - - auto groupInfo = *groupInfoResult.Leak(); - auto newInodeRes = ext2_alloc_inode(&this->fCtx, groupInfo->groupDesc); - if (!newInodeRes) { - kout << "EXT2: Failed to allocate inode for new directory.\n"; - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - mm_free_ptr(parentDirNode); - return nullptr; - } - - UInt32 newInodeNumber = *newInodeRes.Leak(); - - // Write back group descriptor block - UInt32 gdtLba = ext2_block_to_lba(&this->fCtx, groupInfo->groupDescriptorBlock); - if (!ext2_write_block(this->fCtx.drive, gdtLba, groupInfo->blockBuffer, this->fCtx.BlockSize())) { - kout << "EXT2: Failed to write group descriptor after inode allocation.\n"; - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - mm_free_ptr(parentDirNode); - return nullptr; - } - - mm_free_ptr(reinterpret_cast(groupInfo->blockBuffer)); - mm_free_ptr(groupInfo); - - // Create new Ext2Node and initialize inode fields - Ext2Node* newDirNode = reinterpret_cast(mm_alloc_ptr(sizeof(Ext2Node), true, false)); - if (!newDirNode) { - kout << "EXT2: Out of memory for new directory node.\n"; - mm_free_ptr(parentDirNode); - return nullptr; - } - - newDirNode->inodeNumber = newInodeNumber; - rt_zero_memory(&newDirNode->inode, sizeof(EXT2_INODE)); - newDirNode->inode.fMode = (kExt2FileTypeDirectory << 12); - newDirNode->inode.fUID = 0; - newDirNode->inode.fGID = 0; - newDirNode->inode.fLinksCount = 2; // . and .. - newDirNode->inode.fSize = this->fCtx.BlockSize(); - newDirNode->inode.fBlocks = 1; - newDirNode->inode.fCreateTime = 0; - newDirNode->inode.fModifyTime = 0; - - // Allocate a data block for the new directory - auto groupForBlockRes = ext2_get_group_descriptor_info(&this->fCtx, newDirNode->inodeNumber); - if (!groupForBlockRes) { - kout << "EXT2: Failed to get group info for directory block allocation.\n"; - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - auto groupForBlock = *groupForBlockRes.Leak(); - auto newBlockRes = ext2_alloc_block(&this->fCtx, groupForBlock->groupDesc); - if (!newBlockRes) { - kout << "EXT2: Failed to allocate block for new directory contents.\n"; - mm_free_ptr(reinterpret_cast(groupForBlock->blockBuffer)); - mm_free_ptr(groupForBlock); - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - UInt32 newDirBlockNum = *newBlockRes.Leak(); - - // Write back GDT - UInt32 gdtLba2 = ext2_block_to_lba(&this->fCtx, groupForBlock->groupDescriptorBlock); - if (!ext2_write_block(this->fCtx.drive, gdtLba2, groupForBlock->blockBuffer, - this->fCtx.BlockSize())) { - kout << "EXT2: Failed to write GDT after directory block allocation.\n"; - mm_free_ptr(reinterpret_cast(groupForBlock->blockBuffer)); - mm_free_ptr(groupForBlock); - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - mm_free_ptr(reinterpret_cast(groupForBlock->blockBuffer)); - mm_free_ptr(groupForBlock); - - // Set the block in newDirNode - auto setBlkRes = ext2_set_block_address(&this->fCtx, newDirNode, 0, newDirBlockNum); - if (!setBlkRes) { - kout << "EXT2: Failed to set data block for new directory.\n"; - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - // Prepare block with '.' and '..' - auto dirBlockBuf = mm_alloc_ptr(this->fCtx.BlockSize(), true, false); - if (!dirBlockBuf) { - kout << "EXT2: Out of memory preparing directory block.\n"; - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - rt_zero_memory(dirBlockBuf, this->fCtx.BlockSize()); - - // '.' entry - auto dot = reinterpret_cast(dirBlockBuf); - dot->fInode = newInodeNumber; - dot->fNameLength = 1; - dot->fFileType = kExt2FileTypeDirectory; - dot->fRecordLength = ext2_dir_entry_ideal_len(dot->fNameLength); - dot->fName[0] = '.'; - - // '..' entry occupies rest of block - auto dotdot = reinterpret_cast((UInt8*) dirBlockBuf + dot->fRecordLength); - dotdot->fInode = parentDirNode->inodeNumber; - dotdot->fNameLength = 2; - dotdot->fFileType = kExt2FileTypeDirectory; - dotdot->fRecordLength = static_cast(this->fCtx.BlockSize() - dot->fRecordLength); - dotdot->fName[0] = '.'; - dotdot->fName[1] = '.'; - - // Write dir block to disk - UInt32 newDirBlockLba = ext2_block_to_lba(&this->fCtx, newDirBlockNum); - if (!ext2_write_block(this->fCtx.drive, newDirBlockLba, dirBlockBuf, this->fCtx.BlockSize())) { - kout << "EXT2: Failed to write directory block to disk.\n"; - mm_free_ptr(dirBlockBuf); - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - mm_free_ptr(dirBlockBuf); - - // Persist new directory inode - auto writeInodeRes = ext2_write_inode(&this->fCtx, newDirNode); - if (!writeInodeRes) { - kout << "EXT2: Failed to write new directory inode to disk.\n"; - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - // Add directory entry into parent - auto addRes = ext2_add_dir_entry(&this->fCtx, parentDirNode, dirname, newInodeNumber, - kExt2FileTypeDirectory); - if (!addRes) { - kout << "EXT2: Failed to add directory entry for '" << dirname << "' to parent.\n"; - mm_free_ptr(parentDirNode); - mm_free_ptr(newDirNode); - return nullptr; - } - - // Increment parent link count and persist parent inode - parentDirNode->inode.fLinksCount += 1; - auto parentWriteRes = ext2_write_inode(&this->fCtx, parentDirNode); - if (!parentWriteRes) { - kout << "EXT2: Warning: failed to update parent inode after directory creation.\n"; - } - - mm_free_ptr(parentDirNode); - return reinterpret_cast(newDirNode); -} - -#endif -#endif diff --git a/dev/kernel/src/FS/NeFS+FileMgr.cc b/dev/kernel/src/FS/NeFS+FileMgr.cc deleted file mode 100644 index 0fdabd6f..00000000 --- a/dev/kernel/src/FS/NeFS+FileMgr.cc +++ /dev/null @@ -1,276 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#ifndef __NE_MINIMAL_OS__ -#ifdef __FSKIT_INCLUDES_NEFS__ - -#include -#include - -/// @brief NeFS File System Manager. -/// BUGS: 0 - -namespace Kernel { -static inline bool is_valid_nefs_catalog(NodePtr node); - -/// @brief C++ constructor -NeFileSystemMgr::NeFileSystemMgr() { - mParser = new NeFileSystemParser(); - MUST_PASS(mParser); - - kout << "We are done allocating NeFileSystemParser...\n"; -} - -NeFileSystemMgr::~NeFileSystemMgr() { - if (mParser) { - kout << "Destroying NeFileSystemParser...\n"; - delete mParser; - mParser = nullptr; - } -} - -/// @brief Removes a node from the filesystem. -/// @param path The filename -/// @return If it was deleted or not. -bool NeFileSystemMgr::Remove(_Input const Char* path) { - if (path == nullptr || *path == 0) { - kout << "NeFS: Remove called with null or empty path\n"; - return false; - } - return mParser->RemoveCatalog(path); -} - -/// @brief Creates a node with the specified. -/// @param path The filename path. -/// @return The Node pointer. -NodePtr NeFileSystemMgr::Create(_Input const Char* path) { - if (!path || *path == 0) { - kout << "NeFS: Create called with null or empty path\n"; - return nullptr; - } - return rtl_node_cast(mParser->CreateCatalog(path)); -} - -/// @brief Creates a node which is a directory. -/// @param path The filename path. -/// @return The Node pointer. -NodePtr NeFileSystemMgr::CreateDirectory(const Char* path) { - if (!path || *path == 0) { - kout << "NeFS: CreateDirectory called with null or empty path\n"; - return nullptr; - } - return rtl_node_cast(mParser->CreateCatalog(path, 0, kNeFSCatalogKindDir)); -} - -/// @brief Creates a node which is an alias. -/// @param path The filename path. -/// @return The Node pointer. -NodePtr NeFileSystemMgr::CreateAlias(const Char* path) { - if (!path || *path == 0) { - kout << "NeFS: CreateAlias called with null or empty path\n"; - return nullptr; - } - return rtl_node_cast(mParser->CreateCatalog(path, 0, kNeFSCatalogKindAlias)); -} - -NodePtr NeFileSystemMgr::CreateSwapFile(const Char* path) { - if (!path || *path == 0) { - kout << "NeFS: CreateSwapFile called with null or empty path\n"; - return nullptr; - } - return rtl_node_cast(mParser->CreateCatalog(path, 0, kNeFSCatalogKindPage)); -} - -/// @brief Gets the root directory. -/// @return -const Char* NeFileSystemHelper::Root() { - return kNeFSRoot; -} - -/// @brief Gets the up-dir directory. -/// @return -const Char* NeFileSystemHelper::UpDir() { - return kNeFSUpDir; -} - -/// @brief Gets the separator character. -/// @return -Char NeFileSystemHelper::Separator() { - return kNeFSSeparator; -} - -/// @brief Gets the metafile character. -/// @return -Char NeFileSystemHelper::MetaFile() { - return kNeFSMetaFilePrefix; -} - -/// @brief Opens a new file. -/// @param path -/// @param r -/// @return -_Output NodePtr NeFileSystemMgr::Open(_Input const Char* path, _Input const Char* r) { - if (!path || *path == 0) { - kout << "NeFS: Open called with null or empty path\n"; - return nullptr; - } - if (!r || *r == 0) { - kout << "NeFS: Open called with null or empty mode string\n"; - return nullptr; - } - auto catalog = mParser->GetCatalog(path); - if (!catalog) { - kout << "NeFS: Open could not find catalog for path\n"; - return nullptr; - } - return rtl_node_cast(catalog); -} - -Void NeFileSystemMgr::Write(_Input NodePtr node, _Input VoidPtr data, _Input Int32 flags, - _Input SizeT size) { - if (!is_valid_nefs_catalog(node)) { - kout << "NeFS: Write called with invalid node pointer\n"; - return; - } - if (!data) { - kout << "NeFS: Write called with null data pointer\n"; - return; - } - if (!size || size > kNeFSForkSize) { - (Void)(kout << "NeFS: Write called with invalid size: " << hex_number(size)); - kout << "\n"; - return; - } - constexpr auto kDataForkName = kNeFSDataFork; - this->Write(kDataForkName, node, data, flags, size); -} - -_Output VoidPtr NeFileSystemMgr::Read(_Input NodePtr node, _Input Int32 flags, _Input SizeT size) { - if (!is_valid_nefs_catalog(node)) { - kout << "NeFS: Read called with invalid node pointer\n"; - return nullptr; - } - if (!size || size > kNeFSForkSize) { - (Void)(kout << "NeFS: Write called with invalid size: " << hex_number(size)); - kout << "\n"; - return nullptr; - } - constexpr auto kDataForkName = kNeFSDataFork; - return this->Read(kDataForkName, node, flags, size); -} - -Void NeFileSystemMgr::Write(_Input const Char* name, _Input NodePtr node, _Input VoidPtr data, - _Input Int32 flags, _Input SizeT size) { - if (!is_valid_nefs_catalog(node)) { - kout << "NeFS: Write(fork) called with invalid node pointer\n"; - return; - } - if (!name || *name == 0) { - kout << "NeFS: Write(fork) called with null or empty fork name\n"; - return; - } - if (!data) { - kout << "NeFS: Write(fork) called with null data pointer\n"; - return; - } - if (!size || size > kNeFSForkSize) { - (Void)(kout << "NeFS: Write called with invalid size: " << hex_number(size)); - kout << "\n"; - return; - } - NE_UNUSED(flags); - auto cat = reinterpret_cast(node); - if (cat->Kind == kNeFSCatalogKindFile) { - mParser->WriteCatalog(cat->Name, (flags & kFileFlagRsrc ? true : false), data, size, name); - } -} - -_Output VoidPtr NeFileSystemMgr::Read(_Input const Char* name, _Input NodePtr node, - _Input Int32 flags, _Input SizeT sz) { - if (!is_valid_nefs_catalog(node)) { - kout << "NeFS: Read(fork) called with invalid node pointer\n"; - return nullptr; - } - if (!name || *name == 0) { - kout << "NeFS: Read(fork) called with null or empty fork name\n"; - return nullptr; - } - if (!sz || sz > kNeFSForkSize) { - (Void)(kout << "NeFS: Write called with invalid size: " << hex_number(sz)); - kout << "\n"; - return nullptr; - } - NE_UNUSED(flags); - auto cat = reinterpret_cast(node); - if (cat->Kind == kNeFSCatalogKindFile) { - return mParser->ReadCatalog(cat, (flags & kFileFlagRsrc ? true : false), sz, name); - } - return nullptr; -} - -_Output Bool NeFileSystemMgr::Seek(NodePtr node, SizeT off) { - if (!is_valid_nefs_catalog(node)) { - kout << "NeFS: Seek called with invalid node pointer\n"; - return false; - } - // Allow off == 0 - return mParser->Seek(reinterpret_cast(node), off); -} - -/// @brief Tell current offset within catalog. -/// @param node -/// @return kFileMgrNPos if invalid, else current offset. -_Output SizeT NeFileSystemMgr::Tell(NodePtr node) { - if (!is_valid_nefs_catalog(node)) { - kout << "NeFS: Tell called with invalid node pointer\n"; - return kFileMgrNPos; - } - return mParser->Tell(reinterpret_cast(node)); -} - -/// @brief Rewinds the catalog -/// @param node -/// @return False if invalid, nah? calls Seek(node, 0). -_Output Bool NeFileSystemMgr::Rewind(NodePtr node) { - if (!is_valid_nefs_catalog(node)) { - kout << "NeFS: Rewind called with invalid node pointer\n"; - return false; - } - return this->Seek(node, 0); -} - -/// @brief Returns the parser of NeFS. -_Output NeFileSystemParser* NeFileSystemMgr::GetParser() noexcept { - return mParser; -} - -static inline bool is_valid_nefs_catalog(NodePtr node) { - if (!node) return false; - auto cat = reinterpret_cast(node); - switch (cat->Kind) { - case kNeFSCatalogKindFile: - case kNeFSCatalogKindDir: - case kNeFSCatalogKindAlias: - case kNeFSCatalogKindPage: - break; - default: - return false; - } - bool null_found = false; - for (int i = 0; i < kNeFSCatalogNameLen; ++i) { - if (cat->Name[i] == 0) { - null_found = true; - break; - } - } - if (!null_found) return false; - return true; -} - -} // namespace Kernel - -#endif // ifdef __FSKIT_INCLUDES_NEFS__ -#endif // ifndef __NE_MINIMAL_OS__ diff --git a/dev/kernel/src/FS/NeFS+FileSystemParser.cc b/dev/kernel/src/FS/NeFS+FileSystemParser.cc deleted file mode 100644 index bfb8d63a..00000000 --- a/dev/kernel/src/FS/NeFS+FileSystemParser.cc +++ /dev/null @@ -1,870 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#ifdef __FSKIT_INCLUDES_NEFS__ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace Kernel; - -#ifdef __NE_NO_BUILTIN__ -/***********************************************************************************/ -/** - Define those external symbols, to make the editor shutup -*/ -/***********************************************************************************/ - -/***********************************************************************************/ -/// @brief get sector count. -/***********************************************************************************/ -Kernel::SizeT drv_std_get_sector_count(); - -/***********************************************************************************/ -/// @brief get device size. -/***********************************************************************************/ -Kernel::SizeT drv_std_get_size(); - -#endif - -///! BUGS: 0 - -/***********************************************************************************/ -/// This file implements the New extended File System. -/// New extended File System implements a flat linked-list based algorithm. -/// / -/// /Path1/ /Path2/ -/// /readme.rtf /ListContents.pef /readme.lnk <-- symlink. -/// /Path1/readme.rtf -/***********************************************************************************/ -static inline bool is_valid_size(SizeT size, SizeT max_size) { - return size > 0 && size <= max_size; -} - -static inline bool is_valid_lba(Lba lba, DriveTrait& drive) { - NEFS_ROOT_PARTITION_BLOCK part_block; - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fPacket.fPacketContent = reinterpret_cast(&part_block); - drive.fInput(drive.fPacket); - - if (!drive.fPacket.fPacketGood) { - return false; - } - - // Compute the maximum LBA (DiskSize / sector size) - SizeT sectorSize = drive.fSectorSz; - Lba maxLba = part_block.DiskSize / sectorSize; - - return (lba >= part_block.StartCatalog) && (lba < maxLba); -} - -STATIC IMountpoint kMountpoint; -/***********************************************************************************/ -/// @brief Creates a new fork inside the New filesystem partition. -/// @param catalog it's catalog -/// @param the_fork the fork itself. -/// @return the fork -/***********************************************************************************/ -_Output BOOL NeFileSystemParser::CreateFork(_Input NEFS_FORK_STRUCT& the_fork) { - if (the_fork.ForkName[0] == 0 || the_fork.CatalogName[0] == 0 || the_fork.DataSize == 0) { - return NO; - } - - auto catalog = this->GetCatalog(the_fork.CatalogName); - if (!catalog) return NO; - - Lba lba = catalog->DataFork; - if (lba < kNeFSCatalogStartAddress) { - delete catalog; - return NO; - } - - auto& drv = kMountpoint.A(); - Lba lba_prev = lba; - NEFS_FORK_STRUCT prev_fork{}; - NEFS_FORK_STRUCT cur_fork{}; - - while (true) { - drv.fPacket.fPacketLba = lba; - drv.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT); - drv.fPacket.fPacketContent = reinterpret_cast(&cur_fork); - drv.fInput(drv.fPacket); - if (!drv.fPacket.fPacketGood) { - delete catalog; - return NO; - } - - if (cur_fork.Flags & kNeFSFlagCreated) { - if (KStringBuilder::Equals(cur_fork.ForkName, the_fork.ForkName) && - KStringBuilder::Equals(cur_fork.CatalogName, the_fork.CatalogName)) { - break; - } - lba_prev = lba; - lba = cur_fork.NextSibling; - prev_fork = cur_fork; - } else { - if (lba >= kNeFSCatalogStartAddress) { - prev_fork.NextSibling = lba; - drv.fPacket.fPacketLba = lba_prev; - drv.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT); - drv.fPacket.fPacketContent = reinterpret_cast(&prev_fork); - drv.fOutput(drv.fPacket); - } - break; - } - } - - SizeT sectorCount = (the_fork.DataSize + kNeFSSectorSz - 1) / kNeFSSectorSz; - the_fork.DataOffset = lba + 1; - the_fork.PreviousSibling = lba_prev; - the_fork.NextSibling = lba + 1 + sectorCount; - the_fork.Flags |= kNeFSFlagCreated; - - drv.fPacket.fPacketLba = lba; - drv.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT); - drv.fPacket.fPacketContent = reinterpret_cast(&the_fork); - drv.fOutput(drv.fPacket); - - fs_ifs_write(&kMountpoint, drv, IMountpoint::kDriveIndexA); - - delete catalog; - return YES; -} - -/***********************************************************************************/ -/// @brief Find fork inside filesystem. -/// @param catalog the catalog. -/// @param name the fork name. -/// @return the newly found fork. -/***********************************************************************************/ -_Output NEFS_FORK_STRUCT* NeFileSystemParser::FindFork(_Input NEFS_CATALOG_STRUCT* catalog, - _Input const Char* name, - _Input Boolean is_data) { - if (!catalog || !name) return nullptr; - - auto& drive = kMountpoint.A(); - Lba lba = is_data ? catalog->DataFork : catalog->ResourceFork; - NEFS_FORK_STRUCT local_buf{}; - - while (lba >= kNeFSCatalogStartAddress) { - drive.fPacket.fPacketLba = lba; - drive.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT); - drive.fPacket.fPacketContent = reinterpret_cast(&local_buf); - - rt_copy_memory_safe((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime, - rt_string_len("fs/nefs-packet"), sizeof(drive.fPacket.fPacketMime)); - - if (auto res = fs_ifs_read(&kMountpoint, drive, this->mDriveIndex); res) { - switch (res) { - case 1: - err_global_get() = kErrorDiskReadOnly; - break; - case 2: - err_global_get() = kErrorDiskIsFull; - break; - case 3: - err_global_get() = kErrorNoSuchDisk; - break; - default: - break; - } - return nullptr; - } - - if (KStringBuilder::Equals(local_buf.ForkName, name) && - KStringBuilder::Equals(local_buf.CatalogName, catalog->Name)) { - auto result = new NEFS_FORK_STRUCT(); - rt_copy_memory_safe(&local_buf, result, sizeof(NEFS_FORK_STRUCT), sizeof(NEFS_FORK_STRUCT)); - return result; - } - - lba = local_buf.NextSibling; - } - - return nullptr; -} - -/***********************************************************************************/ -/// @brief Simpler factory to create a catalog (assumes you want to create a -/// file.) -/// @param name -/// @return catalog pointer. -/***********************************************************************************/ -_Output NEFS_CATALOG_STRUCT* NeFileSystemParser::CreateCatalog(_Input const Char* name) { - return this->CreateCatalog(name, 0, kNeFSCatalogKindFile); -} - -/***********************************************************************************/ -/// @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 NEFS_CATALOG_STRUCT* NeFileSystemParser::CreateCatalog(_Input const Char* name, - _Input const Int32& flags, - _Input const Int32& kind) { - kout << "CreateCatalog(*...*)\r"; - - if (!name) return nullptr; - SizeT nameLen = rt_string_len(name); - if (nameLen == 0) return nullptr; - - Lba out_lba = 0UL; - - kout << "Checking for path separator...\r"; - - /// a directory should have a slash in the end. - if (kind == kNeFSCatalogKindDir && name[nameLen - 1] != NeFileSystemHelper::Separator()) - return nullptr; - - /// a file shouldn't have a slash in the end. - if (kind != kNeFSCatalogKindDir && name[nameLen - 1] == NeFileSystemHelper::Separator()) - return nullptr; - - NEFS_CATALOG_STRUCT* catalog_copy = this->FindCatalog(name, out_lba); - - if (catalog_copy) { - kout << "Catalog already exists: " << name << ".\r"; - err_global_get() = kErrorFileExists; - delete catalog_copy; - catalog_copy = nullptr; - return nullptr; - } - - Char* parent_name = (Char*) mm_alloc_ptr(nameLen + 1, Yes, No); - rt_copy_memory_safe(const_cast(name), parent_name, nameLen + 1, nameLen + 1); - - if (nameLen < 2) { - mm_free_ptr(parent_name); - err_global_get() = kErrorFileNotFound; - return nullptr; - } - - SizeT index_reverse_copy = nameLen - 1; - if (parent_name[index_reverse_copy] == NeFileSystemHelper::Separator()) { - parent_name[index_reverse_copy] = 0; - --index_reverse_copy; - } - while (index_reverse_copy > 0 && - parent_name[index_reverse_copy] != NeFileSystemHelper::Separator()) { - parent_name[index_reverse_copy] = 0; - --index_reverse_copy; - } - if (index_reverse_copy == 0 && parent_name[0] != NeFileSystemHelper::Separator()) { - mm_free_ptr(parent_name); - err_global_get() = kErrorFileNotFound; - return nullptr; - } - - NEFS_CATALOG_STRUCT* catalog = this->FindCatalog(parent_name, out_lba); - mm_free_ptr(parent_name); - - auto& drive = kMountpoint.A(); - if (catalog && catalog->Kind == kNeFSCatalogKindFile) { - kout << "Parent is a file.\r"; - delete catalog; - return nullptr; - } else if (!catalog) { - Char part_block[sizeof(NEFS_ROOT_PARTITION_BLOCK)] = {0}; - drive.fPacket.fPacketContent = reinterpret_cast(part_block); - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fInput(drive.fPacket); - - NEFS_ROOT_PARTITION_BLOCK* blk_nefs = (NEFS_ROOT_PARTITION_BLOCK*) part_block; - out_lba = blk_nefs->StartCatalog; - } - - if (drive.fPacket.fPacketReadOnly) { - delete catalog; - return nullptr; - } - - NEFS_CATALOG_STRUCT* child_catalog = new NEFS_CATALOG_STRUCT(); - child_catalog->Checksum = 0; - child_catalog->ResourceForkSize = 0UL; - child_catalog->DataForkSize = 0UL; - child_catalog->CatalogFlags = kNeFSStatusUnlocked; - child_catalog->NextSibling = out_lba; - child_catalog->PrevSibling = out_lba; - child_catalog->Kind = kind; - child_catalog->Flags |= kNeFSFlagCreated; - child_catalog->CatalogFlags = flags; - - SizeT i = nameLen; - --i; - if (kind == kNeFSCatalogKindDir) --i; - while (name[i] != '/') --i; - rt_copy_memory_safe((VoidPtr) (name + i), (VoidPtr) child_catalog->Name, rt_string_len(name) - i, - kNeFSCatalogNameLen); - - NEFS_CATALOG_STRUCT temporary_catalog{}; - Lba start_free = out_lba; - - rt_copy_memory_safe((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime, - rt_string_len("fs/nefs-packet"), sizeof(drive.fPacket.fPacketMime)); - - Char buf_part_block[sizeof(NEFS_ROOT_PARTITION_BLOCK)] = {0}; - drive.fPacket.fPacketContent = reinterpret_cast(buf_part_block); - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fInput(drive.fPacket); - - NEFS_ROOT_PARTITION_BLOCK* part_block = (NEFS_ROOT_PARTITION_BLOCK*) buf_part_block; - drive.fPacket.fPacketContent = reinterpret_cast(&temporary_catalog); - drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT); - drive.fPacket.fPacketLba = start_free; - drive.fInput(drive.fPacket); - - if (part_block->FreeCatalog < 1) { - delete child_catalog; - delete catalog; - return nullptr; - } - - kout << "Start finding catalog to allocate or empty space...\r"; - - SizeT catalogSectors = (sizeof(NEFS_CATALOG_STRUCT) + drive.fSectorSz - 1) / drive.fSectorSz; - while (start_free < part_block->StartCatalog + (part_block->CatalogCount * catalogSectors)) { - drive.fPacket.fPacketContent = reinterpret_cast(&temporary_catalog); - drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT); - drive.fPacket.fPacketLba = start_free; - drive.fInput(drive.fPacket); - - if ((temporary_catalog.Flags & kNeFSFlagCreated) == 0) { - child_catalog->NextSibling = start_free + catalogSectors; - - NEFS_CATALOG_STRUCT placeholder{}; - drive.fPacket.fPacketContent = reinterpret_cast(&placeholder); - drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT); - drive.fPacket.fPacketLba = start_free; - drive.fOutput(drive.fPacket); - - child_catalog->DataFork = part_block->DiskSize - start_free; - child_catalog->ResourceFork = child_catalog->DataFork; - - drive.fPacket.fPacketContent = reinterpret_cast(child_catalog); - drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT); - drive.fPacket.fPacketLba = start_free; - drive.fOutput(drive.fPacket); - - drive.fPacket.fPacketContent = reinterpret_cast(buf_part_block); - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fInput(drive.fPacket); - - part_block->FreeSectors -= catalogSectors; - part_block->CatalogCount += 1; - part_block->FreeCatalog -= 1; - - drive.fPacket.fPacketContent = reinterpret_cast(part_block); - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fOutput(drive.fPacket); - - delete catalog; - NEFS_CATALOG_STRUCT* found_catalog = new NEFS_CATALOG_STRUCT(); - rt_copy_memory_safe(&temporary_catalog, found_catalog, sizeof(NEFS_CATALOG_STRUCT), - sizeof(NEFS_CATALOG_STRUCT)); - - delete child_catalog; - return found_catalog; - } else if ((temporary_catalog.Flags & kNeFSFlagCreated) && - KStringBuilder::Equals(temporary_catalog.Name, name)) { - rt_copy_memory_safe(&temporary_catalog, child_catalog, sizeof(NEFS_CATALOG_STRUCT), - sizeof(NEFS_CATALOG_STRUCT)); - delete catalog; - return child_catalog; - } - - start_free += catalogSectors; - } - - delete child_catalog; - delete catalog; - return nullptr; -} - -/***********************************************************************************/ -/// @brief Make a EPM+NeFS drive out of the disk. -/// @param drive The drive to write on. -/// @return If it was sucessful, see err_global_get(). -/***********************************************************************************/ -bool NeFileSystemParser::Format(_Input _Output DriveTrait* drive, _Input const Int32 flags, - const Char* part_name) { - if (!part_name || *part_name == 0) return false; - NE_UNUSED(flags); - - // verify disk. - drive->fVerify(drive->fPacket); - rt_copy_memory_safe((VoidPtr) "fs/nefs-packet", drive->fPacket.fPacketMime, - rt_string_len("fs/nefs-packet"), sizeof(drive->fPacket.fPacketMime)); - if (!drive->fPacket.fPacketGood) { - err_global_get() = kErrorDiskIsCorrupted; - return false; - } - - Char fs_buf[sizeof(NEFS_ROOT_PARTITION_BLOCK)] = {0}; - Lba start = drive->fLbaStart; - - drive->fPacket.fPacketContent = reinterpret_cast(fs_buf); - drive->fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive->fPacket.fPacketLba = start; - drive->fInput(drive->fPacket); - - NEFS_ROOT_PARTITION_BLOCK* part_block = (NEFS_ROOT_PARTITION_BLOCK*) fs_buf; - if (rt_string_cmp(kNeFSIdent, part_block->Ident, kNeFSIdentLen) == 0) return true; - - const auto kNeFSUntitledHD = part_name; - rt_copy_memory_safe((VoidPtr) kNeFSIdent, (VoidPtr) part_block->Ident, kNeFSIdentLen, - sizeof(part_block->Ident)); - rt_copy_memory_safe((VoidPtr) kNeFSUntitledHD, (VoidPtr) part_block->PartitionName, - rt_string_len(kNeFSUntitledHD), sizeof(part_block->PartitionName)); - - SizeT sectorCount = drv_std_get_sector_count(); - SizeT sectorSize = drive->fSectorSz; - SizeT totalBytes = sectorCount * sectorSize; - SizeT catalogEntries = totalBytes / sizeof(NEFS_CATALOG_STRUCT); - SizeT catalogSectors = (sizeof(NEFS_CATALOG_STRUCT) + sectorSize - 1) / sectorSize; - - part_block->Version = kNeFSVersionInteger; - part_block->Kind = kNeFSPartitionTypeStandard; - part_block->StartCatalog = start + catalogSectors; - part_block->Flags = 0UL; - part_block->CatalogCount = catalogEntries; - part_block->FreeCatalog = catalogEntries - 1; - part_block->SectorCount = sectorCount; - part_block->DiskSize = totalBytes; - part_block->SectorSize = sectorSize; - part_block->FreeSectors = sectorCount - catalogSectors; - - drive->fPacket.fPacketContent = reinterpret_cast(fs_buf); - drive->fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive->fPacket.fPacketLba = start; - drive->fOutput(drive->fPacket); - - (Void)(kout << "Drive kind: " << drive->fProtocol() << kendl); - (Void)(kout << "Partition name: " << part_block->PartitionName << kendl); - (Void)(kout << "Start catalog: " << hex_number(part_block->StartCatalog) << kendl); - (Void)(kout << "Number of catalogs: " << hex_number(part_block->CatalogCount) << kendl); - (Void)(kout << "Free catalog: " << hex_number(part_block->FreeCatalog) << kendl); - (Void)(kout << "Free sectors: " << hex_number(part_block->FreeSectors) << kendl); - (Void)(kout << "Sector size: " << hex_number(part_block->SectorSize) << kendl); - - return true; -} - -/***********************************************************************************/ -/// @brief Writes the data fork into a specific catalog. -/// @param catalog the catalog itself -/// @param data the data. -/// @return if the catalog wrote the contents successfully. -/***********************************************************************************/ -bool NeFileSystemParser::WriteCatalog(_Input const Char* catalog_name, Bool is_rsrc_fork, - _Input VoidPtr data, _Input SizeT size_of_data, - _Input const Char* fork_name) { - if (size_of_data < 1) return NO; - - auto catalog = this->GetCatalog(catalog_name); - if (!catalog) { - kout << "NeFS: WriteCatalog failed to find catalog: " << catalog_name << "\n"; - return false; - } - - SizeT maxSize = is_rsrc_fork ? catalog->ResourceForkSize : catalog->DataForkSize; - - if (!is_valid_size(size_of_data, maxSize)) { - (Void)(kout << "NeFS: WriteCatalog called with invalid size: " << hex_number(size_of_data)); - kout << "\n"; - - delete catalog; - return false; - } - - Lba startFork = is_rsrc_fork ? catalog->ResourceFork : catalog->DataFork; - auto& drive = kMountpoint.A(); - - if (!is_valid_lba(startFork, drive)) { - (Void)(kout << "NeFS: WriteCatalog called with invalid LBA: " << hex_number(startFork)); - kout << "\n"; - - delete catalog; - return false; - } - - NEFS_ROOT_PARTITION_BLOCK part_block; - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fPacket.fPacketSize = sizeof(part_block); - drive.fPacket.fPacketContent = reinterpret_cast(&part_block); - drive.fInput(drive.fPacket); - - auto buf = new UInt8[size_of_data]; - rt_set_memory(buf, 0, size_of_data); - rt_copy_memory_safe(data, buf, size_of_data, size_of_data); - rt_copy_memory_safe((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime, - rt_string_len("fs/nefs-packet"), sizeof(drive.fPacket.fPacketMime)); - - NEFS_FORK_STRUCT* fork_data_input = new NEFS_FORK_STRUCT(); - NEFS_FORK_STRUCT prev_fork{}; - - while (startFork >= part_block.StartCatalog && drive.fPacket.fPacketGood) { - drive.fPacket.fPacketContent = reinterpret_cast(fork_data_input); - drive.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT); - drive.fPacket.fPacketLba = startFork; - drive.fInput(drive.fPacket); - - if (!drive.fPacket.fPacketGood) { - break; - } - - if ((fork_data_input->Flags & kNeFSFlagCreated) && - KStringBuilder::Equals(fork_data_input->ForkName, fork_name) && - KStringBuilder::Equals(fork_data_input->CatalogName, catalog_name) && - fork_data_input->DataSize == size_of_data) { - SizeT bytes_left = size_of_data; - SizeT offset = 0; - Lba base_lba = fork_data_input->DataOffset; - - while (bytes_left > 0) { - SizeT chunk = (bytes_left > kNeFSSectorSz) ? kNeFSSectorSz : bytes_left; - drive.fPacket.fPacketContent = reinterpret_cast(buf + offset); - drive.fPacket.fPacketSize = chunk; - drive.fPacket.fPacketLba = base_lba + (offset / kNeFSSectorSz); - drive.fOutput(drive.fPacket); - offset += chunk; - bytes_left -= chunk; - } - - delete fork_data_input; - delete[] buf; - delete catalog; - return true; - } - - prev_fork = *fork_data_input; - startFork = fork_data_input->NextSibling; - } - - delete fork_data_input; - delete[] buf; - delete catalog; - return false; -} - -/***********************************************************************************/ -/// @brief -/// @param catalog_name the catalog name. -/// @return the newly found catalog. -/***********************************************************************************/ -_Output NEFS_CATALOG_STRUCT* NeFileSystemParser::FindCatalog(_Input const Char* catalog_name, - Lba& out_lba, Bool search_hidden, - Bool local_search) { - if (!catalog_name || *catalog_name == 0) return nullptr; - - NEFS_ROOT_PARTITION_BLOCK part{}; - auto& drive = kMountpoint.A(); - - rt_copy_memory_safe((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime, - rt_string_len("fs/nefs-packet"), sizeof(drive.fPacket.fPacketMime)); - drive.fPacket.fPacketContent = reinterpret_cast(&part); - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fInput(drive.fPacket); - - auto start_catalog_lba = kNeFSCatalogStartAddress; - - // Helper lambda to scan from a given LBA - auto scan_from = [&](Lba lba_start, Bool allow_hidden) -> NEFS_CATALOG_STRUCT* { - Lba cursor = lba_start; - NEFS_CATALOG_STRUCT tmp{}; - while (cursor >= part.StartCatalog && drive.fPacket.fPacketGood) { - drive.fPacket.fPacketLba = cursor; - drive.fPacket.fPacketContent = reinterpret_cast(&tmp); - drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT); - drive.fInput(drive.fPacket); - - if (KStringBuilder::Equals( - tmp.Name, catalog_name + (rt_string_len(catalog_name) - rt_string_len(tmp.Name)))) { - if (tmp.Status == kNeFSStatusLocked && !allow_hidden) { - err_global_get() = kErrorFileLocked; - return nullptr; - } - if (!(tmp.Flags & kNeFSFlagCreated)) { - err_global_get() = kErrorFileNotFound; - return nullptr; - } - NEFS_CATALOG_STRUCT* catalog_ptr = new NEFS_CATALOG_STRUCT(); - rt_copy_memory_safe(&tmp, catalog_ptr, sizeof(NEFS_CATALOG_STRUCT), - sizeof(NEFS_CATALOG_STRUCT)); - out_lba = cursor; - return catalog_ptr; - } - cursor = tmp.NextSibling; - } - return nullptr; - }; - - if (!KStringBuilder::Equals(catalog_name, NeFileSystemHelper::Root()) && local_search) { - Char parent_name[kNeFSCatalogNameLen] = {0}; - SizeT nameLen = rt_string_len(catalog_name); - rt_copy_memory_safe(const_cast(catalog_name), parent_name, nameLen + 1, - kNeFSCatalogNameLen); - - SizeT indexReverseCopy = nameLen - 1; - if (parent_name[indexReverseCopy] == NeFileSystemHelper::Separator()) { - parent_name[indexReverseCopy] = 0; - --indexReverseCopy; - } - while (indexReverseCopy > 0 && - parent_name[indexReverseCopy] != NeFileSystemHelper::Separator()) { - parent_name[indexReverseCopy] = 0; - --indexReverseCopy; - } - if (indexReverseCopy == 0 && parent_name[0] != NeFileSystemHelper::Separator()) { - return nullptr; - } - - NEFS_CATALOG_STRUCT* parent_catalog = - this->FindCatalog(parent_name, out_lba, search_hidden, NO); - if (parent_catalog) { - start_catalog_lba = parent_catalog->NextSibling; - delete parent_catalog; - NEFS_CATALOG_STRUCT* found = scan_from(start_catalog_lba, search_hidden); - if (found) return found; - } - } - - return scan_from(part.StartCatalog, search_hidden); -} - -/***********************************************************************************/ -/// @brief Get catalog from filesystem. -/// @param name the catalog's name/ -/// @return -/***********************************************************************************/ -_Output NEFS_CATALOG_STRUCT* NeFileSystemParser::GetCatalog(_Input const Char* name) { - Lba unused = 0; - return this->FindCatalog(name, unused, YES, YES); -} - -/***********************************************************************************/ -/// @brief Closes a catalog, (frees it). -/// @param catalog the catalog to close. -/// @return -/***********************************************************************************/ -_Output Boolean NeFileSystemParser::CloseCatalog(_Input _Output NEFS_CATALOG_STRUCT* 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. -/***********************************************************************************/ -_Output Boolean NeFileSystemParser::RemoveCatalog(_Input const Char* catalog_name) { - if (!catalog_name || KStringBuilder::Equals(catalog_name, NeFileSystemHelper::Root())) { - err_global_get() = kErrorInternal; - return false; - } - - Lba out_lba = 0; - auto catalog = this->FindCatalog(catalog_name, out_lba, YES, YES); - if (!catalog) return false; - - auto& drive = kMountpoint.A(); - NEFS_FORK_STRUCT fork_buf{}; - Lba fork_lba = catalog->DataFork; - while (fork_lba >= kNeFSCatalogStartAddress) { - drive.fPacket.fPacketLba = fork_lba; - drive.fPacket.fPacketSize = sizeof(fork_buf); - drive.fPacket.fPacketContent = reinterpret_cast(&fork_buf); - drive.fInput(drive.fPacket); - - fork_buf.Flags &= (~kNeFSFlagCreated); - fork_buf.Flags |= kNeFSFlagDeleted; - - drive.fPacket.fPacketContent = reinterpret_cast(&fork_buf); - drive.fPacket.fPacketSize = sizeof(fork_buf); - drive.fPacket.fPacketLba = fork_lba; - drive.fOutput(drive.fPacket); - - fork_lba = fork_buf.NextSibling; - } - - fork_lba = catalog->ResourceFork; - while (fork_lba >= kNeFSCatalogStartAddress) { - drive.fPacket.fPacketLba = fork_lba; - drive.fPacket.fPacketSize = sizeof(fork_buf); - drive.fPacket.fPacketContent = reinterpret_cast(&fork_buf); - drive.fInput(drive.fPacket); - - fork_buf.Flags &= (~kNeFSFlagCreated); - fork_buf.Flags |= kNeFSFlagDeleted; - - drive.fPacket.fPacketContent = reinterpret_cast(&fork_buf); - drive.fPacket.fPacketSize = sizeof(fork_buf); - drive.fPacket.fPacketLba = fork_lba; - drive.fOutput(drive.fPacket); - - fork_lba = fork_buf.NextSibling; - } - - if (out_lba >= kNeFSCatalogStartAddress || (catalog->Flags & kNeFSFlagCreated)) { - catalog->Flags &= (~kNeFSFlagCreated); - catalog->Flags |= kNeFSFlagDeleted; - - rt_copy_memory_safe((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime, - rt_string_len("fs/nefs-packet"), sizeof(drive.fPacket.fPacketMime)); - drive.fPacket.fPacketLba = out_lba; - drive.fPacket.fPacketSize = sizeof(NEFS_CATALOG_STRUCT); - drive.fPacket.fPacketContent = reinterpret_cast(catalog); - drive.fOutput(drive.fPacket); - - Char partitionBlockBuf[sizeof(NEFS_ROOT_PARTITION_BLOCK)] = {0}; - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fPacket.fPacketContent = reinterpret_cast(partitionBlockBuf); - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fInput(drive.fPacket); - - NEFS_ROOT_PARTITION_BLOCK* part_block = (NEFS_ROOT_PARTITION_BLOCK*) partitionBlockBuf; - if (part_block->CatalogCount > 0) --part_block->CatalogCount; - ++part_block->FreeSectors; - - drive.fPacket.fPacketContent = reinterpret_cast(part_block); - drive.fPacket.fPacketSize = sizeof(NEFS_ROOT_PARTITION_BLOCK); - drive.fPacket.fPacketLba = kNeFSRootCatalogStartAddress; - drive.fOutput(drive.fPacket); - - delete catalog; - catalog = nullptr; - return true; - } - - delete catalog; - catalog = nullptr; - 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 NeFileSystemParser::ReadCatalog(_Input _Output NEFS_CATALOG_STRUCT* catalog, - _Input Bool is_rsrc_fork, _Input SizeT dataSz, - _Input const Char* forkName) { - if (!catalog) { - err_global_get() = kErrorInvalidData; - return nullptr; - } - // Validate size against fork size - SizeT maxSize = is_rsrc_fork ? catalog->ResourceForkSize : catalog->DataForkSize; - if (!is_valid_size(dataSz, maxSize)) { - kout << "NeFS: ReadCatalog called with invalid size: "; - hex_number(dataSz); - kout << "\n"; - return nullptr; - } - - Lba dataForkLba = is_rsrc_fork ? catalog->ResourceFork : catalog->DataFork; - auto& drive = kMountpoint.A(); - if (!is_valid_lba(dataForkLba, drive)) { - kout << "NeFS: ReadCatalog called with invalid LBA: "; - hex_number(dataForkLba); - kout << "\n"; - return nullptr; - } - - auto* fs_buf = new NEFS_FORK_STRUCT(); - rt_copy_memory_safe((VoidPtr) "fs/nefs-packet", drive.fPacket.fPacketMime, - rt_string_len("fs/nefs-packet"), sizeof(drive.fPacket.fPacketMime)); - - NEFS_FORK_STRUCT* fs_fork_data = nullptr; - while (dataForkLba >= kNeFSCatalogStartAddress) { - drive.fPacket.fPacketLba = dataForkLba; - drive.fPacket.fPacketSize = sizeof(NEFS_FORK_STRUCT); - drive.fPacket.fPacketContent = reinterpret_cast(fs_buf); - drive.fInput(drive.fPacket); - - fs_fork_data = fs_buf; - (Void)(kout << "ForkName: " << fs_fork_data->ForkName << kendl); - (Void)(kout << "CatalogName: " << fs_fork_data->CatalogName << kendl); - - if (KStringBuilder::Equals(forkName, fs_fork_data->ForkName) && - KStringBuilder::Equals(catalog->Name, fs_fork_data->CatalogName)) { - break; - } - dataForkLba = fs_fork_data->NextSibling; - } - - if (dataForkLba < kNeFSCatalogStartAddress) { - delete fs_buf; - return nullptr; - } - return fs_fork_data; -} - -/***********************************************************************************/ -/// @brief Seek in the data fork. -/// @param catalog the catalog offset. -/// @param off where to seek. -/// @return if the seeking was successful. -/***********************************************************************************/ -bool NeFileSystemParser::Seek(_Input _Output NEFS_CATALOG_STRUCT* catalog, SizeT off) { - NE_UNUSED(catalog); - NE_UNUSED(off); - err_global_get() = kErrorUnimplemented; - return false; -} - -/***********************************************************************************/ -/// @brief Tell where we are inside the data fork. -/// @param catalog -/// @return The position on the file. -/***********************************************************************************/ -SizeT NeFileSystemParser::Tell(_Input _Output NEFS_CATALOG_STRUCT* catalog) { - NE_UNUSED(catalog); - err_global_get() = kErrorUnimplemented; - return 0; -} - -namespace Kernel::NeFS { -/***********************************************************************************/ -/// @brief Construct NeFS drives. -/***********************************************************************************/ -Boolean fs_init_nefs(Void) noexcept { - kout << "Creating OpenHeFS disk...\r"; - kMountpoint.A() = io_construct_main_drive(); - if (kMountpoint.A().fPacket.fPacketReadOnly == YES) - ke_panic(RUNTIME_CHECK_FILESYSTEM, "Main disk cannot be mounted."); - NeFileSystemParser parser; - return parser.Format(&kMountpoint.A(), 0, kNeFSVolumeName); -} -} // namespace Kernel::NeFS - -#endif // ifdef __FSKIT_INCLUDES_NEFS__ diff --git a/dev/kernel/src/FS/OpenHeFS+FileMgr.cc b/dev/kernel/src/FS/OpenHeFS+FileMgr.cc deleted file mode 100644 index e70e3626..00000000 --- a/dev/kernel/src/FS/OpenHeFS+FileMgr.cc +++ /dev/null @@ -1,191 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#ifndef __NE_MINIMAL_OS__ -#ifdef __FSKIT_INCLUDES_OPENHEFS__ - -#include -#include - -/// @brief OpenHeFS File System Manager. -/// BUGS: 0 - -namespace Kernel { -/// @brief C++ constructor -HeFileSystemMgr::HeFileSystemMgr() { - mParser = new HeFileSystemParser(); - MUST_PASS(mParser); - - kout << "We are done allocating HeFileSystemParser...\n"; -} - -HeFileSystemMgr::~HeFileSystemMgr() { - if (mParser) { - kout << "Destroying HeFileSystemParser...\n"; - delete mParser; - mParser = nullptr; - } -} - -/// @brief Removes a node from the filesystem. -/// @param path The filename -/// @return If it was deleted or not. -bool HeFileSystemMgr::Remove(_Input const Char* path) { - if (path == nullptr || *path == 0) { - kout << "OpenHeFS: Remove called with null or empty path\n"; - return false; - } - - return NO; -} - -/// @brief Creates a node with the specified. -/// @param path The filename path. -/// @return The Node pointer. -NodePtr HeFileSystemMgr::Create(_Input const Char* path) { - if (!path || *path == 0) { - kout << "OpenHeFS: Create called with null or empty path\n"; - return nullptr; - } - return nullptr; -} - -/// @brief Creates a node which is a directory. -/// @param path The filename path. -/// @return The Node pointer. -NodePtr HeFileSystemMgr::CreateDirectory(const Char* path) { - if (!path || *path == 0) { - kout << "OpenHeFS: CreateDirectory called with null or empty path\n"; - return nullptr; - } - return nullptr; -} - -/// @brief Creates a node which is an alias. -/// @param path The filename path. -/// @return The Node pointer. -NodePtr HeFileSystemMgr::CreateAlias(const Char* path) { - if (!path || *path == 0) { - kout << "OpenHeFS: CreateAlias called with null or empty path\n"; - return nullptr; - } - return nullptr; -} - -NodePtr HeFileSystemMgr::CreateSwapFile(const Char* path) { - if (!path || *path == 0) { - kout << "OpenHeFS: CreateSwapFile called with null or empty path\n"; - return nullptr; - } - return nullptr; -} - -/// @brief Gets the root directory. -/// @return -const Char* NeFileSystemHelper::Root() { - return kHeFSRootDirectory; -} - -/// @brief Gets the up-dir directory. -/// @return -const Char* NeFileSystemHelper::UpDir() { - return kHeFSUpDir; -} - -/// @brief Gets the separator character. -/// @return -Char NeFileSystemHelper::Separator() { - return kHeFSSeparator; -} - -/// @brief Gets the metafile character. -/// @return -Char NeFileSystemHelper::MetaFile() { - return '\0'; -} - -/// @brief Opens a new file. -/// @param path -/// @param r -/// @return -_Output NodePtr HeFileSystemMgr::Open(_Input const Char* path, _Input const Char* r) { - if (!path || *path == 0) { - kout << "OpenHeFS: Open called with null or empty path\n"; - return nullptr; - } - if (!r || *r == 0) { - kout << "OpenHeFS: Open called with null or empty mode string\n"; - return nullptr; - } - return nullptr; -} - -Void HeFileSystemMgr::Write(_Input NodePtr node, _Input VoidPtr data, _Input Int32 flags, - _Input SizeT size) { - NE_UNUSED(node); - NE_UNUSED(flags); - NE_UNUSED(size); - NE_UNUSED(data); -} - -_Output VoidPtr HeFileSystemMgr::Read(_Input NodePtr node, _Input Int32 flags, _Input SizeT size) { - NE_UNUSED(node); - NE_UNUSED(flags); - NE_UNUSED(size); - - return nullptr; -} - -Void HeFileSystemMgr::Write(_Input const Char* name, _Input NodePtr node, _Input VoidPtr data, - _Input Int32 flags, _Input SizeT size) { - NE_UNUSED(node); - NE_UNUSED(flags); - NE_UNUSED(size); - NE_UNUSED(name); - NE_UNUSED(data); -} - -_Output VoidPtr HeFileSystemMgr::Read(_Input const Char* name, _Input NodePtr node, - _Input Int32 flags, _Input SizeT sz) { - NE_UNUSED(node); - NE_UNUSED(flags); - NE_UNUSED(sz); - NE_UNUSED(name); - - return nullptr; -} - -_Output Bool HeFileSystemMgr::Seek(NodePtr node, SizeT off) { - NE_UNUSED(node); - NE_UNUSED(off); - - return false; -} - -/// @brief Tell current offset within catalog. -/// @param node -/// @return kFileMgrNPos if invalid, else current offset. -_Output SizeT HeFileSystemMgr::Tell(NodePtr node) { - NE_UNUSED(node); - return kFileMgrNPos; -} - -/// @brief Rewinds the catalog -/// @param node -/// @return False if invalid, nah? calls Seek(node, 0). -_Output Bool HeFileSystemMgr::Rewind(NodePtr node) { - NE_UNUSED(node); - return kFileMgrNPos; -} - -/// @brief Returns the parser of OpenHeFS. -_Output HeFileSystemParser* HeFileSystemMgr::GetParser() noexcept { - return mParser; -} -} // namespace Kernel - -#endif // ifdef __FSKIT_INCLUDES_OPENHEFS__ -#endif // ifndef __NE_MINIMAL_OS__ diff --git a/dev/kernel/src/FS/OpenHeFS+FileSystemParser.cc b/dev/kernel/src/FS/OpenHeFS+FileSystemParser.cc deleted file mode 100644 index d8e22f18..00000000 --- a/dev/kernel/src/FS/OpenHeFS+FileSystemParser.cc +++ /dev/null @@ -1,1160 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025 Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#ifdef __FSKIT_INCLUDES_OPENHEFS__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Kernel { -namespace Detail { - /// @brief Forward declarations of internal functions. - - /***********************************************************************************/ - /// @brief Traverse the RB-Tree of the filesystem. - /// @param dir The directory to traverse. - /// @param start The starting point of the traversal. - /// @note This function is used to traverse the RB-Tree of the filesystem. - /// @internal Internal filesystem use only. - /***********************************************************************************/ - STATIC ATTRIBUTE(unused) _Output Void - hefsi_traverse_tree(HEFS_INDEX_NODE_DIRECTORY* dir, DriveTrait* mnt, const Lba& start_ind, - Lba& start); - - /***********************************************************************************/ - /// @brief Get the index node of a file or directory. - /// @param boot The boot node of the filesystem. - /// @param mnt The mnt to read from. - /// @param dir_name The name of the directory. - /// @param file_name The name of the file. - /// @param kind The kind of the file (regular, directory, block, character, FIFO, socket, symbolic - /// link, unknown). - /***********************************************************************************/ - STATIC ATTRIBUTE(unused) _Output HEFS_INDEX_NODE* hefsi_fetch_in(HEFS_BOOT_NODE* boot, - DriveTrait* mnt, - const Utf8Char* dir_name, - const Utf8Char* file_name, - UInt8 kind); - - /***********************************************************************************/ - /// @brief Allocate a new index node-> - /// @param boot The boot node of the filesystem. - /// @param mnt The mnt to read/write from. - /// @param dir_name The name of the parent directory. - /// @return Status, see err_global_get(). - /***********************************************************************************/ - STATIC ATTRIBUTE(unused) _Output BOOL - hefsi_update_in_status(HEFS_BOOT_NODE* boot, DriveTrait* mnt, const Utf8Char* dir_name, - HEFS_INDEX_NODE* node, const BOOL create_or_delete); - - /***********************************************************************************/ - /// @brief Balance RB-Tree of the filesystem. - /// @param boot The boot node of the filesystem. - /// @param mnt The mnt to read/write from. - /// @return Status, see err_global_get(). - /***********************************************************************************/ - STATIC ATTRIBUTE(unused) _Output BOOL hefsi_balance_ind(HEFS_BOOT_NODE* boot, DriveTrait* mnt); - - /// @brief Alllocate IND from boot node. - /// @param boot The boot node of the filesystem. - /// @param mnt The mnt to read from. - /// @param dir_name The name of the directory. - /// @param dir_name The parent of the directory. - /// @param flags Directory flags. - /// @param delete_or_create Delete or create directory. - STATIC _Output BOOL hefsi_update_ind_status(HEFS_BOOT_NODE* boot, DriveTrait* mnt, - const Utf8Char* dir_name, UInt16 flags, - const BOOL delete_or_create); - - /// @brief This helper makes it easier for other machines to understand OpenHeFS encoded hashes. - STATIC UInt64 hefsi_to_big_endian_64(UInt64 val) { - return ((val >> 56) & 0x00000000000000FFULL) | ((val >> 40) & 0x000000000000FF00ULL) | - ((val >> 24) & 0x0000000000FF0000ULL) | ((val >> 8) & 0x00000000FF000000ULL) | - ((val << 8) & 0x000000FF00000000ULL) | ((val << 24) & 0x0000FF0000000000ULL) | - ((val << 40) & 0x00FF000000000000ULL) | ((val << 56) & 0xFF00000000000000ULL); - } - - /// @brief Simple algorithm to hash directory entries for INDs. - /// @param path the directory path. - /// @return The hashed path. - template - STATIC UInt64 hefsi_hash_64(const CharT* path) { - if (!path || *path == 0) return 0; - - const UInt64 kFnvBaseOffset = 0xcbf29ce484222325ULL; - const UInt64 kFnvPrimeNumber = 0x100000001b3ULL; - - UInt64 hash = kFnvBaseOffset; - - while (*path) { - hash ^= (CharT) (*path++); - hash *= kFnvPrimeNumber; - } - - return hefsi_to_big_endian_64(hash); - } - - /// @brief Traverse the RB-Tree of the filesystem. - /// @param dir The directory to traverse. - /// @param start The starting point of the traversal. - /// @note This function is used to traverse the RB-Tree of the filesystem. - /// @internal Internal filesystem use only. - STATIC ATTRIBUTE(unused) Void hefsi_traverse_tree(HEFS_INDEX_NODE_DIRECTORY* dir, DriveTrait* mnt, - const Lba& ind_start, Lba& start) { - if (!mnt || !dir) return; - - BOOL check_is_good = NO; - HEFS_INDEX_NODE_DIRECTORY* dir_tmp = new HEFS_INDEX_NODE_DIRECTORY(); - - while (YES) { - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir_tmp; - mnt->fInput(mnt->fPacket); - - if (!mnt->fPacket.fPacketGood) break; - - if (dir_tmp->fNext != 0) { - if (check_is_good) break; - - start = dir_tmp->fNext; - - check_is_good = YES; - continue; - } else if (dir_tmp->fPrev != 0) { - if (check_is_good) break; - - start = dir_tmp->fPrev; - check_is_good = YES; - continue; - } else { - if (dir_tmp->fParent != 0) { - if (check_is_good) break; - - start = dir_tmp->fParent; - check_is_good = YES; - continue; - } else if (dir_tmp->fPrev != 0) { - if (check_is_good) break; - - start = dir_tmp->fPrev; - check_is_good = YES; - continue; - } else { - if (start == 0) { - start = ind_start; - continue; - } - - start += sizeof(HEFS_INDEX_NODE_DIRECTORY); - break; - } - } - } - - delete dir_tmp; - - start += sizeof(HEFS_INDEX_NODE_DIRECTORY); - if (start == 0) start = ind_start; - } - - /***********************************************************************************/ - /// @brief Rotate the RB-Tree to the left or right. - /// @internal - /***********************************************************************************/ - STATIC ATTRIBUTE(unused) _Output Void hefsi_rotate_tree(Lba& start, DriveTrait* mnt) { - if (!start || !mnt) return; - - HEFS_INDEX_NODE_DIRECTORY* cur = - (HEFS_INDEX_NODE_DIRECTORY*) RTL_ALLOCA(sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = cur; - - mnt->fInput(mnt->fPacket); - - if (cur->fHashPath == 0) return; - - HEFS_INDEX_NODE_DIRECTORY* sibling = - (HEFS_INDEX_NODE_DIRECTORY*) RTL_ALLOCA(sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = cur->fPrev; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = sibling; - - mnt->fInput(mnt->fPacket); - - if (sibling->fHashPath == 0) return; - - auto child_sibling = sibling->fChild; - auto child_cur = cur->fChild; - - cur->fChild = child_sibling; - sibling->fChild = child_cur; - - sibling->fChecksum = ke_calculate_crc32((Char*) sibling, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - cur->fChecksum = ke_calculate_crc32((Char*) cur, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = cur->fParent; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = sibling; - - mnt->fOutput(mnt->fPacket); - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = cur; - - mnt->fOutput(mnt->fPacket); - - HEFS_INDEX_NODE_DIRECTORY* sibling_child = - (HEFS_INDEX_NODE_DIRECTORY*) RTL_ALLOCA(sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = child_sibling; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = sibling_child; - - mnt->fInput(mnt->fPacket); - - sibling_child->fParent = cur->fParent; - - sibling_child->fChecksum = - ke_calculate_crc32((Char*) sibling, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fOutput(mnt->fPacket); - - HEFS_INDEX_NODE_DIRECTORY* cur_child = - (HEFS_INDEX_NODE_DIRECTORY*) RTL_ALLOCA(sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = child_cur; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = cur_child; - - mnt->fInput(mnt->fPacket); - - cur_child->fParent = start; - - cur_child->fChecksum = ke_calculate_crc32((Char*) sibling, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fOutput(mnt->fPacket); - - kout << "RB-Tree has been rotated.\r"; - } - - /// @brief Alllocate IND from boot node. - /// @param boot The boot node of the filesystem. - /// @param mnt The mnt to read from. - /// @param dir_name The name of the directory. - /// @param dir_name The parent of the directory. - /// @param flags Directory flags. - /// @param delete_or_create Delete or create directory. - STATIC _Output BOOL hefsi_update_ind_status(HEFS_BOOT_NODE* boot, DriveTrait* mnt, - const Utf8Char* dir_name, UInt16 flags, - const BOOL delete_or_create) { - if (mnt) { - HEFS_INDEX_NODE_DIRECTORY* tmpdir = - (HEFS_INDEX_NODE_DIRECTORY*) mm_alloc_ptr(sizeof(HEFS_INDEX_NODE_DIRECTORY), Yes, No); - - auto start = boot->fStartIND; - auto prev_location = start; - auto parent_location = 0UL; - - MUST_PASS(boot->fStartIND > mnt->fLbaStart); - - while (YES) { - auto prev_start = start; - - if (start) - mnt->fPacket.fPacketLba = start; - else - mnt->fPacket.fPacketLba = prev_location + sizeof(HEFS_INDEX_NODE_DIRECTORY); - - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = tmpdir; - - mnt->fInput(mnt->fPacket); - - BOOL expr = NO; - - if (!delete_or_create) { - expr = (!tmpdir->fCreated && tmpdir->fDeleted) || tmpdir->fHashPath == 0; - } else { - expr = - tmpdir->fCreated && !tmpdir->fDeleted && hefsi_hash_64(dir_name) == tmpdir->fHashPath; - } - - if (expr) { - HEFS_INDEX_NODE_DIRECTORY* dirent = - (HEFS_INDEX_NODE_DIRECTORY*) mm_alloc_ptr(sizeof(HEFS_INDEX_NODE_DIRECTORY), Yes, No); - - rt_set_memory(dirent, 0, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - dirent->fHashPath = delete_or_create ? 0UL : hefsi_hash_64(dir_name); - dirent->fAccessed = 0UL; - dirent->fCreated = delete_or_create ? 0UL : 1UL; - dirent->fDeleted = delete_or_create ? 1UL : 0UL; - dirent->fModified = 0UL; - dirent->fEntryCount = 0UL; - - dirent->fReserved = 0; - dirent->fFlags = flags; - dirent->fChecksum = 0; - - dirent->fEntryCount = 0; - - if (parent_location) { - HEFS_INDEX_NODE_DIRECTORY* tmpend = - (HEFS_INDEX_NODE_DIRECTORY*) RTL_ALLOCA(sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = parent_location; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = tmpend; - - mnt->fInput(mnt->fPacket); - - if (tmpend->fChecksum != - ke_calculate_crc32((Char*) tmpend, sizeof(HEFS_INDEX_NODE_DIRECTORY))) - ke_panic(RUNTIME_CHECK_FILESYSTEM, "Bad CRC32 value, aborting."); - - if (delete_or_create) - --tmpend->fEntryCount; - else - ++tmpend->fEntryCount; - - tmpend->fChecksum = - ke_calculate_crc32((Char*) tmpend, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fOutput(mnt->fPacket); - - auto child_first = tmpend->fChild; - - while (YES) { - mnt->fPacket.fPacketLba = child_first; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = tmpend; - - mnt->fInput(mnt->fPacket); - - if ((!tmpend->fCreated && tmpend->fDeleted) || tmpend->fHashPath == 0) { - start = child_first; - break; - } - - hefsi_traverse_tree(tmpend, mnt, boot->fStartIND, child_first); - } - } - - dirent->fNext = tmpdir->fNext; - dirent->fPrev = tmpdir->fPrev; - dirent->fParent = tmpdir->fParent; - dirent->fChild = tmpdir->fChild; - dirent->fColor = tmpdir->fColor; - - if (dirent->fColor == 0) { - dirent->fColor = dirent->fNext ? kHeFSRed : kHeFSBlack; - } - - if (dirent->fPrev == 0) { - dirent->fPrev = boot->fStartIND; - } - - if (dirent->fParent == 0) { - dirent->fParent = boot->fStartIND; - } - - if (tmpdir->fChild == 0) { - auto child = dirent->fNext + sizeof(HEFS_INDEX_NODE_DIRECTORY); - - HEFS_INDEX_NODE_DIRECTORY* tmpend = - (HEFS_INDEX_NODE_DIRECTORY*) RTL_ALLOCA(sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - while (YES) { - mnt->fPacket.fPacketLba = child; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = tmpend; - - mnt->fInput(mnt->fPacket); - - if ((!tmpend->fCreated && tmpend->fDeleted) || tmpdir->fHashPath == 0) { - break; - } - - child += sizeof(HEFS_INDEX_NODE_DIRECTORY); - if (child > boot->fEndIND) break; - } - - dirent->fColor = kHeFSRed; - dirent->fChild = child; - - if (child > boot->fEndIND) dirent->fChild = boot->fStartIND; - } - - for (SizeT index = 0UL; index < kHeFSSliceCount; ++index) { - dirent->fINSlices[index] = 0UL; - } - - dirent->fChecksum = ke_calculate_crc32((Char*) dirent, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = prev_start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dirent; - - mnt->fOutput(mnt->fPacket); - - err_global_get() = kErrorSuccess; - - mm_free_ptr(dirent); - mm_free_ptr(tmpdir); - - if (!delete_or_create) - ++boot->fINDCount; - else - --boot->fINDCount; - - boot->fChecksum = ke_calculate_crc32((Char*) boot, sizeof(HEFS_BOOT_NODE)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fOutput(mnt->fPacket); - - return YES; - } - - prev_location = start; - - hefsi_traverse_tree(tmpdir, mnt, boot->fStartIND, start); - if (start > boot->fEndIND || start == 0) break; - } - - err_global_get() = kErrorDisk; - mm_free_ptr(tmpdir); - - return NO; - } - - err_global_get() = kErrorDiskIsFull; - return NO; - } - - /// @brief Get the index node of a file or directory. - /// @param boot The boot node of the filesystem. - /// @param mnt The mnt to read from. - /// @param dir_name The name of the directory. - /// @param file_name The name of the file. - /// @param kind The kind of the file (regular, directory, block, character, FIFO, socket, symbolic - /// link, unknown). - STATIC ATTRIBUTE(unused) _Output HEFS_INDEX_NODE* hefsi_fetch_in(HEFS_BOOT_NODE* boot, - DriveTrait* mnt, - const Utf8Char* dir_name, - const Utf8Char* file_name, - UInt8 kind) { - if (mnt) { - if (boot->fStartIND > boot->fEndIND) return nullptr; - if (boot->fStartIN > boot->fEndIN) return nullptr; - - auto start = boot->fStartIND; - HEFS_INDEX_NODE* node = new HEFS_INDEX_NODE(); - - HEFS_INDEX_NODE_DIRECTORY* dir = - (HEFS_INDEX_NODE_DIRECTORY*) mm_alloc_ptr(sizeof(HEFS_INDEX_NODE_DIRECTORY), Yes, No); - - while (YES) { - if (err_global_get() == kErrorDiskIsCorrupted) { - delete dir; - dir = nullptr; - - delete node; - node = nullptr; - - return nullptr; - } - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fInput(mnt->fPacket); - - (Void)(kout << hex_number(hefsi_hash_64(dir_name)) << kendl); - (Void)(kout << hex_number(dir->fHashPath) << kendl); - - if (dir->fHashPath == 0) break; - - if (hefsi_hash_64(dir_name) == dir->fHashPath) { - for (SizeT inode_index = 0UL; inode_index < kHeFSSliceCount; ++inode_index) { - mnt->fPacket.fPacketLba = dir->fINSlices[inode_index]; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE); - mnt->fPacket.fPacketContent = node; - - mnt->fInput(mnt->fPacket); - - (Void)(kout << hex_number(hefsi_hash_64(file_name)) << kendl); - (Void)(kout << hex_number(node->fHashPath) << kendl); - - if (hefsi_hash_64(file_name) == node->fHashPath && node->fKind == kind) { - delete dir; - dir = nullptr; - - return node; - } - } - } - - hefsi_traverse_tree(dir, mnt, boot->fStartIND, start); - if (start == boot->fStartIND || start == boot->fStartIND) break; - } - - delete node; - node = nullptr; - - delete dir; - dir = nullptr; - } - - kout << "Error: Failed to find IN.\r"; - - err_global_get() = kErrorFileNotFound; - - return nullptr; - } - - STATIC ATTRIBUTE(unused) _Output BOOL - hefsi_update_in_status(HEFS_BOOT_NODE* boot, DriveTrait* mnt, const Utf8Char* dir_name, - HEFS_INDEX_NODE* node, BOOL delete_or_create) { - if (!boot || !mnt) return NO; - - auto start = boot->fStartIND; - - if (start > boot->fEndIND) return NO; - if (boot->fStartIN > boot->fEndIN) return NO; - ; - if (boot->fStartBlock > boot->fEndBlock) return NO; - - if (mnt) { - HEFS_INDEX_NODE_DIRECTORY* dir = - (HEFS_INDEX_NODE_DIRECTORY*) mm_alloc_ptr(sizeof(HEFS_INDEX_NODE_DIRECTORY), Yes, No); - - auto hash_file = node->fHashPath; - - while (YES) { - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fInput(mnt->fPacket); - - (Void)(kout << hex_number(hefsi_hash_64(dir_name)) << kendl); - (Void)(kout << hex_number(dir->fHashPath) << kendl); - - if (hefsi_hash_64(dir_name) == dir->fHashPath) { - for (SizeT inode_index = 0UL; inode_index < kHeFSSliceCount; ++inode_index) { - if (dir->fINSlices[inode_index] == 0 && !delete_or_create) { - dir->fINSlices[inode_index] = boot->fStartIN; - - ++dir->fEntryCount; - - dir->fChecksum = ke_calculate_crc32((Char*) dir, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fOutput(mnt->fPacket); - - auto lba = dir->fINSlices[inode_index]; - - node->fOffsetSliceLow = (UInt32) (boot->fStartBlock); - node->fOffsetSliceHigh = (UInt32) (boot->fStartBlock >> 32); - - node->fChecksum = ke_calculate_crc32((Char*) node, sizeof(HEFS_INDEX_NODE)); - - mnt->fPacket.fPacketLba = lba; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE); - mnt->fPacket.fPacketContent = node; - - mnt->fOutput(mnt->fPacket); - - boot->fStartIN += sizeof(HEFS_INDEX_NODE); - boot->fStartBlock += kHeFSBlockLen; - - boot->fChecksum = ke_calculate_crc32((Char*) boot, sizeof(HEFS_BOOT_NODE)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fOutput(mnt->fPacket); - - mm_free_ptr(dir); - - return YES; - } else if (dir->fINSlices[inode_index] != 0 && delete_or_create) { - auto lba = dir->fINSlices[inode_index]; - - HEFS_INDEX_NODE tmp_node{}; - - mnt->fPacket.fPacketLba = lba; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE); - mnt->fPacket.fPacketContent = &tmp_node; - - mnt->fInput(mnt->fPacket); - - if (tmp_node.fHashPath != hash_file) { - continue; - } - - node->fOffsetSliceLow = 0; - node->fOffsetSliceHigh = 0; - - boot->fStartIN -= sizeof(HEFS_INDEX_NODE); - boot->fStartBlock -= kHeFSBlockLen; - - boot->fChecksum = ke_calculate_crc32((Char*) boot, sizeof(HEFS_BOOT_NODE)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fOutput(mnt->fPacket); - - mnt->fPacket.fPacketLba = lba; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE); - mnt->fPacket.fPacketContent = node; - - mnt->fOutput(mnt->fPacket); - - dir->fINSlices[inode_index] = 0; - - if (dir->fEntryCount) --dir->fEntryCount; - - dir->fChecksum = ke_calculate_crc32((Char*) dir, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fOutput(mnt->fPacket); - - mm_free_ptr(dir); - - return YES; - } - } - } - - hefsi_traverse_tree(dir, mnt, boot->fStartIND, start); - if (start > boot->fEndIND || start == 0) break; - } - - mm_free_ptr(dir); - err_global_get() = kErrorFileNotFound; - return NO; - } - - err_global_get() = kErrorDiskIsFull; - return NO; - } - - /// @brief Balance RB-Tree of the filesystem. - /// @param boot The boot node of the filesystem. - /// @param mnt The mnt to read/write from. - /// @return Status, see err_global_get(). - STATIC ATTRIBUTE(unused) _Output BOOL hefsi_balance_ind(HEFS_BOOT_NODE* boot, DriveTrait* mnt) { - if (mnt) { - HEFS_INDEX_NODE_DIRECTORY* dir = - (HEFS_INDEX_NODE_DIRECTORY*) RTL_ALLOCA(sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - auto start = boot->fStartIND; - - while (YES) { - if (start == 0UL || start > boot->fEndIND) break; - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fInput(mnt->fPacket); - - if (!mnt->fPacket.fPacketGood) { - err_global_get() = kErrorDiskIsCorrupted; - - return NO; - } - - if (start == boot->fStartIND) { - dir->fColor = kHeFSBlack; - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fOutput(mnt->fPacket); - } - - if (dir->fColor == kHeFSBlack && dir->fChild != 0UL) { - dir->fColor = kHeFSRed; - hefsi_rotate_tree(start, mnt); - } else if (dir->fColor == kHeFSBlack && dir->fChild == 0UL) { - dir->fColor = kHeFSBlack; - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fOutput(mnt->fPacket); - } - - if (ke_calculate_crc32((Char*) dir, sizeof(HEFS_INDEX_NODE_DIRECTORY)) != dir->fChecksum) { - dir->fChecksum = ke_calculate_crc32((Char*) dir, sizeof(HEFS_INDEX_NODE_DIRECTORY)); - - mnt->fPacket.fPacketLba = start; - mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); - mnt->fPacket.fPacketContent = dir; - - mnt->fOutput(mnt->fPacket); - } - - hefsi_traverse_tree(dir, mnt, boot->fStartIND, start); - } - - err_global_get() = kErrorSuccess; - return YES; - } - - err_global_get() = kErrorDisk; - return NO; - } -} // namespace Detail -} // namespace Kernel - -/// @note OpenHeFS will allocate inodes and ind in advance, to avoid having to allocate them in -/// real-time. -/// @note This is certainly take longer to format a disk with it, but worth-it in the long run. - -namespace Kernel { -/// @brief Make a EPM+OpenHeFS mnt out of the disk. -/// @param mnt The mnt to write on. -/// @return If it was sucessful, see err_local_get(). -_Output Bool HeFileSystemParser::Format(_Input _Output DriveTrait* mnt, _Input const Int32 flags, - _Input const Utf8Char* vol_name) { - // Verify Disk. - mnt->fVerify(mnt->fPacket); - - // if disk isn't good, then error out. - if (false == mnt->fPacket.fPacketGood) { - err_global_get() = kErrorDiskIsCorrupted; - return NO; - } - - if (drv_std_get_size() < kHeFSMinimumDiskSize) { - (Void)(kout << "OpenHeFS recommends at least 128 GiB of free space." << kendl); - } - - HEFS_BOOT_NODE* boot = (HEFS_BOOT_NODE*) RTL_ALLOCA(sizeof(HEFS_BOOT_NODE)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fInput(mnt->fPacket); - - if (!mnt->fPacket.fPacketGood) { - err_global_get() = kErrorDiskIsCorrupted; - - return NO; - } - - // Check if the disk is already formatted. - - if (KStringBuilder::Equals(boot->fMagic, kHeFSMagic) && boot->fVersion == kHeFSVersion) { - if (ke_calculate_crc32((Char*) boot, sizeof(HEFS_BOOT_NODE)) != boot->fChecksum && - boot->fChecksum > 0) { - err_global_get() = kErrorDiskIsCorrupted; - return NO; - } - - err_global_get() = kErrorSuccess; - return YES; - } - - if (ke_calculate_crc32((Char*) boot, sizeof(HEFS_BOOT_NODE)) != boot->fChecksum && - boot->fChecksum > 0) { - err_global_get() = kErrorDiskIsCorrupted; - return NO; - } - - rt_copy_memory_safe((VoidPtr) "fs/hefs-packet", mnt->fPacket.fPacketMime, - rt_string_len("fs/hefs-packet"), sizeof(mnt->fPacket.fPacketMime)); - - urt_copy_memory((VoidPtr) vol_name, boot->fVolName, urt_string_len(vol_name) + 1); - rt_copy_memory_safe((VoidPtr) kHeFSMagic, boot->fMagic, kHeFSMagicLen - 1, sizeof(boot->fMagic)); - - if (mnt->fLbaStart > mnt->fLbaEnd) { - err_global_get() = kErrorDiskIsCorrupted; - - return NO; - } - - boot->fBadSectors = 0; - - boot->fSectorCount = drv_std_get_sector_count(); - boot->fSectorSize = mnt->fSectorSz; - - MUST_PASS(boot->fSectorSize); - - /// @note all OpenHeFS strucutres are equal to 512, so here it's fine, unless fSectoSize is 2048. - const SizeT max_lba = (drv_std_get_size()) / boot->fSectorSize; - - const SizeT dir_max = max_lba / 300; // 5% for directory inodes - const SizeT inode_max = max_lba / 400; // 5% for inodes - - boot->fStartIND = mnt->fLbaStart + kHeFSINDStartOffset; - boot->fEndIND = boot->fStartIND + dir_max; - - boot->fStartIN = boot->fEndIND; - boot->fEndIN = boot->fStartIN + inode_max; - - boot->fStartBlock = boot->fEndIN; - boot->fEndBlock = drv_std_get_size(); - - boot->fINDCount = 0; - - boot->fDiskSize = drv_std_get_size(); - boot->fDiskStatus = kHeFSStatusUnlocked; - - boot->fDiskFlags = flags; - - if (mnt->fKind & kMassStorageDrive) { - boot->fDiskKind = kHeFSMassStorageDevice; - } else if (mnt->fKind & kHeFSOpticalDrive) { - boot->fDiskKind = kHeFSOpticalDrive; - } else { - boot->fDiskKind = kHeFSUnknown; - } - - boot->fVersion = kHeFSVersion; - - boot->fVID = kHeFSInvalidVID; - - boot->fChecksum = ke_calculate_crc32((Char*) boot, sizeof(HEFS_BOOT_NODE)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fOutput(mnt->fPacket); - - (Void)(kout << "Protocol: " << mnt->fProtocol() << kendl); - (Void)(kout8 << u8"Volume Name: " << boot->fVolName << kendl8); - (Void)(kout << "Start IND: " << hex_number(boot->fStartIND) << kendl); - (Void)(kout << "End IND: " << hex_number(boot->fEndIND) << kendl); - (Void)(kout << "Start IN: " << hex_number(boot->fStartIN) << kendl); - (Void)(kout << "End IN: " << hex_number(boot->fEndIN) << kendl); - (Void)(kout << "Start Block: " << hex_number(boot->fStartBlock) << kendl); - (Void)(kout << "End Block: " << hex_number(boot->fEndBlock) << kendl); - (Void)(kout << "Number of IND: " << hex_number(boot->fINDCount) << kendl); - (Void)(kout << "Sector Size: " << hex_number(boot->fSectorSize) << kendl); - (Void)(kout << "Drive Kind: " << Detail::hefs_drive_kind_to_string(boot->fDiskKind) << kendl); - - if (!mnt->fPacket.fPacketGood) { - err_global_get() = kErrorDiskIsCorrupted; - return NO; - } - - /// AMLALE: Better way to create default directories than before. - const Utf8Char* kFileMap[] = {u8"/", u8"/boot", u8"/system", u8"/network", - u8"/devices", u8"/media", u8"/dev", (Utf8Char*) nullptr}; - - SizeT i = 0; - while (kFileMap[++i] != nullptr) { - this->CreateINodeDirectory(mnt, kHeFSEncodingFlagsUTF8, kFileMap[i]); - } - - err_global_get() = kErrorSuccess; - - return YES; -} - -/// @brief Create a new directory on the disk. -/// @param mnt The mnt to write on. -/// @param flags The flags to use. -/// @param dir The directory to create the file in. -/// @return If it was sucessful, see err_local_get(). -_Output Bool HeFileSystemParser::INodeDirectoryCtlManip(_Input DriveTrait* mnt, - _Input const Int32 flags, - const Utf8Char* dir, - const BOOL delete_or_create) { - if (urt_string_len(dir) > kHeFSFileNameLen) { - err_global_get() = kErrorDisk; - return NO; - } - - HEFS_BOOT_NODE* boot = (HEFS_BOOT_NODE*) mm_alloc_ptr(sizeof(HEFS_BOOT_NODE), Yes, No); - - rt_copy_memory_safe((VoidPtr) "fs/hefs-packet", mnt->fPacket.fPacketMime, - rt_string_len("fs/hefs-packet"), sizeof(mnt->fPacket.fPacketMime)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fInput(mnt->fPacket); - - if (!KStringBuilder::Equals(boot->fMagic, kHeFSMagic) || boot->fVersion != kHeFSVersion) { - err_global_get() = kErrorDisk; - return YES; - } - - if (!KStringBuilder::Equals(boot->fMagic, kHeFSMagic) || boot->fVersion != kHeFSVersion) { - err_global_get() = kErrorDiskIsCorrupted; - - kout << "Invalid Boot Node, this can't continue!\r"; - - return NO; - } - - if (KStringBuilder::Equals(dir, kHeFSSearchAllStr)) { - kout << "Error: Invalid directory name.\r"; - - err_global_get() = kErrorInvalidData; - - return NO; - } - - if (Detail::hefsi_update_ind_status(boot, mnt, dir, flags, delete_or_create)) { - // todo: make it smarter for high-throughput. - Detail::hefsi_balance_ind(boot, mnt); - - mm_free_ptr((VoidPtr) boot); - return YES; - } - - mm_free_ptr((VoidPtr) boot); - return NO; -} - -_Output Bool HeFileSystemParser::RemoveINodeDirectory(_Input DriveTrait* mnt, - _Input const Int32 flags, - const Utf8Char* dir) { - return this->INodeDirectoryCtlManip(mnt, flags, dir, YES); -} - -_Output Bool HeFileSystemParser::CreateINodeDirectory(_Input DriveTrait* mnt, - _Input const Int32 flags, - const Utf8Char* dir) { - return this->INodeDirectoryCtlManip(mnt, flags, dir, NO); -} - -_Output Bool HeFileSystemParser::DeleteINode(_Input DriveTrait* mnt, _Input const Int32 flags, - const Utf8Char* dir, const Utf8Char* name, - const UInt8 kind) { - return this->INodeCtlManip(mnt, flags, dir, name, YES, kind); -} - -_Output Bool HeFileSystemParser::CreateINode(_Input DriveTrait* mnt, _Input const Int32 flags, - const Utf8Char* dir, const Utf8Char* name, - const UInt8 kind) { - return this->INodeCtlManip(mnt, flags, dir, name, NO, kind); -} - -_Output Bool HeFileSystemParser::INodeManip(_Input DriveTrait* mnt, VoidPtr block, SizeT block_sz, - const Utf8Char* dir, const Utf8Char* name, - const UInt8 kind, const BOOL is_input) { - if (urt_string_len(dir) > kHeFSFileNameLen) { - err_global_get() = kErrorDisk; - return NO; - } - - if (urt_string_len(name) > kHeFSFileNameLen) { - err_global_get() = kErrorDisk; - return NO; - } - - HEFS_BOOT_NODE* boot = (HEFS_BOOT_NODE*) mm_alloc_ptr(sizeof(HEFS_BOOT_NODE), Yes, No); - - if (!boot) { - err_global_get() = kErrorInvalidData; - return NO; - } - - rt_copy_memory_safe((VoidPtr) "fs/hefs-packet", mnt->fPacket.fPacketMime, - rt_string_len("fs/hefs-packet"), sizeof(mnt->fPacket.fPacketMime)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fInput(mnt->fPacket); - - if (!KStringBuilder::Equals(boot->fMagic, kHeFSMagic) || boot->fVersion != kHeFSVersion) { - (Void)(kout << "Invalid Boot Node, OpenHeFS partition is invalid." << kendl); - mm_free_ptr((VoidPtr) boot); - err_global_get() = kErrorDisk; - return NO; - } - - auto start = Detail::hefsi_fetch_in(boot, mnt, dir, name, kind); - - if (start) { - (Void)(kout << hex_number(start->fHashPath) << kendl); - (Void)(kout << hex_number(start->fOffsetSliceLow) << kendl); - - if (start->fOffsetSliceLow && start->fHashPath) { - mnt->fPacket.fPacketLba = ((UInt64) start->fOffsetSliceHigh << 32) | start->fOffsetSliceLow; - mnt->fPacket.fPacketSize = block_sz; - mnt->fPacket.fPacketContent = block; - - if (is_input) { - mnt->fInput(mnt->fPacket); - } else { - if (start->fFlags & kHeFSFlagsReadOnly) { - mm_free_ptr((VoidPtr) boot); - delete start; - - kout << "Error: File is read-only\r"; - - return NO; - } - - mnt->fOutput(mnt->fPacket); - } - } - } - - mm_free_ptr((VoidPtr) boot); - delete start; - return YES; -} - -/// @brief Create a new file on the disk. -/// @param mnt The mnt to write on. -/// @param flags The flags to use. -/// @param dir The directory to create the file in. -/// @param name The name of the file. -/// @return If it was sucessful, see err_local_get(). -_Output Bool HeFileSystemParser::INodeCtlManip(_Input DriveTrait* mnt, _Input const Int32 flags, - const Utf8Char* dir, const Utf8Char* name, - const BOOL delete_or_create, const UInt8 kind) { - if (urt_string_len(name) > kHeFSFileNameLen) { - err_global_get() = kErrorDisk; - return NO; - } - - if (urt_string_len(dir) > kHeFSFileNameLen) { - err_global_get() = kErrorDisk; - return NO; - } - - HEFS_INDEX_NODE* node = (HEFS_INDEX_NODE*) mm_alloc_ptr(sizeof(HEFS_INDEX_NODE), Yes, No); - - if (!node) { - err_global_get() = kErrorInvalidData; - return NO; - } - - rt_set_memory(node, 0, sizeof(HEFS_INDEX_NODE)); - - HEFS_BOOT_NODE* boot = (HEFS_BOOT_NODE*) RTL_ALLOCA(sizeof(HEFS_BOOT_NODE)); - - if (!boot) { - mm_free_ptr((VoidPtr) node); - err_global_get() = kErrorInvalidData; - - return NO; - } - - rt_copy_memory_safe((VoidPtr) "fs/hefs-packet", mnt->fPacket.fPacketMime, - rt_string_len("fs/hefs-packet"), sizeof(mnt->fPacket.fPacketMime)); - - mnt->fPacket.fPacketLba = mnt->fLbaStart; - mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = boot; - - mnt->fInput(mnt->fPacket); - - if (!KStringBuilder::Equals(boot->fMagic, kHeFSMagic) || boot->fVersion != kHeFSVersion) { - err_global_get() = kErrorDisk; - return YES; - } - - if (KStringBuilder::Equals(dir, kHeFSSearchAllStr)) { - kout << "Error: Invalid file name.\r"; - - err_global_get() = kErrorInvalidData; - return NO; - } - - for (SizeT i_name = 0UL; i_name < urt_string_len(name); ++i_name) { - if (name[i_name] == u'/') { - err_global_get() = kErrorInvalidData; - return NO; - } - } - - if (KStringBuilder::Equals(dir, kHeFSSearchAllStr)) { - kout << "Error: Invalid directory name.\r"; - - err_global_get() = kErrorInvalidData; - return NO; - } - - node->fAccessed = 0; - node->fCreated = delete_or_create ? NO : YES; - node->fDeleted = delete_or_create ? 1UL : NO; - node->fModified = 0; - node->fSize = 0; - node->fKind = kind; - node->fFlags = flags; - node->fChecksum = 0; - node->fGID = 0; - node->fUID = 0; - node->fHashPath = Detail::hefsi_hash_64(name); - - if (Detail::hefsi_update_in_status(boot, mnt, dir, node, delete_or_create)) { - mm_free_ptr((VoidPtr) node); - - Detail::hefsi_balance_ind(boot, mnt); - - err_global_get() = kErrorSuccess; - return YES; - } - - mm_free_ptr((VoidPtr) node); - err_global_get() = kErrorDirectoryNotFound; - - return NO; -} - -STATIC IMountpoint kMountpoint; - -/// @brief Initialize the OpenHeFS filesystem. -/// @return To check its status, see err_local_get(). -Boolean OpenHeFS::fs_init_openhefs(Void) noexcept { - io_construct_main_drive(kMountpoint.A()); - - if (kMountpoint.A().fPacket.fPacketReadOnly == YES) { - kout << "Main disk cannot be mounted (read-only media).\r"; - return YES; - } - - return HeFileSystemParser{}.Format(&kMountpoint.A(), kHeFSEncodingFlagsUTF8, kHeFSDefaultVolumeName); -} -} // namespace Kernel - -#endif // ifdef __FSKIT_INCLUDES_OPENHEFS__ diff --git a/dev/kernel/src/FileMgr.cc b/dev/kernel/src/FileMgr.cc deleted file mode 100644 index 88b17470..00000000 --- a/dev/kernel/src/FileMgr.cc +++ /dev/null @@ -1,49 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include - -/***********************************************************************************/ -/// @file FileMgr.cc -//! @brief File System Manager API. -///! @author Amlal El Mahrouss (amlal@nekernel.org) -/***********************************************************************************/ - -namespace Kernel { -STATIC IFilesystemMgr* kMountedFilesystem = nullptr; - -/// @brief FilesystemMgr getter. -/// @return The mounted filesystem. -_Output IFilesystemMgr* IFilesystemMgr::GetMounted() { - return kMountedFilesystem; -} - -/// @brief Unmount filesystem. -/// @return The unmounted filesystem. -_Output IFilesystemMgr* IFilesystemMgr::Unmount() { - if (kMountedFilesystem) { - auto mount = kMountedFilesystem; - kMountedFilesystem = nullptr; - - return mount; - } - - return nullptr; -} - -/// @brief Mount filesystem. -/// @param mount_ptr The filesystem to mount. -/// @return if it succeeded true, otherwise false. -_Output Bool IFilesystemMgr::Mount(_Input IFilesystemMgr* mount_ptr) { - if (mount_ptr != nullptr) { - kMountedFilesystem = mount_ptr; - return Yes; - } - - return No; -} -} // namespace Kernel diff --git a/dev/kernel/src/GUIDWizard.cc b/dev/kernel/src/GUIDWizard.cc deleted file mode 100644 index 2d1218ed..00000000 --- a/dev/kernel/src/GUIDWizard.cc +++ /dev/null @@ -1,67 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - - File: GUIDWizard.cc - Purpose: GUID helper code - - Revision History: - -======================================== */ - -#include -#include - -// begin of ascii 'readable' characters. (A, C, C, 1, 2) -#define kGUIDAsciiBegin 47 -// @brief Size of UUID. -#define kGUIDSize 37 - -namespace Kernel::CF::XRN::Version1 { -auto cf_make_sequence(const ArrayList& uuidSeq) -> Ref { - GUIDSequence* seq = new GUIDSequence(); - MUST_PASS(seq); - - Ref seq_ref{seq}; - - if (!seq) return seq_ref; - - seq_ref.Leak()->fUuid.fMs1 = uuidSeq[0]; - seq_ref.Leak()->fUuid.fMs2 = uuidSeq[1]; - seq_ref.Leak()->fUuid.fMs3 = uuidSeq[2]; - seq_ref.Leak()->fUuid.fMs4[0] = uuidSeq[3]; - seq_ref.Leak()->fUuid.fMs4[1] = uuidSeq[4]; - seq_ref.Leak()->fUuid.fMs4[2] = uuidSeq[5]; - seq_ref.Leak()->fUuid.fMs4[3] = uuidSeq[6]; - seq_ref.Leak()->fUuid.fMs4[4] = uuidSeq[7]; - seq_ref.Leak()->fUuid.fMs4[5] = uuidSeq[8]; - seq_ref.Leak()->fUuid.fMs4[6] = uuidSeq[9]; - seq_ref.Leak()->fUuid.fMs4[7] = uuidSeq[10]; - - return seq_ref; -} - -// @brief Tries to make a guid out of a string. -// This function is not complete for now -auto cf_try_guid_to_string(Ref& seq) -> ErrorOr> { - Char buf[kGUIDSize]; - - for (SizeT index = 0; index < 16; ++index) { - buf[index] = seq.Leak()->fU8[index] + kGUIDAsciiBegin; - } - - for (SizeT index = 16; index < 24; ++index) { - buf[index] = seq.Leak()->fU16[index] + kGUIDAsciiBegin; - } - - for (SizeT index = 24; index < 28; ++index) { - buf[index] = seq.Leak()->fU32[index] + kGUIDAsciiBegin; - } - - auto view = KStringBuilder::Construct(buf); - - if (view) return ErrorOr>{view.Leak()}; - - return ErrorOr>{kErrorInvalidData}; -} -} // namespace Kernel::CF::XRN::Version1 diff --git a/dev/kernel/src/GUIDWrapper.cc b/dev/kernel/src/GUIDWrapper.cc deleted file mode 100644 index ee29f911..00000000 --- a/dev/kernel/src/GUIDWrapper.cc +++ /dev/null @@ -1,9 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -namespace Kernel::CF::XRN {} diff --git a/dev/kernel/src/Gfx/FBDeviceInterface.cc b/dev/kernel/src/Gfx/FBDeviceInterface.cc deleted file mode 100644 index c5fac330..00000000 --- a/dev/kernel/src/Gfx/FBDeviceInterface.cc +++ /dev/null @@ -1,50 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -using namespace Kernel; - -/// @brief Class constructor -/// @param Out Drive output -/// @param In Drive input -/// @param Cleanup Drive cleanup. -FBDeviceInterface::FBDeviceInterface(void (*out)(DeviceInterface* self, FBDevicePacket* outpacket), - void (*in)(DeviceInterface* self, FBDevicePacket* inpacket)) - : DeviceInterface(out, in) {} - -/// @brief Class desctructor -FBDeviceInterface::~FBDeviceInterface() = default; - -/// @brief Output operator. -/// @param mnt the disk mountpoint. -/// @return the class itself after operation. -FBDeviceInterface& FBDeviceInterface::operator<<(FBDevicePacket* pckt) { - if (!pckt) return *this; - - if (pckt->fHeight == 0 || pckt->fWidth == 0) return *this; - - this->fOut(this, pckt); - - return *this; -} - -/// @brief Input operator. -/// @param mnt the disk mountpoint. -/// @return the class itself after operation. -FBDeviceInterface& FBDeviceInterface::operator>>(FBDevicePacket* pckt) { - if (!pckt) return *this; - - this->fIn(this, pckt); - - return *this; -} - -/// @brief Returns the name of the device interface. -/// @return it's name as a string. -const Char* FBDeviceInterface::Name() const { - return "/devices/fb{}"; -} \ No newline at end of file diff --git a/dev/kernel/src/HardwareThreadScheduler.cc b/dev/kernel/src/HardwareThreadScheduler.cc deleted file mode 100644 index 41d927f6..00000000 --- a/dev/kernel/src/HardwareThreadScheduler.cc +++ /dev/null @@ -1,184 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include -#include -#include - -/***********************************************************************************/ -///! @file HardwareThreadScheduler.cc -///! @brief This file handles multi processing in the Kernel. -///! @brief Multi processing is needed for multi-tasking operations. -/***********************************************************************************/ - -namespace Kernel { -/***********************************************************************************/ -/// @note Those symbols are needed in order to switch and validate the stack. -/***********************************************************************************/ - -EXTERN_C Bool hal_check_task(HAL::StackFramePtr frame); -EXTERN_C Bool mp_register_task(HAL::StackFramePtr frame, ProcessID pid); - -STATIC HardwareThreadScheduler kHardwareThreadScheduler; - -///! A HardwareThread class takes care of it's owned hardware thread. -///! It has a stack for it's core. - -/***********************************************************************************/ -///! @brief C++ constructor. -/***********************************************************************************/ -HardwareThread::HardwareThread() = default; - -/***********************************************************************************/ -///! @brief C++ destructor. -/***********************************************************************************/ -HardwareThread::~HardwareThread() = default; - -/***********************************************************************************/ -//! @brief returns the id of the thread. -/***********************************************************************************/ -ThreadID& HardwareThread::ID() noexcept { - return fID; -} - -/***********************************************************************************/ -//! @brief returns the kind of thread we have. -/***********************************************************************************/ -ThreadKind& HardwareThread::Kind() noexcept { - return fKind; -} - -/***********************************************************************************/ -//! @brief is the thread busy? -//! @return whether the thread is busy or not. -/***********************************************************************************/ -Bool HardwareThread::IsBusy() noexcept { - return fBusy; -} - -/***********************************************************************************/ -/// @brief Get processor stack frame. -/***********************************************************************************/ - -HAL::StackFramePtr HardwareThread::StackFrame() noexcept { - MUST_PASS(this->fStack); - return this->fStack; -} - -Void HardwareThread::Busy(Bool busy) noexcept { - this->fBusy = busy; -} - -HardwareThread::operator bool() { - return this->fStack && !this->fBusy; -} - -/***********************************************************************************/ -/// @brief Wakeup the processor. -/***********************************************************************************/ - -Void HardwareThread::Wake(const bool wakeup) noexcept { - this->fWakeup = wakeup; -} - -/***********************************************************************************/ -/// @brief Switch to hardware thread. -/// @param stack the new hardware thread. -/// @retval true stack was changed, code is running. -/// @retval false stack is invalid, previous code is running. -/***********************************************************************************/ -Bool HardwareThread::Switch(HAL::StackFramePtr frame) { - if (!frame) { - return NO; - } - - if (!hal_check_task(frame)) { - return NO; - } - - this->fStack = frame; - return mp_register_task(fStack, this->fID); -} - -/***********************************************************************************/ -///! @brief Tells if processor is waked up. -/***********************************************************************************/ -bool HardwareThread::IsWakeup() noexcept { - return this->fWakeup; -} - -/***********************************************************************************/ -///! @brief Constructor and destructors. -///! @brief Default constructor. -/***********************************************************************************/ - -HardwareThreadScheduler::HardwareThreadScheduler() = default; - -/***********************************************************************************/ -///! @brief Default destructor. -/***********************************************************************************/ -HardwareThreadScheduler::~HardwareThreadScheduler() = default; - -/***********************************************************************************/ -/// @brief Shared singleton function -/***********************************************************************************/ -HardwareThreadScheduler& HardwareThreadScheduler::The() { - return kHardwareThreadScheduler; -} - -/***********************************************************************************/ -/// @brief Get Stack Frame of AP. -/***********************************************************************************/ -HAL::StackFramePtr HardwareThreadScheduler::Leak() noexcept { - return fThreadList[fCurrentThreadIdx].fStack; -} - -/***********************************************************************************/ -/** - * Get Hardware thread at index. - * @param idx the index - * @return the reference to the hardware thread. - */ -/***********************************************************************************/ -Ref HardwareThreadScheduler::operator[](SizeT idx) { - if (idx > kMaxAPInsideSched) { - HardwareThread* kFakeThread = nullptr; - return {kFakeThread}; - } - - fCurrentThreadIdx = idx; - return &fThreadList[idx]; -} - -/***********************************************************************************/ -/** - * Check if thread pool isn't empty. - * @return - */ -/***********************************************************************************/ -HardwareThreadScheduler::operator bool() noexcept { - return !fThreadList.Empty(); -} - -/***********************************************************************************/ -/** - * Reverse operator bool - * @return - */ -/***********************************************************************************/ -bool HardwareThreadScheduler::operator!() noexcept { - return fThreadList.Empty(); -} - -/***********************************************************************************/ -/// @brief Returns the amount of core present. -/// @return the number of APs. -/***********************************************************************************/ -SizeT HardwareThreadScheduler::Capacity() noexcept { - return fThreadList.Count(); -} -} // namespace Kernel diff --git a/dev/kernel/src/HeapMgr.cc b/dev/kernel/src/HeapMgr.cc deleted file mode 100644 index 848a0377..00000000 --- a/dev/kernel/src/HeapMgr.cc +++ /dev/null @@ -1,260 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include -#include -#include -#include -#include -#include - -/* ======================================== - - Revision History: - 10/8/24: FIX: Fix useless long name, alongside a new WR (WriteRead) field. - 20/10/24: FIX: Fix mm_new_ and mm_delete_ APIs inside HeapMgr.h header. (amlal) - 27/01/25: REFACTOR: Reworked code as the memory manager. - 25/03/25: REFACTOR: Refactor HeapMgr code and log freed address location. - - ======================================== */ - -//! @file HeapMgr.cc -//! @brief Heap system that serves as the main memory manager. - -#define kHeapMgrMagic (0xD4D75) -#define kHeapMgrAlignSz (4U) - -namespace Kernel { -/// @brief Implementation details. -namespace Detail { - struct PACKED MM_INFORMATION_BLOCK; - - /// @brief Kernel heap information block. - /// Located before the address bytes. - /// | HIB | CLASS/STRUCT/DATA TYPES... | - struct PACKED MM_INFORMATION_BLOCK final { - ///! @brief 32-bit value which contains the magic number of the heap. - UInt32 fMagic : 24; - - ///! @brief Is the heap present? - UInt8 fPresent : 1; - - /// @brief Is this value writable? - UInt8 fWriteRead : 1; - - /// @brief Is this value owned by the user? - UInt8 fUser : 1; - - /// @brief Is this a page pointer? - UInt8 fPage : 1; - - /// @brief 32-bit CRC checksum. - UInt32 fCRC32; - - /// @brief 64-bit Allocation flags. - UInt16 fFlags; - - /// @brief 64-bit pointer size. - SizeT fSize; - - /// @brief 64-bit target offset pointer. - UIntPtr fOffset; - - /// @brief Padding. - UInt32 fPad; - - /// @brief Padding bytes for header. - UInt8 fPadding[kHeapMgrAlignSz]; - }; - - /// @brief Check for heap address validity. - /// @param heap_ptr The address_ptr to check. - /// @return Bool if the pointer is valid or not. - _Output auto mm_check_ptr_address(VoidPtr heap_ptr) -> Bool { - if (!heap_ptr) return false; - - IntPtr base_ptr = ((IntPtr) heap_ptr) - sizeof(Detail::MM_INFORMATION_BLOCK); - - /// Add that check in case we're having an integer underflow. /// - - if (base_ptr < 0) { - return false; - } - - return true; - } - - typedef MM_INFORMATION_BLOCK* MM_INFORMATION_BLOCK_PTR; -} // namespace Detail - -STATIC PageMgr kPageMgr; - -/// @brief Allocate chunk of memory. -/// @param sz Size of pointer -/// @param wr Read Write bit. -/// @param user User enable bit. -/// @return The newly allocated pointer. -_Output VoidPtr mm_alloc_ptr(SizeT sz, Bool wr, Bool user, SizeT pad_amount) { - auto sz_fix = sz; - - if (sz_fix == 0) return nullptr; - - sz_fix += sizeof(Detail::MM_INFORMATION_BLOCK); - - auto wrapper = kPageMgr.Request(wr, user, No, sz_fix, pad_amount); - - Detail::MM_INFORMATION_BLOCK_PTR heap_info_ptr = - reinterpret_cast(wrapper.VirtualAddress() + - sizeof(Detail::MM_INFORMATION_BLOCK)); - - heap_info_ptr->fSize = sz_fix; - heap_info_ptr->fMagic = kHeapMgrMagic; - heap_info_ptr->fCRC32 = 0U; // dont fill it for now. - heap_info_ptr->fOffset = - reinterpret_cast(heap_info_ptr) + sizeof(Detail::MM_INFORMATION_BLOCK); - heap_info_ptr->fPage = No; - heap_info_ptr->fWriteRead = wr; - heap_info_ptr->fUser = user; - heap_info_ptr->fPresent = Yes; - heap_info_ptr->fPad = pad_amount; - - rt_set_memory(heap_info_ptr->fPadding, 0, kHeapMgrAlignSz); - - auto result = reinterpret_cast(heap_info_ptr->fOffset); - - (Void)(kout << "HeapMgr: Registered heap address: " - << hex_number(reinterpret_cast(heap_info_ptr)) << kendl); - - return result; -} - -/// @brief Makes a page heap. -/// @param heap_ptr the pointer to make a page heap. -/// @return kErrorSuccess if successful, otherwise an error code. -_Output Int32 mm_make_page(VoidPtr heap_ptr) { - if (Detail::mm_check_ptr_address(heap_ptr) == No) return kErrorHeapNotPresent; - - Detail::MM_INFORMATION_BLOCK_PTR heap_info_ptr = - reinterpret_cast((UIntPtr) heap_ptr - - sizeof(Detail::MM_INFORMATION_BLOCK)); - - if (!heap_info_ptr) return kErrorHeapNotPresent; - - heap_info_ptr->fPage = true; - - (Void)(kout << "HeapMgr: Registered page from heap address: " - << hex_number(reinterpret_cast(heap_info_ptr)) << kendl); - - return kErrorSuccess; -} - -/// @brief Overwrites and set the flags of a heap header. -/// @param heap_ptr the pointer to update. -/// @param flags the flags to set. -_Output Int32 mm_set_ptr_flags(VoidPtr heap_ptr, UInt64 flags) { - if (Detail::mm_check_ptr_address(heap_ptr) == No) return kErrorHeapNotPresent; - - Detail::MM_INFORMATION_BLOCK_PTR heap_info_ptr = - reinterpret_cast((UIntPtr) heap_ptr - - sizeof(Detail::MM_INFORMATION_BLOCK)); - - if (!heap_info_ptr) return kErrorHeapNotPresent; - - heap_info_ptr->fFlags = flags; - - return kErrorSuccess; -} - -/// @brief Gets the flags of a heap header. -/// @param heap_ptr the pointer to get. -_Output UInt64 mm_get_ptr_flags(VoidPtr heap_ptr) { - Detail::MM_INFORMATION_BLOCK_PTR heap_info_ptr = - reinterpret_cast((UIntPtr) heap_ptr - - sizeof(Detail::MM_INFORMATION_BLOCK)); - - if (!heap_info_ptr) return kErrorHeapNotPresent; - - return heap_info_ptr->fFlags; -} - -/// @brief Declare pointer as free. -/// @param heap_ptr the pointer. -/// @return -_Output Int32 mm_free_ptr(VoidPtr heap_ptr) { - if (Detail::mm_check_ptr_address(heap_ptr) == No) return kErrorHeapNotPresent; - - Detail::MM_INFORMATION_BLOCK_PTR heap_info_ptr = - reinterpret_cast((UIntPtr) (heap_ptr) - - sizeof(Detail::MM_INFORMATION_BLOCK)); - - if (heap_info_ptr && heap_info_ptr->fMagic == kHeapMgrMagic) { - if (!heap_info_ptr->fPresent) { - return kErrorHeapNotPresent; - } - - heap_info_ptr->fSize = 0UL; - heap_info_ptr->fPresent = No; - heap_info_ptr->fOffset = 0; - heap_info_ptr->fCRC32 = 0; - heap_info_ptr->fWriteRead = No; - heap_info_ptr->fUser = No; - heap_info_ptr->fMagic = 0; - heap_info_ptr->fPad = 0; - - (Void)(kout << "HeapMgr: Freed heap address: " - << hex_number(reinterpret_cast(heap_info_ptr)) << kendl); - - PTEWrapper page_wrapper( - No, No, No, - reinterpret_cast(heap_info_ptr) - sizeof(Detail::MM_INFORMATION_BLOCK)); - - Ref pte_address{page_wrapper}; - - kPageMgr.Free(pte_address); - - return kErrorSuccess; - } - - return kErrorInternal; -} - -/// @brief Check if pointer is a valid Kernel pointer. -/// @param heap_ptr the pointer -/// @return if it exists. -_Output Boolean mm_is_valid_ptr(VoidPtr heap_ptr) { - if (heap_ptr && HAL::mm_is_bitmap(heap_ptr)) { - Detail::MM_INFORMATION_BLOCK_PTR heap_info_ptr = - reinterpret_cast((UIntPtr) (heap_ptr) - - sizeof(Detail::MM_INFORMATION_BLOCK)); - - return (heap_info_ptr && heap_info_ptr->fPresent && heap_info_ptr->fMagic == kHeapMgrMagic); - } - - return No; -} - -/// @brief Protect the heap with a CRC value. -/// @param heap_ptr HIB pointer. -/// @return if it valid: point has crc now., otherwise fail. -_Output Boolean mm_protect_ptr(VoidPtr heap_ptr) { - if (heap_ptr) { - Detail::MM_INFORMATION_BLOCK_PTR heap_info_ptr = - reinterpret_cast((UIntPtr) heap_ptr - - sizeof(Detail::MM_INFORMATION_BLOCK)); - - /// if valid, present and is heap header, then compute crc32 - if (heap_info_ptr && heap_info_ptr->fPresent && kHeapMgrMagic == heap_info_ptr->fMagic) { - heap_info_ptr->fCRC32 = - ke_calculate_crc32((Char*) heap_info_ptr->fOffset, heap_info_ptr->fSize); - - return Yes; - } - } - - return No; -} -} // namespace Kernel diff --git a/dev/kernel/src/IDylibObject.cc b/dev/kernel/src/IDylibObject.cc deleted file mode 100644 index 61191af1..00000000 --- a/dev/kernel/src/IDylibObject.cc +++ /dev/null @@ -1,13 +0,0 @@ -/* - * ======================================================== - * - * NeKernel - * Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - * - * ======================================================== - */ - -#include -#include - -using namespace Kernel; diff --git a/dev/kernel/src/IFS.cc b/dev/kernel/src/IFS.cc deleted file mode 100644 index 4679b8a3..00000000 --- a/dev/kernel/src/IFS.cc +++ /dev/null @@ -1,89 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include - -/************************************************************* - * - * File: IFS.cc - * Purpose: Filesystem to mountpoint interface. - * Date: 05/26/2025 - * - * Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - * - *************************************************************/ - -/// Useful macros regarding the IFS. - -#define fsi_ifs_write(DRV, TRAITS, MP) (MP->DRV()).fOutput(TRAITS) -#define fsi_ifs_read(DRV, TRAITS, MP) (MP->DRV()).fInput(TRAITS) - -namespace Kernel { -/// @brief Read from fs disk. -/// @param Mnt mounted interface. -/// @param DrvTrait drive info -/// @param DrvIndex drive index. -/// @return -Int32 fs_ifs_read(IMountpoint* Mnt, DriveTrait& DrvTrait, Int32 DrvIndex) { - if (!Mnt) return kErrorDisk; - - DrvTrait.fPacket.fPacketGood = false; - - switch (DrvIndex) { - case IMountpoint::kDriveIndexA: { - fsi_ifs_read(A, DrvTrait.fPacket, Mnt); - break; - } - case IMountpoint::kDriveIndexB: { - fsi_ifs_read(B, DrvTrait.fPacket, Mnt); - break; - } - case IMountpoint::kDriveIndexC: { - fsi_ifs_read(C, DrvTrait.fPacket, Mnt); - break; - } - case IMountpoint::kDriveIndexD: { - fsi_ifs_read(D, DrvTrait.fPacket, Mnt); - break; - } - } - - return DrvTrait.fPacket.fPacketGood ? kErrorSuccess : kErrorDisk; -} - -/// @brief Write to fs disk. -/// @param Mnt mounted interface. -/// @param DrvTrait drive info -/// @param DrvIndex drive index. -/// @return -Int32 fs_ifs_write(IMountpoint* Mnt, DriveTrait& DrvTrait, Int32 DrvIndex) { - if (!Mnt) return kErrorDisk; - - DrvTrait.fPacket.fPacketGood = false; - - switch (DrvIndex) { - case IMountpoint::kDriveIndexA: { - fsi_ifs_write(A, DrvTrait.fPacket, Mnt); - break; - } - case IMountpoint::kDriveIndexB: { - fsi_ifs_write(B, DrvTrait.fPacket, Mnt); - break; - } - case IMountpoint::kDriveIndexC: { - fsi_ifs_write(C, DrvTrait.fPacket, Mnt); - break; - } - case IMountpoint::kDriveIndexD: { - fsi_ifs_write(D, DrvTrait.fPacket, Mnt); - break; - } - } - - return DrvTrait.fPacket.fPacketGood ? kErrorSuccess : kErrorDisk; -} -} // namespace Kernel \ No newline at end of file diff --git a/dev/kernel/src/IPEFDylibObject.cc b/dev/kernel/src/IPEFDylibObject.cc deleted file mode 100644 index 4ba9278d..00000000 --- a/dev/kernel/src/IPEFDylibObject.cc +++ /dev/null @@ -1,109 +0,0 @@ -/* - * ======================================================== - * - * NeKernel - * Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - * - * ======================================================== - */ - -#include -#include -#include -#include -#include -#include - -/* ======================================== - - Revision History: - - 01/02/24: Reworked dll ABI, expect a rtl_init_dylib_pef and - rtl_fini_dylib_pef (amlel) - - 15/02/24: Breaking changes, changed the name of the - routines. (amlel) - - 07/28/24: Replace rt_library_free with rtl_fini_dylib_pef - - 10/8/24: FIX: Fix log comment. - - ======================================== */ - -using namespace Kernel; - -/***********************************************************************************/ -/// @file IPEFDylibObject.cc -/// @brief PEF's Dylib runtime. -///! @author Amlal El Mahrouss (amlal@nekernel.org) -/***********************************************************************************/ - -/***********************************************************************************/ -/** @brief Library initializer. */ -/***********************************************************************************/ - -EXTERN_C IDylibRef rtl_init_dylib_pef(USER_PROCESS& process) { - IDylibRef dll_obj = tls_new_class(); - - if (!dll_obj) { - process.Crash(); - return nullptr; - } - - dll_obj->Mount(new IPEFDylibObject::DylibTraits()); - - if (!dll_obj->Get()) { - tls_delete_class(dll_obj); - dll_obj = nullptr; - - process.Crash(); - - return nullptr; - } - - dll_obj->Get()->ImageObject = process.Image.LeakBlob().Leak().Leak(); - - if (!dll_obj->Get()->ImageObject) { - delete dll_obj->Get(); - - tls_delete_class(dll_obj); - dll_obj = nullptr; - - process.Crash(); - - return nullptr; - } - - dll_obj->Get()->ImageEntrypointOffset = - dll_obj->Load(kPefStart, rt_string_len(kPefStart, 0), kPefCode); - - return dll_obj; -} - -/***********************************************************************************/ -/** @brief Frees the dll_obj. */ -/** @note Please check if the dll_obj got freed! */ -/** @param dll_obj The dll_obj to free. */ -/** @param successful Reports if successful or not. */ -/***********************************************************************************/ - -EXTERN_C Void rtl_fini_dylib_pef(USER_PROCESS& process, IDylibRef dll_obj, BOOL* successful) { - MUST_PASS(successful); - - if (!successful) { - return; - } - - // sanity check (will also trigger a bug check if this fails) - if (dll_obj == nullptr) { - *successful = false; - process.Crash(); - } - - delete dll_obj->Get(); - delete dll_obj; - - dll_obj = nullptr; - - *successful = true; -} diff --git a/dev/kernel/src/IndexableProperty.cc b/dev/kernel/src/IndexableProperty.cc deleted file mode 100644 index 85207d4b..00000000 --- a/dev/kernel/src/IndexableProperty.cc +++ /dev/null @@ -1,45 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include -#include -#include -#include -#include - -/// @brief File indexer API for fast path access. -/// BUGS: 0 - -#define kMaxLenIndexer (256U) - -namespace Kernel { -namespace Indexer { - Index& IndexableProperty::Leak() noexcept { return fIndex; } - - Void IndexableProperty::AddFlag(UInt16 flag) { fFlags |= flag; } - - Void IndexableProperty::RemoveFlag(UInt16 flag) { fFlags &= ~(flag); } - - UInt16 IndexableProperty::HasFlag(UInt16 flag) { return fFlags & flag; } - - /// @brief Index a file into the indexer instance. - /// @param filename filesystem path to access. - /// @param filenameLen used bytes in path. - /// @param indexer the filesystem indexer. - /// @return none, check before if indexer can be claimed (using indexer.HasFlag(kIndexerClaimed)). - Void fs_index_file(const Char* filename, SizeT filenameLen, IndexableProperty& indexer) { - if (!indexer.HasFlag(kIndexerClaimed)) { - indexer.RemoveFlag(kIndexerUnclaimed); - indexer.AddFlag(kIndexerClaimed); - rt_copy_memory_safe(reinterpret_cast(const_cast(filename)), - (VoidPtr) indexer.Leak().Path, filenameLen, kIndexerCatalogNameLength); - - (Void)(kout << "FSKit: Indexed new file: " << filename << kendl); - } - } -} // namespace Indexer -} // namespace Kernel diff --git a/dev/kernel/src/Json.cc b/dev/kernel/src/Json.cc deleted file mode 100644 index 198aed99..00000000 --- a/dev/kernel/src/Json.cc +++ /dev/null @@ -1,9 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -namespace Kernel {} \ No newline at end of file diff --git a/dev/kernel/src/KPC.cc b/dev/kernel/src/KPC.cc deleted file mode 100644 index 4318b9cd..00000000 --- a/dev/kernel/src/KPC.cc +++ /dev/null @@ -1,39 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include -#include - -namespace Kernel { -STATIC Bool kRaiseOnBugCheck = false; - -/// @brief Does a system wide bug check. -/// @param void no params are needed. -/// @return if error-free: false, otherwise true. -Boolean err_bug_check_raise(Void) noexcept { - Char* ptr = new Char[512]; - - if (ptr == nullptr) goto bug_check_fail; - - if (!mm_is_valid_ptr(ptr)) goto bug_check_fail; - - delete[] ptr; - - return Yes; - -bug_check_fail: - if (ptr) delete[] ptr; - - ptr = nullptr; - - if (kRaiseOnBugCheck) { - ke_panic(RUNTIME_CHECK_BAD_BEHAVIOR); - } - - return No; -} -} // namespace Kernel diff --git a/dev/kernel/src/KernelTaskScheduler.cc b/dev/kernel/src/KernelTaskScheduler.cc deleted file mode 100644 index c3628765..00000000 --- a/dev/kernel/src/KernelTaskScheduler.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* ======================================== - - Copyright (C) 2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - - FILE: KernelTaskScheduler.cc - PURPOSE: Kernel Task scheduler. - -======================================== */ - -#include - -/***********************************************************************************/ -/// @file KernelTaskScheduler.cc -/// @brief Kernel Task scheduler. -/// @author Amlal El Mahrouss (amlal@nekernel.org) -/***********************************************************************************/ - -namespace Kernel { -EXTERN_C Void hal_switch_kernel_task(HAL::StackFramePtr frame, KID kid); - -Bool KernelTaskHelper::Add(HAL::StackFramePtr frame_ptr, KID new_kid) { - NE_UNUSED(frame_ptr); - NE_UNUSED(new_kid); - - return NO; -} - -Bool KernelTaskHelper::Remove(const KID kid) { - NE_UNUSED(kid); - - return NO; -} - -Bool KernelTaskHelper::CanBeScheduled(const KERNEL_TASK& task) { - return task.Kid > 0 && task.Image.HasCode(); -} -} // namespace Kernel \ No newline at end of file diff --git a/dev/kernel/src/LockDelegate.cc b/dev/kernel/src/LockDelegate.cc deleted file mode 100644 index 2fe2b464..00000000 --- a/dev/kernel/src/LockDelegate.cc +++ /dev/null @@ -1,11 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -namespace Kernel { -/// @note Leave it empty for now. -} // namespace Kernel diff --git a/dev/kernel/src/MutableArray.cc b/dev/kernel/src/MutableArray.cc deleted file mode 100644 index 3c86e8b8..00000000 --- a/dev/kernel/src/MutableArray.cc +++ /dev/null @@ -1,7 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include diff --git a/dev/kernel/src/Network/IPAddress.cc b/dev/kernel/src/Network/IPAddress.cc deleted file mode 100644 index 98279979..00000000 --- a/dev/kernel/src/Network/IPAddress.cc +++ /dev/null @@ -1,113 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include - -namespace Kernel { -UInt8* RawIPAddress::Address() { - return fAddr; -} - -RawIPAddress::RawIPAddress(UInt8 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; -} - -UInt8& RawIPAddress::operator[](const Size& index) { - kout << "[RawIPAddress::operator[]] Fetching Index...\r"; - - static UInt8 IP_PLACEHOLDER = '0'; - if (index >= 4) return IP_PLACEHOLDER; - - return fAddr[index]; -} - -RawIPAddress6::RawIPAddress6(UInt8 bytes[16]) { - rt_copy_memory(bytes, fAddr, 16); -} - -UInt8& RawIPAddress6::operator[](const Size& index) { - kout << "[RawIPAddress6::operator[]] Fetching Index...\r"; - - static UInt8 IP_PLACEHOLDER = '0'; - if (index >= 16) return IP_PLACEHOLDER; - - return fAddr[index]; -} - -bool RawIPAddress6::operator==(const RawIPAddress6& ipv6) { - for (SizeT index = 0; index < 16; ++index) { - if (ipv6.fAddr[index] != fAddr[index]) return false; - } - - return true; -} - -bool RawIPAddress6::operator!=(const RawIPAddress6& ipv6) { - for (SizeT index = 0; index < 16; ++index) { - if (ipv6.fAddr[index] == fAddr[index]) return false; - } - - return true; -} - -/// @todo -ErrorOr IPFactory::ToKString(Ref& ipv6) { - NE_UNUSED(ipv6); - auto str = KStringBuilder::Construct(""); - return str; -} - -/// @todo -ErrorOr IPFactory::ToKString(Ref& ipv4) { - NE_UNUSED(ipv4); - auto str = KStringBuilder::Construct(""); - return str; -} - -/// @note Doesn't catch IPs such as 256.999.0.1, UNSAFE! -bool IPFactory::IpCheckVersion4(const Char* ip) { - if (!ip) return NO; - - Int32 cnter = 0; - Int32 dot_cnter = 0; - - constexpr const auto kIP4DotCharacter = '.'; - - for (SizeT base = 0; base < rt_string_len(ip); ++base) { - if (ip[base] == kIP4DotCharacter) { - cnter = 0; - ++dot_cnter; - } else { - if (ip[base] > '5' || ip[base] < '0') return NO; - if (!rt_is_alnum(ip[base])) return NO; - if (cnter == 3) return NO; - - ++cnter; - } - } - - if (dot_cnter != 3) return NO; - - return YES; -} -} // namespace Kernel diff --git a/dev/kernel/src/Network/IPCAddress.cc b/dev/kernel/src/Network/IPCAddress.cc deleted file mode 100644 index 2da5ac0a..00000000 --- a/dev/kernel/src/Network/IPCAddress.cc +++ /dev/null @@ -1,27 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - - ======================================== */ - -#include -#include -#include - -namespace Kernel { -bool IPC_ADDR::operator==(const IPC_ADDR& addr) noexcept { - return addr.UserProcessID == this->UserProcessID && addr.UserProcessTeam == this->UserProcessTeam; -} - -bool IPC_ADDR::operator==(IPC_ADDR& addr) noexcept { - return addr.UserProcessID == this->UserProcessID && addr.UserProcessTeam == this->UserProcessTeam; -} - -bool IPC_ADDR::operator!=(const IPC_ADDR& addr) noexcept { - return addr.UserProcessID != this->UserProcessID || addr.UserProcessTeam != this->UserProcessTeam; -} - -bool IPC_ADDR::operator!=(IPC_ADDR& addr) noexcept { - return addr.UserProcessID != this->UserProcessID || addr.UserProcessTeam != this->UserProcessTeam; -} -} // namespace Kernel diff --git a/dev/kernel/src/Network/IPCMessage.cc b/dev/kernel/src/Network/IPCMessage.cc deleted file mode 100644 index b376b7c8..00000000 --- a/dev/kernel/src/Network/IPCMessage.cc +++ /dev/null @@ -1,129 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include -#include - -namespace Kernel { -/***********************************************************************************/ -/// @internal internal use for IPC system only. -/// @brief The internal sanitize function. -/***********************************************************************************/ -Bool ipc_int_sanitize_packet(IPC_MSG* pckt) { - auto endian = RTL_ENDIAN(pckt, ((Char*) pckt)[0]); - - switch (endian) { - case Endian::kEndianBig: { - if (pckt->IpcEndianess == kIPCLittleEndian) goto ipc_check_failed; - - break; - } - case Endian::kEndianLittle: { - if (pckt->IpcEndianess == kIPCBigEndian) goto ipc_check_failed; - - break; - } - case Endian::kEndianMixed: { - if (pckt->IpcEndianess == kIPCMixedEndian) goto ipc_check_failed; - - break; - } - default: - goto ipc_check_failed; - } - - if (pckt->IpcFrom == pckt->IpcTo || pckt->IpcPacketSize > kIPCMsgSize) { - goto ipc_check_failed; - } - - return pckt->IpcPacketSize > 1 && pckt->IpcHeaderMagic == kIPCHeaderMagic; - -ipc_check_failed: - err_local_get() = kErrorIPC; - return false; -} - -/***********************************************************************************/ -/// @brief Sanitize packet function -/// @retval true packet is correct. -/// @retval false packet is incorrect and process has crashed. -/***********************************************************************************/ -Bool ipc_sanitize_packet(IPC_MSG* pckt) { - if (!pckt || !ipc_int_sanitize_packet(pckt)) { - return false; - } - - return true; -} - -/***********************************************************************************/ -/// @brief Construct packet function -/// @retval true packet is correct. -/// @retval false packet is incorrect and process has crashed. -/***********************************************************************************/ -Bool ipc_construct_packet(_Output IPC_MSG** pckt_in) { - // don't act if it's not even valid. - if (!pckt_in) return false; - - if (!*pckt_in) *pckt_in = new IPC_MSG(); - - MUST_PASS(*pckt_in); - - if (*pckt_in) { - const auto endianess = RTL_ENDIAN((*pckt_in), ((Char*) (*pckt_in))[0]); - - (*pckt_in)->IpcHeaderMagic = kIPCHeaderMagic; - - (*pckt_in)->IpcEndianess = static_cast(endianess); - (*pckt_in)->IpcPacketSize = sizeof(IPC_MSG); - - (*pckt_in)->IpcTo.UserProcessID = 0; - (*pckt_in)->IpcTo.UserProcessTeam = 0; - - (*pckt_in)->IpcFrom.UserProcessID = 0; - (*pckt_in)->IpcFrom.UserProcessTeam = 0; - - (*pckt_in)->IpcLock = kIPCLockFree; - - return Yes; - } - - return No; -} - -/***********************************************************************************/ -/// @brief Pass message from **src** to **target** -/// @param src Source message. -/// @param target Target message. -/***********************************************************************************/ -Bool IPC_MSG::Pass(IPC_MSG* src, IPC_MSG* target) noexcept { - if (src && target && (target != src)) { - if (src->IpcMsgSz > target->IpcMsgSz) return No; - if (target->IpcMsgSz > src->IpcMsgSz) return No; - - auto timeout = 0U; - - const auto kLimitTimeout = 1000000U; - - while ((target->IpcLock % kIPCLockUsed) != 0) { - if (timeout > kLimitTimeout) { - return No; - } - } - - ++target->IpcLock; - - rt_copy_memory_safe(src->IpcData, target->IpcData, src->IpcMsgSz, kIPCMsgSize); - - --target->IpcLock; - - return Yes; - } - - return No; -} -} // namespace Kernel diff --git a/dev/kernel/src/Network/MACAddressGetter.cc b/dev/kernel/src/Network/MACAddressGetter.cc deleted file mode 100644 index 09d82a78..00000000 --- a/dev/kernel/src/Network/MACAddressGetter.cc +++ /dev/null @@ -1,13 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -namespace Kernel { -Array& MacAddressGetter::AsBytes() { - return this->fMacAddress; -} -} // namespace Kernel diff --git a/dev/kernel/src/Network/NetworkDevice.cc b/dev/kernel/src/Network/NetworkDevice.cc deleted file mode 100644 index 450c0191..00000000 --- a/dev/kernel/src/Network/NetworkDevice.cc +++ /dev/null @@ -1,29 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include - -namespace Kernel { -/// \brief Getter for fNetworkName. -/// \return Network device name. -const Char* NetworkDevice::Name() const { - return "/devices/net/net{}"; -} - -/// \brief Setter for fNetworkName. -Boolean NetworkDevice::Name(const Char* name) { - if (name == nullptr) return NO; - - if (*name == 0) return NO; - - if (rt_string_len(name) > rt_string_len(this->Name())) return NO; - - rt_copy_memory((VoidPtr) name, (VoidPtr) this->Name(), rt_string_len(this->Name())); - - return YES; -} -} // namespace Kernel diff --git a/dev/kernel/src/New+Delete.cc b/dev/kernel/src/New+Delete.cc deleted file mode 100644 index ba37e7ec..00000000 --- a/dev/kernel/src/New+Delete.cc +++ /dev/null @@ -1,48 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include - -void* operator new[](size_t sz) { - if (sz == 0) ++sz; - - return Kernel::mm_alloc_ptr(sz, true, false); -} - -void* operator new(size_t sz) { - if (sz == 0) ++sz; - - return Kernel::mm_alloc_ptr(sz, true, false); -} - -void operator delete[](void* ptr) noexcept { - if (ptr == nullptr) return; - - Kernel::mm_free_ptr(ptr); -} - -void operator delete(void* ptr) noexcept { - if (ptr == nullptr) return; - - Kernel::mm_free_ptr(ptr); -} - -void operator delete(void* ptr, size_t sz) { - if (ptr == nullptr) return; - - NE_UNUSED(sz); - - Kernel::mm_free_ptr(ptr); -} - -void operator delete[](void* ptr, size_t sz) { - if (ptr == nullptr) return; - - NE_UNUSED(sz); - - Kernel::mm_free_ptr(ptr); -} diff --git a/dev/kernel/src/OwnPtr.cc b/dev/kernel/src/OwnPtr.cc deleted file mode 100644 index e223d448..00000000 --- a/dev/kernel/src/OwnPtr.cc +++ /dev/null @@ -1,7 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include diff --git a/dev/kernel/src/PE32CodeMgr.cc b/dev/kernel/src/PE32CodeMgr.cc deleted file mode 100644 index a8440c23..00000000 --- a/dev/kernel/src/PE32CodeMgr.cc +++ /dev/null @@ -1,258 +0,0 @@ -/* ======================================== - - Copyright (C) 2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Kernel { -namespace Detail { - /***********************************************************************************/ - /// @brief Get the PE32+ platform signature according to the compiled architecture. - /***********************************************************************************/ - - UInt32 ldr_get_platform_pe(void) noexcept { -#if defined(__NE_AMD64__) - return kPEPlatformAMD64; -#elif defined(__NE_ARM64__) - return kPEPlatformARM64; -#else - return kPEPlatformInvalid; -#endif // __32x0__ || __64x0__ || __x86_64__ - } -} // namespace Detail - -/***********************************************************************************/ -/// @brief PE32+ loader constructor w/ blob. -/// @param blob file blob. -/***********************************************************************************/ - -PE32Loader::PE32Loader(const VoidPtr blob) : fCachedBlob(blob) { - MUST_PASS(fCachedBlob); - fBad = false; -} - -/***********************************************************************************/ -/// @brief PE32+ loader constructor. -/// @param path the filesystem path. -/***********************************************************************************/ - -PE32Loader::PE32Loader(const Char* path) : fCachedBlob(nullptr), fBad(false) { - fFile.New(const_cast(path), kRestrictRB); - fPath = KStringBuilder::Construct(path).Leak(); - - auto kPefHeader = "PE32_BLOB"; - fCachedBlob = fFile->Read(kPefHeader, 0); - - if (!fCachedBlob) fBad = YES; -} - -/***********************************************************************************/ -/// @brief PE32+ destructor. -/***********************************************************************************/ - -PE32Loader::~PE32Loader() { - if (fCachedBlob) mm_free_ptr(fCachedBlob); - - fFile.Delete(); -} - -/***********************************************************************************/ -/// @brief Finds the section according to its name. -/// @param name name of section. -/***********************************************************************************/ - -ErrorOr PE32Loader::FindSectionByName(const Char* name) { - if (!fCachedBlob || fBad || !name) return ErrorOr{kErrorInvalidData}; - - LDR_EXEC_HEADER_PTR header_ptr = CF::ldr_find_exec_header((const Char*) fCachedBlob); - LDR_OPTIONAL_HEADER_PTR opt_header_ptr = CF::ldr_find_opt_exec_header((const Char*) fCachedBlob); - - if (!header_ptr || !opt_header_ptr) return ErrorOr{kErrorInvalidData}; - -#ifdef __NE_AMD64__ - if (header_ptr->Machine != kPeMachineAMD64 || header_ptr->Signature != kPeSignature) { - return ErrorOr{kErrorInvalidData}; - } - -#elif defined(__NE_ARM64__) - if (header_ptr->Machine != kPeMachineARM64 || header_ptr->Signature != kPeSignature) { - return ErrorOr{kErrorInvalidData}; - } -#endif // __NE_AMD64__ || __NE_ARM64__ - - if (header_ptr->NumberOfSections < 1) { - return ErrorOr{kErrorInvalidData}; - } - - LDR_SECTION_HEADER_PTR secs = - (LDR_SECTION_HEADER_PTR) (((Char*) opt_header_ptr) + header_ptr->SizeOfOptionalHeader); - - for (SizeT sectIndex = 0; sectIndex < header_ptr->NumberOfSections; ++sectIndex) { - LDR_SECTION_HEADER_PTR sect = &secs[sectIndex]; - - if (KStringBuilder::Equals(name, sect->Name)) { - return ErrorOr(sect); - } - } - - return ErrorOr{kErrorInvalidData}; -} - -/***********************************************************************************/ -/// @brief Finds the symbol according to it's name. -/// @param name name of symbol. -/// @param kind kind of symbol we want. -/***********************************************************************************/ - -ErrorOr PE32Loader::FindSymbol(const Char* name, Int32 kind) { - if (!name || *name == 0) return ErrorOr{kErrorInvalidData}; - - auto section_name = "\0"; - - switch (kind) { - case kPETypeData: - section_name = ".data"; - break; - case kPETypeBSS: - section_name = ".bss"; - break; - case kPETypeText: - section_name = ".text"; - break; - default: - return ErrorOr{kErrorInvalidData}; - } - - auto sec = this->FindSectionByName(section_name); - LDR_SECTION_HEADER_PTR* sec_ptr = (LDR_SECTION_HEADER_PTR*) sec.Leak().Leak(); - - if (!sec_ptr || !*sec_ptr) return ErrorOr{kErrorInvalidData}; - - LDR_OPTIONAL_HEADER_PTR opt_header_ptr = CF::ldr_find_opt_exec_header((const Char*) fCachedBlob); - - if (opt_header_ptr) { - LDR_DATA_DIRECTORY_PTR data_dirs = - (LDR_DATA_DIRECTORY_PTR) ((UInt8*) opt_header_ptr + sizeof(LDR_OPTIONAL_HEADER)); - - LDR_DATA_DIRECTORY_PTR export_dir_entry = &data_dirs[0]; - - if (export_dir_entry->VirtualAddress == 0 || export_dir_entry->Size == 0) - return ErrorOr{kErrorInvalidData}; - - LDR_EXPORT_DIRECTORY* export_dir = - (LDR_EXPORT_DIRECTORY*) ((UIntPtr) fCachedBlob + export_dir_entry->VirtualAddress); - - UInt32* name_table = (UInt32*) ((UIntPtr) fCachedBlob + export_dir->AddressOfNames); - UInt16* ordinal_table = (UInt16*) ((UIntPtr) fCachedBlob + export_dir->AddressOfNameOrdinal); - UInt32* function_table = (UInt32*) ((UIntPtr) fCachedBlob + export_dir->AddressOfFunctions); - - for (UInt32 i = 0; i < export_dir->NumberOfNames; ++i) { - const char* exported_name = (const char*) ((UIntPtr) fCachedBlob + name_table[i]); - - if (KStringBuilder::Equals(exported_name, name)) { - UInt16 ordinal = ordinal_table[i]; - UInt32 rva = function_table[ordinal]; - - VoidPtr symbol_addr = (VoidPtr) ((UIntPtr) fCachedBlob + rva); - - return ErrorOr{symbol_addr}; - } - } - } - - return ErrorOr{kErrorInvalidData}; -} - -/// @brief Finds the executable entrypoint. -/// @return -ErrorOr PE32Loader::FindStart() { - if (auto sym = this->FindSymbol(kPeImageStart, 0); sym) return sym; - - return ErrorOr(kErrorExecutable); -} - -/// @brief Tells if the executable is loaded or not. -/// @return Whether it's not bad and is cached. -bool PE32Loader::IsLoaded() noexcept { - return !fBad && fCachedBlob; -} - -const Char* PE32Loader::Path() { - return fPath.Leak().CData(); -} - -const Char* PE32Loader::AsString() { -#ifdef __32x0__ - return "32x0 PE"; -#elif defined(__64x0__) - return "64x0 PE"; -#elif defined(__x86_64__) - return "x86_64 PE"; -#elif defined(__aarch64__) - return "AARCH64 PE"; -#elif defined(__powerpc64__) - return "POWER64 PE"; -#else - return "???? PE"; -#endif // __32x0__ || __64x0__ || __x86_64__ || __powerpc64__ -} - -const Char* PE32Loader::MIME() { - return kPeApplicationMime; -} - -ErrorOr PE32Loader::GetBlob() { - return ErrorOr{this->fCachedBlob}; -} - -namespace Utils { - ProcessID rtl_create_user_process(PE32Loader& exec, const Int32& process_kind) noexcept { - auto errOrStart = exec.FindStart(); - - if (errOrStart.Error() != kErrorSuccess) return kSchedInvalidPID; - - auto symname = exec.FindSymbol(kPeImageStart, 0); - - if (!symname) { - symname = ErrorOr{(VoidPtr) rt_alloc_string("USER_PROCESS_PE32+")}; - } - - auto id = - UserProcessScheduler::The().Spawn(reinterpret_cast(symname.Leak().Leak()), - errOrStart.Leak().Leak(), exec.GetBlob().Leak().Leak()); - - mm_free_ptr(symname.Leak().Leak()); - - if (id != kSchedInvalidPID) { - auto stacksym = exec.FindSymbol(kPeStackSizeSymbol, 0); - - if (!stacksym) { - stacksym = ErrorOr{(VoidPtr) new UIntPtr(kSchedMaxStackSz)}; - } - - if ((*(volatile UIntPtr*) stacksym.Leak().Leak()) > kSchedMaxStackSz) { - *(volatile UIntPtr*) stacksym.Leak().Leak() = kSchedMaxStackSz; - } - - UserProcessScheduler::The().TheCurrentTeam().AsArray()[id].Kind = process_kind; - UserProcessScheduler::The().TheCurrentTeam().AsArray()[id].StackSize = - *(UIntPtr*) stacksym.Leak().Leak(); - - mm_free_ptr(stacksym.Leak().Leak()); - stacksym.Leak().Leak() = nullptr; - } - - return id; - } -} // namespace Utils -} // namespace Kernel \ No newline at end of file diff --git a/dev/kernel/src/PEFCodeMgr.cc b/dev/kernel/src/PEFCodeMgr.cc deleted file mode 100644 index c0a79c32..00000000 --- a/dev/kernel/src/PEFCodeMgr.cc +++ /dev/null @@ -1,335 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - Copyright (C) 2025, Amlal El Mahrouss & NeKernel contributors, licensed under the Apache 2.0 -license. - -======================================== */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/// @author Amlal El Mahrouss (amlal@nekernel.org) -/// @brief PEF backend for the Code Manager. -/// @file PEFCodeMgr.cc - -/// @brief PEF stack size symbol. -#define kPefStackSizeSymbol "__PEFSizeOfReserveStack" -#define kPefHeapSizeSymbol "__PEFSizeOfReserveHeap" -#define kPefNameSymbol "__PEFProgramName" - -namespace Kernel { -namespace Detail { - /***********************************************************************************/ - /// @brief Get the PEF platform signature according to the compiled architecture. - /***********************************************************************************/ - static UInt32 ldr_get_platform(void) noexcept { -#if defined(__NE_32X0__) - return kPefArch32x0; -#elif defined(__NE_64X0__) - return kPefArch64x0; -#elif defined(__NE_AMD64__) - return kPefArchAMD64; -#elif defined(__NE_PPC64__) - return kPefArchPowerPC; -#elif defined(__NE_ARM64__) - return kPefArchARM64; -#else - return kPefArchInvalid; -#endif // __32x0__ || __64x0__ || __x86_64__ - } -} // namespace Detail - -/***********************************************************************************/ -/// @brief PEF loader constructor w/ blob. -/// @param blob file blob. -/***********************************************************************************/ -PEFLoader::PEFLoader(const VoidPtr blob) : fCachedBlob(blob) { - MUST_PASS(fCachedBlob); - - if (!fCachedBlob) { - this->fBad = YES; - return; - } - - PEFContainer* container = reinterpret_cast(fCachedBlob); - - if (container->Abi == kPefAbi && - container->Count >= - 3) { /* if same ABI, AND: .text, .bss, .data (or at least similar) exists */ - if (container->Cpu == Detail::ldr_get_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]) { - return; - } else if (container->Magic[0] == kPefMagicFat[0] && container->Magic[1] == kPefMagicFat[1] && - container->Magic[2] == kPefMagicFat[2] && container->Magic[3] == kPefMagicFat[3] && - container->Magic[4] == kPefMagicFat[4]) { - /// This is a fat binary. Treat it as such. - this->fFatBinary = YES; - return; - } - } - - kout << "PEFLoader: warning: Binary format error!\r"; - - this->fFatBinary = NO; - this->fBad = YES; - - if (this->fCachedBlob) mm_free_ptr(this->fCachedBlob); - this->fCachedBlob = nullptr; -} - -/***********************************************************************************/ -/// @brief PEF loader constructor. -/// @param path the filesystem path. -/***********************************************************************************/ -PEFLoader::PEFLoader(const Char* path) : fCachedBlob(nullptr), fFatBinary(false), fBad(false) { - fFile.New(const_cast(path), kRestrictRB); - fPath = KStringBuilder::Construct(path).Leak(); - - constexpr auto kPefHeader = "PEF_CONTAINER"; - - /// @note zero here means that the FileMgr will read every container header inside the file. - fCachedBlob = fFile->Read(kPefHeader, 0UL); - - if (!fCachedBlob) { - this->fBad = YES; - return; - } - - PEFContainer* container = reinterpret_cast(fCachedBlob); - - if (container->Abi == kPefAbi && - container->Count >= - 3) { /* if same ABI, AND: .text, .bss, .data (or at least similar) exists */ - if (container->Cpu == Detail::ldr_get_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]) { - return; - } else if (container->Magic[0] == kPefMagicFat[0] && container->Magic[1] == kPefMagicFat[1] && - container->Magic[2] == kPefMagicFat[2] && container->Magic[3] == kPefMagicFat[3] && - container->Magic[4] == kPefMagicFat[4]) { - /// This is a fat binary, treat it as such. - this->fFatBinary = YES; - return; - } - } - - kout << "PEFLoader: warning: Binary format error!\r"; - - this->fFatBinary = NO; - this->fBad = YES; - - if (this->fCachedBlob) mm_free_ptr(this->fCachedBlob); - this->fCachedBlob = nullptr; -} - -/***********************************************************************************/ -/// @brief PEF destructor. -/***********************************************************************************/ -PEFLoader::~PEFLoader() { - if (fCachedBlob) mm_free_ptr(fCachedBlob); - - fFile.Delete(); -} - -/***********************************************************************************/ -/// @brief Finds the symbol according to it's name. -/// @param name name of symbol. -/// @param kind kind of symbol we want. -/***********************************************************************************/ -ErrorOr PEFLoader::FindSymbol(const Char* name, Int32 kind) { - if (!fCachedBlob || fBad || !name) return ErrorOr{kErrorInvalidData}; - - auto blob = fFile->Read(name, sizeof(PEFCommandHeader)); - - if (!blob) return ErrorOr{kErrorInvalidData}; - - PEFContainer* container = reinterpret_cast(fCachedBlob); - - if (!container) return ErrorOr{kErrorInvalidData}; - - PEFCommandHeader* command_header = reinterpret_cast(blob); - - if (command_header->VMSize < 1 || command_header->VMAddress == 0) - return ErrorOr{kErrorInvalidData}; - - /// fat binary check. - if (command_header->Cpu != container->Cpu && !this->fFatBinary) - return ErrorOr{kErrorInvalidData}; - - const auto kMangleCharacter = '$'; - const Char* kContainerKinds[] = {".code64", ".data64", ".zero64", nullptr}; - - ErrorOr error_or_symbol; - - switch (kind) { - case kPefCode: { - error_or_symbol = KStringBuilder::Construct(kContainerKinds[0]); // code symbol. - break; - } - case kPefData: { - error_or_symbol = KStringBuilder::Construct(kContainerKinds[1]); // data symbol. - break; - } - case kPefZero: { - error_or_symbol = KStringBuilder::Construct(kContainerKinds[2]); // block starting symbol. - break; - } - default: - return ErrorOr{kErrorInvalidData}; - // prevent that from the kernel's mode perspective, let that happen if it - // were a user process. - } - - Char* unconst_symbol = const_cast(name); - - for (SizeT i = 0UL; i < rt_string_len(unconst_symbol, kPefNameLen); ++i) { - if (rt_is_space(unconst_symbol[i])) { - unconst_symbol[i] = kMangleCharacter; - } - } - - error_or_symbol.Leak().Leak() += name; - - if (KStringBuilder::Equals(command_header->Name, error_or_symbol.Leak().Leak().CData())) { - if (command_header->Kind == kind) { - if (command_header->Cpu != Detail::ldr_get_platform()) { - if (!this->fFatBinary) { - mm_free_ptr(blob); - blob = nullptr; - - return ErrorOr{kErrorInvalidData}; - } - } - - Char* container_blob_value = new Char[command_header->VMSize]; - - rt_copy_memory_safe((VoidPtr) ((Char*) blob + sizeof(PEFCommandHeader)), container_blob_value, - command_header->VMSize, command_header->VMSize); - - mm_free_ptr(blob); - - kout << "PEFLoader: info: Load stub: " << command_header->Name << "!\r"; - - Int32 ret = 0; - SizeT pages_count = (command_header->VMSize + kPageSize - 1) / kPageSize; - - for (SizeT i_vm{}; i_vm < pages_count; ++i_vm) { - ret = HAL::mm_map_page( - (VoidPtr) (command_header->VMAddress + (i_vm * kPageSize)), - (VoidPtr) (HAL::mm_get_page_addr(container_blob_value) + (i_vm * kPageSize)), - HAL::kMMFlagsPresent | HAL::kMMFlagsUser); - - if (ret != kErrorSuccess) { - /// We set the VMAddress to nullptr, if the mapping fail here. - for (SizeT i_vm_unmap{}; i_vm_unmap < i_vm; ++i_vm_unmap) { - ret = HAL::mm_map_page((VoidPtr) (command_header->VMAddress + (i_vm * kPageSize)), - nullptr, HAL::kMMFlagsPresent | HAL::kMMFlagsUser); - } - - delete[] container_blob_value; - container_blob_value = nullptr; - - return ErrorOr{kErrorInvalidData}; - } - } - - return ErrorOr{container_blob_value}; - } - } - - mm_free_ptr(blob); - return ErrorOr{kErrorInvalidData}; -} - -/// @brief Finds the executable entrypoint. -/// @return -ErrorOr PEFLoader::FindStart() { - if (auto sym = this->FindSymbol(kPefStart, kPefCode); sym) return sym; - - return ErrorOr(kErrorExecutable); -} - -/// @brief Tells if the executable is loaded or not. -/// @return Whether it's not bad and is cached. -bool PEFLoader::IsLoaded() noexcept { - return !fBad && fCachedBlob; -} - -const Char* PEFLoader::Path() { - return fPath.Leak().CData(); -} - -const Char* PEFLoader::AsString() { -#ifdef __32x0__ - return "32x0 PEF"; -#elif defined(__64x0__) - return "64x0 PEF"; -#elif defined(__x86_64__) - return "x86_64 PEF"; -#elif defined(__aarch64__) - return "AARCH64 PEF"; -#elif defined(__powerpc64__) - return "POWER64 PEF"; -#else - return "???? PEF"; -#endif // __32x0__ || __64x0__ || __x86_64__ || __powerpc64__ -} - -const Char* PEFLoader::MIME() { - return kPefApplicationMime; -} - -ErrorOr PEFLoader::GetBlob() { - return ErrorOr{this->fCachedBlob}; -} - -namespace Utils { - ProcessID rtl_create_user_process(PEFLoader& exec, const Int32& process_kind) noexcept { - auto errOrStart = exec.FindStart(); - - if (errOrStart.Error() != kErrorSuccess) return kSchedInvalidPID; - - auto symname = exec.FindSymbol(kPefNameSymbol, kPefData); - - if (!symname) { - symname = ErrorOr{(VoidPtr) rt_alloc_string("USER_PROCESS_PEF")}; - } - - ProcessID id = - UserProcessScheduler::The().Spawn(reinterpret_cast(symname.Leak().Leak()), - errOrStart.Leak().Leak(), exec.GetBlob().Leak().Leak()); - - mm_free_ptr(symname.Leak().Leak()); - - if (id != kSchedInvalidPID) { - auto stacksym = exec.FindSymbol(kPefStackSizeSymbol, kPefData); - - if (!stacksym) { - stacksym = ErrorOr{(VoidPtr) new UIntPtr(kSchedMaxStackSz)}; - } - - if ((*(volatile UIntPtr*) stacksym.Leak().Leak()) > kSchedMaxStackSz) { - *(volatile UIntPtr*) stacksym.Leak().Leak() = kSchedMaxStackSz; - } - - UserProcessScheduler::The().TheCurrentTeam().AsArray()[id].Kind = process_kind; - UserProcessScheduler::The().TheCurrentTeam().AsArray()[id].StackSize = - *(UIntPtr*) stacksym.Leak().Leak(); - - mm_free_ptr(stacksym.Leak().Leak()); - } - - return id; - } -} // namespace Utils -} // namespace Kernel diff --git a/dev/kernel/src/PRDT.cc b/dev/kernel/src/PRDT.cc deleted file mode 100644 index 626a7e16..00000000 --- a/dev/kernel/src/PRDT.cc +++ /dev/null @@ -1,22 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include -#include - -namespace Kernel { -/***********************************************************************************/ -/// @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 Kernel diff --git a/dev/kernel/src/PageMgr.cc b/dev/kernel/src/PageMgr.cc deleted file mode 100644 index 81833ee2..00000000 --- a/dev/kernel/src/PageMgr.cc +++ /dev/null @@ -1,95 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include - -#ifdef __NE_AMD64__ -#include -#elif defined(__NE_ARM64__) -#include -#endif // ifdef __NE_AMD64__ || defined(__NE_ARM64__) - -namespace Kernel { -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() = default; - -/// @brief Flush virtual address. -/// @param VirtAddr -Void PageMgr::FlushTLB() { -#ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ - hal_flush_tlb(); -#endif // !__NE_VIRTUAL_MEMORY_SUPPORT__ -} - -/// @brief Reclaim freed page. -/// @return -Bool PTEWrapper::Reclaim() { - if (!this->fPresent) { - this->fPresent = true; - return true; - } - - return false; -} - -/// @brief Request a PTE. -/// @param Rw Is it read write? or is it read only? -/// @param User user mode? -/// @param ExecDisable disable execution on page? -/// @return -PTEWrapper PageMgr::Request(Boolean Rw, Boolean User, Boolean ExecDisable, SizeT Sz, SizeT Pad) { - // Store PTE wrapper right after PTE. - VoidPtr ptr = Kernel::HAL::mm_alloc_bitmap(Rw, User, Sz, NO, Pad); - - return PTEWrapper{Rw, User, ExecDisable, reinterpret_cast(ptr)}; -} - -/// @brief Disable BitMap. -/// @param wrapper the wrapper. -/// @return If the page bitmap was cleared or not. -Bool PageMgr::Free(Ref& wrapper) { - if (!Kernel::HAL::mm_free_bitmap((VoidPtr) wrapper.Leak().VirtualAddress())) return false; - - return true; -} - -/// @brief Virtual PTE address. -/// @return The virtual address of the page. -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) { - fExecDisable = enable; -} - -Bool PTEWrapper::NoExecute() { - return fExecDisable; -} -} // namespace Kernel diff --git a/dev/kernel/src/Pmm.cc b/dev/kernel/src/Pmm.cc deleted file mode 100644 index 84086929..00000000 --- a/dev/kernel/src/Pmm.cc +++ /dev/null @@ -1,83 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include - -#if defined(__NE_ARM64__) -#include -#endif // defined(__NE_ARM64__) - -#if defined(__NE_AMD64__) -#include -#endif // defined(__NE_AMD64__) - -namespace Kernel { -/***********************************************************************************/ -/// @brief Pmm constructor. -/***********************************************************************************/ -Pmm::Pmm() : fPageMgr() { - kout << "[PMM] Allocate PageMemoryMgr.\r"; -} - -Pmm::~Pmm() = default; - -/***********************************************************************************/ -/// @param If this returns Null pointer, enter emergency mode. -/// @param user is this a user page? -/// @param readWrite is it r/w? -/***********************************************************************************/ -Ref Pmm::RequestPage(Boolean user, Boolean readWrite) { - PTEWrapper pt = fPageMgr.Leak().Request(user, readWrite, false, kPageSize, 0); - - if (pt.fPresent) { - kout << "[PMM]: Allocation failed.\r"; - return {pt}; - } - - return Ref(pt); -} - -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 Kernel diff --git a/dev/kernel/src/Property.cc b/dev/kernel/src/Property.cc deleted file mode 100644 index 8b7454fe..00000000 --- a/dev/kernel/src/Property.cc +++ /dev/null @@ -1,41 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -namespace Kernel::CF { -/***********************************************************************************/ -/// @brief Destructor. -/***********************************************************************************/ -Property::~Property() = default; - -/***********************************************************************************/ -/// @brief Constructor. -/***********************************************************************************/ -Property::Property() = default; - -/***********************************************************************************/ -/// @brief Check if property's name equals to name. -/// @param name string to check. -/***********************************************************************************/ -Bool Property::StringEquals(KBasicString<>& name) { - return this->fName && this->fName == name; -} - -/***********************************************************************************/ -/// @brief Gets the key (name) of property. -/***********************************************************************************/ -KBasicString<>& Property::GetKey() { - return this->fName; -} - -/***********************************************************************************/ -/// @brief Gets the value of the property. -/***********************************************************************************/ -PropertyId& Property::GetValue() { - return fValue; -} -} // namespace Kernel::CF diff --git a/dev/kernel/src/Ref.cc b/dev/kernel/src/Ref.cc deleted file mode 100644 index 90b1c22d..00000000 --- a/dev/kernel/src/Ref.cc +++ /dev/null @@ -1,7 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include diff --git a/dev/kernel/src/Semaphore.cc b/dev/kernel/src/Semaphore.cc deleted file mode 100644 index 484c89ca..00000000 --- a/dev/kernel/src/Semaphore.cc +++ /dev/null @@ -1,7 +0,0 @@ -/* ======================================== - - Copyright (C) 2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include \ No newline at end of file diff --git a/dev/kernel/src/SoftwareTimer.cc b/dev/kernel/src/SoftwareTimer.cc deleted file mode 100644 index eafe8db6..00000000 --- a/dev/kernel/src/SoftwareTimer.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -/// ================================================================================ -/// @brief SoftwareTimer class, meant to be generic. -///! @author Amlal El Mahrouss (amlal@nekernel.org) -/// ================================================================================ - -using namespace Kernel; - -SoftwareTimer::SoftwareTimer(Int64 seconds) : fWaitFor(seconds) { - fDigitalTimer = new UIntPtr(); - MUST_PASS(fDigitalTimer); -} - -SoftwareTimer::~SoftwareTimer() { - delete fDigitalTimer; - fDigitalTimer = nullptr; - - fWaitFor = 0; -} - -BOOL SoftwareTimer::Wait() noexcept { - if (fWaitFor < 1) return NO; - - while (*fDigitalTimer < (*fDigitalTimer + fWaitFor)) { - ++(*fDigitalTimer); - } - - return YES; -} diff --git a/dev/kernel/src/Storage/AHCIDeviceInterface.cc b/dev/kernel/src/Storage/AHCIDeviceInterface.cc deleted file mode 100644 index 02b39fb5..00000000 --- a/dev/kernel/src/Storage/AHCIDeviceInterface.cc +++ /dev/null @@ -1,87 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -using namespace Kernel; - -/// @brief Class constructor -/// @param Out Drive output -/// @param In Drive input -/// @param Cleanup Drive cleanup. -AHCIDeviceInterface::AHCIDeviceInterface(void (*out)(DeviceInterface* self, IMountpoint* outpacket), - void (*in)(DeviceInterface* self, IMountpoint* inpacket)) - : DeviceInterface(out, in) {} - -/// @brief Class desctructor -AHCIDeviceInterface::~AHCIDeviceInterface() = default; - -/// @brief Returns the name of the device interface. -/// @return it's name as a string. -const Char* AHCIDeviceInterface::Name() const { - return "/devices/sda{}"; -} - -/// @brief Output operator. -/// @param mnt the disk mountpoint. -/// @return the class itself after operation. -AHCIDeviceInterface& AHCIDeviceInterface::operator<<(IMountpoint* mnt) { - if (!mnt) return *this; - - for (SizeT driveCount = 0; driveCount < kDriveMaxCount; ++driveCount) { - auto interface = mnt->GetAddressOf(driveCount); - - if ((interface) && - rt_string_cmp((interface)->fProtocol(), "AHCI", rt_string_len("AHCI")) == 0) { - continue; - } else if ((interface) && - rt_string_cmp((interface)->fProtocol(), "AHCI", rt_string_len("AHCI")) != 0) { - return *this; - } - } - - return (AHCIDeviceInterface&) DeviceInterface::operator<<(mnt); -} - -/// @brief Input operator. -/// @param mnt the disk mountpoint. -/// @return the class itself after operation. -AHCIDeviceInterface& AHCIDeviceInterface::operator>>(IMountpoint* mnt) { - if (!mnt) return *this; - - for (SizeT driveCount = 0; driveCount < kDriveMaxCount; ++driveCount) { - auto interface = mnt->GetAddressOf(driveCount); - - // really check if it's ATA. - if ((interface) && - rt_string_cmp((interface)->fProtocol(), "AHCI", rt_string_len("AHCI")) == 0) { - continue; - } else if ((interface) && - rt_string_cmp((interface)->fProtocol(), "AHCI", rt_string_len("AHCI")) != 0) { - return *this; - } - } - - return (AHCIDeviceInterface&) DeviceInterface::operator>>(mnt); -} - -const UInt16& AHCIDeviceInterface::GetPortsImplemented() { - return this->fPortsImplemented; -} - -Void AHCIDeviceInterface::SetPortsImplemented(const UInt16& pi) { - MUST_PASS(pi > 0); - this->fPortsImplemented = pi; -} - -const UInt32& AHCIDeviceInterface::GetIndex() { - return this->fDriveIndex; -} - -Void AHCIDeviceInterface::SetIndex(const UInt32& drv) { - MUST_PASS(IMountpoint::kDriveIndexInvalid < drv); - this->fDriveIndex = drv; -} \ No newline at end of file diff --git a/dev/kernel/src/Storage/ATADeviceInterface.cc b/dev/kernel/src/Storage/ATADeviceInterface.cc deleted file mode 100644 index 8e15fdea..00000000 --- a/dev/kernel/src/Storage/ATADeviceInterface.cc +++ /dev/null @@ -1,96 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -using namespace Kernel; - -/// @brief Class constructor -/// @param Out Drive output -/// @param In Drive input -/// @param Cleanup Drive cleanup. -ATADeviceInterface::ATADeviceInterface(void (*Out)(DeviceInterface*, IMountpoint* outpacket), - void (*In)(DeviceInterface*, IMountpoint* inpacket)) - : DeviceInterface(Out, In) {} - -/// @brief Class desctructor -ATADeviceInterface::~ATADeviceInterface() = default; - -/// @brief Returns the name of the device interface. -/// @return it's name as a string. -const Char* ATADeviceInterface::Name() const { - return "/devices/hda{}"; -} - -/// @brief Output operator. -/// @param Data the disk mountpoint. -/// @return the class itself after operation. -ATADeviceInterface& ATADeviceInterface::operator<<(IMountpoint* Data) { - if (!Data) return *this; - - for (SizeT driveCount = 0; driveCount < kDriveMaxCount; ++driveCount) { - auto interface = Data->GetAddressOf(driveCount); - - if ((interface) && - rt_string_cmp((interface)->fProtocol(), "ATA-", rt_string_len("ATA-")) == 0) { - continue; - } else if ((interface) && - rt_string_cmp((interface)->fProtocol(), "ATA-", rt_string_len("ATA-")) != 0) { - return *this; - } - } - - return (ATADeviceInterface&) DeviceInterface::operator<<(Data); -} - -/// @brief Input operator. -/// @param Data the disk mountpoint. -/// @return the class itself after operation. -ATADeviceInterface& ATADeviceInterface::operator>>(IMountpoint* Data) { - if (!Data) return *this; - - for (SizeT driveCount = 0; driveCount < kDriveMaxCount; ++driveCount) { - auto interface = Data->GetAddressOf(driveCount); - - // really check if it's ATA. - if ((interface) && - rt_string_cmp((interface)->fProtocol(), "ATA-", rt_string_len("ATA-")) == 0) { - continue; - } else if ((interface) && - rt_string_cmp((interface)->fProtocol(), "ATA-", rt_string_len("ATA-")) != 0) { - return *this; - } - } - - return (ATADeviceInterface&) DeviceInterface::operator>>(Data); -} - -const UInt32& ATADeviceInterface::GetIndex() { - return this->fDriveIndex; -} - -Void ATADeviceInterface::SetIndex(const UInt32& drv) { - MUST_PASS(IMountpoint::kDriveIndexInvalid < drv); - this->fDriveIndex = drv; -} - -const UInt16& ATADeviceInterface::GetIO() { - return this->fIO; -} - -Void ATADeviceInterface::SetIO(const UInt16& drv) { - MUST_PASS(0xFFFF != drv); - this->fIO = drv; -} - -const UInt16& ATADeviceInterface::GetMaster() { - return this->fIO; -} - -Void ATADeviceInterface::SetMaster(const UInt16& drv) { - MUST_PASS(0xFFFF != drv); - this->fMaster = drv; -} \ No newline at end of file diff --git a/dev/kernel/src/Storage/NVMEDeviceInterface.cc b/dev/kernel/src/Storage/NVMEDeviceInterface.cc deleted file mode 100644 index f05d384e..00000000 --- a/dev/kernel/src/Storage/NVMEDeviceInterface.cc +++ /dev/null @@ -1,22 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -namespace Kernel { -NVMEDeviceInterface::NVMEDeviceInterface(void (*out)(DeviceInterface*, IMountpoint* outpacket), - void (*in)(DeviceInterface*, IMountpoint* inpacket), - void (*cleanup)(void)) - : DeviceInterface(out, in), fCleanup(cleanup) {} - -NVMEDeviceInterface::~NVMEDeviceInterface() { - if (fCleanup) fCleanup(); -} - -const Char* NVMEDeviceInterface::Name() const { - return ("/devices/nvme{}"); -} -} // namespace Kernel diff --git a/dev/kernel/src/Storage/SCSIDeviceInterface.cc b/dev/kernel/src/Storage/SCSIDeviceInterface.cc deleted file mode 100644 index 2e331ae9..00000000 --- a/dev/kernel/src/Storage/SCSIDeviceInterface.cc +++ /dev/null @@ -1,9 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -using namespace Kernel; diff --git a/dev/kernel/src/Stream.cc b/dev/kernel/src/Stream.cc deleted file mode 100644 index 8572e222..00000000 --- a/dev/kernel/src/Stream.cc +++ /dev/null @@ -1,12 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - - File: Stream.cc - Purpose: Stream object - - Revision History: - -======================================== */ - -#include diff --git a/dev/kernel/src/Swap/DiskSwap.cc b/dev/kernel/src/Swap/DiskSwap.cc deleted file mode 100644 index f0fa5915..00000000 --- a/dev/kernel/src/Swap/DiskSwap.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025 Amlal El Mahrouss , licensed under the Apache 2.0 license. - -======================================== */ - -#include -#include - -namespace Kernel { -static constexpr UInt32 kSwapDiskHeaderMagic = 0x44535750; // 'DSWP' - -/***********************************************************************************/ -/// @brief Write memory chunk onto disk. -/// @param fork_name The swap name to recognize this memory region. -/// @param fork_name_len length of fork name. -/// @param data the data packet. -/// @return Whether the swap was written to disk, or not. -/***********************************************************************************/ -BOOL DiskSwapInterface::Write(const Char* fork_name, SizeT fork_name_len, SWAP_DISK_HEADER* data) { - if (!fork_name || !fork_name_len) return NO; - - if (*fork_name == 0) return NO; - - if (!data || data->fMagic != kSwapDiskHeaderMagic) return NO; - - FileStream file(kSwapPageFilePath, kRestrictWRB); - - ErrorOr ret = file.Write(fork_name, data, sizeof(SWAP_DISK_HEADER) + data->fBlobSz); - - if (ret.Error()) return NO; - - return YES; -} - -/***********************************************************************************/ -/// @brief Read memory chunk from disk. -/// @param fork_name The swap name to recognize this memory region. -/// @param fork_name_len length of fork name. -/// @param data the data packet length. -/// @return Whether the swap was fetched to disk, or not. -/***********************************************************************************/ -SWAP_DISK_HEADER* DiskSwapInterface::Read(const Char* fork_name, SizeT fork_name_len, - SizeT data_len) { - if (!fork_name || !fork_name_len) return nullptr; - - if (*fork_name == 0) return nullptr; - - if (data_len > kSwapBlockMaxSize) return nullptr; - - if (data_len == 0) return nullptr; - - FileStream file(kSwapPageFilePath, kRestrictRB); - - VoidPtr blob = file.Read(fork_name, sizeof(SWAP_DISK_HEADER) + data_len); - - if (!blob || ((SWAP_DISK_HEADER*) blob)->fMagic != kSwapDiskHeaderMagic) { - if (blob) mm_free_ptr(blob); - return nullptr; - } - - return reinterpret_cast(blob); -} -} // namespace Kernel diff --git a/dev/kernel/src/ThreadLocalStorage.cc b/dev/kernel/src/ThreadLocalStorage.cc deleted file mode 100644 index fa445d84..00000000 --- a/dev/kernel/src/ThreadLocalStorage.cc +++ /dev/null @@ -1,52 +0,0 @@ -/* - * ======================================================== - * - * NeKernel - * Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - * - * ======================================================== - */ - -#include -#include -#include -#include - -/***********************************************************************************/ -/// @bugs: 0 -/// @file ThreadLocalStorage.cc -/// @brief NeKernel Thread Local Storage. -///! @author Amlal El Mahrouss (amlal@nekernel.org) -/***********************************************************************************/ - -using namespace Kernel; - -/** - * @brief Checks for cookie inside the TIB. - * @param tib_ptr the TIB to check. - * @return if the cookie is enabled, true; false otherwise - */ - -Boolean tls_check_tib(THREAD_INFORMATION_BLOCK* tib_ptr) { - if (!tib_ptr) return false; - - return tib_ptr->Cookie[kCookieMag0Idx] == kCookieMag0 && - tib_ptr->Cookie[kCookieMag1Idx] == kCookieMag1 && - tib_ptr->Cookie[kCookieMag2Idx] == kCookieMag2; -} - -/** - * @brief System call implementation of the TLS check. - * @param tib_ptr The TIB record. - * @return if the TIB record is valid or not. - */ -EXTERN_C Bool tls_check_syscall_impl(Kernel::VoidPtr tib_ptr) noexcept { - if (!tib_ptr) { - kout << "TLS: Failed because of an invalid TIB...\r"; - return No; - } - - THREAD_INFORMATION_BLOCK* tib = reinterpret_cast(tib_ptr); - - return tls_check_tib(tib); -} diff --git a/dev/kernel/src/Timer.cc b/dev/kernel/src/Timer.cc deleted file mode 100644 index 648cc92b..00000000 --- a/dev/kernel/src/Timer.cc +++ /dev/null @@ -1,19 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -///! BUGS: 0 -///! @file Timer.cc -///! @brief Software Timer implementation -///! @author Amlal El Mahrouss (amlal@nekernel.org) - -using namespace Kernel; - -/// @brief Unimplemented as it is an interface. -BOOL TimerInterface::Wait() noexcept { - return NO; -} diff --git a/dev/kernel/src/UserMgr.cc b/dev/kernel/src/UserMgr.cc deleted file mode 100644 index 103e8ec9..00000000 --- a/dev/kernel/src/UserMgr.cc +++ /dev/null @@ -1,131 +0,0 @@ -/* - * ======================================================== - * - * NeKernel - * Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - * - * File: UserMgr.cc - * Purpose: User Manager, used to provide authentication and security. - * - * ======================================================== - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define kStdUserType (0xEE) -#define kSuperUserType (0xEF) - -/// @file UserMgr.cc -/// @brief Multi-user support. - -namespace Kernel { -namespace Detail { - //////////////////////////////////////////////////////////// - /// \brief Constructs a password by hashing the password. - /// \param password password to hash. - /// \return the hashed password - //////////////////////////////////////////////////////////// - STATIC UInt64 user_fnv_generator(const Char* password, User* user) { - if (!password || !user) return 0; - if (*password == 0) return 0; - - kout << "user_fnv_generator: Hashing user password...\r"; - - const UInt64 kFnvOffsetBasis = 0xcbf29ce484222325ULL; - const UInt64 fFnvPrime = 0x100000001b3ULL; - - UInt64 hash = kFnvOffsetBasis; - - while (*password) { - hash ^= (Char) (*password++); - hash *= fFnvPrime; - } - - kout << "user_fnv_generator: Hashed user password.\r"; - - return hash; - } -} // namespace Detail - -//////////////////////////////////////////////////////////// -/// @brief User ring constructor. -//////////////////////////////////////////////////////////// -User::User(const Int32& sel, const Char* user_name) : mUserRing((UserRingKind) sel) { - MUST_PASS(sel >= 0); - rt_copy_memory_safe((VoidPtr) user_name, this->mUserName, rt_string_len(user_name), - kMaxUserNameLen); -} - -//////////////////////////////////////////////////////////// -/// @brief User ring constructor. -//////////////////////////////////////////////////////////// -User::User(const UserRingKind& ring_kind, const Char* user_name) : mUserRing(ring_kind) { - rt_copy_memory_safe((VoidPtr) user_name, this->mUserName, rt_string_len(user_name), - kMaxUserNameLen); -} - -//////////////////////////////////////////////////////////// -/// @brief User destructor class. -//////////////////////////////////////////////////////////// -User::~User() = default; - -Bool User::Save(const UserPublicKey password) noexcept { - if (!password || *password == 0) return No; - - this->mUserFNV = Detail::user_fnv_generator(password, this); - - kout << "User::Save: Saved password successfully...\r"; - - return Yes; -} - -Bool User::Login(const UserPublicKey password) noexcept { - if (!password || !*password) return No; - - auto ret = this->mUserFNV == Detail::user_fnv_generator(password, this); - - // now check if the password matches. - kout << (ret ? "User::Login: Password matches.\r" : "User::Login: Password doesn't match.\r"); - return ret; -} - -Bool User::operator==(const User& lhs) { - return lhs.mUserRing == this->mUserRing; -} - -Bool User::operator!=(const User& lhs) { - return lhs.mUserRing != this->mUserRing; -} - -//////////////////////////////////////////////////////////// -/// @brief Returns the user's name. -//////////////////////////////////////////////////////////// - -Char* User::Name() noexcept { - return this->mUserName; -} - -//////////////////////////////////////////////////////////// -/// @brief Returns the user's ring. -/// @return The king of ring the user is attached to. -//////////////////////////////////////////////////////////// - -const UserRingKind& User::Ring() noexcept { - return this->mUserRing; -} - -Bool User::IsStdUser() noexcept { - return this->Ring() == UserRingKind::kRingStdUser; -} - -Bool User::IsSuperUser() noexcept { - return this->Ring() == UserRingKind::kRingSuperUser; -} -} // namespace Kernel diff --git a/dev/kernel/src/UserProcessScheduler.cc b/dev/kernel/src/UserProcessScheduler.cc deleted file mode 100644 index 264bddf3..00000000 --- a/dev/kernel/src/UserProcessScheduler.cc +++ /dev/null @@ -1,690 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - - FILE: UserProcessScheduler.cc - PURPOSE: Low-Privilege/Ring-3 process scheduler. - -======================================== */ - -/***********************************************************************************/ -/// @file UserProcessScheduler.cc -/// @brief Unprivileged/Ring-3 process scheduler. -/// @author Amlal El Mahrouss (amlal@nekernel.org) -/***********************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -///! BUGS: 0 - -namespace Kernel { -USER_PROCESS::USER_PROCESS() = default; -USER_PROCESS::~USER_PROCESS() = default; - -/// @brief Gets the last exit code. -/// @note Not thread-safe. -/// @return Int32 the last exit code. - -/***********************************************************************************/ -/// @brief Crashes the current process. -/***********************************************************************************/ - -Void USER_PROCESS::Crash() { - if (this->Status != ProcessStatusKind::kRunning) return; - - this->Status = ProcessStatusKind::kKilled; - - (Void)(kout << this->Name << ": crashed, error id: " << number(-kErrorProcessFault) << kendl); -} - -/***********************************************************************************/ -/// @brief boolean operator, check status. -/***********************************************************************************/ - -USER_PROCESS::operator bool() { - return this->Status == ProcessStatusKind::kRunning; -} - -/***********************************************************************************/ -/// @brief Gets the local last exit code. -/// @note Not thread-safe. -/// @return Int32 the last exit code. -/***********************************************************************************/ - -KPCError& USER_PROCESS::GetExitCode() noexcept { - return this->LastExitCode; -} - -/***********************************************************************************/ -/// @brief Error code variable getter. -/***********************************************************************************/ - -KPCError& USER_PROCESS::GetLocalCode() noexcept { - return this->LocalCode; -} - -/***********************************************************************************/ -/// @brief Wakes process header. -/// @param should_wakeup if the program shall wakeup or not. -/***********************************************************************************/ - -Void USER_PROCESS::Wake(Bool should_wakeup) { - this->Status = should_wakeup ? ProcessStatusKind::kRunning : ProcessStatusKind::kFrozen; -} - -/***********************************************************************************/ -/** @brief Allocate pointer to heap tree. */ -/** @param tree The tree to calibrate */ -/***********************************************************************************/ - -template -STATIC T* sched_try_go_upper_ptr_tree(T* tree) { - if (!tree) { - return nullptr; - } - - tree = tree->Parent; - - if (tree) { - auto tree_tmp = tree->Next; - - if (!tree_tmp) { - return tree; - } - - return tree_tmp; - } - - return tree; -} - -/***********************************************************************************/ -/** @brief Allocate pointer to heap/file tree. */ -/***********************************************************************************/ - -ErrorOr USER_PROCESS::New(SizeT sz, SizeT pad_amount) { - if (this->UsedMemory > kSchedMaxMemoryLimit) return ErrorOr(-kErrorHeapOutOfMemory); - -#ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ - auto vm_register = kKernelVM; - - hal_write_cr3(this->VMRegister); - - auto ptr = mm_alloc_ptr(sz, Yes, Yes, pad_amount); - - hal_write_cr3(vm_register); -#else - auto ptr = mm_alloc_ptr(sz, Yes, Yes, pad_amount); -#endif - - if (!this->HeapTree) { - this->HeapTree = new PROCESS_HEAP_TREE(); - - if (!this->HeapTree) { - this->Crash(); - return ErrorOr(-kErrorHeapOutOfMemory); - } - - this->HeapTree->EntryPad = pad_amount; - this->HeapTree->EntrySize = sz; - - this->HeapTree->Entry = ptr; - - this->HeapTree->Color = kBlackTreeKind; - - this->HeapTree->Prev = nullptr; - this->HeapTree->Next = nullptr; - this->HeapTree->Parent = nullptr; - this->HeapTree->Child = nullptr; - } else { - PROCESS_HEAP_TREE* entry = this->HeapTree; - PROCESS_HEAP_TREE* prev_entry = entry; - - BOOL is_parent = NO; - - while (entry) { - if (entry->EntrySize < 1) break; - - prev_entry = entry; - - if (entry->Child && entry->Child->EntrySize > 0 && entry->Child->EntrySize == sz) { - entry = entry->Child; - is_parent = YES; - } else if (entry->Next && entry->Next->EntrySize > 0 && entry->Next->EntrySize == sz) { - is_parent = NO; - entry = entry->Next; - } else { - entry = sched_try_go_upper_ptr_tree(entry); - if (entry && entry->Color == kBlackTreeKind) break; - } - } - - auto new_entry = new PROCESS_HEAP_TREE(); - - if (!new_entry) { - this->Crash(); - return ErrorOr(-kErrorHeapOutOfMemory); - } - - new_entry->Entry = ptr; - new_entry->EntrySize = sz; - new_entry->EntryPad = pad_amount; - new_entry->Parent = entry; - new_entry->Child = nullptr; - new_entry->Next = nullptr; - new_entry->Prev = nullptr; - - new_entry->Color = kBlackTreeKind; - prev_entry->Color = kRedTreeKind; - - if (is_parent) { - prev_entry->Child = new_entry; - new_entry->Parent = prev_entry; - } else { - prev_entry->Next = new_entry; - new_entry->Prev = prev_entry; - } - } - - this->UsedMemory += sz; - - return ErrorOr(ptr); -} - -/***********************************************************************************/ -/// @brief Gets the name of the current process. -/***********************************************************************************/ - -const Char* USER_PROCESS::GetName() noexcept { - return this->Name; -} - -/***********************************************************************************/ -/// @brief Gets the owner of the process. -/***********************************************************************************/ - -const User* USER_PROCESS::GetOwner() noexcept { - return this->Owner; -} - -/// @brief USER_PROCESS status getter. -const ProcessStatusKind& USER_PROCESS::GetStatus() noexcept { - return this->Status; -} - -/***********************************************************************************/ -/** -@brief Affinity is the time slot allowed for the process. -*/ -/***********************************************************************************/ - -const AffinityKind& USER_PROCESS::GetAffinity() noexcept { - return this->Affinity; -} - -/***********************************************************************************/ -/** @brief Free heap tree. */ -/***********************************************************************************/ - -template -STATIC Void sched_free_ptr_tree(T* tree) { - // Deleting memory lists. Make sure to free all of them. - while (tree) { - if (tree->Entry) { - MUST_PASS(mm_free_ptr(tree->Entry)); - } - - auto next = tree->Next; - - if (next->Child) sched_free_ptr_tree(next->Child); - - tree->Child = nullptr; - - mm_free_ptr(tree); - - tree = nullptr; - tree = next; - } -} - -/***********************************************************************************/ -/** -@brief Exit process method. -@param exit_code The process's exit code. -*/ -/***********************************************************************************/ - -Void USER_PROCESS::Exit(const Int32& exit_code) { - this->Status = exit_code > 0 ? ProcessStatusKind::kKilled : ProcessStatusKind::kFrozen; - this->LastExitCode = exit_code; - -#ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ - auto pd = kKernelVM; - hal_write_cr3(this->VMRegister); -#endif - - sched_free_ptr_tree(this->HeapTree); - this->HeapTree = nullptr; - - sched_free_ptr_tree(this->FileTree); - this->FileTree = nullptr; - -#ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ - hal_write_cr3(pd); -#endif - -#ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ - //! Free the memory's page directory. - if (this->VMRegister) HAL::mm_free_bitmap(this->VMRegister); -#endif - - //! Delete image if not done already. - if (this->Image.fCode && mm_is_valid_ptr(this->Image.fCode)) mm_free_ptr(this->Image.fCode); - - //! Delete blob too. - if (this->Image.fBlob && mm_is_valid_ptr(this->Image.fBlob)) mm_free_ptr(this->Image.fBlob); - - //! Delete stack frame. - if (this->StackFrame && mm_is_valid_ptr(this->StackFrame)) - mm_free_ptr((VoidPtr) this->StackFrame); - - //! Avoid use after free. - this->Image.fBlob = nullptr; - this->Image.fCode = nullptr; - this->StackFrame = nullptr; - - if (this->Kind == kExecutableDylibKind) { - Bool success = false; - - rtl_fini_dylib_pef(*this, reinterpret_cast(this->DylibDelegate), &success); - - if (!success) { - ke_panic(RUNTIME_CHECK_PROCESS); - } - - this->DylibDelegate = nullptr; - } - - this->ProcessId = 0UL; - this->Status = ProcessStatusKind::kFinished; - - --this->ParentTeam->mProcessCur; -} - -/***********************************************************************************/ -/// @brief Add dylib to the process object. -/***********************************************************************************/ - -Bool USER_PROCESS::InitDylib() { - // React according to the process's kind. - switch (this->Kind) { - case USER_PROCESS::kExecutableDylibKind: { - this->DylibDelegate = rtl_init_dylib_pef(*this); - - if (!this->DylibDelegate) { - this->Crash(); - return NO; - } - - return YES; - } - case USER_PROCESS::kExecutableKind: { - return NO; - } - default: { - break; - } - } - - (Void)(kout << "Unknown process kind: " << hex_number(this->Kind) << kendl); - this->Crash(); - - return NO; -} - -/***********************************************************************************/ -/// @brief Add process to team. -/// @param process the process *Ref* class. -/// @return the process index inside the team. -/***********************************************************************************/ - -ProcessID UserProcessScheduler::Spawn(const Char* name, VoidPtr code, VoidPtr image) { - if (!name || !code) { - return -kErrorProcessFault; - } - - if (*name == 0) { - return -kErrorProcessFault; - } - - ProcessID pid = this->mTeam.mProcessCur; - - if (pid > kSchedProcessLimitPerTeam) { - return -kErrorProcessFault; - } - - ++this->mTeam.mProcessCur; - - USER_PROCESS& process = this->mTeam.mProcessList[pid]; - - process.Image.fCode = code; - process.Image.fBlob = image; - - SizeT len = rt_string_len(name); - - if (len > kSchedNameLen) { - return -kErrorProcessFault; - } - - rt_copy_memory_safe(reinterpret_cast(const_cast(name)), process.Name, len, - kSchedNameLen); - -#ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ - process.VMRegister = kKernelVM; -#else - process.VMRegister = 0UL; -#endif // ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ - - process.StackFrame = new HAL::StackFrame(); - - if (!process.StackFrame) { - process.Crash(); - return -kErrorProcessFault; - } - - rt_set_memory(process.StackFrame, 0, sizeof(HAL::StackFrame)); - - process.StackFrame->IP = reinterpret_cast(code); - process.StackFrame->SP = reinterpret_cast(&process.StackReserve[0] + process.StackSize); - -#ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ - HAL::mm_map_page((VoidPtr) process.StackFrame->IP, - (VoidPtr) HAL::mm_get_page_addr((VoidPtr) process.StackFrame->IP), - HAL::kMMFlagsUser | HAL::kMMFlagsPresent); - HAL::mm_map_page((VoidPtr) process.StackFrame->SP, - (VoidPtr) HAL::mm_get_page_addr((VoidPtr) process.StackFrame->SP), - HAL::kMMFlagsUser | HAL::kMMFlagsPresent); -#endif // ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ - - process.StackSize = kSchedMaxStackSz; - - rt_set_memory(process.StackReserve, 0, process.StackSize); - - process.ParentTeam = &mTeam; - - process.ProcessId = pid; - process.Status = ProcessStatusKind::kRunning; - process.PTime = 0; - process.UTime = 0; - process.RTime = 0; - - if (!process.FileTree) { - process.FileTree = new PROCESS_FILE_TREE(); - - if (!process.FileTree) { - process.Crash(); - return ErrorOr(-kErrorHeapOutOfMemory); - } - - /// @todo File Tree allocation and dispose methods (amlal) - } - - (Void)(kout << "ProcessID: " << number(process.ProcessId) << kendl); - (Void)(kout << "ProcesName: " << process.Name << kendl); - - return pid; -} - -/***********************************************************************************/ -/// @brief Retrieves the singleton of the process scheduler. -/***********************************************************************************/ - -UserProcessScheduler& UserProcessScheduler::The() { - STATIC UserProcessScheduler kScheduler; - return kScheduler; -} - -/***********************************************************************************/ - -/// @brief Remove process from the team. -/// @param process_id process slot inside team. -/// @retval true process was removed. -/// @retval false process doesn't exist in team. - -/***********************************************************************************/ - -Void UserProcessScheduler::Remove(ProcessID process_id) { - if (process_id < 0 || process_id > kSchedProcessLimitPerTeam) return; - if (this->mTeam.mProcessList[process_id].Status == ProcessStatusKind::kInvalid) return; - - mTeam.mProcessList[process_id].Exit(kErrorSuccess); -} - -/// @brief Is it a user scheduler? - -Bool UserProcessScheduler::IsUser() { - return Yes; -} - -/// @brief Is it a kernel scheduler? - -Bool UserProcessScheduler::IsKernel() { - return No; -} - -/// @brief Is it a SMP scheduler? - -Bool UserProcessScheduler::HasMP() { - MUST_PASS(kHandoverHeader); - return kHandoverHeader->f_HardwareTables.f_MultiProcessingEnabled; -} - -/***********************************************************************************/ -/// @brief Run User scheduler object. -/// @return USER_PROCESS count executed within a team. -/***********************************************************************************/ - -SizeT UserProcessScheduler::Run() noexcept { - if (mTeam.mProcessCur < 1) { - return 0UL; - } - - SizeT process_index = 0UL; //! we store this guy to tell the scheduler how many - //! things we have scheduled. - - for (; process_index < mTeam.AsArray().Capacity(); ++process_index) { - auto& process = mTeam.AsArray()[process_index]; - - //! Check if the process needs to be run. - if (UserProcessHelper::CanBeScheduled(process)) { - kout << process.Name << " will be run...\r"; - - //! Increase the usage time of the process. - if (process.UTime < process.PTime) { - ++process.UTime; - } - - this->TheCurrentProcess() = process; - - if (UserProcessHelper::Switch(process.StackFrame, process.ProcessId)) { - process.PTime = static_cast(process.Affinity); - - // We add a bigger cooldown according to the RTime and affinity here. - if (process.PTime < process.RTime && AffinityKind::kRealTime != process.Affinity) { - if (process.RTime < (Int32) AffinityKind::kVeryHigh) - process.RTime += (Int32) AffinityKind::kLowUsage; - else if (process.RTime < (Int32) AffinityKind::kHigh) - process.RTime += (Int32) AffinityKind::kStandard; - else if (process.RTime < (Int32) AffinityKind::kStandard) - process.RTime += (Int32) AffinityKind::kHigh; - - process.PTime -= process.RTime; - process.RTime = 0UL; - } - } - } else { - ++process.RTime; - --process.PTime; - } - } - - return process_index; -} - -/// @brief Gets the current scheduled team. -/// @return -UserProcessTeam& UserProcessScheduler::TheCurrentTeam() { - return mTeam; -} - -/***********************************************************************************/ -/// @brief Switches the current team. -/// @param team the new team to switch to. -/// @retval true team was switched. -/// @retval false team was not switched. -/***********************************************************************************/ - -BOOL UserProcessScheduler::SwitchTeam(UserProcessTeam& team) { - if (team.AsArray().Count() < 1) return No; - - this->mTeam = team; - - return Yes; -} - -/// @brief Gets current running process. -/// @return -Ref& UserProcessScheduler::TheCurrentProcess() { - return mTeam.AsRef(); -} - -/// @brief Current proccess id getter. -/// @return USER_PROCESS ID integer. -ErrorOr UserProcessHelper::TheCurrentPID() { - if (!UserProcessScheduler::The().TheCurrentProcess()) - return ErrorOr{-kErrorProcessFault}; - - kout << "UserProcessHelper::TheCurrentPID: Leaking ProcessId...\r"; - return ErrorOr{UserProcessScheduler::The().TheCurrentProcess().Leak().ProcessId}; -} - -/// @brief Check if process can be schedulded. -/// @param process the process reference. -/// @retval true can be schedulded. -/// @retval false cannot be schedulded. -Bool UserProcessHelper::CanBeScheduled(const USER_PROCESS& process) { - if (process.Affinity == AffinityKind::kRealTime) return Yes; - - if (process.Status != ProcessStatusKind::kRunning) return No; - if (process.Affinity == AffinityKind::kInvalid) return No; - if (process.StackSize > kSchedMaxStackSz) return No; - if (!process.Name[0]) return No; - if (process.Signal.SignalID == sig_generate_unique()) return No; - - return process.PTime < 1; -} - -/***********************************************************************************/ -/** - * @brief Start scheduling the current team. - */ -/***********************************************************************************/ - -SizeT UserProcessHelper::StartScheduling() { - return UserProcessScheduler::The().Run(); -} - -/***********************************************************************************/ -/** - * \brief Does a context switch in a CPU. - * \param the_stack the stackframe of the running app. - * \param new_pid the process's ProcessID. - */ -/***********************************************************************************/ - -Bool UserProcessHelper::Switch(HAL::StackFramePtr frame_ptr, ProcessID new_pid) { - (Void)(kout << "IP: " << hex_number(frame_ptr->IP) << kendl); - - for (SizeT index = 0UL; index < HardwareThreadScheduler::The().Capacity(); ++index) { - if (!HardwareThreadScheduler::The()[index].Leak()) continue; - - if (HardwareThreadScheduler::The()[index].Leak()->Kind() == kAPInvalid || - HardwareThreadScheduler::The()[index].Leak()->Kind() == kAPBoot) - continue; - - (Void)(kout << "AP_" << hex_number(index) << kendl); - - if (HardwareThreadScheduler::The()[index].Leak()->IsBusy()) { - (Void)(kout << "AP_" << hex_number(index)); - kout << " is busy\r"; - - continue; - } - - (Void)(kout << "AP_" << hex_number(index)); - kout << " is now trying to run a new task!\r"; - - //////////////////////////////////////////////////////////// - /// Prepare task switch. /// - //////////////////////////////////////////////////////////// - - HardwareThreadScheduler::The()[index].Leak()->Busy(YES); - - Bool ret = HardwareThreadScheduler::The()[index].Leak()->Switch(frame_ptr); - - //////////////////////////////////////////////////////////// - /// Rollback on fail. /// - //////////////////////////////////////////////////////////// - - if (!ret) continue; - - UserProcessHelper::TheCurrentPID().Leak().Leak() = new_pid; - - HardwareThreadScheduler::The()[index].Leak()->fPTime = - UserProcessScheduler::The().TheCurrentTeam().AsArray()[new_pid].PTime; - - (Void)(kout << "AP_" << hex_number(index)); - kout << " is now running a new task!\r"; - - return YES; - } - - kout << "Couldn't find a suitable core for the current process!\r"; - - return NO; -} - -//////////////////////////////////////////////////////////// -/// @brief this checks if any process is on the team. -//////////////////////////////////////////////////////////// -UserProcessScheduler::operator bool() { - for (auto process_index = 0UL; process_index < mTeam.AsArray().Count(); ++process_index) { - auto& process = mTeam.AsArray()[process_index]; - if (UserProcessHelper::CanBeScheduled(process)) return true; - } - - return false; -} - -//////////////////////////////////////////////////////////// -/// @brief this checks if no process is on the team. -//////////////////////////////////////////////////////////// -Bool UserProcessScheduler::operator!() { - SInt64 cnt = 0UL; - - for (auto process_index = 0UL; process_index < mTeam.AsArray().Count(); ++process_index) { - auto& process = mTeam.AsArray()[process_index]; - if (UserProcessHelper::CanBeScheduled(process)) ++cnt; - } - - return cnt == 0L; -} -} // namespace Kernel diff --git a/dev/kernel/src/UserProcessTeam.cc b/dev/kernel/src/UserProcessTeam.cc deleted file mode 100644 index e5b7a7eb..00000000 --- a/dev/kernel/src/UserProcessTeam.cc +++ /dev/null @@ -1,57 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -/***********************************************************************************/ -/// @file UserProcessTeam.cc -/// @brief Process teams implementation. -/// @author Amlal El Mahrouss (amlal@nekernel.org) -/***********************************************************************************/ - -#include - -namespace Kernel { -UserProcessTeam::UserProcessTeam() { - for (SizeT i = 0U; i < this->mProcessList.Count(); ++i) { - this->mProcessList[i] = USER_PROCESS(); - this->mProcessList[i].PTime = 0; - this->mProcessList[i].RTime = 0; - this->mProcessList[i].UTime = 0; - this->mProcessList[i].Status = ProcessStatusKind::kKilled; - this->mProcessList[i].ParentTeam = this; - } - - this->mProcessCur = 0UL; -} - -/***********************************************************************************/ -/// @brief Process list array getter. -/// @return The list of process to schedule. -/***********************************************************************************/ - -Array& UserProcessTeam::AsArray() { - return this->mProcessList; -} - -/***********************************************************************************/ -/// @brief Get team ID. -/// @return The team's ID. -/***********************************************************************************/ - -ProcessID& UserProcessTeam::Id() noexcept { - return this->mTeamId; -} - -/***********************************************************************************/ -/// @brief Get current process getter as Ref. -/// @return The current process header. -/***********************************************************************************/ - -Ref& UserProcessTeam::AsRef() { - return this->mCurrentProcess; -} -} // namespace Kernel - -// last rev 05-03-24 diff --git a/dev/kernel/src/UtfUtils.cc b/dev/kernel/src/UtfUtils.cc deleted file mode 100644 index 47ac2729..00000000 --- a/dev/kernel/src/UtfUtils.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* ======================================== - - Copyright (C) 2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -/// @author Amlal El Mahrouss (amlal@nekernel.org) - -namespace Kernel { -Size urt_string_len(const Utf8Char* str) { - if (!str) return 0; - - SizeT len{0}; - - while (str[len] != u8'\0') ++len; - - return len; -} - -Void urt_set_memory(const voidPtr src, UInt32 dst, Size len) { - if (!src) return; - - Utf8Char* srcChr = reinterpret_cast(src); - Size index = 0; - - while (index < len) { - srcChr[index] = dst; - ++index; - } -} - -Int32 urt_string_cmp(const Utf8Char* src, const Utf8Char* cmp, Size size) { - if (!src) return 0; - - Int32 counter = 0; - - for (Size index = 0; index < size; ++index) { - if (src[index] != cmp[index]) ++counter; - } - - return counter; -} - -Int32 urt_copy_memory(const VoidPtr src, VoidPtr dst, Size len) { - if (!src) return 0; - if (!dst) return 0; - - Utf8Char* srcChr = reinterpret_cast(src); - Utf8Char* dstChar = reinterpret_cast(dst); - - Size index = 0; - - while (index < len) { - dstChar[index] = srcChr[index]; - ++index; - } - - return index; -} -} // namespace Kernel diff --git a/dev/kernel/src/Variant.cc b/dev/kernel/src/Variant.cc deleted file mode 100644 index fcf2f443..00000000 --- a/dev/kernel/src/Variant.cc +++ /dev/null @@ -1,38 +0,0 @@ -/* ======================================== - - Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include - -namespace Kernel { -const Char* Variant::ToString() { - switch (fKind) { - case VariantKind::kTOML: - return ("Class:{TOML}"); - case VariantKind::kJson: - return ("Class:{Json}"); - case VariantKind::kString: - return ("Class:{String}"); - case VariantKind::kBlob: - return ("Class:{Blob}"); - case VariantKind::kNull: - return ("Class:{Null}"); - case VariantKind::kSwap: - return ("Class:{Swap}"); - default: - return ("Class:{Unknown}"); - } -} - -/// @brief Return variant's kind. -Variant::VariantKind& Variant::Kind() { - return this->fKind; -} - -/// @brief Leak variant's instance. -VoidPtr Variant::Leak() { - return this->fPtr; -} -} // namespace Kernel diff --git a/dev/kernel/src/ZXD.cc b/dev/kernel/src/ZXD.cc deleted file mode 100644 index 1baa18f3..00000000 --- a/dev/kernel/src/ZXD.cc +++ /dev/null @@ -1,7 +0,0 @@ -/* ======================================== - - Copyright (C) 2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. - -======================================== */ - -#include -- cgit v1.2.3