diff --git a/lcrash/CMakeLists.txt b/lcrash/CMakeLists.txt index 01ae86d..d57c1d4 100644 --- a/lcrash/CMakeLists.txt +++ b/lcrash/CMakeLists.txt @@ -6,7 +6,7 @@ lw_project(lcrash ) lw_add_executable(lcrash - SOURCES lcrash.c + SOURCES lcrash.c efi/memmap.c ) add_executable(lcrashld IMPORTED) set_property(TARGET lcrashld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld) @@ -15,3 +15,4 @@ set_property(TARGET lcrash PROPERTY LINK_DEPENDS $ ) set_property(TARGET lcrash PROPERTY LINK_OPTIONS -nostdlib -Wl,-T,${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld) +target_compile_options(lcrash PRIVATE -ggdb) diff --git a/lcrash/lcrash.c b/lcrash/lcrash.c index dc816e6..81e87a7 100644 --- a/lcrash/lcrash.c +++ b/lcrash/lcrash.c @@ -1,4 +1,6 @@ #include "lnxboot.h" +#include "efi/types.h" +#include "efi/memmap.h" extern void _start(); @@ -7,7 +9,7 @@ extern void _start(); [[gnu::aligned(1)]] [[gnu::unavailable("not present at runtime. use setup_info instead")]] struct setup_info bzhead = { - .setup_sects = 1, // 1 512-byte sector + .setup_sects = 2, // 1 512-byte sector .boot_flag = 0xAA55, .syssize = 16, .jump_instruction = 0xEB, @@ -16,7 +18,7 @@ struct setup_info bzhead = { .version = 0x020F, .loadflags = 0x01, // LOADED_HIGH, .kernel_alignment = 1, - .relocatable_kernel = 1, + .relocatable_kernel = 0, .xloadflags = 0x13, // XLF_KERNEL_64 | XLF_CAN_BE_LOADED_ABOVE_4G | XLF_5LEVEL .cmdline_size = 255, // max command line size .init_size = 0x10000 // we dont need THAT much memory @@ -60,8 +62,31 @@ void serial_put_formatted_u64(u64 v) { } } -[[gnu::section(".text._start"), gnu::naked]] +/** + * We can't do anything, just hang. + */ +[[noreturn, gnu::naked]] +void Hang() { + // This should make us hang + asm volatile ( + " cli\n" + "1: hlt\n" + " jmp 1b" + ); +} + +/** + * Congratulations, you panicked twice! + */ +[[noreturn]] +void Panic(const char* message) { + // We don't even do anything with the message, but it's nice to have just in case. + Hang(); +} + +[[gnu::section(".text._start"), gnu::naked, gnu::no_reorder]] extern void _start() { + asm ("jmp _start"); asm ( // grab the setup_info and boot_params locations "mov %%rsi, %1\n" "mov %%rsi, %0\n" @@ -72,27 +97,70 @@ extern void _start() { asm ("jmp entry"); } -[[gnu::section(".text._start")]] +c16* FirmwareVendor = 0; + +/** + * we're in some kind of purgatory between booted and not booted, a lot of devices are currently initialized from the previous + * kernel, but we have no idea where they are, what they are, or how to use them. all we have is the stuff in setup_info and + * boot_params, and whatever we can salvage from the crashed kernel. + */ +[[gnu::section(".text._start"), gnu::no_reorder]] void entry() { - // get the zero page - //boot_params = (struct boot_params*)( - // 0x202 - 0x1f1 - // + setup_info->jump_offset - // + (u64)setup_info); + // get command line from kernel. we likely won't use it, but its nice to have. + u8* cmdline_ptr = (u8*)((u64)setup_info->cmd_line_ptr | ((u64)boot_params->ext_cmd_line_ptr << 32)); + + // do we have efi? + struct EfiSystemTable* systab_ptr = 0; + if (boot_params) { + systab_ptr = (struct EfiSystemTable*)( + (u64)boot_params->efi_info.EfiSystemTable | + ((u64)boot_params->efi_info.EfiSystemTableHigh << 32) + ); - // orignally we would try to import the serial port from the kernel (see kexec tools) - // as you can see, we gave up! - // serial_port = (unsigned short)*(long*)&serial_base; - serial_port = 0x3f8; + EfiLoadStoredMemoryMap( + (struct EfiMemoryDescription*)( + (u64)boot_params->efi_info.EfiMemoryMap | + ((u64)boot_params->efi_info.EfiMemoryMapHigh << 32) + ), // this might be 0, we should probably check ---------------V + boot_params->efi_info.EfiMemoryMapSize / boot_params->efi_info.EfiMemoryDescriptionSize, + boot_params->efi_info.EfiMemoryDescriptionSize + ); - // construct pointers - u8* cmdline_ptr = (u8*)((u64)setup_info->cmd_line_ptr | ((u64)boot_params->ext_cmd_line_ptr << 32)); + FirmwareVendor = EfiTranslatePointer(systab_ptr->FirmwareVendor); + while (1) { + volatile char* a = FirmwareVendor; + } + } - // check out command line - serial_puts(cmdline_ptr); - serial_putc('\r'); - serial_putc('\n'); + // -- find acpi -- + struct AcpiRSDP* AcpiRSDP = 0; + // check bootparams + if (boot_params->acpi_rsdp_addr) AcpiRSDP = boot_params->acpi_rsdp_addr; + + // check efi + if (!AcpiRSDP && systab_ptr && systab_ptr->NumberOfTableEntries) { + volatile void* ConfigurationTable = EfiTranslatePointer(systab_ptr->ConfigurationTable); + } + + // we're playing where's waldo with this stupid fucking tableS + if (!AcpiRSDP) { + for (struct AcpiRSDP* addr = 0x00000000; addr < 0x000FFFFF; addr = (void*)addr + 16) { + if (addr->Signature[0] == 'R' && addr->Signature[1] == 'S' + && addr->Signature[2] == 'D' && addr->Signature[3] == ' ' + && addr->Signature[4] == 'P' && addr->Signature[5] == 'T' + && addr->Signature[6] == 'R' && addr->Signature[7] == ' ') { + AcpiRSDP = addr; + break; + } + } + } + + if (!AcpiRSDP) Panic("Failed to find ACPI RSDP"); + + // do we have acpi? + asm volatile ("ljmp 0"); + // we dont have the privilege of getting a rodata segment. any reads off our stack cause a triple fault // for some fucking reason. allocate our strings and shit on the stack. //char s_you_fucked_up[] = "!!! YOU FUCKED UP !!!\n"; @@ -124,6 +192,5 @@ void entry() { // serial_puts(bzhead.cmd_line_ptr); // Die. - asm ("cli"); - asm ("hlt"); + Panic("Nothing left to do."); } diff --git a/lcrash/lcrash.ld b/lcrash/lcrash.ld index b95e18f..fecff53 100644 --- a/lcrash/lcrash.ld +++ b/lcrash/lcrash.ld @@ -1,24 +1,36 @@ OUTPUT_FORMAT(elf64-x86-64) +ENTRY(_start) + +MEMORY { + code (rx) : ORIGIN = 0x0dfe8000, LENGTH = 0x00001000 + data (rw) : ORIGIN = 0x0dff0000, LENGTH = 0x00001000 +} + SECTIONS { .lnxhead 0x01f1 : ALIGN(1) { *(.lnxhead); } - .rodata 0x900000 : ALIGN(1) { + .rodata : ALIGN(1) { *(.rodata); - } + } > data - .text._start 0x80000000 : ALIGN(1) { + /* this section helps us to coerce the linker into not breaking down because of big addresses */ + .text._start 0xdfe8000 : ALIGN(1) { *(.text._start); - } + } > code - .text : ALIGN(512) { *(.text); } + .text : ALIGN(512) { *(.text); } > code .bss : { *(.bss); } - .kernel_imports 0xFFFFFFFF : { - *(.kernel_imports); - } + .debug_info 0 : { *(.debug_info); } + .debug_abbrev 0 : { *(.debug_abbrev); } + .debug_aranges 0 : { *(.debug_aranges); } + .debug_rnglists 0 : { *(.debug_rnglists); } + .debug_line 0 : { *(.debug_line); } + .debug_str 0 : { *(.debug_str); } + .debug_line_str 0 : { *(.debug_line_str); } /DISCARD/ : { *(*); diff --git a/lcrash/lnxboot.h b/lcrash/lnxboot.h index a745c50..9081e0a 100644 --- a/lcrash/lnxboot.h +++ b/lcrash/lnxboot.h @@ -1,9 +1,7 @@ #pragma once -typedef unsigned char u8; -typedef unsigned short u16; -typedef unsigned int u32; -typedef unsigned long long u64; +#include "types.h" +#include "acpi/acpi.h" struct [[gnu::packed]] setup_info { u8 setup_sects; @@ -61,13 +59,14 @@ struct [[gnu::packed]] screen_info { u16 reserved2; u8 orig_video_lines; u8 orig_video_isVGA; - u8 orig_video_points; + u16 orig_video_points; // linear frame buffer u16 lfb_width; u16 lfb_height; u16 lfb_depth; u32 lfb_base; + u32 lfb_size; u16 cl_magic; u16 cl_offset; u16 lfb_linelength; @@ -79,8 +78,8 @@ struct [[gnu::packed]] screen_info { u8 blue_pos; u8 reserved_size; u8 reserved_pos; - u8 vesapm_seg; - u8 vesapm_off; + u16 vesapm_seg; + u16 vesapm_off; u16 pages; u16 vesa_attributes; u32 capabilities; @@ -106,11 +105,20 @@ struct [[gnu::packed]] edid_info { }; struct [[gnu::packed]] efi_info { - u8 pad[0x20]; + u32 EfiLoaderSignature; + u32 EfiSystemTable; + u32 EfiMemoryDescriptionSize; + u32 EfiMemoryDescriptionVersion; + u32 EfiMemoryMap; + u32 EfiMemoryMapSize; + u32 EfiSystemTableHigh; + u32 EfiMemoryMapHigh; }; struct [[gnu::packed]] e820_entry { - u8 pad; + u64 base; + u64 length; + u32 type; }; struct [[gnu::packed]] edd_info { @@ -123,8 +131,8 @@ struct [[gnu::packed]] boot_params { u8 reserved0[0x4]; void* tboot_addr; struct ist_info ist_info; - void* acpi_rsdp_addr; - u8 reserved1[0x2]; + struct acpi_rsdp* acpi_rsdp_addr; + u8 reserved1[0x8]; u8 hd0_info[0x10]; u8 hd1_info[0x10]; struct sys_desc_table sys_desc_table; @@ -136,7 +144,7 @@ struct [[gnu::packed]] boot_params { /// cmd_line_ptr high 32 bits u32 ext_cmd_line_ptr; u8 reserved2[0x70]; - void* cc_blob_address; + u32 cc_blob_address; struct edid_info edid_info; struct efi_info efi_info; u32 alt_mem_k; @@ -150,7 +158,7 @@ struct [[gnu::packed]] boot_params { u8 sentinel; u8 reserved4[0xa0]; // setup_info lives here! u8 edd_mbr_sig_buffer[0x40]; - u8 e20_table[0xa00]; + struct e820_entry e820_table[128]; u8 reserved5[0x30]; u8 eddbuf[0x1ec]; };