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 "memory.h"
|
||||||
|
|
||||||
#include "kernel_args.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_MAGIC 0x600db007
|
||||||
#define KERNEL_HEADER_VERSION 1
|
#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::loaded_elf kernel_elf =
|
||||||
loader::load(kernel->location, kernel->size, bs);
|
loader::load(kernel->location, kernel->size, bs);
|
||||||
|
|
||||||
memory::efi_mem_map efi_map = memory::get_uefi_mappings(bs);
|
*map_key = memory::build_kernel_mem_map(args, bs);
|
||||||
memory::build_kernel_mem_map(efi_map, args, bs);
|
|
||||||
|
|
||||||
efi_map = memory::get_uefi_mappings(bs);
|
|
||||||
*map_key = efi_map.key;
|
|
||||||
|
|
||||||
return kernel_elf;
|
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
|
} // namespace boot
|
||||||
|
|
||||||
/// The UEFI entrypoint for the loader.
|
/// 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
|
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");
|
status_line(L"Getting UEFI memory map");
|
||||||
|
|
||||||
|
efi_mem_map map;
|
||||||
size_t needs_size = 0;
|
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(
|
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)
|
if (status != uefi::status::buffer_too_small)
|
||||||
error::raise(status, L"Error getting memory map size");
|
error::raise(status, L"Error getting memory map size");
|
||||||
|
|
||||||
size_t buffer_size = needs_size + 10*desc_size;
|
if (allocate) {
|
||||||
uefi::memory_descriptor *buffer = nullptr;
|
map.length = needs_size + 10*map.size;
|
||||||
try_or_raise(
|
|
||||||
bs->allocate_pool(
|
|
||||||
uefi::memory_type::loader_data, buffer_size,
|
|
||||||
reinterpret_cast<void**>(&buffer)),
|
|
||||||
L"Allocating space for memory map");
|
|
||||||
|
|
||||||
try_or_raise(
|
try_or_raise(
|
||||||
bs->get_memory_map(&buffer_size, buffer, &map_key, &desc_size, &desc_version),
|
bs->allocate_pool(
|
||||||
L"Getting UEFI memory map");
|
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;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
size_t
|
||||||
build_kernel_mem_map(efi_mem_map &efi_map, kernel::args::header *args, uefi::boot_services *bs)
|
build_kernel_mem_map(kernel::args::header *args, uefi::boot_services *bs)
|
||||||
{
|
{
|
||||||
status_line(L"Creating kernel memory map");
|
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);
|
size_t map_size = efi_map.num_entries() * sizeof(mem_entry);
|
||||||
kernel::args::mem_entry *kernel_map = nullptr;
|
kernel::args::mem_entry *kernel_map = nullptr;
|
||||||
try_or_raise(
|
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.");
|
L"Error allocating kernel memory map module space.");
|
||||||
|
|
||||||
bs->set_mem(kernel_map, map_size, 0);
|
bs->set_mem(kernel_map, map_size, 0);
|
||||||
|
efi_map = get_uefi_mappings(true, bs);
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
bool first = true;
|
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);
|
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
|
uint32_t version; ///< Version of the `memory_descriptor` struct
|
||||||
desc *entries; ///< The array of UEFI descriptors
|
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
|
/// Get the count of entries in the array
|
||||||
inline size_t num_entries() const { return length / size; }
|
inline size_t num_entries() const { return length / size; }
|
||||||
|
|
||||||
@@ -79,13 +81,14 @@ struct efi_mem_map
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Get the memory map from UEFI.
|
/// 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.
|
/// Add the kernel's memory map as a module to the kernel args.
|
||||||
void build_kernel_mem_map(
|
/// \returns The uefi memory map key for the version used to build
|
||||||
efi_mem_map &efi_map,
|
/// this map
|
||||||
kernel::args::header *args,
|
size_t build_kernel_mem_map(kernel::args::header *args, uefi::boot_services *bs);
|
||||||
uefi::boot_services *bs);
|
|
||||||
|
|
||||||
} // namespace boot
|
} // namespace boot
|
||||||
} // namespace memory
|
} // namespace memory
|
||||||
|
|||||||
Reference in New Issue
Block a user