diff --git a/OVMF/OVMF_VARS_4M.fd b/OVMF/OVMF_VARS_4M.fd index 354f061..38251b7 100644 Binary files a/OVMF/OVMF_VARS_4M.fd and b/OVMF/OVMF_VARS_4M.fd differ diff --git a/code/drivers/ahci/ahci.c b/code/drivers/ahci/ahci.c index 2d3857f..399e31f 100644 --- a/code/drivers/ahci/ahci.c +++ b/code/drivers/ahci/ahci.c @@ -1,159 +1,9 @@ -// ahci.c - AHCI SATA driver (basic PRDT, 1 slot, port 0) -#include #include -#include +#include #include -#include -#include -#include - -// AHCI generic host control registers (BAR5 offsets). -#define AHCI_GHC 0x04 // Global Host Control -#define AHCI_PI 0x0C // Ports Implemented -#define AHCI_PORT_BASE(p) (0x100 + (p) * 0x80) - -// Port registers (relative to port base). -#define P_CLB 0x00 // Command List Base Address -#define P_FB 0x08 // FIS Base Address -#define P_IS 0x10 // Interrupt Status -#define P_CMD 0x18 // Command and Status -#define P_TFD 0x20 // Task File Data -#define P_SIG 0x24 // Signature -#define P_SSTS 0x28 // SATA Status -#define P_CI 0x38 // Command Issue - -#define CMD_ST (1 << 0) -#define CMD_FRE (1 << 4) - -#pragma pack(push, 1) -typedef struct { uint8_t cfl:5,a:1,w:1,p:1; uint8_t pmport:4,r:1,b:1,c:1,rsvd:1; uint16_t prdtl; - uint32_t prdbc; uint64_t ctba; uint32_t rsvd2[4]; } HBA_CMD_HEADER; -typedef struct { uint64_t dba; uint32_t rsvd; uint32_t dbc:22, rsvd2:9, i:1; } HBA_PRDT; -typedef struct { uint8_t cfis[64]; uint8_t acmd[16]; uint8_t rsvd[48]; HBA_PRDT prdt[1]; } HBA_CMD_TABLE; -#pragma pack(pop) - -static const HAL_API* gHal; -static volatile uint32_t* gAhci = (volatile uint32_t *)0; -static HBA_CMD_HEADER* gCmdList = (HBA_CMD_HEADER *)0; -static HBA_CMD_TABLE* gCmdTable = (HBA_CMD_TABLE *)0; -static uint8_t* gFisBuf = (uint8_t *)0; -static uint8_t gPort = 0; -static uint64_t gSectors = 0; - -static inline uint32_t PRd(uint32_t off) { - return *(volatile uint32_t *)((uint8_t *)gAhci + off); -} -static inline void PWr(uint32_t off, uint32_t v) { - *(volatile uint32_t *)((uint8_t *)gAhci + off) = v; -} -static inline uint32_t PortRd(uint8_t p, uint32_t off) { - return PRd(AHCI_PORT_BASE(p) + off); -} -static inline void PortWr(uint8_t p, uint32_t off, uint32_t v) { - PWr(AHCI_PORT_BASE(p) + off, v); -} - -static void AhciIssueCmd(uint8_t fis[20], void* buf, uint32_t bytes, int write) { - // Fill FIS in command table. - memcpy(gCmdTable->cfis, fis, 20); - gCmdTable->prdt[0].dba = MmGetPhysicalAddress((uintptr_t)buf); - gCmdTable->prdt[0].dbc = bytes - 1; - gCmdTable->prdt[0].i = 1; - - gCmdList[0].cfl = 5; // FIS length in DWORDs - gCmdList[0].w = write ? 1 : 0; - gCmdList[0].prdtl = 1; - gCmdList[0].prdbc = 0; - gCmdList[0].ctba = MmGetPhysicalAddress((uintptr_t)gCmdTable); - - PortWr(gPort, P_CI, 1); - while (PortRd(gPort, P_CI) & 1) _mm_pause(); -} - -static KSTATUS AhciRead(uint64_t lba, uint32_t count, void* buf) { - uint8_t fis[20] = {0}; - fis[0] = 0x27; fis[1] = 0x80; // H2D, C=1 - fis[2] = 0x25; // READ DMA EXT - fis[4] = (uint8_t)lba; - fis[5] = (uint8_t)(lba >> 8); - fis[6] = (uint8_t)(lba >> 16); - fis[7] = 0x40; // LBA mode - fis[8] = (uint8_t)(lba >> 24); - fis[9] = (uint8_t)(lba >> 32); - fis[10]= (uint8_t)(lba >> 40); - fis[12]= (uint8_t)count; - fis[13]= (uint8_t)(count >> 8); - AhciIssueCmd(fis, buf, count * 512, 0); - return STATUS_SUCCESS; -} - -static KSTATUS AhciWrite(uint64_t lba, uint32_t count, const void* buf) { - uint8_t fis[20] = {0}; - fis[0] = 0x27; fis[1] = 0x80; - fis[2] = 0x35; // WRITE DMA EXT - fis[4] = (uint8_t)lba; - fis[5] = (uint8_t)(lba >> 8); - fis[6] = (uint8_t)(lba >> 16); - fis[7] = 0x40; - fis[8] = (uint8_t)(lba >> 24); - fis[9] = (uint8_t)(lba >> 32); - fis[10]= (uint8_t)(lba >> 40); - fis[12]= (uint8_t)count; - fis[13]= (uint8_t)(count >> 8); - AhciIssueCmd(fis, (void *)buf, count * 512, 1); - return STATUS_SUCCESS; -} KSTATUS DriverEntry(const HAL_API* hal) { - DbgPrint("AHCI: Init\n"); - gHal = hal; - uint8_t bus, dev, fn; - if (!hal->Pci.FindClass(0x01, 0x06, &bus, &dev, &fn)) - return STATUS_NOT_FOUND; // no AHCI controller - - // BAR5 = AHCI base address. - uint32_t bar5 = hal->Pci.ConfigRead32(bus, dev, fn, 0x24) & ~0xFU; - if (!bar5) return STATUS_NOT_FOUND; - - gAhci = (volatile uint32_t *)(gHal->PhysToVirt(bar5)); - - // Enable AHCI mode. - PWr(AHCI_GHC, PRd(AHCI_GHC) | (1 << 31)); - - // Find a port with a connected device. - uint32_t pi = PRd(AHCI_PI); - for (int p = 0; p < 32; p++) { - if (!(pi & (1 << p))) continue; - uint32_t ssts = PortRd((uint8_t)p, P_SSTS); - if ((ssts & 0xF) != 3) continue; // DET: device present + PHY - if (PortRd((uint8_t)p, P_SIG) != 0x00000101) continue; // SATA - gPort = (uint8_t)p; - goto found; - } - return STATUS_NOT_FOUND; -found: - // Allocate command list (1 header), FIS buffer, command table. - gCmdList = (HBA_CMD_HEADER *)MmAllocatePool(4096); - gFisBuf = (uint8_t *)MmAllocatePool(4096); - gCmdTable = (HBA_CMD_TABLE *)MmAllocatePool(4096); - if (!gCmdList || !gFisBuf || !gCmdTable) return STATUS_NO_MEMORY; - memset(gCmdList, 0, 4096); - memset(gFisBuf, 0, 4096); - memset(gCmdTable,0, 4096); - - PortWr(gPort, P_CLB, (uint32_t)(MmGetPhysicalAddress((uintptr_t)gCmdList))); - PortWr(gPort, P_FB, (uint32_t)(MmGetPhysicalAddress((uintptr_t)gFisBuf))); - PortWr(gPort, P_CMD, PortRd(gPort, P_CMD) | CMD_FRE | CMD_ST); - - // Identify to get sector count. - uint8_t fis[20] = {0}; - fis[0] = 0x27; fis[1] = 0x80; fis[2] = 0xEC; - uint16_t ident[256]; - memset(ident, 0, sizeof(ident)); - AhciIssueCmd(fis, ident, 512, 0); - gSectors = *(uint64_t *)(&ident[100]); - if (!gSectors) gSectors = ((uint32_t)ident[61] << 16) | ident[60]; - - DISK_DRIVER drv = { AhciRead, AhciWrite, gSectors }; - return IoRegisterDisk(1, &drv); // drive 1; drive 0 = IDE + (void)hal; + DbgPrint("AHCI: TODO.\n"); + return STATUS_SUCCESS; } diff --git a/code/drivers/usb/usb.c b/code/drivers/usb/usb.c index 13ec507..0f2bd53 100644 --- a/code/drivers/usb/usb.c +++ b/code/drivers/usb/usb.c @@ -6,4 +6,4 @@ KSTATUS DriverEntry(const HAL_API* hal) { (void)hal; DbgPrint("Test runtime driver\n"); return STATUS_SUCCESS; -} \ No newline at end of file +} diff --git a/code/kernel/kmain.c b/code/kernel/kmain.c index de8ddc8..b7fc887 100644 --- a/code/kernel/kmain.c +++ b/code/kernel/kmain.c @@ -24,7 +24,7 @@ typedef struct { size_t capacity; } Header; -#define ARR_INIT_CAPACITY 1 +#define ARR_INIT_CAPACITY 2 #define _arr_header(arr) ((Header*)(arr) - 1) @@ -384,8 +384,8 @@ extern void KernelMain(BOOT_INFO* bootInfo) { // KeInitializeScheduler(); // hal->Screen.Clear(0x000000); - DbgPrint("KernelMain: initialisation complete. %u MB free.\n", - (unsigned)(MmFreeFrameCount() * PAGE_SIZE / (1024 * 1024))); + DbgPrint("KernelMain: initialisation complete. %.2f MB free.\n", + (float)MmFreeFrameCount() * PAGE_SIZE / (1024.0f * 1024.0f)); DbgPrint("KernelMain: Loading system DLLs...\n"); LoadAndRegisterDll("syscall.dll"); @@ -407,8 +407,8 @@ extern void KernelMain(BOOT_INFO* bootInfo) { _enable(); while (1) { - DbgPrint("KernelMain: Idle loop. Free memory: %u MB\n", - (unsigned)(MmFreeFrameCount() * PAGE_SIZE / (1024 * 1024))); + //DbgPrint("KernelMain: Idle loop. Free memory: %.2f MB.\n", + //(float)(MmFreeFrameCount() * PAGE_SIZE) / (1024.0f * 1024.0f)); __halt(); // nothing to do } } diff --git a/code/kernel/mm_phys.c b/code/kernel/mm_phys.c index 9810053..d5a9782 100644 --- a/code/kernel/mm_phys.c +++ b/code/kernel/mm_phys.c @@ -23,7 +23,6 @@ static inline void* PhysToVirt(PHYSICAL_ADDRESS phys) { // --------------------------------------------------------------------------- // Frame stack // --------------------------------------------------------------------------- -#define MAX_FRAMES (256ULL * 1024) // up to 1 GB worth of 4 KB frames typedef struct { PHYSICAL_ADDRESS* Stack; // pointer into physical window @@ -50,12 +49,18 @@ static void PushFrame(PHYSICAL_ADDRESS frame) { void MmInitializePhysical(const MEMORY_MAP* map, uint64_t physicalWindowBase) { gPhysBase = physicalWindowBase; - // --- Phase 1: Find a region large enough to hold the stack array. --- - // We need MAX_FRAMES * sizeof(PHYSICAL_ADDRESS) = 2 MB worst-case. - // Take the first usable region that is large enough. - const size_t stackBytes = MAX_FRAMES * sizeof(PHYSICAL_ADDRESS); - PHYSICAL_ADDRESS stackPhys = 0; + // --- Phase 0: Count total usable frames so we can size the stack + // dynamically instead of capping at a hardcoded 1 GB. --- + uint64_t totalUsableBytes = 0; + for (uint32_t i = 0; i < map->RegionCount; i++) { + if (map->Regions[i].Type == MemoryUsable) + totalUsableBytes += map->Regions[i].Length; + } + const size_t maxFrames = (size_t)(totalUsableBytes / PAGE_SIZE); + const size_t stackBytes = maxFrames * sizeof(PHYSICAL_ADDRESS); + // --- Phase 1: Find a usable region large enough to hold the stack. --- + PHYSICAL_ADDRESS stackPhys = 0; for (uint32_t i = 0; i < map->RegionCount; i++) { const MEMORY_REGION* r = &map->Regions[i]; if (r->Type == MemoryUsable && r->Length >= stackBytes + PAGE_SIZE) { @@ -65,19 +70,16 @@ void MmInitializePhysical(const MEMORY_MAP* map, uint64_t physicalWindowBase) { } if (!stackPhys) { - // Should never happen on any machine with >= 4 MB RAM. - // Hang - there is nothing else we can do. for (;;) { __halt(); } } gFrameStack.Stack = (PHYSICAL_ADDRESS *)PhysToVirt(stackPhys); gFrameStack.Top = 0; - gFrameStack.Capacity = MAX_FRAMES; + gFrameStack.Capacity = maxFrames; gFrameStack.Total = 0; gFrameStack.Lock = (SPINLOCK)SPINLOCK_INIT; - // --- Phase 2: Push all free 4 KB frames from MemoryUsable regions. --- - // Skip the pages occupied by the stack itself. + // --- Phase 2: Push all free 4 KB frames, skipping the stack pages. --- const PHYSICAL_ADDRESS stackEnd = stackPhys + ((stackBytes + PAGE_SIZE - 1) & PAGE_MASK); @@ -89,7 +91,6 @@ void MmInitializePhysical(const MEMORY_MAP* map, uint64_t physicalWindowBase) { PHYSICAL_ADDRESS end = r->Base + r->Length; for (PHYSICAL_ADDRESS frame = base; frame < end; frame += PAGE_SIZE) { - // Skip the frames reserved for our own stack. if (frame >= stackPhys && frame < stackEnd) continue; if (gFrameStack.Top < gFrameStack.Capacity) { gFrameStack.Stack[gFrameStack.Top++] = frame; diff --git a/code/shell/shell.c b/code/shell/shell.c index 5c99d31..f018899 100644 --- a/code/shell/shell.c +++ b/code/shell/shell.c @@ -37,9 +37,9 @@ int main() { // Pass the 32-bit buffer directly to BitBlt BitBlt(600, 400, width, height, image); - for (size_t i = 0; i < 1000000000; i++) { - // burn! - } + // for (size_t i = 0; i < 1000000000; i++) { + // // burn! + // } OutputDebugStringA("Goodbye from the shell!\n");