From d4bb65f49b42da1f6db897da20cc7d96f2ec8381 Mon Sep 17 00:00:00 2001 From: xwashere Date: Tue, 9 Apr 2024 13:18:01 -0400 Subject: [PATCH] [lcrash/cckernel] FIX: don't depend on undefined behavior + fix typo in addend tables --- CMakeLists.txt | 2 +- lcrash/CMakeLists.txt | 6 ++--- lcrash/acpi/acpi.h | 40 +++++++++++++++++++++++++++-- lcrash/efi/memmap.c | 10 +++++--- lcrash/efi/types.h | 1 + lcrash/gdb/autorun.py | 3 ++- lcrash/lcrash.c | 2 +- lcrash/lnxboot.h | 12 ++++++++- lcrash/setup/compressed/elf.c | 46 ++++++++++++++++++++++++++++++++-- lcrash/setup/compressed/elf.h | 18 +++++++++---- lcrash/setup/compressed/gzip.c | 4 +-- lcrash/setup/compressed/main.c | 2 +- lcrash/setup/compressed/mem.S | 9 ++++++- lcrash/util.c | 6 ++--- lcrash/util.h | 2 +- 15 files changed, 136 insertions(+), 27 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ddc8c4..8f4ec08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -365,7 +365,7 @@ add_custom_command(OUTPUT lindows_c.img COMMAND ${CoreUtils_Mkdir_EXECUTABLE} ARGS lindows_c/Users # unmount filesystem - COMMAND "umount" ARGS lindows_c + COMMAND umount ARGS lindows_c DEPENDS lexecutive lcrash diff --git a/lcrash/CMakeLists.txt b/lcrash/CMakeLists.txt index f8ddf26..66ef418 100644 --- a/lcrash/CMakeLists.txt +++ b/lcrash/CMakeLists.txt @@ -8,7 +8,7 @@ lw_project(lcrash enable_language(ASM) lw_add_executable(lcrashkern - SOURCES lcrash.c util.c efi/guid.c efi/memmap.c gdb/gdb.c + SOURCES main.c util.c lnxboot.c acpi/acpi.c efi/efi.c efi/guid.c efi/memmap.c gdb/gdb.c ) add_executable(lcrashkernld IMPORTED) set_property(TARGET lcrashkernld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld) @@ -17,7 +17,7 @@ set_property(TARGET lcrashkern PROPERTY LINK_DEPENDS $ ) set_property(TARGET lcrashkern PROPERTY LINK_OPTIONS -nostdlib -Wl,-T,${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld ) -target_compile_options(lcrashkern PRIVATE -ggdb -fpic -pie) +target_compile_options(lcrashkern PRIVATE -ggdb -fpic -pie -Wall -fanalyzer) target_link_options(lcrashkern PRIVATE -fpic -pie) add_custom_command( @@ -45,7 +45,7 @@ lw_add_executable(cckernel add_executable(cckernelld IMPORTED) set_property(TARGET cckernelld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/setup/compressed/compressed.ld) set_property(TARGET cckernel PROPERTY LINK_OPTIONS -nostdlib -Wl,-T,${CMAKE_CURRENT_SOURCE_DIR}/setup/compressed/compressed.ld) -target_compile_options(cckernel PRIVATE -ggdb -mno-sse -mno-avx) # disable generating SIMD code since we haven't configured it at this stage of the boot thing +target_compile_options(cckernel PRIVATE -ggdb -mno-sse -mno-avx -Wall -fanalyzer) # disable generating SIMD code since we haven't configured it at this stage of the boot thing set_property(SOURCE setup/compressed/cckernel.S PROPERTY OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/lcrashkern.gz ) diff --git a/lcrash/acpi/acpi.h b/lcrash/acpi/acpi.h index 4ee288d..9befbf2 100644 --- a/lcrash/acpi/acpi.h +++ b/lcrash/acpi/acpi.h @@ -5,13 +5,28 @@ struct AcpiRSDP; struct AcpiXSDT; +/** + * Common ACPI table header + */ +struct AcpiSDTHeader { + c8 Signature[4]; + u32 Length; + u8 Revision; + u8 Checksum; + c8 OEMID[6]; + c8 OEMTableID[6]; + u32 OEMRevision; + u32 CreatorID; + u32 CreatorRevision; +}; + /** * ACPI Root System Description Pointer */ struct [[gnu::packed]] AcpiRSDP { - char Signature[8]; + c8 Signature[8]; u8 Checksum; - char OEM[6]; + c8 OEM[6]; u8 Revision; [[gnu::deprecated]] // we dont care :> u32 RSDTAddress; @@ -20,3 +35,24 @@ struct [[gnu::packed]] AcpiRSDP { u8 ExtendedChecksum; u8 Reserved[3]; }; + +/** + * The table of tables + */ +struct AcpiXSDT { + struct AcpiSDTHeader Header; + + /// Pointers to other tables + [[gnu::aligned(4)]] + u64 Tables[]; +}; + +/** + * Initialize ACPI code + */ +void AcpiInitialize(); + +/** + * Check if ACPI is present + */ +bool AcpiPresent(); diff --git a/lcrash/efi/memmap.c b/lcrash/efi/memmap.c index c486cdd..91f020a 100644 --- a/lcrash/efi/memmap.c +++ b/lcrash/efi/memmap.c @@ -15,19 +15,23 @@ void EfiLoadStoredMemoryMap( } /** - * Translate a pointer using what we can recover from the UEFI memory map, may return something invalid. + * Translate a pointer using what we can recover from the UEFI memory map, returns 0 if not found */ void* EfiTranslatePointer(void* FirmwarePointer) { + void* CurrentEntry = (void*)StoredMemoryMap; + // Scan the memory map for where our thing is for (int i = 0; i < StoredMemoryMapEntryCount; i++) { - struct EfiMemoryDescription* Entry = (struct EfiMemoryDescription*)((void*)StoredMemoryMap + i * StoredMemoryMapEntrySize); + struct EfiMemoryDescription* Entry = (struct EfiMemoryDescription*)CurrentEntry; if (FirmwarePointer >= Entry->VirtualStart && FirmwarePointer < Entry->VirtualStart + 0x1000 * Entry->NumberOfPages) { return FirmwarePointer - Entry->VirtualStart + Entry->PhysicalStart; } + + CurrentEntry += StoredMemoryMapEntrySize; } // Well, we tried - return -1; + return 0; } diff --git a/lcrash/efi/types.h b/lcrash/efi/types.h index 9a37787..eaf559c 100644 --- a/lcrash/efi/types.h +++ b/lcrash/efi/types.h @@ -14,6 +14,7 @@ typedef c16 EfiChar16; typedef EfiVoid* EfiHandle; +#define EFI_SIZEOF_GUID 16 typedef struct _EfiGuid { u32 data1; u16 data2; diff --git a/lcrash/gdb/autorun.py b/lcrash/gdb/autorun.py index 2a235b2..5736f21 100644 --- a/lcrash/gdb/autorun.py +++ b/lcrash/gdb/autorun.py @@ -27,4 +27,5 @@ def add_pretty_printer(name, printer, custom_lookup = None): add_pretty_printer("_EfiGuid", EfiGuidPrinter, lambda val: EfiGuidPrinter(val) if val.type.strip_typedefs().tag == "_EfiGuid" else None); -# --- --- +# --- code --- +# def transition_cckernel(): diff --git a/lcrash/lcrash.c b/lcrash/lcrash.c index 66b8fe4..0be9bd8 100644 --- a/lcrash/lcrash.c +++ b/lcrash/lcrash.c @@ -61,7 +61,7 @@ void Panic(const char* message) { Hang(); } -void entry64() { +void entry64(struct boot_params* boot_params) { while (1) {}; Panic("HELLO WORLD."); diff --git a/lcrash/lnxboot.h b/lcrash/lnxboot.h index 9081e0a..6d82888 100644 --- a/lcrash/lnxboot.h +++ b/lcrash/lnxboot.h @@ -131,7 +131,7 @@ struct [[gnu::packed]] boot_params { u8 reserved0[0x4]; void* tboot_addr; struct ist_info ist_info; - struct acpi_rsdp* acpi_rsdp_addr; + struct AcpiRSDP* acpi_rsdp_addr; u8 reserved1[0x8]; u8 hd0_info[0x10]; u8 hd1_info[0x10]; @@ -162,3 +162,13 @@ struct [[gnu::packed]] boot_params { u8 reserved5[0x30]; u8 eddbuf[0x1ec]; }; + +/** + * Setup info provided by cckernel + */ +extern struct setup_info* BootSetupInfo; + +/** + * Boot params provided by cckernel + */ +extern struct boot_params* BootBootParams; diff --git a/lcrash/setup/compressed/elf.c b/lcrash/setup/compressed/elf.c index 92d8954..ad4cbd7 100644 --- a/lcrash/setup/compressed/elf.c +++ b/lcrash/setup/compressed/elf.c @@ -1,7 +1,49 @@ #include "elf.h" -int ElfExecute(void* Binary, void* LoadAddr) { +extern void* memset(void* dest, int ch, uptr count); +extern void* memcpy(void* dest, const void* src, uptr count); + +[[noreturn]] +void ElfExecute(void* Binary, void* LoadAddr, struct boot_params* BootParams) { + struct Elf64_Ehdr* ElfHeader = (struct Elf64_Ehdr*)Binary; + + // Here we would check if we have a valid elf binary + // unfortunately, we would have no way to notify the + // user, so we'll just pray it is + // Hopefully we have progtam headers + void* ProgramHeaders = Binary + ElfHeader->e_phoff; + + // Load everything into memory + for (int i = 0; i < ElfHeader->e_phnum; i++) { + struct Elf64_Phdr* ProgramHeader = (struct Elf64_Phdr*)ProgramHeaders; + + // Only load loadable segments + if (ProgramHeader->p_type == PT_LOAD) { + void* FileStart = Binary + ProgramHeader->p_offset; + void* LoadStart = LoadAddr + ProgramHeader->p_vaddr; + + uptr LoadSize = ProgramHeader->p_memsz; + if (LoadSize > ProgramHeader->p_filesz) LoadSize = ProgramHeader->p_filesz; + + memset(LoadStart, 0, ProgramHeader->p_memsz); + memcpy(LoadStart, FileStart, LoadSize); + } + + ProgramHeaders += ElfHeader->e_phentsize; + } + + // Collect entry point + [[noreturn]] void fake_dont_call(struct boot_params*); // stupid hack + typeof(fake_dont_call)* KernelEntry = LoadAddr + ElfHeader->e_entry; - while (1) {} + // Set boot parameters + struct setup_info* SetupInfo = (void*)BootParams + 0x1f1; + SetupInfo->code32_start = LoadAddr; + + // Enter the kernel + KernelEntry(BootParams); + + // we shouldnt ever end up here + __builtin_unreachable(); } diff --git a/lcrash/setup/compressed/elf.h b/lcrash/setup/compressed/elf.h index ec35c1f..264180a 100644 --- a/lcrash/setup/compressed/elf.h +++ b/lcrash/setup/compressed/elf.h @@ -1,9 +1,18 @@ #pragma once #include "../../types.h" +#include "../../lnxboot.h" -[[packed]] -struct Elf64_Ehdr { +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_TLS 7 + +struct [[gnu::packed]] Elf64_Ehdr { c8 e_ident[16]; u16 e_type; u16 e_machine; @@ -20,8 +29,7 @@ struct Elf64_Ehdr { u16 e_shstrndx; }; -[[packed]] -struct Elf64_Phdr { +struct [[gnu::packed]] Elf64_Phdr { u32 p_type; u32 p_flags; u64 p_offset; @@ -33,4 +41,4 @@ struct Elf64_Phdr { }; /// We don't have space to allocate memory, so we have no idea where we can pass back ELF state, we'll have to do this all at once -int ElfExecute(void* Binary, void* LoadAddr); +void ElfExecute(void* Binary, void* LoadAddr, struct boot_params*); diff --git a/lcrash/setup/compressed/gzip.c b/lcrash/setup/compressed/gzip.c index d8c9176..70badb6 100644 --- a/lcrash/setup/compressed/gzip.c +++ b/lcrash/setup/compressed/gzip.c @@ -33,7 +33,7 @@ void GzipPopulateTable( // Fill in the table in a horribly inefficient manner Code = 0; for (u32 Bits = 0; Bits < 15; Bits++) { - const uptr OutputMask = ~(-1 << Bits); + const uptr OutputMask = ~((uptr)-1 << Bits); for (int i = 0; i < CodeCounts[Bits]; i++) { // Take the next symbol Code = NextSym[Bits]; @@ -93,7 +93,7 @@ uptr GzipDecompress(c8* Input, uptr InputSize, c8* Output) { const u32 DistanceAddends[30] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, - 1537, 2049, 3073, 40097, 6145, 8193, 12289, 15385, 24577 + 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 }; void* Location = (void*)Input; diff --git a/lcrash/setup/compressed/main.c b/lcrash/setup/compressed/main.c index 9a0197f..37b92ee 100644 --- a/lcrash/setup/compressed/main.c +++ b/lcrash/setup/compressed/main.c @@ -23,7 +23,7 @@ void ccmain(void* imgbase, struct boot_params* boot_params) { uptr BinaryLength = GzipDecompress(cckernel, (u8*)&_CC_ecckernel - (u8*)&_CC_cckernel, kernel_load_addr); // start the kernel - ElfExecute(kernel_load_addr, kernel_load_addr + BinaryLength + 0x1000 - BinaryLength % 0x1000); + ElfExecute(kernel_load_addr, kernel_load_addr + BinaryLength + 0x1000 - BinaryLength % 0x1000, boot_params); // we fucked up while (1) {} diff --git a/lcrash/setup/compressed/mem.S b/lcrash/setup/compressed/mem.S index ca4049d..4726041 100644 --- a/lcrash/setup/compressed/mem.S +++ b/lcrash/setup/compressed/mem.S @@ -1,9 +1,16 @@ /// File with support code for gcc memory stuff .section ".text", "ax" - .globl memset + .globl memset memset: mov %rdx, %rcx mov %sil, %al rep stosb (%rdi) mov %rdi, %rax ret + + .globl memcpy +memcpy: + mov %rdx, %rcx + rep movsb (%rsi), (%rdi) + mov %rdi, %rax + ret diff --git a/lcrash/util.c b/lcrash/util.c index 90b4964..e9482cb 100644 --- a/lcrash/util.c +++ b/lcrash/util.c @@ -1,9 +1,9 @@ #include "util.h" #include "types.h" -bool CompareMemory(void* Addr1, void* Addr2, uptr Length) { - u8* Data1 = Addr1; - u8* Data2 = Addr2; +bool CompareMemory(const void* Addr1, const void* Addr2, u32 Length) { + const u8* Data1 = Addr1; + const u8* Data2 = Addr2; for (uptr i = 0; i < Length; i++) { if (Data1[i] != Data2[i]) return false; diff --git a/lcrash/util.h b/lcrash/util.h index 87e110c..80a1988 100644 --- a/lcrash/util.h +++ b/lcrash/util.h @@ -5,4 +5,4 @@ /** * Compare the data at two memory addresses */ -bool CompareMemory(void* Addr1, void* Addr2, uptr Length); +bool CompareMemory(const void* Addr1, const void* Addr2, u32 Length);