mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 08:24:32 -08:00
[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.
This commit is contained in:
@@ -62,11 +62,11 @@ load(
|
|||||||
console::print(L" Kernel section %d physical: 0x%lx\r\n", i, pages);
|
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);
|
console::print(L" Kernel section %d virtual: 0x%lx\r\n", i, pheader->vaddr);
|
||||||
|
|
||||||
// TODO: map these pages into kernel args' page tables
|
// TODO: set appropriate RWX permissions
|
||||||
// remember to set appropriate RWX permissions
|
|
||||||
paging::map_pages(pml4, args, reinterpret_cast<uintptr_t>(pages), pheader->vaddr, pheader->mem_size);
|
paging::map_pages(pml4, args, reinterpret_cast<uintptr_t>(pages), pheader->vaddr, pheader->mem_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console::print(L" Kernel entrypoint: 0x%lx\r\n", header->entrypoint);
|
||||||
return reinterpret_cast<kernel::entrypoint>(header->entrypoint);
|
return reinterpret_cast<kernel::entrypoint>(header->entrypoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,14 +137,18 @@ load_module(
|
|||||||
/// The main procedure for the portion of the loader that runs while
|
/// 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
|
/// UEFI is still in control of the machine. (ie, while the loader still
|
||||||
/// has access to boot services.
|
/// has access to boot services.
|
||||||
kernel::entrypoint
|
kernel::args::header *
|
||||||
bootloader_main_uefi(uefi::handle image, uefi::system_table *st, console &con, size_t *map_key)
|
bootloader_main_uefi(
|
||||||
|
uefi::handle image,
|
||||||
|
uefi::system_table *st,
|
||||||
|
console &con,
|
||||||
|
kernel::entrypoint *kentry)
|
||||||
{
|
{
|
||||||
error::uefi_handler handler(con);
|
error::uefi_handler handler(con);
|
||||||
|
status_line status(L"Performing UEFI pre-boot");
|
||||||
|
|
||||||
uefi::boot_services *bs = st->boot_services;
|
uefi::boot_services *bs = st->boot_services;
|
||||||
uefi::runtime_services *rs = st->runtime_services;
|
uefi::runtime_services *rs = st->runtime_services;
|
||||||
|
|
||||||
memory::init_pointer_fixup(bs, rs);
|
memory::init_pointer_fixup(bs, rs);
|
||||||
|
|
||||||
kernel::args::header *args =
|
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->runtime_services = rs;
|
||||||
args->acpi_table = hw::find_acpi_table(st);
|
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<void**>(&args->modules[i]));
|
||||||
|
|
||||||
fs::file disk = fs::get_boot_volume(image, bs);
|
fs::file disk = fs::get_boot_volume(image, bs);
|
||||||
load_module(disk, args, L"initrd", L"initrd.img", kernel::args::mod_type::initrd);
|
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);
|
load_module(disk, args, L"kernel", L"jsix.elf", kernel::args::mod_type::kernel);
|
||||||
|
|
||||||
paging::allocate_tables(args, bs);
|
paging::allocate_tables(args, bs);
|
||||||
|
*kentry = loader::load(kernel->location, kernel->size, args, bs);
|
||||||
kernel::entrypoint kentry =
|
return args;
|
||||||
loader::load(kernel->location, kernel->size, args, bs);
|
|
||||||
|
|
||||||
*map_key = memory::build_kernel_mem_map(args, bs);
|
|
||||||
|
|
||||||
return kentry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace boot
|
} // namespace boot
|
||||||
@@ -182,14 +185,17 @@ efi_main(uefi::handle image_handle, uefi::system_table *st)
|
|||||||
error::cpu_assert_handler handler;
|
error::cpu_assert_handler handler;
|
||||||
console con(st->boot_services, st->con_out);
|
console con(st->boot_services, st->con_out);
|
||||||
|
|
||||||
size_t map_key;
|
kernel::entrypoint kentry = nullptr;
|
||||||
kernel::entrypoint kentry =
|
kernel::args::header *args =
|
||||||
bootloader_main_uefi(image_handle, st, con, &map_key);
|
bootloader_main_uefi(image_handle, st, con, &kentry);
|
||||||
|
|
||||||
|
size_t map_key = memory::build_kernel_mem_map(args, st->boot_services);
|
||||||
|
|
||||||
try_or_raise(
|
try_or_raise(
|
||||||
st->boot_services->exit_boot_services(image_handle, map_key),
|
st->boot_services->exit_boot_services(image_handle, map_key),
|
||||||
L"Failed to exit boot services");
|
L"Failed to exit boot services");
|
||||||
|
|
||||||
|
kentry(args);
|
||||||
debug_break();
|
debug_break();
|
||||||
return uefi::status::unsupported;
|
return uefi::status::unsupported;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,20 +82,13 @@ init_pointer_fixup(uefi::boot_services *bs, uefi::runtime_services *rs)
|
|||||||
void
|
void
|
||||||
mark_pointer_fixup(void **p)
|
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;
|
fixup_pointers[fixup_pointer_index++] = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void
|
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
|
// Get the pointer to the start of PML4
|
||||||
uint64_t* cr3 = 0;
|
uint64_t* cr3 = 0;
|
||||||
__asm__ __volatile__ ( "mov %%cr3, %0" : "=r" (cr3) );
|
__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);
|
prev.attr == (next->attribute & 0xffffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
efi_mem_map
|
void
|
||||||
get_uefi_mappings(bool allocate, uefi::boot_services *bs)
|
get_uefi_mappings(efi_mem_map *map, 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;
|
|
||||||
|
|
||||||
uefi::status status = bs->get_memory_map(
|
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)
|
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");
|
||||||
|
|
||||||
if (allocate) {
|
if (allocate) {
|
||||||
map.length = needs_size + 10*map.size;
|
map->length += 10*map->size;
|
||||||
|
|
||||||
try_or_raise(
|
try_or_raise(
|
||||||
bs->allocate_pool(
|
bs->allocate_pool(
|
||||||
uefi::memory_type::loader_data, map.length,
|
uefi::memory_type::loader_data, map->length,
|
||||||
reinterpret_cast<void**>(&map.entries)),
|
reinterpret_cast<void**>(&map->entries)),
|
||||||
L"Allocating space for memory map");
|
L"Allocating space for memory map");
|
||||||
|
|
||||||
try_or_raise(
|
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");
|
L"Getting UEFI memory map");
|
||||||
}
|
}
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
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");
|
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);
|
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(
|
||||||
bs->allocate_pages(
|
bs->allocate_pages(
|
||||||
@@ -192,10 +182,10 @@ build_kernel_mem_map(kernel::args::header *args, uefi::boot_services *bs)
|
|||||||
module_type,
|
module_type,
|
||||||
bytes_to_pages(map_size),
|
bytes_to_pages(map_size),
|
||||||
reinterpret_cast<void**>(&kernel_map)),
|
reinterpret_cast<void**>(&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);
|
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;
|
size_t i = 0;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|||||||
@@ -80,11 +80,6 @@ struct efi_mem_map
|
|||||||
iterator end() { return offset_ptr<desc>(entries, length); }
|
iterator end() { return offset_ptr<desc>(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.
|
/// 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
|
/// \returns The uefi memory map key for the version used to build
|
||||||
/// this map
|
/// this map
|
||||||
|
|||||||
Reference in New Issue
Block a user