#include "lnxboot.h" #include "efi/types.h" #include "efi/memmap.h" extern void _start(); [[gnu::section(".lnxhead")]] [[gnu::used]] [[gnu::aligned(1)]] [[gnu::unavailable("not present at runtime. use setup_info instead")]] struct setup_info bzhead = { .setup_sects = 2, // 1 512-byte sector .boot_flag = 0xAA55, .syssize = 16, .jump_instruction = 0xEB, .jump_offset = sizeof(struct setup_info) - __builtin_offsetof(struct setup_info, signature), .signature = 0x53726448, .version = 0x020F, .loadflags = 0x01, // LOADED_HIGH, .kernel_alignment = 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 }; struct setup_info* setup_info; struct boot_params* boot_params; unsigned short serial_port; void outb(unsigned short port, unsigned char value) { asm volatile ( "outb %b0, %1" ::"a" (value) ,"d" (port) ); } void serial_putc(char c) { outb(serial_port, c); } void serial_puts(const char* s) { while (*s) serial_putc(*(s++)); } void serial_put_formatted_u64(u64 v) { if (v == 0) { serial_putc('0'); } else { u64 max = 1; while (v > max) max *= 10; while (v) { serial_putc('0' + (u8)(v / max)); v %= max; max /= 10; } } } /** * 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" "addq $0x1f1, %0" : "=m" (setup_info), "=m" (boot_params) ); asm ("jmp entry"); } 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 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) ); 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 ); FirmwareVendor = EfiTranslatePointer(systab_ptr->FirmwareVendor); while (1) { volatile char* a = FirmwareVendor; } } // -- 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"; //char s_vga_you_fucked_up[] = "YOU FUCKED UP.\n"; //char s_description[] = "A SERIOUS ERROR HAS OCCURED AND LINDOWS HAS STOPPED TO PREVENT FURTHER DAMAGE."; //char s_registers[] = "REGISTERS:"; //char s_call_trace[] = "CALL TRACE:"; //char s_dumpcore[] = "[(D)UMP CORE]"; //char s_poweroff[] = "[(P)OWER OFF]"; //char s_reboot[] = "[(R)EBOOT ]"; // You fucked up. //serial_puts(s_you_fucked_up); //serial_puts(s_description); //serial_putc('\n'); // register dump //serial_puts(s_registers); //serial_putc('\n'); //serial_putc('\n'); // call trace //serial_puts(s_call_trace); //serial_putc('\n'); //serial_putc('\n'); // thing // serial_puts("test\n"); // serial_puts(bzhead.cmd_line_ptr); // Die. Panic("Nothing left to do."); }