lindows/lcrash/lcrash.c

130 lines
3.1 KiB
C

#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");
}