[lcrash/cckernel] FIX: don't depend on undefined behavior + fix typo in addend tables

This commit is contained in:
xwashere 2024-04-09 13:18:01 -04:00
parent 8c6bfe0edf
commit d4bb65f49b
Signed by: XWasHere
GPG Key ID: 042F8BFA1B0EF93B
15 changed files with 136 additions and 27 deletions

View File

@ -365,7 +365,7 @@ add_custom_command(OUTPUT lindows_c.img
COMMAND ${CoreUtils_Mkdir_EXECUTABLE} ARGS lindows_c/Users COMMAND ${CoreUtils_Mkdir_EXECUTABLE} ARGS lindows_c/Users
# unmount filesystem # unmount filesystem
COMMAND "umount" ARGS lindows_c COMMAND umount ARGS lindows_c
DEPENDS DEPENDS
lexecutive lcrash lexecutive lcrash

View File

@ -8,7 +8,7 @@ lw_project(lcrash
enable_language(ASM) enable_language(ASM)
lw_add_executable(lcrashkern 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) add_executable(lcrashkernld IMPORTED)
set_property(TARGET lcrashkernld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld) set_property(TARGET lcrashkernld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld)
@ -17,7 +17,7 @@ set_property(TARGET lcrashkern PROPERTY LINK_DEPENDS
$<TARGET_FILE:LindowsCompilerSpec> $<TARGET_FILE:LindowsCompilerSpec>
) )
set_property(TARGET lcrashkern PROPERTY LINK_OPTIONS -nostdlib -Wl,-T,${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld ) 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) target_link_options(lcrashkern PRIVATE -fpic -pie)
add_custom_command( add_custom_command(
@ -45,7 +45,7 @@ lw_add_executable(cckernel
add_executable(cckernelld IMPORTED) add_executable(cckernelld IMPORTED)
set_property(TARGET cckernelld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/setup/compressed/compressed.ld) 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) 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 set_property(SOURCE setup/compressed/cckernel.S PROPERTY OBJECT_DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/lcrashkern.gz ${CMAKE_CURRENT_BINARY_DIR}/lcrashkern.gz
) )

View File

@ -5,13 +5,28 @@
struct AcpiRSDP; struct AcpiRSDP;
struct AcpiXSDT; 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 * ACPI Root System Description Pointer
*/ */
struct [[gnu::packed]] AcpiRSDP { struct [[gnu::packed]] AcpiRSDP {
char Signature[8]; c8 Signature[8];
u8 Checksum; u8 Checksum;
char OEM[6]; c8 OEM[6];
u8 Revision; u8 Revision;
[[gnu::deprecated]] // we dont care :> [[gnu::deprecated]] // we dont care :>
u32 RSDTAddress; u32 RSDTAddress;
@ -20,3 +35,24 @@ struct [[gnu::packed]] AcpiRSDP {
u8 ExtendedChecksum; u8 ExtendedChecksum;
u8 Reserved[3]; 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();

View File

@ -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* EfiTranslatePointer(void* FirmwarePointer) {
void* CurrentEntry = (void*)StoredMemoryMap;
// Scan the memory map for where our thing is // Scan the memory map for where our thing is
for (int i = 0; i < StoredMemoryMapEntryCount; i++) { 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 && if (FirmwarePointer >= Entry->VirtualStart &&
FirmwarePointer < Entry->VirtualStart + 0x1000 * Entry->NumberOfPages) { FirmwarePointer < Entry->VirtualStart + 0x1000 * Entry->NumberOfPages) {
return FirmwarePointer - Entry->VirtualStart + Entry->PhysicalStart; return FirmwarePointer - Entry->VirtualStart + Entry->PhysicalStart;
} }
CurrentEntry += StoredMemoryMapEntrySize;
} }
// Well, we tried // Well, we tried
return -1; return 0;
} }

View File

@ -14,6 +14,7 @@ typedef c16 EfiChar16;
typedef EfiVoid* EfiHandle; typedef EfiVoid* EfiHandle;
#define EFI_SIZEOF_GUID 16
typedef struct _EfiGuid { typedef struct _EfiGuid {
u32 data1; u32 data1;
u16 data2; u16 data2;

View File

@ -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); add_pretty_printer("_EfiGuid", EfiGuidPrinter, lambda val: EfiGuidPrinter(val) if val.type.strip_typedefs().tag == "_EfiGuid" else None);
# --- --- # --- code ---
# def transition_cckernel():

View File

@ -61,7 +61,7 @@ void Panic(const char* message) {
Hang(); Hang();
} }
void entry64() { void entry64(struct boot_params* boot_params) {
while (1) {}; while (1) {};
Panic("HELLO WORLD."); Panic("HELLO WORLD.");

View File

@ -131,7 +131,7 @@ struct [[gnu::packed]] boot_params {
u8 reserved0[0x4]; u8 reserved0[0x4];
void* tboot_addr; void* tboot_addr;
struct ist_info ist_info; struct ist_info ist_info;
struct acpi_rsdp* acpi_rsdp_addr; struct AcpiRSDP* acpi_rsdp_addr;
u8 reserved1[0x8]; u8 reserved1[0x8];
u8 hd0_info[0x10]; u8 hd0_info[0x10];
u8 hd1_info[0x10]; u8 hd1_info[0x10];
@ -162,3 +162,13 @@ struct [[gnu::packed]] boot_params {
u8 reserved5[0x30]; u8 reserved5[0x30];
u8 eddbuf[0x1ec]; u8 eddbuf[0x1ec];
}; };
/**
* Setup info provided by cckernel
*/
extern struct setup_info* BootSetupInfo;
/**
* Boot params provided by cckernel
*/
extern struct boot_params* BootBootParams;

View File

@ -1,7 +1,49 @@
#include "elf.h" #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();
} }

View File

@ -1,9 +1,18 @@
#pragma once #pragma once
#include "../../types.h" #include "../../types.h"
#include "../../lnxboot.h"
[[packed]] #define PT_NULL 0
struct Elf64_Ehdr { #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]; c8 e_ident[16];
u16 e_type; u16 e_type;
u16 e_machine; u16 e_machine;
@ -20,8 +29,7 @@ struct Elf64_Ehdr {
u16 e_shstrndx; u16 e_shstrndx;
}; };
[[packed]] struct [[gnu::packed]] Elf64_Phdr {
struct Elf64_Phdr {
u32 p_type; u32 p_type;
u32 p_flags; u32 p_flags;
u64 p_offset; 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 /// 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*);

View File

@ -33,7 +33,7 @@ void GzipPopulateTable(
// Fill in the table in a horribly inefficient manner // Fill in the table in a horribly inefficient manner
Code = 0; Code = 0;
for (u32 Bits = 0; Bits < 15; Bits++) { 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++) { for (int i = 0; i < CodeCounts[Bits]; i++) {
// Take the next symbol // Take the next symbol
Code = NextSym[Bits]; Code = NextSym[Bits];
@ -93,7 +93,7 @@ uptr GzipDecompress(c8* Input, uptr InputSize, c8* Output) {
const u32 DistanceAddends[30] = { 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, 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; void* Location = (void*)Input;

View File

@ -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); uptr BinaryLength = GzipDecompress(cckernel, (u8*)&_CC_ecckernel - (u8*)&_CC_cckernel, kernel_load_addr);
// start the kernel // 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 // we fucked up
while (1) {} while (1) {}

View File

@ -1,9 +1,16 @@
/// File with support code for gcc memory stuff /// File with support code for gcc memory stuff
.section ".text", "ax" .section ".text", "ax"
.globl memset .globl memset
memset: memset:
mov %rdx, %rcx mov %rdx, %rcx
mov %sil, %al mov %sil, %al
rep stosb (%rdi) rep stosb (%rdi)
mov %rdi, %rax mov %rdi, %rax
ret ret
.globl memcpy
memcpy:
mov %rdx, %rcx
rep movsb (%rsi), (%rdi)
mov %rdi, %rax
ret

View File

@ -1,9 +1,9 @@
#include "util.h" #include "util.h"
#include "types.h" #include "types.h"
bool CompareMemory(void* Addr1, void* Addr2, uptr Length) { bool CompareMemory(const void* Addr1, const void* Addr2, u32 Length) {
u8* Data1 = Addr1; const u8* Data1 = Addr1;
u8* Data2 = Addr2; const u8* Data2 = Addr2;
for (uptr i = 0; i < Length; i++) { for (uptr i = 0; i < Length; i++) {
if (Data1[i] != Data2[i]) return false; if (Data1[i] != Data2[i]) return false;

View File

@ -5,4 +5,4 @@
/** /**
* Compare the data at two memory addresses * 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);