From a3edb854f43ae372f682c1414ce1a79e26becafc Mon Sep 17 00:00:00 2001 From: JimmyBinoculars Date: Fri, 27 Feb 2026 19:53:40 +0000 Subject: [PATCH] Refactor boot_info.h and related files for improved abstraction and consistency. Updated function signatures to use generic types, replaced UEFI-specific types with kernel types, and enhanced documentation for clarity. Adjusted kernel entry point and service wrappers to align with new structure. --- boot_info.h | 60 ++++++++++++++++++++++++++------------- commands.c | 21 ++++---------- idt.h | 2 +- kernel.c | 69 +++++++++++++++++++++++---------------------- kernel_types.h | 38 +++++++++++++++++++++++++ main.c | 76 ++++++++++++++++++++++++++++++++++---------------- memory.c | 12 ++++---- memory.h | 2 +- string_utils.h | 2 +- task.h | 2 +- 10 files changed, 181 insertions(+), 103 deletions(-) create mode 100644 kernel_types.h diff --git a/boot_info.h b/boot_info.h index 0f6e64f..2fcb968 100644 --- a/boot_info.h +++ b/boot_info.h @@ -1,45 +1,67 @@ /* - * boot_info.h – Shared interface between the UEFI loader and the kernel. + * boot_info.h – Shared interface between the firmware loader and kernel. * - * The BootInfo struct is populated by the loader (main.c) and passed to - * the kernel entry point (kmain). It provides function pointers that - * abstract UEFI Boot/Runtime Services so the kernel can use console I/O, - * memory allocation, and system control without linking against GNU-EFI. + * The BootInfo struct is populated by the platform-specific loader + * (currently the UEFI loader in main.c) and passed to the kernel entry + * point (kmain). It exposes only generic types and function pointers so + * that the kernel remains independent of any particular firmware API. */ #ifndef BOOT_INFO_H #define BOOT_INFO_H -#include +/* + * Status code returned by loader-provided services (0 = success). + * The underlying integer type (UINT64) must be provided by including + * either the firmware headers (e.g. ) or the kernel type + * header before including this file. + */ +typedef UINT64 KSTATUS; -/* Printf-style print function (backed by UEFI ConOut). */ +/* Simple key event used by the kernel's input path. */ +typedef struct { + UINT16 scan_code; + CHAR16 unicode_char; +} KeyEvent; + +/* Printf-style print function (typically backed by firmware console). */ typedef UINTN (*KernelPrintFn)(const CHAR16 *Format, ...); +/* Console output helpers. */ +typedef KSTATUS (*ConsoleClearFn)(void); +typedef KSTATUS (*ConsoleSetAttrFn)(UINTN Attribute); + +/* Keyboard input helpers. */ +typedef KSTATUS (*KeyReadFn)(KeyEvent *Key); + /* - * BootInfo – everything the kernel needs from the UEFI environment. + * BootInfo – everything the kernel needs from the loader at boot time. * * All function pointers are optional: the kernel must NULL-check before * calling. If a service is unavailable the corresponding field is NULL. */ typedef struct { - EFI_SYSTEM_TABLE *SystemTable; /* UEFI System Table */ - /* Console I/O */ - KernelPrintFn print; /* formatted text output */ - EFI_STATUS (*clear_screen)(void); /* clear the console */ - EFI_STATUS (*set_attribute)(UINTN Attribute); /* set text colour/attr */ - EFI_STATUS (*read_key)(EFI_INPUT_KEY *Key); /* blocking key read */ - EFI_STATUS (*try_read_key)(EFI_INPUT_KEY *Key); /* non-blocking key read */ + KernelPrintFn print; /* formatted text output */ + ConsoleClearFn clear_screen; /* clear the console */ + ConsoleSetAttrFn set_attribute; /* set text colour/attr */ + KeyReadFn read_key; /* blocking key read */ + KeyReadFn try_read_key; /* non-blocking key read */ /* System control */ - void (*shutdown)(void); /* power-off the machine */ + void (*shutdown)(void); /* power-off the machine */ /* Physical memory */ - EFI_STATUS (*alloc_pages)(UINTN pages, EFI_PHYSICAL_ADDRESS *addr); - EFI_STATUS (*free_pages)(EFI_PHYSICAL_ADDRESS addr, UINTN pages); + KSTATUS (*alloc_pages)(UINTN pages, UINT64 *addr); + KSTATUS (*free_pages)(UINT64 addr, UINTN pages); + + /* Firmware metadata (for informational commands only). */ + const CHAR16 *firmware_vendor; + UINT32 firmware_major; + UINT32 firmware_minor; } BootInfo; -/* Kernel entry point signature (called by the UEFI loader). */ +/* Kernel entry point signature (called by the loader). */ typedef void (*KernelEntryFn)(BootInfo *Boot); #endif /* BOOT_INFO_H */ diff --git a/commands.c b/commands.c index e3f762f..c8c5ada 100644 --- a/commands.c +++ b/commands.c @@ -11,7 +11,7 @@ * 3. Append an entry to commands[] (before the sentinel) */ -#include +#include "kernel_types.h" #include "commands.h" #include "string_utils.h" #include "memory.h" @@ -112,10 +112,6 @@ static Command commands[] = { * System control * ================================================================ */ -/* - * Try Boot->shutdown first, then fall back to RuntimeServices, then - * print an error if neither is available. - */ static void request_shutdown(BootInfo *Boot) { if (Boot == NULL) { @@ -127,14 +123,6 @@ static void request_shutdown(BootInfo *Boot) return; } - if (Boot->SystemTable != NULL && - Boot->SystemTable->RuntimeServices != NULL && - Boot->SystemTable->RuntimeServices->ResetSystem != NULL) { - Boot->SystemTable->RuntimeServices->ResetSystem( - EfiResetShutdown, EFI_SUCCESS, 0, NULL); - return; - } - SAFE_PRINT(Boot, L"Shutdown service unavailable.\n\r"); } @@ -185,13 +173,14 @@ static void cmd_man(BootInfo *Boot, CHAR16 *Args) static void cmd_clear(BootInfo *Boot, CHAR16 *Args) { - EFI_STATUS Status; + KSTATUS Status; (void)Args; if (Boot != NULL && Boot->clear_screen != NULL) { Status = Boot->clear_screen(); - if (EFI_ERROR(Status)) { - SAFE_PRINT(Boot, L"Failed to clear screen: %r\n\r", Status); + if (Status != 0) { + SAFE_PRINT(Boot, L"Failed to clear screen (status=%ld)\n\r", + (UINT64)Status); } } else { SAFE_PRINT(Boot, L"Clear screen function unavailable.\n\r"); diff --git a/idt.h b/idt.h index c5bce38..7df2932 100644 --- a/idt.h +++ b/idt.h @@ -8,7 +8,7 @@ #ifndef IDT_H #define IDT_H -#include +#include "kernel_types.h" #include "boot_info.h" /* diff --git a/kernel.c b/kernel.c index d8bf497..8eb003e 100644 --- a/kernel.c +++ b/kernel.c @@ -1,17 +1,16 @@ /* * kernel.c – Kernel entry point and interactive shell loop. * - * kmain() is called by the UEFI loader (main.c) after the ELF kernel - * has been mapped into memory. It initialises subsystems (IDT, memory, - * tasks), prints a welcome banner, and enters an interactive read- - * eval-print loop that dispatches typed commands via commands.c. + * kmain() is called by the loader (main.c) after the ELF kernel has been + * mapped into memory. It initialises subsystems (IDT, memory, tasks), + * prints a welcome banner, and enters an interactive read-eval-print + * loop that dispatches typed commands via commands.c. * * While waiting for keyboard input, the shell yields to the cooperative * scheduler so that background tasks can make progress. */ -#include - +#include "kernel_types.h" #include "boot_info.h" #include "commands.h" #include "idt.h" @@ -26,14 +25,21 @@ } \ } while (0) +/* Simple text attribute helper (modelled after UEFI TEXT_ATTR). */ +#define TEXT_ATTR(fg, bg) (UINTN)(((fg) & 0x0F) | (((bg) & 0x0F) << 4)) + +/* Basic colour constants (compatible with UEFI's palette). */ +#define COLOR_BLACK 0x0 +#define COLOR_LIGHTGREEN 0xA + /* ================================================================ * Kernel entry point * ================================================================ */ void kmain(BootInfo *Boot) { - EFI_INPUT_KEY Key; - EFI_STATUS Status; + KeyEvent Key; + KSTATUS Status; UINTN read_errors = 0; if (Boot == NULL) { @@ -42,15 +48,17 @@ void kmain(BootInfo *Boot) if (Boot->clear_screen != NULL) { Status = Boot->clear_screen(); - if (EFI_ERROR(Status)) { - SAFE_PRINT(Boot, L"clear_screen failed: %r\n\r", Status); + if (Status != 0) { + SAFE_PRINT(Boot, L"clear_screen failed (status=%ld)\n\r", + (UINT64)Status); } } if (Boot->set_attribute != NULL) { - Status = Boot->set_attribute(EFI_TEXT_ATTR(EFI_LIGHTGREEN, EFI_BLACK)); - if (EFI_ERROR(Status)) { - SAFE_PRINT(Boot, L"set_attribute failed: %r\n\r", Status); + Status = Boot->set_attribute(TEXT_ATTR(COLOR_LIGHTGREEN, COLOR_BLACK)); + if (Status != 0) { + SAFE_PRINT(Boot, L"set_attribute failed (status=%ld)\n\r", + (UINT64)Status); } } @@ -64,26 +72,18 @@ void kmain(BootInfo *Boot) SAFE_PRINT(Boot, L"================================================\n\r"); SAFE_PRINT(Boot, L"\n\r"); SAFE_PRINT(Boot, L"System Information:\n\r"); - if (Boot->SystemTable != NULL) { - SAFE_PRINT(Boot, L" UEFI Firmware Vendor: %s\n\r", - Boot->SystemTable->FirmwareVendor); - SAFE_PRINT(Boot, L" UEFI Firmware Revision: %d.%d\n\r", - Boot->SystemTable->FirmwareRevision >> 16, - Boot->SystemTable->FirmwareRevision & 0xFFFF); + if (Boot->firmware_vendor != NULL) { + SAFE_PRINT(Boot, L" Firmware Vendor: %s\n\r", Boot->firmware_vendor); + SAFE_PRINT(Boot, L" Firmware Revision: %d.%d\n\r", + Boot->firmware_major, Boot->firmware_minor); } else { - SAFE_PRINT(Boot, L" UEFI System Table: Unavailable\n\r"); + SAFE_PRINT(Boot, L" Firmware information: Unavailable\n\r"); } SAFE_PRINT(Boot, L"\n\r"); SAFE_PRINT(Boot, L"Available Services:\n\r"); SAFE_PRINT(Boot, L" - Console Input/Output: %s\n\r", (Boot->read_key != NULL && Boot->print != NULL) ? L"Active" : L"Unavailable"); - SAFE_PRINT(Boot, L" - Runtime Services: %s\n\r", - (Boot->SystemTable != NULL && - Boot->SystemTable->RuntimeServices != NULL) ? L"Active" : L"Unavailable"); - SAFE_PRINT(Boot, L" - Boot Services: %s\n\r", - (Boot->SystemTable != NULL && - Boot->SystemTable->BootServices != NULL) ? L"Active" : L"Unavailable"); SAFE_PRINT(Boot, L"\n\r"); SAFE_PRINT(Boot, L"Type 'help' for a list of commands.\n\r\n\r"); @@ -97,7 +97,7 @@ void kmain(BootInfo *Boot) /* Try non-blocking read first; yield to other tasks while idle */ if (Boot->try_read_key != NULL) { Status = Boot->try_read_key(&Key); - if (Status == EFI_NOT_READY) { + if (Status != 0) { task_yield(); continue; } @@ -108,16 +108,17 @@ void kmain(BootInfo *Boot) break; } - if (EFI_ERROR(Status)) { + if (Status != 0) { read_errors++; if (read_errors == 1 || (read_errors % 64) == 0) { - SAFE_PRINT(Boot, L"read_key failed: %r\n\r", Status); + SAFE_PRINT(Boot, L"read_key failed (status=%ld)\n\r", + (UINT64)Status); } continue; } read_errors = 0; - if (Key.UnicodeChar == L'\r' || Key.UnicodeChar == L'\n') { + if (Key.unicode_char == L'\r' || Key.unicode_char == L'\n') { /* Enter pressed: execute the buffered command */ line[len] = L'\0'; SAFE_PRINT(Boot, L"\n\r"); @@ -126,17 +127,17 @@ void kmain(BootInfo *Boot) /* Reset for next command */ len = 0; SAFE_PRINT(Boot, L"-> "); - } else if (Key.ScanCode == 0x08 || Key.UnicodeChar == L'\b' || Key.UnicodeChar == 0x7F) { + } else if (Key.scan_code == 0x08 || Key.unicode_char == L'\b' || Key.unicode_char == 0x7F) { /* Backspace */ if (len > 0) { len--; SAFE_PRINT(Boot, L"\b \b"); } - } else if (Key.UnicodeChar >= 32 && Key.UnicodeChar < 127) { + } else if (Key.unicode_char >= 32 && Key.unicode_char < 127) { /* Printable ASCII */ if (len < (sizeof(line) / sizeof(line[0]) - 1)) { - line[len++] = Key.UnicodeChar; - SAFE_PRINT(Boot, L"%c", Key.UnicodeChar); + line[len++] = Key.unicode_char; + SAFE_PRINT(Boot, L"%c", Key.unicode_char); } } } diff --git a/kernel_types.h b/kernel_types.h new file mode 100644 index 0000000..4a917b9 --- /dev/null +++ b/kernel_types.h @@ -0,0 +1,38 @@ +/* + * kernel_types.h – Common fixed-width and utility types for the kernel. + * + * This header deliberately avoids pulling in any firmware- or + * platform-specific headers (such as UEFI's ). All core kernel + * code should include this instead of . + */ + +#ifndef KERNEL_TYPES_H +#define KERNEL_TYPES_H + +#include +#include +#include + +typedef uint8_t UINT8; +typedef uint16_t UINT16; +typedef uint32_t UINT32; +typedef uint64_t UINT64; + +typedef size_t UINTN; + +#ifndef BOOLEAN +typedef bool BOOLEAN; +#endif + +typedef uint16_t CHAR16; + +#ifndef TRUE +#define TRUE ((BOOLEAN)true) +#endif + +#ifndef FALSE +#define FALSE ((BOOLEAN)false) +#endif + +#endif /* KERNEL_TYPES_H */ + diff --git a/main.c b/main.c index e40cf16..8bffac7 100644 --- a/main.c +++ b/main.c @@ -5,7 +5,7 @@ * firmware via the PE32+ entry point. It: * 1. Reads kernel.elf from the EFI System Partition * 2. Parses the ELF64 headers and maps PT_LOAD segments into memory - * 3. Populates a BootInfo struct with UEFI service wrappers + * 3. Populates a BootInfo struct with generic service wrappers * 4. Jumps to the kernel entry point (kmain) */ @@ -227,26 +227,44 @@ static EFI_STATUS load_elf_kernel(VOID *Image, UINTN Size, UINT64 *EntryOut) * UEFI service wrappers (passed to the kernel via BootInfo) * ================================================================ */ -static EFI_STATUS loader_clear_screen(void) +static KSTATUS loader_clear_screen(void) { - return uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + EFI_STATUS Status = uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); + return (KSTATUS)Status; } -static EFI_STATUS loader_set_attribute(UINTN Attribute) +static KSTATUS loader_set_attribute(UINTN Attribute) { - return uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, Attribute); + EFI_STATUS Status = uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, Attribute); + return (KSTATUS)Status; } -static EFI_STATUS loader_read_key(EFI_INPUT_KEY *Key) +static KSTATUS loader_read_key(KeyEvent *Key) { + EFI_STATUS Status; + EFI_INPUT_KEY EfiKey; UINTN Index = 0; + uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &Index); - return uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, Key); + Status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &EfiKey); + if (!EFI_ERROR(Status) && Key != NULL) { + Key->scan_code = EfiKey.ScanCode; + Key->unicode_char = EfiKey.UnicodeChar; + } + return (KSTATUS)Status; } -static EFI_STATUS loader_try_read_key(EFI_INPUT_KEY *Key) +static KSTATUS loader_try_read_key(KeyEvent *Key) { - return uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, Key); + EFI_STATUS Status; + EFI_INPUT_KEY EfiKey; + + Status = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &EfiKey); + if (!EFI_ERROR(Status) && Key != NULL) { + Key->scan_code = EfiKey.ScanCode; + Key->unicode_char = EfiKey.UnicodeChar; + } + return (KSTATUS)Status; } static void loader_shutdown(void) @@ -254,15 +272,23 @@ static void loader_shutdown(void) uefi_call_wrapper(RT->ResetSystem, 4, EfiResetShutdown, EFI_SUCCESS, 0, NULL); } -static EFI_STATUS loader_alloc_pages(UINTN pages, EFI_PHYSICAL_ADDRESS *addr) +static KSTATUS loader_alloc_pages(UINTN pages, UINT64 *addr) { - return uefi_call_wrapper(BS->AllocatePages, 4, - AllocateAnyPages, EfiLoaderData, pages, addr); + EFI_PHYSICAL_ADDRESS Phys = 0; + EFI_STATUS Status = uefi_call_wrapper(BS->AllocatePages, 4, + AllocateAnyPages, EfiLoaderData, + pages, &Phys); + if (!EFI_ERROR(Status) && addr != NULL) { + *addr = (UINT64)Phys; + } + return (KSTATUS)Status; } -static EFI_STATUS loader_free_pages(EFI_PHYSICAL_ADDRESS addr, UINTN pages) +static KSTATUS loader_free_pages(UINT64 addr, UINTN pages) { - return uefi_call_wrapper(BS->FreePages, 2, addr, pages); + EFI_STATUS Status = uefi_call_wrapper(BS->FreePages, 2, + (EFI_PHYSICAL_ADDRESS)addr, pages); + return (KSTATUS)Status; } /* ================================================================ @@ -297,16 +323,18 @@ efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) return Status; } - /* Populate the BootInfo struct with UEFI service wrappers */ - Boot.SystemTable = ST; - Boot.print = Print; - Boot.clear_screen = loader_clear_screen; - Boot.set_attribute = loader_set_attribute; - Boot.read_key = loader_read_key; - Boot.try_read_key = loader_try_read_key; - Boot.shutdown = loader_shutdown; - Boot.alloc_pages = loader_alloc_pages; - Boot.free_pages = loader_free_pages; + /* Populate the BootInfo struct with generic UEFI-backed services */ + Boot.print = Print; + Boot.clear_screen = loader_clear_screen; + Boot.set_attribute = loader_set_attribute; + Boot.read_key = loader_read_key; + Boot.try_read_key = loader_try_read_key; + Boot.shutdown = loader_shutdown; + Boot.alloc_pages = loader_alloc_pages; + Boot.free_pages = loader_free_pages; + Boot.firmware_vendor = SystemTable->FirmwareVendor; + Boot.firmware_major = (SystemTable->FirmwareRevision >> 16) & 0xFFFF; + Boot.firmware_minor = SystemTable->FirmwareRevision & 0xFFFF; /* Jump to the kernel – this should not return */ EntryFn = (KernelEntryFn)(UINTN)KernelEntry; diff --git a/memory.c b/memory.c index 26b54d7..61038a3 100644 --- a/memory.c +++ b/memory.c @@ -3,7 +3,7 @@ * * Implements three layers: * PMM – bitmap-based physical page-frame allocator backed by a - * 16 MB pool obtained from UEFI at boot. + * 16 MB pool obtained from the loader at boot. * Paging – walks and creates 4-level x86-64 page tables; supports * map, unmap, and virtual-to-physical translation. * Heap – first-fit free-list allocator with block splitting and @@ -62,8 +62,8 @@ static BOOLEAN pmm_test_bit(UINTN idx) */ void pmm_init(BootInfo *Boot) { - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS pool_addr = 0; + KSTATUS Status; + UINT64 pool_addr = 0; UINTN i; /* Zero the bitmap – all pages start free */ @@ -77,9 +77,9 @@ void pmm_init(BootInfo *Boot) } Status = Boot->alloc_pages(PMM_POOL_PAGES, &pool_addr); - if (EFI_ERROR(Status)) { - SAFE_PRINT(Boot, L"PMM: failed to allocate pool (%d pages): %r\n\r", - (UINTN)PMM_POOL_PAGES, Status); + if (Status != 0) { + SAFE_PRINT(Boot, L"PMM: failed to allocate pool (%d pages), status=%ld\n\r", + (UINTN)PMM_POOL_PAGES, (UINT64)Status); return; } diff --git a/memory.h b/memory.h index 534563f..e8f4f87 100644 --- a/memory.h +++ b/memory.h @@ -10,7 +10,7 @@ #ifndef MEMORY_H #define MEMORY_H -#include +#include "kernel_types.h" #include "boot_info.h" /* ================================================================ diff --git a/string_utils.h b/string_utils.h index 21481b5..519a629 100644 --- a/string_utils.h +++ b/string_utils.h @@ -8,7 +8,7 @@ #ifndef STRING_UTILS_H #define STRING_UTILS_H -#include +#include "kernel_types.h" /* Return TRUE if Ch is a space or horizontal tab. */ BOOLEAN is_space16(CHAR16 Ch); diff --git a/task.h b/task.h index e700793..80ab2ba 100644 --- a/task.h +++ b/task.h @@ -9,7 +9,7 @@ #ifndef TASK_H #define TASK_H -#include +#include "kernel_types.h" #include "boot_info.h" /* ================================================================