From 6a538ad4f35862db8ddfdeabf45899cac505045f Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Thu, 21 May 2020 23:00:32 -0700 Subject: [PATCH] [boot] Fix several errors getting to kernel * When using the non-allocating version of `get_uefi_mappings` the length was not getting set. Reworked this function. * Having `build_kernel_mem_map` from `bootloader_main_uefi` caused it to get an out of date map key. Moved this function into `efi_main` right before exiting boot services. --- src/boot/loader.cpp | 4 ++-- src/boot/main.cpp | 32 +++++++++++++++++++------------- src/boot/memory.cpp | 36 +++++++++++++----------------------- src/boot/memory.h | 5 ----- 4 files changed, 34 insertions(+), 43 deletions(-) diff --git a/src/boot/loader.cpp b/src/boot/loader.cpp index 847e0ee..9455f50 100644 --- a/src/boot/loader.cpp +++ b/src/boot/loader.cpp @@ -62,11 +62,11 @@ load( console::print(L" Kernel section %d physical: 0x%lx\r\n", i, pages); console::print(L" Kernel section %d virtual: 0x%lx\r\n", i, pheader->vaddr); - // TODO: map these pages into kernel args' page tables - // remember to set appropriate RWX permissions + // TODO: set appropriate RWX permissions paging::map_pages(pml4, args, reinterpret_cast(pages), pheader->vaddr, pheader->mem_size); } + console::print(L" Kernel entrypoint: 0x%lx\r\n", header->entrypoint); return reinterpret_cast(header->entrypoint); } diff --git a/src/boot/main.cpp b/src/boot/main.cpp index acc3af3..7652d93 100644 --- a/src/boot/main.cpp +++ b/src/boot/main.cpp @@ -137,14 +137,18 @@ load_module( /// The main procedure for the portion of the loader that runs while /// UEFI is still in control of the machine. (ie, while the loader still /// has access to boot services. -kernel::entrypoint -bootloader_main_uefi(uefi::handle image, uefi::system_table *st, console &con, size_t *map_key) +kernel::args::header * +bootloader_main_uefi( + uefi::handle image, + uefi::system_table *st, + console &con, + kernel::entrypoint *kentry) { error::uefi_handler handler(con); + status_line status(L"Performing UEFI pre-boot"); uefi::boot_services *bs = st->boot_services; uefi::runtime_services *rs = st->runtime_services; - memory::init_pointer_fixup(bs, rs); kernel::args::header *args = @@ -155,6 +159,10 @@ bootloader_main_uefi(uefi::handle image, uefi::system_table *st, console &con, s args->runtime_services = rs; args->acpi_table = hw::find_acpi_table(st); + memory::mark_pointer_fixup(&args->runtime_services); + for (unsigned i = 0; i < args->num_modules; ++i) + memory::mark_pointer_fixup(reinterpret_cast(&args->modules[i])); + fs::file disk = fs::get_boot_volume(image, bs); load_module(disk, args, L"initrd", L"initrd.img", kernel::args::mod_type::initrd); @@ -162,13 +170,8 @@ bootloader_main_uefi(uefi::handle image, uefi::system_table *st, console &con, s load_module(disk, args, L"kernel", L"jsix.elf", kernel::args::mod_type::kernel); paging::allocate_tables(args, bs); - - kernel::entrypoint kentry = - loader::load(kernel->location, kernel->size, args, bs); - - *map_key = memory::build_kernel_mem_map(args, bs); - - return kentry; + *kentry = loader::load(kernel->location, kernel->size, args, bs); + return args; } } // namespace boot @@ -182,14 +185,17 @@ efi_main(uefi::handle image_handle, uefi::system_table *st) error::cpu_assert_handler handler; console con(st->boot_services, st->con_out); - size_t map_key; - kernel::entrypoint kentry = - bootloader_main_uefi(image_handle, st, con, &map_key); + kernel::entrypoint kentry = nullptr; + kernel::args::header *args = + bootloader_main_uefi(image_handle, st, con, &kentry); + + size_t map_key = memory::build_kernel_mem_map(args, st->boot_services); try_or_raise( st->boot_services->exit_boot_services(image_handle, map_key), L"Failed to exit boot services"); + kentry(args); debug_break(); return uefi::status::unsupported; } diff --git a/src/boot/memory.cpp b/src/boot/memory.cpp index 7d9a44c..70ad356 100644 --- a/src/boot/memory.cpp +++ b/src/boot/memory.cpp @@ -82,20 +82,13 @@ init_pointer_fixup(uefi::boot_services *bs, uefi::runtime_services *rs) void mark_pointer_fixup(void **p) { - if (fixup_pointer_index == 0) { - const size_t count = sizeof(fixup_pointers) / sizeof(void*); - for (size_t i = 0; i < count; ++i) fixup_pointers[i] = 0; - } fixup_pointers[fixup_pointer_index++] = p; } /* void -memory_virtualize(EFI_RUNTIME_SERVICES *runsvc, struct memory_map *map) +virtualize(paging::page_table *pml4, uefi::runtime_services *rs, efi_mem_map *map) { - memory_mark_pointer_fixup((void **)&runsvc); - memory_mark_pointer_fixup((void **)&map); - // Get the pointer to the start of PML4 uint64_t* cr3 = 0; __asm__ __volatile__ ( "mov %%cr3, %0" : "=r" (cr3) ); @@ -146,35 +139,30 @@ can_merge(mem_entry &prev, mem_type type, uefi::memory_descriptor *next) prev.attr == (next->attribute & 0xffffffff); } -efi_mem_map -get_uefi_mappings(bool allocate, uefi::boot_services *bs) +void +get_uefi_mappings(efi_mem_map *map, bool allocate, uefi::boot_services *bs) { status_line(L"Getting UEFI memory map"); - efi_mem_map map; - size_t needs_size = 0; - uefi::status status = bs->get_memory_map( - &needs_size, nullptr, &map.key, &map.size, &map.version); + &map->length, nullptr, &map->key, &map->size, &map->version); if (status != uefi::status::buffer_too_small) error::raise(status, L"Error getting memory map size"); if (allocate) { - map.length = needs_size + 10*map.size; + map->length += 10*map->size; try_or_raise( bs->allocate_pool( - uefi::memory_type::loader_data, map.length, - reinterpret_cast(&map.entries)), + uefi::memory_type::loader_data, map->length, + reinterpret_cast(&map->entries)), L"Allocating space for memory map"); try_or_raise( - bs->get_memory_map(&map.length, map.entries, &map.key, &map.size, &map.version), + bs->get_memory_map(&map->length, map->entries, &map->key, &map->size, &map->version), L"Getting UEFI memory map"); } - - return map; } size_t @@ -182,9 +170,11 @@ build_kernel_mem_map(kernel::args::header *args, uefi::boot_services *bs) { status_line(L"Creating kernel memory map"); - efi_mem_map efi_map = get_uefi_mappings(false, bs); + efi_mem_map efi_map; + get_uefi_mappings(&efi_map, false, bs); size_t map_size = efi_map.num_entries() * sizeof(mem_entry); + kernel::args::mem_entry *kernel_map = nullptr; try_or_raise( bs->allocate_pages( @@ -192,10 +182,10 @@ build_kernel_mem_map(kernel::args::header *args, uefi::boot_services *bs) module_type, bytes_to_pages(map_size), reinterpret_cast(&kernel_map)), - L"Error allocating kernel memory map module space."); + L"Error allocating kernel memory map module space"); bs->set_mem(kernel_map, map_size, 0); - efi_map = get_uefi_mappings(true, bs); + get_uefi_mappings(&efi_map, true, bs); size_t i = 0; bool first = true; diff --git a/src/boot/memory.h b/src/boot/memory.h index 0b87d61..968c9e3 100644 --- a/src/boot/memory.h +++ b/src/boot/memory.h @@ -80,11 +80,6 @@ struct efi_mem_map iterator end() { return offset_ptr(entries, length); } }; -/// Get the memory map from UEFI. -/// \arg allocate If false, don't actually fetch the mappings, just -/// return a structure describing them. -efi_mem_map get_uefi_mappings(bool allocate, uefi::boot_services *bs); - /// Add the kernel's memory map as a module to the kernel args. /// \returns The uefi memory map key for the version used to build /// this map