summaryrefslogtreecommitdiffhomepage
path: root/dev/ZKAKit/HALKit
diff options
context:
space:
mode:
authorAmlal <amlal.elmahrouss@icloud.com>2024-10-28 07:01:58 +0100
committerAmlal <amlal.elmahrouss@icloud.com>2024-10-28 07:01:58 +0100
commite0024d9ea688ee91a77abc0e28c5ea24b13ca67d (patch)
treea4e29bd919cbeccf2689e81a5d52bfc02f2a8b77 /dev/ZKAKit/HALKit
parent36a3600ff7fc65a63b7386b7a680dbe8e647bd8f (diff)
IMP: Refactor whole source code to make it even.
- That is because previously the source was both in lowercase and lettercase. Signed-off-by: Amlal <amlal.elmahrouss@icloud.com>
Diffstat (limited to 'dev/ZKAKit/HALKit')
-rw-r--r--dev/ZKAKit/HALKit/.gitkeep0
-rw-r--r--dev/ZKAKit/HALKit/64x0/.hgkeep0
-rw-r--r--dev/ZKAKit/HALKit/64x0/APM/.hgkeep0
-rw-r--r--dev/ZKAKit/HALKit/64x0/HalVirtualMemory.cc17
-rw-r--r--dev/ZKAKit/HALKit/64x0/MBCI/.gitkeep0
-rw-r--r--dev/ZKAKit/HALKit/64x0/ReadMe.md4
-rw-r--r--dev/ZKAKit/HALKit/AMD64/CPUID.h83
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalACPIFactoryInterface.cc126
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalAPICController.cc39
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalBoot.asm28
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalCPUAMD64.cc101
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalCommonAPI.asm0
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalContextSwitchAMD64.asm42
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalControlRegister.s45
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc113
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalCoreMPScheduler.cc229
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalDebugOutput.cc144
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalDebugPort.cc40
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalDescriptorLoader.cc120
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalInterruptAPI.asm381
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalKernelMain.cc115
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalPagingMgrAMD64.cc159
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalRoutineWait.s9
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalSchedulerCoreAMD64.cc46
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalTimerAMD64.cc86
-rw-r--r--dev/ZKAKit/HALKit/AMD64/HalUtils.asm27
-rw-r--r--dev/ZKAKit/HALKit/AMD64/Hypervisor.h25
-rw-r--r--dev/ZKAKit/HALKit/AMD64/MBCI/.gitkeep0
-rw-r--r--dev/ZKAKit/HALKit/AMD64/PCI/DMA.cc82
-rw-r--r--dev/ZKAKit/HALKit/AMD64/PCI/Database.cc11
-rw-r--r--dev/ZKAKit/HALKit/AMD64/PCI/Device.cc139
-rw-r--r--dev/ZKAKit/HALKit/AMD64/PCI/Express.cc11
-rw-r--r--dev/ZKAKit/HALKit/AMD64/PCI/IO.cc7
-rw-r--r--dev/ZKAKit/HALKit/AMD64/PCI/Iterator.cc41
-rw-r--r--dev/ZKAKit/HALKit/AMD64/PCI/PCI.cc7
-rw-r--r--dev/ZKAKit/HALKit/AMD64/Paging.h99
-rw-r--r--dev/ZKAKit/HALKit/AMD64/Processor.h313
-rw-r--r--dev/ZKAKit/HALKit/AMD64/ReadMe.md4
-rw-r--r--dev/ZKAKit/HALKit/AMD64/Storage/AHCI.cc291
-rw-r--r--dev/ZKAKit/HALKit/AMD64/Storage/ATA-DMA.cc38
-rw-r--r--dev/ZKAKit/HALKit/AMD64/Storage/ATA-PIO.cc197
-rw-r--r--dev/ZKAKit/HALKit/ARM64/.gitkeep0
-rw-r--r--dev/ZKAKit/HALKit/ARM64/APM/.gitkeep0
-rw-r--r--dev/ZKAKit/HALKit/ARM64/APM/APM.cc37
-rw-r--r--dev/ZKAKit/HALKit/ARM64/HalACPIFactoryInterface.cc31
-rw-r--r--dev/ZKAKit/HALKit/ARM64/HalCoreMPScheduler.cc19
-rw-r--r--dev/ZKAKit/HALKit/ARM64/HalDebugOutput.cc81
-rw-r--r--dev/ZKAKit/HALKit/ARM64/HalKernelMain.cc46
-rw-r--r--dev/ZKAKit/HALKit/ARM64/HalPageInternal.S5
-rw-r--r--dev/ZKAKit/HALKit/ARM64/HalPagingMgr.cc86
-rw-r--r--dev/ZKAKit/HALKit/ARM64/HalSchedulerCoreARM64.cc40
-rw-r--r--dev/ZKAKit/HALKit/ARM64/HalTimer.cc14
-rw-r--r--dev/ZKAKit/HALKit/ARM64/MBCI/.keepme0
-rw-r--r--dev/ZKAKit/HALKit/ARM64/Paging.h120
-rw-r--r--dev/ZKAKit/HALKit/ARM64/Processor.h75
-rw-r--r--dev/ZKAKit/HALKit/ARM64/ReadMe.md3
-rw-r--r--dev/ZKAKit/HALKit/ARM64/Storage/.gitkeep0
-rw-r--r--dev/ZKAKit/HALKit/ARM64/Storage/HalFlash.cc66
-rw-r--r--dev/ZKAKit/HALKit/AXP/CR.s11
-rw-r--r--dev/ZKAKit/HALKit/AXP/CoreInterruptHandlerDEC.cpp0
-rw-r--r--dev/ZKAKit/HALKit/AXP/CoreSyscallHandlerDEC.cpp24
-rw-r--r--dev/ZKAKit/HALKit/AXP/HAL.s13
-rw-r--r--dev/ZKAKit/HALKit/AXP/Processor.h7
-rw-r--r--dev/ZKAKit/HALKit/AXP/README1
-rw-r--r--dev/ZKAKit/HALKit/AXP/README.TXT1
-rw-r--r--dev/ZKAKit/HALKit/AXP/SYSCALL.s10
-rw-r--r--dev/ZKAKit/HALKit/AXP/VM.s5
-rw-r--r--dev/ZKAKit/HALKit/POWER/.gitkeep0
-rw-r--r--dev/ZKAKit/HALKit/POWER/APM/.gitkeep0
-rw-r--r--dev/ZKAKit/HALKit/POWER/HalContextSwitchPowerPC.s30
-rw-r--r--dev/ZKAKit/HALKit/POWER/HalHart.cc25
-rw-r--r--dev/ZKAKit/HALKit/POWER/HalSerialPort.cc27
-rw-r--r--dev/ZKAKit/HALKit/POWER/HalStartSequence.s14
-rw-r--r--dev/ZKAKit/HALKit/POWER/HalThread.cc8
-rw-r--r--dev/ZKAKit/HALKit/POWER/HalVirtualMemory.cc49
-rw-r--r--dev/ZKAKit/HALKit/POWER/Hart.h36
-rw-r--r--dev/ZKAKit/HALKit/POWER/MBCI/.gitkeep0
-rw-r--r--dev/ZKAKit/HALKit/POWER/MBCI/HalMBCIHost.cc8
-rw-r--r--dev/ZKAKit/HALKit/POWER/Processor.h62
-rw-r--r--dev/ZKAKit/HALKit/POWER/ReadMe.md4
-rw-r--r--dev/ZKAKit/HALKit/RISCV/.keep0
-rw-r--r--dev/ZKAKit/HALKit/RISCV/APM/.gitkeep0
-rw-r--r--dev/ZKAKit/HALKit/RISCV/Hart.h24
-rw-r--r--dev/ZKAKit/HALKit/RISCV/ReadMe.md4
-rw-r--r--dev/ZKAKit/HALKit/RISCV/Storage/.gitkeep0
-rw-r--r--dev/ZKAKit/HALKit/X86S/.gitkeep0
-rw-r--r--dev/ZKAKit/HALKit/X86S/ACPI/.gitkeep0
-rw-r--r--dev/ZKAKit/HALKit/X86S/Storage/.gitkeep0
88 files changed, 4205 insertions, 0 deletions
diff --git a/dev/ZKAKit/HALKit/.gitkeep b/dev/ZKAKit/HALKit/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/.gitkeep
diff --git a/dev/ZKAKit/HALKit/64x0/.hgkeep b/dev/ZKAKit/HALKit/64x0/.hgkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/64x0/.hgkeep
diff --git a/dev/ZKAKit/HALKit/64x0/APM/.hgkeep b/dev/ZKAKit/HALKit/64x0/APM/.hgkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/64x0/APM/.hgkeep
diff --git a/dev/ZKAKit/HALKit/64x0/HalVirtualMemory.cc b/dev/ZKAKit/HALKit/64x0/HalVirtualMemory.cc
new file mode 100644
index 00000000..ae7faa0b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/64x0/HalVirtualMemory.cc
@@ -0,0 +1,17 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <HALKit/POWER/Processor.h>
+#include <KernelKit/DebugOutput.h>
+
+using namespace Kernel;
+
+/// @brief Flush system TLB, looks like the POWER version, as it acts the same, no specific instruction for that.
+/// @note The 88K MMU should be present as well.
+EXTERN_C void hal_flush_tlb()
+{
+ asm volatile("invltlb");
+}
diff --git a/dev/ZKAKit/HALKit/64x0/MBCI/.gitkeep b/dev/ZKAKit/HALKit/64x0/MBCI/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/64x0/MBCI/.gitkeep
diff --git a/dev/ZKAKit/HALKit/64x0/ReadMe.md b/dev/ZKAKit/HALKit/64x0/ReadMe.md
new file mode 100644
index 00000000..c13494e8
--- /dev/null
+++ b/dev/ZKAKit/HALKit/64x0/ReadMe.md
@@ -0,0 +1,4 @@
+64x0 Hardware Abstraction Layer
+
+- Supported CPU: ZKA Web Services Co 64x0
+- Supported Firmware: CoreBoot
diff --git a/dev/ZKAKit/HALKit/AMD64/CPUID.h b/dev/ZKAKit/HALKit/AMD64/CPUID.h
new file mode 100644
index 00000000..6eda5736
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/CPUID.h
@@ -0,0 +1,83 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+ File: CPUID.h
+ Purpose: CPUID flags.
+
+ Revision History:
+
+ 30/01/24: Added file (amlel)
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.h>
+
+enum
+{
+ eCPUFeatureSSE3 = 1 << 0,
+ eCPUFeaturePCLMUL = 1 << 1,
+ eCPUFeatureDTES64 = 1 << 2,
+ eCPUFeatureMONITOR = 1 << 3,
+ eCPUFeatureDS_CPL = 1 << 4,
+ eCPUFeatureVMX = 1 << 5,
+ eCPUFeatureSMX = 1 << 6,
+ eCPUFeatureEST = 1 << 7,
+ eCPUFeatureTM2 = 1 << 8,
+ eCPUFeatureSSSE3 = 1 << 9,
+ eCPUFeatureCID = 1 << 10,
+ eCPUFeatureSDBG = 1 << 11,
+ eCPUFeatureFMA = 1 << 12,
+ eCPUFeatureCX16 = 1 << 13,
+ eCPUFeatureXTPR = 1 << 14,
+ eCPUFeaturePDCM = 1 << 15,
+ eCPUFeaturePCID = 1 << 17,
+ eCPUFeatureDCA = 1 << 18,
+ eCPUFeatureSSE4_1 = 1 << 19,
+ eCPUFeatureSSE4_2 = 1 << 20,
+ eCPUFeatureX2APIC = 1 << 21,
+ eCPUFeatureMOVBE = 1 << 22,
+ eCPUFeaturePOP3C = 1 << 23,
+ eCPUFeatureECXTSC = 1 << 24,
+ eCPUFeatureAES = 1 << 25,
+ eCPUFeatureXSAVE = 1 << 26,
+ eCPUFeatureOSXSAVE = 1 << 27,
+ eCPUFeatureAVX = 1 << 28,
+ eCPUFeatureF16C = 1 << 29,
+ eCPUFeatureRDRAND = 1 << 30,
+ eCPUFeatureHYPERVISOR = 1 << 31,
+ eCPUFeatureFPU = 1 << 0,
+ eCPUFeatureVME = 1 << 1,
+ eCPUFeatureDE = 1 << 2,
+ eCPUFeaturePSE = 1 << 3,
+ eCPUFeatureEDXTSC = 1 << 4,
+ eCPUFeatureMSR = 1 << 5,
+ eCPUFeaturePAE = 1 << 6,
+ eCPUFeatureMCE = 1 << 7,
+ eCPUFeatureCX8 = 1 << 8,
+ eCPUFeatureAPIC = 1 << 9,
+ eCPUFeatureSEP = 1 << 11,
+ eCPUFeatureMTRR = 1 << 12,
+ eCPUFeaturePGE = 1 << 13,
+ eCPUFeatureMCA = 1 << 14,
+ eCPUFeatureCMOV = 1 << 15,
+ eCPUFeaturePAT = 1 << 16,
+ eCPUFeaturePSE36 = 1 << 17,
+ eCPUFeaturePSN = 1 << 18,
+ eCPUFeatureCLFLUSH = 1 << 19,
+ eCPUFeatureDS = 1 << 21,
+ eCPUFeatureACPI = 1 << 22,
+ eCPUFeatureMMX = 1 << 23,
+ eCPUFeatureFXSR = 1 << 24,
+ eCPUFeatureSSE = 1 << 25,
+ eCPUFeatureSSE2 = 1 << 26,
+ eCPUFeatureSS = 1 << 27,
+ eCPUFeatureHTT = 1 << 28,
+ eCPUFeatureTM = 1 << 29,
+ eCPUFeatureIA64 = 1 << 30,
+ eCPUFeaturePBE = 1 << 31
+};
+
+typedef Kernel::Int64 hal_cpu_feature_type;
diff --git a/dev/ZKAKit/HALKit/AMD64/HalACPIFactoryInterface.cc b/dev/ZKAKit/HALKit/AMD64/HalACPIFactoryInterface.cc
new file mode 100644
index 00000000..8f2ae1e7
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalACPIFactoryInterface.cc
@@ -0,0 +1,126 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <HALKit/AMD64/Processor.h>
+#include <NewKit/String.h>
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/Heap.h>
+
+namespace Kernel
+{
+ namespace Detail
+ {
+ struct FADT final : public SDT
+ {
+ UInt32 FirmwareCtrl;
+ UInt32 Dsdt;
+
+ // field used in ACPI 1.0; no longer in use, for compatibility only
+ UInt8 Reserved;
+
+ UInt8 PreferredPowerManagementProfile;
+ UInt16 SCI_Interrupt;
+ UInt32 SMI_CommandPort;
+ UInt8 AcpiEnable;
+ UInt8 AcpiDisable;
+ UInt8 S4BIOS_REQ;
+ UInt8 PSTATE_Control;
+ UInt32 PM1aEventBlock;
+ UInt32 PM1bEventBlock;
+ UInt32 PM1aControlBlock;
+ UInt32 PM1bControlBlock;
+ UInt32 PM2ControlBlock;
+ UInt32 PMTimerBlock;
+ UInt32 GPE0Block;
+ UInt32 GPE1Block;
+ UInt8 PM1EventLength;
+ UInt8 PM1ControlLength;
+ UInt8 PM2ControlLength;
+ UInt8 PMTimerLength;
+ UInt8 GPE0Length;
+ UInt8 GPE1Length;
+ UInt8 GPE1Base;
+ UInt8 CStateControl;
+ UInt16 WorstC2Latency;
+ UInt16 WorstC3Latency;
+ UInt16 FlushSize;
+ UInt16 FlushStride;
+ UInt8 DutyOffset;
+ UInt8 DutyWidth;
+ UInt8 DayAlarm;
+ UInt8 MonthAlarm;
+ UInt8 Century;
+
+ // reserved in ACPI 1.0; used since ACPI 2.0+
+ UInt16 BootArchitecturkMMFlags;
+
+ UInt8 Reserved2;
+ UInt32 Flags;
+
+ // 12 byte structure; see below for details
+ ACPI_ADDRESS ResetReg;
+
+ UInt8 ResetValue;
+ UInt8 Reserved3[3];
+
+ // 64bit pointers - Available on ACPI 2.0+
+ UInt64 X_FirmwareControl;
+ UInt64 X_Dsdt;
+
+ ACPI_ADDRESS X_PM1aEventBlock;
+ ACPI_ADDRESS X_PM1bEventBlock;
+ ACPI_ADDRESS X_PM1aControlBlock;
+ ACPI_ADDRESS X_PM1bControlBlock;
+ ACPI_ADDRESS X_PM2ControlBlock;
+ ACPI_ADDRESS X_PMTimerBlock;
+ ACPI_ADDRESS X_GPE0Block;
+ ACPI_ADDRESS X_GPE1Block;
+ };
+ } // namespace Detail
+
+ ACPIFactoryInterface::ACPIFactoryInterface(VoidPtr rsp_ptr)
+ : fRsdp(rsp_ptr), fEntries(0)
+ {
+ }
+
+ Void ACPIFactoryInterface::Shutdown()
+ {
+ failed_to_shutdown:
+ // in case no acpi mode, or it's not available.
+ while (Yes)
+ {
+ asm volatile("cli; hlt");
+ }
+ }
+
+ /// @brief Reboot machine in either ACPI or by triple faulting.
+ /// @return nothing it's a reboot.
+ Void ACPIFactoryInterface::Reboot()
+ {
+ failed_to_reboot:
+ asm volatile(".intel_syntax noprefix; "
+ "rt_reset_hardware:; "
+ "cli; "
+ "wait_gate1: ; "
+ "in al,0x64 ; "
+ "and al,2 ; "
+ "jnz wait_gate1 ; "
+ "mov al,0x0D1 ; "
+ "out 0x64,al ; "
+ "wait_gate2: ; "
+ "in al,0x64 ; "
+ "and al,2 ; "
+ "jnz wait_gate2 ; "
+ "mov al,0x0FE ; "
+ "out 0x60,al ; "
+ "xor rax,rax ; "
+ "lidt [rax] ; "
+ "reset_wait: ; "
+ "jmp reset_wait ; "
+ ".att_syntax; ");
+ }
+} // namespace Kernel
diff --git a/dev/ZKAKit/HALKit/AMD64/HalAPICController.cc b/dev/ZKAKit/HALKit/AMD64/HalAPICController.cc
new file mode 100644
index 00000000..af6088f3
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalAPICController.cc
@@ -0,0 +1,39 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <HALKit/AMD64/Processor.h>
+
+#define cIOAPICRegVal (4)
+#define cIOAPICRegReg (0)
+
+namespace Kernel::HAL
+{
+ /// @brief Read from APIC controller.
+ /// @param reg register.
+ UInt32 APICController::Read(UInt32 reg) noexcept
+ {
+ MUST_PASS(this->fApic);
+
+ UInt32 volatile* io_apic = (UInt32 volatile*)this->fApic;
+ io_apic[cIOAPICRegReg] = (reg & 0xFF);
+
+ return io_apic[cIOAPICRegVal];
+ }
+
+ /// @brief Write to APIC controller.
+ /// @param reg register.
+ /// @param value value.
+ Void APICController::Write(UInt32 reg, UInt32 value) noexcept
+ {
+ MUST_PASS(this->fApic);
+
+ UInt32 volatile* io_apic = (UInt32 volatile*)this->fApic;
+
+ io_apic[cIOAPICRegReg] = (reg & 0xFF);
+ io_apic[cIOAPICRegVal] = value;
+ }
+} // namespace Kernel::HAL
diff --git a/dev/ZKAKit/HALKit/AMD64/HalBoot.asm b/dev/ZKAKit/HALKit/AMD64/HalBoot.asm
new file mode 100644
index 00000000..eee26276
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalBoot.asm
@@ -0,0 +1,28 @@
+;; /*
+;; * ========================================================
+;; *
+;; * ZKA
+;; * Copyright ZKA Web Services Co., all rights reserved.
+;; *
+;; * ========================================================
+;; */
+
+[bits 64]
+
+;; Global symbol of this unit
+[extern hal_init_platform]
+
+%define kTypeKernel 100
+%define kArchAmd64 122
+%define kHandoverMagic 0xBADCC
+
+section .ldr
+
+HandoverMagic:
+ dq kHandoverMagic
+HandoverType:
+ dw kTypeKernel
+HandoverPad:
+ dw 0
+HandoverArch:
+ dw kArchAmd64
diff --git a/dev/ZKAKit/HALKit/AMD64/HalCPUAMD64.cc b/dev/ZKAKit/HALKit/AMD64/HalCPUAMD64.cc
new file mode 100644
index 00000000..d24bfc0a
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalCPUAMD64.cc
@@ -0,0 +1,101 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+ File: HalCPU.cc
+ Purpose: Platform processor routines.
+
+------------------------------------------- */
+
+#include <HALKit/AMD64/Paging.h>
+#include <HALKit/AMD64/Processor.h>
+
+/**
+ * @file HalCPU.cc
+ * @brief Common CPU API.
+ */
+
+namespace Kernel::HAL
+{
+ Void Out8(UInt16 port, UInt8 value)
+ {
+ asm volatile("outb %%al, %1"
+ :
+ : "a"(value), "Nd"(port)
+ : "memory");
+ }
+
+ Void Out16(UInt16 port, UInt16 value)
+ {
+ asm volatile("outw %%ax, %1"
+ :
+ : "a"(value), "Nd"(port)
+ : "memory");
+ }
+
+ Void Out32(UInt16 port, UInt32 value)
+ {
+ asm volatile("outl %%eax, %1"
+ :
+ : "a"(value), "Nd"(port)
+ : "memory");
+ }
+
+ UInt8 In8(UInt16 port)
+ {
+ UInt8 value = 0UL;
+ asm volatile("inb %1, %%al"
+ : "=a"(value)
+ : "Nd"(port)
+ : "memory");
+
+ return value;
+ }
+
+ UInt16 In16(UInt16 port)
+ {
+ UInt16 value = 0UL;
+ asm volatile("inw %1, %%ax"
+ : "=a"(value)
+ : "Nd"(port)
+ : "memory");
+
+ return value;
+ }
+
+ UInt32 In32(UInt16 port)
+ {
+ UInt32 value = 0UL;
+ asm volatile("inl %1, %%eax"
+ : "=a"(value)
+ : "Nd"(port)
+ : "memory");
+
+ return value;
+ }
+
+ Void rt_halt()
+ {
+ asm volatile("hlt");
+ }
+
+ Void rt_cli()
+ {
+ asm volatile("cli");
+ }
+
+ Void rt_sti()
+ {
+ asm volatile("sti");
+ }
+
+ Void rt_cld()
+ {
+ asm volatile("cld");
+ }
+
+ Void rt_std()
+ {
+ asm volatile("std");
+ }
+} // namespace Kernel::HAL
diff --git a/dev/ZKAKit/HALKit/AMD64/HalCommonAPI.asm b/dev/ZKAKit/HALKit/AMD64/HalCommonAPI.asm
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalCommonAPI.asm
diff --git a/dev/ZKAKit/HALKit/AMD64/HalContextSwitchAMD64.asm b/dev/ZKAKit/HALKit/AMD64/HalContextSwitchAMD64.asm
new file mode 100644
index 00000000..cb054a0d
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalContextSwitchAMD64.asm
@@ -0,0 +1,42 @@
+;; /*
+;; * ========================================================
+;; *
+;; * ZKA
+;; * Copyright ZKA Web Services Co., all rights reserved.
+;; *
+;; * ========================================================
+;; */
+
+[bits 64]
+
+[global mp_do_task_switch]
+[global mp_do_context_switch_pre]
+[global mp_user_switch_proc]
+[global mp_user_switch_proc_stack_begin]
+
+section .text
+
+;; @brief Switch to user mode.
+mp_do_task_switch:
+ mov rbp, rdx
+ mov rsp, rdx
+
+ mov ax, 0x18 | 3
+ mov ds, ax
+ mov es, ax
+ mov gs, ax
+ mov fs, ax
+
+ push 0x18 | 3
+
+ mov rax, rdx
+ push rax
+
+ o64 pushf
+
+ push 0x20 | 3
+
+ mov rax, rcx
+ push rax
+
+ o64 iret
diff --git a/dev/ZKAKit/HALKit/AMD64/HalControlRegister.s b/dev/ZKAKit/HALKit/AMD64/HalControlRegister.s
new file mode 100644
index 00000000..586f1f83
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalControlRegister.s
@@ -0,0 +1,45 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+.globl hal_write_cr3
+.globl hal_write_cr0
+.globl hal_read_cr2
+.globl hal_read_cr3
+.globl hal_read_cr0
+.globl hal_flush_tlb
+.globl hal_invl_tlb
+
+.text
+
+hal_invl_tlb:
+ invlpg (%rcx)
+ retq
+
+hal_flush_tlb:
+ call hal_read_cr3
+ mov %rax, %rcx
+ call hal_write_cr3
+ retq
+
+hal_read_cr3:
+ movq %cr3, %rax
+ retq
+
+hal_read_cr0:
+ movq %cr0, %rax
+ retq
+
+hal_read_cr2:
+ movq %cr2, %rax
+ retq
+
+hal_write_cr3:
+ movq %rcx, %cr3
+ retq
+
+hal_write_cr0:
+ movq %rcx, %cr0
+ retq
diff --git a/dev/ZKAKit/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc b/dev/ZKAKit/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc
new file mode 100644
index 00000000..b8a84075
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cc
@@ -0,0 +1,113 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/UserProcessScheduler.h>
+#include <NewKit/String.h>
+
+namespace Kernel
+{
+ EXTERN UserProcessScheduler* kProcessScheduler;
+}
+
+/// @brief Handle GPF fault.
+/// @param rsp
+EXTERN_C void idt_handle_gpf(Kernel::UIntPtr rsp)
+{
+ Kernel::UserProcessScheduler::The().CurrentProcess().Leak().Crash();
+}
+
+/// @brief Handle page fault.
+/// @param rsp
+EXTERN_C void idt_handle_pf(Kernel::UIntPtr rsp)
+{
+ Kernel::UserProcessScheduler::The().CurrentProcess().Leak().Crash();
+}
+
+/// @brief Handle scheduler interrupt.
+EXTERN_C void idt_handle_scheduler(Kernel::UIntPtr rsp)
+{
+ Kernel::UserProcessHelper::StartScheduling();
+}
+
+/// @brief Handle math fault.
+/// @param rsp
+EXTERN_C void idt_handle_math(Kernel::UIntPtr rsp)
+{
+ Kernel::UserProcessScheduler::The().CurrentProcess().Leak().Crash();
+}
+
+/// @brief Handle any generic fault.
+/// @param rsp
+EXTERN_C void idt_handle_generic(Kernel::UIntPtr rsp)
+{
+ Kernel::UserProcessScheduler::The().CurrentProcess().Leak().Crash();
+}
+
+/// @brief Handle #UD fault.
+/// @param rsp
+EXTERN_C void idt_handle_ud(Kernel::UIntPtr rsp)
+{
+ Kernel::UserProcessScheduler::The().CurrentProcess().Leak().Crash();
+}
+
+/// @brief Enter syscall from assembly.
+/// @param stack the stack pushed from assembly routine.
+/// @return nothing.
+EXTERN_C Kernel::Void hal_system_call_enter(Kernel::UIntPtr rcx_syscall_index, Kernel::UIntPtr rdx_syscall_struct)
+{
+ if (rcx_syscall_index < kSyscalls.Count())
+ {
+ kcout << "syscall: Enter Syscall.\r";
+
+ if (kSyscalls[rcx_syscall_index].fHooked)
+ {
+ if (kSyscalls[rcx_syscall_index].fProc)
+ {
+ (kSyscalls[rcx_syscall_index].fProc)((Kernel::VoidPtr)rdx_syscall_struct);
+ }
+ else
+ {
+ kcout << "syscall: syscall isn't valid at all! (is nullptr)\r";
+ }
+ }
+ else
+ {
+ kcout << "syscall: syscall isn't hooked at all! (is set to false)\r";
+ }
+
+ kcout << "syscall: Exit Syscall.\r";
+ }
+}
+
+/// @brief Enter Kernel call from assembly (DDK only).
+/// @param stack the stack pushed from assembly routine.
+/// @return nothing.
+EXTERN_C Kernel::Void hal_kernel_call_enter(Kernel::UIntPtr rcx_kerncall_index, Kernel::UIntPtr rdx_kerncall_struct)
+{
+ if (rcx_kerncall_index < kKerncalls.Count())
+ {
+ kcout << "kerncall: Enter Kcall.\r";
+
+ if (kKerncalls[rcx_kerncall_index].fHooked)
+ {
+ if (kKerncalls[rcx_kerncall_index].fProc)
+ {
+ (kKerncalls[rcx_kerncall_index].fProc)((Kernel::VoidPtr)rdx_kerncall_struct);
+ }
+ else
+ {
+ kcout << "kerncall: syscall isn't valid at all! (is nullptr)\r";
+ }
+ }
+ else
+ {
+ kcout << "kerncall: syscall isn't hooked at all! (is set to false)\r";
+ }
+
+ kcout << "kerncall: Exit Kcall.\r";
+ }
+}
diff --git a/dev/ZKAKit/HALKit/AMD64/HalCoreMPScheduler.cc b/dev/ZKAKit/HALKit/AMD64/HalCoreMPScheduler.cc
new file mode 100644
index 00000000..89282ebe
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalCoreMPScheduler.cc
@@ -0,0 +1,229 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <KernelKit/UserProcessScheduler.h>
+#include <HALKit/AMD64/Processor.h>
+#include <NewKit/Stop.h>
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/Semaphore.h>
+#include <KernelKit/UserProcessScheduler.h>
+#include <KernelKit/Timer.h>
+#include <Modules/FB/Text.h>
+
+// Needed for SMP. //
+#include <FirmwareKit/EFI.h>
+#include <KernelKit/HardwareThreadScheduler.h>
+
+#define kApicSignature "APIC"
+
+#define kAPIC_ICR_Low 0x300
+#define kAPIC_ICR_High 0x310
+#define kAPIC_SIPI_Vector 0x00500
+#define kAPIC_EIPI_Vector 0x00400
+
+#define kAPIC_BASE_MSR 0x1B
+#define kAPIC_BASE_MSR_BSP 0x100
+#define kAPIC_BASE_MSR_ENABLE 0x800
+
+#define cSMPMax (32U)
+
+/// @note: _hal_switch_context is internal
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+//! NOTE: fGSI stands 'Field Global System Interrupt'
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+namespace Kernel::HAL
+{
+ struct MADT_TABLE;
+
+ EXTERN_C Void _hal_spin_core(Void);
+
+ STATIC struct MADT_TABLE* kMADTBlock = nullptr;
+ STATIC Bool kSMPAware = false;
+ STATIC Int64 kSMPCount = 0;
+
+ STATIC Int32 cSMPInterrupt = 0;
+ STATIC UInt64 cSMPCores[cSMPMax] = {0};
+ STATIC VoidPtr kRawMADT = nullptr;
+
+ /// @brief Multiple APIC Descriptor Table.
+ struct MADT_TABLE final : public SDT
+ {
+ UInt32 Address; // Madt address
+ UInt8 Flags; // Madt flags
+
+ struct
+ {
+ UInt8 Type;
+ UInt8 Len;
+
+ union {
+ struct
+ {
+ UInt8 IoID;
+ UInt8 Resv;
+ UInt32 IoAddress;
+ UInt32 GISBase;
+ } IOAPIC;
+
+ struct
+ {
+ UInt8 Source;
+ UInt8 IRQSource;
+ UInt32 GSI;
+ UInt16 Flags;
+ } IOAPIC_NMI;
+
+ struct
+ {
+ UInt8 ProcessorID;
+ UInt16 Flags;
+ UInt8 LINT;
+ } LAPIC;
+
+ struct
+ {
+ UInt16 Reserved;
+ UInt64 Address;
+ } LAPIC_ADDRESS_OVERRIDE;
+
+ struct
+ {
+ UInt16 Reserved;
+ UInt32 x2APICID;
+ UInt32 Flags;
+ UInt32 AcpiID;
+ } LAPIC_ADDRESS;
+ };
+ } List[]; // Records List
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////////////
+
+ /***********************************************************************************/
+ /// @brief Send start IPI for CPU.
+ /// @param apicId
+ /// @param vector
+ /// @param targetAddress
+ /// @return
+ /***********************************************************************************/
+
+ Void hal_send_start_ipi(UInt32 apicId, UInt8 vector, UInt32 targetAddress)
+ {
+ Kernel::ke_dma_write(targetAddress, kAPIC_ICR_High, (apicId << 24));
+ Kernel::ke_dma_write(targetAddress, kAPIC_ICR_Low, kAPIC_SIPI_Vector | vector);
+ }
+
+ /***********************************************************************************/
+ /// @brief Send end IPI for CPU.
+ /// @param apicId
+ /// @param vector
+ /// @param targetAddress
+ /// @return
+ /***********************************************************************************/
+ Void hal_send_end_ipi(UInt32 apicId, UInt8 vector, UInt32 targetAddress)
+ {
+ Kernel::ke_dma_write(targetAddress, kAPIC_ICR_High, (apicId << 24));
+ Kernel::ke_dma_write(targetAddress, kAPIC_ICR_Low, kAPIC_EIPI_Vector | vector);
+ }
+
+ EXTERN_C Bool mp_register_process(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr stack_frame);
+
+ struct PROCESS_CONTROL_BLOCK final
+ {
+ HAL::StackFramePtr f_Frame;
+ UInt8* f_Stack;
+ VoidPtr f_Image;
+ } fBlocks[kSchedProcessLimitPerTeam] = {0};
+
+ EXTERN_C HAL::StackFramePtr mp_get_current_context(Void)
+ {
+ return fBlocks[UserProcessScheduler::The().CurrentProcess().Leak().ProcessId % kSchedProcessLimitPerTeam].f_Frame;
+ }
+
+ EXTERN_C Void mp_do_task_switch(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr stack_frame);
+
+ EXTERN_C Bool mp_register_process(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr stack_frame)
+ {
+ fBlocks[UserProcessScheduler::The().CurrentProcess().Leak().ProcessId % kSchedProcessLimitPerTeam].f_Frame = stack_frame;
+ fBlocks[UserProcessScheduler::The().CurrentProcess().Leak().ProcessId % kSchedProcessLimitPerTeam].f_Stack = stack_ptr;
+ fBlocks[UserProcessScheduler::The().CurrentProcess().Leak().ProcessId % kSchedProcessLimitPerTeam].f_Image = image;
+
+ mp_do_task_switch(image, stack_ptr, stack_frame);
+
+ return Yes;
+ }
+
+ /***********************************************************************************/
+ /// @brief Fetch and enable cores inside main CPU.
+ /// @param vendor_ptr RSD PTR structure.
+ /***********************************************************************************/
+ Void mp_get_cores(VoidPtr vendor_ptr) noexcept
+ {
+ if (!vendor_ptr)
+ return;
+
+ auto hw_and_pow_int = PowerFactoryInterface(vendor_ptr);
+ kRawMADT = hw_and_pow_int.Find(kApicSignature).Leak().Leak();
+
+ kMADTBlock = reinterpret_cast<MADT_TABLE*>(kRawMADT);
+
+ kSMPAware = false;
+
+ if (kMADTBlock)
+ {
+ SizeT index = 0;
+
+ // reset values.
+
+ cSMPInterrupt = 0;
+ kSMPCount = 0;
+
+ kcout << "Probing MADT cores...\r";
+
+ UIntPtr madt_address = kMADTBlock->Address;
+
+ while (Yes)
+ {
+ if (kMADTBlock->List[index].Type > 9 ||
+ kSMPCount > cSMPMax)
+ break;
+
+ switch (kMADTBlock->List[index].Type)
+ {
+ case 0x00: {
+ cSMPCores[index] = kMADTBlock->List[index].LAPIC.ProcessorID;
+ kcout << "Core ID: " << number(cSMPCores[index]) << endl;
+ ++kSMPCount;
+ break;
+ }
+ case 0x05: {
+ madt_address = kMADTBlock->List[index].LAPIC_ADDRESS_OVERRIDE.Address;
+ kcout << "Address: " << number(madt_address) << endl;
+ break;
+ }
+ }
+
+ ++index;
+ }
+
+ kcout << "# of cores: " << number(kSMPCount) << endl;
+
+ // Kernel is now SMP aware.
+ // That means that the scheduler is now available (on MP Kernels)
+
+ kSMPAware = true;
+
+ /// TODO: Notify Boot AP that it must start.
+ }
+ }
+} // namespace Kernel::HAL
+
+///////////////////////////////////////////////////////////////////////////////////////
diff --git a/dev/ZKAKit/HALKit/AMD64/HalDebugOutput.cc b/dev/ZKAKit/HALKit/AMD64/HalDebugOutput.cc
new file mode 100644
index 00000000..49cdc964
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalDebugOutput.cc
@@ -0,0 +1,144 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/DebugOutput.h>
+#include <NewKit/Utils.h>
+#include <NewKit/New.h>
+
+namespace Kernel
+{
+ enum CommStatus
+ {
+ kStateInvalid,
+ kStateReady = 0xCF,
+ kStateTransmit = 0xFC,
+ kStateCnt = 3
+ };
+
+ namespace Detail
+ {
+ constexpr short PORT = 0x3F8;
+
+ static int kState = kStateInvalid;
+
+ /// @brief Init COM1.
+ /// @return
+ bool hal_serial_init() noexcept
+ {
+#ifdef __DEBUG__
+ if (kState == kStateReady || kState == kStateTransmit)
+ return true;
+
+ HAL::Out8(PORT + 1, 0x00); // Disable all interrupts
+ HAL::Out8(PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ HAL::Out8(PORT + 0, 0x03); // Set divisor to 3 (lo byte) 38400 baud
+ HAL::Out8(PORT + 1, 0x00); // (hi byte)
+ HAL::Out8(PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ HAL::Out8(PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
+ HAL::Out8(PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+ HAL::Out8(PORT + 4, 0x1E); // Set in loopback mode, test the serial chip
+ HAL::Out8(PORT + 0, 0xAE); // Test serial chip (send byte 0xAE and check if
+ // serial returns same byte)
+
+ // Check if serial is faulty (i.e: not same byte as sent)
+ if (HAL::In8(PORT) != 0xAE)
+ {
+ ke_stop(RUNTIME_CHECK_HANDSHAKE);
+ }
+
+ kState = kStateReady;
+
+ // If serial is not faulty set it in normal operation mode
+ // (not-loopback with IRQs enabled and OUT#1 and OUT#2 bits enabled)
+ HAL::Out8(Detail::PORT + 4, 0x0F);
+#endif // __DEBUG__
+
+ return true;
+ }
+ } // namespace Detail
+
+ EXTERN_C void ke_io_write(const Char* bytes)
+ {
+#ifdef __DEBUG__
+ Detail::hal_serial_init();
+
+ if (!bytes || Detail::kState != kStateReady)
+ return;
+ if (*bytes == 0)
+ return;
+
+ Detail::kState = kStateTransmit;
+
+ SizeT index = 0;
+ SizeT len = 0;
+
+ index = 0;
+ len = rt_string_len(bytes, 255);
+
+ while (index < len)
+ {
+ if (bytes[index] == '\r')
+ HAL::Out8(Detail::PORT, '\r');
+
+ HAL::Out8(Detail::PORT, bytes[index] == '\r' ? '\n' : bytes[index]);
+ ++index;
+ }
+
+ Detail::kState = kStateReady;
+#endif // __DEBUG__
+ }
+
+ EXTERN_C void ke_io_read(const Char* bytes)
+ {
+#ifdef __DEBUG__
+ Detail::hal_serial_init();
+
+ if (!bytes || Detail::kState != kStateReady)
+ return;
+
+ Detail::kState = kStateTransmit;
+
+ SizeT index = 0;
+
+ ///! TODO: Look on how to wait for the UART to complete.
+ while (true)
+ {
+ auto in = HAL::In8(Detail::PORT);
+
+ ///! 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;
+
+ Detail::kState = kStateReady;
+#endif // __DEBUG__
+ }
+
+ TerminalDevice TerminalDevice::The() noexcept
+ {
+ TerminalDevice out(Kernel::ke_io_write, Kernel::ke_io_read);
+ return out;
+ }
+
+} // namespace Kernel
diff --git a/dev/ZKAKit/HALKit/AMD64/HalDebugPort.cc b/dev/ZKAKit/HALKit/AMD64/HalDebugPort.cc
new file mode 100644
index 00000000..c6acfac6
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalDebugPort.cc
@@ -0,0 +1,40 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+//! @file DebuggerPort.cc
+//! @brief UART debug via packets.
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/DebugOutput.h>
+
+// after that we have start of additional data.
+
+namespace Kernel
+{
+ void rt_debug_listen(DebuggerPortHeader* theHook) noexcept
+ {
+ if (theHook == nullptr)
+ return;
+
+ for (UInt32 i = 0U; i < kDebugMaxPorts; ++i)
+ {
+ HAL::Out16(theHook->fPort[i], kDebugMag0);
+ HAL::rt_wait_400ns();
+
+ HAL::Out16(theHook->fPort[i], kDebugMag1);
+ HAL::rt_wait_400ns();
+
+ HAL::Out16(theHook->fPort[i], kDebugMag2);
+ HAL::rt_wait_400ns();
+
+ HAL::Out16(theHook->fPort[i], kDebugMag3);
+ HAL::rt_wait_400ns();
+
+ if (HAL::In16(theHook->fPort[i] != kDebugUnboundPort))
+ theHook->fBoundCnt++;
+ }
+ }
+} // namespace Kernel
diff --git a/dev/ZKAKit/HALKit/AMD64/HalDescriptorLoader.cc b/dev/ZKAKit/HALKit/AMD64/HalDescriptorLoader.cc
new file mode 100644
index 00000000..5f7bde36
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalDescriptorLoader.cc
@@ -0,0 +1,120 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <HALKit/AMD64/Processor.h>
+
+namespace Kernel::HAL
+{
+ namespace Detail
+ {
+ STATIC ::Kernel::Detail::AMD64::InterruptDescriptorAMD64
+ kInterruptVectorTable[kKernelIdtSize];
+
+ STATIC void hal_set_irq_mask(UInt8 irql);
+ STATIC void hal_clear_irq_mask(UInt8 irql);
+
+ STATIC Void hal_enable_pit(UInt16 ticks) noexcept
+ {
+ if (ticks == 0)
+ ticks = 1000;
+
+ // Configure PIT to receieve scheduler interrupts.
+
+ UInt16 cCommonDivisor = kPITFrequency / ticks; // 100 Hz.
+
+ HAL::Out8(kPITControlPort, 0x36); // Command to PIT
+ HAL::Out8(kPITChannel0Port, cCommonDivisor & 0xFF); // Send low byte
+ HAL::Out8(kPITChannel0Port, (cCommonDivisor >> 8) & 0xFF); // Send high byte
+
+ hal_clear_irq_mask(32);
+ }
+
+ STATIC void hal_set_irq_mask(UInt8 irql)
+ {
+ UInt16 port;
+ UInt8 value;
+
+ if (irql < 8)
+ {
+ port = kPICData;
+ }
+ else
+ {
+ port = kPIC2Data;
+ irql -= 8;
+ }
+
+ value = In8(port) | (1 << irql);
+ Out8(port, value);
+ }
+
+ STATIC void hal_clear_irq_mask(UInt8 irql)
+ {
+ UInt16 port;
+ UInt8 value;
+
+ if (irql < 8)
+ {
+ port = kPICData;
+ }
+ else
+ {
+ port = kPIC2Data;
+ irql -= 8;
+ }
+
+ value = In8(port) & ~(1 << irql);
+ Out8(port, value);
+ }
+ } // namespace Detail
+
+ /// @brief Loads the provided Global Descriptor Table.
+ /// @param gdt
+ /// @return
+ Void GDTLoader::Load(RegisterGDT& gdt)
+ {
+ hal_load_gdt(gdt);
+ }
+
+ Void IDTLoader::Load(Register64& idt)
+ {
+ const Int16 kPITTickForScheduler = 100;
+
+ volatile ::Kernel::UIntPtr** ptr_ivt = (volatile ::Kernel::UIntPtr**)idt.Base;
+
+ for (UInt16 idt_indx = 0; idt_indx < kKernelIdtSize; ++idt_indx)
+ {
+ Detail::kInterruptVectorTable[idt_indx].Selector = kIDTSelector;
+ Detail::kInterruptVectorTable[idt_indx].Ist = 0;
+ Detail::kInterruptVectorTable[idt_indx].TypeAttributes = kInterruptGate;
+ Detail::kInterruptVectorTable[idt_indx].OffsetLow = ((UIntPtr)ptr_ivt[idt_indx] & 0xFFFF);
+ Detail::kInterruptVectorTable[idt_indx].OffsetMid = (((UIntPtr)ptr_ivt[idt_indx] >> 16) & 0xFFFF);
+ Detail::kInterruptVectorTable[idt_indx].OffsetHigh =
+ (((UIntPtr)ptr_ivt[idt_indx] >> 32) & 0xFFFFFFFF);
+
+ Detail::kInterruptVectorTable[idt_indx].Zero = 0;
+ }
+
+ idt.Base = (UIntPtr)&Detail::kInterruptVectorTable[0];
+ idt.Limit = sizeof(::Kernel::Detail::AMD64::InterruptDescriptorAMD64) *
+ (kKernelIdtSize)-1;
+
+ hal_load_idt(idt);
+
+ Detail::hal_enable_pit(kPITTickForScheduler);
+ }
+
+ void GDTLoader::Load(Ref<RegisterGDT>& gdt)
+ {
+ GDTLoader::Load(gdt.Leak());
+ }
+
+ void IDTLoader::Load(Ref<Register64>& idt)
+ {
+ IDTLoader::Load(idt.Leak());
+ }
+} // namespace Kernel::HAL
diff --git a/dev/ZKAKit/HALKit/AMD64/HalInterruptAPI.asm b/dev/ZKAKit/HALKit/AMD64/HalInterruptAPI.asm
new file mode 100644
index 00000000..06066f41
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalInterruptAPI.asm
@@ -0,0 +1,381 @@
+;; /*
+;; * ---------------------------------------------------
+;; *
+;; * Copyright ZKA Web Services Co., all rights reserved.
+;; *
+;; * File: HalInterruptAPI.asm
+;; * Purpose: Interrupt API, redirect raw interrupts into their handlers.
+;; *
+;; * ---------------------------------------------------
+;; */
+
+[bits 64]
+
+%define kInterruptId 0x21
+
+%macro IntExp 1
+global __ZKA_INT_%1
+__ZKA_INT_%1:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ sti
+ o64 iret
+%endmacro
+
+%macro IntNormal 1
+global __ZKA_INT_%1
+__ZKA_INT_%1:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ sti
+ o64 iret
+%endmacro
+
+; This file handles the core interrupt table
+; Last edited 31/01/24
+
+global ke_handle_irq
+global kInterruptVectorTable
+
+extern idt_handle_gpf
+extern idt_handle_pf
+extern ke_io_write
+extern idt_handle_ud
+extern idt_handle_generic
+
+section .text
+
+IntNormal 0
+IntNormal 1
+
+IntNormal 2
+
+IntNormal 3
+IntNormal 4
+IntNormal 5
+
+;; Invalid opcode interrupt
+__ZKA_INT_6:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ push rax
+ mov rax, idt_handle_ud
+
+ mov rcx, rsp
+
+ call rax
+ pop rax
+
+ sti
+ o64 iret
+
+IntNormal 7
+
+;; Invalid opcode interrupt
+__ZKA_INT_8:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ push rax
+ mov rax, idt_handle_generic
+
+ mov rcx, rsp
+
+ call rax
+ pop rax
+
+ sti
+ o64 iret
+
+IntNormal 9
+IntExp 10
+IntExp 11
+
+IntExp 12
+
+__ZKA_INT_13:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ push rax
+ mov rax, idt_handle_gpf
+
+ mov rcx, rsp
+
+ call rax
+ pop rax
+
+ sti
+ o64 iret
+
+__ZKA_INT_14:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+ push rax
+ mov rax, idt_handle_pf
+
+ mov rcx, rsp
+
+ call rax
+ pop rax
+
+ sti
+ o64 iret
+
+IntNormal 15
+IntNormal 16
+IntExp 17
+IntNormal 18
+IntNormal 19
+IntNormal 20
+IntNormal 21
+
+IntNormal 22
+
+IntNormal 23
+IntNormal 24
+IntNormal 25
+IntNormal 26
+IntNormal 27
+IntNormal 28
+IntNormal 29
+IntExp 30
+IntNormal 31
+
+[extern idt_handle_scheduler]
+
+__ZKA_INT_32:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ push rax
+ mov rcx, rsp
+ mov rax, idt_handle_scheduler
+ call rax
+ pop rax
+
+ sti
+ o64 iret
+
+IntNormal 33
+
+IntNormal 34
+IntNormal 35
+IntNormal 36
+IntNormal 37
+IntNormal 38
+IntNormal 39
+IntNormal 40
+
+IntNormal 41
+
+IntNormal 42
+IntNormal 43
+IntNormal 44
+IntNormal 45
+IntNormal 46
+IntNormal 47
+IntNormal 48
+IntNormal 49
+
+[extern hal_system_call_enter]
+[extern hal_kernel_call_enter]
+
+__ZKA_INT_50:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ push rax
+ mov rax, hal_system_call_enter
+
+ mov rcx, r8
+ mov rdx, r9
+
+ call rax
+ pop rax
+
+ sti
+
+ o64 iret
+
+__ZKA_INT_51:
+ cli
+
+ mov al, 0x20
+ out 0x20, al
+ out 0xA0, al
+
+ push rax
+ mov rax, hal_kernel_call_enter
+
+ mov rcx, r8
+ mov rdx, r9
+
+ call rax
+ pop rax
+
+ sti
+
+ o64 iret
+
+IntNormal 52
+
+IntNormal 53
+IntNormal 54
+IntNormal 55
+IntNormal 56
+IntNormal 57
+IntNormal 58
+IntNormal 59
+IntNormal 60
+
+%assign i 61
+%rep 195
+ IntNormal i
+%assign i i+1
+%endrep
+
+section .text
+
+[global hal_load_gdt]
+
+hal_load_gdt:
+ cld
+
+ lgdt [rcx]
+
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ mov rax, 0x08
+ push rax
+ push hal_reload_segments
+
+ o64 retf
+
+extern hal_real_init
+
+hal_reload_segments:
+ std
+ ;; Write address of syscall handler.
+ mov rdx, [mp_system_call_handler]
+ shr rdx, 32
+ mov rcx, 0xC0000082
+ wrmsr
+
+ ;; Set segments of syscall handler.
+
+ xor rax, rax
+ mov rdx, 0x230008
+ mov rcx, 0xC0000081
+ wrmsr
+
+ mov ecx, 0xC0000080
+ rdmsr
+ or eax, 1
+ wrmsr
+
+ jmp hal_real_init
+ ret
+
+global hal_load_idt
+global hal_user_code_start
+
+extern hal_system_call_enter
+global mp_system_call_handler
+
+mp_system_call_handler:
+
+ push r8
+ push r9
+ push r10
+ push r11
+ push r12
+ push r13
+ push r14
+ push r15
+
+ jmp hal_system_call_enter
+
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop r11
+ pop r10
+ pop r9
+ pop r8
+
+ o64 sysret
+
+hal_load_idt:
+ lidt [rcx]
+
+ ; Master PIC initialization
+ mov al, 0x11 ; Start initialization in cascade mode
+ out 0x20, al ; Send initialization command to Master PIC
+ out 0xA0, al ; Send initialization command to Slave PIC
+
+ ; Remap the PIC to use vectors 32-39 for Master and 40-47 for Slave
+ mov al, 0x20 ; Set Master PIC offset to 32
+ out 0x21, al ; Send offset to Master PIC
+
+ mov al, 0x28 ; Set Slave PIC offset to 40
+ out 0xA1, al ; Send offset to Slave PIC
+
+ ; Configure Master PIC to inform Slave PIC at IRQ2
+ mov al, 0x04 ; Tell Master PIC there is a Slave PIC at IRQ2
+ out 0x21, al
+
+ ; Configure Slave PIC identity
+ mov al, 0x02 ; Tell Slave PIC its cascade identity
+ out 0xA1, al
+
+ ; Set both PICs to 8086 mode
+ mov al, 0x01 ; 8086 mode
+ out 0x21, al
+ out 0xA1, al
+
+ sti
+
+ ret
+
+section .data
+
+kInterruptVectorTable:
+ %assign i 0
+ %rep 256
+ dq __ZKA_INT_%+i
+ %assign i i+1
+ %endrep
diff --git a/dev/ZKAKit/HALKit/AMD64/HalKernelMain.cc b/dev/ZKAKit/HALKit/AMD64/HalKernelMain.cc
new file mode 100644
index 00000000..507ce217
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalKernelMain.cc
@@ -0,0 +1,115 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/UserProcessScheduler.h>
+#include <KernelKit/HardwareThreadScheduler.h>
+#include <KernelKit/CodeMgr.h>
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <NetworkKit/IPC.h>
+#include <CFKit/Property.h>
+#include <Modules/FB/Text.h>
+
+namespace Kernel::HAL
+{
+ /// @brief Gets the system cores using the MADT.
+ /// @param rsp_ptr The 'RSD PTR' data structure.
+ EXTERN void mp_get_cores(Kernel::voidPtr rsp_ptr) noexcept;
+} // namespace Kernel::HAL
+
+namespace Kernel
+{
+ EXTERN UserProcessScheduler* kProcessScheduler;
+ EXTERN HardwareThreadScheduler* kHardwareThreadScheduler;
+} // namespace Kernel
+
+EXTERN_C Kernel::VoidPtr kInterruptVectorTable[];
+EXTERN_C Kernel::VoidPtr mp_user_switch_proc;
+EXTERN_C Kernel::Char mp_user_switch_proc_stack_begin[];
+
+/// @brief Kernel init procedure.
+EXTERN_C void hal_init_platform(
+ Kernel::HEL::HANDOVER_INFO_HEADER* HandoverHeader)
+{
+ kHandoverHeader = HandoverHeader;
+
+ Kernel::kProcessScheduler = nullptr;
+ Kernel::kHardwareThreadScheduler = nullptr;
+
+ 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));
+
+ /************************************** */
+ /* INITIALIZE GDT AND SEGMENTS. */
+ /************************************** */
+
+ STATIC CONST auto cEntriesCount = 6;
+
+ /* GDT, mostly descriptors for user and kernel segments. */
+ STATIC Kernel::HAL::Detail::ZKA_GDT_ENTRY ALIGN(0x08) cGdt[cEntriesCount] = {
+ {.fLimitLow = 0, .fBaseLow = 0, .fBaseMid = 0, .fAccessByte = 0x00, .fFlags = 0x00, .fBaseHigh = 0}, // Null entry
+ {.fLimitLow = 0xFFFF, .fBaseLow = 0, .fBaseMid = 0, .fAccessByte = 0x9A, .fFlags = 0xAF, .fBaseHigh = 0}, // Kernel code
+ {.fLimitLow = 0xFFFF, .fBaseLow = 0, .fBaseMid = 0, .fAccessByte = 0x92, .fFlags = 0xCF, .fBaseHigh = 0}, // Kernel data
+ {.fLimitLow = 0xFFFF, .fBaseLow = 0, .fBaseMid = 0, .fAccessByte = 0xF2, .fFlags = 0xCF, .fBaseHigh = 0}, // User data
+ {.fLimitLow = 0xFFFF, .fBaseLow = 0, .fBaseMid = 0, .fAccessByte = 0xFA, .fFlags = 0xAF, .fBaseHigh = 0}, // User code
+ };
+
+ // Load memory descriptors.
+ Kernel::HAL::RegisterGDT gdt_reg;
+
+ gdt_reg.Base = reinterpret_cast<Kernel::UIntPtr>(cGdt);
+ gdt_reg.Limit = (sizeof(Kernel::HAL::Detail::ZKA_GDT_ENTRY) * cEntriesCount) - 1;
+
+ //! GDT will load hal_read_init after it successfully loads the segments.
+ Kernel::HAL::GDTLoader gdt_loader;
+ gdt_loader.Load(gdt_reg);
+
+ Kernel::ke_stop(RUNTIME_CHECK_BOOTSTRAP);
+}
+
+EXTERN_C Kernel::Void hal_kernel_server(Kernel::Void) noexcept
+{
+ while (Yes)
+ ;
+}
+
+EXTERN_C Kernel::Void hal_real_init(Kernel::Void) noexcept
+{
+ /* Initialize filesystem. */
+ Kernel::NeFileSystemMgr::Mount(new Kernel::NeFileSystemMgr());
+
+ /* Initialize scheduler. */
+ Kernel::UserProcessHelper::InitializeScheduler();
+
+ const Kernel::Char kKernelServerName[255] = "KernelServer";
+
+ Kernel::rtl_create_process(&hal_kernel_server, kKernelServerName);
+
+ /* Start any cores. */
+ if (kHandoverHeader->f_HardwareTables.f_MultiProcessingEnabled)
+ Kernel::HAL::mp_get_cores(kHandoverHeader->f_HardwareTables.f_VendorPtr);
+
+ Kernel::HAL::Register64 idt_reg;
+ idt_reg.Base = (Kernel::UIntPtr)kInterruptVectorTable;
+
+ /* Load interrupts. */
+ Kernel::HAL::IDTLoader idt_loader;
+ idt_loader.Load(idt_reg);
+
+ while (Yes)
+ ;
+}
diff --git a/dev/ZKAKit/HALKit/AMD64/HalPagingMgrAMD64.cc b/dev/ZKAKit/HALKit/AMD64/HalPagingMgrAMD64.cc
new file mode 100644
index 00000000..39f53fe4
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalPagingMgrAMD64.cc
@@ -0,0 +1,159 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+ File: HalPagingMgr.cc
+ Purpose: Platform Paging Manager..
+
+------------------------------------------- */
+
+#include <HALKit/AMD64/Paging.h>
+#include <HALKit/AMD64/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.
+
+ bool IsValidPage(PTE* pte)
+ {
+ return pte && pte->Present;
+ }
+
+ bool IsWRPage(PTE* pte)
+ {
+ return pte && pte->Wr;
+ }
+
+ bool IsUserPage(PTE* pte)
+ {
+ return pte && pte->User;
+ }
+
+ 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)
+ {
+ kcout << (pte->Present ? "Present" : "Not Present") << endl;
+ kcout << (pte->Wr ? "W/R" : "Not W/R") << endl;
+ kcout << (pte->ExecDisable ? "NX" : "Not NX") << endl;
+ kcout << (pte->User ? "User" : "Not User") << endl;
+ }
+
+ 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;
+
+ // Constants for table index bits
+ const UInt64 cPmlIndexMask = 0x1FFULL; // Mask for PML4, PDPT, PD, PT index (9 bits)
+ const UInt64 cPtIndexMask = 0xFFFULL; // Mask for page table index (12 bits)
+
+ UInt64 cr3 = (UInt64)hal_read_cr3();
+
+ ZKA_PAGE_STORE& page_store = ZKA_PAGE_STORE::The();
+
+ // Extract the indices from the virtual address
+ UInt64 pml4_index = ((UIntPtr)virtual_address >> 39) & cPmlIndexMask;
+ UInt64 pdpt_index = ((UIntPtr)virtual_address >> 30) & cPmlIndexMask;
+ UInt64 pd_index = ((UIntPtr)virtual_address >> 21) & cPmlIndexMask;
+ UInt64 pt_index = ((UIntPtr)virtual_address >> 12) & cPmlIndexMask;
+
+ 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);
+ }
+
+ const auto cPmlEntrySize = 8;
+
+ // Read the PML4 entry from memory
+ UInt64 pml4_base = cr3 & ~cPtIndexMask; // CR3 points to the PML4 table base, mask off lower bits
+ UInt64 pml4_entry = (pml4_base + pml4_index * cPmlEntrySize); // Each entry is 8 bytes
+
+ // Read the PDPT entry
+ UInt64 pdpt_base = pml4_entry & ~cPtIndexMask; // Get the PDPT base physical address
+ UInt64 pdpt_entry = (pdpt_base + pdpt_index * cPmlEntrySize);
+
+ // Read the PD entry
+ UInt64 pd_base = pdpt_entry & ~cPtIndexMask; // Get the Page Directory base physical address
+ UInt64 pd_entry = (pd_base + pd_index * cPmlEntrySize);
+
+ // Read the PT entry
+ UInt64 pt_base = pd_entry & ~cPtIndexMask; // Get the Page Table base physical address
+ UInt64 pt_entry = (pt_base + pt_index * cPmlEntrySize);
+
+ // Lastly, grab the pte entry.
+ ZKA_PDE* pte_struct = reinterpret_cast<ZKA_PDE*>(pt_base);
+
+ return mmi_map_page_table_entry(virtual_address, flags, pte_struct->fEntries[pt_entry]);
+ }
+
+ /// @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)
+ {
+ pt_entry->Present = true;
+
+ if (flags & kMMFlagsWr)
+ pt_entry->Wr = true;
+ else if (flags & ~kMMFlagsWr)
+ pt_entry->Wr = false;
+
+ if (flags & kMMFlagsNX)
+ pt_entry->ExecDisable = true;
+ else if (flags & ~kMMFlagsNX)
+ pt_entry->ExecDisable = false;
+
+ if (flags & kMMFlagsUser)
+ pt_entry->User = true;
+ else if (flags & ~kMMFlagsUser)
+ pt_entry->User = false;
+
+ hal_invl_tlb(reinterpret_cast<VoidPtr>(pt_entry));
+
+ mmi_page_status(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/ZKAKit/HALKit/AMD64/HalRoutineWait.s b/dev/ZKAKit/HALKit/AMD64/HalRoutineWait.s
new file mode 100644
index 00000000..d794882d
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalRoutineWait.s
@@ -0,0 +1,9 @@
+.globl rt_wait_400ns
+
+.section .text
+rt_wait_400ns:
+ jmp .loop
+ .loop:
+ jmp .loop2
+ .loop2:
+ ret
diff --git a/dev/ZKAKit/HALKit/AMD64/HalSchedulerCoreAMD64.cc b/dev/ZKAKit/HALKit/AMD64/HalSchedulerCoreAMD64.cc
new file mode 100644
index 00000000..d4ca494c
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalSchedulerCoreAMD64.cc
@@ -0,0 +1,46 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <HALKit/AMD64/Processor.h>
+#include <KernelKit/UserProcessScheduler.h>
+
+namespace Kernel
+{
+ /***********************************************************************************/
+ /// @brief Unimplemented function (crashes by default)
+ /// @param
+ /***********************************************************************************/
+
+ EXTERN_C Void __zka_pure_call(void)
+ {
+ UserProcessScheduler::The().CurrentProcess().Leak().Crash();
+ }
+
+ Bool hal_check_stack(HAL::StackFramePtr stack_ptr)
+ {
+ if (!stack_ptr)
+ return false;
+
+ return true;
+ }
+
+ /// @brief Wakes up thread.
+ /// Wakes up thread from the hang state.
+ Void mp_wakeup_thread(HAL::StackFrame* stack)
+ {
+ Kernel::UserProcessHelper::StartScheduling();
+ }
+
+ /// @brief makes the thread sleep on a loop.
+ /// hooks and hangs thread to prevent code from executing.
+ Void mp_hang_thread(HAL::StackFrame* stack)
+ {
+ while (Yes)
+ {
+ /* Nothing to do, code is spinning */
+ }
+ }
+} // namespace Kernel
diff --git a/dev/ZKAKit/HALKit/AMD64/HalTimerAMD64.cc b/dev/ZKAKit/HALKit/AMD64/HalTimerAMD64.cc
new file mode 100644
index 00000000..7d6528ed
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalTimerAMD64.cc
@@ -0,0 +1,86 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+ File: HalTimer.cc
+ Purpose: HAL timer
+
+ Revision History:
+
+ 07/07/24: Added file (amlel)
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/Timer.h>
+
+// timer slot 0
+
+#define cHPETCounterRegValue (0x00)
+#define cHPETConfigRegValue (0x20)
+#define cHPETCompRegValue (0x24)
+#define cHPETInterruptRegValue (0x2C)
+
+///! BUGS: 0
+///! @file HalTimer.cc
+///! @brief Hardware Timer (HPET)
+
+namespace Kernel::Detail
+{
+ struct HPET_BLOCK : public Kernel::SDT
+ {
+ Kernel::UInt8 hardware_rev_id;
+ Kernel::UInt8 comparator_count : 5;
+ Kernel::UInt8 counter_size : 1;
+ Kernel::UInt8 reserved : 1;
+ Kernel::UInt8 legacy_replacement : 1;
+ Kernel::UInt16 pci_vendor_id;
+ ACPI_ADDRESS address;
+ Kernel::UInt8 hpet_number;
+ Kernel::UInt16 minimum_tick;
+ Kernel::UInt8 page_protection;
+ } PACKED;
+} // namespace Kernel::Detail
+
+using namespace Kernel;
+
+HardwareTimer::HardwareTimer(Int64 ms)
+ : fWaitFor(ms)
+{
+ auto power = PowerFactoryInterface(kHandoverHeader->f_HardwareTables.f_VendorPtr);
+
+ auto hpet = (Detail::HPET_BLOCK*)power.Find("HPET").Leak().Leak();
+ MUST_PASS(hpet);
+
+ fDigitalTimer = (IntPtr*)hpet->address.Address;
+}
+
+HardwareTimer::~HardwareTimer()
+{
+ fDigitalTimer = nullptr;
+ fWaitFor = 0;
+}
+
+Int32 HardwareTimer::Wait() noexcept
+{
+ if (fWaitFor < 1)
+ return -1;
+
+ // if not enabled yet.
+ if (!(*(fDigitalTimer + cHPETConfigRegValue) & (1 << 0)))
+ {
+ *(fDigitalTimer + cHPETConfigRegValue) |= (1 << 0); // enable it
+ *(fDigitalTimer + cHPETConfigRegValue) |= (1 << 3); // one shot conf
+ }
+
+ UInt64 ticks = fWaitFor / ((*(fDigitalTimer) >> 32) & __UINT32_MAX__);
+ UInt64 prev = *(fDigitalTimer + cHPETCounterRegValue);
+
+ prev += ticks;
+
+ while (*(fDigitalTimer + cHPETCounterRegValue) < (ticks))
+ ;
+
+ return 0;
+}
diff --git a/dev/ZKAKit/HALKit/AMD64/HalUtils.asm b/dev/ZKAKit/HALKit/AMD64/HalUtils.asm
new file mode 100644
index 00000000..910ea55f
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/HalUtils.asm
@@ -0,0 +1,27 @@
+;; /*
+;; * ========================================================
+;; *
+;; * ZKA
+;; * Copyright ZKA Web Services Co., all rights reserved.
+;; *
+;; * ========================================================
+;; */
+
+[bits 64]
+
+[global rt_install_tib]
+
+section .text
+
+;; changed: rs, fs
+;; expected: rcx, rdx
+
+rt_install_tib:
+ mov rcx, gs ;; TIB -> Thread Information Block
+ mov rdx, fs ;; PIB -> Process Information Block
+ ret
+
+;; //////////////////////////////////////////////////// ;;
+
+[extern cBspDone]
+[extern kApicMadtAddressesCount]
diff --git a/dev/ZKAKit/HALKit/AMD64/Hypervisor.h b/dev/ZKAKit/HALKit/AMD64/Hypervisor.h
new file mode 100644
index 00000000..5a0a9aeb
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/Hypervisor.h
@@ -0,0 +1,25 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.h>
+
+namespace Kernel
+{
+ MAKE_STRING_ENUM(HYPERVISOR)
+ ENUM_STRING(Qemu, "TCGTCGTCGTCG");
+ ENUM_STRING(KVM, " KVMKVMKVM ");
+ ENUM_STRING(VMWare, "VMwareVMware");
+ ENUM_STRING(VirtualBox, "VBoxVBoxVBox");
+ ENUM_STRING(Xen, "XenVMMXenVMM");
+ ENUM_STRING(Microsoft, "Microsoft Hv");
+ ENUM_STRING(Parallels, " prl hyperv ");
+ ENUM_STRING(ParallelsAlt, " lrpepyh vr ");
+ ENUM_STRING(Bhyve, "bhyve bhyve ");
+ ENUM_STRING(Qnx, " QNXQVMBSQG ");
+ END_STRING_ENUM()
+} // namespace Kernel
diff --git a/dev/ZKAKit/HALKit/AMD64/MBCI/.gitkeep b/dev/ZKAKit/HALKit/AMD64/MBCI/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/MBCI/.gitkeep
diff --git a/dev/ZKAKit/HALKit/AMD64/PCI/DMA.cc b/dev/ZKAKit/HALKit/AMD64/PCI/DMA.cc
new file mode 100644
index 00000000..056cdf19
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/PCI/DMA.cc
@@ -0,0 +1,82 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/DMA.h>
+
+namespace Kernel
+{
+ DMAWrapper::operator bool()
+ {
+ return fAddress;
+ }
+
+ bool DMAWrapper::operator!()
+ {
+ return !fAddress;
+ }
+
+ Boolean DMAWrapper::Check(UIntPtr offset) const
+ {
+ if (!fAddress)
+ return false;
+ if (offset == 0)
+ return true;
+
+ kcout << "[DMAWrapper::IsIn] Checking offset..\n";
+ return reinterpret_cast<UIntPtr>(fAddress) >= offset;
+ }
+
+ bool DMAWrapper::Write(const UIntPtr& bit, const UIntPtr& offset)
+ {
+ if (!fAddress)
+ return false;
+
+ kcout << "[DMAWrapper::Write] Writing at address..\n";
+
+ auto addr =
+ (volatile UIntPtr*)(reinterpret_cast<UIntPtr>(fAddress) + offset);
+ *addr = bit;
+
+ return true;
+ }
+
+ UIntPtr DMAWrapper::Read(const UIntPtr& offset)
+ {
+ kcout << "[DMAWrapper::Read] checking fAddress..\n";
+ if (!fAddress)
+ return 0;
+
+ kcout << "[DMAWrapper::Read] Reading fAddress..\n";
+ return *(volatile UIntPtr*)(reinterpret_cast<UIntPtr>(fAddress) + offset);
+ ;
+ }
+
+ UIntPtr DMAWrapper::operator[](const UIntPtr& offset)
+ {
+ return this->Read(offset);
+ }
+
+ OwnPtr<IOBuf<Char*>> DMAFactory::Construct(OwnPtr<DMAWrapper>& dma)
+ {
+ if (!dma)
+ return {};
+
+ OwnPtr<IOBuf<Char*>> dmaOwnPtr =
+ make_ptr<IOBuf<Char*>, char*>(reinterpret_cast<char*>(dma->fAddress));
+
+ if (!dmaOwnPtr)
+ return {};
+
+ kcout << "Returning the new OwnPtr<IOBuf<Char*>>!\r";
+ return dmaOwnPtr;
+ }
+
+ DMAWrapper& DMAWrapper::operator=(voidPtr Ptr)
+ {
+ fAddress = Ptr;
+ return *this;
+ }
+} // namespace Kernel
diff --git a/dev/ZKAKit/HALKit/AMD64/PCI/Database.cc b/dev/ZKAKit/HALKit/AMD64/PCI/Database.cc
new file mode 100644
index 00000000..897c51f4
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/PCI/Database.cc
@@ -0,0 +1,11 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/Database.h>
+
+namespace Kernel
+{
+}
diff --git a/dev/ZKAKit/HALKit/AMD64/PCI/Device.cc b/dev/ZKAKit/HALKit/AMD64/PCI/Device.cc
new file mode 100644
index 00000000..19b0886c
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/PCI/Device.cc
@@ -0,0 +1,139 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/PCI/Device.h>
+
+Kernel::UInt ZKA_PCIReadRaw(Kernel::UInt bar, Kernel::UShort bus, Kernel::UShort dev, Kernel::UShort fun)
+{
+ Kernel::UInt target = 0x80000000 | ((Kernel::UInt)bus << 16) |
+ ((Kernel::UInt)dev << 11) | ((Kernel::UInt)fun << 8) |
+ (bar & 0xFC);
+
+ Kernel::HAL::Out32((Kernel::UShort)Kernel::PCI::PciConfigKind::ConfigAddress,
+ target);
+
+ return Kernel::HAL::In32((Kernel::UShort)Kernel::PCI::PciConfigKind::ConfigData);
+}
+
+void ZKA_PCISetCfgTarget(Kernel::UInt bar, Kernel::UShort bus, Kernel::UShort dev, Kernel::UShort fun)
+{
+ Kernel::UInt target = 0x80000000 | ((Kernel::UInt)bus << 16) |
+ ((Kernel::UInt)dev << 11) | ((Kernel::UInt)fun << 8) |
+ (bar & ~3);
+
+ Kernel::HAL::Out32((Kernel::UShort)Kernel::PCI::PciConfigKind::ConfigAddress,
+ target);
+}
+
+#define PCI_BAR_IO 0x01
+#define PCI_BAR_LOWMEM 0x02
+#define PCI_BAR_64 0x04
+#define PCI_BAR_PREFETCH 0x08
+
+namespace Kernel::PCI
+{
+ Device::Device(UShort bus, UShort device, UShort func, UInt32 bar)
+ : fBus(bus), fDevice(device), fFunction(func), fBar(bar)
+ {
+ }
+
+ Device::~Device() = default;
+
+ UInt Device::Read(UInt bar, Size sz)
+ {
+ ZKA_PCISetCfgTarget(bar, fBus, fDevice, fFunction);
+
+ if (sz == 4)
+ return HAL::In32((UShort)PciConfigKind::ConfigData + (bar & 3));
+ if (sz == 2)
+ return HAL::In16((UShort)PciConfigKind::ConfigData + (bar & 3));
+ if (sz == 1)
+ return HAL::In8((UShort)PciConfigKind::ConfigData + (bar & 3));
+
+ return 0xFFFF;
+ }
+
+ void Device::Write(UInt bar, UIntPtr data, Size sz)
+ {
+ ZKA_PCISetCfgTarget(bar, fBus, fDevice, fFunction);
+
+ if (sz == 4)
+ HAL::Out32((UShort)PciConfigKind::ConfigData + (fBar & 3), (UInt)data);
+ if (sz == 2)
+ HAL::Out16((UShort)PciConfigKind::ConfigData + (fBar & 3), (UShort)data);
+ if (sz == 1)
+ HAL::Out8((UShort)PciConfigKind::ConfigData + (fBar & 3), (UChar)data);
+ }
+
+ UShort Device::DeviceId()
+ {
+ return (UShort)(ZKA_PCIReadRaw(0x0 >> 16, fBus, fDevice, fFunction));
+ }
+
+ UShort Device::VendorId()
+ {
+ return (UShort)(ZKA_PCIReadRaw(0x0, fBus, fDevice, fFunction) >> 16);
+ }
+
+ UShort Device::InterfaceId()
+ {
+ return (UShort)(ZKA_PCIReadRaw(0x0, fBus, fDevice, fFunction) >> 16);
+ }
+
+ UChar Device::Class()
+ {
+ return (UChar)(ZKA_PCIReadRaw(0x08, fBus, fDevice, fFunction) >> 24);
+ }
+
+ UChar Device::Subclass()
+ {
+ return (UChar)(ZKA_PCIReadRaw(0x08, fBus, fDevice, fFunction) >> 16);
+ }
+
+ UChar Device::ProgIf()
+ {
+ return (UChar)(ZKA_PCIReadRaw(0x08, fBus, fDevice, fFunction) >> 8);
+ }
+
+ UChar Device::HeaderType()
+ {
+ return (UChar)(ZKA_PCIReadRaw(0xC, fBus, fDevice, fFunction) >> 16);
+ }
+
+ void Device::EnableMmio(UInt32 bar_in)
+ {
+ bool enable = Read(bar_in, sizeof(UChar)) | (1 << 1);
+ Write(bar_in, enable, sizeof(UShort));
+ }
+
+ void Device::BecomeBusMaster(UInt32 bar_in)
+ {
+ bool enable = Read(bar_in, sizeof(UShort)) | (1 << 2);
+ Write(bar_in, enable, sizeof(UShort));
+ }
+
+ UInt32 Device::Bar(UInt32 bar_in)
+ {
+ UInt32 bar = ZKA_PCIReadRaw(bar_in, fBus, fDevice, fFunction);
+ return bar;
+ }
+
+ UShort Device::Vendor()
+ {
+ UShort vendor = VendorId();
+
+ if (vendor != (UShort)PciConfigKind::Invalid)
+ fDevice = (UShort)Read(0x0, sizeof(UShort));
+
+ return fDevice;
+ }
+
+ Device::operator bool()
+ {
+ return VendorId() != (UShort)PciConfigKind::Invalid;
+ }
+} // namespace Kernel::PCI
diff --git a/dev/ZKAKit/HALKit/AMD64/PCI/Express.cc b/dev/ZKAKit/HALKit/AMD64/PCI/Express.cc
new file mode 100644
index 00000000..c1481616
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/PCI/Express.cc
@@ -0,0 +1,11 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/Express.h>
+
+namespace Kernel
+{
+}
diff --git a/dev/ZKAKit/HALKit/AMD64/PCI/IO.cc b/dev/ZKAKit/HALKit/AMD64/PCI/IO.cc
new file mode 100644
index 00000000..c8535c54
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/PCI/IO.cc
@@ -0,0 +1,7 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/IO.h>
diff --git a/dev/ZKAKit/HALKit/AMD64/PCI/Iterator.cc b/dev/ZKAKit/HALKit/AMD64/PCI/Iterator.cc
new file mode 100644
index 00000000..d7e6f7d8
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/PCI/Iterator.cc
@@ -0,0 +1,41 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/Iterator.h>
+
+namespace Kernel::PCI
+{
+ Iterator::Iterator(const Types::PciDeviceKind& type)
+ {
+ // probe devices.
+ for (int bus = 0; bus < ZKA_BUS_COUNT; ++bus)
+ {
+ for (int device = 0; device < ZKA_DEVICE_COUNT; ++device)
+ {
+ for (int function = 0; function < ZKA_FUNCTION_COUNT; ++function)
+ {
+ auto bar = 0x00;
+
+ Device dev(bus, device, function, bar);
+
+ if (dev.Class() == (UChar)type)
+ {
+ fDevices[bus] = dev;
+ }
+ }
+ }
+ }
+ }
+
+ Iterator::~Iterator()
+ {
+ }
+
+ Ref<PCI::Device> Iterator::operator[](const Size& at)
+ {
+ return fDevices[at];
+ }
+} // namespace Kernel::PCI
diff --git a/dev/ZKAKit/HALKit/AMD64/PCI/PCI.cc b/dev/ZKAKit/HALKit/AMD64/PCI/PCI.cc
new file mode 100644
index 00000000..7e056bf9
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/PCI/PCI.cc
@@ -0,0 +1,7 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/PCI.h>
diff --git a/dev/ZKAKit/HALKit/AMD64/Paging.h b/dev/ZKAKit/HALKit/AMD64/Paging.h
new file mode 100644
index 00000000..0d109bb0
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/Paging.h
@@ -0,0 +1,99 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#pragma once
+
+/** ---------------------------------------------------
+
+ * THIS FILE CONTAINS CODE FOR X86_64 PAGING.
+
+------------------------------------------------------- */
+
+#include <NewKit/Defines.h>
+
+#ifndef kPageMax
+#define kPageMax (0x200)
+#endif //! kPageMax
+
+#ifndef kPageAlign
+#define kPageAlign (0x08)
+#endif //! kPageAlign
+
+#ifndef kPageSize
+#define kPageSize (0x100)
+#endif // !kPageSize
+
+#ifndef kAlign
+#define kAlign __BIGGEST_ALIGNMENT__
+#endif // !kAlign
+
+EXTERN_C void hal_flush_tlb();
+EXTERN_C void hal_invl_tlb(Kernel::VoidPtr addr);
+EXTERN_C void hal_write_cr3(Kernel::VoidPtr cr3);
+EXTERN_C void hal_write_cr0(Kernel::VoidPtr bit);
+
+EXTERN_C Kernel::VoidPtr hal_read_cr0(); // @brief CPU control register.
+EXTERN_C Kernel::VoidPtr hal_read_cr2(); // @brief Fault address.
+EXTERN_C Kernel::VoidPtr hal_read_cr3(); // @brief Page table.
+
+namespace Kernel::HAL
+{
+ /// @brief Final page entry (Not PML, PDPT)
+ struct PACKED ZKA_PTE final
+ {
+ UInt64 Present : 1;
+ UInt64 Wr : 1;
+ UInt64 User : 1;
+ UInt64 Wt : 1;
+ UInt64 Cache : 1;
+ UInt64 Accessed : 1;
+ UInt64 Dirty : 1;
+ UInt64 MemoryType : 1;
+ UInt64 Global : 1;
+ UInt64 Resvered1 : 3;
+ UInt64 PhysicalAddress : 36;
+ UInt64 Reserved2 : 10;
+ UInt64 ProtectionKey : 5;
+ UInt64 ExecDisable : 1;
+ };
+
+ 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 ZKA_PDE final
+ {
+ ZKA_PTE* 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::ZKA_PTE PTE;
+ typedef HAL::ZKA_PDE PDE;
+} // namespace Kernel
diff --git a/dev/ZKAKit/HALKit/AMD64/Processor.h b/dev/ZKAKit/HALKit/AMD64/Processor.h
new file mode 100644
index 00000000..968cf5e9
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/Processor.h
@@ -0,0 +1,313 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+ File: Prcoessor.h
+ Purpose: AMD64 processor abstraction.
+
+ Revision History:
+
+ 30/01/24: Added file (amlel)
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Array.h>
+#include <NewKit/Defines.h>
+#include <NewKit/Utils.h>
+#include <FirmwareKit/Handover.h>
+#include <HALKit/AMD64/Paging.h>
+
+#define kPITControlPort 0x43
+#define kPITChannel0Port 0x40
+#define kPITFrequency 1193180
+
+#define kPICCommand 0x20
+#define kPICData 0x21
+#define kPIC2Command 0xA0
+#define kPIC2Data 0xA1
+
+EXTERN_C
+{
+#include <cpuid.h>
+}
+
+#include <HALKit/AMD64/CPUID.h>
+
+/// @brief Maximum entries of the interrupt descriptor table.
+#define kKernelIdtSize (0x100)
+
+/// @brief interrupt for system call.
+#define kKernelInterruptId (0x32)
+
+#define IsActiveLow(FLG) (FLG & 2)
+#define IsLevelTriggered(FLG) (FLG & 8)
+
+#define kInterruptGate (0x8E)
+#define kTrapGate (0xEF)
+#define kTaskGate (0b10001100)
+#define kIDTSelector (0x08)
+
+namespace Kernel
+{
+ namespace Detail::AMD64
+ {
+ struct PACKED InterruptDescriptorAMD64 final
+ {
+ UInt16 OffsetLow; // offset bits 0..15
+ UInt16 Selector; // a code segment selector in GDT or LDT
+ UInt8 Ist;
+ UInt8 TypeAttributes;
+ UInt16 OffsetMid;
+ UInt32 OffsetHigh;
+ UInt32 Zero; // reserved
+ };
+ } // namespace Detail::AMD64
+} // namespace Kernel
+
+namespace Kernel::HAL
+{
+ /// @brief Memory Manager mapping flags.
+ enum
+ {
+ kMMFlagsInvalid = 0 << 0,
+ kMMFlagsPresent = 1 << 0,
+ kMMFlagsWr = 1 << 1,
+ kMMFlagsUser = 1 << 2,
+ kMMFlagsNX = 1 << 3,
+ kMMFlagsCount = 4,
+ };
+
+ struct PACKED Register64 final
+ {
+ UShort Limit;
+ UIntPtr Base;
+ };
+
+ struct PACKED RegisterGDT final
+ {
+ UShort Limit;
+ UIntPtr Base;
+ };
+
+ using RawRegister = UInt64;
+ using Reg = RawRegister;
+ using InterruptId = UInt16; /* For each element in the IVT */
+
+ /// @brief Stack frame (as retrieved from assembly.)
+ struct PACKED StackFrame final
+ {
+ RawRegister R8{0};
+ RawRegister R9{0};
+ RawRegister R10{0};
+ RawRegister FS{0};
+ RawRegister R12{0};
+ RawRegister R13{0};
+ RawRegister R14{0};
+ RawRegister R15{0};
+ RawRegister GS{0};
+ RawRegister SP{0};
+ RawRegister BP{0};
+ };
+
+ typedef StackFrame* StackFramePtr;
+
+ class InterruptDescriptor final
+ {
+ public:
+ UShort Offset;
+ UShort Selector;
+ UChar Ist;
+ UChar Atrributes;
+
+ UShort SecondOffset;
+ UInt ThirdOffset;
+ UInt Zero;
+
+ operator bool()
+ {
+ return Offset != 0xFFFF;
+ }
+ };
+
+ using InterruptDescriptorArray = Array<InterruptDescriptor, 256>;
+
+ class SegmentDescriptor final
+ {
+ public:
+ UInt16 Base;
+ UInt8 BaseMiddle;
+ UInt8 BaseHigh;
+
+ UShort Limit;
+ UChar Gran;
+ UChar AccessByte;
+ };
+
+ /***
+ * @brief Segment Boolean operations
+ */
+ class SegmentDescriptorComparator final
+ {
+ public:
+ Bool IsValid(SegmentDescriptor& seg)
+ {
+ return seg.Base > seg.Limit;
+ }
+
+ Bool Equals(SegmentDescriptor& seg, SegmentDescriptor& segRight)
+ {
+ return seg.Base == segRight.Base && seg.Limit == segRight.Limit;
+ }
+ };
+
+ using SegmentArray = Array<SegmentDescriptor, 6>;
+
+ class GDTLoader final
+ {
+ public:
+ static Void Load(RegisterGDT& gdt);
+ static Void Load(Ref<RegisterGDT>& gdt);
+ };
+
+ class IDTLoader final
+ {
+ public:
+ static Void Load(Register64& idt);
+ static Void Load(Ref<Register64>& idt);
+ };
+
+ Void mp_get_cores(VoidPtr rsp_ptr) noexcept;
+ Void hal_send_start_ipi(UInt32 apicId, UInt8 vector, UInt32 targetAddress);
+ Void hal_send_end_ipi(UInt32 apicId, UInt8 vector, UInt32 targetAddress);
+
+ /// @brief Do a cpuid to check if MSR exists on CPU.
+ /// @retval true it does exists.
+ /// @retval false it doesn't.
+ inline Bool hal_has_msr() noexcept
+ {
+ static UInt32 eax, unused, edx; // eax, edx
+
+ __get_cpuid(1, &eax, &unused, &unused, &edx);
+
+ // edx returns the flag for MSR (which is 1 shifted to 5.)
+ return edx & (1 << 5);
+ }
+
+ /// @brief Get Model-specific register.
+ /// @param msr MSR
+ /// @param lo low byte
+ /// @param hi high byte
+ inline Void hal_get_msr(UInt32 msr, UInt32* lo, UInt32* hi) noexcept
+ {
+ if (!lo || !hi)
+ return;
+
+ asm volatile("rdmsr"
+ : "=a"(*lo), "=d"(*hi)
+ : "c"(msr));
+ }
+
+ /// @brief Set Model-specific register.
+ /// @param msr MSR
+ /// @param lo low byte
+ /// @param hi high byte
+ inline Void hal_set_msr(UInt32 msr, UInt32 lo, UInt32 hi) noexcept
+ {
+ asm volatile("wrmsr"
+ :
+ : "a"(lo), "d"(hi), "c"(msr));
+ }
+
+ /// @brief Processor specific namespace.
+ namespace Detail
+ {
+ /* @brief TSS struct. */
+ struct ZKA_TSS final
+ {
+ UInt32 fReserved1;
+ UInt64 fRsp0;
+ UInt64 fRsp1;
+ UInt64 fRsp2;
+ UInt64 fReserved2;
+ UInt64 fIst1;
+ UInt64 fIst2;
+ UInt64 fIst3;
+ UInt64 fIst4;
+ UInt64 fIst5;
+ UInt64 fIst6;
+ UInt64 fIst7;
+ UInt64 fReserved3;
+ UInt16 fReserved4;
+ UInt16 fIopb;
+ };
+
+ /**
+ @brief Global descriptor table entry, either null, code or data.
+ */
+
+ struct PACKED ZKA_GDT_ENTRY final
+ {
+ UInt16 fLimitLow;
+ UInt16 fBaseLow;
+ UInt8 fBaseMid;
+ UInt8 fAccessByte;
+ UInt8 fFlags;
+ UInt8 fBaseHigh;
+ };
+ } // namespace Detail
+
+ class APICController
+ {
+ public:
+ explicit APICController(VoidPtr base)
+ : fApic(base)
+ {
+ }
+
+ ~APICController() = default;
+
+ ZKA_COPY_DEFAULT(APICController);
+
+ public:
+ UInt32 Read(UInt32 reg) noexcept;
+ Void Write(UInt32 reg, UInt32 value) noexcept;
+
+ private:
+ VoidPtr fApic{nullptr};
+ };
+
+ /// @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);
+
+ EXTERN_C UChar In8(UInt16 port);
+ EXTERN_C UShort In16(UInt16 port);
+ EXTERN_C UInt In32(UInt16 port);
+
+ EXTERN_C void Out16(UShort port, UShort byte);
+ EXTERN_C void Out8(UShort port, UChar byte);
+ EXTERN_C void Out32(UShort port, UInt byte);
+
+ EXTERN_C void rt_wait_400ns();
+ EXTERN_C void rt_halt();
+ EXTERN_C void rt_cli();
+ EXTERN_C void rt_sti();
+ EXTERN_C void rt_cld();
+ EXTERN_C void rt_std();
+} // namespace Kernel::HAL
+
+EXTERN_C Kernel::Void idt_handle_generic(Kernel::UIntPtr rsp);
+EXTERN_C Kernel::Void idt_handle_gpf(Kernel::UIntPtr rsp);
+EXTERN_C Kernel::Void idt_handle_math(Kernel::UIntPtr rsp);
+EXTERN_C Kernel::Void idt_handle_pf(Kernel::UIntPtr rsp);
+
+EXTERN_C Kernel::Void hal_load_idt(Kernel::HAL::Register64 ptr);
+EXTERN_C Kernel::Void hal_load_gdt(Kernel::HAL::RegisterGDT ptr);
+
+inline Kernel::VoidPtr kKernelBitMpStart = nullptr;
+inline Kernel::UIntPtr kKernelBitMpSize = 0UL;
diff --git a/dev/ZKAKit/HALKit/AMD64/ReadMe.md b/dev/ZKAKit/HALKit/AMD64/ReadMe.md
new file mode 100644
index 00000000..7364b8e6
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/ReadMe.md
@@ -0,0 +1,4 @@
+# AMD64 Hardware Abstraction Layer
+
+- Supported CPU: AMD64 CPU.
+- Supported Firmware: EDK 2 w/ ZKA's own extensions for EPM.
diff --git a/dev/ZKAKit/HALKit/AMD64/Storage/AHCI.cc b/dev/ZKAKit/HALKit/AMD64/Storage/AHCI.cc
new file mode 100644
index 00000000..caf7cd7e
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/Storage/AHCI.cc
@@ -0,0 +1,291 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+/**
+ * @file AHCI.cc
+ * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com)
+ * @brief AHCI driver.
+ * @version 0.1
+ * @date 2024-02-02
+ *
+ * @copyright ZKA Web Services Co.
+ *
+ */
+
+#include <Modules/AHCI/AHCI.h>
+#include <KernelKit/PCI/Iterator.h>
+#include <NewKit/Utils.h>
+#include <KernelKit/LockDelegate.h>
+
+#define kMaxAhciPoll 100000
+
+#ifdef __AHCI__
+enum
+{
+ kSATAProgIfAHCI = 0x01,
+ kSATASubClass = 0x06,
+ kSATABar5 = 0x24,
+};
+
+STATIC Kernel::PCI::Device kAhciDevice;
+STATIC HbaPort* kAhciPort = nullptr;
+
+/// @brief Initializes an AHCI disk.
+/// @param PortsImplemented the amount of kAhciPort that have been detected.
+/// @return
+Kernel::Boolean drv_std_init(Kernel::UInt16& PortsImplemented)
+{
+ using namespace Kernel;
+
+ PCI::Iterator iterator(Types::PciDeviceKind::MassStorageController);
+
+ for (SizeT devIndex = 0; devIndex < ZKA_BUS_COUNT; ++devIndex)
+ {
+ // if SATA and then interface is AHCI...
+ if (iterator[devIndex].Leak().Subclass() == kSATASubClass &&
+ iterator[devIndex].Leak().ProgIf() == kSATAProgIfAHCI)
+ {
+ iterator[devIndex].Leak().EnableMmio(0x24); // Enable the memory index_byte/o for this ahci device.
+ iterator[devIndex].Leak().BecomeBusMaster(0x24); // Become bus master for this ahci device, so that we can control it.
+
+ kAhciDevice = iterator[devIndex].Leak(); // And then leak the reference.
+
+ HbaMem* mem_ahci = (HbaMem*)kAhciDevice.Bar(0x24);
+
+ Kernel::UInt32 ports_implemented = mem_ahci->Pi;
+ Kernel::UInt16 ahci_index = 0;
+
+ const Kernel::UInt16 kMaxPortsImplemented = 32;
+ const Kernel::UInt32 kSATASignature = 0x00000101;
+ const Kernel::UInt8 kAhciPresent = 0x03;
+ const Kernel::UInt8 kAhciIPMActive = 0x01;
+
+ Kernel::Boolean detected = false;
+
+ while (ahci_index < kMaxPortsImplemented)
+ {
+ if (ports_implemented)
+ {
+ kcout << "Port is implemented by Host.\r";
+
+ Kernel::UInt8 ipm = (mem_ahci->Ports[ahci_index].Ssts >> 8) & 0x0F;
+ Kernel::UInt8 det = mem_ahci->Ports[ahci_index].Ssts & 0x0F;
+
+ if (mem_ahci->Ports[ahci_index].Sig == kSATASignature)
+ {
+ kcout << "Found AHCI controller.\r";
+
+ detected = true;
+
+ mem_ahci->Ghc |= (1 << kAhciGHC_AE);
+
+ kAhciPort = &mem_ahci->Ports[ahci_index];
+
+ break;
+ }
+ }
+
+ ports_implemented >>= 1;
+ ++ahci_index;
+ }
+
+ return detected;
+ }
+ }
+
+ return No;
+}
+
+Kernel::Boolean drv_std_detected(Kernel::Void)
+{
+ return kAhciDevice.DeviceId() != 0xFFFF;
+}
+
+Kernel::Void drv_std_read(Kernel::UInt64 Lba, Kernel::Char* Buf, Kernel::SizeT SectorSz, Kernel::SizeT Size)
+{
+ STATIC Kernel::Boolean kSlotIsUsed = No;
+
+ Kernel::LockDelegate<kMaxAhciPoll> lock(&kSlotIsUsed);
+
+ if (lock.HasTimedOut())
+ return;
+
+ kSlotIsUsed = Yes;
+
+ Kernel::Int64 free_slot = 0;
+
+ // Prepare command header.
+
+ HbaCmdHeader* cmd_header = (HbaCmdHeader*)kAhciPort->Clb;
+ cmd_header += free_slot;
+
+ // Read operation/set entries count.
+
+ cmd_header->Write = No;
+ cmd_header->Prdtl = (Kernel::UInt16)((Size - 1) >> 4) + 1; // PRDT entries count
+
+ // Prepare command table.
+
+ HbaCmdTbl* cmd_tbl = (HbaCmdTbl*)cmd_header->Ctba;
+ Kernel::rt_set_memory(cmd_tbl, 0, sizeof(HbaCmdTbl));
+
+ Kernel::UInt64 size = Size * kAHCISectorSize;
+ Kernel::Int64 index_byte = 0L;
+
+ for (index_byte = 0; index_byte < cmd_header->Prdtl - 1; index_byte++)
+ {
+ cmd_tbl->prdtEntries[index_byte].Dba = (Kernel::UInt32)(Kernel::UIntPtr)Buf;
+ cmd_tbl->prdtEntries[index_byte].Dbc = (8 * 1024) - 1; // 8KB Buf size
+ cmd_tbl->prdtEntries[index_byte].InterruptBit = 1; // Interrupt on completion
+
+ Size -= 8 * 1024;
+ Buf += 4 * 1024; // Move the Buf pointer forward
+ }
+
+ // Last PRDT entry
+ cmd_tbl->prdtEntries[index_byte].Dba = (Kernel::UInt32)(Kernel::UIntPtr)Buf;
+ cmd_tbl->prdtEntries[index_byte].Dbc = Size - 1; // Byte count left
+ cmd_tbl->prdtEntries[index_byte].InterruptBit = 1;
+
+ // 5. Prepare the command FIS (Frame Information Structure)
+ FisRegH2D* cmd_fis = (FisRegH2D*)(&cmd_tbl->Cfis);
+ Kernel::rt_set_memory(cmd_fis, 0, sizeof(FisRegH2D));
+
+ cmd_fis->FisType = kFISTypeRegH2D;
+ cmd_fis->CmdOrCtrl = 1; // Command
+ cmd_fis->Command = kAHCICmdReadDmaEx;
+
+ cmd_fis->Lba0 = (Kernel::UInt8)Lba;
+ cmd_fis->Lba1 = (Kernel::UInt8)(Lba >> 8);
+ cmd_fis->Lba2 = (Kernel::UInt8)(Lba >> 16);
+ cmd_fis->Device = 1 << 6; // LBA mode
+
+ cmd_fis->Lba3 = (Kernel::UInt8)(Lba >> 24);
+ cmd_fis->Lba4 = (Kernel::UInt8)(Lba >> 32);
+ cmd_fis->Lba5 = (Kernel::UInt8)(Lba >> 40);
+
+ cmd_fis->CountLow = Size & 0xFF;
+ cmd_fis->CountHigh = (Size >> 8) & 0xFF;
+
+ // 6. Issue the command by writing to the kAhciPort's command issue register (CI)
+ kAhciPort->Ci = 1 << free_slot;
+
+ // 7. Wait for the command to complete (simple spinlock, no need for an object here)
+ while (Yes)
+ {
+ if (!(kAhciPort->Ci & (1 << free_slot)))
+ {
+ break; // Command has completed
+ }
+ else if (kAhciPort->Is & (1 << 30))
+ {
+ return; // Error in task file
+ }
+ }
+
+ kSlotIsUsed = No;
+}
+
+Kernel::Void drv_std_write(Kernel::UInt64 Lba, Kernel::Char* Buf, Kernel::SizeT SectorSz, Kernel::SizeT Size)
+{
+ STATIC Kernel::Boolean kSlotIsUsed = No;
+
+ Kernel::LockDelegate<kMaxAhciPoll> lock(&kSlotIsUsed);
+
+ if (lock.HasTimedOut())
+ return;
+
+ kSlotIsUsed = Yes;
+
+ Kernel::Int64 free_slot = 0;
+
+ // Prepare command header.
+
+ HbaCmdHeader* cmd_header = (HbaCmdHeader*)kAhciPort->Clb;
+ cmd_header += free_slot;
+
+ // Read operation/set entries count.
+
+ cmd_header->Write = Yes;
+ cmd_header->Prdtl = (Kernel::UInt16)((Size - 1) >> 4) + 1; // PRDT entries count
+
+ // Prepare command table.
+
+ HbaCmdTbl* cmd_tbl = (HbaCmdTbl*)cmd_header->Ctba;
+ Kernel::rt_set_memory(cmd_tbl, 0, sizeof(HbaCmdTbl));
+
+ Kernel::UInt64 size = Size * kAHCISectorSize;
+ Kernel::Int64 index_byte = 0L;
+
+ for (index_byte = 0; index_byte < cmd_header->Prdtl - 1; index_byte++)
+ {
+ cmd_tbl->prdtEntries[index_byte].Dba = (Kernel::UInt32)(Kernel::UIntPtr)Buf;
+ cmd_tbl->prdtEntries[index_byte].Dbc = (8 * 1024) - 1; // 8KB Buf size
+ cmd_tbl->prdtEntries[index_byte].InterruptBit = 1; // Interrupt on completion
+
+ Size -= 8 * 1024;
+ Buf += 4 * 1024; // Move the Buf pointer forward
+ }
+
+ // Last PRDT entry
+ cmd_tbl->prdtEntries[index_byte].Dba = (Kernel::UInt32)(Kernel::UIntPtr)Buf;
+ cmd_tbl->prdtEntries[index_byte].Dbc = Size - 1; // Byte count left
+ cmd_tbl->prdtEntries[index_byte].InterruptBit = 1;
+
+ // 5. Prepare the command FIS (Frame Information Structure)
+ FisRegH2D* cmd_fis = (FisRegH2D*)(&cmd_tbl->Cfis);
+ Kernel::rt_set_memory(cmd_fis, 0, sizeof(FisRegH2D));
+
+ cmd_fis->FisType = kFISTypeRegH2D;
+ cmd_fis->CmdOrCtrl = 1; // Command
+ cmd_fis->Command = kAHCICmdReadDmaEx;
+
+ cmd_fis->Lba0 = (Kernel::UInt8)Lba;
+ cmd_fis->Lba1 = (Kernel::UInt8)(Lba >> 8);
+ cmd_fis->Lba2 = (Kernel::UInt8)(Lba >> 16);
+ cmd_fis->Device = 1 << 6; // LBA mode
+
+ cmd_fis->Lba3 = (Kernel::UInt8)(Lba >> 24);
+ cmd_fis->Lba4 = (Kernel::UInt8)(Lba >> 32);
+ cmd_fis->Lba5 = (Kernel::UInt8)(Lba >> 40);
+
+ cmd_fis->CountLow = Size & 0xFF;
+ cmd_fis->CountHigh = (Size >> 8) & 0xFF;
+
+ // 6. Issue the command by writing to the kAhciPort's command issue register (CI)
+ kAhciPort->Ci = 1 << free_slot;
+
+ // 7. Wait for the command to complete (simple spinlock, no need for an object here)
+ while (Yes)
+ {
+ if (!(kAhciPort->Ci & (1 << free_slot)))
+ {
+ break; // Command has completed
+ }
+ else if (kAhciPort->Is & (1 << 30))
+ {
+ return; // Error in task file
+ }
+ }
+
+ kSlotIsUsed = No;
+}
+
+/***
+ @brief Gets the number of sectors inside the drive.
+ @return Sector size in bytes.
+ */
+Kernel::SizeT drv_get_sector_count()
+{
+ return 0;
+}
+
+/// @brief Get the drive size.
+Kernel::SizeT drv_get_size()
+{
+ return 0;
+}
+#endif // __AHCI__
diff --git a/dev/ZKAKit/HALKit/AMD64/Storage/ATA-DMA.cc b/dev/ZKAKit/HALKit/AMD64/Storage/ATA-DMA.cc
new file mode 100644
index 00000000..e7393469
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/Storage/ATA-DMA.cc
@@ -0,0 +1,38 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+/**
+ * @file ATA-DMA.cc
+ * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com)
+ * @brief ATA driver (DMA mode).
+ * @version 0.1
+ * @date 2024-02-02
+ *
+ * @copyright Copyright (c) ZKA Web Services Co
+ *
+ */
+
+#include <StorageKit/PRDT.h>
+
+#include <Modules/ATA/ATA.h>
+#include <ArchKit/ArchKit.h>
+
+using namespace Kernel;
+
+EXTERN_C Int32 kPRDTTransferStatus;
+STATIC PRDT kPRDT;
+
+#ifdef __ATA_DMA__
+
+#ifdef __ATA_PIO__
+#error !!! You cant have both PIO and DMA enabled! !!!
+#endif /* ifdef __ATA_PIO__ */
+
+#ifdef __AHCI__
+#error !!! You cant have both ATA and AHCI enabled! !!!
+#endif /* ifdef __AHCI__ */
+
+#endif /* ifdef __ATA_DMA__ */
diff --git a/dev/ZKAKit/HALKit/AMD64/Storage/ATA-PIO.cc b/dev/ZKAKit/HALKit/AMD64/Storage/ATA-PIO.cc
new file mode 100644
index 00000000..6dce33b9
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AMD64/Storage/ATA-PIO.cc
@@ -0,0 +1,197 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+/**
+ * @file ATA-PIO.cc
+ * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com)
+ * @brief ATA driver (PIO mode).
+ * @version 0.1
+ * @date 2024-02-02
+ *
+ * @copyright Copyright (c) ZKA Web Services Co
+ *
+ */
+
+#include <Modules/ATA/ATA.h>
+#include <ArchKit/ArchKit.h>
+
+#ifdef __ATA_PIO__
+
+using namespace Kernel;
+using namespace Kernel::HAL;
+
+/// bugs: 0
+
+#define kATADataLen 256
+
+STATIC Boolean kATADetected = false;
+STATIC Int32 kATADeviceType = kATADeviceCount;
+STATIC Char kATAData[kATADataLen] = {0};
+
+Boolean drv_std_wait_io(UInt16 IO)
+{
+ for (int i = 0; i < 400; i++)
+ In8(IO + ATA_REG_STATUS);
+
+ATAWaitForIO_Retry:
+ auto statRdy = In8(IO + ATA_REG_STATUS);
+
+ if ((statRdy & ATA_SR_BSY))
+ goto ATAWaitForIO_Retry;
+
+ATAWaitForIO_Retry2:
+ statRdy = In8(IO + ATA_REG_STATUS);
+
+ if (statRdy & ATA_SR_ERR)
+ return false;
+
+ if (!(statRdy & ATA_SR_DRDY))
+ goto ATAWaitForIO_Retry2;
+
+ return true;
+}
+
+Void drv_std_select(UInt16 Bus)
+{
+ if (Bus == ATA_PRIMARY_IO)
+ Out8(Bus + ATA_REG_HDDEVSEL, ATA_PRIMARY_SEL);
+ else
+ Out8(Bus + ATA_REG_HDDEVSEL, ATA_SECONDARY_SEL);
+}
+
+Boolean drv_std_init(UInt16 Bus, UInt8 Drive, UInt16& OutBus, UInt8& OutMaster)
+{
+ UInt16 IO = Bus;
+
+ drv_std_select(IO);
+
+ATAInit_Retry:
+ // Bus init, NEIN bit.
+ Out8(IO + ATA_REG_NEIN, 1);
+
+ // identify until it's good
+
+ auto statRdy = In8(IO + ATA_REG_STATUS);
+
+ if (statRdy & ATA_SR_ERR)
+ {
+ kcout << "ERROR: ATA DRIVE RETURNED ERROR BIT! ABORTING...\r";
+
+ return false;
+ }
+
+ if ((statRdy & ATA_SR_BSY))
+ {
+ kcout << "Retrying...";
+ goto ATAInit_Retry;
+ }
+
+ Out8(IO + ATA_REG_COMMAND, ATA_CMD_IDENTIFY);
+
+ /// fetch serial info
+ /// model, speed, number of sectors...
+
+ drv_std_wait_io(IO);
+
+ for (SizeT indexData = 0ul; indexData < kATADataLen; ++indexData)
+ {
+ kATAData[indexData] = In16(IO + ATA_REG_DATA);
+ }
+
+ OutBus = (Bus == ATA_PRIMARY_IO) ? ATA_PRIMARY_IO : ATA_SECONDARY_IO;
+
+ OutMaster = (Bus == ATA_PRIMARY_IO) ? ATA_MASTER : ATA_SLAVE;
+
+ kcout << "INFO: INITIALIZED ATA DRIVE!\r";
+
+ return true;
+}
+
+Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size)
+{
+ Lba /= SectorSz;
+
+ UInt8 Command = ((!Master) ? 0xE0 : 0xF0);
+
+ drv_std_wait_io(IO);
+ drv_std_select(IO);
+
+ Out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F));
+
+ Out8(IO + ATA_REG_SEC_COUNT0, ((Size + SectorSz) / SectorSz));
+
+ Out8(IO + ATA_REG_LBA0, (Lba) & 0xFF);
+ Out8(IO + ATA_REG_LBA1, (Lba) >> 8);
+ Out8(IO + ATA_REG_LBA2, (Lba) >> 16);
+ Out8(IO + ATA_REG_LBA3, (Lba) >> 24);
+
+ Out8(IO + ATA_REG_COMMAND, ATA_CMD_READ_PIO);
+
+ drv_std_wait_io(IO);
+
+ for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff)
+ {
+ drv_std_wait_io(IO);
+ Buf[IndexOff] = In16(IO + ATA_REG_DATA);
+ drv_std_wait_io(IO);
+ }
+
+ drv_std_wait_io(IO);
+}
+
+Void drv_std_write(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size)
+{
+ Lba /= SectorSz;
+
+ UInt8 Command = ((!Master) ? 0xE0 : 0xF0);
+
+ drv_std_wait_io(IO);
+ drv_std_select(IO);
+
+ Out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F));
+
+ Out8(IO + ATA_REG_SEC_COUNT0, ((Size + (SectorSz)) / SectorSz));
+
+ Out8(IO + ATA_REG_LBA0, (Lba) & 0xFF);
+ Out8(IO + ATA_REG_LBA1, (Lba) >> 8);
+ Out8(IO + ATA_REG_LBA2, (Lba) >> 16);
+ Out8(IO + ATA_REG_LBA3, (Lba) >> 24);
+
+ Out8(IO + ATA_REG_COMMAND, ATA_CMD_WRITE_PIO);
+
+ drv_std_wait_io(IO);
+
+ for (SizeT IndexOff = 0; IndexOff < Size; ++IndexOff)
+ {
+ drv_std_wait_io(IO);
+ Out16(IO + ATA_REG_DATA, Buf[IndexOff]);
+ drv_std_wait_io(IO);
+ }
+
+ drv_std_wait_io(IO);
+}
+
+/// @brief is ATA detected?
+Boolean drv_std_detected(Void)
+{
+ return kATADetected;
+}
+
+/***
+ @brief Getter, gets the number of sectors inside the drive.
+*/
+Kernel::SizeT drv_get_sector_count()
+{
+ return (kATAData[61] << 16) | kATAData[60];
+}
+
+/// @brief Get the drive size.
+Kernel::SizeT drv_get_size()
+{
+ return drv_get_sector_count() * kATASectorSize;
+}
+
+#endif /* ifdef __ATA_PIO__ */
diff --git a/dev/ZKAKit/HALKit/ARM64/.gitkeep b/dev/ZKAKit/HALKit/ARM64/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/.gitkeep
diff --git a/dev/ZKAKit/HALKit/ARM64/APM/.gitkeep b/dev/ZKAKit/HALKit/ARM64/APM/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/APM/.gitkeep
diff --git a/dev/ZKAKit/HALKit/ARM64/APM/APM.cc b/dev/ZKAKit/HALKit/ARM64/APM/APM.cc
new file mode 100644
index 00000000..b5e26dc9
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/APM/APM.cc
@@ -0,0 +1,37 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <Modules/APM/APM.h>
+#include <KernelKit/LPC.h>
+
+using namespace Kernel;
+
+/// @brief Send a APM command into it's own IO 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, =0x84000009\n"
+ "hvc #0\n");
+
+ return kErrorSuccess;
+ }
+ case kAPMPowerCommandShutdown: {
+ asm volatile(
+ "ldr x0, =0x84000008\n"
+ "hvc #0\n");
+
+ return kErrorSuccess;
+ }
+ default:
+ return kErrorInvalidData;
+ }
+}
diff --git a/dev/ZKAKit/HALKit/ARM64/HalACPIFactoryInterface.cc b/dev/ZKAKit/HALKit/ARM64/HalACPIFactoryInterface.cc
new file mode 100644
index 00000000..db3b688b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/HalACPIFactoryInterface.cc
@@ -0,0 +1,31 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <NewKit/String.h>
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/Heap.h>
+#include <Modules/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/ZKAKit/HALKit/ARM64/HalCoreMPScheduler.cc b/dev/ZKAKit/HALKit/ARM64/HalCoreMPScheduler.cc
new file mode 100644
index 00000000..f30871fa
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/HalCoreMPScheduler.cc
@@ -0,0 +1,19 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <Modules/ACPI/ACPIFactoryInterface.h>
+#include <KernelKit/UserProcessScheduler.h>
+
+using namespace Kernel;
+
+EXTERN_C Void mp_do_task_switch(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr stack_frame);
+
+EXTERN_C Bool mp_register_process(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr stack_frame)
+{
+ mp_do_task_switch(image, stack_ptr, stack_frame);
+
+ return Yes;
+}
diff --git a/dev/ZKAKit/HALKit/ARM64/HalDebugOutput.cc b/dev/ZKAKit/HALKit/ARM64/HalDebugOutput.cc
new file mode 100644
index 00000000..c98d87a5
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/HalDebugOutput.cc
@@ -0,0 +1,81 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#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__
+ }
+
+ 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/ZKAKit/HALKit/ARM64/HalKernelMain.cc b/dev/ZKAKit/HALKit/ARM64/HalKernelMain.cc
new file mode 100644
index 00000000..95b3a9b0
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/HalKernelMain.cc
@@ -0,0 +1,46 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <Modules/FB/FB.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 <Modules/ACPI/ACPIFactoryInterface.h>
+#include <NetworkKit/IPC.h>
+#include <CFKit/Property.h>
+
+Kernel::Void hal_real_init(Kernel::Void) noexcept;
+EXTERN_C Kernel::Void ke_dll_entrypoint(Kernel::Void);
+
+EXTERN_C void hal_init_platform(
+ Kernel::HEL::HANDOVER_INFO_HEADER* HandoverHeader)
+{
+
+ /************************************************** */
+ /* INITIALIZE AND VALIDATE HEADER. */
+ /************************************************** */
+
+ kHandoverHeader = HandoverHeader;
+
+ if (kHandoverHeader->f_Magic != kHandoverMagic &&
+ kHandoverHeader->f_Version != kHandoverVersion)
+ {
+ return;
+ }
+
+ /************************************** */
+ /* INITIALIZE BIT MAP. */
+ /************************************** */
+
+ while (Yes)
+ {
+ }
+}
diff --git a/dev/ZKAKit/HALKit/ARM64/HalPageInternal.S b/dev/ZKAKit/HALKit/ARM64/HalPageInternal.S
new file mode 100644
index 00000000..8fcf40ff
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/HalPageInternal.S
@@ -0,0 +1,5 @@
+.text
+
+hal_flush_tlb:
+ tlbi
+ ret
diff --git a/dev/ZKAKit/HALKit/ARM64/HalPagingMgr.cc b/dev/ZKAKit/HALKit/ARM64/HalPagingMgr.cc
new file mode 100644
index 00000000..52dd738b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/HalPagingMgr.cc
@@ -0,0 +1,86 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+ 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/ZKAKit/HALKit/ARM64/HalSchedulerCoreARM64.cc b/dev/ZKAKit/HALKit/ARM64/HalSchedulerCoreARM64.cc
new file mode 100644
index 00000000..49927c84
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/HalSchedulerCoreARM64.cc
@@ -0,0 +1,40 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <KernelKit/UserProcessScheduler.h>
+
+namespace Kernel
+{
+ EXTERN_C Void __zka_pure_call(void)
+ {
+ UserProcessScheduler::The().CurrentProcess().Leak().Crash();
+ }
+
+ bool hal_check_stack(HAL::StackFramePtr stackPtr)
+ {
+ if (!stackPtr)
+ return No;
+
+ if (stackPtr->BP == 0 || stackPtr->SP == 0)
+ return No;
+
+ return Yes;
+ }
+
+ /// @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_UNUSUED(stack);
+ }
+} // namespace Kernel
diff --git a/dev/ZKAKit/HALKit/ARM64/HalTimer.cc b/dev/ZKAKit/HALKit/ARM64/HalTimer.cc
new file mode 100644
index 00000000..18b15bf3
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/HalTimer.cc
@@ -0,0 +1,14 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+ File: HalTimer.cc
+ Purpose: HAL timer
+
+ Revision History:
+
+ 07/07/24: Added file (amlel)
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
diff --git a/dev/ZKAKit/HALKit/ARM64/MBCI/.keepme b/dev/ZKAKit/HALKit/ARM64/MBCI/.keepme
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/MBCI/.keepme
diff --git a/dev/ZKAKit/HALKit/ARM64/Paging.h b/dev/ZKAKit/HALKit/ARM64/Paging.h
new file mode 100644
index 00000000..74b4bab0
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/Paging.h
@@ -0,0 +1,120 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#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/ZKAKit/HALKit/ARM64/Processor.h b/dev/ZKAKit/HALKit/ARM64/Processor.h
new file mode 100644
index 00000000..793761e2
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/Processor.h
@@ -0,0 +1,75 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#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()
+ {
+ while (Yes)
+ {
+ }
+ }
+
+} // 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/ZKAKit/HALKit/ARM64/ReadMe.md b/dev/ZKAKit/HALKit/ARM64/ReadMe.md
new file mode 100644
index 00000000..c51229f2
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/ReadMe.md
@@ -0,0 +1,3 @@
+# ARM64 Hardware Abstraction Layer
+
+- Supported Firmware: CoreBoot/EDK/OpenMobileBoot
diff --git a/dev/ZKAKit/HALKit/ARM64/Storage/.gitkeep b/dev/ZKAKit/HALKit/ARM64/Storage/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/Storage/.gitkeep
diff --git a/dev/ZKAKit/HALKit/ARM64/Storage/HalFlash.cc b/dev/ZKAKit/HALKit/ARM64/Storage/HalFlash.cc
new file mode 100644
index 00000000..24999070
--- /dev/null
+++ b/dev/ZKAKit/HALKit/ARM64/Storage/HalFlash.cc
@@ -0,0 +1,66 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <NewKit/Defines.h>
+#include <ArchKit/ArchKit.h>
+
+/// @file Flash.cc
+/// @brief Flash memory builtin.
+
+#ifdef __USE_MBCI_FLASH__
+
+#define cMaxFlash (4U)
+
+namespace Kernel
+{
+ /// /:\\BRIDGE\\FLSH\\1
+ constexpr auto cFlashBridgeMagic = "FLSH";
+ constexpr auto cFlashBridgeRevision = 1;
+
+ STATIC const Boolean kFlashEnabled = No;
+ STATIC SizeT kFlashSize[cMaxFlash] = {};
+ STATIC SizeT kFlashSectorSz[cMaxFlash] = {};
+
+ /// @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 sector count.
+ /// @return drive sector count.
+ SizeT drv_get_sector_count(Int32 slot)
+ {
+ if (slot > cMaxFlash)
+ return 0;
+
+ return kFlashSectorSz[slot];
+ }
+
+ /// @brief get device size.
+ /// @return drive size
+ SizeT drv_get_size(Int32 slot)
+ {
+ if (slot > cMaxFlash)
+ return 0;
+
+ return kFlashSize[slot];
+ }
+
+ /// @brief Enable flash memory at slot.
+ STATIC Void drv_enable_flash(Int32 arg)
+ {
+ kcout << "Enabled FLSH hardware.\r";
+ }
+
+ /// @brief Disable flash memory at slot.
+ STATIC Void drv_disable_flash(Int32 arg)
+ {
+ kcout << "Disabled FLSH hardware.\r";
+ }
+} // namespace Kernel
+
+#endif // if __USE_MBCI_FLASH__ (Bridge)
diff --git a/dev/ZKAKit/HALKit/AXP/CR.s b/dev/ZKAKit/HALKit/AXP/CR.s
new file mode 100644
index 00000000..4d68257d
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AXP/CR.s
@@ -0,0 +1,11 @@
+.globl read_lr1
+.globl read_lr0
+
+.section .text
+ read_lr0:
+ movq %r30, %cr3
+ ret
+
+ hal_read_cr0:
+ movq %r30, %cr0
+ ret \ No newline at end of file
diff --git a/dev/ZKAKit/HALKit/AXP/CoreInterruptHandlerDEC.cpp b/dev/ZKAKit/HALKit/AXP/CoreInterruptHandlerDEC.cpp
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AXP/CoreInterruptHandlerDEC.cpp
diff --git a/dev/ZKAKit/HALKit/AXP/CoreSyscallHandlerDEC.cpp b/dev/ZKAKit/HALKit/AXP/CoreSyscallHandlerDEC.cpp
new file mode 100644
index 00000000..c164dce0
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AXP/CoreSyscallHandlerDEC.cpp
@@ -0,0 +1,24 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.h>
+#include <HALKit/AXP/Processor.h>
+
+/// @brief Internal call for syscall, to work with C++.
+/// @param stack
+/// @return nothing.
+EXTERN_C void rt_syscall_handle(Kernel::HAL::StackFrame* stack)
+{
+ if (stack->Rcx <= (kSyscalls.Count() - 1))
+ {
+ kcout << "syscall: enter.\r";
+
+ if (kSyscalls[stack->Rcx].Leak().Leak().fHooked)
+ (kSyscalls[stack->Rcx].Leak().Leak().fProc)(stack);
+
+ kcout << "syscall: exit.\r";
+ }
+}
diff --git a/dev/ZKAKit/HALKit/AXP/HAL.s b/dev/ZKAKit/HALKit/AXP/HAL.s
new file mode 100644
index 00000000..0178527f
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AXP/HAL.s
@@ -0,0 +1,13 @@
+.globl rt_wait_400ns
+
+.section .text
+rt_wait_400ns:
+ jmp .L
+.L:
+ jmp .L2
+ wtint ;; wait for interrupt
+.L2:
+
+ ret
+
+
diff --git a/dev/ZKAKit/HALKit/AXP/Processor.h b/dev/ZKAKit/HALKit/AXP/Processor.h
new file mode 100644
index 00000000..cdb39054
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AXP/Processor.h
@@ -0,0 +1,7 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#pragma once
diff --git a/dev/ZKAKit/HALKit/AXP/README b/dev/ZKAKit/HALKit/AXP/README
new file mode 100644
index 00000000..91e7b134
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AXP/README
@@ -0,0 +1 @@
+This is for DEC Alpha.
diff --git a/dev/ZKAKit/HALKit/AXP/README.TXT b/dev/ZKAKit/HALKit/AXP/README.TXT
new file mode 100644
index 00000000..11e138f9
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AXP/README.TXT
@@ -0,0 +1 @@
+An toy HAL to test the Kernel portability.
diff --git a/dev/ZKAKit/HALKit/AXP/SYSCALL.s b/dev/ZKAKit/HALKit/AXP/SYSCALL.s
new file mode 100644
index 00000000..19cab808
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AXP/SYSCALL.s
@@ -0,0 +1,10 @@
+.section .text
+system_handle_user_call:
+ .cfi_startproc
+
+ push %r0
+ jmp %r1
+ mov %r30, %r2
+
+ .cfi_endproc
+ retsys \ No newline at end of file
diff --git a/dev/ZKAKit/HALKit/AXP/VM.s b/dev/ZKAKit/HALKit/AXP/VM.s
new file mode 100644
index 00000000..7024086b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/AXP/VM.s
@@ -0,0 +1,5 @@
+.global hal_flush_tlb
+
+.section .text
+hal_flush_tlb:
+ swppal \ No newline at end of file
diff --git a/dev/ZKAKit/HALKit/POWER/.gitkeep b/dev/ZKAKit/HALKit/POWER/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/POWER/.gitkeep
diff --git a/dev/ZKAKit/HALKit/POWER/APM/.gitkeep b/dev/ZKAKit/HALKit/POWER/APM/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/POWER/APM/.gitkeep
diff --git a/dev/ZKAKit/HALKit/POWER/HalContextSwitchPowerPC.s b/dev/ZKAKit/HALKit/POWER/HalContextSwitchPowerPC.s
new file mode 100644
index 00000000..380dc375
--- /dev/null
+++ b/dev/ZKAKit/HALKit/POWER/HalContextSwitchPowerPC.s
@@ -0,0 +1,30 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+.align 4
+.type name, @function
+.text
+.globl mp_do_task_switch
+
+/* r3 (3) = assigner stack, r4 (4) = assignee stack */
+mp_do_task_switch:
+ lwz 0(%4), 0(%3)
+ lwz 4(%4), 4(%3)
+ lwz 8(%4), 8(%3)
+ lwz 12(%4), 12(%3)
+ lwz 14(%4), 14(%3)
+ lwz 18(%4), 18(%3)
+ lwz 22(%4), 22(%3)
+ lwz 24(%4), 24(%3)
+ lwz 28(%4), 28(%3)
+ lwz 32(%4), 32(%3)
+ lwz 34(%4), 34(%3)
+ lwz 38(%4), 38(%3)
+
+ /* also change exception level */
+
+ /* we are done here, the assignee should start executing code now. */
+ blr
diff --git a/dev/ZKAKit/HALKit/POWER/HalHart.cc b/dev/ZKAKit/HALKit/POWER/HalHart.cc
new file mode 100644
index 00000000..ff5025d5
--- /dev/null
+++ b/dev/ZKAKit/HALKit/POWER/HalHart.cc
@@ -0,0 +1,25 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <HALKit/POWER/Processor.h>
+#include <KernelKit/DebugOutput.h>
+#include <HALKit/POWER/Hart.h>
+
+using namespace Kernel;
+
+/// @brief wakes up thread.
+/// wakes up thread from hang.
+void mp_wakeup_thread(HAL::StackFramePtr stack)
+{
+ ZKA_UNUSED(stack);
+}
+
+/// @brief makes thread sleep.
+/// hooks and hangs thread to prevent code from executing.
+void mp_hang_thread(HAL::StackFramePtr stack)
+{
+ ZKA_UNUSED(stack);
+}
diff --git a/dev/ZKAKit/HALKit/POWER/HalSerialPort.cc b/dev/ZKAKit/HALKit/POWER/HalSerialPort.cc
new file mode 100644
index 00000000..29bc8fa5
--- /dev/null
+++ b/dev/ZKAKit/HALKit/POWER/HalSerialPort.cc
@@ -0,0 +1,27 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <HALKit/POWER/Processor.h>
+#include <KernelKit/DebugOutput.h>
+
+using namespace Kernel;
+
+/// @brief Writes to COM1.
+/// @param bytes
+void ke_io_write(const Char* bytes)
+{
+ if (!bytes)
+ return;
+
+ SizeT index = 0;
+ SizeT len = rt_string_len(bytes, 255);
+
+ while (index < len)
+ {
+ // TODO
+ ++index;
+ }
+}
diff --git a/dev/ZKAKit/HALKit/POWER/HalStartSequence.s b/dev/ZKAKit/HALKit/POWER/HalStartSequence.s
new file mode 100644
index 00000000..b9f1bee8
--- /dev/null
+++ b/dev/ZKAKit/HALKit/POWER/HalStartSequence.s
@@ -0,0 +1,14 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+.globl __ImageStart
+.extern hal_init_platform
+.align 4
+.text
+
+__ImageStart:
+ bl hal_init_platform
+ blr
diff --git a/dev/ZKAKit/HALKit/POWER/HalThread.cc b/dev/ZKAKit/HALKit/POWER/HalThread.cc
new file mode 100644
index 00000000..7a0d5ccb
--- /dev/null
+++ b/dev/ZKAKit/HALKit/POWER/HalThread.cc
@@ -0,0 +1,8 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <HALKit/POWER/Processor.h>
+#include <KernelKit/DebugOutput.h>
diff --git a/dev/ZKAKit/HALKit/POWER/HalVirtualMemory.cc b/dev/ZKAKit/HALKit/POWER/HalVirtualMemory.cc
new file mode 100644
index 00000000..e21d7074
--- /dev/null
+++ b/dev/ZKAKit/HALKit/POWER/HalVirtualMemory.cc
@@ -0,0 +1,49 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <HALKit/POWER/Processor.h>
+#include <KernelKit/DebugOutput.h>
+#include <HALKit/POWER/MMU.h>
+
+/// @note Refer to SoC documentation.
+
+using namespace Kernel;
+
+EXTERN_C Void hal_write_tlb(UInt32 mas0, UInt32 mas1, UInt32 mas2, UInt32 mas3, UInt32 mas7)
+{
+ hal_mtspr(MAS0, mas0);
+ hal_mtspr(MAS1, mas1);
+ hal_mtspr(MAS2, mas2);
+ hal_mtspr(MAS3, mas3);
+ hal_mtspr(MAS7, mas7);
+
+ hal_flush_tlb();
+}
+
+EXTERN_C Bool hal_set_tlb(UInt8 tlb, UInt32 epn, UInt64 rpn, UInt8 perms, UInt8 wimge, UInt8 ts, UInt8 esel, UInt8 tsize, UInt8 iprot)
+{
+ if ((hal_mfspr(SPRN_MMUCFG) & MMUCFG_MAVN) == MMUCFG_MAVN_V1 && (tsize & 1))
+ {
+ // this MMU does not allow odd tsize values
+ return false;
+ }
+
+ UInt32 mas0 = FSL_BOOKE_MAS0(tlb, esel, 0);
+ UInt32 mas1 = FSL_BOOKE_MAS1(1, iprot, 0, ts, tsize);
+ UInt32 mas2 = FSL_BOOKE_MAS2(epn, wimge);
+ UInt32 mas3 = FSL_BOOKE_MAS3(rpn, 0, perms);
+ UInt32 mas7 = FSL_BOOKE_MAS7(rpn);
+
+ hal_write_tlb(mas0, mas1, mas2, mas3, mas7);
+
+ return true;
+}
+
+/// @brief Flush TLB
+EXTERN_C void hal_flush_tlb()
+{
+ asm volatile("isync;tlbwe;msync;isync");
+}
diff --git a/dev/ZKAKit/HALKit/POWER/Hart.h b/dev/ZKAKit/HALKit/POWER/Hart.h
new file mode 100644
index 00000000..2e40784e
--- /dev/null
+++ b/dev/ZKAKit/HALKit/POWER/Hart.h
@@ -0,0 +1,36 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+ File: Hart.h
+ Purpose: POWER hardware threads.
+
+ Revision History:
+
+ 14/04/24: Added file (amlel)
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.h>
+
+struct HAL_HARDWARE_THREAD;
+
+/// @brief hardware thread indentification type.
+typedef Kernel::Int32 PPCHartType;
+
+/// @brief Hardware thread information structure.
+typedef struct HAL_HARDWARE_THREAD
+{
+ Kernel::UIntPtr fStartAddress;
+ Kernel::UInt8 fPrivleged : 1;
+ Kernel::UInt32 fPagkMMFlags;
+ PPCHartType fIdentNumber;
+} HAL_HARDWARE_THREAD;
+
+/// @brief Set PC to specific hart.
+/// @param hart the hart
+/// @param epc the pc.
+/// @return
+EXTERN_C Kernel::Void hal_set_pc_to_hart(HAL_HARDWARE_THREAD* hart, Kernel::VoidPtr epc);
diff --git a/dev/ZKAKit/HALKit/POWER/MBCI/.gitkeep b/dev/ZKAKit/HALKit/POWER/MBCI/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/POWER/MBCI/.gitkeep
diff --git a/dev/ZKAKit/HALKit/POWER/MBCI/HalMBCIHost.cc b/dev/ZKAKit/HALKit/POWER/MBCI/HalMBCIHost.cc
new file mode 100644
index 00000000..7a0d5ccb
--- /dev/null
+++ b/dev/ZKAKit/HALKit/POWER/MBCI/HalMBCIHost.cc
@@ -0,0 +1,8 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+------------------------------------------- */
+
+#include <HALKit/POWER/Processor.h>
+#include <KernelKit/DebugOutput.h>
diff --git a/dev/ZKAKit/HALKit/POWER/Processor.h b/dev/ZKAKit/HALKit/POWER/Processor.h
new file mode 100644
index 00000000..4df55fc4
--- /dev/null
+++ b/dev/ZKAKit/HALKit/POWER/Processor.h
@@ -0,0 +1,62 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+ Purpose: POWER processor header.
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.h>
+#include <NewKit/Utils.h>
+
+#define NoOp() asm volatile("mr 0, 0")
+#define kHalPPCAlignment __attribute__((aligned(4)))
+
+namespace Kernel::HAL
+{
+ typedef UIntPtr Reg;
+
+ /// @brief Stack frame (as retrieved from assembly.)
+ 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()
+ {
+ while (true)
+ {
+ NoOp(); // no oop.
+ }
+ }
+
+ inline void rt_cli()
+ {
+ NoOp(); // no oop
+ }
+} // namespace Kernel::HAL
+
+EXTERN_C Kernel::Void int_handle_math(Kernel::UIntPtr sp);
+EXTERN_C Kernel::Void int_handle_pf(Kernel::UIntPtr sp);
+
+/// @brief Set TLB.
+Kernel::Bool hal_set_tlb(Kernel::UInt8 tlb, Kernel::UInt32 epn, Kernel::UInt64 rpn, Kernel::UInt8 perms, Kernel::UInt8 wimge, Kernel::UInt8 ts, Kernel::UInt8 esel, Kernel::UInt8 tsize, Kernel::UInt8 iprot);
+
+/// @brief Write TLB.
+Kernel::Void hal_write_tlb(Kernel::UInt32 mas0, Kernel::UInt32 mas1, Kernel::UInt32 mas2, Kernel::UInt32 mas3, Kernel::UInt32 mas7);
+
+/// @brief Flush TLB.
+EXTERN_C Kernel::Void hal_flush_tlb();
diff --git a/dev/ZKAKit/HALKit/POWER/ReadMe.md b/dev/ZKAKit/HALKit/POWER/ReadMe.md
new file mode 100644
index 00000000..a9751581
--- /dev/null
+++ b/dev/ZKAKit/HALKit/POWER/ReadMe.md
@@ -0,0 +1,4 @@
+POWER Hardware Abstraction Layer
+
+- Supported CPU: POWER
+- Supported Firmware: CoreBoot \ No newline at end of file
diff --git a/dev/ZKAKit/HALKit/RISCV/.keep b/dev/ZKAKit/HALKit/RISCV/.keep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/RISCV/.keep
diff --git a/dev/ZKAKit/HALKit/RISCV/APM/.gitkeep b/dev/ZKAKit/HALKit/RISCV/APM/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/RISCV/APM/.gitkeep
diff --git a/dev/ZKAKit/HALKit/RISCV/Hart.h b/dev/ZKAKit/HALKit/RISCV/Hart.h
new file mode 100644
index 00000000..b5e842c0
--- /dev/null
+++ b/dev/ZKAKit/HALKit/RISCV/Hart.h
@@ -0,0 +1,24 @@
+/* -------------------------------------------
+
+ Copyright ZKA Web Services Co.
+
+ File: Hart.h
+ Purpose: RISC-V hardware threads.
+
+ Revision History:
+
+ 30/01/24: Added file (amlel)
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.h>
+
+typedef Kernel::Int32 Rv64HartType;
+
+/// @brief Set PC to specific hart.
+/// @param hart the hart
+/// @param epc the pc.
+/// @return
+EXTERN_C Kernel::Void hal_set_pc_to_hart(Rv64HartType hart, Kernel::VoidPtr epc);
diff --git a/dev/ZKAKit/HALKit/RISCV/ReadMe.md b/dev/ZKAKit/HALKit/RISCV/ReadMe.md
new file mode 100644
index 00000000..b099aa31
--- /dev/null
+++ b/dev/ZKAKit/HALKit/RISCV/ReadMe.md
@@ -0,0 +1,4 @@
+RISCV64 Hardware Abstraction Layer
+
+- Supported CPU: RISCV64
+- Supported Firmware: CoreBoot \ No newline at end of file
diff --git a/dev/ZKAKit/HALKit/RISCV/Storage/.gitkeep b/dev/ZKAKit/HALKit/RISCV/Storage/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/RISCV/Storage/.gitkeep
diff --git a/dev/ZKAKit/HALKit/X86S/.gitkeep b/dev/ZKAKit/HALKit/X86S/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/X86S/.gitkeep
diff --git a/dev/ZKAKit/HALKit/X86S/ACPI/.gitkeep b/dev/ZKAKit/HALKit/X86S/ACPI/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/X86S/ACPI/.gitkeep
diff --git a/dev/ZKAKit/HALKit/X86S/Storage/.gitkeep b/dev/ZKAKit/HALKit/X86S/Storage/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/dev/ZKAKit/HALKit/X86S/Storage/.gitkeep