#include "bios.h" #include "ioport.h" #include "fw_cfg.h" static void *_fw_cfg_read_blob(int faddr, int fsize, int fdata) { void *addr; int length; fw_cfg_select(faddr); addr = (void *)fw_cfg_readl_le(); fw_cfg_select(fsize); length = fw_cfg_readl_le(); fw_cfg_select(fdata); fw_cfg_read(addr, length); return addr; } /* BX = address of data block * DX = cmdline_addr-setup_addr-16 */ asm("pm16_boot_linux:" ".code16;" "mov $0, %eax; mov %eax, %cr0;" "ljmpl $0xf000, $(1f - 0xf0000); 1:" "mov %bx, %ds; mov %bx, %es;" "mov %bx, %fs; mov %bx, %gs; mov %bx, %ss;" "mov %dx, %sp;" "add $0x20, %bx; pushw %bx;" // push CS "xor %eax, %eax; pushw %ax;" // push IP "xor %ebx, %ebx;" "xor %ecx, %ecx;" "xor %edx, %edx;" "xor %edi, %edi;" "xor %ebp, %ebp;" "lret;" ".code32"); void boot_linux(void) { void *setup_addr, *cmdline_addr; #define fw_cfg_read_blob(f) \ _fw_cfg_read_blob(f##_ADDR, f##_SIZE, f##_DATA) setup_addr = fw_cfg_read_blob(FW_CFG_SETUP); cmdline_addr = fw_cfg_read_blob(FW_CFG_CMDLINE); fw_cfg_read_blob(FW_CFG_INITRD); fw_cfg_read_blob(FW_CFG_KERNEL); asm volatile( "ljmp $0x18, $pm16_boot_linux - 0xf0000" : : "b" (((uintptr_t) setup_addr) >> 4), "d" (cmdline_addr - setup_addr - 16)); panic(); }