[boot] Build the kernel mem map from the UEFI one

Created kernel args memory map structure, looping through UEFI's memory
map to copy and condense.

Tags: boot memory
This commit is contained in:
Justin C. Miller
2020-05-10 16:26:17 -07:00
parent 21b0b08908
commit c713f4ff6f
4 changed files with 142 additions and 4 deletions

View File

@@ -28,6 +28,7 @@ warnflags = $
-Wno-unused-result $ -Wno-unused-result $
-Wno-deprecated-declarations $ -Wno-deprecated-declarations $
-Wno-unused-function $ -Wno-unused-function $
-Wno-address-of-packed-member $
-Werror -Werror
ccflags = $ ccflags = $

View File

@@ -9,6 +9,9 @@
namespace boot { namespace boot {
namespace memory { namespace memory {
using mem_entry = kernel::args::mem_entry;
using mem_type = kernel::args::mem_type;
size_t fixup_pointer_index = 0; size_t fixup_pointer_index = 0;
void **fixup_pointers[64]; void **fixup_pointers[64];
uint64_t *new_pml4 = 0; uint64_t *new_pml4 = 0;
@@ -147,6 +150,15 @@ memory_virtualize(EFI_RUNTIME_SERVICES *runsvc, struct memory_map *map)
} }
*/ */
bool
can_merge(mem_entry &prev, mem_type type, uefi::memory_descriptor *next)
{
return
prev.type == type &&
prev.start + (page_size * prev.pages) == next->physical_start &&
prev.attr == (next->attribute & 0xffffffff);
}
efi_mem_map efi_mem_map
get_mappings(uefi::boot_services *bs) get_mappings(uefi::boot_services *bs)
{ {
@@ -182,13 +194,113 @@ get_mappings(uefi::boot_services *bs)
map.version = desc_version; map.version = desc_version;
map.entries = buffer; map.entries = buffer;
size_t map_size = map.num_entries() * sizeof(mem_entry);
kernel::args::mem_entry *kernel_map = nullptr;
try_or_raise(
bs->allocate_pages(
uefi::allocate_type::any_pages,
module_type,
bytes_to_pages(map_size),
reinterpret_cast<void**>(&kernel_map)),
L"Error allocating kernel memory map module space.");
bs->set_mem(kernel_map, map_size, 0);
size_t i = 0;
bool first = true;
for (auto desc : map) { for (auto desc : map) {
//for(size_t i = 0; i < map.num_entries(); ++i) { /*
//uefi::memory_descriptor *desc = map[i];
console::print(L" Range %lx (%lx) %x(%s) [%lu]\r\n", console::print(L" Range %lx (%lx) %x(%s) [%lu]\r\n",
desc->physical_start, desc->attribute, desc->type, memory_type_name(desc->type), desc->number_of_pages); desc->physical_start, desc->attribute, desc->type, memory_type_name(desc->type), desc->number_of_pages);
*/
mem_type type;
switch (desc->type) {
case uefi::memory_type::reserved:
case uefi::memory_type::unusable_memory:
case uefi::memory_type::acpi_memory_nvs:
case uefi::memory_type::pal_code:
continue;
case uefi::memory_type::loader_code:
case uefi::memory_type::loader_data:
case uefi::memory_type::boot_services_code:
case uefi::memory_type::boot_services_data:
case uefi::memory_type::conventional_memory:
type = mem_type::free;
break;
case uefi::memory_type::runtime_services_code:
case uefi::memory_type::runtime_services_data:
type = mem_type::uefi_runtime;
break;
case uefi::memory_type::acpi_reclaim_memory:
type = mem_type::acpi;
break;
case uefi::memory_type::memory_mapped_io:
case uefi::memory_type::memory_mapped_io_port_space:
type = mem_type::mmio;
break;
case uefi::memory_type::persistent_memory:
type = mem_type::persistent;
break;
case args_type:
type = mem_type::args;
break;
case module_type:
type = mem_type::module;
break;
case kernel_type:
type = mem_type::kernel;
break;
case table_type:
type = mem_type::table;
break;
default:
error::raise(
uefi::status::invalid_parameter,
L"Got an unexpected memory type from UEFI memory map");
}
// TODO: validate uefi's map is sorted
if (first) {
first = false;
kernel_map[i].start = desc->physical_start;
kernel_map[i].pages = desc->number_of_pages;
kernel_map[i].type = type;
kernel_map[i].attr = (desc->attribute & 0xffffffff);
continue;
}
mem_entry &prev = kernel_map[i];
if (can_merge(prev, type, desc)) {
prev.pages += desc->number_of_pages;
} else {
mem_entry &next = kernel_map[++i];
next.start = desc->physical_start;
next.pages = desc->number_of_pages;
next.type = type;
next.attr = (desc->attribute & 0xffffffff);
}
} }
/*
for (size_t i = 0; i<map.num_entries(); ++i) {
mem_entry &ent = kernel_map[i];
console::print(L" Range %lx (%x) %d [%lu]\r\n",
ent.start, ent.attr, ent.type, ent.pages);
}
*/
return map; return map;
} }

View File

@@ -56,7 +56,8 @@ void mark_pointer_fixup(void **p);
/// Struct that represents UEFI's memory map. Contains a pointer to the map data /// Struct that represents UEFI's memory map. Contains a pointer to the map data
/// as well as the data on how to read it. /// as well as the data on how to read it.
struct efi_mem_map { struct efi_mem_map
{
using desc = uefi::memory_descriptor; using desc = uefi::memory_descriptor;
using iterator = offset_iterator<desc>; using iterator = offset_iterator<desc>;

View File

@@ -32,14 +32,38 @@ enum class mode : uint8_t {
debug debug
}; };
#pragma pack(push, 1)
struct module { struct module {
void *location; void *location;
size_t size; size_t size;
mod_type type; mod_type type;
mod_flags flags; mod_flags flags;
}
__attribute__((packed));
enum class mem_type : uint32_t {
free,
args,
kernel,
module,
table,
acpi,
uefi_runtime,
mmio,
persistent
}; };
/// Structure to hold an entry in the memory map.
struct mem_entry
{
uintptr_t start;
size_t pages;
mem_type type;
uint32_t attr;
}
__attribute__((packed));
struct header { struct header {
uint32_t magic; uint32_t magic;
uint16_t version; uint16_t version;