From 83d48e09bb51955988da94131896f31c1211b7bf Mon Sep 17 00:00:00 2001 From: Maksymilian Wilczynski Date: Sun, 3 May 2026 19:54:51 +0200 Subject: [PATCH] remove weird double spaces, remove /EXPORT from build.bat in favor of __declspec(dllexport) --- OVMF/OVMF_VARS_4M.fd | Bin 540672 -> 540672 bytes build.bat | 28 +++++++--------------------- code/boot/main.c | 2 +- code/drivers/ahci/ahci.c | 18 +++++++++--------- code/hal/hal_api.h | 10 +++++----- code/hal/hal_disk.c | 8 ++++---- code/hal/hal_keyboard.c | 12 ++++++------ code/hal/hal_main.c | 10 +++++----- code/hal/hal_screen.c | 4 ++-- code/hal/io_driver.h | 10 +++++----- code/kernel/io_file.c | 12 ++++++------ code/kernel/io_file.h | 12 ++++++------ code/kernel/ke_debug.c | 2 +- code/kernel/ke_debug.h | 2 +- code/kernel/ke_event.c | 8 ++++---- code/kernel/ke_event.h | 8 ++++---- code/kernel/ke_irp.c | 14 +++++++------- code/kernel/ke_irp.h | 16 ++++++++-------- code/kernel/ke_irq.c | 2 +- code/kernel/ke_irq.h | 2 +- code/kernel/ke_sched.c | 2 +- code/kernel/ke_sched.h | 10 +++++----- code/kernel/ke_semaphore.c | 8 ++++---- code/kernel/ke_semaphore.h | 8 ++++---- code/kernel/ke_switch.asm | 4 ++-- code/kernel/ke_syscall.asm | 2 +- code/kernel/ke_syscall.c | 8 ++++---- code/kernel/ke_thread.c | 8 ++++---- code/kernel/ke_thread.h | 12 ++++++------ code/kernel/mm_phys.c | 4 ++-- code/kernel/mm_phys.h | 4 ++-- code/kernel/mm_virt.c | 24 ++++++++++++------------ code/kernel/mm_virt.h | 20 ++++++++++---------- code/kernel/syscall_nr.h | 6 +++--- code/shell/shell.c | 2 +- code/video/bink.h | 2 +- code/video/rrCore.h | 4 ++-- code/win32/kernel32.c | 6 +++--- code/win32/user32.c | 2 +- code/win32/winmm.c | 2 +- readme.md | 8 ++++---- 41 files changed, 156 insertions(+), 170 deletions(-) diff --git a/OVMF/OVMF_VARS_4M.fd b/OVMF/OVMF_VARS_4M.fd index 386e81a20754853342df8b723662df29375e160a..88cb33122859ea44ab046fb512ca0af8eb2de260 100644 GIT binary patch delta 71 zcmZo@P;3CAEsRVPCi?|BZFiZ#c!_KCyW9%a$!V%elMD0|7_B!?47$kGE;gGHh?%yF Z&1Q~EX%k>+6JTuStatus and fires // irp->CompletionEvent / irp->CompletionFn. // // This gives true async I/O from the caller's perspective: IoSubmitIrp() -// returns STATUS_PENDING immediately. Multiple callers can have outstanding +// returns STATUS_PENDING immediately. Multiple callers can have outstanding // requests against different drives concurrently without stalling each other. // // NCQ extension (future work — see "NCQ TODO" comments): @@ -30,13 +30,13 @@ // • In AhciIsr: completed slots = prev_sact ^ port->sact; look up // slot_irp[slot] and fire each completion from within the ISR. // • The worker becomes a pure dispatcher: grab a free slot, build the -// command, issue it, return immediately. No per-slot KeWaitForEvent. +// command, issue it, return immediately. No per-slot KeWaitForEvent. // // Interrupt model (unchanged): // GHC.IE and per-port PORT_IE are enabled after each port is initialised. // AhciIsr fires on the PCI IRQ line and signals the per-drive completionEvent. // port_issue_cmd blocks the worker thread on KeWaitForEvent instead of -// spinning on CI. port_issue_cmd_poll is kept for early init (IDENTIFY) +// spinning on CI. port_issue_cmd_poll is kept for early init (IDENTIFY) // before the scheduler is live. #include @@ -383,7 +383,7 @@ typedef struct { // ----------------------------------------------------------------------- // IRP queue — async dispatch // ----------------------------------------------------------------------- - // AhciWorker blocks here waiting for work. AhciSubmitIrp enqueues an IRP + // AhciWorker blocks here waiting for work. AhciSubmitIrp enqueues an IRP // and signals the semaphore to wake the worker. IRP_QUEUE irpQueue; THREAD *workerThread; @@ -838,7 +838,7 @@ static KSTATUS AhciSubmitIrp(void *ctx, IRP *irp) { // AhciWorker — kernel thread, one per drive. // Dequeues IRPs and executes them one at a time using the existing -// single-slot interrupt-driven path. Completion fires the IRP's event +// single-slot interrupt-driven path. Completion fires the IRP's event // and/or callback so the original caller can observe the result without // ever having blocked in a driver call. // @@ -1106,7 +1106,7 @@ KSTATUS AhciInitialize(const HAL_API *hal) { // Phase 5b: create the IRP queue semaphore and initialise the queue. // The semaphore starts at 0; each submitted IRP increments it by one. SEMAPHORE *irpSem = (SEMAPHORE *)0; - st = SemaphoreCreate(0, 0x7FFFFFFF, &irpSem); + st = KeSemaphoreCreate(0, 0x7FFFFFFF, &irpSem); if (!KSUCCESS(st)) { DbgPrint("AHCI: port %u: semaphore create failed (0x%x)\n", portno, st); continue; @@ -1167,7 +1167,7 @@ KSTATUS AhciInitialize(const HAL_API *hal) { } // ----------------------------------------------------------------------- - // Register the ISR. All ports on this HBA share one PCI IRQ line. + // Register the ISR. All ports on this HBA share one PCI IRQ line. // Do this after all drives are initialised so the ISR sees valid state. // ----------------------------------------------------------------------- KeIrqRegister(g_irq, AhciIsr); diff --git a/code/hal/hal_api.h b/code/hal/hal_api.h index 2300cf0..46ca93d 100644 --- a/code/hal/hal_api.h +++ b/code/hal/hal_api.h @@ -65,8 +65,8 @@ typedef struct HAL_INTC { } HAL_INTC; typedef struct HAL_POWER { - // ACPI S5 soft-off. Disables interrupts, writes SLP_EN to PM1a/b_CNT, - // and halts if firmware doesn't respond. Does not return. + // ACPI S5 soft-off. Disables interrupts, writes SLP_EN to PM1a/b_CNT, + // and halts if firmware doesn't respond. Does not return. void (*Shutdown)(void); } HAL_POWER; @@ -101,6 +101,6 @@ typedef struct HAL_INIT_PARAMS { #define HAL_API_VERSION 1 -const HAL_API* HalGetApi(void); -void HalRegisterScheduler(void (*pKeSchedulerTick)(void)); -KSTATUS HalInitialize(const HAL_INIT_PARAMS* params); +__declspec(dllexport) const HAL_API* HalGetApi(void); +__declspec(dllexport) void HalRegisterScheduler(void (*pKeSchedulerTick)(void)); +__declspec(dllexport) KSTATUS HalInitialize(const HAL_INIT_PARAMS* params); diff --git a/code/hal/hal_disk.c b/code/hal/hal_disk.c index 7e663ce..6bb7b43 100644 --- a/code/hal/hal_disk.c +++ b/code/hal/hal_disk.c @@ -6,7 +6,7 @@ // in the dependency graph. // // HalDiskDispatch is the one bridge: it calls the driver's SubmitIrp (async) -// or runs the sync callbacks inline and writes irp->Status. It does not +// or runs the sync callbacks inline and writes irp->Status. It does not // touch irp->CompletionEvent — that is ke_irp.c's responsibility. #include @@ -20,7 +20,7 @@ static DISK_DRIVER gDrives[MAX_DRIVES]; static bool gPresent[MAX_DRIVES]; -KSTATUS IoRegisterDisk(uint8_t index, const DISK_DRIVER *driver) { +__declspec(dllexport) KSTATUS IoRegisterDisk(uint8_t index, const DISK_DRIVER *driver) { if (index >= MAX_DRIVES || !driver) return STATUS_INVALID_PARAMETER; if (gPresent[index]) return STATUS_ALREADY_EXISTS; gDrives[index] = *driver; @@ -39,10 +39,10 @@ KSTATUS IoRegisterDisk(uint8_t index, const DISK_DRIVER *driver) { // ke_irp.c must NOT touch irp->CompletionEvent // yet; the driver will fire it. // Returns STATUS_SUCCESS — sync fallback ran; irp->Status is already -// written. ke_irp.c should fire completion hooks. +// written. ke_irp.c should fire completion hooks. // Returns STATUS_NOT_FOUND — drive not registered. -KSTATUS HalDiskDispatch(uint8_t drive, IRP *irp) { +__declspec(dllexport) KSTATUS HalDiskDispatch(uint8_t drive, IRP *irp) { if (drive >= MAX_DRIVES || !gPresent[drive]) return STATUS_NOT_FOUND; DISK_DRIVER *drv = &gDrives[drive]; diff --git a/code/hal/hal_keyboard.c b/code/hal/hal_keyboard.c index 8daa319..a5f49a7 100644 --- a/code/hal/hal_keyboard.c +++ b/code/hal/hal_keyboard.c @@ -1,15 +1,15 @@ // hal_keyboard.c – PS/2 keyboard, interrupt-driven, 256-entry ring buffer // // Scan-code set 1 (XT-compatible), as output by the 8042's built-in -// translation layer. Supports make/break for all standard keys, Shift / +// translation layer. Supports make/break for all standard keys, Shift / // Ctrl / Alt / CapsLock / NumLock modifiers, and the E0-prefixed extended // key set (arrows, Home/End/PgUp/PgDn/Ins/Del, RCtrl, RAlt, numpad-Enter, // numpad-divide). // // Threading model // --------------- -// Single-producer (ISR on IRQ 1) / single-consumer ring buffer. All -// ISR-written state is declared volatile. On a uniprocessor, volatile +// Single-producer (ISR on IRQ 1) / single-consumer ring buffer. All +// ISR-written state is declared volatile. On a uniprocessor, volatile // plus the natural atomicity of aligned int reads/writes is sufficient. // On SMP, add acquire/release memory barriers around gHead and gTail. // @@ -69,7 +69,7 @@ static volatile bool gNextExtended = false; // previous byte was 0xE0 static void (* volatile gCallback)(uint8_t) = NULL; // -- ASCII translation tables – scan-code set 1, non-extended keys only -------- -// Index = 7-bit make code (SC1_BREAK_BIT cleared). 0 = no printable glyph. +// Index = 7-bit make code (SC1_BREAK_BIT cleared). 0 = no printable glyph. // Numpad digits yield their digit characters; a NumLock-aware wrapper can // substitute cursor-movement codes (e.g. HAL_KEY_HOME) when NumLock is clear. // @@ -234,7 +234,7 @@ static bool KbdPoll(void) { return gHead != gTail; } -// Blocking read. Spins with PAUSE until a make code is available. +// Blocking read. Spins with PAUSE until a make code is available. // On a preemptive kernel, replace the _mm_pause() loop with a // condition variable or sti/hlt to avoid wasting CPU cycles. static uint8_t KbdReadScancode(void) { @@ -247,7 +247,7 @@ static uint8_t KbdReadScancode(void) { } // Returns the ASCII character for the next keypress, applying the current -// Shift and CapsLock state. Returns 0 for keys with no ASCII mapping +// Shift and CapsLock state. Returns 0 for keys with no ASCII mapping // (function keys, arrows, unmodified Ctrl/Alt keys, etc.). // // CapsLock inverts shift only for alphabetic keys (a–z); digit and symbol diff --git a/code/hal/hal_main.c b/code/hal/hal_main.c index be70523..6c5b9c4 100644 --- a/code/hal/hal_main.c +++ b/code/hal/hal_main.c @@ -295,7 +295,7 @@ static void WalkAcpi(uintptr_t rsdpPhys) { } // --------------------------------------------------------------------------- -// HalShutdown - ACPI S5 soft power-off. Does not return. +// HalShutdown - ACPI S5 soft power-off. Does not return. // --------------------------------------------------------------------------- #include @@ -309,12 +309,12 @@ static void HalShutdown(void) { if (gPm1aCntBlk) __outword(gPm1aCntBlk, valA); if (gPm1bCntBlk) __outword(gPm1bCntBlk, valB); - // Firmware should have powered off by now. If it didn't, halt. + // Firmware should have powered off by now. If it didn't, halt. while (true) __halt(); } // --------------------------------------------------------------------------- -KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) { +__declspec(dllexport) KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) { if (gInitialised) return STATUS_ALREADY_EXISTS; gPhysBase = initParams->PhysicalWindowBase; gApi.PhysToVirt = HalPhysToVirt; @@ -360,8 +360,8 @@ KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) { return STATUS_SUCCESS; } -void HalRegisterScheduler(void (*pKeSchedulerTick)(void)) { +__declspec(dllexport) void HalRegisterScheduler(void (*pKeSchedulerTick)(void)) { gTimerCallback = pKeSchedulerTick; } -const HAL_API* HalGetApi(void) { return &gApi; } +__declspec(dllexport) const HAL_API* HalGetApi(void) { return &gApi; } diff --git a/code/hal/hal_screen.c b/code/hal/hal_screen.c index 6a671aa..0af77e6 100644 --- a/code/hal/hal_screen.c +++ b/code/hal/hal_screen.c @@ -1,7 +1,7 @@ // hal_screen.c - GOP framebuffer screen driver with embedded 8x16 font // -// The 8x16 bitmap font is a standard VGA/PC font. We embed just the -// printable ASCII range (0x20–0x7E). Each glyph is 16 bytes; bit 7 of +// The 8x16 bitmap font is a standard VGA/PC font. We embed just the +// printable ASCII range (0x20–0x7E). Each glyph is 16 bytes; bit 7 of // each byte is the leftmost pixel. #include #include diff --git a/code/hal/io_driver.h b/code/hal/io_driver.h index 574d82a..41355e9 100644 --- a/code/hal/io_driver.h +++ b/code/hal/io_driver.h @@ -1,7 +1,7 @@ #pragma once // io_driver.h - driver-side interface for registering disk controllers // -// DISK_DRIVER.SubmitIrp is the async path. IRP is forward-declared here so +// DISK_DRIVER.SubmitIrp is the async path. IRP is forward-declared here so // this header (and hal_disk.c) remain free of kernel sync-object dependencies. // Drivers that implement SubmitIrp include ke_irp.h themselves. @@ -25,16 +25,16 @@ typedef struct DISK_DRIVER { // --- Asynchronous path (optional) -------------------------------------- // NULL = driver has not implemented async; IoSubmitIrp() falls back to - // the sync path. Returns STATUS_PENDING when the IRP is accepted. + // the sync path. Returns STATUS_PENDING when the IRP is accepted. KSTATUS (*SubmitIrp)(void *ctx, struct IRP *irp); uint64_t SectorCount; } DISK_DRIVER; -KSTATUS IoRegisterDisk (uint8_t driveIndex, const DISK_DRIVER *driver); +__declspec(dllexport) KSTATUS IoRegisterDisk(uint8_t driveIndex, const DISK_DRIVER *driver); -// Internal dispatch used by ke_irp.c. Calls SubmitIrp if present, otherwise +// Internal dispatch used by ke_irp.c. Calls SubmitIrp if present, otherwise // runs the sync callbacks inline and writes irp->Status; does NOT touch any // kernel sync objects so it is safe to call from the HAL layer. // Returns STATUS_PENDING (async path taken) or STATUS_SUCCESS (ran inline). -KSTATUS HalDiskDispatch (uint8_t drive, struct IRP *irp); +__declspec(dllexport) KSTATUS HalDiskDispatch(uint8_t drive, struct IRP *irp); diff --git a/code/kernel/io_file.c b/code/kernel/io_file.c index 2c7a6bf..1b6a19e 100644 --- a/code/kernel/io_file.c +++ b/code/kernel/io_file.c @@ -17,7 +17,7 @@ static VOLUME_ENTRY gVolumes[MAX_DRIVES]; // --------------------------------------------------------------------------- // Registration // --------------------------------------------------------------------------- -KSTATUS IoRegisterFilesystem(uint8_t volumeIndex, +__declspec(dllexport) KSTATUS IoRegisterFilesystem(uint8_t volumeIndex, IO_FILESYSTEM *fs, const IO_VOLUME_PARAMS *vol) { if (volumeIndex >= MAX_DRIVES || !fs || !vol) @@ -54,7 +54,7 @@ static void FileDestroy(OBJECT* obj) { // --------------------------------------------------------------------------- // IoOpenFile // --------------------------------------------------------------------------- -KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out) { +__declspec(dllexport) KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out) { if (!path || !out) return STATUS_INVALID_PARAMETER; const char* relPath; @@ -83,7 +83,7 @@ KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out) { // --------------------------------------------------------------------------- // IoReadFile - sequential read at current offset // --------------------------------------------------------------------------- -KSTATUS IoReadFile(FILE_OBJECT* file, void* buf, size_t size, size_t* bytesRead) { +__declspec(dllexport) KSTATUS IoReadFile(FILE_OBJECT* file, void* buf, size_t size, size_t* bytesRead) { if (!file || !buf) return STATUS_INVALID_PARAMETER; if (file->Offset >= file->Size) { *bytesRead = 0; return STATUS_SUCCESS; } @@ -98,16 +98,16 @@ KSTATUS IoReadFile(FILE_OBJECT* file, void* buf, size_t size, size_t* bytesRead) } // --------------------------------------------------------------------------- -KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset) { +__declspec(dllexport) KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset) { if (!file) return STATUS_INVALID_PARAMETER; file->Offset = offset; return STATUS_SUCCESS; } -uint64_t IoGetFileSize(FILE_OBJECT* file) { +__declspec(dllexport) uint64_t IoGetFileSize(FILE_OBJECT* file) { return file ? file->Size : 0; } -void IoCloseFile(FILE_OBJECT* file) { +__declspec(dllexport) void IoCloseFile(FILE_OBJECT* file) { if (file) ObDereferenceObject(&file->Header); } diff --git a/code/kernel/io_file.h b/code/kernel/io_file.h index c12cb8b..f77db54 100644 --- a/code/kernel/io_file.h +++ b/code/kernel/io_file.h @@ -53,14 +53,14 @@ typedef struct IO_VOLUME_PARAMS { // Registration - called by fat32.sys from DriverEntry // --------------------------------------------------------------------------- // driveIndex matches the index passed to IoRegisterDisk. -KSTATUS IoRegisterFilesystem(uint8_t driveIndex, IO_FILESYSTEM* fs, const IO_VOLUME_PARAMS *vol); +__declspec(dllexport) KSTATUS IoRegisterFilesystem(uint8_t driveIndex, IO_FILESYSTEM* fs, const IO_VOLUME_PARAMS *vol); // --------------------------------------------------------------------------- // Kernel-side API // --------------------------------------------------------------------------- -KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out); -KSTATUS IoReadFile(FILE_OBJECT* file, void* buf, +__declspec(dllexport) KSTATUS IoOpenFile(const char* path, FILE_OBJECT **out); +__declspec(dllexport) KSTATUS IoReadFile(FILE_OBJECT* file, void* buf, size_t size, size_t* bytesRead); -KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset); -uint64_t IoGetFileSize(FILE_OBJECT* file); -void IoCloseFile(FILE_OBJECT* file); +__declspec(dllexport) KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset); +__declspec(dllexport) uint64_t IoGetFileSize(FILE_OBJECT* file); +__declspec(dllexport) void IoCloseFile(FILE_OBJECT* file); diff --git a/code/kernel/ke_debug.c b/code/kernel/ke_debug.c index f2a88a3..ccf21c6 100644 --- a/code/kernel/ke_debug.c +++ b/code/kernel/ke_debug.c @@ -14,7 +14,7 @@ void kernel_putchar(char c) { PrintChar(c, 0x00FF00, 0x000000); } -void DbgPrint(const char* fmt, ...) { +__declspec(dllexport) void DbgPrint(const char* fmt, ...) { if (!gDebugEnabled) return; static SPINLOCK sl = {0}; diff --git a/code/kernel/ke_debug.h b/code/kernel/ke_debug.h index 179dd42..cd4f726 100644 --- a/code/kernel/ke_debug.h +++ b/code/kernel/ke_debug.h @@ -4,6 +4,6 @@ #include void KeInitDebug(void (*PrintPtr)(char, uint32_t, uint32_t), int v); -void DbgPrint(const char* fmt, ...); +__declspec(dllexport) void DbgPrint(const char* fmt, ...); #endif // KE_DEBUG_H \ No newline at end of file diff --git a/code/kernel/ke_event.c b/code/kernel/ke_event.c index 066c932..60581b2 100644 --- a/code/kernel/ke_event.c +++ b/code/kernel/ke_event.c @@ -7,7 +7,7 @@ static void EventDestroy(OBJECT* obj) { (void)obj; } -KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out) { +__declspec(dllexport) KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out) { if (!out) return STATUS_INVALID_PARAMETER; EVENT* e = (EVENT *)ObAllocateObject(ObjectTypeEvent, sizeof(EVENT)); if (!e) return STATUS_NO_MEMORY; @@ -20,7 +20,7 @@ KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out) { return STATUS_SUCCESS; } -void KeSignalEvent(EVENT* event) { +__declspec(dllexport) void KeSignalEvent(EVENT* event) { if (!event) return; uintptr_t flags = KeAcquireSpinlock(&event->Lock); @@ -46,14 +46,14 @@ void KeSignalEvent(EVENT* event) { KeReleaseSpinlock(&event->Lock, flags); } -void KeClearEvent(EVENT* event) { +__declspec(dllexport) void KeClearEvent(EVENT* event) { if (!event) return; uintptr_t flags = KeAcquireSpinlock(&event->Lock); event->Signaled = 0; KeReleaseSpinlock(&event->Lock, flags); } -KSTATUS KeWaitForEvent(EVENT* event) { +__declspec(dllexport) KSTATUS KeWaitForEvent(EVENT* event) { if (!event) return STATUS_INVALID_PARAMETER; THREAD* self = KeCurrentThread(); diff --git a/code/kernel/ke_event.h b/code/kernel/ke_event.h index 11e6ebe..d492283 100644 --- a/code/kernel/ke_event.h +++ b/code/kernel/ke_event.h @@ -16,7 +16,7 @@ typedef struct EVENT { LIST_ENTRY WaitList; } EVENT; -KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out); -void KeSignalEvent(EVENT* event); -void KeClearEvent(EVENT* event); -KSTATUS KeWaitForEvent(EVENT* event); +__declspec(dllexport) KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialState, EVENT **out); +__declspec(dllexport) void KeSignalEvent(EVENT* event); +__declspec(dllexport) void KeClearEvent(EVENT* event); +__declspec(dllexport) KSTATUS KeWaitForEvent(EVENT* event); diff --git a/code/kernel/ke_irp.c b/code/kernel/ke_irp.c index 8da55c9..718d9ad 100644 --- a/code/kernel/ke_irp.c +++ b/code/kernel/ke_irp.c @@ -1,7 +1,7 @@ // ke_irp.c - I/O Request Packet dispatch and queue helpers // // This file lives in the kernel layer and is the ONLY place that bridges the -// IRP abstraction to kernel sync objects. All calls to KeEventCreate, +// IRP abstraction to kernel sync objects. All calls to KeEventCreate, // KeSignalEvent, KeWaitForEvent, KeSignalSemaphore, and ObDereferenceObject // are confined here; hal_disk.c and io_driver.h remain free of those symbols. // @@ -26,13 +26,13 @@ // ke_irp.h can avoid including ke_semaphore.h, keeping the header safe // for inclusion from the HAL layer. -void IrpQueueInit(IRP_QUEUE *q, struct SEMAPHORE *sem) { +__declspec(dllexport) void IrpQueueInit(IRP_QUEUE *q, struct SEMAPHORE *sem) { q->Lock = (SPINLOCK)SPINLOCK_INIT; q->Semaphore = sem; LIST_INIT(&q->Head); } -void IrpQueueEnqueue(IRP_QUEUE *q, IRP *irp) { +__declspec(dllexport) void IrpQueueEnqueue(IRP_QUEUE *q, IRP *irp) { uintptr_t flags = KeAcquireSpinlock(&q->Lock); if (irp->Flags & IRP_FLAG_PRIORITY) ListInsertHead(&q->Head, &irp->Link); @@ -43,7 +43,7 @@ void IrpQueueEnqueue(IRP_QUEUE *q, IRP *irp) { KeSignalSemaphore((SEMAPHORE *)q->Semaphore); } -IRP *IrpQueueDequeue(IRP_QUEUE *q) { +__declspec(dllexport) IRP *IrpQueueDequeue(IRP_QUEUE *q) { uintptr_t flags = KeAcquireSpinlock(&q->Lock); LIST_ENTRY *node = ListPopHead(&q->Head); KeReleaseSpinlock(&q->Lock, flags); @@ -58,7 +58,7 @@ IRP *IrpQueueDequeue(IRP_QUEUE *q) { // If the dispatch ran inline (sync fallback), we fire the completion hooks // here in the kernel layer where we can legally call KeSignalEvent. -KSTATUS IoSubmitIrp(IRP *irp) { +__declspec(dllexport) KSTATUS IoSubmitIrp(IRP *irp) { if (!irp) return STATUS_INVALID_PARAMETER; KSTATUS st = HalDiskDispatch(irp->DriveIndex, irp); @@ -84,10 +84,10 @@ KSTATUS IoSubmitIrp(IRP *irp) { // IoSubmitIrpSync // ------------------------------------------------------------------------- // Creates a stack-allocated auto-reset event, attaches it to the IRP, -// submits, and blocks. Callers that already provided a CompletionEvent +// submits, and blocks. Callers that already provided a CompletionEvent // should use IoSubmitIrp() directly and wait on their own event instead. -KSTATUS IoSubmitIrpSync(IRP *irp) { +__declspec(dllexport) KSTATUS IoSubmitIrpSync(IRP *irp) { if (!irp) return STATUS_INVALID_PARAMETER; EVENT *ev = (EVENT *)0; diff --git a/code/kernel/ke_irp.h b/code/kernel/ke_irp.h index 0e99dc0..12f057c 100644 --- a/code/kernel/ke_irp.h +++ b/code/kernel/ke_irp.h @@ -3,7 +3,7 @@ // // This header intentionally includes only ke_list.h, ke_spinlock.h, and // ke_status.h — all of which are pure-inline / macro headers with no -// external symbol references. ke_event.h and ke_semaphore.h are forward- +// external symbol references. ke_event.h and ke_semaphore.h are forward- // declared here so the HAL layer (hal_disk.c, io_driver.h) can include this // header without dragging in kernel sync-object link dependencies. // @@ -80,16 +80,16 @@ typedef struct IRP_QUEUE { } IRP_QUEUE; // Non-inline: defined in ke_irp.c, which can pull in ke_semaphore.h safely. -void IrpQueueInit (IRP_QUEUE *q, struct SEMAPHORE *sem); -void IrpQueueEnqueue (IRP_QUEUE *q, IRP *irp); -IRP *IrpQueueDequeue (IRP_QUEUE *q); +__declspec(dllexport) void IrpQueueInit (IRP_QUEUE *q, struct SEMAPHORE *sem); +__declspec(dllexport) void IrpQueueEnqueue (IRP_QUEUE *q, IRP *irp); +__declspec(dllexport) IRP *IrpQueueDequeue (IRP_QUEUE *q); // ------------------------------------------------------------------------- // Public dispatch API — implemented in kernel/ke_irp.c // ------------------------------------------------------------------------- -// Submit asynchronously. Returns STATUS_PENDING on success. -KSTATUS IoSubmitIrp (IRP *irp); +// Submit asynchronously. Returns STATUS_PENDING on success. +__declspec(dllexport) KSTATUS IoSubmitIrp (IRP *irp); -// Submit and block until complete. Returns irp->Status. -KSTATUS IoSubmitIrpSync(IRP *irp); +// Submit and block until complete. Returns irp->Status. +__declspec(dllexport) KSTATUS IoSubmitIrpSync(IRP *irp); diff --git a/code/kernel/ke_irq.c b/code/kernel/ke_irq.c index cedb976..c6f8591 100644 --- a/code/kernel/ke_irq.c +++ b/code/kernel/ke_irq.c @@ -11,7 +11,7 @@ void KeIrqInitialize(const HAL_API *hal) { gHal = hal; } -void KeIrqRegister(uint8_t irq, void (*handler)(void)) { +__declspec(dllexport) void KeIrqRegister(uint8_t irq, void (*handler)(void)) { if (irq >= MAX_IRQS || !handler) return; gIrqHandlers[irq] = handler; gHal->Intc.RouteIrq(irq); diff --git a/code/kernel/ke_irq.h b/code/kernel/ke_irq.h index 10ba7c2..a609e51 100644 --- a/code/kernel/ke_irq.h +++ b/code/kernel/ke_irq.h @@ -3,5 +3,5 @@ #include void KeIrqInitialize(const HAL_API *hal); -void KeIrqRegister(uint8_t irq, void (*handler)(void)); +__declspec(dllexport) void KeIrqRegister(uint8_t irq, void (*handler)(void)); void KeIrqDispatch(uint8_t irq); // called from ke_syscall.asm diff --git a/code/kernel/ke_sched.c b/code/kernel/ke_sched.c index 508a681..cde5f98 100644 --- a/code/kernel/ke_sched.c +++ b/code/kernel/ke_sched.c @@ -152,7 +152,7 @@ void KeSchedulerTick(void) { KeSchedulerPostSwitch(); } -void KeYield(void) { +__declspec(dllexport) void KeYield(void) { THREAD* cur = gCurrentThread; if (!cur) return; diff --git a/code/kernel/ke_sched.h b/code/kernel/ke_sched.h index d307123..a0f6644 100644 --- a/code/kernel/ke_sched.h +++ b/code/kernel/ke_sched.h @@ -1,9 +1,9 @@ #pragma once // ke_sched.h - Multi-Level Feedback Queue scheduler -// Three run queues (Low / Normal / High). IRQ 0 drives KeSchedulerTick. +// Three run queues (Low / Normal / High). IRQ 0 drives KeSchedulerTick. #include -#define QUANTUM_MS 10 /* base time slice in milliseconds */ +#define QUANTUM_MS 10 // base time slice in milliseconds // Called once by KernelMain before any threads are created. void KeInitializeScheduler(void); @@ -15,11 +15,11 @@ void KeUnreadyThread(THREAD* thread); // Called from the timer ISR every QUANTUM_MS. void KeSchedulerTick(void); -// Voluntarily yield the CPU. Picks the next runnable thread immediately. -void KeYield(void); +// Voluntarily yield the CPU. Picks the next runnable thread immediately. +__declspec(dllexport) void KeYield(void); // Returns the thread currently running on this CPU (reads GS:[0]). THREAD* KeCurrentThread(void); -// Set the current-thread GS slot. Called once per CPU at boot. +// Set the current-thread GS slot. Called once per CPU at boot. void KeSetCurrentThread(THREAD* thread); diff --git a/code/kernel/ke_semaphore.c b/code/kernel/ke_semaphore.c index 152ccab..4621857 100644 --- a/code/kernel/ke_semaphore.c +++ b/code/kernel/ke_semaphore.c @@ -7,7 +7,7 @@ static void SemDestroy(OBJECT* obj) { (void)obj; } -KSTATUS SemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out) { +__declspec(dllexport) KSTATUS KeSemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out) { if (!out || initial < 0 || max < 1 || initial > max) return STATUS_INVALID_PARAMETER; SEMAPHORE* s = (SEMAPHORE *)ObAllocateObject(ObjectTypeSemaphore, sizeof(SEMAPHORE)); @@ -21,7 +21,7 @@ KSTATUS SemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out) { return STATUS_SUCCESS; } -KSTATUS KeWaitSemaphore(SEMAPHORE* sem) { +__declspec(dllexport) KSTATUS KeWaitSemaphore(SEMAPHORE* sem) { if (!sem) return STATUS_INVALID_PARAMETER; THREAD* self = KeCurrentThread(); @@ -38,7 +38,7 @@ KSTATUS KeWaitSemaphore(SEMAPHORE* sem) { } } -KSTATUS KeTrySemaphore(SEMAPHORE* sem) { +__declspec(dllexport) KSTATUS KeTrySemaphore(SEMAPHORE* sem) { if (!sem) return STATUS_INVALID_PARAMETER; uintptr_t flags = KeAcquireSpinlock(&sem->Lock); if (sem->Count > 0) { @@ -50,7 +50,7 @@ KSTATUS KeTrySemaphore(SEMAPHORE* sem) { return STATUS_FAILURE; } -void KeSignalSemaphore(SEMAPHORE* sem) { +__declspec(dllexport) void KeSignalSemaphore(SEMAPHORE* sem) { if (!sem) return; uintptr_t flags = KeAcquireSpinlock(&sem->Lock); if (!LIST_IS_EMPTY(&sem->WaitList)) { diff --git a/code/kernel/ke_semaphore.h b/code/kernel/ke_semaphore.h index befed8b..011a640 100644 --- a/code/kernel/ke_semaphore.h +++ b/code/kernel/ke_semaphore.h @@ -14,7 +14,7 @@ typedef struct SEMAPHORE { LIST_ENTRY WaitList; } SEMAPHORE; -KSTATUS SemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out); -KSTATUS KeWaitSemaphore(SEMAPHORE* semaphore); -KSTATUS KeTrySemaphore(SEMAPHORE* semaphore); -void KeSignalSemaphore(SEMAPHORE* semaphore); +__declspec(dllexport) KSTATUS KeSemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out); +__declspec(dllexport) KSTATUS KeWaitSemaphore(SEMAPHORE* semaphore); +__declspec(dllexport) KSTATUS KeTrySemaphore(SEMAPHORE* semaphore); +__declspec(dllexport) void KeSignalSemaphore(SEMAPHORE* semaphore); diff --git a/code/kernel/ke_switch.asm b/code/kernel/ke_switch.asm index db7143b..7bb9b1b 100644 --- a/code/kernel/ke_switch.asm +++ b/code/kernel/ke_switch.asm @@ -89,7 +89,7 @@ KeThreadEntry ENDP ; ------------------------------------------------------------------------- ; KeKernelThreadEntry - landing pad for kernel-mode threads created by -; KeCreateKernelThread. Never touches ring 3; no IRETQ. +; KeCreateKernelThread. Never touches ring 3; no IRETQ. ; ; Stack layout when we arrive here (above the KCONTEXT already popped by ; KeSwitchContext's ret): @@ -97,7 +97,7 @@ KeThreadEntry ENDP ; [rsp+08] arg ptr ; ; We pop both into non-volatile registers so KeSchedulerPostSwitch can -; clobber volatile ones freely, then call fn(arg). On return we call +; clobber volatile ones freely, then call fn(arg). On return we call ; KeExitThread so the thread is cleanly destroyed. ; ------------------------------------------------------------------------- KeKernelThreadEntry PROC diff --git a/code/kernel/ke_syscall.asm b/code/kernel/ke_syscall.asm index d768b03..3d19aea 100644 --- a/code/kernel/ke_syscall.asm +++ b/code/kernel/ke_syscall.asm @@ -37,7 +37,7 @@ KeSyscallEntry PROC KeSyscallEntry ENDP ; --------------------------------------------------------------------------- -; Fault stubs - print a message and halt. A real kernel would do a bugcheck. +; Fault stubs - print a message and halt. A real kernel would do a bugcheck. ; --------------------------------------------------------------------------- EXTERN DbgPrint:PROC diff --git a/code/kernel/ke_syscall.c b/code/kernel/ke_syscall.c index f19d1ad..79f3a29 100644 --- a/code/kernel/ke_syscall.c +++ b/code/kernel/ke_syscall.c @@ -26,7 +26,7 @@ // -> obj->Destroy(obj) [type-specific cleanup, e.g. FileDestroy] // -> MmFreePool(obj) // -// There is no separate SyscallCloseFile. Removing that stub was the right +// There is no separate SyscallCloseFile. Removing that stub was the right // call: the object model already handled it; the dedicated syscall was only // adding a footgun where callers could bypass the unified refcount path. @@ -288,7 +288,7 @@ static uint64_t SyscallSemCreate(uint64_t a0, uint64_t a1, uint64_t a2, (void)a3; (void)a4; (void)a5; if (!a2) return STATUS_INVALID_PARAMETER; SEMAPHORE* sem = NULL; - KSTATUS s = SemaphoreCreate((int32_t)a0, (int32_t)a1, &sem); + KSTATUS s = KeSemaphoreCreate((int32_t)a0, (int32_t)a1, &sem); if (!KSUCCESS(s)) return s; uint32_t h = 0; s = AllocHandleForCurrent(&sem->Header, &h); @@ -440,8 +440,8 @@ static uint64_t SyscallQueueRecv(uint64_t a0, uint64_t a1, uint64_t a2, // --------------------------------------------------------------------------- // SYS_CLOSE_HANDLE (26) a0 = handle // -// The one and only close path. KeCloseHandle drops the handle-table reference -// on 'obj'. If that was the last reference, ObDereferenceObject runs the +// The one and only close path. KeCloseHandle drops the handle-table reference +// on 'obj'. If that was the last reference, ObDereferenceObject runs the // type-specific Destroy callback (FileDestroy, etc.) and frees the pool memory. // No per-type close syscall needed or wanted. // --------------------------------------------------------------------------- diff --git a/code/kernel/ke_thread.c b/code/kernel/ke_thread.c index f7db4ea..ffce41e 100644 --- a/code/kernel/ke_thread.c +++ b/code/kernel/ke_thread.c @@ -33,7 +33,7 @@ static void ThreadDestroy(OBJECT* obj) { } } -KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg, +__declspec(dllexport) KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg, THREAD_PRIORITY priority, THREAD **out) { if (!owner || !out) return STATUS_INVALID_PARAMETER; if (priority >= PriorityCount) return STATUS_INVALID_PARAMETER; @@ -110,7 +110,7 @@ KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg, return STATUS_SUCCESS; } -void KeExitThread(THREAD* thread, int code) { +__declspec(dllexport) void KeExitThread(THREAD* thread, int code) { (void)code; if (!thread) return; @@ -133,9 +133,9 @@ void KeExitThread(THREAD* thread, int code) { // --------------------------------------------------------------------------- extern void KeKernelThreadEntry(void); -KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg, +__declspec(dllexport) KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg, THREAD_PRIORITY priority, THREAD **out) { - // Kernel threads are owned by the idle process. We need a PROCESS* for + // Kernel threads are owned by the idle process. We need a PROCESS* for // the owner field; grab it from the idle/init thread that already exists. THREAD* idleThread = KeCurrentThread(); // safe to call before scheduler starts PROCESS* owner = idleThread ? idleThread->Owner : (PROCESS*)0; diff --git a/code/kernel/ke_thread.h b/code/kernel/ke_thread.h index 6bae3e7..6f383fc 100644 --- a/code/kernel/ke_thread.h +++ b/code/kernel/ke_thread.h @@ -69,18 +69,18 @@ typedef struct THREAD { void* UserStackBase; // Tracks user stack allocation to prevent memory leaks } THREAD; -KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg, +__declspec(dllexport) KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, uintptr_t arg, THREAD_PRIORITY priority, THREAD **out); -// Create a kernel-mode-only thread. fn is called directly in ring 0 with -// arg; when fn returns the thread exits automatically. No user stack or TEB -// is allocated. The thread is owned by the idle process and runs at the +// Create a kernel-mode-only thread. fn is called directly in ring 0 with +// arg; when fn returns the thread exits automatically. No user stack or TEB +// is allocated. The thread is owned by the idle process and runs at the // given priority. -KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg, +__declspec(dllexport) KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg, THREAD_PRIORITY priority, THREAD **out); // Mark a thread dead and deschedule it permanently. -void KeExitThread(THREAD* thread, int code); +__declspec(dllexport) void KeExitThread(THREAD* thread, int code); // Block / unblock primitives used by sync objects. void KeBlockThread(THREAD* thread, OBJECT* waitObject); diff --git a/code/kernel/mm_phys.c b/code/kernel/mm_phys.c index 30a6e25..42f7d21 100644 --- a/code/kernel/mm_phys.c +++ b/code/kernel/mm_phys.c @@ -1,7 +1,7 @@ // mm_phys.c - physical memory manager // // The free-frame stack is a flat array of PHYSICAL_ADDRESS values carved out of -// the first suitable usable region before any allocation is served. All access +// the first suitable usable region before any allocation is served. All access // to physical memory goes through the direct physical window established by the // bootloader at PhysicalWindowBase (always 0xFFFF880000000000). // @@ -124,7 +124,7 @@ void MmFreeFrame(PHYSICAL_ADDRESS frame) { KeReleaseSpinlock(&gFrameStack.Lock, flags); } -PHYSICAL_ADDRESS MmAllocateContiguous(size_t count) { +__declspec(dllexport) PHYSICAL_ADDRESS MmAllocateContiguous(size_t count) { if (!count) return (PHYSICAL_ADDRESS)0; uintptr_t flags = KeAcquireSpinlock(&gFrameStack.Lock); diff --git a/code/kernel/mm_phys.h b/code/kernel/mm_phys.h index cb314ea..e9328bd 100644 --- a/code/kernel/mm_phys.h +++ b/code/kernel/mm_phys.h @@ -20,8 +20,8 @@ PHYSICAL_ADDRESS MmAllocateFrame(void); void MmFreeFrame(PHYSICAL_ADDRESS frame); // Allocate 'count' physically contiguous 4 KB frames. -// Returns 0 on failure. Use sparingly (DMA, page tables). -PHYSICAL_ADDRESS MmAllocateContiguous(size_t count); +// Returns 0 on failure. Use sparingly (DMA, page tables). +__declspec(dllexport) PHYSICAL_ADDRESS MmAllocateContiguous(size_t count); size_t MmFreeFrameCount(void); size_t MmTotalFrameCount(void); diff --git a/code/kernel/mm_virt.c b/code/kernel/mm_virt.c index 7ff6cc0..f0c43fb 100644 --- a/code/kernel/mm_virt.c +++ b/code/kernel/mm_virt.c @@ -11,7 +11,7 @@ // // User heap: // A single best-fit free list in the lower half. -// Backed on demand from the PMM. No per-process heaps. +// Backed on demand from the PMM. No per-process heaps. #include #include #include @@ -60,7 +60,7 @@ static PHYSICAL_ADDRESS EnsureTable(PHYSICAL_ADDRESS parentPhys, // --------------------------------------------------------------------------- // Public mapping // --------------------------------------------------------------------------- -KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags) { +__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags) { unsigned userFlag = (flags & PAGE_USER) ? PAGE_USER : 0; PHYSICAL_ADDRESS pdpt = EnsureTable(gPml4Phys, PML4_IDX(virt), userFlag); @@ -76,7 +76,7 @@ KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags) { return STATUS_SUCCESS; } -KSTATUS MmUnmapPage(uintptr_t virt) { +__declspec(dllexport) KSTATUS MmUnmapPage(uintptr_t virt) { uint64_t* e4 = PtePtr(gPml4Phys, PML4_IDX(virt)); if (!(*e4 & PAGE_PRESENT)) return STATUS_NOT_FOUND; uint64_t* e3 = PtePtr(*e4 & ~0xFFFULL, PDPT_IDX(virt)); @@ -89,7 +89,7 @@ KSTATUS MmUnmapPage(uintptr_t virt) { return STATUS_SUCCESS; } -KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint64_t flags) { +__declspec(dllexport) KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint64_t flags) { if (!size) return STATUS_SUCCESS; // Round down to page boundary, round size up. @@ -115,7 +115,7 @@ KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint64_t flags) { return STATUS_SUCCESS; } -PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) { +__declspec(dllexport) PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) { if (!gPml4Phys) return 0; // Not initialized uint64_t pml4_idx = (virt >> 39) & 0x1FF; @@ -153,7 +153,7 @@ PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) { // Boundary-tag allocator (used for both pool and user heap) // --------------------------------------------------------------------------- // Each allocation has a BLOCK_HDR immediately before the user data, and a -// BLOCK_FTR immediately after. Both carry the block size and a 'free' flag. +// BLOCK_FTR immediately after. Both carry the block size and a 'free' flag. // This allows O(1) coalescing of adjacent free blocks. #define BLOCK_MAGIC 0xB10CB10CUL @@ -433,16 +433,16 @@ void MmActivate(void) { // --------------------------------------------------------------------------- // Public pool API // --------------------------------------------------------------------------- -void* MmAllocatePool(size_t size) { return HeapAlloc(&gPoolHeap, size); } -void MmFreePool(void* ptr) { HeapFree(&gPoolHeap, ptr); } -void* MmReallocatePool(void* ptr, size_t newSize) { return HeapRealloc(&gPoolHeap, ptr, newSize); } +__declspec(dllexport) void* MmAllocatePool(size_t size) { return HeapAlloc(&gPoolHeap, size); } +__declspec(dllexport) void MmFreePool(void* ptr) { HeapFree(&gPoolHeap, ptr); } +__declspec(dllexport) void* MmReallocatePool(void* ptr, size_t newSize) { return HeapRealloc(&gPoolHeap, ptr, newSize); } // --------------------------------------------------------------------------- // Public user heap API // --------------------------------------------------------------------------- -void* MmAllocateUserMemory(size_t size) { return HeapAlloc(&gUserHeap, size); } -void MmFreeUserMemory(void* ptr, size_t size) { (void)size; HeapFree(&gUserHeap, ptr); } -void* MmReallocateUserMemory(void* ptr, size_t newSize) { return HeapRealloc(&gUserHeap, ptr, newSize); } +__declspec(dllexport) void* MmAllocateUserMemory(size_t size) { return HeapAlloc(&gUserHeap, size); } +__declspec(dllexport) void MmFreeUserMemory(void* ptr, size_t size) { (void)size; HeapFree(&gUserHeap, ptr); } +__declspec(dllexport) void* MmReallocateUserMemory(void* ptr, size_t newSize) { return HeapRealloc(&gUserHeap, ptr, newSize); } size_t MmGetKernelPoolUsage(void) { // Returns bytes committed to the kernel pool diff --git a/code/kernel/mm_virt.h b/code/kernel/mm_virt.h index 2a6d0fa..b335942 100644 --- a/code/kernel/mm_virt.h +++ b/code/kernel/mm_virt.h @@ -40,34 +40,34 @@ void MmActivate(void); // --------------------------------------------------------------------------- // Page mapping // --------------------------------------------------------------------------- -KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags); -KSTATUS MmUnmapPage(uintptr_t virt); +__declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags); +__declspec(dllexport) KSTATUS MmUnmapPage(uintptr_t virt); // Modify protection flags on an already-mapped virtual range. // 'flags' is the complete new set of PAGE_* bits - it replaces the old flags // entirely (except the physical address, which is preserved). // Returns STATUS_NOT_FOUND if any page in the range is not mapped. -KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint64_t flags); +__declspec(dllexport) KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint64_t flags); // Walk the page tables to translate a virtual address to physical. // Returns 0 if the address is not mapped. -PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt); +__declspec(dllexport) PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt); // --------------------------------------------------------------------------- // Kernel pool - ring 0 only, never PAGE_USER. // Best-fit free-list allocator, thread-safe via spinlock. // --------------------------------------------------------------------------- -void* MmAllocatePool(size_t size); -void MmFreePool(void* ptr); -void* MmReallocatePool(void* ptr, size_t newSize); +__declspec(dllexport) void* MmAllocatePool(size_t size); +__declspec(dllexport) void MmFreePool(void* ptr); +__declspec(dllexport) void* MmReallocatePool(void* ptr, size_t newSize); // --------------------------------------------------------------------------- // User heap - shared flat space, ring 3 accessible. // All allocations are PAGE_PRESENT | PAGE_WRITE | PAGE_USER. // --------------------------------------------------------------------------- -void* MmAllocateUserMemory(size_t size); -void MmFreeUserMemory(void* ptr, size_t size); -void* MmReallocateUserMemory(void* ptr, size_t newSize); +__declspec(dllexport) void* MmAllocateUserMemory(size_t size); +__declspec(dllexport) void MmFreeUserMemory(void* ptr, size_t size); +__declspec(dllexport) void* MmReallocateUserMemory(void* ptr, size_t newSize); size_t MmGetKernelPoolUsage(void); size_t MmGetUserHeapUsage(void); diff --git a/code/kernel/syscall_nr.h b/code/kernel/syscall_nr.h index aa351a6..06b3481 100644 --- a/code/kernel/syscall_nr.h +++ b/code/kernel/syscall_nr.h @@ -11,10 +11,10 @@ // // Handle semantics: // Every kernel object (file, mutex, semaphore, event, queue) is reference- -// counted. SYS_CLOSE_HANDLE is the ONE way to close any handle regardless -// of the object type behind it. KeCloseHandle calls ObDereferenceObject, +// counted. SYS_CLOSE_HANDLE is the ONE way to close any handle regardless +// of the object type behind it. KeCloseHandle calls ObDereferenceObject, // which fires the type-specific Destroy callback (e.g. FileDestroy) -// automatically when the refcount reaches zero. There is no separate +// automatically when the refcount reaches zero. There is no separate // SYS_CLOSE_FILE - that was redundant. // --------------------------------------------------------------------------- diff --git a/code/shell/shell.c b/code/shell/shell.c index 40ca376..c75ae58 100644 --- a/code/shell/shell.c +++ b/code/shell/shell.c @@ -118,7 +118,7 @@ static char* trim(char* s) { } // --------------------------------------------------------------------------- -// Run one command. Returns 1 if the shell should exit. +// Run one command. Returns 1 if the shell should exit. // --------------------------------------------------------------------------- static int runCommand(const char* cmd) { if (!cmd || *cmd == '\0') diff --git a/code/video/bink.h b/code/video/bink.h index 6a0b50b..62d4eb1 100644 --- a/code/video/bink.h +++ b/code/video/bink.h @@ -173,7 +173,7 @@ typedef struct BINKSND { // will do it's own threading) // 2 = No background thread processing at all, but setup // thread mutexes, so that BinkServiceSound() can be - // call from an external background thread. + // call from an external background thread. U32 SoundDroppedOut; U32 sndconvert8; // convert back to 8-bit sound at runtime diff --git a/code/video/rrCore.h b/code/video/rrCore.h index 93d5724..314b54d 100644 --- a/code/video/rrCore.h +++ b/code/video/rrCore.h @@ -1,5 +1,5 @@ /// ======================================================================== -// (C) Copyright 1994- 2014 RAD Game Tools, Inc. Global types header file +// (C) Copyright 1994- 2014 RAD Game Tools, Inc. Global types header file // ======================================================================== #ifndef __RADRR_COREH__ @@ -648,7 +648,7 @@ !defined(__RADPSP__) && !defined(__RADPSP2__) && !defined(__RADPS3__) && !defined(__RADSPU__) && \ !defined(__RADWII__) && !defined(__RADIPHONE__) && !defined(__RADX32__) && !defined(__RADARM__) && \ !defined(__RADWIIU__) && !defined(__RADANDROID__) && !defined(__RADNACL__) && !defined (__RADQNX__) ) - #error "RAD.H did not detect your platform. Define DOS, WINDOWS, WIN32, macintosh, powerpc, or appropriate console." + #error "RAD.H did not detect your platform. Define DOS, WINDOWS, WIN32, macintosh, powerpc, or appropriate console." #endif diff --git a/code/win32/kernel32.c b/code/win32/kernel32.c index ce9e75f..d39c580 100644 --- a/code/win32/kernel32.c +++ b/code/win32/kernel32.c @@ -9,9 +9,9 @@ // HANDLE_TO_KH / KH_TO_HANDLE do that conversion in one place. // - INVALID_HANDLE_VALUE maps to kernel handle 0 (the always-invalid slot). // - HeapAlloc / HeapFree / HeapReAlloc ignore the HANDLE heap argument and -// always use the single kernel user-heap. This is fine: we don't expose +// always use the single kernel user-heap. This is fine: we don't expose // multiple heaps, and NULL is a legal (no-op) heap argument under Win32. -// - GetLastError / SetLastError are per-thread on Windows. We keep a single +// - GetLastError / SetLastError are per-thread on Windows. We keep a single // global for now; enough for Bink and similar single-threaded guests. // - File I/O uses SYS_OPEN_FILE / SYS_READ_FILE / SYS_SEEK_FILE / // SYS_GET_FILE_SIZE / SYS_CLOSE_HANDLE (unified close path - no separate @@ -342,7 +342,7 @@ __declspec(dllexport) DWORD GetCurrentThreadId(void) { return (DWORD)SysGetCurr __declspec(dllexport) DWORD GetCurrentProcessId(void) { return (DWORD)SysGetCurrentPid(); } // GetModuleHandleA/W – no PE map; return NULL so callers that check can fail -// gracefully. GetModuleHandleA(NULL) on Windows returns the exe base; we +// gracefully. GetModuleHandleA(NULL) on Windows returns the exe base; we // return a recognisable non-NULL sentinel so code that just passes it to // GetProcAddress doesn't immediately crash. __declspec(dllexport) HANDLE GetModuleHandleA(const char* lpModuleName) { diff --git a/code/win32/user32.c b/code/win32/user32.c index 2eafcb1..1253c24 100644 --- a/code/win32/user32.c +++ b/code/win32/user32.c @@ -23,7 +23,7 @@ typedef void* HWND; // --------------------------------------------------------------------------- // GetAsyncKeyState: returns non-zero if a key is available in the input -// buffer. We have no per-key state, so the vKey argument is ignored and +// buffer. We have no per-key state, so the vKey argument is ignored and // the high bit (key-down) is set whenever SysKbPoll reports data waiting. __declspec(dllexport) short GetAsyncKeyState(int vKey) { (void)vKey; diff --git a/code/win32/winmm.c b/code/win32/winmm.c index 394a1da..e21fc4e 100644 --- a/code/win32/winmm.c +++ b/code/win32/winmm.c @@ -52,7 +52,7 @@ typedef struct { // --------------------------------------------------------------------------- // timeGetTime is the lightweight alternative to GetTickCount; both return -// milliseconds since system start. We forward to the kernel tick counter. +// milliseconds since system start. We forward to the kernel tick counter. extern uint64_t SysGetTick(void); __declspec(dllexport) unsigned long timeGetTime(void) { diff --git a/readme.md b/readme.md index 2538372..d29111b 100644 --- a/readme.md +++ b/readme.md @@ -4,9 +4,9 @@ Boots. Runs processes. Mimics Windows to some extent. ## what is it? -A 64-bit operating system kernel written from scratch. -UEFI bootloader, physical and virtual memory managers, preemptive scheduler, HAL, VFS, PE loader, partial Win32 layer. -It boots into a shell. +A 64-bit operating system kernel written from scratch. +UEFI bootloader, physical and virtual memory managers, preemptive scheduler, HAL, VFS, PE loader, partial Win32 layer. +It boots into a shell. ~20k lines of C and assembly. ## features @@ -39,7 +39,7 @@ drivers are PE32+ `.sys` files with an entry point preferably named DriverEntry drivers to be loaded have their path stored in `drivers.ini`, split into essential for boot (loaded by bootloader) and not required for boot (loaded by kernel). -a disk driver fills in a `DISK_DRIVER` vtable and calls `IoRegisterDisk(index, &driver)`. +a disk driver fills in a `DISK_DRIVER` vtable and calls `IoRegisterDisk(index, &driver)`. a filesystem driver fills in an `IO_FILESYSTEM` vtable and calls `IoRegisterFilesystem(index, &fs, &vol)`. ## how it boots