mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[boot] Only allocate memory map once
The `build_kernel_mem_map` function now calls `get_uefi_mappings` itself, instead of having the efi map passed in. `get_uefi_mappings` also now takes a `bool allocate` to direct it to actually allocate the map or not. If it doesn't, it instead just returns the size of the map and the metadata - which `build_kernel_mem_map` uses to decide how much space to first allocate for the kernel's map.
This commit is contained in:
@@ -15,15 +15,8 @@
|
||||
#include "memory.h"
|
||||
|
||||
#include "kernel_args.h"
|
||||
|
||||
/*
|
||||
#include "guids.h"
|
||||
#include "loader.h"
|
||||
#include "utility.h"
|
||||
|
||||
#ifndef SCRATCH_PAGES
|
||||
#define SCRATCH_PAGES 64
|
||||
#endif
|
||||
|
||||
#define KERNEL_HEADER_MAGIC 0x600db007
|
||||
#define KERNEL_HEADER_VERSION 1
|
||||
|
||||
@@ -171,115 +164,10 @@ bootloader_main_uefi(uefi::handle image, uefi::system_table *st, console &con, s
|
||||
loader::loaded_elf kernel_elf =
|
||||
loader::load(kernel->location, kernel->size, bs);
|
||||
|
||||
memory::efi_mem_map efi_map = memory::get_uefi_mappings(bs);
|
||||
memory::build_kernel_mem_map(efi_map, args, bs);
|
||||
|
||||
efi_map = memory::get_uefi_mappings(bs);
|
||||
*map_key = efi_map.key;
|
||||
|
||||
*map_key = memory::build_kernel_mem_map(args, bs);
|
||||
return kernel_elf;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
struct loader_data load;
|
||||
load.data_length = data_length;
|
||||
status = loader_load_kernel(bootsvc, &load);
|
||||
CHECK_EFI_STATUS_OR_FAIL(status);
|
||||
|
||||
console::print(L" %x image bytes at 0x%x\r\n", load.kernel_length, load.kernel);
|
||||
console::print(L" %x data bytes at 0x%x\r\n", load.data_length, load.data);
|
||||
console::print(L" %x initrd bytes at 0x%x\r\n", load.initrd_length, load.initrd);
|
||||
|
||||
struct kernel_header *version = (struct kernel_header *)load.kernel;
|
||||
if (version->magic != KERNEL_HEADER_MAGIC) {
|
||||
console::print(L" bad magic %x\r\n", version->magic);
|
||||
CHECK_EFI_STATUS_OR_FAIL(EFI_CRC_ERROR);
|
||||
}
|
||||
|
||||
console::print(L" Kernel version %d.%d.%d %x%s\r\n",
|
||||
version->major, version->minor, version->patch, version->gitsha & 0x0fffffff,
|
||||
version->gitsha & 0xf0000000 ? L"*" : L"");
|
||||
console::print(L" Entrypoint 0x%x\r\n", load.kernel_entry);
|
||||
|
||||
kernel_entry kernel_main =
|
||||
reinterpret_cast<kernel_entry>(load.kernel_entry);
|
||||
memory_mark_pointer_fixup((void **)&kernel_main);
|
||||
|
||||
// Set up the kernel data pages to pass to the kernel
|
||||
//
|
||||
struct kernel_args *data_header = (struct kernel_args *)load.data;
|
||||
memory_mark_pointer_fixup((void **)&data_header);
|
||||
|
||||
data_header->magic = DATA_HEADER_MAGIC;
|
||||
data_header->version = DATA_HEADER_VERSION;
|
||||
data_header->length = sizeof(struct kernel_args);
|
||||
|
||||
data_header->scratch_pages = SCRATCH_PAGES;
|
||||
data_header->flags = 0;
|
||||
|
||||
data_header->initrd = load.initrd;
|
||||
data_header->initrd_length = load.initrd_length;
|
||||
memory_mark_pointer_fixup((void **)&data_header->initrd);
|
||||
|
||||
data_header->data = load.data;
|
||||
data_header->data_length = load.data_length;
|
||||
memory_mark_pointer_fixup((void **)&data_header->data);
|
||||
|
||||
data_header->memory_map = (EFI_MEMORY_DESCRIPTOR *)(data_header + 1);
|
||||
memory_mark_pointer_fixup((void **)&data_header->memory_map);
|
||||
|
||||
data_header->runtime = runsvc;
|
||||
memory_mark_pointer_fixup((void **)&data_header->runtime);
|
||||
|
||||
data_header->acpi_table = acpi_table;
|
||||
memory_mark_pointer_fixup((void **)&data_header->acpi_table);
|
||||
|
||||
data_header->_reserved0 = 0;
|
||||
data_header->_reserved1 = 0;
|
||||
|
||||
// Figure out the framebuffer (if any) and add that to the data header
|
||||
//
|
||||
status = con_get_framebuffer(
|
||||
bootsvc,
|
||||
&data_header->frame_buffer,
|
||||
&data_header->frame_buffer_length,
|
||||
&data_header->hres,
|
||||
&data_header->vres,
|
||||
&data_header->rmask,
|
||||
&data_header->gmask,
|
||||
&data_header->bmask);
|
||||
CHECK_EFI_STATUS_OR_FAIL(status);
|
||||
memory_mark_pointer_fixup((void **)&data_header->frame_buffer);
|
||||
|
||||
// Save the memory map and tell the firmware we're taking control.
|
||||
//
|
||||
struct memory_map map;
|
||||
map.length = (load.data_length - header_size);
|
||||
map.entries =
|
||||
reinterpret_cast<EFI_MEMORY_DESCRIPTOR *>(data_header->memory_map);
|
||||
|
||||
status = memory_get_map(bootsvc, &map);
|
||||
CHECK_EFI_STATUS_OR_FAIL(status);
|
||||
|
||||
data_header->memory_map_length = map.length;
|
||||
data_header->memory_map_desc_size = map.size;
|
||||
|
||||
detect_debug_mode(runsvc, data_header);
|
||||
|
||||
// bootsvc->Stall(5000000);
|
||||
|
||||
status = bootsvc->ExitBootServices(image_handle, map.key);
|
||||
CHECK_EFI_STATUS_OR_ASSERT(status, 0);
|
||||
|
||||
memory_virtualize(runsvc, &map);
|
||||
|
||||
// Hand control to the kernel
|
||||
//
|
||||
kernel_main(data_header);
|
||||
return EFI_LOAD_ERROR;
|
||||
}
|
||||
*/
|
||||
} // namespace boot
|
||||
|
||||
/// The UEFI entrypoint for the loader.
|
||||
|
||||
@@ -161,47 +161,43 @@ can_merge(mem_entry &prev, mem_type type, uefi::memory_descriptor *next)
|
||||
}
|
||||
|
||||
efi_mem_map
|
||||
get_uefi_mappings(uefi::boot_services *bs)
|
||||
get_uefi_mappings(bool allocate, uefi::boot_services *bs)
|
||||
{
|
||||
status_line(L"Getting UEFI memory map");
|
||||
|
||||
efi_mem_map map;
|
||||
size_t needs_size = 0;
|
||||
size_t map_key = 0;
|
||||
size_t desc_size = 0;
|
||||
uint32_t desc_version = 0;
|
||||
|
||||
uefi::status status = bs->get_memory_map(
|
||||
&needs_size, nullptr, &map_key, &desc_size, &desc_version);
|
||||
&needs_size, nullptr, &map.key, &map.size, &map.version);
|
||||
|
||||
if (status != uefi::status::buffer_too_small)
|
||||
error::raise(status, L"Error getting memory map size");
|
||||
|
||||
size_t buffer_size = needs_size + 10*desc_size;
|
||||
uefi::memory_descriptor *buffer = nullptr;
|
||||
try_or_raise(
|
||||
bs->allocate_pool(
|
||||
uefi::memory_type::loader_data, buffer_size,
|
||||
reinterpret_cast<void**>(&buffer)),
|
||||
L"Allocating space for memory map");
|
||||
if (allocate) {
|
||||
map.length = needs_size + 10*map.size;
|
||||
|
||||
try_or_raise(
|
||||
bs->get_memory_map(&buffer_size, buffer, &map_key, &desc_size, &desc_version),
|
||||
L"Getting UEFI memory map");
|
||||
try_or_raise(
|
||||
bs->allocate_pool(
|
||||
uefi::memory_type::loader_data, map.length,
|
||||
reinterpret_cast<void**>(&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),
|
||||
L"Getting UEFI memory map");
|
||||
}
|
||||
|
||||
efi_mem_map map;
|
||||
map.length = buffer_size;
|
||||
map.size = desc_size;
|
||||
map.key = map_key;
|
||||
map.version = desc_version;
|
||||
map.entries = buffer;
|
||||
return map;
|
||||
}
|
||||
|
||||
void
|
||||
build_kernel_mem_map(efi_mem_map &efi_map, kernel::args::header *args, uefi::boot_services *bs)
|
||||
size_t
|
||||
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);
|
||||
|
||||
size_t map_size = efi_map.num_entries() * sizeof(mem_entry);
|
||||
kernel::args::mem_entry *kernel_map = nullptr;
|
||||
try_or_raise(
|
||||
@@ -213,6 +209,7 @@ build_kernel_mem_map(efi_mem_map &efi_map, kernel::args::header *args, uefi::boo
|
||||
L"Error allocating kernel memory map module space.");
|
||||
|
||||
bs->set_mem(kernel_map, map_size, 0);
|
||||
efi_map = get_uefi_mappings(true, bs);
|
||||
|
||||
size_t i = 0;
|
||||
bool first = true;
|
||||
@@ -312,6 +309,8 @@ build_kernel_mem_map(efi_mem_map &efi_map, kernel::args::header *args, uefi::boo
|
||||
ent.start, ent.attr, ent.type, ent.pages);
|
||||
}
|
||||
*/
|
||||
|
||||
return efi_map.key;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -68,6 +68,8 @@ struct efi_mem_map
|
||||
uint32_t version; ///< Version of the `memory_descriptor` struct
|
||||
desc *entries; ///< The array of UEFI descriptors
|
||||
|
||||
efi_mem_map() : length(0), size(0), key(0), version(0), entries(nullptr) {}
|
||||
|
||||
/// Get the count of entries in the array
|
||||
inline size_t num_entries() const { return length / size; }
|
||||
|
||||
@@ -79,13 +81,14 @@ struct efi_mem_map
|
||||
};
|
||||
|
||||
/// Get the memory map from UEFI.
|
||||
efi_mem_map get_uefi_mappings(uefi::boot_services *bs);
|
||||
/// \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.
|
||||
void build_kernel_mem_map(
|
||||
efi_mem_map &efi_map,
|
||||
kernel::args::header *args,
|
||||
uefi::boot_services *bs);
|
||||
/// \returns The uefi memory map key for the version used to build
|
||||
/// this map
|
||||
size_t build_kernel_mem_map(kernel::args::header *args, uefi::boot_services *bs);
|
||||
|
||||
} // namespace boot
|
||||
} // namespace memory
|
||||
|
||||
Reference in New Issue
Block a user