From c3773639dbec70a109e5eddc6a729196356ecce1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 20 May 2015 23:46:42 +0200 Subject: boot the kernel Signed-off-by: Paolo Bonzini --- Makefile | 2 ++ cstart.S | 1 + include/bios.h | 2 ++ linuxboot.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 2 +- 5 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 linuxboot.c diff --git a/Makefile b/Makefile index fa43371..4e41822 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,7 @@ obj16-y = e820.o int10.o int15.o obj-y = $(obj16-y) entry.o main.o string.o printf.o cstart.o fw_cfg.o +obj-y += linuxboot.o + all-y = bios.bin CFLAGS := -O2 -Wall -g diff --git a/cstart.S b/cstart.S index 5ca61c8..cef3950 100644 --- a/cstart.S +++ b/cstart.S @@ -25,6 +25,7 @@ gdt32: .quad 0 .quad 0x00cf9b000000ffff // flat 32-bit code segment .quad 0x00cf93000000ffff // flat 32-bit data segment + .quad 0x008f9b0f0000ffff // 16-bit code segment at 0xF0000 gdt32_end: gdt32_descr: diff --git a/include/bios.h b/include/bios.h index bd7f77b..dfc20af 100644 --- a/include/bios.h +++ b/include/bios.h @@ -36,6 +36,8 @@ extern void bios_irq(void); extern void bios_int10(void); extern void bios_int15(void); +extern void boot_linux(void); + extern struct e820map e820; #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) diff --git a/linuxboot.c b/linuxboot.c new file mode 100644 index 0000000..51bfba3 --- /dev/null +++ b/linuxboot.c @@ -0,0 +1,57 @@ +#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(); +} diff --git a/main.c b/main.c index 2378abb..e954d75 100644 --- a/main.c +++ b/main.c @@ -104,6 +104,6 @@ int main(void) // extract_smbios(); // extract_kernel(); // make_bios_readonly(); - // boot_linux(); + boot_linux(); panic(); } -- cgit v1.1