From 467a58c9c657371606f5132d512baa5a898919d4 Mon Sep 17 00:00:00 2001 From: Maksymilian Wilczynski Date: Mon, 15 Jun 2026 10:17:48 +0200 Subject: [PATCH] rewrite comments into one, unified style --- code/boot/uefi/main.c | 188 ++-- code/build/build.c | 45 +- code/common/include/common/ini_parser.h | 10 +- code/common/ini_parser.c | 8 +- code/common/libc.c | 436 ++++---- code/drivers/bus/pci/pci.c | 45 +- code/drivers/bus/pci/pci.h | 2 + code/drivers/bus/usb/usb.c | 5 +- code/drivers/bus/usb/usb.h | 6 +- code/drivers/bus/usb/usb_bus.c | 39 +- code/drivers/bus/usb/usb_composite.c | 8 +- code/drivers/bus/usb/usb_core.c | 26 +- code/drivers/bus/usb/usb_hid.c | 36 +- code/drivers/bus/usb/usb_hub.c | 52 +- code/drivers/bus/usb/usb_storage.c | 27 +- code/drivers/bus/usb/usb_xhci.c | 93 +- code/drivers/display/vmwaresvga/vmwaresvga.c | 181 +-- code/drivers/display/vmwaresvga/vmwaresvga.h | 13 +- code/drivers/fs/fat32/fat32.c | 136 +-- code/drivers/fs/fat32/fat32.h | 3 +- code/drivers/fs/fat32/fat32_mount.c | 4 +- code/drivers/input/ps2/ps2.c | 12 +- code/drivers/input/ps2/ps2.h | 3 +- code/drivers/input/ps2/ps2_i8042.c | 14 +- code/drivers/net/lwip/lwip_stack.c | 35 +- code/drivers/net/lwip/lwip_sys_arch.c | 64 +- code/drivers/net/rtl8139/rtl8139.c | 27 +- code/drivers/net/rtl8139/rtl8139.h | 3 +- code/drivers/net/rtl8139/rtl8139_pci.c | 4 +- code/drivers/net/rtl816x/rtl816x.c | 26 +- code/drivers/net/rtl816x/rtl816x.h | 3 +- code/drivers/storage/ahci/ahci.c | 112 +- code/drivers/storage/ahci/ahci.h | 88 +- code/drivers/storage/ahci/ahci_port.c | 39 +- code/drivers/storage/ata/ata.c | 32 +- code/drivers/storage/ata/ata.h | 3 +- code/kernel/hal/hal_apic.c | 27 +- code/kernel/hal/hal_disk.c | 4 +- code/kernel/hal/hal_keyboard.c | 3 +- code/kernel/hal/hal_main.c | 57 +- code/kernel/hal/hal_mouse.c | 3 +- code/kernel/hal/hal_pci.c | 5 +- code/kernel/hal/hal_rtc.c | 13 +- code/kernel/hal/hal_screen.c | 41 +- code/kernel/hal/hal_timer.c | 40 +- code/kernel/include/kernel/display_cursor.h | 4 +- code/kernel/include/kernel/hal/font8x16.h | 1044 +++++++++--------- code/kernel/include/kernel/hal/hal_apic.h | 3 +- code/kernel/include/kernel/hal/hal_debug.h | 8 +- code/kernel/include/kernel/io_file.h | 34 +- code/kernel/include/kernel/ke_apc.h | 6 +- code/kernel/include/kernel/ke_cpu.h | 4 +- code/kernel/include/kernel/ke_debug.h | 6 +- code/kernel/include/kernel/ke_display.h | 2 + code/kernel/include/kernel/ke_dpc.h | 4 +- code/kernel/include/kernel/ke_event.h | 4 +- code/kernel/include/kernel/ke_idt.h | 4 +- code/kernel/include/kernel/ke_input.h | 2 + code/kernel/include/kernel/ke_irp.h | 36 +- code/kernel/include/kernel/ke_irq.h | 2 + code/kernel/include/kernel/ke_irql.h | 4 +- code/kernel/include/kernel/ke_list.h | 93 +- code/kernel/include/kernel/ke_mutex.h | 6 +- code/kernel/include/kernel/ke_process.h | 42 +- code/kernel/include/kernel/ke_queue.h | 8 +- code/kernel/include/kernel/ke_sched.h | 2 + code/kernel/include/kernel/ke_selftest.h | 2 + code/kernel/include/kernel/ke_semaphore.h | 4 +- code/kernel/include/kernel/ke_settings.h | 2 + code/kernel/include/kernel/ke_smp.h | 2 + code/kernel/include/kernel/ke_spinlock.h | 11 +- code/kernel/include/kernel/ke_syscall.h | 6 +- code/kernel/include/kernel/ke_thread.h | 18 +- code/kernel/include/kernel/ke_time.h | 2 + code/kernel/include/kernel/ke_trap.h | 4 +- code/kernel/include/kernel/ke_userenv.h | 6 +- code/kernel/include/kernel/ke_util.h | 9 +- code/kernel/include/kernel/ldr_image.h | 2 + code/kernel/include/kernel/mm_phys.h | 2 + code/kernel/include/kernel/mm_virt.h | 22 +- code/kernel/include/kernel/net_socket.h | 4 +- code/kernel/include/kernel/ob_object.h | 2 + code/kernel/include/kernel/syscall_nr.h | 4 +- code/kernel/io_device.c | 48 +- code/kernel/io_file.c | 73 +- code/kernel/ke_apc.c | 14 +- code/kernel/ke_cpu.c | 10 +- code/kernel/ke_debug.c | 42 +- code/kernel/ke_display.c | 54 +- code/kernel/ke_dpc.c | 6 +- code/kernel/ke_event.c | 8 +- code/kernel/ke_idt.c | 33 +- code/kernel/ke_input.c | 27 +- code/kernel/ke_irp.c | 37 +- code/kernel/ke_irq.c | 10 +- code/kernel/ke_irql.c | 10 +- code/kernel/ke_mutex.c | 8 +- code/kernel/ke_process.c | 49 +- code/kernel/ke_queue.c | 7 +- code/kernel/ke_sched.c | 45 +- code/kernel/ke_selftest.c | 33 +- code/kernel/ke_semaphore.c | 8 +- code/kernel/ke_settings.c | 4 +- code/kernel/ke_smp.c | 50 +- code/kernel/ke_syscall.c | 615 ++++------- code/kernel/ke_thread.c | 24 +- code/kernel/ke_time.c | 30 +- code/kernel/ke_trap.c | 8 +- code/kernel/kmain.c | 89 +- code/kernel/ldr_image.c | 60 +- code/kernel/mm_phys.c | 34 +- code/kernel/mm_virt.c | 127 ++- code/kernel/net_device.c | 10 +- code/kernel/net_socket.c | 15 +- code/kernel/net_stack.c | 5 +- code/kernel/ob_object.c | 6 +- code/public/ntlite/boot_info.h | 34 +- code/public/ntlite/ddi/display.h | 4 +- code/public/ntlite/ddi/hal_api.h | 12 +- code/public/ntlite/ddi/input_device.h | 2 + code/public/ntlite/ddi/io_driver.h | 20 +- code/public/ntlite/ddi/net_abi.h | 2 + code/public/ntlite/ddi/net_device.h | 4 +- code/public/ntlite/ddi/net_stack.h | 4 +- code/public/ntlite/ddi/pci.h | 4 +- code/public/ntlite/dirent.h | 2 + code/public/ntlite/display.h | 4 +- code/public/ntlite/input.h | 4 +- code/public/ntlite/memory_map.h | 62 +- code/public/ntlite/status.h | 14 +- code/public/ntlite/string_view.h | 15 + code/public/ntlite/syscall.h | 56 +- code/public/ntlite/time.h | 2 + code/user/apps/edit/edit.c | 38 +- code/user/apps/httpget/httpget.c | 15 + code/user/apps/ping/ping.c | 17 + code/user/apps/resolve/resolve.c | 8 + code/user/apps/shell_native/shell_native.c | 68 +- code/user/apps/shell_posix/shell_posix.c | 14 + code/user/apps/shell_win32/shell_win32.c | 18 +- code/user/apps/tcpserve/tcpserve.c | 10 + code/user/apps/udp/udp.c | 16 +- code/user/apps/video/video.c | 8 +- code/user/personalities/posix/posix.h | 34 +- code/user/personalities/posix/posix_dir.c | 8 +- code/user/personalities/posix/posix_fd.c | 8 +- code/user/personalities/posix/posix_fd.h | 4 +- code/user/personalities/posix/posix_io.c | 13 +- code/user/personalities/posix/posix_path.c | 6 +- code/user/personalities/posix/posix_path.h | 4 +- code/user/personalities/posix/posix_proc.c | 15 +- code/user/personalities/posix/posix_socket.c | 32 +- code/user/personalities/posix/posix_thread.c | 27 +- code/user/personalities/win32/gdi32.c | 51 +- code/user/personalities/win32/kernel32.c | 286 +++-- code/user/personalities/win32/ole32.c | 27 +- code/user/personalities/win32/user32.c | 22 +- code/user/personalities/win32/winmm.c | 25 +- code/user/runtime/heap.c | 24 +- code/user/runtime/heap_exports.c | 6 +- code/user/system/init/init.c | 13 +- code/user/tests/async_apc/async_apc.c | 8 + code/user/tests/async_cancel/async_cancel.c | 6 + 163 files changed, 3560 insertions(+), 2556 deletions(-) diff --git a/code/boot/uefi/main.c b/code/boot/uefi/main.c index ecad020..7bf1f07 100644 --- a/code/boot/uefi/main.c +++ b/code/boot/uefi/main.c @@ -1,5 +1,5 @@ -// boot/main.c - UEFI bootloader -// +// UEFI bootloader entry point. This file parses configuration, loads PE images, builds the initial page tables, converts the EFI memory map, and hands a BOOT_INFO block to the kernel. + // Responsibilities (see design ยง5.2): // 1. Parse boot.ini // 2. Read drivers/drivers.ini @@ -10,8 +10,7 @@ // 7. Convert EFI memory map -> MEMORY_MAP // 8. ExitBootServices // 9. Set up minimal GDT/IDT, enable NXE, set CR3 -// 10. Fill BOOT_INFO and jump to KernelMain -// +// 10. Fill BOOT_INFO and jump to KernelMain. #include #include @@ -28,6 +27,7 @@ int _fltused = 0; #define PHYS_MAP_BASE 0xFFFF880000000000ULL #define PAGE_SIZE 4096ULL +// Implements the ascii Str To Unicode Str S operation. static int AsciiStrToUnicodeStrS(const char* Source, uint16_t* Dest, size_t DestMax) { if (!Source || !Dest || !DestMax) return -1; @@ -39,6 +39,7 @@ static int AsciiStrToUnicodeStrS(const char* Source, uint16_t* Dest, size_t Dest return -1; // Buffer too small } +// Implements the ascii Str Cpy S operation. int AsciiStrCpyS(char* Dest, size_t DestMax, const char* Source) { if (!Dest || !Source || !DestMax) return -1; @@ -50,11 +51,12 @@ int AsciiStrCpyS(char* Dest, size_t DestMax, const char* Source) { return -1; } +// Implements the unicode Str To Ascii Str S operation. int UnicodeStrToAsciiStrS(const uint16_t* Source, char* Dest, size_t DestMax) { if (!Source || !Dest || !DestMax) return -1; for (size_t i = 0; i < DestMax; i++) { - // Narrowing: only taking the lower 8 bits + // Narrowing: only taking the lower 8 bits. Dest[i] = (char)(Source[i] & 0xFF); if (Source[i] == 0) return 0; @@ -64,9 +66,7 @@ int UnicodeStrToAsciiStrS(const uint16_t* Source, char* Dest, size_t DestMax) { return -1; } -// --------------------------------------------------------------------------- -// PE32+ checksum validation -// --------------------------------------------------------------------------- +// Validates the PE32+ checksum using the same field layout the Windows loader expects. static UINT32 ComputePeChecksum(const UINT8* buf, UINTN size) { UINT64 checksum = 0; const UINT16* words = (const UINT16 *)buf; @@ -88,20 +88,18 @@ static UINT32 ComputePeChecksum(const UINT8* buf, UINTN size) { checksum = (checksum & 0xFFFF) + (checksum >> 16); checksum += (UINT64)size; - // Restore. + // Restore the image buffer before returning so checksum validation is non-destructive. ((UINT16 *)buf)[cksumOff / 2] = savedLo; ((UINT16 *)buf)[cksumOff / 2 + 1] = savedHi; return (UINT32)checksum; } -// --------------------------------------------------------------------------- -// Page table helpers -// --------------------------------------------------------------------------- +// Allocates and links the minimal x86-64 page tables used before KernelMain runs. static UINT64* AllocPage(EFI_PHYSICAL_ADDRESS* physOut) { VOID* mem = NULL; gBS->AllocatePages(AllocateAnyPages, EfiLoaderData, 1, (EFI_PHYSICAL_ADDRESS *)&mem); gBS->SetMem(mem, PAGE_SIZE, 0); - if (physOut) *physOut = (EFI_PHYSICAL_ADDRESS)mem; // identity-mapped in UEFI + if (physOut) *physOut = (EFI_PHYSICAL_ADDRESS)mem; // UEFI identity maps loader allocations here. return (UINT64 *)mem; } @@ -115,6 +113,7 @@ static UINT64* AllocPage(EFI_PHYSICAL_ADDRESS* physOut) { static UINT64* gPml4; +// Implements the ensure Table operation. static UINT64* EnsureTable(UINT64* parent, UINTN index) { UINT64* entry = &parent[index]; if (!(*entry & 1)) { @@ -126,6 +125,7 @@ static UINT64* EnsureTable(UINT64* parent, UINTN index) { return (UINT64 *)(*entry & ~0xFFFULL); } +// Implements the map4 K operation. static void Map4K(UINT64 virt, UINT64 phys, UINT64 flags) { UINT64* pdpt = EnsureTable(gPml4, PML4_IDX(virt)); UINT64* pdt = EnsureTable(pdpt, PDPT_IDX(virt)); @@ -133,17 +133,20 @@ static void Map4K(UINT64 virt, UINT64 phys, UINT64 flags) { pt[PT_IDX(virt)] = phys | flags; } +// Implements the map2 M operation. static void Map2M(UINT64 virt, UINT64 phys, UINT64 flags) { UINT64* pdpt = EnsureTable(gPml4, PML4_IDX(virt)); UINT64* pdt = EnsureTable(pdpt, PDPT_IDX(virt)); pdt[PDT_IDX(virt)] = phys | flags | 0x80ULL; // PS bit } +// Implements the map1 G operation. static void Map1G(UINT64 virt, UINT64 phys, UINT64 flags) { UINT64* pdpt = EnsureTable(gPml4, PML4_IDX(virt)); pdpt[PDPT_IDX(virt)] = phys | flags | 0x80ULL; // PS bit } +// Maps range Smart. static void MapRangeSmart(UINT64 virt, UINT64 phys, UINT64 size, UINT64 flags) { while (size) { if ((virt & (PAGE_1G - 1)) == 0 && (phys & (PAGE_1G - 1)) == 0 && size >= PAGE_1G) { @@ -195,34 +198,33 @@ static void MapRangeSkipping(UINT64 virt, UINT64 phys, UINT64 size, UINT64 flags } } -// --------------------------------------------------------------------------- -// File loading -// --------------------------------------------------------------------------- +// File loading. static EFI_FILE_PROTOCOL* gRoot; +// Loads file. static UINT8* LoadFile(CHAR16* path, UINTN* sizeOut) { EFI_STATUS Status; EFI_FILE_PROTOCOL* fh; - // Open the file + // Open the file. Status = gRoot->Open(gRoot, &fh, path, EFI_FILE_MODE_READ, 0); if (EFI_ERROR(Status)) return NULL; - // Get the correct buffer size for EFI_FILE_INFO + // Get the correct buffer size for EFI_FILE_INFO. EFI_FILE_INFO* info; UINTN infoSz = 0; - // This first call will fail but will return the required size in infoSz + // This first call will fail but will return the required size in infoSz. fh->GetInfo(fh, &gEfiFileInfoGuid, &infoSz, NULL); - // Allocate the buffer for the info struct + // Allocate the buffer for the info struct. info = AllocatePool(infoSz); if (info == NULL) { fh->Close(fh); return NULL; } - // Now actually get the info + // Now actually get the info. Status = fh->GetInfo(fh, &gEfiFileInfoGuid, &infoSz, info); if (EFI_ERROR(Status)) { FreePool(info); @@ -230,7 +232,7 @@ static UINT8* LoadFile(CHAR16* path, UINTN* sizeOut) { return NULL; } - // Allocate buffer for file content + // Allocate buffer for file content. UINTN sz = (UINTN)info->FileSize; FreePool(info); // Don't need this anymore @@ -240,7 +242,7 @@ static UINT8* LoadFile(CHAR16* path, UINTN* sizeOut) { return NULL; } - // Read the file into the buffer + // Read the file into the buffer. Status = fh->Read(fh, &sz, buf); fh->Close(fh); @@ -253,9 +255,7 @@ static UINT8* LoadFile(CHAR16* path, UINTN* sizeOut) { return buf; } -// --------------------------------------------------------------------------- -// INI parsing state -// --------------------------------------------------------------------------- +// INI parsing state. typedef struct { BOOT_INFO* bi; CHAR16 drivers[32][64]; @@ -265,6 +265,7 @@ typedef struct { } PARSE_STATE; +// Parses boot Ini Integer. static int ParseBootIniInteger(const char* val) { int out = 0; if (!val) return 0; @@ -290,10 +291,10 @@ static int ParseBootIniInteger(const char* val) { static void BootIniCb(const char* section, const char* key, const char* val, void* ud) { PARSE_STATE* s = (PARSE_STATE *)ud; - // [kernel] debug = bitmask: 1=console, 2=selftests, 4=file log + // [kernel] debug = bitmask: 1=console, 2=selftests, 4=file log. if (!AsciiStrCmp(section, "kernel") && !AsciiStrCmp(key, "debug")) s->debug = ParseBootIniInteger(val); - // [init] commandline = hello.exe + // [init] commandline = hello.exe. else if (!AsciiStrCmp(section, "init") && !AsciiStrCmp(key, "commandline")) AsciiStrCpyS(s->commandLine, 64, val); } @@ -308,9 +309,7 @@ static void DriversIniCb(const char* section, const char* key, } } -// --------------------------------------------------------------------------- -// EFI Memory Map -> MEMORY_MAP conversion -// --------------------------------------------------------------------------- +// EFI Memory Map -> MEMORY_MAP conversion. static EFI_PHYSICAL_ADDRESS AllocateApTrampolinePageBelow1M(void) { // AP startup via SIPI requires the first instruction page to live below @@ -326,6 +325,7 @@ static EFI_PHYSICAL_ADDRESS AllocateApTrampolinePageBelow1M(void) { return phys; } +// Converts memory Map. static void ConvertMemoryMap(MEMORY_MAP* out) { UINTN mapSize = 0, descSz = 0, mapKey; UINT32 descVer; gBS->GetMemoryMap(&mapSize, NULL, &mapKey, &descSz, &descVer); @@ -402,7 +402,7 @@ typedef struct { #define IMAGE_ORDINAL_FLAG64 0x8000000000000000ULL -// --- Essential PE Structures (if not in your headers) --- +// These PE structures are kept local because the bootloader only needs the subset used by image loading. #pragma pack(push, 1) typedef struct { UINT32 VirtualAddress; @@ -428,36 +428,36 @@ typedef struct { } IMAGE_SECTION_HEADER; #pragma pack(pop) -// --- The PE Loader --- +// The PE loader maps image sections into their final virtual addresses before the kernel switches page tables. EFI_STATUS LoadPeImage(UINT8* rawFile, UINT64 virtDest, EFI_PHYSICAL_ADDRESS* outPhys) { UINT32 peOff = *(UINT32*)(rawFile + 0x3C); UINT8* ntHeaders = rawFile + peOff; - // Validate Signature + // Validate Signature. if (*(UINT32*)ntHeaders != 0x00004550) { Print(L"Signature mismatch\n"); return EFI_INVALID_PARAMETER; } // "PE\0\0" UINT16 sizeOfOptHeader = *(UINT16*)(ntHeaders + 20); UINT16 numSections = *(UINT16*)(ntHeaders + 6); - // Offsets for PE32+ (64-bit) + // Offsets for PE32+ (64-bit). UINT64 imageBase = *(UINT64*)(ntHeaders + 24 + 24); UINT32 sizeOfImage = *(UINT32*)(ntHeaders + 24 + 56); UINT32 sizeOfHeaders = *(UINT32*)(ntHeaders + 24 + 60); IMAGE_DATA_DIRECTORY* dataDirs = (IMAGE_DATA_DIRECTORY*)(ntHeaders + 24 + 112); IMAGE_DATA_DIRECTORY* relocDir = &dataDirs[5]; - //IMAGE_DATA_DIRECTORY* importDir = &dataDirs[1]; + //IMAGE_DATA_DIRECTORY* importDir = &dataDirs[1];. - // Allocate Physical Memory for the mapped image + // Allocate Physical Memory for the mapped image. UINTN pages = (sizeOfImage + PAGE_SIZE - 1) / PAGE_SIZE; EFI_PHYSICAL_ADDRESS physBase; gBS->AllocatePages(AllocateAnyPages, EfiLoaderData, pages, &physBase); gBS->SetMem((VOID*)physBase, pages * PAGE_SIZE, 0); - // Copy Headers + // Copy Headers. gBS->CopyMem((VOID*)physBase, rawFile, sizeOfHeaders); - // Map Sections to their RVAs + // Map Sections to their RVAs. IMAGE_SECTION_HEADER* sections = (IMAGE_SECTION_HEADER*)(ntHeaders + 24 + sizeOfOptHeader); for (int i = 0; i < numSections; i++) { if (sections[i].SizeOfRawData > 0) { @@ -497,11 +497,12 @@ EFI_STATUS LoadPeImage(UINT8* rawFile, UINT64 virtDest, EFI_PHYSICAL_ADDRESS* ou return EFI_SUCCESS; } +// Returns export Rva. static UINT32 GetExportRva(UINT8* providerPhys, const char* funcName) { UINT32 peOff = *(UINT32*)(providerPhys + 0x3C); UINT8* ntHeaders = providerPhys + peOff; - // Export Dir is index 0 in the DataDirectory array + // Export Dir is index 0 in the DataDirectory array. UINT32 exportDirRva = *(UINT32*)(ntHeaders + 24 + 112); if (!exportDirRva) return 0; // No exports! @@ -511,7 +512,7 @@ static UINT32 GetExportRva(UINT8* providerPhys, const char* funcName) { UINT32* addrOfNames = (UINT32*)(providerPhys + exports->AddressOfNames); UINT16* addrOfOrdinals = (UINT16*)(providerPhys + exports->AddressOfNameOrdinals); - // Binary search is faster, but linear is fine for a bootloader + // Binary search is faster, but linear is fine for a bootloader. for (UINT32 i = 0; i < exports->NumberOfNames; i++) { char* name = (char*)(providerPhys + addrOfNames[i]); if (AsciiStrCmp(name, funcName) == 0) { @@ -526,13 +527,13 @@ EFI_STATUS ResolveImports(UINT8* consumerPhys, UINT8* providerPhys, UINT64 provi UINT32 peOff = *(UINT32*)(consumerPhys + 0x3C); UINT8* ntHeaders = consumerPhys + peOff; - // Import Dir is index 1 in the DataDirectory array + // Import Dir is index 1 in the DataDirectory array. UINT32 importDirRva = *(UINT32*)(ntHeaders + 24 + 112 + 8); if (!importDirRva) return EFI_SUCCESS; // No imports to resolve IMAGE_IMPORT_DESCRIPTOR* importDesc = (IMAGE_IMPORT_DESCRIPTOR*)(consumerPhys + importDirRva); - // Iterate through all imported DLLs + // Iterate through all imported DLLs. while (importDesc->Name != 0) { char* dllName = (char*)(consumerPhys + importDesc->Name); @@ -551,11 +552,11 @@ EFI_STATUS ResolveImports(UINT8* consumerPhys, UINT8* providerPhys, UINT64 provi int i = 0; while (origFirstThunk[i].u1.Function != 0) { if (origFirstThunk[i].u1.Ordinal & IMAGE_ORDINAL_FLAG64) { - // Import by Ordinal (Usually you don't do this in modern kernels, but good to handle) + // Import by Ordinal (Usually you don't do this in modern kernels, but good to handle). Print(L"Error: Ordinal imports not supported in basic loader.\n"); return EFI_UNSUPPORTED; } else { - // Import by Name + // Import by Name. IMAGE_IMPORT_BY_NAME* importByName = (IMAGE_IMPORT_BY_NAME*)(consumerPhys + origFirstThunk[i].u1.AddressOfData); char* funcName = (char*)importByName->Name; @@ -579,17 +580,15 @@ EFI_STATUS ResolveImports(UINT8* consumerPhys, UINT8* providerPhys, UINT64 provi return EFI_SUCCESS; } -// --------------------------------------------------------------------------- -// UefiMain -// --------------------------------------------------------------------------- +// UefiMain. EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { InitializeLib(ImageHandle, SystemTable); - // Open root filesystem on the device we actually booted from + // Open root filesystem on the device we actually booted from. EFI_LOADED_IMAGE_PROTOCOL* LoadedImage; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* fs; - // Get the LoadedImage protocol for this application + // Get the LoadedImage protocol for this application. EFI_STATUS Status = gBS->HandleProtocol( ImageHandle, &gEfiLoadedImageProtocolGuid, @@ -601,7 +600,7 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable return Status; } - // Get the SimpleFileSystem protocol for the device we were loaded from + // Get the SimpleFileSystem protocol for the device we were loaded from. Status = gBS->HandleProtocol( LoadedImage->DeviceHandle, &gEfiSimpleFileSystemProtocolGuid, @@ -613,16 +612,16 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable return Status; } - // Open the volume + // Open the volume. Status = fs->OpenVolume(fs, &gRoot); if (EFI_ERROR(Status)) { Print(L"Failed to open root volume\n"); return Status; } - //Print(L"1\n"); + //Print(L"1\n");. - // --- Parse boot.ini --- + // boot.ini controls debugger and runtime policy before the kernel has a filesystem service. UINTN sz; UINT8* bootIniRaw = LoadFile(L"boot.ini", &sz); PARSE_STATE ps = {0}; @@ -633,9 +632,9 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable FreePool(bootIniRaw); } - //Print(L"2\n"); + //Print(L"2\n");. - // --- Parse drivers/drivers.ini --- + // drivers.ini decides which boot and runtime drivers are loaded into the initial module list. UINT8* drvIniRaw = LoadFile(L"drivers\\drivers.ini", &sz); if (drvIniRaw) { char* txt = (char *)drvIniRaw; @@ -644,7 +643,7 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable FreePool(drvIniRaw); } - //Print(L"3\n"); + //Print(L"3\n");. BOOT_INFO* bi = AllocateZeroPool(sizeof(BOOT_INFO)); bi->Magic = BOOT_INFO_MAGIC; @@ -676,23 +675,24 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable // Current mapping cursor for upper half. UINT64 virtCursor = KERNEL_VIRT_BASE; - //Print(L"4\n"); + //Print(L"4\n");. - // --- Load and validate PE images --- + // Core images are loaded first because driver import resolution depends on them. typedef struct { - CHAR16* path; - char name[32]; - UINT8* physBase; // Temporary storage for import resolution - UINT64 virtBase; + CHAR16* path; + char name[32]; + UINT8* physBase; // Temporary storage for import resolution. + UINT64 virtBase; } MODULE_LOAD_INFO; MODULE_LOAD_INFO core[] = { { L"system\\colonel.exe", "kernel.exe", NULL, KERNEL_VIRT_BASE }, - { L"system\\hal.dll", "hal.dll", NULL, 0 /* Calculated dynamically */ }, + // The HAL virtual size is filled after the image is loaded because it depends on the PE headers. + { L"system\\hal.dll", "hal.dll", NULL, 0 }, }; for (int i = 0; i < 2; i++) { - //Print(L"Loading %s...\n", core[i].path); + // The firmware console can be noisy here, so per-module load prints stay disabled unless early loader debugging is needed. UINTN rawSize; UINT8* rawBuf = LoadFile(core[i].path, &rawSize); if (!rawBuf) { @@ -701,7 +701,7 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable return EFI_NOT_FOUND; } - // Map sections and apply base relocations + // Map sections and apply base relocations. EFI_PHYSICAL_ADDRESS physBase; EFI_STATUS status = LoadPeImage(rawBuf, virtCursor, &physBase); if (EFI_ERROR(status)) { @@ -710,30 +710,30 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable return status; } - // Store locations for the Import Resolver + // Store image locations so the import resolver can patch cross-module references. core[i].physBase = (UINT8*)physBase; core[i].virtBase = virtCursor; - // Map the pages into the new PML4 - // We need the SizeOfImage from the mapped headers + // Images are mapped by SizeOfImage so zero-filled sections occupy their final virtual range. UINT32 peOff = *(UINT32*)(rawBuf + 0x3C); UINT32 imgLen = *(UINT32*)(rawBuf + peOff + 4 + 20 + 56); // SizeOfImage imgLen = (imgLen + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); for (UINT64 off = 0; off < imgLen; off += PAGE_SIZE) { - Map4K(virtCursor + off, physBase + off, 0x03 /* P|W */); + // The bootloader keeps the flag literal local because this file owns its minimal page-table encoder. + Map4K(virtCursor + off, physBase + off, 0x03); } - // Fill BOOT_INFO + // Fill BOOT_INFO. AsciiStrCpyS(bi->Modules[bi->ModuleCount].Name, 32, core[i].name); bi->Modules[bi->ModuleCount].VirtBase = virtCursor; bi->Modules[bi->ModuleCount].ImageSize = imgLen; bi->ModuleCount++; - // Increment cursor (1MB alignment for safety) + // Increment cursor (1MB alignment for safety). virtCursor = (virtCursor + imgLen + 0xFFFFF) & ~0xFFFFF; - // We can free the raw file buffer now; sections are in physBase + // We can free the raw file buffer now; sections are in physBase. FreePool(rawBuf); } @@ -742,9 +742,9 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable while(true); } - //Print(L"5\n"); + //Print(L"5\n");. - // Load driver .sys files into raw buffers + // Load driver .sys files into raw buffers. for (int i = 0; i < ps.driverCount; i++) { CHAR16 path[128]; UnicodeSPrint(path, sizeof(path), L"drivers\\%s", ps.drivers[i]); @@ -756,7 +756,7 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable continue; } - // Store file info for the kernel to process later + // Store file info for the kernel to process later. char name[32]; UnicodeStrToAsciiStrS(ps.drivers[i], name, 32); @@ -767,9 +767,9 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable mod->VirtBase = 0; // Kernel will map this later } - //Print(L"6\n"); + //Print(L"6\n");. - // Query GOP FIRST, before the GetMemoryMap loop + // Query GOP FIRST, before the GetMemoryMap loop. EFI_GRAPHICS_OUTPUT_PROTOCOL* gop; UINT64 fbBase = 0; UINT64 fbBytes = 0; @@ -795,11 +795,11 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable } } - //Print(L"7\n"); + //Print(L"7\n");. bi->ApTrampolinePhys = (uintptr_t)AllocateApTrampolinePageBelow1M(); - // --- Map physical RAM as direct window AND identity map --- + // Usable RAM is mapped both through the physical direct window and identity mappings until the final CR3 switch. UINTN mapSize = 0, descSz = 0, mapKey; UINT32 descVer; gBS->GetMemoryMap(&mapSize, NULL, &mapKey, &descSz, &descVer); mapSize += 8 * descSz; @@ -886,9 +886,7 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable } FreePool(efiMap); - // ------------------------------------------------------------------------- // Explicitly Map Standard Architectural MMIO - // ------------------------------------------------------------------------- // Motherboards frequently omit the APIC/IOAPIC/HPET from the UEFI memory map. // We explicitly map the region from 0xFEC00000 up through 0xFEE00FFF // to guarantee the HAL can access them via the physical window. @@ -897,24 +895,24 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable Map4K(PHYS_MAP_BASE + phys, phys, 0x13); // Physical Window Map, P|W|PCD } - //Print(L"8\n"); + //Print(L"8\n");. - // --- Convert EFI memory map -> MEMORY_MAP --- + // The kernel consumes a compact memory map so it does not need EFI descriptor semantics after boot. ConvertMemoryMap(&bi->MemoryMap); - // --- Locate ACPI RSDP --- - // Define the standard UEFI ACPI GUIDs + // The RSDP physical address is captured before firmware services are unavailable. + // Define the standard UEFI ACPI GUIDs. EFI_GUID acpi2Guid = { 0x8868e871, 0xe4f1, 0x11d3, {0xbc, 0x22, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81} }; EFI_GUID acpi1Guid = { 0xeb9d2d30, 0x2d88, 0x11d3, {0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }; bi->RsdpPhysical = 0; void* acpi1Table = NULL; - // Search the UEFI Configuration Table + // Search the UEFI Configuration Table. for (UINTN i = 0; i < SystemTable->NumberOfTableEntries; i++) { EFI_GUID* vendorGuid = &SystemTable->ConfigurationTable[i].VendorGuid; - // Check for ACPI 2.0 (Preferred) + // Check for ACPI 2.0 (Preferred). if (vendorGuid->Data1 == acpi2Guid.Data1 && vendorGuid->Data2 == acpi2Guid.Data2 && vendorGuid->Data3 == acpi2Guid.Data3 && @@ -925,7 +923,7 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable break; // Found the best one, stop searching } - // Check for ACPI 1.0 (Fallback) + // Check for ACPI 1.0 (Fallback). if (vendorGuid->Data1 == acpi1Guid.Data1 && vendorGuid->Data2 == acpi1Guid.Data2 && vendorGuid->Data3 == acpi1Guid.Data3 && @@ -936,24 +934,24 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable } } - // Fallback to ACPI 1.0 if ACPI 2.0 wasn't found + // Fallback to ACPI 1.0 if ACPI 2.0 wasn't found. if (bi->RsdpPhysical == 0 && acpi1Table != NULL) { bi->RsdpPhysical = (UINT64)acpi1Table; } // Print it out to verify the bootloader actually found it before launching the kernel - //Print(L"Found RSDP at: 0x%016llX\n", bi->RsdpPhysical); + //Print(L"Found RSDP at: 0x%016llX\n", bi->RsdpPhysical);. bi->PhysicalMapBase = PHYS_MAP_BASE; bi->Debug = (UINT32)ps.debug; - //Print(L"9\n"); + //Print(L"9\n");. - // --- ExitBootServices --- + // ExitBootServices is the point of no return for firmware allocation, file I/O, and protocol access. gBS->GetMemoryMap(&mapSize, NULL, &mapKey, &descSz, &descVer); gBS->ExitBootServices(ImageHandle, mapKey); - // --- Load minimal GDT / IDT, enable NXE, set CR3 --- + // The bootloader installs the CPU state the kernel expects before jumping into the upper half. // (These are inline since we have no runtime services after ExitBootServices.) // GDT is set up by the kernel's KeInitializeGdt; we just need a valid one to // reach KernelMain. The bootloader installed a flat 64-bit GDT earlier via @@ -966,7 +964,7 @@ EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable // Switch to our new PML4. __writecr3((UINT64)gPml4); - // --- Jump to KernelMain --- + // KernelMain receives BOOT_INFO in the new address space and takes ownership of the machine. typedef void (*KERNEL_ENTRY)(BOOT_INFO *); KERNEL_ENTRY KernelMain = (KERNEL_ENTRY)bi->Modules[0].VirtBase; diff --git a/code/build/build.c b/code/build/build.c index 9ffbda8..5bcbee4 100644 --- a/code/build/build.c +++ b/code/build/build.c @@ -1,10 +1,10 @@ +// Project build orchestrator. This file describes the Windows/MSVC build graph and keeps driver dependencies explicit. + #define NOB_IMPLEMENTATION #include "nob.h" -// Replicate your compiler and linker flags. Keep the literals in macros so -// they can be used in file-scope aggregate initializers. MSVC C rejects -// initializing a static object with the value of another object, even if that -// object is a const char*. +// Compiler and linker flags stay in macros so they can be used in file-scope aggregate initializers. +// MSVC C rejects initializing a static object from another object, even when the source object is const. #define CFLAGS_LITERAL "/nologo /W3 /WX /Od /GS- /Gs999999 /Gz /Gy /EHsc- /GR- /Oi- /Z7 /std:c17 /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /Icode\\public /Icode\\common\\include /Icode\\kernel\\include" #define LWIP_CFLAGS_LITERAL CFLAGS_LITERAL " /Icode\\drivers\\net\\lwip\\include /Icode\\third_party\\lwip\\src\\include /wd4005 /wd4100 /wd4103 /wd4127 /wd4244 /wd4267 /wd4706" #define LFLAGS_LITERAL "/nologo /NODEFAULTLIB /DEBUG" @@ -39,6 +39,7 @@ static const Driver_Target STANDALONE_DRIVERS[] = { DRIVER_TARGET_LIBS("rtl8139", "obj\\drivers\\rtl8139", "code\\drivers\\net\\rtl8139\\rtl8139.c", "bin\\pci.lib"), }; +// Creates layout. void create_layout() { const char *dirs[] = { "obj", "bin", "obj\\boot", "obj\\kernel", "obj\\lwip", "obj\\hal", @@ -52,7 +53,7 @@ void create_layout() { for (size_t i = 0; i < NOB_ARRAY_LEN(STANDALONE_DRIVERS); i++) nob_mkdir_if_not_exists(STANDALONE_DRIVERS[i].obj_dir); } -// Helper to run a shell command string and wait for it +// Runs a shell command and waits for it to finish. bool run_sync(const char *cmd_str) { Nob_Cmd cmd = {0}; nob_cmd_append(&cmd, "cmd.exe", "/c", cmd_str); @@ -61,7 +62,7 @@ bool run_sync(const char *cmd_str) { return ok; } -// Helper to launch a shell command into the background +// Launches a shell command while the build graph continues. Nob_Proc run_async(const char *cmd_str) { Nob_Cmd cmd = {0}; nob_cmd_append(&cmd, "cmd.exe", "/c", cmd_str); @@ -70,18 +71,19 @@ Nob_Proc run_async(const char *cmd_str) { return proc; } +// Runs the requested operation. int main(int argc, char **argv) { - // Magic macro: Checks if build.c is newer than build.exe and recompiles itself if so + // The build tool rebuilds itself before doing any real work so the graph below matches the source. NOB_GO_REBUILD_URSELF(argc, argv); - // 1. Initial Checks & Setup + // The disk image must exist before the build can copy fresh binaries into it. if (!nob_file_exists("disk.vhd")) { nob_log(NOB_INFO, "disk.vhd missing, calling mkimage.bat..."); if (!run_sync("mkimage.bat")) return 1; } create_layout(); - // 2. Sequential Phase (Bootloader, Core Kernel, and DLLs) + // Core images build sequentially because later images link against earlier import libraries. nob_log(NOB_INFO, "--- Building Core Subsystems ---"); const char *core_tasks[] = { @@ -96,16 +98,16 @@ int main(int argc, char **argv) { nob_temp_sprintf("cl %s /c /Foobj\\runtime\\user_heap.obj code\\user\\runtime\\heap.c", CFLAGS), nob_temp_sprintf("cl %s /c /Foobj\\runtime\\user_heap_exports.obj code\\user\\runtime\\heap_exports.c", CFLAGS), - // Bootloader + // Bootloader. nob_temp_sprintf("cl %s /MP /c /Icode\\boot\\uefi\\include /Foobj\\boot\\ code\\boot\\uefi\\*.c && link %s /FORCE:MULTIPLE /SUBSYSTEM:EFI_APPLICATION /ENTRY:UefiMain /OUT:bin\\bootx64.efi obj\\libc.obj obj\\ini_parser.obj code\\boot\\uefi\\efilib.lib obj\\boot\\*.obj", CFLAGS, LFLAGS), - // HAL + // HAL. nob_temp_sprintf("cl %s /MP /c /Foobj\\hal\\ code\\kernel\\hal\\*.c && link %s /DLL /OUT:bin\\hal.dll /ENTRY:HalInitialize /IGNORE:4216 obj\\printf.obj obj\\libc.obj obj\\hal\\*.obj", CFLAGS, LFLAGS), - // Kernel + // Kernel. nob_temp_sprintf("cl %s /DKE_DISPLAY_BUILD /MP /c /Foobj\\kernel\\ code\\kernel\\*.c && link %s /SUBSYSTEM:NATIVE /ENTRY:KernelMain /OUT:bin\\kernel.exe bin\\hal.lib obj\\ini_parser.obj obj\\printf.obj obj\\libc.obj obj\\kernel\\*.obj", CFLAGS, LFLAGS), - // Subsystem DLLs + // Subsystem DLLs. "link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\syscall.dll obj\\syscall\\stubs.obj", nob_temp_sprintf("cl %s /DUSER_HEAP_EXPORTS /MP /c /Foobj\\win32\\ code\\user\\runtime\\heap.c code\\user\\runtime\\heap_exports.c code\\user\\personalities\\win32\\*.c && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\win32.dll bin\\syscall.lib obj\\libc.obj obj\\win32\\*.obj", CFLAGS), nob_temp_sprintf("cl %s /DUSER_HEAP_EXPORTS /MP /c /Foobj\\posix\\ code\\user\\runtime\\heap.c code\\user\\runtime\\heap_exports.c code\\user\\personalities\\posix\\*.c && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\posix.dll bin\\syscall.lib obj\\libc.obj obj\\posix\\*.obj", CFLAGS) @@ -115,8 +117,7 @@ int main(int argc, char **argv) { if (!run_sync(core_tasks[i])) return 1; } - // 3. Driver dependency phase. pci.sys owns PCI enumeration and exports - // bin\pci.lib, so it must be built before PCI function drivers link. + // PCI builds before PCI function drivers because it exports the bus-driver import library. nob_log(NOB_INFO, "--- Building Bus Drivers ---"); const char *pci_cmd = nob_temp_sprintf( "cl %s /MP /c /Fo%s\\ %s && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\%s.sys /IMPLIB:bin\\%s.lib /ENTRY:DriverEntry bin\\hal.lib bin\\kernel.lib obj\\printf.obj obj\\libc.obj %s\\*.obj", @@ -125,7 +126,7 @@ int main(int argc, char **argv) { ); if (!run_sync(pci_cmd)) return 1; - // 4. Parallel Phase (Drivers and Applications) + // 4. Parallel Phase (Drivers and Applications). nob_log(NOB_INFO, "--- Compiling Drivers and Apps in Parallel ---"); Nob_Procs procs = {0}; @@ -141,7 +142,7 @@ int main(int argc, char **argv) { nob_da_append(&procs, run_async(cmd)); } - // Parse lwIP Sources and Queue it + // Parse lwIP Sources and Queue it. Nob_String_Builder sb = {0}, lwip_files = {0}; if (nob_read_entire_file("code\\drivers\\net\\lwip\\lwip_sources.txt", &sb)) { Nob_String_View sv = nob_sv_from_parts(sb.items, sb.count); @@ -157,9 +158,9 @@ int main(int argc, char **argv) { nob_da_append(&procs, run_async(nob_temp_sprintf("cl %s /MP /c /Foobj\\lwip\\ %s && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\lwip.sys /ENTRY:DriverEntry bin\\hal.lib bin\\kernel.lib obj\\libc.obj obj\\lwip\\*.obj", LWIP_CFLAGS, lwip_files.items))); } - // Queue Subsystem Applications + // Queue Subsystem Applications. const char *apps[][4] = { - // Folder, Libs, Name, Optional Extra Link Args + // Folder, Libs, Name, Optional Extra Link Args. {"system\\init", "bin\\syscall.lib obj\\libc.obj obj\\runtime\\user_heap.obj obj\\runtime\\user_heap_exports.obj", "init", "/ENTRY:_start"}, {"apps\\shell_win32", "bin\\win32.lib obj\\libc.obj", "shell_win32", "/ENTRY:main"}, {"apps\\shell_posix", "bin\\posix.lib obj\\libc.obj", "shell_posix", "/ENTRY:main"}, @@ -184,16 +185,16 @@ int main(int argc, char **argv) { nob_da_append(&procs, run_async(cmd)); } - // Wait for everything to link simultaneously + // Wait for everything to link simultaneously. if (!nob_procs_wait(procs)) { nob_log(NOB_ERROR, "One or more parallel build jobs failed!"); return 1; } - // 4. Mounting & Packing Image + // 4. Mounting & Packing Image. nob_log(NOB_INFO, "--- Mounting disk.vhd ---"); - // Resolve the absolute path to disk.vhd for diskpart + // Resolve the absolute path to disk.vhd for diskpart. char vhd_path[MAX_PATH]; GetFullPathNameA("disk.vhd", MAX_PATH, vhd_path, NULL); diff --git a/code/common/include/common/ini_parser.h b/code/common/include/common/ini_parser.h index a169759..9381b6d 100644 --- a/code/common/include/common/ini_parser.h +++ b/code/common/include/common/ini_parser.h @@ -1,4 +1,6 @@ -#pragma once -typedef void (*IniCallback)(const char* section, const char* key, - const char* value, void* userdata); -void IniParse(char* buf, IniCallback cb, void* userdata); +// Shared INI parser declarations for boot and kernel configuration readers. + +#pragma once +typedef void (*IniCallback)(const char* section, const char* key, + const char* value, void* userdata); +void IniParse(char* buf, IniCallback cb, void* userdata); diff --git a/code/common/ini_parser.c b/code/common/ini_parser.c index f541b20..0a27732 100644 --- a/code/common/ini_parser.c +++ b/code/common/ini_parser.c @@ -1,16 +1,18 @@ -// ini_parser.c - minimal [section] key=value parser -// Used by the bootloader to read boot.ini and drivers/drivers.ini. -// No heap; caller provides fixed-size output buffers. +// Minimal INI parser. This file accepts the small configuration dialect used by boot.ini and drivers.ini. + #include #include +// Checks whether ws. static inline int IsWs(char c) { return c == ' ' || c == '\t' || c == '\r'; } +// Implements the trim Left operation. static char* TrimLeft(char* s) { while (*s && IsWs(*s)) s++; return s; } +// Implements the trim Right operation. static void TrimRight(char* s) { char* e = s + strlen(s); while (e > s && IsWs(*(e-1))) *--e = '\0'; diff --git a/code/common/libc.c b/code/common/libc.c index fc76cc9..89dc672 100644 --- a/code/common/libc.c +++ b/code/common/libc.c @@ -1,210 +1,226 @@ -// everyone needs a little libc -#include -#include -#include - -char* strcpy(char* dest, const char* src) { - char* d = dest; - while (*src) *d++ = *src++; - *d = 0; - return dest; -} - -char* strncpy(char* dest, const char* src, size_t n) { - size_t i; - for (i = 0; i < n && src[i]; i++) dest[i] = src[i]; - for (; i < n; i++) dest[i] = 0; - return dest; -} - -char* strcat(char* dest, const char* src) { - char* ptr = dest; - while (*ptr != '\0') { - ptr++; - } - while (*src != '\0') { - *ptr = *src; - ptr++; - src++; - } - *ptr = '\0'; - return dest; -} - -char* strncat(char* dest, const char* src, size_t n) { - char* ptr = dest; - while (*ptr != '\0') { - ptr++; - } - while (n > 0 && *src != '\0') { - *ptr = *src; - ptr++; - src++; - n--; - } - *ptr = '\0'; - return dest; -} - -int strcmp(const char* s1, const char* s2) { - while (*s1 && *s1 == *s2) s1++, s2++; - return (unsigned char)*s1 - (unsigned char)*s2; -} - -int strncmp(const char *s1, const char *s2, size_t n) { - while (n && *s1 && (*s1 == *s2)) { - s1++; - s2++; - n--; - } - return n == 0 ? 0 : *(unsigned char *)s1 - *(unsigned char *)s2; -} - -int _stricmp(const char* s1, const char* s2) { - // 0x20 (32) is the bit that differs between 'A' and 'a' - while (*s1 && ((*s1 | 0x20) == (*s2 | 0x20))) { - s1++, s2++; - } - return (unsigned char)(*s1 | 0x20) - (unsigned char)(*s2 | 0x20); -} - -size_t strlen(const char* s) { - size_t n = 0; - while (*s++) n++; - return n; -} - -size_t strnlen(const char *s, size_t maxlen) { - size_t len; - for (len = 0; len < maxlen; len++) { - if (s[len] == '\0') { - break; - } - } - return len; -} - -char* strchr(const char* s, int c) { - while (*s) { - if (*s == (char)c) return (char *)s; - s++; - } - return NULL; -} - -char* strrchr(const char* s, int c) { - char ch = (char)c; - const char* last = NULL; - do { - if (*s == ch) last = s; - } while (*s++); - return (char*)last; -} - -void* memset(void* dest, int c, size_t n) { - unsigned char* d = (unsigned char*)dest; - size_t qwords = n / 8; - size_t tail = n % 8; - - if (qwords > 0) { - uint64_t value = (unsigned char)c; - value |= value << 8; - value |= value << 16; - value |= value << 32; - __stosq((unsigned __int64*)d, value, qwords); - d += qwords * 8; - } - - if (tail > 0) { - __stosb(d, (unsigned char)c, tail); - } - - return dest; -} - -void* memcpy(void* dest, const void* src, size_t n) { - unsigned char* d = (unsigned char*)dest; - const unsigned char* s = (const unsigned char*)src; - size_t qwords = n / 8; - size_t tail = n % 8; - - if (qwords > 0) { - __movsq((unsigned __int64*)d, (const unsigned __int64*)s, qwords); - d += qwords * 8; - s += qwords * 8; - } - - if (tail > 0) { - __movsb(d, s, tail); - } - - return dest; -} - -void* memmove(void* dest, const void* src, size_t n) { - unsigned char* d = (unsigned char*)dest; - const unsigned char* s = (const unsigned char*)src; - - if (d < s) { - // Forward copy: safe to use chunked __movsq + tail - size_t qwords = n / 8; - size_t tail = n % 8; - if (qwords > 0) { - __movsq((unsigned __int64*)d, (const unsigned __int64*)s, qwords); - d += qwords * 8; - s += qwords * 8; - } - if (tail > 0) { - __movsb(d, s, tail); - } - } else if (d > s) { - // Backward copy: must process from end to avoid corruption - size_t qwords = n / 8; - size_t tail = n % 8; - - // Copy tail bytes first from the very end - if (tail > 0) { - for (size_t i = tail; i > 0; i--) { - d[qwords * 8 + i - 1] = s[qwords * 8 + i - 1]; - } - } - - // Copy 64-bit chunks backward - if (qwords > 0) { - unsigned __int64* dq = (unsigned __int64*)d; - const unsigned __int64* sq = (const unsigned __int64*)s; - for (size_t i = qwords; i > 0; i--) { - dq[i - 1] = sq[i - 1]; - } - } - } - return dest; -} - -int memcmp(const void* s1, const void* s2, size_t n) { - const unsigned __int64* a64 = (const unsigned __int64*)s1; - const unsigned __int64* b64 = (const unsigned __int64*)s2; - size_t qwords = n / 8; - size_t tail = n % 8; - - // Compare 8-byte blocks - for (size_t i = 0; i < qwords; i++) { - if (a64[i] != b64[i]) { - // Locate the exact mismatching byte within the quadword - const unsigned char* a8 = (const unsigned char*)&a64[i]; - const unsigned char* b8 = (const unsigned char*)&b64[i]; - for (size_t j = 0; j < 8; j++) { - if (a8[j] != b8[j]) return (int)a8[j] - (int)b8[j]; - } - } - } - - // Compare remaining tail bytes - const unsigned char* a8 = (const unsigned char*)(a64 + qwords); - const unsigned char* b8 = (const unsigned char*)(b64 + qwords); - for (size_t i = 0; i < tail; i++) { - if (a8[i] != b8[i]) return (int)a8[i] - (int)b8[i]; - } - - return 0; -} +// Small freestanding C runtime subset shared by boot, kernel, drivers, and user support libraries. + +#include +#include +#include + +// Implements the strcpy operation. +char* strcpy(char* dest, const char* src) { + char* d = dest; + while (*src) *d++ = *src++; + *d = 0; + return dest; +} + +// Implements the strncpy operation. +char* strncpy(char* dest, const char* src, size_t n) { + size_t i; + for (i = 0; i < n && src[i]; i++) dest[i] = src[i]; + for (; i < n; i++) dest[i] = 0; + return dest; +} + +// Implements the strcat operation. +char* strcat(char* dest, const char* src) { + char* ptr = dest; + while (*ptr != '\0') { + ptr++; + } + while (*src != '\0') { + *ptr = *src; + ptr++; + src++; + } + *ptr = '\0'; + return dest; +} + +// Implements the strncat operation. +char* strncat(char* dest, const char* src, size_t n) { + char* ptr = dest; + while (*ptr != '\0') { + ptr++; + } + while (n > 0 && *src != '\0') { + *ptr = *src; + ptr++; + src++; + n--; + } + *ptr = '\0'; + return dest; +} + +// Implements the strcmp operation. +int strcmp(const char* s1, const char* s2) { + while (*s1 && *s1 == *s2) s1++, s2++; + return (unsigned char)*s1 - (unsigned char)*s2; +} + +// Implements the strncmp operation. +int strncmp(const char *s1, const char *s2, size_t n) { + while (n && *s1 && (*s1 == *s2)) { + s1++; + s2++; + n--; + } + return n == 0 ? 0 : *(unsigned char *)s1 - *(unsigned char *)s2; +} + +// Implements the stricmp operation. +int _stricmp(const char* s1, const char* s2) { + // ASCII case folding works here because bit 0x20 distinguishes 'A' from 'a'. + while (*s1 && ((*s1 | 0x20) == (*s2 | 0x20))) { + s1++, s2++; + } + return (unsigned char)(*s1 | 0x20) - (unsigned char)(*s2 | 0x20); +} + +// Implements the strlen operation. +size_t strlen(const char* s) { + size_t n = 0; + while (*s++) n++; + return n; +} + +// Implements the strnlen operation. +size_t strnlen(const char *s, size_t maxlen) { + size_t len; + for (len = 0; len < maxlen; len++) { + if (s[len] == '\0') { + break; + } + } + return len; +} + +// Implements the strchr operation. +char* strchr(const char* s, int c) { + while (*s) { + if (*s == (char)c) return (char *)s; + s++; + } + return NULL; +} + +// Implements the strrchr operation. +char* strrchr(const char* s, int c) { + char ch = (char)c; + const char* last = NULL; + do { + if (*s == ch) last = s; + } while (*s++); + return (char*)last; +} + +// Implements the memset operation. +void* memset(void* dest, int c, size_t n) { + unsigned char* d = (unsigned char*)dest; + size_t qwords = n / 8; + size_t tail = n % 8; + + if (qwords > 0) { + uint64_t value = (unsigned char)c; + value |= value << 8; + value |= value << 16; + value |= value << 32; + __stosq((unsigned __int64*)d, value, qwords); + d += qwords * 8; + } + + if (tail > 0) { + __stosb(d, (unsigned char)c, tail); + } + + return dest; +} + +// Implements the memcpy operation. +void* memcpy(void* dest, const void* src, size_t n) { + unsigned char* d = (unsigned char*)dest; + const unsigned char* s = (const unsigned char*)src; + size_t qwords = n / 8; + size_t tail = n % 8; + + if (qwords > 0) { + __movsq((unsigned __int64*)d, (const unsigned __int64*)s, qwords); + d += qwords * 8; + s += qwords * 8; + } + + if (tail > 0) { + __movsb(d, s, tail); + } + + return dest; +} + +// Implements the memmove operation. +void* memmove(void* dest, const void* src, size_t n) { + unsigned char* d = (unsigned char*)dest; + const unsigned char* s = (const unsigned char*)src; + + if (d < s) { + // Forward copy: safe to use chunked __movsq + tail. + size_t qwords = n / 8; + size_t tail = n % 8; + if (qwords > 0) { + __movsq((unsigned __int64*)d, (const unsigned __int64*)s, qwords); + d += qwords * 8; + s += qwords * 8; + } + if (tail > 0) { + __movsb(d, s, tail); + } + } else if (d > s) { + // Backward copy: must process from end to avoid corruption. + size_t qwords = n / 8; + size_t tail = n % 8; + + // Copy tail bytes first from the very end. + if (tail > 0) { + for (size_t i = tail; i > 0; i--) { + d[qwords * 8 + i - 1] = s[qwords * 8 + i - 1]; + } + } + + // Copy 64-bit chunks backward. + if (qwords > 0) { + unsigned __int64* dq = (unsigned __int64*)d; + const unsigned __int64* sq = (const unsigned __int64*)s; + for (size_t i = qwords; i > 0; i--) { + dq[i - 1] = sq[i - 1]; + } + } + } + return dest; +} + +// Implements the memcmp operation. +int memcmp(const void* s1, const void* s2, size_t n) { + const unsigned __int64* a64 = (const unsigned __int64*)s1; + const unsigned __int64* b64 = (const unsigned __int64*)s2; + size_t qwords = n / 8; + size_t tail = n % 8; + + // Compare 8-byte blocks. + for (size_t i = 0; i < qwords; i++) { + if (a64[i] != b64[i]) { + // Locate the exact mismatching byte within the quadword. + const unsigned char* a8 = (const unsigned char*)&a64[i]; + const unsigned char* b8 = (const unsigned char*)&b64[i]; + for (size_t j = 0; j < 8; j++) { + if (a8[j] != b8[j]) return (int)a8[j] - (int)b8[j]; + } + } + } + + // Compare remaining tail bytes. + const unsigned char* a8 = (const unsigned char*)(a64 + qwords); + const unsigned char* b8 = (const unsigned char*)(b64 + qwords); + for (size_t i = 0; i < tail; i++) { + if (a8[i] != b8[i]) return (int)a8[i] - (int)b8[i]; + } + + return 0; +} diff --git a/code/drivers/bus/pci/pci.c b/code/drivers/bus/pci/pci.c index e5c069f..0f24a20 100644 --- a/code/drivers/bus/pci/pci.c +++ b/code/drivers/bus/pci/pci.c @@ -1,4 +1,5 @@ -// pci.c - PCI bus driver, PDO enumerator, and exported PCI DDI +// PCI bus driver. This file owns PCI enumeration, PDO creation, BAR decoding, and explicit MMIO mappings for function drivers. + #include "pci.h" #include @@ -20,24 +21,26 @@ static const HAL_API* gHal; static DRIVER_OBJECT gPciDriver; static uint32_t gPciDeviceCount; -/* - * PCI MMIO BARs use a private virtual aperture instead of the physical - * direct map. This avoids cacheability aliasing with large direct-map pages - * and keeps BAR mappings page-granular. - */ +// PCI MMIO BARs use a private virtual aperture instead of the physical +// direct map. This avoids cacheability aliasing with large direct-map pages +// and keeps BAR mappings page-granular. + #define PCI_MMIO_VA_BASE 0xFFFF900000000000ULL #define PCI_MMIO_VA_LIMIT 0xFFFF980000000000ULL static uintptr_t gPciMmioNext = PCI_MMIO_VA_BASE; +// Implements the align Up64 operation. static uint64_t PciAlignUp64(uint64_t value, uint64_t alignment) { return (value + alignment - 1u) & ~(alignment - 1u); } +// Implements the default Mmio Flags operation. static uint64_t PciDefaultMmioFlags(void) { return PAGE_PRESENT | PAGE_WRITE | PAGE_WRITETHROUGH | PAGE_NOCACHE | PAGE_NX; } +// Creates mmio Va. static KSTATUS PciAllocateMmioVa(uint64_t length, uintptr_t* outVa) { if (!outVa || !length) return STATUS_INVALID_PARAMETER; @@ -54,6 +57,7 @@ static KSTATUS PciAllocateMmioVa(uint64_t length, uintptr_t* outVa) { return STATUS_SUCCESS; } +// Checks whether pdo. static bool PciIsPdo(DEVICE_OBJECT* pdo, PCI_PDO_EXTENSION** outExt) { if (!pdo || pdo->Type != DeviceObjectPhysical || pdo->u.Pdo.BusType != IoBusPci) return false; @@ -63,26 +67,31 @@ static bool PciIsPdo(DEVICE_OBJECT* pdo, PCI_PDO_EXTENSION** outExt) { return true; } +// Implements the raw Read32 operation. static uint32_t PciRawRead32(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset) { if (!gHal || offset > 0xFCu) return 0xFFFFFFFFu; return gHal->Pci.Read32(0, bus, dev, fn, offset & 0xFCu); } +// Implements the raw Write32 operation. static void PciRawWrite32(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, uint32_t value) { if (!gHal || offset > 0xFCu) return; gHal->Pci.Write32(0, bus, dev, fn, offset & 0xFCu, value); } +// Implements the raw Read8 operation. static uint8_t PciRawRead8(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset) { uint32_t v = PciRawRead32(bus, dev, fn, offset); return (uint8_t)(v >> ((offset & 3u) * 8u)); } +// Implements the raw Read16 operation. static uint16_t PciRawRead16(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset) { uint32_t v = PciRawRead32(bus, dev, fn, offset); return (uint16_t)(v >> ((offset & 2u) * 8u)); } +// Implements the raw Write8 operation. static void PciRawWrite8(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, uint8_t value) { uint16_t aligned = offset & ~3u; uint32_t shift = (offset & 3u) * 8u; @@ -92,6 +101,7 @@ static void PciRawWrite8(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, PciRawWrite32(bus, dev, fn, aligned, old); } +// Implements the raw Write16 operation. static void PciRawWrite16(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, uint16_t value) { uint16_t aligned = offset & ~3u; uint32_t shift = (offset & 2u) * 8u; @@ -101,6 +111,7 @@ static void PciRawWrite16(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, PciRawWrite32(bus, dev, fn, aligned, old); } +// Implements the bar Size From Mask operation. static uint64_t PciBarSizeFromMask(uint64_t mask, uint64_t baseMask) { uint64_t sizeMask = mask & baseMask; if (!sizeMask || sizeMask == baseMask) @@ -108,6 +119,7 @@ static uint64_t PciBarSizeFromMask(uint64_t mask, uint64_t baseMask) { return (~sizeMask + 1u) & baseMask; } +// Implements the header Bar Count operation. static uint8_t PciHeaderBarCount(uint8_t headerType) { switch (headerType & PCI_HEADER_TYPE_MASK) { case 0x00: return 6; @@ -117,6 +129,7 @@ static uint8_t PciHeaderBarCount(uint8_t headerType) { } } +// Implements the decode Bars operation. static void PciDecodeBars(PCI_PDO_EXTENSION* ext) { uint8_t barCount = PciHeaderBarCount(ext->Info.HeaderType); for (uint8_t i = 0; i < PCI_MAX_BARS; i++) { @@ -255,6 +268,7 @@ static void PciDecodeBars(PCI_PDO_EXTENSION* ext) { } } +// Returns capability Offset. static uint8_t PciFindCapabilityOffset(PCI_PDO_EXTENSION* ext) { uint16_t status = (uint16_t)(PciRawRead32(ext->Info.Address.Bus, ext->Info.Address.Device, @@ -270,6 +284,7 @@ static uint8_t PciFindCapabilityOffset(PCI_PDO_EXTENSION* ext) { return cap; } +// Creates ids. static void PciMakeIds(const PCI_DEVICE_INFO* info, IO_DEVICE_ID* ids, char storage[][IO_MAX_DEVICE_ID_CHARS], size_t* outCount) { size_t count = 0; @@ -311,6 +326,7 @@ static void PciMakeIds(const PCI_DEVICE_INFO* info, IO_DEVICE_ID* ids, char stor *outCount = count; } +// Creates pdo. static KSTATUS PciCreatePdo(uint8_t bus, uint8_t dev, uint8_t fn) { uint32_t id = PciRawRead32(bus, dev, fn, PCI_REG_VENDOR_DEVICE); uint16_t vendor = (uint16_t)(id & 0xFFFFu); @@ -385,6 +401,7 @@ static KSTATUS PciCreatePdo(uint8_t bus, uint8_t dev, uint8_t fn) { return STATUS_SUCCESS; } +// Implements the enumerate Bus operation. static void PciEnumerateBus(void) { for (uint32_t bus = 0; bus < 256u; bus++) { for (uint32_t dev = 0; dev < 32u; dev++) { @@ -406,6 +423,7 @@ static void PciEnumerateBus(void) { } } +// Dispatches pnp. static KSTATUS PciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return STATUS_INVALID_PARAMETER; IO_STACK_LOCATION* ios = IoGetCurrentIrpStackLocation(irp); @@ -425,10 +443,12 @@ static KSTATUS PciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } +// Implements the driver Abi Version operation. __declspec(dllexport) uint32_t PciDriverAbiVersion(void) { return 1u; } +// Returns device Info. __declspec(dllexport) KSTATUS PciGetDeviceInfo(DEVICE_OBJECT* pdo, PCI_DEVICE_INFO* outInfo) { PCI_PDO_EXTENSION* ext; if (!outInfo || !PciIsPdo(pdo, &ext)) return STATUS_INVALID_PARAMETER; @@ -436,6 +456,7 @@ __declspec(dllexport) KSTATUS PciGetDeviceInfo(DEVICE_OBJECT* pdo, PCI_DEVICE_IN return STATUS_SUCCESS; } +// Returns config8. __declspec(dllexport) KSTATUS PciReadConfig8(DEVICE_OBJECT* pdo, uint16_t offset, uint8_t* outValue) { PCI_PDO_EXTENSION* ext; if (!outValue || offset > 0xFFu || !PciIsPdo(pdo, &ext)) return STATUS_INVALID_PARAMETER; @@ -443,6 +464,7 @@ __declspec(dllexport) KSTATUS PciReadConfig8(DEVICE_OBJECT* pdo, uint16_t offset return STATUS_SUCCESS; } +// Returns config16. __declspec(dllexport) KSTATUS PciReadConfig16(DEVICE_OBJECT* pdo, uint16_t offset, uint16_t* outValue) { PCI_PDO_EXTENSION* ext; if (!outValue || offset > 0xFEu || !PciIsPdo(pdo, &ext)) return STATUS_INVALID_PARAMETER; @@ -450,6 +472,7 @@ __declspec(dllexport) KSTATUS PciReadConfig16(DEVICE_OBJECT* pdo, uint16_t offse return STATUS_SUCCESS; } +// Returns config32. __declspec(dllexport) KSTATUS PciReadConfig32(DEVICE_OBJECT* pdo, uint16_t offset, uint32_t* outValue) { PCI_PDO_EXTENSION* ext; if (!outValue || offset > 0xFCu || !PciIsPdo(pdo, &ext)) return STATUS_INVALID_PARAMETER; @@ -457,6 +480,7 @@ __declspec(dllexport) KSTATUS PciReadConfig32(DEVICE_OBJECT* pdo, uint16_t offse return STATUS_SUCCESS; } +// Updates config8. __declspec(dllexport) KSTATUS PciWriteConfig8(DEVICE_OBJECT* pdo, uint16_t offset, uint8_t value) { PCI_PDO_EXTENSION* ext; if (offset > 0xFFu || !PciIsPdo(pdo, &ext)) return STATUS_INVALID_PARAMETER; @@ -464,6 +488,7 @@ __declspec(dllexport) KSTATUS PciWriteConfig8(DEVICE_OBJECT* pdo, uint16_t offse return STATUS_SUCCESS; } +// Updates config16. __declspec(dllexport) KSTATUS PciWriteConfig16(DEVICE_OBJECT* pdo, uint16_t offset, uint16_t value) { PCI_PDO_EXTENSION* ext; if (offset > 0xFEu || !PciIsPdo(pdo, &ext)) return STATUS_INVALID_PARAMETER; @@ -471,6 +496,7 @@ __declspec(dllexport) KSTATUS PciWriteConfig16(DEVICE_OBJECT* pdo, uint16_t offs return STATUS_SUCCESS; } +// Updates config32. __declspec(dllexport) KSTATUS PciWriteConfig32(DEVICE_OBJECT* pdo, uint16_t offset, uint32_t value) { PCI_PDO_EXTENSION* ext; if (offset > 0xFCu || !PciIsPdo(pdo, &ext)) return STATUS_INVALID_PARAMETER; @@ -478,6 +504,7 @@ __declspec(dllexport) KSTATUS PciWriteConfig32(DEVICE_OBJECT* pdo, uint16_t offs return STATUS_SUCCESS; } +// Returns bar. __declspec(dllexport) KSTATUS PciGetBar(DEVICE_OBJECT* pdo, uint8_t index, PCI_BAR* outBar) { PCI_PDO_EXTENSION* ext; if (!outBar || index >= PCI_MAX_BARS || !PciIsPdo(pdo, &ext)) return STATUS_INVALID_PARAMETER; @@ -486,6 +513,7 @@ __declspec(dllexport) KSTATUS PciGetBar(DEVICE_OBJECT* pdo, uint8_t index, PCI_B return STATUS_SUCCESS; } +// Maps a PCI BAR through the private MMIO aperture with explicit cache attributes. __declspec(dllexport) KSTATUS PciMapBar(DEVICE_OBJECT* pdo, uint8_t index, uint64_t pageFlags, void** outVirtual, uint64_t* outLength) { PCI_BAR bar; if (!outVirtual) return STATUS_INVALID_PARAMETER; @@ -522,6 +550,7 @@ __declspec(dllexport) KSTATUS PciMapBar(DEVICE_OBJECT* pdo, uint8_t index, uint6 return STATUS_SUCCESS; } +// Enables device. __declspec(dllexport) KSTATUS PciEnableDevice(DEVICE_OBJECT* pdo, uint32_t flags) { PCI_PDO_EXTENSION* ext; if (!PciIsPdo(pdo, &ext)) return STATUS_INVALID_PARAMETER; @@ -544,6 +573,7 @@ __declspec(dllexport) KSTATUS PciEnableDevice(DEVICE_OBJECT* pdo, uint32_t flags return STATUS_SUCCESS; } +// Returns interrupt. __declspec(dllexport) KSTATUS PciGetInterrupt(DEVICE_OBJECT* pdo, uint8_t* outIrq) { PCI_PDO_EXTENSION* ext; if (!outIrq || !PciIsPdo(pdo, &ext)) return STATUS_INVALID_PARAMETER; @@ -552,6 +582,7 @@ __declspec(dllexport) KSTATUS PciGetInterrupt(DEVICE_OBJECT* pdo, uint8_t* outIr return STATUS_SUCCESS; } +// Returns capability. static uint8_t PciFindCapability(PCI_PDO_EXTENSION* ext, uint8_t capId) { if (!ext || !ext->CapabilityOffset) return 0; @@ -572,6 +603,7 @@ static uint8_t PciFindCapability(PCI_PDO_EXTENSION* ext, uint8_t capId) { return 0; } +// Enables msi. __declspec(dllexport) KSTATUS PciEnableMsi(DEVICE_OBJECT* pdo, uint8_t irqSlot) { PCI_PDO_EXTENSION* ext; if (!PciIsPdo(pdo, &ext)) @@ -627,6 +659,7 @@ __declspec(dllexport) KSTATUS PciEnableMsi(DEVICE_OBJECT* pdo, uint8_t irqSlot) return STATUS_SUCCESS; } +// Implements the driver Entry operation. KSTATUS DriverEntry(const HAL_API* hal) { if (!hal) return STATUS_INVALID_PARAMETER; gHal = hal; diff --git a/code/drivers/bus/pci/pci.h b/code/drivers/bus/pci/pci.h index 187cfee..c3212e4 100644 --- a/code/drivers/bus/pci/pci.h +++ b/code/drivers/bus/pci/pci.h @@ -1,3 +1,5 @@ +// PCI bus-driver declarations shared with PCI function drivers. + #pragma once #include diff --git a/code/drivers/bus/usb/usb.c b/code/drivers/bus/usb/usb.c index 65f9811..a81fd37 100644 --- a/code/drivers/bus/usb/usb.c +++ b/code/drivers/bus/usb/usb.c @@ -1,4 +1,5 @@ -// usb.c - USB bus driver entry point and host-controller driver registration. +// USB driver package entry point. This file registers the USB bus, class, hub, HID, storage, and xHCI drivers. + #include "usb.h" DRIVER_OBJECT gXhciDriver; @@ -23,6 +24,7 @@ const char* UsbControllerName(uint8_t progIf) { } } +// Initializes xhci Driver. static KSTATUS UsbInitializeXhciDriver(void) { memset(&gXhciDriver, 0, sizeof(gXhciDriver)); IoInitializeDriverObject(&gXhciDriver, SYS_SV_LITERAL("xhci")); @@ -32,6 +34,7 @@ static KSTATUS UsbInitializeXhciDriver(void) { return IoRegisterDriverObject(&gXhciDriver); } +// Implements the driver Entry operation. KSTATUS DriverEntry(const HAL_API* hal) { if (!hal) return STATUS_INVALID_PARAMETER; DbgPrint("usb: driver loading\n"); diff --git a/code/drivers/bus/usb/usb.h b/code/drivers/bus/usb/usb.h index 3554c15..3746a89 100644 --- a/code/drivers/bus/usb/usb.h +++ b/code/drivers/bus/usb/usb.h @@ -1,4 +1,5 @@ -// usb.h - internal USB/xHCI driver interfaces shared across usb.sys translation units. +// USB core declarations shared by bus, class, hub, HID, storage, and xHCI code. + #pragma once #include @@ -29,6 +30,7 @@ #if USB_DEBUG_VERBOSE #define UsbTrace DbgPrint #else +// Implements the trace operation. static __inline void UsbTrace(const char* fmt, ...) { (void)fmt; } #endif @@ -221,7 +223,7 @@ static __inline void UsbTrace(const char* fmt, ...) { (void)fmt; } #define USB_MAX_TRACKED_ENDPOINTS 8u #define USB_MAX_DEVICE_ID_TEXT 96u #define USB_MAX_PIPES 32u -#define USB_IOCTL_SUBMIT_URB 0x55534201u /* USB1 */ +#define USB_IOCTL_SUBMIT_URB 0x55534201u // USB1 #define USB_ROOT_HUB_MAX_PORTS XHCI_MAX_ROOT_PORTS #define USB_EXTERNAL_HUB_MAX_PORTS 31u #define USB_ROOT_PORT_ENUM_RETRIES 3u diff --git a/code/drivers/bus/usb/usb_bus.c b/code/drivers/bus/usb/usb_bus.c index bbe6f23..e5598fd 100644 --- a/code/drivers/bus/usb/usb_bus.c +++ b/code/drivers/bus/usb/usb_bus.c @@ -1,5 +1,5 @@ -// usb_bus.c - USB bus/HCD/PDO/URB core model. -// +// USB bus manager. This file owns device addressing, descriptor reads, and child PDO creation. + // This is the structural USB bus layer used by the upcoming composite, hub, // and hotplug stages. The legacy direct xHCI class path is still present for // boot HID/storage during migration, but newly enumerated xHCI devices now also @@ -11,6 +11,7 @@ DRIVER_OBJECT gUsbBusDriver; static bool gUsbBusModelReady; static uint8_t gUsbNextControllerIndex; +// Implements the device Destroy operation. static void UsbDeviceDestroy(OBJECT* object) { USB_DEVICE* dev = (USB_DEVICE*)object; if (dev->RemoveLockReady) { @@ -23,6 +24,7 @@ static void UsbDeviceDestroy(OBJECT* object) { } } +// Implements the pipe Destroy operation. static void UsbPipeDestroy(OBJECT* object) { USB_PIPE* pipe = (USB_PIPE*)object; if (pipe->Device) { @@ -31,28 +33,34 @@ static void UsbPipeDestroy(OBJECT* object) { } } +// Implements the reference Device operation. void UsbReferenceDevice(USB_DEVICE* dev) { if (dev) ObReferenceObject(&dev->Header); } +// Implements the dereference Device operation. void UsbDereferenceDevice(USB_DEVICE* dev) { if (dev) ObDereferenceObject(&dev->Header); } +// Implements the reference Pipe operation. void UsbReferencePipe(USB_PIPE* pipe) { if (pipe) ObReferenceObject(&pipe->Header); } +// Implements the dereference Pipe operation. void UsbDereferencePipe(USB_PIPE* pipe) { if (pipe) ObDereferenceObject(&pipe->Header); } +// Creates dma Buffer. void* UsbAllocateDmaBuffer(USB_DEVICE* dev, size_t pages, PHYSICAL_ADDRESS* outPhys) { if (!dev || !dev->Hcd || !dev->Hcd->Operations || !dev->Hcd->Operations->AllocateDma) return (void*)0; return dev->Hcd->Operations->AllocateDma(dev->Hcd, pages, outPhys); } +// Creates device. static USB_DEVICE* UsbAllocateDevice(void) { USB_DEVICE* dev = (USB_DEVICE*)ObAllocateObject(ObjectTypeUsbDevice, sizeof(USB_DEVICE)); if (!dev) return (USB_DEVICE*)0; @@ -90,10 +98,12 @@ KSTATUS UsbCreatePipe(USB_DEVICE* dev, return STATUS_SUCCESS; } +// Implements the id From Buffer operation. static SYS_STRING_VIEW UsbIdFromBuffer(char* buf) { return SysSvFromCstr(buf); } +// Implements the id Put Char operation. static void UsbIdPutChar(char* buf, size_t cap, size_t* pos, char ch) { if (!buf || !pos || cap == 0) return; @@ -106,6 +116,7 @@ static void UsbIdPutChar(char* buf, size_t cap, size_t* pos, char ch) { buf[cap - 1] = '\0'; } +// Implements the id Append Literal operation. static void UsbIdAppendLiteral(char* buf, size_t cap, size_t* pos, const char* text) { if (!text) return; @@ -113,6 +124,7 @@ static void UsbIdAppendLiteral(char* buf, size_t cap, size_t* pos, const char* t UsbIdPutChar(buf, cap, pos, *text++); } +// Implements the id Append Hex operation. static void UsbIdAppendHex(char* buf, size_t cap, size_t* pos, uint32_t value, uint8_t digits) { static const char kHex[] = "0123456789ABCDEF"; while (digits) { @@ -121,6 +133,7 @@ static void UsbIdAppendHex(char* buf, size_t cap, size_t* pos, uint32_t value, u } } +// Implements the format Vid Pid Rev operation. static void UsbFormatVidPidRev(char* buf, size_t cap, uint16_t vid, uint16_t pid, uint16_t rev) { size_t pos = 0; if (cap) buf[0] = '\0'; @@ -132,6 +145,7 @@ static void UsbFormatVidPidRev(char* buf, size_t cap, uint16_t vid, uint16_t pid UsbIdAppendHex(buf, cap, &pos, rev, 4); } +// Implements the format Vid Pid operation. static void UsbFormatVidPid(char* buf, size_t cap, uint16_t vid, uint16_t pid) { size_t pos = 0; if (cap) buf[0] = '\0'; @@ -141,6 +155,7 @@ static void UsbFormatVidPid(char* buf, size_t cap, uint16_t vid, uint16_t pid) { UsbIdAppendHex(buf, cap, &pos, pid, 4); } +// Implements the format Vid Pid Mi operation. static void UsbFormatVidPidMi(char* buf, size_t cap, uint16_t vid, uint16_t pid, uint8_t mi) { size_t pos = 0; if (cap) buf[0] = '\0'; @@ -152,6 +167,7 @@ static void UsbFormatVidPidMi(char* buf, size_t cap, uint16_t vid, uint16_t pid, UsbIdAppendHex(buf, cap, &pos, mi, 2); } +// Implements the format Class Sub Prot operation. static void UsbFormatClassSubProt(char* buf, size_t cap, uint8_t cls, uint8_t sub, uint8_t proto) { size_t pos = 0; if (cap) buf[0] = '\0'; @@ -163,6 +179,7 @@ static void UsbFormatClassSubProt(char* buf, size_t cap, uint8_t cls, uint8_t su UsbIdAppendHex(buf, cap, &pos, proto, 2); } +// Implements the format Class operation. static void UsbFormatClass(char* buf, size_t cap, uint8_t cls) { size_t pos = 0; if (cap) buf[0] = '\0'; @@ -171,18 +188,21 @@ static void UsbFormatClass(char* buf, size_t cap, uint8_t cls) { } +// Implements the format Composite operation. static void UsbFormatComposite(char* buf, size_t cap) { size_t pos = 0; if (cap) buf[0] = '\0'; UsbIdAppendLiteral(buf, cap, &pos, "USB\\COMPOSITE"); } +// Implements the format Root Hub operation. static void UsbFormatRootHub(char* buf, size_t cap) { size_t pos = 0; if (cap) buf[0] = '\0'; UsbIdAppendLiteral(buf, cap, &pos, "USB\\ROOT_HUB"); } +// Creates device Ids. static void UsbMakeDeviceIds(const XHCI_DEVICE* xdev, IO_DEVICE_ID* ids, char idbuf[][USB_MAX_DEVICE_ID_TEXT], size_t* outCount) { size_t n = 0; UsbFormatVidPidRev(idbuf[n], USB_MAX_DEVICE_ID_TEXT, xdev->VendorId, xdev->ProductId, xdev->BcdDevice); @@ -233,6 +253,7 @@ static void UsbMakeInterfaceIds(const XHCI_DEVICE* xdev, *outCount = n; } +// Initializes bus Model. KSTATUS UsbInitializeBusModel(void) { if (gUsbBusModelReady) return STATUS_SUCCESS; @@ -263,6 +284,7 @@ void UsbInitializeHcd(USB_HCD* hcd, hcd->MaxRootPorts = maxRootPorts; } +// Creates root Hub Pdo. KSTATUS UsbCreateRootHubPdo(USB_HCD* hcd) { if (!hcd) return STATUS_INVALID_PARAMETER; if (hcd->RootHubPdo) return STATUS_ALREADY_EXISTS; @@ -298,6 +320,7 @@ KSTATUS UsbCreateRootHubPdo(USB_HCD* hcd) { return STATUS_SUCCESS; } +// Creates device Pdo. KSTATUS UsbCreateDevicePdo(USB_HCD* hcd, XHCI_DEVICE* xdev, DEVICE_OBJECT* parent) { if (!hcd || !xdev) return STATUS_INVALID_PARAMETER; if (xdev->UsbPdo) return STATUS_ALREADY_EXISTS; @@ -365,6 +388,7 @@ KSTATUS UsbCreateDevicePdo(USB_HCD* hcd, XHCI_DEVICE* xdev, DEVICE_OBJECT* paren return STATUS_SUCCESS; } +// Creates interface Pdos. KSTATUS UsbCreateInterfacePdos(USB_HCD* hcd, XHCI_DEVICE* xdev, DEVICE_OBJECT* parent) { if (!hcd || !xdev || !xdev->UsbDevice) return STATUS_INVALID_PARAMETER; DEVICE_OBJECT* deviceParent = parent ? parent : xdev->UsbPdo; @@ -419,6 +443,7 @@ KSTATUS UsbCreateInterfacePdos(USB_HCD* hcd, XHCI_DEVICE* xdev, DEVICE_OBJECT* p } +// Implements the reference First Child operation. static DEVICE_OBJECT* UsbReferenceFirstChild(DEVICE_OBJECT* parent) { if (!parent) return (DEVICE_OBJECT*)0; uintptr_t flags = KeAcquireSpinlock(&parent->Lock); @@ -429,12 +454,14 @@ static DEVICE_OBJECT* UsbReferenceFirstChild(DEVICE_OBJECT* parent) { return child; } +// Implements the send Pnp If Alive operation. static void UsbSendPnpIfAlive(DEVICE_OBJECT* pdo, IO_PNP_MINOR_FUNCTION minor) { if (!pdo || pdo->DeletePending) return; (void)IoSendPnpIrpSync(pdo, minor); } +// Releases device Object Children. KSTATUS UsbRemoveDeviceObjectChildren(DEVICE_OBJECT* parent, bool surprise) { if (!parent) return STATUS_INVALID_PARAMETER; @@ -454,6 +481,7 @@ KSTATUS UsbRemoveDeviceObjectChildren(DEVICE_OBJECT* parent, bool surprise) { return STATUS_SUCCESS; } +// Releases pdo Subtree. KSTATUS UsbRemovePdoSubtree(DEVICE_OBJECT* pdo, bool surprise) { if (!pdo || pdo->Type != DeviceObjectPhysical) return STATUS_INVALID_PARAMETER; @@ -471,6 +499,7 @@ KSTATUS UsbRemovePdoSubtree(DEVICE_OBJECT* pdo, bool surprise) { return STATUS_SUCCESS; } +// Submits urb To Hcd. static KSTATUS UsbSubmitUrbToHcd(USB_PDO_EXTENSION* ext, USB_URB* urb) { if (!ext || !urb) return STATUS_INVALID_PARAMETER; USB_HCD* hcd = ext->Hcd; @@ -485,6 +514,7 @@ static KSTATUS UsbSubmitUrbToHcd(USB_PDO_EXTENSION* ext, USB_URB* urb) { return hcd->Operations->SubmitUrb(hcd, urb); } +// Cancels urb. KSTATUS UsbCancelUrb(USB_URB* urb) { if (!urb || !urb->Device || !urb->Device->Hcd) return STATUS_INVALID_PARAMETER; @@ -494,6 +524,7 @@ KSTATUS UsbCancelUrb(USB_URB* urb) { return hcd->Operations->CancelUrb(hcd, urb); } +// Submits urb Sync. KSTATUS UsbSubmitUrbSync(DEVICE_OBJECT* target, USB_URB* urb) { if (!target || !urb) return STATUS_INVALID_PARAMETER; @@ -510,11 +541,13 @@ KSTATUS UsbSubmitUrbSync(DEVICE_OBJECT* target, USB_URB* urb) { return KSUCCESS(st) ? urb->Status : st; } +// Implements the async Urb Irp Complete operation. static void UsbAsyncUrbIrpComplete(IRP* irp, void* context) { (void)context; IoFreeIrp(irp); } +// Submits urb Async. KSTATUS UsbSubmitUrbAsync(DEVICE_OBJECT* target, USB_URB* urb) { if (!target || !urb) return STATUS_INVALID_PARAMETER; @@ -539,6 +572,7 @@ KSTATUS UsbSubmitUrbAsync(DEVICE_OBJECT* target, USB_URB* urb) { return st; } +// Dispatches internal Device Control. KSTATUS UsbDispatchInternalDeviceControl(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return STATUS_INVALID_PARAMETER; IO_STACK_LOCATION* ios = IoGetCurrentIrpStackLocation(irp); @@ -570,6 +604,7 @@ KSTATUS UsbDispatchInternalDeviceControl(DEVICE_OBJECT* device, IRP* irp) { return STATUS_PENDING; } +// Dispatches pdo Pnp. KSTATUS UsbDispatchPdoPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return STATUS_INVALID_PARAMETER; IO_STACK_LOCATION* ios = IoGetCurrentIrpStackLocation(irp); diff --git a/code/drivers/bus/usb/usb_composite.c b/code/drivers/bus/usb/usb_composite.c index e9487b1..6889152 100644 --- a/code/drivers/bus/usb/usb_composite.c +++ b/code/drivers/bus/usb/usb_composite.c @@ -1,4 +1,5 @@ -// usb_composite.c - USB composite function driver and interface-PDO bus. +// USB composite driver. This file owns multi-interface device attachment and function handoff. + #include "usb.h" DRIVER_OBJECT gUsbCompositeDriver; @@ -12,6 +13,7 @@ static const IO_DRIVER_ID_TABLE gUsbCompositeIdTable = { sizeof(gUsbCompositeIds) / sizeof(gUsbCompositeIds[0]), }; +// Implements the composite Create Interfaces operation. static KSTATUS UsbCompositeCreateInterfaces(USB_COMPOSITE_EXTENSION* ext) { if (!ext || !ext->Device || ext->InterfacesCreated) return STATUS_SUCCESS; @@ -26,6 +28,7 @@ static KSTATUS UsbCompositeCreateInterfaces(USB_COMPOSITE_EXTENSION* ext) { return st; } +// Implements the composite Forward Pnp operation. static KSTATUS UsbCompositeForwardPnp(DEVICE_OBJECT* device, IRP* irp, KSTATUS localStatus) { if (!KSUCCESS(localStatus)) { IoCompleteRequest(irp, localStatus, 0); @@ -34,6 +37,7 @@ static KSTATUS UsbCompositeForwardPnp(DEVICE_OBJECT* device, IRP* irp, KSTATUS l return IoForwardIrpToLower(device, irp); } +// Implements the composite Dispatch Pnp operation. KSTATUS UsbCompositeDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return STATUS_INVALID_PARAMETER; @@ -110,6 +114,7 @@ KSTATUS UsbCompositeDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } +// Implements the composite Add Device operation. KSTATUS UsbCompositeAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return STATUS_INVALID_PARAMETER; @@ -139,6 +144,7 @@ KSTATUS UsbCompositeAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDevi return STATUS_SUCCESS; } +// Initializes composite Driver. KSTATUS UsbInitializeCompositeDriver(void) { memset(&gUsbCompositeDriver, 0, sizeof(gUsbCompositeDriver)); IoInitializeDriverObject(&gUsbCompositeDriver, SYS_SV_LITERAL("usb-composite")); diff --git a/code/drivers/bus/usb/usb_core.c b/code/drivers/bus/usb/usb_core.c index 899f540..4e70b68 100644 --- a/code/drivers/bus/usb/usb_core.c +++ b/code/drivers/bus/usb/usb_core.c @@ -1,4 +1,5 @@ -// usb_core.c - USB descriptor/configuration parsing, interface publishing, and root-port enumeration. +// USB core helpers. This file owns common descriptor, string, and request utilities. + #include "usb.h" KSTATUS XhciSetConfiguration(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, @@ -25,6 +26,7 @@ KSTATUS XhciSetConfiguration(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, } +// Returns tracked Interface By Number. static USB_TRACKED_INTERFACE* UsbFindTrackedInterfaceByNumber(XHCI_DEVICE* dev, uint8_t interfaceNumber) { if (!dev) return (USB_TRACKED_INTERFACE*)0; for (uint8_t i = 0; i < dev->InterfaceCount && i < USB_MAX_TRACKED_INTERFACES; i++) { @@ -108,15 +110,15 @@ void XhciLogConfigurationTree(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, dev->SlotId, iface->bInterfaceNumber); } } else { - /* - * Alternate settings are not independent USB interfaces. Real - * UVC cameras often expose one VideoStreaming interface with - * many alternate settings, and publishing each alternate setting - * as a separate PDO causes duplicate interface devices and can - * exhaust USB_MAX_TRACKED_INTERFACES. Track only alternate - * setting zero until a function driver explicitly selects a - * different setting. - */ + + // Alternate settings are not independent USB interfaces. Real + // UVC cameras often expose one VideoStreaming interface with + // many alternate settings, and publishing each alternate setting + // as a separate PDO causes duplicate interface devices and can + // exhaust USB_MAX_TRACKED_INTERFACES. Track only alternate + // setting zero until a function driver explicitly selects a + // different setting. + tracked = (USB_TRACKED_INTERFACE*)0; } @@ -253,6 +255,7 @@ KSTATUS XhciDiscoverAndSetConfiguration(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, } +// Implements the rollback Enumerated Slot operation. static void XhciRollbackEnumeratedSlot(XHCI_CONTROLLER* xhci, uint8_t slotId) { if (!xhci || slotId == 0 || slotId > XHCI_MAX_TRACKED_SLOTS) return; @@ -377,6 +380,7 @@ static KSTATUS XhciEnumeratePathEx(XHCI_CONTROLLER* xhci, return STATUS_SUCCESS; } +// Implements the enumerate Port Ex operation. KSTATUS XhciEnumeratePortEx(XHCI_CONTROLLER* xhci, uint8_t port, uint8_t* outSlotId) { if (outSlotId) *outSlotId = 0; @@ -426,11 +430,13 @@ KSTATUS XhciEnumerateHubPortEx(XHCI_CONTROLLER* xhci, return XhciEnumeratePathEx(xhci, hubPort, speed, &path, hub->Self, outSlotId); } +// Implements the enumerate Port operation. KSTATUS XhciEnumeratePort(XHCI_CONTROLLER* xhci, uint8_t port) { return XhciEnumeratePortEx(xhci, port, (uint8_t*)0); } +// Implements the enumerate Root Ports operation. void XhciEnumerateRootPorts(XHCI_CONTROLLER* xhci) { uint32_t attempted = 0; uint32_t configured = 0; diff --git a/code/drivers/bus/usb/usb_hid.c b/code/drivers/bus/usb/usb_hid.c index 1478dd2..0534d2c 100644 --- a/code/drivers/bus/usb/usb_hid.c +++ b/code/drivers/bus/usb/usb_hid.c @@ -1,6 +1,8 @@ -// usb_hid.c - USB HID boot keyboard/mouse class binding and report handling. +// USB HID class driver. This file owns HID interface probing and input report translation. + #include "usb.h" +// Implements the hid Key In Report operation. bool XhciHidKeyInReport(const uint8_t* keys, uint8_t key) { if (key == 0 || key == 1) return false; for (uint8_t i = 0; i < 6; i++) { @@ -25,6 +27,7 @@ INPUT_KEY XhciHidModifierKey(uint8_t bit) { } +// Submits hid Key. void XhciSubmitHidKey(INPUT_KEY key, bool pressed) { if (key == INPUT_KEY_NONE) return; INPUT_KEY_EVENT ev; @@ -34,6 +37,7 @@ void XhciSubmitHidKey(INPUT_KEY key, bool pressed) { } +// Processes boot Keyboard Report. void XhciProcessBootKeyboardReport(XHCI_DEVICE* dev, const uint8_t* report, uint16_t len) { if (len < 8) return; @@ -63,6 +67,7 @@ void XhciProcessBootKeyboardReport(XHCI_DEVICE* dev, const uint8_t* report, uint } +// Processes boot Mouse Report. void XhciProcessBootMouseReport(XHCI_DEVICE* dev, const uint8_t* report, uint16_t len) { if (len < 3) return; @@ -84,6 +89,7 @@ void XhciProcessBootMouseReport(XHCI_DEVICE* dev, const uint8_t* report, uint16_ } +// Implements the arm Hid Interrupt In operation. KSTATUS XhciArmHidInterruptIn(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { if (!dev->HidActive || dev->HidArmed || !dev->HidRing || !dev->HidBuffer) return STATUS_SUCCESS; @@ -112,6 +118,7 @@ KSTATUS XhciArmHidInterruptIn(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { } +// Implements the arm All Hid operation. void XhciArmAllHid(XHCI_CONTROLLER* xhci) { for (uint8_t slot = 1; slot <= XHCI_MAX_TRACKED_SLOTS; slot++) { XHCI_DEVICE* dev = &xhci->Devices[slot]; @@ -157,6 +164,7 @@ static void XhciHandleLegacyHidTransferEvent(XHCI_CONTROLLER* xhci, uint64_t trb } +// Starts hid Interrupts. KSTATUS XhciStartHidInterrupts(XHCI_CONTROLLER* xhci) { if (!xhci || xhci->HidDeviceCount == 0) return STATUS_SUCCESS; @@ -166,6 +174,7 @@ KSTATUS XhciStartHidInterrupts(XHCI_CONTROLLER* xhci) { } +// Updates hid Boot Protocol. KSTATUS XhciSetHidBootProtocol(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { USB_SETUP_PACKET setup; setup.bmRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; @@ -197,6 +206,7 @@ KSTATUS XhciSetHidBootProtocol(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { } +// Creates hid Memory. KSTATUS XhciAllocateHidMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { if (dev->HidRing && dev->HidBuffer) return STATUS_SUCCESS; @@ -223,6 +233,7 @@ KSTATUS XhciAllocateHidMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { } +// Implements the configure Hid Endpoint operation. KSTATUS XhciConfigureHidEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { if (!dev->HidCandidate) return STATUS_SUCCESS; @@ -298,9 +309,7 @@ KSTATUS XhciConfigureHidEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { } -// ------------------------------------------------------------------------- // PDO/FDO boot HID function driver path. -// ------------------------------------------------------------------------- DRIVER_OBJECT gUsbHidDriver; @@ -316,6 +325,7 @@ static const IO_DRIVER_ID_TABLE gUsbHidIdTable = { }; +// Implements the hid Is Qemu Absolute Tablet Pdo operation. static bool UsbHidIsQemuAbsoluteTabletPdo(const USB_PDO_EXTENSION* pdoExt, const USB_ENDPOINT_DESCRIPTOR* ep) { if (!pdoExt || !pdoExt->Device || !ep) return false; @@ -327,14 +337,14 @@ static bool UsbHidIsQemuAbsoluteTabletPdo(const USB_PDO_EXTENSION* pdoExt, const if (pdoExt->Device->VendorId != 0x0627u || pdoExt->Device->ProductId != 0x0001u) return false; - /* - * QEMU's usb-kbd and usb-tablet commonly share VID:PID 0627:0001. - * Do not classify by VID:PID alone: the boot keyboard is subclass/protocol - * 01/01, while usb-tablet is the non-boot HID interface 00/00. - */ + // QEMU's usb-kbd and usb-tablet commonly share VID:PID 0627:0001. + // Do not classify by VID:PID alone: the boot keyboard is subclass/protocol + // 01/01, while usb-tablet is the non-boot HID interface 00/00. + return (ep->wMaxPacketSize & 0x07FFu) >= 6u; } +// Implements the hid Find Interrupt In Pdo operation. static const USB_ENDPOINT_DESCRIPTOR* UsbHidFindInterruptInPdo(const USB_PDO_EXTENSION* ext) { if (!ext) return (const USB_ENDPOINT_DESCRIPTOR*)0; @@ -349,6 +359,7 @@ static const USB_ENDPOINT_DESCRIPTOR* UsbHidFindInterruptInPdo(const USB_PDO_EXT } +// Implements the hid Process Boot Keyboard Report operation. static void UsbHidProcessBootKeyboardReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) { if (!ext || len < 8) return; @@ -377,6 +388,7 @@ static void UsbHidProcessBootKeyboardReport(USB_HID_EXTENSION* ext, const uint8_ memcpy(ext->LastKeys, keys, sizeof(ext->LastKeys)); } +// Implements the hid Process Boot Mouse Report operation. static void UsbHidProcessBootMouseReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) { if (!ext || len < 3) return; @@ -397,6 +409,7 @@ static void UsbHidProcessBootMouseReport(USB_HID_EXTENSION* ext, const uint8_t* ext->LastButtons = buttons; } +// Implements the hid Process Qemu Tablet Report operation. static void UsbHidProcessQemuTabletReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) { if (!ext || len < 5) return; @@ -417,6 +430,7 @@ static void UsbHidProcessQemuTabletReport(USB_HID_EXTENSION* ext, const uint8_t* static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext); +// Implements the hid Interrupt Complete operation. static void UsbHidInterruptComplete(USB_URB* urb, void* context) { USB_HID_EXTENSION* ext = (USB_HID_EXTENSION*)context; if (!ext || urb != &ext->InterruptUrb) @@ -451,6 +465,7 @@ static void UsbHidInterruptComplete(USB_URB* urb, void* context) { (void)UsbHidArmInterrupt(ext); } +// Implements the hid Send Boot Protocol operation. static KSTATUS UsbHidSendBootProtocol(USB_HID_EXTENSION* ext) { if (!ext || !ext->LowerDevice || !ext->Device) return STATUS_INVALID_PARAMETER; @@ -494,6 +509,7 @@ static KSTATUS UsbHidSendBootProtocol(USB_HID_EXTENSION* ext) { return STATUS_SUCCESS; } +// Implements the hid Arm Interrupt operation. static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext) { if (!ext || !ext->Started || ext->SurpriseRemoved || ext->Removed) return STATUS_OBJECT_DEAD; @@ -524,6 +540,7 @@ static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext) { return STATUS_SUCCESS; } +// Implements the hid Start Device operation. static KSTATUS UsbHidStartDevice(DEVICE_OBJECT* device, USB_HID_EXTENSION* ext) { if (!device || !ext || !ext->Device || !ext->InterfacePdo) return STATUS_INVALID_PARAMETER; @@ -614,6 +631,7 @@ static KSTATUS UsbHidStartDevice(DEVICE_OBJECT* device, USB_HID_EXTENSION* ext) } +// Implements the hid Dispatch Pnp operation. KSTATUS UsbHidDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return STATUS_INVALID_PARAMETER; @@ -699,6 +717,7 @@ KSTATUS UsbHidDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } +// Implements the hid Add Device operation. KSTATUS UsbHidAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return STATUS_INVALID_PARAMETER; @@ -759,6 +778,7 @@ KSTATUS UsbHidAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObje return STATUS_SUCCESS; } +// Initializes hid Driver. KSTATUS UsbInitializeHidDriver(void) { memset(&gUsbHidDriver, 0, sizeof(gUsbHidDriver)); IoInitializeDriverObject(&gUsbHidDriver, SYS_SV_LITERAL("usb-hid")); diff --git a/code/drivers/bus/usb/usb_hub.c b/code/drivers/bus/usb/usb_hub.c index 0812615..583115f 100644 --- a/code/drivers/bus/usb/usb_hub.c +++ b/code/drivers/bus/usb/usb_hub.c @@ -1,5 +1,5 @@ -// usb_hub.c - USB hub function driver. -// +// USB hub driver. This file owns hub probing, port status handling, and child-device enumeration. + // Root hubs and external hubs are represented by the same FDO abstraction. The // xHCI root hub feeds port-change events directly into this driver, while an // external hub feeds the same port state machine from its interrupt-IN change @@ -21,16 +21,19 @@ static const IO_DRIVER_ID_TABLE gUsbHubIdTable = { #define USB_HUB_PORT_ENUMERATING 0xffu #define USB_HUB_PORT_FAILED 0xfeu +// Implements the hub Slot Busy operation. static bool UsbHubSlotBusy(uint8_t slot) { return slot != 0 && slot != USB_HUB_PORT_ENUMERATING && slot != USB_HUB_PORT_FAILED; } +// Implements the hub Root Port Connected operation. static bool UsbHubRootPortConnected(XHCI_CONTROLLER* xhci, uint8_t port) { if (!xhci || !xhci->Op || port == 0) return false; uint32_t portsc = XhciRead32(xhci->Op, XhciPortReg(port)); return (portsc & XHCI_PORTSC_CCS) != 0; } +// Implements the hub Clear Root Port Failure operation. static void UsbHubClearRootPortFailure(USB_HUB_EXTENSION* hub, uint8_t port) { if (!hub || port == 0 || port > USB_ROOT_HUB_MAX_PORTS) return; hub->RootPortFailCount[port] = 0; @@ -38,6 +41,7 @@ static void UsbHubClearRootPortFailure(USB_HUB_EXTENSION* hub, uint8_t port) { hub->RootPortSlot[port] = 0; } +// Implements the hub Mark Root Port Failed operation. static void UsbHubMarkRootPortFailed(USB_HUB_EXTENSION* hub, uint8_t port) { if (!hub || port == 0 || port > USB_ROOT_HUB_MAX_PORTS) return; hub->RootPortSlot[port] = USB_HUB_PORT_FAILED; @@ -71,14 +75,13 @@ static KSTATUS UsbHubEnumerateRootPortWithRetries(USB_HUB_EXTENSION* hub, hub->RootPortFailCount[port] = attempt; - /* - * On real Intel laptop controllers some internal full-speed devices - * respond with xHCI USB Transaction Error during Address Device while - * the port is still settling. Retry that boundedly while the port is - * held in ENUMERATING state so queued PSC events cannot start parallel - * enumerations. Descriptor/control timeouts are not retried here; they - * are usually dead/firmware-owned ports and retrying them stalls boot. - */ + // On real Intel laptop controllers some internal full-speed devices + // respond with xHCI USB Transaction Error during Address Device while + // the port is still settling. Retry that boundedly while the port is + // held in ENUMERATING state so queued PSC events cannot start parallel + // enumerations. Descriptor/control timeouts are not retried here; they + // are usually dead/firmware-owned ports and retrying them stalls boot. + if (last != STATUS_DEVICE_ERROR || attempt == maxAttempts) break; @@ -97,6 +100,7 @@ static KSTATUS UsbHubEnumerateRootPortWithRetries(USB_HUB_EXTENSION* hub, return last; } +// Implements the hub Pop Pending Root Port operation. static bool UsbHubPopPendingRootPort(USB_HUB_EXTENSION* hub, uint8_t* outPort) { if (!hub || !outPort) return false; @@ -118,6 +122,7 @@ static bool UsbHubPopPendingRootPort(USB_HUB_EXTENSION* hub, uint8_t* outPort) { return false; } +// Implements the hub Pop Pending External Port operation. static bool UsbHubPopPendingExternalPort(USB_HUB_EXTENSION* hub, uint8_t* outPort) { if (!hub || !outPort) return false; @@ -142,6 +147,7 @@ static bool UsbHubPopPendingExternalPort(USB_HUB_EXTENSION* hub, uint8_t* outPor return false; } +// Implements the hub Record Root Port Change operation. static void UsbHubRecordRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) { if (!hub || port == 0 || port > hub->PortCount) return; @@ -154,6 +160,7 @@ static void UsbHubRecordRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) { KeSignalSemaphore(hub->WorkerSemaphore); } +// Implements the hub Queue External Port Change operation. void UsbHubQueueExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) { if (!hub || port == 0 || port > hub->PortCount || port > USB_EXTERNAL_HUB_MAX_PORTS) return; @@ -164,6 +171,7 @@ void UsbHubQueueExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) { KeSignalSemaphore(hub->WorkerSemaphore); } +// Implements the hub Remove Slot Child operation. static void UsbHubRemoveSlotChild(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t slot) { if (!hub || !hub->Hcd || slot == 0) return; @@ -197,6 +205,7 @@ static void UsbHubRemoveSlotChild(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t } } +// Implements the hub Remove Root Child operation. static void UsbHubRemoveRootChild(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t slot) { UsbHubRemoveSlotChild(hub, port, slot); } @@ -249,6 +258,7 @@ static KSTATUS UsbHubControlNoData(USB_HUB_EXTENSION* hub, return UsbSubmitUrbSync(hub->LowerDevice, &urb); } +// Implements the hub Read Descriptor operation. static KSTATUS UsbHubReadDescriptor(USB_HUB_EXTENSION* hub, USB_HUB_DESCRIPTOR* outDesc) { if (!hub || !outDesc || !hub->ChangeBitmap || !hub->ChangeBitmapPhys) return STATUS_INVALID_PARAMETER; @@ -271,6 +281,7 @@ static KSTATUS UsbHubReadDescriptor(USB_HUB_EXTENSION* hub, USB_HUB_DESCRIPTOR* return STATUS_SUCCESS; } +// Implements the hub Get Port Status operation. static KSTATUS UsbHubGetPortStatus(USB_HUB_EXTENSION* hub, uint8_t port, USB_HUB_PORT_STATUS* outStatus) { if (!hub || !outStatus || port == 0) return STATUS_INVALID_PARAMETER; @@ -291,6 +302,7 @@ static KSTATUS UsbHubGetPortStatus(USB_HUB_EXTENSION* hub, uint8_t port, USB_HUB return STATUS_SUCCESS; } +// Implements the hub Set Port Feature operation. static KSTATUS UsbHubSetPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint16_t feature) { return UsbHubControlNoData(hub, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER, @@ -299,6 +311,7 @@ static KSTATUS UsbHubSetPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint16 port); } +// Implements the hub Clear Port Feature operation. static KSTATUS UsbHubClearPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint16_t feature) { return UsbHubControlNoData(hub, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER, @@ -307,6 +320,7 @@ static KSTATUS UsbHubClearPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint port); } +// Implements the hub Speed From Port Status operation. static uint8_t UsbHubSpeedFromPortStatus(uint16_t status) { if (status & USB_HUB_PORT_STATUS_LOW_SPEED) return 2u; @@ -315,6 +329,7 @@ static uint8_t UsbHubSpeedFromPortStatus(uint16_t status) { return 1u; } +// Implements the hub Reset External Port operation. static KSTATUS UsbHubResetExternalPort(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t* outSpeed) { if (outSpeed) *outSpeed = 0; if (!hub || port == 0) @@ -355,6 +370,7 @@ static KSTATUS UsbHubResetExternalPort(USB_HUB_EXTENSION* hub, uint8_t port, uin return STATUS_SUCCESS; } +// Implements the hub Handle External Port Change operation. static void UsbHubHandleExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) { if (!hub || hub->Kind != UsbHubKindExternal || port == 0 || port > hub->PortCount || port > USB_EXTERNAL_HUB_MAX_PORTS) return; @@ -433,6 +449,7 @@ static void UsbHubHandleExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) } } +// Implements the hub Handle Root Port Change operation. static void UsbHubHandleRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) { if (!hub || !hub->Hcd || port == 0 || port > hub->PortCount || port > USB_ROOT_HUB_MAX_PORTS) return; @@ -509,6 +526,7 @@ static void UsbHubHandleRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) { static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub); static KSTATUS UsbHubDoRootPortScan(USB_HCD* hcd); +// Implements the hub Take Initial Root Scan operation. static bool UsbHubTakeInitialRootScan(USB_HUB_EXTENSION* hub) { if (!hub || hub->Kind != UsbHubKindRoot) return false; @@ -522,6 +540,7 @@ static bool UsbHubTakeInitialRootScan(USB_HUB_EXTENSION* hub) { return take; } +// Implements the hub Worker operation. static void UsbHubWorker(void* arg) { USB_HUB_EXTENSION* hub = (USB_HUB_EXTENSION*)arg; while (hub && hub->WorkerRunning) { @@ -546,6 +565,7 @@ static void UsbHubWorker(void* arg) { } } +// Implements the hub Do Root Port Scan operation. static KSTATUS UsbHubDoRootPortScan(USB_HCD* hcd) { if (!hcd || !hcd->RootHubContext) return STATUS_INVALID_PARAMETER; @@ -592,6 +612,7 @@ static KSTATUS UsbHubDoRootPortScan(USB_HCD* hcd) { return STATUS_SUCCESS; } +// Implements the hub Schedule Root Scan operation. KSTATUS UsbHubScheduleRootScan(USB_HCD* hcd) { if (!hcd || !hcd->RootHubContext) return STATUS_INVALID_PARAMETER; @@ -609,6 +630,7 @@ KSTATUS UsbHubScheduleRootScan(USB_HCD* hcd) { return STATUS_SUCCESS; } +// Implements the hub Queue Root Port Change operation. void UsbHubQueueRootPortChange(USB_HCD* hcd, uint8_t port) { if (!hcd || !hcd->RootHubContext) return; @@ -616,6 +638,7 @@ void UsbHubQueueRootPortChange(USB_HCD* hcd, uint8_t port) { UsbHubRecordRootPortChange(hub, port); } +// Implements the hub Scan External Ports operation. static KSTATUS UsbHubScanExternalPorts(USB_HUB_EXTENSION* hub) { if (!hub || hub->Kind != UsbHubKindExternal) return STATUS_INVALID_PARAMETER; @@ -643,6 +666,7 @@ static KSTATUS UsbHubScanExternalPorts(USB_HUB_EXTENSION* hub) { return STATUS_SUCCESS; } +// Implements the hub Find Interrupt In operation. static const USB_ENDPOINT_DESCRIPTOR* UsbHubFindInterruptIn(USB_PDO_EXTENSION* pdoExt) { if (!pdoExt) return (const USB_ENDPOINT_DESCRIPTOR*)0; @@ -676,6 +700,7 @@ static const USB_ENDPOINT_DESCRIPTOR* UsbHubFindInterruptIn(USB_PDO_EXTENSION* p return (const USB_ENDPOINT_DESCRIPTOR*)0; } +// Implements the hub External Change Complete operation. static void UsbHubExternalChangeComplete(USB_URB* urb, void* context) { USB_HUB_EXTENSION* hub = (USB_HUB_EXTENSION*)context; if (!hub || urb != &hub->ChangeUrb) @@ -697,6 +722,7 @@ static void UsbHubExternalChangeComplete(USB_URB* urb, void* context) { } } +// Implements the hub Arm External Interrupt operation. static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub) { if (!hub || !hub->InterruptPipe || !hub->ChangeBitmap || hub->ChangeUrbPending) return; @@ -724,6 +750,7 @@ static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub) { } } +// Implements the hub Start Root Device operation. static KSTATUS UsbHubStartRootDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) { hub->PortCount = hub->Hcd ? hub->Hcd->MaxRootPorts : 0; if (hub->PortCount > USB_ROOT_HUB_MAX_PORTS) @@ -752,6 +779,7 @@ static KSTATUS UsbHubStartRootDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* h return STATUS_SUCCESS; } +// Implements the hub Start External Device operation. static KSTATUS UsbHubStartExternalDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) { if (!hub || !hub->Device) return STATUS_INVALID_PARAMETER; @@ -821,6 +849,7 @@ static KSTATUS UsbHubStartExternalDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSIO return STATUS_SUCCESS; } +// Implements the hub Start Device operation. static KSTATUS UsbHubStartDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) { if (!device || !hub || hub->Started) return STATUS_SUCCESS; @@ -830,6 +859,7 @@ static KSTATUS UsbHubStartDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) return UsbHubStartExternalDevice(device, hub); } +// Implements the hub Dispatch Pnp operation. KSTATUS UsbHubDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return STATUS_INVALID_PARAMETER; @@ -932,6 +962,7 @@ KSTATUS UsbHubDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } +// Implements the hub Add Device operation. KSTATUS UsbHubAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return STATUS_INVALID_PARAMETER; @@ -1017,6 +1048,7 @@ KSTATUS UsbHubAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObje return STATUS_SUCCESS; } +// Initializes hub Driver. KSTATUS UsbInitializeHubDriver(void) { memset(&gUsbHubDriver, 0, sizeof(gUsbHubDriver)); IoInitializeDriverObject(&gUsbHubDriver, SYS_SV_LITERAL("usb-hub")); diff --git a/code/drivers/bus/usb/usb_storage.c b/code/drivers/bus/usb/usb_storage.c index c4c96f4..1a032aa 100644 --- a/code/drivers/bus/usb/usb_storage.c +++ b/code/drivers/bus/usb/usb_storage.c @@ -1,5 +1,5 @@ -// usb_storage.c - USB mass-storage BOT/SCSI class driver. -// +// USB mass-storage driver. This file owns bulk-only transport and storage-device exposure. + // The storage driver now binds as a USB function driver to an interface PDO // (USB\CLASS_08&SUBCLASS_06&PROT_50). It creates a disk FDO above that // interface stack and issues BOT transfers through USB URBs. The xHCI HCD @@ -18,6 +18,7 @@ static const IO_DRIVER_ID_TABLE gUsbStorageIdTable = { sizeof(gUsbStorageIds) / sizeof(gUsbStorageIds[0]), }; +// Implements the storage From Disk Device operation. static USB_STORAGE_EXTENSION* UsbStorageFromDiskDevice(DEVICE_OBJECT* device) { if (!device || !device->DeviceExtension) return (USB_STORAGE_EXTENSION*)0; @@ -28,6 +29,7 @@ static USB_STORAGE_EXTENSION* UsbStorageFromDiskDevice(DEVICE_OBJECT* device) { return diskExt->Storage; } +// Implements the storage From Interface Device operation. static USB_STORAGE_EXTENSION* UsbStorageFromInterfaceDevice(DEVICE_OBJECT* device) { if (!device || !device->DeviceExtension) return (USB_STORAGE_EXTENSION*)0; @@ -38,6 +40,7 @@ static USB_STORAGE_EXTENSION* UsbStorageFromInterfaceDevice(DEVICE_OBJECT* devic return ext; } +// Implements the storage Find Bulk Endpoint operation. static const USB_ENDPOINT_DESCRIPTOR* UsbStorageFindBulkEndpoint(const USB_PDO_EXTENSION* pdoExt, bool wantIn) { if (!pdoExt) return (const USB_ENDPOINT_DESCRIPTOR*)0; @@ -150,11 +153,13 @@ KSTATUS UsbStorageBotCommand(USB_STORAGE_EXTENSION* storage, return STATUS_SUCCESS; } +// Implements the be32 operation. uint32_t UsbBe32(const uint8_t* p) { return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3]; } +// Updates be32. void UsbStoreBe32(uint8_t* p, uint32_t v) { p[0] = (uint8_t)(v >> 24); p[1] = (uint8_t)(v >> 16); @@ -162,11 +167,13 @@ void UsbStoreBe32(uint8_t* p, uint32_t v) { p[3] = (uint8_t)v; } +// Updates be16. void UsbStoreBe16(uint8_t* p, uint16_t v) { p[0] = (uint8_t)(v >> 8); p[1] = (uint8_t)v; } +// Implements the storage Inquiry operation. KSTATUS UsbStorageInquiry(USB_STORAGE_EXTENSION* storage) { if (!storage || !storage->XhciDevice) return STATUS_INVALID_PARAMETER; @@ -188,6 +195,7 @@ KSTATUS UsbStorageInquiry(USB_STORAGE_EXTENSION* storage) { return STATUS_SUCCESS; } +// Implements the storage Request Sense operation. KSTATUS UsbStorageRequestSense(USB_STORAGE_EXTENSION* storage) { if (!storage || !storage->XhciDevice) return STATUS_INVALID_PARAMETER; @@ -199,6 +207,7 @@ KSTATUS UsbStorageRequestSense(USB_STORAGE_EXTENSION* storage) { dev->MassBuffer, dev->MassBufferPhys, 18, true); } +// Implements the storage Test Unit Ready operation. KSTATUS UsbStorageTestUnitReady(USB_STORAGE_EXTENSION* storage) { if (!storage || !storage->XhciDevice) return STATUS_INVALID_PARAMETER; @@ -220,6 +229,7 @@ KSTATUS UsbStorageTestUnitReady(USB_STORAGE_EXTENSION* storage) { return last; } +// Implements the storage Read Capacity operation. KSTATUS UsbStorageReadCapacity(USB_STORAGE_EXTENSION* storage) { if (!storage || !storage->XhciDevice) return STATUS_INVALID_PARAMETER; @@ -287,6 +297,7 @@ KSTATUS UsbStorageReadWriteSectors(USB_STORAGE_EXTENSION* storage, return STATUS_SUCCESS; } +// Implements the storage Acquire Io operation. void UsbStorageAcquireIo(USB_STORAGE_EXTENSION* storage) { if (!storage) return; XHCI_CONTROLLER* xhci = storage->Device ? (XHCI_CONTROLLER*)storage->Device->Hcd->ControllerContext : (XHCI_CONTROLLER*)0; @@ -295,10 +306,12 @@ void UsbStorageAcquireIo(USB_STORAGE_EXTENSION* storage) { } } +// Implements the storage Release Io operation. void UsbStorageReleaseIo(USB_STORAGE_EXTENSION* storage) { if (storage) _InterlockedExchange(&storage->IoBusy, 0); } +// Implements the storage Dispatch Read Write operation. KSTATUS UsbStorageDispatchReadWrite(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return STATUS_INVALID_PARAMETER; @@ -362,6 +375,7 @@ KSTATUS UsbStorageDispatchReadWrite(DEVICE_OBJECT* device, IRP* irp) { return STATUS_PENDING; } +// Creates mass Storage Memory. KSTATUS XhciAllocateMassStorageMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { if (dev->MassInRing && dev->MassOutRing && dev->MassBuffer) return STATUS_SUCCESS; @@ -382,6 +396,7 @@ KSTATUS XhciAllocateMassStorageMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { return STATUS_SUCCESS; } +// Implements the configure Mass Storage Endpoints operation. KSTATUS XhciConfigureMassStorageEndpoints(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { if (!dev->MassCandidate) return STATUS_SUCCESS; @@ -451,6 +466,7 @@ KSTATUS XhciConfigureMassStorageEndpoints(XHCI_CONTROLLER* xhci, XHCI_DEVICE* de return STATUS_SUCCESS; } +// Returns free Disk Index. uint8_t UsbFindFreeDiskIndex(void) { for (uint8_t i = 0; i < 8; i++) { if (!IoDiskDevicePresent(i)) @@ -459,6 +475,7 @@ uint8_t UsbFindFreeDiskIndex(void) { return 0xFFu; } +// Implements the storage Register Disk operation. KSTATUS UsbStorageRegisterDisk(USB_STORAGE_EXTENSION* storage) { if (!storage || storage->BlockSize != USB_STORAGE_SECTOR_SIZE || storage->BlockCount == 0) return STATUS_NOT_SUPPORTED; @@ -502,6 +519,7 @@ KSTATUS UsbStorageRegisterDisk(USB_STORAGE_EXTENSION* storage) { return STATUS_SUCCESS; } +// Implements the storage Start Device operation. static KSTATUS UsbStorageStartDevice(DEVICE_OBJECT* device, USB_STORAGE_EXTENSION* storage) { if (!device || !storage || !storage->InterfacePdo || !storage->Device) return STATUS_INVALID_PARAMETER; @@ -618,6 +636,7 @@ fail: return st; } +// Implements the storage Disk Pnp operation. static KSTATUS UsbStorageDiskPnp(DEVICE_OBJECT* device, IRP* irp, USB_STORAGE_EXTENSION* storage, IO_PNP_MINOR_FUNCTION minor) { if (!device || !irp || !storage) return STATUS_INVALID_PARAMETER; @@ -668,6 +687,7 @@ static KSTATUS UsbStorageDiskPnp(DEVICE_OBJECT* device, IRP* irp, USB_STORAGE_EX } } +// Implements the storage Interface Pnp operation. static KSTATUS UsbStorageInterfacePnp(DEVICE_OBJECT* device, IRP* irp, USB_STORAGE_EXTENSION* storage, IO_PNP_MINOR_FUNCTION minor) { if (!device || !irp || !storage) return STATUS_INVALID_PARAMETER; @@ -745,6 +765,7 @@ static KSTATUS UsbStorageInterfacePnp(DEVICE_OBJECT* device, IRP* irp, USB_STORA } } +// Implements the storage Dispatch Pnp operation. KSTATUS UsbStorageDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return STATUS_INVALID_PARAMETER; @@ -765,6 +786,7 @@ KSTATUS UsbStorageDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } +// Implements the storage Add Device operation. KSTATUS UsbStorageAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return STATUS_INVALID_PARAMETER; @@ -815,6 +837,7 @@ KSTATUS UsbStorageAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDevice return STATUS_SUCCESS; } +// Initializes storage Driver. KSTATUS UsbInitializeStorageDriver(void) { memset(&gUsbStorageDriver, 0, sizeof(gUsbStorageDriver)); IoInitializeDriverObject(&gUsbStorageDriver, SYS_SV_LITERAL("usb-storage")); diff --git a/code/drivers/bus/usb/usb_xhci.c b/code/drivers/bus/usb/usb_xhci.c index ee6679e..0c394eb 100644 --- a/code/drivers/bus/usb/usb_xhci.c +++ b/code/drivers/bus/usb/usb_xhci.c @@ -1,11 +1,14 @@ -// usb_xhci.c - xHCI host-controller, MMIO, rings, commands, event dispatch, and generic transfers. +// xHCI USB host-controller driver. This file owns MMIO setup, rings, slots, endpoints, and transfer completion. + #include "usb.h" +// Implements the align Up32 operation. uint32_t UsbAlignUp32(uint32_t value, uint32_t align) { return (value + align - 1u) & ~(align - 1u); } +// Implements the barrier operation. void XhciBarrier(void) { _ReadWriteBarrier(); _mm_mfence(); @@ -13,26 +16,31 @@ void XhciBarrier(void) { } +// Implements the read8 operation. uint8_t XhciRead8(volatile uint8_t* base, uint32_t reg) { return *(volatile uint8_t*)(base + reg); } +// Implements the read16 operation. uint16_t XhciRead16(volatile uint8_t* base, uint32_t reg) { return *(volatile uint16_t*)(base + reg); } +// Implements the read32 operation. uint32_t XhciRead32(volatile uint8_t* base, uint32_t reg) { return *(volatile uint32_t*)(base + reg); } +// Implements the write32 operation. void XhciWrite32(volatile uint8_t* base, uint32_t reg, uint32_t value) { *(volatile uint32_t*)(base + reg) = value; } +// Implements the read64 operation. uint64_t XhciRead64(volatile uint8_t* base, uint32_t reg) { uint32_t lo = XhciRead32(base, reg); uint32_t hi = XhciRead32(base, reg + 4u); @@ -40,12 +48,14 @@ uint64_t XhciRead64(volatile uint8_t* base, uint32_t reg) { } +// Implements the write64 operation. void XhciWrite64(volatile uint8_t* base, uint32_t reg, uint64_t value) { XhciWrite32(base, reg, (uint32_t)value); XhciWrite32(base, reg + 4u, (uint32_t)(value >> 32)); } +// Implements the delay Us operation. void UsbDelayUs(const HAL_API* hal, uint32_t us) { if (hal && hal->Timer.Stall) hal->Timer.Stall(us); else { @@ -103,42 +113,50 @@ void* UsbDmaAllocPages(XHCI_CONTROLLER* xhci, size_t pages, } +// Implements the scratchpad Count operation. uint16_t XhciScratchpadCount(uint32_t hcs2) { return (uint16_t)((((hcs2 >> 16) & 0x3E0u) | ((hcs2 >> 27) & 0x1Fu)) & 0x3FFu); } +// Implements the trb Type operation. uint32_t XhciTrbType(const XHCI_TRB* trb) { return (trb->Control >> XHCI_TRB_TYPE_SHIFT) & XHCI_TRB_TYPE_MASK; } +// Implements the completion Code operation. uint32_t XhciCompletionCode(const XHCI_TRB* trb) { return (trb->Status >> 24) & 0xFFu; } +// Implements the event Slot Id operation. uint8_t XhciEventSlotId(const XHCI_TRB* trb) { return (uint8_t)(trb->Control >> 24); } +// Implements the event Endpoint Id operation. uint8_t XhciEventEndpointId(const XHCI_TRB* trb) { return (uint8_t)((trb->Control >> 16) & 0x1Fu); } +// Implements the transfer Residue operation. uint32_t XhciTransferResidue(const XHCI_TRB* trb) { return trb->Status & 0xFFFFFFu; } +// Implements the input Control Context operation. uint32_t* XhciInputControlContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { (void)xhci; return (uint32_t*)dev->InputContext; } +// Implements the input Slot Context operation. uint32_t* XhciInputSlotContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { return (uint32_t*)(dev->InputContext + xhci->ContextBytes); } @@ -150,6 +168,7 @@ uint32_t* XhciInputEndpointContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, } +// Implements the ep Max Packet operation. uint32_t XhciEpMaxPacket(uint8_t speed) { switch (speed) { case 2: return 8; // low-speed @@ -162,6 +181,7 @@ uint32_t XhciEpMaxPacket(uint8_t speed) { } +// Implements the setup Packet To U64 operation. uint64_t UsbSetupPacketToU64(const USB_SETUP_PACKET* setup) { uint64_t v = 0; v |= (uint64_t)setup->bmRequestType; @@ -186,6 +206,7 @@ const char* XhciPortSpeedName(uint32_t speed) { +// Parses supported Protocols. void XhciParseSupportedProtocols(XHCI_CONTROLLER* xhci) { memset(xhci->PortProtocolMajor, 0, sizeof(xhci->PortProtocolMajor)); memset(xhci->PortProtocolMinor, 0, sizeof(xhci->PortProtocolMinor)); @@ -233,6 +254,7 @@ void XhciParseSupportedProtocols(XHCI_CONTROLLER* xhci) { } +// Implements the port Protocol Major operation. uint8_t XhciPortProtocolMajor(XHCI_CONTROLLER* xhci, uint8_t port, uint32_t portsc) { if (port <= XHCI_MAX_ROOT_PORTS && xhci->PortProtocolMajor[port]) return xhci->PortProtocolMajor[port]; @@ -276,6 +298,7 @@ const char* UsbInterfaceClassName(uint8_t klass, uint8_t subclass, uint8_t proto } +// Implements the log Port Status operation. void XhciLogPortStatus(XHCI_CONTROLLER* xhci) { for (uint8_t port = 1; port <= xhci->MaxPorts; port++) { uint32_t off = XHCI_OP_PORT_BASE + ((uint32_t)port - 1u) * XHCI_OP_PORT_STRIDE; @@ -297,6 +320,7 @@ void XhciLogPortStatus(XHCI_CONTROLLER* xhci) { } } +// Implements the power Root Ports operation. void XhciPowerRootPorts(XHCI_CONTROLLER* xhci) { if (!xhci || !xhci->Op) return; @@ -323,6 +347,7 @@ void XhciPowerRootPorts(XHCI_CONTROLLER* xhci) { } +// Implements the ack Interrupter0 operation. void XhciAckInterrupter0(XHCI_CONTROLLER* xhci) { if (!xhci->Runtime) return; volatile uint8_t* ir0 = xhci->Runtime + 0x20u; @@ -331,6 +356,7 @@ void XhciAckInterrupter0(XHCI_CONTROLLER* xhci) { } +// Updates erdp. void XhciUpdateErdp(XHCI_CONTROLLER* xhci) { volatile uint8_t* ir0 = xhci->Runtime + 0x20u; uint64_t erdp = xhci->EventRingPhys + (uint64_t)xhci->EventDequeue * sizeof(XHCI_TRB); @@ -338,6 +364,7 @@ void XhciUpdateErdp(XHCI_CONTROLLER* xhci) { } +// Returns command Waiter Locked. static XHCI_WAIT_TARGET* XhciFindCommandWaiterLocked(XHCI_CONTROLLER* xhci, uint64_t commandPhys) { for (XHCI_WAIT_TARGET* w = xhci->WaiterList; w; w = w->Next) { if (w->CommandPhys && w->CommandPhys == commandPhys) @@ -401,6 +428,7 @@ static XHCI_WAIT_TARGET* XhciClaimTransferWaiter(XHCI_CONTROLLER* xhci, } +// Implements the drain Event Ring operation. bool XhciDrainEventRing(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target) { (void)target; bool processed = false; @@ -457,6 +485,7 @@ bool XhciDrainEventRing(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target) { } +// Implements the drain Event Ring Locked operation. bool XhciDrainEventRingLocked(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target) { if (!xhci) return false; uintptr_t flags = KeAcquireSpinlock(&xhci->EventLock); @@ -466,6 +495,7 @@ bool XhciDrainEventRingLocked(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target) { } +// Waits for target Complete. bool XhciWaitTargetComplete(const XHCI_WAIT_TARGET* target) { if (!target) return false; if (target->CommandPhys && !target->CommandMatched) return false; @@ -474,6 +504,7 @@ bool XhciWaitTargetComplete(const XHCI_WAIT_TARGET* target) { } +// Registers wait Target. void XhciRegisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target) { if (!xhci || !target || target->Registered) return; @@ -486,6 +517,7 @@ void XhciRegisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target) { } +// Implements the unregister Wait Target operation. void XhciUnregisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target) { if (!xhci || !target || !target->Registered) return; @@ -561,12 +593,13 @@ void XhciEventDpcRoutine(KDPC* dpc, void* context, } -#define XHCI_CONTROLLER_MAGIC 0x58484349u /* XHCI */ +#define XHCI_CONTROLLER_MAGIC 0x58484349u // XHCI #define XHCI_MAX_CONTROLLERS 8u static XHCI_CONTROLLER* gXhciControllers[XHCI_MAX_CONTROLLERS]; static uint32_t gXhciControllerCount; +// Registers controller. static KSTATUS XhciRegisterController(XHCI_CONTROLLER* xhci) { if (!xhci) return STATUS_INVALID_PARAMETER; for (uint32_t i = 0; i < gXhciControllerCount; i++) { @@ -579,6 +612,7 @@ static KSTATUS XhciRegisterController(XHCI_CONTROLLER* xhci) { return STATUS_SUCCESS; } +// Implements the isr operation. void XhciIsr(void) { for (uint32_t i = 0; i < gXhciControllerCount; i++) { XHCI_CONTROLLER* xhci = gXhciControllers[i]; @@ -597,6 +631,7 @@ void XhciIsr(void) { } +// Implements the bios Handoff operation. KSTATUS XhciBiosHandoff(XHCI_CONTROLLER* xhci) { uint32_t xecp = (xhci->Hcc1 >> 16) & 0xFFFFu; if (!xecp) return STATUS_SUCCESS; @@ -641,6 +676,7 @@ KSTATUS XhciBiosHandoff(XHCI_CONTROLLER* xhci) { } +// Implements the stop And Reset operation. KSTATUS XhciStopAndReset(XHCI_CONTROLLER* xhci) { uint32_t cmd = XhciRead32(xhci->Op, XHCI_OP_USBCMD); if (cmd & XHCI_USBCMD_RS) { @@ -674,6 +710,7 @@ KSTATUS XhciStopAndReset(XHCI_CONTROLLER* xhci) { } +// Creates scratchpads. KSTATUS XhciAllocateScratchpads(XHCI_CONTROLLER* xhci) { if (xhci->ScratchpadCount == 0) return STATUS_SUCCESS; if (xhci->ScratchpadCount > XHCI_MAX_SCRATCHPADS) { @@ -708,6 +745,7 @@ KSTATUS XhciAllocateScratchpads(XHCI_CONTROLLER* xhci) { } +// Creates runtime Memory. KSTATUS XhciAllocateRuntimeMemory(XHCI_CONTROLLER* xhci) { xhci->Dcbaa = (uint64_t*)UsbDmaAllocPages(xhci, 1, &xhci->DcbaaPhys); xhci->CommandRing = (XHCI_TRB*)UsbDmaAllocPages(xhci, 1, &xhci->CommandRingPhys); @@ -749,6 +787,7 @@ KSTATUS XhciAllocateRuntimeMemory(XHCI_CONTROLLER* xhci) { } +// Implements the program Runtime operation. KSTATUS XhciProgramRuntime(XHCI_CONTROLLER* xhci) { uint8_t slots = xhci->MaxSlots; if (slots == 0) return STATUS_DEVICE_ERROR; @@ -770,6 +809,7 @@ KSTATUS XhciProgramRuntime(XHCI_CONTROLLER* xhci) { } +// Implements the command Trb Phys operation. uint64_t XhciCommandTrbPhys(XHCI_CONTROLLER* xhci, uint32_t index) { return xhci->CommandRingPhys + (uint64_t)index * sizeof(XHCI_TRB); } @@ -853,6 +893,7 @@ KSTATUS XhciSubmitCommand(XHCI_CONTROLLER* xhci, } +// Submits noop Command. KSTATUS XhciSubmitNoopCommand(XHCI_CONTROLLER* xhci) { XHCI_COMMAND_RESULT result; KSTATUS st = XhciSubmitCommand( @@ -873,6 +914,7 @@ KSTATUS XhciSubmitNoopCommand(XHCI_CONTROLLER* xhci) { } +// Enables slot. KSTATUS XhciEnableSlot(XHCI_CONTROLLER* xhci, uint8_t* outSlotId) { XHCI_COMMAND_RESULT result; memset(&result, 0, sizeof(result)); @@ -898,6 +940,7 @@ KSTATUS XhciEnableSlot(XHCI_CONTROLLER* xhci, uint8_t* outSlotId) { +// Disables slot. KSTATUS XhciDisableSlot(XHCI_CONTROLLER* xhci, uint8_t slotId) { if (!xhci || slotId == 0) return STATUS_INVALID_PARAMETER; @@ -919,6 +962,7 @@ KSTATUS XhciDisableSlot(XHCI_CONTROLLER* xhci, uint8_t slotId) { return STATUS_SUCCESS; } +// Implements the address Device operation. KSTATUS XhciAddressDevice(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { XHCI_COMMAND_RESULT result; memset(&result, 0, sizeof(result)); @@ -939,6 +983,7 @@ KSTATUS XhciAddressDevice(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { } +// Starts the requested operation. KSTATUS XhciStart(XHCI_CONTROLLER* xhci) { uint32_t cmd = XhciRead32(xhci->Op, XHCI_OP_USBCMD); cmd |= XHCI_USBCMD_RS; @@ -956,6 +1001,7 @@ KSTATUS XhciStart(XHCI_CONTROLLER* xhci) { } +// Enables interrupts. void XhciEnableInterrupts(XHCI_CONTROLLER* xhci) { volatile uint8_t* ir0 = xhci->Runtime + 0x20u; XhciWrite32(xhci->Op, XHCI_OP_USBSTS, @@ -966,27 +1012,30 @@ void XhciEnableInterrupts(XHCI_CONTROLLER* xhci) { } +// Implements the port Reg operation. uint32_t XhciPortReg(uint8_t port) { return XHCI_OP_PORT_BASE + ((uint32_t)port - 1u) * XHCI_OP_PORT_STRIDE; } +// Clears port Changes. void XhciClearPortChanges(XHCI_CONTROLLER* xhci, uint8_t port) { uint32_t off = XhciPortReg(port); uint32_t portsc = XhciRead32(xhci->Op, off); uint32_t changes = portsc & XHCI_PORTSC_CHANGE_MASK; if (changes) { - /* - * PORTSC is a mixed register. The change bits are RW1C, but many - * other bits are either RO or have side effects when written as one - * (PED disables the port; PR starts a reset). Preserve only Port - * Power and write one to the RW1C change bits. - */ + + // PORTSC is a mixed register. The change bits are RW1C, but many + // other bits are either RO or have side effects when written as one + // (PED disables the port; PR starts a reset). Preserve only Port + // Power and write one to the RW1C change bits. + XhciWrite32(xhci->Op, off, (portsc & XHCI_PORTSC_PP) | changes); } } +// Implements the reset Port operation. KSTATUS XhciResetPort(XHCI_CONTROLLER* xhci, uint8_t port, uint8_t* outSpeed) { uint32_t off = XhciPortReg(port); uint32_t portsc = XhciRead32(xhci->Op, off); @@ -1000,12 +1049,12 @@ KSTATUS XhciResetPort(XHCI_CONTROLLER* xhci, uint8_t port, uint8_t* outSpeed) { portsc = XhciRead32(xhci->Op, off); if (protocol >= 3u || speed >= 4u) { - /* - * SuperSpeed ports are enabled by link training. Do not issue a - * USB2-style PORTSC.PR reset; on real Intel controllers that can make - * the link drop during early enumeration. If firmware/controller - * already has PR set, just wait for it to settle. - */ + + // SuperSpeed ports are enabled by link training. Do not issue a + // USB2-style PORTSC.PR reset; on real Intel controllers that can make + // the link drop during early enumeration. If firmware/controller + // already has PR set, just wait for it to settle. + bool enabled = false; for (uint32_t i = 0; i < 1000000u; i++) { portsc = XhciRead32(xhci->Op, off); @@ -1070,6 +1119,7 @@ KSTATUS XhciResetPort(XHCI_CONTROLLER* xhci, uint8_t port, uint8_t* outSpeed) { } +// Creates device Memory. KSTATUS XhciAllocateDeviceMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { dev->InputContext = (uint8_t*)UsbDmaAllocPages(xhci, 1, &dev->InputContextPhys); dev->DeviceContext = (uint8_t*)UsbDmaAllocPages(xhci, 1, &dev->DeviceContextPhys); @@ -1094,6 +1144,7 @@ KSTATUS XhciAllocateDeviceMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { } +// Builds default Control Context. void XhciBuildDefaultControlContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { memset(dev->InputContext, 0, PAGE_SIZE); memset(dev->DeviceContext, 0, PAGE_SIZE); @@ -1137,6 +1188,7 @@ void XhciBuildDefaultControlContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { } +// Implements the ep0 Trb Phys operation. uint64_t XhciEp0TrbPhys(XHCI_DEVICE* dev, uint32_t index) { return dev->Ep0RingPhys + (uint64_t)index * sizeof(XHCI_TRB); } @@ -1405,6 +1457,7 @@ KSTATUS XhciGetConfigurationDescriptor(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, } +// Implements the endpoint Id From Address operation. uint8_t XhciEndpointIdFromAddress(uint8_t endpointAddress) { uint8_t number = endpointAddress & USB_ENDPOINT_NUMBER_MASK; if (number == 0) return 1; @@ -1412,6 +1465,7 @@ uint8_t XhciEndpointIdFromAddress(uint8_t endpointAddress) { } +// Implements the interrupt Interval operation. uint8_t XhciInterruptInterval(uint8_t speed, uint8_t usbInterval) { if (usbInterval == 0) usbInterval = 1; @@ -1544,6 +1598,7 @@ KSTATUS XhciBulkTransfer(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, +// Implements the configure Pipe Endpoint operation. KSTATUS XhciConfigurePipeEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_PIPE* pipe) { if (!xhci || !dev || !pipe || !pipe->Open) return STATUS_INVALID_PARAMETER; @@ -1631,6 +1686,7 @@ KSTATUS XhciConfigurePipeEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_P return STATUS_SUCCESS; } +// Implements the hcd Submit Interrupt Urb operation. static KSTATUS XhciHcdSubmitInterruptUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_URB* urb) { if (!xhci || !dev || !urb || !urb->Pipe || !urb->BufferPhys || urb->Length == 0) return STATUS_INVALID_PARAMETER; @@ -1725,6 +1781,7 @@ void XhciHandleAsyncTransferEvent(XHCI_CONTROLLER* xhci, uint64_t trbPhys, IoCompleteRequest(completeIrp, st, KSUCCESS(st) ? actual : 0); } +// Implements the hcd Submit Bulk Urb operation. static KSTATUS XhciHcdSubmitBulkUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_URB* urb) { if (!xhci || !dev || !urb || !urb->Pipe || !urb->BufferPhys || urb->Length == 0) return STATUS_INVALID_PARAMETER; @@ -1764,6 +1821,7 @@ static KSTATUS XhciHcdSubmitBulkUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB return st; } +// Implements the hcd Submit Urb operation. static KSTATUS XhciHcdSubmitUrb(USB_HCD* hcd, USB_URB* urb) { if (!hcd || !urb || !urb->Device) return STATUS_INVALID_PARAMETER; @@ -1806,6 +1864,7 @@ static KSTATUS XhciHcdSubmitUrb(USB_HCD* hcd, USB_URB* urb) { return st; } +// Implements the hcd Cancel Urb operation. static KSTATUS XhciHcdCancelUrb(USB_HCD* hcd, USB_URB* urb) { (void)hcd; if (!urb) return STATUS_INVALID_PARAMETER; @@ -1815,16 +1874,19 @@ static KSTATUS XhciHcdCancelUrb(USB_HCD* hcd, USB_URB* urb) { return STATUS_SUCCESS; } +// Implements the hcd Allocate Dma operation. static void* XhciHcdAllocateDma(USB_HCD* hcd, size_t pages, PHYSICAL_ADDRESS* outPhys) { if (!hcd) return (void*)0; return UsbDmaAllocPages((XHCI_CONTROLLER*)hcd->ControllerContext, pages, outPhys); } +// Implements the hcd Reset Root Port operation. static KSTATUS XhciHcdResetRootPort(USB_HCD* hcd, uint8_t port, uint8_t* outSpeed) { if (!hcd) return STATUS_INVALID_PARAMETER; return XhciResetPort((XHCI_CONTROLLER*)hcd->ControllerContext, port, outSpeed); } +// Implements the hcd Clear Root Port Changes operation. static KSTATUS XhciHcdClearRootPortChanges(USB_HCD* hcd, uint8_t port) { if (!hcd) return STATUS_INVALID_PARAMETER; XhciClearPortChanges((XHCI_CONTROLLER*)hcd->ControllerContext, port); @@ -1839,6 +1901,7 @@ const USB_HCD_OPERATIONS gXhciHcdOperations = { XhciHcdAllocateDma, }; +// Starts controller. KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) { if (!xhci || xhci->Magic != XHCI_CONTROLLER_MAGIC || !xhci->Pdo || !xhci->Fdo) return STATUS_INVALID_PARAMETER; @@ -2011,6 +2074,7 @@ KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) { return STATUS_SUCCESS; } +// Dispatches pnp. KSTATUS XhciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp || !device->DeviceExtension) return STATUS_INVALID_PARAMETER; @@ -2061,6 +2125,7 @@ KSTATUS XhciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } +// Implements the add Device operation. KSTATUS XhciAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return STATUS_INVALID_PARAMETER; diff --git a/code/drivers/display/vmwaresvga/vmwaresvga.c b/code/drivers/display/vmwaresvga/vmwaresvga.c index 1495639..180b8c2 100644 --- a/code/drivers/display/vmwaresvga/vmwaresvga.c +++ b/code/drivers/display/vmwaresvga/vmwaresvga.c @@ -1,9 +1,4 @@ -// vmwaresvga.c - VMware SVGA-II PCI display provider. -// -// The default renderer is the legacy guest-framebuffer path: draw into BAR1, -// enqueue SVGA_CMD_UPDATE through BAR2, and synchronize with the device. -// Screen objects remain available behind VMWSVGA_ENABLE_SCREEN_OBJECTS for -// future validation. +// VMware SVGA-II PCI display provider. This file owns adapter setup, FIFO command submission, framebuffer presentation, and cursor integration. #include "vmwaresvga.h" @@ -23,16 +18,19 @@ static const IO_DRIVER_ID_TABLE gVmwSvgaIdTable = { static KSTATUS VmwSvgaSyncDevice(VMWSVGA_DEVICE* v); static void VmwSvgaWakeFifo(VMWSVGA_DEVICE* v); +// Reads a 32-bit SVGA register through the indexed I/O port pair. static uint32_t VmwSvgaReadReg(VMWSVGA_DEVICE* v, uint32_t reg) { __outdword((unsigned short)(v->IoBase + SVGA_INDEX_PORT), reg); return __indword((unsigned short)(v->IoBase + SVGA_VALUE_PORT)); } +// Writes a 32-bit SVGA register through the indexed I/O port pair. static void VmwSvgaWriteReg(VMWSVGA_DEVICE* v, uint32_t reg, uint32_t value) { __outdword((unsigned short)(v->IoBase + SVGA_INDEX_PORT), reg); __outdword((unsigned short)(v->IoBase + SVGA_VALUE_PORT), value); } +// Negotiates the highest SVGA device ID supported by the adapter. static uint32_t VmwSvgaProbeId(VMWSVGA_DEVICE* v) { for (uint32_t id = SVGA_ID_2; id >= SVGA_ID_0; id--) { VmwSvgaWriteReg(v, SVGA_REG_ID, id); @@ -45,6 +43,7 @@ static uint32_t VmwSvgaProbeId(VMWSVGA_DEVICE* v) { return SVGA_ID_INVALID; } +// Chooses the runtime display mode, preferring the current boot framebuffer size. static KSTATUS VmwSvgaChooseMode(uint32_t* outWidth, uint32_t* outHeight) { if (!outWidth || !outHeight) return STATUS_INVALID_PARAMETER; @@ -64,11 +63,12 @@ static KSTATUS VmwSvgaChooseMode(uint32_t* outWidth, uint32_t* outHeight) { return STATUS_SUCCESS; } +// Programs the visible guest display rectangle used by the legacy framebuffer path. static void VmwSvgaProgramLegacyDisplayTopology(VMWSVGA_DEVICE* v, uint32_t width, uint32_t height, uint32_t caps) { if (!v || (caps & SVGA_CAP_DISPLAY_TOPOLOGY) == 0) return; - /* Legacy GFB rendering still needs one visible primary display rectangle. */ + // Legacy GFB rendering still needs one visible primary display rectangle. VmwSvgaWriteReg(v, SVGA_REG_NUM_GUEST_DISPLAYS, 1u); VmwSvgaWriteReg(v, SVGA_REG_DISPLAY_ID, 0u); VmwSvgaWriteReg(v, SVGA_REG_DISPLAY_IS_PRIMARY, 1u); @@ -78,6 +78,7 @@ static void VmwSvgaProgramLegacyDisplayTopology(VMWSVGA_DEVICE* v, uint32_t widt VmwSvgaWriteReg(v, SVGA_REG_DISPLAY_HEIGHT, height); } +// Programs the SVGA device mode before FIFO and framebuffer use. static KSTATUS VmwSvgaSetMode(VMWSVGA_DEVICE* v) { if (!v) return STATUS_INVALID_PARAMETER; @@ -118,6 +119,7 @@ static KSTATUS VmwSvgaSetMode(VMWSVGA_DEVICE* v) { return STATUS_SUCCESS; } +// Clips a display rectangle to the current framebuffer bounds. static bool VmwSvgaClipRect(VMWSVGA_DEVICE* v, DISPLAY_RECT* r) { if (!v || !r || r->W <= 0 || r->H <= 0) return false; @@ -141,6 +143,7 @@ static bool VmwSvgaClipRect(VMWSVGA_DEVICE* v, DISPLAY_RECT* r) { return true; } +// Returns the next FIFO dword offset, wrapping at FIFO_MAX. static uint32_t VmwSvgaFifoNext(VMWSVGA_DEVICE* v, uint32_t offset) { uint32_t next = offset + sizeof(uint32_t); uint32_t min = v->Fifo[SVGA_FIFO_MIN]; @@ -150,6 +153,7 @@ static uint32_t VmwSvgaFifoNext(VMWSVGA_DEVICE* v, uint32_t offset) { return next; } +// Writes one command dword into the SVGA FIFO and waits for space if needed. static KSTATUS VmwSvgaFifoWrite(VMWSVGA_DEVICE* v, uint32_t value) { if (!v || !v->FifoReady || !v->Fifo) return STATUS_NOT_SUPPORTED; @@ -182,6 +186,7 @@ static KSTATUS VmwSvgaFifoWrite(VMWSVGA_DEVICE* v, uint32_t value) { return STATUS_TIMEOUT; } +// Checks whether an extended FIFO register is valid for this device. static bool VmwSvgaHasFifoRegister(VMWSVGA_DEVICE* v, uint32_t index) { if (!v || !v->Fifo || !v->FifoReady) return false; @@ -189,6 +194,7 @@ static bool VmwSvgaHasFifoRegister(VMWSVGA_DEVICE* v, uint32_t index) { v->Fifo[SVGA_FIFO_MIN] >= (index + 1u) * sizeof(uint32_t); } +// Wakes the host side of the SVGA FIFO after new commands are queued. static void VmwSvgaWakeFifo(VMWSVGA_DEVICE* v) { if (!v || !v->FifoReady) return; @@ -207,6 +213,7 @@ static void VmwSvgaWakeFifo(VMWSVGA_DEVICE* v) { static KSTATUS VmwSvgaUploadCursorImage(VMWSVGA_DEVICE* v, int width, int height, int hotX, int hotY, const uint32_t* argbPixels); +// Implements the premultiply Argb For Bgra operation. static uint32_t VmwSvgaPremultiplyArgbForBgra(uint32_t argb) { uint32_t a = argb >> 24; if (a == 0) @@ -224,6 +231,7 @@ static uint32_t VmwSvgaPremultiplyArgbForBgra(uint32_t argb) { return (a << 24) | (r << 16) | (g << 8) | b; } +// Implements the cursor Commit operation. static void VmwSvgaCursorCommit(VMWSVGA_DEVICE* v) { if (!v || !v->HardwareCursor || !v->CursorImageDefined) return; @@ -231,6 +239,7 @@ static void VmwSvgaCursorCommit(VMWSVGA_DEVICE* v) { if (v->CursorBypass3 && VmwSvgaHasFifoRegister(v, SVGA_FIFO_CURSOR_ON) && VmwSvgaHasFifoRegister(v, SVGA_FIFO_CURSOR_X) && + // Checks whether an extended FIFO register is valid for this device. VmwSvgaHasFifoRegister(v, SVGA_FIFO_CURSOR_Y)) { v->Fifo[SVGA_FIFO_CURSOR_X] = (uint32_t)v->CursorX; v->Fifo[SVGA_FIFO_CURSOR_Y] = (uint32_t)v->CursorY; @@ -245,19 +254,19 @@ static void VmwSvgaCursorCommit(VMWSVGA_DEVICE* v) { return; } - /* - * Legacy QEMU SVGA cursors are frontend/host cursors. Re-defining the - * cursor image from the input path can stall the FIFO/frontend after a - * GTK focus/grab transition, so cursor activity must only update the - * legacy position/visibility registers. The image is defined once when - * SetCursorImage runs. - */ + // Legacy QEMU SVGA cursors are frontend/host cursors. Re-defining the + // cursor image from the input path can stall the FIFO/frontend after a + // GTK focus/grab transition, so cursor activity must only update the + // legacy position/visibility registers. The image is defined once when + // SetCursorImage runs. + VmwSvgaWriteReg(v, SVGA_REG_CURSOR_ID, 0u); VmwSvgaWriteReg(v, SVGA_REG_CURSOR_X, (uint32_t)v->CursorX); VmwSvgaWriteReg(v, SVGA_REG_CURSOR_Y, (uint32_t)v->CursorY); VmwSvgaWriteReg(v, SVGA_REG_CURSOR_ON, v->CursorVisible ? SVGA_CURSOR_ON_SHOW : SVGA_CURSOR_ON_HIDE); } +// Implements the cursor Set Visible operation. static void VmwSvgaCursorSetVisible(VMWSVGA_DEVICE* v, bool visible) { if (!v || !v->HardwareCursor) return; @@ -265,6 +274,7 @@ static void VmwSvgaCursorSetVisible(VMWSVGA_DEVICE* v, bool visible) { VmwSvgaCursorCommit(v); } +// Implements the cursor Set Position operation. static void VmwSvgaCursorSetPosition(VMWSVGA_DEVICE* v, int x, int y) { if (!v || !v->HardwareCursor) return; @@ -273,6 +283,7 @@ static void VmwSvgaCursorSetPosition(VMWSVGA_DEVICE* v, int x, int y) { VmwSvgaCursorCommit(v); } +// Implements the define Alpha Cursor operation. static KSTATUS VmwSvgaDefineAlphaCursor(VMWSVGA_DEVICE* v, int width, int height, int hotX, int hotY, const uint32_t* argbPixels) { KSTATUS st = VmwSvgaFifoWrite(v, SVGA_CMD_DEFINE_ALPHA_CURSOR); if (!KSUCCESS(st)) return st; @@ -303,13 +314,13 @@ static uint32_t VmwSvgaPackMonoCursorDword(const uint8_t* bits, int height, int y, uint32_t dwordIndex) { - /* - * SVGA classic cursor scanlines are padded to 32 bits. QEMU stores - * FIFO dwords in guest-endian order and then interprets the result as - * bytes via cursor_set_mono(), whose first pixel is bit 0x80 of byte 0. - * Therefore byte 0 of the numeric dword must contain pixels 0..7, - * byte 1 pixels 8..15, and so on. - */ + + // SVGA classic cursor scanlines are padded to 32 bits. QEMU stores + // FIFO dwords in guest-endian order and then interprets the result as + // bytes via cursor_set_mono(), whose first pixel is bit 0x80 of byte 0. + // Therefore byte 0 of the numeric dword must contain pixels 0..7, + // byte 1 pixels 8..15, and so on. + uint8_t bytes[4] = { 0, 0, 0, 0 }; uint32_t baseX = dwordIndex * 32u; @@ -331,17 +342,18 @@ static uint32_t VmwSvgaPackMonoCursorDword(const uint8_t* bits, ((uint32_t)bytes[3] << 24); } +// Implements the classic Cursor Width operation. static int VmwSvgaClassicCursorWidth(int width) { - /* - * QEMU's VMware SVGA implementation reads classic cursor masks as - * SVGA dword-padded scanlines, then passes the raw byte stream to - * cursor_set_mono(), which advances rows by ceil(width / 8) bytes. - * For widths that are not a multiple of 32 pixels, those two row - * strides differ and every other row is decoded from padding bytes. - * Define the classic cursor with a 32-pixel-aligned visible width and - * leave the extra pixels transparent. The real cursor image remains - * at the left edge and the hotspot is unchanged. - */ + + // QEMU's VMware SVGA implementation reads classic cursor masks as + // SVGA dword-padded scanlines, then passes the raw byte stream to + // cursor_set_mono(), which advances rows by ceil(width / 8) bytes. + // For widths that are not a multiple of 32 pixels, those two row + // strides differ and every other row is decoded from padding bytes. + // Define the classic cursor with a 32-pixel-aligned visible width and + // leave the extra pixels transparent. The real cursor image remains + // at the left edge and the hotspot is unchanged. + return (width + 31) & ~31; } @@ -351,15 +363,15 @@ static void VmwSvgaBuildMonoCursorBits(const uint32_t* argbPixels, int height, uint8_t* andBits, uint8_t* xorBits) { - /* - * Classic SVGA cursors are AND/XOR masks. The most compatible path is - * a 1bpp AND mask plus a 1bpp XOR mask: - * transparent: AND=1 XOR=0 - * black: AND=0 XOR=0 - * white: AND=0 XOR=1 - * This intentionally discards antialiasing, but avoids QEMU/GTK's - * fragile 32bpp classic host-cursor path. - */ + + // Classic SVGA cursors are AND/XOR masks. The most compatible path is + // a 1bpp AND mask plus a 1bpp XOR mask: + // transparent: AND=1 XOR=0 + // black: AND=0 XOR=0 + // white: AND=0 XOR=1 + // This intentionally discards antialiasing, but avoids QEMU/GTK's + // fragile 32bpp classic host-cursor path. + for (int y = 0; y < height; y++) { for (int x = 0; x < encodedWidth; x++) { size_t out = (size_t)y * (size_t)encodedWidth + (size_t)x; @@ -387,6 +399,7 @@ static void VmwSvgaBuildMonoCursorBits(const uint32_t* argbPixels, } } +// Implements the define Classic Cursor operation. static KSTATUS VmwSvgaDefineClassicCursor(VMWSVGA_DEVICE* v, int width, int height, int hotX, int hotY, const uint32_t* argbPixels) { int encodedWidth = VmwSvgaClassicCursorWidth(width); uint32_t dwordsPerRow = ((uint32_t)encodedWidth + 31u) / 32u; @@ -447,6 +460,7 @@ done: return st; } +// Implements the upload Cursor Image operation. static KSTATUS VmwSvgaUploadCursorImage(VMWSVGA_DEVICE* v, int width, int height, int hotX, int hotY, const uint32_t* argbPixels) { if (!v || !v->HardwareCursor || !argbPixels || width <= 0 || height <= 0) return STATUS_INVALID_PARAMETER; @@ -464,6 +478,7 @@ static KSTATUS VmwSvgaUploadCursorImage(VMWSVGA_DEVICE* v, int width, int height return st; } +// Implements the define Cursor Image operation. static KSTATUS VmwSvgaDefineCursorImage(VMWSVGA_DEVICE* v, int width, int height, int hotX, int hotY, const uint32_t* argbPixels) { if (!v || !v->HardwareCursor || !argbPixels || width <= 0 || height <= 0) return STATUS_INVALID_PARAMETER; @@ -495,10 +510,12 @@ static KSTATUS VmwSvgaDefineCursorImage(VMWSVGA_DEVICE* v, int width, int height } +// Implements the align Up32 operation. static uint32_t VmwSvgaAlignUp32(uint32_t value, uint32_t alignment) { return (value + alignment - 1u) & ~(alignment - 1u); } +// Implements the define Screen Object operation. static KSTATUS VmwSvgaDefineScreenObject(VMWSVGA_DEVICE* v) { if (!v || !v->FifoReady || !v->UseScreenObject) return STATUS_INVALID_PARAMETER; @@ -506,50 +523,52 @@ static KSTATUS VmwSvgaDefineScreenObject(VMWSVGA_DEVICE* v) { KSTATUS st = VmwSvgaFifoWrite(v, SVGA_CMD_DEFINE_SCREEN); if (!KSUCCESS(st)) return st; - /* SVGAScreenObject, structSize = 11 dwords with backingStore+cloneCount. */ - st = VmwSvgaFifoWrite(v, 44u); /* structSize */ + // SVGAScreenObject, structSize = 11 dwords with backingStore+cloneCount. + st = VmwSvgaFifoWrite(v, 44u); // structSize if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, v->ScreenId); /* id */ + st = VmwSvgaFifoWrite(v, v->ScreenId); // id if (!KSUCCESS(st)) return st; st = VmwSvgaFifoWrite(v, SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY); if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, v->Width); /* size.width */ + st = VmwSvgaFifoWrite(v, v->Width); // size.width if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, v->Height); /* size.height */ + st = VmwSvgaFifoWrite(v, v->Height); // size.height if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, 0u); /* root.x */ + st = VmwSvgaFifoWrite(v, 0u); // root.x if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, 0u); /* root.y */ + st = VmwSvgaFifoWrite(v, 0u); // root.y if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, SVGA_GMR_FRAMEBUFFER); /* backingStore.ptr.gmrId */ + st = VmwSvgaFifoWrite(v, SVGA_GMR_FRAMEBUFFER); // backingStore.ptr.gmrId if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, v->ScreenBackingOffset); /* backingStore.ptr.offset */ + st = VmwSvgaFifoWrite(v, v->ScreenBackingOffset); // backingStore.ptr.offset if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, v->BytesPerLine); /* backingStore.pitch */ + st = VmwSvgaFifoWrite(v, v->BytesPerLine); // backingStore.pitch if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, 0u); /* cloneCount */ + st = VmwSvgaFifoWrite(v, 0u); // cloneCount if (!KSUCCESS(st)) return st; return VmwSvgaSyncDevice(v); } +// Implements the define Gmrfb operation. static KSTATUS VmwSvgaDefineGmrfb(VMWSVGA_DEVICE* v) { if (!v || !v->FifoReady || !v->UseScreenObject) return STATUS_INVALID_PARAMETER; KSTATUS st = VmwSvgaFifoWrite(v, SVGA_CMD_DEFINE_GMRFB); if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, SVGA_GMR_FRAMEBUFFER); /* ptr.gmrId */ + st = VmwSvgaFifoWrite(v, SVGA_GMR_FRAMEBUFFER); // ptr.gmrId if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, v->ScreenSourceOffset); /* ptr.offset */ + st = VmwSvgaFifoWrite(v, v->ScreenSourceOffset); // ptr.offset if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, v->BytesPerLine); /* bytesPerLine */ + st = VmwSvgaFifoWrite(v, v->BytesPerLine); // bytesPerLine if (!KSUCCESS(st)) return st; st = VmwSvgaFifoWrite(v, SVGA_GMRFB_FORMAT_32BPP_24DEPTH); if (!KSUCCESS(st)) return st; return STATUS_SUCCESS; } +// Blits gmrfb To Screen. static KSTATUS VmwSvgaBlitGmrfbToScreen(VMWSVGA_DEVICE* v, int x, int y, int w, int h) { DISPLAY_RECT r = { x, y, w, h }; if (!VmwSvgaClipRect(v, &r)) @@ -557,25 +576,26 @@ static KSTATUS VmwSvgaBlitGmrfbToScreen(VMWSVGA_DEVICE* v, int x, int y, int w, KSTATUS st = VmwSvgaFifoWrite(v, SVGA_CMD_BLIT_GMRFB_TO_SCREEN); if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, (uint32_t)r.X); /* srcOrigin.x */ + st = VmwSvgaFifoWrite(v, (uint32_t)r.X); // srcOrigin.x if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, (uint32_t)r.Y); /* srcOrigin.y */ + st = VmwSvgaFifoWrite(v, (uint32_t)r.Y); // srcOrigin.y if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, (uint32_t)r.X); /* destRect.left */ + st = VmwSvgaFifoWrite(v, (uint32_t)r.X); // destRect.left if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, (uint32_t)r.Y); /* destRect.top */ + st = VmwSvgaFifoWrite(v, (uint32_t)r.Y); // destRect.top if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, (uint32_t)(r.X + r.W)); /* destRect.right */ + st = VmwSvgaFifoWrite(v, (uint32_t)(r.X + r.W)); // destRect.right if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, (uint32_t)(r.Y + r.H)); /* destRect.bottom */ + st = VmwSvgaFifoWrite(v, (uint32_t)(r.Y + r.H)); // destRect.bottom if (!KSUCCESS(st)) return st; - st = VmwSvgaFifoWrite(v, v->ScreenId); /* destScreenId */ + st = VmwSvgaFifoWrite(v, v->ScreenId); // destScreenId if (!KSUCCESS(st)) return st; VmwSvgaWakeFifo(v); return STATUS_SUCCESS; } +// Initializes screen Object. static KSTATUS VmwSvgaInitializeScreenObject(VMWSVGA_DEVICE* v) { if (!v || !v->FifoReady) return STATUS_INVALID_PARAMETER; @@ -586,12 +606,11 @@ static KSTATUS VmwSvgaInitializeScreenObject(VMWSVGA_DEVICE* v) { bool hasScreenObject2 = ((v->FifoCaps & SVGA_FIFO_CAP_SCREEN_OBJECT_2) != 0) && ((v->Capabilities & SVGA_CAP_SCREEN_OBJECT_2) != 0); - /* - * Real VMware can advertise SCREEN_OBJECT_2 without also setting the - * original FIFO_CAP_SCREEN_OBJECT bit. The command set is still the - * Screen Object command set: DEFINE_SCREEN, DEFINE_GMRFB, and - * BLIT_GMRFB_TO_SCREEN. Treat either capability generation as usable. - */ + // Real VMware can advertise SCREEN_OBJECT_2 without also setting the + // original FIFO_CAP_SCREEN_OBJECT bit. The command set is still the + // Screen Object command set: DEFINE_SCREEN, DEFINE_GMRFB, and + // BLIT_GMRFB_TO_SCREEN. Treat either capability generation as usable. + if (!hasScreenObject1 && !hasScreenObject2) { DbgPrint("VMWSVGA: screen object unavailable: screenObject1=%u screenObject2=%u caps=0x%x fifoCaps=0x%x\n", hasScreenObject1 ? 1u : 0u, @@ -640,6 +659,7 @@ static KSTATUS VmwSvgaInitializeScreenObject(VMWSVGA_DEVICE* v) { return STATUS_SUCCESS; } +// Implements the legacy Update operation. static KSTATUS VmwSvgaLegacyUpdate(VMWSVGA_DEVICE* v, int x, int y, int w, int h) { DISPLAY_RECT r = { x, y, w, h }; if (!VmwSvgaClipRect(v, &r)) @@ -660,6 +680,7 @@ static KSTATUS VmwSvgaLegacyUpdate(VMWSVGA_DEVICE* v, int x, int y, int w, int h return STATUS_SUCCESS; } +// Updates the requested value. static KSTATUS VmwSvgaUpdate(VMWSVGA_DEVICE* v, int x, int y, int w, int h) { DISPLAY_RECT r = { x, y, w, h }; if (!VmwSvgaClipRect(v, &r)) @@ -676,6 +697,7 @@ static KSTATUS VmwSvgaUpdate(VMWSVGA_DEVICE* v, int x, int y, int w, int h) { return VmwSvgaLegacyUpdate(v, r.X, r.Y, r.W, r.H); } +// Waits until the SVGA host has consumed the queued FIFO work. static KSTATUS VmwSvgaSyncDevice(VMWSVGA_DEVICE* v) { if (!v) return STATUS_INVALID_PARAMETER; @@ -691,6 +713,7 @@ static KSTATUS VmwSvgaSyncDevice(VMWSVGA_DEVICE* v) { return STATUS_TIMEOUT; } +// Implements the blend Pixel operation. static uint32_t VmwSvgaBlendPixel(uint32_t dst, uint32_t src) { uint8_t a = (uint8_t)(src >> 24); if (a == 0) return dst; @@ -709,10 +732,12 @@ static uint32_t VmwSvgaBlendPixel(uint32_t dst, uint32_t src) { return ((uint32_t)rr << 16) | ((uint32_t)gg << 8) | bb; } +// Implements the from Display operation. static VMWSVGA_DEVICE* VmwSvgaFromDisplay(DISPLAY_DEVICE* device) { return device ? (VMWSVGA_DEVICE*)device->DriverContext : NULL; } +// Implements the display Get Mode operation. static KSTATUS VmwSvgaDisplayGetMode(DISPLAY_DEVICE* device, DISPLAY_MODE* outMode) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !outMode || !v->Framebuffer) @@ -724,6 +749,7 @@ static KSTATUS VmwSvgaDisplayGetMode(DISPLAY_DEVICE* device, DISPLAY_MODE* outMo return STATUS_SUCCESS; } +// Implements the display Blit operation. static KSTATUS VmwSvgaDisplayBlit(DISPLAY_DEVICE* device, int x, int y, int w, int h, const uint32_t* pixels) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !v->Backbuffer || !pixels || w <= 0 || h <= 0) @@ -747,6 +773,7 @@ static KSTATUS VmwSvgaDisplayBlit(DISPLAY_DEVICE* device, int x, int y, int w, i return STATUS_SUCCESS; } +// Implements the display Fill Rect operation. static KSTATUS VmwSvgaDisplayFillRect(DISPLAY_DEVICE* device, int x, int y, int w, int h, uint32_t color) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !v->Backbuffer || w <= 0 || h <= 0) @@ -767,6 +794,7 @@ static KSTATUS VmwSvgaDisplayFillRect(DISPLAY_DEVICE* device, int x, int y, int return STATUS_SUCCESS; } +// Implements the display Copy Rect operation. static KSTATUS VmwSvgaDisplayCopyRect(DISPLAY_DEVICE* device, int dstX, int dstY, int srcX, int srcY, int w, int h) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !v->Backbuffer || w <= 0 || h <= 0) @@ -803,6 +831,7 @@ static KSTATUS VmwSvgaDisplayCopyRect(DISPLAY_DEVICE* device, int dstX, int dstY return STATUS_SUCCESS; } +// Implements the display Read Rect operation. static KSTATUS VmwSvgaDisplayReadRect(DISPLAY_DEVICE* device, int x, int y, int w, int h, uint32_t* outPixels, uint32_t outStride) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !v->Backbuffer || !outPixels || outStride == 0 || w <= 0 || h <= 0) @@ -825,6 +854,7 @@ static KSTATUS VmwSvgaDisplayReadRect(DISPLAY_DEVICE* device, int x, int y, int return STATUS_SUCCESS; } +// Implements the display Present operation. static KSTATUS VmwSvgaDisplayPresent(DISPLAY_DEVICE* device, const DISPLAY_RECT* rects, size_t rectCount) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !v->Framebuffer || !v->Backbuffer) @@ -866,6 +896,7 @@ static KSTATUS VmwSvgaDisplayPresent(DISPLAY_DEVICE* device, const DISPLAY_RECT* return result; } +// Implements the display Sync operation. static KSTATUS VmwSvgaDisplaySync(DISPLAY_DEVICE* device) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); KSTATUS st = VmwSvgaSyncDevice(v); @@ -874,6 +905,7 @@ static KSTATUS VmwSvgaDisplaySync(DISPLAY_DEVICE* device) { return st; } +// Implements the display Set Cursor Image operation. static KSTATUS VmwSvgaDisplaySetCursorImage(DISPLAY_DEVICE* device, int width, int height, int hotX, int hotY, const uint32_t* argbPixels) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !v->HardwareCursor) @@ -881,6 +913,7 @@ static KSTATUS VmwSvgaDisplaySetCursorImage(DISPLAY_DEVICE* device, int width, i return VmwSvgaDefineCursorImage(v, width, height, hotX, hotY, argbPixels); } +// Implements the display Set Cursor Position operation. static KSTATUS VmwSvgaDisplaySetCursorPosition(DISPLAY_DEVICE* device, int x, int y) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v) @@ -893,6 +926,7 @@ static KSTATUS VmwSvgaDisplaySetCursorPosition(DISPLAY_DEVICE* device, int x, in return STATUS_SUCCESS; } +// Implements the restore Cursor operation. static void VmwSvgaRestoreCursor(VMWSVGA_DEVICE* v) { if (!v || !v->CursorDrawn || !v->Backbuffer || !v->Framebuffer) return; @@ -912,6 +946,7 @@ static void VmwSvgaRestoreCursor(VMWSVGA_DEVICE* v) { v->CursorDrawY = -1; } +// Draws cursor. static void VmwSvgaDrawCursor(VMWSVGA_DEVICE* v) { if (!v || !v->Backbuffer || !v->Framebuffer) return; @@ -944,6 +979,7 @@ static void VmwSvgaDrawCursor(VMWSVGA_DEVICE* v) { (void)VmwSvgaUpdate(v, dirty.X, dirty.Y, dirty.W, dirty.H); } +// Implements the display Show Cursor operation. static KSTATUS VmwSvgaDisplayShowCursor(DISPLAY_DEVICE* device, bool show) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v) @@ -978,6 +1014,7 @@ static KSTATUS VmwSvgaDisplayShowCursor(DISPLAY_DEVICE* device, bool show) { return STATUS_SUCCESS; } +// Implements the display Query Stats operation. static KSTATUS VmwSvgaDisplayQueryStats(DISPLAY_DEVICE* device, DISPLAY_STATS* outStats) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !outStats) @@ -1000,6 +1037,7 @@ static const DISPLAY_DEVICE_OPS gVmwSvgaDisplayOps = { .QueryStats = VmwSvgaDisplayQueryStats, }; +// Implements the select Bars operation. static KSTATUS VmwSvgaSelectBars(VMWSVGA_DEVICE* v) { PCI_BAR bar; memset(&bar, 0, sizeof(bar)); @@ -1029,10 +1067,12 @@ static KSTATUS VmwSvgaSelectBars(VMWSVGA_DEVICE* v) { return STATUS_SUCCESS; } +// Implements the mmio Page Flags operation. static uint64_t VmwSvgaMmioPageFlags(void) { return PAGE_PRESENT | PAGE_WRITE | PAGE_WRITETHROUGH | PAGE_NOCACHE | PAGE_NX; } +// Maps bars. static KSTATUS VmwSvgaMapBars(VMWSVGA_DEVICE* v) { uint64_t mmioFlags = VmwSvgaMmioPageFlags(); KSTATUS st = PciMapBar(v->Pdo, 1, mmioFlags, @@ -1068,6 +1108,7 @@ static KSTATUS VmwSvgaMapBars(VMWSVGA_DEVICE* v) { return STATUS_SUCCESS; } +// Returns mode. static KSTATUS VmwSvgaReadMode(VMWSVGA_DEVICE* v) { v->Width = VmwSvgaReadReg(v, SVGA_REG_WIDTH); v->Height = VmwSvgaReadReg(v, SVGA_REG_HEIGHT); @@ -1133,6 +1174,7 @@ static KSTATUS VmwSvgaReadMode(VMWSVGA_DEVICE* v) { return STATUS_SUCCESS; } +// Returns the active FIFO size reported by the device, not the larger PCI BAR aperture. static uint32_t VmwSvgaGetFifoMaxBytes(VMWSVGA_DEVICE* v) { uint64_t limit = v->FifoBytes; if (v->FifoDeviceBytes != 0 && (uint64_t)v->FifoDeviceBytes < limit) @@ -1142,6 +1184,7 @@ static uint32_t VmwSvgaGetFifoMaxBytes(VMWSVGA_DEVICE* v) { return (uint32_t)limit & ~3u; } +// Initializes fifo. static KSTATUS VmwSvgaInitializeFifo(VMWSVGA_DEVICE* v) { if (!v->Fifo || v->FifoBytes < 4096u) return STATUS_DEVICE_ERROR; @@ -1188,6 +1231,7 @@ static KSTATUS VmwSvgaInitializeFifo(VMWSVGA_DEVICE* v) { return STATUS_SUCCESS; } +// Starts device. static KSTATUS VmwSvgaStartDevice(VMWSVGA_DEVICE* v) { if (!v || v->Magic != VMWSVGA_DEVICE_MAGIC || !v->Fdo || !v->Pdo) return STATUS_INVALID_PARAMETER; @@ -1322,6 +1366,7 @@ static KSTATUS VmwSvgaStartDevice(VMWSVGA_DEVICE* v) { return STATUS_SUCCESS; } +// Dispatches pnp. KSTATUS VmwSvgaDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp || !device->DeviceExtension) return STATUS_INVALID_PARAMETER; @@ -1368,6 +1413,7 @@ KSTATUS VmwSvgaDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } +// Implements the add Device operation. KSTATUS VmwSvgaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return STATUS_INVALID_PARAMETER; @@ -1396,6 +1442,7 @@ KSTATUS VmwSvgaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObj return STATUS_SUCCESS; } +// Implements the driver Entry operation. KSTATUS DriverEntry(const HAL_API* hal) { if (!hal) return STATUS_INVALID_PARAMETER; diff --git a/code/drivers/display/vmwaresvga/vmwaresvga.h b/code/drivers/display/vmwaresvga/vmwaresvga.h index fbe6f7c..feb8567 100644 --- a/code/drivers/display/vmwaresvga/vmwaresvga.h +++ b/code/drivers/display/vmwaresvga/vmwaresvga.h @@ -1,3 +1,5 @@ +// VMware SVGA-II device definitions shared by the display provider implementation. + #pragma once // vmwaresvga.h - VMware SVGA-II display provider internals. @@ -19,7 +21,7 @@ #define VMWSVGA_VENDOR_VMWARE 0x15ADu #define VMWSVGA_DEVICE_SVGA2 0x0405u -#define VMWSVGA_DEVICE_MAGIC 0x564D5356u /* VMSV */ +#define VMWSVGA_DEVICE_MAGIC 0x564D5356u // VMSV #define SVGA_ID_INVALID 0xFFFFFFFFu #define SVGA_ID_0 0x90000000u @@ -125,11 +127,10 @@ #define SVGA_SCREEN_OBJECT_ID_PRIMARY 0u #define SVGA_GMRFB_FORMAT_32BPP_24DEPTH ((32u) | (24u << 8)) -/* - * The production path is legacy GFB + UPDATE. Screen objects are kept behind - * an opt-in switch until the SO/GMRFB path is independently validated on real - * VMware hosts. - */ +// The production path is legacy GFB + UPDATE. Screen objects are kept behind +// an opt-in switch until the SO/GMRFB path is independently validated on real +// VMware hosts. + #ifndef VMWSVGA_ENABLE_SCREEN_OBJECTS #define VMWSVGA_ENABLE_SCREEN_OBJECTS 0 #endif diff --git a/code/drivers/fs/fat32/fat32.c b/code/drivers/fs/fat32/fat32.c index 2cb5d6a..ed99abc 100644 --- a/code/drivers/fs/fat32/fat32.c +++ b/code/drivers/fs/fat32/fat32.c @@ -1,9 +1,8 @@ -// fat32.c - FAT32 filesystem core, directory, cache, and I/O implementation. +// FAT32 filesystem driver. This file owns filesystem operations and FAT-backed file access. + #include "fat32.h" -// --------------------------------------------------------------------------- -// On-disk structures -// --------------------------------------------------------------------------- +// On-disk structures. #pragma pack(push, 1) typedef struct { @@ -110,9 +109,7 @@ typedef struct { // FAT32_VOL forward declaration (needed by cache helpers). typedef struct FAT32_VOL_S FAT32_VOL; -// --------------------------------------------------------------------------- // FAT sector cache (fixes #1 and #5) -// --------------------------------------------------------------------------- // 32 direct-mapped slots, indexed by (lba % FAT_CACHE_SLOTS). // Write-back: WriteFatEntry modifies the in-cache bytes and marks the slot // dirty. FlushFatCache() propagates dirty slots to every FAT copy at once, @@ -164,12 +161,14 @@ static KSTATUS FatCacheRead(FAT32_VOL *v, uint64_t lba, uint8_t **out) { return STATUS_SUCCESS; } +// Implements the fat Cache Mark Dirty operation. static void FatCacheMarkDirty(FAT32_VOL *v, uint64_t lba) { uint32_t slot = (uint32_t)(lba % FAT_CACHE_SLOTS); if (gFatCache[slot].valid && gFatCache[slot].vol == v && gFatCache[slot].lba == lba) gFatCache[slot].dirty = true; } +// Implements the fat Cache Invalidate operation. static void FatCacheInvalidate(void) { for (int i = 0; i < FAT_CACHE_SLOTS; i++) { gFatCache[i].vol = (FAT32_VOL*)0; @@ -182,9 +181,7 @@ static void FatCacheInvalidate(void) { // Defined after FAT32_VOL is fully declared (below). static void FlushFatCache(FAT32_VOL *v); -// --------------------------------------------------------------------------- -// Driver state -// --------------------------------------------------------------------------- +// Driver state. struct FAT32_VOL_S { uint8_t DriveIndex; // physical disk DEVICE_OBJECT index uint64_t PartitionLba; // absolute LBA of the mounted volume @@ -208,9 +205,7 @@ typedef struct { uint32_t DirentOffset; } FAT32_FILE; -// --------------------------------------------------------------------------- -// Raw sector I/O (bypasses FAT cache; used for file data and cache eviction) -// --------------------------------------------------------------------------- +// Raw sector I/O (bypasses FAT cache; used for file data and cache eviction). static KSTATUS ReadSectorsRaw(FAT32_VOL *v, uint64_t lba, uint32_t count, void *buf) { if (!v) return STATUS_INVALID_PARAMETER; @@ -225,15 +220,15 @@ static KSTATUS WriteSectorsRaw(FAT32_VOL *v, uint64_t lba, // Convenience aliases for file-data I/O. static KSTATUS ReadSectors (FAT32_VOL *v, uint64_t lba, uint32_t n, void *b) { return ReadSectorsRaw (v, lba, n, b); } +// Updates sectors. static KSTATUS WriteSectors(FAT32_VOL *v, uint64_t lba, uint32_t n, const void *b) { return WriteSectorsRaw(v, lba, n, b); } +// Implements the cluster To Lba operation. static uint64_t ClusterToLba(FAT32_VOL *v, uint32_t cluster) { return v->DataStart + (uint64_t)(cluster - 2) * v->SectorsPerCluster; } -// --------------------------------------------------------------------------- -// FlushFatCache โ€” needs full FAT32_VOL definition -// --------------------------------------------------------------------------- +// FlushFatCache โ€” needs full FAT32_VOL definition. static void FlushFatCache(FAT32_VOL *v) { uint64_t fat0Start = (uint64_t)v->PartitionLba + v->ReservedSectors; @@ -253,9 +248,7 @@ static void FlushFatCache(FAT32_VOL *v) { } } -// --------------------------------------------------------------------------- -// FAT read / write (through cache) -// --------------------------------------------------------------------------- +// FAT read / write (through cache). static uint32_t FatEntry(FAT32_VOL *v, uint32_t cluster) { uint32_t fatOffset = cluster * 4; @@ -268,6 +261,7 @@ static uint32_t FatEntry(FAT32_VOL *v, uint32_t cluster) { return *(uint32_t *)(sec + offInSec) & 0x0FFFFFFF; } +// Updates fat Entry. static KSTATUS WriteFatEntry(FAT32_VOL *v, uint32_t cluster, uint32_t value) { uint32_t fatOffset = cluster * 4; uint64_t sector = (uint64_t)v->PartitionLba + v->ReservedSectors @@ -285,9 +279,7 @@ static KSTATUS WriteFatEntry(FAT32_VOL *v, uint32_t cluster, uint32_t value) { return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// Cluster allocation (fix #3: next-free hint + two-phase wrap-around scan) -// --------------------------------------------------------------------------- +// Cluster allocation (fix #3: next-free hint + two-phase wrap-around scan). static uint32_t AllocCluster(FAT32_VOL *v) { if (v->TotalClusters == 0) return 0; @@ -317,6 +309,7 @@ static uint32_t AllocCluster(FAT32_VOL *v) { return 0; } +// Appends cluster. static uint32_t AppendCluster(FAT32_VOL *v, uint32_t lastCluster) { uint32_t newCluster = AllocCluster(v); if (!newCluster) return 0; @@ -324,6 +317,7 @@ static uint32_t AppendCluster(FAT32_VOL *v, uint32_t lastCluster) { return newCluster; } +// Returns chain End. static uint32_t GetChainEnd(FAT32_VOL *v, uint32_t start, uint32_t *outCount) { uint32_t cluster = start, prev = start, count = 0; while (cluster >= 2 && cluster < FAT32_EOC) { @@ -334,6 +328,7 @@ static uint32_t GetChainEnd(FAT32_VOL *v, uint32_t start, uint32_t *outCount) { return prev; } +// Releases cluster Chain. static void FreeClusterChain(FAT32_VOL *v, uint32_t start) { uint32_t cluster = start; while (cluster >= 2 && cluster < FAT32_EOC) { @@ -344,9 +339,7 @@ static void FreeClusterChain(FAT32_VOL *v, uint32_t start) { } } -// --------------------------------------------------------------------------- -// FAT timestamp and DIRENT metadata helpers -// --------------------------------------------------------------------------- +// FAT timestamp and DIRENT metadata helpers. typedef struct FAT32_ENCODED_TIME { uint16_t Date; @@ -367,10 +360,12 @@ typedef struct FAT32_DIRENT_UPDATE { #define FAT32_DIRENT_UPDATE_WRITE_TIME 0x00000008u #define FAT32_DIRENT_UPDATE_ACCESS_DATE 0x00000010u +// Implements the fat Is Leap Year operation. static int FatIsLeapYear(uint32_t year) { return ((year % 4u) == 0u && (year % 100u) != 0u) || ((year % 400u) == 0u); } +// Implements the fat Days In Month operation. static uint32_t FatDaysInMonth(uint32_t year, uint32_t month) { static const uint8_t days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; if (month < 1u || month > 12u) return 31u; @@ -389,11 +384,13 @@ static uint64_t FatCalendarToEpochSeconds(uint32_t year, uint32_t month, uint32_ return (((days * 24u) + hour) * 60u + minute) * 60u + second; } +// Implements the fat Day Of Week operation. static uint8_t FatDayOfWeek(uint32_t year, uint32_t month, uint32_t day) { uint64_t epoch = FatCalendarToEpochSeconds(year, month, day, 0, 0, 0); return (uint8_t)(((epoch / 86400u) + 4u) % 7u); } +// Implements the fat Encode Date operation. static uint16_t FatEncodeDate(const SYS_SYSTEM_TIME* t) { uint32_t year = t && t->Year ? t->Year : 1980u; uint32_t month = t && t->Month ? t->Month : 1u; @@ -408,6 +405,7 @@ static uint16_t FatEncodeDate(const SYS_SYSTEM_TIME* t) { return (uint16_t)(((year - 1980u) << 9) | (month << 5) | day); } +// Implements the fat Encode Time operation. static uint16_t FatEncodeTime(const SYS_SYSTEM_TIME* t) { uint32_t hour = t ? t->Hour : 0u; uint32_t minute = t ? t->Minute : 0u; @@ -418,6 +416,7 @@ static uint16_t FatEncodeTime(const SYS_SYSTEM_TIME* t) { return (uint16_t)((hour << 11) | (minute << 5) | (second / 2u)); } +// Implements the fat Encode Create Time Tenth operation. static uint8_t FatEncodeCreateTimeTenth(const SYS_SYSTEM_TIME* t) { uint32_t second = t ? t->Second : 0u; uint32_t ms = t ? t->Millisecond : 0u; @@ -428,6 +427,7 @@ static uint8_t FatEncodeCreateTimeTenth(const SYS_SYSTEM_TIME* t) { return (uint8_t)v; } +// Implements the fat Query Encoded Time operation. static void FatQueryEncodedTime(FAT32_ENCODED_TIME* out) { SYS_SYSTEM_TIME now; memset(&now, 0, sizeof(now)); @@ -472,6 +472,7 @@ static void FatDecodeDateTime(uint16_t date, uint16_t time, uint8_t createTenth, out->EpochSeconds = FatCalendarToEpochSeconds(year, month, day, hour, minute, second); } +// Implements the fat Decode Access Date operation. static void FatDecodeAccessDate(uint16_t date, SYS_SYSTEM_TIME* out) { FatDecodeDateTime(date, 0, 0, out); } @@ -527,9 +528,7 @@ static KSTATUS DirentUpdateFirstCluster(FAT32_VOL *v, uint64_t lba, return DirentUpdateMetadata(v, lba, offset, &u); } -// --------------------------------------------------------------------------- -// 8.3 name matching / assembly -// --------------------------------------------------------------------------- +// 8.3 name matching / assembly. static int MatchRaw83(const char dirName[8], const char dirExt[3], const char wantName[8], const char wantExt[3]) { @@ -541,6 +540,7 @@ static char FatUpperChar(char c); static int FatIsLowerChar(char c); static int FatIsValidShortChar(char c); +// Implements the make83 Name V operation. static void Make83NameV(SYS_STRING_VIEW src, char name8[8], char ext3[3]) { memset(name8, ' ', 8); memset(ext3, ' ', 3); @@ -571,19 +571,20 @@ static void Make83NameV(SYS_STRING_VIEW src, char name8[8], char ext3[3]) { } } -// --------------------------------------------------------------------------- -// LFN assembly / matching -// --------------------------------------------------------------------------- +// LFN assembly / matching. #define MAX_LFN 256 +// Implements the fat Upper Char operation. static char FatUpperChar(char c) { return (c >= 'a' && c <= 'z') ? (char)(c - 32) : c; } +// Implements the fat Is Lower Char operation. static int FatIsLowerChar(char c) { return c >= 'a' && c <= 'z'; } +// Implements the fat Is Valid Short Char operation. static int FatIsValidShortChar(char c) { c = FatUpperChar(c); if (c >= 'A' && c <= 'Z') return 1; @@ -621,12 +622,14 @@ static int FatNameIsStructurallyShort83V(SYS_STRING_VIEW name) { return baseLen >= 1 && baseLen <= 8 && extLen <= 3; } +// Implements the fat Component Has Lower V operation. static int FatComponentHasLowerV(SYS_STRING_VIEW name, size_t start, size_t end) { for (size_t i = start; i < end; i++) if (FatIsLowerChar(name.Data[i])) return 1; return 0; } +// Implements the fat Component Has Upper V operation. static int FatComponentHasUpperV(SYS_STRING_VIEW name, size_t start, size_t end) { for (size_t i = start; i < end; i++) if (name.Data[i] >= 'A' && name.Data[i] <= 'Z') return 1; @@ -667,6 +670,7 @@ static int FatNameNeedsLfnForCreateV(SYS_STRING_VIEW name) { return 0; } +// Implements the fat Short Name Case Flags V operation. static uint8_t FatShortNameCaseFlagsV(SYS_STRING_VIEW name) { if (!FatNameIsStructurallyShort83V(name)) return 0; size_t baseEnd, extStart, extEnd; @@ -682,6 +686,7 @@ static uint8_t FatShortNameCaseFlagsV(SYS_STRING_VIEW name) { return flags; } +// Implements the lfn Checksum operation. static uint8_t LfnChecksum(const char name8[8], const char ext3[3]) { uint8_t sum = 0; for (int i = 0; i < 11; i++) { @@ -691,6 +696,7 @@ static uint8_t LfnChecksum(const char name8[8], const char ext3[3]) { return sum; } +// Implements the lfn Set Char operation. static void LfnSetChar(LFN_ENTRY *e, int idx, uint16_t value) { if (idx < 5) e->Name1[idx] = value; else if (idx < 11) e->Name2[idx - 5] = value; @@ -719,6 +725,7 @@ static void BuildLfnEntry(LFN_ENTRY *e, const char *name, size_t nameLen, } } +// Creates legacy Broken Dot83. static void MakeLegacyBrokenDot83(const char *src, char name8[8], char ext3[3]) { // This exactly models the pre-fix bug for ".doomrc": empty name + "DOO". memset(name8, ' ', 8); @@ -758,12 +765,14 @@ static int ShortNameExistsRaw(FAT32_VOL *v, uint32_t dirCluster, return 0; } +// Implements the fat Alias Append Char operation. static void FatAliasAppendChar(char *dst, int *len, int maxLen, char c) { c = FatUpperChar(c); if (!FatIsValidShortChar(c)) return; if (*len < maxLen) dst[(*len)++] = c; } +// Builds alias Stem Ext V. static void BuildAliasStemExtV(SYS_STRING_VIEW src, char stem[9], char ext3[3]) { memset(stem, 0, 9); memset(ext3, ' ', 3); @@ -838,6 +847,7 @@ static int MakeUniqueShortAliasV(FAT32_VOL *v, uint32_t dirCluster, return 0; } +// Creates legacy Broken Dot83 V. static void MakeLegacyBrokenDot83V(SYS_STRING_VIEW src, char name8[8], char ext3[3]) { // This exactly models the pre-fix bug for ".doomrc": empty name + "DOO". memset(name8, ' ', 8); @@ -894,6 +904,7 @@ static KSTATUS DeleteLegacyBrokenDotAliasV(FAT32_VOL *v, uint32_t dirCluster, return STATUS_SUCCESS; } +// Implements the lfn Append operation. static void LfnAppend(char *lfn, const LFN_ENTRY *e) { int seq = (e->Order & 0x3F) - 1; if (seq < 0 || seq >= (MAX_LFN / 13)) return; @@ -910,13 +921,12 @@ static void LfnAppend(char *lfn, const LFN_ENTRY *e) { } -// --------------------------------------------------------------------------- -// Directory search and view-native path traversal -// --------------------------------------------------------------------------- +// Directory search and view-native path traversal. static int Fat32IsPathSep(char c) { return c == '\\' || c == '/'; } +// Implements the name View Is Valid operation. static int Fat32NameViewIsValid(SYS_STRING_VIEW name) { if (!SysSvIsValid(name)) return 0; if (name.Length == 0 || name.Length >= MAX_LFN) return 0; @@ -927,6 +937,7 @@ static int Fat32NameViewIsValid(SYS_STRING_VIEW name) { return 1; } +// Implements the lfn Match V operation. static int LfnMatchV(const char *lfn, SYS_STRING_VIEW want) { if (!lfn || !SysSvIsValid(want)) return 0; size_t i = 0; @@ -1104,9 +1115,7 @@ static KSTATUS SplitPathV(SYS_STRING_VIEW path, SYS_STRING_VIEW* parent, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// Find a free DIRENT slot -// --------------------------------------------------------------------------- +// Find a free DIRENT slot. static int FindFreeDirent(FAT32_VOL *v, uint32_t dirCluster, uint64_t *outLba, uint32_t *outOffset) { uint8_t *clusterBuf = (uint8_t *)MmAllocatePool(v->BytesPerCluster); @@ -1197,9 +1206,7 @@ static int FindFreeDirentRun(FAT32_VOL *v, uint32_t dirCluster, uint32_t needed, return 0; } -// --------------------------------------------------------------------------- -// Open / Close -// --------------------------------------------------------------------------- +// Open / Close. KSTATUS Fat32Open(IO_FILESYSTEM *fs, SYS_STRING_VIEW path, void **fileCtx) { if (!fs || !fileCtx || !SysSvIsValid(path) || path.Length == 0) return STATUS_INVALID_PARAMETER; @@ -1217,6 +1224,7 @@ KSTATUS Fat32Open(IO_FILESYSTEM *fs, SYS_STRING_VIEW path, void **fileCtx) { return STATUS_SUCCESS; } +// Releases the requested object. void Fat32Close(IO_FILESYSTEM *fs, void *fileCtx) { (void)fs; FAT32_FILE *f = (FAT32_FILE *)fileCtx; @@ -1224,14 +1232,12 @@ void Fat32Close(IO_FILESYSTEM *fs, void *fileCtx) { MmFreePool(fileCtx); } -// --------------------------------------------------------------------------- // Read (fix #4: contiguous-run coalescing) -// --------------------------------------------------------------------------- // We peek ahead in the FAT chain: if cluster N+1 == cluster N physically, // extend the current run instead of issuing a new ReadSectors call. // Run length is capped at MAX_RUN_SECTORS to stay within the AHCI bounce // buffer (128 sectors = 64 KB). -// + // FatEntry() calls in the peek loop are nearly free because they hit the // FAT sector cache (fix #1). @@ -1326,9 +1332,7 @@ KSTATUS Fat32Read(IO_FILESYSTEM *fs, void *fileCtx, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- // Write (fix #4: contiguous-run coalescing) -// --------------------------------------------------------------------------- // Same strategy as read. Whole-cluster-aligned runs skip the read-modify- // write; partial head/tail clusters still require it. @@ -1442,11 +1446,10 @@ KSTATUS Fat32Write(IO_FILESYSTEM *fs, void *fileCtx, return (written == size) ? STATUS_SUCCESS : STATUS_DEVICE_ERROR; } -// --------------------------------------------------------------------------- -// Create -// --------------------------------------------------------------------------- +// Create. KSTATUS Fat32Truncate(IO_FILESYSTEM *fs, void *fileCtx, uint64_t newSize); +// Creates the requested object. KSTATUS Fat32Create(IO_FILESYSTEM *fs, SYS_STRING_VIEW path, void **fileCtx) { if (!fs || !fileCtx || !SysSvIsValid(path) || path.Length == 0) return STATUS_INVALID_PARAMETER; @@ -1559,9 +1562,7 @@ KSTATUS Fat32Create(IO_FILESYSTEM *fs, SYS_STRING_VIEW path, void **fileCtx) { return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// Truncate -// --------------------------------------------------------------------------- +// Truncate. KSTATUS Fat32Truncate(IO_FILESYSTEM *fs, void *fileCtx, uint64_t newSize) { (void)fs; FAT32_FILE *f = (FAT32_FILE *)fileCtx; @@ -1625,9 +1626,7 @@ update_size: return s; } } -// --------------------------------------------------------------------------- -// Delete -// --------------------------------------------------------------------------- +// Delete. KSTATUS Fat32Delete(IO_FILESYSTEM *fs, SYS_STRING_VIEW path) { if (!fs || !SysSvIsValid(path) || path.Length == 0) return STATUS_INVALID_PARAMETER; @@ -1650,13 +1649,12 @@ KSTATUS Fat32Delete(IO_FILESYSTEM *fs, SYS_STRING_VIEW path) { return STATUS_SUCCESS; } +// Returns size. uint64_t Fat32GetSize(IO_FILESYSTEM *fs, void *fileCtx) { (void)fs; return ((FAT32_FILE *)fileCtx)->FileSize; } -// --------------------------------------------------------------------------- // Directory enumeration (fix #2: cluster buffer cached in context) -// --------------------------------------------------------------------------- // Previously: allocate + ReadSectors + return 1 entry + free, every call. // Now: buffer lives in FAT32_DIR_CTX; ReadSectors fires only on cluster // boundaries. @@ -1672,6 +1670,7 @@ typedef struct { uint8_t *ClusterBuf; // allocated once in OpenDir, freed in CloseDir } FAT32_DIR_CTX; +// Opens dir. KSTATUS Fat32OpenDir(IO_FILESYSTEM *fs, SYS_STRING_VIEW dirPath, void **dirCtx) { if (!fs || !dirCtx || !SysSvIsValid(dirPath)) return STATUS_INVALID_PARAMETER; @@ -1703,6 +1702,7 @@ KSTATUS Fat32OpenDir(IO_FILESYSTEM *fs, SYS_STRING_VIEW dirPath, void **dirCtx) return STATUS_SUCCESS; } +// Returns dir. KSTATUS Fat32ReadDir(IO_FILESYSTEM *fs, void *dirCtx, KDIR_ENTRY *out) { (void)fs; FAT32_DIR_CTX *ctx = (FAT32_DIR_CTX *)dirCtx; @@ -1764,6 +1764,7 @@ KSTATUS Fat32ReadDir(IO_FILESYSTEM *fs, void *dirCtx, KDIR_ENTRY *out) { return STATUS_NO_MORE_FILES; } +// Releases dir. void Fat32CloseDir(IO_FILESYSTEM *fs, void *dirCtx) { (void)fs; FAT32_DIR_CTX *ctx = (FAT32_DIR_CTX *)dirCtx; @@ -1771,9 +1772,7 @@ void Fat32CloseDir(IO_FILESYSTEM *fs, void *dirCtx) { MmFreePool(ctx); } -// --------------------------------------------------------------------------- -// Volume scan (MBR + GPT + superfloppy) -// --------------------------------------------------------------------------- +// Volume scan (MBR + GPT + superfloppy). static const EFI_GUID GUID_EFI_SYSTEM = { 0xC12A7328, 0xF81F, 0x11D2, {0xBA,0x4B,0x00,0xA0,0xC9,0x3E,0xC9,0x3B} }; static const EFI_GUID GUID_MS_BASIC_DATA = { 0xEBD0A0A2, 0xB9E5, 0x4433, {0x87,0xC0,0x68,0xB6,0xB7,0x26,0x99,0xC7} }; static const EFI_GUID GUID_LINUX_BASIC_DATA = { 0x0FC63DAF, 0x8483, 0x4772, {0x8E,0x79,0x3D,0x69,0xD8,0x47,0x7D,0xE4} }; @@ -1785,6 +1784,7 @@ typedef struct FAT32_PARTITION_CANDIDATE { uint64_t SectorCount; } FAT32_PARTITION_CANDIDATE; +// Returns le32. static uint32_t ReadLe32(const void* p) { const uint8_t* b = (const uint8_t*)p; return (uint32_t)b[0] @@ -1793,6 +1793,7 @@ static uint32_t ReadLe32(const void* p) { | ((uint32_t)b[3] << 24); } +// Checks whether fat32 Vbr. static int IsFat32Vbr(FAT32_VOL *v, uint64_t lba) { uint8_t sector[512]; if (!KSUCCESS(ReadSectors(v, lba, 1, sector))) return 0; @@ -1946,9 +1947,7 @@ static uint32_t Fat32EnumerateDiskVolumes(uint8_t diskIndex, return count; } -// --------------------------------------------------------------------------- // Native async read/write -// --------------------------------------------------------------------------- // Metadata work (FAT traversal/allocation and partial-cluster read-modify // preparation) still runs synchronously in the caller/completion context, but // file data transfers are submitted as disk IRPs and completion is chained from @@ -1990,6 +1989,7 @@ static volatile int gFat32AsyncInitState; static void Fat32AsyncReadSubmitNext(FAT32_ASYNC_RW* ctx); static void Fat32AsyncWriteSubmitNext(FAT32_ASYNC_RW* ctx); +// Implements the async Worker operation. static void Fat32AsyncWorker(void* arg) { (void)arg; @@ -2013,6 +2013,7 @@ static void Fat32AsyncWorker(void* arg) { } } +// Implements the ensure Async Worker Started operation. static KSTATUS Fat32EnsureAsyncWorkerStarted(void) { uintptr_t flags = KeAcquireSpinlock(&gFat32AsyncLock); if (gFat32AsyncInitState == 2) { @@ -2044,6 +2045,7 @@ static KSTATUS Fat32EnsureAsyncWorkerStarted(void) { return s; } +// Implements the async Queue Continuation operation. static void Fat32AsyncQueueContinuation(FAT32_ASYNC_RW* ctx) { if (!ctx) return; @@ -2053,6 +2055,7 @@ static void Fat32AsyncQueueContinuation(FAT32_ASYNC_RW* ctx) { KeSignalSemaphore(gFat32AsyncSemaphore); } +// Implements the async Finish operation. static void Fat32AsyncFinish(FAT32_ASYNC_RW* ctx, KSTATUS status, size_t information) { if (!ctx) return; if (ctx->CurrentDevice) { @@ -2066,6 +2069,7 @@ static void Fat32AsyncFinish(FAT32_ASYNC_RW* ctx, KSTATUS status, size_t informa if (complete) complete(completeContext, status, information); } +// Implements the async Read Irp Complete operation. static void Fat32AsyncReadIrpComplete(IRP* irp, void* completeCtx) { FAT32_ASYNC_RW* ctx = (FAT32_ASYNC_RW*)completeCtx; if (!ctx) return; @@ -2089,6 +2093,7 @@ static void Fat32AsyncReadIrpComplete(IRP* irp, void* completeCtx) { Fat32AsyncQueueContinuation(ctx); } +// Implements the async Read Submit Next operation. static void Fat32AsyncReadSubmitNext(FAT32_ASYNC_RW* ctx) { if (ctx->Remaining == 0) { Fat32AsyncFinish(ctx, STATUS_SUCCESS, ctx->Done); @@ -2206,6 +2211,7 @@ KSTATUS Fat32ReadAsync(IO_FILESYSTEM *fs, void *fileCtx, return STATUS_PENDING; } +// Implements the async Write Irp Complete operation. static void Fat32AsyncWriteIrpComplete(IRP* irp, void* completeCtx) { FAT32_ASYNC_RW* ctx = (FAT32_ASYNC_RW*)completeCtx; if (!ctx) return; @@ -2228,6 +2234,7 @@ static void Fat32AsyncWriteIrpComplete(IRP* irp, void* completeCtx) { Fat32AsyncQueueContinuation(ctx); } +// Implements the async Write Submit Next operation. static void Fat32AsyncWriteSubmitNext(FAT32_ASYNC_RW* ctx) { if (ctx->Remaining == 0) { uint64_t newEnd = ctx->Offset + ctx->Done; @@ -2396,9 +2403,7 @@ KSTATUS Fat32WriteAsync(IO_FILESYSTEM *fs, void *fileCtx, return STATUS_PENDING; } -// --------------------------------------------------------------------------- -// DriverEntry -// --------------------------------------------------------------------------- +// DriverEntry. #define FAT32_MAX_VOLUMES 8 static FAT32_VOL gVols[FAT32_MAX_VOLUMES]; @@ -2408,6 +2413,7 @@ static bool gVolumeMounted[FAT32_MAX_VOLUMES]; static uint32_t gMountedCount; static bool gDiskScanned[FAT32_MAX_VOLUMES]; +// Returns free Volume Index. static int Fat32FindFreeVolumeIndex(void) { for (uint8_t i = 0; i < FAT32_MAX_VOLUMES; i++) { if (!gVolumeMounted[i] && !IoFilesystemPresent(i)) @@ -2416,6 +2422,7 @@ static int Fat32FindFreeVolumeIndex(void) { return -1; } +// Implements the try Mount Disk operation. static uint32_t Fat32TryMountDisk(uint8_t disk) { if (disk >= FAT32_MAX_VOLUMES) return 0; @@ -2513,6 +2520,7 @@ static uint32_t Fat32TryMountDisk(uint8_t disk) { return mountedHere; } +// Implements the disk Arrival operation. static void Fat32DiskArrival(uint8_t driveIndex, DEVICE_OBJECT* device, void* context) { (void)device; (void)context; @@ -2526,6 +2534,7 @@ static void Fat32DiskArrival(uint8_t driveIndex, DEVICE_OBJECT* device, void* co } } +// Implements the unmount Disk operation. static void Fat32UnmountDisk(uint8_t diskIndex, IO_DEVICE_CHANGE change) { uint32_t removed = 0; @@ -2580,6 +2589,7 @@ static void Fat32DiskChange(uint8_t driveIndex, } } +// Implements the driver Entry operation. KSTATUS DriverEntry(const HAL_API *hal) { DbgPrint("FAT32: Init\n"); if (!hal) return STATUS_INVALID_PARAMETER; diff --git a/code/drivers/fs/fat32/fat32.h b/code/drivers/fs/fat32/fat32.h index 804ccec..ccd039f 100644 --- a/code/drivers/fs/fat32/fat32.h +++ b/code/drivers/fs/fat32/fat32.h @@ -1,4 +1,5 @@ -// fat32.h - shared FAT32 driver internals. +// FAT32 driver internals shared by mount, directory, and file I/O code. + #pragma once #include diff --git a/code/drivers/fs/fat32/fat32_mount.c b/code/drivers/fs/fat32/fat32_mount.c index bffc562..cd598a2 100644 --- a/code/drivers/fs/fat32/fat32_mount.c +++ b/code/drivers/fs/fat32/fat32_mount.c @@ -1,6 +1,8 @@ -// fat32_mount.c - filesystem vtable/mount wiring. +// FAT32 mount logic. This file owns volume probing, BPB validation, and mount-table insertion. + #include "fat32.h" +// Initializes vtable. void Fat32InitVtable(IO_FILESYSTEM* fs, FAT32_VOL* vol) { memset(fs, 0, sizeof(*fs)); fs->Open = Fat32Open; diff --git a/code/drivers/input/ps2/ps2.c b/code/drivers/input/ps2/ps2.c index 24f532f..e133246 100644 --- a/code/drivers/input/ps2/ps2.c +++ b/code/drivers/input/ps2/ps2.c @@ -1,4 +1,5 @@ -// ps2.c - PS/2 keyboard/mouse event decoding and kernel input binding. +// PS/2 input driver package entry point. This file registers keyboard and mouse devices. + #include "ps2.h" static KDPC gMouseDpc; @@ -9,6 +10,7 @@ static PS2_MOUSE_PACKET gMouseDpcQueue[MOUSE_DPC_QUEUE_SIZE]; static volatile int gMouseDpcHead; static volatile int gMouseDpcTail; +// Implements the ps2 Set1 To Key operation. static INPUT_KEY Ps2Set1ToKey(uint8_t make, bool extended) { if (extended) { switch (make) { @@ -119,6 +121,7 @@ static INPUT_KEY Ps2Set1ToKey(uint8_t make, bool extended) { } } +// Implements the ps2 Keyboard Isr operation. static void Ps2KeyboardIsr(void) { uint8_t sc = __inbyte(PS2_DATA); if (sc == SC1_EXT_PREFIX) { @@ -141,6 +144,7 @@ static void Ps2KeyboardIsr(void) { KeInputSubmitKey(&event); } +// Implements the ps2 Mouse Dpc Routine operation. static void Ps2MouseDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2) { (void)dpc; (void)context; @@ -161,6 +165,7 @@ static void Ps2MouseDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, } } +// Implements the ps2 Mouse Isr operation. static void Ps2MouseIsr(void) { uint8_t data = __inbyte(PS2_DATA); @@ -190,6 +195,7 @@ static void Ps2MouseIsr(void) { } } +// Implements the ps2 Controller Prepare operation. static void Ps2ControllerPrepare(void) { Ps2WriteCommand(0xADu); // disable keyboard port Ps2WriteCommand(0xA7u); // disable aux port @@ -208,6 +214,7 @@ static void Ps2ControllerPrepare(void) { Ps2FlushOutput(); } +// Implements the ps2 Controller Enable Interrupts operation. static void Ps2ControllerEnableInterrupts(void) { uint8_t commandByte = Ps2ReadCommandByte(); commandByte |= 0x01u; @@ -215,6 +222,7 @@ static void Ps2ControllerEnableInterrupts(void) { Ps2WriteCommandByte(commandByte); } +// Implements the ps2 Keyboard Initialize operation. static void Ps2KeyboardInitialize(void) { // Enable scanning. If the keyboard is absent, the timeout/ACK failure is // non-fatal; the IRQ path simply never produces events. @@ -222,6 +230,7 @@ static void Ps2KeyboardInitialize(void) { DbgPrint("ps2: keyboard enable did not ACK\n"); } +// Implements the ps2 Mouse Initialize operation. static void Ps2MouseInitialize(void) { if (!Ps2SendMouse(0xFFu)) { DbgPrint("ps2: mouse reset did not ACK\n"); @@ -237,6 +246,7 @@ static void Ps2MouseInitialize(void) { DbgPrint("ps2: mouse enable did not ACK\n"); } +// Implements the driver Entry operation. KSTATUS DriverEntry(const HAL_API* hal) { (void)hal; diff --git a/code/drivers/input/ps2/ps2.h b/code/drivers/input/ps2/ps2.h index ec52d41..bfcadec 100644 --- a/code/drivers/input/ps2/ps2.h +++ b/code/drivers/input/ps2/ps2.h @@ -1,4 +1,5 @@ -// ps2.h - shared i8042/PS/2 driver internals. +// PS/2 driver internals shared by the package entry point and i8042 controller code. + #pragma once #include diff --git a/code/drivers/input/ps2/ps2_i8042.c b/code/drivers/input/ps2/ps2_i8042.c index fb0ff0c..18af070 100644 --- a/code/drivers/input/ps2/ps2_i8042.c +++ b/code/drivers/input/ps2/ps2_i8042.c @@ -1,10 +1,13 @@ -// ps2_i8042.c - 8042 controller and device command helpers. +// i8042 controller driver. This file owns PS/2 controller commands, IRQ handling, and packet decoding. + #include "ps2.h" +// Implements the ps2 Pause operation. void Ps2Pause(void) { _mm_pause(); } +// Implements the ps2 Wait Input operation. void Ps2WaitInput(void) { int timeout = 100000; while ((__inbyte(PS2_STAT) & PS2_STAT_IN_FULL) && --timeout) { @@ -12,6 +15,7 @@ void Ps2WaitInput(void) { } } +// Implements the ps2 Wait Output operation. bool Ps2WaitOutput(void) { int timeout = 5000000; while (!(__inbyte(PS2_STAT) & PS2_STAT_OUT_FULL) && --timeout) { @@ -20,6 +24,7 @@ bool Ps2WaitOutput(void) { return timeout != 0; } +// Implements the ps2 Flush Output operation. void Ps2FlushOutput(void) { int timeout = 100000; while ((__inbyte(PS2_STAT) & PS2_STAT_OUT_FULL) && --timeout) { @@ -27,36 +32,43 @@ void Ps2FlushOutput(void) { } } +// Implements the ps2 Read Data operation. uint8_t Ps2ReadData(void) { if (!Ps2WaitOutput()) return 0xFFu; return __inbyte(PS2_DATA); } +// Implements the ps2 Write Command operation. void Ps2WriteCommand(uint8_t command) { Ps2WaitInput(); __outbyte(PS2_CMD, command); } +// Implements the ps2 Write Data operation. void Ps2WriteData(uint8_t data) { Ps2WaitInput(); __outbyte(PS2_DATA, data); } +// Implements the ps2 Read Command Byte operation. uint8_t Ps2ReadCommandByte(void) { Ps2WriteCommand(0x20u); return Ps2ReadData(); } +// Implements the ps2 Write Command Byte operation. void Ps2WriteCommandByte(uint8_t commandByte) { Ps2WriteCommand(0x60u); Ps2WriteData(commandByte); } +// Implements the ps2 Send Keyboard operation. bool Ps2SendKeyboard(uint8_t byte) { Ps2WriteData(byte); return Ps2ReadData() == 0xFAu; } +// Implements the ps2 Send Mouse operation. bool Ps2SendMouse(uint8_t byte) { Ps2WriteCommand(0xD4u); Ps2WriteData(byte); diff --git a/code/drivers/net/lwip/lwip_stack.c b/code/drivers/net/lwip/lwip_stack.c index 8830eb5..5490d0d 100644 --- a/code/drivers/net/lwip/lwip_stack.c +++ b/code/drivers/net/lwip/lwip_stack.c @@ -1,4 +1,4 @@ -// lwip_stack.c - lwIP network stack provider driver. +// lwIP stack provider glue. This file bridges the kernel network-device model into lwIP. #include #include @@ -130,6 +130,7 @@ static const NET_STACK_PROVIDER gLwipProvider = { LwipProviderResolveHostIpv4, }; +// Implements the err To Status operation. static KSTATUS LwipErrToStatus(err_t err) { switch (err) { case ERR_OK: return STATUS_SUCCESS; @@ -150,10 +151,12 @@ static KSTATUS LwipErrToStatus(err_t err) { } } +// Implements the ascii Is Digit operation. static int LwipAsciiIsDigit(char c) { return c >= '0' && c <= '9'; } +// Parses ipv4 Part. static int LwipParseIpv4Part(const char** cursor, uint8_t* out) { const char* p = *cursor; uint32_t value = 0; @@ -175,6 +178,7 @@ static int LwipParseIpv4Part(const char** cursor, uint8_t* out) { return 1; } +// Parses ipv4. static int LwipParseIpv4(const char* text, ip4_addr_t* out) { if (!text || !out) return 0; @@ -205,6 +209,7 @@ static KSTATUS LwipGetSettingIpv4(const char* section, const char* key, return STATUS_SUCCESS; } +// Copies section Name. static KSTATUS LwipCopySectionName(char* out, size_t outSize, const char* prefix, const char* name) { if (!out || !outSize || !prefix || !name) return STATUS_INVALID_PARAMETER; @@ -219,6 +224,7 @@ static KSTATUS LwipCopySectionName(char* out, size_t outSize, const char* prefix return STATUS_SUCCESS; } +// Loads config From Section. static KSTATUS LwipLoadConfigFromSection(const char* section, LWIP_NETIF_CONFIG* cfg) { if (!section || !cfg) return STATUS_INVALID_PARAMETER; @@ -262,6 +268,7 @@ static KSTATUS LwipLoadConfigFromSection(const char* section, LWIP_NETIF_CONFIG* return STATUS_INVALID_PARAMETER; } +// Loads netif Config. static KSTATUS LwipLoadNetifConfig(const NET_DEVICE* device, LWIP_NETIF_CONFIG* cfg) { if (!device || !cfg) return STATUS_INVALID_PARAMETER; @@ -291,17 +298,20 @@ static KSTATUS LwipLoadNetifConfig(const NET_DEVICE* device, LWIP_NETIF_CONFIG* return STATUS_SUCCESS; } +// Implements the socket Lock operation. static KSTATUS LwipSocketLock(LWIP_PROVIDER_SOCKET* s) { if (!s || !s->Lock) return STATUS_INVALID_PARAMETER; return KeWaitSemaphore(s->Lock); } +// Implements the socket Unlock operation. static void LwipSocketUnlock(LWIP_PROVIDER_SOCKET* s) { if (s && s->Lock) KeSignalSemaphore(s->Lock); } +// Implements the socket Callback operation. static void LwipSocketCallback(struct netconn* conn, enum netconn_evt evt, u16_t len) { (void)len; if (!conn) @@ -362,10 +372,12 @@ static KSTATUS LwipSocketAllocateWithConn(uint32_t domain, uint32_t type, uint32 return STATUS_SUCCESS; } +// Implements the socket Make Ip operation. static void LwipSocketMakeIp(const SYS_SOCKET_ADDRESS_IPV4_K* address, ip_addr_t* out) { IP_ADDR4(out, address->Address[0], address->Address[1], address->Address[2], address->Address[3]); } +// Implements the socket Fill Address operation. static void LwipSocketFillAddress(SYS_SOCKET_ADDRESS_IPV4_K* out, const ip_addr_t* ip, u16_t port) { if (!out) return; @@ -378,6 +390,7 @@ static void LwipSocketFillAddress(SYS_SOCKET_ADDRESS_IPV4_K* out, const ip_addr_ out->Address[3] = (uint8_t)ip4_addr4(ip_2_ip4(ip)); } +// Implements the low Level Output operation. static err_t LwipLowLevelOutput(struct netif* netif, struct pbuf* p) { LWIP_BINDING* b = (LWIP_BINDING*)netif->state; if (!b || !b->Device || !p || p->tot_len < NET_ETHERNET_HEADER_LENGTH) @@ -405,6 +418,7 @@ static err_t LwipLowLevelOutput(struct netif* netif, struct pbuf* p) { return KSUCCESS(st) ? ERR_OK : ERR_IF; } +// Implements the netif Init operation. static err_t LwipNetifInit(struct netif* netif) { LWIP_BINDING* b = (LWIP_BINDING*)netif->state; if (!b || !b->Device) @@ -422,6 +436,7 @@ static err_t LwipNetifInit(struct netif* netif) { return ERR_OK; } +// Attaches callback. static void LwipAttachCallback(void* arg) { LWIP_ATTACH_CTX* ctx = (LWIP_ATTACH_CTX*)arg; LWIP_BINDING* b = ctx->Binding; @@ -490,11 +505,13 @@ static void LwipAttachCallback(void* arg) { KeSignalSemaphore(ctx->Done); } +// Initializes done. static void LwipInitDone(void* arg) { SEMAPHORE* sem = (SEMAPHORE*)arg; KeSignalSemaphore(sem); } +// Implements the stack Initialize operation. static KSTATUS LwipStackInitialize(const HAL_API* hal) { if (gLwipInitialized) return STATUS_SUCCESS; @@ -519,6 +536,7 @@ static KSTATUS LwipStackInitialize(const HAL_API* hal) { return STATUS_SUCCESS; } +// Implements the provider Attach Device operation. static KSTATUS LwipProviderAttachDevice(NET_DEVICE* device) { if (!gLwipInitialized) return STATUS_NOT_SUPPORTED; @@ -576,6 +594,7 @@ static KSTATUS LwipProviderAttachDevice(NET_DEVICE* device) { return STATUS_SUCCESS; } +// Implements the provider Receive Frame operation. static KSTATUS LwipProviderReceiveFrame(NET_DEVICE* device, const void* frame, size_t length) { if (!gLwipInitialized) return STATUS_NOT_SUPPORTED; @@ -609,6 +628,7 @@ static KSTATUS LwipProviderReceiveFrame(NET_DEVICE* device, const void* frame, s return STATUS_SUCCESS; } +// Implements the provider Socket Create operation. static KSTATUS LwipProviderSocketCreate(uint32_t domain, uint32_t type, uint32_t protocol, void** outSocket) { if (!outSocket) return STATUS_INVALID_PARAMETER; @@ -655,6 +675,7 @@ static KSTATUS LwipProviderSocketCreate(uint32_t domain, uint32_t type, uint32_t return STATUS_SUCCESS; } +// Implements the provider Socket Close operation. static void LwipProviderSocketClose(void* socket) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s) @@ -681,6 +702,7 @@ static void LwipProviderSocketClose(void* socket) { MmFreePool(s); } +// Implements the provider Bind operation. static KSTATUS LwipProviderBind(void* socket, const SYS_SOCKET_ADDRESS_IPV4_K* address, size_t addressSize) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s || !address) @@ -711,6 +733,7 @@ static KSTATUS LwipProviderBind(void* socket, const SYS_SOCKET_ADDRESS_IPV4_K* a return LwipErrToStatus(err); } +// Implements the provider Listen operation. static KSTATUS LwipProviderListen(void* socket, uint32_t backlog) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s) @@ -739,6 +762,7 @@ static KSTATUS LwipProviderListen(void* socket, uint32_t backlog) { return LwipErrToStatus(err); } +// Implements the provider Accept operation. static KSTATUS LwipProviderAccept(void* socket, void** acceptedOut, SYS_SOCKET_ADDRESS_IPV4_K* remoteOut) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s || !acceptedOut) @@ -795,6 +819,7 @@ static KSTATUS LwipProviderAccept(void* socket, void** acceptedOut, SYS_SOCKET_A return STATUS_SUCCESS; } +// Implements the provider Connect operation. static KSTATUS LwipProviderConnect(void* socket, const SYS_SOCKET_ADDRESS_IPV4_K* address, size_t addressSize) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s || !address) @@ -830,6 +855,7 @@ static KSTATUS LwipProviderConnect(void* socket, const SYS_SOCKET_ADDRESS_IPV4_K return LwipErrToStatus(err); } +// Implements the provider Send operation. static KSTATUS LwipProviderSend(void* socket, const void* buffer, size_t length, uint32_t flags, size_t* sentOut) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (sentOut) @@ -913,6 +939,7 @@ static KSTATUS LwipReceiveFromBuffered(LWIP_PROVIDER_SOCKET* s, uint8_t* out, return STATUS_SUCCESS; } +// Implements the provider Receive operation. static KSTATUS LwipProviderReceive(void* socket, void* buffer, size_t length, uint32_t flags, size_t* receivedOut) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (receivedOut) @@ -1103,6 +1130,7 @@ static KSTATUS LwipProviderReceiveFrom(void* socket, void* buffer, size_t length return LwipErrToStatus(err); } +// Implements the provider Set Option operation. static KSTATUS LwipProviderSetOption(void* socket, uint32_t option, const void* value, size_t valueSize) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s || !value) @@ -1141,6 +1169,7 @@ static KSTATUS LwipProviderSetOption(void* socket, uint32_t option, const void* return STATUS_SUCCESS; } +// Implements the provider Get Option operation. static KSTATUS LwipProviderGetOption(void* socket, uint32_t option, void* value, size_t valueSize, size_t* actualSizeOut) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (actualSizeOut) @@ -1177,6 +1206,7 @@ static KSTATUS LwipProviderGetOption(void* socket, uint32_t option, void* value, return STATUS_SUCCESS; } +// Implements the provider Poll operation. static KSTATUS LwipProviderPoll(void* socket, uint32_t events, uint32_t* returnedEventsOut) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s || !returnedEventsOut) @@ -1215,6 +1245,7 @@ static KSTATUS LwipProviderPoll(void* socket, uint32_t events, uint32_t* returne return STATUS_SUCCESS; } +// Implements the provider Shutdown operation. static KSTATUS LwipProviderShutdown(void* socket, uint32_t how) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s) @@ -1240,6 +1271,7 @@ static KSTATUS LwipProviderShutdown(void* socket, uint32_t how) { return LwipErrToStatus(err); } +// Implements the provider Resolve Host Ipv4 operation. static KSTATUS LwipProviderResolveHostIpv4(const char* name, SYS_SOCKET_ADDRESS_IPV4_K* addressOut) { if (!name || !addressOut) return STATUS_INVALID_PARAMETER; @@ -1263,6 +1295,7 @@ static KSTATUS LwipProviderResolveHostIpv4(const char* name, SYS_SOCKET_ADDRESS_ return STATUS_SUCCESS; } +// Implements the driver Entry operation. KSTATUS DriverEntry(const HAL_API* hal) { DbgPrint("lwIP: driver loading...\n"); diff --git a/code/drivers/net/lwip/lwip_sys_arch.c b/code/drivers/net/lwip/lwip_sys_arch.c index 7c6aa8e..8ceb47a 100644 --- a/code/drivers/net/lwip/lwip_sys_arch.c +++ b/code/drivers/net/lwip/lwip_sys_arch.c @@ -1,4 +1,5 @@ -// lwip_sys_arch.c - lwIP OS abstraction layer for the kernel. +// lwIP OS-abstraction layer. This file maps lwIP synchronization and timing primitives onto kernel services. + #include #include #include @@ -42,18 +43,20 @@ struct sys_mbox { static uint64_t (*gLwipQueryTicksUs)(void) = 0; -static uint32_t gRandState = 0x4b4e4554u; /* 'KNET' */ +static uint32_t gRandState = 0x4b4e4554u; // 'KNET' +// Implements the port Set Timer Query operation. void LwipPortSetTimerQuery(uint64_t (*query_ticks_us)(void)) { gLwipQueryTicksUs = query_ticks_us; } unsigned int lwip_port_rand(void) { - /* Tiny deterministic LCG. Good enough for ephemeral port randomisation. */ + // Tiny deterministic LCG. Good enough for ephemeral port randomisation. gRandState = gRandState * 1664525u + 1013904223u; return gRandState; } +// Implements the sys init operation. void sys_init(void) { } @@ -67,22 +70,20 @@ u32_t sys_jiffies(void) { return sys_now(); } -/* - * lwIP's core/sys.c provides sys_msleep() when it is not a macro. Do not - * define it here as well, or MSVC links both sys.obj and lwip_sys_arch.obj - * with a duplicate sys_msleep symbol. - */ +// lwIP's core/sys.c provides sys_msleep() when it is not a macro. Do not +// define it here as well, or MSVC links both sys.obj and lwip_sys_arch.obj +// with a duplicate sys_msleep symbol. -/* - * First bring-up errno storage for lwIP's socket/netdb compatibility layer. - * This is global, not per-thread; the kernel socket-object wrapper should - * eventually translate lwIP errors to KSTATUS instead of exposing this. - */ -// fuckass microsoft +// First bring-up errno storage for lwIP's socket/netdb compatibility layer. +// This is global, not per-thread; the kernel socket-object wrapper should +// eventually translate lwIP errors to KSTATUS instead of exposing this. + +// fuckass microsoft. #ifdef errno #undef errno #endif int errno; +// Implements the errno operation. int* __cdecl _errno(void) { return &errno; } err_t sys_sem_new(sys_sem_t* sem, u8_t count) { @@ -105,6 +106,7 @@ err_t sys_sem_new(sys_sem_t* sem, u8_t count) { return ERR_OK; } +// Implements the sys sem signal operation. void sys_sem_signal(sys_sem_t* sem) { if (sem && *sem && (*sem)->Sem) KeSignalSemaphore((*sem)->Sem); @@ -132,6 +134,7 @@ u32_t sys_arch_sem_wait(sys_sem_t* sem, u32_t timeout) { } } +// Implements the sys sem free operation. void sys_sem_free(sys_sem_t* sem) { if (!sem || !*sem) return; @@ -161,16 +164,19 @@ err_t sys_mutex_new(sys_mutex_t* mutex) { return ERR_OK; } +// Implements the sys mutex lock operation. void sys_mutex_lock(sys_mutex_t* mutex) { if (mutex && *mutex && (*mutex)->Sem) (void)KeWaitSemaphore((*mutex)->Sem); } +// Implements the sys mutex unlock operation. void sys_mutex_unlock(sys_mutex_t* mutex) { if (mutex && *mutex && (*mutex)->Sem) KeSignalSemaphore((*mutex)->Sem); } +// Implements the sys mutex free operation. void sys_mutex_free(sys_mutex_t* mutex) { if (!mutex || !*mutex) return; @@ -180,6 +186,7 @@ void sys_mutex_free(sys_mutex_t* mutex) { *mutex = 0; } +// Implements the mbox Try Post operation. static err_t LwipMboxTryPost(sys_mbox_t* mbox, void* msg) { if (!mbox || !*mbox || !(*mbox)->Valid) return ERR_ARG; @@ -232,8 +239,9 @@ err_t sys_mbox_new(sys_mbox_t* mbox, int size) { return ERR_OK; } +// Implements the sys mbox post operation. void sys_mbox_post(sys_mbox_t* mbox, void* msg) { - /* lwIP promises this is not called from ISR context. */ + // lwIP promises this is not called from ISR context. while (LwipMboxTryPost(mbox, msg) != ERR_OK) KeYield(); } @@ -246,6 +254,7 @@ err_t sys_mbox_trypost_fromisr(sys_mbox_t* mbox, void* msg) { return LwipMboxTryPost(mbox, msg); } +// Implements the mbox Pop After Item operation. static u32_t LwipMboxPopAfterItem(sys_mbox_t* mbox, void** msg, u32_t waited) { struct sys_mbox* m = *mbox; uintptr_t flags = KeAcquireSpinlock(&m->Lock); @@ -299,6 +308,7 @@ u32_t sys_arch_mbox_tryfetch(sys_mbox_t* mbox, void** msg) { return LwipMboxPopAfterItem(mbox, msg, 0); } +// Implements the sys mbox free operation. void sys_mbox_free(sys_mbox_t* mbox) { if (!mbox || !*mbox) return; @@ -327,18 +337,17 @@ sys_thread_t sys_thread_new(const char* name, lwip_thread_fn thread, void* arg, else if (prio <= 0) kp = PriorityLow; - /* - * lwIP thread entries already use the same ABI as kernel worker threads: - * - * void entry(void* arg) - * - * Do not bounce through a heap-allocated thunk. The first scaffold used a - * tiny { function, argument } heap block and a wrapper, but an early boot - * crash showed the wrapper sometimes loaded a bogus function pointer and - * jumped into lwIP's .rdata strings. Passing the lwIP entry directly keeps - * the initial thread stack simple: KeKernelThreadEntry calls exactly the - * function pointer that lwIP supplied, with exactly the argument it supplied. - */ + // lwIP thread entries already use the same ABI as kernel worker threads: + + // void entry(void* arg) + + // Do not bounce through a heap-allocated thunk. The first scaffold used a + // tiny { function, argument } heap block and a wrapper, but an early boot + // crash showed the wrapper sometimes loaded a bogus function pointer and + // jumped into lwIP's .rdata strings. Passing the lwIP entry directly keeps + // the initial thread stack simple: KeKernelThreadEntry calls exactly the + // function pointer that lwIP supplied, with exactly the argument it supplied. + THREAD* t = 0; KSTATUS st = KeCreateKernelThread((uintptr_t)thread, (uintptr_t)arg, @@ -356,6 +365,7 @@ sys_prot_t sys_arch_protect(void) { return (sys_prot_t)flags; } +// Implements the sys arch unprotect operation. void sys_arch_unprotect(sys_prot_t pval) { if (((uintptr_t)pval) & 0x200u) _enable(); diff --git a/code/drivers/net/rtl8139/rtl8139.c b/code/drivers/net/rtl8139/rtl8139.c index f4008ce..d9c07e3 100644 --- a/code/drivers/net/rtl8139/rtl8139.c +++ b/code/drivers/net/rtl8139/rtl8139.c @@ -1,4 +1,5 @@ -// rtl8139.c - packet I/O, interrupt, and DriverEntry path. +// Realtek RTL8139 network driver. This file owns PCI attachment, MMIO setup, RX/TX rings, and net-device registration. + #include "rtl8139.h" const HAL_API* gHal; @@ -16,40 +17,47 @@ static const IO_DRIVER_ID_TABLE gRtl8139IdTable = { sizeof(gRtl8139Ids) / sizeof(gRtl8139Ids[0]), }; +// Implements the memory Barrier operation. static __forceinline void Rtl8139MemoryBarrier(void) { _ReadWriteBarrier(); _mm_mfence(); _ReadWriteBarrier(); } +// Implements the read8 operation. static uint8_t Rtl8139Read8(RTL8139_DEVICE* r, uint32_t reg) { if (r->UseMmio) return *(volatile uint8_t*)(r->Mmio + reg); return __inbyte((unsigned short)(r->IoBase + reg)); } +// Implements the read16 operation. static uint16_t Rtl8139Read16(RTL8139_DEVICE* r, uint32_t reg) { if (r->UseMmio) return *(volatile uint16_t*)(r->Mmio + reg); return __inword((unsigned short)(r->IoBase + reg)); } +// Implements the read32 operation. static uint32_t Rtl8139Read32(RTL8139_DEVICE* r, uint32_t reg) { if (r->UseMmio) return *(volatile uint32_t*)(r->Mmio + reg); return __indword((unsigned short)(r->IoBase + reg)); } +// Implements the write8 operation. static void Rtl8139Write8(RTL8139_DEVICE* r, uint32_t reg, uint8_t value) { if (r->UseMmio) *(volatile uint8_t*)(r->Mmio + reg) = value; else __outbyte((unsigned short)(r->IoBase + reg), value); } +// Implements the write16 operation. static void Rtl8139Write16(RTL8139_DEVICE* r, uint32_t reg, uint16_t value) { if (r->UseMmio) *(volatile uint16_t*)(r->Mmio + reg) = value; else __outword((unsigned short)(r->IoBase + reg), value); } +// Implements the write32 operation. static void Rtl8139Write32(RTL8139_DEVICE* r, uint32_t reg, uint32_t value) { if (r->UseMmio) *(volatile uint32_t*)(r->Mmio + reg) = value; else __outdword((unsigned short)(r->IoBase + reg), value); @@ -59,6 +67,7 @@ static void Rtl8139Write32(RTL8139_DEVICE* r, uint32_t reg, uint32_t value) { +// Implements the reset operation. static KSTATUS Rtl8139Reset(RTL8139_DEVICE* r) { Rtl8139Write8(r, RTL8139_REG_CMD, RTL8139_CMD_RST); for (uint32_t i = 0; i < 1000; i++) { @@ -70,12 +79,14 @@ static KSTATUS Rtl8139Reset(RTL8139_DEVICE* r) { return STATUS_TIMEOUT; } +// Returns mac. static void Rtl8139ReadMac(RTL8139_DEVICE* r) { for (uint32_t i = 0; i < 6; i++) r->NetDevice.HardwareAddress[i] = Rtl8139Read8(r, RTL8139_REG_IDR0 + i); r->NetDevice.HardwareAddressLength = 6; } +// Creates dma. static KSTATUS Rtl8139AllocateDma(RTL8139_DEVICE* r) { r->RxPhys = MmAllocateContiguous(RTL8139_RX_PAGES); r->TxPhys = MmAllocateContiguous(RTL8139_TX_PAGES); @@ -101,6 +112,7 @@ static KSTATUS Rtl8139AllocateDma(RTL8139_DEVICE* r) { return STATUS_SUCCESS; } +// Implements the rx Read16 operation. static uint16_t Rtl8139RxRead16(RTL8139_DEVICE* r, uint32_t offset) { offset %= RTL8139_RX_RING_SIZE; uint16_t lo = r->RxBuffer[offset]; @@ -108,6 +120,7 @@ static uint16_t Rtl8139RxRead16(RTL8139_DEVICE* r, uint32_t offset) { return (uint16_t)(lo | (hi << 8)); } +// Implements the rx Copy operation. static void Rtl8139RxCopy(RTL8139_DEVICE* r, uint32_t offset, void* dst, uint32_t length) { uint8_t* out = (uint8_t*)dst; offset %= RTL8139_RX_RING_SIZE; @@ -120,6 +133,7 @@ static void Rtl8139RxCopy(RTL8139_DEVICE* r, uint32_t offset, void* dst, uint32_ memcpy(out + first, r->RxBuffer, length - first); } +// Implements the program Hardware operation. static void Rtl8139ProgramHardware(RTL8139_DEVICE* r) { // Wake the device and clear stale interrupts before installing buffers. Rtl8139Write8(r, RTL8139_REG_CONFIG1, 0x00); @@ -148,6 +162,7 @@ static void Rtl8139ProgramHardware(RTL8139_DEVICE* r) { Rtl8139Write16(r, RTL8139_REG_IMR, RTL8139_INTR_ENABLES); } +// Handles rx. static void Rtl8139HandleRx(RTL8139_DEVICE* r) { for (uint32_t budget = 0; budget < 64; budget++) { uint8_t cmd = Rtl8139Read8(r, RTL8139_REG_CMD); @@ -192,6 +207,7 @@ static void Rtl8139HandleRx(RTL8139_DEVICE* r) { } } +// Implements the dpc Routine operation. static void Rtl8139DpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2) { (void)dpc; (void)systemArgument1; @@ -212,6 +228,7 @@ static void Rtl8139DpcRoutine(KDPC* dpc, void* context, void* systemArgument1, v DbgPrint("RTL8139: interrupt error bits=0x%04x\n", status); } +// Registers device. static KSTATUS Rtl8139RegisterDevice(RTL8139_DEVICE* r) { if (!r) return STATUS_INVALID_PARAMETER; @@ -233,6 +250,7 @@ static KSTATUS Rtl8139RegisterDevice(RTL8139_DEVICE* r) { return STATUS_SUCCESS; } +// Implements the unregister Device operation. static void Rtl8139UnregisterDevice(RTL8139_DEVICE* r) { if (!r) return; @@ -248,6 +266,7 @@ static void Rtl8139UnregisterDevice(RTL8139_DEVICE* r) { KeReleaseSpinlock(&gRtl8139RegistryLock, flags); } +// Implements the isr operation. static void Rtl8139Isr(void) { RTL8139_DEVICE* snapshot[RTL8139_MAX_DEVICES]; uint32_t count = 0; @@ -276,6 +295,7 @@ static void Rtl8139Isr(void) { } } +// Implements the send Frame operation. static KSTATUS Rtl8139SendFrame(NET_DEVICE* device, const void* frame, size_t length) { if (!device || !frame) return STATUS_INVALID_PARAMETER; @@ -312,6 +332,7 @@ static KSTATUS Rtl8139SendFrame(NET_DEVICE* device, const void* frame, size_t le return STATUS_SUCCESS; } +// Implements the select Register Bar operation. static KSTATUS Rtl8139SelectRegisterBar(RTL8139_DEVICE* r) { if (!r || !r->Pdo) return STATUS_INVALID_PARAMETER; @@ -377,6 +398,7 @@ static KSTATUS Rtl8139SelectRegisterBar(RTL8139_DEVICE* r) { return STATUS_NOT_FOUND; } +// Starts device. static KSTATUS Rtl8139StartDevice(RTL8139_DEVICE* r) { if (!r || r->Magic != RTL8139_DEVICE_MAGIC || !r->Pdo || !r->Fdo) return STATUS_INVALID_PARAMETER; @@ -462,6 +484,7 @@ static KSTATUS Rtl8139StartDevice(RTL8139_DEVICE* r) { return STATUS_SUCCESS; } +// Dispatches pnp. KSTATUS Rtl8139DispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp || !device->DeviceExtension) return STATUS_INVALID_PARAMETER; @@ -504,6 +527,7 @@ KSTATUS Rtl8139DispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } +// Implements the add Device operation. KSTATUS Rtl8139AddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return STATUS_INVALID_PARAMETER; @@ -532,6 +556,7 @@ KSTATUS Rtl8139AddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObj return STATUS_SUCCESS; } +// Implements the driver Entry operation. KSTATUS DriverEntry(const HAL_API* hal) { if (!hal) return STATUS_INVALID_PARAMETER; diff --git a/code/drivers/net/rtl8139/rtl8139.h b/code/drivers/net/rtl8139/rtl8139.h index 5645c28..fb0d102 100644 --- a/code/drivers/net/rtl8139/rtl8139.h +++ b/code/drivers/net/rtl8139/rtl8139.h @@ -1,4 +1,5 @@ -// rtl8139.h - shared rtl8139 driver internals. +// Realtek RTL8139 driver internals shared by the PCI and packet paths. + #pragma once #include diff --git a/code/drivers/net/rtl8139/rtl8139_pci.c b/code/drivers/net/rtl8139/rtl8139_pci.c index 5f408fd..494d2bd 100644 --- a/code/drivers/net/rtl8139/rtl8139_pci.c +++ b/code/drivers/net/rtl8139/rtl8139_pci.c @@ -1,2 +1,2 @@ -// rtl8139_pci.c intentionally empty. -// PCI enumeration, BAR decoding, mapping, and command-register policy now live in pci.sys. +// Driver support for rtl8139 pci. + diff --git a/code/drivers/net/rtl816x/rtl816x.c b/code/drivers/net/rtl816x/rtl816x.c index 6dc51f3..4ff78a3 100644 --- a/code/drivers/net/rtl816x/rtl816x.c +++ b/code/drivers/net/rtl816x/rtl816x.c @@ -1,4 +1,5 @@ -// rtl816x.c - rtl8168/rtl8169 packet I/O, interrupt, and PCI function-driver path. +// Realtek RTL816x network driver. This file owns PCI attachment, descriptor rings, and net-device registration. + #include "rtl816x.h" const HAL_API* gHal; @@ -17,45 +18,53 @@ static const IO_DRIVER_ID_TABLE gRtl816xIdTable = { sizeof(gRtl816xIds) / sizeof(gRtl816xIds[0]), }; +// Implements the rtl Memory Barrier operation. static __forceinline void RtlMemoryBarrier(void) { _ReadWriteBarrier(); _mm_mfence(); _ReadWriteBarrier(); } +// Implements the rtl Read8 operation. static uint8_t RtlRead8(RTL816X_DEVICE* r, uint32_t reg) { if (r->UseMmio) return *(volatile uint8_t*)(r->Mmio + reg); return __inbyte((unsigned short)(r->IoBase + reg)); } +// Implements the rtl Read16 operation. static uint16_t RtlRead16(RTL816X_DEVICE* r, uint32_t reg) { if (r->UseMmio) return *(volatile uint16_t*)(r->Mmio + reg); return __inword((unsigned short)(r->IoBase + reg)); } +// Implements the rtl Read32 operation. static uint32_t RtlRead32(RTL816X_DEVICE* r, uint32_t reg) { if (r->UseMmio) return *(volatile uint32_t*)(r->Mmio + reg); return __indword((unsigned short)(r->IoBase + reg)); } +// Implements the rtl Write8 operation. static void RtlWrite8(RTL816X_DEVICE* r, uint32_t reg, uint8_t value) { if (r->UseMmio) *(volatile uint8_t*)(r->Mmio + reg) = value; else __outbyte((unsigned short)(r->IoBase + reg), value); } +// Implements the rtl Write16 operation. static void RtlWrite16(RTL816X_DEVICE* r, uint32_t reg, uint16_t value) { if (r->UseMmio) *(volatile uint16_t*)(r->Mmio + reg) = value; else __outword((unsigned short)(r->IoBase + reg), value); } +// Implements the rtl Write32 operation. static void RtlWrite32(RTL816X_DEVICE* r, uint32_t reg, uint32_t value) { if (r->UseMmio) *(volatile uint32_t*)(r->Mmio + reg) = value; else __outdword((unsigned short)(r->IoBase + reg), value); } +// Implements the rtl Reset operation. static KSTATUS RtlReset(RTL816X_DEVICE* r) { RtlWrite8(r, RTL_REG_CHIP_CMD, RTL_CMD_RESET); for (uint32_t i = 0; i < 1000; i++) { @@ -67,12 +76,14 @@ static KSTATUS RtlReset(RTL816X_DEVICE* r) { return STATUS_TIMEOUT; } +// Implements the rtl Read Mac operation. static void RtlReadMac(RTL816X_DEVICE* r) { for (uint32_t i = 0; i < 6; i++) r->NetDevice.HardwareAddress[i] = RtlRead8(r, RTL_REG_MAC0 + i); r->NetDevice.HardwareAddressLength = 6; } +// Implements the rtl Allocate Dma operation. static KSTATUS RtlAllocateDma(RTL816X_DEVICE* r) { r->RxRingPhys = MmAllocateContiguous(RTL_RING_PAGES); r->TxRingPhys = MmAllocateContiguous(RTL_RING_PAGES); @@ -100,6 +111,7 @@ static KSTATUS RtlAllocateDma(RTL816X_DEVICE* r) { return STATUS_SUCCESS; } +// Implements the rtl Init Descriptors operation. static void RtlInitDescriptors(RTL816X_DEVICE* r) { for (uint32_t i = 0; i < RTL_RX_COUNT; i++) { PHYSICAL_ADDRESS p = r->RxBuffersPhys + (PHYSICAL_ADDRESS)i * RTL_BUF_SIZE; @@ -122,6 +134,7 @@ static void RtlInitDescriptors(RTL816X_DEVICE* r) { RtlMemoryBarrier(); } +// Implements the rtl Program Hardware operation. static void RtlProgramHardware(RTL816X_DEVICE* r) { RtlWrite8(r, RTL_REG_CFG9346, 0xC0); @@ -151,6 +164,7 @@ static void RtlProgramHardware(RTL816X_DEVICE* r) { RtlWrite16(r, RTL_REG_INTR_MASK, RTL_INTR_ENABLES); } +// Implements the rtl Handle Rx operation. static void RtlHandleRx(RTL816X_DEVICE* r) { for (uint32_t budget = 0; budget < RTL_RX_COUNT; budget++) { RTL_DESC* d = &r->RxRing[r->RxIndex]; @@ -188,6 +202,7 @@ static void RtlHandleRx(RTL816X_DEVICE* r) { } } +// Implements the rtl Dpc Routine operation. static void RtlDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2) { (void)dpc; (void)systemArgument1; @@ -212,6 +227,7 @@ static void RtlDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* DbgPrint("RTL816X: interrupt status error bits=0x%04x\n", status); } +// Implements the rtl Register Device operation. static KSTATUS RtlRegisterDevice(RTL816X_DEVICE* r) { if (!r) return STATUS_INVALID_PARAMETER; @@ -233,6 +249,7 @@ static KSTATUS RtlRegisterDevice(RTL816X_DEVICE* r) { return STATUS_SUCCESS; } +// Implements the rtl Unregister Device operation. static void RtlUnregisterDevice(RTL816X_DEVICE* r) { if (!r) return; @@ -248,6 +265,7 @@ static void RtlUnregisterDevice(RTL816X_DEVICE* r) { KeReleaseSpinlock(&gRtl816xRegistryLock, flags); } +// Implements the rtl Isr operation. static void RtlIsr(void) { RTL816X_DEVICE* snapshot[RTL816X_MAX_DEVICES]; uint32_t count = 0; @@ -276,6 +294,7 @@ static void RtlIsr(void) { } } +// Implements the rtl Send Frame operation. static KSTATUS RtlSendFrame(NET_DEVICE* device, const void* frame, size_t length) { if (!device || !frame) return STATUS_INVALID_PARAMETER; @@ -315,6 +334,7 @@ static KSTATUS RtlSendFrame(NET_DEVICE* device, const void* frame, size_t length return STATUS_SUCCESS; } +// Implements the rtl Select Register Bar operation. static KSTATUS RtlSelectRegisterBar(RTL816X_DEVICE* r) { if (!r || !r->Pdo) return STATUS_INVALID_PARAMETER; @@ -380,6 +400,7 @@ static KSTATUS RtlSelectRegisterBar(RTL816X_DEVICE* r) { return STATUS_NOT_FOUND; } +// Implements the rtl Start Device operation. static KSTATUS RtlStartDevice(RTL816X_DEVICE* r) { if (!r || r->Magic != RTL816X_DEVICE_MAGIC || !r->Pdo || !r->Fdo) return STATUS_INVALID_PARAMETER; @@ -465,6 +486,7 @@ static KSTATUS RtlStartDevice(RTL816X_DEVICE* r) { return STATUS_SUCCESS; } +// Dispatches pnp. KSTATUS Rtl816xDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp || !device->DeviceExtension) return STATUS_INVALID_PARAMETER; @@ -507,6 +529,7 @@ KSTATUS Rtl816xDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } +// Implements the add Device operation. KSTATUS Rtl816xAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return STATUS_INVALID_PARAMETER; @@ -535,6 +558,7 @@ KSTATUS Rtl816xAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObj return STATUS_SUCCESS; } +// Implements the driver Entry operation. KSTATUS DriverEntry(const HAL_API* hal) { if (!hal) return STATUS_INVALID_PARAMETER; diff --git a/code/drivers/net/rtl816x/rtl816x.h b/code/drivers/net/rtl816x/rtl816x.h index 4e72d91..e89e60d 100644 --- a/code/drivers/net/rtl816x/rtl816x.h +++ b/code/drivers/net/rtl816x/rtl816x.h @@ -1,4 +1,5 @@ -// rtl816x.h - shared rtl8168/rtl8169 driver internals. +// Realtek RTL816x driver internals shared by the PCI and packet paths. + #pragma once #include diff --git a/code/drivers/storage/ahci/ahci.c b/code/drivers/storage/ahci/ahci.c index 73e3a06..b4d4b70 100644 --- a/code/drivers/storage/ahci/ahci.c +++ b/code/drivers/storage/ahci/ahci.c @@ -1,4 +1,5 @@ -// ahci.c - AHCI disk command path and DriverEntry. +// AHCI storage driver. This file owns controller attachment, drive discovery, command submission, and worker-driven IRP completion. + #include "ahci.h" const HAL_API *g_hal; @@ -17,21 +18,21 @@ static const IO_DRIVER_ID_TABLE g_ahciIdTable = { sizeof(g_ahciIds) / sizeof(g_ahciIds[0]), }; -// --------------------------------------------------------------------------- -// Helpers -// --------------------------------------------------------------------------- +// Helpers. static KSTATUS AhciStartController(AHCI_CONTROLLER* ctl); -// Accessors for port structure memory at known offsets from structVirt/Phys +// Accessors for port structure memory at known offsets from structVirt/Phys. static inline HBA_CMD_HEADER *cmd_list(AHCI_DRIVE *drv) { return (HBA_CMD_HEADER *)((uint8_t *)drv->structVirt + PORT_OFF_CMDLIST); } +// Implements the cmd list phys operation. static inline uint64_t cmd_list_phys(AHCI_DRIVE *drv) { return drv->structPhys + PORT_OFF_CMDLIST; } +// Implements the fis phys operation. static inline uint64_t fis_phys(AHCI_DRIVE *drv) { return drv->structPhys + PORT_OFF_FIS; } @@ -42,20 +43,17 @@ static inline HBA_CMD_TBL *cmd_tbl(AHCI_DRIVE *drv, int slot) { + (uint32_t)slot * PORT_CMDTBL_SIZE); } +// Implements the cmd tbl phys operation. static inline uint64_t cmd_tbl_phys(AHCI_DRIVE *drv, int slot) { return drv->structPhys + PORT_OFF_CMDTBLS + (uint64_t)slot * PORT_CMDTBL_SIZE; } -// --------------------------------------------------------------------------- -// Port engine start / stop (polling safe) -// --------------------------------------------------------------------------- +// Port engine start / stop (polling safe). -// --------------------------------------------------------------------------- -// Port memory initialisation -// --------------------------------------------------------------------------- +// Port memory initialisation. static KSTATUS port_init_memory(AHCI_DRIVE *drv) { uint64_t flags = PAGE_PRESENT | PAGE_WRITE | PAGE_NOCACHE; @@ -63,7 +61,7 @@ static KSTATUS port_init_memory(AHCI_DRIVE *drv) { drv->structPhys = MmAllocateContiguous(PORT_PAGES_STRUCT); if (!drv->structPhys) return STATUS_NO_MEMORY; drv->structVirt = g_hal->PhysToVirt(drv->structPhys); - // Force NOCACHE on DMA descriptor memory + // Force NOCACHE on DMA descriptor memory. MmSetPageProtect((uintptr_t)drv->structVirt, PORT_PAGES_STRUCT * 4096, flags); memset(drv->structVirt, 0, PORT_PAGES_STRUCT * 4096); @@ -72,7 +70,7 @@ static KSTATUS port_init_memory(AHCI_DRIVE *drv) { if (!drv->bouncePhys) return STATUS_NO_MEMORY; drv->bounceVirt = g_hal->PhysToVirt(drv->bouncePhys); // Bounce buffer: NOCACHE to ensure CPU writes reach physical memory - // before the HBA's DMA engine reads them + // before the HBA's DMA engine reads them. MmSetPageProtect((uintptr_t)drv->bounceVirt, BOUNCE_PAGES * 4096, flags); memset(drv->bounceVirt, 0, BOUNCE_BYTES); @@ -81,15 +79,15 @@ static KSTATUS port_init_memory(AHCI_DRIVE *drv) { port_stop(port); - // Set command list base + // Set command list base. port->clb = (uint32_t)(cmd_list_phys(drv) & 0xFFFFFFFF); port->clbu = (uint32_t)(cmd_list_phys(drv) >> 32); - // Set FIS base + // Set FIS base. port->fb = (uint32_t)(fis_phys(drv) & 0xFFFFFFFF); port->fbu = (uint32_t)(fis_phys(drv) >> 32); - // Initialise all 32 command headers, pointing each to its command table + // Initialise all 32 command headers, pointing each to its command table. HBA_CMD_HEADER *hdrs = cmd_list(drv); for (int i = 0; i < NUM_CMD_SLOTS; i++) { hdrs[i].prdtl = PORT_PRDT_COUNT; @@ -98,7 +96,7 @@ static KSTATUS port_init_memory(AHCI_DRIVE *drv) { hdrs[i].ctbau = (uint32_t)(tbl >> 32); } - // Clear any stale interrupts then start the port engine + // Clear any stale interrupts then start the port engine. port->serr = (uint32_t)-1; port->is = (uint32_t)-1; @@ -107,19 +105,17 @@ static KSTATUS port_init_memory(AHCI_DRIVE *drv) { return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- // Issue a command - polling fallback (used during early init / IDENTIFY only, // before the scheduler and interrupt handler are live). // Returns STATUS_SUCCESS, STATUS_DEVICE_ERROR, or STATUS_TIMEOUT. -// --------------------------------------------------------------------------- static KSTATUS port_issue_cmd_poll(AHCI_DRIVE *drv) { HBA_PORT *port = drv->port; - // Clear pending interrupts before issuing + // Clear pending interrupts before issuing. port->is = (uint32_t)-1; - // Wait for port to be idle (not BSY or DRQ) + // Wait for port to be idle (not BSY or DRQ). int spin = 0; while ((port->tfd & (ATA_SR_BUSY | ATA_SR_DRQ)) && spin < POLL_TIMEOUT) spin++; @@ -128,10 +124,10 @@ static KSTATUS port_issue_cmd_poll(AHCI_DRIVE *drv) { return STATUS_TIMEOUT; } - // Issue slot 0 + // Issue slot 0. port->ci = (1u << 0); - // Poll until slot 0 clears + // Poll until slot 0 clears. while (true) { if (!(port->ci & (1u << 0))) break; if (port->is & (PORT_IS_TFES | PORT_IS_HBFS | PORT_IS_HBDS | PORT_IS_IFS)) { @@ -152,10 +148,8 @@ static KSTATUS port_issue_cmd_poll(AHCI_DRIVE *drv) { return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- // Interrupt bottom half. The ISR owns hardware acknowledgement and status // capture; this DPC wakes the worker thread after the hard IRQ has unwound. -// --------------------------------------------------------------------------- static void AhciCompletionDpc(KDPC *dpc, void *context, void *systemArgument1, void *systemArgument2) { @@ -168,11 +162,9 @@ static void AhciCompletionDpc(KDPC *dpc, void *context, KeSignalEvent(drv->completionEvent); } -// --------------------------------------------------------------------------- // ISR - called from KeIrqDispatch on the AHCI PCI IRQ line. // Walks all registered drives, checks if their port raised an interrupt, // captures IS, clears it, and queues the per-drive completion DPC. -// --------------------------------------------------------------------------- static void AhciIsr(void) { for (int c = 0; c < g_controllerCount; c++) { @@ -206,11 +198,9 @@ static void AhciIsr(void) { } } -// --------------------------------------------------------------------------- // Issue a command - interrupt-driven (runtime path). // Caller has already built slot 0 via build_rw_cmd / port_identify. // Blocks the current thread until the ISR signals completionEvent. -// --------------------------------------------------------------------------- static KSTATUS port_issue_cmd(AHCI_DRIVE *drv) { HBA_PORT *port = drv->port; @@ -220,7 +210,7 @@ static KSTATUS port_issue_cmd(AHCI_DRIVE *drv) { port->is = (uint32_t)-1; drv->lastIs = 0; - // Wait for port idle + // Wait for port idle. int spin = 0; while ((port->tfd & (ATA_SR_BUSY | ATA_SR_DRQ)) && spin < POLL_TIMEOUT) spin++; @@ -245,9 +235,7 @@ static KSTATUS port_issue_cmd(AHCI_DRIVE *drv) { return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// Build a standard DMA read or write command in slot 0 -// --------------------------------------------------------------------------- +// Build a standard DMA read or write command in slot 0. static void build_rw_cmd(AHCI_DRIVE *drv, uint64_t lba, uint32_t sectors, uint64_t bufPhys, bool write) { @@ -256,7 +244,7 @@ static void build_rw_cmd(AHCI_DRIVE *drv, uint64_t lba, uint32_t sectors, memset(tbl, 0, PORT_CMDTBL_SIZE); - // How many PRDT entries we need (each covers up to 8K = 16 sectors) + // How many PRDT entries we need (each covers up to 8K = 16 sectors). uint32_t prdtl = (sectors + 15) / 16; if (prdtl > PORT_PRDT_COUNT) prdtl = PORT_PRDT_COUNT; // capped (see caller) @@ -265,7 +253,7 @@ static void build_rw_cmd(AHCI_DRIVE *drv, uint64_t lba, uint32_t sectors, hdr->prdtl = (uint16_t)prdtl; hdr->prdbc = 0; - // Fill PRDT entries + // Fill PRDT entries. uint32_t remaining = sectors; uint64_t buf = bufPhys; for (uint32_t i = 0; i < prdtl; i++) { @@ -281,7 +269,7 @@ static void build_rw_cmd(AHCI_DRIVE *drv, uint64_t lba, uint32_t sectors, remaining -= sects; } - // Build H2D FIS + // Build H2D FIS. FIS_REG_H2D *fis = (FIS_REG_H2D *)tbl->cfis; memset(fis, 0, sizeof(*fis)); fis->fis_type = FIS_TYPE_REG_H2D; @@ -300,12 +288,10 @@ static void build_rw_cmd(AHCI_DRIVE *drv, uint64_t lba, uint32_t sectors, fis->counth = (uint8_t)(sectors >> 8); } -// --------------------------------------------------------------------------- -// IDENTIFY command - fills a 512-byte buffer and returns it -// --------------------------------------------------------------------------- +// IDENTIFY command - fills a 512-byte buffer and returns it. static KSTATUS port_identify(AHCI_DRIVE *drv) { - // Reuse bounce buffer for IDENTIFY data (512 bytes) + // Reuse bounce buffer for IDENTIFY data (512 bytes). memset(drv->bounceVirt, 0, 512); HBA_CMD_HEADER *hdr = cmd_list(drv); @@ -334,17 +320,17 @@ static KSTATUS port_identify(AHCI_DRIVE *drv) { KSTATUS st = port_issue_cmd_poll(drv); if (!KSUCCESS(st)) return st; - // Parse sector count from IDENTIFY data + // Parse sector count from IDENTIFY data. const uint16_t *id = (const uint16_t *)drv->bounceVirt; if (id[ATA_IDENT_W83] & (1u << 10)) { - // 48-bit LBA supported + // 48-bit LBA supported. drv->sectorCount = (uint64_t)id[ATA_IDENT_W100] | ((uint64_t)id[ATA_IDENT_W100 + 1] << 16) | ((uint64_t)id[ATA_IDENT_W100 + 2] << 32) | ((uint64_t)id[ATA_IDENT_W100 + 3] << 48); } else { - // 28-bit LBA + // 28-bit LBA. drv->sectorCount = (uint64_t)id[ATA_IDENT_W60] | ((uint64_t)id[ATA_IDENT_W60 + 1] << 16); } @@ -352,7 +338,7 @@ static KSTATUS port_identify(AHCI_DRIVE *drv) { return STATUS_SUCCESS; } -// Core read logic +// Core read logic. static KSTATUS do_read(AHCI_DRIVE *drv, uint64_t lba, uint32_t count, void *buf) { uint8_t *out = (uint8_t *)buf; @@ -372,7 +358,7 @@ static KSTATUS do_read(AHCI_DRIVE *drv, uint64_t lba, return STATUS_SUCCESS; } -// Core write logic +// Core write logic. static KSTATUS do_write(AHCI_DRIVE *drv, uint64_t lba, uint32_t count, const void *buf) { const uint8_t *in = (const uint8_t *)buf; @@ -392,9 +378,7 @@ static KSTATUS do_write(AHCI_DRIVE *drv, uint64_t lba, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// Async IRP dispatch -// --------------------------------------------------------------------------- +// Async IRP dispatch. static KSTATUS AhciGetIrpReadWrite(IRP* irp, bool* outWrite, uint64_t* outLba, @@ -449,12 +433,14 @@ static KSTATUS AhciDispatchReadWrite(DEVICE_OBJECT *device, IRP *irp) { return STATUS_PENDING; } +// Cancels release Remove Lock. static void AhciCancelReleaseRemoveLock(IRP* irp, void* context) { AHCI_DRIVE* drv = (AHCI_DRIVE*)context; if (drv) IoReleaseRemoveLock(&drv->removeLock, irp); } +// Dispatches drive Pnp. static KSTATUS AhciDispatchDrivePnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return STATUS_INVALID_PARAMETER; AHCI_DRIVE* drv = (AHCI_DRIVE*)device->DeviceExtension; @@ -492,6 +478,7 @@ static KSTATUS AhciDispatchDrivePnp(DEVICE_OBJECT* device, IRP* irp) { } } +// Dispatches controller Pnp. static KSTATUS AhciDispatchControllerPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return STATUS_INVALID_PARAMETER; AHCI_CONTROLLER* ctl = (AHCI_CONTROLLER*)device->DeviceExtension; @@ -545,6 +532,7 @@ static KSTATUS AhciDispatchControllerPnp(DEVICE_OBJECT* device, IRP* irp) { } } +// Dispatches pnp. static KSTATUS AhciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !device->DeviceExtension) return STATUS_INVALID_PARAMETER; @@ -562,14 +550,14 @@ static KSTATUS AhciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { // 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. -// -// NCQ TODO: replace the serialised loop with a multi-slot dispatcher: + +// NCQ remains serialized until the driver grows a multi-slot dispatcher: // 1. KeWaitSemaphore() to wait for a free slot AND a pending IRP. // 2. Pick the oldest IRP from the queue. // 3. Grab a free bit in drv->slotMask (under the slot spinlock). // 4. Copy write data into slotBounce[slot], build the NCQ FIS (FPDMA), // record slotIrp[slot] = irp, and issue via port->sact + port->ci. -// 5. Return immediately - the ISR drives all completions. +// 5. Return immediately so the ISR can drive all completions. static void AhciWorker(uintptr_t arg) { AHCI_DRIVE *drv = (AHCI_DRIVE *)arg; @@ -599,9 +587,7 @@ static void AhciWorker(uintptr_t arg) { } } -// --------------------------------------------------------------------------- -// AHCI controller initialisation -// --------------------------------------------------------------------------- +// AHCI controller initialisation. @@ -622,11 +608,12 @@ static void AhciWorker(uintptr_t arg) { // TFES (bit 30) - Task File Error Status - error // HBFS (bit 29) - Host Bus Fatal error // HBDS (bit 28) - Host Bus Data error -// IFS (bit 27) - Interface Fatal error +// IFS (bit 27) - Interface Fatal error. #define PORT_IE_NORMAL (0x0000000Fu) #define PORT_IE_ERRORS (PORT_IS_TFES | PORT_IS_HBFS | PORT_IS_HBDS | PORT_IS_IFS) #define PORT_IE_ALL (PORT_IE_NORMAL | PORT_IE_ERRORS) +// Registers controller. static KSTATUS AhciRegisterController(AHCI_CONTROLLER* ctl) { if (!ctl) return STATUS_INVALID_PARAMETER; for (int i = 0; i < g_controllerCount; i++) { @@ -639,6 +626,7 @@ static KSTATUS AhciRegisterController(AHCI_CONTROLLER* ctl) { return STATUS_SUCCESS; } +// Starts controller. static KSTATUS AhciStartController(AHCI_CONTROLLER* ctl) { if (!ctl || ctl->magic != AHCI_CONTROLLER_MAGIC || !ctl->pdo || !ctl->fdo) return STATUS_INVALID_PARAMETER; @@ -723,7 +711,7 @@ static KSTATUS AhciStartController(AHCI_CONTROLLER* ctl) { HBA_PORT *port = &ctl->hba->ports[portno]; - // Phase 1: physical link check + // Phase 1: physical link check. if (!port_link_up(port)) { DbgPrint("AHCI: port %u: no link (ssts=0x%08x)\n", portno, port->ssts); continue; @@ -739,28 +727,28 @@ static KSTATUS AhciStartController(AHCI_CONTROLLER* ctl) { drv->port = port; drv->portNo = (uint8_t)portno; - // Phase 2: allocate command list, FIS buffer, bounce buffer + // Phase 2: allocate command list, FIS buffer, bounce buffer. st = port_init_memory(drv); if (!KSUCCESS(st)) { DbgPrint("AHCI: port %u: memory init failed (0x%x)\n", portno, st); continue; } - // Phase 3: COMRESET - forces device to re-send D2H FIS for valid SIG + // Phase 3: COMRESET - forces device to re-send D2H FIS for valid SIG. st = port_comreset(drv); if (!KSUCCESS(st)) { DbgPrint("AHCI: port %u: COMRESET failed\n", portno); continue; } - // Phase 4: filter to SATA disks + // Phase 4: filter to SATA disks. if (!port_is_sata_disk(port)) { DbgPrint("AHCI: port %u: not a SATA disk (sig=0x%08x), skipping\n", portno, port->sig); continue; } - // Phase 5: create per-drive completion event (auto-reset, initially clear) + // Phase 5: create per-drive completion event (auto-reset, initially clear). st = KeEventCreate(EventAutoReset, 0, &drv->completionEvent); if (!KSUCCESS(st)) { DbgPrint("AHCI: port %u: event create failed (0x%x)\n", portno, st); @@ -783,7 +771,7 @@ static KSTATUS AhciStartController(AHCI_CONTROLLER* ctl) { continue; } - // Phase 6: IDENTIFY (polled - scheduler not yet running) + // Phase 6: IDENTIFY (polled - scheduler not yet running). st = port_identify(drv); if (!KSUCCESS(st)) { DbgPrint("AHCI: port %u: IDENTIFY failed (0x%x)\n", portno, st); @@ -852,6 +840,7 @@ static KSTATUS AhciStartController(AHCI_CONTROLLER* ctl) { return STATUS_SUCCESS; } +// Implements the add Device operation. static KSTATUS AhciAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return STATUS_INVALID_PARAMETER; @@ -879,6 +868,7 @@ static KSTATUS AhciAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDevic return STATUS_SUCCESS; } +// Implements the driver Entry operation. KSTATUS DriverEntry(const HAL_API *hal) { DbgPrint("AHCI: driver loading...\n"); g_hal = hal; diff --git a/code/drivers/storage/ahci/ahci.h b/code/drivers/storage/ahci/ahci.h index adc9dea..c6ff2ec 100644 --- a/code/drivers/storage/ahci/ahci.h +++ b/code/drivers/storage/ahci/ahci.h @@ -1,4 +1,5 @@ -// ahci.h - shared AHCI driver internals. +// AHCI driver state and register definitions shared across controller and port code. + #pragma once #include @@ -16,7 +17,6 @@ #include #include -// --------------------------------------------------------------------------- typedef enum { FIS_TYPE_REG_H2D = 0x27, FIS_TYPE_REG_D2H = 0x34, @@ -29,7 +29,7 @@ typedef enum { } FIS_TYPE; #pragma pack(push, 1) -// Register FIS - Host to Device (H2D) +// Register FIS - Host to Device (H2D). typedef struct { uint8_t fis_type; // FIS_TYPE_REG_H2D uint8_t pmport : 4; @@ -37,21 +37,21 @@ typedef struct { uint8_t c : 1; // 1 = Command, 0 = Control uint8_t command; uint8_t featurel; - // DW1 + // DW1. uint8_t lba0, lba1, lba2; uint8_t device; - // DW2 + // DW2. uint8_t lba3, lba4, lba5; uint8_t featureh; - // DW3 + // DW3. uint8_t countl, counth; uint8_t icc; uint8_t control; - // DW4 + // DW4. uint8_t rsv1[4]; } FIS_REG_H2D; -// Register FIS - Device to Host (D2H) +// Register FIS - Device to Host (D2H). typedef struct { uint8_t fis_type; uint8_t pmport : 4; @@ -69,7 +69,7 @@ typedef struct { uint8_t rsv4[4]; } FIS_REG_D2H; -// DMA Setup FIS +// DMA Setup FIS. typedef struct { uint8_t fis_type; uint8_t pmport : 4; @@ -85,7 +85,7 @@ typedef struct { uint32_t resvd; } FIS_DMA_SETUP; -// PIO Setup FIS +// PIO Setup FIS. typedef struct { uint8_t fis_type; uint8_t pmport : 4; @@ -106,7 +106,7 @@ typedef struct { uint8_t rsv4[2]; } FIS_PIO_SETUP; -// Set Device Bits FIS +// Set Device Bits FIS. typedef struct { uint8_t fis_type; uint8_t pmport : 4; @@ -121,11 +121,9 @@ typedef struct { uint32_t protocol; } FIS_DEV_BITS; -// --------------------------------------------------------------------------- -// HBA structures (volatile - MMIO) -// --------------------------------------------------------------------------- +// HBA structures (volatile - MMIO). -// Received FIS structure in host memory +// Received FIS structure in host memory. typedef volatile struct { FIS_DMA_SETUP dsfis; // 0x00 DMA Setup FIS uint8_t pad0[4]; @@ -138,9 +136,9 @@ typedef volatile struct { uint8_t rsv[0x100-0xA0]; } HBA_FIS; -// Command List header (one entry = one slot) +// Command List header (one entry = one slot). typedef struct { - // DW0 + // DW0. uint8_t cfl : 5; // Command FIS length in DWORDs (2..16) uint8_t a : 1; // ATAPI uint8_t w : 1; // Write (H2D=1, D2H=0) @@ -151,16 +149,16 @@ typedef struct { uint8_t rsv0 : 1; uint8_t pmp : 4; // Port multiplier port uint16_t prdtl; // PRDT length in entries - // DW1 + // DW1. volatile uint32_t prdbc; // PRDT byte count transferred - // DW2,3 + // DW2,3. uint32_t ctba; // Command table base address (128-byte aligned) uint32_t ctbau; // Upper 32 bits - // DW4-7 + // DW4-7. uint32_t rsv1[4]; } HBA_CMD_HEADER; -// Physical Region Descriptor Table entry +// Physical Region Descriptor Table entry. typedef struct { uint32_t dba; // Data base address uint32_t dbau; // Upper 32 bits @@ -170,7 +168,7 @@ typedef struct { uint32_t i : 1; // Interrupt on completion } HBA_PRDT_ENTRY; -// Command Table +// Command Table. typedef struct { uint8_t cfis[64]; // Command FIS (up to 64 bytes) uint8_t acmd[16]; // ATAPI command (12 or 16 bytes) @@ -179,7 +177,7 @@ typedef struct { } HBA_CMD_TBL; #pragma pack(pop) -// Port registers +// Port registers. typedef volatile struct { uint32_t clb; // 0x00 Command list base (1K-aligned) uint32_t clbu; // 0x04 Command list base upper @@ -202,7 +200,7 @@ typedef volatile struct { uint32_t vendor[4]; } HBA_PORT; -// Generic Host Control registers (starts at ABAR) +// Generic Host Control registers (starts at ABAR). typedef volatile struct { uint32_t cap; // 0x00 Host capability uint32_t ghc; // 0x04 Global host control @@ -220,9 +218,7 @@ typedef volatile struct { HBA_PORT ports[32]; // 0x100 Port control registers } HBA_MEM; -// --------------------------------------------------------------------------- -// Constants -// --------------------------------------------------------------------------- +// Constants. // PCI/AHCI binding. PCI enumeration, BAR decoding, interrupt line // discovery, and command-register policy are owned by pci.sys. @@ -231,20 +227,20 @@ typedef volatile struct { #define AHCI_DRIVE_MAGIC 0x41484452u // 'AHDR' #define MAX_AHCI_CONTROLLERS 8 -// GHC register bits +// GHC register bits. #define GHC_AE (1u << 31) // AHCI Enable #define GHC_IE (1u << 1) // Interrupt Enable #define GHC_HR (1u << 0) // HBA Reset -// BOHC register bits +// BOHC register bits. #define BOHC_BOS (1u << 0) // BIOS-owned semaphore #define BOHC_OOS (1u << 1) // OS-owned semaphore #define BOHC_BB (1u << 4) // BIOS Busy -// CAP2 bits +// CAP2 bits. #define CAP2_BOH (1u << 0) // BIOS/OS handoff capable -// Port CMD register bits +// Port CMD register bits. #define PORT_CMD_ST (1u << 0) // Start #define PORT_CMD_FRE (1u << 4) // FIS Receive Enable #define PORT_CMD_FR (1u << 14) // FIS Receive Running @@ -253,34 +249,34 @@ typedef volatile struct { #define PORT_CMD_SUD (1u << 1) // Spin-Up Device #define PORT_CMD_ICC_ACTIVE (0x1u << 28) -// Port IS register bits (interrupt status) +// Port IS register bits (interrupt status). #define PORT_IS_TFES (1u << 30) // Task File Error Status #define PORT_IS_HBFS (1u << 29) // Host Bus Fatal Error #define PORT_IS_HBDS (1u << 28) // Host Bus Data Error #define PORT_IS_IFS (1u << 27) // Interface Fatal Error -// Port SSTS register +// Port SSTS register. #define PORT_DET_PRESENT 0x3 #define PORT_IPM_ACTIVE 0x1 -// Port signatures +// Port signatures. #define SATA_SIG_ATA 0x00000101 #define SATA_SIG_ATAPI 0xEB140101 #define SATA_SIG_SEMB 0xC33C0101 #define SATA_SIG_PM 0x96690101 -// ATA commands +// ATA commands. #define ATA_CMD_READ_DMA_EX 0x25 #define ATA_CMD_WRITE_DMA_EX 0x35 #define ATA_CMD_IDENTIFY 0xEC #define ATA_CMD_FLUSH_EXT 0xEA -// ATA status bits +// ATA status bits. #define ATA_SR_BUSY 0x80 #define ATA_SR_DRQ 0x08 #define ATA_SR_ERR 0x01 -// IDENTIFY word offsets +// IDENTIFY word offsets. #define ATA_IDENT_W83 83 // bit 10 = 48-bit LBA supported #define ATA_IDENT_W100 100 // 48-bit LBA sector count (4 words) #define ATA_IDENT_W60 60 // 28-bit LBA sector count (2 words) @@ -289,7 +285,7 @@ typedef volatile struct { // Offset 0: Command List 1024 bytes (32 ร— 32-byte headers) // Offset 1024: Received FIS 256 bytes // Offset 2048: Command Tables 32 ร— 256 bytes = 8192 bytes -// Total: 10240 bytes โ†’ 3 pages (12288 bytes) +// Total: 10240 bytes โ†’ 3 pages (12288 bytes). #define PORT_PAGES_STRUCT 3 #define PORT_OFF_CMDLIST 0 #define PORT_OFF_FIS 1024 @@ -297,12 +293,12 @@ typedef volatile struct { #define PORT_CMDTBL_SIZE 256 // 64 CFIS + 16 ACMD + 48 rsv + 8ร—16 PRDT #define PORT_PRDT_COUNT 8 // PRDT entries per command table -// Bounce buffer: 128 sectors ร— 512 bytes = 64 KB = 16 pages +// Bounce buffer: 128 sectors ร— 512 bytes = 64 KB = 16 pages. #define BOUNCE_SECTORS 128 #define BOUNCE_BYTES (BOUNCE_SECTORS * 512) #define BOUNCE_PAGES (BOUNCE_BYTES / 4096) -// Polling timeout (spin iterations) +// Polling timeout (spin iterations). #define POLL_TIMEOUT 1000000 #define MAX_AHCI_DRIVES 8 @@ -316,7 +312,7 @@ typedef volatile struct { typedef struct AHCI_CONTROLLER AHCI_CONTROLLER; -// Per-drive context +// Per-drive context. typedef struct { uint32_t magic; // AHCI_DRIVE_MAGIC AHCI_CONTROLLER* controller; // owning AHCI controller FDO extension @@ -324,11 +320,11 @@ typedef struct { uint64_t sectorCount; // Total LBA sectors on device uint8_t portNo; // Physical port index (for ISR dispatch) - // Structures block (command list + FIS + cmd tables) + // Structures block (command list + FIS + cmd tables). uint64_t structPhys; // Physical base void* structVirt; // Virtual base - // Bounce buffer for DMA data + // Bounce buffer for DMA data. uint64_t bouncePhys; void* bounceVirt; @@ -342,9 +338,7 @@ typedef struct { // Bottom-half used to wake the worker outside hard IRQ/DIRQL context. KDPC completionDpc; - // ----------------------------------------------------------------------- // IRP queue - async dispatch - // ----------------------------------------------------------------------- // AhciWorker blocks here waiting for work. AHCI dispatch enqueues an IRP // and signals the semaphore to wake the worker. IRP_QUEUE irpQueue; @@ -354,12 +348,12 @@ typedef struct { THREAD* workerThread; DEVICE_OBJECT* deviceObject; - // NCQ TODO: for multi-slot NCQ, add: + // Multi-slot NCQ needs per-slot ownership state in addition to the serialized queue: // uint32_t slotMask; // bitmask of in-flight slots // IRP* slotIrp[NUM_CMD_SLOTS]; // slot โ†’ pending IRP // uint64_t slotBouncePhys[NUM_CMD_SLOTS]; // void* slotBounceVirt[NUM_CMD_SLOTS]; - // volatile uint32_t prevSact; // previous port->sact snapshot + // volatile uint32_t prevSact; // previous port->sact snapshot. } AHCI_DRIVE; struct AHCI_CONTROLLER { diff --git a/code/drivers/storage/ahci/ahci_port.c b/code/drivers/storage/ahci/ahci_port.c index ad4fab3..56ca872 100644 --- a/code/drivers/storage/ahci/ahci_port.c +++ b/code/drivers/storage/ahci/ahci_port.c @@ -1,6 +1,8 @@ -// ahci_port.c - AHCI MMIO mapping, HBA reset, and port link bring-up helpers. +// AHCI port helpers. This file owns port reset, command-table setup, and per-port command execution. + #include "ahci.h" +// Implements the ahci map mmio operation. KSTATUS ahci_map_mmio(uint64_t physBase, uint64_t length) { if (length == 0) length = AHCI_MMIO_PAGES * 4096ull; @@ -27,24 +29,26 @@ KSTATUS ahci_map_mmio(uint64_t physBase, uint64_t length) { } +// Implements the port stop operation. void port_stop(HBA_PORT *port) { - // Clear ST (bit 0) + // Clear ST (bit 0). port->cmd &= ~PORT_CMD_ST; - // Wait for CR (bit 15) to clear (command list DMA stops) + // Wait for CR (bit 15) to clear (command list DMA stops). for (int i = 0; i < POLL_TIMEOUT; i++) { if (!(port->cmd & PORT_CMD_CR)) break; } - // Clear FRE (bit 4) + // Clear FRE (bit 4). port->cmd &= ~PORT_CMD_FRE; - // Wait for FR (bit 14) to clear + // Wait for FR (bit 14) to clear. for (int i = 0; i < POLL_TIMEOUT; i++) { if (!(port->cmd & PORT_CMD_FR)) break; } } +// Implements the port start operation. void port_start(HBA_PORT *port) { - // Wait until CR is clear before setting ST + // Wait until CR is clear before setting ST. for (int i = 0; i < POLL_TIMEOUT; i++) { if (!(port->cmd & PORT_CMD_CR)) break; } @@ -53,24 +57,25 @@ void port_start(HBA_PORT *port) { } +// Implements the hba reset operation. KSTATUS hba_reset(HBA_MEM *hba) { - // BIOS/OS handoff (spec ยง10.6.3) + // BIOS/OS handoff (spec ยง10.6.3). if (hba->cap2 & CAP2_BOH) { hba->bohc |= BOHC_OOS; - // Wait for BIOS to clear BOS + // Wait for BIOS to clear BOS. for (int i = 0; i < POLL_TIMEOUT; i++) { if (!(hba->bohc & BOHC_BOS)) break; } - // Give the BIOS another moment to clear Busy + // Give the BIOS another moment to clear Busy. for (int i = 0; i < 800000; i++) { if (!(hba->bohc & BOHC_BB)) break; } } - // Enable AHCI mode before reset so the reset actually takes effect + // Enable AHCI mode before reset so the reset actually takes effect. hba->ghc |= GHC_AE; - // HBA reset + // HBA reset. hba->ghc |= GHC_HR; for (int i = 0; i < POLL_TIMEOUT; i++) { if (!(hba->ghc & GHC_HR)) break; @@ -87,6 +92,7 @@ KSTATUS hba_reset(HBA_MEM *hba) { } +// Implements the port link up operation. bool port_link_up(HBA_PORT *port) { uint32_t det = port->ssts & 0x0F; uint32_t ipm = (port->ssts >> 8) & 0x0F; @@ -94,17 +100,20 @@ bool port_link_up(HBA_PORT *port) { } +// Implements the port is sata disk operation. bool port_is_sata_disk(HBA_PORT *port) { return port->sig == SATA_SIG_ATA; } +// Implements the ahci delay ms operation. void ahci_delay_ms(uint32_t ms) { for (uint32_t i = 0; i < ms * 1000; i++) __outbyte(0x80, 0); } +// Implements the port comreset operation. KSTATUS port_comreset(AHCI_DRIVE *drv) { HBA_PORT *port = drv->port; @@ -112,14 +121,14 @@ KSTATUS port_comreset(AHCI_DRIVE *drv) { for (int i = 0; i < POLL_TIMEOUT; i++) if (!(port->cmd & PORT_CMD_CR)) break; - // Assert COMRESET: SControl.DET = 1, hold for โ‰ฅ 1ms + // Assert COMRESET: SControl.DET = 1, hold for โ‰ฅ 1ms. port->sctl = (port->sctl & ~0x0Fu) | 0x1u; ahci_delay_ms(1); - // Deassert: DET = 0 + // Deassert: DET = 0. port->sctl = port->sctl & ~0x0Fu; - // Poll for DET = 3, up to 1 second + // Poll for DET = 3, up to 1 second. bool link_ok = false; for (int i = 0; i < 1000; i++) { if ((port->ssts & 0x0Fu) == PORT_DET_PRESENT) { link_ok = true; break; } @@ -134,7 +143,7 @@ KSTATUS port_comreset(AHCI_DRIVE *drv) { port->is = (uint32_t)-1; port->cmd |= PORT_CMD_ST; - // Wait up to 500ms for a valid signature (D2H FIS from device) + // Wait up to 500ms for a valid signature (D2H FIS from device). for (int i = 0; i < 500; i++) { uint32_t sig = port->sig; if (sig != 0xFFFFFFFFu && sig != 0x00000000u) break; diff --git a/code/drivers/storage/ata/ata.c b/code/drivers/storage/ata/ata.c index 9ca5605..be99d06 100644 --- a/code/drivers/storage/ata/ata.c +++ b/code/drivers/storage/ata/ata.c @@ -1,4 +1,5 @@ -// ata.c - PCI IDE / ATA disk driver. +// ATA compatibility storage driver. This file owns legacy IDE probing and PIO disk access for older virtual hardware. + #include "ata.h" const HAL_API* gAtaHal; @@ -15,30 +16,37 @@ static const IO_DRIVER_ID_TABLE gAtaIdTable = { sizeof(gAtaIds) / sizeof(gAtaIds[0]), }; +// Implements the in8 operation. static uint8_t AtaIn8(ATA_CHANNEL* ch, uint8_t reg) { return __inbyte((unsigned short)(ch->CommandBase + reg)); } +// Implements the in16 operation. static uint16_t AtaIn16(ATA_CHANNEL* ch, uint8_t reg) { return __inword((unsigned short)(ch->CommandBase + reg)); } +// Implements the out8 operation. static void AtaOut8(ATA_CHANNEL* ch, uint8_t reg, uint8_t value) { __outbyte((unsigned short)(ch->CommandBase + reg), value); } +// Implements the out16 operation. static void AtaOut16(ATA_CHANNEL* ch, uint8_t reg, uint16_t value) { __outword((unsigned short)(ch->CommandBase + reg), value); } +// Implements the alt Status operation. static uint8_t AtaAltStatus(ATA_CHANNEL* ch) { return __inbyte((unsigned short)(ch->ControlBase + ATA_REG_ALT_STATUS)); } +// Implements the device Control operation. static void AtaDeviceControl(ATA_CHANNEL* ch, uint8_t value) { __outbyte((unsigned short)(ch->ControlBase + ATA_REG_DEVICE_CONTROL), value); } +// Implements the delay400ns operation. static void AtaDelay400ns(ATA_CHANNEL* ch) { (void)AtaAltStatus(ch); (void)AtaAltStatus(ch); @@ -46,6 +54,7 @@ static void AtaDelay400ns(ATA_CHANNEL* ch) { (void)AtaAltStatus(ch); } +// Waits for not Busy. static KSTATUS AtaWaitNotBusy(ATA_CHANNEL* ch) { for (uint32_t i = 0; i < ATA_POLL_LIMIT; i++) { if (!(AtaIn8(ch, ATA_REG_STATUS) & ATA_STATUS_BSY)) @@ -55,6 +64,7 @@ static KSTATUS AtaWaitNotBusy(ATA_CHANNEL* ch) { return STATUS_TIMEOUT; } +// Waits for drq. static KSTATUS AtaWaitDrq(ATA_CHANNEL* ch) { for (uint32_t i = 0; i < ATA_POLL_LIMIT; i++) { uint8_t st = AtaIn8(ch, ATA_REG_STATUS); @@ -69,12 +79,14 @@ static KSTATUS AtaWaitDrq(ATA_CHANNEL* ch) { return STATUS_TIMEOUT; } +// Implements the select Drive operation. static void AtaSelectDrive(ATA_DEVICE* dev) { ATA_CHANNEL* ch = dev->Channel; AtaOut8(ch, ATA_REG_DRIVE_HEAD, (uint8_t)(0xA0u | (dev->Drive ? 0x10u : 0u))); AtaDelay400ns(ch); } +// Implements the identify operation. static KSTATUS AtaIdentify(ATA_DEVICE* dev) { ATA_CHANNEL* ch = dev->Channel; uint16_t ident[256]; @@ -139,6 +151,7 @@ static KSTATUS AtaIdentify(ATA_DEVICE* dev) { return dev->SectorCount ? STATUS_SUCCESS : STATUS_NOT_FOUND; } +// Implements the program Lba operation. static KSTATUS AtaProgramLba(ATA_DEVICE* dev, uint64_t lba, uint16_t count, bool write) { ATA_CHANNEL* ch = dev->Channel; @@ -168,6 +181,7 @@ static KSTATUS AtaProgramLba(ATA_DEVICE* dev, uint64_t lba, uint16_t count, bool return STATUS_SUCCESS; } +// Returns pio. static KSTATUS AtaReadPio(ATA_DEVICE* dev, uint64_t lba, uint32_t count, void* buffer) { if (!dev || !buffer) return STATUS_INVALID_PARAMETER; @@ -210,6 +224,7 @@ static KSTATUS AtaReadPio(ATA_DEVICE* dev, uint64_t lba, uint32_t count, void* b return st; } +// Flushes the requested operation. static KSTATUS AtaFlush(ATA_DEVICE* dev) { ATA_CHANNEL* ch = dev->Channel; KSTATUS st = AtaWaitNotBusy(ch); @@ -219,6 +234,7 @@ static KSTATUS AtaFlush(ATA_DEVICE* dev) { return AtaWaitNotBusy(ch); } +// Updates pio. static KSTATUS AtaWritePio(ATA_DEVICE* dev, uint64_t lba, uint32_t count, const void* buffer) { if (!dev || !buffer) return STATUS_INVALID_PARAMETER; @@ -285,6 +301,7 @@ static KSTATUS AtaGetIrpReadWrite(IRP* irp, bool* outWrite, uint64_t* outLba, return STATUS_SUCCESS; } +// Implements the worker operation. static void AtaWorker(uintptr_t arg) { ATA_DEVICE* dev = (ATA_DEVICE*)arg; if (!dev) @@ -315,6 +332,7 @@ static void AtaWorker(uintptr_t arg) { } } +// Dispatches read Write. KSTATUS AtaDispatchReadWrite(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp || !device->DeviceExtension) return STATUS_INVALID_PARAMETER; @@ -345,6 +363,7 @@ KSTATUS AtaDispatchReadWrite(DEVICE_OBJECT* device, IRP* irp) { return STATUS_PENDING; } +// Returns free Disk Index. static uint8_t AtaFindFreeDiskIndex(void) { for (uint8_t i = 0; i < 8; i++) { if (!IoDiskDevicePresent(i)) @@ -353,6 +372,7 @@ static uint8_t AtaFindFreeDiskIndex(void) { return 0xFFu; } +// Implements the bar Io Base operation. static uint16_t AtaBarIoBase(ATA_CONTROLLER* ctl, uint8_t barIndex, uint16_t fallback) { PCI_BAR bar; KSTATUS st = PciGetBar(ctl->Pdo, barIndex, &bar); @@ -361,6 +381,7 @@ static uint16_t AtaBarIoBase(ATA_CONTROLLER* ctl, uint8_t barIndex, uint16_t fal return fallback; } +// Initializes channel. static KSTATUS AtaInitChannel(ATA_CONTROLLER* ctl, uint8_t index) { ATA_CHANNEL* ch = &ctl->Channels[index]; memset(ch, 0, sizeof(*ch)); @@ -398,6 +419,7 @@ static KSTATUS AtaInitChannel(ATA_CONTROLLER* ctl, uint8_t index) { return STATUS_SUCCESS; } +// Registers disk. static KSTATUS AtaRegisterDisk(ATA_DEVICE* dev) { DEVICE_OBJECT* disk = (DEVICE_OBJECT*)0; KSTATUS st = IoCreateDevice(&gAtaDriver, 0, &disk); @@ -433,6 +455,7 @@ static KSTATUS AtaRegisterDisk(ATA_DEVICE* dev) { return STATUS_SUCCESS; } +// Probes drive. static KSTATUS AtaProbeDrive(ATA_CONTROLLER* ctl, ATA_CHANNEL* ch, uint8_t drive) { ATA_DEVICE* dev = &ch->Devices[drive]; memset(dev, 0, sizeof(*dev)); @@ -470,6 +493,7 @@ static KSTATUS AtaProbeDrive(ATA_CONTROLLER* ctl, ATA_CHANNEL* ch, uint8_t drive return STATUS_SUCCESS; } +// Registers controller. static KSTATUS AtaRegisterController(ATA_CONTROLLER* ctl) { if (!ctl) return STATUS_INVALID_PARAMETER; for (uint32_t i = 0; i < gAtaControllerCount; i++) { @@ -482,6 +506,7 @@ static KSTATUS AtaRegisterController(ATA_CONTROLLER* ctl) { return STATUS_SUCCESS; } +// Starts controller. static KSTATUS AtaStartController(ATA_CONTROLLER* ctl) { if (!ctl || ctl->Magic != ATA_CONTROLLER_MAGIC || !ctl->Pdo || !ctl->Fdo) return STATUS_INVALID_PARAMETER; @@ -538,12 +563,14 @@ static KSTATUS AtaStartController(ATA_CONTROLLER* ctl) { return STATUS_SUCCESS; } +// Cancels release Remove Lock. static void AtaCancelReleaseRemoveLock(IRP* irp, void* context) { ATA_DEVICE* dev = (ATA_DEVICE*)context; if (dev) IoReleaseRemoveLock(&dev->RemoveLock, irp); } +// Releases controller Devices. static void AtaRemoveControllerDevices(ATA_CONTROLLER* ctl, IO_DEVICE_CHANGE change) { if (!ctl) return; for (uint8_t c = 0; c < ATA_CHANNEL_COUNT; c++) { @@ -566,6 +593,7 @@ static void AtaRemoveControllerDevices(ATA_CONTROLLER* ctl, IO_DEVICE_CHANGE cha } } +// Dispatches pnp. KSTATUS AtaDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp || !device->DeviceExtension) return STATUS_INVALID_PARAMETER; @@ -637,6 +665,7 @@ KSTATUS AtaDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { return STATUS_INVALID_PARAMETER; } +// Implements the add Device operation. KSTATUS AtaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return STATUS_INVALID_PARAMETER; @@ -663,6 +692,7 @@ KSTATUS AtaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) return STATUS_SUCCESS; } +// Implements the driver Entry operation. KSTATUS DriverEntry(const HAL_API* hal) { if (!hal) return STATUS_INVALID_PARAMETER; diff --git a/code/drivers/storage/ata/ata.h b/code/drivers/storage/ata/ata.h index c762dde..f3818d9 100644 --- a/code/drivers/storage/ata/ata.h +++ b/code/drivers/storage/ata/ata.h @@ -1,4 +1,5 @@ -// ata.h - PCI IDE / ATA driver internals. +// ATA compatibility driver definitions shared by the storage implementation. + #pragma once #include diff --git a/code/kernel/hal/hal_apic.c b/code/kernel/hal/hal_apic.c index 1806388..8da818f 100644 --- a/code/kernel/hal/hal_apic.c +++ b/code/kernel/hal/hal_apic.c @@ -1,4 +1,5 @@ -// hal_apic.c - Local APIC + I/O APIC +// HAL APIC support. This file owns local APIC, I/O APIC, and interrupt-controller setup. + #include #include #include @@ -6,7 +7,7 @@ extern HAL_API gApi; -// ---- Local APIC ---- +// ---- Local APIC ----. static volatile uint32_t* gLapic = (volatile uint32_t *)0; #define LAPIC_REG(off) (*(volatile uint32_t *)((uint8_t *)gLapic + (off))) #define LAPIC_ID 0x020 @@ -28,7 +29,7 @@ static volatile uint32_t* gLapic = (volatile uint32_t *)0; #define APIC_VECTOR_RESCHEDULE 0xF0u -// ---- I/O APIC ---- +// ---- I/O APIC ----. static volatile uint32_t* gIoapic = (volatile uint32_t *)0; static uint32_t gBspLapicId = 0; static uint8_t gX2ApicSupported = 0; @@ -36,15 +37,18 @@ static uint8_t gX2ApicEnabled = 0; #define IOAPIC_IDX 0x00 #define IOAPIC_DATA 0x10 +// Implements the ioapic Read operation. static uint32_t IoapicRead(uint8_t reg) { *(volatile uint32_t *)((uint8_t *)gIoapic + IOAPIC_IDX) = reg; return *(volatile uint32_t *)((uint8_t *)gIoapic + IOAPIC_DATA); } +// Implements the ioapic Write operation. static void IoapicWrite(uint8_t reg, uint32_t val) { *(volatile uint32_t *)((uint8_t *)gIoapic + IOAPIC_IDX) = reg; *(volatile uint32_t *)((uint8_t *)gIoapic + IOAPIC_DATA) = val; } +// Implements the apic Detect Mode operation. static void HalApicDetectMode(void) { int regs[4] = {0, 0, 0, 0}; __cpuid(regs, 1); @@ -54,17 +58,20 @@ static void HalApicDetectMode(void) { gX2ApicEnabled = (gX2ApicSupported && (apicBase & IA32_APIC_BASE_X2APIC)) ? 1u : 0u; } +// Implements the apic Stall Fallback operation. static void HalApicStallFallback(uint32_t loops) { for (volatile uint32_t i = 0; i < loops; i++) { _mm_pause(); } } +// Implements the apic Stall Us operation. static void HalApicStallUs(uint32_t us) { if (gApi.Timer.Stall) gApi.Timer.Stall(us); else HalApicStallFallback(us * 128u + 1u); } +// Implements the apic Wait Icr Idle operation. static void HalApicWaitIcrIdle(void) { if (gX2ApicEnabled) return; @@ -76,6 +83,7 @@ static void HalApicWaitIcrIdle(void) { } } +// Implements the apic Send Ipi operation. static void HalApicSendIpi(uint32_t lapicId, uint32_t low) { if (gX2ApicEnabled) { __writemsr(IA32_X2APIC_ICR, ((uint64_t)lapicId << 32) | low); @@ -94,20 +102,24 @@ static void HalApicSendIpi(uint32_t lapicId, uint32_t low) { // Interrupt vector base: IRQ 0 -> vector 0x20, IRQ 1 -> vector 0x21, ... #define IRQ_VECTOR_BASE 0x20 +// Returns bsp Lapic Id. __declspec(dllexport) uint32_t HalGetBspLapicId(void) { return gBspLapicId; } +// Implements the apic Using X2 Apic operation. __declspec(dllexport) uint8_t HalApicUsingX2Apic(void) { return gX2ApicEnabled; } +// Implements the apic Can Address Id operation. __declspec(dllexport) uint8_t HalApicCanAddressId(uint32_t lapicId) { if (gX2ApicEnabled) return 1u; return (lapicId < 256u) ? 1u : 0u; } +// Implements the apic Enable Current Cpu operation. __declspec(dllexport) void HalApicEnableCurrentCpu(void) { uint64_t apicBase = __readmsr(IA32_APIC_BASE) | IA32_APIC_BASE_ENABLE; @@ -123,6 +135,7 @@ __declspec(dllexport) void HalApicEnableCurrentCpu(void) { LAPIC_REG(LAPIC_SPURIOUS) = LAPIC_ENABLE | 0xFF; } +// Implements the apic Send Panic Ipi operation. __declspec(dllexport) void HalApicSendPanicIpi(void) { if (!gLapic && !gX2ApicEnabled) return; @@ -133,11 +146,13 @@ __declspec(dllexport) void HalApicSendPanicIpi(void) { HalApicSendIpi(0, (3u << 18) | (4u << 8)); // all-excluding-self, NMI } +// Implements the apic Send Reschedule Ipi operation. __declspec(dllexport) void HalApicSendRescheduleIpi(uint32_t lapicId) { if (!gLapic && !gX2ApicEnabled) return; HalApicSendIpi(lapicId, APIC_VECTOR_RESCHEDULE); // fixed delivery, physical destination } +// Implements the apic Send Tlb Shootdown Ipi operation. __declspec(dllexport) void HalApicSendTlbShootdownIpi(uint32_t lapicId) { if (!gLapic && !gX2ApicEnabled) return; @@ -148,6 +163,7 @@ __declspec(dllexport) void HalApicSendTlbShootdownIpi(uint32_t lapicId) { HalApicSendIpi(lapicId, (4u << 8)); // NMI delivery, physical destination } +// Starts application Processor. __declspec(dllexport) KSTATUS HalStartApplicationProcessor(uint32_t lapicId, uint8_t startupVector) { if ((!gLapic && !gX2ApicEnabled) || !startupVector || lapicId == gBspLapicId) return STATUS_INVALID_PARAMETER; @@ -166,6 +182,7 @@ __declspec(dllexport) KSTATUS HalStartApplicationProcessor(uint32_t lapicId, uin return STATUS_SUCCESS; } +// Implements the apic Route Irq operation. void HalApicRouteIrq(uint8_t irq) { // Full initial setup of the redirection entry. // Sets the vector and clears the mask bit in one write. @@ -174,12 +191,14 @@ void HalApicRouteIrq(uint8_t irq) { IoapicWrite(IOREDTBL_LO(irq), vector); // unmasked (bit 16 = 0), edge, fixed } +// Implements the apic Mask Irq operation. void HalApicMaskIrq(uint8_t irq) { uint32_t lo = IoapicRead(IOREDTBL_LO(irq)); lo |= (1 << 16); IoapicWrite(IOREDTBL_LO(irq), lo); } +// Implements the apic Unmask Irq operation. void HalApicUnmaskIrq(uint8_t irq) { uint32_t lo = IoapicRead(IOREDTBL_LO(irq)); lo &= ~(1 << 16); // clear mask bit @@ -188,6 +207,7 @@ void HalApicUnmaskIrq(uint8_t irq) { IoapicWrite(IOREDTBL_LO(irq), lo); } +// Implements the apic Send Eoi operation. void HalApicSendEoi(void) { if (gX2ApicEnabled) { __writemsr(IA32_X2APIC_EOI, 0); @@ -196,6 +216,7 @@ void HalApicSendEoi(void) { LAPIC_REG(LAPIC_EOI) = 0; } +// Implements the apic Initialize operation. void HalApicInitialize(uintptr_t lapicPhys, uintptr_t ioapicPhys) { HalApicDetectMode(); diff --git a/code/kernel/hal/hal_disk.c b/code/kernel/hal/hal_disk.c index 74b72df..80ec963 100644 --- a/code/kernel/hal/hal_disk.c +++ b/code/kernel/hal/hal_disk.c @@ -1,2 +1,2 @@ -// hal_disk.c intentionally left empty. -// Disk registration and dispatch live in kernel/io_device.c. +// HAL disk stub support. This file preserves the old HAL disk API while storage lives in drivers. + diff --git a/code/kernel/hal/hal_keyboard.c b/code/kernel/hal/hal_keyboard.c index 9d6890b..e7446f6 100644 --- a/code/kernel/hal/hal_keyboard.c +++ b/code/kernel/hal/hal_keyboard.c @@ -1 +1,2 @@ -// hal_keyboard.c - input moved out of HAL into kernel input core and ps2.sys. +// HAL keyboard stub support. Keyboard input is handled by the kernel input core and ps2.sys. + diff --git a/code/kernel/hal/hal_main.c b/code/kernel/hal/hal_main.c index afbb95f..357815b 100644 --- a/code/kernel/hal/hal_main.c +++ b/code/kernel/hal/hal_main.c @@ -1,4 +1,5 @@ -// hal_main.c - HAL initialisation and HalGetApi +// HAL initialization entry point. This file discovers platform tables and publishes the HAL API to the kernel. + #include #include #include @@ -23,15 +24,13 @@ HAL_API gApi; static int gInitialised = 0; extern void (*gTimerCallback)(void); -// --------------------------------------------------------------------------- // ACPI table walker - minimal, just enough to find APIC and HPET addresses. -// --------------------------------------------------------------------------- #define ACPI_SIG(a,b,c,d) ((uint32_t)(a)|((uint32_t)(b)<<8)|((uint32_t)(c)<<16)|((uint32_t)(d)<<24)) #pragma pack(push, 1) #pragma warning(disable : 4200) -// ACPI RSDP (Root System Description Pointer) +// ACPI RSDP (Root System Description Pointer). typedef struct { char Signature[8]; uint8_t Checksum; @@ -44,7 +43,7 @@ typedef struct { uint8_t Padding[3]; } RSDP; -// ACPI SDT Header +// ACPI SDT Header. typedef struct { char Signature[4]; uint32_t Length; @@ -57,19 +56,19 @@ typedef struct { uint32_t CreatorRevision; } ACPISDTHeader; -// RSDT (Root System Description Table) +// RSDT (Root System Description Table). typedef struct { ACPISDTHeader Header; uint32_t PointerToOtherSDT[]; } RSDT; -// XSDT (Extended System Description Table) +// XSDT (Extended System Description Table). typedef struct { ACPISDTHeader Header; uint64_t PointerToOtherSDT[]; } XSDT; -// MADT (Multiple APIC Description Table) +// MADT (Multiple APIC Description Table). typedef struct { ACPISDTHeader Header; uint32_t LocalAPICAddress; @@ -94,9 +93,11 @@ static int gS5Found = 0; int debugEnabled = 0; int _fltused; // MSVC floating-point helper anchor +// Implements the hal putchar operation. static void hal_putchar(char c) { gApi.Screen.PrintChar(c, 0xCCCCCC, 0x012456); } +// Implements the dbg Print operation. void HalDbgPrint(const char* fmt, ...) { if (!debugEnabled) return; @@ -131,6 +132,7 @@ typedef struct { } ACPI_GAS; #pragma pack(pop) +// Implements the acpi Read U32 operation. static uint32_t AcpiReadU32(const void* table, uint32_t tableLen, uint32_t off) { uint32_t value = 0; if (off + sizeof(value) <= tableLen) @@ -138,6 +140,7 @@ static uint32_t AcpiReadU32(const void* table, uint32_t tableLen, uint32_t off) return value; } +// Implements the acpi Read U64 operation. static uint64_t AcpiReadU64(const void* table, uint32_t tableLen, uint32_t off) { uint64_t value = 0; if (off + sizeof(value) <= tableLen) @@ -145,6 +148,7 @@ static uint64_t AcpiReadU64(const void* table, uint32_t tableLen, uint32_t off) return value; } +// Implements the acpi Read Gas Io Port operation. static uint16_t AcpiReadGasIoPort(const void* table, uint32_t tableLen, uint32_t off) { ACPI_GAS gas; if (off + sizeof(gas) > tableLen) return 0; @@ -214,6 +218,7 @@ static const uint8_t* AmlParseNameString(const uint8_t* p, const uint8_t* end, return p; } +// Implements the aml Read Integer operation. static int AmlReadInteger(const uint8_t** pp, const uint8_t* end, uint8_t* out) { const uint8_t* p = *pp; if (p >= end) return 0; @@ -290,6 +295,7 @@ static void ScanDsdtForS5(const uint8_t* aml, uint32_t len) { HalDbgPrint("HAL: _S5_ not found in DSDT; ACPI shutdown disabled\n"); } +// Validates checksum. static int validate_checksum(void* table, uint32_t length) { uint8_t sum = 0; uint8_t* bytes = (uint8_t*)table; @@ -299,6 +305,7 @@ static int validate_checksum(void* table, uint32_t length) { return sum == 0; } +// Parses fadt. static void ParseFadt(const ACPISDTHeader* header) { const void* fadt = header; uint32_t len = header->Length; @@ -326,6 +333,7 @@ static void ParseFadt(const ACPISDTHeader* header) { if (dsdtPhys) { const ACPISDTHeader* dsdt = (const ACPISDTHeader*)(dsdtPhys + gPhysBase); if (memcmp(dsdt->Signature, "DSDT", 4) == 0 && + // Validates checksum. validate_checksum((void*)dsdt, dsdt->Length)) { const uint8_t* aml = (const uint8_t*)(dsdt + 1); ScanDsdtForS5(aml, dsdt->Length - (uint32_t)sizeof(ACPISDTHeader)); @@ -336,6 +344,7 @@ static void ParseFadt(const ACPISDTHeader* header) { } +// Implements the add Cpu Record operation. static void HalAddCpuRecord(uint32_t uid, uint32_t lapicId, uint32_t flags) { if (gCpuTopology.CpuCount >= HAL_MAX_CPUS) return; @@ -353,6 +362,7 @@ static void HalAddCpuRecord(uint32_t uid, uint32_t lapicId, uint32_t flags) { cpu->Enabled = (flags & 1u) ? 1u : 0u; } +// Parses madt. static void ParseMadt(MADT* madt) { gLapicPhys = madt->LocalAPICAddress; uint8_t* p = (uint8_t *)(madt + 1); @@ -383,10 +393,11 @@ static void ParseMadt(MADT* madt) { } } +// Implements the walk Acpi operation. static void WalkAcpi(uintptr_t rsdpPhys) { if (!rsdpPhys) return; - // Map RSDP into virtual memory + // Map RSDP into virtual memory. RSDP* rsdp = (RSDP*)(rsdpPhys + gPhysBase); if (memcmp(rsdp->Signature, "RSD PTR ", 8) != 0) { @@ -398,11 +409,12 @@ static void WalkAcpi(uintptr_t rsdpPhys) { uint32_t count = 0; int isXsdt = 0; - // Safely find and validate the XSDT (ACPI 2.0+) + // Safely find and validate the XSDT (ACPI 2.0+). if (rsdp->Revision >= 2 && rsdp->XsdtAddress != 0) { XSDT* xsdt = (XSDT*)(rsdp->XsdtAddress + gPhysBase); if (validate_checksum(xsdt, xsdt->Header.Length) && + // Implements the memcmp operation. memcmp(xsdt->Header.Signature, "XSDT", 4) == 0) { sdtHeader = &xsdt->Header; @@ -411,11 +423,12 @@ static void WalkAcpi(uintptr_t rsdpPhys) { } } - // Fallback to safely finding and validating the RSDT (ACPI 1.0) + // Fallback to safely finding and validating the RSDT (ACPI 1.0). if (sdtHeader == NULL && rsdp->RsdtAddress != 0) { RSDT* rsdt = (RSDT*)((uintptr_t)rsdp->RsdtAddress + gPhysBase); if (validate_checksum(rsdt, rsdt->Header.Length) && + // Implements the memcmp operation. memcmp(rsdt->Header.Signature, "RSDT", 4) == 0) { sdtHeader = &rsdt->Header; @@ -429,7 +442,7 @@ static void WalkAcpi(uintptr_t rsdpPhys) { return; } - // Walk the tables + // Walk the tables. for (uint32_t i = 0; i < count; i++) { uintptr_t tablePhys = 0; @@ -439,34 +452,32 @@ static void WalkAcpi(uintptr_t rsdpPhys) { tablePhys = ((RSDT*)sdtHeader)->PointerToOtherSDT[i]; } - // Paranoid alignment check to reject firmware garbage pointers + // Paranoid alignment check to reject firmware garbage pointers. if (!tablePhys || (tablePhys & 3) != 0) continue; ACPISDTHeader* header = (ACPISDTHeader*)(tablePhys + gPhysBase); - // Ensure the table isn't corrupt before parsing + // Ensure the table isn't corrupt before parsing. if (!validate_checksum(header, header->Length)) continue; - // Parse MADT + // Parse MADT. if (memcmp(header->Signature, "APIC", 4) == 0) { ParseMadt((MADT*)header); } - // Parse FADT (signature "FACP") for PM1 control ports and DSDT pointer + // Parse FADT (signature "FACP") for PM1 control ports and DSDT pointer. else if (memcmp(header->Signature, "FACP", 4) == 0) { ParseFadt(header); } - // Parse HPET + // Parse HPET. else if (memcmp(header->Signature, "HPET", 4) == 0) { // HPET base address block is located at offset 44 - // (which is 8 bytes past the 36-byte ACPISDTHeader) + // (which is 8 bytes past the 36-byte ACPISDTHeader). gHpetPhys = *(uint64_t*)((uint8_t*)header + 44) & ~0xFFFULL; } } } -// --------------------------------------------------------------------------- // HalShutdown - ACPI S5 soft power-off. Does not return. -// --------------------------------------------------------------------------- static void HalShutdown(void) { // Silence! Stop the world! _disable(); @@ -477,7 +488,7 @@ static void HalShutdown(void) { while (true) __halt(); } - // SLP_EN (bit 13) | SLP_TYPx (bits 12:10) + // SLP_EN (bit 13) | SLP_TYPx (bits 12:10). uint16_t valA = (uint16_t)(((uint16_t)gSlpTypA << 10) | (1 << 13)); uint16_t valB = (uint16_t)(((uint16_t)gSlpTypB << 10) | (1 << 13)); @@ -488,7 +499,6 @@ static void HalShutdown(void) { while (true) __halt(); } -// --------------------------------------------------------------------------- __declspec(dllexport) KSTATUS HalGetProcessorTopology(HAL_CPU_TOPOLOGY* out) { if (!out) return STATUS_INVALID_PARAMETER; @@ -526,7 +536,6 @@ __declspec(dllexport) KSTATUS HalGetProcessorTopology(HAL_CPU_TOPOLOGY* out) { return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- __declspec(dllexport) KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) { if (gInitialised) return STATUS_ALREADY_EXISTS; gPhysBase = initParams->PhysicalWindowBase; @@ -585,8 +594,10 @@ __declspec(dllexport) KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) { return STATUS_SUCCESS; } +// Registers scheduler. __declspec(dllexport) void HalRegisterScheduler(void (*pKeSchedulerTick)(void)) { gTimerCallback = pKeSchedulerTick; } +// Returns api. __declspec(dllexport) const HAL_API* HalGetApi(void) { return &gApi; } diff --git a/code/kernel/hal/hal_mouse.c b/code/kernel/hal/hal_mouse.c index 6f60f47..6366b7f 100644 --- a/code/kernel/hal/hal_mouse.c +++ b/code/kernel/hal/hal_mouse.c @@ -1 +1,2 @@ -// hal_mouse.c - input moved out of HAL into kernel input core and ps2.sys. +// HAL mouse stub support. Mouse input is handled by the kernel input core and ps2.sys. + diff --git a/code/kernel/hal/hal_pci.c b/code/kernel/hal/hal_pci.c index fc5e34d..5cf281e 100644 --- a/code/kernel/hal/hal_pci.c +++ b/code/kernel/hal/hal_pci.c @@ -1,10 +1,12 @@ -// hal_pci.c - raw PCI configuration access via legacy Mechanism 1 port I/O +// HAL PCI configuration access. This file owns legacy mechanism-1 PCI config port I/O. + #include #include #define PCI_CONFIG_ADDR 0xCF8 #define PCI_CONFIG_DATA 0xCFC +// Creates addr. static uint32_t MakeAddr(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset) { return 0x80000000UL | ((uint32_t)bus << 16) @@ -38,6 +40,7 @@ static void PciWrite32(uint16_t segment, __outdword(PCI_CONFIG_DATA, value); } +// Implements the pci Initialize operation. void HalPciInitialize(HAL_PCI* out) { out->Read32 = PciRead32; out->Write32 = PciWrite32; diff --git a/code/kernel/hal/hal_rtc.c b/code/kernel/hal/hal_rtc.c index ec7bbef..2408939 100644 --- a/code/kernel/hal/hal_rtc.c +++ b/code/kernel/hal/hal_rtc.c @@ -1,4 +1,5 @@ -// hal_rtc.c - legacy CMOS RTC fallback clock +// HAL RTC support. This file reads the CMOS clock as the fallback wall-clock source. + #include #include #include @@ -22,19 +23,23 @@ static uint8_t gCenturyRegister; +// Implements the rtc Read operation. static uint8_t RtcRead(uint8_t reg) { __outbyte(CMOS_INDEX_PORT, (uint8_t)(reg | 0x80u)); // keep NMI masked while selecting. return __inbyte(CMOS_DATA_PORT); } +// Implements the rtc Update In Progress operation. static bool RtcUpdateInProgress(void) { return (RtcRead(RTC_REG_STATUS_A) & 0x80u) != 0; } +// Implements the rtc Bcd To Binary operation. static uint8_t RtcBcdToBinary(uint8_t value) { return (uint8_t)(((value >> 4) * 10u) + (value & 0x0Fu)); } +// Implements the rtc Read Stable operation. static bool RtcReadStable(HAL_RTC_TIME* out) { if (!out) return false; @@ -111,10 +116,12 @@ static bool RtcReadStable(HAL_RTC_TIME* out) { return true; } +// Implements the rtc Leap Year operation. static bool RtcLeapYear(uint16_t year) { return ((year % 4u) == 0u && (year % 100u) != 0u) || ((year % 400u) == 0u); } +// Implements the rtc Days In Month operation. static uint8_t RtcDaysInMonth(uint16_t year, uint8_t month) { static const uint8_t days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; if (month < 1u || month > 12u) return 0; @@ -122,6 +129,7 @@ static uint8_t RtcDaysInMonth(uint16_t year, uint8_t month) { return days[month - 1u]; } +// Implements the rtc Valid operation. static bool RtcValid(const HAL_RTC_TIME* t) { if (!t) return false; if (t->Year < 1970u || t->Year > 9999u) return false; @@ -132,6 +140,7 @@ static bool RtcValid(const HAL_RTC_TIME* t) { return true; } +// Implements the rtc Query Time operation. static KSTATUS HalRtcQueryTime(HAL_RTC_TIME* outTime) { if (!outTime) return STATUS_INVALID_PARAMETER; @@ -144,10 +153,12 @@ static KSTATUS HalRtcQueryTime(HAL_RTC_TIME* outTime) { return STATUS_SUCCESS; } +// Implements the rtc Set Century Register operation. void HalRtcSetCenturyRegister(uint8_t centuryRegister) { gCenturyRegister = centuryRegister; } +// Implements the rtc Initialize operation. void HalRtcInitialize(HAL_RTC* out) { if (!out) return; out->QueryTime = HalRtcQueryTime; diff --git a/code/kernel/hal/hal_screen.c b/code/kernel/hal/hal_screen.c index 70057b4..7808ddb 100644 --- a/code/kernel/hal/hal_screen.c +++ b/code/kernel/hal/hal_screen.c @@ -1,5 +1,5 @@ -// hal_screen.c - GOP framebuffer screen driver with embedded 8x16 font -// +// HAL screen support. This file owns GOP framebuffer drawing before a runtime display provider takes over. + // 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. @@ -22,18 +22,15 @@ static int gCursorX = 0, gCursorY = 0; #define SCREEN_DEFAULT_FG 0xCCCCCCu #define SCREEN_DEFAULT_BG 0x012456u -// --------------------------------------------------------------------------- -// 8x16 VGA font - printable ASCII only (glyph 0 = space = 0x20) -// --------------------------------------------------------------------------- +// 8x16 VGA font - printable ASCII only (glyph 0 = space = 0x20). #include // see font8x16.h -// --------------------------------------------------------------------------- -// Internals -// --------------------------------------------------------------------------- +// Internals. static inline uint32_t* ScreenBackbufferPixel(int x, int y) { return gBackbuffer ? (gBackbuffer + y * gStride + x) : (gFb + y * gStride + x); } +// Updates pixel Raw. static inline void PutPixelRaw(int x, int y, uint32_t color) { if ((unsigned)x >= (unsigned)gWidth || (unsigned)y >= (unsigned)gHeight) return; @@ -42,6 +39,7 @@ static inline void PutPixelRaw(int x, int y, uint32_t color) { gFb[y * gStride + x] = color; } +// Implements the screen Flush Rows operation. static void ScreenFlushRows(int startY, int rows) { if (!gBackbuffer || rows <= 0) return; @@ -60,9 +58,7 @@ static void ScreenFlushRows(int startY, int rows) { (size_t)rows * rowBytes); } -// --------------------------------------------------------------------------- -// HAL_SCREEN implementations -// --------------------------------------------------------------------------- +// HAL_SCREEN implementations. static void ScreenClear(uint32_t color) { for (int y = 0; y < gHeight; y++) for (int x = 0; x < gWidth; x++) @@ -77,12 +73,14 @@ static void ScreenClear(uint32_t color) { gCursorX = 0; gCursorY = 0; } +// Implements the screen Put Pixel operation. static void ScreenPutPixel(int x, int y, uint32_t color) { PutPixelRaw(x, y, color); } +// Implements the screen Blit operation. static void ScreenBlit(int x, int y, int w, int h, const uint32_t* pixels) { - // Calculate clipping bounds + // Calculate clipping bounds. int startX = (x < 0) ? 0 : x; int startY = (y < 0) ? 0 : y; int endX = (x + w > gWidth) ? gWidth : (x + w); @@ -91,16 +89,16 @@ static void ScreenBlit(int x, int y, int w, int h, const uint32_t* pixels) { int drawW = endX - startX; int drawH = endY - startY; - // If the image is entirely off-screen, do nothing + // If the image is entirely off-screen, do nothing. if (drawW <= 0 || drawH <= 0) { return; } - // Adjust the source pointer if the image was clipped on the top or left + // Adjust the source pointer if the image was clipped on the top or left. int srcOffsetX = startX - x; int srcOffsetY = startY - y; - // Calculate bytes to copy per row + // Calculate bytes to copy per row. size_t bytesPerRow = (size_t)drawW * sizeof(uint32_t); for (int row = 0; row < drawH; row++) { @@ -113,8 +111,10 @@ static void ScreenBlit(int x, int y, int w, int h, const uint32_t* pixels) { } } +// Implements the screen Get Size operation. static void ScreenGetSize(int* w, int* h) { *w = gWidth; *h = gHeight; } +// Implements the screen Get Framebuffer operation. static KSTATUS ScreenGetFramebuffer(HAL_FRAMEBUFFER_INFO* outInfo) { if (!outInfo || !gFb || gWidth <= 0 || gHeight <= 0 || gStride <= 0) return STATUS_INVALID_PARAMETER; @@ -127,6 +127,7 @@ static KSTATUS ScreenGetFramebuffer(HAL_FRAMEBUFFER_INFO* outInfo) { return STATUS_SUCCESS; } +// Implements the screen Scroll operation. static void ScreenScroll(int lines) { if (lines <= 0) return; @@ -152,6 +153,7 @@ static void ScreenScroll(int lines) { ScreenFlushRows(0, gHeight); } +// Implements the screen Put Char operation. static void ScreenPutChar(char c, int x, int y, uint32_t fg, uint32_t bg) { const uint8_t* glyph = Font8x16 + ((uint8_t)c * 16); for (int row = 0; row < 16; row++) { @@ -163,11 +165,12 @@ static void ScreenPutChar(char c, int x, int y, uint32_t fg, uint32_t bg) { } } +// Implements the screen Print Char operation. static void ScreenPrintChar(char c, uint32_t fg, uint32_t bg) { int cols = gWidth / FONT_W; int rows = gHeight / FONT_H; - // Mirror to serial + // Mirror to serial. while ((__inbyte(0x3FD) & 0x20) == 0); if (c == '\n') __outbyte(0x3F8, '\r'); __outbyte(0x3F8, c); @@ -194,11 +197,9 @@ static void ScreenPrintChar(char c, uint32_t fg, uint32_t bg) { } } -// --------------------------------------------------------------------------- // Mouse cursor โ€“ 12ร—19 monochrome arrow sprite // 0 = transparent 1 = black outline 2 = white fill // The hotspot is at (0,0) (top-left pixel = tip of the arrow). -// --------------------------------------------------------------------------- #define CURSOR_W 16 #define CURSOR_H 25 @@ -317,9 +318,7 @@ void HalScreenEraseCursor(void) { gCursorDrawY = -1; } -// --------------------------------------------------------------------------- -// Populate the HAL_SCREEN vtable -// --------------------------------------------------------------------------- +// Populate the HAL_SCREEN vtable. void HalScreenInitialize(void* (*AllocatePool)(size_t size), uintptr_t fb, int w, int h, int stride, HAL_SCREEN* out) { gFb = (uint32_t *)fb; diff --git a/code/kernel/hal/hal_timer.c b/code/kernel/hal/hal_timer.c index fbf7b3b..109f98b 100644 --- a/code/kernel/hal/hal_timer.c +++ b/code/kernel/hal/hal_timer.c @@ -1,4 +1,5 @@ -// hal_timer.c - Local APIC timer +// HAL timer support. This file owns APIC timer calibration and early tick delivery. + #include #include #include @@ -30,15 +31,19 @@ static volatile uint64_t* gHpet = NULL; static volatile uint64_t gTicks = 0; void (* volatile gTimerCallback)(void) = NULL; +// Implements the outb operation. static inline void outb(uint16_t port, uint8_t val) { __outbyte(port, val); } +// Implements the inb operation. static inline uint8_t inb(uint16_t port) { return __inbyte(port); } +// Implements the timer Isr operation. static void TimerIsr(void) { gTicks++; if (gTimerCallback) gTimerCallback(); - // EOI is sent by KeIrqDispatch after this returns + // EOI is sent by KeIrqDispatch after this returns. } +// Returns ticks. static uint64_t QueryTicks(void) { // Prefer HPET when present: it is already a monotonically increasing main // counter and avoids races between the LAPIC periodic tick and the current @@ -76,8 +81,9 @@ static uint64_t QueryTicks(void) { return (baseTicks1 * TIMER_PERIOD_MS * 1000ull) + subQuantumUs; } +// Implements the stall operation. static void Stall(uint32_t us) { - // Priority 1: Use HPET (Highest Precision) + // Priority 1: Use HPET (Highest Precision). if (gHpet && gHpetTicksPerUs > 0) { uint64_t start = gHpet[30]; // Offset 0xF0 is the Main Counter uint64_t delta = (uint64_t)us * gHpetTicksPerUs; @@ -87,7 +93,7 @@ static void Stall(uint32_t us) { return; } - // Priority 2: Use APIC Timer (High Precision, but handles wrap-around) + // Priority 2: Use APIC Timer (High Precision, but handles wrap-around). if (gApicTicksPerUs > 0) { uint32_t total_ticks = us * gApicTicksPerUs; uint32_t last_val = LAPIC_REG(LAPIC_TIMER_CUR); @@ -98,7 +104,7 @@ static void Stall(uint32_t us) { if (current < last_val) { elapsed += (last_val - current); } else if (current > last_val) { - // Handled the reset/wrap at the end of TIMER_PERIOD_MS + // Handled the reset/wrap at the end of TIMER_PERIOD_MS. uint32_t init_val = LAPIC_REG(LAPIC_TIMER_INIT); elapsed += (last_val + (init_val - current)); } @@ -108,7 +114,7 @@ static void Stall(uint32_t us) { return; } - // Priority 3: Fallback to Port 0x80 + // Priority 3: Fallback to Port 0x80. for (uint32_t i = 0; i < us; i++) { __outbyte(0x80, 0); } @@ -116,16 +122,16 @@ static void Stall(uint32_t us) { // Returns HPET ticks/second, or 0 if HPET is unavailable. static uint64_t HpetInit(uintptr_t hpetPhys) { - // HPET register block, accessed through physical window + // HPET register block, accessed through physical window. volatile uint64_t *hpet = (volatile uint64_t *)gApi.PhysToVirt(hpetPhys); // General Capabilities register (offset 0): - // Bits 63:32 = counter clock period in femtoseconds + // Bits 63:32 = counter clock period in femtoseconds. uint64_t caps = hpet[0]; uint32_t periodFs = (uint32_t)(caps >> 32); if (!periodFs) return 0; - // Enable the HPET main counter (General Configuration, offset 0x10, bit 0) + // Enable the HPET main counter (General Configuration, offset 0x10, bit 0). hpet[2] |= 1; // offset 0x10 / 8 = index 2 return (uint64_t)1e15 / periodFs; // ticks per second @@ -133,21 +139,21 @@ static uint64_t HpetInit(uintptr_t hpetPhys) { // Use PIT channel 2 one-shot to measure how many APIC ticks elapse in 10 ms, then return ticks/ms. static uint32_t CalibrateApicTimerViaPit(void) { - // Divide by 16 + // Divide by 16. LAPIC_REG(LAPIC_TIMER_DIV) = TIMER_DIV16; - // Mask, set vector - leave masked during calibration + // Mask, set vector - leave masked during calibration. LAPIC_REG(LAPIC_TIMER_LVT) = TIMER_MASKED | TIMER_VECTOR; - // Load max count + // Load max count. LAPIC_REG(LAPIC_TIMER_INIT) = 0xFFFFFFFF; - // PIT channel 2: one-shot, ~10 ms + // PIT channel 2: one-shot, ~10 ms. uint16_t pit_count = (uint16_t)(PIT_HZ / 100); // 11931 โ‰ˆ 10 ms outb(0x61, (inb(0x61) & ~0x02) | 0x01); // gate on, speaker off outb(0x43, 0xB0); // ch2, lo/hi, mode 0, binary outb(0x42, (uint8_t)(pit_count & 0xFF)); outb(0x42, (uint8_t)(pit_count >> 8)); - // Wait for OUT2 (bit 5 of port 0x61) to go high + // Wait for OUT2 (bit 5 of port 0x61) to go high. while (!(inb(0x61) & 0x20)) _mm_pause(); uint32_t elapsed = 0xFFFFFFFF - LAPIC_REG(LAPIC_TIMER_CUR); @@ -160,14 +166,14 @@ static uint32_t CalibrateApicTimerViaHpet(uintptr_t hpetPhys) { uint64_t hpetHz = HpetInit(hpetPhys); if (!hpetHz) return 0; - // Ticks in 10 ms = hpetHz / 100 + // Ticks in 10 ms = hpetHz / 100. uint64_t ticksFor10ms = hpetHz / 100; LAPIC_REG(LAPIC_TIMER_DIV) = TIMER_DIV16; LAPIC_REG(LAPIC_TIMER_LVT) = TIMER_MASKED | TIMER_VECTOR; LAPIC_REG(LAPIC_TIMER_INIT) = 0xFFFFFFFF; - // HPET main counter is at offset 0xF0, index 0xF0/8 = 30 + // HPET main counter is at offset 0xF0, index 0xF0/8 = 30. uint64_t hpetStart = hpet[30]; while ((hpet[30] - hpetStart) < ticksFor10ms) _mm_pause(); @@ -175,6 +181,7 @@ static uint32_t CalibrateApicTimerViaHpet(uintptr_t hpetPhys) { return elapsed / 10; // APIC ticks per ms } +// Implements the timer Configure Current Cpu operation. __declspec(dllexport) void HalTimerConfigureCurrentCpu(void) { if (!gLapic || !gApicTicksPerQuantum) return; LAPIC_REG(LAPIC_TIMER_DIV) = TIMER_DIV16; @@ -182,6 +189,7 @@ __declspec(dllexport) void HalTimerConfigureCurrentCpu(void) { LAPIC_REG(LAPIC_TIMER_INIT) = gApicTicksPerQuantum; } +// Implements the timer Initialize operation. KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER *out) { gLapic = (volatile uint32_t *)gApi.PhysToVirt(lapicPhys); HalDbgPrint("HAL: lapicPhys=0x%016llX, lapicVirt=0x%016llX, hpetPhys=0x%016llX\n", lapicPhys, (uintptr_t)gLapic, hpetPhys); diff --git a/code/kernel/include/kernel/display_cursor.h b/code/kernel/include/kernel/display_cursor.h index ed5de0c..7647658 100644 --- a/code/kernel/include/kernel/display_cursor.h +++ b/code/kernel/include/kernel/display_cursor.h @@ -1,5 +1,7 @@ +// Kernel display cursor declarations shared by implementation files and kernel clients. + #pragma once -// display_cursor.h - shared default software cursor image +// display_cursor.h - shared default software cursor image. #include diff --git a/code/kernel/include/kernel/hal/font8x16.h b/code/kernel/include/kernel/hal/font8x16.h index e7e332b..8bc2b3f 100644 --- a/code/kernel/include/kernel/hal/font8x16.h +++ b/code/kernel/include/kernel/hal/font8x16.h @@ -1,521 +1,523 @@ -#pragma once -// font8x16.h - embedded 8x16 CP437 bitmap font. -// Source: PC Face oldschool-vga-8x16 fontlist.js. -// Converted from: oldschool-vga-8x16-fontlist.js -// Layout: 256 glyphs * 16 scanlines. Bit 7 is the leftmost pixel. -#include - -static const uint8_t Font8x16[256 * 16] = { - // 0x00 - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x01 - 0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00, - // 0x02 - 0x00,0x00,0x7E,0xFF,0xDB,0xFF,0xFF,0xC3,0xE7,0xFF,0xFF,0x7E,0x00,0x00,0x00,0x00, - // 0x03 - 0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00, - // 0x04 - 0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00, - // 0x05 - 0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, - // 0x06 - 0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, - // 0x07 - 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x08 - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - // 0x09 - 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00, - // 0x0A - 0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF, - // 0x0B - 0x00,0x00,0x1E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, - // 0x0C - 0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00, - // 0x0D - 0x00,0x00,0x3F,0x33,0x3F,0x30,0x30,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00, - // 0x0E - 0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00, - // 0x0F - 0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00, - // 0x10 - 0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00, - // 0x11 - 0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, - // 0x12 - 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00, - // 0x13 - 0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, - // 0x14 - 0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00, - // 0x15 - 0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00, - // 0x16 - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00, - // 0x17 - 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, - // 0x18 - 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, - // 0x19 - 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00, - // 0x1A - 0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x1B - 0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x1C - 0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x1D - 0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x1E - 0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00, - // 0x1F - 0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, - // 0x20 - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x21 - 0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, - // 0x22 - 0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x23 - 0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00, - // 0x24 - 0x18,0x18,0x7C,0xC6,0xC2,0xC0,0x7C,0x06,0x06,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00, - // 0x25 - 0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00, - // 0x26 - 0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, - // 0x27 - 0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x28 - 0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00, - // 0x29 - 0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00, - // 0x2A - 0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x2B - 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x2C - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00, - // 0x2D - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x2E - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, - // 0x2F - 0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00, - // 0x30 - 0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, - // 0x31 - 0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00, - // 0x32 - 0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00, - // 0x33 - 0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x34 - 0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00, - // 0x35 - 0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x36 - 0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x37 - 0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, - // 0x38 - 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x39 - 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00, - // 0x3A - 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, - // 0x3B - 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00, - // 0x3C - 0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00, - // 0x3D - 0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x3E - 0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00, - // 0x3F - 0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, - // 0x40 - 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00, - // 0x41 - 0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, - // 0x42 - 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00, - // 0x43 - 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00, - // 0x44 - 0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00, - // 0x45 - 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, - // 0x46 - 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, - // 0x47 - 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00, - // 0x48 - 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, - // 0x49 - 0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, - // 0x4A - 0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, - // 0x4B - 0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, - // 0x4C - 0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, - // 0x4D - 0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, - // 0x4E - 0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, - // 0x4F - 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x50 - 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, - // 0x51 - 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00, - // 0x52 - 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, - // 0x53 - 0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x54 - 0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, - // 0x55 - 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x56 - 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00, - // 0x57 - 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00, - // 0x58 - 0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00, - // 0x59 - 0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, - // 0x5A - 0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00, - // 0x5B - 0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00, - // 0x5C - 0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, - // 0x5D - 0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00, - // 0x5E - 0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x5F - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00, - // 0x60 - 0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x61 - 0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, - // 0x62 - 0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00, - // 0x63 - 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x64 - 0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, - // 0x65 - 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x66 - 0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, - // 0x67 - 0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00, - // 0x68 - 0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, - // 0x69 - 0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, - // 0x6A - 0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, - // 0x6B - 0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00, - // 0x6C - 0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, - // 0x6D - 0x00,0x00,0x00,0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xD6,0xD6,0xC6,0x00,0x00,0x00,0x00, - // 0x6E - 0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, - // 0x6F - 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x70 - 0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00, - // 0x71 - 0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00, - // 0x72 - 0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, - // 0x73 - 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x74 - 0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00, - // 0x75 - 0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, - // 0x76 - 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, - // 0x77 - 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00, - // 0x78 - 0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00, - // 0x79 - 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00, - // 0x7A - 0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, - // 0x7B - 0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00, - // 0x7C - 0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, - // 0x7D - 0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, - // 0x7E - 0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0x7F - 0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00, - // 0x80 - 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00, - // 0x81 - 0x00,0x00,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, - // 0x82 - 0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x83 - 0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, - // 0x84 - 0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, - // 0x85 - 0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, - // 0x86 - 0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, - // 0x87 - 0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00, - // 0x88 - 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x89 - 0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x8A - 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x8B - 0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, - // 0x8C - 0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, - // 0x8D - 0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, - // 0x8E - 0x00,0xC6,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, - // 0x8F - 0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, - // 0x90 - 0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, - // 0x91 - 0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00, - // 0x92 - 0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00, - // 0x93 - 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x94 - 0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x95 - 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x96 - 0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, - // 0x97 - 0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, - // 0x98 - 0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00, - // 0x99 - 0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x9A - 0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0x9B - 0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00, - // 0x9C - 0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00, - // 0x9D - 0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00, - // 0x9E - 0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00, - // 0x9F - 0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00, - // 0xA0 - 0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, - // 0xA1 - 0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, - // 0xA2 - 0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0xA3 - 0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, - // 0xA4 - 0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, - // 0xA5 - 0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, - // 0xA6 - 0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xA7 - 0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xA8 - 0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, - // 0xA9 - 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00, - // 0xAA - 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, - // 0xAB - 0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00, - // 0xAC - 0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9E,0x3E,0x06,0x06,0x00,0x00, - // 0xAD - 0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00, - // 0xAE - 0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xAF - 0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xB0 - 0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, - // 0xB1 - 0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA, - // 0xB2 - 0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77, - // 0xB3 - 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - // 0xB4 - 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - // 0xB5 - 0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - // 0xB6 - 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, - // 0xB7 - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, - // 0xB8 - 0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - // 0xB9 - 0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, - // 0xBA - 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, - // 0xBB - 0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, - // 0xBC - 0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xBD - 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xBE - 0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xBF - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - // 0xC0 - 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xC1 - 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xC2 - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - // 0xC3 - 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - // 0xC4 - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xC5 - 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - // 0xC6 - 0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - // 0xC7 - 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, - // 0xC8 - 0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xC9 - 0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, - // 0xCA - 0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xCB - 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, - // 0xCC - 0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, - // 0xCD - 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xCE - 0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, - // 0xCF - 0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xD0 - 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xD1 - 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - // 0xD2 - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, - // 0xD3 - 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xD4 - 0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xD5 - 0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - // 0xD6 - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, - // 0xD7 - 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, - // 0xD8 - 0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - // 0xD9 - 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xDA - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - // 0xDB - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - // 0xDC - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, - // 0xDD - 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, - // 0xDE - 0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, - // 0xDF - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xE0 - 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00, - // 0xE1 - 0x00,0x00,0x78,0xCC,0xCC,0xCC,0xD8,0xCC,0xC6,0xC6,0xC6,0xCC,0x00,0x00,0x00,0x00, - // 0xE2 - 0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00, - // 0xE3 - 0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00, - // 0xE4 - 0x00,0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, - // 0xE5 - 0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, - // 0xE6 - 0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xC0,0x00,0x00,0x00, - // 0xE7 - 0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, - // 0xE8 - 0x00,0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, - // 0xE9 - 0x00,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, - // 0xEA - 0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00, - // 0xEB - 0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, - // 0xEC - 0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xED - 0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00, - // 0xEE - 0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00, - // 0xEF - 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, - // 0xF0 - 0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00, - // 0xF1 - 0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00, - // 0xF2 - 0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00, - // 0xF3 - 0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00, - // 0xF4 - 0x00,0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, - // 0xF5 - 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, - // 0xF6 - 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, - // 0xF7 - 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xF8 - 0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xF9 - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xFA - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xFB - 0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00, - // 0xFC - 0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xFD - 0x00,0x70,0xD8,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - // 0xFE - 0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00, - // 0xFF - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; +// Kernel font8x16 declarations shared by implementation files and kernel clients. + +#pragma once +// font8x16.h - embedded 8x16 CP437 bitmap font. +// Source: PC Face oldschool-vga-8x16 fontlist.js. +// Converted from: oldschool-vga-8x16-fontlist.js +// Layout: 256 glyphs * 16 scanlines. Bit 7 is the leftmost pixel. +#include + +static const uint8_t Font8x16[256 * 16] = { + // 0x00. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x01. + 0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00, + // 0x02. + 0x00,0x00,0x7E,0xFF,0xDB,0xFF,0xFF,0xC3,0xE7,0xFF,0xFF,0x7E,0x00,0x00,0x00,0x00, + // 0x03. + 0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00, + // 0x04. + 0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00, + // 0x05. + 0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, + // 0x06. + 0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, + // 0x07. + 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x08. + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + // 0x09. + 0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00, + // 0x0A. + 0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF, + // 0x0B. + 0x00,0x00,0x1E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, + // 0x0C. + 0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00, + // 0x0D. + 0x00,0x00,0x3F,0x33,0x3F,0x30,0x30,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00, + // 0x0E. + 0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00, + // 0x0F. + 0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00, + // 0x10. + 0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00, + // 0x11. + 0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, + // 0x12. + 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00, + // 0x13. + 0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, + // 0x14. + 0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00, + // 0x15. + 0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00, + // 0x16. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00, + // 0x17. + 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, + // 0x18. + 0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, + // 0x19. + 0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00, + // 0x1A. + 0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x1B. + 0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x1C. + 0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x1D. + 0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x1E. + 0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00, + // 0x1F. + 0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, + // 0x20. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x21. + 0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, + // 0x22. + 0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x23. + 0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00, + // 0x24. + 0x18,0x18,0x7C,0xC6,0xC2,0xC0,0x7C,0x06,0x06,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00, + // 0x25. + 0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00, + // 0x26. + 0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, + // 0x27. + 0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x28. + 0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00, + // 0x29. + 0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00, + // 0x2A. + 0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x2B. + 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x2C. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00, + // 0x2D. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x2E. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, + // 0x2F. + 0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00, + // 0x30. + 0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, + // 0x31. + 0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00, + // 0x32. + 0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00, + // 0x33. + 0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x34. + 0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00, + // 0x35. + 0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x36. + 0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x37. + 0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, + // 0x38. + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x39. + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00, + // 0x3A. + 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, + // 0x3B. + 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00, + // 0x3C. + 0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00, + // 0x3D. + 0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x3E. + 0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00, + // 0x3F. + 0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, + // 0x40. + 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00, + // 0x41. + 0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, + // 0x42. + 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00, + // 0x43. + 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00, + // 0x44. + 0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00, + // 0x45. + 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, + // 0x46. + 0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, + // 0x47. + 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00, + // 0x48. + 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, + // 0x49. + 0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, + // 0x4A. + 0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, + // 0x4B. + 0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, + // 0x4C. + 0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, + // 0x4D. + 0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, + // 0x4E. + 0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, + // 0x4F. + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x50. + 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, + // 0x51. + 0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00, + // 0x52. + 0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, + // 0x53. + 0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x54. + 0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, + // 0x55. + 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x56. + 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00, + // 0x57. + 0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00, + // 0x58. + 0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00, + // 0x59. + 0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, + // 0x5A. + 0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00, + // 0x5B. + 0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00, + // 0x5C. + 0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, + // 0x5D. + 0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00, + // 0x5E. + 0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x5F. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00, + // 0x60. + 0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x61. + 0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, + // 0x62. + 0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00, + // 0x63. + 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x64. + 0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, + // 0x65. + 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x66. + 0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, + // 0x67. + 0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00, + // 0x68. + 0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, + // 0x69. + 0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, + // 0x6A. + 0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, + // 0x6B. + 0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00, + // 0x6C. + 0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, + // 0x6D. + 0x00,0x00,0x00,0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xD6,0xD6,0xC6,0x00,0x00,0x00,0x00, + // 0x6E. + 0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, + // 0x6F. + 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x70. + 0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00, + // 0x71. + 0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00, + // 0x72. + 0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, + // 0x73. + 0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x74. + 0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00, + // 0x75. + 0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, + // 0x76. + 0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, + // 0x77. + 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00, + // 0x78. + 0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00, + // 0x79. + 0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00, + // 0x7A. + 0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, + // 0x7B. + 0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00, + // 0x7C. + 0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, + // 0x7D. + 0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, + // 0x7E. + 0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0x7F. + 0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00, + // 0x80. + 0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00, + // 0x81. + 0x00,0x00,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, + // 0x82. + 0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x83. + 0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, + // 0x84. + 0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, + // 0x85. + 0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, + // 0x86. + 0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, + // 0x87. + 0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00, + // 0x88. + 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x89. + 0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x8A. + 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x8B. + 0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, + // 0x8C. + 0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, + // 0x8D. + 0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, + // 0x8E. + 0x00,0xC6,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, + // 0x8F. + 0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, + // 0x90. + 0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, + // 0x91. + 0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00, + // 0x92. + 0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00, + // 0x93. + 0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x94. + 0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x95. + 0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x96. + 0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, + // 0x97. + 0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, + // 0x98. + 0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00, + // 0x99. + 0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x9A. + 0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0x9B. + 0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00, + // 0x9C. + 0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00, + // 0x9D. + 0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00, + // 0x9E. + 0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00, + // 0x9F. + 0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00, + // 0xA0. + 0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, + // 0xA1. + 0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, + // 0xA2. + 0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0xA3. + 0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, + // 0xA4. + 0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, + // 0xA5. + 0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, + // 0xA6. + 0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xA7. + 0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xA8. + 0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, + // 0xA9. + 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00, + // 0xAA. + 0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, + // 0xAB. + 0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00, + // 0xAC. + 0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9E,0x3E,0x06,0x06,0x00,0x00, + // 0xAD. + 0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00, + // 0xAE. + 0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xAF. + 0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xB0. + 0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, + // 0xB1. + 0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA, + // 0xB2. + 0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77, + // 0xB3. + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + // 0xB4. + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + // 0xB5. + 0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + // 0xB6. + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + // 0xB7. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + // 0xB8. + 0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + // 0xB9. + 0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + // 0xBA. + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + // 0xBB. + 0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + // 0xBC. + 0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xBD. + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xBE. + 0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xBF. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + // 0xC0. + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xC1. + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xC2. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + // 0xC3. + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + // 0xC4. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xC5. + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + // 0xC6. + 0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + // 0xC7. + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + // 0xC8. + 0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xC9. + 0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + // 0xCA. + 0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xCB. + 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + // 0xCC. + 0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + // 0xCD. + 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xCE. + 0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + // 0xCF. + 0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xD0. + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xD1. + 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + // 0xD2. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + // 0xD3. + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xD4. + 0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xD5. + 0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + // 0xD6. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + // 0xD7. + 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, + // 0xD8. + 0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + // 0xD9. + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xDA. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + // 0xDB. + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + // 0xDC. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + // 0xDD. + 0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, + // 0xDE. + 0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, + // 0xDF. + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xE0. + 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00, + // 0xE1. + 0x00,0x00,0x78,0xCC,0xCC,0xCC,0xD8,0xCC,0xC6,0xC6,0xC6,0xCC,0x00,0x00,0x00,0x00, + // 0xE2. + 0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00, + // 0xE3. + 0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00, + // 0xE4. + 0x00,0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, + // 0xE5. + 0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, + // 0xE6. + 0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xC0,0x00,0x00,0x00, + // 0xE7. + 0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, + // 0xE8. + 0x00,0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, + // 0xE9. + 0x00,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, + // 0xEA. + 0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00, + // 0xEB. + 0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, + // 0xEC. + 0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xED. + 0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00, + // 0xEE. + 0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00, + // 0xEF. + 0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, + // 0xF0. + 0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00, + // 0xF1. + 0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00, + // 0xF2. + 0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00, + // 0xF3. + 0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00, + // 0xF4. + 0x00,0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + // 0xF5. + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, + // 0xF6. + 0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, + // 0xF7. + 0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xF8. + 0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xF9. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xFA. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xFB. + 0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00, + // 0xFC. + 0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xFD. + 0x00,0x70,0xD8,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + // 0xFE. + 0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00, + // 0xFF. + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; diff --git a/code/kernel/include/kernel/hal/hal_apic.h b/code/kernel/include/kernel/hal/hal_apic.h index 38dad95..38f3f24 100644 --- a/code/kernel/include/kernel/hal/hal_apic.h +++ b/code/kernel/include/kernel/hal/hal_apic.h @@ -1,4 +1,5 @@ -// hal_apic.h +// Kernel hal apic declarations shared by implementation files and kernel clients. + #pragma once #include #include diff --git a/code/kernel/include/kernel/hal/hal_debug.h b/code/kernel/include/kernel/hal/hal_debug.h index 9eb8b7f..4166e62 100644 --- a/code/kernel/include/kernel/hal/hal_debug.h +++ b/code/kernel/include/kernel/hal/hal_debug.h @@ -1,4 +1,6 @@ -#pragma once -// hal_debug.h - HAL debug output function - +// Kernel hal debug declarations shared by implementation files and kernel clients. + +#pragma once +// hal_debug.h - HAL debug output function. + void HalDbgPrint(const char* fmt, ...); \ No newline at end of file diff --git a/code/kernel/include/kernel/io_file.h b/code/kernel/include/kernel/io_file.h index ae941cf..291803c 100644 --- a/code/kernel/include/kernel/io_file.h +++ b/code/kernel/include/kernel/io_file.h @@ -1,3 +1,5 @@ +// Kernel io file declarations shared by implementation files and kernel clients. + #pragma once // io_file.h - VFS layer // Filesystem drivers register an IO_FILESYSTEM vtable via IoRegisterFilesystem. @@ -23,9 +25,7 @@ typedef void (*IO_FS_ASYNC_COMPLETE)(void* completeContext, KSTATUS status, size_t information); -// --------------------------------------------------------------------------- // Filesystem driver vtable - filled in by a filesystem driver. -// --------------------------------------------------------------------------- typedef struct IO_FILESYSTEM { // Open a file by absolute path (e.g. "apps\\shell.exe"). // Returns an opaque per-file driver cookie in* fileCtx. @@ -80,9 +80,7 @@ typedef struct IO_FILESYSTEM { // Optional driver-private data. void* DriverCtx; - // --------------------------------------------------------------------------- - // Directory enumeration (optional - may be NULL if not supported) - // --------------------------------------------------------------------------- + // Directory enumeration (optional - may be NULL if not supported). // Open a directory iterator for 'dirPath' (relative or drive-prefixed). // Returns an opaque per-iteration driver cookie in *dirCtx. @@ -100,9 +98,7 @@ typedef struct IO_FILESYSTEM { } IO_FILESYSTEM; -// --------------------------------------------------------------------------- -// IO_STATUS_BLOCK - completion status visible to async callers -// --------------------------------------------------------------------------- +// IO_STATUS_BLOCK - completion status visible to async callers. typedef struct IO_STATUS_BLOCK { volatile KSTATUS Status; volatile size_t Information; @@ -112,9 +108,7 @@ struct EVENT; struct KAPC; typedef struct IO_ASYNC_FILE_REQUEST_OBJECT IO_ASYNC_FILE_REQUEST_OBJECT; -// --------------------------------------------------------------------------- -// FILE_OBJECT - the kernel object returned to callers -// --------------------------------------------------------------------------- +// FILE_OBJECT - the kernel object returned to callers. typedef struct FILE_OBJECT { OBJECT Header; // must be first IO_FILESYSTEM* Fs; @@ -124,9 +118,7 @@ typedef struct FILE_OBJECT { uint64_t Offset; // current position for sequential reads } FILE_OBJECT; -// --------------------------------------------------------------------------- -// DIR_OBJECT - kernel object for an open directory iterator -// --------------------------------------------------------------------------- +// DIR_OBJECT - kernel object for an open directory iterator. typedef struct DIR_OBJECT { OBJECT Header; // must be first IO_FILESYSTEM* Fs; @@ -139,18 +131,14 @@ typedef struct IO_VOLUME_PARAMS { uint64_t PartitionSize; // sectors, for bounds checking } IO_VOLUME_PARAMS; -// --------------------------------------------------------------------------- // Registration - called by fat32.sys from DriverEntry -// --------------------------------------------------------------------------- // driveIndex matches the index passed to IoRegisterDiskDevice. __declspec(dllexport) KSTATUS IoRegisterFilesystem(uint8_t driveIndex, IO_FILESYSTEM* fs, const IO_VOLUME_PARAMS *vol); __declspec(dllexport) KSTATUS IoUnregisterFilesystem(uint8_t driveIndex); __declspec(dllexport) KSTATUS IoUnregisterFilesystemsForDisk(uint8_t diskIndex); __declspec(dllexport) bool IoFilesystemPresent(uint8_t driveIndex); -// --------------------------------------------------------------------------- -// Kernel-side API -// --------------------------------------------------------------------------- +// Kernel-side API. __declspec(dllexport) KSTATUS IoOpenFile(SYS_STRING_VIEW path, FILE_OBJECT **out); __declspec(dllexport) KSTATUS IoReadFile(FILE_OBJECT* file, void* buf, size_t size, size_t* bytesRead); @@ -183,15 +171,11 @@ __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); -// --------------------------------------------------------------------------- -// Directory enumeration API -// --------------------------------------------------------------------------- +// Directory enumeration API. __declspec(dllexport) KSTATUS IoOpenDir (SYS_STRING_VIEW dirPath, DIR_OBJECT** out); __declspec(dllexport) KSTATUS IoReadDir (DIR_OBJECT* dir, KDIR_ENTRY* entryOut); __declspec(dllexport) void IoCloseDir(DIR_OBJECT* dir); -// --------------------------------------------------------------------------- -// Current Working Directory -// --------------------------------------------------------------------------- +// Current Working Directory. __declspec(dllexport) KSTATUS IoSetCwd(SYS_STRING_VIEW path); __declspec(dllexport) KSTATUS IoGetCwd(char* buf, size_t size); diff --git a/code/kernel/include/kernel/ke_apc.h b/code/kernel/include/kernel/ke_apc.h index 5fc5552..6d63f72 100644 --- a/code/kernel/include/kernel/ke_apc.h +++ b/code/kernel/include/kernel/ke_apc.h @@ -1,6 +1,8 @@ +// Kernel ke apc declarations shared by implementation files and kernel clients. + #pragma once // ke_apc.h - kernel APC infrastructure -// + // Kernel APCs are per-thread callbacks that run in the target thread's // context when that thread reaches PASSIVE_LEVEL and APC delivery is enabled. // They are the first APC layer; user APCs will build on this once trap-frame @@ -43,7 +45,7 @@ typedef struct SYS_USER_APC_FRAME_K { uint64_t SystemArgument2; } SYS_USER_APC_FRAME_K; -#define SYS_USER_APC_FRAME_MAGIC 0x3143504152455355ULL /* "USERAPC1" little-ish */ +#define SYS_USER_APC_FRAME_MAGIC 0x3143504152455355ULL // "USERAPC1" little-ish struct KUSER_APC { LIST_ENTRY Link; diff --git a/code/kernel/include/kernel/ke_cpu.h b/code/kernel/include/kernel/ke_cpu.h index 5b83bd2..a3df523 100644 --- a/code/kernel/include/kernel/ke_cpu.h +++ b/code/kernel/include/kernel/ke_cpu.h @@ -1,6 +1,8 @@ +// Kernel ke cpu declarations shared by implementation files and kernel clients. + #pragma once // ke_cpu.h - per-CPU execution state -// + // Every processor that reaches kernel-owned state has a KCPU record. The record // owns CPU-local scheduler, IRQL, GDT, and TSS state. diff --git a/code/kernel/include/kernel/ke_debug.h b/code/kernel/include/kernel/ke_debug.h index 8982908..a8d5d25 100644 --- a/code/kernel/include/kernel/ke_debug.h +++ b/code/kernel/include/kernel/ke_debug.h @@ -1,3 +1,5 @@ +// Kernel ke debug declarations shared by implementation files and kernel clients. + #ifndef KE_DEBUG_H #define KE_DEBUG_H @@ -31,15 +33,13 @@ typedef enum KE_PANIC_CODE { __declspec(dllexport) _Noreturn void KePanic(int code, const char* fmt, ...); __declspec(dllexport) int KeHandleNmiIpi(void); -// --------------------------------------------------------------------------- // Fault dispatch - called from the IDT fault stubs (ke_syscall.asm). -// + // The old scalar entry only reported RIP/error/CR2, which is not enough for // debugging null indirect calls. The frame entry snapshots user GPRs plus the // CPU exception frame, including user RSP. For a CALL through a null function // pointer, RIP is 0 and [RSP] is usually the return address after the bad call; // that is the useful caller site. -// --------------------------------------------------------------------------- typedef struct KFAULT_FRAME { uint64_t Magic; uint64_t Vector; diff --git a/code/kernel/include/kernel/ke_display.h b/code/kernel/include/kernel/ke_display.h index 418fee9..e226715 100644 --- a/code/kernel/include/kernel/ke_display.h +++ b/code/kernel/include/kernel/ke_display.h @@ -1,3 +1,5 @@ +// Kernel ke display declarations shared by implementation files and kernel clients. + #pragma once #include #include diff --git a/code/kernel/include/kernel/ke_dpc.h b/code/kernel/include/kernel/ke_dpc.h index a1530eb..76ccf3c 100644 --- a/code/kernel/include/kernel/ke_dpc.h +++ b/code/kernel/include/kernel/ke_dpc.h @@ -1,6 +1,8 @@ +// Kernel ke dpc declarations shared by implementation files and kernel clients. + #pragma once // ke_dpc.h - deferred procedure calls -// + // DPCs are the kernel's bottom-half mechanism. Hardware ISRs can queue a DPC // after acknowledging/capturing device state; the DPC then runs later at // DISPATCH_LEVEL from the common interrupt-exit path. DPC routines must not diff --git a/code/kernel/include/kernel/ke_event.h b/code/kernel/include/kernel/ke_event.h index ac826fc..0573d36 100644 --- a/code/kernel/include/kernel/ke_event.h +++ b/code/kernel/include/kernel/ke_event.h @@ -1,5 +1,7 @@ +// Kernel ke event declarations shared by implementation files and kernel clients. + #pragma once -// ke_event.h - auto-reset and manual-reset events +// ke_event.h - auto-reset and manual-reset events. #include #include #include diff --git a/code/kernel/include/kernel/ke_idt.h b/code/kernel/include/kernel/ke_idt.h index 30ad0f7..f26c869 100644 --- a/code/kernel/include/kernel/ke_idt.h +++ b/code/kernel/include/kernel/ke_idt.h @@ -1,5 +1,7 @@ +// Kernel ke idt declarations shared by implementation files and kernel clients. + #pragma once -// ke_idt.h - IDT, GDT, and TSS setup +// ke_idt.h - IDT, GDT, and TSS setup. #include // 64-bit TSS - minimal; we only care about RSP0. diff --git a/code/kernel/include/kernel/ke_input.h b/code/kernel/include/kernel/ke_input.h index d2b8358..f695390 100644 --- a/code/kernel/include/kernel/ke_input.h +++ b/code/kernel/include/kernel/ke_input.h @@ -1,3 +1,5 @@ +// Kernel ke input declarations shared by implementation files and kernel clients. + #pragma once #include #include diff --git a/code/kernel/include/kernel/ke_irp.h b/code/kernel/include/kernel/ke_irp.h index c59510c..53999a6 100644 --- a/code/kernel/include/kernel/ke_irp.h +++ b/code/kernel/include/kernel/ke_irp.h @@ -1,6 +1,8 @@ +// Kernel ke irp declarations shared by implementation files and kernel clients. + #pragma once // ke_irp.h - I/O Request Packet and remove-lock primitives -// + // IRPs are stack-based. A caller builds an IRP with one or more // IO_STACK_LOCATION entries, submits it to a DEVICE_OBJECT, and the I/O // manager/driver stack advances CurrentLocation as the IRP is forwarded. @@ -18,9 +20,7 @@ struct SEMAPHORE; struct KAPC; typedef struct DEVICE_OBJECT DEVICE_OBJECT; -// ------------------------------------------------------------------------- -// IRP major/minor functions -// ------------------------------------------------------------------------- +// IRP major/minor functions. typedef enum IO_MAJOR_FUNCTION { IRP_MJ_CREATE = 0, @@ -50,17 +50,13 @@ typedef enum IO_DEVICE_RELATION_TYPE { IoRemovalRelations = 1, } IO_DEVICE_RELATION_TYPE; -// ------------------------------------------------------------------------- -// IRP flags -// ------------------------------------------------------------------------- +// IRP flags. #define IRP_FLAG_PRIORITY (1u << 0) // insert at head of a driver queue #define IRP_FLAG_CANCELLED (1u << 1) #define IRP_FLAG_COMPLETED (1u << 2) -// ------------------------------------------------------------------------- -// IRP stack parameters -// ------------------------------------------------------------------------- +// IRP stack parameters. typedef struct IO_STACK_LOCATION { IO_MAJOR_FUNCTION MajorFunction; @@ -91,18 +87,14 @@ typedef struct IO_STACK_LOCATION { } Parameters; } IO_STACK_LOCATION; -// ------------------------------------------------------------------------- -// Forward declaration / callbacks -// ------------------------------------------------------------------------- +// Forward declaration / callbacks. typedef struct IRP IRP; typedef void (*IRP_COMPLETION_FN)(IRP* irp, void* ctx); typedef void (*IRP_CANCEL_ROUTINE)(DEVICE_OBJECT* device, IRP* irp); -// ------------------------------------------------------------------------- -// I/O Request Packet -// ------------------------------------------------------------------------- +// I/O Request Packet. typedef struct IRP { LIST_ENTRY Link; @@ -135,9 +127,7 @@ typedef struct IRP { IO_STACK_LOCATION Stack[1]; } IRP; -// ------------------------------------------------------------------------- -// Remove lock -// ------------------------------------------------------------------------- +// Remove lock. typedef struct IO_REMOVE_LOCK { SPINLOCK Lock; @@ -152,9 +142,7 @@ __declspec(dllexport) KSTATUS IoAcquireRemoveLock(IO_REMOVE_LOCK* lock, IRP* irp __declspec(dllexport) void IoReleaseRemoveLock(IO_REMOVE_LOCK* lock, IRP* irp); __declspec(dllexport) void IoReleaseRemoveLockAndWait(IO_REMOVE_LOCK* lock, IRP* removeIrp); -// ------------------------------------------------------------------------- -// IRP_QUEUE (per-device, driver-internal) -// ------------------------------------------------------------------------- +// IRP_QUEUE (per-device, driver-internal). typedef struct IRP_QUEUE { SPINLOCK Lock; @@ -172,9 +160,7 @@ __declspec(dllexport) void IrpQueueCancelAllEx(IRP_QUEUE* q, void* context); __declspec(dllexport) void IrpQueueCancelAll(IRP_QUEUE* q, KSTATUS status); -// ------------------------------------------------------------------------- -// IRP allocation / stack helpers -// ------------------------------------------------------------------------- +// IRP allocation / stack helpers. __declspec(dllexport) KSTATUS IoAllocateIrp(uint8_t stackCount, IRP** outIrp); __declspec(dllexport) void IoFreeIrp(IRP* irp); diff --git a/code/kernel/include/kernel/ke_irq.h b/code/kernel/include/kernel/ke_irq.h index 77709e2..f4c2560 100644 --- a/code/kernel/include/kernel/ke_irq.h +++ b/code/kernel/include/kernel/ke_irq.h @@ -1,3 +1,5 @@ +// Kernel ke irq declarations shared by implementation files and kernel clients. + #pragma once #include #include diff --git a/code/kernel/include/kernel/ke_irql.h b/code/kernel/include/kernel/ke_irql.h index fcd4ec9..cf817d4 100644 --- a/code/kernel/include/kernel/ke_irql.h +++ b/code/kernel/include/kernel/ke_irql.h @@ -1,6 +1,8 @@ +// Kernel ke irql declarations shared by implementation files and kernel clients. + #pragma once // ke_irql.h - software IRQL skeleton -// + // This is intentionally small for the first IRQL/APC bring-up step. It does // not yet program interrupt hardware or replace the spinlock interrupt-disable // path. It gives the kernel one authoritative execution-level state plus diff --git a/code/kernel/include/kernel/ke_list.h b/code/kernel/include/kernel/ke_list.h index 02f8324..d0fc80d 100644 --- a/code/kernel/include/kernel/ke_list.h +++ b/code/kernel/include/kernel/ke_list.h @@ -1,44 +1,49 @@ -#pragma once -// ke_list.h - intrusive doubly-linked list -// Used throughout the kernel for run queues, wait lists, thread lists, etc. -#include - -typedef struct LIST_ENTRY { - struct LIST_ENTRY* Fwd; - struct LIST_ENTRY* Bwd; -} LIST_ENTRY; - -#define LIST_INIT(head) ((head)->Fwd = (head)->Bwd = (head)) -#define LIST_IS_EMPTY(head) ((head)->Fwd == (head)) - -// Recover the containing struct pointer from an embedded LIST_ENTRY. -#define CONTAINING_RECORD(ptr, type, member) \ - ((type *)((char *)(ptr) - offsetof(type, member))) - -static inline void ListInsertTail(LIST_ENTRY* head, LIST_ENTRY* node) { - node->Bwd = head->Bwd; - node->Fwd = head; - head->Bwd->Fwd = node; - head->Bwd = node; -} - -static inline void ListInsertHead(LIST_ENTRY* head, LIST_ENTRY* node) { - node->Fwd = head->Fwd; - node->Bwd = head; - head->Fwd->Bwd = node; - head->Fwd = node; -} - -static inline void ListRemove(LIST_ENTRY* node) { - node->Bwd->Fwd = node->Fwd; - node->Fwd->Bwd = node->Bwd; - node->Fwd = node->Bwd = node; /* self-loop: poison against double-remove */ -} - -// Pop the first entry off the list, or NULL if empty. -static inline LIST_ENTRY* ListPopHead(LIST_ENTRY* head) { - if (LIST_IS_EMPTY(head)) return (LIST_ENTRY *)0; - LIST_ENTRY* node = head->Fwd; - ListRemove(node); - return node; -} +// Kernel ke list declarations shared by implementation files and kernel clients. + +#pragma once +// ke_list.h - intrusive doubly-linked list +// Used throughout the kernel for run queues, wait lists, thread lists, etc. +#include + +typedef struct LIST_ENTRY { + struct LIST_ENTRY* Fwd; + struct LIST_ENTRY* Bwd; +} LIST_ENTRY; + +#define LIST_INIT(head) ((head)->Fwd = (head)->Bwd = (head)) +#define LIST_IS_EMPTY(head) ((head)->Fwd == (head)) + +// Recover the containing struct pointer from an embedded LIST_ENTRY. +#define CONTAINING_RECORD(ptr, type, member) \ + ((type *)((char *)(ptr) - offsetof(type, member))) + +// Implements the list Insert Tail operation. +static inline void ListInsertTail(LIST_ENTRY* head, LIST_ENTRY* node) { + node->Bwd = head->Bwd; + node->Fwd = head; + head->Bwd->Fwd = node; + head->Bwd = node; +} + +// Implements the list Insert Head operation. +static inline void ListInsertHead(LIST_ENTRY* head, LIST_ENTRY* node) { + node->Fwd = head->Fwd; + node->Bwd = head; + head->Fwd->Bwd = node; + head->Fwd = node; +} + +// Implements the list Remove operation. +static inline void ListRemove(LIST_ENTRY* node) { + node->Bwd->Fwd = node->Fwd; + node->Fwd->Bwd = node->Bwd; + node->Fwd = node->Bwd = node; // self-loop: poison against double-remove +} + +// Pop the first entry off the list, or NULL if empty. +static inline LIST_ENTRY* ListPopHead(LIST_ENTRY* head) { + if (LIST_IS_EMPTY(head)) return (LIST_ENTRY *)0; + LIST_ENTRY* node = head->Fwd; + ListRemove(node); + return node; +} diff --git a/code/kernel/include/kernel/ke_mutex.h b/code/kernel/include/kernel/ke_mutex.h index 2fb8193..7db2b60 100644 --- a/code/kernel/include/kernel/ke_mutex.h +++ b/code/kernel/include/kernel/ke_mutex.h @@ -1,5 +1,7 @@ +// Kernel ke mutex declarations shared by implementation files and kernel clients. + #pragma once -// ke_mutex.h - binary ownership mutex +// ke_mutex.h - binary ownership mutex. #include #include #include @@ -8,7 +10,7 @@ typedef struct MUTEX { OBJECT Header; SPINLOCK Lock; - struct THREAD* Owner; /* NULL if unowned */ + struct THREAD* Owner; // NULL if unowned LIST_ENTRY WaitList; } MUTEX; diff --git a/code/kernel/include/kernel/ke_process.h b/code/kernel/include/kernel/ke_process.h index 7711f8f..759201d 100644 --- a/code/kernel/include/kernel/ke_process.h +++ b/code/kernel/include/kernel/ke_process.h @@ -1,3 +1,5 @@ +// Kernel ke process declarations shared by implementation files and kernel clients. + #pragma once // ke_process.h - process model // A process owns a handle table and a list of threads. @@ -37,23 +39,23 @@ typedef struct PROCESS_MODULE { } PROCESS_MODULE; typedef struct PROCESS { - OBJECT Header; /* must be first */ + OBJECT Header; // must be first uint32_t ProcessId; - char Name[PROCESS_NAME_MAX]; /* UTF-8 */ + char Name[PROCESS_NAME_MAX]; // UTF-8 char CurrentDirectory[PROCESS_CWD_MAX]; size_t CurrentDirectoryLength; uint8_t CurrentDrive; SPINLOCK CwdLock; - /* Thread list. */ - LIST_ENTRY ThreadList; /* links THREAD.ProcessLink */ + // Thread list. + LIST_ENTRY ThreadList; // links THREAD.ProcessLink uint32_t ThreadCount; - /* Handle table. - Index 0 is always empty (the invalid handle). - Each live entry holds one object reference plus rights metadata. */ + // Handle table. + // Index 0 is always empty (the invalid handle). + // Each live entry holds one object reference plus rights metadata. HANDLE_ENTRY Handles[HANDLE_TABLE_SIZE]; SPINLOCK HandleLock; @@ -61,11 +63,11 @@ typedef struct PROCESS { volatile long Terminating; volatile long Exited; - /* Main executable image. Used for cleanup. */ + // Main executable image. Used for cleanup. uintptr_t ImageBase; size_t ImageSize; - /* User-mode process environment. The initial thread sees this through GS->TEB->PEB. */ + // User-mode process environment. The initial thread sees this through GS->TEB->PEB. uintptr_t UserPebBase; size_t UserPebSize; uintptr_t UserImagePathBase; @@ -75,21 +77,21 @@ typedef struct PROCESS { uintptr_t UserCwdBase; size_t UserCwdSize; - /* Per-process user virtual regions. The actual VA arena is global because - NT-Lite currently uses one shared address space; this list tracks - ownership so leaked user mappings can be reclaimed on process exit. */ + // Per-process user virtual regions. The actual VA arena is global because + // NT-Lite currently uses one shared address space; this list tracks + // ownership so leaked user mappings can be reclaimed on process exit. LIST_ENTRY UserRegions; SPINLOCK UserRegionLock; - /* Per-process loaded modules (user processes only). */ + // Per-process loaded modules (user processes only). PROCESS_MODULE Modules[PROCESS_MODULE_MAX]; uint32_t ModuleCount; - /* Signaled (manual-reset) when the process exits. - Waiters block on this via KeWaitForEvent. */ + // Signaled (manual-reset) when the process exits. + // Waiters block on this via KeWaitForEvent. EVENT* ExitEvent; - LIST_ENTRY GlobalLink; /* node in the global process list */ + LIST_ENTRY GlobalLink; // node in the global process list } PROCESS; KSTATUS KeCreateProcess(const char* name, PROCESS **out); @@ -103,7 +105,7 @@ KSTATUS KeTerminateProcess(PROCESS* process, int exitCode); int KeIsProcessTerminating(PROCESS* process); KSTATUS KeGetProcessExitCode(PROCESS* process, int* exitCodeOut); -/* Handle table operations. */ +// Handle table operations. KSTATUS KeAllocateHandle(PROCESS* process, OBJECT* object, uint32_t* handleOut); KSTATUS KeAllocateHandleWithRights(PROCESS* process, OBJECT* object, uint32_t rights, uint32_t* handleOut); void KeCloseHandle(PROCESS* process, uint32_t handle); @@ -111,13 +113,13 @@ OBJECT* KeLookupHandle(PROCESS* process, uint32_t handle); OBJECT* KeLookupHandleWithRights(PROCESS* process, uint32_t handle, uint32_t requiredRights); uint32_t KeGetHandleRights(PROCESS* process, uint32_t handle); -/* Return the global process list head (kernel-internal). */ +// Return the global process list head (kernel-internal). LIST_ENTRY* KeGetProcessList(void); PROCESS* KeGetCurrentProcess(void); PROCESS* KeGetSystemProcess(void); struct SYS_PROCESS_INFO; -/* Copy a snapshot of rich process information into caller-provided storage. */ +// Copy a snapshot of rich process information into caller-provided storage. size_t KeCopyProcessInfo(struct SYS_PROCESS_INFO* infoOut, size_t maxCount); -/* Find a live process by its ProcessId. Bumps refcount; caller must ObDereferenceObject. */ +// Find a live process by its ProcessId. Bumps refcount; caller must ObDereferenceObject. PROCESS* KeGetProcessById(uint32_t pid); diff --git a/code/kernel/include/kernel/ke_queue.h b/code/kernel/include/kernel/ke_queue.h index 9115394..89065f7 100644 --- a/code/kernel/include/kernel/ke_queue.h +++ b/code/kernel/include/kernel/ke_queue.h @@ -1,3 +1,5 @@ +// Kernel ke queue declarations shared by implementation files and kernel clients. + #pragma once // ke_queue.h - fixed-depth message queue // Processes share an address space, so a pointer in Param[] is valid @@ -9,14 +11,14 @@ #include #include -#define QUEUE_MESSAGE_SIZE 64 /* bytes, fixed */ +#define QUEUE_MESSAGE_SIZE 64 // bytes, fixed #define QUEUE_DEPTH 256 typedef struct QUEUE_MESSAGE { uint32_t Type; uint32_t Flags; - uint64_t Param[6]; /* 48 bytes of payload */ -} QUEUE_MESSAGE; /* total: 64 bytes */ + uint64_t Param[6]; // 48 bytes of payload +} QUEUE_MESSAGE; // total: 64 bytes typedef struct QUEUE { OBJECT Header; diff --git a/code/kernel/include/kernel/ke_sched.h b/code/kernel/include/kernel/ke_sched.h index dc94d95..bd27cca 100644 --- a/code/kernel/include/kernel/ke_sched.h +++ b/code/kernel/include/kernel/ke_sched.h @@ -1,3 +1,5 @@ +// Kernel ke sched declarations shared by implementation files and kernel clients. + #pragma once // ke_sched.h - Multi-Level Feedback Queue scheduler // Three run queues (Low / Normal / High). IRQ 0 drives KeSchedulerTick. diff --git a/code/kernel/include/kernel/ke_selftest.h b/code/kernel/include/kernel/ke_selftest.h index 83ac960..530ee41 100644 --- a/code/kernel/include/kernel/ke_selftest.h +++ b/code/kernel/include/kernel/ke_selftest.h @@ -1,3 +1,5 @@ +// Kernel ke selftest declarations shared by implementation files and kernel clients. + #pragma once // ke_selftest.h - kernel bring-up and regression self-tests. diff --git a/code/kernel/include/kernel/ke_semaphore.h b/code/kernel/include/kernel/ke_semaphore.h index c987d0e..36b302b 100644 --- a/code/kernel/include/kernel/ke_semaphore.h +++ b/code/kernel/include/kernel/ke_semaphore.h @@ -1,5 +1,7 @@ +// Kernel ke semaphore declarations shared by implementation files and kernel clients. + #pragma once -// ke_semaphore.h - counting semaphore +// ke_semaphore.h - counting semaphore. #include #include #include diff --git a/code/kernel/include/kernel/ke_settings.h b/code/kernel/include/kernel/ke_settings.h index 573a4cc..8f4cbad 100644 --- a/code/kernel/include/kernel/ke_settings.h +++ b/code/kernel/include/kernel/ke_settings.h @@ -1,3 +1,5 @@ +// Kernel ke settings declarations shared by implementation files and kernel clients. + #pragma once #include diff --git a/code/kernel/include/kernel/ke_smp.h b/code/kernel/include/kernel/ke_smp.h index 993fe2a..81faac0 100644 --- a/code/kernel/include/kernel/ke_smp.h +++ b/code/kernel/include/kernel/ke_smp.h @@ -1,3 +1,5 @@ +// Kernel ke smp declarations shared by implementation files and kernel clients. + #pragma once #include #include diff --git a/code/kernel/include/kernel/ke_spinlock.h b/code/kernel/include/kernel/ke_spinlock.h index 653ce21..9129ade 100644 --- a/code/kernel/include/kernel/ke_spinlock.h +++ b/code/kernel/include/kernel/ke_spinlock.h @@ -1,12 +1,14 @@ +// Kernel ke spinlock declarations shared by implementation files and kernel clients. + #pragma once // ke_spinlock.h - spinlock for short, non-sleeping critical sections -// + // Step 3 IRQL bring-up: // * Acquiring a spinlock disables maskable interrupts and raises the software // IRQL to at least DISPATCH_LEVEL. // * Releasing restores both the previous IRQL and the previous RFLAGS.IF // state through the returned cookie. -// + // The public type remains uintptr_t so existing callers do not need to change. // Never hold a spinlock across a wait/blocking operation. #include @@ -23,15 +25,18 @@ typedef struct SPINLOCK { #define KI_SPINLOCK_IRQL_SHIFT ((unsigned)(sizeof(uintptr_t) * 8u - 8u)) #define KI_SPINLOCK_FLAGS_MASK (~(((uintptr_t)0xFFu) << KI_SPINLOCK_IRQL_SHIFT)) +// Implements the pack Spinlock Cookie operation. static __forceinline uintptr_t KiPackSpinlockCookie(uintptr_t flags, KIRQL oldIrql) { return (flags & KI_SPINLOCK_FLAGS_MASK) | (((uintptr_t)oldIrql) << KI_SPINLOCK_IRQL_SHIFT); } +// Implements the spinlock Cookie Flags operation. static __forceinline uintptr_t KiSpinlockCookieFlags(uintptr_t cookie) { return cookie & KI_SPINLOCK_FLAGS_MASK; } +// Implements the spinlock Cookie Irql operation. static __forceinline KIRQL KiSpinlockCookieIrql(uintptr_t cookie) { return (KIRQL)(cookie >> KI_SPINLOCK_IRQL_SHIFT); } @@ -62,6 +67,7 @@ static __forceinline void KeReleaseSpinlock(SPINLOCK* sl, uintptr_t cookie) { __writeeflags(flags); } +// Implements the try Acquire Spinlock operation. static __forceinline int KeTryAcquireSpinlock(SPINLOCK* sl, uintptr_t* outCookie) { uintptr_t flags = __readeflags(); _disable(); @@ -85,6 +91,7 @@ static __forceinline uintptr_t KeAcquireSpinlockRaiseToDpc(SPINLOCK* sl) { return KeAcquireSpinlock(sl); } +// Releases spinlock From Dpc. static __forceinline void KeReleaseSpinlockFromDpc(SPINLOCK* sl, uintptr_t cookie) { KeReleaseSpinlock(sl, cookie); } diff --git a/code/kernel/include/kernel/ke_syscall.h b/code/kernel/include/kernel/ke_syscall.h index 3b62f65..9f675df 100644 --- a/code/kernel/include/kernel/ke_syscall.h +++ b/code/kernel/include/kernel/ke_syscall.h @@ -1,11 +1,13 @@ +// Kernel ke syscall declarations shared by implementation files and kernel clients. + #pragma once #include #include -// Set the HAL API pointer for syscalls +// Set the HAL API pointer for syscalls. void KeSyscallInit(const HAL_API* hal); -// Syscall dispatcher, called from assembly entry point +// Syscall dispatcher, called from assembly entry point. uint64_t KeSyscallDispatch(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5); diff --git a/code/kernel/include/kernel/ke_thread.h b/code/kernel/include/kernel/ke_thread.h index 2a14837..5acde67 100644 --- a/code/kernel/include/kernel/ke_thread.h +++ b/code/kernel/include/kernel/ke_thread.h @@ -1,3 +1,5 @@ +// Kernel ke thread declarations shared by implementation files and kernel clients. + #pragma once // ke_thread.h - thread model // A THREAD is the unit of scheduling. Every thread belongs to exactly one process. @@ -9,8 +11,8 @@ #include #include -#define KSTACK_SIZE (64 * 1024) /* 64 KB kernel stack */ -#define USTACK_SIZE (512 * 1024) /* 512 KB user stack */ +#define KSTACK_SIZE (64 * 1024) // 64 KB kernel stack +#define USTACK_SIZE (512 * 1024) // 512 KB user stack typedef enum THREAD_PRIORITY { PriorityLow = 0, @@ -31,11 +33,11 @@ typedef enum THREAD_STATE { typedef struct KCONTEXT { uint64_t R15, R14, R13, R12; uint64_t Rbp, Rbx; - uint64_t Rip; /* return address back into KeSwitchContext */ + uint64_t Rip; // return address back into KeSwitchContext } KCONTEXT; typedef struct THREAD { - OBJECT Header; /* must be first */ + OBJECT Header; // must be first uint32_t ThreadId; THREAD_STATE State; @@ -46,8 +48,8 @@ typedef struct THREAD { uint32_t QuantaConsumed; PROCESS* Owner; - LIST_ENTRY ProcessLink; /* node in Owner->ThreadList */ - LIST_ENTRY SchedulerLink; /* node in run queue or wait list */ + LIST_ENTRY ProcessLink; // node in Owner->ThreadList + LIST_ENTRY SchedulerLink; // node in run queue or wait list // Kernel stack - never PAGE_USER, pointed to by TssRsp0. void* KernelStackBase; @@ -152,14 +154,14 @@ __declspec(dllexport) KSTATUS KeCreateKernelThreadWithAffinity(uintptr_t fn, uin __declspec(dllexport) void KeExitThread(THREAD* thread, int code); // Block / unblock primitives used by sync objects. -// + // Correct wait pattern: // object lock held // KePrepareBlockThread(self, object, alertable); // insert self into object's wait list // release object lock // KeCommitBlockThread(self, alertable); -// + // The split form prevents the classic lost wakeup where an ISR/DPC signals // the object after the waiter is queued but before the waiter marks itself // waiting. Alertable waits are explicit at every call site. diff --git a/code/kernel/include/kernel/ke_time.h b/code/kernel/include/kernel/ke_time.h index 7bc8db9..813db9a 100644 --- a/code/kernel/include/kernel/ke_time.h +++ b/code/kernel/include/kernel/ke_time.h @@ -1,3 +1,5 @@ +// Kernel ke time declarations shared by implementation files and kernel clients. + #pragma once #include #include diff --git a/code/kernel/include/kernel/ke_trap.h b/code/kernel/include/kernel/ke_trap.h index 8d6eae6..312d6e1 100644 --- a/code/kernel/include/kernel/ke_trap.h +++ b/code/kernel/include/kernel/ke_trap.h @@ -1,6 +1,8 @@ +// Kernel ke trap declarations shared by implementation files and kernel clients. + #pragma once // ke_trap.h - trap-frame metadata for syscall/interrupt return paths -// + // KTRAP_FRAME is built by ke_syscall.asm on kernel entry. It is intentionally // an editable return frame: user APC delivery can rewrite Rip/Rsp in the frame, // and KiExitTrapFrame commits those values back to the hardware IRET slots. diff --git a/code/kernel/include/kernel/ke_userenv.h b/code/kernel/include/kernel/ke_userenv.h index a5cd02e..16dc516 100644 --- a/code/kernel/include/kernel/ke_userenv.h +++ b/code/kernel/include/kernel/ke_userenv.h @@ -1,3 +1,5 @@ +// Kernel ke userenv declarations shared by implementation files and kernel clients. + #pragma once // ke_userenv.h - kernel view of the user-mode process/thread environment. // This is this OS' ABI, not a Windows compatibility structure. @@ -6,8 +8,8 @@ #include #include -#define SYS_PEB_MAGIC 0x30424550u /* "PEB0" */ -#define SYS_TEB_MAGIC 0x30424554u /* "TEB0" */ +#define SYS_PEB_MAGIC 0x30424550u // "PEB0" +#define SYS_TEB_MAGIC 0x30424554u // "TEB0" #define SYS_ENV_VERSION 1u #define SYS_CWD_MAX 520u diff --git a/code/kernel/include/kernel/ke_util.h b/code/kernel/include/kernel/ke_util.h index ce4aea4..8b20bf4 100644 --- a/code/kernel/include/kernel/ke_util.h +++ b/code/kernel/include/kernel/ke_util.h @@ -1,23 +1,22 @@ -// ke_util.h - kernel utility macros (dynamic arrays, etc.) +// Kernel ke util declarations shared by implementation files and kernel clients. + #pragma once #include #include -// --------------------------------------------------------------------------- // Dynamic array (stretchy-buffer style) -// + // T *buf = NULL; // arr_push(buf, value); // appends; grows automatically // arr_push_front(buf, value); // prepends // arr_remove(buf, i); // removes index i, shifts tail left // size_t n = arr_len(buf); // element count (0 if buf == NULL) // arr_free(buf); // frees header + data -// + // The allocation layout is: // [ Header (count, capacity) ][ T[0] ][ T[1] ] ... // buf always points at T[0]; the Header lives one slot before it. -// --------------------------------------------------------------------------- typedef struct { size_t count; diff --git a/code/kernel/include/kernel/ldr_image.h b/code/kernel/include/kernel/ldr_image.h index f72d6b3..e2b816d 100644 --- a/code/kernel/include/kernel/ldr_image.h +++ b/code/kernel/include/kernel/ldr_image.h @@ -1,3 +1,5 @@ +// Kernel ldr image declarations shared by implementation files and kernel clients. + #pragma once // ldr_image.h - minimal PE32+ loader // Loads an already-mapped PE image and resolves its imports. diff --git a/code/kernel/include/kernel/mm_phys.h b/code/kernel/include/kernel/mm_phys.h index 16bb887..998a843 100644 --- a/code/kernel/include/kernel/mm_phys.h +++ b/code/kernel/include/kernel/mm_phys.h @@ -1,3 +1,5 @@ +// Kernel mm phys declarations shared by implementation files and kernel clients. + #pragma once // mm_phys.h - physical memory manager (PMM) // Bitmap allocator over 4 KB frames, seeded from MEMORY_MAP. diff --git a/code/kernel/include/kernel/mm_virt.h b/code/kernel/include/kernel/mm_virt.h index ad5f332..389d934 100644 --- a/code/kernel/include/kernel/mm_virt.h +++ b/code/kernel/include/kernel/mm_virt.h @@ -1,3 +1,5 @@ +// Kernel mm virt declarations shared by implementation files and kernel clients. + #pragma once // mm_virt.h - virtual memory manager (VMM) // Manages the single shared PML4, kernel pool, and page-granular user VM regions. @@ -30,9 +32,7 @@ typedef enum USER_REGION_TYPE { #define USER_REGION_GUARD_HIGH 0x00000002u #define USER_REGION_ZERO 0x00000004u -// --------------------------------------------------------------------------- -// Page flags (x86-64 PTE bits) -// --------------------------------------------------------------------------- +// Page flags (x86-64 PTE bits). #define PAGE_PRESENT (1ULL << 0) #define PAGE_WRITE (1ULL << 1) #define PAGE_USER (1ULL << 2) @@ -40,9 +40,7 @@ typedef enum USER_REGION_TYPE { #define PAGE_NOCACHE (1ULL << 4) #define PAGE_NX (1ULL << 63) -// --------------------------------------------------------------------------- -// Virtual address space constants -// --------------------------------------------------------------------------- +// Virtual address space constants. #define USER_BASE 0x0000000000001000ULL #define USER_LIMIT 0x00007FFFFFFFF000ULL @@ -51,9 +49,7 @@ typedef enum USER_REGION_TYPE { #define POOL_BASE 0xFFFFC00000000000ULL #define POOL_LIMIT 0xFFFFE00000000000ULL -// --------------------------------------------------------------------------- // Initialisation -// --------------------------------------------------------------------------- // Called by KernelMain after MmInitializePhysical. // bootPml4Phys: the PML4 set up by the bootloader. // poolSize: initial reservation for kernel pool (bytes, page-aligned). @@ -62,9 +58,7 @@ void MmInitializeVirtual(PHYSICAL_ADDRESS bootPml4Phys, size_t poolSize); // Install the shared PML4 into CR3. Called once at the end of KernelMain init. void MmActivate(void); -// --------------------------------------------------------------------------- -// Page mapping -// --------------------------------------------------------------------------- +// Page mapping. __declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags, MM_MAP_MODE mode); __declspec(dllexport) KSTATUS MmUnmapPage(uintptr_t virt); @@ -86,9 +80,7 @@ void MmFlushTlbForKernelMapping(uintptr_t virt); int MmHandleTlbShootdownNmi(void); -// --------------------------------------------------------------------------- // User/kernel copy boundary helpers -// --------------------------------------------------------------------------- // MmQueryPage returns the physical address and effective PAGE_* bits for a // mapped virtual address. The reported PAGE_USER/PAGE_WRITE bits account for // every page-table level, not just the leaf entry. @@ -105,20 +97,16 @@ __declspec(dllexport) KSTATUS MmProbeUserWrite(void* ptr, size_t size); __declspec(dllexport) KSTATUS CopyFromUser(void* kernelDst, const void* userSrc, size_t size); __declspec(dllexport) KSTATUS CopyToUser(void* userDst, const void* kernelSrc, size_t size); -// --------------------------------------------------------------------------- // Kernel pool - ring 0 only, never PAGE_USER. // Best-fit free-list allocator, thread-safe via spinlock. -// --------------------------------------------------------------------------- __declspec(dllexport) void* MmAllocatePool(size_t size); __declspec(dllexport) void MmFreePool(void* ptr); __declspec(dllexport) void* MmReallocatePool(void* ptr, size_t newSize); -// --------------------------------------------------------------------------- // User virtual regions. // The kernel has one shared user VA arena, but every user mapping is owned by // a PROCESS so process teardown can reclaim leaked memory. Guard pages are // reserved VA with no present PTE. -// --------------------------------------------------------------------------- KSTATUS MmCreateUserRegion(PROCESS* process, size_t size, size_t alignment, uint64_t pageFlags, uint32_t regionFlags, USER_REGION_TYPE type, void** outBase); diff --git a/code/kernel/include/kernel/net_socket.h b/code/kernel/include/kernel/net_socket.h index f31a6f9..25fcd1b 100644 --- a/code/kernel/include/kernel/net_socket.h +++ b/code/kernel/include/kernel/net_socket.h @@ -1,6 +1,8 @@ +// Kernel net socket declarations shared by implementation files and kernel clients. + #pragma once // net_socket.h - process-owned, provider-neutral kernel socket objects. -// + // The native networking ABI lives in net_abi.h. Protocol implementation lives // in a network stack driver registered through net_stack.h. diff --git a/code/kernel/include/kernel/ob_object.h b/code/kernel/include/kernel/ob_object.h index ae8fde8..67b8bfc 100644 --- a/code/kernel/include/kernel/ob_object.h +++ b/code/kernel/include/kernel/ob_object.h @@ -1,3 +1,5 @@ +// Kernel ob object declarations shared by implementation files and kernel clients. + #pragma once // ob_object.h - executive object model // Every resource the kernel tracks is a typed, reference-counted OBJECT. diff --git a/code/kernel/include/kernel/syscall_nr.h b/code/kernel/include/kernel/syscall_nr.h index 8560228..a05a408 100644 --- a/code/kernel/include/kernel/syscall_nr.h +++ b/code/kernel/include/kernel/syscall_nr.h @@ -1,10 +1,12 @@ +// Kernel syscall nr declarations shared by implementation files and kernel clients. + #pragma once // syscall_nr.h // INT 0x40 calling convention, MS x64: // RAX = syscall number // RCX, RDX, R8, R9 = args 0-3 // R10, R11 = args 4-5 (loaded by SYSCALL_STUB6) -// RAX = return value +// RAX = return value. #define SYS_EXIT_PROCESS 0 #define SYS_EXIT_THREAD 1 diff --git a/code/kernel/io_device.c b/code/kernel/io_device.c index 4f111d2..c44cf91 100644 --- a/code/kernel/io_device.c +++ b/code/kernel/io_device.c @@ -1,4 +1,5 @@ -// io_device.c - I/O manager: driver/device objects, stacks, PnP skeleton, disk namespace +// I/O manager. This file owns driver objects, device stacks, PnP dispatch, and the disk namespace. + #include #include #include @@ -10,10 +11,12 @@ #define MAX_DRIVER_OBJECTS 64 #define MAX_PDO_OBJECTS 128 +// Implements the sv Or Unnamed operation. static SYS_STRING_VIEW IoSvOrUnnamed(SYS_STRING_VIEW name) { return SysSvIsEmpty(name) ? SYS_SV_LITERAL("") : name; } +// Implements the bus Type Name operation. static const char* IoBusTypeName(IO_BUS_TYPE busType) { switch (busType) { case IoBusPci: return "pci"; @@ -22,15 +25,14 @@ static const char* IoBusTypeName(IO_BUS_TYPE busType) { } } -// ------------------------------------------------------------------------- -// Driver object registry / PDO AddDevice binding -// ------------------------------------------------------------------------- +// Driver object registry / PDO AddDevice binding. static DRIVER_OBJECT* gDriverObjects[MAX_DRIVER_OBJECTS]; static uint32_t gDriverObjectCount; static DEVICE_OBJECT* gPhysicalDevices[MAX_PDO_OBJECTS]; static uint32_t gPhysicalDeviceCount; +// Implements the driver Matches Pdo operation. static bool IoDriverMatchesPdo(const DRIVER_OBJECT* driver, const DEVICE_OBJECT* pdo) { if (!driver || !driver->IdTable || !pdo || pdo->Type != DeviceObjectPhysical) return false; @@ -47,6 +49,7 @@ static bool IoDriverMatchesPdo(const DRIVER_OBJECT* driver, const DEVICE_OBJECT* return false; } +// Implements the try Add Device For Driver operation. static bool IoTryAddDeviceForDriver(DRIVER_OBJECT* driver, DEVICE_OBJECT* pdo) { if (!driver || !pdo || !driver->DriverAddDevice) return false; @@ -81,6 +84,7 @@ __declspec(dllexport) void IoInitializeDriverObject(DRIVER_OBJECT* driver, driver->Name = name; } +// Registers driver Object. __declspec(dllexport) KSTATUS IoRegisterDriverObject(DRIVER_OBJECT* driver) { if (!driver) return STATUS_INVALID_PARAMETER; if (gDriverObjectCount >= MAX_DRIVER_OBJECTS) @@ -100,9 +104,7 @@ __declspec(dllexport) KSTATUS IoRegisterDriverObject(DRIVER_OBJECT* driver) { return STATUS_SUCCESS; } -// ------------------------------------------------------------------------- -// Device object lifetime -// ------------------------------------------------------------------------- +// Device object lifetime. static void IoDeviceDestroy(OBJECT* object) { DEVICE_OBJECT* dev = (DEVICE_OBJECT*)object; @@ -221,6 +223,7 @@ __declspec(dllexport) KSTATUS IoCreatePhysicalDevice(DRIVER_OBJECT* busDriver, return STATUS_SUCCESS; } +// Registers physical Device. __declspec(dllexport) KSTATUS IoRegisterPhysicalDevice(DEVICE_OBJECT* pdo) { if (!pdo || pdo->Type != DeviceObjectPhysical) return STATUS_INVALID_PARAMETER; @@ -264,14 +267,17 @@ __declspec(dllexport) KSTATUS IoSetDeviceName(DEVICE_OBJECT* device, return STATUS_SUCCESS; } +// Implements the reference Device Object operation. __declspec(dllexport) void IoReferenceDeviceObject(DEVICE_OBJECT* device) { if (device) ObReferenceObject(&device->Header); } +// Implements the dereference Device Object operation. __declspec(dllexport) void IoDereferenceDeviceObject(DEVICE_OBJECT* device) { if (device) ObDereferenceObject(&device->Header); } +// Releases physical Device Registry Entry. static void IoRemovePhysicalDeviceRegistryEntry(DEVICE_OBJECT* device) { if (!device || device->Type != DeviceObjectPhysical) return; @@ -288,6 +294,7 @@ static void IoRemovePhysicalDeviceRegistryEntry(DEVICE_OBJECT* device) { } } +// Implements the unlink Device From Parent operation. static void IoUnlinkDeviceFromParent(DEVICE_OBJECT* device) { if (!device || !device->Parent) return; @@ -309,6 +316,7 @@ static void IoUnlinkDeviceFromParent(DEVICE_OBJECT* device) { IoDereferenceDeviceObject(parent); } +// Releases device. __declspec(dllexport) void IoDeleteDevice(DEVICE_OBJECT* device) { if (!device) return; if (device->DeletePending) @@ -321,9 +329,7 @@ __declspec(dllexport) void IoDeleteDevice(DEVICE_OBJECT* device) { IoDereferenceDeviceObject(device); } -// ------------------------------------------------------------------------- -// Device stack management -// ------------------------------------------------------------------------- +// Device stack management. __declspec(dllexport) DEVICE_OBJECT* IoAttachDeviceToDeviceStack(DEVICE_OBJECT* source, DEVICE_OBJECT* target) { @@ -339,6 +345,7 @@ __declspec(dllexport) DEVICE_OBJECT* IoAttachDeviceToDeviceStack(DEVICE_OBJECT* return top; } +// Implements the detach Device operation. __declspec(dllexport) void IoDetachDevice(DEVICE_OBJECT* source) { if (!source || !source->LowerDevice) return; @@ -349,6 +356,7 @@ __declspec(dllexport) void IoDetachDevice(DEVICE_OBJECT* source) { IoDereferenceDeviceObject(lower); } +// Returns attached Device Reference. __declspec(dllexport) DEVICE_OBJECT* IoGetAttachedDeviceReference(DEVICE_OBJECT* device) { if (!device) return (DEVICE_OBJECT*)0; DEVICE_OBJECT* top = device; @@ -358,9 +366,7 @@ __declspec(dllexport) DEVICE_OBJECT* IoGetAttachedDeviceReference(DEVICE_OBJECT* return top; } -// ------------------------------------------------------------------------- -// Device-stack helpers / PnP dispatch -// ------------------------------------------------------------------------- +// Device-stack helpers / PnP dispatch. __declspec(dllexport) uint8_t IoGetDeviceStackSize(DEVICE_OBJECT* device) { uint8_t count = 0; @@ -369,6 +375,7 @@ __declspec(dllexport) uint8_t IoGetDeviceStackSize(DEVICE_OBJECT* device) { return count ? count : 1; } +// Implements the forward Irp To Lower operation. __declspec(dllexport) KSTATUS IoForwardIrpToLower(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp || !device->LowerDevice) return STATUS_NOT_SUPPORTED; @@ -413,9 +420,7 @@ __declspec(dllexport) KSTATUS IoSendPnpIrpSync(DEVICE_OBJECT* device, return st; } -// ------------------------------------------------------------------------- -// Disk namespace -// ------------------------------------------------------------------------- +// Disk namespace. #define MAX_DISK_DEVICES 8 #define MAX_DISK_CALLBACKS 16 @@ -438,6 +443,7 @@ static uint32_t gDiskChangeCallbackCount; static IO_DISK_ARRIVAL_CALLBACK_ENTRY gDiskArrivalCallbacks[MAX_DISK_CALLBACKS]; static uint32_t gDiskArrivalCallbackCount; +// Implements the notify Disk Change operation. static void IoNotifyDiskChange(uint8_t driveIndex, DEVICE_OBJECT* device, IO_DEVICE_CHANGE change) { for (uint32_t i = 0; i < gDiskChangeCallbackCount; i++) { IO_DISK_CHANGE_CALLBACK_ENTRY* entry = &gDiskChangeCallbacks[i]; @@ -477,6 +483,7 @@ __declspec(dllexport) KSTATUS IoRegisterDiskDevice(uint8_t driveIndex, return STATUS_SUCCESS; } +// Implements the notify Disk Surprise Removed operation. __declspec(dllexport) KSTATUS IoNotifyDiskSurpriseRemoved(uint8_t driveIndex) { if (driveIndex >= MAX_DISK_DEVICES) return STATUS_INVALID_PARAMETER; @@ -489,6 +496,7 @@ __declspec(dllexport) KSTATUS IoNotifyDiskSurpriseRemoved(uint8_t driveIndex) { return STATUS_SUCCESS; } +// Implements the unregister Disk Device operation. __declspec(dllexport) KSTATUS IoUnregisterDiskDevice(uint8_t driveIndex) { if (driveIndex >= MAX_DISK_DEVICES) return STATUS_INVALID_PARAMETER; @@ -562,29 +570,31 @@ __declspec(dllexport) KSTATUS IoEnumerateDiskDevices(IO_DISK_ARRIVAL_CALLBACK ca return STATUS_SUCCESS; } +// Returns disk Device. __declspec(dllexport) DEVICE_OBJECT* IoGetDiskDevice(uint8_t driveIndex) { if (driveIndex >= MAX_DISK_DEVICES) return (DEVICE_OBJECT*)0; return gDiskDevices[driveIndex]; } +// Implements the reference Disk Device operation. __declspec(dllexport) DEVICE_OBJECT* IoReferenceDiskDevice(uint8_t driveIndex) { DEVICE_OBJECT* dev = IoGetDiskDevice(driveIndex); if (dev) IoReferenceDeviceObject(dev); return dev; } +// Implements the disk Device Present operation. __declspec(dllexport) bool IoDiskDevicePresent(uint8_t driveIndex) { return IoGetDiskDevice(driveIndex) != (DEVICE_OBJECT*)0; } +// Implements the disk Sector Count operation. __declspec(dllexport) uint64_t IoDiskSectorCount(uint8_t driveIndex) { DEVICE_OBJECT* dev = IoGetDiskDevice(driveIndex); return dev ? dev->u.Disk.SectorCount : 0; } -// ------------------------------------------------------------------------- -// Dispatch -// ------------------------------------------------------------------------- +// Dispatch. __declspec(dllexport) KSTATUS IoCallDriver(DEVICE_OBJECT* device, IRP* irp) { if (!device || !device->DriverObject || !irp) diff --git a/code/kernel/io_file.c b/code/kernel/io_file.c index 56a7ee0..a608942 100644 --- a/code/kernel/io_file.c +++ b/code/kernel/io_file.c @@ -1,4 +1,5 @@ -// io_file.c - VFS dispatch layer +// Kernel file I/O layer. This file owns file handles, filesystem dispatch, and asynchronous request plumbing. + #include #include #include @@ -22,9 +23,7 @@ typedef struct { static VOLUME_ENTRY gVolumes[MAX_DRIVES]; -// --------------------------------------------------------------------------- -// Async file I/O worker -// --------------------------------------------------------------------------- +// Async file I/O worker. typedef enum IO_ASYNC_FILE_OP { IoAsyncFileRead = 0, IoAsyncFileWrite = 1, @@ -61,6 +60,7 @@ static SPINLOCK gAsyncFileQueueLock = SPINLOCK_INIT; static LIST_ENTRY gAsyncFileQueue; static SEMAPHORE* gAsyncFileSemaphore; +// Implements the io Async File Request Destroy operation. static void KiIoAsyncFileRequestDestroy(OBJECT* obj) { IO_ASYNC_FILE_REQUEST_OBJECT* req = CONTAINING_RECORD(obj, IO_ASYNC_FILE_REQUEST_OBJECT, Header); @@ -101,6 +101,7 @@ static void KiIoCompleteAsyncFileRequest(IO_ASYNC_FILE_REQUEST_OBJECT* req, KeSignalEvent(req->CompletionEvent); } +// Implements the io Async File Dequeue operation. static IO_ASYNC_FILE_REQUEST_OBJECT* KiIoAsyncFileDequeue(void) { uintptr_t flags = KeAcquireSpinlock(&gAsyncFileQueueLock); LIST_ENTRY* node = ListPopHead(&gAsyncFileQueue); @@ -121,6 +122,7 @@ static IO_ASYNC_FILE_REQUEST_OBJECT* KiIoAsyncFileDequeue(void) { return req; } +// Implements the io Async File Worker operation. static void KiIoAsyncFileWorker(void* arg) { (void)arg; @@ -162,6 +164,7 @@ static void KiIoAsyncFileWorker(void* arg) { } } +// Implements the io Ensure Async File Io Started operation. static KSTATUS KiIoEnsureAsyncFileIoStarted(void) { uintptr_t flags = KeAcquireSpinlock(&gAsyncFileInitLock); if (gAsyncFileInitState == 2) { @@ -337,10 +340,12 @@ __declspec(dllexport) KSTATUS IoWriteFileAsyncKernel(FILE_OBJECT* file, const vo requestOut); } +// Implements the async File Request Object operation. __declspec(dllexport) OBJECT* IoAsyncFileRequestObject(IO_ASYNC_FILE_REQUEST_OBJECT* req) { return req ? &req->Header : (OBJECT*)0; } +// Cancels async File Request. __declspec(dllexport) KSTATUS IoCancelAsyncFileRequest(IO_ASYNC_FILE_REQUEST_OBJECT* req) { if (!req) return STATUS_INVALID_PARAMETER; @@ -382,11 +387,9 @@ __declspec(dllexport) KSTATUS IoQueryAsyncFileRequest(IO_ASYNC_FILE_REQUEST_OBJE return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- // Current Working Directory // Stored as (CurrentDrive, drive-relative path with no trailing backslash). // Exported as native "N:/path" so personalities can round-trip volumes. -// --------------------------------------------------------------------------- #define CWD_MAX PROCESS_CWD_MAX typedef struct KRESOLVED_PATH { @@ -395,6 +398,7 @@ typedef struct KRESOLVED_PATH { SYS_STRING_VIEW Path; } KRESOLVED_PATH; +// Implements the format Cwd operation. static size_t KiFormatCwd(uint8_t drive, SYS_STRING_VIEW rel, char* buf, size_t size) { if (!buf || size == 0 || !SysSvIsValid(rel)) return 0; if (drive > 7) drive = 0; @@ -410,6 +414,7 @@ static size_t KiFormatCwd(uint8_t drive, SYS_STRING_VIEW rel, char* buf, size_t return needed; } +// Returns cwd. __declspec(dllexport) KSTATUS IoGetCwd(char* buf, size_t size) { if (!buf || size == 0) return STATUS_INVALID_PARAMETER; @@ -423,6 +428,7 @@ __declspec(dllexport) KSTATUS IoGetCwd(char* buf, size_t size) { return needed && needed <= size ? STATUS_SUCCESS : STATUS_BUFFER_TOO_SMALL; } +// Implements the sv Has Drive Root operation. static int KiSvHasDriveRoot(SYS_STRING_VIEW path) { return path.Length >= 3 && path.Data[0] >= '0' && path.Data[0] <= '7' && @@ -449,6 +455,7 @@ static int KiAppendComponent(char* work, size_t* workLen, size_t cap, return KiAppendBytes(work, workLen, cap, data, len); } +// Implements the pop Component operation. static void KiPopComponent(char* work, size_t* workLen) { if (!work || !workLen || *workLen == 0) return; size_t i = *workLen; @@ -529,6 +536,7 @@ static KSTATUS KiResolvePathV(SYS_STRING_VIEW input, KRESOLVED_PATH* out) { return STATUS_SUCCESS; } +// Updates cwd. __declspec(dllexport) KSTATUS IoSetCwd(SYS_STRING_VIEW path) { if (path.Length && !path.Data) return STATUS_INVALID_PARAMETER; if (!KeCanWait()) return STATUS_INVALID_IRQL; @@ -571,9 +579,7 @@ __declspec(dllexport) KSTATUS IoSetCwd(SYS_STRING_VIEW path) { return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// Registration -// --------------------------------------------------------------------------- +// Registration. __declspec(dllexport) KSTATUS IoRegisterFilesystem(uint8_t volumeIndex, IO_FILESYSTEM *fs, const IO_VOLUME_PARAMS *vol) { @@ -586,6 +592,7 @@ __declspec(dllexport) KSTATUS IoRegisterFilesystem(uint8_t volumeIndex, return STATUS_SUCCESS; } +// Implements the unregister Filesystem operation. __declspec(dllexport) KSTATUS IoUnregisterFilesystem(uint8_t volumeIndex) { if (volumeIndex >= MAX_DRIVES) return STATUS_INVALID_PARAMETER; @@ -596,6 +603,7 @@ __declspec(dllexport) KSTATUS IoUnregisterFilesystem(uint8_t volumeIndex) { return STATUS_SUCCESS; } +// Implements the unregister Filesystems For Disk operation. __declspec(dllexport) KSTATUS IoUnregisterFilesystemsForDisk(uint8_t diskIndex) { KSTATUS last = STATUS_NOT_FOUND; for (uint8_t i = 0; i < MAX_DRIVES; i++) { @@ -607,23 +615,20 @@ __declspec(dllexport) KSTATUS IoUnregisterFilesystemsForDisk(uint8_t diskIndex) return last; } +// Implements the filesystem Present operation. __declspec(dllexport) bool IoFilesystemPresent(uint8_t volumeIndex) { if (volumeIndex >= MAX_DRIVES) return false; return gVolumes[volumeIndex].Fs != (IO_FILESYSTEM*)0; } -// --------------------------------------------------------------------------- -// Destructor -// --------------------------------------------------------------------------- +// Destructor. static void KiFileDestroy(OBJECT* obj) { FILE_OBJECT* f = CONTAINING_RECORD(obj, FILE_OBJECT, Header); if (f->Fs && f->FileCtx) f->Fs->Close(f->Fs, f->FileCtx); } -// --------------------------------------------------------------------------- -// IoOpenFile -// --------------------------------------------------------------------------- +// IoOpenFile. __declspec(dllexport) KSTATUS IoOpenFile(SYS_STRING_VIEW path, FILE_OBJECT **out) { if ((!path.Data && path.Length) || !out) return STATUS_INVALID_PARAMETER; if (!KeCanWait()) return STATUS_INVALID_IRQL; @@ -640,7 +645,8 @@ __declspec(dllexport) KSTATUS IoOpenFile(SYS_STRING_VIEW path, FILE_OBJECT **out s = fs->Open(fs, resolved.Path, &fileCtx); if (!KSUCCESS(s)) return s; - FILE_OBJECT* f = (FILE_OBJECT *)ObAllocateObject(ObjectTypeFile /* reuse slot */, + // File objects reuse the generic object slot because the handle table only needs the shared header contract here. + FILE_OBJECT* f = (FILE_OBJECT *)ObAllocateObject(ObjectTypeFile, sizeof(FILE_OBJECT)); if (!f) { fs->Close(fs, fileCtx); return STATUS_NO_MEMORY; } f->Header.Destroy = KiFileDestroy; @@ -654,10 +660,8 @@ __declspec(dllexport) KSTATUS IoOpenFile(SYS_STRING_VIEW path, FILE_OBJECT **out return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- // Explicit-offset file I/O. Async I/O is built on these routines so it does // not race the sequential FILE_OBJECT.Offset used by legacy read/write calls. -// --------------------------------------------------------------------------- __declspec(dllexport) KSTATUS IoReadFileAt(FILE_OBJECT* file, uint64_t offset, void* buf, size_t size, size_t* bytesRead) { @@ -700,9 +704,7 @@ __declspec(dllexport) KSTATUS IoWriteFileAt(FILE_OBJECT* file, uint64_t offset, return s; } -// --------------------------------------------------------------------------- -// IoReadFile - sequential read at current offset -// --------------------------------------------------------------------------- +// IoReadFile - sequential read at current offset. __declspec(dllexport) KSTATUS IoReadFile(FILE_OBJECT* file, void* buf, size_t size, size_t* bytesRead) { if (bytesRead) *bytesRead = 0; @@ -721,9 +723,7 @@ __declspec(dllexport) KSTATUS IoReadFile(FILE_OBJECT* file, void* buf, return s; } -// --------------------------------------------------------------------------- -// IoWriteFile - sequential write at current offset -// --------------------------------------------------------------------------- +// IoWriteFile - sequential write at current offset. __declspec(dllexport) KSTATUS IoWriteFile(FILE_OBJECT* file, const void* buf, size_t size, size_t* bytesWritten) { if (bytesWritten) *bytesWritten = 0; @@ -742,9 +742,7 @@ __declspec(dllexport) KSTATUS IoWriteFile(FILE_OBJECT* file, const void* buf, return s; } -// --------------------------------------------------------------------------- -// IoCreateFile - create a new file and return it open for writing -// --------------------------------------------------------------------------- +// IoCreateFile - create a new file and return it open for writing. __declspec(dllexport) KSTATUS IoCreateFile(SYS_STRING_VIEW path, FILE_OBJECT** out) { if ((!path.Data && path.Length) || !out || path.Length == 0) return STATUS_INVALID_PARAMETER; if (!KeCanWait()) return STATUS_INVALID_IRQL; @@ -775,9 +773,7 @@ __declspec(dllexport) KSTATUS IoCreateFile(SYS_STRING_VIEW path, FILE_OBJECT** o return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// IoDeleteFile - delete a file by path (does not require an open handle) -// --------------------------------------------------------------------------- +// IoDeleteFile - delete a file by path (does not require an open handle). __declspec(dllexport) KSTATUS IoDeleteFile(SYS_STRING_VIEW path) { if ((!path.Data && path.Length) || path.Length == 0) return STATUS_INVALID_PARAMETER; if (!KeCanWait()) return STATUS_INVALID_IRQL; @@ -793,6 +789,7 @@ __declspec(dllexport) KSTATUS IoDeleteFile(SYS_STRING_VIEW path) { return fs->Delete(fs, resolved.Path); } +// Implements the rename File operation. __declspec(dllexport) KSTATUS IoRenameFile(SYS_STRING_VIEW oldPath, SYS_STRING_VIEW newPath) { if ((!oldPath.Data && oldPath.Length) || (!newPath.Data && newPath.Length) || oldPath.Length == 0 || newPath.Length == 0) return STATUS_INVALID_PARAMETER; @@ -813,6 +810,7 @@ __declspec(dllexport) KSTATUS IoRenameFile(SYS_STRING_VIEW oldPath, SYS_STRING_V return fs->Rename(fs, oldResolved.Path, newResolved.Path); } +// Creates dir. __declspec(dllexport) KSTATUS IoCreateDir(SYS_STRING_VIEW path) { if ((!path.Data && path.Length) || path.Length == 0) return STATUS_INVALID_PARAMETER; if (!KeCanWait()) return STATUS_INVALID_IRQL; @@ -828,6 +826,7 @@ __declspec(dllexport) KSTATUS IoCreateDir(SYS_STRING_VIEW path) { return fs->CreateDir(fs, resolved.Path); } +// Releases dir. __declspec(dllexport) KSTATUS IoRemoveDir(SYS_STRING_VIEW path) { if ((!path.Data && path.Length) || path.Length == 0) return STATUS_INVALID_PARAMETER; if (!KeCanWait()) return STATUS_INVALID_IRQL; @@ -843,9 +842,7 @@ __declspec(dllexport) KSTATUS IoRemoveDir(SYS_STRING_VIEW path) { return fs->RemoveDir(fs, resolved.Path); } -// --------------------------------------------------------------------------- -// IoTruncateFile - resize the file; updates the cached Size on success -// --------------------------------------------------------------------------- +// IoTruncateFile - resize the file; updates the cached Size on success. __declspec(dllexport) KSTATUS IoTruncateFile(FILE_OBJECT* file, uint64_t newSize) { if (!file) return STATUS_INVALID_PARAMETER; if (!KeCanWait()) return STATUS_INVALID_IRQL; @@ -861,7 +858,6 @@ __declspec(dllexport) KSTATUS IoTruncateFile(FILE_OBJECT* file, uint64_t newSize return s; } -// --------------------------------------------------------------------------- __declspec(dllexport) KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset) { if (!file) return STATUS_INVALID_PARAMETER; uintptr_t flags = KeAcquireSpinlock(&file->Lock); @@ -870,6 +866,7 @@ __declspec(dllexport) KSTATUS IoSeekFile(FILE_OBJECT* file, uint64_t offset) { return STATUS_SUCCESS; } +// Returns file Size. __declspec(dllexport) uint64_t IoGetFileSize(FILE_OBJECT* file) { if (!file) return 0; uintptr_t flags = KeAcquireSpinlock(&file->Lock); @@ -878,19 +875,19 @@ __declspec(dllexport) uint64_t IoGetFileSize(FILE_OBJECT* file) { return size; } +// Releases file. __declspec(dllexport) void IoCloseFile(FILE_OBJECT* file) { if (file) ObDereferenceObject(&file->Header); } -// --------------------------------------------------------------------------- -// Directory enumeration -// --------------------------------------------------------------------------- +// Directory enumeration. static void KiDirDestroy(OBJECT* obj) { DIR_OBJECT* d = (DIR_OBJECT*)obj; // Header is first member if (d->Fs && d->DirCtx) d->Fs->CloseDir(d->Fs, d->DirCtx); } +// Opens dir. __declspec(dllexport) KSTATUS IoOpenDir(SYS_STRING_VIEW dirPath, DIR_OBJECT** out) { if (!out) return STATUS_INVALID_PARAMETER; if (dirPath.Length && !dirPath.Data) return STATUS_INVALID_PARAMETER; @@ -937,6 +934,7 @@ __declspec(dllexport) KSTATUS IoOpenDir(SYS_STRING_VIEW dirPath, DIR_OBJECT** ou return STATUS_SUCCESS; } +// Returns dir. __declspec(dllexport) KSTATUS IoReadDir(DIR_OBJECT* dir, KDIR_ENTRY* entryOut) { if (!dir || !entryOut) return STATUS_INVALID_PARAMETER; if (!KeCanWait()) return STATUS_INVALID_IRQL; @@ -944,6 +942,7 @@ __declspec(dllexport) KSTATUS IoReadDir(DIR_OBJECT* dir, KDIR_ENTRY* entryOut) { return dir->Fs->ReadDir(dir->Fs, dir->DirCtx, entryOut); } +// Releases dir. __declspec(dllexport) void IoCloseDir(DIR_OBJECT* dir) { if (dir) ObDereferenceObject(&dir->Header); } diff --git a/code/kernel/ke_apc.c b/code/kernel/ke_apc.c index 93a8a83..026dcc0 100644 --- a/code/kernel/ke_apc.c +++ b/code/kernel/ke_apc.c @@ -1,4 +1,5 @@ -// ke_apc.c - kernel APC infrastructure +// Kernel APC infrastructure. This file owns APC queuing, delivery, and user-mode return transitions. + #include #include #include @@ -9,6 +10,7 @@ #include #include +// Initializes apc State. void KiInitializeApcState(THREAD* thread) { if (!thread) return; LIST_INIT(&thread->ApcQueue); @@ -88,6 +90,7 @@ __declspec(dllexport) bool KeInsertQueueApc(KAPC* apc, return true; } +// Implements the enter Critical Region operation. __declspec(dllexport) void KeEnterCriticalRegion(void) { THREAD* thread = KeGetCurrentThread(); if (!thread) return; @@ -97,6 +100,7 @@ __declspec(dllexport) void KeEnterCriticalRegion(void) { KeReleaseSpinlock(&thread->ApcLock, flags); } +// Implements the leave Critical Region operation. __declspec(dllexport) void KeLeaveCriticalRegion(void) { THREAD* thread = KeGetCurrentThread(); if (!thread) return; @@ -111,12 +115,14 @@ __declspec(dllexport) void KeLeaveCriticalRegion(void) { KiDeliverKernelApcs(); } +// Implements the are Kernel Apcs Disabled operation. __declspec(dllexport) bool KeAreKernelApcsDisabled(void) { THREAD* thread = KeGetCurrentThread(); if (!thread) return true; return thread->KernelApcDisable != 0; } +// Implements the pop Kernel Apc operation. static KAPC* KiPopKernelApc(THREAD* thread) { uintptr_t flags = KeAcquireSpinlock(&thread->ApcLock); LIST_ENTRY* node = ListPopHead(&thread->ApcQueue); @@ -129,6 +135,7 @@ static KAPC* KiPopKernelApc(THREAD* thread) { return CONTAINING_RECORD(node, KAPC, Link); } +// Implements the deliver Kernel Apcs operation. void KiDeliverKernelApcs(void) { THREAD* thread = KeGetCurrentThread(); if (!thread) @@ -178,6 +185,7 @@ void KiDeliverKernelApcs(void) { } +// Updates user Apc Dispatcher. __declspec(dllexport) KSTATUS KeSetUserApcDispatcher(void* dispatcher) { THREAD* thread = KeGetCurrentThread(); if (!thread) return STATUS_FAILURE; @@ -221,6 +229,7 @@ __declspec(dllexport) KSTATUS KeQueueUserApc(THREAD* thread, return STATUS_SUCCESS; } +// Implements the pop User Apc operation. static KUSER_APC* KiPopUserApc(THREAD* thread) { uintptr_t flags = KeAcquireSpinlock(&thread->UserApcLock); LIST_ENTRY* node = ListPopHead(&thread->UserApcQueue); @@ -233,6 +242,7 @@ static KUSER_APC* KiPopUserApc(THREAD* thread) { return CONTAINING_RECORD(node, KUSER_APC, Link); } +// Implements the check For User Apc Delivery operation. void KiCheckForUserApcDelivery(KTRAP_FRAME* frame) { if (!frame || !KeTrapFrameFromUser(frame)) return; @@ -288,6 +298,7 @@ void KiCheckForUserApcDelivery(KTRAP_FRAME* frame) { MmFreePool(apc); } +// Implements the rundown Apc State operation. void KiRundownApcState(THREAD* thread) { if (!thread) return; @@ -322,6 +333,7 @@ void KiRundownApcState(THREAD* thread) { thread->UserApcDeliveryActive = 0; } +// Implements the user Apc Return operation. __declspec(dllexport) uint64_t KeUserApcReturn(const SYS_USER_APC_FRAME_K* userFrame) { SYS_USER_APC_FRAME_K frameCopy; KSTATUS s = CopyFromUser(&frameCopy, userFrame, sizeof(frameCopy)); diff --git a/code/kernel/ke_cpu.c b/code/kernel/ke_cpu.c index 126a56e..4dd22d7 100644 --- a/code/kernel/ke_cpu.c +++ b/code/kernel/ke_cpu.c @@ -1,4 +1,5 @@ -// ke_cpu.c - bootstrap/per-CPU state plumbing +// CPU-local kernel state. This file owns bootstrap and per-CPU bookkeeping shared by scheduler and SMP code. + #include #include #include @@ -16,6 +17,7 @@ static volatile long gKernelGsReady = 0; extern KCPU* KeReadCurrentCpuFromGs(void); +// Loads kernel Gs Base. void KeLoadKernelGsBase(KCPU* cpu) { if (!cpu) cpu = &gCpus[0]; @@ -25,6 +27,7 @@ void KeLoadKernelGsBase(KCPU* cpu) { gKernelGsReady = 1; } +// Updates user Gs Base. void KeSetUserGsBase(uintptr_t userGsBase) { // While running in the kernel, GS_BASE is the current KCPU. The user TEB // base is parked in IA32_KERNEL_GS_BASE so swapgs can exchange it with the @@ -32,10 +35,12 @@ void KeSetUserGsBase(uintptr_t userGsBase) { __writemsr(IA32_KERNEL_GS_BASE, (uint64_t)userGsBase); } +// Returns user Gs Base. uintptr_t KeGetUserGsBase(void) { return (uintptr_t)__readmsr(IA32_KERNEL_GS_BASE); } +// Initializes bootstrap Cpu. void KeInitializeBootstrapCpu(void) { memset(gCpus, 0, sizeof(gCpus)); @@ -73,6 +78,7 @@ void KeInitializeBootstrapCpu(void) { KeSetUserGsBase(0); } +// Returns current Cpu. KCPU* KeGetCurrentCpu(void) { if (gKernelGsReady) { KCPU* cpu = KeReadCurrentCpuFromGs(); @@ -84,12 +90,14 @@ KCPU* KeGetCurrentCpu(void) { return &gCpus[0]; } +// Returns cpu By Index. KCPU* KeGetCpuByIndex(uint32_t index) { if (index >= KE_MAX_CPUS) return (KCPU*)0; return &gCpus[index]; } +// Returns current Cpu Index. uint32_t KeGetCurrentCpuIndex(void) { return KeGetCurrentCpu()->CpuIndex; } diff --git a/code/kernel/ke_debug.c b/code/kernel/ke_debug.c index b202035..092fecb 100644 --- a/code/kernel/ke_debug.c +++ b/code/kernel/ke_debug.c @@ -1,4 +1,5 @@ -// ke_debug.c - debugging utilities +// Kernel debugging and bugcheck support. This file owns panic reporting, process fault reporting, and diagnostic queries. + #include #include #include @@ -31,6 +32,7 @@ static size_t gDebugLogWrite; static size_t gDebugLogUsed; static volatile long gDebugLogFlushing; +// Implements the debug Log Append Locked operation. static void KiDebugLogAppendLocked(const char* text, size_t len) { if (!gDebugLogBuffer || gDebugLogSize == 0 || !text || len == 0) return; @@ -53,6 +55,7 @@ static void KiDebugLogAppendLocked(const char* text, size_t len) { gDebugLogUsed += len; } +// Implements the debug Console Write operation. static void KiDebugConsoleWrite(const char* text, size_t len) { if (!PrintChar || !text) return; @@ -64,12 +67,14 @@ static volatile long gPanicInProgress = 0; static volatile uintptr_t gPanicOwnerToken = 0; static volatile long gPanicStoppedCpuCount = 0; +// Implements the panic Secondary Halt operation. static _Noreturn void KiPanicSecondaryHalt(void) { _disable(); _InterlockedIncrement(&gPanicStoppedCpuCount); for (;;) __halt(); } +// Implements the panic Current Token operation. static uintptr_t KiPanicCurrentToken(void) { THREAD* thread = KeGetCurrentThread(); if (thread) @@ -80,15 +85,18 @@ static uintptr_t KiPanicCurrentToken(void) { return 1u; } +// Implements the panic Is Active operation. static int KiPanicIsActive(void) { return _InterlockedCompareExchange((volatile long*)&gPanicInProgress, 0, 0) != 0; } +// Implements the panic Current Cpu Owns Report operation. static int KiPanicCurrentCpuOwnsReport(void) { uintptr_t token = KiPanicCurrentToken(); return token != 0 && gPanicOwnerToken == token; } +// Implements the begin Fatal Report operation. static void KiBeginFatalReport(void) { _disable(); uintptr_t token = KiPanicCurrentToken(); @@ -114,11 +122,13 @@ __declspec(dllexport) int KeHandleNmiIpi(void) { return 0; } +// Implements the kernel Put Char operation. void KiKernelPutChar(char c) { if (PrintChar) PrintChar(c, 0xCCCCCC, 0x012456); } +// Initializes debug. void KeInitDebug(void (*PrintPtr)(char, uint32_t, uint32_t), uint32_t flags) { gDebugFlags = flags; gDebugEnabled = (flags & (KE_DEBUG_CONSOLE | KE_DEBUG_FILE_LOG)) != 0; @@ -136,10 +146,12 @@ void KeInitDebug(void (*PrintPtr)(char, uint32_t, uint32_t), uint32_t flags) { } } +// Returns debug Flags. uint32_t KeGetDebugFlags(void) { return gDebugFlags; } +// Updates debug Console Writer. void KeSetDebugConsoleWriter(void (*PrintPtr)(char, uint32_t, uint32_t)) { if (!PrintPtr) return; @@ -147,6 +159,7 @@ void KeSetDebugConsoleWriter(void (*PrintPtr)(char, uint32_t, uint32_t)) { printf_set_putchar(KiKernelPutChar); } +// Implements the dbg Print operation. __declspec(dllexport) void DbgPrint(const char* fmt, ...) { if (!gDebugEnabled || !fmt) return; @@ -179,6 +192,7 @@ __declspec(dllexport) void DbgPrint(const char* fmt, ...) { KeReleaseSpinlock(&gDebugPrintLock, flags); } +// Flushes debug Log To File. __declspec(dllexport) KSTATUS KeFlushDebugLogToFile(SYS_STRING_VIEW path) { if (!gDebugLogBuffer || gDebugLogSize == 0 || !SysSvIsValid(path) || path.Length == 0) return STATUS_INVALID_PARAMETER; @@ -228,7 +242,7 @@ __declspec(dllexport) KSTATUS KeFlushDebugLogToFile(SYS_STRING_VIEW path) { return (KSUCCESS(st) && totalWritten == used) ? STATUS_SUCCESS : st; } -// KePanic +// KePanic. __declspec(dllexport) _Noreturn void KePanic(int code, const char* fmt, ...) { KiBeginFatalReport(); @@ -276,13 +290,11 @@ __declspec(dllexport) void KePrintConsole(const char* buf, size_t len) { PrintChar(buf[i], 0xCCCCCC, 0x012456); } -// --------------------------------------------------------------------------- // KeBugCheckProcess - user-mode fault handler -// + // Resolves the faulting RIP to a module name, prints a yellow crash banner, // kills the offending process, then exits the current thread so the scheduler // can continue running everything else. -// --------------------------------------------------------------------------- // Return the short exception name for a CPU exception vector. // Keep this table complete for vectors 0..31 so faults never collapse into @@ -326,6 +338,7 @@ static const char* KiFaultVectorName(int vector) { } } +// Implements the fault Has Error Code operation. static int KiFaultHasErrorCode(int vector) { switch (vector) { case 8: // #DF @@ -374,10 +387,12 @@ static const char* KiResolveModuleEx(PROCESS* proc, uintptr_t addr, return "unknown"; } +// Implements the resolve Module operation. static const char* KiResolveModule(PROCESS* proc, uintptr_t addr) { return KiResolveModuleEx(proc, addr, (uintptr_t*)0, (size_t*)0); } +// Prints address. static void KiPrintAddress(PROCESS* proc, const char* label, uintptr_t addr) { uintptr_t base = 0; size_t size = 0; @@ -396,6 +411,7 @@ static void KiPrintAddress(PROCESS* proc, const char* label, uintptr_t addr) { } } +// Implements the user Read U64 operation. static int KiUserReadU64(uintptr_t addr, uint64_t* out) { if (!out) return 0; if (!addr) return 0; @@ -405,6 +421,7 @@ static int KiUserReadU64(uintptr_t addr, uint64_t* out) { return 1; } +// Implements the user Read U8 operation. static int KiUserReadU8(uintptr_t addr, uint8_t* out) { if (!out) return 0; if (!addr) return 0; @@ -414,6 +431,7 @@ static int KiUserReadU8(uintptr_t addr, uint8_t* out) { return 1; } +// Dumps bytes. static void KiDumpBytes(PROCESS* proc, const char* label, uintptr_t center) { if (!center) { printf("%s: \n", label); @@ -438,6 +456,7 @@ static void KiDumpBytes(PROCESS* proc, const char* label, uintptr_t center) { } } +// Implements the user Read I32 operation. static int KiUserReadI32(uintptr_t addr, int32_t* out) { if (!out) return 0; if (!addr) return 0; @@ -447,6 +466,7 @@ static int KiUserReadI32(uintptr_t addr, int32_t* out) { return 1; } +// Dumps indirect Call Slot. static void KiDumpIndirectCallSlot(PROCESS* proc, uintptr_t ret) { if (!ret) return; @@ -461,12 +481,14 @@ static void KiDumpIndirectCallSlot(PROCESS* proc, uintptr_t ret) { if (KiUserReadU8(ret - 6, &b0) && KiUserReadU8(ret - 5, &b1) && b0 == 0xff && b1 == 0x15 && + // Implements the user Read I32 operation. KiUserReadI32(ret - 4, &disp)) { insn = ret - 6; } else if (KiUserReadU8(ret - 7, &b0) && KiUserReadU8(ret - 6, &b1) && KiUserReadU8(ret - 5, &b2) && b0 == 0x48 && b1 == 0xff && b2 == 0x15 && + // Implements the user Read I32 operation. KiUserReadI32(ret - 4, &disp)) { insn = ret - 7; } else { @@ -490,6 +512,7 @@ static void KiDumpIndirectCallSlot(PROCESS* proc, uintptr_t ret) { KiDumpBytes(proc, "Bytes near indirect slot", slot); } +// Dumps modules. static void KiDumpModules(PROCESS* proc) { if (!proc) return; @@ -513,6 +536,7 @@ static void KiDumpModules(PROCESS* proc) { } } +// Dumps user Stack. static void KiDumpUserStack(PROCESS* proc, uintptr_t rsp) { printf("User stack @ %016llx:\n", (unsigned long long)rsp); if (!rsp) { @@ -548,6 +572,7 @@ static void KiDumpUserStack(PROCESS* proc, uintptr_t rsp) { } } +// Dumps fault Frame. static void KiDumpFaultFrame(PROCESS* proc, const KFAULT_FRAME* f) { if (!f) return; @@ -586,6 +611,7 @@ static void KiDumpFaultFrame(PROCESS* proc, const KFAULT_FRAME* f) { KiDumpUserStack(proc, (uintptr_t)f->Rsp); } +// Prints crash Char. static void KiPrintCrashChar(char c) { if (PrintChar) PrintChar(c, 0xFFAA00, 0x000000); // amber - distinct from green debug / red panic @@ -621,6 +647,7 @@ static void KiPrintCrashHeader(PROCESS* proc, int vector, uintptr_t rip, (unsigned long long)errCode); } +// Implements the finish Faulted Process operation. static _Noreturn void KiFinishFaultedProcess(PROCESS* proc, THREAD* thread) { printf_set_putchar(KiKernelPutChar); @@ -640,6 +667,7 @@ _Noreturn void KeBugCheckProcess(int vector, uintptr_t rip, uintptr_t errCode, u KiFinishFaultedProcess(proc, thread); } +// Implements the fault Dispatch Frame operation. __declspec(dllexport) _Noreturn void KeFaultDispatchFrame(const KFAULT_FRAME* frame) { // Panic NMIs are broadcast to stop all other CPUs. Do not try to decode // the interrupted context on a secondary CPU once another CPU owns panic. @@ -718,13 +746,11 @@ __declspec(dllexport) _Noreturn void KeFaultDispatchFrame(const KFAULT_FRAME* fr KiFinishFaultedProcess(proc, thread); } -// --------------------------------------------------------------------------- // KeFaultDispatch - single C entry point for all three IDT fault stubs. -// + // The asm stubs (ke_syscall.asm) collect the CPU exception frame values and // call here. We check the CS RPL to decide: kernel fault โ†’ panic and halt, // user fault โ†’ KeBugCheckProcess (kill process, resume scheduler). -// --------------------------------------------------------------------------- __declspec(dllexport) _Noreturn void KeFaultDispatch(int vector, uintptr_t rip, uintptr_t errCode, uintptr_t cr2, uintptr_t cs) { diff --git a/code/kernel/ke_display.c b/code/kernel/ke_display.c index afa3ef7..90c7bc2 100644 --- a/code/kernel/ke_display.c +++ b/code/kernel/ke_display.c @@ -1,9 +1,4 @@ -// ke_display.c - kernel display manager -// -// The display manager owns the primary display device, cursor policy, dirty -// rectangles, and the kernel/user screen API. The first provider is a boot -// framebuffer backend over the HAL GOP framebuffer; later GPU drivers register -// DISPLAY_DEVICE providers here. +// Kernel display manager. This file owns provider registration, framebuffer routing, dirty rectangles, text console state, and cursor delegation. #include #include @@ -96,28 +91,33 @@ static const DISPLAY_DEVICE_OPS gBootFbOps = { }; +// Checks whether a primary display provider is available. static bool KiDisplayHasDevice(void) { return gPrimaryDisplay && gPrimaryDisplay->Ops; } +// Checks whether the active provider expects the manager to draw the cursor into the framebuffer. static bool KiDisplayUsesSoftwareCursor(void) { return KiDisplayHasDevice() && (gPrimaryDisplay->Caps & DISPLAY_CAP_SOFTWARE_CURSOR) && gPrimaryDisplay->Ops->ShowCursor; } +// Checks whether the active provider owns cursor presentation in hardware or device firmware. static bool KiDisplayUsesHardwareCursor(void) { return KiDisplayHasDevice() && (gPrimaryDisplay->Caps & DISPLAY_CAP_HARDWARE_CURSOR) && gPrimaryDisplay->Ops->ShowCursor; } +// Checks whether the active provider exposes any cursor-control path. static bool KiDisplayHasCursorOps(void) { return KiDisplayHasDevice() && (gPrimaryDisplay->Caps & (DISPLAY_CAP_SOFTWARE_CURSOR | DISPLAY_CAP_HARDWARE_CURSOR)) && gPrimaryDisplay->Ops->ShowCursor; } +// Clips a rectangle to a display mode so providers never see negative or out-of-bounds regions. static bool KiDisplayClipRect(const DISPLAY_MODE* mode, DISPLAY_RECT* rect) { if (!mode || !rect || rect->W <= 0 || rect->H <= 0) return false; @@ -141,12 +141,14 @@ static bool KiDisplayClipRect(const DISPLAY_MODE* mode, DISPLAY_RECT* rect) { return true; } +// Implements the display Dirty All operation. static void KiDisplayDirtyAll(void) { gDisplayStats.DirtyAllCount++; gDirtyAll = true; gDirtyRectCount = 0; } +// Implements the display Add Dirty operation. static void KiDisplayAddDirty(int x, int y, int w, int h) { if (!KiDisplayHasDevice() || gDirtyAll || w <= 0 || h <= 0) return; @@ -174,6 +176,7 @@ static void KiDisplayAddDirty(int x, int y, int w, int h) { gDirtyRects[gDirtyRectCount++] = rect; } +// Implements the display Flush Dirty operation. static KSTATUS KiDisplayFlushDirty(void) { if (!KiDisplayHasDevice() || !gPrimaryDisplay->Ops->Present) return STATUS_SUCCESS; @@ -207,6 +210,7 @@ static KSTATUS KiDisplayFlushDirty(void) { return s; } +// Implements the display Hide Cursor For Draw operation. static void KiDisplayHideCursorForDraw(void) { if (!gCursorDrawn || !KiDisplayUsesSoftwareCursor()) return; @@ -215,6 +219,7 @@ static void KiDisplayHideCursorForDraw(void) { gCursorDrawn = false; } +// Implements the display Restore Cursor After Draw operation. static void KiDisplayRestoreCursorAfterDraw(void) { if (!gCursorVisible || gCursorDrawn || !KiDisplayHasCursorOps()) return; @@ -226,11 +231,13 @@ static void KiDisplayRestoreCursorAfterDraw(void) { gCursorDrawn = true; } +// Implements the display Begin Draw operation. static void KiDisplayBeginDraw(void) { if (gDrawDepth++ == 0) KiDisplayHideCursorForDraw(); } +// Implements the display End Draw operation. static KSTATUS KiDisplayEndDraw(void) { KSTATUS s = STATUS_SUCCESS; if (gDrawDepth > 0) @@ -243,6 +250,7 @@ static KSTATUS KiDisplayEndDraw(void) { return s; } +// Implements the display Draw Blit No Cursor operation. static KSTATUS KiDisplayDrawBlitNoCursor(int x, int y, int w, int h, const uint32_t* pixels) { if (!pixels || w <= 0 || h <= 0) return STATUS_INVALID_PARAMETER; @@ -258,6 +266,7 @@ static KSTATUS KiDisplayDrawBlitNoCursor(int x, int y, int w, int h, const uint3 return s; } +// Implements the display Fill Rect No Cursor operation. static KSTATUS KiDisplayFillRectNoCursor(int x, int y, int w, int h, uint32_t color) { if (w <= 0 || h <= 0) return STATUS_INVALID_PARAMETER; @@ -273,6 +282,7 @@ static KSTATUS KiDisplayFillRectNoCursor(int x, int y, int w, int h, uint32_t co return s; } +// Implements the display Copy Rect No Cursor operation. static KSTATUS KiDisplayCopyRectNoCursor(int dstX, int dstY, int srcX, int srcY, int w, int h) { if (w <= 0 || h <= 0) return STATUS_INVALID_PARAMETER; @@ -288,10 +298,12 @@ static KSTATUS KiDisplayCopyRectNoCursor(int dstX, int dstY, int srcX, int srcY, return s; } +// Implements the display Console Index operation. static size_t KiDisplayConsoleIndex(int col, int row) { return (size_t)row * DISPLAY_CONSOLE_MAX_COLS + (size_t)col; } +// Implements the display Console Color operation. static uint32_t KiDisplayConsoleColor(uint8_t index) { static const uint32_t colors[16] = { 0x00000000u, 0x000000AAu, 0x0000AA00u, 0x0000AAAAu, @@ -302,14 +314,17 @@ static uint32_t KiDisplayConsoleColor(uint8_t index) { return colors[index & 0x0Fu]; } +// Implements the display Console Fg operation. static uint32_t KiDisplayConsoleFg(uint16_t attr) { return KiDisplayConsoleColor((uint8_t)(attr & 0x0Fu)); } +// Implements the display Console Bg operation. static uint32_t KiDisplayConsoleBg(uint16_t attr) { return KiDisplayConsoleColor((uint8_t)((attr >> 4) & 0x0Fu)); } +// Implements the display Get Console Grid Locked operation. static bool KiDisplayGetConsoleGridLocked(int* outCols, int* outRows) { DISPLAY_MODE mode; if (!KiDisplayHasDevice() || !gPrimaryDisplay->Ops->GetMode) @@ -329,6 +344,7 @@ static bool KiDisplayGetConsoleGridLocked(int* outCols, int* outRows) { return true; } +// Implements the display Console Reset Cells Locked operation. static void KiDisplayConsoleResetCellsLocked(void) { for (size_t i = 0; i < DISPLAY_CONSOLE_MAX_CELLS; i++) { gConsoleCells[i] = ' '; @@ -337,6 +353,7 @@ static void KiDisplayConsoleResetCellsLocked(void) { gConsoleAttribute = DISPLAY_CONSOLE_DEFAULT_ATTR; } +// Implements the display Console Scroll Cells Locked operation. static void KiDisplayConsoleScrollCellsLocked(int cols, int rows, int cellLines) { if (cols <= 0 || rows <= 0 || cellLines <= 0) return; @@ -370,6 +387,7 @@ static void KiDisplayConsoleScrollCellsLocked(int cols, int rows, int cellLines) } } +// Implements the display Draw Char Pixels Locked operation. static KSTATUS KiDisplayDrawCharPixelsLocked(char c, int x, int y, uint32_t fg, uint32_t bg) { uint32_t glyphPixels[FONT_W * FONT_H]; const uint8_t* glyph = Font8x16 + ((uint8_t)c * 16u); @@ -383,6 +401,7 @@ static KSTATUS KiDisplayDrawCharPixelsLocked(char c, int x, int y, uint32_t fg, return KiDisplayDrawBlitNoCursor(x, y, FONT_W, FONT_H, glyphPixels); } +// Implements the display Draw Console Cell Locked operation. static KSTATUS KiDisplayDrawConsoleCellLocked(int col, int row, char c, uint16_t attr, bool updateCell) { if (updateCell) { size_t i = KiDisplayConsoleIndex(col, row); @@ -395,6 +414,7 @@ static KSTATUS KiDisplayDrawConsoleCellLocked(int col, int row, char c, uint16_t KiDisplayConsoleBg(attr)); } +// Implements the display Serial Write Char operation. static void KiDisplaySerialWriteChar(char c) { while ((__inbyte(0x3FD) & 0x20) == 0) { } if (c == '\n') @@ -402,6 +422,7 @@ static void KiDisplaySerialWriteChar(char c) { __outbyte(0x3F8, (uint8_t)c); } +// Implements the display Initialize operation. void KeDisplayInitialize(const HAL_API* hal) { gDisplayHal = hal; gDisplayList = NULL; @@ -498,6 +519,7 @@ DISPLAY_API KSTATUS KeDisplayRegisterDevice(DISPLAY_DEVICE* device) { return result; } +// Implements the display Seed New Primary operation. static KSTATUS KiDisplaySeedNewPrimary(DISPLAY_DEVICE* oldDevice, DISPLAY_DEVICE* newDevice) { if (!oldDevice || !newDevice || oldDevice == newDevice) return STATUS_SUCCESS; @@ -540,6 +562,7 @@ DISPLAY_API void KeDisplaySuspendConsole(bool suspend) { _InterlockedExchange((volatile long*)&gDisplayConsoleSuspended, suspend ? 1 : 0); } +// Implements the display Output Suspended operation. static bool KiDisplayOutputSuspended(void) { return _InterlockedCompareExchange((volatile long*)&gDisplayConsoleSuspended, 0, 0) != 0; } @@ -644,6 +667,7 @@ DISPLAY_API KSTATUS KeDisplayFillRect(int x, int y, int w, int h, uint32_t color return KSUCCESS(s) ? ps : s; } +// Implements the display Clear Locked operation. static KSTATUS KiDisplayClearLocked(uint32_t color) { DISPLAY_MODE mode; if (!KiDisplayHasDevice() || !gPrimaryDisplay->Ops->GetMode) @@ -675,6 +699,7 @@ DISPLAY_API KSTATUS KeDisplayCopyRect(int dstX, int dstY, int srcX, int srcY, in return KSUCCESS(s) ? ps : s; } +// Implements the display Scroll Locked operation. static KSTATUS KiDisplayScrollLocked(int lines) { if (lines <= 0) return STATUS_SUCCESS; @@ -705,6 +730,7 @@ DISPLAY_API KSTATUS KeDisplayScroll(int lines) { return s; } +// Implements the display Put Char Locked operation. static KSTATUS KiDisplayPutCharLocked(char c, int x, int y, uint32_t fg, uint32_t bg) { KiDisplayBeginDraw(); KSTATUS s = KiDisplayDrawCharPixelsLocked(c, x, y, fg, bg); @@ -789,6 +815,7 @@ DISPLAY_API KSTATUS KeDisplayPrintChar(char c, uint32_t fg, uint32_t bg) { return STATUS_SUCCESS; } +// Implements the display Debug Print Char operation. void KeDisplayDebugPrintChar(char c, uint32_t fg, uint32_t bg) { (void)KeDisplayPrintChar(c, fg, bg); } @@ -1069,10 +1096,12 @@ DISPLAY_API KSTATUS KeDisplayShowCursor(bool show) { return s; } +// Implements the boot Fb Context operation. static BOOTFB_CONTEXT* BootFbContext(DISPLAY_DEVICE* device) { return device ? (BOOTFB_CONTEXT*)device->DriverContext : NULL; } +// Implements the boot Fb Get Mode operation. static KSTATUS BootFbGetMode(DISPLAY_DEVICE* device, DISPLAY_MODE* outMode) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !fb->Framebuffer || !outMode) @@ -1085,6 +1114,7 @@ static KSTATUS BootFbGetMode(DISPLAY_DEVICE* device, DISPLAY_MODE* outMode) { return STATUS_SUCCESS; } +// Implements the boot Fb Blit operation. static KSTATUS BootFbBlit(DISPLAY_DEVICE* device, int x, int y, int w, int h, const uint32_t* pixels) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !fb->Framebuffer || !pixels || w <= 0 || h <= 0) @@ -1114,6 +1144,7 @@ static KSTATUS BootFbBlit(DISPLAY_DEVICE* device, int x, int y, int w, int h, co return STATUS_SUCCESS; } +// Implements the boot Fb Fill Rect operation. static KSTATUS BootFbFillRect(DISPLAY_DEVICE* device, int x, int y, int w, int h, uint32_t color) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !fb->Framebuffer || w <= 0 || h <= 0) @@ -1139,6 +1170,7 @@ static KSTATUS BootFbFillRect(DISPLAY_DEVICE* device, int x, int y, int w, int h return STATUS_SUCCESS; } +// Implements the boot Fb Copy Rect operation. static KSTATUS BootFbCopyRect(DISPLAY_DEVICE* device, int dstX, int dstY, int srcX, int srcY, int w, int h) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !fb->Framebuffer || w <= 0 || h <= 0) @@ -1177,6 +1209,7 @@ static KSTATUS BootFbCopyRect(DISPLAY_DEVICE* device, int dstX, int dstY, int sr return STATUS_SUCCESS; } +// Implements the boot Fb Read Rect operation. static KSTATUS BootFbReadRect(DISPLAY_DEVICE* device, int x, int y, int w, int h, uint32_t* outPixels, uint32_t outStride) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !fb->Framebuffer || !outPixels || outStride == 0 || w <= 0 || h <= 0) @@ -1201,6 +1234,7 @@ static KSTATUS BootFbReadRect(DISPLAY_DEVICE* device, int x, int y, int w, int h return STATUS_SUCCESS; } +// Implements the boot Fb Present operation. static KSTATUS BootFbPresent(DISPLAY_DEVICE* device, const DISPLAY_RECT* rects, size_t rectCount) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !fb->Framebuffer) @@ -1231,12 +1265,14 @@ static KSTATUS BootFbPresent(DISPLAY_DEVICE* device, const DISPLAY_RECT* rects, return STATUS_SUCCESS; } +// Implements the boot Fb Sync operation. static KSTATUS BootFbSync(DISPLAY_DEVICE* device) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (fb) fb->Stats.SyncCount++; return STATUS_SUCCESS; } +// Implements the boot Fb Set Cursor Image operation. static KSTATUS BootFbSetCursorImage(DISPLAY_DEVICE* device, int width, int height, int hotX, int hotY, const uint32_t* argbPixels) { (void)device; (void)width; @@ -1247,6 +1283,7 @@ static KSTATUS BootFbSetCursorImage(DISPLAY_DEVICE* device, int width, int heigh return STATUS_NOT_SUPPORTED; } +// Implements the boot Fb Set Cursor Position operation. static KSTATUS BootFbSetCursorPosition(DISPLAY_DEVICE* device, int x, int y) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (fb) fb->Stats.CursorMoveCount++; @@ -1255,6 +1292,7 @@ static KSTATUS BootFbSetCursorPosition(DISPLAY_DEVICE* device, int x, int y) { return STATUS_SUCCESS; } +// Implements the display Blend Pixel operation. static inline uint32_t KiDisplayBlendPixel(uint32_t dst, uint32_t src) { uint8_t a = (uint8_t)(src >> 24); if (a == 0) return dst; @@ -1273,6 +1311,7 @@ static inline uint32_t KiDisplayBlendPixel(uint32_t dst, uint32_t src) { return ((uint32_t)rr << 16) | ((uint32_t)gg << 8) | bb; } +// Implements the boot Fb Restore Cursor operation. static void BootFbRestoreCursor(BOOTFB_CONTEXT* fb) { if (!fb || !fb->Framebuffer || !fb->Backbuffer || gCursorDrawX < 0) return; @@ -1291,6 +1330,7 @@ static void BootFbRestoreCursor(BOOTFB_CONTEXT* fb) { gCursorDrawY = -1; } +// Implements the boot Fb Draw Cursor operation. static void BootFbDrawCursor(BOOTFB_CONTEXT* fb, int x, int y) { if (!fb || !fb->Framebuffer || !fb->Backbuffer) return; @@ -1315,6 +1355,7 @@ static void BootFbDrawCursor(BOOTFB_CONTEXT* fb, int x, int y) { } } +// Implements the boot Fb Show Cursor operation. static KSTATUS BootFbShowCursor(DISPLAY_DEVICE* device, bool show) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !fb->Framebuffer || !fb->Backbuffer) @@ -1330,6 +1371,7 @@ static KSTATUS BootFbShowCursor(DISPLAY_DEVICE* device, bool show) { return STATUS_SUCCESS; } +// Implements the boot Fb Query Stats operation. static KSTATUS BootFbQueryStats(DISPLAY_DEVICE* device, DISPLAY_STATS* outStats) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !outStats) diff --git a/code/kernel/ke_dpc.c b/code/kernel/ke_dpc.c index d679e8e..71878bb 100644 --- a/code/kernel/ke_dpc.c +++ b/code/kernel/ke_dpc.c @@ -1,4 +1,5 @@ -// ke_dpc.c - deferred procedure calls +// Deferred procedure call infrastructure. This file owns DPC queuing and execution outside hard IRQ context. + #include #include #include @@ -9,6 +10,7 @@ static SPINLOCK gDpcLock; static volatile long gDpcInitialized = 0; static volatile long gDpcActive = 0; +// Initializes dpc System. void KeInitializeDpcSystem(void) { LIST_INIT(&gDpcQueue); gDpcLock = (SPINLOCK)SPINLOCK_INIT; @@ -16,6 +18,7 @@ void KeInitializeDpcSystem(void) { gDpcInitialized = 1; } +// Implements the ensure Dpc Initialized operation. static void KiEnsureDpcInitialized(void) { if (gDpcInitialized) return; @@ -60,6 +63,7 @@ __declspec(dllexport) bool KeInsertQueueDpc(KDPC* dpc, return true; } +// Implements the drain Dpc Queue operation. void KiDrainDpcQueue(void) { if (!gDpcInitialized) return; diff --git a/code/kernel/ke_event.c b/code/kernel/ke_event.c index 537330f..458d7f6 100644 --- a/code/kernel/ke_event.c +++ b/code/kernel/ke_event.c @@ -1,4 +1,5 @@ -// ke_event.c - synchronisation events +// Kernel event primitive. This file owns manual-reset event state and waiter wakeups. + #include #include #include @@ -7,8 +8,10 @@ #include #include +// Implements the event Destroy operation. static void KiEventDestroy(OBJECT* obj) { (void)obj; } +// Implements the event Create operation. __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)); @@ -22,6 +25,7 @@ __declspec(dllexport) KSTATUS KeEventCreate(EVENT_TYPE type, uint32_t initialSta return STATUS_SUCCESS; } +// Signals event. __declspec(dllexport) void KeSignalEvent(EVENT* event) { if (!event) return; uintptr_t flags = KeAcquireSpinlock(&event->Lock); @@ -52,6 +56,7 @@ __declspec(dllexport) void KeSignalEvent(EVENT* event) { KeReleaseSpinlock(&event->Lock, flags); } +// Clears event. __declspec(dllexport) void KeClearEvent(EVENT* event) { if (!event) return; uintptr_t flags = KeAcquireSpinlock(&event->Lock); @@ -59,6 +64,7 @@ __declspec(dllexport) void KeClearEvent(EVENT* event) { KeReleaseSpinlock(&event->Lock, flags); } +// Waits for for Event. __declspec(dllexport) KSTATUS KeWaitForEvent(EVENT* event, uint8_t alertable) { if (!event) return STATUS_INVALID_PARAMETER; if (!KeCanWait()) return STATUS_INVALID_IRQL; diff --git a/code/kernel/ke_idt.c b/code/kernel/ke_idt.c index b43d656..fbb58ac 100644 --- a/code/kernel/ke_idt.c +++ b/code/kernel/ke_idt.c @@ -1,5 +1,5 @@ -// ke_idt.c - GDT, IDT, and TSS initialisation -// +// Kernel descriptor-table setup. This file owns GDT, IDT, and TSS initialization. + // GDT layout (matches segment selectors in ke_switch.asm / ke_syscall.asm): // 0x00 null // 0x08 ring-0 code (64-bit) @@ -7,13 +7,13 @@ // 0x18 ring-3 code (64-bit, DPL=3) // 0x20 ring-3 data (DPL=3) - note: 0x1B/0x23 = 0x18|3 / 0x20|3 // 0x28 TSS low -// 0x30 TSS high +// 0x30 TSS high. #include #include #include #include -// External assembly procedures +// External assembly procedures. extern void KeFlushGdt(void* pGdtr, uint16_t codeSel, uint16_t dataSel, uint16_t tssSel); extern void KeFlushIdt(void* pIdtr); @@ -76,9 +76,7 @@ extern void KeFaultRSV31(void); #define NUM_IRQS 24 -// --------------------------------------------------------------------------- -// GDT -// --------------------------------------------------------------------------- +// GDT. static void KiGdtSetEntry(uint64_t* gdt, int idx, uint32_t base, uint32_t limit, uint8_t access, uint8_t flags) { gdt[idx] = @@ -90,6 +88,7 @@ static void KiGdtSetEntry(uint64_t* gdt, int idx, uint32_t base, uint32_t limit, ((uint64_t)(base >> 24 & 0xFF)<< 56); } +// Implements the gdt Set Tss operation. static void KiGdtSetTss(uint64_t* gdt, int idx, uintptr_t base, uint32_t limit) { // TSS descriptor is 16 bytes (two GDT slots). gdt[idx] = 0; @@ -105,6 +104,7 @@ static void KiGdtSetTss(uint64_t* gdt, int idx, uintptr_t base, uint32_t limit) gdt[idx+1] = (base >> 32); } +// Initializes gdt For Cpu. void KeInitializeGdtForCpu(KCPU* cpu) { if (!cpu) return; @@ -113,15 +113,15 @@ void KeInitializeGdtForCpu(KCPU* cpu) { memset(gdt, 0, sizeof(cpu->Gdt)); - // 0x00: Null + // 0x00: Null. KiGdtSetEntry(gdt, 0, 0, 0, 0, 0); - // 0x08: Ring-0 Code (Access 0x9A, Flags 0xA for 64-bit) + // 0x08: Ring-0 Code (Access 0x9A, Flags 0xA for 64-bit). KiGdtSetEntry(gdt, 1, 0, 0xFFFFF, 0x9A, 0xA); - // 0x10: Ring-0 Data + // 0x10: Ring-0 Data. KiGdtSetEntry(gdt, 2, 0, 0xFFFFF, 0x92, 0xC); - // 0x18: Ring-3 Code + // 0x18: Ring-3 Code. KiGdtSetEntry(gdt, 3, 0, 0xFFFFF, 0xFA, 0xA); - // 0x20: Ring-3 Data + // 0x20: Ring-3 Data. KiGdtSetEntry(gdt, 4, 0, 0xFFFFF, 0xF2, 0xC); // 0x28: CPU-local TSS (occupies slots 0x28 and 0x30). @@ -135,6 +135,7 @@ void KeInitializeGdtForCpu(KCPU* cpu) { cpu->Gdtr.Base = (uint64_t)cpu->Gdt; } +// Loads gdt For Current Cpu. void KeLoadGdtForCurrentCpu(KCPU* cpu) { if (!cpu) cpu = KeGetCurrentCpu(); KeFlushGdt(&cpu->Gdtr, 0x08, 0x10, 0x28); @@ -145,21 +146,21 @@ void KeLoadGdtForCurrentCpu(KCPU* cpu) { KeLoadKernelGsBase(cpu); } +// Initializes gdt. void KeInitializeGdt(void) { KCPU* cpu = KeGetCurrentCpu(); KeInitializeGdtForCpu(cpu); KeLoadGdtForCurrentCpu(cpu); } +// Updates current Tss Rsp0. void KeSetCurrentTssRsp0(uintptr_t rsp0) { TSS64* tss = KeGetCurrentTss(); if (tss) tss->RSP0 = rsp0; } -// --------------------------------------------------------------------------- -// IDT -// --------------------------------------------------------------------------- +// IDT. #define IDT_ENTRIES 256 #pragma pack(push, 1) @@ -191,6 +192,7 @@ static void KiIdtSetGate(int vec, uintptr_t handler, gIdt[vec].MustBeZero = 0; } +// Initializes idt. void KeInitializeIdt(void) { memset(gIdt, 0, sizeof(gIdt)); @@ -231,6 +233,7 @@ void KeInitializeIdt(void) { KeLoadIdtForCurrentCpu(); } +// Loads idt For Current Cpu. void KeLoadIdtForCurrentCpu(void) { IDTR idtr = { sizeof(gIdt) - 1, (uint64_t)gIdt }; KeFlushIdt(&idtr); diff --git a/code/kernel/ke_input.c b/code/kernel/ke_input.c index 2a0a29d..b1bebc5 100644 --- a/code/kernel/ke_input.c +++ b/code/kernel/ke_input.c @@ -1,4 +1,5 @@ -// ke_input.c - kernel-owned canonical input core +// Kernel input core. This file owns canonical keyboard and mouse state shared by input drivers and syscalls. + #include #include #include @@ -76,6 +77,7 @@ static const KEY_CHAR_PAIR gCharMap[] = { { INPUT_KEY_KP_0, '0', '0' }, { INPUT_KEY_KP_PERIOD, '.', '.' }, }; +// Implements the input Queue Key operation. static void KiInputQueueKey(INPUT_KEY key, char ch) { if (key == INPUT_KEY_NONE) return; int next = (gKeyTail + 1) & (int)KEY_QUEUE_MASK; @@ -85,11 +87,13 @@ static void KiInputQueueKey(INPUT_KEY key, char ch) { gKeyTail = next; } +// Implements the input Queue Has Space operation. static bool KiInputQueueHasSpace(void) { int next = (gKeyTail + 1) & (int)KEY_QUEUE_MASK; return next != gKeyHead; } +// Implements the input Key Is Repeatable operation. static bool KiInputKeyIsRepeatable(INPUT_KEY key) { if (key == INPUT_KEY_NONE) return false; @@ -110,18 +114,21 @@ static bool KiInputKeyIsRepeatable(INPUT_KEY key) { } } +// Implements the input Now Ticks operation. static uint64_t KiInputNowTicks(void) { if (gInputHal && gInputHal->Timer.QueryTicks) return gInputHal->Timer.QueryTicks(); return 0; } +// Implements the input Start Repeat operation. static void KiInputStartRepeat(INPUT_KEY key, uint64_t now) { if (!KiInputKeyIsRepeatable(key)) return; gRepeatKey = key; gRepeatNextTick = now + KEY_REPEAT_DELAY_US; } +// Implements the input Stop Repeat operation. static void KiInputStopRepeat(INPUT_KEY key) { if (gRepeatKey == key) { gRepeatKey = INPUT_KEY_NONE; @@ -129,6 +136,7 @@ static void KiInputStopRepeat(INPUT_KEY key) { } } +// Implements the input Service Repeat operation. static void KiInputServiceRepeat(void) { INPUT_KEY key = gRepeatKey; if (!KiInputKeyIsRepeatable(key) || key >= MAX_INPUT_KEYS || !gKeyDown[key]) { @@ -150,6 +158,7 @@ static void KiInputServiceRepeat(void) { gRepeatNextTick = now + KEY_REPEAT_PERIOD_US; } +// Implements the input Set Modifier operation. static void KiInputSetModifier(INPUT_KEY key, bool pressed) { uint32_t bit = 0; switch (key) { @@ -173,6 +182,7 @@ static void KiInputSetModifier(INPUT_KEY key, bool pressed) { if (pressed && key == INPUT_KEY_NUM_LOCK) gModifiers ^= INPUT_MOD_NUM_LOCK; } +// Implements the input Key To Char operation. static char KiInputKeyToChar(INPUT_KEY key) { if (key >= INPUT_KEY_A && key <= INPUT_KEY_Z) { bool shifted = (gModifiers & INPUT_MOD_SHIFT) != 0; @@ -190,6 +200,7 @@ static char KiInputKeyToChar(INPUT_KEY key) { return 0; } +// Implements the input Initialize operation. void KeInputInitialize(const HAL_API* hal) { gInputHal = hal; memset((void*)gKeyDown, 0, sizeof(gKeyDown)); @@ -214,6 +225,7 @@ void KeInputInitialize(const HAL_API* hal) { DbgPrint("Input: kernel input core initialized (%dx%d)\n", w, h); } +// Implements the input Register Device operation. __declspec(dllexport) KSTATUS KeInputRegisterDevice(const char* name, uint32_t flags, uint32_t* outDeviceId) { (void)flags; uint32_t id = gNextInputDeviceId++; @@ -223,6 +235,7 @@ __declspec(dllexport) KSTATUS KeInputRegisterDevice(const char* name, uint32_t f return STATUS_SUCCESS; } +// Implements the input Submit Key operation. __declspec(dllexport) void KeInputSubmitKey(const INPUT_KEY_EVENT* event) { if (!event) return; INPUT_KEY key = event->Key; @@ -251,6 +264,7 @@ __declspec(dllexport) void KeInputSubmitKey(const INPUT_KEY_EVENT* event) { } } +// Implements the input Commit Mouse Position operation. static void KiInputCommitMousePosition(int nx, int ny, uint8_t buttons) { int bw = gMouseBoundsW; int bh = gMouseBoundsH; @@ -268,6 +282,7 @@ static void KiInputCommitMousePosition(int nx, int ny, uint8_t buttons) { KeDisplaySetCursorPosition(nx, ny); } +// Implements the input Submit Mouse operation. __declspec(dllexport) void KeInputSubmitMouse(const INPUT_MOUSE_EVENT* event) { if (!event) return; @@ -285,6 +300,7 @@ __declspec(dllexport) void KeInputSubmitMouse(const INPUT_MOUSE_EVENT* event) { } } +// Implements the input Submit Mouse Absolute operation. __declspec(dllexport) void KeInputSubmitMouseAbsolute(const INPUT_MOUSE_ABSOLUTE_EVENT* event) { if (!event) return; @@ -305,6 +321,7 @@ __declspec(dllexport) void KeInputSubmitMouseAbsolute(const INPUT_MOUSE_ABSOLUTE } } +// Implements the input Submit Mouse Absolute Scaled operation. __declspec(dllexport) void KeInputSubmitMouseAbsoluteScaled(uint32_t rawX, uint32_t rawY, uint32_t maxX, uint32_t maxY, int wheel, uint8_t buttons) { int bw = gMouseBoundsW; int bh = gMouseBoundsH; @@ -324,6 +341,7 @@ INPUT_KEY KeInputKbPoll(void) { return (gKeyHead == gKeyTail) ? INPUT_KEY_NONE : gKeyQueue[gKeyHead].key; } +// Implements the input Is Key Down operation. bool KeInputIsKeyDown(INPUT_KEY key) { if (key == INPUT_KEY_NONE || key >= MAX_INPUT_KEYS) return false; return gKeyDown[key] != 0; @@ -337,6 +355,7 @@ INPUT_KEY KeInputReadKey(void) { return key; } +// Implements the input Read Char operation. char KeInputReadChar(void) { if (gKeyHead == gKeyTail) KiInputServiceRepeat(); if (gKeyHead == gKeyTail) return 0; @@ -345,14 +364,17 @@ char KeInputReadChar(void) { return ch; } +// Implements the input Get Modifiers operation. uint32_t KeInputGetModifiers(void) { return gModifiers; } +// Implements the input Mouse Poll operation. bool KeInputMousePoll(void) { return gMouseHead != gMouseTail; } +// Implements the input Mouse Read operation. bool KeInputMouseRead(int* dx, int* dy, uint8_t* buttons) { if (!dx || !dy || !buttons) return false; if (gMouseHead == gMouseTail) return false; @@ -365,11 +387,13 @@ bool KeInputMouseRead(int* dx, int* dy, uint8_t* buttons) { return true; } +// Implements the input Mouse Get Position operation. void KeInputMouseGetPosition(int* x, int* y) { if (x) *x = gMouseX; if (y) *y = gMouseY; } +// Implements the input Mouse Set Position operation. void KeInputMouseSetPosition(int x, int y) { int bw = gMouseBoundsW; int bh = gMouseBoundsH; @@ -384,6 +408,7 @@ void KeInputMouseSetPosition(int x, int y) { KeDisplaySetCursorPosition(x, y); } +// Implements the input Mouse Set Bounds operation. void KeInputMouseSetBounds(int w, int h) { if (w < 1) w = 1; if (h < 1) h = 1; diff --git a/code/kernel/ke_irp.c b/code/kernel/ke_irp.c index f1cbdda..b565caa 100644 --- a/code/kernel/ke_irp.c +++ b/code/kernel/ke_irp.c @@ -1,4 +1,4 @@ -// ke_irp.c - I/O Request Packet dispatch, queue, cancellation, remove-locks +// I/O request packet infrastructure. This file owns IRP dispatch, queuing, cancellation, and remove-lock helpers. #include #include @@ -10,9 +10,7 @@ #include #include -// ------------------------------------------------------------------------- -// IRP_QUEUE operations -// ------------------------------------------------------------------------- +// IRP_QUEUE operations. __declspec(dllexport) void IrpQueueInit(IRP_QUEUE* q, struct SEMAPHORE* sem) { q->Lock = (SPINLOCK)SPINLOCK_INIT; @@ -20,6 +18,7 @@ __declspec(dllexport) void IrpQueueInit(IRP_QUEUE* q, struct SEMAPHORE* sem) { LIST_INIT(&q->Head); } +// Implements the irp Queue Enqueue operation. __declspec(dllexport) void IrpQueueEnqueue(IRP_QUEUE* q, IRP* irp) { uintptr_t flags = KeAcquireSpinlock(&q->Lock); if (irp->Flags & IRP_FLAG_PRIORITY) @@ -30,6 +29,7 @@ __declspec(dllexport) void IrpQueueEnqueue(IRP_QUEUE* q, IRP* irp) { KeSignalSemaphore((SEMAPHORE*)q->Semaphore); } +// Implements the irp Queue Dequeue operation. __declspec(dllexport) IRP* IrpQueueDequeue(IRP_QUEUE* q) { uintptr_t flags = KeAcquireSpinlock(&q->Lock); LIST_ENTRY* node = ListPopHead(&q->Head); @@ -58,13 +58,12 @@ __declspec(dllexport) void IrpQueueCancelAllEx(IRP_QUEUE* q, } } +// Implements the irp Queue Cancel All operation. __declspec(dllexport) void IrpQueueCancelAll(IRP_QUEUE* q, KSTATUS status) { IrpQueueCancelAllEx(q, status, (IRP_QUEUE_CANCEL_CALLBACK)0, (void*)0); } -// ------------------------------------------------------------------------- -// Remove locks -// ------------------------------------------------------------------------- +// Remove locks. __declspec(dllexport) KSTATUS IoInitializeRemoveLock(IO_REMOVE_LOCK* lock) { if (!lock) return STATUS_INVALID_PARAMETER; @@ -76,6 +75,7 @@ __declspec(dllexport) KSTATUS IoInitializeRemoveLock(IO_REMOVE_LOCK* lock) { return STATUS_SUCCESS; } +// Releases remove Lock. __declspec(dllexport) void IoDestroyRemoveLock(IO_REMOVE_LOCK* lock) { if (!lock) return; if (lock->RemovedEvent) { @@ -84,6 +84,7 @@ __declspec(dllexport) void IoDestroyRemoveLock(IO_REMOVE_LOCK* lock) { } } +// Implements the acquire Remove Lock operation. __declspec(dllexport) KSTATUS IoAcquireRemoveLock(IO_REMOVE_LOCK* lock, IRP* irp) { (void)irp; if (!lock) return STATUS_INVALID_PARAMETER; @@ -97,6 +98,7 @@ __declspec(dllexport) KSTATUS IoAcquireRemoveLock(IO_REMOVE_LOCK* lock, IRP* irp return STATUS_SUCCESS; } +// Releases remove Lock. __declspec(dllexport) void IoReleaseRemoveLock(IO_REMOVE_LOCK* lock, IRP* irp) { (void)irp; if (!lock) return; @@ -105,6 +107,7 @@ __declspec(dllexport) void IoReleaseRemoveLock(IO_REMOVE_LOCK* lock, IRP* irp) { KeSignalEvent(lock->RemovedEvent); } +// Releases remove Lock And Wait. __declspec(dllexport) void IoReleaseRemoveLockAndWait(IO_REMOVE_LOCK* lock, IRP* removeIrp) { (void)removeIrp; if (!lock) return; @@ -124,15 +127,14 @@ __declspec(dllexport) void IoReleaseRemoveLockAndWait(IO_REMOVE_LOCK* lock, IRP* KeWaitForEvent(lock->RemovedEvent, 0); } -// ------------------------------------------------------------------------- -// IRP helpers -// ------------------------------------------------------------------------- +// IRP helpers. static size_t IoIrpSize(uint8_t stackCount) { if (stackCount == 0) stackCount = 1; return sizeof(IRP) + ((size_t)stackCount - 1u) * sizeof(IO_STACK_LOCATION); } +// Creates irp. __declspec(dllexport) KSTATUS IoAllocateIrp(uint8_t stackCount, IRP** outIrp) { if (!outIrp) return STATUS_INVALID_PARAMETER; if (stackCount == 0) stackCount = 1; @@ -143,10 +145,12 @@ __declspec(dllexport) KSTATUS IoAllocateIrp(uint8_t stackCount, IRP** outIrp) { return STATUS_SUCCESS; } +// Releases irp. __declspec(dllexport) void IoFreeIrp(IRP* irp) { if (irp) MmFreePool(irp); } +// Initializes irp. __declspec(dllexport) void IoInitializeIrp(IRP* irp, uint8_t stackCount) { if (!irp) return; if (stackCount == 0) stackCount = 1; @@ -159,22 +163,26 @@ __declspec(dllexport) void IoInitializeIrp(IRP* irp, uint8_t stackCount) { irp->CurrentLocation = 0; } +// Returns current Irp Stack Location. __declspec(dllexport) IO_STACK_LOCATION* IoGetCurrentIrpStackLocation(IRP* irp) { if (!irp || irp->CurrentLocation >= irp->StackCount) return (IO_STACK_LOCATION*)0; return &irp->Stack[irp->CurrentLocation]; } +// Returns next Irp Stack Location. __declspec(dllexport) IO_STACK_LOCATION* IoGetNextIrpStackLocation(IRP* irp) { if (!irp || irp->CurrentLocation + 1u >= irp->StackCount) return (IO_STACK_LOCATION*)0; return &irp->Stack[irp->CurrentLocation + 1u]; } +// Implements the skip Current Irp Stack Location operation. __declspec(dllexport) void IoSkipCurrentIrpStackLocation(IRP* irp) { if (!irp) return; if (irp->CurrentLocation + 1u < irp->StackCount) irp->CurrentLocation++; } +// Copies current Irp Stack Location To Next. __declspec(dllexport) void IoCopyCurrentIrpStackLocationToNext(IRP* irp) { IO_STACK_LOCATION* cur = IoGetCurrentIrpStackLocation(irp); IO_STACK_LOCATION* next = IoGetNextIrpStackLocation(irp); @@ -183,12 +191,14 @@ __declspec(dllexport) void IoCopyCurrentIrpStackLocationToNext(IRP* irp) { irp->CurrentLocation++; } +// Updates completion Routine. __declspec(dllexport) void IoSetCompletionRoutine(IRP* irp, IRP_COMPLETION_FN fn, void* ctx) { if (!irp) return; irp->CompletionFn = fn; irp->CompletionCtx = ctx; } +// Updates cancel Routine. __declspec(dllexport) IRP_CANCEL_ROUTINE IoSetCancelRoutine(IRP* irp, IRP_CANCEL_ROUTINE routine) { if (!irp) return (IRP_CANCEL_ROUTINE)0; uintptr_t flags = KeAcquireSpinlock(&irp->CancelLock); @@ -198,6 +208,7 @@ __declspec(dllexport) IRP_CANCEL_ROUTINE IoSetCancelRoutine(IRP* irp, IRP_CANCEL return old; } +// Cancels irp. __declspec(dllexport) void IoCancelIrp(IRP* irp) { if (!irp) return; @@ -262,9 +273,7 @@ __declspec(dllexport) void IoBuildDeviceIoControlIrp(IRP* irp, ios->Parameters.DeviceIoControl.OutputLength = outputLength; } -// ------------------------------------------------------------------------- -// Completion/submission -// ------------------------------------------------------------------------- +// Completion/submission. __declspec(dllexport) KSTATUS IoCompleteRequest(IRP* irp, KSTATUS status, size_t information) { if (!irp) return STATUS_INVALID_PARAMETER; @@ -293,6 +302,7 @@ __declspec(dllexport) KSTATUS IoCompleteRequest(IRP* irp, KSTATUS status, size_t return STATUS_SUCCESS; } +// Submits irp. __declspec(dllexport) KSTATUS IoSubmitIrp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return STATUS_INVALID_PARAMETER; irp->Status = STATUS_FAILURE; @@ -301,6 +311,7 @@ __declspec(dllexport) KSTATUS IoSubmitIrp(DEVICE_OBJECT* device, IRP* irp) { return IoCallDriver(device, irp); } +// Submits irp Sync. __declspec(dllexport) KSTATUS IoSubmitIrpSync(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return STATUS_INVALID_PARAMETER; diff --git a/code/kernel/ke_irq.c b/code/kernel/ke_irq.c index 24abff8..35f969f 100644 --- a/code/kernel/ke_irq.c +++ b/code/kernel/ke_irq.c @@ -1,4 +1,5 @@ -// ke_irq.c - IRQ dispatch, kernel-side +// Interrupt manager. This file owns IRQ routing, handler dispatch, and post-interrupt scheduling hooks. + #include #include #include @@ -24,6 +25,7 @@ static IRQ_HANDLER_LIST gIrqHandlers[MAX_IRQS]; static bool gIrqSoftwareVector[MAX_IRQS]; static const HAL_API *gHal; +// Implements the irq To Irql operation. static KIRQL KiIrqToIrql(uint8_t irq) { uint32_t level = (uint32_t)DIRQL_BASE + (uint32_t)irq; if (level >= HIGH_LEVEL) @@ -31,10 +33,12 @@ static KIRQL KiIrqToIrql(uint8_t irq) { return (KIRQL)level; } +// Implements the irq Initialize operation. void KeIrqInitialize(const HAL_API *hal) { gHal = hal; } +// Implements the irq Allocate Msi Vector operation. __declspec(dllexport) KSTATUS KeIrqAllocateMsiVector(uint8_t* outIrq) { if (!outIrq) return STATUS_INVALID_PARAMETER; @@ -52,6 +56,7 @@ __declspec(dllexport) KSTATUS KeIrqAllocateMsiVector(uint8_t* outIrq) { return STATUS_NO_MEMORY; } +// Implements the irq Register operation. __declspec(dllexport) void KeIrqRegister(uint8_t irq, void (*handler)(void)) { if (irq >= MAX_IRQS || !handler) return; @@ -71,6 +76,7 @@ __declspec(dllexport) void KeIrqRegister(uint8_t irq, void (*handler)(void)) { gHal->Intc.RouteIrq(irq); } +// Implements the irq Dispatch operation. void KeIrqDispatch(uint8_t irq) { KIRQL targetIrql = KiIrqToIrql(irq); KIRQL currentIrql = KeGetCurrentIrql(); @@ -103,10 +109,12 @@ void KeIrqDispatch(uint8_t irq) { KeLowerIrql(oldIrql); } +// Implements the enter Interrupt operation. void KiEnterInterrupt(void) { KeGetCurrentCpu()->InterruptDepth++; } +// Implements the exit Interrupt operation. void KiExitInterrupt(void) { KCPU* cpu = KeGetCurrentCpu(); if (cpu->InterruptDepth) diff --git a/code/kernel/ke_irql.c b/code/kernel/ke_irql.c index fa4149c..b3fa396 100644 --- a/code/kernel/ke_irql.c +++ b/code/kernel/ke_irql.c @@ -1,9 +1,11 @@ -// ke_irql.c - software IRQL skeleton +// Kernel IRQL model. This file owns the software interrupt-priority state used by IRQ and scheduler code. + #include #include #include #include +// Implements the irql Name operation. __declspec(dllexport) const char* KeIrqlName(KIRQL irql) { switch (irql) { case PASSIVE_LEVEL: return "PASSIVE_LEVEL"; @@ -17,10 +19,12 @@ __declspec(dllexport) const char* KeIrqlName(KIRQL irql) { } } +// Returns current Irql. __declspec(dllexport) KIRQL KeGetCurrentIrql(void) { return KeGetCurrentCpu()->CurrentIrql; } +// Implements the raise Irql operation. __declspec(dllexport) KIRQL KeRaiseIrql(KIRQL newIrql) { KCPU* cpu = KeGetCurrentCpu(); KIRQL oldIrql = cpu->CurrentIrql; @@ -39,6 +43,7 @@ __declspec(dllexport) KIRQL KeRaiseIrql(KIRQL newIrql) { return oldIrql; } +// Implements the lower Irql operation. __declspec(dllexport) void KeLowerIrql(KIRQL oldIrql) { KCPU* cpu = KeGetCurrentCpu(); KIRQL currentIrql = cpu->CurrentIrql; @@ -59,6 +64,7 @@ __declspec(dllexport) void KeLowerIrql(KIRQL oldIrql) { KiDeliverKernelApcs(); } +// Implements the assert Irql operation. __declspec(dllexport) void KeAssertIrql(KIRQL expected) { KIRQL currentIrql = KeGetCurrentIrql(); if (currentIrql != expected) { @@ -68,6 +74,7 @@ __declspec(dllexport) void KeAssertIrql(KIRQL expected) { } } +// Implements the assert Irql At Or Below operation. __declspec(dllexport) void KeAssertIrqlAtOrBelow(KIRQL maxIrql) { KIRQL currentIrql = KeGetCurrentIrql(); if (currentIrql > maxIrql) { @@ -77,6 +84,7 @@ __declspec(dllexport) void KeAssertIrqlAtOrBelow(KIRQL maxIrql) { } } +// Checks whether wait. __declspec(dllexport) int KeCanWait(void) { return KeGetCurrentIrql() == PASSIVE_LEVEL; } diff --git a/code/kernel/ke_mutex.c b/code/kernel/ke_mutex.c index a37cb45..1d1b034 100644 --- a/code/kernel/ke_mutex.c +++ b/code/kernel/ke_mutex.c @@ -1,4 +1,5 @@ -// ke_mutex.c - binary ownership mutex +// Kernel mutex primitive. This file owns exclusive ownership, wait queues, and priority-aware wakeups. + #include #include #include @@ -7,8 +8,10 @@ #include #include +// Implements the mutex Destroy operation. static void KiMutexDestroy(OBJECT* obj) { (void)obj; } +// Implements the mutex Create operation. KSTATUS KeMutexCreate(MUTEX **out) { if (!out) return STATUS_INVALID_PARAMETER; MUTEX* m = (MUTEX *)ObAllocateObject(ObjectTypeMutex, sizeof(MUTEX)); @@ -21,6 +24,7 @@ KSTATUS KeMutexCreate(MUTEX **out) { return STATUS_SUCCESS; } +// Implements the acquire Mutex operation. KSTATUS KeAcquireMutex(MUTEX* mutex) { if (!mutex) return STATUS_INVALID_PARAMETER; if (!KeCanWait()) return STATUS_INVALID_IRQL; @@ -40,6 +44,7 @@ KSTATUS KeAcquireMutex(MUTEX* mutex) { return KeCommitBlockThread(self, 0); } +// Implements the try Acquire Mutex operation. KSTATUS KeTryAcquireMutex(MUTEX* mutex) { if (!mutex) return STATUS_INVALID_PARAMETER; THREAD* self = KeGetCurrentThread(); @@ -53,6 +58,7 @@ KSTATUS KeTryAcquireMutex(MUTEX* mutex) { return STATUS_FAILURE; } +// Releases mutex. void KeReleaseMutex(MUTEX* mutex) { if (!mutex) return; uintptr_t flags = KeAcquireSpinlock(&mutex->Lock); diff --git a/code/kernel/ke_process.c b/code/kernel/ke_process.c index d861e48..4911578 100644 --- a/code/kernel/ke_process.c +++ b/code/kernel/ke_process.c @@ -1,4 +1,5 @@ -// ke_process.c - process model +// Kernel process model. This file owns address-space metadata, handle tables, and process lifetime transitions. + #include #include #include @@ -12,14 +13,13 @@ #include #include -// --------------------------------------------------------------------------- -// Global process list -// --------------------------------------------------------------------------- +// Global process list. static LIST_ENTRY gProcessList; static SPINLOCK gProcessListLock; static uint32_t gNextProcessId = 0; static PROCESS* gSystemProcess = (PROCESS*)0; +// Processes init. static void KiProcessInit(void) { static int inited = 0; if (!inited) { @@ -29,11 +29,13 @@ static void KiProcessInit(void) { } } +// Returns process List. LIST_ENTRY* KeGetProcessList(void) { KiProcessInit(); return &gProcessList; } +// Returns current Process. PROCESS* KeGetCurrentProcess(void) { THREAD* currentThread = KeGetCurrentThread(); if (currentThread) { @@ -42,10 +44,12 @@ PROCESS* KeGetCurrentProcess(void) { return NULL; } +// Returns system Process. PROCESS* KeGetSystemProcess(void) { return gSystemProcess; } +// Creates system Process. KSTATUS KeCreateSystemProcess(PROCESS** out) { if (!out) return STATUS_INVALID_PARAMETER; if (gSystemProcess) { @@ -65,6 +69,7 @@ KSTATUS KeCreateSystemProcess(PROCESS** out) { return STATUS_SUCCESS; } +// Implements the count Process Handles Locked operation. static uint32_t KiCountProcessHandlesLocked(PROCESS* process) { uint32_t count = 0; if (!process) return 0; @@ -75,6 +80,7 @@ static uint32_t KiCountProcessHandlesLocked(PROCESS* process) { return count; } +// Copies truncated String. static void KiCopyTruncatedString(char* dst, size_t dstSize, const char* src, size_t srcLen) { if (!dst || dstSize == 0) return; size_t n = 0; @@ -87,6 +93,7 @@ static void KiCopyTruncatedString(char* dst, size_t dstSize, const char* src, si dst[n] = '\0'; } +// Copies process Info. size_t KeCopyProcessInfo(struct SYS_PROCESS_INFO* infoOut, size_t maxCount) { KiProcessInit(); @@ -151,9 +158,7 @@ size_t KeCopyProcessInfo(struct SYS_PROCESS_INFO* infoOut, size_t maxCount) { return count; } -// --------------------------------------------------------------------------- -// Destructor (called by ObDereferenceObject when RefCount hits zero) -// --------------------------------------------------------------------------- +// Destructor (called by ObDereferenceObject when RefCount hits zero). static void KiProcessDestroy(OBJECT* obj) { PROCESS* proc = CONTAINING_RECORD(obj, PROCESS, Header); @@ -201,9 +206,7 @@ static void KiProcessDestroy(OBJECT* obj) { // Destroy returns. } -// --------------------------------------------------------------------------- -// KeCreateProcess -// --------------------------------------------------------------------------- +// KeCreateProcess. KSTATUS KeCreateProcess(const char* name, PROCESS **out) { KiProcessInit(); @@ -262,9 +265,7 @@ KSTATUS KeCreateProcess(const char* name, PROCESS **out) { } -// --------------------------------------------------------------------------- -// KeSetupUserProcessEnvironment -// --------------------------------------------------------------------------- +// KeSetupUserProcessEnvironment. static KSTATUS KiCopyEnvironmentStringView(PROCESS* proc, SYS_STRING_VIEW src, uintptr_t* baseOut, @@ -314,6 +315,7 @@ static KSTATUS KiCopyEnvironmentStringViewFixed(PROCESS* proc, return STATUS_SUCCESS; } +// Releases partial Process Environment. static void KiFreePartialProcessEnvironment(PROCESS* proc) { if (!proc) return; @@ -424,9 +426,7 @@ fail: return s; } -// --------------------------------------------------------------------------- -// Process exit / termination -// --------------------------------------------------------------------------- +// Process exit / termination. static void KiCompleteProcessExitIfLastThread(PROCESS* process) { if (!process) return; @@ -439,6 +439,7 @@ static void KiCompleteProcessExitIfLastThread(PROCESS* process) { } } +// Implements the exit Process operation. void KeExitProcess(PROCESS* process, int exitCode) { if (!process) return; process->ExitCode = exitCode; @@ -450,6 +451,7 @@ void KeExitProcess(PROCESS* process, int exitCode) { KiCompleteProcessExitIfLastThread(process); } +// Implements the terminate Process operation. KSTATUS KeTerminateProcess(PROCESS* process, int exitCode) { if (!process) return STATUS_INVALID_PARAMETER; @@ -483,22 +485,19 @@ KSTATUS KeTerminateProcess(PROCESS* process, int exitCode) { return STATUS_SUCCESS; } +// Checks whether process Terminating. int KeIsProcessTerminating(PROCESS* process) { return process && process->Terminating != 0; } -// --------------------------------------------------------------------------- -// KeGetProcessExitCode -// --------------------------------------------------------------------------- +// KeGetProcessExitCode. KSTATUS KeGetProcessExitCode(PROCESS* process, int* exitCodeOut) { if (!process || !exitCodeOut) return STATUS_INVALID_PARAMETER; *exitCodeOut = process->ExitCode; return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// Handle table -// --------------------------------------------------------------------------- +// Handle table. KSTATUS KeAllocateHandleWithRights(PROCESS* process, OBJECT* object, uint32_t rights, uint32_t* handleOut) { if (!process || !object || !handleOut || rights == 0) return STATUS_INVALID_PARAMETER; @@ -520,10 +519,12 @@ KSTATUS KeAllocateHandleWithRights(PROCESS* process, OBJECT* object, uint32_t ri return STATUS_NO_MEMORY; } +// Creates handle. KSTATUS KeAllocateHandle(PROCESS* process, OBJECT* object, uint32_t* handleOut) { return KeAllocateHandleWithRights(process, object, HANDLE_RIGHT_ALL, handleOut); } +// Releases handle. void KeCloseHandle(PROCESS* process, uint32_t handle) { if (!process || handle == 0 || handle >= HANDLE_TABLE_SIZE) return; @@ -540,6 +541,7 @@ void KeCloseHandle(PROCESS* process, uint32_t handle) { KeReleaseSpinlock(&process->HandleLock, flags); } +// Returns handle With Rights. OBJECT* KeLookupHandleWithRights(PROCESS* process, uint32_t handle, uint32_t requiredRights) { if (!process || handle == 0 || handle >= HANDLE_TABLE_SIZE) return (OBJECT*)0; @@ -554,10 +556,12 @@ OBJECT* KeLookupHandleWithRights(PROCESS* process, uint32_t handle, uint32_t req return obj; } +// Returns handle. OBJECT* KeLookupHandle(PROCESS* process, uint32_t handle) { return KeLookupHandleWithRights(process, handle, 0); } +// Returns handle Rights. uint32_t KeGetHandleRights(PROCESS* process, uint32_t handle) { if (!process || handle == 0 || handle >= HANDLE_TABLE_SIZE) return 0; @@ -567,6 +571,7 @@ uint32_t KeGetHandleRights(PROCESS* process, uint32_t handle) { return rights; } +// Returns process By Id. PROCESS* KeGetProcessById(uint32_t pid) { KiProcessInit(); uintptr_t flags = KeAcquireSpinlock(&gProcessListLock); diff --git a/code/kernel/ke_queue.c b/code/kernel/ke_queue.c index b4865ab..3b3922f 100644 --- a/code/kernel/ke_queue.c +++ b/code/kernel/ke_queue.c @@ -1,4 +1,5 @@ -// ke_queue.c - ring-buffer message queue +// Kernel message queue primitive. This file owns bounded queue storage and blocking send/receive behavior. + #include #include #include @@ -6,8 +7,10 @@ #include #include +// Implements the queue Destroy operation. static void KiQueueDestroy(OBJECT* obj) { (void)obj; } +// Implements the queue Create operation. KSTATUS KeQueueCreate(QUEUE **out) { if (!out) return STATUS_INVALID_PARAMETER; QUEUE* q = (QUEUE *)ObAllocateObject(ObjectTypeQueue, sizeof(QUEUE)); @@ -21,6 +24,7 @@ KSTATUS KeQueueCreate(QUEUE **out) { return STATUS_SUCCESS; } +// Implements the send Message operation. KSTATUS KeSendMessage(QUEUE* queue, const QUEUE_MESSAGE* msg, bool blocking) { if (!queue || !msg) return STATUS_INVALID_PARAMETER; if (blocking && !KeCanWait()) return STATUS_INVALID_IRQL; @@ -56,6 +60,7 @@ KSTATUS KeSendMessage(QUEUE* queue, const QUEUE_MESSAGE* msg, bool blocking) { } } +// Implements the receive Message operation. KSTATUS KeReceiveMessage(QUEUE* queue, QUEUE_MESSAGE* msg, bool blocking) { if (!queue || !msg) return STATUS_INVALID_PARAMETER; if (blocking && !KeCanWait()) return STATUS_INVALID_IRQL; diff --git a/code/kernel/ke_sched.c b/code/kernel/ke_sched.c index e22bd30..1504df4 100644 --- a/code/kernel/ke_sched.c +++ b/code/kernel/ke_sched.c @@ -1,4 +1,5 @@ -// ke_sched.c - MLFQ scheduler +// Kernel scheduler. This file owns run queues, dispatch decisions, preemption, and CPU-local scheduling state. + #include #include #include @@ -22,6 +23,7 @@ static uint32_t gAgingCounter = 0; static KE_SCHED_STATS gSchedStats; static PROCESS* gIdleProcess; +// Implements the default Thread Affinity Mask operation. static uint64_t KiDefaultThreadAffinityMask(void) { // Normal kernel, user, and driver-created threads are BSP-affine by // default. Code that is explicitly audited for AP execution can widen its @@ -29,10 +31,12 @@ static uint64_t KiDefaultThreadAffinityMask(void) { return 1ULL; } +// Implements the thread Is Killed Locked operation. static int KiThreadIsKilledLocked(const THREAD* thread) { return thread && !thread->IsIdleThread && thread->Owner && KeIsProcessTerminating(thread->Owner); } +// Implements the thread Can Run On Cpu Locked operation. static int KiThreadCanRunOnCpuLocked(const THREAD* thread, const KCPU* cpu) { if (!thread || !cpu) return 0; if (thread->IsIdleThread) return thread == cpu->IdleThread; @@ -40,6 +44,7 @@ static int KiThreadCanRunOnCpuLocked(const THREAD* thread, const KCPU* cpu) { return (thread->AffinityMask & (1ULL << cpu->CpuIndex)) != 0; } +// Implements the cpu Is Idle Locked operation. static int KiCpuIsIdleLocked(const KCPU* cpu) { if (!cpu || !cpu->Online) return 0; @@ -47,6 +52,7 @@ static int KiCpuIsIdleLocked(const KCPU* cpu) { return (!cur || cur == cpu->IdleThread || cur->State != ThreadRunning); } +// Implements the any Idle Primary For Thread Locked operation. static int KiAnyIdlePrimaryForThreadLocked(const THREAD* thread) { if (!thread || thread->IsIdleThread) return 0; @@ -65,6 +71,7 @@ static int KiAnyIdlePrimaryForThreadLocked(const THREAD* thread) { return 0; } +// Checks whether defer To Idle Primary Locked. static int KiShouldDeferToIdlePrimaryLocked(KCPU* cpu, const THREAD* thread) { if (!cpu || !thread || thread->IsIdleThread) return 0; @@ -78,6 +85,7 @@ static int KiShouldDeferToIdlePrimaryLocked(KCPU* cpu, const THREAD* thread) { return KiAnyIdlePrimaryForThreadLocked(thread); } +// Implements the request Reschedule Cpu Locked operation. static void KiRequestRescheduleCpuLocked(KCPU* target) { if (!target || !target->Online) return; @@ -90,6 +98,7 @@ static void KiRequestRescheduleCpuLocked(KCPU* target) { } } +// Implements the poke Runnable Cpus Locked operation. static void KiPokeRunnableCpusLocked(THREAD* thread) { if (!thread || thread->IsIdleThread) return; @@ -137,6 +146,7 @@ static void KiPokeRunnableCpusLocked(THREAD* thread) { } } +// Implements the base Quantum For Priority operation. static uint32_t KiBaseQuantumForPriority(THREAD_PRIORITY priority) { switch (priority) { case PriorityHigh: return SCHED_HIGH_QUANTUM_TICKS; @@ -146,6 +156,7 @@ static uint32_t KiBaseQuantumForPriority(THREAD_PRIORITY priority) { } } +// Implements the compute Quantum Locked operation. static uint32_t KiComputeQuantumLocked(THREAD* thread) { if (!thread || thread == KeGetCurrentCpu()->IdleThread) return 1; @@ -164,15 +175,19 @@ static uint32_t KiComputeQuantumLocked(THREAD* thread) { return quantum ? quantum : 1; } +// Implements the refill Quantum Locked operation. static void KiRefillQuantumLocked(THREAD* thread) { if (!thread) return; thread->QuantumTicks = KiComputeQuantumLocked(thread); thread->QuantumRemaining = thread->QuantumTicks; } +// Returns current Thread. THREAD* KeGetCurrentThread(void) { return KeGetCurrentCpu()->CurrentThread; } +// Updates current Thread. void KeSetCurrentThread(THREAD* t) { KeGetCurrentCpu()->CurrentThread = t; } +// Returns scheduler Stats. void KeGetSchedulerStats(KE_SCHED_STATS* out) { if (!out) return; uintptr_t flags = KeAcquireSpinlock(&gSchedLock); @@ -181,6 +196,7 @@ void KeGetSchedulerStats(KE_SCHED_STATS* out) { } +// Implements the arm Post Switch Unlock operation. static void KiArmPostSwitchUnlock(THREAD* thread, uintptr_t cookie) { // The scheduler lock is intentionally held across KeSwitchContext(). The // unlock cookie belongs to the thread continuation that will resume after @@ -191,11 +207,13 @@ static void KiArmPostSwitchUnlock(THREAD* thread, uintptr_t cookie) { thread->SwitchLockCookie = cookie; } +// Implements the post Switch Unlock Cookie operation. static uintptr_t KiPostSwitchUnlockCookie(THREAD* thread) { return thread ? thread->SwitchLockCookie : 0x202ULL; } +// Implements the scheduler Bug operation. static void KiSchedulerBug(const char* where, THREAD* thread, const char* why) { KePanic(KE_PANIC_CODE_SCHEDULER, "scheduler invariant failed: %s: thread=0x%016llX tid=%u state=%u queued=%u runningCpu=%u idle=%u: %s\n", @@ -209,6 +227,7 @@ static void KiSchedulerBug(const char* where, THREAD* thread, const char* why) { why ? why : "?"); } +// Implements the assert Ready Queue Candidate Locked operation. static void KiAssertReadyQueueCandidateLocked(const char* where, THREAD* thread) { if (!thread) KiSchedulerBug(where, thread, "null thread"); @@ -222,6 +241,7 @@ static void KiAssertReadyQueueCandidateLocked(const char* where, THREAD* thread) KiSchedulerBug(where, thread, "thread still reserved/running on a CPU"); } +// Implements the assert Picked Thread Locked operation. static void KiAssertPickedThreadLocked(const char* where, THREAD* thread) { if (!thread) KiSchedulerBug(where, thread, "null picked thread"); @@ -235,6 +255,7 @@ static void KiAssertPickedThreadLocked(const char* where, THREAD* thread) { KiSchedulerBug(where, thread, "picked thread was not ready"); } +// Inserts ready Locked. static void KiInsertReadyLocked(THREAD* thread) { KiAssertReadyQueueCandidateLocked("KiInsertReadyLocked", thread); @@ -249,6 +270,7 @@ static void KiInsertReadyLocked(THREAD* thread) { static int KiAnyRunnableForCpuLocked(KCPU* cpu); +// Implements the any Runnable For Current Cpu operation. static int KiAnyRunnableForCurrentCpu(void) { KCPU* cpu = KeGetCurrentCpu(); uintptr_t flags = KeAcquireSpinlock(&gSchedLock); @@ -257,6 +279,7 @@ static int KiAnyRunnableForCurrentCpu(void) { return any; } +// Implements the idle Loop operation. static void KiIdleLoop(void) { for (;;) { KCPU* cpu = KeGetCurrentCpu(); @@ -279,6 +302,7 @@ static void KiIdleLoop(void) { } } +// Initializes scheduler Global. void KiInitializeSchedulerGlobal(void) { for (int i = 0; i < PriorityCount; i++) LIST_INIT(&gRunQueue[i]); gSchedLock = (SPINLOCK)SPINLOCK_INIT; @@ -294,6 +318,7 @@ void KiInitializeSchedulerGlobal(void) { (void)systemProc; } +// Creates idle Thread For Cpu. KSTATUS KiCreateIdleThreadForCpu(KCPU* cpu) { if (!cpu || !gIdleProcess) return STATUS_INVALID_PARAMETER; @@ -366,6 +391,7 @@ KSTATUS KiCreateIdleThreadForCpu(KCPU* cpu) { return STATUS_SUCCESS; } +// Initializes scheduler. void KeInitializeScheduler(void) { KiInitializeSchedulerGlobal(); @@ -376,7 +402,7 @@ void KeInitializeScheduler(void) { (unsigned)cpu->CpuIndex, s); } -// Safely release the lock and clean up any dead threads natively post-switch +// Safely release the lock and clean up any dead threads natively post-switch. void KeSchedulerPostSwitch(void) { KCPU* cpu = KeGetCurrentCpu(); THREAD* cur = cpu->CurrentThread; @@ -392,6 +418,7 @@ void KeSchedulerPostSwitch(void) { } } +// Updates thread Affinity Mask. void KeSetThreadAffinityMask(THREAD* thread, uint64_t affinityMask) { if (!thread || thread->IsIdleThread) return; @@ -405,10 +432,12 @@ void KeSetThreadAffinityMask(THREAD* thread, uint64_t affinityMask) { KeReleaseSpinlock(&gSchedLock, flags); } +// Returns default Thread Affinity Mask. uint64_t KeGetDefaultThreadAffinityMask(void) { return KiDefaultThreadAffinityMask(); } +// Implements the ready Thread operation. void KeReadyThread(THREAD* thread) { if (!thread) return; @@ -419,6 +448,7 @@ void KeReadyThread(THREAD* thread) { KeReleaseSpinlock(&gSchedLock, flags); } +// Implements the unready Thread operation. void KeUnreadyThread(THREAD* thread) { if (!thread) return; uintptr_t flags = KeAcquireSpinlock(&gSchedLock); @@ -430,6 +460,7 @@ void KeUnreadyThread(THREAD* thread) { } +// Implements the any Runnable For Cpu Locked operation. static int KiAnyRunnableForCpuLocked(KCPU* cpu) { if (!cpu) cpu = KeGetCurrentCpu(); @@ -447,6 +478,7 @@ static int KiAnyRunnableForCpuLocked(KCPU* cpu) { return 0; } +// Implements the pick Next For Cpu operation. static THREAD* KiPickNextForCpu(KCPU* cpu) { if (!cpu) cpu = KeGetCurrentCpu(); @@ -472,17 +504,20 @@ static THREAD* KiPickNextForCpu(KCPU* cpu) { } +// Implements the request Reschedule operation. void KiRequestReschedule(void) { KCPU* cpu = KeGetCurrentCpu(); if (cpu) _InterlockedExchange(&cpu->ReschedulePending, 1); } +// Checks whether reschedule Pending. int KiIsReschedulePending(void) { KCPU* cpu = KeGetCurrentCpu(); return cpu && _InterlockedCompareExchange(&cpu->ReschedulePending, 0, 0) != 0; } +// Implements the schedule operation. static void KiSchedule(void) { KCPU* cpu = KeGetCurrentCpu(); THREAD* cur = cpu->CurrentThread; @@ -547,12 +582,14 @@ static void KiSchedule(void) { KeSchedulerPostSwitch(); } +// Implements the schedule From Interrupt operation. void KiScheduleFromInterrupt(void) { if (!KiIsReschedulePending()) return; KiSchedule(); } +// Implements the scheduler Mark Thread Waiting operation. void KiSchedulerMarkThreadWaiting(THREAD* thread) { if (!thread) return; @@ -574,6 +611,7 @@ void KiSchedulerMarkThreadWaiting(THREAD* thread) { KeReleaseSpinlock(&gSchedLock, flags); } +// Implements the scheduler Note Voluntary Block operation. void KiSchedulerNoteVoluntaryBlock(THREAD* thread) { if (!thread) return; uintptr_t flags = KeAcquireSpinlock(&gSchedLock); @@ -583,6 +621,7 @@ void KiSchedulerNoteVoluntaryBlock(THREAD* thread) { } +// Implements the scheduler Wake Thread operation. void KiSchedulerWakeThread(THREAD* thread, KSTATUS status) { if (!thread) return; @@ -627,6 +666,7 @@ void KiSchedulerWakeThread(THREAD* thread, KSTATUS status) { KeReleaseSpinlock(&gSchedLock, flags); } +// Implements the scheduler Tick operation. void KeSchedulerTick(void) { KCPU* cpu = KeGetCurrentCpu(); THREAD* cur = cpu->CurrentThread; @@ -705,6 +745,7 @@ void KeSchedulerTick(void) { KiRequestReschedule(); } +// Implements the yield operation. __declspec(dllexport) void KeYield(void) { KeAssertIrql(PASSIVE_LEVEL); KiSchedule(); diff --git a/code/kernel/ke_selftest.c b/code/kernel/ke_selftest.c index 431ee17..c898f52 100644 --- a/code/kernel/ke_selftest.c +++ b/code/kernel/ke_selftest.c @@ -1,4 +1,5 @@ -// ke_selftest.c - kernel bring-up and regression self-tests. +// Kernel self-tests. This file runs bring-up regression checks before normal user workloads start. + #include #include #include @@ -20,9 +21,7 @@ #include #include -// ------------------------------------------------------------------------- -// Kernel APC self-test -// ------------------------------------------------------------------------- +// Kernel APC self-test. typedef struct KI_APC_SELFTEST_STATE { EVENT* ReadyEvent; @@ -85,6 +84,7 @@ static void KiApcSelfTestCrossThreadRoutine(void* normalContext, KeSignalEvent(st->DoneEvent); } +// Implements the apc Self Test Worker operation. static void KiApcSelfTestWorker(void* arg) { KI_APC_SELFTEST_STATE* st = (KI_APC_SELFTEST_STATE*)arg; @@ -135,6 +135,7 @@ static void KiApcAlertableSelfTestNormalRoutine(void* normalContext, st->ApcDelivered++; } +// Implements the apc Alertable Self Test Worker operation. static void KiApcAlertableSelfTestWorker(void* arg) { KI_APC_ALERTABLE_SELFTEST_STATE* st = (KI_APC_ALERTABLE_SELFTEST_STATE*)arg; @@ -159,6 +160,7 @@ static void KiApcAlertableSelfTestWorker(void* arg) { KeExitThread(KeGetCurrentThread(), 0); } +// Runs kernel Apc Self Test. static void KiRunKernelApcSelfTest(void) { DbgPrint("APC selftest: begin\n"); @@ -346,9 +348,7 @@ static void KiRunKernelApcSelfTest(void) { DbgPrint("APC selftest: PASS\n"); } -// ------------------------------------------------------------------------- -// IRP + kernel APC self-test -// ------------------------------------------------------------------------- +// IRP + kernel APC self-test. typedef struct KI_IRP_APC_SELFTEST_STATE { EVENT* CompletionEvent; @@ -401,6 +401,7 @@ static void KiIrpApcSelfTestNormalRoutine(void* normalContext, st->ApcInformation = irp->Information; } +// Runs irp Kernel Apc Self Test. static void KiRunIrpKernelApcSelfTest(const HAL_API* hal) { DbgPrint("IRP/APC selftest: begin\n"); @@ -477,9 +478,7 @@ static void KiRunIrpKernelApcSelfTest(const HAL_API* hal) { -// ------------------------------------------------------------------------- -// Virtual memory mapping invariants -// ------------------------------------------------------------------------- +// Virtual memory mapping invariants. static void KiRunMemoryMappingSelfTest(void) { PHYSICAL_ADDRESS phys = 0; uint64_t flags = 0; @@ -494,9 +493,7 @@ static void KiRunMemoryMappingSelfTest(void) { DbgPrint("MM selftest: page zero unmapped\n"); } -// ------------------------------------------------------------------------- -// String-view ABI self-test -// ------------------------------------------------------------------------- +// String-view ABI self-test. static void KiRunStringViewSelfTest(void) { DbgPrint("STRINGVIEW selftest: begin\n"); @@ -530,9 +527,7 @@ static void KiRunStringViewSelfTest(void) { DbgPrint("STRINGVIEW selftest: PASS\n"); } -// ------------------------------------------------------------------------- -// Async file I/O self-test -// ------------------------------------------------------------------------- +// Async file I/O self-test. typedef struct KI_FILE_ASYNC_SELFTEST_STATE { EVENT* CompletionEvent; @@ -581,6 +576,7 @@ static void KiFileAsyncSelfTestNormalRoutine(void* normalContext, st->ApcStatus = status; } +// Runs async File Io Self Test. static void KiRunAsyncFileIoSelfTest(void) { DbgPrint("FILE/ASYNC selftest: begin\n"); @@ -711,6 +707,7 @@ static void KiRunAsyncFileIoSelfTest(void) { s = IoReadFileAt(rf, 0, verify, sizeof(payload) - 1, &got); if (!KSUCCESS(s) || got != sizeof(payload) - 1 || + // Implements the memcmp operation. memcmp(verify, payload, sizeof(payload) - 1) != 0) { KePanic(KE_PANIC_CODE_SELFTEST, "FILE/ASYNC selftest: verify failed status=%u got=%llu\n", s, (uint64_t)got); @@ -729,6 +726,7 @@ static void KiRunAsyncFileIoSelfTest(void) { } +// Runs trap Frame Self Test. static void KiRunTrapFrameSelfTest(void) { DbgPrint("TRAP selftest: begin\n"); @@ -748,6 +746,7 @@ static void KiRunTrapFrameSelfTest(void) { +// Runs core Hardening Self Tests. void KiRunCoreHardeningSelfTests(void) { DbgPrint("CORE selftest: begin\n"); @@ -819,6 +818,7 @@ void KiRunCoreHardeningSelfTests(void) { } +// Runs early Kernel Self Tests. void KiRunEarlyKernelSelfTests(void) { KSTATUS s = KeRunApplicationProcessorSchedulerSelfTests(); if (!KSUCCESS(s)) { @@ -828,6 +828,7 @@ void KiRunEarlyKernelSelfTests(void) { } } +// Runs kernel Self Tests. void KiRunKernelSelfTests(const HAL_API* hal) { DbgPrint("Kernel selftests: begin\n"); KiRunKernelApcSelfTest(); diff --git a/code/kernel/ke_semaphore.c b/code/kernel/ke_semaphore.c index 42e1d98..01e7770 100644 --- a/code/kernel/ke_semaphore.c +++ b/code/kernel/ke_semaphore.c @@ -1,4 +1,5 @@ -// ke_semaphore.c - counting semaphore +// Kernel semaphore primitive. This file owns counting wakeups and bounded resource acquisition. + #include #include #include @@ -6,8 +7,10 @@ #include #include +// Implements the semaphore Destroy operation. static void KiSemaphoreDestroy(OBJECT* obj) { (void)obj; } +// Implements the semaphore Create operation. __declspec(dllexport) KSTATUS KeSemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE **out) { if (!out || initial < 0 || max < 1 || initial > max) return STATUS_INVALID_PARAMETER; @@ -22,6 +25,7 @@ __declspec(dllexport) KSTATUS KeSemaphoreCreate(int32_t initial, int32_t max, SE return STATUS_SUCCESS; } +// Waits for semaphore. __declspec(dllexport) KSTATUS KeWaitSemaphore(SEMAPHORE* sem) { if (!sem) return STATUS_INVALID_PARAMETER; if (!KeCanWait()) return STATUS_INVALID_IRQL; @@ -41,6 +45,7 @@ __declspec(dllexport) KSTATUS KeWaitSemaphore(SEMAPHORE* sem) { return KeCommitBlockThread(self, 0); } +// Implements the try Semaphore operation. __declspec(dllexport) KSTATUS KeTrySemaphore(SEMAPHORE* sem) { if (!sem) return STATUS_INVALID_PARAMETER; uintptr_t flags = KeAcquireSpinlock(&sem->Lock); @@ -53,6 +58,7 @@ __declspec(dllexport) KSTATUS KeTrySemaphore(SEMAPHORE* sem) { return STATUS_FAILURE; } +// Signals semaphore. __declspec(dllexport) void KeSignalSemaphore(SEMAPHORE* sem) { if (!sem) return; uintptr_t flags = KeAcquireSpinlock(&sem->Lock); diff --git a/code/kernel/ke_settings.c b/code/kernel/ke_settings.c index 2507350..1cf3f09 100644 --- a/code/kernel/ke_settings.c +++ b/code/kernel/ke_settings.c @@ -1,5 +1,5 @@ -// ke_settings.c - small system/settings.ini reader. -// +// Kernel settings reader. This file loads simple runtime settings from the system configuration file. + // This intentionally exposes generic string settings only. Subsystems and // drivers own the policy for interpreting their sections. diff --git a/code/kernel/ke_smp.c b/code/kernel/ke_smp.c index 27947f1..a1ed696 100644 --- a/code/kernel/ke_smp.c +++ b/code/kernel/ke_smp.c @@ -1,5 +1,5 @@ -// ke_smp.c - SMP application-processor startup and scheduler admission -// +// SMP bring-up and CPU topology management. This file owns AP startup, CPU admission, and topology-derived scheduling metadata. + // The bootloader is intentionally not involved in AP ownership. The kernel // asks the HAL for MADT-discovered LAPIC IDs, copies a small low-memory x86 AP // startup blob, sends INIT/SIPI through the local APIC, and waits for each AP @@ -42,7 +42,7 @@ #define AP_CR0_NE 0x00000020u #define AP_CR0_PG 0x80000000u -#define AP_BOOT_MAGIC 0x3436544F4F425041ULL /* 'APBOOT64' */ +#define AP_BOOT_MAGIC 0x3436544F4F425041ULL // 'APBOOT64' #define AP_STATE_EMPTY 0u #define AP_STATE_READY 1u #define AP_STATE_LONG_MODE 2u @@ -51,12 +51,12 @@ #define AP_STATE_FAILED 0xFFFFFFFFu #define AP_STAGE_NONE 0x00000000u -#define AP_STAGE_LONG64 0x4C4D3634u /* 'LM64' */ -#define AP_STAGE_ENTRY 0x454E5452u /* 'ENTR' */ -#define AP_STAGE_GS 0x47534241u /* 'GSBA' */ -#define AP_STAGE_GDT 0x47445421u /* 'GDT!' */ -#define AP_STAGE_IDT 0x49445421u /* 'IDT!' */ -#define AP_STAGE_PARK 0x5041524Bu /* 'PARK' */ +#define AP_STAGE_LONG64 0x4C4D3634u // 'LM64' +#define AP_STAGE_ENTRY 0x454E5452u // 'ENTR' +#define AP_STAGE_GS 0x47534241u // 'GSBA' +#define AP_STAGE_GDT 0x47445421u // 'GDT!' +#define AP_STAGE_IDT 0x49445421u // 'IDT!' +#define AP_STAGE_PARK 0x5041524Bu // 'PARK' #pragma pack(push, 1) typedef struct AP_BOOT_BLOCK { @@ -81,15 +81,23 @@ static PHYSICAL_ADDRESS gApTrampolinePhys; static PHYSICAL_ADDRESS gReservedApTrampolinePhys; static AP_BOOT_BLOCK* gApBootBlock; +// Implements the emit8 operation. static void KiEmit8(uint8_t** p, uint8_t v) { *(*p)++ = v; } +// Implements the emit16 operation. static void KiEmit16(uint8_t** p, uint16_t v) { memcpy(*p, &v, sizeof(v)); *p += sizeof(v); } +// Implements the emit32 operation. static void KiEmit32(uint8_t** p, uint32_t v) { memcpy(*p, &v, sizeof(v)); *p += sizeof(v); } +// Implements the emit64 operation. static void KiEmit64(uint8_t** p, uint64_t v) { memcpy(*p, &v, sizeof(v)); *p += sizeof(v); } +// Implements the patch16 operation. static void KiPatch16(uint8_t* base, size_t off, uint16_t v) { memcpy(base + off, &v, sizeof(v)); } +// Implements the patch32 operation. static void KiPatch32(uint8_t* base, size_t off, uint32_t v) { memcpy(base + off, &v, sizeof(v)); } +// Implements the patch64 operation. static void KiPatch64(uint8_t* base, size_t off, uint64_t v) { memcpy(base + off, &v, sizeof(v)); } +// Implements the gdt Descriptor operation. static uint64_t KiGdtDescriptor(uint32_t base, uint32_t limit, uint8_t access, uint8_t flags) { return ((uint64_t)(limit & 0xFFFF)) | ((uint64_t)(base & 0xFFFFFF) << 16) | @@ -99,6 +107,7 @@ static uint64_t KiGdtDescriptor(uint32_t base, uint32_t limit, uint8_t access, u ((uint64_t)((base >> 24) & 0xFF) << 56); } +// Updates application Processor Trampoline. void KeSetApplicationProcessorTrampoline(uint64_t trampolinePhys) { if (trampolinePhys >= PAGE_SIZE && trampolinePhys < AP_TRAMPOLINE_MAX_PHYS && @@ -109,6 +118,7 @@ void KeSetApplicationProcessorTrampoline(uint64_t trampolinePhys) { } } +// Builds ap Trampoline. static KSTATUS KiBuildApTrampoline(void) { if (gApTrampolinePhys) return STATUS_SUCCESS; @@ -155,7 +165,7 @@ static KSTATUS KiBuildApTrampoline(void) { uint32_t physBase = (uint32_t)frame; uint8_t* p = page; - // --- 16-bit real-mode SIPI entry --- + // --- 16-bit real-mode SIPI entry ---. KiEmit8(&p, 0xFA); // cli KiEmit8(&p, 0x8C); KiEmit8(&p, 0xC8); // mov ax, cs KiEmit8(&p, 0x8E); KiEmit8(&p, 0xD8); // mov ds, ax @@ -171,7 +181,7 @@ static KSTATUS KiBuildApTrampoline(void) { while (((uintptr_t)(p - page)) & 0x0F) KiEmit8(&p, 0x90); uint32_t prot32Off = (uint32_t)(p - page); - // --- 32-bit protected-mode transition to long mode --- + // --- 32-bit protected-mode transition to long mode ---. KiEmit8(&p, 0x66); KiEmit8(&p, 0xB8); KiEmit16(&p, 0x0010); // mov ax, 0x10 KiEmit8(&p, 0x8E); KiEmit8(&p, 0xD8); // mov ds, ax KiEmit8(&p, 0x8E); KiEmit8(&p, 0xC0); // mov es, ax @@ -197,7 +207,7 @@ static KSTATUS KiBuildApTrampoline(void) { while (((uintptr_t)(p - page)) & 0x0F) KiEmit8(&p, 0x90); uint32_t long64Off = (uint32_t)(p - page); - // --- 64-bit entry. Jump into high-half KiApKernelEntry(KCPU*). --- + // --- 64-bit entry. Jump into high-half KiApKernelEntry(KCPU*). ---. KiEmit8(&p, 0x48); KiEmit8(&p, 0xBB); size_t bootBlockPatch = (size_t)(p - page); KiEmit64(&p, 0); // mov rbx, bootblock KiEmit8(&p, 0xC7); KiEmit8(&p, 0x83); KiEmit32(&p, (uint32_t)offsetof(AP_BOOT_BLOCK, Stage)); KiEmit32(&p, AP_STAGE_LONG64); KiEmit8(&p, 0xC7); KiEmit8(&p, 0x83); KiEmit32(&p, (uint32_t)offsetof(AP_BOOT_BLOCK, State)); KiEmit32(&p, AP_STATE_LONG_MODE); @@ -324,6 +334,7 @@ _Noreturn void KiApKernelEntry(KCPU* cpu) { } } +// Prepares cpu Record. static void KiPrepareCpuRecord(uint32_t cpuIndex, const HAL_CPU_INFO* info) { KCPU* cpu = &gCpus[cpuIndex]; memset(cpu, 0, sizeof(*cpu)); @@ -354,6 +365,7 @@ static void KiPrepareCpuRecord(uint32_t cpuIndex, const HAL_CPU_INFO* info) { } +// Implements the ceil Log2 U32 operation. static uint32_t KiCeilLog2U32(uint32_t value) { if (value <= 1u) return 0u; @@ -366,6 +378,7 @@ static uint32_t KiCeilLog2U32(uint32_t value) { return shift; } +// Implements the mask Width operation. static uint32_t KiMaskWidth(uint32_t shift) { if (shift >= 32u) return 0xFFFFFFFFu; @@ -382,6 +395,7 @@ typedef struct KI_CPUID_TOPOLOGY_PARAMS { const char* Source; } KI_CPUID_TOPOLOGY_PARAMS; +// Returns cpuid Topology Leaf. static void KiReadCpuidTopologyLeaf(uint32_t leaf, KI_CPUID_TOPOLOGY_PARAMS* out) { if (!out) return; @@ -408,6 +422,7 @@ static void KiReadCpuidTopologyLeaf(uint32_t leaf, KI_CPUID_TOPOLOGY_PARAMS* out } } +// Implements the detect Cpuid Topology Params operation. static KI_CPUID_TOPOLOGY_PARAMS KiDetectCpuidTopologyParams(void) { KI_CPUID_TOPOLOGY_PARAMS topo; memset(&topo, 0, sizeof(topo)); @@ -472,6 +487,7 @@ static KI_CPUID_TOPOLOGY_PARAMS KiDetectCpuidTopologyParams(void) { return topo; } +// Builds processor Topology. void KeBuildProcessorTopology(void) { KI_CPUID_TOPOLOGY_PARAMS topo = KiDetectCpuidTopologyParams(); @@ -570,6 +586,7 @@ void KeBuildProcessorTopology(void) { } } +// Creates ap Stack. static KSTATUS KiAllocateApStack(KCPU* cpu) { // AP kernel stacks do not need physically contiguous memory. Requiring // MmAllocateContiguous(8) made SMP startup depend on a DMA-style run being @@ -593,6 +610,7 @@ static KSTATUS KiAllocateApStack(KCPU* cpu) { } +// Implements the ap Stage Name operation. static const char* KiApStageName(uint32_t stage) { switch (stage) { case AP_STAGE_NONE: return "none"; @@ -606,6 +624,7 @@ static const char* KiApStageName(uint32_t stage) { } } +// Fills boot Block For Cpu. static void KiFillBootBlockForCpu(KCPU* cpu, uint32_t apIndex) { memset(gApBootBlock, 0, sizeof(*gApBootBlock)); gApBootBlock->Magic = AP_BOOT_MAGIC; @@ -618,6 +637,7 @@ static void KiFillBootBlockForCpu(KCPU* cpu, uint32_t apIndex) { gApBootBlock->ApIndex = apIndex; } +// Starts application Processors. KSTATUS KeStartApplicationProcessors(void) { HAL_CPU_TOPOLOGY topo; KSTATUS st = HalGetProcessorTopology(&topo); @@ -757,6 +777,7 @@ KSTATUS KeStartApplicationProcessors(void) { return STATUS_SUCCESS; } +// Implements the admit Application Processors To Scheduler operation. KSTATUS KeAdmitApplicationProcessorsToScheduler(void) { if (gCpuCount <= 1) { DbgPrint("SMP: no AP scheduler admission needed\n"); @@ -815,7 +836,7 @@ KSTATUS KeAdmitApplicationProcessorsToScheduler(void) { #define SMP_AP_WORKER_ROUNDS 64u #define SMP_AP_WORKER_TIMEOUT_SPINS 4000000u -#define SMP_AP_TEST_MAGIC 0x524B575041504D53ULL /* 'SMPAPWKR' */ +#define SMP_AP_TEST_MAGIC 0x524B575041504D53ULL // 'SMPAPWKR' typedef struct SMP_AP_WORK_TEST SMP_AP_WORK_TEST; @@ -844,6 +865,7 @@ struct SMP_AP_WORK_TEST { SMP_AP_WORKER_ARG Workers[KE_MAX_CPUS]; }; +// Implements the smp Ap Controlled Worker operation. static void KiSmpApControlledWorker(void* context) { SMP_AP_WORKER_ARG* arg = (SMP_AP_WORKER_ARG*)context; if (!arg || arg->Magic != SMP_AP_TEST_MAGIC || !arg->StepEvent) { @@ -895,6 +917,7 @@ static void KiSmpApControlledWorker(void* context) { _InterlockedIncrement(&arg->Test->DoneCount); } +// Waits for for Worker Counter. static int KiWaitForWorkerCounter(volatile long* counter, long expected, const char* what) { for (uint32_t spin = 0; spin < SMP_AP_WORKER_TIMEOUT_SPINS; spin++) { if (_InterlockedCompareExchange(counter, 0, 0) >= expected) @@ -909,6 +932,7 @@ static int KiWaitForWorkerCounter(volatile long* counter, long expected, const c return 0; } +// Runs application Processor Scheduler Self Tests. KSTATUS KeRunApplicationProcessorSchedulerSelfTests(void) { if (gCpuCount <= 1) { DbgPrint("SMP scheduler selftest: SKIP, no APs\n"); diff --git a/code/kernel/ke_syscall.c b/code/kernel/ke_syscall.c index 3fd845f..81fc6e4 100644 --- a/code/kernel/ke_syscall.c +++ b/code/kernel/ke_syscall.c @@ -1,31 +1,29 @@ -// ke_syscall.c - system call dispatcher -// +// Kernel syscall dispatcher. This file validates user requests and bridges user-mode ABI calls into kernel services. + // KeSyscallEntry (ke_syscall.asm) handles the INT 0x40 ring-3 -> ring-0 // transition, re-orders the arguments to match MS x64, and calls // KeSyscallDispatch with: -// + // nr = original RAX (syscall number) // a0 .. a5 = RCX, RDX, R8, R9, R10, R11 (user arguments) -// + // Every handler receives the same (a0..a5) signature even if it uses fewer // arguments; unused parameters are silently ignored. -// + // Return value (RAX) is a KSTATUS code *or* an arbitrary 64-bit datum // (pointer, size, tick count, etc.) depending on the call; conventions are // documented in syscall_nr.h. -// -// --------------------------------------------------------------------------- + // Unified handle design -// --------------------------------------------------------------------------- // All kernel objects (FILE_OBJECT, MUTEX, SEMAPHORE, EVENT, QUEUE) are // reference-counted OBJECTs stored in the per-process handle table. // SYS_CLOSE_HANDLE is the single close path for every type: -// + // KeCloseHandle(proc, handle) // -> ObDereferenceObject(obj) // -> obj->Destroy(obj) [type-specific cleanup, e.g. KiFileDestroy] // -> MmFreePool(obj) -// + // 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. @@ -65,9 +63,7 @@ #include #include -// --------------------------------------------------------------------------- -// HAL pointer - set once at boot by KeSyscallSetHal() -// --------------------------------------------------------------------------- +// HAL pointer - set once at boot by KeSyscallSetHal(). static const HAL_API* gHal; typedef struct SYS_IO_STATUS_BLOCK_K { @@ -99,15 +95,14 @@ typedef struct SYS_USER_ASYNC_APC_CONTEXT { void* UserContext; } SYS_USER_ASYNC_APC_CONTEXT; +// Implements the syscall Init operation. void KeSyscallInit(const HAL_API* hal) { gHal = hal; } -// --------------------------------------------------------------------------- // Helper: look up a handle and type-check it in one call. // Bumps the refcount on success; caller must ObDereferenceObject when done. // Returns NULL if the handle is invalid or the type does not match. -// --------------------------------------------------------------------------- static OBJECT* KiHandleToObject(uint32_t handle, OBJECT_TYPE expected, uint32_t requiredRights) { PROCESS* proc = KeGetCurrentProcess(); if (!proc) return NULL; @@ -120,11 +115,9 @@ static OBJECT* KiHandleToObject(uint32_t handle, OBJECT_TYPE expected, uint32_t return obj; } -// --------------------------------------------------------------------------- // Helper: allocate a handle in the current process's table for 'obj'. // Takes one reference on behalf of the handle slot. // On failure, drops the reference it would have stored. -// --------------------------------------------------------------------------- static KSTATUS KiAllocHandleForCurrentWithRights(OBJECT* obj, uint32_t rights, uint32_t* handleOut) { PROCESS* proc = KeGetCurrentProcess(); if (!proc) { @@ -142,6 +135,7 @@ static KSTATUS KiAllocHandleForCurrentWithRights(OBJECT* obj, uint32_t rights, u return s; } +// Creates handle For Current. static KSTATUS KiAllocHandleForCurrent(OBJECT* obj, uint32_t* handleOut) { return KiAllocHandleForCurrentWithRights(obj, HANDLE_RIGHT_ALL, handleOut); } @@ -152,6 +146,7 @@ static KSTATUS KiAllocHandleForCurrent(OBJECT* obj, uint32_t* handleOut) { #define SYSCALL_IO_MAX_BYTES (16ULL * 1024ULL * 1024ULL) #define SYSCALL_BLIT_MAX_BYTES (16ULL * 1024ULL * 1024ULL) +// Copies user Request. static KSTATUS KiCopyUserRequest(uint64_t arg, void* dst, size_t size) { if (!arg || !dst || size == 0) return STATUS_INVALID_PARAMETER; return CopyFromUser(dst, (const void*)(uintptr_t)arg, size); @@ -198,26 +193,31 @@ static KSTATUS KiImportUserTextView(SYS_STRING_VIEW userView, return STATUS_SUCCESS; } +// Copies handle To User. static KSTATUS KiCopyHandleToUser(uint64_t arg, uint32_t value) { if (!arg) return STATUS_INVALID_PARAMETER; return CopyToUser((void*)(uintptr_t)arg, &value, sizeof(value)); } +// Copies u32 To User. static KSTATUS KiCopyU32ToUser(uint64_t arg, uint32_t value) { if (!arg) return STATUS_INVALID_PARAMETER; return CopyToUser((void*)(uintptr_t)arg, &value, sizeof(value)); } +// Copies size To User. static KSTATUS KiCopySizeToUser(uint64_t arg, size_t value) { if (!arg) return STATUS_INVALID_PARAMETER; return CopyToUser((void*)(uintptr_t)arg, &value, sizeof(value)); } +// Copies int To User. static KSTATUS KiCopyIntToUser(uint64_t arg, int value) { if (!arg) return STATUS_INVALID_PARAMETER; return CopyToUser((void*)(uintptr_t)arg, &value, sizeof(value)); } +// Implements the mul Size operation. static int KiMulSize(size_t a, size_t b, size_t* out) { if (!out) return 0; if (a && b > ((size_t)-1) / a) return 0; @@ -225,13 +225,9 @@ static int KiMulSize(size_t a, size_t b, size_t* out) { return 1; } -// =========================================================================== -// Individual syscall handlers -// =========================================================================== +// Individual syscall handlers. -// --------------------------------------------------------------------------- -// SYS_EXIT_PROCESS (0) a0 = exitCode -// --------------------------------------------------------------------------- +// SYS_EXIT_PROCESS (0) a0 = exitCode. static uint64_t SyscallExitProcess(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -242,9 +238,7 @@ static uint64_t SyscallExitProcess(uint64_t a0, uint64_t a1, uint64_t a2, while (true) ; // unreachable - KeExitThread does not return } -// --------------------------------------------------------------------------- -// SYS_EXIT_THREAD (1) a0 = exitCode -// --------------------------------------------------------------------------- +// SYS_EXIT_THREAD (1) a0 = exitCode. static uint64_t SyscallExitThread(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -253,9 +247,7 @@ static uint64_t SyscallExitThread(uint64_t a0, uint64_t a1, uint64_t a2, while (true); } -// --------------------------------------------------------------------------- -// SYS_CREATE_THREAD (2) a0=entry a1=arg a2=priority a3=*tidOut -// --------------------------------------------------------------------------- +// SYS_CREATE_THREAD (2) a0=entry a1=arg a2=priority a3=*tidOut. static uint64_t SyscallCreateThread(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a4; (void)a5; @@ -279,9 +271,7 @@ static uint64_t SyscallCreateThread(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// SYS_GET_CURRENT_TID (3) -// --------------------------------------------------------------------------- +// SYS_GET_CURRENT_TID (3). static uint64_t SyscallGetCurrentTid(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -289,9 +279,7 @@ static uint64_t SyscallGetCurrentTid(uint64_t a0, uint64_t a1, uint64_t a2, return t ? t->ThreadId : 0; } -// --------------------------------------------------------------------------- -// SYS_GET_CURRENT_PID (4) -// --------------------------------------------------------------------------- +// SYS_GET_CURRENT_PID (4). static uint64_t SyscallGetCurrentPid(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -299,9 +287,7 @@ static uint64_t SyscallGetCurrentPid(uint64_t a0, uint64_t a1, uint64_t a2, return p ? p->ProcessId : 0; } -// --------------------------------------------------------------------------- -// SYS_YIELD (5) -// --------------------------------------------------------------------------- +// SYS_YIELD (5). static uint64_t SyscallYield(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -309,9 +295,7 @@ static uint64_t SyscallYield(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// SYS_SLEEP (6) a0 = milliseconds -// --------------------------------------------------------------------------- +// SYS_SLEEP (6) a0 = milliseconds. static uint64_t SyscallSleep(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -322,9 +306,7 @@ static uint64_t SyscallSleep(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// SYS_SET_USER_APC_DISPATCHER a0 = dispatcher entry in syscall.dll/user image -// --------------------------------------------------------------------------- +// SYS_SET_USER_APC_DISPATCHER a0 = dispatcher entry in syscall.dll/user image. static uint64_t SyscallSetUserApcDispatcher(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -334,18 +316,14 @@ static uint64_t SyscallSetUserApcDispatcher(uint64_t a0, uint64_t a1, uint64_t a return KeSetUserApcDispatcher((void*)(uintptr_t)a0); } -// --------------------------------------------------------------------------- -// SYS_APC_RETURN a0 = SYS_USER_APC_FRAME* on the user stack -// --------------------------------------------------------------------------- +// SYS_APC_RETURN a0 = SYS_USER_APC_FRAME* on the user stack. static uint64_t SyscallApcReturn(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; return KeUserApcReturn((const SYS_USER_APC_FRAME_K*)(uintptr_t)a0); } -// --------------------------------------------------------------------------- -// SYS_SET_THREAD_PRIORITY (7) a0 = priority -// --------------------------------------------------------------------------- +// SYS_SET_THREAD_PRIORITY (7) a0 = priority. static uint64_t SyscallSetThreadPriority(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -356,9 +334,7 @@ static uint64_t SyscallSetThreadPriority(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// SYS_VM_* page-granular user virtual memory -// --------------------------------------------------------------------------- +// SYS_VM_* page-granular user virtual memory. static KSTATUS KiVmProtectToPageFlags(uint32_t protect, uint64_t* flagsOut) { if (!flagsOut) return STATUS_INVALID_PARAMETER; switch (protect) { @@ -383,6 +359,7 @@ static KSTATUS KiVmProtectToPageFlags(uint32_t protect, uint64_t* flagsOut) { } } +// Implements the page Flags To Vm Protect operation. static uint32_t KiPageFlagsToVmProtect(uint64_t flags) { if (!(flags & PAGE_PRESENT)) return SYS_VM_NOACCESS; bool writable = (flags & PAGE_WRITE) != 0; @@ -500,9 +477,7 @@ static uint64_t SyscallVmQuery(uint64_t a0, uint64_t a1, uint64_t a2, return CopyToUser((void*)(uintptr_t)a1, &info, sizeof(info)); } -// --------------------------------------------------------------------------- -// SYS_CREATE_MUTEX (11) a0 = *handleOut -// --------------------------------------------------------------------------- +// SYS_CREATE_MUTEX (11) a0 = *handleOut. static uint64_t SyscallMutexCreate(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -521,9 +496,7 @@ static uint64_t SyscallMutexCreate(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_ACQUIRE_MUTEX (12) a0 = handle -// --------------------------------------------------------------------------- +// SYS_ACQUIRE_MUTEX (12) a0 = handle. static uint64_t SyscallMutexAcquire(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -534,9 +507,7 @@ static uint64_t SyscallMutexAcquire(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_TRY_ACQUIRE_MUTEX (13) a0 = handle -// --------------------------------------------------------------------------- +// SYS_TRY_ACQUIRE_MUTEX (13) a0 = handle. static uint64_t SyscallMutexTryAcquire(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -547,9 +518,7 @@ static uint64_t SyscallMutexTryAcquire(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_RELEASE_MUTEX (14) a0 = handle -// --------------------------------------------------------------------------- +// SYS_RELEASE_MUTEX (14) a0 = handle. static uint64_t SyscallMutexRelease(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -560,9 +529,7 @@ static uint64_t SyscallMutexRelease(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// SYS_CREATE_SEM (15) a0=initial a1=max a2=*handleOut -// --------------------------------------------------------------------------- +// SYS_CREATE_SEM (15) a0=initial a1=max a2=*handleOut. static uint64_t SyscallSemCreate(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a3; (void)a4; (void)a5; @@ -581,9 +548,7 @@ static uint64_t SyscallSemCreate(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_WAIT_SEM (16) a0 = handle -// --------------------------------------------------------------------------- +// SYS_WAIT_SEM (16) a0 = handle. static uint64_t SyscallSemWait(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -594,9 +559,7 @@ static uint64_t SyscallSemWait(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_TRY_WAIT_SEM (17) a0 = handle -// --------------------------------------------------------------------------- +// SYS_TRY_WAIT_SEM (17) a0 = handle. static uint64_t SyscallSemTryWait(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -607,9 +570,7 @@ static uint64_t SyscallSemTryWait(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_SIGNAL_SEM (18) a0 = handle -// --------------------------------------------------------------------------- +// SYS_SIGNAL_SEM (18) a0 = handle. static uint64_t SyscallSemSignal(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -620,9 +581,7 @@ static uint64_t SyscallSemSignal(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// SYS_CREATE_EVENT (19) a0=type a1=initialState a2=*handleOut -// --------------------------------------------------------------------------- +// SYS_CREATE_EVENT (19) a0=type a1=initialState a2=*handleOut. static uint64_t SyscallEventCreate(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a3; (void)a4; (void)a5; @@ -641,9 +600,7 @@ static uint64_t SyscallEventCreate(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_SIGNAL_EVENT (20) a0 = handle -// --------------------------------------------------------------------------- +// SYS_SIGNAL_EVENT (20) a0 = handle. static uint64_t SyscallEventSignal(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -654,9 +611,7 @@ static uint64_t SyscallEventSignal(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// SYS_CLEAR_EVENT (21) a0 = handle -// --------------------------------------------------------------------------- +// SYS_CLEAR_EVENT (21) a0 = handle. static uint64_t SyscallEventClear(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -667,9 +622,7 @@ static uint64_t SyscallEventClear(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// SYS_WAIT_EVENT a0 = handle, a1 = alertable -// --------------------------------------------------------------------------- +// SYS_WAIT_EVENT a0 = handle, a1 = alertable. static uint64_t SyscallEventWait(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -686,9 +639,7 @@ static uint64_t SyscallEventWait(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_CREATE_QUEUE (23) a0 = *handleOut -// --------------------------------------------------------------------------- +// SYS_CREATE_QUEUE (23) a0 = *handleOut. static uint64_t SyscallQueueCreate(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -707,9 +658,7 @@ static uint64_t SyscallQueueCreate(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_SEND_QUEUE (24) a0=handle a1=*msg a2=blocking -// --------------------------------------------------------------------------- +// SYS_SEND_QUEUE (24) a0=handle a1=*msg a2=blocking. static uint64_t SyscallQueueSend(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a3; (void)a4; (void)a5; @@ -726,9 +675,7 @@ static uint64_t SyscallQueueSend(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_RECV_QUEUE (25) a0=handle a1=*msg a2=blocking -// --------------------------------------------------------------------------- +// SYS_RECV_QUEUE (25) a0=handle a1=*msg a2=blocking. static uint64_t SyscallQueueRecv(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a3; (void)a4; (void)a5; @@ -745,14 +692,12 @@ static uint64_t SyscallQueueRecv(uint64_t a0, uint64_t a1, uint64_t a2, return CopyToUser((void*)(uintptr_t)a1, &msg, sizeof(msg)); } -// --------------------------------------------------------------------------- // 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 // type-specific Destroy callback (KiFileDestroy, etc.) and frees the pool memory. // No per-type close syscall needed or wanted. -// --------------------------------------------------------------------------- static uint64_t SyscallCloseHandle(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -762,9 +707,7 @@ static uint64_t SyscallCloseHandle(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// SYS_OPEN_FILE (27) a0=*path a1=*handleOut -// --------------------------------------------------------------------------- +// SYS_OPEN_FILE (27) a0=*path a1=*handleOut. static uint64_t SyscallOpenFile(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -796,9 +739,7 @@ static uint64_t SyscallOpenFile(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_READ_FILE (28) a0=handle a1=buf a2=size a3=*bytesReadOut -// --------------------------------------------------------------------------- +// SYS_READ_FILE (28) a0=handle a1=buf a2=size a3=*bytesReadOut. static uint64_t SyscallReadFile(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a4; (void)a5; @@ -833,9 +774,7 @@ static uint64_t SyscallReadFile(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_WRITE_FILE (29) a0=handle a1=buf a2=size a3=*bytesWrittenOut -// --------------------------------------------------------------------------- +// SYS_WRITE_FILE (29) a0=handle a1=buf a2=size a3=*bytesWrittenOut. static uint64_t SyscallWriteFile(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a4; (void)a5; @@ -888,6 +827,7 @@ static void SyscallUserAsyncKernelRoutine(KAPC* apc, KeGetCurrentIrql()); } +// Implements the user Async Apc Context Free operation. static void SyscallUserAsyncApcContextFree(SYS_USER_ASYNC_APC_CONTEXT* ctx) { if (!ctx) return; if (ctx->TargetThread) { @@ -897,6 +837,7 @@ static void SyscallUserAsyncApcContextFree(SYS_USER_ASYNC_APC_CONTEXT* ctx) { MmFreePool(ctx); } +// Implements the user Async Apc Rundown operation. static void SyscallUserAsyncApcRundown(KAPC* apc) { if (!apc) return; SYS_USER_ASYNC_APC_CONTEXT* ctx = CONTAINING_RECORD(apc, SYS_USER_ASYNC_APC_CONTEXT, KernelApc); @@ -925,6 +866,7 @@ static void SyscallUserAsyncNormalRoutine(void* normalContext, SyscallUserAsyncApcContextFree(ctx); } +// Implements the async File Common operation. static uint64_t SyscallAsyncFileCommon(uint64_t a0, bool write) { if (!a0) return STATUS_INVALID_PARAMETER; @@ -1063,27 +1005,21 @@ static uint64_t SyscallAsyncFileCommon(uint64_t a0, bool write) { return s; } -// --------------------------------------------------------------------------- -// SYS_READ_FILE_ASYNC (43) a0=*SYS_ASYNC_FILE_REQUEST -// --------------------------------------------------------------------------- +// SYS_READ_FILE_ASYNC (43) a0=*SYS_ASYNC_FILE_REQUEST. static uint64_t SyscallReadFileAsync(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; return SyscallAsyncFileCommon(a0, false); } -// --------------------------------------------------------------------------- -// SYS_WRITE_FILE_ASYNC (44) a0=*SYS_ASYNC_FILE_REQUEST -// --------------------------------------------------------------------------- +// SYS_WRITE_FILE_ASYNC (44) a0=*SYS_ASYNC_FILE_REQUEST. static uint64_t SyscallWriteFileAsync(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; return SyscallAsyncFileCommon(a0, true); } -// --------------------------------------------------------------------------- -// SYS_CANCEL_IO a0 = async request handle -// --------------------------------------------------------------------------- +// SYS_CANCEL_IO a0 = async request handle. static uint64_t SyscallCancelIo(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1096,9 +1032,7 @@ static uint64_t SyscallCancelIo(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_CREATE_FILE (30) a0=*path a1=*handleOut -// --------------------------------------------------------------------------- +// SYS_CREATE_FILE (30) a0=*path a1=*handleOut. static uint64_t SyscallCreateFile(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1130,9 +1064,7 @@ static uint64_t SyscallCreateFile(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_DELETE_FILE (31) a0=*path -// --------------------------------------------------------------------------- +// SYS_DELETE_FILE (31) a0=*path. static uint64_t SyscallDeleteFile(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1150,9 +1082,7 @@ static uint64_t SyscallDeleteFile(uint64_t a0, uint64_t a1, uint64_t a2, return IoDeleteFile(path); } -// --------------------------------------------------------------------------- -// SYS_TRUNCATE_FILE (32) a0=handle a1=newSize -// --------------------------------------------------------------------------- +// SYS_TRUNCATE_FILE (32) a0=handle a1=newSize. static uint64_t SyscallTruncateFile(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -1163,9 +1093,7 @@ static uint64_t SyscallTruncateFile(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_GET_FILE_POS (33) a0=handle -> current seek offset -// --------------------------------------------------------------------------- +// SYS_GET_FILE_POS (33) a0=handle -> current seek offset. static uint64_t SyscallGetFilePos(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1178,9 +1106,7 @@ static uint64_t SyscallGetFilePos(uint64_t a0, uint64_t a1, uint64_t a2, return pos; } -// --------------------------------------------------------------------------- -// SYS_SEEK_FILE (34) a0=handle a1=offset -// --------------------------------------------------------------------------- +// SYS_SEEK_FILE (34) a0=handle a1=offset. static uint64_t SyscallSeekFile(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -1191,9 +1117,7 @@ static uint64_t SyscallSeekFile(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_GET_FILE_SIZE (35) a0=handle -> uint64_t -// --------------------------------------------------------------------------- +// SYS_GET_FILE_SIZE (35) a0=handle -> uint64_t. static uint64_t SyscallGetFileSize(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1204,9 +1128,7 @@ static uint64_t SyscallGetFileSize(uint64_t a0, uint64_t a1, uint64_t a2, return sz; } -// --------------------------------------------------------------------------- -// SYS_BLIT_SCREEN (66) a0=x a1=y a2=w a3=h a4=*pixels -// --------------------------------------------------------------------------- +// SYS_BLIT_SCREEN (66) a0=x a1=y a2=w a3=h a4=*pixels. static uint64_t SyscallBlitScreen(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a5; @@ -1234,18 +1156,14 @@ static uint64_t SyscallBlitScreen(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_CLEAR_SCREEN (67) a0=color -// --------------------------------------------------------------------------- +// SYS_CLEAR_SCREEN (67) a0=color. static uint64_t SyscallClearScreen(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; return KeDisplayClear((uint32_t)a0); } -// --------------------------------------------------------------------------- -// SYS_GET_SCREEN_SIZE (68) a0=*widthOut a1=*heightOut -// --------------------------------------------------------------------------- +// SYS_GET_SCREEN_SIZE (68) a0=*widthOut a1=*heightOut. static uint64_t SyscallGetScreenSize(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -1263,9 +1181,7 @@ static uint64_t SyscallGetScreenSize(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// SYS_PUT_SCREEN_CHAR (65) a0=c a1=x a2=y a3=fg a4=bg -// --------------------------------------------------------------------------- +// SYS_PUT_SCREEN_CHAR (65) a0=c a1=x a2=y a3=fg a4=bg. static uint64_t SyscallPutScreenChar(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a5; @@ -1273,9 +1189,7 @@ static uint64_t SyscallPutScreenChar(uint64_t a0, uint64_t a1, uint64_t a2, (uint32_t)a3, (uint32_t)a4); } -// --------------------------------------------------------------------------- -// SYS_GET_CONSOLE_INFO (61) a0=*SYS_CONSOLE_INFO -// --------------------------------------------------------------------------- +// SYS_GET_CONSOLE_INFO (61) a0=*SYS_CONSOLE_INFO. static uint64_t SyscallGetConsoleInfo(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1295,9 +1209,7 @@ static uint64_t SyscallGetConsoleInfo(uint64_t a0, uint64_t a1, uint64_t a2, return CopyToUser((void*)(uintptr_t)a0, &out, sizeof(out)); } -// --------------------------------------------------------------------------- -// SYS_SET_CONSOLE_CURSOR (62) a0=column a1=row -// --------------------------------------------------------------------------- +// SYS_SET_CONSOLE_CURSOR (62) a0=column a1=row. static uint64_t SyscallSetConsoleCursor(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -1307,9 +1219,7 @@ static uint64_t SyscallSetConsoleCursor(uint64_t a0, uint64_t a1, uint64_t a2, return KeDisplaySetConsoleCursor(col, row); } -// --------------------------------------------------------------------------- -// SYS_FILL_CONSOLE_CHARACTER (63) a0=char a1=column a2=row a3=count a4=*writtenOut -// --------------------------------------------------------------------------- +// SYS_FILL_CONSOLE_CHARACTER (63) a0=char a1=column a2=row a3=count a4=*writtenOut. static uint64_t SyscallFillConsoleCharacter(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a5; @@ -1326,9 +1236,7 @@ static uint64_t SyscallFillConsoleCharacter(uint64_t a0, uint64_t a1, uint64_t a return s; } -// --------------------------------------------------------------------------- -// SYS_FILL_CONSOLE_ATTRIBUTE (64) a0=attribute a1=column a2=row a3=count a4=*writtenOut -// --------------------------------------------------------------------------- +// SYS_FILL_CONSOLE_ATTRIBUTE (64) a0=attribute a1=column a2=row a3=count a4=*writtenOut. static uint64_t SyscallFillConsoleAttribute(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a5; @@ -1345,27 +1253,21 @@ static uint64_t SyscallFillConsoleAttribute(uint64_t a0, uint64_t a1, uint64_t a return s; } -// --------------------------------------------------------------------------- -// SYS_POLL_KEYBOARD (70) -> next INPUT_KEY or INPUT_KEY_NONE -// --------------------------------------------------------------------------- +// SYS_POLL_KEYBOARD (70) -> next INPUT_KEY or INPUT_KEY_NONE. static uint64_t SyscallKbPoll(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; return (uint64_t)KeInputKbPoll(); } -// --------------------------------------------------------------------------- -// SYS_IS_KEY_DOWN (71) a0=INPUT_KEY -> 1 or 0 -// --------------------------------------------------------------------------- +// SYS_IS_KEY_DOWN (71) a0=INPUT_KEY -> 1 or 0. static uint64_t SyscallKbIsKeyDown(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; return KeInputIsKeyDown((INPUT_KEY)a0) ? 1u : 0u; } -// --------------------------------------------------------------------------- -// SYS_READ_KEYBOARD_CHAR (72) -> char (blocks, yields while waiting) -// --------------------------------------------------------------------------- +// SYS_READ_KEYBOARD_CHAR (72) -> char (blocks, yields while waiting). static uint64_t SyscallKbReadChar(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1373,9 +1275,7 @@ static uint64_t SyscallKbReadChar(uint64_t a0, uint64_t a1, uint64_t a2, return (uint64_t)(uint8_t)KeInputReadChar(); } -// --------------------------------------------------------------------------- -// SYS_READ_KEY (73) -> INPUT_KEY (blocks, yields while waiting) -// --------------------------------------------------------------------------- +// SYS_READ_KEY (73) -> INPUT_KEY (blocks, yields while waiting). static uint64_t SyscallKbReadKey(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1383,27 +1283,21 @@ static uint64_t SyscallKbReadKey(uint64_t a0, uint64_t a1, uint64_t a2, return (uint64_t)KeInputReadKey(); } -// --------------------------------------------------------------------------- -// SYS_GET_KEY_MODIFIERS (74) -> uint32_t INPUT_MOD_* flags -// --------------------------------------------------------------------------- +// SYS_GET_KEY_MODIFIERS (74) -> uint32_t INPUT_MOD_* flags. static uint64_t SyscallKbGetModifiers(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; return (uint64_t)KeInputGetModifiers(); } -// --------------------------------------------------------------------------- -// SYS_POLL_MOUSE (75) -> 1 or 0 -// --------------------------------------------------------------------------- +// SYS_POLL_MOUSE (75) -> 1 or 0. static uint64_t SyscallMousePoll(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; return KeInputMousePoll() ? 1u : 0u; } -// --------------------------------------------------------------------------- -// SYS_READ_MOUSE (76) a0=*dx a1=*dy a2=*buttons -> 1 or 0 -// --------------------------------------------------------------------------- +// SYS_READ_MOUSE (76) a0=*dx a1=*dy a2=*buttons -> 1 or 0. static uint64_t SyscallMouseRead(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a3; (void)a4; (void)a5; @@ -1419,9 +1313,7 @@ static uint64_t SyscallMouseRead(uint64_t a0, uint64_t a1, uint64_t a2, return 1u; } -// --------------------------------------------------------------------------- -// SYS_GET_MOUSE_POS (77) a0=*x a1=*y -// --------------------------------------------------------------------------- +// SYS_GET_MOUSE_POS (77) a0=*x a1=*y. static uint64_t SyscallMouseGetPos(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -1434,18 +1326,14 @@ static uint64_t SyscallMouseGetPos(uint64_t a0, uint64_t a1, uint64_t a2, return KiCopyIntToUser(a1, y); } -// --------------------------------------------------------------------------- -// SYS_GET_TICK (78) -> uint64_t microseconds -// --------------------------------------------------------------------------- +// SYS_GET_TICK (78) -> uint64_t microseconds. static uint64_t SyscallGetTick(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a0; (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; return gHal ? gHal->Timer.QueryTicks() : 0; } -// --------------------------------------------------------------------------- -// SYS_GET_SYSTEM_TIME a0=*SYS_SYSTEM_TIME -// --------------------------------------------------------------------------- +// SYS_GET_SYSTEM_TIME a0=*SYS_SYSTEM_TIME. static uint64_t SyscallGetSystemTime(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1457,9 +1345,7 @@ static uint64_t SyscallGetSystemTime(uint64_t a0, uint64_t a1, uint64_t a2, return CopyToUser((void*)(uintptr_t)a0, &t, sizeof(t)); } -// --------------------------------------------------------------------------- -// SYS_PRINT_DEBUG (79) a0=*str -// --------------------------------------------------------------------------- +// SYS_PRINT_DEBUG (79) a0=*str. static uint64_t SyscallDebugPrint(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1484,9 +1370,7 @@ static uint64_t SyscallDebugPrint(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// SYS_QUERY_TRAP_FRAME a0=*SYS_TRAP_FRAME_INFO -// --------------------------------------------------------------------------- +// SYS_QUERY_TRAP_FRAME a0=*SYS_TRAP_FRAME_INFO. static uint64_t SyscallQueryTrapFrame(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1507,9 +1391,7 @@ static uint64_t SyscallQueryTrapFrame(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_CREATE_PROCESS (50) a0=*path a1=*handleOut a2=*cmdline (optional) -// --------------------------------------------------------------------------- +// SYS_CREATE_PROCESS (50) a0=*path a1=*handleOut a2=*cmdline (optional). static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1555,7 +1437,7 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2, if (!KSUCCESS(s)) { ProcDbg("CreateProcess: KeCreateProcess failed st=%d\n", s); MmFreePool(mem); return s; } ProcDbg("CreateProcess: created pid=%u name=%s\n", proc->ProcessId, proc->Name); - // Inherit CWD from parent + // Inherit CWD from parent. PROCESS* parent = KeGetCurrentProcess(); if (parent) { uintptr_t flags = KeAcquireSpinlock(&parent->CwdLock); @@ -1641,10 +1523,8 @@ static uint64_t SyscallCreateProcess(uint64_t a0, uint64_t a1, uint64_t a2, ObDereferenceObject(&proc->Header); return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- // SYS_WAIT_FOR_PROCESS (51) a0=handle // Blocks until the target process signals its ExitEvent. -// --------------------------------------------------------------------------- static uint64_t SyscallWaitForProcess(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1657,9 +1537,7 @@ static uint64_t SyscallWaitForProcess(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_GET_PROCESS_EXIT_CODE (52) a0=handle a1=*exitCodeOut -// --------------------------------------------------------------------------- +// SYS_GET_PROCESS_EXIT_CODE (52) a0=handle a1=*exitCodeOut. static uint64_t SyscallGetProcessExitCode(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -1675,10 +1553,8 @@ static uint64_t SyscallGetProcessExitCode(uint64_t a0, uint64_t a1, uint64_t a2, return KiCopyIntToUser(a1, exitCode); } -// --------------------------------------------------------------------------- // SYS_WRITE_CONSOLE (60) a0=*buf a1=len // Writes user console text in white; distinct from green SYS_PRINT_DEBUG. -// --------------------------------------------------------------------------- static uint64_t SyscallWriteConsole(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1703,9 +1579,7 @@ static uint64_t SyscallWriteConsole(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// SYS_OPEN_DIR (54) a0=*dirPath a1=*handleOut -// --------------------------------------------------------------------------- +// SYS_OPEN_DIR (54) a0=*dirPath a1=*handleOut. static uint64_t SyscallOpenDir(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1743,10 +1617,8 @@ static uint64_t SyscallOpenDir(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- // SYS_READ_DIR (55) a0=handle a1=*KDIR_ENTRY // Returns STATUS_NO_MORE_FILES when the directory is exhausted. -// --------------------------------------------------------------------------- static uint64_t SyscallReadDir(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -1763,9 +1635,7 @@ static uint64_t SyscallReadDir(uint64_t a0, uint64_t a1, uint64_t a2, return CopyToUser((void*)(uintptr_t)a1, &entry, sizeof(entry)); } -// --------------------------------------------------------------------------- -// SYS_SET_CWD (56) a0=*path -// --------------------------------------------------------------------------- +// SYS_SET_CWD (56) a0=*path. static uint64_t SyscallSetCwd(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1783,9 +1653,7 @@ static uint64_t SyscallSetCwd(uint64_t a0, uint64_t a1, uint64_t a2, return IoSetCwd(path); } -// --------------------------------------------------------------------------- -// SYS_GET_CWD (57) a0=*buf a1=size -// --------------------------------------------------------------------------- +// SYS_GET_CWD (57) a0=*buf a1=size. static uint64_t SyscallGetCwd(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1809,14 +1677,12 @@ static uint64_t SyscallGetCwd(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- // SYS_WAIT_THREAD (58) a0=tid // Blocks the caller until the thread with the given TID exits. // Searches the current process's thread list; cross-process join is not // supported in v1 (POSIX pthread_join is always intra-process). // Returns STATUS_NOT_FOUND if the TID is unknown (already reaped or never // existed) - treat the same as a successful join at the POSIX layer. -// --------------------------------------------------------------------------- static uint64_t SyscallWaitThread(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1853,11 +1719,9 @@ static uint64_t SyscallWaitThread(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- // SYS_GET_PROCESS_PID (59) a0=procHandle a1=*pidOut // Returns the numeric PID of a process identified by handle. // Used by posix_spawn to map the kernel handle back to a pid_t for waitpid. -// --------------------------------------------------------------------------- static uint64_t SyscallGetProcessPid(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -1871,17 +1735,15 @@ static uint64_t SyscallGetProcessPid(uint64_t a0, uint64_t a1, uint64_t a2, return KiCopyU32ToUser(a1, pid); } -// =========================================================================== // Named Queue Registry -// + // A flat, fixed-size table of { name -> QUEUE* } pairs protected by a // spinlock. The registry holds one reference to each published queue for // the lifetime of the entry, so the queue object cannot be destroyed while // it is registered even if every process closes its own handle to it. -// + // Limits: NAMED_QUEUE_MAX names, each up to NAMED_QUEUE_NAME_MAX bytes. // These are generous for the intended usage (a handful of system servers). -// =========================================================================== #define NAMED_QUEUE_MAX 16 #define NAMED_QUEUE_NAME_MAX 64 @@ -1902,13 +1764,11 @@ static int KiNamedQueueNameEquals(const NAMED_QUEUE_ENTRY* entry, return SysSvEqual(SysSvFromParts(entry->Name, entry->NameLength), name); } -// --------------------------------------------------------------------------- // SYS_PUBLISH_QUEUE (60) a0=*name a1=queueHandle -// + // Registers the queue identified by 'queueHandle' under 'name'. // Fails with STATUS_ALREADY_EXISTS if the name is already taken. // The registry bumps the queue's refcount so it outlives the handle. -// --------------------------------------------------------------------------- static uint64_t SyscallPublishQueue(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -1952,13 +1812,11 @@ static uint64_t SyscallPublishQueue(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_NO_MEMORY; } -// --------------------------------------------------------------------------- // SYS_OPEN_NAMED_QUEUE (61) a0=*name a1=*handleOut -// + // Looks up 'name' in the registry and allocates a handle to the queue in the // calling process's handle table. Returns STATUS_NOT_FOUND if no match. // Callers that race against the publisher should retry on NOT_FOUND. -// --------------------------------------------------------------------------- static uint64_t SyscallOpenNamedQueue(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -2005,14 +1863,12 @@ static uint64_t SyscallOpenNamedQueue(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- // SYS_DUPLICATE_QUEUE (62) a0=handle a1=targetPid a2=*handleOut -// + // Looks up the QUEUE behind 'handle' in the CALLER's table, then allocates // a new handle for the same object in the TARGET process's table. // Both processes share the same underlying QUEUE (refcount bumped). // The caller's own handle is unchanged. -// --------------------------------------------------------------------------- static uint64_t SyscallQueueDuplicate(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a3; (void)a4; (void)a5; @@ -2042,13 +1898,11 @@ static uint64_t SyscallQueueDuplicate(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- // SYS_GET_NAMED_QUEUE_OWNER_PID (63) a0=*name a1=*pidOut -// + // Returns the ProcessId of whoever published the named queue. // Lets a client get the publisher's PID so it can duplicate one of its // own handles into that process via SYS_DUPLICATE_QUEUE. -// --------------------------------------------------------------------------- static uint64_t SyscallNamedQueueOwnerPid(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -2095,9 +1949,7 @@ static uint64_t SyscallKillProcess(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_GET_PROCESS_LIST (6) a0=*SYS_PROCESS_INFO[] a1=maxCount a2=*countOut -// --------------------------------------------------------------------------- +// SYS_GET_PROCESS_LIST (6) a0=*SYS_PROCESS_INFO[] a1=maxCount a2=*countOut. static uint64_t SyscallGetProcessList(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a3; (void)a4; (void)a5; @@ -2131,9 +1983,7 @@ static uint64_t SyscallGetProcessList(uint64_t a0, uint64_t a1, uint64_t a2, return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// SYS_RENAME_FILE (66) a0=*oldPath a1=*newPath -// --------------------------------------------------------------------------- +// SYS_RENAME_FILE (66) a0=*oldPath a1=*newPath. static uint64_t SyscallRenameFile(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -2154,9 +2004,7 @@ static uint64_t SyscallRenameFile(uint64_t a0, uint64_t a1, uint64_t a2, return IoRenameFile(oldPath, newPath); } -// --------------------------------------------------------------------------- -// SYS_CREATE_DIR (67) a0=*path -// --------------------------------------------------------------------------- +// SYS_CREATE_DIR (67) a0=*path. static uint64_t SyscallCreateDir(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -2173,9 +2021,7 @@ static uint64_t SyscallCreateDir(uint64_t a0, uint64_t a1, uint64_t a2, return IoCreateDir(path); } -// --------------------------------------------------------------------------- -// SYS_REMOVE_DIR (68) a0=*path -// --------------------------------------------------------------------------- +// SYS_REMOVE_DIR (68) a0=*path. static uint64_t SyscallRemoveDir(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -2234,9 +2080,7 @@ typedef struct SYS_MEMORY_STATUS_K { #define SYS_POLL_MAX_FDS 64u -// --------------------------------------------------------------------------- -// SYS_CREATE_SOCKET a0=domain a1=type a2=protocol a3=*handleOut -// --------------------------------------------------------------------------- +// SYS_CREATE_SOCKET a0=domain a1=type a2=protocol a3=*handleOut. static uint64_t SyscallSocket(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a4; (void)a5; @@ -2261,9 +2105,7 @@ static uint64_t SyscallSocket(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_BIND_SOCKET a0=socketHandle a1=*SYS_SOCKET_ADDRESS_IPV4 a2=addressSize -// --------------------------------------------------------------------------- +// SYS_BIND_SOCKET a0=socketHandle a1=*SYS_SOCKET_ADDRESS_IPV4 a2=addressSize. static uint64_t SyscallBind(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a3; (void)a4; (void)a5; @@ -2282,9 +2124,7 @@ static uint64_t SyscallBind(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_LISTEN_SOCKET a0=socketHandle a1=backlog -// --------------------------------------------------------------------------- +// SYS_LISTEN_SOCKET a0=socketHandle a1=backlog. static uint64_t SyscallListen(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -2297,10 +2137,8 @@ static uint64_t SyscallListen(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- // SYS_ACCEPT_SOCKET a0=listenSocket a1=*remoteAddressOut(optional) -// a2=*remoteAddressSizeInOut(optional) a3=*acceptedHandleOut -// --------------------------------------------------------------------------- +// a2=*remoteAddressSizeInOut(optional) a3=*acceptedHandleOut. static uint64_t SyscallAccept(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a4; (void)a5; @@ -2354,9 +2192,7 @@ static uint64_t SyscallAccept(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_CONNECT_SOCKET a0=socketHandle a1=*SYS_SOCKET_ADDRESS_IPV4 a2=addressSize -// --------------------------------------------------------------------------- +// SYS_CONNECT_SOCKET a0=socketHandle a1=*SYS_SOCKET_ADDRESS_IPV4 a2=addressSize. static uint64_t SyscallConnect(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a3; (void)a4; (void)a5; @@ -2375,9 +2211,7 @@ static uint64_t SyscallConnect(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_SEND_SOCKET a0=socketHandle a1=*buffer a2=length a3=flags a4=*sentOut(optional) -// --------------------------------------------------------------------------- +// SYS_SEND_SOCKET a0=socketHandle a1=*buffer a2=length a3=flags a4=*sentOut(optional). static uint64_t SyscallSend(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a5; @@ -2411,9 +2245,7 @@ static uint64_t SyscallSend(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_RECV_SOCKET a0=socketHandle a1=*buffer a2=length a3=flags a4=*receivedOut(optional) -// --------------------------------------------------------------------------- +// SYS_RECV_SOCKET a0=socketHandle a1=*buffer a2=length a3=flags a4=*receivedOut(optional). static uint64_t SyscallRecv(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a5; @@ -2448,9 +2280,7 @@ static uint64_t SyscallRecv(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_SHUTDOWN_SOCKET a0=socketHandle a1=SYS_SHUTDOWN_SOCKET_* -// --------------------------------------------------------------------------- +// SYS_SHUTDOWN_SOCKET a0=socketHandle a1=SYS_SHUTDOWN_SOCKET_*. static uint64_t SyscallShutdown(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -2463,9 +2293,7 @@ static uint64_t SyscallShutdown(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_SEND_TO_SOCKET a0=socketHandle a1=*SYS_SOCKET_SEND_TO_REQUEST -// --------------------------------------------------------------------------- +// SYS_SEND_TO_SOCKET a0=socketHandle a1=*SYS_SOCKET_SEND_TO_REQUEST. static uint64_t SyscallSendTo(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -2506,9 +2334,7 @@ static uint64_t SyscallSendTo(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_RECV_FROM_SOCKET a0=socketHandle a1=*SYS_SOCKET_RECV_FROM_REQUEST -// --------------------------------------------------------------------------- +// SYS_RECV_FROM_SOCKET a0=socketHandle a1=*SYS_SOCKET_RECV_FROM_REQUEST. static uint64_t SyscallRecvFrom(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -2573,9 +2399,7 @@ static uint64_t SyscallRecvFrom(uint64_t a0, uint64_t a1, uint64_t a2, } -// --------------------------------------------------------------------------- -// SYS_RESOLVE_HOST a0=*SYS_RESOLVE_HOST_REQUEST -// --------------------------------------------------------------------------- +// SYS_RESOLVE_HOST a0=*SYS_RESOLVE_HOST_REQUEST. static uint64_t SyscallResolveHost(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -2619,9 +2443,7 @@ static uint64_t SyscallResolveHost(uint64_t a0, uint64_t a1, uint64_t a2, } -// --------------------------------------------------------------------------- -// SYS_SET_SOCKET_OPTION a0=socketHandle a1=*SYS_SOCKET_OPTION_REQUEST -// --------------------------------------------------------------------------- +// SYS_SET_SOCKET_OPTION a0=socketHandle a1=*SYS_SOCKET_OPTION_REQUEST. static uint64_t SyscallSetSocketOption(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -2645,9 +2467,7 @@ static uint64_t SyscallSetSocketOption(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_GET_SOCKET_OPTION a0=socketHandle a1=*SYS_SOCKET_OPTION_REQUEST -// --------------------------------------------------------------------------- +// SYS_GET_SOCKET_OPTION a0=socketHandle a1=*SYS_SOCKET_OPTION_REQUEST. static uint64_t SyscallGetSocketOption(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a2; (void)a3; (void)a4; (void)a5; @@ -2679,6 +2499,7 @@ static uint64_t SyscallGetSocketOption(uint64_t a0, uint64_t a1, uint64_t a2, return s; } +// Polls deadline Expired. static int KiPollDeadlineExpired(uint64_t start, uint32_t timeoutMs) { if (timeoutMs == 0) return 1; @@ -2689,9 +2510,7 @@ static int KiPollDeadlineExpired(uint64_t start, uint32_t timeoutMs) { return (gHal->Timer.QueryTicks() - start) >= ((uint64_t)timeoutMs * 1000u); } -// --------------------------------------------------------------------------- -// SYS_POLL a0=*SYS_POLLFD array a1=count a2=timeoutMs a3=*readyOut(optional) -// --------------------------------------------------------------------------- +// SYS_POLL a0=*SYS_POLLFD array a1=count a2=timeoutMs a3=*readyOut(optional). static uint64_t SyscallPoll(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a4; (void)a5; @@ -2748,9 +2567,7 @@ static uint64_t SyscallPoll(uint64_t a0, uint64_t a1, uint64_t a2, return s; } -// --------------------------------------------------------------------------- -// SYS_GET_MEMORY_STATUS a0=*SYS_MEMORY_STATUS -// --------------------------------------------------------------------------- +// SYS_GET_MEMORY_STATUS a0=*SYS_MEMORY_STATUS. static uint64_t SyscallGetMemoryStatus(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { (void)a1; (void)a2; (void)a3; (void)a4; (void)a5; @@ -2765,9 +2582,7 @@ static uint64_t SyscallGetMemoryStatus(uint64_t a0, uint64_t a1, uint64_t a2, } -// --------------------------------------------------------------------------- -// SYS_QUERY_KERNEL_STATS a0=classId a1=buffer a2=bufferSize a3=*requiredSizeOut -// --------------------------------------------------------------------------- +// SYS_QUERY_KERNEL_STATS a0=classId a1=buffer a2=bufferSize a3=*requiredSizeOut. static KSTATUS KiReturnKernelStats(uint64_t bufferArg, size_t bufferSize, uint64_t requiredArg, const void* src, size_t size) { @@ -2878,116 +2693,112 @@ static uint64_t SyscallQueryKernelStats(uint64_t a0, uint64_t a1, uint64_t a2, } } -// =========================================================================== // Dispatch table - index must match SYS_* in syscall_nr.h exactly. -// =========================================================================== typedef uint64_t (*SYSCALL_HANDLER)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t); static const SYSCALL_HANDLER gSyscallTable[SYS_MAX] = { - /* 00 SYS_EXIT_PROCESS */ SyscallExitProcess, - /* 01 SYS_EXIT_THREAD */ SyscallExitThread, - /* 02 SYS_CREATE_PROCESS */ SyscallCreateProcess, - /* 03 SYS_WAIT_FOR_PROCESS */ SyscallWaitForProcess, - /* 04 SYS_GET_PROCESS_EXIT_CODE */ SyscallGetProcessExitCode, - /* 05 SYS_KILL_PROCESS */ SyscallKillProcess, - /* 06 SYS_GET_PROCESS_LIST */ SyscallGetProcessList, - /* 07 SYS_GET_PROCESS_PID */ SyscallGetProcessPid, - /* 08 SYS_CREATE_THREAD */ SyscallCreateThread, - /* 09 SYS_WAIT_THREAD */ SyscallWaitThread, - /* 10 SYS_GET_CURRENT_TID */ SyscallGetCurrentTid, - /* 11 SYS_GET_CURRENT_PID */ SyscallGetCurrentPid, - /* 12 SYS_SET_THREAD_PRIORITY */ SyscallSetThreadPriority, - /* 13 SYS_YIELD */ SyscallYield, - /* 14 SYS_SLEEP */ SyscallSleep, - /* 15 SYS_SET_USER_APC_DISPATCHER */ SyscallSetUserApcDispatcher, - /* 16 SYS_APC_RETURN */ SyscallApcReturn, - /* 17 SYS_ALLOC_VM */ SyscallVmAlloc, - /* 18 SYS_FREE_VM */ SyscallVmFree, - /* 19 SYS_PROTECT_VM */ SyscallVmProtect, - /* 20 SYS_QUERY_VM */ SyscallVmQuery, - /* 21 SYS_CLOSE_HANDLE */ SyscallCloseHandle, - /* 22 SYS_CREATE_MUTEX */ SyscallMutexCreate, - /* 23 SYS_ACQUIRE_MUTEX */ SyscallMutexAcquire, - /* 24 SYS_TRY_ACQUIRE_MUTEX */ SyscallMutexTryAcquire, - /* 25 SYS_RELEASE_MUTEX */ SyscallMutexRelease, - /* 26 SYS_CREATE_SEM */ SyscallSemCreate, - /* 27 SYS_WAIT_SEM */ SyscallSemWait, - /* 28 SYS_TRY_WAIT_SEM */ SyscallSemTryWait, - /* 29 SYS_SIGNAL_SEM */ SyscallSemSignal, - /* 30 SYS_CREATE_EVENT */ SyscallEventCreate, - /* 31 SYS_SIGNAL_EVENT */ SyscallEventSignal, - /* 32 SYS_CLEAR_EVENT */ SyscallEventClear, - /* 33 SYS_WAIT_EVENT */ SyscallEventWait, - /* 34 SYS_CREATE_QUEUE */ SyscallQueueCreate, - /* 35 SYS_SEND_QUEUE */ SyscallQueueSend, - /* 36 SYS_RECV_QUEUE */ SyscallQueueRecv, - /* 37 SYS_PUBLISH_QUEUE */ SyscallPublishQueue, - /* 38 SYS_OPEN_NAMED_QUEUE */ SyscallOpenNamedQueue, - /* 39 SYS_DUPLICATE_QUEUE */ SyscallQueueDuplicate, - /* 40 SYS_GET_NAMED_QUEUE_OWNER_PID */ SyscallNamedQueueOwnerPid, - /* 41 SYS_OPEN_FILE */ SyscallOpenFile, - /* 42 SYS_CREATE_FILE */ SyscallCreateFile, - /* 43 SYS_READ_FILE */ SyscallReadFile, - /* 44 SYS_WRITE_FILE */ SyscallWriteFile, - /* 45 SYS_READ_FILE_ASYNC */ SyscallReadFileAsync, - /* 46 SYS_WRITE_FILE_ASYNC */ SyscallWriteFileAsync, - /* 47 SYS_CANCEL_IO */ SyscallCancelIo, - /* 48 SYS_SEEK_FILE */ SyscallSeekFile, - /* 49 SYS_GET_FILE_POS */ SyscallGetFilePos, - /* 50 SYS_GET_FILE_SIZE */ SyscallGetFileSize, - /* 51 SYS_TRUNCATE_FILE */ SyscallTruncateFile, - /* 52 SYS_DELETE_FILE */ SyscallDeleteFile, - /* 53 SYS_RENAME_FILE */ SyscallRenameFile, - /* 54 SYS_OPEN_DIR */ SyscallOpenDir, - /* 55 SYS_READ_DIR */ SyscallReadDir, - /* 56 SYS_CREATE_DIR */ SyscallCreateDir, - /* 57 SYS_REMOVE_DIR */ SyscallRemoveDir, - /* 58 SYS_SET_CWD */ SyscallSetCwd, - /* 59 SYS_GET_CWD */ SyscallGetCwd, - /* 60 SYS_WRITE_CONSOLE */ SyscallWriteConsole, - /* 61 SYS_GET_CONSOLE_INFO */ SyscallGetConsoleInfo, - /* 62 SYS_SET_CONSOLE_CURSOR */ SyscallSetConsoleCursor, - /* 63 SYS_FILL_CONSOLE_CHARACTER */ SyscallFillConsoleCharacter, - /* 64 SYS_FILL_CONSOLE_ATTRIBUTE */ SyscallFillConsoleAttribute, - /* 65 SYS_PUT_SCREEN_CHAR */ SyscallPutScreenChar, - /* 66 SYS_BLIT_SCREEN */ SyscallBlitScreen, - /* 67 SYS_CLEAR_SCREEN */ SyscallClearScreen, - /* 68 SYS_GET_SCREEN_SIZE */ SyscallGetScreenSize, - /* 69 SYS_QUERY_DISPLAY_INFO */ SyscallQueryDisplayInfo, - /* 70 SYS_POLL_KEYBOARD */ SyscallKbPoll, - /* 71 SYS_IS_KEY_DOWN */ SyscallKbIsKeyDown, - /* 72 SYS_READ_KEYBOARD_CHAR */ SyscallKbReadChar, - /* 73 SYS_READ_KEY */ SyscallKbReadKey, - /* 74 SYS_GET_KEY_MODIFIERS */ SyscallKbGetModifiers, - /* 75 SYS_POLL_MOUSE */ SyscallMousePoll, - /* 76 SYS_READ_MOUSE */ SyscallMouseRead, - /* 77 SYS_GET_MOUSE_POS */ SyscallMouseGetPos, - /* 78 SYS_GET_TICK */ SyscallGetTick, - /* 79 SYS_PRINT_DEBUG */ SyscallDebugPrint, - /* 80 SYS_QUERY_TRAP_FRAME */ SyscallQueryTrapFrame, - /* 81 SYS_CREATE_SOCKET */ SyscallSocket, - /* 82 SYS_BIND_SOCKET */ SyscallBind, - /* 83 SYS_LISTEN_SOCKET */ SyscallListen, - /* 84 SYS_ACCEPT_SOCKET */ SyscallAccept, - /* 85 SYS_CONNECT_SOCKET */ SyscallConnect, - /* 86 SYS_SEND_SOCKET */ SyscallSend, - /* 87 SYS_RECV_SOCKET */ SyscallRecv, - /* 88 SYS_SHUTDOWN_SOCKET */ SyscallShutdown, - /* 89 SYS_SEND_TO_SOCKET */ SyscallSendTo, - /* 90 SYS_RECV_FROM_SOCKET */ SyscallRecvFrom, - /* 91 SYS_RESOLVE_HOST */ SyscallResolveHost, - /* 92 SYS_SET_SOCKET_OPTION */ SyscallSetSocketOption, - /* 93 SYS_GET_SOCKET_OPTION */ SyscallGetSocketOption, - /* 94 SYS_POLL */ SyscallPoll, - /* 95 SYS_GET_MEMORY_STATUS */ SyscallGetMemoryStatus, - /* 96 SYS_QUERY_KERNEL_STATS */ SyscallQueryKernelStats, - /* 97 SYS_GET_SYSTEM_TIME */ SyscallGetSystemTime + SyscallExitProcess, // 00 SYS_EXIT_PROCESS. + SyscallExitThread, // 01 SYS_EXIT_THREAD. + SyscallCreateProcess, // 02 SYS_CREATE_PROCESS. + SyscallWaitForProcess, // 03 SYS_WAIT_FOR_PROCESS. + SyscallGetProcessExitCode, // 04 SYS_GET_PROCESS_EXIT_CODE. + SyscallKillProcess, // 05 SYS_KILL_PROCESS. + SyscallGetProcessList, // 06 SYS_GET_PROCESS_LIST. + SyscallGetProcessPid, // 07 SYS_GET_PROCESS_PID. + SyscallCreateThread, // 08 SYS_CREATE_THREAD. + SyscallWaitThread, // 09 SYS_WAIT_THREAD. + SyscallGetCurrentTid, // 10 SYS_GET_CURRENT_TID. + SyscallGetCurrentPid, // 11 SYS_GET_CURRENT_PID. + SyscallSetThreadPriority, // 12 SYS_SET_THREAD_PRIORITY. + SyscallYield, // 13 SYS_YIELD. + SyscallSleep, // 14 SYS_SLEEP. + SyscallSetUserApcDispatcher, // 15 SYS_SET_USER_APC_DISPATCHER. + SyscallApcReturn, // 16 SYS_APC_RETURN. + SyscallVmAlloc, // 17 SYS_ALLOC_VM. + SyscallVmFree, // 18 SYS_FREE_VM. + SyscallVmProtect, // 19 SYS_PROTECT_VM. + SyscallVmQuery, // 20 SYS_QUERY_VM. + SyscallCloseHandle, // 21 SYS_CLOSE_HANDLE. + SyscallMutexCreate, // 22 SYS_CREATE_MUTEX. + SyscallMutexAcquire, // 23 SYS_ACQUIRE_MUTEX. + SyscallMutexTryAcquire, // 24 SYS_TRY_ACQUIRE_MUTEX. + SyscallMutexRelease, // 25 SYS_RELEASE_MUTEX. + SyscallSemCreate, // 26 SYS_CREATE_SEM. + SyscallSemWait, // 27 SYS_WAIT_SEM. + SyscallSemTryWait, // 28 SYS_TRY_WAIT_SEM. + SyscallSemSignal, // 29 SYS_SIGNAL_SEM. + SyscallEventCreate, // 30 SYS_CREATE_EVENT. + SyscallEventSignal, // 31 SYS_SIGNAL_EVENT. + SyscallEventClear, // 32 SYS_CLEAR_EVENT. + SyscallEventWait, // 33 SYS_WAIT_EVENT. + SyscallQueueCreate, // 34 SYS_CREATE_QUEUE. + SyscallQueueSend, // 35 SYS_SEND_QUEUE. + SyscallQueueRecv, // 36 SYS_RECV_QUEUE. + SyscallPublishQueue, // 37 SYS_PUBLISH_QUEUE. + SyscallOpenNamedQueue, // 38 SYS_OPEN_NAMED_QUEUE. + SyscallQueueDuplicate, // 39 SYS_DUPLICATE_QUEUE. + SyscallNamedQueueOwnerPid, // 40 SYS_GET_NAMED_QUEUE_OWNER_PID. + SyscallOpenFile, // 41 SYS_OPEN_FILE. + SyscallCreateFile, // 42 SYS_CREATE_FILE. + SyscallReadFile, // 43 SYS_READ_FILE. + SyscallWriteFile, // 44 SYS_WRITE_FILE. + SyscallReadFileAsync, // 45 SYS_READ_FILE_ASYNC. + SyscallWriteFileAsync, // 46 SYS_WRITE_FILE_ASYNC. + SyscallCancelIo, // 47 SYS_CANCEL_IO. + SyscallSeekFile, // 48 SYS_SEEK_FILE. + SyscallGetFilePos, // 49 SYS_GET_FILE_POS. + SyscallGetFileSize, // 50 SYS_GET_FILE_SIZE. + SyscallTruncateFile, // 51 SYS_TRUNCATE_FILE. + SyscallDeleteFile, // 52 SYS_DELETE_FILE. + SyscallRenameFile, // 53 SYS_RENAME_FILE. + SyscallOpenDir, // 54 SYS_OPEN_DIR. + SyscallReadDir, // 55 SYS_READ_DIR. + SyscallCreateDir, // 56 SYS_CREATE_DIR. + SyscallRemoveDir, // 57 SYS_REMOVE_DIR. + SyscallSetCwd, // 58 SYS_SET_CWD. + SyscallGetCwd, // 59 SYS_GET_CWD. + SyscallWriteConsole, // 60 SYS_WRITE_CONSOLE. + SyscallGetConsoleInfo, // 61 SYS_GET_CONSOLE_INFO. + SyscallSetConsoleCursor, // 62 SYS_SET_CONSOLE_CURSOR. + SyscallFillConsoleCharacter, // 63 SYS_FILL_CONSOLE_CHARACTER. + SyscallFillConsoleAttribute, // 64 SYS_FILL_CONSOLE_ATTRIBUTE. + SyscallPutScreenChar, // 65 SYS_PUT_SCREEN_CHAR. + SyscallBlitScreen, // 66 SYS_BLIT_SCREEN. + SyscallClearScreen, // 67 SYS_CLEAR_SCREEN. + SyscallGetScreenSize, // 68 SYS_GET_SCREEN_SIZE. + SyscallQueryDisplayInfo, // 69 SYS_QUERY_DISPLAY_INFO. + SyscallKbPoll, // 70 SYS_POLL_KEYBOARD. + SyscallKbIsKeyDown, // 71 SYS_IS_KEY_DOWN. + SyscallKbReadChar, // 72 SYS_READ_KEYBOARD_CHAR. + SyscallKbReadKey, // 73 SYS_READ_KEY. + SyscallKbGetModifiers, // 74 SYS_GET_KEY_MODIFIERS. + SyscallMousePoll, // 75 SYS_POLL_MOUSE. + SyscallMouseRead, // 76 SYS_READ_MOUSE. + SyscallMouseGetPos, // 77 SYS_GET_MOUSE_POS. + SyscallGetTick, // 78 SYS_GET_TICK. + SyscallDebugPrint, // 79 SYS_PRINT_DEBUG. + SyscallQueryTrapFrame, // 80 SYS_QUERY_TRAP_FRAME. + SyscallSocket, // 81 SYS_CREATE_SOCKET. + SyscallBind, // 82 SYS_BIND_SOCKET. + SyscallListen, // 83 SYS_LISTEN_SOCKET. + SyscallAccept, // 84 SYS_ACCEPT_SOCKET. + SyscallConnect, // 85 SYS_CONNECT_SOCKET. + SyscallSend, // 86 SYS_SEND_SOCKET. + SyscallRecv, // 87 SYS_RECV_SOCKET. + SyscallShutdown, // 88 SYS_SHUTDOWN_SOCKET. + SyscallSendTo, // 89 SYS_SEND_TO_SOCKET. + SyscallRecvFrom, // 90 SYS_RECV_FROM_SOCKET. + SyscallResolveHost, // 91 SYS_RESOLVE_HOST. + SyscallSetSocketOption, // 92 SYS_SET_SOCKET_OPTION. + SyscallGetSocketOption, // 93 SYS_GET_SOCKET_OPTION. + SyscallPoll, // 94 SYS_POLL. + SyscallGetMemoryStatus, // 95 SYS_GET_MEMORY_STATUS. + SyscallQueryKernelStats, // 96 SYS_QUERY_KERNEL_STATS. + SyscallGetSystemTime // 97 SYS_GET_SYSTEM_TIME. }; -// --------------------------------------------------------------------------- -// Entry point - called from ke_syscall.asm after argument re-ordering -// --------------------------------------------------------------------------- +// KeSyscallDispatch is entered from ke_syscall.asm after the assembly stub has reordered registers into the C calling convention. uint64_t KeSyscallDispatch(uint64_t nr, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5) { KiValidateSyscallTrapFrame(nr, a0, a1, a2, a3, a4, a5); diff --git a/code/kernel/ke_thread.c b/code/kernel/ke_thread.c index 6c3cd27..f73200d 100644 --- a/code/kernel/ke_thread.c +++ b/code/kernel/ke_thread.c @@ -1,4 +1,5 @@ -// ke_thread.c - thread model +// Thread manager. This file owns thread allocation, kernel/user startup contexts, and lifecycle transitions. + #include #include #include @@ -31,6 +32,7 @@ STATIC_ASSERT_OFFSET(THREAD, FpuContext, 168); static uint32_t gNextThreadId = 1; extern void KeThreadEntry(void); +// Implements the thread Destroy operation. static void KiThreadDestroy(OBJECT* obj) { THREAD* thread = CONTAINING_RECORD(obj, THREAD, Header); @@ -65,6 +67,7 @@ static void KiThreadDestroy(OBJECT* obj) { KeReleaseSpinlock(&owner->HandleLock, flags); if (remaining == 0 && owner->Terminating && + // Implements the interlocked Exchange operation. _InterlockedExchange(&owner->Exited, 1) == 0) { if (owner->ExitEvent) KeSignalEvent(owner->ExitEvent); } @@ -213,6 +216,7 @@ __declspec(dllexport) KSTATUS KeCreateThread(PROCESS* owner, uintptr_t entry, ui return STATUS_SUCCESS; } +// Implements the exit Thread operation. __declspec(dllexport) void KeExitThread(THREAD* thread, int code) { (void)code; if (!thread) return; @@ -229,18 +233,15 @@ __declspec(dllexport) void KeExitThread(THREAD* thread, int code) { KeYield(); } -// --------------------------------------------------------------------------- // KeCreateKernelThread -// --------------------------------------------------------------------------- // Kernel threads never go to ring 3: they have no user stack, no TEB, and // their entry stub (KeKernelThreadEntry) calls the function directly then // calls KeExitThread instead of IRETQ-ing. -// + // Stack layout built here (from KernelStackTop downward): // [ksp - 8 ] arg <-- popped by KeKernelThreadEntry as r12 // [ksp - 16] fn <-- popped by KeKernelThreadEntry as rbx -// [ksp - 16 - sizeof(KCONTEXT)] KCONTEXT { .Rip = KeKernelThreadEntry } -// --------------------------------------------------------------------------- +// [ksp - 16 - sizeof(KCONTEXT)] KCONTEXT { .Rip = KeKernelThreadEntry }. extern void KeKernelThreadEntry(void); static KSTATUS KiCreateKernelThreadWithAffinity(uintptr_t fn, uintptr_t arg, @@ -338,6 +339,7 @@ __declspec(dllexport) KSTATUS KeCreateKernelThreadWithAffinity(uintptr_t fn, uin return KiCreateKernelThreadWithAffinity(fn, arg, priority, affinityMask, out); } +// Prepares block Thread. void KePrepareBlockThread(THREAD* thread, OBJECT* waitObject, uint8_t alertable) { // Called with the synchronization object's spinlock held, so the caller is // normally at DISPATCH_LEVEL here. This function only marks intent to @@ -353,12 +355,14 @@ void KePrepareBlockThread(THREAD* thread, OBJECT* waitObject, uint8_t alertable) } +// Updates thread Wait List. void KeSetThreadWaitList(THREAD* thread, LIST_ENTRY* waitListHead) { KeAssertIrqlAtOrBelow(DISPATCH_LEVEL); if (!thread) return; thread->WaitListHead = waitListHead; } +// Implements the finish Wait operation. static void KiFinishWait(THREAD* thread, KSTATUS status) { thread->WaitObject = (OBJECT*)0; thread->WaitStatus = status; @@ -366,6 +370,7 @@ static void KiFinishWait(THREAD* thread, KSTATUS status) { thread->AlertableWait = 0; } +// Implements the commit Block Thread operation. KSTATUS KeCommitBlockThread(THREAD* thread, uint8_t alertable) { KeAssertIrql(PASSIVE_LEVEL); if (!thread) return STATUS_INVALID_PARAMETER; @@ -405,21 +410,25 @@ KSTATUS KeCommitBlockThread(THREAD* thread, uint8_t alertable) { } +// Implements the block Thread operation. KSTATUS KeBlockThread(THREAD* thread, OBJECT* waitObject, uint8_t alertable) { KePrepareBlockThread(thread, waitObject, alertable); return KeCommitBlockThread(thread, alertable); } +// Implements the unblock Thread With Status operation. void KeUnblockThreadWithStatus(THREAD* thread, KSTATUS status) { if (!thread) return; KiSchedulerWakeThread(thread, status); } +// Implements the unblock Thread operation. void KeUnblockThread(THREAD* thread) { KeUnblockThreadWithStatus(thread, STATUS_SUCCESS); } +// Implements the alert Thread With Status operation. static KSTATUS KiAlertThreadWithStatus(THREAD* thread, KSTATUS status) { if (!thread) return STATUS_INVALID_PARAMETER; @@ -433,14 +442,17 @@ static KSTATUS KiAlertThreadWithStatus(THREAD* thread, KSTATUS status) { return STATUS_SUCCESS; } +// Implements the alert Thread operation. KSTATUS KeAlertThread(THREAD* thread) { return KiAlertThreadWithStatus(thread, STATUS_ALERTED); } +// Implements the wake Thread For Kernel Apc operation. void KiWakeThreadForKernelApc(THREAD* thread) { (void)KiAlertThreadWithStatus(thread, STATUS_KERNEL_APC); } +// Implements the wake Thread For User Apc operation. void KiWakeThreadForUserApc(THREAD* thread) { (void)KiAlertThreadWithStatus(thread, STATUS_USER_APC); } diff --git a/code/kernel/ke_time.c b/code/kernel/ke_time.c index abe996b..42b0d11 100644 --- a/code/kernel/ke_time.c +++ b/code/kernel/ke_time.c @@ -1,4 +1,5 @@ -// ke_time.c - kernel wall-clock time service +// Kernel wall-clock service. This file owns boot-time conversion, timezone policy, and current-time queries. + #include #include #include @@ -50,10 +51,12 @@ static KE_TIME_ZONE_POLICY gTimeZonePolicy = { }; static KE_HARDWARE_CLOCK_MODE gHardwareClockMode = KeHardwareClockUtc; +// Checks whether leap Year. static bool KiIsLeapYear(uint32_t year) { return ((year % 4u) == 0u && (year % 100u) != 0u) || ((year % 400u) == 0u); } +// Implements the days In Month operation. static uint32_t KiDaysInMonth(uint32_t year, uint32_t month) { static const uint8_t days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; if (month == 2u && KiIsLeapYear(year)) return 29u; @@ -73,6 +76,7 @@ static bool KiValidCalendar(uint32_t year, uint32_t month, uint32_t day, return true; } +// Implements the days Before Year operation. static uint64_t KiDaysBeforeYear(uint32_t year) { uint64_t days = 0; for (uint32_t y = 1970u; y < year; y++) @@ -89,6 +93,7 @@ static uint64_t KiCalendarToEpochSeconds(uint32_t year, uint32_t month, uint32_t return (((days * 24u) + hour) * 60u + minute) * 60u + second; } +// Implements the epoch Seconds To Calendar operation. static void KiEpochSecondsToCalendar(uint64_t epochSeconds, SYS_SYSTEM_TIME* out) { uint64_t days = epochSeconds / 86400u; uint32_t sod = (uint32_t)(epochSeconds % 86400u); @@ -119,17 +124,20 @@ static void KiEpochSecondsToCalendar(uint64_t epochSeconds, SYS_SYSTEM_TIME* out out->DayOfWeek = (uint8_t)((totalDays + 4u) % 7u); // 1970-01-01 was Thursday. } +// Implements the day Of Week operation. static uint32_t KiDayOfWeek(uint32_t year, uint32_t month, uint32_t day) { uint64_t epoch = KiCalendarToEpochSeconds(year, month, day, 0, 0, 0); return (uint32_t)(((epoch / 86400u) + 4u) % 7u); } +// Implements the last Sunday Of Month operation. static uint32_t KiLastSundayOfMonth(uint32_t year, uint32_t month) { uint32_t last = KiDaysInMonth(year, month); uint32_t dow = KiDayOfWeek(year, month, last); // Sunday == 0. return last - dow; } +// Implements the central Europe Dst Active Utc operation. static bool KiCentralEuropeDstActiveUtc(uint64_t utcEpochSeconds) { SYS_SYSTEM_TIME utc; memset(&utc, 0, sizeof(utc)); @@ -142,6 +150,7 @@ static bool KiCentralEuropeDstActiveUtc(uint64_t utcEpochSeconds) { return utcEpochSeconds >= startUtc && utcEpochSeconds < endUtc; } +// Implements the offset For Utc Epoch operation. static int16_t KiOffsetForUtcEpoch(uint64_t utcEpochSeconds, bool* daylight) { int32_t offset = gTimeZonePolicy.StandardOffsetMinutes; bool dst = false; @@ -157,6 +166,7 @@ static int16_t KiOffsetForUtcEpoch(uint64_t utcEpochSeconds, bool* daylight) { return (int16_t)offset; } +// Implements the local Epoch To Utc operation. static uint64_t KiLocalEpochToUtc(uint64_t localEpochSeconds, int16_t offsetMinutes) { uint64_t offsetSeconds = (uint64_t)((offsetMinutes < 0) ? -offsetMinutes : offsetMinutes) * 60u; if (offsetMinutes >= 0) @@ -164,6 +174,7 @@ static uint64_t KiLocalEpochToUtc(uint64_t localEpochSeconds, int16_t offsetMinu return localEpochSeconds + offsetSeconds; } +// Implements the rebase Utc From Source operation. static void KiRebaseUtcFromSource(void) { if (gSourceTimeZoneKnown) { gBaseUtcEpochSeconds = KiLocalEpochToUtc(gSourceRawEpochSeconds, gSourceTimeZoneMinutes); @@ -183,11 +194,13 @@ static void KiRebaseUtcFromSource(void) { gBaseTickMicroseconds = gSourceTickMicroseconds; } +// Implements the ascii Lower operation. static int KiAsciiLower(int c) { if (c >= 'A' && c <= 'Z') return c + ('a' - 'A'); return c; } +// Implements the string Equals No Case operation. static bool KiStringEqualsNoCase(const char* a, const char* b) { if (!a || !b) return false; while (*a && *b) { @@ -199,6 +212,7 @@ static bool KiStringEqualsNoCase(const char* a, const char* b) { return *a == '\0' && *b == '\0'; } +// Parses int32. static bool KiParseInt32(const char* s, int32_t* out) { if (!s || !*s || !out) return false; @@ -223,6 +237,7 @@ static bool KiParseInt32(const char* s, int32_t* out) { return true; } +// Implements the starts With No Case operation. static bool KiStartsWithNoCase(const char* s, const char* prefix) { if (!s || !prefix) return false; while (*prefix) { @@ -234,10 +249,12 @@ static bool KiStartsWithNoCase(const char* s, const char* prefix) { return true; } +// Parses utc Offset. static bool KiParseUtcOffset(const char* s, int16_t* out) { if (!s || !out) return false; if (KiStringEqualsNoCase(s, "utc") || KiStringEqualsNoCase(s, "gmt") || + // Implements the string Equals No Case operation. KiStringEqualsNoCase(s, "z") || KiStringEqualsNoCase(s, "utcz")) { *out = 0; return true; @@ -290,6 +307,7 @@ static bool KiParseUtcOffset(const char* s, int16_t* out) { return true; } +// Implements the apply Default Time Zone Policy operation. static void KiApplyDefaultTimeZonePolicy(void) { gTimeZonePolicy.StandardOffsetMinutes = KE_CE_STANDARD_OFFSET; gTimeZonePolicy.DstRule = KeDstRuleCentralEurope; @@ -297,6 +315,7 @@ static void KiApplyDefaultTimeZonePolicy(void) { gHardwareClockMode = KeHardwareClockUtc; } +// Implements the time Initialize operation. void KeTimeInitialize(const BOOT_INFO* bootInfo, const HAL_API* hal) { gTimeHal = hal; KiApplyDefaultTimeZonePolicy(); @@ -350,6 +369,7 @@ void KeTimeInitialize(const BOOT_INFO* bootInfo, const HAL_API* hal) { } } +// Implements the time Reload Settings operation. KSTATUS KeTimeReloadSettings(void) { KE_TIME_ZONE_POLICY policy = gTimeZonePolicy; char value[64]; @@ -359,6 +379,7 @@ KSTATUS KeTimeReloadSettings(void) { KSTATUS st = KeGetSettingString("time", "timezone", value, sizeof(value)); if (KSUCCESS(st)) { if (KiStringEqualsNoCase(value, "central-europe") || + // Implements the string Equals No Case operation. KiStringEqualsNoCase(value, "europe/warsaw")) { policy.StandardOffsetMinutes = KE_CE_STANDARD_OFFSET; policy.DstRule = KeDstRuleCentralEurope; @@ -374,6 +395,7 @@ KSTATUS KeTimeReloadSettings(void) { policy.TimeZoneKnown = true; fixedTimezone = true; } else if (KiStringEqualsNoCase(value, "custom") || + // Implements the string Equals No Case operation. KiStringEqualsNoCase(value, "manual")) { policy.DstRule = KeDstRuleNone; policy.TimeZoneKnown = true; @@ -381,6 +403,7 @@ KSTATUS KeTimeReloadSettings(void) { allowStandardOffsetSetting = true; } else if (KiStringEqualsNoCase(value, "utc") || KiStringEqualsNoCase(value, "gmt") || + // Implements the string Equals No Case operation. KiStringEqualsNoCase(value, "z")) { policy.StandardOffsetMinutes = 0; policy.DstRule = KeDstRuleNone; @@ -415,9 +438,11 @@ KSTATUS KeTimeReloadSettings(void) { } else if (KiStringEqualsNoCase(value, "central-europe")) { policy.DstRule = KeDstRuleCentralEurope; } else if (KiStringEqualsNoCase(value, "on") || KiStringEqualsNoCase(value, "yes") || + // Implements the string Equals No Case operation. KiStringEqualsNoCase(value, "true") || KiStringEqualsNoCase(value, "1")) { policy.DstRule = KeDstRuleAlways; } else if (KiStringEqualsNoCase(value, "off") || KiStringEqualsNoCase(value, "no") || + // Implements the string Equals No Case operation. KiStringEqualsNoCase(value, "false") || KiStringEqualsNoCase(value, "0")) { policy.DstRule = KeDstRuleNone; } @@ -430,6 +455,7 @@ KSTATUS KeTimeReloadSettings(void) { hardwareClockMode = KeHardwareClockUtc; } else if (KiStringEqualsNoCase(value, "local") || KiStringEqualsNoCase(value, "localtime") || + // Implements the string Equals No Case operation. KiStringEqualsNoCase(value, "wall-clock")) { hardwareClockMode = KeHardwareClockLocal; } @@ -451,6 +477,7 @@ KSTATUS KeTimeReloadSettings(void) { return STATUS_SUCCESS; } +// Returns system Time. __declspec(dllexport) KSTATUS KeQuerySystemTime(SYS_SYSTEM_TIME* outTime) { if (!outTime) return STATUS_INVALID_PARAMETER; @@ -492,6 +519,7 @@ __declspec(dllexport) KSTATUS KeQuerySystemTime(SYS_SYSTEM_TIME* outTime) { return STATUS_SUCCESS; } +// Returns unix Time Seconds. __declspec(dllexport) uint64_t KeQueryUnixTimeSeconds(void) { SYS_SYSTEM_TIME t; if (KeQuerySystemTime(&t) != STATUS_SUCCESS) diff --git a/code/kernel/ke_trap.c b/code/kernel/ke_trap.c index f91b930..00867d8 100644 --- a/code/kernel/ke_trap.c +++ b/code/kernel/ke_trap.c @@ -1,4 +1,5 @@ -// ke_trap.c - current-thread trap-frame tracking and validation +// Trap-frame tracking. This file owns current-thread trap snapshots and validation for user diagnostics. + #include #include #include @@ -43,17 +44,20 @@ STATIC_ASSERT_OFFSET(KTRAP_FRAME, SsSlot, 216); STATIC_ASSERT_OFFSET(KTRAP_FRAME, PreviousFrame, 224); _Static_assert(sizeof(KTRAP_FRAME) == 240, "KTRAP_FRAME size must match ke_syscall.asm"); +// Implements the trap Frame From User operation. int KeTrapFrameFromUser(const KTRAP_FRAME* frame) { if (!frame || frame->Magic != KTRAP_FRAME_MAGIC) return 0; return (frame->Cs & 3u) == 3u; } +// Returns current Trap Frame. KTRAP_FRAME* KeGetCurrentTrapFrame(void) { THREAD* t = KeGetCurrentThread(); if (!t) return (KTRAP_FRAME*)0; return t->TrapFrame; } +// Implements the enter Trap Frame operation. void KiEnterTrapFrame(KTRAP_FRAME* frame) { if (!frame || frame->Magic != KTRAP_FRAME_MAGIC) KePanic(KE_PANIC_CODE_TRAP, "KiEnterTrapFrame: invalid trap frame 0x%016llX\n", (uint64_t)frame); @@ -66,6 +70,7 @@ void KiEnterTrapFrame(KTRAP_FRAME* frame) { t->TrapFrame = frame; } +// Implements the exit Trap Frame operation. void KiExitTrapFrame(KTRAP_FRAME* frame) { if (!frame || frame->Magic != KTRAP_FRAME_MAGIC) KePanic(KE_PANIC_CODE_TRAP, "KiExitTrapFrame: invalid trap frame 0x%016llX\n", (uint64_t)frame); @@ -113,6 +118,7 @@ void KiValidateSyscallTrapFrame(uint64_t nr, uint64_t a0, uint64_t a1, } } +// Returns current Trap Frame. KSTATUS KeQueryCurrentTrapFrame(SYS_TRAP_FRAME_INFO_K* out) { if (!out) return STATUS_INVALID_PARAMETER; diff --git a/code/kernel/kmain.c b/code/kernel/kmain.c index 33e9fdd..94e526f 100644 --- a/code/kernel/kmain.c +++ b/code/kernel/kmain.c @@ -1,4 +1,5 @@ -// kmain.c - kernel entry point +// Kernel entry point. This file connects boot information to core subsystem initialization and scheduler start. + #include #include #include @@ -39,6 +40,7 @@ typedef KSTATUS (*DRIVER_ENTRY_FN)(const HAL_API *); // HAL pointer cached at boot for subsystems that still need platform services. static const HAL_API* gKmainHal; +// Implements the page In Bootloader Region operation. static int KiPageInBootloaderRegion(const BOOT_INFO* bootInfo, PHYSICAL_ADDRESS page) { for (uint32_t i = 0; i < bootInfo->MemoryMap.RegionCount; i++) { const MEMORY_REGION* r = &bootInfo->MemoryMap.Regions[i]; @@ -53,6 +55,7 @@ static int KiPageInBootloaderRegion(const BOOT_INFO* bootInfo, PHYSICAL_ADDRESS return 0; } +// Implements the reclaim Bootloader Memory operation. static void KiReclaimBootloaderMemory(const BOOT_INFO* bootInfo) { // Reclaim only the raw buffers backing boot-loaded .sys modules. // The kernel/HAL images, page tables, and bootloader code remain live. @@ -70,9 +73,7 @@ static void KiReclaimBootloaderMemory(const BOOT_INFO* bootInfo) { } } -// --------------------------------------------------------------------------- -// Phase Helper: Resolve Imports for core modules -// --------------------------------------------------------------------------- +// Phase Helper: Resolve Imports for core modules. static void KiResolveSystemImports(BOOT_INFO* bootInfo) { // Only resolve imports for kernel.exe and hal.dll (typically indices 0 and 1). // The bootloader maps these, but drivers are now passed as raw physical files. @@ -85,9 +86,7 @@ static void KiResolveSystemImports(BOOT_INFO* bootInfo) { } } -// --------------------------------------------------------------------------- -// Phase Helper: Initialize dynamically loaded .sys drivers -// --------------------------------------------------------------------------- +// Phase Helper: Initialize dynamically loaded .sys drivers. static void KiDriversIniCb(const char* section, const char* key, const char* val, void* ud) { (void)val; @@ -102,23 +101,24 @@ static void KiDriversIniCb(const char* section, const char* key, } } +// Initializes drivers. static void KiInitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) { DbgPrint("KiInitializeDrivers: Initializing drivers...\n"); - // boot drivers (provided by the bootloader) + // boot drivers (provided by the bootloader). for (uint32_t i = 0; i < bootInfo->ModuleCount; i++) { BOOT_MODULE* mod = &bootInfo->Modules[i]; // Skip modules that are already mapped (Kernel/HAL) - // or have no physical data (invalid) + // or have no physical data (invalid). if (mod->VirtBase != 0 || mod->PhysBase == 0) continue; DbgPrint("KiInitializeDrivers: Loading boot driver %s\n", mod->Name); - // Calculate virtual address of the raw file in the physical window + // Calculate virtual address of the raw file in the physical window. void* rawPeBuffer = (void*)(bootInfo->PhysicalMapBase + mod->PhysBase); - // Map the PE image into kernel space + // Map the PE image into kernel space. uintptr_t mappedBase = 0; KSTATUS st = LdrLoadImage(rawPeBuffer, mod->ImageSize, &mappedBase, false); if (!KSUCCESS(st)) { @@ -126,19 +126,19 @@ static void KiInitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) { continue; } - // Update the struct so other modules can find it + // Update the struct so other modules can find it. mod->VirtBase = mappedBase; - // Resolve imports (can now see Kernel, HAL, and previous drivers) + // Resolve imports (can now see Kernel, HAL, and previous drivers). if (!KSUCCESS(LdrResolveImports(mappedBase))) { DbgPrint("ERROR: Failed to resolve imports for %s\n", mod->Name); continue; } - // Register with the global module list so subsequent drivers can import from this one + // Register with the global module list so subsequent drivers can import from this one. LdrRegisterModule(mod->Name, mod->VirtBase); - // Execute Entry Point + // Execute Entry Point. DRIVER_ENTRY_FN entry = (DRIVER_ENTRY_FN)LdrGetEntryPoint(mappedBase); if (entry) { KSTATUS ds = entry(hal); @@ -148,7 +148,7 @@ static void KiInitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) { } } - // runtime drivers + // runtime drivers. KSTATUS s; FILE_OBJECT* f; @@ -174,7 +174,7 @@ static void KiInitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) { for (uint32_t i = 0; i < arr_len(runtimeKeys); i++) { DbgPrint("Found runtime driver: %s\n", runtimeKeys[i]); - // Load the driver + // Load the driver. size_t len = strlen(runtimeKeys[i]); char* path = MmAllocatePool(len + 10); if (!path) { @@ -182,7 +182,7 @@ static void KiInitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) { continue; } - // memcpy maneuvers + // memcpy maneuvers. memcpy(path, "drivers\\", 8); memcpy(path + 8, runtimeKeys[i], len + 1); @@ -228,26 +228,24 @@ static void KiInitializeDrivers(BOOT_INFO* bootInfo, const HAL_API* hal) { } } - // Free the individual strings allocated via strdup in the callback + // Free the individual strings allocated via strdup in the callback. if (runtimeKeys) { for (uint32_t i = 0; i < arr_len(runtimeKeys); i++) { if (runtimeKeys[i]) { MmFreePool(runtimeKeys[i]); } } - // Free the dynamic array structure itself + // Free the dynamic array structure itself. arr_free(runtimeKeys); } - // Free the file buffer + // Free the file buffer. MmFreePool(mem); } -// --------------------------------------------------------------------------- // Phase Helper: Load and launch a process from the filesystem. // Returns the new PROCESS* with one reference owned by the caller. // Returns NULL on failure. -// --------------------------------------------------------------------------- static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) { KSTATUS s; FILE_OBJECT* f; @@ -335,6 +333,7 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) { return proc; } +// Implements the system Init Thread operation. void SystemInitThread(void* arg) { SYSTEM_INIT_ARGS* args = (SYSTEM_INIT_ARGS*)arg; @@ -379,36 +378,32 @@ void SystemInitThread(void* arg) { MmFreePool(args); } -// --------------------------------------------------------------------------- -// Main Kernel Entry -// --------------------------------------------------------------------------- +// Main Kernel Entry. extern void KernelMain(BOOT_INFO* bootInfo) { - // - // Physical & Virtual Memory initialization - // + + // Physical & Virtual Memory initialization. + if (!MmInitializePhysical(&bootInfo->MemoryMap, bootInfo->PhysicalMapBase)) { _disable(); while (true) __halt(); // there's nothing we can do } PHYSICAL_ADDRESS pml4 = (PHYSICAL_ADDRESS)__readcr3(); - MmInitializeVirtual(pml4, 1 * 1024 * 1024 /* 1 MB initial pool */); + // The early virtual allocator starts small because it only needs bootstrap page tables before the PMM is online. + MmInitializeVirtual(pml4, 1 * 1024 * 1024); + + // Bootstrap CPU and architecture setup (GDT/IDT/Faults). - // - // Bootstrap CPU and architecture setup (GDT/IDT/Faults) - // KeInitializeBootstrapCpu(); KeInitializeGdt(); KeInitializeIdt(); - // // Register boot modules (Allows LdrGetExport to work for drivers and the HAL) // Note: Kept to a single call here to avoid the duplicate in your original code. - // + LdrRegisterModulesFromBootInfo(bootInfo); - // - // HAL Initialization - // + // HAL Initialization. + HAL_INIT_PARAMS halParams = { .PhysicalWindowBase = bootInfo->PhysicalMapBase, .FramebufferBase = bootInfo->FramebufferBase, @@ -455,15 +450,13 @@ extern void KernelMain(BOOT_INFO* bootInfo) { KeSyscallInit(hal); - // - // Dynamic Linking & Driver Execution - // - KiResolveSystemImports(bootInfo); - //KiInitializeDrivers(bootInfo, hal); + // Dynamic Linking & Driver Execution. + + KiResolveSystemImports(bootInfo); + //KiInitializeDrivers(bootInfo, hal);. + + // Scheduler Prep & Status Update. - // - // Scheduler Prep & Status Update - // KeInitializeScheduler(); KSTATUS smpSchedStatus = KeAdmitApplicationProcessorsToScheduler(); @@ -473,12 +466,12 @@ extern void KernelMain(BOOT_INFO* bootInfo) { KiRunCoreHardeningSelfTests(); - // Pack the arguments for the init thread + // Pack the arguments for the init thread. SYSTEM_INIT_ARGS* initArgs = MmAllocatePool(sizeof(SYSTEM_INIT_ARGS)); initArgs->bootInfo = bootInfo; initArgs->hal = hal; - // Spawn the Initialization Thread + // Spawn the Initialization Thread. THREAD* initThread = (THREAD*)0; KSTATUS st = KeCreateKernelThread((uintptr_t)SystemInitThread, (uintptr_t)initArgs, diff --git a/code/kernel/ldr_image.c b/code/kernel/ldr_image.c index a1d805f..fb97fc7 100644 --- a/code/kernel/ldr_image.c +++ b/code/kernel/ldr_image.c @@ -1,4 +1,5 @@ -// ldr_image.c - PE32+ loader and export resolver +// PE image loader. This file owns image mapping, relocation, import resolution, and export lookup. + #include #include #include @@ -20,9 +21,7 @@ int _stricmp(const char* a, const char* b); -// --------------------------------------------------------------------------- -// PE32+ structures (just what we need) -// --------------------------------------------------------------------------- +// PE32+ structures (just what we need). #define PE_SIGNATURE 0x00004550UL // 'PE\0\0' #define IMAGE_FILE_MACHINE_AMD64 0x8664 #define IMAGE_FILE_MACHINE_I386 0x014c @@ -88,10 +87,12 @@ typedef struct { uint32_t Characteristics; } SECTION_HEADER; +// Implements the align Pe Size operation. static size_t KiAlignPeSize(size_t value) { return (value + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); } +// Implements the compute Required Image Size operation. static KSTATUS KiComputeRequiredImageSize(const PE_HEADER* pe, size_t fileSize, size_t* outSize) { if (!pe || !outSize) return STATUS_INVALID_PARAMETER; @@ -158,9 +159,7 @@ typedef struct { #define IMAGE_SCN_MEM_READ 0x40000000u #define IMAGE_SCN_MEM_WRITE 0x80000000u -// --------------------------------------------------------------------------- -// Module registry -// --------------------------------------------------------------------------- +// Module registry. #define MAX_MODULES 32 typedef struct { @@ -173,6 +172,7 @@ static MODULE_ENTRY gModules[MAX_MODULES]; static uint32_t gModuleCount = 0; +// Implements the canonical Module Name operation. static const char* KiCanonicalModuleName(const char* name) { if (!name) return name; @@ -191,6 +191,7 @@ static const char* KiCanonicalModuleName(const char* name) { return name; } +// Returns module Base In Table. static uintptr_t KiFindModuleBaseInTable(const MODULE_ENTRY* modules, uint32_t count, const char* name) { for (uint32_t i = 0; i < count; i++) { if (_stricmp(modules[i].Name, name) == 0) return modules[i].Base; @@ -198,6 +199,7 @@ static uintptr_t KiFindModuleBaseInTable(const MODULE_ENTRY* modules, uint32_t c return 0; } +// Registers module Entry. static void KiRegisterModuleEntry(MODULE_ENTRY* entry, const char* name, uintptr_t base, size_t size) { strncpy(entry->Name, name, 31); entry->Name[31] = '\0'; @@ -205,9 +207,10 @@ static void KiRegisterModuleEntry(MODULE_ENTRY* entry, const char* name, uintptr entry->Size = size; } +// Implements the ldr Register Modules From Boot Info operation. void LdrRegisterModulesFromBootInfo(const BOOT_INFO* bootInfo) { for (uint32_t i = 0; i < bootInfo->ModuleCount && gModuleCount < MAX_MODULES; i++) { - // Only register modules that have a virtual base (Kernel, HAL) + // Only register modules that have a virtual base (Kernel, HAL). if (bootInfo->Modules[i].VirtBase != 0) { KiRegisterModuleEntry(&gModules[gModuleCount], bootInfo->Modules[i].Name, @@ -218,6 +221,7 @@ void LdrRegisterModulesFromBootInfo(const BOOT_INFO* bootInfo) { } } +// Implements the ldr Register Module operation. void LdrRegisterModule(const char* name, uintptr_t base) { if (gModuleCount < MAX_MODULES) { KiRegisterModuleEntry(&gModules[gModuleCount], name, base, 0); @@ -225,6 +229,7 @@ void LdrRegisterModule(const char* name, uintptr_t base) { } } +// Returns global Module Base. static uintptr_t KiFindGlobalModuleBase(const char* name) { return KiFindModuleBaseInTable(gModules, gModuleCount, KiCanonicalModuleName(name)); } @@ -242,6 +247,7 @@ static uintptr_t KiFindProcessModuleBaseInTable( return 0; } +// Returns process Or Global Module Base. static uintptr_t KiFindProcessOrGlobalModuleBase(PROCESS* process, const char* name) { if (process) { uintptr_t base = KiFindProcessModuleBaseInTable(process->Modules, process->ModuleCount, name); @@ -250,6 +256,7 @@ static uintptr_t KiFindProcessOrGlobalModuleBase(PROCESS* process, const char* n return KiFindGlobalModuleBase(name); } +// Returns export At Base. static void* KiGetExportAtBase(uintptr_t base, const char* functionName) { if (!base) return (void *)0; @@ -278,19 +285,19 @@ static void* KiGetExportAtBase(uintptr_t base, const char* functionName) { return (void *)0; } -// --------------------------------------------------------------------------- -// Export lookup -// --------------------------------------------------------------------------- +// Export lookup. void* LdrGetExport(const char* moduleName, const char* functionName) { uintptr_t base = KiFindGlobalModuleBase(KiCanonicalModuleName(moduleName)); return KiGetExportAtBase(base, functionName); } +// Implements the ldr Get Export For Process operation. void* LdrGetExportForProcess(PROCESS* process, const char* moduleName, const char* functionName) { uintptr_t base = KiFindProcessOrGlobalModuleBase(process, KiCanonicalModuleName(moduleName)); return KiGetExportAtBase(base, functionName); } +// Implements the ldr Get Image Size operation. size_t LdrGetImageSize(uintptr_t base) { if (!base) return 0; uint32_t peOffset = *(uint32_t *)(base + 0x3C); @@ -299,6 +306,7 @@ size_t LdrGetImageSize(uintptr_t base) { return (size_t)pe->OptionalHeader.SizeOfImage; } +// Implements the ldr Get Mapped Image Size operation. size_t LdrGetMappedImageSize(PROCESS* process, uintptr_t base) { if (!base) return 0; if (process) { @@ -311,6 +319,7 @@ size_t LdrGetMappedImageSize(PROCESS* process, uintptr_t base) { } +// Releases loaded Image For Process. static void KiFreeLoadedImageForProcess(PROCESS* process, uintptr_t imageBase, bool user) { if (!imageBase) return; size_t imageSize = user ? LdrGetMappedImageSize(process, imageBase) : LdrGetImageSize(imageBase); @@ -318,11 +327,13 @@ static void KiFreeLoadedImageForProcess(PROCESS* process, uintptr_t imageBase, b else MmFreePool((void*)imageBase); } +// Releases loaded Image. static void KiFreeLoadedImage(uintptr_t imageBase, bool user) { KiFreeLoadedImageForProcess(KeGetCurrentProcess(), imageBase, user); } +// Implements the ldr Protect Image For Process operation. KSTATUS LdrProtectImageForProcess(PROCESS* process, uintptr_t imageBase, bool user) { if (!imageBase) return STATUS_INVALID_PARAMETER; if (user && !process) return STATUS_INVALID_PARAMETER; @@ -389,18 +400,14 @@ KSTATUS LdrProtectImageForProcess(PROCESS* process, uintptr_t imageBase, bool us } -// --------------------------------------------------------------------------- -// Entry point lookup -// --------------------------------------------------------------------------- +// Entry point lookup. uintptr_t LdrGetEntryPoint(uintptr_t base) { uint32_t pe_offset = *(uint32_t*)(base + 0x3C); uint32_t entry_rva = *(uint32_t*)(base + pe_offset + 0x28); return base + entry_rva; } -// --------------------------------------------------------------------------- -// Base Relocation -// --------------------------------------------------------------------------- +// Base Relocation. static KSTATUS LdrApplyRelocations(uintptr_t base, uintptr_t delta) { uint32_t peOffset = *(uint32_t *)(base + 0x3C); PE_HEADER* pe = (PE_HEADER *)(base + peOffset); @@ -422,7 +429,7 @@ static KSTATUS LdrApplyRelocations(uintptr_t base, uintptr_t delta) { int type = entries[i] >> 12; int offset = entries[i] & 0xFFF; - // For 64-bit PEs, we mostly care about DIR64 (Type 10) + // For 64-bit PEs, we mostly care about DIR64 (Type 10). if (type == IMAGE_REL_BASED_DIR64) { uint64_t* ptr = (uint64_t *)(base + block->VirtualAddress + offset); *ptr += delta; @@ -433,16 +440,16 @@ static KSTATUS LdrApplyRelocations(uintptr_t base, uintptr_t delta) { return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- -// Import resolution -// --------------------------------------------------------------------------- +// Import resolution. typedef void* (*EXPORT_LOOKUP_FN)(void* ctx, const char* moduleName, const char* functionName); +// Implements the global Export Lookup operation. static void* KiGlobalExportLookup(void* ctx, const char* moduleName, const char* functionName) { (void)ctx; return LdrGetExport(moduleName, functionName); } +// Processes export Lookup. static void* KiProcessExportLookup(void* ctx, const char* moduleName, const char* functionName) { return LdrGetExportForProcess((PROCESS*)ctx, moduleName, functionName); } @@ -473,9 +480,8 @@ static KSTATUS LdrResolveImportsCommon( dllName = KiCanonicalModuleName(dllName); LdrDbg("LDR: resolve import dll=%s image=%016llx pid=%u\n", dllName, (unsigned long long)imageBase, process ? process->ProcessId : 0); - // - // Ensure dependency is loaded into the process - // + // Ensure dependency is loaded into the process. + if (process) { uintptr_t modBase = KiFindProcessOrGlobalModuleBase(process, dllName); @@ -540,6 +546,7 @@ static KSTATUS LdrResolveImportsCommon( return STATUS_SUCCESS; } +// Implements the ldr Resolve Imports operation. KSTATUS LdrResolveImports(uintptr_t imageBase) { return LdrResolveImportsCommon( (PROCESS*)0, @@ -549,6 +556,7 @@ KSTATUS LdrResolveImports(uintptr_t imageBase) { ); } +// Implements the ldr Resolve Imports For Process operation. KSTATUS LdrResolveImportsForProcess(PROCESS* process, uintptr_t imageBase) { return LdrResolveImportsCommon( process, @@ -558,6 +566,7 @@ KSTATUS LdrResolveImportsForProcess(PROCESS* process, uintptr_t imageBase) { ); } +// Implements the ldr Register Process Module operation. static KSTATUS LdrRegisterProcessModule(PROCESS* process, const char* name, uintptr_t base) { if (!process || !name || !base) return STATUS_INVALID_PARAMETER; @@ -577,6 +586,7 @@ static KSTATUS LdrRegisterProcessModule(PROCESS* process, const char* name, uint return STATUS_SUCCESS; } +// Implements the ldr Load Module For Process operation. KSTATUS LdrLoadModuleForProcess(PROCESS* process, const char* filename, uintptr_t* baseOut) { if (!process || !filename) return STATUS_INVALID_PARAMETER; @@ -735,10 +745,12 @@ static KSTATUS KiLdrLoadImageCommon(PROCESS* process, const void* buffer, size_t return STATUS_SUCCESS; } +// Implements the ldr Load Image For Process operation. KSTATUS LdrLoadImageForProcess(PROCESS* process, const void* buffer, size_t size, uintptr_t* baseOut) { return KiLdrLoadImageCommon(process, buffer, size, baseOut, true); } +// Implements the ldr Load Image operation. KSTATUS LdrLoadImage(const void* buffer, size_t size, uintptr_t* baseOut, bool user) { return KiLdrLoadImageCommon(user ? KeGetCurrentProcess() : (PROCESS*)0, buffer, size, baseOut, user); } diff --git a/code/kernel/mm_phys.c b/code/kernel/mm_phys.c index 79763b6..cf60293 100644 --- a/code/kernel/mm_phys.c +++ b/code/kernel/mm_phys.c @@ -1,5 +1,5 @@ -// mm_phys.c - physical memory manager -// +// Physical-memory manager. This file owns frame accounting and boot memory-map consumption. + // Bitmap allocator over 4 KB physical frames. One bitmap records which PFNs // exist in usable RAM, and one bitmap records which usable PFNs are currently // free. This keeps single-frame allocation simple while making contiguous @@ -8,18 +8,15 @@ #include #include -// --------------------------------------------------------------------------- // Physical-to-virtual translation via the direct map window. -// --------------------------------------------------------------------------- static uint64_t gPhysBase = 0; // set by MmInitializePhysical +// Implements the phys To Virt operation. static inline void* KiPhysToVirt(PHYSICAL_ADDRESS phys) { return (void *)(phys + gPhysBase); } -// --------------------------------------------------------------------------- -// Frame bitmap -// --------------------------------------------------------------------------- +// Frame bitmap. typedef struct { uint8_t* Usable; // bit = 1 when PFN belongs to usable RAM @@ -33,34 +30,42 @@ typedef struct { static FRAME_BITMAP gFrameBitmap; +// Implements the align Up operation. static inline PHYSICAL_ADDRESS KiAlignUp(PHYSICAL_ADDRESS value) { return (value + PAGE_SIZE - 1) & PAGE_MASK; } +// Implements the align Down operation. static inline PHYSICAL_ADDRESS KiAlignDown(PHYSICAL_ADDRESS value) { return value & PAGE_MASK; } +// Implements the bit Test operation. static inline int KiBitTest(const uint8_t* bits, size_t index) { return (bits[index >> 3] & (uint8_t)(1u << (index & 7))) != 0; } +// Implements the bit Set operation. static inline void KiBitSet(uint8_t* bits, size_t index) { bits[index >> 3] |= (uint8_t)(1u << (index & 7)); } +// Implements the bit Clear operation. static inline void KiBitClear(uint8_t* bits, size_t index) { bits[index >> 3] &= (uint8_t)~(1u << (index & 7)); } +// Implements the pfn Usable Locked operation. static inline int KiPfnUsableLocked(size_t pfn) { return pfn < gFrameBitmap.MaxPfn && KiBitTest(gFrameBitmap.Usable, pfn); } +// Implements the pfn Free Locked operation. static inline int KiPfnFreeLocked(size_t pfn) { return KiPfnUsableLocked(pfn) && KiBitTest(gFrameBitmap.Free, pfn); } +// Implements the mark Usable Free Range operation. static void KiMarkUsableFreeRange(size_t firstPfn, size_t count) { for (size_t i = 0; i < count; i++) { size_t pfn = firstPfn + i; @@ -76,6 +81,7 @@ static void KiMarkUsableFreeRange(size_t firstPfn, size_t count) { } } +// Releases usable Pfn. static void KiRemoveUsablePfn(size_t pfn) { if (pfn >= gFrameBitmap.MaxPfn) return; if (KiBitTest(gFrameBitmap.Free, pfn)) { @@ -88,9 +94,7 @@ static void KiRemoveUsablePfn(size_t pfn) { } } -// --------------------------------------------------------------------------- -// Initialisation -// --------------------------------------------------------------------------- +// Initialisation. bool MmInitializePhysical(const MEMORY_MAP* map, uint64_t physicalWindowBase) { if (!map) return false; gPhysBase = physicalWindowBase; @@ -183,9 +187,7 @@ bool MmInitializePhysical(const MEMORY_MAP* map, uint64_t physicalWindowBase) { return true; } -// --------------------------------------------------------------------------- -// Public API -// --------------------------------------------------------------------------- +// Public API. PHYSICAL_ADDRESS MmAllocateFrameInRange(PHYSICAL_ADDRESS minInclusive, PHYSICAL_ADDRESS maxExclusive) { minInclusive = KiAlignUp(minInclusive); @@ -217,10 +219,12 @@ PHYSICAL_ADDRESS MmAllocateFrameBelow(PHYSICAL_ADDRESS maxExclusive) { return MmAllocateFrameInRange(PAGE_SIZE, maxExclusive); } +// Creates frame. __declspec(dllexport) PHYSICAL_ADDRESS MmAllocateFrame(void) { return MmAllocateFrameInRange(PAGE_SIZE, (PHYSICAL_ADDRESS)gFrameBitmap.MaxPfn * PAGE_SIZE); } +// Releases frame. void MmFreeFrame(PHYSICAL_ADDRESS frame) { if (!frame || (frame & (PAGE_SIZE - 1))) return; size_t pfn = (size_t)(frame / PAGE_SIZE); @@ -233,6 +237,7 @@ void MmFreeFrame(PHYSICAL_ADDRESS frame) { KeReleaseSpinlock(&gFrameBitmap.Lock, flags); } +// Creates contiguous. __declspec(dllexport) PHYSICAL_ADDRESS MmAllocateContiguous(size_t count) { if (!count || count > gFrameBitmap.MaxPfn) return (PHYSICAL_ADDRESS)0; @@ -261,6 +266,7 @@ __declspec(dllexport) PHYSICAL_ADDRESS MmAllocateContiguous(size_t count) { return (PHYSICAL_ADDRESS)0; } +// Releases frame Count. size_t MmFreeFrameCount(void) { uintptr_t flags = KeAcquireSpinlock(&gFrameBitmap.Lock); size_t count = gFrameBitmap.FreeFrames; @@ -268,9 +274,11 @@ size_t MmFreeFrameCount(void) { return count; } +// Implements the total Frame Count operation. size_t MmTotalFrameCount(void) { return gFrameBitmap.TotalFrames; } +// Returns physical Stats. void MmQueryPhysicalStats(MM_PHYSICAL_STATS* out) { if (!out) return; diff --git a/code/kernel/mm_virt.c b/code/kernel/mm_virt.c index df14b40..716a47b 100644 --- a/code/kernel/mm_virt.c +++ b/code/kernel/mm_virt.c @@ -1,14 +1,14 @@ -// mm_virt.c - virtual memory manager -// +// Kernel virtual-memory manager. This file owns kernel page-table construction, mapping attributes, and direct-map maintenance. + // Page tables: // One PML4 shared by all processes. // Upper half (bit 47 set) has U/S = 0 - ring-3 access always faults. // Lower half pages are PAGE_USER. -// + // Kernel pool: // A boundary-tag (header + footer) free-list allocator starting at POOL_BASE. // Pages are committed on demand from the PMM. -// + // User heap: // A single best-fit free list in the lower half. // Page-granular lower-half regions owned by PROCESS metadata. Sub-page @@ -24,21 +24,19 @@ #include #include -// --------------------------------------------------------------------------- -// Helpers - physical window access -// --------------------------------------------------------------------------- +// Helpers - physical window access. static uint64_t gPhysBase = PHYS_MAP_BASE; +// Implements the phys To Virt operation. static inline void* KiPhysToVirt(PHYSICAL_ADDRESS p) { return (void *)(p + gPhysBase); } +// Implements the pte Ptr operation. static inline uint64_t* KiPtePtr(PHYSICAL_ADDRESS tablePhys, unsigned idx) { return (uint64_t *)KiPhysToVirt(tablePhys) + idx; } -// --------------------------------------------------------------------------- -// PML4 / page-table helpers -// --------------------------------------------------------------------------- +// PML4 / page-table helpers. static PHYSICAL_ADDRESS gPml4Phys = 0; static SPINLOCK gPageTableLock = SPINLOCK_INIT; @@ -78,13 +76,12 @@ static PHYSICAL_ADDRESS KiEnsureTable(PHYSICAL_ADDRESS parentPhys, return childPhys; } -// --------------------------------------------------------------------------- -// TLB/cache coherency hooks -// --------------------------------------------------------------------------- +// TLB/cache coherency hooks. void MmFlushTlbLocal(uintptr_t virt) { __invlpg((void*)virt); } +// Implements the acquire Tlb Shootdown Lock operation. static void KiAcquireTlbShootdownLock(void) { // Do not use the normal spinlock here: it masks interrupts while spinning. // A CPU spinning with IF=0 on the shootdown lock could not acknowledge a @@ -95,11 +92,13 @@ static void KiAcquireTlbShootdownLock(void) { _ReadWriteBarrier(); } +// Releases tlb Shootdown Lock. static void KiReleaseTlbShootdownLock(void) { _ReadWriteBarrier(); _InterlockedExchange(&gTlbShootdownLock, 0); } +// Flushes tlb For Kernel Mapping. void MmFlushTlbForKernelMapping(uintptr_t virt) { MmFlushTlbLocal(virt); @@ -146,6 +145,7 @@ void MmFlushTlbForKernelMapping(uintptr_t virt) { } } +// Handles tlb Shootdown. static int KiHandleTlbShootdown(void) { if (_InterlockedCompareExchange(&gTlbShootdownActive, 0, 0) == 0) return 0; @@ -158,13 +158,12 @@ static int KiHandleTlbShootdown(void) { return 1; } +// Handles tlb Shootdown Nmi. int MmHandleTlbShootdownNmi(void) { return KiHandleTlbShootdown(); } -// --------------------------------------------------------------------------- -// Public mapping -// --------------------------------------------------------------------------- +// Public mapping. __declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, uint64_t flags, MM_MAP_MODE mode) { unsigned userFlag = (flags & PAGE_USER) ? PAGE_USER : 0; @@ -199,6 +198,7 @@ __declspec(dllexport) KSTATUS MmMapPage(uintptr_t virt, PHYSICAL_ADDRESS phys, u } +// Releases page. __declspec(dllexport) KSTATUS MmUnmapPage(uintptr_t virt) { uintptr_t lockFlags = KeAcquireSpinlock(&gPageTableLock); @@ -226,6 +226,7 @@ __declspec(dllexport) KSTATUS MmUnmapPage(uintptr_t virt) { } +// Changes page attributes for 4 KiB mappings and refuses huge-page leaves that cannot be edited in place. __declspec(dllexport) KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint64_t flags) { if (!size) return STATUS_SUCCESS; @@ -282,6 +283,7 @@ __declspec(dllexport) KSTATUS MmSetPageProtect(uintptr_t virt, size_t size, uint } +// Returns physical Address. __declspec(dllexport) PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) { if (!gPml4Phys) return 0; // Not initialized @@ -299,7 +301,7 @@ __declspec(dllexport) PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) { uint64_t* pdpt = KiPhysToVirt(pml4[pml4_idx] & PAGE_FRAME_4K_MASK); if (!(pdpt[pdpt_idx] & PAGE_PRESENT)) goto out; - // Check for 1GB huge pages (bit 7 - PS) + // Check for 1GB huge pages (bit 7 - PS). if (pdpt[pdpt_idx] & PAGE_PS) { result = (pdpt[pdpt_idx] & PAGE_FRAME_1G_MASK) + (virt & 0x3FFFFFFF); goto out; @@ -308,7 +310,7 @@ __declspec(dllexport) PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) { uint64_t* pd = KiPhysToVirt(pdpt[pdpt_idx] & PAGE_FRAME_4K_MASK); if (!(pd[pd_idx] & PAGE_PRESENT)) goto out; - // Check for 2MB huge pages (bit 7 - PS) + // Check for 2MB huge pages (bit 7 - PS). if (pd[pd_idx] & PAGE_PS) { result = (pd[pd_idx] & PAGE_FRAME_2M_MASK) + (virt & 0x1FFFFF); goto out; @@ -317,7 +319,7 @@ __declspec(dllexport) PHYSICAL_ADDRESS MmGetPhysicalAddress(uintptr_t virt) { uint64_t* pt = KiPhysToVirt(pd[pd_idx] & PAGE_FRAME_4K_MASK); if (!(pt[pt_idx] & PAGE_PRESENT)) goto out; - // Extract the physical frame and add the offset within the page + // Extract the physical frame and add the offset within the page. result = (pt[pt_idx] & PAGE_FRAME_4K_MASK) + (virt & 0xFFF); out: @@ -327,9 +329,7 @@ out: -// --------------------------------------------------------------------------- -// Page query and user/kernel copy boundary helpers -// --------------------------------------------------------------------------- +// Page query and user/kernel copy boundary helpers. __declspec(dllexport) KSTATUS MmQueryPage(uintptr_t virt, PHYSICAL_ADDRESS* physOut, uint64_t* flagsOut) { @@ -409,6 +409,7 @@ out: } +// Implements the user Range Valid operation. static int KiUserRangeValid(uintptr_t addr, size_t size) { if (size == 0) return 1; if (addr < USER_BASE) return 0; @@ -417,6 +418,7 @@ static int KiUserRangeValid(uintptr_t addr, size_t size) { return 1; } +// Probes user Range. static KSTATUS KiProbeUserRange(uintptr_t addr, size_t size, uint64_t requiredFlags) { if (!KiUserRangeValid(addr, size)) return STATUS_ACCESS_DENIED; @@ -442,14 +444,17 @@ static KSTATUS KiProbeUserRange(uintptr_t addr, size_t size, uint64_t requiredFl return STATUS_SUCCESS; } +// Probes user Read. __declspec(dllexport) KSTATUS MmProbeUserRead(const void* ptr, size_t size) { return KiProbeUserRange((uintptr_t)ptr, size, PAGE_PRESENT | PAGE_USER); } +// Probes user Write. __declspec(dllexport) KSTATUS MmProbeUserWrite(void* ptr, size_t size) { return KiProbeUserRange((uintptr_t)ptr, size, PAGE_PRESENT | PAGE_USER | PAGE_WRITE); } +// Copies from User. __declspec(dllexport) KSTATUS CopyFromUser(void* kernelDst, const void* userSrc, size_t size) { if (!kernelDst && size) return STATUS_INVALID_PARAMETER; @@ -460,6 +465,7 @@ __declspec(dllexport) KSTATUS CopyFromUser(void* kernelDst, const void* userSrc, return STATUS_SUCCESS; } +// Copies to User. __declspec(dllexport) KSTATUS CopyToUser(void* userDst, const void* kernelSrc, size_t size) { if (!kernelSrc && size) return STATUS_INVALID_PARAMETER; @@ -470,9 +476,7 @@ __declspec(dllexport) KSTATUS CopyToUser(void* userDst, const void* kernelSrc, s return STATUS_SUCCESS; } -// --------------------------------------------------------------------------- // 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. // This allows O(1) coalescing of adjacent free blocks. @@ -498,15 +502,19 @@ typedef struct BLOCK_FTR { #define OVERHEAD (HDR_SIZE + FTR_SIZE) #define MIN_BLOCK (OVERHEAD + sizeof(void*)) +// Implements the hdr To Ftr operation. static inline BLOCK_FTR* KiHdrToFtr(BLOCK_HDR* h) { return (BLOCK_FTR *)((char *)h + HDR_SIZE + h->Size); } +// Implements the ftr To Hdr operation. static inline BLOCK_HDR* KiFtrToHdr(BLOCK_FTR* f) { return (BLOCK_HDR *)((char *)f - HDR_SIZE - f->Size); } +// Implements the next Block operation. static inline BLOCK_HDR* KiNextBlock(BLOCK_HDR* h) { return (BLOCK_HDR *)((char *)h + HDR_SIZE + h->Size + FTR_SIZE); } +// Implements the prev Ftr operation. static inline BLOCK_FTR* KiPrevFtr(BLOCK_HDR* h) { return (BLOCK_FTR *)((char *)h - FTR_SIZE); } @@ -520,6 +528,7 @@ typedef struct HEAP { SPINLOCK Lock; } HEAP; +// Implements the heap Ensure Mapped operation. static int KiHeapEnsureMapped(HEAP* h, uintptr_t start, size_t size) { if (!h || !size) return 1; if (start < h->Start) return 0; @@ -592,6 +601,7 @@ static void KiFreeListRemove(HEAP* h, BLOCK_HDR* blk) { blk->PrevFree = blk->NextFree = (BLOCK_HDR *)0; } +// Implements the heap Try Decommit Tail operation. static void KiHeapTryDecommitTail(HEAP* h, BLOCK_HDR* blk) { (void)h; if (!blk || blk->Free == 0) return; @@ -607,6 +617,7 @@ static void KiHeapTryDecommitTail(HEAP* h, BLOCK_HDR* blk) { KiHdrToFtr(blk)->Free = 1; } +// Implements the heap Alloc operation. static void* KiHeapAlloc(HEAP* h, size_t size) { if (!size) return (void *)0; size = (size + 7) & ~7ULL; // 8-byte align @@ -670,6 +681,7 @@ static void* KiHeapAlloc(HEAP* h, size_t size) { return (char *)best + HDR_SIZE; } +// Implements the heap Free operation. static void KiHeapFree(HEAP* h, void* ptr) { if (!ptr) return; BLOCK_HDR* blk = (BLOCK_HDR *)((char *)ptr - HDR_SIZE); @@ -717,27 +729,28 @@ static void KiHeapFree(HEAP* h, void* ptr) { KeReleaseSpinlock(&h->Lock, flags); } +// Implements the heap Realloc operation. static void* KiHeapRealloc(HEAP* h, void* ptr, size_t new_size) { - // If ptr is NULL, realloc acts like malloc + // If ptr is NULL, realloc acts like malloc. if (!ptr) { return KiHeapAlloc(h, new_size); } - // If size is 0, realloc acts like free + // If size is 0, realloc acts like free. if (new_size == 0) { KiHeapFree(h, ptr); return (void*)0; } - // Retrieve the header of the existing block + // Retrieve the header of the existing block. BLOCK_HDR* blk = (BLOCK_HDR *)((char *)ptr - HDR_SIZE); - // Sanity checks to prevent operating on corrupted or already-freed pointers + // Sanity checks to prevent operating on corrupted or already-freed pointers. if (blk->Magic != BLOCK_MAGIC || blk->Free) { return (void*)0; } - // Align the requested size (matches KiHeapAlloc 8-byte alignment) + // Align the requested size (matches KiHeapAlloc 8-byte alignment). size_t aligned_size = (new_size + 7) & ~7ULL; // If the current block is already big enough, we can reuse it in-place. @@ -758,20 +771,16 @@ static void* KiHeapRealloc(HEAP* h, void* ptr, size_t new_size) { // We only copy up to the old block's usable size. memcpy(new_ptr, ptr, blk->Size); - // Free the old block + // Free the old block. KiHeapFree(h, ptr); return new_ptr; } -// --------------------------------------------------------------------------- -// Kernel pool -// --------------------------------------------------------------------------- +// Kernel pool. static HEAP gPoolHeap; -// --------------------------------------------------------------------------- -// User virtual region arena -// --------------------------------------------------------------------------- +// User virtual region arena. typedef struct USER_VA_REGION { LIST_ENTRY ProcessLink; LIST_ENTRY GlobalLink; @@ -794,9 +803,7 @@ static int gUserRegionListReady = 0; #define USER_REGION_ARENA_BASE 0x0000100000000000ULL -// --------------------------------------------------------------------------- -// Module init -// --------------------------------------------------------------------------- +// Module init. void MmInitializeVirtual(PHYSICAL_ADDRESS bootPml4Phys, size_t poolSize) { gPml4Phys = bootPml4Phys; gPageTableLock = (SPINLOCK)SPINLOCK_INIT; @@ -822,38 +829,40 @@ void MmInitializeVirtual(PHYSICAL_ADDRESS bootPml4Phys, size_t poolSize) { gUserRegionListReady = 1; } +// Implements the activate operation. void MmActivate(void) { __writecr3(gPml4Phys); } -// --------------------------------------------------------------------------- -// Public pool API -// --------------------------------------------------------------------------- +// Public pool API. __declspec(dllexport) void* MmAllocatePool(size_t size) { return KiHeapAlloc(&gPoolHeap, size); } +// Releases pool. __declspec(dllexport) void MmFreePool(void* ptr) { KiHeapFree(&gPoolHeap, ptr); } +// Implements the reallocate Pool operation. __declspec(dllexport) void* MmReallocatePool(void* ptr, size_t newSize) { return KiHeapRealloc(&gPoolHeap, ptr, newSize); } -// --------------------------------------------------------------------------- -// User virtual region API -// --------------------------------------------------------------------------- +// User virtual region API. static inline uintptr_t KiAlignUpPtr(uintptr_t v, size_t align) { if (align < PAGE_SIZE) align = PAGE_SIZE; if (align & (align - 1)) return 0; return (v + (uintptr_t)align - 1) & ~((uintptr_t)align - 1); } +// Implements the align Up Size operation. static inline size_t KiAlignUpSize(size_t v, size_t align) { if (align < PAGE_SIZE) align = PAGE_SIZE; if (align & (align - 1)) return 0; return (v + align - 1) & ~(align - 1); } +// Implements the ranges Overlap operation. static int KiRangesOverlap(uintptr_t aBase, size_t aSize, uintptr_t bBase, size_t bSize) { uintptr_t aEnd = aBase + aSize; uintptr_t bEnd = bBase + bSize; return aBase < bEnd && bBase < aEnd; } +// Returns user Va Range. static KSTATUS KiFindUserVaRange(size_t reservationSize, size_t alignment, uintptr_t* baseOut) { if (!baseOut || !reservationSize) return STATUS_INVALID_PARAMETER; if (!gUserRegionListReady) return STATUS_FAILURE; @@ -887,6 +896,7 @@ static KSTATUS KiFindUserVaRange(size_t reservationSize, size_t alignment, uintp } } +// Returns user Region Locked. static USER_VA_REGION* KiFindUserRegionLocked(PROCESS* process, const void* base) { if (!process || !base) return (USER_VA_REGION*)0; uintptr_t b = (uintptr_t)base; @@ -897,6 +907,7 @@ static USER_VA_REGION* KiFindUserRegionLocked(PROCESS* process, const void* base return (USER_VA_REGION*)0; } +// Returns user Region Containing Locked. static USER_VA_REGION* KiFindUserRegionContainingLocked(PROCESS* process, uintptr_t base, size_t size) { if (!process || !base || !size) return (USER_VA_REGION*)0; if (base > (uintptr_t)-1 - (size - 1)) return (USER_VA_REGION*)0; @@ -910,6 +921,7 @@ static USER_VA_REGION* KiFindUserRegionContainingLocked(PROCESS* process, uintpt return (USER_VA_REGION*)0; } +// Releases user Region Payload. static void KiUnmapUserRegionPayload(USER_VA_REGION* r) { if (!r) return; uintptr_t end = r->Base + r->CommittedSize; @@ -1007,6 +1019,7 @@ KSTATUS MmCreateUserRegion(PROCESS* process, size_t size, size_t alignment, return STATUS_SUCCESS; } +// Implements the ensure User Region Mapped operation. KSTATUS MmEnsureUserRegionMapped(PROCESS* process, void* base, size_t size, uint64_t pageFlags) { KeAssertIrql(PASSIVE_LEVEL); if (!process || !base || !size) return STATUS_INVALID_PARAMETER; @@ -1061,6 +1074,7 @@ KSTATUS MmEnsureUserRegionMapped(PROCESS* process, void* base, size_t size, uint return STATUS_SUCCESS; } +// Implements the protect User Region operation. KSTATUS MmProtectUserRegion(PROCESS* process, void* base, size_t size, uint64_t pageFlags) { KeAssertIrql(PASSIVE_LEVEL); if (!process || !base || !size) return STATUS_INVALID_PARAMETER; @@ -1143,6 +1157,7 @@ KSTATUS MmProtectUserRegion(PROCESS* process, void* base, size_t size, uint64_t return STATUS_SUCCESS; } +// Releases user Region. KSTATUS MmDestroyUserRegion(PROCESS* process, void* base) { KeAssertIrql(PASSIVE_LEVEL); if (!process || !base) return STATUS_INVALID_PARAMETER; @@ -1165,6 +1180,7 @@ KSTATUS MmDestroyUserRegion(PROCESS* process, void* base) { return STATUS_SUCCESS; } +// Releases all User Regions. void MmDestroyAllUserRegions(PROCESS* process) { KeAssertIrql(PASSIVE_LEVEL); if (!process) return; @@ -1213,6 +1229,7 @@ KSTATUS MmQueryUserRegion(PROCESS* process, const void* address, void** baseOut, } +// Returns process User Memory. void MmQueryProcessUserMemory(PROCESS* process, size_t* regionCountOut, size_t* reservedBytesOut, size_t* committedBytesOut) { size_t regions = 0; size_t reserved = 0; @@ -1234,6 +1251,7 @@ void MmQueryProcessUserMemory(PROCESS* process, size_t* regionCountOut, size_t* if (committedBytesOut) *committedBytesOut = committed; } +// Returns user Region Size. size_t MmGetUserRegionSize(PROCESS* process, const void* base) { if (!process || !base) return 0; uintptr_t procFlags = KeAcquireSpinlock(&process->UserRegionLock); @@ -1243,6 +1261,7 @@ size_t MmGetUserRegionSize(PROCESS* process, const void* base) { return size; } +// Returns user Region Size By Base. size_t MmGetUserRegionSizeByBase(const void* base) { if (!base) return 0; uintptr_t b = (uintptr_t)base; @@ -1260,6 +1279,7 @@ size_t MmGetUserRegionSizeByBase(const void* base) { } +// Implements the user Region Type Name operation. static const char* KiUserRegionTypeName(USER_REGION_TYPE type) { switch (type) { case UserRegionGeneric: return "generic"; @@ -1275,6 +1295,7 @@ static const char* KiUserRegionTypeName(USER_REGION_TYPE type) { } } +// Implements the debug Dump User Regions operation. void MmDebugDumpUserRegions(PROCESS* process) { if (!process) { DbgPrint("MM: user regions: \n"); @@ -1302,6 +1323,7 @@ void MmDebugDumpUserRegions(PROCESS* process) { if (!count) DbgPrint(" \n"); } +// Implements the debug Describe Pool Address operation. static void KiDebugDescribePoolAddress(uintptr_t addr) { DbgPrint("MM: kernel pool start=%016llx brk=%016llx limit=%016llx usage=%llu KiB\n", (unsigned long long)gPoolHeap.Start, @@ -1347,6 +1369,7 @@ static void KiDebugDescribePoolAddress(uintptr_t addr) { KeReleaseSpinlock(&gPoolHeap.Lock, flags); } +// Implements the debug Describe Address operation. void MmDebugDescribeAddress(uintptr_t addr) { PHYSICAL_ADDRESS phys = 0; uint64_t flags = 0; @@ -1385,6 +1408,7 @@ void MmDebugDescribeAddress(uintptr_t addr) { } } +// Creates user Memory For Process. __declspec(dllexport) void* MmAllocateUserMemoryForProcess(PROCESS* process, size_t size) { void* base = (void*)0; if (!process || !size) return (void*)0; @@ -1396,11 +1420,13 @@ __declspec(dllexport) void* MmAllocateUserMemoryForProcess(PROCESS* process, siz return KSUCCESS(s) ? base : (void*)0; } +// Releases user Memory For Process. __declspec(dllexport) void MmFreeUserMemoryForProcess(PROCESS* process, void* ptr) { if (!process || !ptr) return; (void)MmDestroyUserRegion(process, ptr); } +// Implements the reallocate User Memory For Process operation. __declspec(dllexport) void* MmReallocateUserMemoryForProcess(PROCESS* process, void* ptr, size_t newSize) { if (!process) return (void*)0; if (!ptr) return MmAllocateUserMemoryForProcess(process, newSize); @@ -1420,21 +1446,25 @@ __declspec(dllexport) void* MmReallocateUserMemoryForProcess(PROCESS* process, v return newPtr; } +// Creates user Memory. __declspec(dllexport) void* MmAllocateUserMemory(size_t size) { PROCESS* process = KeGetCurrentProcess(); return MmAllocateUserMemoryForProcess(process, size); } +// Releases user Memory. __declspec(dllexport) void MmFreeUserMemory(void* ptr) { PROCESS* process = KeGetCurrentProcess(); MmFreeUserMemoryForProcess(process, ptr); } +// Implements the reallocate User Memory operation. __declspec(dllexport) void* MmReallocateUserMemory(void* ptr, size_t newSize) { PROCESS* process = KeGetCurrentProcess(); return MmReallocateUserMemoryForProcess(process, ptr, newSize); } +// Creates user Image For Process. __declspec(dllexport) void* MmAllocateUserImageForProcess(PROCESS* process, size_t size) { void* base = (void*)0; if (!process || !size) return (void*)0; @@ -1446,27 +1476,32 @@ __declspec(dllexport) void* MmAllocateUserImageForProcess(PROCESS* process, size return KSUCCESS(s) ? base : (void*)0; } +// Releases user Image For Process. __declspec(dllexport) void MmFreeUserImageForProcess(PROCESS* process, void* ptr, size_t size) { (void)size; if (!process || !ptr) return; (void)MmDestroyUserRegion(process, ptr); } +// Creates user Image. __declspec(dllexport) void* MmAllocateUserImage(size_t size) { PROCESS* process = KeGetCurrentProcess(); return MmAllocateUserImageForProcess(process, size); } +// Releases user Image. __declspec(dllexport) void MmFreeUserImage(void* ptr, size_t size) { PROCESS* process = KeGetCurrentProcess(); MmFreeUserImageForProcess(process, ptr, size); } +// Returns kernel Pool Usage. size_t MmGetKernelPoolUsage(void) { - // Returns bytes committed to the kernel pool + // Returns bytes committed to the kernel pool. return (size_t)(gPoolHeap.Brk - gPoolHeap.Start); } +// Returns user Heap Usage. size_t MmGetUserHeapUsage(void) { size_t total = 0; if (!gUserRegionListReady) return 0; diff --git a/code/kernel/net_device.c b/code/kernel/net_device.c index e340c3a..0a913d1 100644 --- a/code/kernel/net_device.c +++ b/code/kernel/net_device.c @@ -1,4 +1,5 @@ -// net_device.c - minimal network-device registry and stack-provider RX handoff. +// Network device registry. This file owns net-device registration and RX handoff to the active stack provider. + #include #include #include @@ -14,6 +15,7 @@ static NET_DEVICE* gNetDevices[NET_MAX_DEVICES]; static uint32_t gNetDeviceCount = 0; static SPINLOCK gNetLock = SPINLOCK_INIT; +// Implements the net Make Default Name operation. static void NetMakeDefaultName(NET_DEVICE* device, uint32_t index) { if (!device || device->Name[0]) return; @@ -25,6 +27,7 @@ static void NetMakeDefaultName(NET_DEVICE* device, uint32_t index) { device->Name[4] = '\0'; } +// Implements the net Is Device Registered Locked operation. static bool NetIsDeviceRegisteredLocked(const NET_DEVICE* device) { for (uint32_t i = 0; i < gNetDeviceCount; ++i) { if (gNetDevices[i] == device) @@ -33,10 +36,12 @@ static bool NetIsDeviceRegisteredLocked(const NET_DEVICE* device) { return false; } +// Implements the net Device Has Ethernet Address operation. static bool NetDeviceHasEthernetAddress(const NET_DEVICE* device) { return device && device->HardwareAddressLength == NET_ETHERNET_ADDRESS_LENGTH; } +// Implements the net Log Hardware Address operation. static void NetLogHardwareAddress(const NET_DEVICE* device) { if (NetDeviceHasEthernetAddress(device)) { DbgPrint("%02x:%02x:%02x:%02x:%02x:%02x", @@ -48,6 +53,7 @@ static void NetLogHardwareAddress(const NET_DEVICE* device) { } } +// Implements the net Register Device operation. __declspec(dllexport) KSTATUS NetRegisterDevice(NET_DEVICE* device) { if (!device || !device->SendFrame) return STATUS_INVALID_PARAMETER; @@ -90,6 +96,7 @@ __declspec(dllexport) KSTATUS NetRegisterDevice(NET_DEVICE* device) { return STATUS_SUCCESS; } +// Implements the net Get Device Count operation. __declspec(dllexport) uint32_t NetGetDeviceCount(void) { uintptr_t flags = KeAcquireSpinlock(&gNetLock); uint32_t count = gNetDeviceCount; @@ -97,6 +104,7 @@ __declspec(dllexport) uint32_t NetGetDeviceCount(void) { return count; } +// Implements the net Get Device operation. __declspec(dllexport) NET_DEVICE* NetGetDevice(uint32_t index) { uintptr_t flags = KeAcquireSpinlock(&gNetLock); NET_DEVICE* device = (index < gNetDeviceCount) ? gNetDevices[index] : (NET_DEVICE*)0; diff --git a/code/kernel/net_socket.c b/code/kernel/net_socket.c index adbd508..2b477f1 100644 --- a/code/kernel/net_socket.c +++ b/code/kernel/net_socket.c @@ -1,4 +1,4 @@ -// net_socket.c - process-owned socket objects with provider-neutral dispatch. +// Kernel socket layer. This file owns process socket objects and provider-neutral socket dispatch. #include #include @@ -12,6 +12,7 @@ #define NET_SOCKET_UDP_MAX_BYTES 65507u #define NET_SOCKET_RAW_MAX_BYTES 65535u +// Implements the net Socket Destroy operation. static void NetSocketDestroy(OBJECT* object) { SOCKET_OBJECT* socket = (SOCKET_OBJECT*)object; if (socket->Provider && socket->ProviderSocket) { @@ -56,6 +57,7 @@ static KSTATUS NetSocketGetProviderSocket(SOCKET_OBJECT* socket, return STATUS_SUCCESS; } +// Implements the net Socket Create operation. KSTATUS NetSocketCreate(uint32_t domain, uint32_t type, uint32_t protocol, SOCKET_OBJECT** out) { if (!out) return STATUS_INVALID_PARAMETER; @@ -78,6 +80,7 @@ KSTATUS NetSocketCreate(uint32_t domain, uint32_t type, uint32_t protocol, SOCKE return st; } +// Implements the net Socket Bind operation. KSTATUS NetSocketBind(SOCKET_OBJECT* socket, const SYS_SOCKET_ADDRESS_IPV4_K* address, size_t addressSize) { const NET_STACK_PROVIDER* provider = NULL; void* providerSocket = NULL; @@ -85,6 +88,7 @@ KSTATUS NetSocketBind(SOCKET_OBJECT* socket, const SYS_SOCKET_ADDRESS_IPV4_K* ad return KSUCCESS(st) ? provider->Bind(providerSocket, address, addressSize) : st; } +// Implements the net Socket Listen operation. KSTATUS NetSocketListen(SOCKET_OBJECT* socket, uint32_t backlog) { const NET_STACK_PROVIDER* provider = NULL; void* providerSocket = NULL; @@ -92,6 +96,7 @@ KSTATUS NetSocketListen(SOCKET_OBJECT* socket, uint32_t backlog) { return KSUCCESS(st) ? provider->Listen(providerSocket, backlog) : st; } +// Implements the net Socket Accept operation. KSTATUS NetSocketAccept(SOCKET_OBJECT* socket, SOCKET_OBJECT** acceptedOut, SYS_SOCKET_ADDRESS_IPV4_K* remoteOut) { if (!acceptedOut) return STATUS_INVALID_PARAMETER; @@ -121,6 +126,7 @@ KSTATUS NetSocketAccept(SOCKET_OBJECT* socket, SOCKET_OBJECT** acceptedOut, SYS_ return st; } +// Implements the net Socket Connect operation. KSTATUS NetSocketConnect(SOCKET_OBJECT* socket, const SYS_SOCKET_ADDRESS_IPV4_K* address, size_t addressSize) { const NET_STACK_PROVIDER* provider = NULL; void* providerSocket = NULL; @@ -128,6 +134,7 @@ KSTATUS NetSocketConnect(SOCKET_OBJECT* socket, const SYS_SOCKET_ADDRESS_IPV4_K* return KSUCCESS(st) ? provider->Connect(providerSocket, address, addressSize) : st; } +// Implements the net Socket Send operation. KSTATUS NetSocketSend(SOCKET_OBJECT* socket, const void* buffer, size_t length, uint32_t flags, size_t* sentOut) { if (sentOut) *sentOut = 0; @@ -142,6 +149,7 @@ KSTATUS NetSocketSend(SOCKET_OBJECT* socket, const void* buffer, size_t length, return KSUCCESS(st) ? provider->Send(providerSocket, buffer, length, flags, sentOut) : st; } +// Implements the net Socket Receive operation. KSTATUS NetSocketReceive(SOCKET_OBJECT* socket, void* buffer, size_t length, uint32_t flags, size_t* receivedOut) { if (receivedOut) *receivedOut = 0; @@ -194,6 +202,7 @@ KSTATUS NetSocketReceiveFrom(SOCKET_OBJECT* socket, void* buffer, size_t length, return KSUCCESS(st) ? provider->ReceiveFrom(providerSocket, buffer, length, flags, remoteOut, receivedOut) : st; } +// Implements the net Socket Shutdown operation. KSTATUS NetSocketShutdown(SOCKET_OBJECT* socket, uint32_t how) { const NET_STACK_PROVIDER* provider = NULL; void* providerSocket = NULL; @@ -201,6 +210,7 @@ KSTATUS NetSocketShutdown(SOCKET_OBJECT* socket, uint32_t how) { return KSUCCESS(st) ? provider->Shutdown(providerSocket, how) : st; } +// Implements the net Socket Set Option operation. KSTATUS NetSocketSetOption(SOCKET_OBJECT* socket, uint32_t option, const void* value, size_t valueSize) { const NET_STACK_PROVIDER* provider = NULL; void* providerSocket = NULL; @@ -208,6 +218,7 @@ KSTATUS NetSocketSetOption(SOCKET_OBJECT* socket, uint32_t option, const void* v return KSUCCESS(st) ? provider->SetOption(providerSocket, option, value, valueSize) : st; } +// Implements the net Socket Get Option operation. KSTATUS NetSocketGetOption(SOCKET_OBJECT* socket, uint32_t option, void* value, size_t valueSize, size_t* actualSizeOut) { const NET_STACK_PROVIDER* provider = NULL; void* providerSocket = NULL; @@ -215,6 +226,7 @@ KSTATUS NetSocketGetOption(SOCKET_OBJECT* socket, uint32_t option, void* value, return KSUCCESS(st) ? provider->GetOption(providerSocket, option, value, valueSize, actualSizeOut) : st; } +// Implements the net Socket Poll operation. KSTATUS NetSocketPoll(SOCKET_OBJECT* socket, uint32_t events, uint32_t* returnedEventsOut) { if (!returnedEventsOut) return STATUS_INVALID_PARAMETER; @@ -226,6 +238,7 @@ KSTATUS NetSocketPoll(SOCKET_OBJECT* socket, uint32_t events, uint32_t* returned return KSUCCESS(st) ? provider->Poll(providerSocket, events, returnedEventsOut) : st; } +// Implements the net Resolve Host Ipv4 operation. KSTATUS NetResolveHostIpv4(const char* name, SYS_SOCKET_ADDRESS_IPV4_K* addressOut) { if (!name || !addressOut) return STATUS_INVALID_PARAMETER; diff --git a/code/kernel/net_stack.c b/code/kernel/net_stack.c index 5c6d900..4b5e440 100644 --- a/code/kernel/net_stack.c +++ b/code/kernel/net_stack.c @@ -1,4 +1,4 @@ -// net_stack.c - single network stack provider registry. +// Network stack registry. This file owns the single active stack provider binding. #include #include @@ -10,6 +10,7 @@ static const NET_STACK_PROVIDER* gNetStackProvider = 0; static SPINLOCK gNetStackLock = SPINLOCK_INIT; +// Implements the net Validate Stack Provider operation. static KSTATUS NetValidateStackProvider(const NET_STACK_PROVIDER* p) { if (!p || p->Version != NET_STACK_PROVIDER_VERSION || !p->Name) return STATUS_INVALID_PARAMETER; @@ -25,6 +26,7 @@ static KSTATUS NetValidateStackProvider(const NET_STACK_PROVIDER* p) { return STATUS_SUCCESS; } +// Implements the net Register Stack Provider operation. __declspec(dllexport) KSTATUS NetRegisterStackProvider(const NET_STACK_PROVIDER* provider) { KSTATUS st = NetValidateStackProvider(provider); if (!KSUCCESS(st)) @@ -57,6 +59,7 @@ __declspec(dllexport) KSTATUS NetRegisterStackProvider(const NET_STACK_PROVIDER* return STATUS_SUCCESS; } +// Implements the net Get Stack Provider operation. __declspec(dllexport) const NET_STACK_PROVIDER* NetGetStackProvider(void) { uintptr_t flags = KeAcquireSpinlock(&gNetStackLock); const NET_STACK_PROVIDER* p = gNetStackProvider; diff --git a/code/kernel/ob_object.c b/code/kernel/ob_object.c index f200f71..5276b51 100644 --- a/code/kernel/ob_object.c +++ b/code/kernel/ob_object.c @@ -1,9 +1,11 @@ -// ob_object.c - executive object manager +// Object manager. This file owns reference-counted kernel objects and handle-table lifetime rules. + #include #include #include #include +// Creates object. __declspec(dllexport) OBJECT* ObAllocateObject(OBJECT_TYPE type, size_t size) { if (size < sizeof(OBJECT)) size = sizeof(OBJECT); @@ -17,11 +19,13 @@ __declspec(dllexport) OBJECT* ObAllocateObject(OBJECT_TYPE type, size_t size) { return obj; } +// Implements the reference Object operation. __declspec(dllexport) void ObReferenceObject(OBJECT* object) { if (!object) return; _InterlockedIncrement(&object->RefCount); } +// Implements the dereference Object operation. __declspec(dllexport) void ObDereferenceObject(OBJECT* object) { if (!object) return; long prev = _InterlockedDecrement(&object->RefCount); diff --git a/code/public/ntlite/boot_info.h b/code/public/ntlite/boot_info.h index e25a31e..7a0a2fd 100644 --- a/code/public/ntlite/boot_info.h +++ b/code/public/ntlite/boot_info.h @@ -1,10 +1,12 @@ +// Public NTLite boot info ABI declarations shared between kernel, drivers, and user mode. + #pragma once -// boot_info.h - shared between bootx64.efi and kernel.exe -// The bootloader fills this structure and passes a pointer to KernelMain. +// Boot information ABI shared between bootx64.efi and kernel.exe. +// The bootloader fills this structure immediately before ExitBootServices so the kernel starts with a firmware-free view of memory and devices. #include #include -#define BOOT_INFO_MAGIC 0x424F4F54494E464FULL /* 'BOOTINFO' */ +#define BOOT_INFO_MAGIC 0x424F4F54494E464FULL // 'BOOTINFO' #define MAX_BOOT_MODULES 32 #define BOOT_TIME_FLAG_VALID 0x0001u @@ -29,43 +31,43 @@ typedef struct BOOT_TIME { } BOOT_TIME; typedef struct BOOT_MODULE { - char Name[32]; /* e.g. "hal.dll", "ata.sys" */ - uintptr_t VirtBase; /* Virtual address (mapped) */ - uintptr_t PhysBase; /* Raw physical address (file) */ - size_t ImageSize; /* File size / Image size */ + char Name[32]; // e.g. "hal.dll", "ata.sys" + uintptr_t VirtBase; // Virtual address (mapped) + uintptr_t PhysBase; // Raw physical address (file) + size_t ImageSize; // File size / Image size } BOOT_MODULE; typedef struct BOOT_INFO { uint64_t Magic; - /* Physical memory. */ + // Physical memory. MEMORY_MAP MemoryMap; - /* GOP framebuffer. */ + // GOP framebuffer. uintptr_t FramebufferBase; uint32_t FramebufferWidth; uint32_t FramebufferHeight; - uint32_t FramebufferStride; /* pixels per row */ + uint32_t FramebufferStride; // pixels per row - /* Loaded modules. */ + // Loaded modules. BOOT_MODULE Modules[MAX_BOOT_MODULES]; uint32_t ModuleCount; uint32_t _pad1; char CommandLine[64]; - /* ACPI RSDP physical address (for APIC, HPET). */ + // ACPI RSDP physical address (for APIC, HPET). uintptr_t RsdpPhysical; - /* Direct physical window base - always 0xFFFF880000000000. */ + // Direct physical window base - always 0xFFFF880000000000. uintptr_t PhysicalMapBase; - /* Reserved low-memory page for the AP startup trampoline, or zero. */ + // Reserved low-memory page for the AP startup trampoline, or zero. uintptr_t ApTrampolinePhys; - /* From boot.ini */ + // From boot.ini. uint32_t Debug; - /* Firmware wall-clock snapshot taken before ExitBootServices. */ + // Firmware wall-clock snapshot taken before ExitBootServices. BOOT_TIME BootTime; } BOOT_INFO; diff --git a/code/public/ntlite/ddi/display.h b/code/public/ntlite/ddi/display.h index b9a0936..542d5db 100644 --- a/code/public/ntlite/ddi/display.h +++ b/code/public/ntlite/ddi/display.h @@ -1,6 +1,8 @@ +// Public NTLite display ABI declarations shared between kernel, drivers, and user mode. + #pragma once // display.h - display device DDI -// + // Display providers register DISPLAY_DEVICE objects with the kernel display // manager. The boot framebuffer backend is registered by the kernel itself; // PCI/virtual GPU drivers register additional providers later. diff --git a/code/public/ntlite/ddi/hal_api.h b/code/public/ntlite/ddi/hal_api.h index ed8a3a0..bad5824 100644 --- a/code/public/ntlite/ddi/hal_api.h +++ b/code/public/ntlite/ddi/hal_api.h @@ -1,5 +1,7 @@ +// Public NTLite hal api ABI declarations shared between kernel, drivers, and user mode. + #pragma once -// hal_api.h - HAL interface table exported as HalGetApi() +// hal_api.h - HAL interface table exported as HalGetApi(). #include #include #include @@ -100,19 +102,19 @@ typedef struct HAL_API { } HAL_API; typedef struct HAL_INIT_PARAMS { - // Framebuffer + // Framebuffer. uintptr_t FramebufferBase; uint32_t FramebufferWidth; uint32_t FramebufferHeight; uint32_t FramebufferStride; - // ACPI + // ACPI. uintptr_t RsdpPhysical; - // Memory + // Memory. uint64_t PhysicalWindowBase; - // Debug + // Debug. int Debug; void* (*AllocatePool)(size_t size); diff --git a/code/public/ntlite/ddi/input_device.h b/code/public/ntlite/ddi/input_device.h index 4070fa3..8e73df8 100644 --- a/code/public/ntlite/ddi/input_device.h +++ b/code/public/ntlite/ddi/input_device.h @@ -1,3 +1,5 @@ +// Public NTLite input device ABI declarations shared between kernel, drivers, and user mode. + #pragma once // input_device.h - driver-facing input submission DDI. diff --git a/code/public/ntlite/ddi/io_driver.h b/code/public/ntlite/ddi/io_driver.h index 44475c7..8f17fc5 100644 --- a/code/public/ntlite/ddi/io_driver.h +++ b/code/public/ntlite/ddi/io_driver.h @@ -1,6 +1,8 @@ +// Public NTLite io driver ABI declarations shared between kernel, drivers, and user mode. + #pragma once // io_driver.h - kernel driver/device I/O model -// + // Device lifetime is owned by the I/O manager. Bus drivers create PDOs, // function/filter drivers attach FDOs, and PnP/remove IRPs tear stacks down. // Disk indexes are only a compatibility namespace above DEVICE_OBJECTs. @@ -27,9 +29,7 @@ typedef KSTATUS (*PDRIVER_DISPATCH)(DEVICE_OBJECT* device, IRP* irp); typedef KSTATUS (*PDRIVER_ADD_DEVICE)(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject); -// ------------------------------------------------------------------------- -// Bus / identity -// ------------------------------------------------------------------------- +// Bus / identity. typedef enum IO_BUS_TYPE { IoBusUnknown = 0, @@ -51,9 +51,7 @@ typedef struct IO_DRIVER_ID_TABLE { #define IO_MAX_DEVICE_ID_CHARS 96u #define IO_MAX_DEVICE_NAME_CHARS 64u -// ------------------------------------------------------------------------- -// Driver/device objects -// ------------------------------------------------------------------------- +// Driver/device objects. typedef enum DEVICE_OBJECT_TYPE { DeviceObjectPhysical = 1, @@ -128,9 +126,7 @@ struct DEVICE_OBJECT { #define DEVICE_OBJECT_DISK 0x00000001u #define DEVICE_OBJECT_REMOVABLE 0x00000002u -// ------------------------------------------------------------------------- -// Object/device creation and stack management -// ------------------------------------------------------------------------- +// Object/device creation and stack management. __declspec(dllexport) void IoInitializeDriverObject(DRIVER_OBJECT* driver, SYS_STRING_VIEW name); @@ -165,9 +161,7 @@ __declspec(dllexport) uint8_t IoGetDeviceStackSize(DEVICE_OBJECT* device); __declspec(dllexport) KSTATUS IoSendPnpIrpSync(DEVICE_OBJECT* device, IO_PNP_MINOR_FUNCTION minor); -// ------------------------------------------------------------------------- -// Disk namespace above storage DEVICE_OBJECTs -// ------------------------------------------------------------------------- +// Disk namespace above storage DEVICE_OBJECTs. typedef enum IO_DEVICE_CHANGE { IoDeviceArrived = 0, diff --git a/code/public/ntlite/ddi/net_abi.h b/code/public/ntlite/ddi/net_abi.h index fc7dc68..5dc7bf2 100644 --- a/code/public/ntlite/ddi/net_abi.h +++ b/code/public/ntlite/ddi/net_abi.h @@ -1,3 +1,5 @@ +// Public NTLite net abi ABI declarations shared between kernel, drivers, and user mode. + #pragma once // net_abi.h - native networking ABI shared by the kernel socket facade // and network stack provider drivers. diff --git a/code/public/ntlite/ddi/net_device.h b/code/public/ntlite/ddi/net_device.h index 9762e12..91f3ed8 100644 --- a/code/public/ntlite/ddi/net_device.h +++ b/code/public/ntlite/ddi/net_device.h @@ -1,6 +1,8 @@ +// Public NTLite net device ABI declarations shared between kernel, drivers, and user mode. + #pragma once // net_device.h - kernel network-device registry. -// + // NIC drivers register NET_DEVICE objects here and feed complete Ethernet // frames into NetReceiveFrame(). Protocol ownership belongs to whichever // network stack driver registered through net_stack.h. diff --git a/code/public/ntlite/ddi/net_stack.h b/code/public/ntlite/ddi/net_stack.h index 623e3d1..760498e 100644 --- a/code/public/ntlite/ddi/net_stack.h +++ b/code/public/ntlite/ddi/net_stack.h @@ -1,6 +1,8 @@ +// Public NTLite net stack ABI declarations shared between kernel, drivers, and user mode. + #pragma once // net_stack.h - provider interface between kernel socket facade and network stack drivers. -// + // The kernel owns process handles, user-memory copying, NET_DEVICE registration, // and SOCKET_OBJECT lifetime. A stack driver owns protocol implementation. diff --git a/code/public/ntlite/ddi/pci.h b/code/public/ntlite/ddi/pci.h index 50fb21e..0836a6a 100644 --- a/code/public/ntlite/ddi/pci.h +++ b/code/public/ntlite/ddi/pci.h @@ -1,6 +1,8 @@ +// Public NTLite pci ABI declarations shared between kernel, drivers, and user mode. + #pragma once // pci.h - PCI bus driver DDI exported by pci.sys -// + // Function drivers must not enumerate PCI or decode BARs themselves. They bind // to PCI PDOs through the I/O manager and use these routines to access the PCI // function represented by their PDO. diff --git a/code/public/ntlite/dirent.h b/code/public/ntlite/dirent.h index dc1bc38..ed3590a 100644 --- a/code/public/ntlite/dirent.h +++ b/code/public/ntlite/dirent.h @@ -1,3 +1,5 @@ +// Public NTLite dirent ABI declarations shared between kernel, drivers, and user mode. + #pragma once // dirent.h - directory entry returned by SysReadDir. diff --git a/code/public/ntlite/display.h b/code/public/ntlite/display.h index d0cf30c..c2dda13 100644 --- a/code/public/ntlite/display.h +++ b/code/public/ntlite/display.h @@ -1,6 +1,8 @@ +// Public NTLite display ABI declarations shared between kernel, drivers, and user mode. + #pragma once // display.h - user/kernel shared display ABI types -// + // This header is safe for user-mode code. It contains only plain syscall ABI // data types and capability bits. Kernel/driver provider interfaces live in // . diff --git a/code/public/ntlite/input.h b/code/public/ntlite/input.h index bd31755..198d6a3 100644 --- a/code/public/ntlite/input.h +++ b/code/public/ntlite/input.h @@ -1,6 +1,8 @@ +// Public NTLite input ABI declarations shared between kernel, drivers, and user mode. + #pragma once // input.h - canonical keyboard/mouse input ABI shared by kernel, drivers, and user-mode. -// + // Key values intentionally follow USB HID Keyboard/Keypad usage IDs. PS/2, // USB HID, and future input drivers all translate their hardware format into // these values before entering the kernel input core. diff --git a/code/public/ntlite/memory_map.h b/code/public/ntlite/memory_map.h index 4881c30..3a99a79 100644 --- a/code/public/ntlite/memory_map.h +++ b/code/public/ntlite/memory_map.h @@ -1,30 +1,32 @@ -#pragma once -// memory_map.h - shared between bootx64.efi and kernel.exe -// Describes physical memory layout passed from bootloader to kernel. -#include - -#define MEMORY_MAP_MAGIC 0x4D454D4D41500000ULL /* 'MEMMAP\0\0' */ -#define MEMORY_MAX_REGIONS 256 - -typedef enum MEMORY_TYPE { - MemoryUsable = 0, /* free RAM, available to the PMM */ - MemoryReserved = 1, /* firmware-reserved, do not touch */ - MemoryMappedIO = 2, /* device MMIO regions */ - MemoryFramebuffer = 3, /* GOP framebuffer */ - MemoryBootloader = 4, /* bootloader code/data (reclaimable) */ - MemoryKernel = 5, /* kernel + HAL + drivers image pages */ -} MEMORY_TYPE; - -typedef struct MEMORY_REGION { - uint64_t Base; - uint64_t Length; /* in bytes, always page-aligned */ - MEMORY_TYPE Type; - uint32_t _pad; -} MEMORY_REGION; - -typedef struct MEMORY_MAP { - uint64_t Magic; - uint32_t RegionCount; - uint32_t _pad; - MEMORY_REGION Regions[MEMORY_MAX_REGIONS]; -} MEMORY_MAP; +// Public NTLite memory map ABI declarations shared between kernel, drivers, and user mode. + +#pragma once +// memory_map.h - shared between bootx64.efi and kernel.exe +// Describes physical memory layout passed from bootloader to kernel. +#include + +#define MEMORY_MAP_MAGIC 0x4D454D4D41500000ULL // 'MEMMAP\0\0' +#define MEMORY_MAX_REGIONS 256 + +typedef enum MEMORY_TYPE { + MemoryUsable = 0, // free RAM, available to the PMM + MemoryReserved = 1, // firmware-reserved, do not touch + MemoryMappedIO = 2, // device MMIO regions + MemoryFramebuffer = 3, // GOP framebuffer + MemoryBootloader = 4, // bootloader code/data (reclaimable) + MemoryKernel = 5, // kernel + HAL + drivers image pages +} MEMORY_TYPE; + +typedef struct MEMORY_REGION { + uint64_t Base; + uint64_t Length; // in bytes, always page-aligned + MEMORY_TYPE Type; + uint32_t _pad; +} MEMORY_REGION; + +typedef struct MEMORY_MAP { + uint64_t Magic; + uint32_t RegionCount; + uint32_t _pad; + MEMORY_REGION Regions[MEMORY_MAX_REGIONS]; +} MEMORY_MAP; diff --git a/code/public/ntlite/status.h b/code/public/ntlite/status.h index cc1c6ff..026d965 100644 --- a/code/public/ntlite/status.h +++ b/code/public/ntlite/status.h @@ -1,3 +1,5 @@ +// Public NTLite status ABI declarations shared between kernel, drivers, and user mode. + #pragma once // ke_status.h - kernel status codes // All fallible kernel functions return KSTATUS. @@ -6,7 +8,7 @@ typedef uint32_t KSTATUS; -// --- General & Control (0x0000) --- +// --- General & Control (0x0000) ---. #define STATUS_SUCCESS ((KSTATUS)0x0000) #define STATUS_FAILURE ((KSTATUS)0x0001) #define STATUS_NOT_SUPPORTED ((KSTATUS)0x0002) @@ -16,31 +18,31 @@ typedef uint32_t KSTATUS; #define STATUS_KERNEL_APC ((KSTATUS)0x0006) #define STATUS_USER_APC ((KSTATUS)0x0007) -// --- Validation & Parameters (0x0010) --- +// --- Validation & Parameters (0x0010) ---. #define STATUS_INVALID_PARAMETER ((KSTATUS)0x0010) #define STATUS_INVALID_HANDLE ((KSTATUS)0x0011) #define STATUS_BUFFER_TOO_SMALL ((KSTATUS)0x0012) #define STATUS_CHECKSUM_MISMATCH ((KSTATUS)0x0013) -// --- Resource & Access (0x0020) --- +// --- Resource & Access (0x0020) ---. #define STATUS_NO_MEMORY ((KSTATUS)0x0020) #define STATUS_ACCESS_DENIED ((KSTATUS)0x0021) #define STATUS_NOT_FOUND ((KSTATUS)0x0022) #define STATUS_ALREADY_EXISTS ((KSTATUS)0x0023) #define STATUS_OBJECT_NAME_COLLISION ((KSTATUS)0x0024) -// --- State & Lifecycle (0x0030) --- +// --- State & Lifecycle (0x0030) ---. #define STATUS_OBJECT_DEAD ((KSTATUS)0x0030) #define STATUS_QUEUE_FULL ((KSTATUS)0x0031) #define STATUS_QUEUE_EMPTY ((KSTATUS)0x0032) #define STATUS_CANCELLED ((KSTATUS)0x0033) -// --- Hardware & External (0x0040) --- +// --- Hardware & External (0x0040) ---. #define STATUS_DEVICE_ERROR ((KSTATUS)0x0040) #define STATUS_NO_MORE_FILES ((KSTATUS)0x0050) -// --- Execution level (0x0060) --- +// --- Execution level (0x0060) ---. #define STATUS_INVALID_IRQL ((KSTATUS)0x0060) #define KSUCCESS(s) ((s) == STATUS_SUCCESS) diff --git a/code/public/ntlite/string_view.h b/code/public/ntlite/string_view.h index d9cdf9c..1e89ebd 100644 --- a/code/public/ntlite/string_view.h +++ b/code/public/ntlite/string_view.h @@ -1,3 +1,5 @@ +// Public NTLite string view ABI declarations shared between kernel, drivers, and user mode. + #pragma once // sys_string.h - shared native string-view ABI. // A SYS_STRING_VIEW is a borrowed byte span. It is not NUL-terminated by @@ -18,6 +20,7 @@ typedef struct SYS_STRING_VIEW { #define SYS_SV_LITERAL(s) ((SYS_STRING_VIEW){ (s), sizeof(s) - 1 }) #define SYS_SV_NULL ((SYS_STRING_VIEW){ (const char*)0, 0 }) +// Implements the sv From Parts operation. static inline SYS_STRING_VIEW SysSvFromParts(const char* data, size_t length) { SYS_STRING_VIEW v; v.Data = data; @@ -25,6 +28,7 @@ static inline SYS_STRING_VIEW SysSvFromParts(const char* data, size_t length) { return v; } +// Implements the sv From Cstr operation. static inline SYS_STRING_VIEW SysSvFromCstr(const char* s) { SYS_STRING_VIEW v; v.Data = s; @@ -32,14 +36,17 @@ static inline SYS_STRING_VIEW SysSvFromCstr(const char* s) { return v; } +// Implements the sv Is Empty operation. static inline int SysSvIsEmpty(SYS_STRING_VIEW s) { return s.Length == 0; } +// Implements the sv Is Valid operation. static inline int SysSvIsValid(SYS_STRING_VIEW s) { return s.Data != (const char*)0 || s.Length == 0; } +// Implements the sv Equal operation. static inline int SysSvEqual(SYS_STRING_VIEW a, SYS_STRING_VIEW b) { if (a.Length != b.Length) return 0; if (a.Length == 0) return 1; @@ -47,10 +54,12 @@ static inline int SysSvEqual(SYS_STRING_VIEW a, SYS_STRING_VIEW b) { return memcmp(a.Data, b.Data, a.Length) == 0; } +// Implements the ascii Lower operation. static inline char SysAsciiLower(char c) { return (c >= 'A' && c <= 'Z') ? (char)(c + ('a' - 'A')) : c; } +// Implements the sv Equal Ascii I operation. static inline int SysSvEqualAsciiI(SYS_STRING_VIEW a, SYS_STRING_VIEW b) { if (a.Length != b.Length) return 0; if (a.Length == 0) return 1; @@ -61,14 +70,17 @@ static inline int SysSvEqualAsciiI(SYS_STRING_VIEW a, SYS_STRING_VIEW b) { return 1; } +// Implements the sv Equal Lit operation. static inline int SysSvEqualLit(SYS_STRING_VIEW a, const char* lit) { return SysSvEqual(a, SysSvFromCstr(lit)); } +// Implements the sv Equal Lit Ascii I operation. static inline int SysSvEqualLitAsciiI(SYS_STRING_VIEW a, const char* lit) { return SysSvEqualAsciiI(a, SysSvFromCstr(lit)); } +// Implements the sv Contains Byte operation. static inline int SysSvContainsByte(SYS_STRING_VIEW s, char ch) { if (!s.Data && s.Length) return 0; for (size_t i = 0; i < s.Length; i++) { @@ -77,12 +89,14 @@ static inline int SysSvContainsByte(SYS_STRING_VIEW s, char ch) { return 0; } +// Implements the sv Slice operation. static inline SYS_STRING_VIEW SysSvSlice(SYS_STRING_VIEW s, size_t off, size_t len) { if (off > s.Length) off = s.Length; if (len > s.Length - off) len = s.Length - off; return SysSvFromParts(s.Data ? s.Data + off : (const char*)0, len); } +// Implements the sv Trim Ascii operation. static inline SYS_STRING_VIEW SysSvTrimAscii(SYS_STRING_VIEW s) { size_t begin = 0; size_t end = s.Length; @@ -99,6 +113,7 @@ static inline SYS_STRING_VIEW SysSvTrimAscii(SYS_STRING_VIEW s) { return SysSvSlice(s, begin, end - begin); } +// Implements the sv Copy Z operation. static inline int SysSvCopyZ(char* dst, size_t dstSize, SYS_STRING_VIEW src) { if (!dst || dstSize == 0) return 0; if (src.Length && !src.Data) return 0; diff --git a/code/public/ntlite/syscall.h b/code/public/ntlite/syscall.h index 4bc50d7..29db87b 100644 --- a/code/public/ntlite/syscall.h +++ b/code/public/ntlite/syscall.h @@ -1,5 +1,7 @@ +// Public NTLite syscall ABI declarations shared between kernel, drivers, and user mode. + #pragma once -// Syscall.h +// Syscall.h. #include #include @@ -22,12 +24,10 @@ #define SYS_STATUS_CANCELLED 0x33u #define SYS_STATUS_NOT_FOUND 0x22u -// --------------------------------------------------------------------------- // User process/thread environment -// --------------------------------------------------------------------------- // GS base points at SYS_TEB. GS:[0] is the process PEB pointer. -#define SYS_PEB_MAGIC 0x30424550u /* "PEB0" */ -#define SYS_TEB_MAGIC 0x30424554u /* "TEB0" */ +#define SYS_PEB_MAGIC 0x30424550u // "PEB0" +#define SYS_TEB_MAGIC 0x30424554u // "TEB0" #define SYS_ENV_VERSION 1u #define SYS_CWD_MAX 520u @@ -60,17 +60,17 @@ typedef struct SYS_TEB { #endif // SYS_USER_ENV_TYPES_DEFINED +// Returns peb. static inline SYS_PEB* SysGetPeb(void) { return (SYS_PEB*)(uintptr_t)__readgsqword(0); } +// Returns teb. static inline SYS_TEB* SysGetTeb(void) { return (SYS_TEB*)(uintptr_t)__readgsqword(offsetof(SYS_TEB, Self)); } -// --------------------------------------------------------------------------- -// APC and async I/O ABI -// --------------------------------------------------------------------------- +// APC and async I/O ABI. typedef struct SYS_IO_STATUS_BLOCK { volatile uint32_t Status; volatile uint64_t Information; @@ -109,9 +109,7 @@ typedef struct SYS_USER_APC_FRAME { void SysUserApcDispatcher(void); -// --------------------------------------------------------------------------- -// Trap-frame query ABI -// --------------------------------------------------------------------------- +// Trap-frame query ABI. typedef struct SYS_TRAP_FRAME_INFO { uint32_t Size; uint32_t Kind; @@ -133,9 +131,7 @@ typedef struct SYS_TRAP_FRAME_INFO { uint64_t R11; } SYS_TRAP_FRAME_INFO; -// --------------------------------------------------------------------------- -// String-view based syscall request structures -// --------------------------------------------------------------------------- +// String-view based syscall request structures. typedef struct SYS_CREATE_PROCESS_REQUEST { SYS_STRING_VIEW Path; SYS_STRING_VIEW CommandLine; @@ -185,9 +181,7 @@ typedef struct SYS_NAMED_QUEUE_OWNER_REQUEST { uint32_t* PidOut; } SYS_NAMED_QUEUE_OWNER_REQUEST; -// --------------------------------------------------------------------------- -// Process & thread lifecycle (0-14) -// --------------------------------------------------------------------------- +// Process & thread lifecycle (0-14). void SysExitProcess(int exitCode); void SysExitThread(int exitCode); uint32_t SysCreateProcess(const SYS_CREATE_PROCESS_REQUEST* request); @@ -246,9 +240,7 @@ uint32_t SysSleep(uint64_t ms); uint32_t SysSetUserApcDispatcher(void* dispatcher); uint32_t SysApcReturn(const SYS_USER_APC_FRAME* frame); -// --------------------------------------------------------------------------- -// Virtual memory and handles -// --------------------------------------------------------------------------- +// Virtual memory and handles. typedef enum SYS_PROTECT_VMION { SYS_VM_NOACCESS = 0, SYS_VM_READ = 1, @@ -276,9 +268,7 @@ uint32_t SysProtectVm(void* base, size_t pageCount, uint32_t protect, uint32_t* uint32_t SysQueryVm(void* address, SYS_VM_REGION_INFO* out); uint32_t SysCloseHandle(uint32_t handle); -// --------------------------------------------------------------------------- -// Synchronization primitives (19-31) -// --------------------------------------------------------------------------- +// Synchronization primitives (19-31). uint32_t SysCreateMutex(uint32_t* handleOut); uint32_t SysAcquireMutex(uint32_t handle); uint32_t SysTryAcquireMutex(uint32_t handle); @@ -294,9 +284,7 @@ uint32_t SysSignalEvent(uint32_t handle); uint32_t SysClearEvent(uint32_t handle); uint32_t SysWaitEvent(uint32_t handle, uint32_t alertable); -// --------------------------------------------------------------------------- -// Queues and named queues (32-38) -// --------------------------------------------------------------------------- +// Queues and named queues (32-38). uint32_t SysCreateQueue(uint32_t* handleOut); uint32_t SysSendQueue(uint32_t handle, const void* msg, bool blocking); uint32_t SysRecvQueue(uint32_t handle, void* msg, bool blocking); @@ -305,9 +293,7 @@ uint32_t SysOpenNamedQueue(const SYS_OPEN_NAMED_QUEUE_REQUEST* request); uint32_t SysDuplicateQueue(uint32_t handle, uint32_t targetPid, uint32_t* handleOut); uint32_t SysGetNamedQueueOwnerPid(const SYS_NAMED_QUEUE_OWNER_REQUEST* request); -// --------------------------------------------------------------------------- -// Files, directories, and current directory (39-56) -// --------------------------------------------------------------------------- +// Files, directories, and current directory (39-56). uint32_t SysOpenFile(const SYS_PATH_HANDLE_REQUEST* request); uint32_t SysCreateFile(const SYS_PATH_HANDLE_REQUEST* request); uint32_t SysReadFile(uint32_t handle, void* buf, size_t size, size_t* bytesRead); @@ -329,9 +315,7 @@ uint32_t SysRemoveDir(const SYS_PATH_REQUEST* request); uint32_t SysSetCwd(const SYS_PATH_REQUEST* request); uint32_t SysGetCwd(const SYS_GET_CWD_REQUEST* request); -// --------------------------------------------------------------------------- // Console and graphics. -// --------------------------------------------------------------------------- typedef struct SYS_CONSOLE_INFO { uint32_t Columns; uint32_t Rows; @@ -351,9 +335,7 @@ uint32_t SysClearScreen(uint32_t color); uint32_t SysGetScreenSize(int* widthOut, int* heightOut); uint32_t SysQueryDisplayInfo(SYS_DISPLAY_INFO* infoOut); -// --------------------------------------------------------------------------- // Input. -// --------------------------------------------------------------------------- uint64_t SysPollKeyboard(void); uint64_t SysIsKeyDown(INPUT_KEY key); char SysReadKeyboardChar(void); @@ -365,9 +347,7 @@ uint64_t SysReadMouse(int* dx, int* dy, uint8_t* buttons); void SysGetMousePos(int* x, int* y); -// --------------------------------------------------------------------------- -// Native sockets -// --------------------------------------------------------------------------- +// Native sockets. #define SYS_AF_INET 2u #define SYS_SOCK_STREAM 1u #define SYS_SOCK_DGRAM 2u @@ -511,9 +491,7 @@ typedef struct SYS_CPU_STATS { #define SYS_CPU_FLAG_BSP 0x00000010u #define SYS_CPU_FLAG_PRIMARY 0x00000020u -// --------------------------------------------------------------------------- -// Time and diagnostics -// --------------------------------------------------------------------------- +// Time and diagnostics. uint64_t SysGetTick(void); uint32_t SysPrintDebug(const SYS_PRINT_DEBUG_REQUEST* request); uint32_t SysQueryTrapFrame(SYS_TRAP_FRAME_INFO* info); diff --git a/code/public/ntlite/time.h b/code/public/ntlite/time.h index 4ed1703..bc8de2b 100644 --- a/code/public/ntlite/time.h +++ b/code/public/ntlite/time.h @@ -1,3 +1,5 @@ +// Public NTLite time ABI declarations shared between kernel, drivers, and user mode. + #pragma once #include diff --git a/code/user/apps/edit/edit.c b/code/user/apps/edit/edit.c index 5402480..dec31ef 100644 --- a/code/user/apps/edit/edit.c +++ b/code/user/apps/edit/edit.c @@ -1,9 +1,4 @@ -// edit.c - tiny native text editor for nt-lite -// Controls: -// arrows/home/end/pageup/pagedown move -// enter/backspace/delete/tab edit -// ctrl+s save -// ctrl+q quit (press twice if dirty) +// User application entry points for edit. #include #include @@ -72,10 +67,12 @@ typedef struct SCREEN_CELL { static SCREEN_CELL gScreenCache[MAX_SCREEN_COLS * MAX_SCREEN_ROWS]; static bool gScreenCacheValid = false; +// Implements the invalidate screen cache operation. static void invalidate_screen_cache(void) { gScreenCacheValid = false; } +// Updates screen size. static void update_screen_size(void) { int pxW = 0, pxH = 0; int oldCols = gCols; @@ -95,6 +92,7 @@ static void update_screen_size(void) { invalidate_screen_cache(); } +// Updates cell. static void put_cell(int col, int row, char c, uint32_t fg, uint32_t bg) { if (col < 0 || row < 0 || col >= gCols || row >= gRows) return; @@ -114,14 +112,17 @@ static void put_cell(int col, int row, char c, uint32_t fg, uint32_t bg) { SysPutScreenChar(c, col * GLYPH_W, row * GLYPH_H, fg, bg); } +// Clears row. static void clear_row(int row, uint32_t bg) { for (int x = 0; x < gCols; x++) put_cell(x, row, ' ', COL_FG, bg); } +// Draws text. static void draw_text(int col, int row, const char* s, uint32_t fg, uint32_t bg) { while (*s && col < gCols) put_cell(col++, row, *s++, fg, bg); } +// Implements the msg set operation. static void msg_set(const char* s) { size_t n = strlen(s); if (n >= sizeof(gMessage)) n = sizeof(gMessage) - 1; @@ -129,15 +130,18 @@ static void msg_set(const char* s) { gMessage[n] = 0; } +// Appends char. static void append_char(char* b, size_t cap, size_t* p, char c) { if (*p + 1 < cap) b[(*p)++] = c; b[*p < cap ? *p : cap - 1] = 0; } +// Appends str. static void append_str(char* b, size_t cap, size_t* p, const char* s) { while (*s) append_char(b, cap, p, *s++); } +// Appends u32. static void append_u32(char* b, size_t cap, size_t* p, uint32_t v) { char tmp[12]; int n = 0; @@ -149,6 +153,7 @@ static void append_u32(char* b, size_t cap, size_t* p, uint32_t v) { while (n > 0) append_char(b, cap, p, tmp[--n]); } +// Implements the key to char operation. static char key_to_char(INPUT_KEY key, uint32_t mods) { if (key >= INPUT_KEY_A && key <= INPUT_KEY_Z) { bool shifted = (mods & INPUT_MOD_SHIFT) != 0; @@ -178,6 +183,7 @@ static char key_to_char(INPUT_KEY key, uint32_t mods) { return 0; } +// Implements the clamp cursor operation. static void clamp_cursor(void) { if (gLineCount < 1) gLineCount = 1; if (gCy < 0) gCy = 0; @@ -186,6 +192,7 @@ static void clamp_cursor(void) { if (gCx > gLines[gCy].len) gCx = gLines[gCy].len; } +// Implements the ensure visible operation. static void ensure_visible(void) { int textRows = gRows - 2; if (textRows < 1) textRows = 1; @@ -199,6 +206,7 @@ static void ensure_visible(void) { if (gLeft < 0) gLeft = 0; } +// Implements the render operation. static void render(void) { update_screen_size(); @@ -251,6 +259,7 @@ static void render(void) { gScreenCacheValid = true; } +// Inserts char at cursor. static void insert_char_at_cursor(char c) { LINE* ln = &gLines[gCy]; if (ln->len >= MAX_LINE - 1) { msg_set("line too long"); return; } @@ -261,6 +270,7 @@ static void insert_char_at_cursor(char c) { gDirty = true; } +// Implements the newline at cursor operation. static void newline_at_cursor(void) { if (gLineCount >= MAX_LINES) { msg_set("too many lines"); return; } @@ -282,6 +292,7 @@ static void newline_at_cursor(void) { gDirty = true; } +// Implements the backspace at cursor operation. static void backspace_at_cursor(void) { if (gCx > 0) { LINE* ln = &gLines[gCy]; @@ -309,6 +320,7 @@ static void backspace_at_cursor(void) { gDirty = true; } +// Releases at cursor. static void delete_at_cursor(void) { LINE* ln = &gLines[gCy]; if (gCx < ln->len) { @@ -330,26 +342,31 @@ static void delete_at_cursor(void) { gDirty = true; } +// Moves left. static void move_left(void) { if (gCx > 0) gCx--; else if (gCy > 0) { gCy--; gCx = gLines[gCy].len; } } +// Moves right. static void move_right(void) { if (gCx < gLines[gCy].len) gCx++; else if (gCy + 1 < gLineCount) { gCy++; gCx = 0; } } +// Moves up. static void move_up(void) { if (gCy > 0) gCy--; if (gCx > gLines[gCy].len) gCx = gLines[gCy].len; } +// Moves down. static void move_down(void) { if (gCy + 1 < gLineCount) gCy++; if (gCx > gLines[gCy].len) gCx = gLines[gCy].len; } +// Updates file. static void save_file(void) { uint32_t h = 0; SYS_PATH_HANDLE_REQUEST pathReq = { SysSvFromCstr(gFilename), &h }; @@ -378,6 +395,7 @@ static void save_file(void) { msg_set("saved"); } +// Implements the reset buffer operation. static void reset_buffer(void) { gLineCount = 1; gLines[0].len = 0; @@ -386,6 +404,7 @@ static void reset_buffer(void) { gDirty = false; } +// Loads file. static void load_file(void) { reset_buffer(); @@ -423,11 +442,13 @@ static void load_file(void) { msg_set(truncated ? "loaded, truncated long file" : "loaded"); } +// Implements the skip spaces operation. static const char* skip_spaces(const char* s) { while (s && (*s == ' ' || *s == '\t')) s++; return s; } +// Implements the skip token operation. static const char* skip_token(const char* s) { s = skip_spaces(s); if (!s || !*s) return s; @@ -441,6 +462,7 @@ static const char* skip_token(const char* s) { return s; } +// Returns token. static bool read_token(const char* s, char* out, size_t cap) { s = skip_spaces(s); if (!s || !*s || cap == 0) return false; @@ -461,6 +483,7 @@ static bool read_token(const char* s, char* out, size_t cap) { return n != 0; } +// Parses filename from cmdline. static void parse_filename_from_cmdline(void) { SYS_PEB* peb = SysGetPeb(); const char* cmd = (peb && peb->CommandLine.Data) ? peb->CommandLine.Data : NULL; @@ -469,6 +492,7 @@ static void parse_filename_from_cmdline(void) { strcpy(gFilename, "untitled.txt"); } +// Implements the editor loop operation. static void editor_loop(void) { while (true) { render(); @@ -527,11 +551,13 @@ static void editor_loop(void) { } } +// Prints the requested operation. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); } +// Runs the requested operation. int main(void) { parse_filename_from_cmdline(); load_file(); diff --git a/code/user/apps/httpget/httpget.c b/code/user/apps/httpget/httpget.c index 757a70d..00d1e45 100644 --- a/code/user/apps/httpget/httpget.c +++ b/code/user/apps/httpget/httpget.c @@ -1,18 +1,23 @@ +// User application entry points for httpget. + #include #include #include #include #include +// Prints the requested operation. static void print(const char* s) { if (s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); } } +// Prints char. static void print_char(char c) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) }; SysWriteConsole(&req); } +// Prints u64. static void print_u64(uint64_t v) { char buf[32]; int n = 0; @@ -24,6 +29,7 @@ static void print_u64(uint64_t v) { while (n > 0) print_char(buf[--n]); } +// Appends char. static void append_char(char* dst, size_t cap, size_t* off, char c) { if (!dst || !off || cap == 0 || *off + 1 >= cap) return; dst[*off] = c; @@ -31,11 +37,13 @@ static void append_char(char* dst, size_t cap, size_t* off, char c) { dst[*off] = 0; } +// Appends str. static void append_str(char* dst, size_t cap, size_t* off, const char* s) { if (!s) return; while (*s) append_char(dst, cap, off, *s++); } +// Appends u8. static void append_u8(char* dst, size_t cap, size_t* off, uint8_t v) { if (v >= 100) { append_char(dst, cap, off, (char)('0' + v / 100)); @@ -50,6 +58,7 @@ static void append_u8(char* dst, size_t cap, size_t* off, uint8_t v) { } } +// Implements the format ipv4 operation. static void format_ipv4(char* dst, size_t cap, const uint8_t ip[4]) { size_t off = 0; if (!dst || cap == 0) return; @@ -60,6 +69,7 @@ static void format_ipv4(char* dst, size_t cap, const uint8_t ip[4]) { append_u8(dst, cap, &off, ip[3]); } +// Parses u8. static bool parse_u8(const char** p, uint8_t* out) { const char* s = *p; uint32_t v = 0; @@ -76,6 +86,7 @@ static bool parse_u8(const char** p, uint8_t* out) { return true; } +// Parses ipv4. static bool parse_ipv4(const char* s, uint8_t ip[4]) { if (!s || !ip) return false; for (int i = 0; i < 4; i++) { @@ -88,6 +99,7 @@ static bool parse_ipv4(const char* s, uint8_t ip[4]) { return *s == 0; } +// Implements the next token operation. static const char* next_token(const char* s, char* out, size_t outSize) { if (!s || !out || outSize == 0) return NULL; while (*s == ' ' || *s == '\t') s++; @@ -102,11 +114,13 @@ static const char* next_token(const char* s, char* out, size_t outSize) { return s; } +// Implements the usage operation. static void usage(void) { print("usage: httpget.exe [host-or-ipv4] [path]\n"); print("default: httpget.exe 10.0.2.2 /\n"); } +// Implements the resolve host operation. static uint32_t resolve_host(const char* host, uint8_t ip[4]) { if (parse_ipv4(host, ip)) return SYS_STATUS_SUCCESS; @@ -134,6 +148,7 @@ static uint32_t resolve_host(const char* host, uint8_t ip[4]) { return SYS_STATUS_SUCCESS; } +// Runs the requested operation. int main(void) { uint8_t ip[4] = {10, 0, 2, 2}; char host[256]; diff --git a/code/user/apps/ping/ping.c b/code/user/apps/ping/ping.c index 3792b03..d56fde6 100644 --- a/code/user/apps/ping/ping.c +++ b/code/user/apps/ping/ping.c @@ -1,3 +1,5 @@ +// User application entry points for ping. + #include #include #include @@ -11,15 +13,18 @@ #define PING_PAYLOAD_BYTES 32u #define PING_PACKET_BYTES (8u + PING_PAYLOAD_BYTES) +// Prints the requested operation. static void print(const char* s) { if (s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); } } +// Prints char. static void print_char(char c) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) }; SysWriteConsole(&req); } +// Prints u64. static void print_u64(uint64_t v) { char buf[32]; int n = 0; @@ -31,11 +36,13 @@ static void print_u64(uint64_t v) { while (n > 0) print_char(buf[--n]); } +// Prints ipv4. static void print_ipv4(const uint8_t ip[4]) { print_u64(ip[0]); print("."); print_u64(ip[1]); print("."); print_u64(ip[2]); print("."); print_u64(ip[3]); } +// Prints rtt us. static void print_rtt_us(uint64_t us) { uint64_t whole = us / US_PER_MS; uint64_t frac = us % US_PER_MS; @@ -46,6 +53,7 @@ static void print_rtt_us(uint64_t us) { print_u64(frac); } +// Implements the format ipv4 operation. static void format_ipv4(char* out, size_t outSize, const uint8_t ip[4]) { if (!out || outSize == 0) return; size_t off = 0; @@ -62,6 +70,7 @@ static void format_ipv4(char* out, size_t outSize, const uint8_t ip[4]) { out[off < outSize ? off : outSize - 1] = 0; } +// Implements the next token operation. static const char* next_token(const char* s, char* out, size_t outSize) { if (!s || !out || outSize == 0) return NULL; while (*s == ' ' || *s == '\t') s++; @@ -76,6 +85,7 @@ static const char* next_token(const char* s, char* out, size_t outSize) { return s; } +// Parses u8. static bool parse_u8(const char** p, uint8_t* out) { const char* s = *p; uint32_t v = 0; @@ -92,6 +102,7 @@ static bool parse_u8(const char** p, uint8_t* out) { return true; } +// Parses ipv4. static bool parse_ipv4(const char* s, uint8_t ip[4]) { if (!s || !ip) return false; for (int i = 0; i < 4; i++) { @@ -104,6 +115,7 @@ static bool parse_ipv4(const char* s, uint8_t ip[4]) { return *s == 0; } +// Parses u32. static bool parse_u32(const char* s, uint32_t* out) { if (!s || !*s || !out) return false; uint32_t v = 0; @@ -118,6 +130,7 @@ static bool parse_u32(const char* s, uint32_t* out) { return true; } +// Implements the resolve host operation. static uint32_t resolve_host(const char* host, uint8_t ip[4]) { if (parse_ipv4(host, ip)) return SYS_STATUS_SUCCESS; @@ -145,6 +158,7 @@ static uint32_t resolve_host(const char* host, uint8_t ip[4]) { return SYS_STATUS_SUCCESS; } +// Implements the icmp checksum operation. static uint16_t icmp_checksum(const uint8_t* data, size_t length) { uint32_t sum = 0; while (length >= 2) { @@ -160,6 +174,7 @@ static uint16_t icmp_checksum(const uint8_t* data, size_t length) { return (uint16_t)(~sum & 0xFFFFu); } +// Creates echo request. static void make_echo_request(uint8_t packet[PING_PACKET_BYTES], uint16_t ident, uint16_t seq) { memset(packet, 0, PING_PACKET_BYTES); packet[0] = 8; // echo request @@ -207,11 +222,13 @@ static bool parse_echo_reply(const uint8_t* buf, size_t len, uint16_t ident, uin return false; } +// Implements the usage operation. static void usage(void) { print("usage: apps/ping.exe [host-or-ipv4] [count]\n"); print("default: apps/ping.exe 10.0.2.2 4\n"); } +// Runs the requested operation. int main(void) { char host[256]; char tok[256]; diff --git a/code/user/apps/resolve/resolve.c b/code/user/apps/resolve/resolve.c index 0009033..26a2565 100644 --- a/code/user/apps/resolve/resolve.c +++ b/code/user/apps/resolve/resolve.c @@ -1,17 +1,22 @@ +// User application entry points for resolve. + #include #include #include #include +// Prints the requested operation. static void print(const char* s) { if (s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); } } +// Prints char. static void print_char(char c) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) }; SysWriteConsole(&req); } +// Prints u64. static void print_u64(uint64_t v) { char buf[32]; int n = 0; @@ -23,6 +28,7 @@ static void print_u64(uint64_t v) { while (n > 0) print_char(buf[--n]); } +// Implements the next token operation. static const char* next_token(const char* s, char* out, size_t outSize) { if (!s || !out || outSize == 0) return NULL; while (*s == ' ' || *s == '\t') s++; @@ -37,11 +43,13 @@ static const char* next_token(const char* s, char* out, size_t outSize) { return s; } +// Prints ipv4. static void print_ipv4(const uint8_t ip[4]) { print_u64(ip[0]); print("."); print_u64(ip[1]); print("."); print_u64(ip[2]); print("."); print_u64(ip[3]); } +// Runs the requested operation. int main(void) { char name[256]; const char* cmd = SysGetPeb()->CommandLine.Data; diff --git a/code/user/apps/shell_native/shell_native.c b/code/user/apps/shell_native/shell_native.c index 0d2324b..5d638cb 100644 --- a/code/user/apps/shell_native/shell_native.c +++ b/code/user/apps/shell_native/shell_native.c @@ -1,3 +1,5 @@ +// User application entry points for shell_native. + #include #include #include @@ -7,41 +9,46 @@ #define MAX_CMD 256 #define MAX_PROCS 64 // Maximum number of processes we will fetch at once -// --------------------------------------------------------------------------- -// Output helpers -// --------------------------------------------------------------------------- +// Output helpers. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); } +// Opens file. static uint32_t open_file(const char* path, uint32_t* handleOut) { SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut }; return SysOpenFile(&req); } +// Creates file. static uint32_t create_file(const char* path, uint32_t* handleOut) { SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut }; return SysCreateFile(&req); } +// Opens dir. static uint32_t open_dir(const char* path, uint32_t* handleOut) { SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut }; return SysOpenDir(&req); } +// Updates cwd. static uint32_t set_cwd(const char* path) { SYS_PATH_REQUEST req = { SysSvFromCstr(path) }; return SysSetCwd(&req); } +// Releases file. static uint32_t delete_file(const char* path) { SYS_PATH_REQUEST req = { SysSvFromCstr(path) }; return SysDeleteFile(&req); } +// Creates process. static uint32_t create_process(const char* path, uint32_t* handleOut, const char* cmdline) { SYS_CREATE_PROCESS_REQUEST req = { SysSvFromCstr(path), SysSvFromCstr(cmdline), handleOut }; return SysCreateProcess(&req); } +// Prints u Int. static void printUInt(uint32_t n) { char buf[12]; int i = 0; if (n == 0) { print("0"); return; } @@ -49,11 +56,13 @@ static void printUInt(uint32_t n) { while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); } } +// Prints int. static void printInt(int32_t n) { if (n < 0) { print("-"); printUInt((uint32_t)-(n + 1) + 1); } else { printUInt((uint32_t)n); } } +// Prints u Int64. static void printUInt64(uint64_t n) { if (n == 0) { print("0"); return; } char buf[20]; int i = 0; @@ -61,34 +70,40 @@ static void printUInt64(uint64_t n) { while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); } } +// Implements the u64 Digits operation. static uint32_t u64Digits(uint64_t n) { uint32_t digits = 1; while (n >= 10u) { n /= 10u; digits++; } return digits; } +// Prints spaces. static void printSpaces(size_t count) { while (count--) print(" "); } +// Prints u Int Width. static void printUIntWidth(uint32_t n, size_t width) { uint32_t digits = u64Digits(n); if (width > digits) printSpaces(width - digits); printUInt(n); } +// Prints u Int Zero Width. static void printUIntZeroWidth(uint32_t n, size_t width) { uint32_t digits = u64Digits(n); while (width > digits) { print("0"); width--; } printUInt(n); } +// Prints u Int64 Width. static void printUInt64Width(uint64_t n, size_t width) { uint32_t digits = u64Digits(n); if (width > digits) printSpaces(width - digits); printUInt64(n); } +// Prints hex32. static void printHex32(uint32_t v) { static const char hex[] = "0123456789abcdef"; char buf[9]; @@ -100,6 +115,7 @@ static void printHex32(uint32_t v) { print(buf); } +// Prints dir Time. static void printDirTime(const SYS_SYSTEM_TIME* t) { if (!t || !(t->Flags & SYS_TIME_FLAG_VALID)) { print("---- -- -- --:-- "); @@ -117,15 +133,14 @@ static void printDirTime(const SYS_SYSTEM_TIME* t) { print(" "); } +// Prints string Width. static void printStringWidth(const char* s, size_t width) { size_t len = s ? strlen(s) : 0; if (s) print(s); if (width > len) printSpaces(width - len); } -// --------------------------------------------------------------------------- -// Line editor -// --------------------------------------------------------------------------- +// Line editor. static void readLine(char* buf, int len) { int pos = 0; while (true) { @@ -139,6 +154,7 @@ static void readLine(char* buf, int len) { buf[pos] = '\0'; } +// Implements the trim operation. static char* trim(char* s) { while (*s == ' ') s++; int len = (int)strlen(s); @@ -147,9 +163,7 @@ static char* trim(char* s) { return s; } -// --------------------------------------------------------------------------- -// Built-in commands -// --------------------------------------------------------------------------- +// Built-in commands. static void cmd_help() { print("Available commands:\n" " help - Show this list\n" @@ -167,17 +181,20 @@ static void cmd_help() { " exit - Close the shell\n"); } +// Prints size Ki B. static void printSizeKiB(uint64_t bytes) { printUInt64(bytes / 1024u); print(" KiB"); } +// Prints pages Ki B. static void printPagesKiB(uint64_t pages) { printUInt64(pages * 4u); print(" KiB"); } +// Prints cpu Flags. static void printCpuFlags(uint32_t flags) { if (flags & SYS_CPU_FLAG_BSP) print("bsp "); if (flags & SYS_CPU_FLAG_ONLINE) print("online "); @@ -187,6 +204,7 @@ static void printCpuFlags(uint32_t flags) { if (flags & SYS_CPU_FLAG_PRESENT) print("present "); } +// Implements the cmd stats operation. static void cmd_stats(void) { SYS_SCHEDULER_STATS sched; SYS_PMM_STATS pmm; @@ -263,6 +281,7 @@ static void cmd_stats(void) { } +// Implements the cmd time operation. static void cmd_time(void) { SYS_SYSTEM_TIME t; uint32_t status = SysGetSystemTime(&t); @@ -290,6 +309,7 @@ static void cmd_time(void) { print("\n"); } +// Prints display Caps. static void printDisplayCaps(uint32_t caps) { bool any = false; if (caps & DISPLAY_CAP_FRAMEBUFFER) { print("framebuffer"); any = true; } @@ -303,6 +323,7 @@ static void printDisplayCaps(uint32_t caps) { if (!any) print("none"); } +// Prints display Stats. static void printDisplayStats(const char* title, const DISPLAY_STATS* st) { print(title); print(":\n"); print(" blit: "); printUInt64(st->BlitCount); print("\n"); @@ -318,6 +339,7 @@ static void printDisplayStats(const char* title, const DISPLAY_STATS* st) { print(" hide="); printUInt64(st->CursorHideCount); print("\n"); } +// Implements the cmd display operation. static void cmd_display(void) { SYS_DISPLAY_INFO info; uint32_t status = SysQueryDisplayInfo(&info); @@ -338,6 +360,7 @@ static void cmd_display(void) { printDisplayStats("Provider counters", &info.DeviceStats); } +// Implements the cmd mem operation. static void cmd_mem(void) { SYS_MEMORY_STATUS st; if (SysGetMemoryStatus(&st) != 0) { @@ -355,6 +378,7 @@ static void cmd_mem(void) { print("\n"); } +// Processes state Name. static const char* processStateName(uint32_t state) { switch (state) { case SYS_PROCESS_STATE_RUNNING: return "run"; @@ -364,6 +388,7 @@ static const char* processStateName(uint32_t state) { } } +// Implements the cmd ps operation. static void cmd_ps(void) { SYS_PROCESS_INFO procs[MAX_PROCS]; size_t count = 0; @@ -424,6 +449,7 @@ static void cmd_ps(void) { } } +// Implements the cmd write operation. static void cmd_write(const char* args) { char filename[MAX_CMD]; int i = 0; while (args[i] != ' ' && args[i] != '\0' && i < MAX_CMD - 1) { @@ -439,6 +465,7 @@ static void cmd_write(const char* args) { print("File written successfully.\n"); } +// Implements the cmd dir operation. static void cmd_dir(const char* path) { uint32_t hDir; const char* target = (path && *path != '\0') ? path : "."; @@ -452,7 +479,7 @@ static void cmd_dir(const char* path) { while (SysReadDir(hDir, &ke) == 0) { printDirTime(&ke.LastWriteTime); - // Corrected Attribute Check: 0x10 is the Directory bit in FAT + // Corrected Attribute Check: 0x10 is the Directory bit in FAT. if (ke.Attr & 0x10) { print(" "); } else { @@ -461,7 +488,7 @@ static void cmd_dir(const char* path) { print(ke.Name); - // Optional: print file size for non-directories + // Optional: print file size for non-directories. if (!(ke.Attr & 0x10)) { print(" ("); printUInt(ke.FileSize); @@ -473,6 +500,7 @@ static void cmd_dir(const char* path) { SysCloseHandle(hDir); } +// Implements the cmd type operation. static void cmd_type(const char* filename) { uint32_t hFile; if (open_file(filename, &hFile) != 0) { print("type: cannot open file\n"); return; } @@ -484,6 +512,7 @@ static void cmd_type(const char* filename) { } +// Implements the extract Program Path operation. static bool extractProgramPath(const char* cmdline, char* out, size_t outSize) { if (!cmdline || !out || outSize == 0) return false; @@ -504,24 +533,22 @@ static bool extractProgramPath(const char* cmdline, char* out, size_t outSize) { return pos != 0; } -// --------------------------------------------------------------------------- -// Run one command -// --------------------------------------------------------------------------- +// Run one command. static int runCommand(const char* cmd) { if (!cmd || *cmd == '\0') return 0; if (strcmp(cmd, "exit") == 0) return 1; if (strcmp(cmd, "help") == 0) { cmd_help(); return 0; } if (strcmp(cmd, "clear") == 0) { SysClearScreen(0x012456); return 0; } if (strncmp(cmd, "crash", 5) == 0) { - // Check the sub-option trailing "crash " (offset 6) + // Check the sub-option trailing "crash " (offset 6). if (strcmp(cmd + 6, "void") == 0) { - // Jumping into the void + // Jumping into the void. void (*invalid_func)(void) = NULL; invalid_func(); return 0; } else if (strcmp(cmd + 6, "noncanonical") == 0) { - // Non-canonical pointer dereference + // Non-canonical pointer dereference. volatile int *ptr = (volatile int*)0x4242424242424242ULL; *ptr = 1337; return 0; @@ -531,21 +558,21 @@ static int runCommand(const char* cmd) { return 0; } else if (strcmp(cmd + 6, "nx") == 0) { - // NX / DEP Violation + // NX / DEP Violation. unsigned char code[] = { 0xC3 }; void (*execute_stack)(void) = (void (*)(void))code; execute_stack(); return 0; } else if (strcmp(cmd + 6, "divzero") == 0) { - // Division by zero + // Division by zero. volatile int zero = 0; volatile int result = 1 / zero; (void)result; return 0; } else { - // Default fallback if just "crash" or an unknown sub-option is passed + // Default fallback if just "crash" or an unknown sub-option is passed. *(volatile int*)0 = 42; return 0; } @@ -574,6 +601,7 @@ static int runCommand(const char* cmd) { return 0; } +// Runs the requested operation. int main(void) { const char* cmdline = SysGetPeb()->CommandLine.Data; char lineBuf[MAX_CMD]; diff --git a/code/user/apps/shell_posix/shell_posix.c b/code/user/apps/shell_posix/shell_posix.c index 52235c9..2762363 100644 --- a/code/user/apps/shell_posix/shell_posix.c +++ b/code/user/apps/shell_posix/shell_posix.c @@ -1,3 +1,5 @@ +// User application entry points for shell_posix. + #include #include #include @@ -28,8 +30,10 @@ extern void PosixFdInit(void); static int hIn = 0; static int hOut = 1; +// Prints the requested operation. static void print(const char* s) { write(hOut, s, strlen(s)); } +// Prints u Int. static void printUInt(uint32_t n) { char buf[12]; int i = 0; if (n == 0) { print("0"); return; } @@ -37,11 +41,13 @@ static void printUInt(uint32_t n) { while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); } } +// Prints int. static void printInt(int32_t n) { if (n < 0) { print("-"); n = -n; } printUInt((uint32_t)n); } +// Returns line. static void readLine(char* buf, int len) { int pos = 0; while (true) { @@ -55,6 +61,7 @@ static void readLine(char* buf, int len) { } +// Implements the split Command Line operation. static int splitCommandLine(char* line, char** argv, int maxArgv) { int argc = 0; char* p = line; @@ -79,6 +86,7 @@ static int splitCommandLine(char* line, char** argv, int maxArgv) { return argc; } +// Implements the trim operation. static char* trim(char* s) { while (*s == ' ') s++; int len = (int)strlen(s); @@ -87,6 +95,7 @@ static char* trim(char* s) { return s; } +// Implements the cmd help operation. static void cmd_help() { print("Available commands:\n" " help - Show this list\n" @@ -99,6 +108,7 @@ static void cmd_help() { " exit - Close the shell\n"); } +// Implements the cmd write operation. static void cmd_write(const char* args) { char filename[MAX_CMD]; int i = 0; while (args[i] != ' ' && args[i] != '\0' && i < MAX_CMD - 1) { @@ -113,6 +123,7 @@ static void cmd_write(const char* args) { print("File written successfully.\n"); } +// Implements the cmd dir operation. static void cmd_dir(const char* path) { const char* target = (path && *path != '\0') ? path : "."; DIR* d = opendir(target); @@ -125,6 +136,7 @@ static void cmd_dir(const char* path) { closedir(d); } +// Implements the cmd type operation. static void cmd_type(const char* filename) { int fd = open(filename, 0); // O_RDONLY if (fd < 0) { print("type: cannot open file\n"); return; } @@ -133,6 +145,7 @@ static void cmd_type(const char* filename) { close(fd); print("\n"); } +// Runs command. static int runCommand(const char* cmd) { if (!cmd || *cmd == '\0') return 0; if (strcmp(cmd, "exit") == 0) return 1; @@ -162,6 +175,7 @@ static int runCommand(const char* cmd) { return 0; } +// Runs the requested operation. int main(void) { PosixFdInit(); diff --git a/code/user/apps/shell_win32/shell_win32.c b/code/user/apps/shell_win32/shell_win32.c index a0aaecb..3f3c017 100644 --- a/code/user/apps/shell_win32/shell_win32.c +++ b/code/user/apps/shell_win32/shell_win32.c @@ -1,3 +1,5 @@ +// User application entry points for shell_win32. + #include #include #include @@ -8,16 +10,17 @@ static HANDLE hIn = INVALID_HANDLE_VALUE; static HANDLE hOut = INVALID_HANDLE_VALUE; -// External/Custom API +// External/Custom API. BOOL ClearConsoleScreenBuffer(HANDLE hConsole); -// --- Output Helpers --- +// --- Output Helpers ---. static void print(const char* s) { DWORD written; if (hOut != INVALID_HANDLE_VALUE) WriteConsoleA(hOut, s, (DWORD)strlen(s), &written, 0); else OutputDebugStringA(s); } +// Prints u Int. static void printUInt(uint32_t n) { char buf[12]; int i = 0; if (n == 0) { print("0"); return; } @@ -25,12 +28,13 @@ static void printUInt(uint32_t n) { while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); } } +// Prints int. static void printInt(int32_t n) { if (n < 0) { print("-"); n = -n; } printUInt((uint32_t)n); } -// --- Line Editor --- +// --- Line Editor ---. static void readLine(char* buf, int len) { int pos = 0; while (true) { @@ -49,6 +53,7 @@ static void readLine(char* buf, int len) { buf[pos] = '\0'; } +// Implements the trim operation. static char* trim(char* s) { while (*s == ' ') s++; int len = (int)strlen(s); @@ -57,7 +62,7 @@ static char* trim(char* s) { return s; } -// --- Built-in Commands --- +// --- Built-in Commands ---. static void cmd_help() { print("Available commands:\n" " help - Show this list\n" @@ -70,6 +75,7 @@ static void cmd_help() { " exit - Close the shell\n"); } +// Implements the cmd write operation. static void cmd_write(const char* args) { char filename[MAX_PATH]; int i = 0; while (args[i] != ' ' && args[i] != '\0' && i < MAX_PATH - 1) { @@ -88,6 +94,7 @@ static void cmd_write(const char* args) { print("File written successfully.\n"); } +// Implements the cmd dir operation. static void cmd_dir(const char* path) { WIN32_FIND_DATAA fd; char search_path[MAX_PATH]; @@ -107,6 +114,7 @@ static void cmd_dir(const char* path) { FindClose(hFind); } +// Implements the cmd type operation. static void cmd_type(const char* filename) { HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (hFile == INVALID_HANDLE_VALUE) { print("type: cannot open file\n"); return; } @@ -117,6 +125,7 @@ static void cmd_type(const char* filename) { CloseHandle(hFile); print("\n"); } +// Runs command. static int runCommand(const char* cmd) { if (!cmd || *cmd == '\0') return 0; if (strcmp(cmd, "exit") == 0) return 1; @@ -145,6 +154,7 @@ static int runCommand(const char* cmd) { return 0; } +// Runs the requested operation. int main(void) { hIn = GetStdHandle(STD_INPUT_HANDLE); hOut = GetStdHandle(STD_OUTPUT_HANDLE); diff --git a/code/user/apps/tcpserve/tcpserve.c b/code/user/apps/tcpserve/tcpserve.c index 45e0936..640ef9d 100644 --- a/code/user/apps/tcpserve/tcpserve.c +++ b/code/user/apps/tcpserve/tcpserve.c @@ -1,18 +1,23 @@ +// User application entry points for tcpserve. + #include #include #include #include #include +// Prints the requested operation. static void print(const char* s) { if (s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); } } +// Prints char. static void print_char(char c) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) }; SysWriteConsole(&req); } +// Prints u64. static void print_u64(uint64_t v) { char buf[32]; int n = 0; @@ -24,11 +29,13 @@ static void print_u64(uint64_t v) { while (n > 0) print_char(buf[--n]); } +// Prints ipv4. static void print_ipv4(const uint8_t ip[4]) { print_u64(ip[0]); print("."); print_u64(ip[1]); print("."); print_u64(ip[2]); print("."); print_u64(ip[3]); } +// Implements the next token operation. static const char* next_token(const char* s, char* out, size_t outSize) { if (!s || !out || outSize == 0) return NULL; while (*s == ' ' || *s == '\t') s++; @@ -43,6 +50,7 @@ static const char* next_token(const char* s, char* out, size_t outSize) { return s; } +// Parses port. static bool parse_port(const char* s, uint16_t* out) { if (!s || !*s || !out) return false; uint32_t v = 0; @@ -56,11 +64,13 @@ static bool parse_port(const char* s, uint16_t* out) { return true; } +// Implements the usage operation. static void usage(void) { print("usage: tcpserve.exe [port]\n"); print("default: tcpserve.exe 8080\n"); } +// Runs the requested operation. int main(void) { uint16_t port = 8080; diff --git a/code/user/apps/udp/udp.c b/code/user/apps/udp/udp.c index 5bb4eb8..13f15b0 100644 --- a/code/user/apps/udp/udp.c +++ b/code/user/apps/udp/udp.c @@ -1,18 +1,23 @@ +// User application entry points for udp. + #include #include #include #include #include +// Prints the requested operation. static void print(const char* s) { if (s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); } } +// Prints char. static void print_char(char c) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) }; SysWriteConsole(&req); } +// Prints u64. static void print_u64(uint64_t v) { char buf[32]; int n = 0; @@ -24,11 +29,13 @@ static void print_u64(uint64_t v) { while (n > 0) print_char(buf[--n]); } +// Prints ipv4. static void print_ipv4(const uint8_t ip[4]) { print_u64(ip[0]); print("."); print_u64(ip[1]); print("."); print_u64(ip[2]); print("."); print_u64(ip[3]); } +// Implements the next token operation. static const char* next_token(const char* s, char* out, size_t outSize) { if (!s || !out || outSize == 0) return NULL; while (*s == ' ' || *s == '\t') s++; @@ -43,6 +50,7 @@ static const char* next_token(const char* s, char* out, size_t outSize) { return s; } +// Parses u8. static bool parse_u8(const char** p, uint8_t* out) { const char* s = *p; uint32_t v = 0; @@ -59,6 +67,7 @@ static bool parse_u8(const char** p, uint8_t* out) { return true; } +// Parses ipv4. static bool parse_ipv4(const char* s, uint8_t ip[4]) { if (!s || !ip) return false; for (int i = 0; i < 4; i++) { @@ -71,6 +80,7 @@ static bool parse_ipv4(const char* s, uint8_t ip[4]) { return *s == 0; } +// Parses port. static bool parse_port(const char* s, uint16_t* out) { if (!s || !*s || !out) return false; uint32_t v = 0; @@ -84,6 +94,7 @@ static bool parse_port(const char* s, uint16_t* out) { return true; } +// Implements the usage operation. static void usage(void) { print("usage:\n"); print(" udp.exe send [message]\n"); @@ -93,6 +104,7 @@ static void usage(void) { print(" udp.exe listen 9999\n"); } +// Runs send. static int run_send(const char* cmd) { char tok[256]; uint8_t ip[4]; @@ -103,7 +115,7 @@ static int run_send(const char* cmd) { cmd = next_token(cmd, tok, sizeof(tok)); if (!tok[0] || !parse_port(tok, &port)) { usage(); return 1; } - // Skip leading whitespace, then take the entire remaining command line + // Skip leading whitespace, then take the entire remaining command line. if (cmd) { while (*cmd == ' ' || *cmd == '\t') { cmd++; @@ -151,6 +163,7 @@ static int run_send(const char* cmd) { return 0; } +// Runs listen. static int run_listen(const char* cmd) { char tok[64]; uint16_t port = 0; @@ -211,6 +224,7 @@ static int run_listen(const char* cmd) { return 0; } +// Runs the requested operation. int main(void) { const char* cmd = SysGetPeb()->CommandLine.Data; char tok[64]; diff --git a/code/user/apps/video/video.c b/code/user/apps/video/video.c index cf16403..eb49abf 100644 --- a/code/user/apps/video/video.c +++ b/code/user/apps/video/video.c @@ -1,3 +1,5 @@ +// User application entry points for video. + #include #include #include @@ -5,6 +7,7 @@ #include #include "bink.h" +// Implements the command Line Second Token operation. static const char* commandLineSecondToken(const char* cmdline, char* out, size_t outSize) { if (!out || outSize == 0) return "video.bk2"; strcpy(out, "video.bk2"); @@ -37,6 +40,7 @@ static const char* commandLineSecondToken(const char* cmdline, char* out, size_t return out; } +// Runs the requested operation. int main(void) { const char* cmdline = GetCommandLineA(); char videoPath[260]; @@ -92,7 +96,7 @@ int main(void) { ExitProcess(1); } - // Prepare the Win32 BITMAPINFO structure + // Prepare the Win32 BITMAPINFO structure. BITMAPINFO bmi; memset(&bmi, 0, sizeof(bmi)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); @@ -121,7 +125,7 @@ int main(void) { // Welcome to the GDI pipeline! PAINTSTRUCT ps; - // Using NULL/0 as the HWND since we don't have a real window handle yet + // Using NULL/0 as the HWND since we don't have a real window handle yet. HDC hdc = BeginPaint((HWND)0, &ps); StretchDIBits( diff --git a/code/user/personalities/posix/posix.h b/code/user/personalities/posix/posix.h index 90548b1..c3cfdab 100644 --- a/code/user/personalities/posix/posix.h +++ b/code/user/personalities/posix/posix.h @@ -1,3 +1,5 @@ +// POSIX compatibility support for posix. + #pragma once // posix.h - POSIX type and constant definitions for posix.dll // Covers just what open/read/write/close/lseek/spawn/pthread/chdir need. @@ -6,9 +8,7 @@ #include #include -// --------------------------------------------------------------------------- -// errno -// --------------------------------------------------------------------------- +// errno. #ifdef errno #undef errno #endif @@ -59,9 +59,7 @@ extern int errno; // defined in posix_fd.c; single global in v1 #define ETIMEDOUT 116 #define ECONNRESET 104 -// --------------------------------------------------------------------------- -// open() flags -// --------------------------------------------------------------------------- +// open() flags. #define O_RDONLY 0x0000 #define O_WRONLY 0x0001 #define O_RDWR 0x0002 @@ -69,25 +67,19 @@ extern int errno; // defined in posix_fd.c; single global in v1 #define O_TRUNC 0x0200 #define O_APPEND 0x0400 -// --------------------------------------------------------------------------- -// lseek() whence -// --------------------------------------------------------------------------- +// lseek() whence. #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 -// --------------------------------------------------------------------------- -// Scalar types -// --------------------------------------------------------------------------- +// Scalar types. typedef int32_t pid_t; typedef int32_t off_t; typedef uint32_t mode_t; typedef int64_t ssize_t; -// --------------------------------------------------------------------------- -// Sockets -// --------------------------------------------------------------------------- +// Sockets. typedef uint16_t sa_family_t; typedef uint16_t in_port_t; typedef uint32_t in_addr_t; @@ -195,25 +187,19 @@ __declspec(dllexport) struct hostent* gethostbyname(const char* name); __declspec(dllexport) int getaddrinfo(const char* node, const char* service, const struct addrinfo* hints, struct addrinfo** res); __declspec(dllexport) void freeaddrinfo(struct addrinfo* res); -// --------------------------------------------------------------------------- -// pthread types -// --------------------------------------------------------------------------- +// pthread types. typedef struct { uint32_t Tid; } pthread_t; typedef struct { uint32_t Handle; } pthread_mutex_t; typedef void* pthread_attr_t; // unused in v1 typedef void* pthread_mutexattr_t; -// --------------------------------------------------------------------------- -// posix_spawn types (file_actions and attrp both ignored in v1) -// --------------------------------------------------------------------------- +// posix_spawn types (file_actions and attrp both ignored in v1). typedef void* posix_spawn_file_actions_t; typedef void* posix_spawnattr_t; __declspec(dllexport) const char* posix_get_command_line(void); -// --------------------------------------------------------------------------- -// dirent (used by posix_dir.c) -// --------------------------------------------------------------------------- +// dirent (used by posix_dir.c). #define NAME_MAX 259 typedef struct dirent { diff --git a/code/user/personalities/posix/posix_dir.c b/code/user/personalities/posix/posix_dir.c index b573d98..fa13d17 100644 --- a/code/user/personalities/posix/posix_dir.c +++ b/code/user/personalities/posix/posix_dir.c @@ -1,4 +1,5 @@ -// posix_dir.c - chdir, getcwd, opendir, readdir, closedir +// POSIX compatibility support for posix dir. + #include #include #include @@ -10,6 +11,7 @@ typedef SYS_DIR_ENTRY KDIR_ENTRY; #define KATTR_DIR 0x10 +// Implements the chdir operation. __declspec(dllexport) int chdir(const char* path) { char native[512]; PosixTranslatePath(path, native, sizeof(native)); @@ -19,6 +21,7 @@ __declspec(dllexport) int chdir(const char* path) { return 0; } +// Implements the getcwd operation. __declspec(dllexport) char* getcwd(char* buf, size_t size) { if (!buf || size == 0) { errno = EINVAL; return (char*)0; } char native[512]; @@ -31,6 +34,7 @@ __declspec(dllexport) char* getcwd(char* buf, size_t size) { return buf; } +// Implements the opendir operation. __declspec(dllexport) DIR* opendir(const char* path) { char native[512]; PosixTranslatePath(path, native, sizeof(native)); @@ -47,6 +51,7 @@ __declspec(dllexport) DIR* opendir(const char* path) { return d; } +// Implements the readdir operation. __declspec(dllexport) struct dirent* readdir(DIR* d) { if (!d) { errno = EBADF; return (struct dirent*)0; } KDIR_ENTRY ke; @@ -62,6 +67,7 @@ __declspec(dllexport) struct dirent* readdir(DIR* d) { return &d->Current; } +// Implements the closedir operation. __declspec(dllexport) int closedir(DIR* d) { if (!d) { errno = EBADF; return -1; } SysCloseHandle(d->KHandle); diff --git a/code/user/personalities/posix/posix_fd.c b/code/user/personalities/posix/posix_fd.c index edcb148..763ca72 100644 --- a/code/user/personalities/posix/posix_fd.c +++ b/code/user/personalities/posix/posix_fd.c @@ -1,10 +1,12 @@ -// posix_fd.c - file descriptor table +// POSIX compatibility support for posix fd. + #include #include "posix.h" #include "posix_fd.h" int errno = 0; +// Implements the status To Errno operation. int PosixStatusToErrno(uint32_t s) { switch (s) { case 0x0000: return 0; // STATUS_SUCCESS @@ -26,6 +28,7 @@ int PosixStatusToErrno(uint32_t s) { static FD_ENTRY gFdTable[FD_TABLE_PIDS][FD_MAX]; +// Implements the fd Init operation. __declspec(dllexport) void PosixFdInit(void) { uint32_t pid = SysGetCurrentPid(); uint32_t slot = pid % FD_TABLE_PIDS; @@ -40,6 +43,7 @@ __declspec(dllexport) void PosixFdInit(void) { gFdTable[slot][2] = (FD_ENTRY){ FD_CONSOLE_W, 0, true }; } +// Implements the fd Alloc operation. __declspec(dllexport) int FdAlloc(uint32_t pid, FD_TYPE type, uint32_t khandle) { uint32_t slot = pid % FD_TABLE_PIDS; for (int fd = 3; fd < FD_MAX; fd++) { @@ -52,6 +56,7 @@ __declspec(dllexport) int FdAlloc(uint32_t pid, FD_TYPE type, uint32_t khandle) return -1; } +// Implements the fd Get operation. __declspec(dllexport) FD_ENTRY* FdGet(uint32_t pid, int fd) { if (fd < 0 || fd >= FD_MAX) { errno = EBADF; return (FD_ENTRY*)0; } uint32_t slot = pid % FD_TABLE_PIDS; @@ -60,6 +65,7 @@ __declspec(dllexport) FD_ENTRY* FdGet(uint32_t pid, int fd) { return e; } +// Implements the fd Free operation. __declspec(dllexport) void FdFree(uint32_t pid, int fd) { if (fd < 0 || fd >= FD_MAX) return; uint32_t slot = pid % FD_TABLE_PIDS; diff --git a/code/user/personalities/posix/posix_fd.h b/code/user/personalities/posix/posix_fd.h index 53fe94a..9ef343a 100644 --- a/code/user/personalities/posix/posix_fd.h +++ b/code/user/personalities/posix/posix_fd.h @@ -1,5 +1,7 @@ +// POSIX compatibility support for posix fd. + #pragma once -// posix_fd.h - file descriptor table (internal to posix.dll) +// posix_fd.h - file descriptor table (internal to posix.dll). #include #include diff --git a/code/user/personalities/posix/posix_io.c b/code/user/personalities/posix/posix_io.c index 5481883..6579da5 100644 --- a/code/user/personalities/posix/posix_io.c +++ b/code/user/personalities/posix/posix_io.c @@ -1,4 +1,5 @@ -// posix_io.c - open, read, write, close, lseek +// POSIX compatibility support for posix io. + #include #include #include @@ -6,14 +7,17 @@ #include "posix_fd.h" #include "posix_path.h" +// Implements the clearscreen operation. __declspec(dllexport) void clearscreen(void) { SysClearScreen(0x012456); } +// Implements the clearkeyboard operation. __declspec(dllexport) void clearkeyboard(void) { while (SysPollKeyboard()) (void)SysReadKeyboardChar(); } +// Opens the requested operation. __declspec(dllexport) int open(const char* path, int flags, ...) { char native[512]; const char* p = PosixTranslatePath(path, native, sizeof(native)); @@ -21,7 +25,7 @@ __declspec(dllexport) int open(const char* path, int flags, ...) { uint32_t pid = SysGetCurrentPid(); FD_TYPE type = FD_FILE; - // Synthetic devices + // Synthetic devices. if (strcmp(p, SYNTH_DEVNULL) == 0) { int fd = FdAlloc(pid, FD_DEVNULL, 0); return fd; @@ -53,6 +57,7 @@ __declspec(dllexport) int open(const char* path, int flags, ...) { return fd; } +// Returns the requested value. __declspec(dllexport) ssize_t read(int fd, void* buf, size_t count) { if (count == 0) return 0; uint32_t pid = SysGetCurrentPid(); @@ -92,6 +97,7 @@ __declspec(dllexport) ssize_t read(int fd, void* buf, size_t count) { } } +// Updates the requested value. __declspec(dllexport) ssize_t write(int fd, const void* buf, size_t count) { if (count == 0) return 0; uint32_t pid = SysGetCurrentPid(); @@ -125,6 +131,7 @@ __declspec(dllexport) ssize_t write(int fd, const void* buf, size_t count) { } } +// Releases the requested object. __declspec(dllexport) int close(int fd) { uint32_t pid = SysGetCurrentPid(); FD_ENTRY* e = FdGet(pid, fd); @@ -135,6 +142,7 @@ __declspec(dllexport) int close(int fd) { return 0; } +// Implements the unlink operation. __declspec(dllexport) int unlink(const char* path) { if (!path) { errno = EINVAL; return -1; } @@ -152,6 +160,7 @@ __declspec(dllexport) int unlink(const char* path) { return 0; } +// Implements the lseek operation. __declspec(dllexport) off_t lseek(int fd, off_t offset, int whence) { uint32_t pid = SysGetCurrentPid(); FD_ENTRY* e = FdGet(pid, fd); diff --git a/code/user/personalities/posix/posix_path.c b/code/user/personalities/posix/posix_path.c index db2b795..5231f86 100644 --- a/code/user/personalities/posix/posix_path.c +++ b/code/user/personalities/posix/posix_path.c @@ -1,12 +1,15 @@ -// posix_path.c - POSIX <-> native path translation +// POSIX compatibility support for posix path. + #include #include #include "posix_path.h" +// Implements the flip Slashes operation. static void FlipSlashes(char* s) { for (; *s; s++) if (*s == '/') *s = '\\'; } +// Checks whether drive Mount. static int IsDriveMount(const char* p) { return p && p[0] == '/' && p[1] >= '0' && p[1] <= '7' && (p[2] == '\0' || p[2] == '/'); @@ -50,6 +53,7 @@ const char* PosixTranslatePath(const char* in, char* out, size_t outSize) { return out; } +// Implements the native To Posix operation. void NativeToPosix(const char* in, char* out, size_t outSize) { if (!in || !out || outSize == 0) return; diff --git a/code/user/personalities/posix/posix_path.h b/code/user/personalities/posix/posix_path.h index 7ebc58f..795b7e0 100644 --- a/code/user/personalities/posix/posix_path.h +++ b/code/user/personalities/posix/posix_path.h @@ -1,5 +1,7 @@ +// POSIX compatibility support for posix path. + #pragma once -// posix_path.h - POSIX <-> native path translation +// posix_path.h - POSIX <-> native path translation. // SYNTHETIC sentinel returned from PosixTranslatePath for /dev/null and // /dev/zero; the caller must handle these before passing to any syscall. diff --git a/code/user/personalities/posix/posix_proc.c b/code/user/personalities/posix/posix_proc.c index 8f49db4..5c377fb 100644 --- a/code/user/personalities/posix/posix_proc.c +++ b/code/user/personalities/posix/posix_proc.c @@ -1,4 +1,5 @@ -// posix_proc.c - posix_spawn, waitpid, getpid +// POSIX compatibility support for posix proc. + #include #include #include @@ -8,18 +9,20 @@ static SYS_PEB* gProcessPeb = NULL; +// Implements the peb operation. static SYS_PEB* PosixPeb(void) { if (!gProcessPeb) gProcessPeb = SysGetPeb(); return gProcessPeb; } +// Implements the posix get command line operation. __declspec(dllexport) const char* posix_get_command_line(void) { SYS_PEB* peb = PosixPeb(); if (!peb || peb->Magic != SYS_PEB_MAGIC || !peb->CommandLine.Data) return ""; return peb->CommandLine.Data; } -// pid -> proc handle table (user-mode side, for waitpid) +// pid -> proc handle table (user-mode side, for waitpid). #define PROC_TABLE_SIZE 32 typedef struct { pid_t pid; @@ -29,6 +32,7 @@ typedef struct { static ProcEntry gProcTable[PROC_TABLE_SIZE]; +// Implements the proc Table Insert operation. static void ProcTableInsert(pid_t pid, uint32_t handle) { for (int i = 0; i < PROC_TABLE_SIZE; i++) { if (!gProcTable[i].used) { @@ -39,6 +43,7 @@ static void ProcTableInsert(pid_t pid, uint32_t handle) { SysCloseHandle(handle); } +// Implements the proc Table Find operation. static uint32_t ProcTableFind(pid_t pid) { for (int i = 0; i < PROC_TABLE_SIZE; i++) if (gProcTable[i].used && gProcTable[i].pid == pid) @@ -46,6 +51,7 @@ static uint32_t ProcTableFind(pid_t pid) { return 0; } +// Implements the proc Table Remove operation. static void ProcTableRemove(pid_t pid) { for (int i = 0; i < PROC_TABLE_SIZE; i++) if (gProcTable[i].used && gProcTable[i].pid == pid) @@ -72,9 +78,7 @@ static void BuildCmdline(char* const argv[], char* out, size_t outSize) { if (pos < outSize) out[pos] = '\0'; } -// --------------------------------------------------------------------------- -// POSIX API -// --------------------------------------------------------------------------- +// POSIX API. __declspec(dllexport) pid_t getpid(void) { return (pid_t)SysGetCurrentPid(); @@ -133,6 +137,7 @@ __declspec(dllexport) pid_t waitpid(pid_t pid, int* status, int options) { return pid; } +// Implements the exit operation. __declspec(dllexport) void exit(int status) { SysExitProcess(status); } diff --git a/code/user/personalities/posix/posix_socket.c b/code/user/personalities/posix/posix_socket.c index b8fd82c..ea426db 100644 --- a/code/user/personalities/posix/posix_socket.c +++ b/code/user/personalities/posix/posix_socket.c @@ -1,4 +1,5 @@ -// posix_socket.c - POSIX-ish socket wrappers over native Sys* sockets. +// POSIX compatibility support for posix socket. + #include #include #include @@ -7,10 +8,12 @@ #include "posix.h" #include "posix_fd.h" +// Implements the bswap16 operation. static uint16_t bswap16(uint16_t x) { return (uint16_t)((x << 8) | (x >> 8)); } +// Implements the bswap32 operation. static uint32_t bswap32(uint32_t x) { return ((x & 0x000000FFu) << 24) | ((x & 0x0000FF00u) << 8) | @@ -18,11 +21,16 @@ static uint32_t bswap32(uint32_t x) { ((x & 0xFF000000u) >> 24); } +// Implements the htons operation. __declspec(dllexport) uint16_t htons(uint16_t x) { return bswap16(x); } +// Implements the ntohs operation. __declspec(dllexport) uint16_t ntohs(uint16_t x) { return bswap16(x); } +// Implements the htonl operation. __declspec(dllexport) uint32_t htonl(uint32_t x) { return bswap32(x); } +// Implements the ntohl operation. __declspec(dllexport) uint32_t ntohl(uint32_t x) { return bswap32(x); } +// Parses byte. static int ParseByte(const char** p, uint8_t* out) { const char* s = *p; if (*s < '0' || *s > '9') return 0; @@ -37,6 +45,7 @@ static int ParseByte(const char** p, uint8_t* out) { return 1; } +// Parses ipv4 Bytes. static int ParseIpv4Bytes(const char* text, uint8_t out[4]) { const char* p = text; for (int i = 0; i < 4; i++) { @@ -49,6 +58,7 @@ static int ParseIpv4Bytes(const char* text, uint8_t out[4]) { return *p == '\0'; } +// Implements the inet addr operation. __declspec(dllexport) in_addr_t inet_addr(const char* text) { uint8_t b[4]; if (!text || !ParseIpv4Bytes(text, b)) return INADDR_NONE; @@ -58,6 +68,7 @@ __declspec(dllexport) in_addr_t inet_addr(const char* text) { return out; } +// Implements the inet ntoa operation. __declspec(dllexport) char* inet_ntoa(struct in_addr in) { static char buf[16]; const uint8_t* p = (const uint8_t*)&in.s_addr; @@ -74,6 +85,7 @@ __declspec(dllexport) char* inet_ntoa(struct in_addr in) { return buf; } +// Implements the sock Addr To Sys operation. static int SockAddrToSys(const struct sockaddr* addr, socklen_t addrlen, SYS_SOCKET_ADDRESS_IPV4* out) { if (!addr || !out || addrlen < sizeof(struct sockaddr_in)) { errno = EINVAL; return -1; } const struct sockaddr_in* in = (const struct sockaddr_in*)addr; @@ -90,6 +102,7 @@ static int SockAddrToSys(const struct sockaddr* addr, socklen_t addrlen, SYS_SOC return 0; } +// Implements the to Sock Addr operation. static void SysToSockAddr(const SYS_SOCKET_ADDRESS_IPV4* in, struct sockaddr* addr, socklen_t* addrlen) { if (!addr || !addrlen) return; if (*addrlen < sizeof(struct sockaddr_in)) { @@ -109,6 +122,7 @@ static void SysToSockAddr(const SYS_SOCKET_ADDRESS_IPV4* in, struct sockaddr* ad *addrlen = sizeof(struct sockaddr_in); } +// Implements the socket Fd Get operation. static FD_ENTRY* SocketFdGet(int fd) { FD_ENTRY* e = FdGet(SysGetCurrentPid(), fd); if (!e) return (FD_ENTRY*)0; @@ -116,6 +130,7 @@ static FD_ENTRY* SocketFdGet(int fd) { return e; } +// Implements the socket operation. __declspec(dllexport) int socket(int domain, int type, int protocol) { uint32_t kh = 0; uint32_t s = SysCreateSocket((uint32_t)domain, (uint32_t)type, (uint32_t)protocol, &kh); @@ -129,6 +144,7 @@ __declspec(dllexport) int socket(int domain, int type, int protocol) { return fd; } +// Implements the bind operation. __declspec(dllexport) int bind(int fd, const struct sockaddr* addr, socklen_t addrlen) { FD_ENTRY* e = SocketFdGet(fd); if (!e) return -1; @@ -139,6 +155,7 @@ __declspec(dllexport) int bind(int fd, const struct sockaddr* addr, socklen_t ad return 0; } +// Implements the listen operation. __declspec(dllexport) int listen(int fd, int backlog) { FD_ENTRY* e = SocketFdGet(fd); if (!e) return -1; @@ -147,6 +164,7 @@ __declspec(dllexport) int listen(int fd, int backlog) { return 0; } +// Implements the accept operation. __declspec(dllexport) int accept(int fd, struct sockaddr* addr, socklen_t* addrlen) { FD_ENTRY* e = SocketFdGet(fd); if (!e) return -1; @@ -167,6 +185,7 @@ __declspec(dllexport) int accept(int fd, struct sockaddr* addr, socklen_t* addrl return outfd; } +// Implements the connect operation. __declspec(dllexport) int connect(int fd, const struct sockaddr* addr, socklen_t addrlen) { FD_ENTRY* e = SocketFdGet(fd); if (!e) return -1; @@ -177,6 +196,7 @@ __declspec(dllexport) int connect(int fd, const struct sockaddr* addr, socklen_t return 0; } +// Implements the send operation. __declspec(dllexport) ssize_t send(int fd, const void* buf, size_t len, int flags) { FD_ENTRY* e = SocketFdGet(fd); if (!e) return -1; @@ -186,6 +206,7 @@ __declspec(dllexport) ssize_t send(int fd, const void* buf, size_t len, int flag return (ssize_t)sent; } +// Implements the recv operation. __declspec(dllexport) ssize_t recv(int fd, void* buf, size_t len, int flags) { FD_ENTRY* e = SocketFdGet(fd); if (!e) return -1; @@ -240,6 +261,7 @@ __declspec(dllexport) ssize_t recvfrom(int fd, void* buf, size_t len, int flags, return (ssize_t)got; } +// Implements the shutdown operation. __declspec(dllexport) int shutdown(int fd, int how) { FD_ENTRY* e = SocketFdGet(fd); if (!e) return -1; @@ -248,12 +270,14 @@ __declspec(dllexport) int shutdown(int fd, int how) { return 0; } +// Implements the timeval To Ms operation. static uint32_t TimevalToMs(const struct timeval* tv) { if (!tv) return 0; uint64_t ms = (uint64_t)tv->tv_sec * 1000u + (uint64_t)(tv->tv_usec / 1000); return ms > 0xFFFFFFFFu ? 0xFFFFFFFFu : (uint32_t)ms; } +// Implements the setsockopt operation. __declspec(dllexport) int setsockopt(int fd, int level, int optname, const void* optval, socklen_t optlen) { if (level != SOL_SOCKET || !optval) { errno = EINVAL; return -1; } FD_ENTRY* e = SocketFdGet(fd); @@ -285,6 +309,7 @@ __declspec(dllexport) int setsockopt(int fd, int level, int optname, const void* return 0; } +// Implements the getsockopt operation. __declspec(dllexport) int getsockopt(int fd, int level, int optname, void* optval, socklen_t* optlen) { if (level != SOL_SOCKET || !optval || !optlen) { errno = EINVAL; return -1; } FD_ENTRY* e = SocketFdGet(fd); @@ -322,6 +347,7 @@ __declspec(dllexport) int getsockopt(int fd, int level, int optname, void* optva return 0; } +// Polls the requested operation. __declspec(dllexport) int poll(struct pollfd* fds, nfds_t nfds, int timeout) { if (!fds || nfds == 0 || nfds > 64) { errno = EINVAL; return -1; } @@ -370,6 +396,7 @@ __declspec(dllexport) int poll(struct pollfd* fds, nfds_t nfds, int timeout) { return out; } +// Parses port. static unsigned ParsePort(const char* s) { unsigned v = 0; if (!s) return 0; @@ -381,6 +408,7 @@ static unsigned ParsePort(const char* s) { return *s == '\0' ? v : 0; } +// Implements the resolve Name Ipv4 operation. static int ResolveNameIpv4(const char* name, SYS_SOCKET_ADDRESS_IPV4* out) { uint8_t b[4]; if (ParseIpv4Bytes(name, b)) { @@ -402,6 +430,7 @@ static int ResolveNameIpv4(const char* name, SYS_SOCKET_ADDRESS_IPV4* out) { return 0; } +// Implements the gethostbyname operation. __declspec(dllexport) struct hostent* gethostbyname(const char* name) { static struct hostent h; static char hname[256]; @@ -467,6 +496,7 @@ __declspec(dllexport) int getaddrinfo(const char* node, const char* service, return 0; } +// Implements the freeaddrinfo operation. __declspec(dllexport) void freeaddrinfo(struct addrinfo* res) { if (res) free(res); } diff --git a/code/user/personalities/posix/posix_thread.c b/code/user/personalities/posix/posix_thread.c index 5bdb156..998e3a2 100644 --- a/code/user/personalities/posix/posix_thread.c +++ b/code/user/personalities/posix/posix_thread.c @@ -1,10 +1,11 @@ -// posix_thread.c - pthread_create, pthread_join, pthread_exit, pthread_mutex_* +// POSIX compatibility support for posix thread. + #include #include #include #include "posix.h" -// Thread return-value table (PID-keyed like the fd table) +// Thread return-value table (PID-keyed like the fd table). #define PTHREAD_TABLE_PIDS 32 #define PTHREAD_TABLE_SIZE 32 @@ -16,6 +17,7 @@ typedef struct { static PTHREAD_SLOT gPthreadTable[PTHREAD_TABLE_PIDS][PTHREAD_TABLE_SIZE]; +// Implements the pthread Slot Alloc operation. static PTHREAD_SLOT* PthreadSlotAlloc(uint32_t pid, uint32_t tid) { PTHREAD_SLOT* table = gPthreadTable[pid % PTHREAD_TABLE_PIDS]; for (int i = 0; i < PTHREAD_TABLE_SIZE; i++) { @@ -27,6 +29,7 @@ static PTHREAD_SLOT* PthreadSlotAlloc(uint32_t pid, uint32_t tid) { return (PTHREAD_SLOT*)0; } +// Implements the pthread Slot Find operation. static PTHREAD_SLOT* PthreadSlotFind(uint32_t pid, uint32_t tid) { PTHREAD_SLOT* table = gPthreadTable[pid % PTHREAD_TABLE_PIDS]; for (int i = 0; i < PTHREAD_TABLE_SIZE; i++) @@ -35,15 +38,14 @@ static PTHREAD_SLOT* PthreadSlotFind(uint32_t pid, uint32_t tid) { return (PTHREAD_SLOT*)0; } -// --------------------------------------------------------------------------- -// Trampoline - this is what actually runs as the new thread -// --------------------------------------------------------------------------- +// Trampoline - this is what actually runs as the new thread. typedef struct { void* (*Fn)(void*); void* Arg; uint32_t Pid; // owner pid, for the retval table } PTHREAD_TRAMP; +// Implements the pthread Trampoline operation. static void PthreadTrampoline(uintptr_t raw) { PTHREAD_TRAMP* tr = (PTHREAD_TRAMP*)raw; void* (*fn)(void*) = tr->Fn; @@ -67,9 +69,7 @@ static void PthreadTrampoline(uintptr_t raw) { SysExitThread(0); } -// --------------------------------------------------------------------------- -// pthread API -// --------------------------------------------------------------------------- +// pthread API. __declspec(dllexport) int pthread_create(pthread_t* t, const pthread_attr_t* attr, void* (*fn)(void*), void* arg) { @@ -85,7 +85,7 @@ __declspec(dllexport) int pthread_create(pthread_t* t, const pthread_attr_t* att uint32_t tid = 0; uint32_t s = SysCreateThread((uint64_t)PthreadTrampoline, - (uint64_t)tr, 1 /*PriorityNormal*/, &tid); + (uint64_t)tr, 1, &tid); if (s != 0) { free(tr); return EAGAIN; @@ -96,10 +96,11 @@ __declspec(dllexport) int pthread_create(pthread_t* t, const pthread_attr_t* att return 0; } +// Implements the pthread join operation. __declspec(dllexport) int pthread_join(pthread_t t, void** retval) { uint32_t pid = SysGetCurrentPid(); uint32_t s = SysWaitThread(t.Tid); - // STATUS_NOT_FOUND (0x22) means already dead - treat as success + // STATUS_NOT_FOUND (0x22) means already dead - treat as success. if (s != 0 && s != 0x0022) return ESRCH; PTHREAD_SLOT* slot = PthreadSlotFind(pid, t.Tid); @@ -108,6 +109,7 @@ __declspec(dllexport) int pthread_join(pthread_t t, void** retval) { return 0; } +// Implements the pthread exit operation. __declspec(dllexport) void pthread_exit(void* retval) { uint32_t pid = SysGetCurrentPid(); uint32_t tid = SysGetCurrentTid(); @@ -117,6 +119,7 @@ __declspec(dllexport) void pthread_exit(void* retval) { while (1); // unreachable } +// Implements the pthread mutex init operation. __declspec(dllexport) int pthread_mutex_init(pthread_mutex_t* m, const pthread_mutexattr_t* attr) { (void)attr; uint32_t h; @@ -126,22 +129,26 @@ __declspec(dllexport) int pthread_mutex_init(pthread_mutex_t* m, const pthread_m return 0; } +// Implements the pthread mutex destroy operation. __declspec(dllexport) int pthread_mutex_destroy(pthread_mutex_t* m) { SysCloseHandle(m->Handle); m->Handle = 0; return 0; } +// Implements the pthread mutex lock operation. __declspec(dllexport) int pthread_mutex_lock(pthread_mutex_t* m) { uint32_t s = SysAcquireMutex(m->Handle); return s == 0 ? 0 : EINVAL; } +// Implements the pthread mutex trylock operation. __declspec(dllexport) int pthread_mutex_trylock(pthread_mutex_t* m) { uint32_t s = SysTryAcquireMutex(m->Handle); return s == 0 ? 0 : EAGAIN; } +// Implements the pthread mutex unlock operation. __declspec(dllexport) int pthread_mutex_unlock(pthread_mutex_t* m) { uint32_t s = SysReleaseMutex(m->Handle); return s == 0 ? 0 : EINVAL; diff --git a/code/user/personalities/win32/gdi32.c b/code/user/personalities/win32/gdi32.c index e251c5c..504fe96 100644 --- a/code/user/personalities/win32/gdi32.c +++ b/code/user/personalities/win32/gdi32.c @@ -1,4 +1,5 @@ -// gdi32.c +// Win32 GDI compatibility stubs. This file provides enough drawing API surface for simple applications. + #include #include #include @@ -10,9 +11,7 @@ #include #endif -// --------------------------------------------------------------------------- -// Win32 Base Types -// --------------------------------------------------------------------------- +// Win32 Base Types. typedef void* HDC; typedef unsigned long DWORD; typedef unsigned short WORD; @@ -23,14 +22,12 @@ typedef int BOOL; #define TRUE 1 #define FALSE 0 -// StretchDIBits Constants +// StretchDIBits Constants. #define BI_RGB 0L #define DIB_RGB_COLORS 0 #define SRCCOPY (DWORD)0x00CC0020 -// --------------------------------------------------------------------------- -// GDI Structs -// --------------------------------------------------------------------------- +// GDI Structs. typedef struct tagBITMAPINFOHEADER { DWORD biSize; LONG biWidth; @@ -58,11 +55,9 @@ typedef struct tagBITMAPINFO { } BITMAPINFO; -// --------------------------------------------------------------------------- -// GDI Exports -// --------------------------------------------------------------------------- +// GDI Exports. -// Static buffers to persist between function calls +// Static buffers to persist between function calls. static uint32_t* destBuffer = NULL; static int* srcX_map = NULL; static int currentDestCapacity = 0; @@ -77,12 +72,12 @@ __declspec(dllexport) int StretchDIBits( { (void)hdc; (void)lpbmi; (void)iUsage; (void)rop; - // Safety check to prevent division by zero + // Safety check to prevent division by zero. if (DestWidth <= 0 || DestHeight <= 0 || SrcWidth <= 0 || SrcHeight <= 0) { return 0; } - // Handle trivial case (1:1 copy) to bypass allocation and scaling overhead + // Handle trivial case (1:1 copy) to bypass allocation and scaling overhead. if (DestWidth == SrcWidth && DestHeight == SrcHeight && xSrc == 0 && ySrc == 0) { SysBlitScreen(xDest, yDest, DestWidth, DestHeight, (const uint32_t*)lpBits); return DestHeight; @@ -90,7 +85,7 @@ __declspec(dllexport) int StretchDIBits( const uint32_t* srcPixels = (const uint32_t*)lpBits; - // Only reallocate if the new size is LARGER than what we already have + // Only reallocate if the new size is LARGER than what we already have. int requiredPixels = DestWidth * DestHeight; if (requiredPixels > currentDestCapacity) { free(destBuffer); @@ -105,63 +100,63 @@ __declspec(dllexport) int StretchDIBits( } for (int dx = 0; dx < DestWidth; ++dx) { - // Nearest neighbor coordinate mapping + // Nearest neighbor coordinate mapping. srcX_map[dx] = xSrc + (dx * SrcWidth) / DestWidth; - // Clamp to safe bounds + // Clamp to safe bounds. if (srcX_map[dx] < 0) srcX_map[dx] = 0; if (srcX_map[dx] >= SrcWidth) srcX_map[dx] = SrcWidth - 1; } - // Process the image row by row + // Process the image row by row. for (int dy = 0; dy < DestHeight; ++dy) { - // Map destination Y to source Y + // Map destination Y to source Y. int sy = ySrc + (dy * SrcHeight) / DestHeight; if (sy < 0) sy = 0; if (sy >= SrcHeight) sy = SrcHeight - 1; - // Assumes stride == SrcWidth (tightly packed 32bpp) + // Assumes stride == SrcWidth (tightly packed 32bpp). const uint32_t* srcRow = srcPixels + (sy * SrcWidth); uint32_t* dstRow = destBuffer + (dy * DestWidth); int dx = 0; #if defined(__SSE2__) || defined(_M_X64) - // Process 4 pixels (16 bytes) per loop iteration using SSE2 + // Process 4 pixels (16 bytes) per loop iteration using SSE2. for (; dx <= DestWidth - 4; dx += 4) { // Gather 4 source pixels using our precomputed X map. - // Note: _mm_set_epi32 takes arguments in reverse order (3, 2, 1, 0) + // Note: _mm_set_epi32 takes arguments in reverse order (3, 2, 1, 0). __m128i pixels = _mm_set_epi32( srcRow[srcX_map[dx + 3]], srcRow[srcX_map[dx + 2]], srcRow[srcX_map[dx + 1]], srcRow[srcX_map[dx + 0]] ); - // Issue a single 128-bit unaligned store + // Issue a single 128-bit unaligned store. _mm_storeu_si128((__m128i*)&dstRow[dx], pixels); } #elif defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(_M_ARM64) - // Process 4 pixels per loop iteration using ARM NEON + // Process 4 pixels per loop iteration using ARM NEON. for (; dx <= DestWidth - 4; dx += 4) { - // Initialize a vector and populate lanes (avoids stack-memory hop) + // Initialize a vector and populate lanes (avoids stack-memory hop). uint32x4_t pixels = vdupq_n_u32(0); pixels = vsetq_lane_u32(srcRow[srcX_map[dx + 0]], pixels, 0); pixels = vsetq_lane_u32(srcRow[srcX_map[dx + 1]], pixels, 1); pixels = vsetq_lane_u32(srcRow[srcX_map[dx + 2]], pixels, 2); pixels = vsetq_lane_u32(srcRow[srcX_map[dx + 3]], pixels, 3); - // Issue a single 128-bit store + // Issue a single 128-bit store. vst1q_u32(&dstRow[dx], pixels); } #endif - // Epilogue: Handle remaining pixels if DestWidth isn't a multiple of 4 + // Epilogue: Handle remaining pixels if DestWidth isn't a multiple of 4. for (; dx < DestWidth; ++dx) { dstRow[dx] = srcRow[srcX_map[dx]]; } } - // Direct mapping to kernel screen blit using the stretched buffer + // Direct mapping to kernel screen blit using the stretched buffer. SysBlitScreen(xDest, yDest, DestWidth, DestHeight, destBuffer); return DestHeight; diff --git a/code/user/personalities/win32/kernel32.c b/code/user/personalities/win32/kernel32.c index 1c8f4a6..649472b 100644 --- a/code/user/personalities/win32/kernel32.c +++ b/code/user/personalities/win32/kernel32.c @@ -1,8 +1,8 @@ -// kernel32.c - Win32 personality layer -// +// Win32 kernel32 compatibility layer. This file maps common Win32 process, file, console, heap, and timing APIs onto native syscalls. + // Thin wrappers around syscall.dll stubs that expose a familiar Win32 API // surface to user-mode code originally written for Windows. -// + // Design notes: // - HANDLE is void*; we store the uint32_t kernel handle as a pointer value // so Win32 code can pass it around opaquely without knowing its size. @@ -27,9 +27,7 @@ #include #include -// --------------------------------------------------------------------------- -// Types -// --------------------------------------------------------------------------- +// Types. typedef void* HANDLE; typedef unsigned long DWORD; typedef unsigned short WORD; @@ -78,6 +76,7 @@ typedef struct _MEMORY_BASIC_INFORMATION { DWORD Type; } MEMORY_BASIC_INFORMATION; +// Implements the win Protect To Sys Vm operation. static uint32_t WinProtectToSysVm(DWORD protect) { switch (protect) { case PAGE_NOACCESS: return SYS_VM_NOACCESS; @@ -91,6 +90,7 @@ static uint32_t WinProtectToSysVm(DWORD protect) { } } +// Implements the protect Vm To Win operation. static DWORD SysProtectVmToWin(uint32_t protect) { switch (protect) { case SYS_VM_NOACCESS: return PAGE_NOACCESS; @@ -103,7 +103,7 @@ static DWORD SysProtectVmToWin(uint32_t protect) { } } -// File-find structures +// File-find structures. typedef struct _FILETIME { DWORD dwLowDateTime; DWORD dwHighDateTime; @@ -133,7 +133,7 @@ typedef struct _WIN32_FIND_DATAA { char cAlternateFileName[14]; } WIN32_FIND_DATAA; -// CreateFileA disposition / access flags (subset used by Bink and similar) +// CreateFileA disposition / access flags (subset used by Bink and similar). #define GENERIC_READ 0x80000000UL #define GENERIC_WRITE 0x40000000UL #define GENERIC_READ 0x80000000UL @@ -147,11 +147,9 @@ typedef struct _WIN32_FIND_DATAA { #define FILE_CURRENT 1 #define FILE_END 2 -// --------------------------------------------------------------------------- // Handle conversion helpers // uint32_t kernel handle <-> opaque Win32 HANDLE // Kernel handle 0 == invalid; we map that to INVALID_HANDLE_VALUE (NULL). -// --------------------------------------------------------------------------- static inline HANDLE KH_TO_HANDLE(uint32_t kh) { return (HANDLE)(uintptr_t)kh; } static inline uint32_t HANDLE_TO_KH(HANDLE h) { return (uint32_t)(uintptr_t)h; } @@ -175,7 +173,7 @@ static inline BOOL IS_NOOP_SYNC_HANDLE(HANDLE h) { return v == WIN32_MUTEX_SENTINEL || v == WIN32_SEMA_SENTINEL; } -// Path translator +// Path translator. static void TranslatePath(const char* input, char* output) { if (!output) return; if (!input) { output[0] = '\0'; return; } @@ -190,7 +188,7 @@ static void TranslatePath(const char* input, char* output) { output[1] = ':'; output[2] = '/'; - // Copy the rest, swapping backslashes to forward slashes + // Copy the rest, swapping backslashes to forward slashes. const char* src = input + 3; char* dst = output + 3; while (*src) { @@ -199,7 +197,7 @@ static void TranslatePath(const char* input, char* output) { } *dst = '\0'; } else { - // Fallback for relative paths: just swap slashes + // Fallback for relative paths: just swap slashes. while (*input) { *output = (*input == '\\') ? '/' : *input; input++; output++; @@ -209,31 +207,37 @@ static void TranslatePath(const char* input, char* output) { } +// Implements the k32 Open File Native operation. static uint32_t K32OpenFileNative(const char* path, uint32_t* handleOut) { SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut }; return SysOpenFile(&req); } +// Implements the k32 Create File Native operation. static uint32_t K32CreateFileNative(const char* path, uint32_t* handleOut) { SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut }; return SysCreateFile(&req); } +// Implements the k32 Delete File Native operation. static uint32_t K32DeleteFileNative(const char* path) { SYS_PATH_REQUEST req = { SysSvFromCstr(path) }; return SysDeleteFile(&req); } +// Implements the k32 Open Dir Native operation. static uint32_t K32OpenDirNative(const char* path, uint32_t* handleOut) { SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut }; return SysOpenDir(&req); } +// Implements the k32 Set Cwd Native operation. static uint32_t K32SetCwdNative(const char* path) { SYS_PATH_REQUEST req = { SysSvFromCstr(path) }; return SysSetCwd(&req); } +// Implements the k32 Get Cwd Native operation. static uint32_t K32GetCwdNative(char* buffer, size_t capacity, size_t* lengthOut) { size_t len = 0; size_t writable = (buffer && capacity) ? capacity - 1 : 0; @@ -244,16 +248,19 @@ static uint32_t K32GetCwdNative(char* buffer, size_t capacity, size_t* lengthOut return s; } +// Implements the k32 Create Process Native operation. static uint32_t K32CreateProcessNative(const char* path, uint32_t* handleOut, const char* commandLine) { SYS_CREATE_PROCESS_REQUEST req = { SysSvFromCstr(path), SysSvFromCstr(commandLine), handleOut }; return SysCreateProcess(&req); } +// Implements the k32 Write Console Span operation. static void K32WriteConsoleSpan(const char* data, size_t length) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(data, length) }; SysWriteConsole(&req); } +// Implements the k32 Debug Print A operation. static void K32DebugPrintA(const char* s) { if (!s) return; SYS_PRINT_DEBUG_REQUEST req = { SysSvFromCstr(s) }; @@ -270,6 +277,7 @@ typedef struct WIN32_THREAD_ENV { static WIN32_THREAD_ENV gFallbackThreadEnv; +// Implements the k32 Thread Env operation. static WIN32_THREAD_ENV* K32ThreadEnv(void) { SYS_TEB* teb = SysGetTeb(); if (!teb || teb->Magic != SYS_TEB_MAGIC) return &gFallbackThreadEnv; @@ -284,12 +292,14 @@ static WIN32_THREAD_ENV* K32ThreadEnv(void) { return env; } +// Implements the k32 Last Error Slot operation. static DWORD* K32LastErrorSlot(void) { return &K32ThreadEnv()->LastError; } #define gLastError (*K32LastErrorSlot()) +// Implements the file Exists A operation. static BOOL KiFileExistsA(const char* path) { if (!path || !*path) return FALSE; char native[MAX_PATH]; @@ -300,6 +310,7 @@ static BOOL KiFileExistsA(const char* path) { return TRUE; } +// Copies search Path Result. static DWORD KiCopySearchPathResult(char* out, DWORD outChars, const char* text, char** filePart) { DWORD len = (DWORD)strlen(text); if (out && outChars) { @@ -367,52 +378,46 @@ __declspec(dllexport) DWORD SearchPathA(const char* lpPath, const char* lpFileNa return 0; } -// --------------------------------------------------------------------------- -// GetLastError / SetLastError (single-threaded stub) -// --------------------------------------------------------------------------- +// GetLastError / SetLastError (single-threaded stub). static SYS_PEB* gProcessPeb = NULL; +// Implements the peb operation. static SYS_PEB* Win32Peb(void) { if (!gProcessPeb) gProcessPeb = SysGetPeb(); return gProcessPeb; } +// Returns last Error. __declspec(dllexport) DWORD GetLastError(void) { return gLastError; } +// Updates last Error. __declspec(dllexport) void SetLastError(DWORD err) { gLastError = err; } -// --------------------------------------------------------------------------- -// Process termination -// --------------------------------------------------------------------------- +// Process termination. __declspec(dllexport) _Noreturn void ExitProcess(unsigned int code) { SysExitProcess((int)code); while (true) ; // unreachable } -// --------------------------------------------------------------------------- -// Debug output -// --------------------------------------------------------------------------- +// Debug output. __declspec(dllexport) void OutputDebugStringA(const char* str) { if (str) K32DebugPrintA(str); } -// --------------------------------------------------------------------------- -// Timer -// --------------------------------------------------------------------------- +// Timer. __declspec(dllexport) DWORD GetTickCount(void) { return (DWORD)(SysGetTick() / 1000); } +// Returns tick Count64. __declspec(dllexport) uint64_t GetTickCount64(void) { return SysGetTick() / 1000; } -// --------------------------------------------------------------------------- -// Memory (heap argument is ignored - single user-mode heap) -// --------------------------------------------------------------------------- +// Memory (heap argument is ignored - single user-mode heap). __declspec(dllexport) void* HeapAlloc(void* heap, DWORD flags, size_t size) { (void)heap; (void)flags; if (!size) return NULL; @@ -421,6 +426,7 @@ __declspec(dllexport) void* HeapAlloc(void* heap, DWORD flags, size_t size) { return ptr; } +// Implements the heap Free operation. __declspec(dllexport) BOOL HeapFree(void* heap, DWORD flags, void* ptr) { (void)heap; (void)flags; // Win32's HeapFree doesn't need the size; we pass 0 and the user-mode heap carries the block size. @@ -442,9 +448,7 @@ __declspec(dllexport) void* GetProcessHeap(void) { return (void*)1; } -// --------------------------------------------------------------------------- -// Virtual memory compatibility -// --------------------------------------------------------------------------- +// Virtual memory compatibility. __declspec(dllexport) void* VirtualAlloc(void* lpAddress, size_t dwSize, DWORD flAllocationType, DWORD flProtect) { (void)flAllocationType; @@ -461,6 +465,7 @@ __declspec(dllexport) void* VirtualAlloc(void* lpAddress, size_t dwSize, return base; } +// Implements the virtual Free operation. __declspec(dllexport) BOOL VirtualFree(void* lpAddress, size_t dwSize, DWORD dwFreeType) { (void)dwSize; (void)dwFreeType; if (!lpAddress) return TRUE; @@ -507,7 +512,7 @@ __declspec(dllexport) size_t VirtualQuery(const void* lpAddress, return sizeof(MEMORY_BASIC_INFORMATION); } -// --- Win32 API --- +// --- Win32 API ---. // GetAsyncKeyState implementation over the canonical input key namespace. __declspec(dllexport) SHORT GetAsyncKeyState(int vKey) { @@ -522,7 +527,7 @@ __declspec(dllexport) SHORT GetAsyncKeyState(int vKey) { } static const struct { int vk; INPUT_KEY key; } vk_to_key[] = { - // Letters + // Letters. { 0x41, INPUT_KEY_A }, { 0x42, INPUT_KEY_B }, { 0x43, INPUT_KEY_C }, { 0x44, INPUT_KEY_D }, { 0x45, INPUT_KEY_E }, { 0x46, INPUT_KEY_F }, { 0x47, INPUT_KEY_G }, { 0x48, INPUT_KEY_H }, { 0x49, INPUT_KEY_I }, @@ -533,28 +538,28 @@ __declspec(dllexport) SHORT GetAsyncKeyState(int vKey) { { 0x56, INPUT_KEY_V }, { 0x57, INPUT_KEY_W }, { 0x58, INPUT_KEY_X }, { 0x59, INPUT_KEY_Y }, { 0x5A, INPUT_KEY_Z }, - // Numbers + // Numbers. { 0x31, INPUT_KEY_1 }, { 0x32, INPUT_KEY_2 }, { 0x33, INPUT_KEY_3 }, { 0x34, INPUT_KEY_4 }, { 0x35, INPUT_KEY_5 }, { 0x36, INPUT_KEY_6 }, { 0x37, INPUT_KEY_7 }, { 0x38, INPUT_KEY_8 }, { 0x39, INPUT_KEY_9 }, { 0x30, INPUT_KEY_0 }, - // Arrows + // Arrows. { 0x26, INPUT_KEY_UP }, { 0x28, INPUT_KEY_DOWN }, { 0x25, INPUT_KEY_LEFT }, { 0x27, INPUT_KEY_RIGHT }, - // Controls + // Controls. { 0x1B, INPUT_KEY_ESCAPE }, { 0x0D, INPUT_KEY_ENTER }, { 0x20, INPUT_KEY_SPACE }, { 0x08, INPUT_KEY_BACKSPACE }, { 0x09, INPUT_KEY_TAB }, - // Function Keys + // Function Keys. { 0x70, INPUT_KEY_F1 }, { 0x71, INPUT_KEY_F2 }, { 0x72, INPUT_KEY_F3 }, { 0x73, INPUT_KEY_F4 }, { 0x74, INPUT_KEY_F5 }, { 0x75, INPUT_KEY_F6 }, { 0x76, INPUT_KEY_F7 }, { 0x77, INPUT_KEY_F8 }, { 0x78, INPUT_KEY_F9 }, { 0x79, INPUT_KEY_F10 }, { 0x7A, INPUT_KEY_F11 }, { 0x7B, INPUT_KEY_F12 }, - // Symbols + // Symbols. { 0xBD, INPUT_KEY_MINUS }, { 0xBB, INPUT_KEY_EQUAL }, { 0xBC, INPUT_KEY_COMMA }, { 0xBE, INPUT_KEY_PERIOD }, }; @@ -569,10 +574,10 @@ __declspec(dllexport) SHORT GetAsyncKeyState(int vKey) { return 0; } -// FlushConsoleInputBuffer: clear the keyboard input buffer +// FlushConsoleInputBuffer: clear the keyboard input buffer. __declspec(dllexport) BOOL FlushConsoleInputBuffer(HANDLE hConsoleInput) { (void)hConsoleInput; - // Drain the keyboard buffer by reading until empty + // Drain the keyboard buffer by reading until empty. while (SysPollKeyboard()) { (void)SysReadKeyboardChar(); } @@ -585,9 +590,7 @@ __declspec(dllexport) BOOL ClearConsoleScreenBuffer(HANDLE hConsole) { return TRUE; } -// --------------------------------------------------------------------------- -// Locale / code-page stubs -// --------------------------------------------------------------------------- +// Locale / code-page stubs. __declspec(dllexport) int MultiByteToWideChar(unsigned int cp, DWORD flags, const char* src, int srcLen, unsigned short* dst, int dstLen) { @@ -623,17 +626,18 @@ __declspec(dllexport) int WideCharToMultiByte(unsigned int cp, DWORD flags, return out; } +// Returns aCP. __declspec(dllexport) DWORD GetACP(void) { return 1252; } // Windows-1252 +// Returns oEMCP. __declspec(dllexport) DWORD GetOEMCP(void) { return 437; } // DOS Latin US +// Checks whether dBCS Lead Byte Ex. __declspec(dllexport) BOOL IsDBCSLeadByteEx(unsigned int CodePage, BYTE TestChar) { (void)CodePage; (void)TestChar; return FALSE; } -// --------------------------------------------------------------------------- -// File I/O -// --------------------------------------------------------------------------- +// File I/O. // CreateFileA - opens or creates a file. // Supported modes: @@ -642,14 +646,14 @@ __declspec(dllexport) BOOL IsDBCSLeadByteEx(unsigned int CodePage, BYTE TestChar // OPEN_EXISTING + GENERIC_READ|GENERIC_WRITE -> open existing, read-write // CREATE_ALWAYS + GENERIC_WRITE -> create/truncate, write // OPEN_ALWAYS + GENERIC_WRITE -> create if absent, write -// TRUNCATE_EXISTING + GENERIC_WRITE -> open & truncate to zero +// TRUNCATE_EXISTING + GENERIC_WRITE -> open & truncate to zero. __declspec(dllexport) HANDLE CreateFileA(const char* name, DWORD access, DWORD share, void* sa, DWORD disposition, DWORD flags, void* templ) { (void)share; (void)sa; (void)flags; (void)templ; - // Translate the path from Windows format to custom 0:/ format + // Translate the path from Windows format to custom 0:/ format. char translatedName[260]; TranslatePath(name, translatedName); @@ -842,16 +846,12 @@ __declspec(dllexport) BOOL CloseHandle(HANDLE hObject) { return TRUE; } -// =========================================================================== // Extended shims - funcs.txt additions // All functions here return plausible values; no real implementation exists // unless a matching syscall stub is available. -// =========================================================================== -// --------------------------------------------------------------------------- // Additional Heap APIs // We have one kernel heap; the HANDLE is always ignored. -// --------------------------------------------------------------------------- typedef int HEAP_INFORMATION_CLASS; // opaque @@ -862,11 +862,13 @@ __declspec(dllexport) HANDLE HeapCreate(DWORD flOptions, return (HANDLE)(uintptr_t)1; // non-NULL sentinel } +// Implements the heap Destroy operation. __declspec(dllexport) BOOL HeapDestroy(HANDLE hHeap) { (void)hHeap; return TRUE; } +// Implements the heap Size operation. __declspec(dllexport) size_t HeapSize(HANDLE heap, DWORD flags, const void* ptr) { (void)heap; (void)flags; (void)ptr; return (size_t)-1; // Win32 returns (SIZE_T)-1 on error / unsupported @@ -879,25 +881,27 @@ __declspec(dllexport) BOOL HeapSetInformation(HANDLE HeapHandle, return TRUE; } -// --------------------------------------------------------------------------- -// Process & Module pseudo-handles / queries -// --------------------------------------------------------------------------- +// Process & Module pseudo-handles / queries. // Pseudo-handles matching Windows convention: -1 = process, -2 = thread. __declspec(dllexport) HANDLE GetCurrentProcess(void) { return (HANDLE)(uintptr_t)(~(uintptr_t)0); } +// Returns current Thread. __declspec(dllexport) HANDLE GetCurrentThread(void) { return (HANDLE)(uintptr_t)(~(uintptr_t)1); } +// Returns current Thread Id. __declspec(dllexport) DWORD GetCurrentThreadId(void) { return (DWORD)SysGetCurrentTid(); } +// Returns current Process Id. __declspec(dllexport) DWORD GetCurrentProcessId(void) { return (DWORD)SysGetCurrentPid(); } // Tiny TLS index allocator; slot values are stored per thread in WIN32_THREAD_ENV. static uint64_t gTlsBitmap = 1; // reserve slot 0 +// Implements the tls Alloc operation. __declspec(dllexport) DWORD TlsAlloc(void) { for (DWORD i = 1; i < WIN32_TLS_SLOTS; i++) { uint64_t bit = 1ULL << i; @@ -907,6 +911,7 @@ __declspec(dllexport) DWORD TlsAlloc(void) { return 0xFFFFFFFFUL; } +// Implements the tls Free operation. __declspec(dllexport) BOOL TlsFree(DWORD dwTlsIndex) { if (dwTlsIndex >= WIN32_TLS_SLOTS || !(gTlsBitmap & (1ULL << dwTlsIndex))) { gLastError = 87; return FALSE; } WIN32_THREAD_ENV* env = K32ThreadEnv(); @@ -915,6 +920,7 @@ __declspec(dllexport) BOOL TlsFree(DWORD dwTlsIndex) { return TRUE; } +// Implements the tls Get Value operation. __declspec(dllexport) void* TlsGetValue(DWORD dwTlsIndex) { if (dwTlsIndex >= WIN32_TLS_SLOTS || !(gTlsBitmap & (1ULL << dwTlsIndex))) { gLastError = 87; return NULL; } WIN32_THREAD_ENV* env = K32ThreadEnv(); @@ -922,6 +928,7 @@ __declspec(dllexport) void* TlsGetValue(DWORD dwTlsIndex) { return env->TlsSlots[dwTlsIndex]; } +// Implements the tls Set Value operation. __declspec(dllexport) BOOL TlsSetValue(DWORD dwTlsIndex, void* lpTlsValue) { if (dwTlsIndex >= WIN32_TLS_SLOTS || !(gTlsBitmap & (1ULL << dwTlsIndex))) { gLastError = 87; return FALSE; } WIN32_THREAD_ENV* env = K32ThreadEnv(); @@ -933,11 +940,13 @@ __declspec(dllexport) BOOL TlsSetValue(DWORD dwTlsIndex, void* lpTlsValue) { #define WIN32_HMODULE_EXE ((HANDLE)(uintptr_t)0x00400000UL) #define WIN32_HMODULE_WIN32 ((HANDLE)(uintptr_t)0x57333232UL) // W322 +// Implements the stricmp A operation. static int KiStricmpA(const char* a, const char* b) { while (*a && (((unsigned char)*a | 0x20) == ((unsigned char)*b | 0x20))) { a++; b++; } return ((unsigned char)*a | 0x20) - ((unsigned char)*b | 0x20); } +// Checks whether win32 Dll Name A. static BOOL KiIsWin32DllNameA(const char* name) { return name && ( !KiStricmpA(name, "kernel32.dll") || !KiStricmpA(name, "user32.dll") || @@ -945,10 +954,12 @@ static BOOL KiIsWin32DllNameA(const char* name) { !KiStricmpA(name, "winmm.dll") || !KiStricmpA(name, "win32.dll")); } +// Implements the dbg Write A operation. static void KiDbgWriteA(const char* s) { if (s) K32WriteConsoleSpan(s, strlen(s)); } +// Returns module Handle A. __declspec(dllexport) HANDLE GetModuleHandleA(const char* lpModuleName) { if (!lpModuleName) return WIN32_HMODULE_EXE; if (KiIsWin32DllNameA(lpModuleName)) return WIN32_HMODULE_WIN32; @@ -956,10 +967,12 @@ __declspec(dllexport) HANDLE GetModuleHandleA(const char* lpModuleName) { return NULL; } +// Returns module Handle W. __declspec(dllexport) HANDLE GetModuleHandleW(const unsigned short* lpModuleName) { return lpModuleName ? NULL : WIN32_HMODULE_EXE; } +// Loads library A. __declspec(dllexport) HANDLE LoadLibraryA(const char* lpLibFileName) { if (KiIsWin32DllNameA(lpLibFileName)) return WIN32_HMODULE_WIN32; gLastError = 2; // ERROR_FILE_NOT_FOUND @@ -984,6 +997,7 @@ __declspec(dllexport) BOOL FillConsoleOutputAttribute(HANDLE hConsoleOutput, DWORD* lpNumberOfAttrsWritten); __declspec(dllexport) BOOL SetConsoleCursorPosition(HANDLE hConsoleOutput, COORD dwCursorPosition); +// Returns proc Address. __declspec(dllexport) void* GetProcAddress(HANDLE hModule, const char* lpProcName) { if (hModule != WIN32_HMODULE_WIN32 || !lpProcName) { gLastError = 127; return NULL; } @@ -1010,6 +1024,7 @@ __declspec(dllexport) void* GetProcAddress(HANDLE hModule, const char* lpProcNam return NULL; } +// Releases library. __declspec(dllexport) BOOL FreeLibrary(HANDLE hLibModule) { (void)hLibModule; return TRUE; @@ -1033,6 +1048,7 @@ __declspec(dllexport) DWORD GetModuleFileNameA(HANDLE hModule, return copy; } +// Implements the terminate Process operation. __declspec(dllexport) BOOL TerminateProcess(HANDLE hProcess, unsigned int uExitCode) { (void)hProcess; SysExitProcess((int)uExitCode); @@ -1053,6 +1069,7 @@ typedef struct { HANDLE hStdInput, hStdOutput, hStdError; } STARTUPINFOA; +// Returns startup Info A. __declspec(dllexport) void GetStartupInfoA(STARTUPINFOA* lpStartupInfo) { if (!lpStartupInfo) return; // Zero every field, then set the mandatory cb. @@ -1061,15 +1078,14 @@ __declspec(dllexport) void GetStartupInfoA(STARTUPINFOA* lpStartupInfo) { lpStartupInfo->cb = (DWORD)sizeof(*lpStartupInfo); } +// Returns command Line A. __declspec(dllexport) char* GetCommandLineA(void) { SYS_PEB* peb = Win32Peb(); if (!peb || peb->Magic != SYS_PEB_MAGIC || !peb->CommandLine.Data) return ""; return (char*)peb->CommandLine.Data; } -// --------------------------------------------------------------------------- -// Threading -// --------------------------------------------------------------------------- +// Threading. #define WAIT_OBJECT_0 0x00000000UL #define WAIT_TIMEOUT 0x00000102UL @@ -1085,7 +1101,7 @@ __declspec(dllexport) HANDLE CreateThread(void* lpThreadAttributes, uint32_t tid = 0; uint32_t s = SysCreateThread((uint64_t)(uintptr_t)lpStartAddress, (uint64_t)(uintptr_t)lpParameter, - 0 /* normal priority */, &tid); + 0, &tid); if (s != 0) { gLastError = 11; return INVALID_HANDLE_VALUE; } if (lpThreadId) *lpThreadId = (DWORD)tid; return TID_TO_THREAD_HANDLE(tid); @@ -1115,6 +1131,7 @@ __declspec(dllexport) DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMillisec } +// Implements the extract Application Path A operation. static BOOL ExtractApplicationPathA(const char* commandLine, char* out, size_t outSize) { if (!commandLine || !out || outSize == 0) return FALSE; @@ -1135,9 +1152,7 @@ static BOOL ExtractApplicationPathA(const char* commandLine, char* out, size_t o return pos != 0; } -// --------------------------------------------------------------------------- -// Process creation -// --------------------------------------------------------------------------- +// Process creation. typedef struct { HANDLE hProcess; @@ -1163,7 +1178,7 @@ __declspec(dllexport) BOOL CreateProcessA( (void)bInheritHandles; (void)dwCreationFlags; (void)lpEnvironment; (void)lpStartupInfo; - // lpProcessInformation is mandatory + // lpProcessInformation is mandatory. if (!lpProcessInformation) { gLastError = 87; // ERROR_INVALID_PARAMETER return FALSE; @@ -1231,6 +1246,7 @@ __declspec(dllexport) BOOL CreateProcessA( return TRUE; } +// Returns exit Code Process. __declspec(dllexport) BOOL GetExitCodeProcess(HANDLE hProcess, DWORD* lpExitCode) { if (!lpExitCode) { gLastError = 87; return FALSE; } uint32_t kh = HANDLE_TO_KH(hProcess); @@ -1242,6 +1258,7 @@ __declspec(dllexport) BOOL GetExitCodeProcess(HANDLE hProcess, DWORD* lpExitCode return TRUE; } +// Implements the resume Thread operation. __declspec(dllexport) DWORD ResumeThread(HANDLE hThread) { (void)hThread; return 0; // previous suspend count @@ -1249,11 +1266,13 @@ __declspec(dllexport) DWORD ResumeThread(HANDLE hThread) { #define THREAD_PRIORITY_NORMAL 0 +// Updates thread Priority. __declspec(dllexport) BOOL SetThreadPriority(HANDLE hThread, int nPriority) { (void)hThread; (void)nPriority; return TRUE; } +// Returns thread Priority. __declspec(dllexport) int GetThreadPriority(HANDLE hThread) { (void)hThread; return THREAD_PRIORITY_NORMAL; @@ -1265,29 +1284,31 @@ __declspec(dllexport) uintptr_t SetThreadAffinityMask(HANDLE hThread, return 1; // previous mask: CPU 0 only } +// Implements the sleep operation. __declspec(dllexport) void Sleep(DWORD dwMilliseconds) { SysSleep(dwMilliseconds); } -// --------------------------------------------------------------------------- -// Console I/O -// --------------------------------------------------------------------------- +// Console I/O. #define STD_INPUT_HANDLE ((DWORD)-10) #define STD_OUTPUT_HANDLE ((DWORD)-11) #define STD_ERROR_HANDLE ((DWORD)-12) +// Implements the k32 Is Std Handle Value operation. static BOOL K32IsStdHandleValue(HANDLE h, DWORD stdHandle) { uintptr_t value = (uintptr_t)h; return value == (uintptr_t)stdHandle || value == (uintptr_t)(intptr_t)(int32_t)stdHandle; } +// Implements the k32 Is Console Output Handle operation. static BOOL K32IsConsoleOutputHandle(HANDLE h) { return h && h != INVALID_HANDLE_VALUE && (K32IsStdHandleValue(h, STD_OUTPUT_HANDLE) || K32IsStdHandleValue(h, STD_ERROR_HANDLE)); } +// Implements the k32 Set Console Last Error operation. static void K32SetConsoleLastError(uint32_t status) { switch (status) { case SYS_STATUS_SUCCESS: @@ -1327,14 +1348,14 @@ __declspec(dllexport) BOOL ReadConsoleA(HANDLE hConsoleInput, while (i < nNumberOfCharsToRead) { char c = SysReadKeyboardChar(); - // Ignore unmapped keys (Shift, Ctrl, etc.) + // Ignore unmapped keys (Shift, Ctrl, etc.). if (c == 0) continue; // Deliver the raw character; the caller handles echo and line editing. buf[i] = c; i++; - // Stop reading when the user presses Enter + // Stop reading when the user presses Enter. if (c == '\n' || c == '\r') { // If your shell expects strings to be \n terminated, leave this. // If your shell expects \0 termination without a newline, @@ -1473,9 +1494,7 @@ __declspec(dllexport) BOOL FillConsoleOutputAttribute(HANDLE hConsoleOutput, return TRUE; } -// --------------------------------------------------------------------------- -// Directory enumeration (FindFirstFileA / FindNextFileA / FindClose) -// --------------------------------------------------------------------------- +// Directory enumeration (FindFirstFileA / FindNextFileA / FindClose). typedef SYS_DIR_ENTRY KDIR_ENTRY; @@ -1494,10 +1513,10 @@ typedef struct { static int WildMatch(const char* pat, const char* name) { while (*pat && *name) { if (*pat == '*') { - // Skip consecutive stars + // Skip consecutive stars. while (*pat == '*') pat++; if (!*pat) return 1; // trailing * matches everything - // Try matching the rest of the pattern at every position + // Try matching the rest of the pattern at every position. while (*name) { if (WildMatch(pat, name)) return 1; name++; @@ -1509,7 +1528,7 @@ static int WildMatch(const char* pat, const char* name) { if (*pat != '?' && p != n) return 0; pat++; name++; } - // Consume trailing stars in the pattern + // Consume trailing stars in the pattern. while (*pat == '*') pat++; return (*pat == '\0' && *name == '\0'); } @@ -1518,17 +1537,17 @@ static int WildMatch(const char* pat, const char* name) { // "apps\\*" -> dir="apps" pat="*" // "*.txt" -> dir="" pat="*.txt" // "*" -> dir="" pat="*" -// "apps\\" -> dir="apps" pat="*" +// "apps\\" -> dir="apps" pat="*". static void SplitFindPath(const char* searchPath, char* dirOut, size_t dirSize, char* patOut, size_t patSize) { - // Find last backslash or forward-slash + // Find last backslash or forward-slash. const char* last = NULL; for (const char* p = searchPath; *p; p++) if (*p == '\\' || *p == '/') last = p; if (!last) { - // No separator: whole string is the pattern, dir is CWD + // No separator: whole string is the pattern, dir is CWD. if (dirOut && dirSize) dirOut[0] = '\0'; if (patOut && patSize) { size_t len = strlen(searchPath); @@ -1537,14 +1556,14 @@ static void SplitFindPath(const char* searchPath, patOut[len] = '\0'; } } else { - // Everything before the last separator is the directory + // Everything before the last separator is the directory. if (dirOut) { size_t len = (size_t)(last - searchPath); if (len + 1 > dirSize) len = dirSize - 1; memcpy(dirOut, searchPath, len); dirOut[len] = '\0'; } - // Everything after the last separator is the pattern + // Everything after the last separator is the pattern. if (patOut) { const char* p = last + 1; size_t len = strlen(p); @@ -1554,7 +1573,7 @@ static void SplitFindPath(const char* searchPath, } } - // Empty pattern defaults to "*" + // Empty pattern defaults to "*". if (patOut && patOut[0] == '\0') { patOut[0] = '*'; patOut[1] = '\0'; } @@ -1565,10 +1584,12 @@ static void SplitFindPath(const char* searchPath, #define FILE_ATTRIBUTE_ARCHIVE 0x00000020UL #define FILE_ATTRIBUTE_NORMAL 0x00000080UL +// Implements the k32 Dir Is Leap Year operation. static int K32DirIsLeapYear(unsigned int year) { return ((year % 4u) == 0u && (year % 100u) != 0u) || ((year % 400u) == 0u); } +// Implements the k32 Dir Days In Month operation. static unsigned int K32DirDaysInMonth(unsigned int year, unsigned int month) { static const unsigned char days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; if (month < 1u || month > 12u) return 31u; @@ -1576,6 +1597,7 @@ static unsigned int K32DirDaysInMonth(unsigned int year, unsigned int month) { return days[month - 1u]; } +// Implements the k32 Dir Calendar To Epoch Seconds operation. static uint64_t K32DirCalendarToEpochSeconds(const SYS_SYSTEM_TIME* st) { uint64_t days = 0; for (unsigned int y = 1970u; y < st->Year; y++) @@ -1586,6 +1608,7 @@ static uint64_t K32DirCalendarToEpochSeconds(const SYS_SYSTEM_TIME* st) { return (((days * 24u) + st->Hour) * 60u + st->Minute) * 60u + st->Second; } +// Implements the k32 Dir Store File Time operation. static void K32DirStoreFileTime(FILETIME* ft, const SYS_SYSTEM_TIME* st) { if (!ft || !st || !(st->Flags & SYS_TIME_FLAG_VALID) || st->Year < 1970u) { if (ft) { ft->dwLowDateTime = 0; ft->dwHighDateTime = 0; } @@ -1600,8 +1623,9 @@ static void K32DirStoreFileTime(FILETIME* ft, const SYS_SYSTEM_TIME* st) { ft->dwHighDateTime = (DWORD)(value >> 32); } +// Implements the kdir To Find Data operation. static void KdirToFindData(const KDIR_ENTRY* ke, WIN32_FIND_DATAA* fd) { - // Zero the entire struct (covers all FILETIME and reserved fields) + // Zero the entire struct (covers all FILETIME and reserved fields). unsigned char* p = (unsigned char*)fd; for (size_t i = 0; i < sizeof(*fd); i++) p[i] = 0; @@ -1629,16 +1653,16 @@ __declspec(dllexport) HANDLE FindFirstFileA(const char* lpFileName, return INVALID_HANDLE_VALUE; } - // Translate the path + // Translate the path. char translatedInput[MAX_PATH]; TranslatePath(lpFileName, translatedInput); - // Split path into directory and wildcard pattern + // Split path into directory and wildcard pattern. char dir[MAX_PATH]; char pat[MAX_PATH]; SplitFindPath(translatedInput, dir, sizeof(dir), pat, sizeof(pat)); - // Open the kernel directory iterator + // Open the kernel directory iterator. uint32_t kh = 0; uint32_t s = K32OpenDirNative(dir[0] ? dir : NULL, &kh); if (s != 0 || kh == 0) { @@ -1646,7 +1670,7 @@ __declspec(dllexport) HANDLE FindFirstFileA(const char* lpFileName, return INVALID_HANDLE_VALUE; } - // Allocate our user-side FIND_HANDLE wrapper + // Allocate our user-side FIND_HANDLE wrapper. FIND_HANDLE* fh = (FIND_HANDLE*)HeapAlloc(NULL, 0, sizeof(FIND_HANDLE)); if (!fh) { SysCloseHandle(kh); @@ -1659,12 +1683,12 @@ __declspec(dllexport) HANDLE FindFirstFileA(const char* lpFileName, memcpy(fh->pattern, pat, patLen); fh->pattern[patLen] = '\0'; - // Read the first entry that matches the pattern + // Read the first entry that matches the pattern. KDIR_ENTRY ke; for (;;) { uint32_t rs = SysReadDir(kh, &ke); if (rs != 0) { - // Directory exhausted or error + // Directory exhausted or error. SysCloseHandle(kh); HeapFree(NULL, 0, fh); gLastError = 18; // ERROR_NO_MORE_FILES @@ -1700,6 +1724,7 @@ __declspec(dllexport) BOOL FindNextFileA(HANDLE hFindFile, } } +// Returns close. __declspec(dllexport) BOOL FindClose(HANDLE hFindFile) { if (hFindFile == INVALID_HANDLE_VALUE) { gLastError = 6; @@ -1711,9 +1736,7 @@ __declspec(dllexport) BOOL FindClose(HANDLE hFindFile) { return TRUE; } -// --------------------------------------------------------------------------- -// Current Working Directory -// --------------------------------------------------------------------------- +// Current Working Directory. __declspec(dllexport) BOOL SetCurrentDirectoryA(const char* lpPathName) { if (!lpPathName) { gLastError = 87; return FALSE; } @@ -1726,6 +1749,7 @@ __declspec(dllexport) BOOL SetCurrentDirectoryA(const char* lpPathName) { return TRUE; } +// Returns current Directory A. __declspec(dllexport) DWORD GetCurrentDirectoryA(DWORD nBufferLength, char* lpBuffer) { if (!lpBuffer || nBufferLength == 0) { // Return required size (including NUL). Max CWD is 512 bytes + "C:\\". @@ -1764,7 +1788,6 @@ __declspec(dllexport) DWORD GetCurrentDirectoryA(DWORD nBufferLength, char* lpBu return (DWORD)(needed - 1); // length without NUL, matching Win32 } -// --------------------------------------------------------------------------- __declspec(dllexport) HANDLE CreateMutexA(void* lpMutexAttributes, BOOL bInitialOwner, const char* lpName) { @@ -1772,6 +1795,7 @@ __declspec(dllexport) HANDLE CreateMutexA(void* lpMutexAttributes, BOOL bInitial return (HANDLE)WIN32_MUTEX_SENTINEL; } +// Releases mutex. __declspec(dllexport) BOOL ReleaseMutex(HANDLE hMutex) { (void)hMutex; return TRUE; @@ -1792,16 +1816,15 @@ __declspec(dllexport) BOOL ReleaseSemaphore(HANDLE hSemaphore, long lReleaseCoun return TRUE; } -// --------------------------------------------------------------------------- // Critical Sections & Condition Variables // Single-threaded: all locks are no-ops. -// --------------------------------------------------------------------------- // Minimal opaque types; callers allocate these from their Windows headers - // we just need the pointer to be accepted by our stubs. typedef struct { uintptr_t _opaque[5]; } CRITICAL_SECTION; typedef struct { void* _ptr; } CONDITION_VARIABLE; +// Initializes critical Section. __declspec(dllexport) void InitializeCriticalSection(CRITICAL_SECTION* lpCS) { (void)lpCS; } @@ -1810,13 +1833,18 @@ __declspec(dllexport) BOOL InitializeCriticalSectionAndSpinCount(CRITICAL_SECTIO (void)lpCS; (void)dwSpinCount; return TRUE; } +// Releases critical Section. __declspec(dllexport) void DeleteCriticalSection(CRITICAL_SECTION* lpCS) { (void)lpCS; } +// Implements the enter Critical Section operation. __declspec(dllexport) void EnterCriticalSection(CRITICAL_SECTION* lpCS) { (void)lpCS; } +// Implements the leave Critical Section operation. __declspec(dllexport) void LeaveCriticalSection(CRITICAL_SECTION* lpCS) { (void)lpCS; } +// Implements the try Enter Critical Section operation. __declspec(dllexport) BOOL TryEnterCriticalSection(CRITICAL_SECTION* lpCS) { (void)lpCS; return TRUE; } +// Initializes condition Variable. __declspec(dllexport) void InitializeConditionVariable(CONDITION_VARIABLE* cv) { (void)cv; } __declspec(dllexport) BOOL SleepConditionVariableCS(CONDITION_VARIABLE* cv, @@ -1825,12 +1853,12 @@ __declspec(dllexport) BOOL SleepConditionVariableCS(CONDITION_VARIABLE* cv, (void)cv; (void)cs; (void)dwMilliseconds; return TRUE; } +// Implements the wake Condition Variable operation. __declspec(dllexport) void WakeConditionVariable(CONDITION_VARIABLE* cv) { (void)cv; } +// Implements the wake All Condition Variable operation. __declspec(dllexport) void WakeAllConditionVariable(CONDITION_VARIABLE* cv) { (void)cv; } -// --------------------------------------------------------------------------- -// Timing & Performance Counters -// --------------------------------------------------------------------------- +// Timing & Performance Counters. typedef union { struct { DWORD LowPart; long HighPart; } u; @@ -1862,7 +1890,7 @@ static long long TscFreqCalibrate(void) { uint64_t t0 = SysGetTick(); uint64_t tsc0 = __rdtsc(); - // Simple busy wait for the duration + // Simple busy wait for the duration. while ((SysGetTick() - t0) < CALIBRATION_US) { _mm_pause(); } @@ -1873,10 +1901,11 @@ static long long TscFreqCalibrate(void) { uint64_t delta_tsc = tsc1 - tsc0; uint64_t delta_us = t1 - t0; - // Hz = (Delta TSC / Delta Microseconds) * 1,000,000 + // Hz = (Delta TSC / Delta Microseconds) * 1,000,000. return (long long)(delta_tsc * 1000000ULL / delta_us); } +// Implements the tsc Freq Get operation. static long long TscFreqGet(void) { if (gTscFreq) return gTscFreq; @@ -1887,11 +1916,13 @@ static long long TscFreqGet(void) { return f; } +// Returns performance Frequency. __declspec(dllexport) BOOL QueryPerformanceFrequency(LARGE_INTEGER* lpFrequency) { if (lpFrequency) lpFrequency->QuadPart = TscFreqGet(); return TRUE; } +// Returns performance Counter. __declspec(dllexport) BOOL QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceCount) { // Ensure calibration happens before the first read. TscFreqGet(); @@ -1900,10 +1931,12 @@ __declspec(dllexport) BOOL QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceC return TRUE; } +// Implements the k32 Is Leap Year operation. static BOOL K32IsLeapYear(unsigned int year) { return ((year % 4u) == 0u && (year % 100u) != 0u) || ((year % 400u) == 0u); } +// Implements the k32 Days In Month operation. static unsigned int K32DaysInMonth(unsigned int year, unsigned int month) { static const unsigned char days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; if (month == 2u && K32IsLeapYear(year)) return 29u; @@ -1911,6 +1944,7 @@ static unsigned int K32DaysInMonth(unsigned int year, unsigned int month) { return days[month - 1u]; } +// Implements the k32 Calendar To Epoch Seconds operation. static uint64_t K32CalendarToEpochSeconds(const SYSTEMTIME* st) { uint64_t days = 0; for (unsigned int y = 1970u; y < st->wYear; y++) @@ -1921,17 +1955,20 @@ static uint64_t K32CalendarToEpochSeconds(const SYSTEMTIME* st) { return (((days * 24u) + st->wHour) * 60u + st->wMinute) * 60u + st->wSecond; } +// Implements the k32 Epoch To File Time operation. static uint64_t K32EpochToFileTime(uint64_t epochSeconds, uint32_t nanosecond) { const uint64_t WINDOWS_EPOCH_BIAS_SECONDS = 11644473600ULL; return (epochSeconds + WINDOWS_EPOCH_BIAS_SECONDS) * 10000000ULL + ((uint64_t)nanosecond / 100ULL); } +// Implements the k32 Store File Time operation. static void K32StoreFileTime(FILETIME* ft, uint64_t value) { ft->dwLowDateTime = (DWORD)(value & 0xFFFFFFFFULL); ft->dwHighDateTime = (DWORD)(value >> 32); } +// Returns system Time. __declspec(dllexport) void GetSystemTime(SYSTEMTIME* lpSystemTime) { if (!lpSystemTime) return; @@ -1968,6 +2005,7 @@ __declspec(dllexport) BOOL SystemTimeToFileTime(const SYSTEMTIME* lpSystemTime, return TRUE; } +// Returns system Time As File Time. __declspec(dllexport) void GetSystemTimeAsFileTime(void* lpSystemTimeAsFileTime) { if (!lpSystemTimeAsFileTime) return; @@ -1982,9 +2020,7 @@ __declspec(dllexport) void GetSystemTimeAsFileTime(void* lpSystemTimeAsFileTime) memcpy(lpSystemTimeAsFileTime, &ft, sizeof(ft)); } -// --------------------------------------------------------------------------- -// System Information -// --------------------------------------------------------------------------- +// System Information. typedef struct { union { @@ -2003,6 +2039,7 @@ typedef struct { unsigned short wProcessorRevision; } SYSTEM_INFO; +// Returns system Info. __declspec(dllexport) void GetSystemInfo(SYSTEM_INFO* lpSystemInfo) { if (!lpSystemInfo) return; unsigned char* p = (unsigned char*)lpSystemInfo; @@ -2042,6 +2079,7 @@ __declspec(dllexport) BOOL GetLogicalProcessorInformation(void* Buffer, #define MAX_PATH 260 +// Returns system Directory A. __declspec(dllexport) unsigned int GetSystemDirectoryA(char* lpBuffer, unsigned int uSize) { static const char sysdir[] = "C:\\Windows\\System32"; unsigned int needed = sizeof(sysdir); // includes NUL @@ -2051,6 +2089,7 @@ __declspec(dllexport) unsigned int GetSystemDirectoryA(char* lpBuffer, unsigned return needed - 1; // return length without NUL, matching Win32 } +// Returns windows Directory A. __declspec(dllexport) unsigned int GetWindowsDirectoryA(char* lpBuffer, unsigned int uSize) { static const char windir[] = "C:\\Windows"; unsigned int needed = sizeof(windir); @@ -2060,6 +2099,7 @@ __declspec(dllexport) unsigned int GetWindowsDirectoryA(char* lpBuffer, unsigned return needed - 1; } +// Returns static Env A. static const char* LookupStaticEnvA(const char* name) { if (!name) return NULL; if (strcmp(name, "HOME") == 0) return "."; @@ -2090,41 +2130,42 @@ __declspec(dllexport) DWORD GetEnvironmentVariableA(const char* lpName, char* lp return len; } +// Returns environment Strings. __declspec(dllexport) char* GetEnvironmentStrings(void) { // Double-NUL-terminated environment block. static char env[] = "HOME=.\0USERPROFILE=.\0HOMEDRIVE=C:\0HOMEPATH=\\\0\0"; return env; } +// Releases environment Strings A. __declspec(dllexport) BOOL FreeEnvironmentStringsA(char* penv) { (void)penv; return TRUE; } +// Returns environment Strings W. __declspec(dllexport) unsigned short* GetEnvironmentStringsW(void) { static unsigned short emptyEnvW[2] = { 0, 0 }; return emptyEnvW; } +// Releases environment Strings W. __declspec(dllexport) BOOL FreeEnvironmentStringsW(unsigned short* penv) { (void)penv; return TRUE; } -// --------------------------------------------------------------------------- -// Handle / Error helpers -// --------------------------------------------------------------------------- +// Handle / Error helpers. __declspec(dllexport) unsigned int SetErrorMode(unsigned int uMode) { (void)uMode; return 0; // previous mode } +// Updates handle Count. __declspec(dllexport) unsigned int SetHandleCount(unsigned int uNumber) { return uNumber < 256 ? 256 : uNumber; } -// --------------------------------------------------------------------------- -// File helpers -// --------------------------------------------------------------------------- +// File helpers. #define FILE_TYPE_UNKNOWN 0x0000 #define FILE_TYPE_DISK 0x0001 @@ -2135,6 +2176,7 @@ __declspec(dllexport) unsigned int SetHandleCount(unsigned int uNumber) { #define STD_OUTPUT_HANDLE ((DWORD)-11) #define STD_ERROR_HANDLE ((DWORD)-12) +// Returns file Type. __declspec(dllexport) DWORD GetFileType(HANDLE hFile) { if (!hFile || hFile == INVALID_HANDLE_VALUE) return FILE_TYPE_UNKNOWN; if (K32IsStdHandleValue(hFile, STD_INPUT_HANDLE) || @@ -2144,19 +2186,19 @@ __declspec(dllexport) DWORD GetFileType(HANDLE hFile) { return FILE_TYPE_DISK; } -// --------------------------------------------------------------------------- -// Exception Handling & Debugging -// --------------------------------------------------------------------------- +// Exception Handling & Debugging. #define EXCEPTION_CONTINUE_SEARCH 0 #define EXCEPTION_EXECUTE_HANDLER 1 +// Implements the add Vectored Exception Handler operation. __declspec(dllexport) void* AddVectoredExceptionHandler(unsigned long First, void* Handler) { (void)First; (void)Handler; // Return a non-NULL sentinel so callers can pass it to RemoveVectoredExceptionHandler. return (void*)(uintptr_t)0x56455843UL; // 'VEXC' } +// Releases vectored Exception Handler. __declspec(dllexport) unsigned long RemoveVectoredExceptionHandler(void* Handle) { (void)Handle; return 1; // success @@ -2173,6 +2215,7 @@ __declspec(dllexport) void RaiseException(DWORD dwExceptionCode, DWORD dwExcepti typedef struct _EXCEPTION_POINTERS { void* ExceptionRecord; void* ContextRecord; } EXCEPTION_POINTERS; +// Implements the unhandled Exception Filter operation. __declspec(dllexport) long UnhandledExceptionFilter(EXCEPTION_POINTERS* ExceptionInfo) { (void)ExceptionInfo; return EXCEPTION_CONTINUE_SEARCH; @@ -2181,18 +2224,18 @@ __declspec(dllexport) long UnhandledExceptionFilter(EXCEPTION_POINTERS* Exceptio typedef long (*LPTOP_LEVEL_EXCEPTION_FILTER)(EXCEPTION_POINTERS*); __declspec(dllexport) LPTOP_LEVEL_EXCEPTION_FILTER +// Updates unhandled Exception Filter. SetUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpFilter) { (void)lpFilter; return NULL; // previous filter: none } +// Checks whether debugger Present. __declspec(dllexport) BOOL IsDebuggerPresent(void) { return FALSE; } -// --------------------------------------------------------------------------- -// RTL Exception / Unwind (SEH infrastructure - all stubs) -// --------------------------------------------------------------------------- +// RTL Exception / Unwind (SEH infrastructure - all stubs). typedef struct _RUNTIME_FUNCTION { unsigned int BeginAddress; @@ -2207,6 +2250,7 @@ __declspec(dllexport) BOOL RtlAddFunctionTable(RUNTIME_FUNCTION* FunctionTable, return TRUE; } +// Implements the rtl Delete Function Table operation. __declspec(dllexport) BOOL RtlDeleteFunctionTable(RUNTIME_FUNCTION* FunctionTable) { (void)FunctionTable; return TRUE; @@ -2237,6 +2281,7 @@ __declspec(dllexport) void* RtlVirtualUnwind(unsigned long HandlerType, return NULL; } +// Implements the rtl Capture Context operation. __declspec(dllexport) void RtlCaptureContext(void* ContextRecord) { // Zero out the context record so callers don't read garbage. if (!ContextRecord) return; @@ -2254,12 +2299,11 @@ __declspec(dllexport) void RtlUnwindEx(void* TargetFrame, void* TargetIp, while (true) ; } -// --------------------------------------------------------------------------- -// Code Pages & Locale helpers -// --------------------------------------------------------------------------- +// Code Pages & Locale helpers. typedef struct { unsigned int MaxCharSize; unsigned char DefaultChar[2]; unsigned char LeadByte[12]; } CPINFO; +// Returns cP Info. __declspec(dllexport) BOOL GetCPInfo(unsigned int CodePage, CPINFO* lpCPInfo) { (void)CodePage; if (lpCPInfo) { @@ -2271,6 +2315,7 @@ __declspec(dllexport) BOOL GetCPInfo(unsigned int CodePage, CPINFO* lpCPInfo) { return TRUE; } +// Checks whether valid Code Page. __declspec(dllexport) BOOL IsValidCodePage(unsigned int CodePage) { // Acknowledge the two code pages we claim to support. return (CodePage == 1252 || CodePage == 437) ? TRUE : FALSE; @@ -2312,11 +2357,9 @@ __declspec(dllexport) int GetLocaleInfoA(unsigned int Locale, DWORD LCType, return 0; } -// --------------------------------------------------------------------------- // Fiber Local Storage (FLS) // We implement a minimal 64-slot static table so callers that use FLS for // thread-local-ish state don't immediately fail. -// --------------------------------------------------------------------------- #define FLS_MAX_SLOTS 64 #define FLS_OUT_OF_INDEXES 0xFFFFFFFFUL @@ -2324,6 +2367,7 @@ __declspec(dllexport) int GetLocaleInfoA(unsigned int Locale, DWORD LCType, static void* gFlsSlots[FLS_MAX_SLOTS]; static int gFlsUsed[FLS_MAX_SLOTS]; // 0 = free, 1 = allocated +// Implements the fls Alloc operation. __declspec(dllexport) DWORD FlsAlloc(void* lpCallback) { (void)lpCallback; for (int i = 0; i < FLS_MAX_SLOTS; i++) { @@ -2337,6 +2381,7 @@ __declspec(dllexport) DWORD FlsAlloc(void* lpCallback) { return (DWORD)FLS_OUT_OF_INDEXES; } +// Implements the fls Get Value operation. __declspec(dllexport) void* FlsGetValue(DWORD dwFlsIndex) { if (dwFlsIndex >= FLS_MAX_SLOTS || !gFlsUsed[dwFlsIndex]) { gLastError = 87; // ERROR_INVALID_PARAMETER @@ -2345,6 +2390,7 @@ __declspec(dllexport) void* FlsGetValue(DWORD dwFlsIndex) { return gFlsSlots[dwFlsIndex]; } +// Implements the fls Set Value operation. __declspec(dllexport) BOOL FlsSetValue(DWORD dwFlsIndex, void* lpFlsData) { if (dwFlsIndex >= FLS_MAX_SLOTS || !gFlsUsed[dwFlsIndex]) { gLastError = 87; @@ -2354,6 +2400,7 @@ __declspec(dllexport) BOOL FlsSetValue(DWORD dwFlsIndex, void* lpFlsData) { return TRUE; } +// Implements the fls Free operation. __declspec(dllexport) BOOL FlsFree(DWORD dwFlsIndex) { if (dwFlsIndex >= FLS_MAX_SLOTS || !gFlsUsed[dwFlsIndex]) { gLastError = 87; @@ -2364,10 +2411,9 @@ __declspec(dllexport) BOOL FlsFree(DWORD dwFlsIndex) { return TRUE; } -// --------------------------------------------------------------------------- // Pointer encoding (security cookie obfuscation) // We have no security cookie; return the pointer unchanged. -// --------------------------------------------------------------------------- __declspec(dllexport) void* EncodePointer(void* Ptr) { return Ptr; } +// Implements the decode Pointer operation. __declspec(dllexport) void* DecodePointer(void* Ptr) { return Ptr; } diff --git a/code/user/personalities/win32/ole32.c b/code/user/personalities/win32/ole32.c index 5bd9b71..aac9815 100644 --- a/code/user/personalities/win32/ole32.c +++ b/code/user/personalities/win32/ole32.c @@ -1,13 +1,11 @@ -// ole32.c - Win32 COM / OLE stubs -// No COM infrastructure at this stage; all functions fail gracefully. +// Win32 OLE compatibility stubs. This file satisfies applications that probe COM initialization paths. + #include #include #include #include -// --------------------------------------------------------------------------- -// Types -// --------------------------------------------------------------------------- +// Types. typedef long HRESULT; typedef void* IUnknown; @@ -34,26 +32,23 @@ typedef struct { void* punkVal; unsigned char bVal; unsigned int ulVal; - // ... (only common fields; full union is ~16 bytes) + // ... (only common fields; full union is ~16 bytes). unsigned char padding[16]; }; } PROPVARIANT; -// --------------------------------------------------------------------------- -// COM initialisation -// --------------------------------------------------------------------------- +// COM initialisation. __declspec(dllexport) HRESULT CoInitializeEx(void* reserved, unsigned long coInit) { (void)reserved; (void)coInit; return S_OK; // Pretend success; no actual apartment is created. } +// Implements the co Uninitialize operation. __declspec(dllexport) void CoUninitialize(void) { // No-op. } -// --------------------------------------------------------------------------- -// Object creation -// --------------------------------------------------------------------------- +// Object creation. __declspec(dllexport) HRESULT CoCreateInstance(const GUID* clsid, IUnknown* outer, unsigned long ctx, const GUID* iid, void** ppv) { @@ -62,16 +57,12 @@ __declspec(dllexport) HRESULT CoCreateInstance(const GUID* clsid, IUnknown* oute return E_NOTIMPL; } -// --------------------------------------------------------------------------- -// Memory -// --------------------------------------------------------------------------- +// Memory. __declspec(dllexport) void CoTaskMemFree(void* pv) { if (pv) free(pv); } -// --------------------------------------------------------------------------- -// PROPVARIANT -// --------------------------------------------------------------------------- +// PROPVARIANT. __declspec(dllexport) HRESULT PropVariantClear(PROPVARIANT* pvar) { if (!pvar) return E_NOTIMPL; // Zero the entire structure; no deep release needed for stub types. diff --git a/code/user/personalities/win32/user32.c b/code/user/personalities/win32/user32.c index 5fbb43f..78091ae 100644 --- a/code/user/personalities/win32/user32.c +++ b/code/user/personalities/win32/user32.c @@ -1,4 +1,5 @@ -// user32.c - Win32 User Interface +// Win32 user32 compatibility stubs. This file provides windowing and message APIs that applications may probe. + #include #include #include @@ -14,13 +15,14 @@ typedef struct tagPAINTSTRUCT { } PAINTSTRUCT; +// Implements the user32 Debug Print A operation. static void User32DebugPrintA(const char* s) { if (!s) return; SYS_PRINT_DEBUG_REQUEST req = { SysSvFromCstr(s) }; SysPrintDebug(&req); } -// --- Painting Functions --- +// --- Painting Functions ---. __declspec(dllexport) HDC BeginPaint(HWND hwnd, PAINTSTRUCT* lpPaint) { (void)hwnd; if (lpPaint) { @@ -30,20 +32,24 @@ __declspec(dllexport) HDC BeginPaint(HWND hwnd, PAINTSTRUCT* lpPaint) { return (HDC)1; } +// Implements the end Paint operation. __declspec(dllexport) BOOL EndPaint(HWND hwnd, const PAINTSTRUCT* lp) { (void)hwnd; (void)lp; return 1; } -// --- Message Loop Stubs --- +// --- Message Loop Stubs ---. __declspec(dllexport) int GetMessage(void* m, HWND h, uint32_t f, uint32_t l) { (void)m; (void)h; (void)f; (void)l; SysYield(); return 0; } +// Returns message. __declspec(dllexport) int PeekMessage(void* m, HWND h, uint32_t f, uint32_t l, uint32_t r) { (void)m; (void)h; (void)f; (void)l; (void)r; return 0; } +// Dispatches message. __declspec(dllexport) int DispatchMessage(const void* m) { (void)m; return 0; } +// Translates message. __declspec(dllexport) int TranslateMessage(const void* m) { (void)m; return 0; } -// --- Dialogs & UI --- +// --- Dialogs & UI ---. __declspec(dllexport) int MessageBoxA(HWND h, const char* txt, const char* cap, uint32_t type) { (void)h; (void)cap; (void)type; User32DebugPrintA("USER32: MessageBoxA: "); @@ -52,23 +58,29 @@ __declspec(dllexport) int MessageBoxA(HWND h, const char* txt, const char* cap, return 1; // IDOK } -// --- Window Queries --- +// --- Window Queries ---. __declspec(dllexport) HWND GetDesktopWindow(void) { return (HWND)0; } +// Returns active Window. __declspec(dllexport) HWND GetActiveWindow(void) { return (HWND)0; } +// Returns top Window. __declspec(dllexport) HWND GetTopWindow(HWND hwnd){ (void)hwnd; return (HWND)0; } +// Returns window. __declspec(dllexport) HWND GetWindow(HWND hwnd, unsigned int cmd) { (void)hwnd; (void)cmd; return (HWND)0; } +// Returns window Long A. __declspec(dllexport) long GetWindowLongA(HWND hwnd, int index) { (void)hwnd; (void)index; return 0; } +// Returns window Long Ptr A. __declspec(dllexport) intptr_t GetWindowLongPtrA(HWND hwnd, int index) { (void)hwnd; (void)index; return 0; } +// Returns window Thread Process Id. __declspec(dllexport) unsigned long GetWindowThreadProcessId(HWND hwnd, unsigned long* pid) { (void)hwnd; if (pid) *pid = 1; diff --git a/code/user/personalities/win32/winmm.c b/code/user/personalities/win32/winmm.c index 30cc01b..79eaea3 100644 --- a/code/user/personalities/win32/winmm.c +++ b/code/user/personalities/win32/winmm.c @@ -1,12 +1,10 @@ -// winmm.c - Win32 multimedia: waveform audio, timer -// Stubs only; no audio hardware access at this stage. +// Win32 multimedia compatibility stubs. This file provides minimal timing and sound API entry points. + #include #include #include -// --------------------------------------------------------------------------- -// Types -// --------------------------------------------------------------------------- +// Types. typedef unsigned int MMRESULT; typedef void* HWAVEOUT; @@ -48,17 +46,13 @@ typedef struct { } u; } MMTIME; -// --------------------------------------------------------------------------- -// Timer -// --------------------------------------------------------------------------- +// Timer. __declspec(dllexport) unsigned long timeGetTime(void) { return (unsigned long)(SysGetTick() / 1000u); } -// --------------------------------------------------------------------------- -// Waveform audio (stubs - no audio hardware at this stage) -// --------------------------------------------------------------------------- +// Waveform audio (stubs - no audio hardware at this stage). __declspec(dllexport) MMRESULT waveOutOpen(HWAVEOUT* phwo, unsigned int deviceId, const WAVEFORMATEX* fmt, uintptr_t callback, @@ -68,6 +62,7 @@ __declspec(dllexport) MMRESULT waveOutOpen(HWAVEOUT* phwo, unsigned int deviceId return MMSYSERR_NOTSUPPORTED; } +// Implements the wave Out Close operation. __declspec(dllexport) MMRESULT waveOutClose(HWAVEOUT hwo) { (void)hwo; return MMSYSERR_NOERROR; } @@ -82,22 +77,27 @@ __declspec(dllexport) MMRESULT waveOutUnprepareHeader(HWAVEOUT hwo, WAVEHDR* hdr (void)hwo; (void)hdr; (void)size; return MMSYSERR_NOERROR; } +// Implements the wave Out Write operation. __declspec(dllexport) MMRESULT waveOutWrite(HWAVEOUT hwo, WAVEHDR* hdr, unsigned int size) { (void)hwo; (void)hdr; (void)size; return MMSYSERR_NOTSUPPORTED; } +// Implements the wave Out Pause operation. __declspec(dllexport) MMRESULT waveOutPause(HWAVEOUT hwo) { (void)hwo; return MMSYSERR_NOERROR; } +// Implements the wave Out Restart operation. __declspec(dllexport) MMRESULT waveOutRestart(HWAVEOUT hwo) { (void)hwo; return MMSYSERR_NOERROR; } +// Implements the wave Out Reset operation. __declspec(dllexport) MMRESULT waveOutReset(HWAVEOUT hwo) { (void)hwo; return MMSYSERR_NOERROR; } +// Implements the wave Out Set Volume operation. __declspec(dllexport) MMRESULT waveOutSetVolume(HWAVEOUT hwo, unsigned long volume) { (void)hwo; (void)volume; return MMSYSERR_NOTSUPPORTED; } @@ -109,16 +109,15 @@ __declspec(dllexport) MMRESULT waveOutGetPosition(HWAVEOUT hwo, MMTIME* mmt, return MMSYSERR_NOERROR; } -// --------------------------------------------------------------------------- // Timer resolution control // No hardware timer reprogramming at this stage; pretend success so callers // that wrap their audio/game loop in timeBeginPeriod(1) don't bail out. -// --------------------------------------------------------------------------- __declspec(dllexport) MMRESULT timeBeginPeriod(unsigned int uPeriod) { (void)uPeriod; return MMSYSERR_NOERROR; } +// Implements the time End Period operation. __declspec(dllexport) MMRESULT timeEndPeriod(unsigned int uPeriod) { (void)uPeriod; return MMSYSERR_NOERROR; diff --git a/code/user/runtime/heap.c b/code/user/runtime/heap.c index 9320430..629a180 100644 --- a/code/user/runtime/heap.c +++ b/code/user/runtime/heap.c @@ -1,4 +1,5 @@ -// heap.c - user-mode page-backed heap +// User-mode page-backed heap. This file owns segment allocation, block splitting, coalescing, and exported allocation primitives. + #include #include #include @@ -8,11 +9,10 @@ #define USER_HEAP_PAGE_SIZE 4096u #define USER_HEAP_MIN_PAGES 16u #define USER_HEAP_ALIGN 16u -#define USER_HEAP_MAGIC 0x48424C4Bu /* KLBH */ +#define USER_HEAP_MAGIC 0x48424C4Bu // KLBH. + +// The alignment mask must be pointer-sized because a 32-bit mask would truncate high user virtual addresses. -/* - * Keep the mask pointer-sized. A 32-bit unsigned mask truncates high VA bits. - */ #define ALIGN_UP(v, a) (((v) + ((uintptr_t)(a) - 1)) & ~((uintptr_t)(a) - 1)) typedef struct HEAP_BLOCK { @@ -34,29 +34,35 @@ typedef struct HEAP_SEGMENT { static volatile long gHeapLock; static HEAP_SEGMENT* gSegments; +// Acquires the process-local heap lock. static void HeapLock(void) { while (_InterlockedCompareExchange(&gHeapLock, 1, 0) != 0) _mm_pause(); _ReadWriteBarrier(); } +// Releases the process-local heap lock. static void HeapUnlock(void) { _ReadWriteBarrier(); _InterlockedExchange(&gHeapLock, 0); } +// Rounds requested allocation sizes up to the heap alignment while preserving non-zero allocation semantics. static size_t AlignSize(size_t size) { return ALIGN_UP(size ? size : 1, USER_HEAP_ALIGN); } +// Returns the user-visible payload address for a heap block. static void* BlockPayload(HEAP_BLOCK* block) { return (void*)((uint8_t*)block + sizeof(HEAP_BLOCK)); } +// Returns the heap block header that owns a user-visible payload address. static HEAP_BLOCK* PayloadBlock(void* ptr) { return (HEAP_BLOCK*)((uint8_t*)ptr - sizeof(HEAP_BLOCK)); } +// Finds the heap segment that contains a candidate payload pointer. static HEAP_SEGMENT* SegmentForPointer(void* ptr) { uintptr_t p = (uintptr_t)ptr; for (HEAP_SEGMENT* seg = gSegments; seg; seg = seg->Next) { @@ -68,6 +74,7 @@ static HEAP_SEGMENT* SegmentForPointer(void* ptr) { return (HEAP_SEGMENT*)0; } +// Splits a free block only when the tail can hold another aligned allocation. static void SplitBlock(HEAP_BLOCK* block, size_t size) { size_t aligned = AlignSize(size); if (block->Size < aligned + sizeof(HEAP_BLOCK) + USER_HEAP_ALIGN) @@ -85,6 +92,7 @@ static void SplitBlock(HEAP_BLOCK* block, size_t size) { block->Next = tail; } +// Implements the coalesce Block operation. static void CoalesceBlock(HEAP_BLOCK* block) { if (block->Next && block->Next->Magic == USER_HEAP_MAGIC && block->Next->Free) { HEAP_BLOCK* next = block->Next; @@ -101,6 +109,7 @@ static void CoalesceBlock(HEAP_BLOCK* block) { } } +// Implements the add Segment operation. static HEAP_SEGMENT* AddSegment(size_t payloadSize) { size_t need = sizeof(HEAP_SEGMENT) + sizeof(HEAP_BLOCK) + AlignSize(payloadSize); size_t pages = (need + USER_HEAP_PAGE_SIZE - 1) / USER_HEAP_PAGE_SIZE; @@ -130,6 +139,7 @@ static HEAP_SEGMENT* AddSegment(size_t payloadSize) { return seg; } +// Releases segment If Empty. static void RemoveSegmentIfEmpty(HEAP_SEGMENT* seg) { if (!seg || !seg->First || !seg->First->Free || seg->First->Prev || seg->First->Next) return; @@ -141,6 +151,7 @@ static void RemoveSegmentIfEmpty(HEAP_SEGMENT* seg) { SysFreeVm(seg); } +// Implements the malloc operation. void* _malloc(size_t size) { if (!size) return 0; size = AlignSize(size); @@ -166,6 +177,7 @@ void* _malloc(size_t size) { } } +// Releases the requested object. void _free(void* ptr) { if (!ptr) return; @@ -188,6 +200,7 @@ void _free(void* ptr) { HeapUnlock(); } +// Implements the calloc operation. void* _calloc(size_t count, size_t size) { if (count && size > ((size_t)-1) / count) return 0; @@ -197,6 +210,7 @@ void* _calloc(size_t count, size_t size) { return ptr; } +// Implements the realloc operation. void* _realloc(void* ptr, size_t newSize) { if (!ptr) return _malloc(newSize); if (!newSize) { diff --git a/code/user/runtime/heap_exports.c b/code/user/runtime/heap_exports.c index 126c0ae..a4d128c 100644 --- a/code/user/runtime/heap_exports.c +++ b/code/user/runtime/heap_exports.c @@ -1,8 +1,4 @@ -// heap_exports.c - public CRT allocator names -// Intentionally includes nothing. MSVC/UCRT headers declare malloc/free with -// compiler attributes that conflict with /Gz in this freestanding build. -// Keep the real heap implementation in heap.c under private names and expose -// only these tiny forwarding thunks here. +// User-mode heap exports. This file exposes allocation entry points expected by user personality DLLs. #ifdef USER_HEAP_EXPORTS #define HEAP_EXPORT __declspec(dllexport) diff --git a/code/user/system/init/init.c b/code/user/system/init/init.c index 344c666..25545cd 100644 --- a/code/user/system/init/init.c +++ b/code/user/system/init/init.c @@ -1,4 +1,5 @@ -// init.c - first user-mode process +// Init support. + #include #include #include @@ -6,24 +7,25 @@ #define STATUS_SUCCESS 0u +// Implements the itoa operation. void itoa(int num, char* str) { int i = 0; int is_negative = 0; - // Handle 0 explicitly + // Handle 0 explicitly. if (num == 0) { str[i++] = '0'; str[i] = '\0'; return; } - // Handle negative numbers + // Handle negative numbers. if (num < 0) { is_negative = 1; num = -num; } - // Process individual digits (result is in reverse) + // Process individual digits (result is in reverse). while (num != 0) { int rem = num % 10; str[i++] = rem + '0'; @@ -36,7 +38,7 @@ void itoa(int num, char* str) { str[i] = '\0'; // Null terminate - // Reverse the string + // Reverse the string. int start = 0; int end = i - 1; while (start < end) { @@ -48,6 +50,7 @@ void itoa(int num, char* str) { } } +// Implements the debug print operation. static void debug_print(const char* s) { SYS_PRINT_DEBUG_REQUEST req = { SysSvFromCstr(s) }; (void)SysPrintDebug(&req); diff --git a/code/user/tests/async_apc/async_apc.c b/code/user/tests/async_apc/async_apc.c index f72ff47..f45639f 100644 --- a/code/user/tests/async_apc/async_apc.c +++ b/code/user/tests/async_apc/async_apc.c @@ -1,3 +1,5 @@ +// User-mode regression test for async_apc. + #include #include #include @@ -7,16 +9,19 @@ #define EVENT_AUTO_RESET 0u +// Prints the requested operation. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); } +// Opens file. static uint32_t open_file(const char* path, uint32_t* handleOut) { SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut }; return SysOpenFile(&req); } +// Prints hex8. static void print_hex8(uint8_t v) { static const char h[] = "0123456789ABCDEF"; char b[3]; @@ -26,6 +31,7 @@ static void print_hex8(uint8_t v) { print(b); } +// Prints u64. static void print_u64(uint64_t n) { char buf[32]; int i = 0; @@ -46,6 +52,7 @@ typedef struct APC_TEST_STATE { volatile uint64_t Information; } APC_TEST_STATE; +// Implements the file apc operation. static void file_apc(void* context, SYS_IO_STATUS_BLOCK* iosb, uint64_t information) { APC_TEST_STATE* st = (APC_TEST_STATE*)context; st->Status = iosb ? iosb->Status : 0xFFFFFFFFu; @@ -54,6 +61,7 @@ static void file_apc(void* context, SYS_IO_STATUS_BLOCK* iosb, uint64_t informat do { SYS_PRINT_DEBUG_REQUEST req = { SYS_SV_LITERAL("async_apc: user APC callback ran\n") }; SysPrintDebug(&req); } while (0); } +// Runs the requested operation. int main(void) { print("async_apc: start\n"); diff --git a/code/user/tests/async_cancel/async_cancel.c b/code/user/tests/async_cancel/async_cancel.c index 845468a..0df69c7 100644 --- a/code/user/tests/async_cancel/async_cancel.c +++ b/code/user/tests/async_cancel/async_cancel.c @@ -1,3 +1,5 @@ +// User-mode regression test for async_cancel. + #include #include #include @@ -6,16 +8,19 @@ #define EVENT_AUTO_RESET 0u +// Prints the requested operation. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); } +// Opens file. static uint32_t open_file(const char* path, uint32_t* handleOut) { SYS_PATH_HANDLE_REQUEST req = { SysSvFromCstr(path), handleOut }; return SysOpenFile(&req); } +// Prints u64. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -33,6 +38,7 @@ static void print_u64(uint64_t v) { } } +// Runs the requested operation. int main(void) { print("async_cancel: start\n");