summaryrefslogtreecommitdiffhomepage
path: root/Kernel/HALKit/AMD64
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/HALKit/AMD64')
-rw-r--r--Kernel/HALKit/AMD64/CPUID.hxx81
-rw-r--r--Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx123
-rw-r--r--Kernel/HALKit/AMD64/HalControlRegister.s40
-rw-r--r--Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp101
-rw-r--r--Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp124
-rw-r--r--Kernel/HALKit/AMD64/HalDebugOutput.cxx145
-rw-r--r--Kernel/HALKit/AMD64/HalDebugPort.cxx40
-rw-r--r--Kernel/HALKit/AMD64/HalDescriptorLoader.cpp90
-rw-r--r--Kernel/HALKit/AMD64/HalHardwareMP.cpp34
-rw-r--r--Kernel/HALKit/AMD64/HalInstallTIB.asm22
-rw-r--r--Kernel/HALKit/AMD64/HalInterruptAPI.asm222
-rw-r--r--Kernel/HALKit/AMD64/HalKernelMain.cxx85
-rw-r--r--Kernel/HALKit/AMD64/HalKernelMouse.cxx190
-rw-r--r--Kernel/HALKit/AMD64/HalNewBoot.asm41
-rw-r--r--Kernel/HALKit/AMD64/HalPageAlloc.cpp103
-rw-r--r--Kernel/HALKit/AMD64/HalPageAlloc.hpp88
-rw-r--r--Kernel/HALKit/AMD64/HalProcessor.cpp97
-rw-r--r--Kernel/HALKit/AMD64/HalRoutines.s12
-rw-r--r--Kernel/HALKit/AMD64/HalSMPCore.cxx30
-rw-r--r--Kernel/HALKit/AMD64/HalSMPCoreManager.asm26
-rw-r--r--Kernel/HALKit/AMD64/Hypervisor.hpp26
-rw-r--r--Kernel/HALKit/AMD64/MBCI/.gitkeep0
-rw-r--r--Kernel/HALKit/AMD64/PCI/Database.cxx11
-rw-r--r--Kernel/HALKit/AMD64/PCI/Device.cxx130
-rw-r--r--Kernel/HALKit/AMD64/PCI/Dma.cxx82
-rw-r--r--Kernel/HALKit/AMD64/PCI/Express.cxx11
-rw-r--r--Kernel/HALKit/AMD64/PCI/IO.cxx7
-rw-r--r--Kernel/HALKit/AMD64/PCI/Iterator.cxx44
-rw-r--r--Kernel/HALKit/AMD64/PCI/PCI.cxx7
-rw-r--r--Kernel/HALKit/AMD64/Processor.hpp212
-rw-r--r--Kernel/HALKit/AMD64/Storage/AHCI.cxx67
-rw-r--r--Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx38
-rw-r--r--Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx192
33 files changed, 2521 insertions, 0 deletions
diff --git a/Kernel/HALKit/AMD64/CPUID.hxx b/Kernel/HALKit/AMD64/CPUID.hxx
new file mode 100644
index 00000000..0e570148
--- /dev/null
+++ b/Kernel/HALKit/AMD64/CPUID.hxx
@@ -0,0 +1,81 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+ File: CPUID.hxx
+ Purpose: CPUID flags.
+
+ Revision History:
+
+ 30/01/24: Added file (amlel)
+
+------------------------------------------- */
+
+#pragma once
+
+enum
+{
+ CPU_FEATURE_ECX_SSE3 = 1 << 0,
+ CPU_FEATURE_ECX_PCLMUL = 1 << 1,
+ CPU_FEATURE_ECX_DTES64 = 1 << 2,
+ CPU_FEATURE_ECX_MONITOR = 1 << 3,
+ CPU_FEATURE_ECX_DS_CPL = 1 << 4,
+ CPU_FEATURE_ECX_VMX = 1 << 5,
+ CPU_FEATURE_ECX_SMX = 1 << 6,
+ CPU_FEATURE_ECX_EST = 1 << 7,
+ CPU_FEATURE_ECX_TM2 = 1 << 8,
+ CPU_FEATURE_ECX_SSSE3 = 1 << 9,
+ CPU_FEATURE_ECX_CID = 1 << 10,
+ CPU_FEATURE_ECX_SDBG = 1 << 11,
+ CPU_FEATURE_ECX_FMA = 1 << 12,
+ CPU_FEATURE_ECX_CX16 = 1 << 13,
+ CPU_FEATURE_ECX_XTPR = 1 << 14,
+ CPU_FEATURE_ECX_PDCM = 1 << 15,
+ CPU_FEATURE_ECX_PCID = 1 << 17,
+ CPU_FEATURE_ECX_DCA = 1 << 18,
+ CPU_FEATURE_ECX_SSE4_1 = 1 << 19,
+ CPU_FEATURE_ECX_SSE4_2 = 1 << 20,
+ CPU_FEATURE_ECX_X2APIC = 1 << 21,
+ CPU_FEATURE_ECX_MOVBE = 1 << 22,
+ CPU_FEATURE_ECX_POP3C = 1 << 23,
+ CPU_FEATURE_ECX_TSC = 1 << 24,
+ CPU_FEATURE_ECX_AES = 1 << 25,
+ CPU_FEATURE_ECX_XSAVE = 1 << 26,
+ CPU_FEATURE_ECX_OSXSAVE = 1 << 27,
+ CPU_FEATURE_ECX_AVX = 1 << 28,
+ CPU_FEATURE_ECX_F16C = 1 << 29,
+ CPU_FEATURE_ECX_RDRAND = 1 << 30,
+ CPU_FEATURE_ECX_HYPERVISOR = 1 << 31,
+ CPU_FEATURE_EDX_FPU = 1 << 0,
+ CPU_FEATURE_EDX_VME = 1 << 1,
+ CPU_FEATURE_EDX_DE = 1 << 2,
+ CPU_FEATURE_EDX_PSE = 1 << 3,
+ CPU_FEATURE_EDX_TSC = 1 << 4,
+ CPU_FEATURE_EDX_MSR = 1 << 5,
+ CPU_FEATURE_EDX_PAE = 1 << 6,
+ CPU_FEATURE_EDX_MCE = 1 << 7,
+ CPU_FEATURE_EDX_CX8 = 1 << 8,
+ CPU_FEATURE_EDX_APIC = 1 << 9,
+ CPU_FEATURE_EDX_SEP = 1 << 11,
+ CPU_FEATURE_EDX_MTRR = 1 << 12,
+ CPU_FEATURE_EDX_PGE = 1 << 13,
+ CPU_FEATURE_EDX_MCA = 1 << 14,
+ CPU_FEATURE_EDX_CMOV = 1 << 15,
+ CPU_FEATURE_EDX_PAT = 1 << 16,
+ CPU_FEATURE_EDX_PSE36 = 1 << 17,
+ CPU_FEATURE_EDX_PSN = 1 << 18,
+ CPU_FEATURE_EDX_CLFLUSH = 1 << 19,
+ CPU_FEATURE_EDX_DS = 1 << 21,
+ CPU_FEATURE_EDX_ACPI = 1 << 22,
+ CPU_FEATURE_EDX_MMX = 1 << 23,
+ CPU_FEATURE_EDX_FXSR = 1 << 24,
+ CPU_FEATURE_EDX_SSE = 1 << 25,
+ CPU_FEATURE_EDX_SSE2 = 1 << 26,
+ CPU_FEATURE_EDX_SS = 1 << 27,
+ CPU_FEATURE_EDX_HTT = 1 << 28,
+ CPU_FEATURE_EDX_TM = 1 << 29,
+ CPU_FEATURE_EDX_IA64 = 1 << 30,
+ CPU_FEATURE_EDX_PBE = 1 << 31
+};
+
+typedef int CPU_FEATURE; \ No newline at end of file
diff --git a/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx b/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx
new file mode 100644
index 00000000..3609165f
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalACPIFactoryInterface.cxx
@@ -0,0 +1,123 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <Builtins/ACPI/ACPIFactoryInterface.hxx>
+#include <HALKit/AMD64/Processor.hpp>
+#include <NewKit/String.hpp>
+
+namespace NewOS
+{
+
+ /// Custom to the virtual machine, you'll need to parse the MADT instead.
+
+ void rt_shutdown_acpi_qemu_20(void)
+ {
+ HAL::Out16(0xb004, 0x2000);
+ }
+
+ void rt_shutdown_acpi_qemu_30_plus(void)
+ {
+ HAL::Out16(0x604, 0x2000);
+ }
+
+ void rt_shutdown_acpi_virtualbox(void)
+ {
+ HAL::Out16(0x4004, 0x3400);
+ }
+
+ /// You have to parse the MADT!
+
+ ACPIFactoryInterface::ACPIFactoryInterface(voidPtr rsdPtr)
+ : fRsdp(rsdPtr), fEntries(0)
+ {
+ }
+
+ Void ACPIFactoryInterface::Shutdown()
+ {
+#ifdef __DEBUG__
+ rt_shutdown_acpi_qemu_30_plus();
+#else
+
+#endif
+ }
+
+ /// @brief Reboot (shutdowns on qemu.)
+ /// @return
+ Void ACPIFactoryInterface::Reboot()
+ {
+#ifdef __DEBUG__
+ rt_shutdown_acpi_qemu_30_plus();
+#else
+
+#endif
+ }
+
+ /// @brief Finds a descriptor table inside ACPI XSDT.
+ ErrorOr<voidPtr> ACPIFactoryInterface::Find(const char* signature)
+ {
+ MUST_PASS(fRsdp);
+
+ if (!signature)
+ return ErrorOr<voidPtr>{-2};
+
+ if (*signature == 0)
+ return ErrorOr<voidPtr>{-3};
+
+ RSDP* rsdPtr = reinterpret_cast<RSDP*>(this->fRsdp);
+
+ if (rsdPtr->Revision <= 1)
+ {
+ return ErrorOr<voidPtr>{-4};
+ }
+
+ SDT* xsdt = (SDT*)(rsdPtr->XsdtAddress >> (rsdPtr->XsdtAddress & 0xFFF));
+
+ SizeT num = xsdt->Length + sizeof(SDT) / 8;
+
+ this->fEntries = num;
+
+ kcout << "ACPI: Number of entries: " << number(num) << endl;
+ kcout << "ACPI: Address of XSDT: " << hex_number((UIntPtr)xsdt) << endl;
+
+ constexpr short ACPI_SIGNATURE_LENGTH = 4;
+
+ for (Size index = 0; index < num; ++index)
+ {
+ SDT* sdt = (SDT*)*((UInt64*)(UInt64)xsdt + sizeof(SDT) + (index * 8));
+
+ for (int signature_index = 0; signature_index < 4; signature_index++)
+ {
+ if (sdt->Signature[signature_index] != signature[signature_index])
+ break;
+
+ if (signature_index == 3)
+ return ErrorOr<voidPtr>(reinterpret_cast<voidPtr>((SDT*)sdt));
+ }
+ }
+
+ return ErrorOr<voidPtr>{-1};
+ }
+
+ /***
+ @brief check SDT header
+ @param checksum the header to checksum
+ @param len the length of it.
+*/
+ bool ACPIFactoryInterface::Checksum(const char* checksum, SSizeT len)
+ {
+ if (len == 0)
+ return -1;
+
+ char chr = 0;
+
+ for (int index = 0; index < len; ++index)
+ {
+ chr += checksum[index];
+ }
+
+ return chr == 0;
+ }
+} // namespace NewOS
diff --git a/Kernel/HALKit/AMD64/HalControlRegister.s b/Kernel/HALKit/AMD64/HalControlRegister.s
new file mode 100644
index 00000000..7798ea09
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalControlRegister.s
@@ -0,0 +1,40 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+.globl hal_write_cr3
+.globl hal_write_cr0
+.globl hal_read_cr2
+.globl hal_read_cr3
+.globl hal_read_cr0
+.globl hal_flush_tlb
+
+.text
+
+hal_flush_tlb:
+ call hal_read_cr3
+ mov %rcx, %rax
+ call hal_write_cr3
+ ret
+
+hal_read_cr3:
+ movq %cr3, %rax
+ ret
+
+hal_read_cr0:
+ movq %rax, %cr0
+ ret
+
+hal_read_cr2:
+ movq %rax, %cr2
+ ret
+
+hal_write_cr3:
+ movq %cr3, %rdi
+ ret
+
+hal_write_cr0:
+ movq %cr0, %rdi
+ ret
diff --git a/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp b/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp
new file mode 100644
index 00000000..1f2e21e2
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cpp
@@ -0,0 +1,101 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hpp>
+#include <KernelKit/ProcessScheduler.hpp>
+#include <NewKit/String.hpp>
+
+/// @brief Handle GPF fault.
+/// @param rsp
+EXTERN_C void idt_handle_gpf(NewOS::UIntPtr rsp)
+{
+ MUST_PASS(NewOS::ProcessScheduler::Shared().Leak().GetCurrent());
+
+ NewOS::kcout << "New OS: Stack Pointer: "
+ << NewOS::StringBuilder::FromInt("rsp{%}", rsp);
+
+ NewOS::kcout
+ << "New OS: General Protection Fault, caused by "
+ << NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().GetName();
+
+ NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash();
+}
+
+/// @brief Handle the scheduler interrupt, raised from the HPET timer.
+/// @param rsp
+EXTERN_C void idt_handle_scheduler(NewOS::UIntPtr rsp)
+{
+ NewOS::kcout << NewOS::StringBuilder::FromInt("rsp{%}", rsp);
+
+ NewOS::kcout
+ << "New OS: Will be scheduled back later "
+ << NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().GetName()
+ << NewOS::end_line();
+
+ /// schedule another process.
+ if (!NewOS::ProcessHelper::StartScheduling())
+ {
+ NewOS::kcout << "New OS: Continue schedule this process...\r";
+ }
+}
+
+/// @brief Handle page fault.
+/// @param rsp
+EXTERN_C void idt_handle_pf(NewOS::UIntPtr rsp)
+{
+ MUST_PASS(NewOS::ProcessScheduler::Shared().Leak().GetCurrent());
+ NewOS::kcout << NewOS::StringBuilder::FromInt("rsp{%}", rsp);
+
+ NewOS::kcout
+ << "New OS: Segmentation Fault, caused by "
+ << NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().GetName();
+
+ NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash();
+}
+
+/// @brief Handle math fault.
+/// @param rsp
+EXTERN_C void idt_handle_math(NewOS::UIntPtr rsp)
+{
+ MUST_PASS(NewOS::ProcessScheduler::Shared().Leak().GetCurrent());
+ NewOS::kcout << NewOS::StringBuilder::FromInt("rsp{%}", rsp);
+
+ NewOS::kcout
+ << "New OS: Math error, caused by "
+ << NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().GetName();
+
+ NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash();
+}
+
+/// @brief Handle any generic fault.
+/// @param rsp
+EXTERN_C void idt_handle_generic(NewOS::UIntPtr rsp)
+{
+ MUST_PASS(NewOS::ProcessScheduler::Shared().Leak().GetCurrent());
+ NewOS::kcout << NewOS::StringBuilder::FromInt("sp{%}", rsp);
+
+ NewOS::kcout
+ << "New OS: Execution error, caused by "
+ << NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().GetName();
+
+ NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash();
+}
+
+/// @brief Handle #UD fault.
+/// @param rsp
+EXTERN_C void idt_handle_ud(NewOS::UIntPtr rsp)
+{
+ MUST_PASS(NewOS::ProcessScheduler::Shared().Leak().GetCurrent());
+
+ NewOS::kcout << "New OS: Stack Pointer: "
+ << NewOS::StringBuilder::FromInt("rsp{%}", rsp);
+
+ NewOS::kcout
+ << "New OS: Invalid interrupt, caused by "
+ << NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().GetName();
+
+ NewOS::ProcessScheduler::Shared().Leak().GetCurrent().Leak().Crash();
+}
diff --git a/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp b/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp
new file mode 100644
index 00000000..2129d790
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalCoreMultiProcessingAMD64.cpp
@@ -0,0 +1,124 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <Builtins/ACPI/ACPIFactoryInterface.hxx>
+#include <HALKit/AMD64/Processor.hpp>
+#include <NewKit/KernelCheck.hpp>
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+//! NOTE: fGSI stands 'Field Global System Interrupt'
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+namespace NewOS::HAL
+{
+ constexpr Int32 kThreadAPIC = 0;
+ constexpr Int32 kThreadLAPIC = 1;
+ constexpr Int32 kThreadIOAPIC = 2;
+ constexpr Int32 kThreadAPIC64 = 3;
+ constexpr Int32 kThreadBoot = 4;
+
+ /*
+ *
+ * this is used to store info about the current running thread
+ * we use this struct to determine if we can use it, or mark it as used or on
+ * sleep.
+ *
+ */
+
+ struct ProcessorInfoAMD64 final
+ {
+ Int32 ThreadType;
+ UIntPtr JumpAddress;
+
+ struct
+ {
+ UInt32 Code;
+ UInt32 Data;
+ UInt32 BSS;
+ } Selector;
+ };
+
+ STATIC voidPtr kApicMadt = nullptr;
+ STATIC const char* kApicSignature = "APIC";
+
+ /// @brief Multiple APIC descriptor table.
+ struct MadtType final : public SDT
+ {
+ struct MadtAddress final
+ {
+ UInt32 fFlags; // 1 = Dual Legacy PICs installed
+ UInt32 fPhysicalAddress;
+
+ Char fType;
+ Char fRecLen; // record length
+ } Madt[];
+ };
+
+ struct MadtProcessorLocalApic final
+ {
+ Char fProcessorId;
+ Char fApicId;
+ UInt32 fFlags;
+ };
+
+ struct MadtIOApic final
+ {
+ Char fApicId;
+ Char fReserved;
+ UInt32 fAddress;
+ UInt32 fSystemInterruptBase;
+ };
+
+ struct MadtInterruptSource final
+ {
+ Char fBusSource;
+ Char fIrqSource;
+ UInt32 fGSI;
+ UInt16 fFlags;
+ };
+
+ struct MadtInterruptNmi final
+ {
+ Char fNmiSource;
+ Char fReserved;
+ UInt16 fFlags;
+ UInt32 fGSI;
+ };
+
+ struct MadtLocalApicAddressOverride final
+ {
+ UInt16 fResvered;
+ UIntPtr fAddress;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////////////
+
+ STATIC MadtType* kApicInfoBlock = nullptr;
+
+ ///////////////////////////////////////////////////////////////////////////////////////
+
+ void hal_system_get_cores(voidPtr rsdPtr)
+ {
+ kcout << "New OS: Constructing ACPIFactoryInterface...\r";
+
+ auto acpi = ACPIFactoryInterface(rsdPtr);
+ kApicMadt = acpi.Find(kApicSignature).Leak().Leak();
+
+ if (kApicMadt)
+ {
+ kcout << "New OS: Successfuly fetched the MADT!\r";
+ kApicInfoBlock = (MadtType*)kApicMadt;
+ }
+ else
+ {
+ MUST_PASS(false);
+ }
+ }
+} // namespace NewOS::HAL
+
+///////////////////////////////////////////////////////////////////////////////////////
diff --git a/Kernel/HALKit/AMD64/HalDebugOutput.cxx b/Kernel/HALKit/AMD64/HalDebugOutput.cxx
new file mode 100644
index 00000000..3227be1f
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalDebugOutput.cxx
@@ -0,0 +1,145 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hpp>
+#include <KernelKit/DebugOutput.hpp>
+#include <KernelKit/Framebuffer.hpp>
+#include <NewKit/Utils.hpp>
+
+namespace NewOS
+{
+ enum CommStatus
+ {
+ kStateInvalid,
+ kStateReady = 0xCF,
+ kStateTransmit = 0xFC,
+ kStateCnt = 3
+ };
+
+ namespace Detail
+ {
+ constexpr short PORT = 0x3F8;
+
+ static int kState = kStateInvalid;
+
+ /// @brief Init COM1.
+ /// @return
+ bool 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::serial_init();
+
+ if (!bytes || Detail::kState != kStateReady)
+ return;
+ if (*bytes == 0)
+ return;
+
+ Detail::kState = kStateTransmit;
+
+ SizeT index = 0;
+ SizeT len = rt_string_len(bytes, 256);
+
+ 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::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::Shared() noexcept
+ {
+ static TerminalDevice* out = nullptr;
+
+ if (!out)
+ out = new TerminalDevice(NewOS::ke_io_write, NewOS::ke_io_read);
+
+ return *out;
+ }
+
+} // namespace NewOS
diff --git a/Kernel/HALKit/AMD64/HalDebugPort.cxx b/Kernel/HALKit/AMD64/HalDebugPort.cxx
new file mode 100644
index 00000000..6d7a03f5
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalDebugPort.cxx
@@ -0,0 +1,40 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+//! @file DebuggerPort.cxx
+//! @brief UART debug via packets.
+
+#include <ArchKit/ArchKit.hpp>
+#include <KernelKit/DebugOutput.hpp>
+
+// after that we have start of additional data.
+
+namespace NewOS
+{
+ 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 NewOS
diff --git a/Kernel/HALKit/AMD64/HalDescriptorLoader.cpp b/Kernel/HALKit/AMD64/HalDescriptorLoader.cpp
new file mode 100644
index 00000000..689c1742
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalDescriptorLoader.cpp
@@ -0,0 +1,90 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hpp>
+
+namespace NewOS::HAL
+{
+ namespace Detail
+ {
+ STATIC RegisterGDT kRegGdt;
+ STATIC HAL::Register64 kRegIdt;
+
+ STATIC ::NewOS::Detail::AMD64::InterruptDescriptorAMD64
+ kInterruptVectorTable[kKernelIdtSize];
+
+ STATIC Void RemapPIC(Void) noexcept
+ {
+ // Remap PIC.
+ HAL::Out8(0x20, 0x10 | 0x01);
+ HAL::Out8(0xA0, 0x10 | 0x01);
+
+ HAL::Out8(0x21, 32);
+ HAL::Out8(0xA1, 40);
+
+ HAL::Out8(0x21, 4);
+ HAL::Out8(0xA1, 2);
+
+ HAL::Out8(0x21, 0x01);
+ HAL::Out8(0xA1, 0x01);
+
+ HAL::Out8(0x21, 0x00);
+ HAL::Out8(0xA1, 0x00);
+ }
+ } // namespace Detail
+
+ /// @brief Loads the provided Global Descriptor Table.
+ /// @param gdt
+ /// @return
+ Void GDTLoader::Load(RegisterGDT& gdt)
+ {
+ MUST_PASS(gdt.Base != 0);
+
+ Detail::kRegGdt.Base = gdt.Base;
+ Detail::kRegGdt.Limit = gdt.Limit;
+
+ hal_load_gdt(Detail::kRegGdt);
+ }
+
+ Void IDTLoader::Load(Register64& idt)
+ {
+ volatile ::NewOS::UIntPtr** baseIdt = (volatile ::NewOS::UIntPtr**)idt.Base;
+
+ MUST_PASS(baseIdt);
+
+ Detail::RemapPIC();
+
+ for (UInt16 i = 0; i < kKernelIdtSize; ++i)
+ {
+ MUST_PASS(baseIdt[i]);
+
+ Detail::kInterruptVectorTable[i].Selector = kGdtCodeSelector;
+ Detail::kInterruptVectorTable[i].Ist = 0x0;
+ Detail::kInterruptVectorTable[i].TypeAttributes = kInterruptGate;
+ Detail::kInterruptVectorTable[i].OffsetLow = ((UIntPtr)baseIdt[i] & 0xFFFF);
+ Detail::kInterruptVectorTable[i].OffsetMid = (((UIntPtr)baseIdt[i] >> 16) & 0xFFFF);
+ Detail::kInterruptVectorTable[i].OffsetHigh =
+ (((UIntPtr)baseIdt[i] >> 32) & 0xFFFFFFFF);
+ Detail::kInterruptVectorTable[i].Zero = 0x0;
+ }
+
+ Detail::kRegIdt.Base = reinterpret_cast<UIntPtr>(Detail::kInterruptVectorTable);
+ Detail::kRegIdt.Limit = sizeof(::NewOS::Detail::AMD64::InterruptDescriptorAMD64) *
+ (kKernelIdtSize - 1);
+
+ hal_load_idt(Detail::kRegIdt);
+ }
+
+ void GDTLoader::Load(Ref<RegisterGDT>& gdt)
+ {
+ GDTLoader::Load(gdt.Leak());
+ }
+
+ void IDTLoader::Load(Ref<Register64>& idt)
+ {
+ IDTLoader::Load(idt.Leak());
+ }
+} // namespace NewOS::HAL
diff --git a/Kernel/HALKit/AMD64/HalHardwareMP.cpp b/Kernel/HALKit/AMD64/HalHardwareMP.cpp
new file mode 100644
index 00000000..2ebf45fd
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalHardwareMP.cpp
@@ -0,0 +1,34 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hpp>
+
+// bugs = 0
+
+namespace NewOS
+{
+ /// @brief wakes up thread.
+ /// wakes up thread from hang.
+ void rt_wakeup_thread(HAL::StackFrame* stack)
+ {
+ HAL::rt_cli();
+
+ stack->Rcx = 0;
+
+ HAL::rt_sti();
+ }
+
+ /// @brief makes thread sleep.
+ /// hooks and hangs thread to prevent code from executing.
+ void rt_hang_thread(HAL::StackFrame* stack)
+ {
+ HAL::rt_cli();
+
+ stack->Rcx = 1;
+
+ HAL::rt_sti();
+ }
+} // namespace NewOS
diff --git a/Kernel/HALKit/AMD64/HalInstallTIB.asm b/Kernel/HALKit/AMD64/HalInstallTIB.asm
new file mode 100644
index 00000000..a5f3ef73
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalInstallTIB.asm
@@ -0,0 +1,22 @@
+;; /*
+;; * ========================================================
+;; *
+;; * NewOS
+;; * Copyright SoftwareLabs, all rights reserved.
+;; *
+;; * ========================================================
+;; */
+
+[bits 64]
+
+[global rt_install_tib]
+
+;; changed: rs, fs
+;; expected: rcx, rdx
+
+rt_install_tib:
+ mov rcx, gs ;; TIB -> Thread Information Block
+ mov rdx, fs ;; PIB -> Process Information Block
+ ret
+
+;; //////////////////////////////////////////////////// ;;
diff --git a/Kernel/HALKit/AMD64/HalInterruptAPI.asm b/Kernel/HALKit/AMD64/HalInterruptAPI.asm
new file mode 100644
index 00000000..e4063388
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalInterruptAPI.asm
@@ -0,0 +1,222 @@
+;; /*
+;; * ---------------------------------------------------
+;; *
+;; * Copyright SoftwareLabs, all rights reserved.
+;; *
+;; * File: HalInterruptAPI.asm
+;; * Purpose: Interrupt routing, redirect raw interrupts into their handlers.
+;; *
+;; * ---------------------------------------------------
+;; */
+
+[bits 64]
+
+%define kInterruptId 0x21
+
+%macro IntExp 1
+global __HCR_INT_%1
+__HCR_INT_%1:
+ cld
+
+ iretq
+%endmacro
+
+%macro IntNormal 1
+global __HCR_INT_%1
+__HCR_INT_%1:
+ cld
+
+ iretq
+%endmacro
+
+; This file handles the core interrupt table
+; Last edited 31/01/24
+
+global _ke_power_on_self_test
+global ke_handle_irq
+global kInterruptVectorTable
+
+extern _hal_handle_mouse
+extern idt_handle_gpf
+extern idt_handle_pf
+extern ke_io_write
+extern idt_handle_ud
+
+section .text
+
+IntNormal 0
+IntNormal 1
+
+IntNormal 2
+
+IntNormal 3
+IntNormal 4
+IntNormal 5
+
+;; Invalid opcode interrupt
+__HCR_INT_6:
+ cli
+
+ push rax
+
+ mov rcx, rsp
+ call idt_handle_ud
+
+ pop rax
+
+ sti
+ iretq
+
+IntNormal 7
+IntExp 8
+IntNormal 9
+IntExp 10
+IntExp 11
+
+IntExp 12
+
+__HCR_INT_13:
+ cli
+
+ push rax
+
+ mov rcx, rsp
+ call idt_handle_gpf
+
+ pop rax
+
+ sti
+ iretq
+
+__HCR_INT_14:
+ cli
+
+ push rax
+
+ mov rcx, rsp
+ call idt_handle_pf
+
+ pop rax
+
+ sti
+ iretq
+
+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
+
+IntNormal 32
+
+IntNormal 33
+
+IntNormal 34
+IntNormal 35
+IntNormal 36
+IntNormal 37
+IntNormal 38
+IntNormal 39
+IntNormal 40
+IntNormal 41
+IntNormal 42
+IntNormal 43
+
+__HCR_INT_44:
+ cli
+
+ ;; TODO: CoreEvents dispatch routine.
+
+ push rax
+ call _hal_handle_mouse
+ pop rax
+
+ sti
+ iretq
+
+IntNormal 45
+IntNormal 46
+IntNormal 47
+IntNormal 48
+IntNormal 49
+
+__HCR_INT_50:
+ cli
+
+ ;; todo handle system calls.
+
+ sti
+ iretq
+
+IntNormal 51
+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
+
+;; this one is doing a POST for us.
+;; testing interrupts.
+_ke_power_on_self_test:
+ int 0x32
+ int 0x32
+ int 0x32
+ int 0x32
+
+ ret
+
+[global hal_load_gdt]
+
+hal_load_gdt:
+ lgdt [rcx]
+ push 0x08
+ lea rax, [rel rt_reload_segments]
+ push rax
+ retfq
+rt_reload_segments:
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+ ret
+
+global hal_load_idt
+
+hal_load_idt:
+ lidt [rcx]
+ sti
+ ret
+
+section .data
+
+kInterruptVectorTable:
+ %assign i 0
+ %rep 256
+ dq __HCR_INT_%+i
+ %assign i i+1
+ %endrep
diff --git a/Kernel/HALKit/AMD64/HalKernelMain.cxx b/Kernel/HALKit/AMD64/HalKernelMain.cxx
new file mode 100644
index 00000000..e2533241
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalKernelMain.cxx
@@ -0,0 +1,85 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hpp>
+#include <Builtins/Toolbox/Toolbox.hxx>
+#include <FirmwareKit/Handover.hxx>
+#include <KernelKit/FileManager.hpp>
+#include <KernelKit/Framebuffer.hpp>
+#include <KernelKit/KernelHeap.hpp>
+#include <KernelKit/PEFCodeManager.hxx>
+#include <KernelKit/ProcessScheduler.hpp>
+#include <KernelKit/UserHeap.hpp>
+#include <NewKit/Json.hpp>
+
+EXTERN_C NewOS::VoidPtr kInterruptVectorTable[];
+EXTERN_C void AppMain();
+
+namespace NewOS::HAL
+{
+ /// @brief Gets the system cores using the MADT.
+ /// @param rsdPtr the RSD PTR.
+ extern void hal_system_get_cores(NewOS::voidPtr rsdPtr);
+} // namespace NewOS::HAL
+
+EXTERN_C void hal_init_platform(
+ NewOS::HEL::HandoverInformationHeader* HandoverHeader)
+{
+ kHandoverHeader = HandoverHeader;
+
+ if (kHandoverHeader->f_Magic != kHandoverMagic &&
+ kHandoverHeader->f_Version != kHandoverVersion)
+ {
+ return;
+ }
+
+ /// Setup kernel globals.
+ kKernelVirtualSize = HandoverHeader->f_VirtualSize;
+ kKernelVirtualStart = reinterpret_cast<NewOS::VoidPtr>(
+ reinterpret_cast<NewOS::UIntPtr>(HandoverHeader->f_VirtualStart) + kVirtualAddressStartOffset);
+
+ kKernelPhysicalStart = HandoverHeader->f_PhysicalStart;
+
+ STATIC NewOS::HAL::Detail::NewOSGDT GDT = {
+ {0, 0, 0, 0x00, 0x00, 0}, // null entry
+ {0, 0, 0, 0x9a, 0xaf, 0}, // kernel code
+ {0, 0, 0, 0x92, 0xaf, 0}, // kernel data
+ {0, 0, 0, 0x00, 0x00, 0}, // null entry
+ {0, 0, 0, 0x9a, 0xaf, 0}, // user code
+ {0, 0, 0, 0x92, 0xaf, 0}, // user data
+ };
+
+ NewOS::HAL::RegisterGDT gdtBase;
+
+ gdtBase.Base = reinterpret_cast<NewOS::UIntPtr>(&GDT);
+ gdtBase.Limit = sizeof(NewOS::HAL::Detail::NewOSGDT) - 1;
+
+ /// Load GDT.
+
+ NewOS::HAL::GDTLoader gdt;
+ gdt.Load(gdtBase);
+
+ /// Load IDT.
+
+ NewOS::HAL::Register64 idtBase;
+ idtBase.Base = (NewOS::UIntPtr)kInterruptVectorTable;
+ idtBase.Limit = 0;
+
+ NewOS::HAL::IDTLoader idt;
+ idt.Load(idtBase);
+
+ /// START POST
+
+ NewOS::HAL::Detail::_ke_power_on_self_test();
+
+ NewOS::HAL::hal_system_get_cores(kHandoverHeader->f_HardwareTables.f_RsdPtr);
+
+ /// END POST
+
+ AppMain();
+
+ NewOS::ke_stop(RUNTIME_CHECK_BOOTSTRAP);
+}
diff --git a/Kernel/HALKit/AMD64/HalKernelMouse.cxx b/Kernel/HALKit/AMD64/HalKernelMouse.cxx
new file mode 100644
index 00000000..926a9d5a
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalKernelMouse.cxx
@@ -0,0 +1,190 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <Builtins/PS2/PS2MouseInterface.hxx>
+#include <Builtins/Toolbox/Toolbox.hxx>
+#include <Builtins/Toolbox/Rsrc/Cursor.rsrc>
+#include <KernelKit/Framebuffer.hpp>
+#include <NewKit/Defines.hpp>
+
+// forward decl.
+EXTERN_C NewOS::Boolean _hal_draw_mouse();
+EXTERN_C NewOS::Void _hal_init_mouse();
+
+STATIC NewOS::Int32 kPrevX = 10;
+STATIC NewOS::Int32 kPrevY = 10;
+STATIC NewOS::Int32 kX = 10;
+STATIC NewOS::Int32 kY = 10;
+STATIC NewOS::Int32 kMouseCycle = 0;
+STATIC NewOS::PS2MouseInterface kMousePS2;
+STATIC NewOS::Char kMousePacket[4] = {};
+STATIC NewOS::Boolean kMousePacketReady = false;
+
+STATIC ToolboxInitRsrc();
+
+#define kPS2Leftbutton 0b00000001
+#define kPS2Middlebutton 0b00000010
+#define kPS2Rightbutton 0b00000100
+#define kPS2XSign 0b00010000
+#define kPS2YSign 0b00100000
+#define kPS2XOverflow 0b01000000
+#define kPS2YOverflow 0b10000000
+
+using namespace NewOS;
+
+Void hal_handle_mouse()
+{
+ NewOS::UInt8 data = HAL::In8(0x60);
+
+ switch (kMouseCycle)
+ {
+ case 0:
+ if (kMousePacketReady)
+ break;
+ if ((data & 0b00001000) == 0)
+ break;
+ kMousePacket[0] = data;
+ kMouseCycle++;
+ break;
+ case 1:
+ if (kMousePacketReady)
+ break;
+ kMousePacket[1] = data;
+ kMouseCycle++;
+ break;
+ case 2:
+ if (kMousePacketReady)
+ break;
+ kMousePacket[2] = data;
+ kMousePacketReady = true;
+ kMouseCycle = 0;
+ break;
+ }
+
+ // Notify PIC controller that we're done with it's interrupt.
+
+ NewOS::HAL::Out8(0x20, 0x20);
+ NewOS::HAL::Out8(0xA0, 0x20);
+}
+
+/// @brief Interrupt handler for the mouse.
+EXTERN_C Void _hal_handle_mouse()
+{
+ hal_handle_mouse();
+}
+
+EXTERN_C Boolean _hal_left_button_pressed()
+{
+ return kMousePacket[0] & kPS2Leftbutton;
+}
+EXTERN_C Boolean _hal_right_button_pressed()
+{
+ return kMousePacket[0] & kPS2Rightbutton;
+}
+EXTERN_C Boolean _hal_middle_button_pressed()
+{
+ return kMousePacket[0] & kPS2Middlebutton;
+}
+
+/// @brief Draws the kernel's mouse.
+EXTERN_C Boolean _hal_draw_mouse()
+{
+ if (!kMousePacketReady)
+ return false;
+
+ bool xNegative, yNegative, xOverflow, yOverflow;
+
+ if (kMousePacket[0] & kPS2XSign)
+ {
+ xNegative = true;
+ }
+ else
+ xNegative = false;
+
+ if (kMousePacket[0] & kPS2YSign)
+ {
+ yNegative = true;
+ }
+ else
+ yNegative = false;
+
+ if (kMousePacket[0] & kPS2XOverflow)
+ {
+ xOverflow = true;
+ }
+ else
+ xOverflow = false;
+
+ if (kMousePacket[0] & kPS2YOverflow)
+ {
+ yOverflow = true;
+ }
+ else
+ yOverflow = false;
+
+ if (!xNegative)
+ {
+ kX += kMousePacket[1];
+ if (xOverflow)
+ {
+ kX += 255;
+ }
+ }
+ else
+ {
+ kMousePacket[1] = 256 - kMousePacket[1];
+ kX -= kMousePacket[1];
+ if (xOverflow)
+ {
+ kX -= 255;
+ }
+ }
+
+ if (!yNegative)
+ {
+ kY -= kMousePacket[2];
+ if (yOverflow)
+ {
+ kY -= 255;
+ }
+ }
+ else
+ {
+ kMousePacket[2] = 256 - kMousePacket[2];
+ kY += kMousePacket[2];
+ if (yOverflow)
+ {
+ kY += 255;
+ }
+ }
+
+ if (kX < 0)
+ kX = 0;
+ if (kX > kHandoverHeader->f_GOP.f_Width - 8)
+ kX = kHandoverHeader->f_GOP.f_Width - 8;
+
+ if (kY < 0)
+ kY = 0;
+ if (kY > kHandoverHeader->f_GOP.f_Height - 16)
+ kY = kHandoverHeader->f_GOP.f_Height - 16;
+
+ /// Draw mouse here.
+
+ kPrevX = kX;
+ kPrevY = kY;
+
+ kMousePacketReady = false;
+ return true;
+}
+
+/// @brief Init kernel mouse.
+EXTERN_C Void _hal_init_mouse()
+{
+ kMousePS2.Init();
+
+ HAL::Out8(0x21, 0b11111001);
+ HAL::Out8(0xA1, 0b11101111);
+}
diff --git a/Kernel/HALKit/AMD64/HalNewBoot.asm b/Kernel/HALKit/AMD64/HalNewBoot.asm
new file mode 100644
index 00000000..7c60d363
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalNewBoot.asm
@@ -0,0 +1,41 @@
+;; /*
+;; * ========================================================
+;; *
+;; * NewOS
+;; * Copyright SoftwareLabs, all rights reserved.
+;; *
+;; * ========================================================
+;; */
+
+[bits 64]
+
+;; Global symbol of this unit
+[global MainLong]
+[global MainUnsupported]
+
+%define kTypeKernel 100
+%define kArchAmd64 122
+%define kHandoverMagic 0xBADCC
+
+section .NewBoot
+
+HandoverMagic: dq kHandoverMagic
+HandoverType: dw kTypeKernel
+HandoverArch: dw kArchAmd64
+;; This NewBootStart points to Main.
+HandoverStart: dq __ImageStart
+
+section .text
+
+global __ImageStart
+global __NewBootJumpProc
+
+extern hal_init_platform
+
+;; Just a simple setup, we'd also need to tell some before
+__NewBootJumpProc:
+__ImageStart:
+ push rcx
+ call hal_init_platform
+ pop rcx
+ ret
diff --git a/Kernel/HALKit/AMD64/HalPageAlloc.cpp b/Kernel/HALKit/AMD64/HalPageAlloc.cpp
new file mode 100644
index 00000000..db2aad73
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalPageAlloc.cpp
@@ -0,0 +1,103 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hpp>
+#include <HALKit/AMD64/HalPageAlloc.hpp>
+#include <NewKit/Defines.hpp>
+#include <NewKit/KernelCheck.hpp>
+
+STATIC NewOS::Boolean kAllocationInProgress = false;
+
+namespace NewOS
+{
+ namespace HAL
+ {
+ namespace Detail
+ {
+ struct VirtualMemoryHeader
+ {
+ UInt32 Magic;
+ Boolean Present;
+ Boolean ReadWrite;
+ Boolean User;
+ SizeT PageSize;
+ };
+
+ struct VirtualMemoryHeaderTraits
+ {
+ /// @brief Get next header.
+ /// @param current
+ /// @return
+ VirtualMemoryHeader* Next(VirtualMemoryHeader* current)
+ {
+ return current + sizeof(PTE) + current->PageSize;
+ }
+
+ /// @brief Get previous header.
+ /// @param current
+ /// @return
+ VirtualMemoryHeader* Prev(VirtualMemoryHeader* current)
+ {
+ return current - sizeof(PTE) - current->PageSize;
+ }
+ };
+ } // namespace Detail
+
+ /// @brief Allocates a new page of memory.
+ /// @param sz the size of it.
+ /// @param rw read/write flag.
+ /// @param user user flag.
+ /// @return the page table of it.
+ STATIC auto hal_try_alloc_new_page(Boolean rw, Boolean user, SizeT size) -> VoidPtr
+ {
+ if (kAllocationInProgress)
+ return nullptr;
+
+ kAllocationInProgress = true;
+
+ constexpr auto cVMTMagic = 0xDEEFD00D;
+
+ ///! fetch from the start.
+ Detail::VirtualMemoryHeader* vmHeader = reinterpret_cast<Detail::VirtualMemoryHeader*>(kKernelVirtualStart);
+ Detail::VirtualMemoryHeaderTraits traits;
+
+ while (vmHeader->Present &&
+ vmHeader->Magic != cVMTMagic)
+ {
+ vmHeader = traits.Next(vmHeader);
+ }
+
+ vmHeader->Magic = cVMTMagic;
+ vmHeader->Present = true;
+ vmHeader->ReadWrite = rw;
+ vmHeader->User = user;
+ vmHeader->PageSize = size;
+
+ kAllocationInProgress = false;
+
+ return reinterpret_cast<VoidPtr>(vmHeader);
+ }
+
+ /// @brief Allocate a new page to be used by the OS.
+ /// @param rw read/write bit.
+ /// @param user user bit.
+ /// @return
+ auto hal_alloc_page(Boolean rw, Boolean user, SizeT size) -> VoidPtr
+ {
+ /// Wait for a ongoing allocation to complete.
+ while (kAllocationInProgress)
+ {
+ ;
+ }
+
+ if (size == 0)
+ ++size;
+
+ /// allocate new page.
+ return hal_try_alloc_new_page(rw, user, size);
+ }
+ } // namespace HAL
+} // namespace NewOS
diff --git a/Kernel/HALKit/AMD64/HalPageAlloc.hpp b/Kernel/HALKit/AMD64/HalPageAlloc.hpp
new file mode 100644
index 00000000..2831c87a
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalPageAlloc.hpp
@@ -0,0 +1,88 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#pragma once
+
+/** ---------------------------------------------------
+
+ * THIS FILE CONTAINS CODE FOR X86_64 PAGING.
+
+------------------------------------------------------- */
+
+#include <NewKit/Defines.hpp>
+
+#ifndef kPTEMax
+#define kPTEMax (0x200)
+#endif //! kPTEMax
+
+#ifndef kPTEAlign
+#define kPTEAlign (0x1000)
+#endif //! kPTEAlign
+
+#ifndef kPTESize
+#define kPTESize (0x1000)
+#endif // !kPTESize
+
+EXTERN_C void hal_flush_tlb();
+EXTERN_C void hal_write_cr3(NewOS::UIntPtr pde);
+EXTERN_C void hal_write_cr0(NewOS::UIntPtr bit);
+
+EXTERN_C NewOS::UIntPtr hal_read_cr0(); // @brief CPU control register.
+EXTERN_C NewOS::UIntPtr hal_read_cr2(); // @brief Fault address.
+EXTERN_C NewOS::UIntPtr hal_read_cr3(); // @brief Page table.
+
+namespace NewOS::HAL
+{
+ struct PACKED PageTable64 final
+ {
+ bool Present : 1;
+ bool Rw : 1;
+ bool User : 1;
+ bool Wt : 1;
+ bool Cache : 1;
+ bool Accessed : 1;
+ NewOS::Int32 Reserved : 6;
+ NewOS::UIntPtr PhysicalAddress : 36;
+ NewOS::Int32 Reserved1 : 15;
+ bool 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 PageDirectory64 final
+ {
+ PageTable64 ALIGN(kPTEAlign) Pte[kPTEMax];
+ };
+
+ VoidPtr hal_alloc_page(Boolean rw, Boolean user, SizeT size);
+} // namespace NewOS::HAL
+
+namespace NewOS
+{
+ typedef HAL::PageTable64 PTE;
+ typedef HAL::PageDirectory64 PDE;
+} // namespace NewOS
diff --git a/Kernel/HALKit/AMD64/HalProcessor.cpp b/Kernel/HALKit/AMD64/HalProcessor.cpp
new file mode 100644
index 00000000..31cee72c
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalProcessor.cpp
@@ -0,0 +1,97 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <HALKit/AMD64/Processor.hpp>
+
+/**
+ * @file Processor.cpp
+ * @brief This file is about processor specific functions (in/out/cli/std...)
+ */
+
+namespace NewOS::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 NewOS::HAL
diff --git a/Kernel/HALKit/AMD64/HalRoutines.s b/Kernel/HALKit/AMD64/HalRoutines.s
new file mode 100644
index 00000000..e4944111
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalRoutines.s
@@ -0,0 +1,12 @@
+.globl hal_load_idt
+.globl hal_load_gdt
+.globl rt_wait_400ns
+.globl rt_get_current_context
+
+.section .text
+rt_wait_400ns:
+ jmp .loop
+ .loop:
+ jmp .loop2
+ .loop2:
+ ret
diff --git a/Kernel/HALKit/AMD64/HalSMPCore.cxx b/Kernel/HALKit/AMD64/HalSMPCore.cxx
new file mode 100644
index 00000000..a1310c4e
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalSMPCore.cxx
@@ -0,0 +1,30 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <KernelKit/ProcessScheduler.hpp>
+
+using namespace NewOS;
+Void ProcessHeader::SetEntrypoint(UIntPtr& imageStart) noexcept
+{
+ if (imageStart == 0)
+ this->Crash();
+
+ this->StackFrame->Rbp = imageStart;
+ this->StackFrame->Rsp = this->StackFrame->Rbp;
+}
+
+namespace NewOS
+{
+ bool rt_check_stack(HAL::StackFramePtr stackPtr)
+ {
+ if (!stackPtr)
+ return false;
+ if (stackPtr->Rbp == 0 || stackPtr->Rsp == 0)
+ return false;
+
+ return true;
+ }
+} // namespace NewOS
diff --git a/Kernel/HALKit/AMD64/HalSMPCoreManager.asm b/Kernel/HALKit/AMD64/HalSMPCoreManager.asm
new file mode 100644
index 00000000..18f80398
--- /dev/null
+++ b/Kernel/HALKit/AMD64/HalSMPCoreManager.asm
@@ -0,0 +1,26 @@
+;; /*
+;; * ========================================================
+;; *
+;; * NewOS
+;; * Copyright SoftwareLabs, all rights reserved.
+;; *
+;; * ========================================================
+;; */
+
+[bits 64]
+
+[global rt_get_current_context]
+[global rt_do_context_switch]
+
+section .text
+
+;; writes to rdx the stackframe inside rcx.
+;; rcx: Stack Pointer
+;; rdx: SMP core address.
+rt_do_context_switch:
+
+ retfq
+
+;; gets the current stack frame.
+rt_get_current_context:
+ retfq
diff --git a/Kernel/HALKit/AMD64/Hypervisor.hpp b/Kernel/HALKit/AMD64/Hypervisor.hpp
new file mode 100644
index 00000000..9beaae42
--- /dev/null
+++ b/Kernel/HALKit/AMD64/Hypervisor.hpp
@@ -0,0 +1,26 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Defines.hpp>
+
+namespace NewOS
+{
+ 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 NewOS
diff --git a/Kernel/HALKit/AMD64/MBCI/.gitkeep b/Kernel/HALKit/AMD64/MBCI/.gitkeep
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/Kernel/HALKit/AMD64/MBCI/.gitkeep
diff --git a/Kernel/HALKit/AMD64/PCI/Database.cxx b/Kernel/HALKit/AMD64/PCI/Database.cxx
new file mode 100644
index 00000000..1c2628d0
--- /dev/null
+++ b/Kernel/HALKit/AMD64/PCI/Database.cxx
@@ -0,0 +1,11 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/Database.hpp>
+
+namespace NewOS
+{
+}
diff --git a/Kernel/HALKit/AMD64/PCI/Device.cxx b/Kernel/HALKit/AMD64/PCI/Device.cxx
new file mode 100644
index 00000000..6f2265ae
--- /dev/null
+++ b/Kernel/HALKit/AMD64/PCI/Device.cxx
@@ -0,0 +1,130 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <ArchKit/ArchKit.hpp>
+#include <KernelKit/PCI/Device.hpp>
+
+NewOS::UInt NewOSPCIReadRaw(NewOS::UInt bar, NewOS::UShort bus, NewOS::UShort dev, NewOS::UShort fun)
+{
+ NewOS::UInt target = 0x80000000 | ((NewOS::UInt)bus << 16) |
+ ((NewOS::UInt)dev << 11) | ((NewOS::UInt)fun << 8) |
+ (bar & 0xFC);
+
+ NewOS::HAL::Out32((NewOS::UShort)NewOS::PCI::PciConfigKind::ConfigAddress,
+ target);
+
+ return NewOS::HAL::In32((NewOS::UShort)NewOS::PCI::PciConfigKind::ConfigData);
+}
+
+void NewOSPCISetCfgTarget(NewOS::UInt bar, NewOS::UShort bus, NewOS::UShort dev, NewOS::UShort fun)
+{
+ NewOS::UInt target = 0x80000000 | ((NewOS::UInt)bus << 16) |
+ ((NewOS::UInt)dev << 11) | ((NewOS::UInt)fun << 8) |
+ (bar & ~3);
+
+ NewOS::HAL::Out32((NewOS::UShort)NewOS::PCI::PciConfigKind::ConfigAddress,
+ target);
+}
+
+namespace NewOS::PCI
+{
+ Device::Device(UShort bus, UShort device, UShort func, UShort bar)
+ : fBus(bus), fDevice(device), fFunction(func), fBar(bar)
+ {
+ }
+
+ Device::~Device()
+ {
+ }
+
+ UInt Device::Read(UInt bar, Size sz)
+ {
+ NewOSPCISetCfgTarget(bar, fBus, fDevice, fFunction);
+
+ if (sz == 4)
+ return HAL::In32((UShort)PciConfigKind::ConfigData + (fBar & 3));
+ if (sz == 2)
+ return HAL::In16((UShort)PciConfigKind::ConfigData + (fBar & 3));
+ if (sz == 1)
+ return HAL::In8((UShort)PciConfigKind::ConfigData + (fBar & 3));
+
+ return 0xFFFF;
+ }
+
+ void Device::Write(UInt bar, UIntPtr data, Size sz)
+ {
+ NewOSPCISetCfgTarget(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)(NewOSPCIReadRaw(0x0 >> 16, fBus, fDevice, fFunction));
+ }
+
+ UShort Device::VendorId()
+ {
+ return (UShort)(NewOSPCIReadRaw(0x0, fBus, fDevice, fFunction) >> 16);
+ }
+
+ UShort Device::InterfaceId()
+ {
+ return (UShort)(NewOSPCIReadRaw(0x0, fBus, fDevice, fFunction) >> 16);
+ }
+
+ UChar Device::Class()
+ {
+ return (UChar)(NewOSPCIReadRaw(0x08, fBus, fDevice, fFunction) >> 24);
+ }
+
+ UChar Device::Subclass()
+ {
+ return (UChar)(NewOSPCIReadRaw(0x08, fBus, fDevice, fFunction) >> 16);
+ }
+
+ UChar Device::ProgIf()
+ {
+ return (UChar)(NewOSPCIReadRaw(0x08, fBus, fDevice, fFunction) >> 8);
+ }
+
+ UChar Device::HeaderType()
+ {
+ return (UChar)(NewOSPCIReadRaw(0xC, fBus, fDevice, fFunction) >> 16);
+ }
+
+ void Device::EnableMmio()
+ {
+ bool enable = Read(0x04, sizeof(UChar)) | (1 << 1);
+ Write(0x04, enable, sizeof(UShort));
+ }
+
+ void Device::BecomeBusMaster()
+ {
+ bool enable = Read(0x04, sizeof(UShort)) | (1 << 2);
+ Write(0x04, enable, sizeof(UShort));
+ }
+
+ 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 NewOS::PCI
diff --git a/Kernel/HALKit/AMD64/PCI/Dma.cxx b/Kernel/HALKit/AMD64/PCI/Dma.cxx
new file mode 100644
index 00000000..aacbafd8
--- /dev/null
+++ b/Kernel/HALKit/AMD64/PCI/Dma.cxx
@@ -0,0 +1,82 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/Dma.hpp>
+
+namespace NewOS
+{
+ 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 NewOS
diff --git a/Kernel/HALKit/AMD64/PCI/Express.cxx b/Kernel/HALKit/AMD64/PCI/Express.cxx
new file mode 100644
index 00000000..4fde7ca2
--- /dev/null
+++ b/Kernel/HALKit/AMD64/PCI/Express.cxx
@@ -0,0 +1,11 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/Express.hpp>
+
+namespace NewOS
+{
+}
diff --git a/Kernel/HALKit/AMD64/PCI/IO.cxx b/Kernel/HALKit/AMD64/PCI/IO.cxx
new file mode 100644
index 00000000..4bd4db4f
--- /dev/null
+++ b/Kernel/HALKit/AMD64/PCI/IO.cxx
@@ -0,0 +1,7 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/IO.hpp>
diff --git a/Kernel/HALKit/AMD64/PCI/Iterator.cxx b/Kernel/HALKit/AMD64/PCI/Iterator.cxx
new file mode 100644
index 00000000..e1af15ad
--- /dev/null
+++ b/Kernel/HALKit/AMD64/PCI/Iterator.cxx
@@ -0,0 +1,44 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/Iterator.hpp>
+
+#define PCI_ITERATOR_FIND_AND_UNWRAP(DEV, SZ) \
+ if (DEV.Leak()) \
+ return DEV.Leak();
+
+namespace NewOS::PCI
+{
+ Iterator::Iterator(const Types::PciDeviceKind& type)
+ {
+ // probe devices.
+ for (int bus = 0; bus < NEWOS_BUS_COUNT; ++bus)
+ {
+ for (int device = 0; device < NEWOS_DEVICE_COUNT; ++device)
+ {
+ for (int function = 0; function < NEWOS_FUNCTION_COUNT; ++function)
+ {
+ Device dev(bus, device, function, 0);
+
+ if (dev.Class() == (UChar)type)
+ {
+ fDevices[bus].Leak().Leak() = dev;
+ }
+ }
+ }
+ }
+ }
+
+ Iterator::~Iterator()
+ {
+ }
+
+ Ref<PCI::Device> Iterator::operator[](const Size& sz)
+ {
+ PCI_ITERATOR_FIND_AND_UNWRAP(fDevices[sz], sz);
+ return {};
+ }
+} // namespace NewOS::PCI
diff --git a/Kernel/HALKit/AMD64/PCI/PCI.cxx b/Kernel/HALKit/AMD64/PCI/PCI.cxx
new file mode 100644
index 00000000..71644f17
--- /dev/null
+++ b/Kernel/HALKit/AMD64/PCI/PCI.cxx
@@ -0,0 +1,7 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+#include <KernelKit/PCI/PCI.hpp>
diff --git a/Kernel/HALKit/AMD64/Processor.hpp b/Kernel/HALKit/AMD64/Processor.hpp
new file mode 100644
index 00000000..69dc1acb
--- /dev/null
+++ b/Kernel/HALKit/AMD64/Processor.hpp
@@ -0,0 +1,212 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+ File: Prcoessor.hxx
+ Purpose: AMD64 processor abstraction.
+
+ Revision History:
+
+ 30/01/24: Added file (amlel)
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NewKit/Array.hpp>
+#include <NewKit/Defines.hpp>
+#include <NewKit/Utils.hpp>
+#include <FirmwareKit/Handover.hxx>
+
+#ifdef kCPUBackendName
+#undef kCPUBackendName
+#endif // ifdef kCPUBackendName
+
+#define kCPUBackendName "AMD64"
+
+#define IsActiveLow(FLG) (FLG & 2)
+#define IsLevelTriggered(FLG) (FLG & 8)
+
+#define kInterruptGate (0x8E)
+#define kTrapGate (0xEF)
+#define kTaskGate (0b10001100)
+#define kGdtCodeSelector (0x08)
+#define kVirtualAddressStartOffset (0x10000000)
+
+namespace NewOS
+{
+ 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; // bits 0..2 holds Interrupt Stack Table offset, rest of bits zero.
+ UInt8 TypeAttributes; // gate type, dpl, and p fields
+ UInt16 OffsetMid; // offset bits 16..31
+ UInt32 OffsetHigh; // offset bits 32..63
+ UInt32 Zero; // reserved
+ };
+ } // namespace Detail::AMD64
+} // namespace NewOS
+
+namespace NewOS::HAL
+{
+ 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();
+
+ struct PACKED Register64 final
+ {
+ UShort Limit;
+ UIntPtr Base;
+ };
+
+ struct PACKED RegisterGDT final
+ {
+ UShort Limit;
+ UIntPtr Base;
+ };
+
+ using RawRegister = UInt64;
+
+ using InterruptId = UShort; /* For each element in the IVT */
+ using interruptTrap = UIntPtr(UIntPtr sp);
+
+ typedef UIntPtr Reg;
+
+ struct PACKED StackFrame final
+ {
+ Reg IntNum, Exception;
+ Reg Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
+ Reg R8, R9, R10, R11, R12, R13, R14, R15;
+ Reg Gs, Fs;
+ };
+
+ 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 hal_system_get_cores(VoidPtr rsdPtr);
+
+ /// @brief Processor specific structures.
+ namespace Detail
+ {
+ EXTERN_C void _ke_power_on_self_test(void);
+
+ /**
+ @brief Global descriptor table entry, either null, code or data.
+*/
+
+ struct PACKED NewOSGDTRecord final
+ {
+ UInt16 Limit0;
+ UInt16 Base0;
+ UInt8 Base1;
+ UInt8 AccessByte;
+ UInt8 Limit1_Flags;
+ UInt8 Base2;
+ };
+
+ struct PACKED ALIGN(0x1000) NewOSGDT final
+ {
+ NewOSGDTRecord Null;
+ NewOSGDTRecord KernCode;
+ NewOSGDTRecord KernData;
+ NewOSGDTRecord UserNull;
+ NewOSGDTRecord UserCode;
+ NewOSGDTRecord UserData;
+ };
+ } // namespace Detail
+} // namespace NewOS::HAL
+
+EXTERN_C void idt_handle_generic(NewOS::UIntPtr rsp);
+EXTERN_C void idt_handle_gpf(NewOS::UIntPtr rsp);
+EXTERN_C void idt_handle_math(NewOS::UIntPtr rsp);
+EXTERN_C void idt_handle_pf(NewOS::UIntPtr rsp);
+
+EXTERN_C void hal_load_idt(NewOS::HAL::Register64 ptr);
+EXTERN_C void hal_load_gdt(NewOS::HAL::RegisterGDT ptr);
+
+/// @brief Maximum size of the IDT.
+#define kKernelIdtSize 0x100
+#define kKernelInterruptId 0x32
+
+inline NewOS::VoidPtr kKernelVirtualStart = (NewOS::VoidPtr)kVirtualAddressStartOffset;
+inline NewOS::UIntPtr kKernelVirtualSize = 0UL;
+
+inline NewOS::VoidPtr kKernelPhysicalStart = nullptr;
diff --git a/Kernel/HALKit/AMD64/Storage/AHCI.cxx b/Kernel/HALKit/AMD64/Storage/AHCI.cxx
new file mode 100644
index 00000000..109d9cb9
--- /dev/null
+++ b/Kernel/HALKit/AMD64/Storage/AHCI.cxx
@@ -0,0 +1,67 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+/**
+ * @file AHCI.cxx
+ * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com)
+ * @brief AHCI driver.
+ * @version 0.1
+ * @date 2024-02-02
+ *
+ * @copyright Copyright (c) SoftwareLabs
+ *
+ */
+
+#include <Builtins/AHCI/AHCI.hxx>
+#include <KernelKit/PCI/Iterator.hpp>
+
+#ifdef __AHCI__
+enum
+{
+ kSATAProgIfAHCI = 0x01,
+ kSATASubClass = 0x06
+};
+
+static NewOS::PCI::Device kAhciDevice;
+
+/// @brief Initializes an AHCI disk.
+/// @param PortsImplemented the amount of port that have been detected.
+/// @return
+NewOS::Boolean drv_std_init(NewOS::UInt16& PortsImplemented)
+{
+ using namespace NewOS;
+
+ PCI::Iterator iterator(Types::PciDeviceKind::MassStorageController);
+ for (SizeT devIndex = 0; devIndex < NEWOS_BUS_COUNT; ++devIndex)
+ {
+ if (iterator[devIndex].Leak().Subclass() == kSATASubClass &&
+ iterator[devIndex].Leak().ProgIf() == kSATAProgIfAHCI)
+ {
+ iterator[devIndex].Leak().EnableMmio(); /// enable the memory i/o for this ahci device.
+ kAhciDevice = iterator[devIndex].Leak(); /// and then leak the reference.
+
+ kcout << "New Kernel: [PCI] Found AHCI controller.\r";
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+NewOS::Boolean drv_std_detected(NewOS::Void)
+{
+ return kAhciDevice.DeviceId() != 0xFFFF;
+}
+
+NewOS::Void drv_std_read(NewOS::UInt64 Lba, NewOS::Char* Buf, NewOS::SizeT SectorSz, NewOS::SizeT Size)
+{
+}
+
+NewOS::Void drv_std_write(NewOS::UInt64 Lba, NewOS::Char* Buf, NewOS::SizeT SectorSz, NewOS::SizeT Size)
+{
+}
+#endif // __AHCI__
diff --git a/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx b/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx
new file mode 100644
index 00000000..97812bd8
--- /dev/null
+++ b/Kernel/HALKit/AMD64/Storage/ATA-DMA.cxx
@@ -0,0 +1,38 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+/**
+ * @file ATA-DMA.cxx
+ * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com)
+ * @brief ATA driver (DMA mode).
+ * @version 0.1
+ * @date 2024-02-02
+ *
+ * @copyright Copyright (c) SoftwareLabs
+ *
+ */
+
+#include <StorageKit/PRDT.hpp>
+
+#include <Builtins/ATA/ATA.hxx>
+#include <ArchKit/ArchKit.hpp>
+
+using namespace NewOS;
+
+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/Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx b/Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx
new file mode 100644
index 00000000..d09d9a67
--- /dev/null
+++ b/Kernel/HALKit/AMD64/Storage/ATA-PIO.cxx
@@ -0,0 +1,192 @@
+/* -------------------------------------------
+
+ Copyright SoftwareLabs
+
+------------------------------------------- */
+
+/**
+ * @file ATA-PIO.cxx
+ * @author Amlal El Mahrouss (amlalelmahrouss@icloud.com)
+ * @brief ATA driver (PIO mode).
+ * @version 0.1
+ * @date 2024-02-02
+ *
+ * @copyright Copyright (c) SoftwareLabs
+ *
+ */
+
+#include <Builtins/ATA/ATA.hxx>
+#include <ArchKit/ArchKit.hpp>
+
+#ifdef __ATA_PIO__
+
+using namespace NewOS;
+using namespace NewOS::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 < 4; 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)
+{
+ if (drv_std_detected())
+ return true;
+
+ UInt16 IO = Bus;
+
+ drv_std_select(IO);
+
+ // Bus init, NEIN bit.
+ Out8(IO + ATA_REG_NEIN, 1);
+
+ // identify until it's good.
+ATAInit_Retry:
+ auto statRdy = In8(IO + ATA_REG_STATUS);
+
+ if (statRdy & ATA_SR_ERR)
+ {
+ return false;
+ }
+
+ if ((statRdy & ATA_SR_BSY))
+ 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;
+
+ return true;
+}
+
+Void drv_std_read(UInt64 Lba, UInt16 IO, UInt8 Master, Char* Buf, SizeT SectorSz, SizeT Size)
+{
+ UInt8 Command = ((!Master) ? 0xE0 : 0xF0);
+
+ Lba /= SectorSz;
+
+ drv_std_wait_io(IO);
+ drv_std_select(IO);
+
+ Out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F));
+
+ /// Compute sector count.
+ Out8(IO + ATA_REG_SEC_COUNT0, SectorSz / (SectorSz / 2));
+
+ Out8(IO + ATA_REG_LBA0, (Lba));
+ Out8(IO + ATA_REG_LBA1, (Lba) >> 8);
+ Out8(IO + ATA_REG_LBA2, (Lba) >> 16);
+
+ 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)
+{
+ UInt8 Command = ((!Master) ? 0xE0 : 0xF0);
+
+ Lba /= SectorSz;
+
+ drv_std_wait_io(IO);
+ drv_std_select(IO);
+
+ /// Compute sector count.
+ Out8(IO + ATA_REG_HDDEVSEL, (Command) | (((Lba) >> 24) & 0x0F));
+
+ Out8(IO + ATA_REG_SEC_COUNT0, SectorSz / (SectorSz / 2));
+
+ Out8(IO + ATA_REG_LBA0, (Lba));
+ Out8(IO + ATA_REG_LBA1, (Lba) >> 8);
+ Out8(IO + ATA_REG_LBA2, (Lba) >> 16);
+
+ 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.
+*/
+NewOS::SizeT drv_std_get_sector_count()
+{
+ return (kATAData[61] << 16) | kATAData[60];
+}
+
+/// @brief Get the drive size.
+NewOS::SizeT drv_std_get_drv_size()
+{
+ return drv_std_get_sector_count() * kATASectorSize;
+}
+
+#endif /* ifdef __ATA_PIO__ */