diff --git a/src/firmware/multiboot.c b/src/firmware/multiboot.c index c6b3923..4a272f4 100644 --- a/src/firmware/multiboot.c +++ b/src/firmware/multiboot.c @@ -43,19 +43,104 @@ static struct { char *modules[16]; } config; -void -multiboot_init(char *kernel_path, char *initrd_path, char *cmdline) { - config.kernel = kernel_path; - config.cmdline = cmdline; +static +int +multiboot_parse_image(const char *image, struct multiboot_header *hdr) { + FILE *f; + uint32_t *head; + size_t bytes; + int i, ret = -1; + + f = fopen(image, "r"); + if (!f) { + fprintf(stderr, "Failed to load kernel image: %s", strerror(errno)); + return -1; + } + + head = malloc(MULTIBOOT_SEARCH); + if (!head) + return -2; + + bytes = fread(head, 1, MULTIBOOT_SEARCH, f); + + /* Search Multiboot magic */ + for (i = 0; i < bytes / sizeof(*head); i++) { + if (head[i] == MULTIBOOT_HEADER_MAGIC) { + memcpy(hdr, &head[i]); - int i = 0; - config.modules[i++] = initrd_path; - config.modules[i++] = NULL; + /* Verify checksum */ + ret = (hdr->magic + hdr->flags + hdr->checksum == 0) ? 0 : -3; + + break; + } + } + + free(head); + fclose(f); + + return ret; +} + +int +multiboot_init(char *opts[]) { + config.kernel = opts[0]; + config.cmdline = opts[1]; + config.modules = &opts[2]; + + return 0; } uint64_t multiboot(void) { + int ret, i; + char *module; + struct multiboot_header hdr; - return 0; + /* Check integrity and load header of multiboot image */ + ret = multiboot_parse_image(config.kernel, &hdr); + if (ret) + abort(); + + /* Load OS image (kernel) */ + ret = multiboot_load_kernel(config.kernel, hdr.load_addr, hdr.load_end_addr); + if (ret) + abort(); + + /* Load modules (initrd..) */ + for (i = 0; i < 16 && module = config.modules[i]; i++) { + FILE *f = fopen(module, "r"); + if (f) { + multiboot_load_module(module); + } + else { + fprintf(stderr, "Failed to open module: %s\n", module); + } + } + + /* Prepare machine state. See: Section 3.2 of Multiboot spec 0.6 */ + xh_vcpu_reset(0); + + xh_vm_set_desc(0, VM_REG_GUEST_GDTR, BASE_GDT, 0x1f, 0); + xh_vm_set_desc(0, VM_REG_GUEST_CS, 0, 0xffffffff, 0xc09b); + xh_vm_set_desc(0, VM_REG_GUEST_DS, 0, 0xffffffff, 0xc093); + xh_vm_set_desc(0, VM_REG_GUEST_ES, 0, 0xffffffff, 0xc093); + xh_vm_set_desc(0, VM_REG_GUEST_SS, 0, 0xffffffff, 0xc093); + + xh_vm_set_register(0, VM_REG_GUEST_CS, 0x10); + xh_vm_set_register(0, VM_REG_GUEST_DS, 0x18); + xh_vm_set_register(0, VM_REG_GUEST_ES, 0x18); + xh_vm_set_register(0, VM_REG_GUEST_SS, 0x18); + + xh_vm_set_register(0, VM_REG_GUEST_CR0, CR0_PE); + xh_vm_set_register(0, VM_REG_GUEST_RFLAGS, 0); + + xh_vm_set_register(0, VM_REG_GUEST_RBP, 0); + xh_vm_set_register(0, VM_REG_GUEST_RDI, 0); + xh_vm_set_register(0, VM_REG_GUEST_RBX, /* MB info struct */); + xh_vm_set_register(0, VM_REG_GUEST_RSI, ); + xh_vm_set_register(0, VM_REG_GUEST_RIP, ); + xh_vm_set_register(0, VM_REG_GUEST_RAX, 0x2BADB002); + + return kernel.base; }