#include "lnxboot.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 = 1, // 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 = 1, .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; } } } [[gnu::section(".text._start"), gnu::naked]] extern void _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"); } [[gnu::section(".text._start")]] void entry() { // get the zero page //boot_params = (struct boot_params*)( // 0x202 - 0x1f1 // + setup_info->jump_offset // + (u64)setup_info); // 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; // construct pointers u8* cmdline_ptr = (u8*)((u64)setup_info->cmd_line_ptr | ((u64)boot_params->ext_cmd_line_ptr << 32)); // check out command line serial_puts(cmdline_ptr); serial_putc('\r'); serial_putc('\n'); // 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. asm ("cli"); asm ("hlt"); }