summaryrefslogtreecommitdiffhomepage
path: root/dev/Kernel/HALKit/ARM64
diff options
context:
space:
mode:
authorAmlal <amlal.elmahrouss@icloud.com>2025-01-24 10:38:36 +0100
committerAmlal <amlal.elmahrouss@icloud.com>2025-01-24 10:38:36 +0100
commit7b4bd3577a31d0f0adc7371840642791ae1567f4 (patch)
tree1a8afc973aaa739d0d763315cad2fd376d1cea9c /dev/Kernel/HALKit/ARM64
ADD: Open version, with important changes kept out.
Signed-off-by: Amlal <amlal.elmahrouss@icloud.com>
Diffstat (limited to 'dev/Kernel/HALKit/ARM64')
-rw-r--r--dev/Kernel/HALKit/ARM64/APM/APM+IO.cc37
-rw-r--r--dev/Kernel/HALKit/ARM64/ApplicationProcessor.h19
-rw-r--r--dev/Kernel/HALKit/ARM64/HalACPIFactoryInterface.cc31
-rw-r--r--dev/Kernel/HALKit/ARM64/HalApplicationProcessor.cc136
-rw-r--r--dev/Kernel/HALKit/ARM64/HalDebugOutput.cc83
-rw-r--r--dev/Kernel/HALKit/ARM64/HalKernelMain.cc52
-rw-r--r--dev/Kernel/HALKit/ARM64/HalKernelPanic.cc80
-rw-r--r--dev/Kernel/HALKit/ARM64/HalPageInternal.S5
-rw-r--r--dev/Kernel/HALKit/ARM64/HalPagingMgrARM64.cc86
-rw-r--r--dev/Kernel/HALKit/ARM64/HalSchedulerCoreARM64.cc24
-rw-r--r--dev/Kernel/HALKit/ARM64/HalSchedulerCorePrimitivesARM64.cc35
-rw-r--r--dev/Kernel/HALKit/ARM64/HalTimerARM64.cc14
-rw-r--r--dev/Kernel/HALKit/ARM64/MBCI/MBCI.cc7
-rw-r--r--dev/Kernel/HALKit/ARM64/Paging.h120
-rw-r--r--dev/Kernel/HALKit/ARM64/Processor.h86
-rw-r--r--dev/Kernel/HALKit/ARM64/ReadMe.md3
-rw-r--r--dev/Kernel/HALKit/ARM64/Storage/MFlash+IO.cc84
17 files changed, 902 insertions, 0 deletions
diff --git a/dev/Kernel/HALKit/ARM64/APM/APM+IO.cc b/dev/Kernel/HALKit/ARM64/APM/APM+IO.cc
new file mode 100644
index 00000000..ba29bd61
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/APM/APM+IO.cc
@@ -0,0 +1,37 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#include <Mod/APM/APM.h>
+#include <KernelKit/LPC.h>
+
+using namespace Kernel;
+
+/// @brief Send APM command to it's space.
+/// @param base_dma the IO base port.
+/// @param cmd the command.
+/// @return status code.
+EXTERN_C Int32 apm_send_io_command(UInt16 cmd, APMPowerCmd value)
+{
+ switch (cmd)
+ {
+ case kAPMPowerCommandReboot: {
+ asm volatile(
+ "ldr x0, =0x84000004\n"
+ "svc #0\n");
+
+ return kErrorSuccess;
+ }
+ case kAPMPowerCommandShutdown: {
+ asm volatile(
+ "ldr x0, =0x84000008\n"
+ "svc #0\n");
+
+ return kErrorSuccess;
+ }
+ default:
+ return kErrorInvalidData;
+ }
+}
diff --git a/dev/Kernel/HALKit/ARM64/ApplicationProcessor.h b/dev/Kernel/HALKit/ARM64/ApplicationProcessor.h
new file mode 100644
index 00000000..cccb9d77
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/ApplicationProcessor.h
@@ -0,0 +1,19 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.h>
+#include <HALKit/ARM64/Processor.h>
+
+/************************************************** */
+/* INITIALIZE THE GIC ON CPU. */
+/************************************************** */
+
+namespace Kernel
+{
+ BOOL mp_initialize_gic(Kernel::Void);
+} \ No newline at end of file
diff --git a/dev/Kernel/HALKit/ARM64/HalACPIFactoryInterface.cc b/dev/Kernel/HALKit/ARM64/HalACPIFactoryInterface.cc
new file mode 100644
index 00000000..69459f66
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalACPIFactoryInterface.cc
@@ -0,0 +1,31 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#include <Mod/ACPI/ACPIFactoryInterface.h>
+#include <NewKit/KString.h>
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/Heap.h>
+#include <Mod/APM/APM.h>
+
+namespace Kernel
+{
+ ACPIFactoryInterface::ACPIFactoryInterface(VoidPtr rsp_ptr)
+ : fRsdp(rsp_ptr), fEntries(0)
+ {
+ }
+
+ Void ACPIFactoryInterface::Shutdown()
+ {
+ apm_send_io_command(kAPMPowerCommandShutdown, 0);
+ }
+
+ /// @brief Reboot machine in either ACPI or by triple faulting.
+ /// @return nothing it's a reboot.
+ Void ACPIFactoryInterface::Reboot()
+ {
+ apm_send_io_command(kAPMPowerCommandReboot, 0);
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/ARM64/HalApplicationProcessor.cc b/dev/Kernel/HALKit/ARM64/HalApplicationProcessor.cc
new file mode 100644
index 00000000..6b09a415
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalApplicationProcessor.cc
@@ -0,0 +1,136 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#include <HALKit/ARM64/Processor.h>
+#include <KernelKit/DebugOutput.h>
+#include <HALKit/ARM64/ApplicationProcessor.h>
+#include <KernelKit/UserProcessScheduler.h>
+
+#define GICD_BASE 0x08000000 // Distributor base address
+#define GICC_BASE 0x08010000 // CPU interface base address
+
+#define GICD_CTLR 0x000 // Distributor Control Register
+#define GICD_ISENABLER 0x100 // Interrupt Set-Enable Registers
+#define GICD_ICENABLER 0x180 // Interrupt Clear-Enable Registers
+#define GICD_ISPENDR 0x200 // Interrupt Set-Pending Registers
+#define GICD_ICPENDR 0x280 // Interrupt Clear-Pending Registers
+#define GICD_IPRIORITYR 0x400 // Interrupt Priority Registers
+#define GICD_ITARGETSR 0x800 // Interrupt Processor Targets Registers
+#define GICD_ICFGR 0xC00 // Interrupt Configuration Registers
+
+#define GICC_CTLR 0x000 // CPU Interface Control Register
+#define GICC_PMR 0x004 // Interrupt Priority Mask Register
+#define GICC_IAR 0x00C // Interrupt Acknowledge Register
+#define GICC_EOIR 0x010 // End of Interrupt Register
+
+// ================================================================= //
+
+namespace Kernel
+{
+ struct PROCESS_CONTROL_BLOCK final
+ {
+ HAL::StackFramePtr mFrame;
+ };
+
+ STATIC PROCESS_CONTROL_BLOCK kProcessBlocks[kSchedProcessLimitPerTeam] = {0};
+
+ namespace Detail
+ {
+ STATIC BOOL kGICEnabled = NO;
+
+ STATIC void mp_hang_fn(void)
+ {
+ while (YES)
+ ;
+ }
+
+ Void mp_setup_gic_el0(Void)
+ {
+ // enable distributor.
+ HAL::hal_mmio_write(GICD_BASE + GICD_CTLR, YES);
+
+ UInt32 gicc_ctlr = HAL::hal_mmio_read<UInt32>(GICC_BASE + GICC_CTLR);
+
+ const auto kEnableSignalInt = YES;
+
+ gicc_ctlr |= kEnableSignalInt; // Enable signaling of interrupts
+ gicc_ctlr |= (kEnableSignalInt << 1); // Allow Group 1 interrupts in EL0
+
+ HAL::hal_mmio_write(GICC_BASE + GICC_CTLR, gicc_ctlr);
+
+ // Set priority mask (accept all priorities)
+ HAL::hal_mmio_write(GICC_BASE + GICC_PMR, 0xFF);
+
+ UInt32 icfgr = HAL::hal_mmio_read<UInt32>(GICD_BASE + GICD_ICFGR + (32 / 16) * 4);
+
+ icfgr |= (0x2 << ((32 % 16) * 2)); // Edge-triggered
+ HAL::hal_mmio_write(GICD_BASE + GICD_ICFGR + (32 / 16) * 4, icfgr);
+
+ // Target interrupt 32 to CPU 1
+ HAL::hal_mmio_write(GICD_BASE + GICD_ITARGETSR + (32 / 4) * 4, 0x2 << ((32 % 4) * 8));
+
+ // Set interrupt 32 priority to lowest (0xFF)
+ HAL::hal_mmio_write(GICD_BASE + GICD_IPRIORITYR + (32 / 4) * 4, 0xFF << ((32 % 4) * 8));
+
+ // Enable interrupt 32 for AP.
+ HAL::hal_mmio_write(GICD_BASE + GICD_ISENABLER + (32 / 32) * 4, 0x01 << (32 % 32));
+
+ kcout << "AP's GIC configured in ISR 32." << endl;
+ }
+
+ BOOL mp_handle_gic_interrupt_el0(Void)
+ {
+ // Read the interrupt ID
+ UInt32 interrupt_id = HAL::hal_mmio_read<UInt32>(GICC_BASE + GICC_IAR);
+
+ // Check if it's a valid interrupt (not spurious)
+ if ((interrupt_id & 0x3FF) < 1020)
+ {
+ kcout << "Handling interrupt for AP: " << (interrupt_id & 0x3FF) << endl;
+
+ // TODO: Handle code here.
+
+ // End the interrupt
+
+ HAL::hal_mmio_write(GICC_BASE + GICC_EOIR, interrupt_id);
+
+ return YES;
+ }
+
+ // spurious interrupt
+ return NO;
+ }
+ } // namespace Detail
+
+ EXTERN_C HAL::StackFramePtr mp_get_current_context(ProcessID pid)
+ {
+ return kProcessBlocks[pid % kSchedProcessLimitPerTeam].mFrame;
+ }
+
+ EXTERN_C Bool mp_register_process(HAL::StackFramePtr stack_frame, ProcessID pid)
+ {
+ MUST_PASS(stack_frame);
+
+ const auto process_index = pid % kSchedProcessLimitPerTeam;
+
+ kProcessBlocks[process_index].mFrame = stack_frame;
+
+ return YES;
+ }
+
+ BOOL mp_initialize_gic(Void)
+ {
+ if (!Detail::kGICEnabled)
+ {
+ Detail::kGICEnabled = YES;
+ Detail::mp_setup_gic_el0();
+
+ return YES;
+ }
+
+ return NO;
+ }
+} // namespace Kernel \ No newline at end of file
diff --git a/dev/Kernel/HALKit/ARM64/HalDebugOutput.cc b/dev/Kernel/HALKit/ARM64/HalDebugOutput.cc
new file mode 100644
index 00000000..e2b2db88
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalDebugOutput.cc
@@ -0,0 +1,83 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/DebugOutput.h>
+#include <NewKit/Utils.h>
+#include <NewKit/New.h>
+
+namespace Kernel
+{
+ EXTERN_C void ke_io_write(const Char* bytes)
+ {
+#ifdef __DEBUG__
+ if (*bytes == 0)
+ return;
+
+ SizeT index = 0;
+ SizeT len = 0;
+
+ index = 0;
+ len = rt_string_len(bytes, 255);
+
+ volatile UInt8* uart_ptr = (UInt8*)0x09000000;
+
+ while (index < len)
+ {
+ if (bytes[index] == '\r')
+ *uart_ptr = '\r';
+
+ *uart_ptr = bytes[index] == '\r' ? '\n' : bytes[index];
+ ++index;
+ }
+#endif // __DEBUG__
+ }
+
+ TerminalDevice::~TerminalDevice() = default;
+
+ EXTERN_C void ke_io_read(const Char* bytes)
+ {
+#ifdef __DEBUG__
+ SizeT index = 0;
+
+ volatile UInt8* uart_ptr = (UInt8*)0x09000000;
+
+ ///! TODO: Look on how to wait for the UART to complete.
+ while (Yes)
+ {
+ auto in = *uart_ptr;
+
+ ///! If enter pressed then break.
+ if (in == 0xD)
+ {
+ break;
+ }
+
+ if (in < '0' || in < 'A' || in < 'a')
+ {
+ if (in != '@' || in != '!' || in != '?' || in != '.' || in != '/' ||
+ in != ':')
+ {
+ continue;
+ }
+ }
+
+ ((char*)bytes)[index] = in;
+
+ ++index;
+ }
+
+ ((char*)bytes)[index] = 0;
+#endif // __DEBUG__
+ }
+
+ TerminalDevice TerminalDevice::The() noexcept
+ {
+ TerminalDevice out(Kernel::ke_io_write, Kernel::ke_io_read);
+ return out;
+ }
+
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/ARM64/HalKernelMain.cc b/dev/Kernel/HALKit/ARM64/HalKernelMain.cc
new file mode 100644
index 00000000..7756facd
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalKernelMain.cc
@@ -0,0 +1,52 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <Mod/CoreGfx/FBMgr.h>
+#include <FirmwareKit/Handover.h>
+#include <KernelKit/FileMgr.h>
+#include <KernelKit/Heap.h>
+#include <KernelKit/PEFCodeMgr.h>
+#include <KernelKit/UserProcessScheduler.h>
+#include <NewKit/Json.h>
+#include <KernelKit/CodeMgr.h>
+#include <Mod/ACPI/ACPIFactoryInterface.h>
+#include <NetworkKit/IPC.h>
+#include <HALKit/ARM64/Processor.h>
+#include <CFKit/Property.h>
+
+EXTERN_C void hal_init_platform(
+ Kernel::HEL::BootInfoHeader* handover_hdr)
+{
+
+ /************************************************** */
+ /* INITIALIZE AND VALIDATE HEADER. */
+ /************************************************** */
+
+ kHandoverHeader = handover_hdr;
+
+ if (kHandoverHeader->f_Magic != kHandoverMagic &&
+ kHandoverHeader->f_Version != kHandoverVersion)
+ {
+ return;
+ }
+
+ /************************************** */
+ /* INITIALIZE BIT MAP. */
+ /************************************** */
+
+ kKernelBitMpSize = kHandoverHeader->f_BitMapSize;
+ kKernelBitMpStart = reinterpret_cast<Kernel::VoidPtr>(
+ reinterpret_cast<Kernel::UIntPtr>(kHandoverHeader->f_BitMapStart));
+
+ /// @note do initialize the interrupts after it.
+
+ Kernel::mp_initialize_gic();
+
+ while (YES)
+ {
+ }
+}
diff --git a/dev/Kernel/HALKit/ARM64/HalKernelPanic.cc b/dev/Kernel/HALKit/ARM64/HalKernelPanic.cc
new file mode 100644
index 00000000..8be2db2f
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalKernelPanic.cc
@@ -0,0 +1,80 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#include <NewKit/KernelPanic.h>
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/Timer.h>
+#include <KernelKit/DebugOutput.h>
+#include <NewKit/KString.h>
+#include <FirmwareKit/Handover.h>
+#include <KernelKit/FileMgr.h>
+#include <Mod/CoreGfx/FBMgr.h>
+#include <Mod/CoreGfx/TextMgr.h>
+#include <NewKit/Utils.h>
+
+/* Each error code is attributed with an ID, which will prompt a string onto the
+ * screen. Wait for debugger... */
+
+namespace Kernel
+{
+ /// @brief Dumping factory class.
+ class RecoveryFactory final
+ {
+ public:
+ STATIC Void Recover() noexcept;
+ };
+
+ /***********************************************************************************/
+ /// @brief Stops execution of the kernel.
+ /// @param id kernel stop ID.
+ /***********************************************************************************/
+ Void ke_panic(const Kernel::Int32& id, const Char* message)
+ {
+ fb_init();
+
+ auto panic_text = RGB(0xff, 0xff, 0xff);
+
+ auto y = 10;
+ auto x = 10;
+
+ Char* message_apicid = new Char[128];
+ rt_set_memory(message_apicid, 0, 128);
+
+ rt_copy_memory((VoidPtr) "panic id: ", message_apicid, rt_string_len("panic id: "));
+ rt_to_string(message_apicid + rt_string_len("panic id: "), (UIntPtr)id, 10);
+
+ fb_render_string(message_apicid, y, x, panic_text);
+
+ y += 10;
+
+ fb_render_string((message ? message : "message: panic raised, going nowhere after this!"), y, x, panic_text);
+
+ y += 10;
+
+ fb_clear();
+
+ RecoveryFactory::Recover();
+ }
+
+ Void RecoveryFactory::Recover() noexcept
+ {
+ while (YES)
+ {
+ HAL::rt_halt();
+ }
+ }
+
+ void ke_runtime_check(bool expr, const Char* file, const Char* line)
+ {
+ if (!expr)
+ {
+ kcout << "FAILED: FILE: " << file << endl;
+ kcout << "FAILED: LINE: " << line << endl;
+
+ ke_panic(RUNTIME_CHECK_FAILED, file); // Runtime Check failed
+ }
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/ARM64/HalPageInternal.S b/dev/Kernel/HALKit/ARM64/HalPageInternal.S
new file mode 100644
index 00000000..8fcf40ff
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalPageInternal.S
@@ -0,0 +1,5 @@
+.text
+
+hal_flush_tlb:
+ tlbi
+ ret
diff --git a/dev/Kernel/HALKit/ARM64/HalPagingMgrARM64.cc b/dev/Kernel/HALKit/ARM64/HalPagingMgrARM64.cc
new file mode 100644
index 00000000..0991fd37
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalPagingMgrARM64.cc
@@ -0,0 +1,86 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.
+
+ File: HalPagingMgr.cc
+ Purpose: Platform Paging Manager..
+
+------------------------------------------- */
+
+#include <HALKit/ARM64/Paging.h>
+#include <HALKit/ARM64/Processor.h>
+
+namespace Kernel::HAL
+{
+ typedef UInt32 PageTableIndex;
+
+ /// \brief Page store type.
+ struct ZKA_PAGE_STORE final
+ {
+ struct
+ {
+ PDE* fPde{nullptr};
+ PTE* fPte{nullptr};
+ VoidPtr fVAddr{nullptr};
+ } fInternalStore;
+
+ Bool fStoreOp{No}; // Store operation in progress.
+
+ static ZKA_PAGE_STORE& The()
+ {
+ static ZKA_PAGE_STORE the;
+ return the;
+ }
+ };
+
+ /// \brief Retrieve the page status of a PTE.
+ STATIC Void mmi_page_status(PTE* pte)
+ {
+ }
+
+ STATIC Int32 mmi_map_page_table_entry(VoidPtr virtual_address, UInt32 flags, PTE* pt_entry);
+
+ /// @brief Maps or allocates a page from virtual_address.
+ /// @param virtual_address a valid virtual address.
+ /// @param phys_addr point to physical address.
+ /// @param flags the flags to put on the page.
+ /// @return Status code of page manipulation process.
+ EXTERN_C Int32 mm_map_page(VoidPtr virtual_address, UInt32 flags)
+ {
+ if (!virtual_address ||
+ !flags)
+ return 0;
+
+ ZKA_PAGE_STORE& page_store = ZKA_PAGE_STORE::The();
+
+ while (page_store.fStoreOp)
+ ;
+
+ page_store.fStoreOp = Yes;
+
+ if (page_store.fInternalStore.fVAddr == virtual_address)
+ {
+ page_store.fStoreOp = No;
+ return mmi_map_page_table_entry(page_store.fInternalStore.fVAddr, flags, page_store.fInternalStore.fPte);
+ }
+
+ return 1;
+ }
+
+ /// @brief Maps flags for a specific pte.
+ /// @internal Internal function.
+ STATIC Int32 mmi_map_page_table_entry(VoidPtr virtual_address, UInt32 flags, PTE* pt_entry)
+ {
+ ZKA_PAGE_STORE& page_store = ZKA_PAGE_STORE::The();
+
+ // Update Internal store.
+
+ page_store.fInternalStore.fPde = nullptr;
+ page_store.fInternalStore.fPte = pt_entry;
+ page_store.fInternalStore.fVAddr = virtual_address;
+
+ page_store.fStoreOp = No;
+
+ return 0;
+ }
+} // namespace Kernel::HAL
diff --git a/dev/Kernel/HALKit/ARM64/HalSchedulerCoreARM64.cc b/dev/Kernel/HALKit/ARM64/HalSchedulerCoreARM64.cc
new file mode 100644
index 00000000..ff1dd448
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalSchedulerCoreARM64.cc
@@ -0,0 +1,24 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#include <KernelKit/UserProcessScheduler.h>
+
+namespace Kernel
+{
+ /// @brief Wakes up thread.
+ /// Wakes up thread from the hang state.
+ Void mp_wakeup_thread(HAL::StackFrame* stack)
+ {
+ ZKA_UNUSED(stack);
+ }
+
+ /// @brief makes the thread sleep on a loop.
+ /// hooks and hangs thread to prevent code from executing.
+ Void mp_hang_thread(HAL::StackFrame* stack)
+ {
+ ZKA_UNUSED(stack);
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/ARM64/HalSchedulerCorePrimitivesARM64.cc b/dev/Kernel/HALKit/ARM64/HalSchedulerCorePrimitivesARM64.cc
new file mode 100644
index 00000000..b254e670
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalSchedulerCorePrimitivesARM64.cc
@@ -0,0 +1,35 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#include <HALKit/ARM64/Processor.h>
+#include <KernelKit/UserProcessScheduler.h>
+
+namespace Kernel
+{
+ /***********************************************************************************/
+ /// @brief Unimplemented function (crashes by default)
+ /// @param void
+ /***********************************************************************************/
+
+ EXTERN_C Void __zka_pure_call(UserProcess* process)
+ {
+ if (process)
+ process->Crash();
+ }
+
+ /***********************************************************************************/
+ /// @brief Validate user stack.
+ /// @param stack_ptr the frame pointer.
+ /***********************************************************************************/
+
+ EXTERN_C Bool hal_check_stack(HAL::StackFramePtr stack_ptr)
+ {
+ if (!stack_ptr)
+ return No;
+
+ return stack_ptr->SP != 0 && stack_ptr->BP != 0;
+ }
+} // namespace Kernel
diff --git a/dev/Kernel/HALKit/ARM64/HalTimerARM64.cc b/dev/Kernel/HALKit/ARM64/HalTimerARM64.cc
new file mode 100644
index 00000000..f860c5a2
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/HalTimerARM64.cc
@@ -0,0 +1,14 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.
+
+ File: HalTimer.cc
+ Purpose: HAL timer
+
+ Revision History:
+
+ 07/07/24: Added file (amlel)
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
diff --git a/dev/Kernel/HALKit/ARM64/MBCI/MBCI.cc b/dev/Kernel/HALKit/ARM64/MBCI/MBCI.cc
new file mode 100644
index 00000000..d9c39f4a
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/MBCI/MBCI.cc
@@ -0,0 +1,7 @@
+/* -------------------------------------------
+
+ Copyright (C) 2025, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#include <Mod/MBCI/MBCI.h> \ No newline at end of file
diff --git a/dev/Kernel/HALKit/ARM64/Paging.h b/dev/Kernel/HALKit/ARM64/Paging.h
new file mode 100644
index 00000000..f20c9fcf
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/Paging.h
@@ -0,0 +1,120 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
+
+/** ---------------------------------------------------
+
+ * THIS FILE CONTAINS CODE FOR ARMV8 PAGING.
+
+------------------------------------------------------- */
+
+#include <NewKit/Defines.h>
+
+#ifndef kPageMax
+#define kPageMax (0x200)
+#endif //! kPageMax
+
+#ifndef kPageAlign
+#define kPageAlign (0x1000)
+#endif //! kPageAlign
+
+#ifndef kPageSize
+#define kPageSize (0x1000)
+#endif // !kPageSize
+
+//! short format address range
+
+#define c16KBPage 0b000
+#define c8KBPage 0b001
+#define c4KBPage 0b010
+#define c2KBPage 0b011
+#define c1KBPage 0b100
+#define c512BPage 0b101
+#define c256BPage 0b110
+#define c128BPage 0b111
+
+/// Long format address range
+
+#define cPageMAll \
+ { \
+ 0b000, 0b000 \
+ }
+#define cPageMToMax(M) \
+ { \
+ M, 0b000 \
+ }
+#define cPageMaxToM(M) \
+ { \
+ 0b000, M \
+ }
+#define cPageMToN(M, N) \
+ { \
+ M, N \
+ }
+
+namespace Kernel::HAL
+{
+ struct PACKED PTE_4KB final
+ {
+ UInt64 Valid : 1;
+ UInt64 Table : 1;
+ UInt64 AttrIndex : 3;
+ UInt64 NS : 1;
+ UInt64 AP : 2;
+ UInt64 SH : 2;
+ UInt64 AF : 1;
+ UInt64 NG : 1;
+ UInt64 Reserved1 : 1;
+ UInt64 Contiguous : 1;
+ UInt64 Dirty : 1;
+ UInt64 Reserved : 2;
+ UInt64 PhysicalAddress : 36;
+ UInt64 Reserved3 : 4;
+ UInt64 PXN : 1;
+ UInt64 XN : 1;
+ UInt64 Reserved4 : 9;
+ };
+
+ namespace Detail
+ {
+ enum class ControlRegisterBits
+ {
+ ProtectedModeEnable = 0,
+ MonitorCoProcessor = 1,
+ Emulation = 2,
+ TaskSwitched = 3,
+ ExtensionType = 4,
+ NumericError = 5,
+ WriteProtect = 16,
+ AlignementMask = 18,
+ NotWriteThrough = 29,
+ CacheDisable = 30,
+ PageEnable = 31,
+ };
+
+ inline UInt8 control_register_cast(ControlRegisterBits reg)
+ {
+ return static_cast<UInt8>(reg);
+ }
+ } // namespace Detail
+
+ struct PDE_4KB final
+ {
+ PTE_4KB ALIGN(kPageAlign) fEntries[kPageMax];
+ };
+
+ auto mm_alloc_bitmap(Boolean wr, Boolean user, SizeT size, Bool is_page) -> VoidPtr;
+ auto mm_free_bitmap(VoidPtr page_ptr) -> Bool;
+} // namespace Kernel::HAL
+
+namespace Kernel
+{
+ typedef HAL::PTE_4KB PTE;
+ typedef HAL::PDE_4KB PDE;
+} // namespace Kernel
+
+EXTERN_C void hal_flush_tlb();
diff --git a/dev/Kernel/HALKit/ARM64/Processor.h b/dev/Kernel/HALKit/ARM64/Processor.h
new file mode 100644
index 00000000..2e640a7f
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/Processor.h
@@ -0,0 +1,86 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Array.h>
+#include <NewKit/Defines.h>
+#include <NewKit/Utils.h>
+#include <FirmwareKit/Handover.h>
+
+#define kCPUBackendName "ARMv8"
+
+namespace Kernel::HAL
+{
+ struct PACKED Register64 final
+ {
+ UShort Limit;
+ UIntPtr Base;
+ };
+
+ /// @brief Memory Manager mapping flags.
+ enum
+ {
+ kMMFlagsPresent = 1 << 0,
+ kMMFlagsWr = 1 << 1,
+ kMMFlagsUser = 1 << 2,
+ kMMFlagsNX = 1 << 3,
+ kMMFlagsCount = 3,
+ };
+
+ /// @brief Set a PTE from pd_base.
+ /// @param virt_addr a valid virtual address.
+ /// @param phys_addr point to physical address.
+ /// @param flags the flags to put on the page.
+ /// @return Status code of page manip.
+ EXTERN_C Int32 mm_map_page(VoidPtr virt_addr, UInt32 flags);
+
+ typedef UIntPtr Reg;
+ typedef Register64 Register;
+
+ /// @note let's keep the same name as AMD64 HAL.
+ struct PACKED StackFrame final
+ {
+ Reg R8{0};
+ Reg R9{0};
+ Reg R10{0};
+ Reg R11{0};
+ Reg R12{0};
+ Reg R13{0};
+ Reg R14{0};
+ Reg R15{0};
+ Reg SP{0};
+ Reg BP{0};
+ };
+
+ typedef StackFrame* StackFramePtr;
+
+ inline Void rt_halt() noexcept
+ {
+ while (Yes)
+ {
+ }
+ }
+
+ template <typename DataKind>
+ inline void hal_mmio_write(UIntPtr address, DataKind value)
+ {
+ *reinterpret_cast<volatile DataKind*>(address) = value;
+ }
+
+ template <typename DataKind>
+ inline DataKind hal_mmio_read(UIntPtr address)
+ {
+ return *reinterpret_cast<volatile DataKind*>(address);
+ }
+} // namespace Kernel::HAL
+
+inline Kernel::VoidPtr kKernelBitMpStart = nullptr;
+inline Kernel::UIntPtr kKernelBitMpSize = 0UL;
+
+inline Kernel::VoidPtr kKernelPhysicalStart = nullptr;
+
+#include <HALKit/ARM64/Paging.h>
diff --git a/dev/Kernel/HALKit/ARM64/ReadMe.md b/dev/Kernel/HALKit/ARM64/ReadMe.md
new file mode 100644
index 00000000..c51229f2
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/ReadMe.md
@@ -0,0 +1,3 @@
+# ARM64 Hardware Abstraction Layer
+
+- Supported Firmware: CoreBoot/EDK/OpenMobileBoot
diff --git a/dev/Kernel/HALKit/ARM64/Storage/MFlash+IO.cc b/dev/Kernel/HALKit/ARM64/Storage/MFlash+IO.cc
new file mode 100644
index 00000000..bcde2435
--- /dev/null
+++ b/dev/Kernel/HALKit/ARM64/Storage/MFlash+IO.cc
@@ -0,0 +1,84 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024-2025, Amlal EL Mahrouss, all rights reserved.
+
+------------------------------------------- */
+
+#ifdef ZKA_USE_MBCI_FLASH
+
+#include <NewKit/Defines.h>
+#include <ArchKit/ArchKit.h>
+#include <Mod/MFlash/MFlash.h>
+#include <Mod/MBCI/MBCI.h>
+
+/// @file MFlash.cc
+/// @brief MBCI Flash support.
+
+#define kMaxFlashSlots (8U)
+
+namespace Kernel
+{
+ /// /Mount/Flash/n
+ constexpr auto kFlashBridgeMagic = "FLSH";
+ constexpr auto kFlashBridgeRevision = 1;
+
+ STATIC BOOL kFlashEnabled = NO;
+ STATIC SizeT kFlashSize[kMaxFlashSlots] = {};
+ STATIC SizeT kFlashSectorSz[kMaxFlashSlots] = {};
+ STATIC IMBCIHost* kFlashMetaPackets[kMaxFlashSlots] = {};
+ STATIC IMBCIHost* kFlashDataPackets[kMaxFlashSlots] = {};
+
+ /// @brief Enable flash memory builtin.
+ STATIC Void drv_enable_flash(Int32 slot);
+
+ /// @brief Disable flash memory builtin.
+ STATIC Void drv_disable_flash(Int32 slot);
+
+ /// @brief get slot sector count.
+ /// @return slot sector count.
+ SizeT drv_get_sector_count(Int32 slot)
+ {
+ if (slot > kMaxFlashSlots)
+ return 0;
+
+ return kFlashSectorSz[slot];
+ }
+
+ /// @brief get slot full size (in bytes).
+ /// @return drive slot size
+ SizeT drv_get_size(Int32 slot)
+ {
+ if (slot > kMaxFlashSlots)
+ return 0;
+
+ return kFlashSize[slot];
+ }
+
+ /// @brief Enable flash memory at slot.
+ BOOL drv_enable_at(Int32 slot)
+ {
+ if (slot > kMaxFlashSlots)
+ return NO;
+
+ kFlashMetaPackets[slot]->InterruptEnable = YES;
+
+ kcout << "Enabled hardware slot at: " << number(slot) << endl;
+
+ return YES;
+ }
+
+ /// @brief Disable flash memory at slot.
+ BOOL drv_disable_at(Int32 slot)
+ {
+ if (slot > kMaxFlashSlots)
+ return NO;
+
+ kFlashMetaPackets[slot]->InterruptEnable = NO;
+
+ kcout << "Disabled hardware slot at: " << number(slot) << endl;
+
+ return YES;
+ }
+} // namespace Kernel
+
+#endif // if ZKA_USE_MBCI_FLASH