From d126ebf73370fbc64913aa6ff19db56a39f625b2 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Thu, 15 May 2025 18:42:59 +0200 Subject: feat(kernel): pushing the fixes regarding the scheduler, and working on making the LAPIC work correctly. Signed-off-by: Amlal El Mahrouss --- dev/kernel/HALKit/AMD64/HalCommonAPI.asm | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'dev/kernel/HALKit/AMD64/HalCommonAPI.asm') diff --git a/dev/kernel/HALKit/AMD64/HalCommonAPI.asm b/dev/kernel/HALKit/AMD64/HalCommonAPI.asm index c1dfc66a..432f79d3 100644 --- a/dev/kernel/HALKit/AMD64/HalCommonAPI.asm +++ b/dev/kernel/HALKit/AMD64/HalCommonAPI.asm @@ -79,4 +79,32 @@ mp_system_call_handler: o64 sysret -[bits 16] + +section .text + +global sched_jump_to_task + +;; Jump to the task from its stack frame. +sched_jump_to_task: + push rbp + mov rbp, rsp + + mov r8, [rcx + 0x10] + mov r9, [rcx + 0x18] + mov r10, [rcx + 0x20] + mov r11, [rcx + 0x28] + mov r12, [rcx + 0x30] + mov r13, [rcx + 0x38] + mov r14, [rcx + 0x40] + mov r15, [rcx + 0x48] + + mov rax, [rcx + 0x00] + mov rsp, [rcx + 0x08] ; SP + + jmp rax + +global rtl_ne_task + +rtl_ne_task: + jmp $ + ret \ No newline at end of file -- cgit v1.2.3 From 163f32fbfbfa2fb0744787769fb3d4865f57d8dd Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Sun, 18 May 2025 10:29:30 +0200 Subject: feat(kernel{sched/hal}): int 3 if something is wrong in `sched_jump_to_task` why: - After the image's entry is done, and no exit is called. also: - Added sched_idle_task to CPS's API. Signed-off-by: Amlal El Mahrouss --- dev/kernel/HALKit/AMD64/HalCommonAPI.asm | 7 ++++--- dev/kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc | 6 +++--- dev/kernel/HALKit/AMD64/HalKernelMain.cc | 8 +++----- dev/kernel/KernelKit/CoreProcessScheduler.h | 2 ++ 4 files changed, 12 insertions(+), 11 deletions(-) (limited to 'dev/kernel/HALKit/AMD64/HalCommonAPI.asm') diff --git a/dev/kernel/HALKit/AMD64/HalCommonAPI.asm b/dev/kernel/HALKit/AMD64/HalCommonAPI.asm index 432f79d3..a04aeb95 100644 --- a/dev/kernel/HALKit/AMD64/HalCommonAPI.asm +++ b/dev/kernel/HALKit/AMD64/HalCommonAPI.asm @@ -99,12 +99,13 @@ sched_jump_to_task: mov r15, [rcx + 0x48] mov rax, [rcx + 0x00] - mov rsp, [rcx + 0x08] ; SP + mov rsp, [rcx + 0x08] jmp rax + int 3 ;; Never continue here. -global rtl_ne_task +global sched_idle_task -rtl_ne_task: +sched_idle_task: jmp $ ret \ No newline at end of file diff --git a/dev/kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc b/dev/kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc index 00c206f0..7e2b8957 100644 --- a/dev/kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc +++ b/dev/kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc @@ -20,11 +20,11 @@ STATIC BOOL kIsRunning = NO; STATIC void hal_idt_send_eoi(UInt8 vector) { ((volatile UInt32*) kApicBaseAddress)[0xB0 / 4] = 0; - if (vector >= 0x20 && vector <= 0x2F) { + if (vector >= kPICCommand && vector <= 0x2F) { if (vector >= 0x28) { - Kernel::HAL::rt_out8(0xA0, 0x20); + Kernel::HAL::rt_out8(kPIC2Command, kPICCommand); } - Kernel::HAL::rt_out8(0x20, 0x20); + Kernel::HAL::rt_out8(kPICCommand, kPICCommand); } kIsRunning = NO; diff --git a/dev/kernel/HALKit/AMD64/HalKernelMain.cc b/dev/kernel/HALKit/AMD64/HalKernelMain.cc index 00dafc7b..581af60a 100644 --- a/dev/kernel/HALKit/AMD64/HalKernelMain.cc +++ b/dev/kernel/HALKit/AMD64/HalKernelMain.cc @@ -103,12 +103,10 @@ EXTERN_C Int32 hal_init_platform(Kernel::HEL::BootInfoHeader* handover_hdr) { return kEfiFail; } -EXTERN_C void rtl_ne_task(void); - EXTERN_C Kernel::Void hal_real_init(Kernel::Void) noexcept { - Kernel::rtl_create_user_process(rtl_ne_task, "MgmtSrv"); - Kernel::rtl_create_user_process(rtl_ne_task, "LaunchSrv"); - Kernel::rtl_create_user_process(rtl_ne_task, "SecSrv"); + Kernel::rtl_create_user_process(sched_idle_task, "MgmtSrv"); //! Mgmt command server. + Kernel::rtl_create_user_process(sched_idle_task, "LaunchSrv"); //! launchd + Kernel::rtl_create_user_process(sched_idle_task, "SecSrv"); //! Login Server Kernel::HAL::mp_init_cores(kHandoverHeader->f_HardwareTables.f_VendorPtr); diff --git a/dev/kernel/KernelKit/CoreProcessScheduler.h b/dev/kernel/KernelKit/CoreProcessScheduler.h index 6cb17261..6ac55424 100644 --- a/dev/kernel/KernelKit/CoreProcessScheduler.h +++ b/dev/kernel/KernelKit/CoreProcessScheduler.h @@ -19,6 +19,8 @@ #define kSchedNameLen (128U) +EXTERN_C void sched_idle_task(void); + namespace Kernel { class USER_PROCESS; class KERNEL_TASK; -- cgit v1.2.3 From bec0e457ad346783be7f84be71bb0eddc881847c Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Tue, 20 May 2025 13:46:07 +0200 Subject: wip: feat(kernel): Add stub for ring-3 switch on the AP side of the scheduling system. why? - To let the code run in user mode, as specified in the design. next: - Debug the #06 interrupt when switching to task. Signed-off-by: Amlal El Mahrouss --- dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc | 6 +- dev/kernel/HALKit/AMD64/HalCommonAPI.asm | 11 +- dev/kernel/src/FS/HeFS+FileSystemParser.cc | 242 ++++++++++----------- 3 files changed, 131 insertions(+), 128 deletions(-) (limited to 'dev/kernel/HALKit/AMD64/HalCommonAPI.asm') diff --git a/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc b/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc index 78db9b16..46ad8fd6 100644 --- a/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc +++ b/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc @@ -112,12 +112,10 @@ EXTERN_C BOOL mp_register_process(HAL::StackFramePtr stack_frame, ProcessID thrd kHWThread[thrdid].mFramePtr = stack_frame; kHWThread[thrdid].mThreadID = thrdid; - STATIC HardwareTimer timer{rtl_milliseconds(1000)}; - - timer.Wait(); - HardwareThreadScheduler::The()[thrdid].Leak()->Busy(NO); + sched_jump_to_task(stack_frame); + return YES; } diff --git a/dev/kernel/HALKit/AMD64/HalCommonAPI.asm b/dev/kernel/HALKit/AMD64/HalCommonAPI.asm index a04aeb95..230f50ed 100644 --- a/dev/kernel/HALKit/AMD64/HalCommonAPI.asm +++ b/dev/kernel/HALKit/AMD64/HalCommonAPI.asm @@ -84,11 +84,16 @@ section .text global sched_jump_to_task -;; Jump to the task from its stack frame. sched_jump_to_task: push rbp mov rbp, rsp + mov ax, 0x20 + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov r8, [rcx + 0x10] mov r9, [rcx + 0x18] mov r10, [rcx + 0x20] @@ -101,11 +106,11 @@ sched_jump_to_task: mov rax, [rcx + 0x00] mov rsp, [rcx + 0x08] - jmp rax + o64 sysret int 3 ;; Never continue here. global sched_idle_task sched_idle_task: jmp $ - ret \ No newline at end of file + ret diff --git a/dev/kernel/src/FS/HeFS+FileSystemParser.cc b/dev/kernel/src/FS/HeFS+FileSystemParser.cc index 519707d7..c8de1507 100644 --- a/dev/kernel/src/FS/HeFS+FileSystemParser.cc +++ b/dev/kernel/src/FS/HeFS+FileSystemParser.cc @@ -36,14 +36,14 @@ namespace Detail { /***********************************************************************************/ /// @brief Get the index node of a file or directory. - /// @param root The root node of the filesystem. + /// @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* root, + STATIC ATTRIBUTE(unused) _Output HEFS_INDEX_NODE* hefsi_fetch_in(HEFS_BOOT_NODE* boot, DriveTrait* mnt, const Utf8Char* dir_name, const Utf8Char* file_name, @@ -51,31 +51,31 @@ namespace Detail { /***********************************************************************************/ /// @brief Allocate a new index node-> - /// @param root The root node of the filesystem. + /// @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* root, DriveTrait* mnt, const Utf8Char* dir_name, + 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 root The root node 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* root, DriveTrait* mnt); + STATIC ATTRIBUTE(unused) _Output BOOL hefsi_balance_ind(HEFS_BOOT_NODE* boot, DriveTrait* mnt); /// @brief Alllocate IND from boot node. - /// @param root The root node of the filesystem. + /// @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* root, DriveTrait* mnt, + STATIC _Output BOOL hefsi_update_ind_status(HEFS_BOOT_NODE* boot, DriveTrait* mnt, const Utf8Char* dir_name, UInt16 flags, const BOOL delete_or_create); @@ -251,24 +251,24 @@ namespace Detail { } /// @brief Alllocate IND from boot node. - /// @param root The root node of the filesystem. + /// @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* root, DriveTrait* mnt, + 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_new_ptr(sizeof(HEFS_INDEX_NODE_DIRECTORY), Yes, No); - auto start = root->fStartIND; + auto start = boot->fStartIND; auto prev_location = start; auto parent_location = 0UL; - MUST_PASS(root->fStartIND > mnt->fLbaStart); + MUST_PASS(boot->fStartIND > mnt->fLbaStart); while (YES) { auto prev_start = start; @@ -323,7 +323,7 @@ namespace Detail { if (tmpend->fChecksum != ke_calculate_crc32((Char*) tmpend, sizeof(HEFS_INDEX_NODE_DIRECTORY))) - ke_panic(RUNTIME_CHECK_FILESYSTEM, "Bad CRC32"); + ke_panic(RUNTIME_CHECK_FILESYSTEM, "Bad CRC32 value, aborting."); if (delete_or_create) --tmpend->fEntryCount; @@ -349,7 +349,7 @@ namespace Detail { break; } - hefsi_traverse_tree(tmpend, mnt, root->fStartIND, child_first); + hefsi_traverse_tree(tmpend, mnt, boot->fStartIND, child_first); } } @@ -364,11 +364,11 @@ namespace Detail { } if (dirent->fPrev == 0) { - dirent->fPrev = root->fStartIND; + dirent->fPrev = boot->fStartIND; } if (dirent->fParent == 0) { - dirent->fParent = root->fStartIND; + dirent->fParent = boot->fStartIND; } if (tmpdir->fChild == 0) { @@ -389,13 +389,13 @@ namespace Detail { } child += sizeof(HEFS_INDEX_NODE_DIRECTORY); - if (child > root->fEndIND) break; + if (child > boot->fEndIND) break; } dirent->fColor = kHeFSRed; dirent->fChild = child; - if (child > root->fEndIND) dirent->fChild = root->fStartIND; + if (child > boot->fEndIND) dirent->fChild = boot->fStartIND; } for (SizeT index = 0UL; index < kHeFSSliceCount; ++index) { @@ -416,15 +416,15 @@ namespace Detail { mm_delete_ptr(tmpdir); if (!delete_or_create) - ++root->fINDCount; + ++boot->fINDCount; else - --root->fINDCount; + --boot->fINDCount; - root->fChecksum = ke_calculate_crc32((Char*) root, sizeof(HEFS_BOOT_NODE)); + 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 = root; + mnt->fPacket.fPacketContent = boot; mnt->fOutput(mnt->fPacket); @@ -433,8 +433,8 @@ namespace Detail { prev_location = start; - hefsi_traverse_tree(tmpdir, mnt, root->fStartIND, start); - if (start > root->fEndIND || start == 0) break; + hefsi_traverse_tree(tmpdir, mnt, boot->fStartIND, start); + if (start > boot->fEndIND || start == 0) break; } err_global_get() = kErrorDisk; @@ -448,22 +448,22 @@ namespace Detail { } /// @brief Get the index node of a file or directory. - /// @param root The root node of the filesystem. + /// @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* root, + 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 (root->fStartIND > root->fEndIND) return nullptr; - if (root->fStartIN > root->fEndIN) return nullptr; + if (boot->fStartIND > boot->fEndIND) return nullptr; + if (boot->fStartIN > boot->fEndIN) return nullptr; - auto start = root->fStartIND; + auto start = boot->fStartIND; HEFS_INDEX_NODE* node = new HEFS_INDEX_NODE(); HEFS_INDEX_NODE_DIRECTORY* dir = @@ -511,8 +511,8 @@ namespace Detail { } } - hefsi_traverse_tree(dir, mnt, root->fStartIND, start); - if (start == root->fStartIND || start == root->fStartIND) break; + hefsi_traverse_tree(dir, mnt, boot->fStartIND, start); + if (start == boot->fStartIND || start == boot->fStartIND) break; } delete node; @@ -530,16 +530,16 @@ namespace Detail { } STATIC ATTRIBUTE(unused) _Output BOOL - hefsi_update_in_status(HEFS_BOOT_NODE* root, DriveTrait* mnt, const Utf8Char* dir_name, + hefsi_update_in_status(HEFS_BOOT_NODE* boot, DriveTrait* mnt, const Utf8Char* dir_name, HEFS_INDEX_NODE* node, BOOL delete_or_create) { - if (!root || !mnt) return NO; + if (!boot || !mnt) return NO; - auto start = root->fStartIND; + auto start = boot->fStartIND; - if (start > root->fEndIND) return NO; - if (root->fStartIN > root->fEndIN) return NO; + if (start > boot->fEndIND) return NO; + if (boot->fStartIN > boot->fEndIN) return NO; ; - if (root->fStartBlock > root->fEndBlock) return NO; + if (boot->fStartBlock > boot->fEndBlock) return NO; if (mnt) { HEFS_INDEX_NODE_DIRECTORY* dir = @@ -560,7 +560,7 @@ namespace Detail { 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] = root->fStartIN; + dir->fINSlices[inode_index] = boot->fStartIN; ++dir->fEntryCount; @@ -574,8 +574,8 @@ namespace Detail { auto lba = dir->fINSlices[inode_index]; - node->fOffsetSliceLow = (UInt32) (root->fStartBlock); - node->fOffsetSliceHigh = (UInt32) (root->fStartBlock >> 32); + node->fOffsetSliceLow = (UInt32) (boot->fStartBlock); + node->fOffsetSliceHigh = (UInt32) (boot->fStartBlock >> 32); node->fChecksum = ke_calculate_crc32((Char*) node, sizeof(HEFS_INDEX_NODE)); @@ -585,14 +585,14 @@ namespace Detail { mnt->fOutput(mnt->fPacket); - root->fStartIN += sizeof(HEFS_INDEX_NODE); - root->fStartBlock += kHeFSBlockLen; + boot->fStartIN += sizeof(HEFS_INDEX_NODE); + boot->fStartBlock += kHeFSBlockLen; - root->fChecksum = ke_calculate_crc32((Char*) root, sizeof(HEFS_BOOT_NODE)); + 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 = root; + mnt->fPacket.fPacketContent = boot; mnt->fOutput(mnt->fPacket); @@ -617,14 +617,14 @@ namespace Detail { node->fOffsetSliceLow = 0; node->fOffsetSliceHigh = 0; - root->fStartIN -= sizeof(HEFS_INDEX_NODE); - root->fStartBlock -= kHeFSBlockLen; + boot->fStartIN -= sizeof(HEFS_INDEX_NODE); + boot->fStartBlock -= kHeFSBlockLen; - root->fChecksum = ke_calculate_crc32((Char*) root, sizeof(HEFS_BOOT_NODE)); + 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 = root; + mnt->fPacket.fPacketContent = boot; mnt->fOutput(mnt->fPacket); @@ -653,8 +653,8 @@ namespace Detail { } } - hefsi_traverse_tree(dir, mnt, root->fStartIND, start); - if (start > root->fEndIND || start == 0) break; + hefsi_traverse_tree(dir, mnt, boot->fStartIND, start); + if (start > boot->fEndIND || start == 0) break; } mm_delete_ptr(dir); @@ -667,18 +667,18 @@ namespace Detail { } /// @brief Balance RB-Tree of the filesystem. - /// @param root The root node 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* root, DriveTrait* mnt) { + 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 = root->fStartIND; + auto start = boot->fStartIND; while (YES) { - if (start == 0UL || start > root->fEndIND) break; + if (start == 0UL || start > boot->fEndIND) break; mnt->fPacket.fPacketLba = start; mnt->fPacket.fPacketSize = sizeof(HEFS_INDEX_NODE_DIRECTORY); @@ -692,7 +692,7 @@ namespace Detail { return NO; } - if (start == root->fStartIND) { + if (start == boot->fStartIND) { dir->fColor = kHeFSBlack; mnt->fPacket.fPacketLba = start; @@ -725,7 +725,7 @@ namespace Detail { mnt->fOutput(mnt->fPacket); } - hefsi_traverse_tree(dir, mnt, root->fStartIND, start); + hefsi_traverse_tree(dir, mnt, boot->fStartIND, start); } err_global_get() = kErrorSuccess; @@ -763,11 +763,11 @@ _Output Bool HeFileSystemParser::Format(_Input _Output DriveTrait* mnt, _Input c return NO; } - HEFS_BOOT_NODE* root = (HEFS_BOOT_NODE*) RTL_ALLOCA(sizeof(HEFS_BOOT_NODE)); + 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 = root; + mnt->fPacket.fPacketContent = boot; mnt->fInput(mnt->fPacket); @@ -779,9 +779,9 @@ _Output Bool HeFileSystemParser::Format(_Input _Output DriveTrait* mnt, _Input c // Check if the disk is already formatted. - if (KStringBuilder::Equals(root->fMagic, kHeFSMagic) && root->fVersion == kHeFSVersion) { - if (ke_calculate_crc32((Char*) root, sizeof(HEFS_BOOT_NODE)) != root->fChecksum && - root->fChecksum > 0) { + 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; } @@ -790,8 +790,8 @@ _Output Bool HeFileSystemParser::Format(_Input _Output DriveTrait* mnt, _Input c return YES; } - if (ke_calculate_crc32((Char*) root, sizeof(HEFS_BOOT_NODE)) != root->fChecksum && - root->fChecksum > 0) { + if (ke_calculate_crc32((Char*) boot, sizeof(HEFS_BOOT_NODE)) != boot->fChecksum && + boot->fChecksum > 0) { err_global_get() = kErrorDiskIsCorrupted; return NO; } @@ -799,8 +799,8 @@ _Output Bool HeFileSystemParser::Format(_Input _Output DriveTrait* mnt, _Input c rt_copy_memory((VoidPtr) "fs/hefs-packet", mnt->fPacket.fPacketMime, rt_string_len("fs/hefs-packet")); - urt_copy_memory((VoidPtr) vol_name, root->fVolName, urt_string_len(vol_name) + 1); - rt_copy_memory((VoidPtr) kHeFSMagic, root->fMagic, kHeFSMagicLen - 1); + urt_copy_memory((VoidPtr) vol_name, boot->fVolName, urt_string_len(vol_name) + 1); + rt_copy_memory((VoidPtr) kHeFSMagic, boot->fMagic, kHeFSMagicLen - 1); if (mnt->fLbaStart > mnt->fLbaEnd) { err_global_get() = kErrorDiskIsCorrupted; @@ -808,66 +808,66 @@ _Output Bool HeFileSystemParser::Format(_Input _Output DriveTrait* mnt, _Input c return NO; } - root->fBadSectors = 0; + boot->fBadSectors = 0; - root->fSectorCount = drv_std_get_sector_count(); - root->fSectorSize = mnt->fSectorSz; + boot->fSectorCount = drv_std_get_sector_count(); + boot->fSectorSize = mnt->fSectorSz; - MUST_PASS(root->fSectorSize); + MUST_PASS(boot->fSectorSize); /// @note all HeFS strucutres are equal to 512, so here it's fine, unless fSectoSize is 2048. - const SizeT max_lba = (drv_std_get_size()) / root->fSectorSize; + 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 - root->fStartIND = mnt->fLbaStart + kHeFSINDStartOffset; - root->fEndIND = root->fStartIND + dir_max; + boot->fStartIND = mnt->fLbaStart + kHeFSINDStartOffset; + boot->fEndIND = boot->fStartIND + dir_max; - root->fStartIN = root->fEndIND; - root->fEndIN = root->fStartIN + inode_max; + boot->fStartIN = boot->fEndIND; + boot->fEndIN = boot->fStartIN + inode_max; - root->fStartBlock = root->fEndIN; - root->fEndBlock = drv_std_get_size(); + boot->fStartBlock = boot->fEndIN; + boot->fEndBlock = drv_std_get_size(); - root->fINDCount = 0; + boot->fINDCount = 0; - root->fDiskSize = drv_std_get_size(); - root->fDiskStatus = kHeFSStatusUnlocked; + boot->fDiskSize = drv_std_get_size(); + boot->fDiskStatus = kHeFSStatusUnlocked; - root->fDiskFlags = flags; + boot->fDiskFlags = flags; if (mnt->fKind & kMassStorageDrive) { - root->fDiskKind = kHeFSMassStorageDevice; + boot->fDiskKind = kHeFSMassStorageDevice; } else if (mnt->fKind & kHeFSOpticalDrive) { - root->fDiskKind = kHeFSOpticalDrive; + boot->fDiskKind = kHeFSOpticalDrive; } else { - root->fDiskKind = kHeFSUnknown; + boot->fDiskKind = kHeFSUnknown; } - root->fVersion = kHeFSVersion; + boot->fVersion = kHeFSVersion; - root->fVID = kHeFSInvalidVID; + boot->fVID = kHeFSInvalidVID; - root->fChecksum = ke_calculate_crc32((Char*) root, sizeof(HEFS_BOOT_NODE)); + 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 = root; + mnt->fPacket.fPacketContent = boot; mnt->fOutput(mnt->fPacket); (Void)(kout << "Protocol: " << mnt->fProtocol() << kendl); - (Void)(kout8 << u8"Volume Name: " << root->fVolName << kendl8); - (Void)(kout << "Start IND: " << hex_number(root->fStartIND) << kendl); - (Void)(kout << "End IND: " << hex_number(root->fEndIND) << kendl); - (Void)(kout << "Start IN: " << hex_number(root->fStartIN) << kendl); - (Void)(kout << "End IN: " << hex_number(root->fEndIN) << kendl); - (Void)(kout << "Start Block: " << hex_number(root->fStartBlock) << kendl); - (Void)(kout << "End Block: " << hex_number(root->fEndBlock) << kendl); - (Void)(kout << "Number of IND: " << hex_number(root->fINDCount) << kendl); - (Void)(kout << "Sector Size: " << hex_number(root->fSectorSize) << kendl); - (Void)(kout << "Drive Kind: " << Detail::hefs_drive_kind_to_string(root->fDiskKind) << 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; @@ -902,23 +902,23 @@ _Output Bool HeFileSystemParser::INodeDirectoryCtlManip(_Input DriveTrait* mnt, return NO; } - HEFS_BOOT_NODE* root = (HEFS_BOOT_NODE*) mm_new_ptr(sizeof(HEFS_BOOT_NODE), Yes, No); + HEFS_BOOT_NODE* boot = (HEFS_BOOT_NODE*) mm_new_ptr(sizeof(HEFS_BOOT_NODE), Yes, No); rt_copy_memory((VoidPtr) "fs/hefs-packet", mnt->fPacket.fPacketMime, rt_string_len("fs/hefs-packet")); mnt->fPacket.fPacketLba = mnt->fLbaStart; mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = root; + mnt->fPacket.fPacketContent = boot; mnt->fInput(mnt->fPacket); - if (!KStringBuilder::Equals(root->fMagic, kHeFSMagic) || root->fVersion != kHeFSVersion) { + if (!KStringBuilder::Equals(boot->fMagic, kHeFSMagic) || boot->fVersion != kHeFSVersion) { err_global_get() = kErrorDisk; return YES; } - if (!KStringBuilder::Equals(root->fMagic, kHeFSMagic) || root->fVersion != kHeFSVersion) { + if (!KStringBuilder::Equals(boot->fMagic, kHeFSMagic) || boot->fVersion != kHeFSVersion) { err_global_get() = kErrorDiskIsCorrupted; kout << "Invalid Boot Node, this can't continue!\r"; @@ -934,15 +934,15 @@ _Output Bool HeFileSystemParser::INodeDirectoryCtlManip(_Input DriveTrait* mnt, return NO; } - if (Detail::hefsi_update_ind_status(root, mnt, dir, flags, delete_or_create)) { + if (Detail::hefsi_update_ind_status(boot, mnt, dir, flags, delete_or_create)) { // todo: make it smarter for high-throughput. - Detail::hefsi_balance_ind(root, mnt); + Detail::hefsi_balance_ind(boot, mnt); - mm_delete_ptr((VoidPtr) root); + mm_delete_ptr((VoidPtr) boot); return YES; } - mm_delete_ptr((VoidPtr) root); + mm_delete_ptr((VoidPtr) boot); return NO; } @@ -983,9 +983,9 @@ _Output Bool HeFileSystemParser::INodeManip(_Input DriveTrait* mnt, VoidPtr bloc return NO; } - HEFS_BOOT_NODE* root = (HEFS_BOOT_NODE*) mm_new_ptr(sizeof(HEFS_BOOT_NODE), Yes, No); + HEFS_BOOT_NODE* boot = (HEFS_BOOT_NODE*) mm_new_ptr(sizeof(HEFS_BOOT_NODE), Yes, No); - if (!root) { + if (!boot) { err_global_get() = kErrorInvalidData; return NO; } @@ -995,18 +995,18 @@ _Output Bool HeFileSystemParser::INodeManip(_Input DriveTrait* mnt, VoidPtr bloc mnt->fPacket.fPacketLba = mnt->fLbaStart; mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = root; + mnt->fPacket.fPacketContent = boot; mnt->fInput(mnt->fPacket); - if (!KStringBuilder::Equals(root->fMagic, kHeFSMagic) || root->fVersion != kHeFSVersion) { + if (!KStringBuilder::Equals(boot->fMagic, kHeFSMagic) || boot->fVersion != kHeFSVersion) { (Void)(kout << "Invalid Boot Node, HeFS partition is invalid." << kendl); - mm_delete_ptr((VoidPtr) root); + mm_delete_ptr((VoidPtr) boot); err_global_get() = kErrorDisk; return NO; } - auto start = Detail::hefsi_fetch_in(root, mnt, dir, name, kind); + auto start = Detail::hefsi_fetch_in(boot, mnt, dir, name, kind); if (start) { (Void)(kout << hex_number(start->fHashPath) << kendl); @@ -1021,7 +1021,7 @@ _Output Bool HeFileSystemParser::INodeManip(_Input DriveTrait* mnt, VoidPtr bloc mnt->fInput(mnt->fPacket); } else { if (start->fFlags & kHeFSFlagsReadOnly) { - mm_delete_ptr((VoidPtr) root); + mm_delete_ptr((VoidPtr) boot); delete start; kout << "Error: File is read-only\r"; @@ -1034,7 +1034,7 @@ _Output Bool HeFileSystemParser::INodeManip(_Input DriveTrait* mnt, VoidPtr bloc } } - mm_delete_ptr((VoidPtr) root); + mm_delete_ptr((VoidPtr) boot); delete start; return YES; } @@ -1067,9 +1067,9 @@ _Output Bool HeFileSystemParser::INodeCtlManip(_Input DriveTrait* mnt, _Input co rt_set_memory(node, 0, sizeof(HEFS_INDEX_NODE)); - HEFS_BOOT_NODE* root = (HEFS_BOOT_NODE*) RTL_ALLOCA(sizeof(HEFS_BOOT_NODE)); + HEFS_BOOT_NODE* boot = (HEFS_BOOT_NODE*) RTL_ALLOCA(sizeof(HEFS_BOOT_NODE)); - if (!root) { + if (!boot) { mm_delete_ptr((VoidPtr) node); err_global_get() = kErrorInvalidData; @@ -1081,11 +1081,11 @@ _Output Bool HeFileSystemParser::INodeCtlManip(_Input DriveTrait* mnt, _Input co mnt->fPacket.fPacketLba = mnt->fLbaStart; mnt->fPacket.fPacketSize = sizeof(HEFS_BOOT_NODE); - mnt->fPacket.fPacketContent = root; + mnt->fPacket.fPacketContent = boot; mnt->fInput(mnt->fPacket); - if (!KStringBuilder::Equals(root->fMagic, kHeFSMagic) || root->fVersion != kHeFSVersion) { + if (!KStringBuilder::Equals(boot->fMagic, kHeFSMagic) || boot->fVersion != kHeFSVersion) { err_global_get() = kErrorDisk; return YES; } @@ -1112,8 +1112,8 @@ _Output Bool HeFileSystemParser::INodeCtlManip(_Input DriveTrait* mnt, _Input co } node->fAccessed = 0; - node->fCreated = delete_or_create ? 0UL : 1UL; - node->fDeleted = delete_or_create ? 1UL : 0UL; + node->fCreated = delete_or_create ? NO : YES; + node->fDeleted = delete_or_create ? 1UL : NO; node->fModified = 0; node->fSize = 0; node->fKind = kind; @@ -1123,10 +1123,10 @@ _Output Bool HeFileSystemParser::INodeCtlManip(_Input DriveTrait* mnt, _Input co node->fUID = 0; node->fHashPath = Detail::hefsi_hash_64(name); - if (Detail::hefsi_update_in_status(root, mnt, dir, node, delete_or_create)) { + if (Detail::hefsi_update_in_status(boot, mnt, dir, node, delete_or_create)) { mm_delete_ptr((VoidPtr) node); - Detail::hefsi_balance_ind(root, mnt); + Detail::hefsi_balance_ind(boot, mnt); err_global_get() = kErrorSuccess; return YES; -- cgit v1.2.3 From 58d2af14429be02b580cde5b3e23978530d8ab74 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Wed, 21 May 2025 10:19:07 +0200 Subject: feat(kernel): Architectural changes, and introducing a kKernelVM. see code for more details. Signed-off-by: Amlal El Mahrouss --- dev/boot/src/BootThread.cc | 3 ++ dev/boot/src/HEL/AMD64/BootEFI.cc | 2 +- dev/kernel/ArchKit/ArchKit.h | 8 +++- dev/kernel/FirmwareKit/Handover.h | 2 + dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc | 22 +++------- dev/kernel/HALKit/AMD64/HalCommonAPI.asm | 48 +++++++++++++++----- .../HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc | 51 +--------------------- dev/kernel/HALKit/AMD64/HalInterruptAPI.asm | 22 ---------- dev/kernel/HALKit/AMD64/HalKernelMain.cc | 27 ++++++++++-- dev/kernel/HALKit/AMD64/Processor.h | 2 - dev/kernel/HALKit/ARM64/HalApplicationProcessor.cc | 2 +- dev/kernel/HALKit/ARM64/Processor.h | 2 - dev/kernel/KernelKit/KernelTaskScheduler.h | 2 +- dev/kernel/src/HardwareThreadScheduler.cc | 4 +- dev/kernel/src/UserProcessScheduler.cc | 23 +++++++--- 15 files changed, 100 insertions(+), 120 deletions(-) (limited to 'dev/kernel/HALKit/AMD64/HalCommonAPI.asm') diff --git a/dev/boot/src/BootThread.cc b/dev/boot/src/BootThread.cc index ada864bb..b502b52e 100644 --- a/dev/boot/src/BootThread.cc +++ b/dev/boot/src/BootThread.cc @@ -175,6 +175,9 @@ Int32 BootThread::Start(HEL::BootInfoHeader* handover, Bool own_stack) { writer.Write("BootZ: Stack address: ").Write((UIntPtr) &fStack[mib_cast(16) - 1]).Write("\r"); writer.Write("BootZ: Stack size: ").Write(mib_cast(16)).Write("\r"); + fHandover->f_StackTop = &fStack[mib_cast(16) - 1]; + fHandover->f_StackSz = mib_cast(16); + auto ret = rt_jump_to_address(fStartAddress, fHandover, &fStack[mib_cast(16) - 1]); // we don't need the stack anymore. diff --git a/dev/boot/src/HEL/AMD64/BootEFI.cc b/dev/boot/src/HEL/AMD64/BootEFI.cc index 45566d6c..33dfd3ca 100644 --- a/dev/boot/src/HEL/AMD64/BootEFI.cc +++ b/dev/boot/src/HEL/AMD64/BootEFI.cc @@ -243,7 +243,7 @@ EFI_EXTERN_C EFI_API Int32 BootloaderMain(EfiHandlePtr image_handle, EfiSystemTa handover_hdr->f_KernelImage = reader_kernel.Blob(); handover_hdr->f_KernelSz = reader_kernel.Size(); - kernel_thread.Start(handover_hdr, NO); + kernel_thread.Start(handover_hdr, YES); } Boot::BootFileReader reader_netboot(L"net.efi", image_handle); diff --git a/dev/kernel/ArchKit/ArchKit.h b/dev/kernel/ArchKit/ArchKit.h index 41a36e69..d511658f 100644 --- a/dev/kernel/ArchKit/ArchKit.h +++ b/dev/kernel/ArchKit/ArchKit.h @@ -77,8 +77,14 @@ struct HalSyscallEntry final { operator bool() { return fHooked; } }; +EXTERN_C Kernel::HAL::StackFramePtr mp_get_current_context(Kernel::Int64 pid); + inline Kernel::Array kSysCalls; inline Kernel::Array kKernCalls; -EXTERN_C Kernel::HAL::StackFramePtr mp_get_current_context(Kernel::Int64 pid); +#ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ + +inline Kernel::VoidPtr kKernelVM = nullptr; + +#endif // __NE_VIRTUAL_MEMORY_SUPPORT__ \ No newline at end of file diff --git a/dev/kernel/FirmwareKit/Handover.h b/dev/kernel/FirmwareKit/Handover.h index d3ccc724..cda27e52 100644 --- a/dev/kernel/FirmwareKit/Handover.h +++ b/dev/kernel/FirmwareKit/Handover.h @@ -63,6 +63,8 @@ struct BootInfoHeader final { SizeT f_KernelSz; VoidPtr f_StartupImage; SizeT f_StartupSz; + VoidPtr f_StackTop; + SizeT f_StackSz; WideChar f_FirmwareVendorName[32]; SizeT f_FirmwareVendorLen; diff --git a/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc b/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc index e4ad1024..ada2ee3f 100644 --- a/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc +++ b/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc @@ -113,27 +113,17 @@ EXTERN_C HAL::StackFramePtr mp_get_current_context(Int64 thrdid) { /// @param thrdid The thread ID. /***********************************************************************************/ -EXTERN_C BOOL mp_register_process(HAL::StackFramePtr stack_frame, ProcessID thrdid) { +EXTERN_C BOOL mp_register_task(HAL::StackFramePtr stack_frame, ProcessID thrdid) { if (thrdid > kSMPCount) return NO; - if (!mp_is_smp()) { - if (stack_frame) { - kHWThread[thrdid].mFramePtr = stack_frame; - kHWThread[thrdid].mThreadID = thrdid; - HardwareThreadScheduler::The()[thrdid].Leak()->Busy(NO); + kHWThread[thrdid].mFramePtr = stack_frame; + kHWThread[thrdid].mThreadID = thrdid; - sched_jump_to_task(stack_frame); + HardwareThreadScheduler::The()[thrdid].Leak()->Busy(NO); - return YES; - } - } else { - kHWThread[thrdid].mFramePtr = stack_frame; - kHWThread[thrdid].mThreadID = thrdid; - - return YES; - } + sched_jump_to_task(stack_frame); - return NO; + return YES; } /***********************************************************************************/ diff --git a/dev/kernel/HALKit/AMD64/HalCommonAPI.asm b/dev/kernel/HALKit/AMD64/HalCommonAPI.asm index 230f50ed..d0ce2418 100644 --- a/dev/kernel/HALKit/AMD64/HalCommonAPI.asm +++ b/dev/kernel/HALKit/AMD64/HalCommonAPI.asm @@ -56,6 +56,8 @@ extern hal_system_call_enter global mp_system_call_handler mp_system_call_handler: + push rbp + mov rbp, rsp push r8 push r9 @@ -77,7 +79,9 @@ mp_system_call_handler: pop r9 pop r8 - o64 sysret + pop rbp + + o64 iret section .text @@ -88,12 +92,40 @@ sched_jump_to_task: push rbp mov rbp, rsp - mov ax, 0x20 + mov ax, 0x30 mov ds, ax mov es, ax mov fs, ax mov gs, ax + mov ax, 0x18 + ltr ax + + push 0x30 + mov rdx, [rcx + 0x08] + push rdx + o64 pushf + push 0x28 + mov rdx, [rcx + 0x00] + push rdx + + call sched_recover_registers + + o64 iret + +global sched_idle_task + +sched_idle_task: + mov ax, cs + and ax, 3 + + jmp $ + ret + +sched_recover_registers: + push rbp + mov rbp, rsp + mov r8, [rcx + 0x10] mov r9, [rcx + 0x18] mov r10, [rcx + 0x20] @@ -103,14 +135,6 @@ sched_jump_to_task: mov r14, [rcx + 0x40] mov r15, [rcx + 0x48] - mov rax, [rcx + 0x00] - mov rsp, [rcx + 0x08] - - o64 sysret - int 3 ;; Never continue here. + pop rbp -global sched_idle_task - -sched_idle_task: - jmp $ - ret + ret \ No newline at end of file diff --git a/dev/kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc b/dev/kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc index 51fc4f0e..633adccb 100644 --- a/dev/kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc +++ b/dev/kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc @@ -37,14 +37,6 @@ EXTERN_C Kernel::Void idt_handle_gpf(Kernel::UIntPtr rsp) { auto& process = Kernel::UserProcessScheduler::The().TheCurrentProcess(); - if (!process) { - ke_panic(RUNTIME_CHECK_BAD_BEHAVIOR, "General Access Fault."); - } - if (process.Leak().Signal.SignalID == SIGKILL || process.Leak().Signal.SignalID == SIGABRT || - process.Leak().Signal.SignalID == SIGTRAP) { - dbg_break_point(); - } - Kernel::kout << "Kernel: General Access Fault.\r"; process.Leak().Signal.SignalArg = rsp; @@ -63,15 +55,6 @@ EXTERN_C void idt_handle_pf(Kernel::UIntPtr rsp) { auto& process = Kernel::UserProcessScheduler::The().TheCurrentProcess(); - if (!process) { - ke_panic(RUNTIME_CHECK_BAD_BEHAVIOR, "Access Fault."); - } - - if (process.Leak().Signal.SignalID == SIGKILL || process.Leak().Signal.SignalID == SIGABRT || - process.Leak().Signal.SignalID == SIGTRAP) { - dbg_break_point(); - } - Kernel::kout << "Kernel: Page Fault.\r"; Kernel::kout << "Kernel: SIGKILL\r"; @@ -104,14 +87,6 @@ EXTERN_C void idt_handle_math(Kernel::UIntPtr rsp) { auto& process = Kernel::UserProcessScheduler::The().TheCurrentProcess(); - if (!process) { - ke_panic(RUNTIME_CHECK_BAD_BEHAVIOR, "Math Fault."); - } - if (process.Leak().Signal.SignalID == SIGKILL || process.Leak().Signal.SignalID == SIGABRT || - process.Leak().Signal.SignalID == SIGTRAP) { - dbg_break_point(); - } - Kernel::kout << "Kernel: Math error (division by zero?).\r"; process.Leak().Signal.SignalArg = rsp; @@ -130,15 +105,6 @@ EXTERN_C void idt_handle_generic(Kernel::UIntPtr rsp) { auto& process = Kernel::UserProcessScheduler::The().TheCurrentProcess(); - if (!process) { - ke_panic(RUNTIME_CHECK_BAD_BEHAVIOR, "Generic Fault."); - } - - if (process.Leak().Signal.SignalID == SIGKILL || process.Leak().Signal.SignalID == SIGABRT || - process.Leak().Signal.SignalID == SIGTRAP) { - dbg_break_point(); - } - (Void)(Kernel::kout << "Kernel: Process RSP: " << Kernel::hex_number(rsp) << Kernel::kendl); Kernel::kout << "Kernel: Access Process Fault.\r"; @@ -152,19 +118,9 @@ EXTERN_C void idt_handle_generic(Kernel::UIntPtr rsp) { } EXTERN_C Kernel::Void idt_handle_breakpoint(Kernel::UIntPtr rip) { - auto& process = Kernel::UserProcessScheduler::The().TheCurrentProcess(); - - if (!process) { - while (YES) - ; - } - hal_idt_send_eoi(3); - if (process.Leak().Signal.SignalID == SIGKILL || process.Leak().Signal.SignalID == SIGABRT || - process.Leak().Signal.SignalID == SIGTRAP) { - dbg_break_point(); - } + auto& process = Kernel::UserProcessScheduler::The().TheCurrentProcess(); (Void)(Kernel::kout << "Kernel: Process RIP: " << Kernel::hex_number(rip) << Kernel::kendl); @@ -189,11 +145,6 @@ EXTERN_C void idt_handle_ud(Kernel::UIntPtr rsp) { auto& process = Kernel::UserProcessScheduler::The().TheCurrentProcess(); - if (!process) { - while (YES) - ; - } - if (process.Leak().Signal.SignalID == SIGKILL || process.Leak().Signal.SignalID == SIGABRT || process.Leak().Signal.SignalID == SIGTRAP) { dbg_break_point(); diff --git a/dev/kernel/HALKit/AMD64/HalInterruptAPI.asm b/dev/kernel/HALKit/AMD64/HalInterruptAPI.asm index a6b194d3..5e82f969 100644 --- a/dev/kernel/HALKit/AMD64/HalInterruptAPI.asm +++ b/dev/kernel/HALKit/AMD64/HalInterruptAPI.asm @@ -20,8 +20,6 @@ __NE_INT_%1: std - add rsp, 8 - o64 iret %endmacro @@ -61,8 +59,6 @@ __NE_INT_0: std - add rsp, 8 - o64 iret __NE_INT_1: @@ -83,8 +79,6 @@ __NE_INT_2: std - add rsp, 8 - o64 iret ;; @brief Triggers a breakpoint and freeze the process. RIP is also fetched. @@ -96,8 +90,6 @@ __NE_INT_3: std - add rsp, 8 - o64 iret __NE_INT_4: @@ -109,16 +101,12 @@ __NE_INT_4: std - add rsp, 8 - o64 iret __NE_INT_5: cld std - add rsp, 8 - o64 iret ;; Invalid opcode interrupt @@ -130,8 +118,6 @@ __NE_INT_6: std - add rsp, 8 - o64 iret __NE_INT_7: @@ -142,8 +128,6 @@ __NE_INT_7: std - add rsp, 8 - o64 iret ;; Invalid opcode interrupt @@ -156,8 +140,6 @@ __NE_INT_8: std - add rsp, 8 - o64 iret IntNormal 9 @@ -187,8 +169,6 @@ __NE_INT_14: std - add rsp, 8 - o64 iret IntNormal 15 @@ -247,8 +227,6 @@ __NE_INT_40: std - add rsp, 8 - o64 iret IntNormal 41 diff --git a/dev/kernel/HALKit/AMD64/HalKernelMain.cc b/dev/kernel/HALKit/AMD64/HalKernelMain.cc index 4de43f27..5394645a 100644 --- a/dev/kernel/HALKit/AMD64/HalKernelMain.cc +++ b/dev/kernel/HALKit/AMD64/HalKernelMain.cc @@ -38,9 +38,9 @@ EXTERN_C Int32 hal_init_platform(Kernel::HEL::BootInfoHeader* handover_hdr) { Boot::ExitBootServices(handover_hdr->f_HardwareTables.f_ImageKey, handover_hdr->f_HardwareTables.f_ImageHandle); - kKernelCR3 = kHandoverHeader->f_PageStart; + kKernelVM = kHandoverHeader->f_PageStart; - hal_write_cr3(kKernelCR3); + hal_write_cr3(kKernelVM); /************************************** */ /* INITIALIZE BIT MAP. */ @@ -54,7 +54,12 @@ EXTERN_C Int32 hal_init_platform(Kernel::HEL::BootInfoHeader* handover_hdr) { /* INITIALIZE GDT AND SEGMENTS. */ /************************************** */ - STATIC CONST auto kGDTEntriesCount = 6; + STATIC CONST auto kGDTEntriesCount = 8; + + STATIC HAL::Detail::NE_TSS kKernelTSS{}; + + kKernelTSS.fRsp0 = (UInt64) kHandoverHeader->f_StackTop; + kKernelTSS.fIopb = sizeof(HAL::Detail::NE_TSS); /* The GDT, mostly descriptors for user and kernel segments. */ STATIC Kernel::HAL::Detail::NE_GDT_ENTRY ALIGN(0x08) kGDTArray[kGDTEntriesCount] = { @@ -76,6 +81,8 @@ EXTERN_C Int32 hal_init_platform(Kernel::HEL::BootInfoHeader* handover_hdr) { .fAccessByte = 0x92, .fFlags = 0xCF, .fBaseHigh = 0}, // Kernel data + {}, // TSS data low + {}, // TSS data high {.fLimitLow = 0x0, .fBaseLow = 0, .fBaseMid = 0, @@ -90,6 +97,20 @@ EXTERN_C Int32 hal_init_platform(Kernel::HEL::BootInfoHeader* handover_hdr) { .fBaseHigh = 0}, // User data }; + kGDTArray[3].fLimitLow = sizeof(HAL::Detail::NE_TSS) - 1; + kGDTArray[3].fBaseLow = ((UIntPtr) &kKernelTSS) & 0xFFFF; + kGDTArray[3].fBaseMid = (((UIntPtr) &kKernelTSS) >> 16) & 0xFF; + kGDTArray[3].fAccessByte = 0x89; // Present, type 9 = 64-bit available TSS + kGDTArray[3].fFlags = 0x20 | ((((UIntPtr) &kKernelTSS) >> 24) & 0x0F); + kGDTArray[3].fBaseHigh = (((UIntPtr) &kKernelTSS) >> 24) & 0xFF; + + kGDTArray[4].fLimitLow = ((UIntPtr) &kKernelTSS >> 32) & 0xFFFF; + kGDTArray[4].fBaseLow = 0; + kGDTArray[4].fBaseMid = 0; + kGDTArray[4].fAccessByte = 0; + kGDTArray[4].fFlags = 0; + kGDTArray[4].fBaseHigh = 0; + // Load memory descriptors. Kernel::HAL::Register64 gdt_reg; diff --git a/dev/kernel/HALKit/AMD64/Processor.h b/dev/kernel/HALKit/AMD64/Processor.h index c574f8d5..3bf0ad3e 100644 --- a/dev/kernel/HALKit/AMD64/Processor.h +++ b/dev/kernel/HALKit/AMD64/Processor.h @@ -285,6 +285,4 @@ EXTERN_C ATTRIBUTE(naked) Kernel::Void hal_load_gdt(Kernel::HAL::Register64 ptr) inline Kernel::VoidPtr kKernelBitMpStart = nullptr; inline Kernel::UIntPtr kKernelBitMpSize = 0UL; -inline Kernel::VoidPtr kKernelCR3 = nullptr; - #endif // __NE_AMD64__ */ \ No newline at end of file diff --git a/dev/kernel/HALKit/ARM64/HalApplicationProcessor.cc b/dev/kernel/HALKit/ARM64/HalApplicationProcessor.cc index 5be41e4e..70a5e2d9 100644 --- a/dev/kernel/HALKit/ARM64/HalApplicationProcessor.cc +++ b/dev/kernel/HALKit/ARM64/HalApplicationProcessor.cc @@ -113,7 +113,7 @@ EXTERN_C HAL::StackFramePtr mp_get_current_context(ProcessID thrdid) { /// @param thrdid The thread ID. /***********************************************************************************/ -EXTERN_C Bool mp_register_process(HAL::StackFramePtr stack_frame, ProcessID thrdid) { +EXTERN_C Bool mp_register_task(HAL::StackFramePtr stack_frame, ProcessID thrdid) { MUST_PASS(Detail::kGICEnabled); if (!stack_frame) return NO; diff --git a/dev/kernel/HALKit/ARM64/Processor.h b/dev/kernel/HALKit/ARM64/Processor.h index f52b854f..ba1ed11e 100644 --- a/dev/kernel/HALKit/ARM64/Processor.h +++ b/dev/kernel/HALKit/ARM64/Processor.h @@ -72,8 +72,6 @@ inline Void hal_wfi(Void) { inline Kernel::VoidPtr kKernelBitMpStart = nullptr; inline Kernel::UIntPtr kKernelBitMpSize = 0UL; -inline Kernel::VoidPtr kKernelPDE = nullptr; - #include #endif // __NE_ARM64__ \ No newline at end of file diff --git a/dev/kernel/KernelKit/KernelTaskScheduler.h b/dev/kernel/KernelKit/KernelTaskScheduler.h index f4ff4125..57b83ccb 100644 --- a/dev/kernel/KernelKit/KernelTaskScheduler.h +++ b/dev/kernel/KernelKit/KernelTaskScheduler.h @@ -16,7 +16,7 @@ namespace Kernel { class KERNEL_TASK final { -public: + public: Char Name[kSchedNameLen] = {"KERNEL_TASK"}; ProcessSubsystem SubSystem{ProcessSubsystem::kProcessSubsystemDriver}; HAL::StackFramePtr StackFrame{nullptr}; diff --git a/dev/kernel/src/HardwareThreadScheduler.cc b/dev/kernel/src/HardwareThreadScheduler.cc index b801632c..23365af5 100644 --- a/dev/kernel/src/HardwareThreadScheduler.cc +++ b/dev/kernel/src/HardwareThreadScheduler.cc @@ -21,7 +21,7 @@ namespace Kernel { /***********************************************************************************/ EXTERN_C Bool hal_check_stack(HAL::StackFramePtr frame); -EXTERN_C Bool mp_register_process(HAL::StackFramePtr frame, ProcessID pid); +EXTERN_C Bool mp_register_task(HAL::StackFramePtr frame, ProcessID pid); STATIC HardwareThreadScheduler kHardwareThreadScheduler; @@ -94,7 +94,7 @@ Void HardwareThread::Wake(const bool wakeup) noexcept { Bool HardwareThread::Switch(HAL::StackFramePtr frame) { this->fStack = frame; - Bool ret = mp_register_process(fStack, this->fPID); + Bool ret = mp_register_task(fStack, this->fPID); return ret; } diff --git a/dev/kernel/src/UserProcessScheduler.cc b/dev/kernel/src/UserProcessScheduler.cc index 0de38532..a901e6d0 100644 --- a/dev/kernel/src/UserProcessScheduler.cc +++ b/dev/kernel/src/UserProcessScheduler.cc @@ -21,6 +21,7 @@ #include #include #include +#include "NewKit/Macros.h" ///! BUGS: 0 @@ -125,7 +126,7 @@ ErrorOr USER_PROCESS::New(SizeT sz, SizeT pad_amount) { if (this->UsedMemory > kSchedMaxMemoryLimit) return ErrorOr(-kErrorHeapOutOfMemory); #ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ - auto vm_register = kKernelCR3; + auto vm_register = kKernelVM; hal_write_cr3(this->VMRegister); auto ptr = mm_new_ptr(sz, Yes, Yes, pad_amount); @@ -271,7 +272,7 @@ Void USER_PROCESS::Exit(const Int32& exit_code) { auto memory_ptr_list = this->HeapTree; #ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ - auto pd = kKernelCR3; + auto pd = kKernelVM; hal_write_cr3(this->VMRegister); #endif @@ -384,7 +385,7 @@ ProcessID UserProcessScheduler::Spawn(const Char* name, VoidPtr code, VoidPtr im rt_copy_memory(reinterpret_cast(const_cast(name)), process.Name, len); #ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ - process.VMRegister = kKernelCR3; + process.VMRegister = kKernelVM; #else process.VMRegister = 0UL; #endif // ifdef __NE_VIRTUAL_MEMORY_SUPPORT__ @@ -401,6 +402,15 @@ ProcessID UserProcessScheduler::Spawn(const Char* name, VoidPtr code, VoidPtr im 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_phys_address((VoidPtr) process.StackFrame->IP), + HAL::kMMFlagsUser | HAL::kMMFlagsPresent); + HAL::mm_map_page((VoidPtr) process.StackFrame->SP, + (VoidPtr) HAL::mm_get_phys_address((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); @@ -494,6 +504,8 @@ SizeT UserProcessScheduler::Run() noexcept { if (UserProcessHelper::CanBeScheduled(process)) { kout << process.Name << " will be scheduled...\r"; + this->TheCurrentProcess() = process; + if (UserProcessHelper::Switch(process.StackFrame, process.ProcessId)) { process.PTime = static_cast(process.Affinity); @@ -606,6 +618,7 @@ Bool UserProcessHelper::Switch(HAL::StackFramePtr frame_ptr, PID new_pid) { if (HardwareThreadScheduler::The()[index].Leak()->IsBusy()) { (Void)(kout << "AP_" << hex_number(index)); kout << " is busy\r"; + continue; } @@ -627,10 +640,6 @@ Bool UserProcessHelper::Switch(HAL::StackFramePtr frame_ptr, PID new_pid) { HardwareThreadScheduler::The()[index].Leak()->fPTime = UserProcessScheduler::The().TheCurrentTeam().AsArray()[new_pid].PTime; - HardwareThreadScheduler::The()[index].Leak()->Wake(YES); - - UserProcessScheduler::The().TheCurrentProcess() = - UserProcessScheduler::The().TheCurrentTeam().AsArray()[new_pid]; return YES; } -- cgit v1.2.3 From 54a0f4c49d9bfb955174c87dae2f442d7f5a8b25 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Fri, 23 May 2025 11:12:31 +0200 Subject: feat!(Kernel): Improvements on the BitMapMgr, HTS, and UPS. other: - Add ZXD header file. - Reworking AMD64 interrupts. - Improved HTS's design implementation. - Improved UPS's balancing implementation. breaking changes: - Rename MemoryMgr to HeapMgr. Signed-off-by: Amlal El Mahrouss --- dev/boot/src/HEL/AMD64/BootATA+Next.cc | 270 --------------------- dev/boot/src/HEL/AMD64/BootATA.cc | 256 ------------------- dev/boot/src/HEL/AMD64/BootATAcc | 266 ++++++++++++++++++++ dev/boot/src/HEL/AMD64/BootEFI.cc | 20 +- dev/boot/src/docs/KERN_VER.md | 18 +- dev/boot/src/docs/MKFS_HEFS.md | 106 ++++++++ dev/kernel/HALKit/AMD64/HalACPIFactoryInterface.cc | 2 +- dev/kernel/HALKit/AMD64/HalAPStartup.s | 12 - dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc | 2 - .../HALKit/AMD64/HalApplicationProcessorStartup.s | 14 ++ dev/kernel/HALKit/AMD64/HalCommonAPI.asm | 3 - .../HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc | 66 +---- dev/kernel/HALKit/AMD64/HalKernelMain.cc | 1 + dev/kernel/HALKit/AMD64/Storage/PIO+Generic.cc | 26 +- dev/kernel/HALKit/ARM64/HalACPIFactoryInterface.cc | 2 +- .../HALKit/ARM64/HalApplicationProcessorStartup.s | 12 + dev/kernel/HALKit/ARM64/HalKernelMain.cc | 2 +- dev/kernel/KernelKit/FileMgr.h | 11 +- dev/kernel/KernelKit/HardwareThreadScheduler.h | 1 - dev/kernel/KernelKit/HeapMgr.h | 58 +++++ dev/kernel/KernelKit/HeapMgr.inl | 35 +++ dev/kernel/KernelKit/MemoryMgr.h | 78 ------ dev/kernel/KernelKit/Zxd.h | 37 +++ dev/kernel/NeKit/Function.h | 1 - dev/kernel/NeKit/New.h | 2 +- dev/kernel/NeKit/Ref.h | 2 +- dev/kernel/src/ACPIFactoryInterface.cc | 2 +- dev/kernel/src/BitMapMgr.cc | 10 +- dev/kernel/src/FS/Ext2+FileMgr.cc | 2 +- dev/kernel/src/FS/HeFS+FileMgr.cc | 2 +- dev/kernel/src/FS/NeFS+FileMgr.cc | 2 +- dev/kernel/src/HardwareThreadScheduler.cc | 13 +- dev/kernel/src/HeapMgr.cc | 260 ++++++++++++++++++++ dev/kernel/src/KPC.cc | 2 +- dev/kernel/src/MemoryMgr.cc | 260 -------------------- dev/kernel/src/New+Delete.cc | 2 +- dev/kernel/src/PEFCodeMgr.cc | 2 +- dev/kernel/src/User.cc | 2 +- dev/kernel/src/UserProcessScheduler.cc | 22 +- docs/drawio/ZXD_DESIGN.drawio | 62 ++--- tooling/mkfs.hefs.cc | 4 +- 41 files changed, 918 insertions(+), 1032 deletions(-) delete mode 100644 dev/boot/src/HEL/AMD64/BootATA+Next.cc delete mode 100644 dev/boot/src/HEL/AMD64/BootATA.cc create mode 100644 dev/boot/src/HEL/AMD64/BootATAcc create mode 100644 dev/boot/src/docs/MKFS_HEFS.md delete mode 100644 dev/kernel/HALKit/AMD64/HalAPStartup.s create mode 100644 dev/kernel/HALKit/AMD64/HalApplicationProcessorStartup.s create mode 100644 dev/kernel/HALKit/ARM64/HalApplicationProcessorStartup.s create mode 100644 dev/kernel/KernelKit/HeapMgr.h create mode 100644 dev/kernel/KernelKit/HeapMgr.inl delete mode 100644 dev/kernel/KernelKit/MemoryMgr.h create mode 100644 dev/kernel/KernelKit/Zxd.h create mode 100644 dev/kernel/src/HeapMgr.cc delete mode 100644 dev/kernel/src/MemoryMgr.cc (limited to 'dev/kernel/HALKit/AMD64/HalCommonAPI.asm') diff --git a/dev/boot/src/HEL/AMD64/BootATA+Next.cc b/dev/boot/src/HEL/AMD64/BootATA+Next.cc deleted file mode 100644 index 547d4f99..00000000 --- a/dev/boot/src/HEL/AMD64/BootATA+Next.cc +++ /dev/null @@ -1,270 +0,0 @@ -/* ------------------------------------------- - - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. - -------------------------------------------- */ - -/** - * @file BootATA.cc - * @author Amlal El Mahrouss (amlal@nekernel.org) - * @brief ATA driver. - * @version 0.1 - * @date 2024-02-02 - * - * @copyright Copyright (c) Amlal El Mahrouss - * - */ - -#if 0 - -#include -#include -#include - -#define kATADataLen (256) - -/// bugs: 0 - -using namespace Boot; - -static Boolean kATADetected = false; -static UInt16 kATAData[kATADataLen] = {0}; - -Boolean boot_ata_detected(Void); - -STATIC Boolean boot_ata_wait_io(UInt16 IO) { - for (int i = 0; i < 400; i++) rt_in8(IO + ATA_REG_STATUS); - -ATAWaitForIO_Retry: - auto status_rdy = rt_in8(IO + ATA_REG_STATUS); - - if ((status_rdy & ATA_SR_BSY)) goto ATAWaitForIO_Retry; - -ATAWaitForIO_Retry2: - status_rdy = rt_in8(IO + ATA_REG_STATUS); - - if (status_rdy & ATA_SR_ERR) return false; - - if (!(status_rdy & ATA_SR_DRDY)) goto ATAWaitForIO_Retry2; - - return true; -} - -Void boot_ata_select(UInt16 Bus) { - if (Bus == ATA_PRIMARY_IO) - rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_PRIMARY_SEL); - else - rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_SECONDARY_SEL); -} - -Boolean boot_ata_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster) { - NE_UNUSED(Drive); - - if (boot_ata_detected()) return true; - - BootTextWriter writer; - - UInt16 IO = Bus; - - boot_ata_select(IO); - - // Bus init, NEIN bit. - rt_out8(IO + ATA_REG_NEIN, 1); - - // identify until it's good. -ATAInit_Retry: - auto status_rdy = rt_in8(IO + ATA_REG_STATUS); - - if (status_rdy & ATA_SR_ERR) { - writer.Write(L"BootZ: ATA: Not an IDE based drive.\r"); - - return false; - } - - if ((status_rdy & ATA_SR_BSY)) goto ATAInit_Retry; - - boot_ata_select(IO); - - rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); - - /// fetch serial info - /// model, speed, number of sectors... - - while (!(rt_in8(IO + ATA_REG_STATUS) & ATA_SR_DRQ)); - - for (SizeT indexData = 0ul; indexData < kATADataLen; ++indexData) { - kATAData[indexData] = rt_in16(IO + ATA_REG_DATA); - } - - OutBus = (Bus == ATA_PRIMARY_IO) ? BootDeviceATA::kPrimary : BootDeviceATA::kSecondary; - - OutMaster = (Bus == ATA_PRIMARY_IO) ? ATA_MASTER : ATA_SLAVE; - - return true; -} - -Void boot_ata_read(UInt64 Lba, UInt16 IO, UInt8 Master, CharacterTypeASCII* Buf, SizeT SectorSz, - SizeT Size) { - Lba /= SectorSz; - - UInt8 Command = ((!Master) ? 0xE0 : 0xF0); - - boot_ata_wait_io(IO); - boot_ata_select(IO); - - rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); - - rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + SectorSz) / SectorSz)); - - rt_out8(IO + ATA_REG_LBA0, (Lba) & 0xFF); - rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8); - rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); - rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); - - rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_READ_PIO); - - while (!(rt_in8(IO + ATA_REG_STATUS) & ATA_SR_DRQ)); - - for (SizeT IndexOff = 0; IndexOff < Size; IndexOff += 2) { - boot_ata_wait_io(IO); - - auto in = rt_in16(IO + ATA_REG_DATA); - - Buf[IndexOff] = in & 0xFF; - Buf[IndexOff + 1] = (in >> 8) & 0xFF; - boot_ata_wait_io(IO); - } -} - -Void boot_ata_write(UInt64 Lba, UInt16 IO, UInt8 Master, CharacterTypeASCII* Buf, SizeT SectorSz, - SizeT Size) { - Lba /= SectorSz; - - UInt8 Command = ((!Master) ? 0xE0 : 0xF0); - - boot_ata_wait_io(IO); - boot_ata_select(IO); - - rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); - - rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + (SectorSz)) / SectorSz)); - - rt_out8(IO + ATA_REG_LBA0, (Lba) & 0xFF); - rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8); - rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); - rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); - - rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); - - while (!(rt_in8(IO + ATA_REG_STATUS) & ATA_SR_DRQ)); - - for (SizeT IndexOff = 0; IndexOff < Size; IndexOff += 2) { - boot_ata_wait_io(IO); - - UInt8 low = (UInt8) Buf[IndexOff]; - UInt8 high = (IndexOff + 1 < Size) ? (UInt8) Buf[IndexOff + 1] : 0; - UInt16 packed = (high << 8) | low; - - rt_out16(IO + ATA_REG_DATA, packed); - - boot_ata_wait_io(IO); - } - - boot_ata_wait_io(IO); -} - -/// @check is ATA detected? -Boolean boot_ata_detected(Void) { - return kATADetected; -} - -/*** - * - * - * @brief ATA Device class. - * - * - */ - -/** - * @brief ATA Device constructor. - * @param void none. - */ -BootDeviceATA::BootDeviceATA() noexcept { - if (boot_ata_init(ATA_PRIMARY_IO, true, this->Leak().mBus, this->Leak().mMaster) || - boot_ata_init(ATA_SECONDARY_IO, true, this->Leak().mBus, this->Leak().mMaster)) { - kATADetected = true; - } -} -/** - * @brief Is ATA detected? - */ -BootDeviceATA::operator bool() { - return boot_ata_detected(); -} - -/** - @brief Read Buf from disk - @param Sz Sector size - @param Buf buffer -*/ -BootDeviceATA& BootDeviceATA::Read(CharacterTypeASCII* Buf, SizeT SectorSz) { - if (!boot_ata_detected()) { - Leak().mErr = true; - return *this; - } - - this->Leak().mErr = false; - - if (!Buf || SectorSz < 1) return *this; - - boot_ata_read(this->Leak().mBase, this->Leak().mBus, this->Leak().mMaster, Buf, SectorSz, - this->Leak().mSize); - - return *this; -} - -/** - @brief Write Buf into disk - @param Sz Sector size - @param Buf buffer -*/ -BootDeviceATA& BootDeviceATA::Write(CharacterTypeASCII* Buf, SizeT SectorSz) { - if (!boot_ata_detected()) { - Leak().mErr = true; - return *this; - } - - Leak().mErr = false; - - if (!Buf || SectorSz < 1 || this->Leak().mSize < 1) { - Leak().mErr = true; - return *this; - } - - boot_ata_write(this->Leak().mBase, this->Leak().mBus, this->Leak().mMaster, Buf, SectorSz, - this->Leak().mSize); - - return *this; -} - -/** - * @brief ATA trait getter. - * @return BootDeviceATA::ATATrait& the drive config. - */ -BootDeviceATA::ATATrait& BootDeviceATA::Leak() { - return mTrait; -} - -/*** - @brief Getter, gets the number of sectors inside the drive. -*/ -SizeT BootDeviceATA::GetSectorsCount() noexcept { - return (kATAData[61] << 16) | kATAData[60]; -} - -SizeT BootDeviceATA::GetDiskSize() noexcept { - return this->GetSectorsCount() * BootDeviceATA::kSectorSize; -} - -#endif \ No newline at end of file diff --git a/dev/boot/src/HEL/AMD64/BootATA.cc b/dev/boot/src/HEL/AMD64/BootATA.cc deleted file mode 100644 index 903a650d..00000000 --- a/dev/boot/src/HEL/AMD64/BootATA.cc +++ /dev/null @@ -1,256 +0,0 @@ -/* ------------------------------------------- - - Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. - -------------------------------------------- */ - -/** - * @file BootATA.cc - * @author Amlal El Mahrouss (amlal@nekernel.org) - * @brief ATA driver. - * @version 0.1 - * @date 2024-02-02 - * - * @copyright Copyright (c) Amlal El Mahrouss - * - */ - -#include -#include -#include - -#define kATADataLen (256) - -/// bugs: 0 - -using namespace Boot; - -static Boolean kATADetected = false; -static UInt16 kATAData[kATADataLen] = {0}; - -Boolean boot_ata_detected(Void); - -STATIC Boolean boot_ata_wait_io(UInt16 IO) { - for (int i = 0; i < 400; i++) rt_in8(IO + ATA_REG_STATUS); - -ATAWaitForIO_Retry: - auto status_rdy = rt_in8(IO + ATA_REG_STATUS); - - if ((status_rdy & ATA_SR_BSY)) goto ATAWaitForIO_Retry; - -ATAWaitForIO_Retry2: - status_rdy = rt_in8(IO + ATA_REG_STATUS); - - if (status_rdy & ATA_SR_ERR) return false; - - if (!(status_rdy & ATA_SR_DRDY)) goto ATAWaitForIO_Retry2; - - return true; -} - -Void boot_ata_select(UInt16 Bus) { - if (Bus == ATA_PRIMARY_IO) - rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_PRIMARY_SEL); - else - rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_SECONDARY_SEL); -} - -Boolean boot_ata_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster) { - NE_UNUSED(Drive); - - if (boot_ata_detected()) return true; - - BootTextWriter writer; - - UInt16 IO = Bus; - - boot_ata_select(IO); - - // Bus init, NEIN bit. - rt_out8(IO + ATA_REG_NEIN, 1); - - // identify until it's good. -ATAInit_Retry: - auto status_rdy = rt_in8(IO + ATA_REG_STATUS); - - if (status_rdy & ATA_SR_ERR) { - writer.Write(L"BootZ: ATA: Not an IDE based drive.\r"); - - return false; - } - - if ((status_rdy & ATA_SR_BSY)) goto ATAInit_Retry; - - rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); - - /// fetch serial info - /// model, speed, number of sectors... - - boot_ata_wait_io(IO); - - for (SizeT indexData = 0ul; indexData < kATADataLen; ++indexData) { - kATAData[indexData] = Kernel::HAL::rt_in16(IO + ATA_REG_DATA); - } - - OutBus = (Bus == ATA_PRIMARY_IO) ? BootDeviceATA::kPrimary : BootDeviceATA::kSecondary; - - OutMaster = (Bus == ATA_PRIMARY_IO) ? ATA_MASTER : ATA_SLAVE; - - // Why? the current disk driver writes whole word instead of a single byte (expected btw) so i'm - // planning to finish +Next drivers for 0.0.3 - return NO; -} - -Void boot_ata_read(UInt64 Lba, UInt16 IO, UInt8 Master, CharacterTypeASCII* Buf, SizeT SectorSz, - SizeT Size) { - Lba /= SectorSz; - - UInt8 Command = ((!Master) ? 0xE0 : 0xF0); - - boot_ata_wait_io(IO); - boot_ata_select(IO); - - rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); - - rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + SectorSz) / SectorSz)); - - rt_out8(IO + ATA_REG_LBA0, (Lba) &0xFF); - rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8); - rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); - rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); - - rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_READ_PIO); - - boot_ata_wait_io(IO); - - for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff) { - boot_ata_wait_io(IO); - Buf[IndexOff] = Kernel::HAL::rt_in16(IO + ATA_REG_DATA); - boot_ata_wait_io(IO); - } -} - -Void boot_ata_write(UInt64 Lba, UInt16 IO, UInt8 Master, CharacterTypeASCII* Buf, SizeT SectorSz, - SizeT Size) { - Lba /= SectorSz; - - UInt8 Command = ((!Master) ? 0xE0 : 0xF0); - - boot_ata_wait_io(IO); - boot_ata_select(IO); - - rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); - - rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + (SectorSz)) / SectorSz)); - - rt_out8(IO + ATA_REG_LBA0, (Lba) &0xFF); - rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8); - rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); - rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); - - rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); - - boot_ata_wait_io(IO); - - for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff) { - boot_ata_wait_io(IO); - rt_out16(IO + ATA_REG_DATA, Buf[IndexOff]); - boot_ata_wait_io(IO); - } - - boot_ata_wait_io(IO); -} - -/// @check is ATA detected? -Boolean boot_ata_detected(Void) { - return kATADetected; -} - -/*** - * - * - * @brief ATA Device class. - * - * - */ - -/** - * @brief ATA Device constructor. - * @param void none. - */ -BootDeviceATA::BootDeviceATA() noexcept { - if (boot_ata_init(ATA_PRIMARY_IO, true, this->Leak().mBus, this->Leak().mMaster) || - boot_ata_init(ATA_SECONDARY_IO, true, this->Leak().mBus, this->Leak().mMaster)) { - kATADetected = true; - } -} -/** - * @brief Is ATA detected? - */ -BootDeviceATA::operator bool() { - return boot_ata_detected(); -} - -/** - @brief Read Buf from disk - @param Sz Sector size - @param Buf buffer -*/ -BootDeviceATA& BootDeviceATA::Read(CharacterTypeASCII* Buf, SizeT SectorSz) { - if (!boot_ata_detected()) { - Leak().mErr = true; - return *this; - } - - this->Leak().mErr = false; - - if (!Buf || SectorSz < 1) return *this; - - boot_ata_read(this->Leak().mBase, this->Leak().mBus, this->Leak().mMaster, Buf, SectorSz, - this->Leak().mSize); - - return *this; -} - -/** - @brief Write Buf into disk - @param Sz Sector size - @param Buf buffer -*/ -BootDeviceATA& BootDeviceATA::Write(CharacterTypeASCII* Buf, SizeT SectorSz) { - if (!boot_ata_detected()) { - Leak().mErr = true; - return *this; - } - - Leak().mErr = false; - - if (!Buf || SectorSz < 1 || this->Leak().mSize < 1) { - Leak().mErr = true; - return *this; - } - - boot_ata_write(this->Leak().mBase, this->Leak().mBus, this->Leak().mMaster, Buf, SectorSz, - this->Leak().mSize); - - return *this; -} - -/** - * @brief ATA trait getter. - * @return BootDeviceATA::ATATrait& the drive config. - */ -BootDeviceATA::ATATrait& BootDeviceATA::Leak() { - return mTrait; -} - -/*** - @brief Getter, gets the number of sectors inside the drive. -*/ -SizeT BootDeviceATA::GetSectorsCount() noexcept { - return (kATAData[61] << 16) | kATAData[60]; -} - -SizeT BootDeviceATA::GetDiskSize() noexcept { - return this->GetSectorsCount() * BootDeviceATA::kSectorSize; -} diff --git a/dev/boot/src/HEL/AMD64/BootATAcc b/dev/boot/src/HEL/AMD64/BootATAcc new file mode 100644 index 00000000..4fd6dc16 --- /dev/null +++ b/dev/boot/src/HEL/AMD64/BootATAcc @@ -0,0 +1,266 @@ +/* ------------------------------------------- + + Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. + +------------------------------------------- */ + +/** + * @file BootATA.cc + * @author Amlal El Mahrouss (amlal@nekernel.org) + * @brief ATA driver. + * @version 0.1 + * @date 2024-02-02 + * + * @copyright Copyright (c) Amlal El Mahrouss + * + */ + +#include +#include +#include + +#define kATADataLen (256) + +/// bugs: 0 + +using namespace Boot; + +static Boolean kATADetected = false; +static UInt16 kATAData[kATADataLen] = {0}; + +Boolean boot_ata_detected(Void); + +STATIC Boolean boot_ata_wait_io(UInt16 IO) { + for (int i = 0; i < 400; i++) rt_in8(IO + ATA_REG_STATUS); + +ATAWaitForIO_Retry: + auto status_rdy = rt_in8(IO + ATA_REG_STATUS); + + if ((status_rdy & ATA_SR_BSY)) goto ATAWaitForIO_Retry; + +ATAWaitForIO_Retry2: + status_rdy = rt_in8(IO + ATA_REG_STATUS); + + if (status_rdy & ATA_SR_ERR) return false; + + if (!(status_rdy & ATA_SR_DRDY)) goto ATAWaitForIO_Retry2; + + return true; +} + +Void boot_ata_select(UInt16 Bus) { + if (Bus == ATA_PRIMARY_IO) + rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_PRIMARY_SEL); + else + rt_out8(Bus + ATA_REG_HDDEVSEL, ATA_SECONDARY_SEL); +} + +Boolean boot_ata_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster) { + NE_UNUSED(Drive); + + if (boot_ata_detected()) return true; + + BootTextWriter writer; + + UInt16 IO = Bus; + + boot_ata_select(IO); + + // Bus init, NEIN bit. + rt_out8(IO + ATA_REG_NEIN, 1); + + // identify until it's good. +ATAInit_Retry: + auto status_rdy = rt_in8(IO + ATA_REG_STATUS); + + if (status_rdy & ATA_SR_ERR) { + writer.Write(L"BootZ: ATA: Not an IDE based drive.\r"); + + return false; + } + + if ((status_rdy & ATA_SR_BSY)) goto ATAInit_Retry; + + boot_ata_select(IO); + + rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + + /// fetch serial info + /// model, speed, number of sectors... + + while (!(rt_in8(IO + ATA_REG_STATUS) & ATA_SR_DRQ)); + + for (SizeT indexData = 0ul; indexData < kATADataLen; ++indexData) { + kATAData[indexData] = rt_in16(IO + ATA_REG_DATA); + } + + OutBus = (Bus == ATA_PRIMARY_IO) ? BootDeviceATA::kPrimary : BootDeviceATA::kSecondary; + + OutMaster = (Bus == ATA_PRIMARY_IO) ? ATA_MASTER : ATA_SLAVE; + + return true; +} + +Void boot_ata_read(UInt64 Lba, UInt16 IO, UInt8 Master, CharacterTypeASCII* Buf, SizeT SectorSz, + SizeT Size) { + Lba /= SectorSz; + + UInt8 Command = ((!Master) ? 0xE0 : 0xF0); + + boot_ata_wait_io(IO); + boot_ata_select(IO); + + rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); + + rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + SectorSz) / SectorSz)); + + rt_out8(IO + ATA_REG_LBA0, (Lba) & 0xFF); + rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8); + rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); + rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); + + rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_READ_PIO); + + while (!(rt_in8(IO + ATA_REG_STATUS) & ATA_SR_DRQ)); + + for (SizeT IndexOff = 0; IndexOff < Size; IndexOff += 2) { + boot_ata_wait_io(IO); + + auto in = rt_in16(IO + ATA_REG_DATA); + + Buf[IndexOff] = in & 0xFF; + Buf[IndexOff + 1] = (in >> 8) & 0xFF; + boot_ata_wait_io(IO); + } +} + +Void boot_ata_write(UInt64 Lba, UInt16 IO, UInt8 Master, CharacterTypeASCII* Buf, SizeT SectorSz, + SizeT Size) { + Lba /= SectorSz; + + UInt8 Command = ((!Master) ? 0xE0 : 0xF0); + + boot_ata_wait_io(IO); + boot_ata_select(IO); + + rt_out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F)); + + rt_out8(IO + ATA_REG_SEC_COUNT0, ((Size + (SectorSz)) / SectorSz)); + + rt_out8(IO + ATA_REG_LBA0, (Lba) & 0xFF); + rt_out8(IO + ATA_REG_LBA1, (Lba) >> 8); + rt_out8(IO + ATA_REG_LBA2, (Lba) >> 16); + rt_out8(IO + ATA_REG_LBA3, (Lba) >> 24); + + rt_out8(IO + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO); + + while (!(rt_in8(IO + ATA_REG_STATUS) & ATA_SR_DRQ)); + + for (SizeT IndexOff = 0; IndexOff < Size; IndexOff += 2) { + boot_ata_wait_io(IO); + + UInt8 low = (UInt8) Buf[IndexOff]; + UInt8 high = (IndexOff + 1 < Size) ? (UInt8) Buf[IndexOff + 1] : 0; + UInt16 packed = (high << 8) | low; + + rt_out16(IO + ATA_REG_DATA, packed); + + boot_ata_wait_io(IO); + } + + boot_ata_wait_io(IO); +} + +/// @check is ATA detected? +Boolean boot_ata_detected(Void) { + return kATADetected; +} + +/*** + * + * + * @brief ATA Device class. + * + * + */ + +/** + * @brief ATA Device constructor. + * @param void none. + */ +BootDeviceATA::BootDeviceATA() noexcept { + if (boot_ata_init(ATA_PRIMARY_IO, true, this->Leak().mBus, this->Leak().mMaster) || + boot_ata_init(ATA_SECONDARY_IO, true, this->Leak().mBus, this->Leak().mMaster)) { + kATADetected = true; + } +} +/** + * @brief Is ATA detected? + */ +BootDeviceATA::operator bool() { + return boot_ata_detected(); +} + +/** + @brief Read Buf from disk + @param Sz Sector size + @param Buf buffer +*/ +BootDeviceATA& BootDeviceATA::Read(CharacterTypeASCII* Buf, SizeT SectorSz) { + if (!boot_ata_detected()) { + Leak().mErr = true; + return *this; + } + + this->Leak().mErr = false; + + if (!Buf || SectorSz < 1) return *this; + + boot_ata_read(this->Leak().mBase, this->Leak().mBus, this->Leak().mMaster, Buf, SectorSz, + this->Leak().mSize); + + return *this; +} + +/** + @brief Write Buf into disk + @param Sz Sector size + @param Buf buffer +*/ +BootDeviceATA& BootDeviceATA::Write(CharacterTypeASCII* Buf, SizeT SectorSz) { + if (!boot_ata_detected()) { + Leak().mErr = true; + return *this; + } + + Leak().mErr = false; + + if (!Buf || SectorSz < 1 || this->Leak().mSize < 1) { + Leak().mErr = true; + return *this; + } + + boot_ata_write(this->Leak().mBase, this->Leak().mBus, this->Leak().mMaster, Buf, SectorSz, + this->Leak().mSize); + + return *this; +} + +/** + * @brief ATA trait getter. + * @return BootDeviceATA::ATATrait& the drive config. + */ +BootDeviceATA::ATATrait& BootDeviceATA::Leak() { + return mTrait; +} + +/*** + @brief Getter, gets the number of sectors inside the drive. +*/ +SizeT BootDeviceATA::GetSectorsCount() noexcept { + return (kATAData[61] << 16) | kATAData[60]; +} + +SizeT BootDeviceATA::GetDiskSize() noexcept { + return this->GetSectorsCount() * BootDeviceATA::kSectorSize; +} diff --git a/dev/boot/src/HEL/AMD64/BootEFI.cc b/dev/boot/src/HEL/AMD64/BootEFI.cc index 1d46b731..84a4d295 100644 --- a/dev/boot/src/HEL/AMD64/BootEFI.cc +++ b/dev/boot/src/HEL/AMD64/BootEFI.cc @@ -196,16 +196,6 @@ EFI_EXTERN_C EFI_API Int32 BootloaderMain(EfiHandlePtr image_handle, EfiSystemTa WideChar kernel_path[256U] = L"krnl.efi"; UInt32 kernel_path_sz = StrLen("krnl.efi"); - if (ST->RuntimeServices->GetVariable(L"/props/kernel_path", kEfiGlobalNamespaceVarGUID, nullptr, - &kernel_path_sz, kernel_path) != kEfiOk) { - /// access attributes (in order) - /// EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS - UInt32 attr = 0x00000001 | 0x00000002 | 0x00000004; - - ST->RuntimeServices->SetVariable(L"/props/kernel_path", kEfiGlobalNamespaceVarGUID, &attr, - &kernel_path_sz, kernel_path); - } - UInt32 sz_ver = sizeof(UInt64); UInt64 ver = KERNEL_VERSION_BCD; @@ -219,6 +209,16 @@ EFI_EXTERN_C EFI_API Int32 BootloaderMain(EfiHandlePtr image_handle, EfiSystemTa &sz_ver, &ver); writer.Write("BootZ: Version has been updated: ").Write(ver).Write("\r"); + + if (ST->RuntimeServices->GetVariable(L"/props/kernel_path", kEfiGlobalNamespaceVarGUID, nullptr, + &kernel_path_sz, kernel_path) != kEfiOk) { + /// access attributes (in order) + /// EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS + UInt32 attr = 0x00000001 | 0x00000002 | 0x00000004; + + ST->RuntimeServices->SetVariable(L"/props/kernel_path", kEfiGlobalNamespaceVarGUID, &attr, + &kernel_path_sz, kernel_path); + } } else { writer.Write("BootZ: Version: ").Write(ver).Write("\r"); } diff --git a/dev/boot/src/docs/KERN_VER.md b/dev/boot/src/docs/KERN_VER.md index cabdb1d2..0659431b 100644 --- a/dev/boot/src/docs/KERN_VER.md +++ b/dev/boot/src/docs/KERN_VER.md @@ -1,6 +1,18 @@ -# The `/props/kern_ver` NVRAM variable +# `/props/kern_ver` โ€” NVRAM EFI Variable The `/props/kern_ver` variable is used to track NeKernel's current version in a BCD format. -- Use it to track the current's NeKernel version, in order to adapt your drivers to it. -- It is also useful to keep track of it, for other purposes (bug tracking, development of new features) \ No newline at end of file +## ๐Ÿ›  Reason + +- It is also used for: + - Bug tracking and system patching. + - Version and compatibility checking. + +## ๐Ÿงช Usage + +N/A + +## ยฉ License + + Copyright (C) 2025, + Amlal El Mahrouss โ€“ All rights reserved. \ No newline at end of file diff --git a/dev/boot/src/docs/MKFS_HEFS.md b/dev/boot/src/docs/MKFS_HEFS.md new file mode 100644 index 00000000..c9aa0628 --- /dev/null +++ b/dev/boot/src/docs/MKFS_HEFS.md @@ -0,0 +1,106 @@ +# `mkfs.hefs` โ€“ HeFS Filesystem Formatter + +`mkfs.hefs` is a command-line utility used to format a block device or disk image with the **High-throughput Extended File System (HeFS)** used by NeKernel. This tool initializes a HeFS volume by writing a boot node and configuring directory and inode index regions, block ranges, and volume metadata. + +--- + +## ๐Ÿ›  Features + +- Writes a valid `BootNode` to the specified output device or file. +- Sets disk size, sector size, and volume label. +- Supports user-defined ranges for: + - Index Node Directory (IND) + - Inodes (IN) + - Data blocks +- UTF-8 encoded volume label support. +- Fully compatible with NeKernel's VFS subsystem. + +--- + +## ๐Ÿงช Usage + + mkfs.hefs -L