mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
Parse ELF and load kernel, specify mem types
* Very bare-bones ELF parsing to load the kernel * Custom memory type values for allocated memory
This commit is contained in:
@@ -7,13 +7,13 @@ namespace elf {
|
||||
constexpr uint8_t version = 1;
|
||||
constexpr uint8_t word_size = 2;
|
||||
constexpr uint8_t endianness = 1;
|
||||
constexpr uint8_t os_abi = 1;
|
||||
constexpr uint8_t os_abi = 0;
|
||||
constexpr uint16_t machine = 0x3e;
|
||||
|
||||
const unsigned ELF_PT_LOAD = 1;
|
||||
const unsigned ELF_ST_PROGBITS = 1;
|
||||
const unsigned ELF_ST_NOBITS = 8;
|
||||
const unsigned long ELF_SHF_ALLOC = 0x2;
|
||||
const unsigned PT_LOAD = 1;
|
||||
const unsigned ST_PROGBITS = 1;
|
||||
const unsigned ST_NOBITS = 8;
|
||||
const unsigned long SHF_ALLOC = 0x2;
|
||||
|
||||
struct header
|
||||
{
|
||||
|
||||
@@ -51,7 +51,7 @@ file::open(const wchar_t *path)
|
||||
}
|
||||
|
||||
void *
|
||||
file::load(size_t *out_size)
|
||||
file::load(size_t *out_size, uefi::memory_type mem_type)
|
||||
{
|
||||
uint8_t buffer[sizeof(uefi::protos::file_info) + 100];
|
||||
size_t size = sizeof(buffer);
|
||||
@@ -69,8 +69,7 @@ file::load(size_t *out_size)
|
||||
try_or_raise(
|
||||
m_bs->allocate_pages(
|
||||
uefi::allocate_type::any_pages,
|
||||
uefi::memory_type::loader_data,
|
||||
pages, &data),
|
||||
mem_type, pages, &data),
|
||||
L"Could not allocate pages to load file");
|
||||
|
||||
size = info->file_size;
|
||||
|
||||
@@ -15,7 +15,9 @@ public:
|
||||
~file();
|
||||
|
||||
file open(const wchar_t *path);
|
||||
void * load(size_t *out_size);
|
||||
void * load(
|
||||
size_t *out_size,
|
||||
uefi::memory_type mem_type = uefi::memory_type::loader_data);
|
||||
|
||||
private:
|
||||
friend file get_boot_volume(uefi::handle, uefi::boot_services*);
|
||||
|
||||
@@ -5,87 +5,86 @@
|
||||
#include "console.h"
|
||||
#include "elf.h"
|
||||
#include "error.h"
|
||||
#include "memory.h"
|
||||
|
||||
namespace boot {
|
||||
namespace loader {
|
||||
|
||||
using memory::offset_ptr;
|
||||
|
||||
static bool
|
||||
is_elfheader_valid(const elf::header *header)
|
||||
{
|
||||
return false;
|
||||
return
|
||||
header->magic[0] == 0x7f &&
|
||||
header->magic[1] == 'E' &&
|
||||
header->magic[2] == 'L' &&
|
||||
header->magic[3] == 'F' &&
|
||||
header->word_size == elf::word_size &&
|
||||
header->endianness == elf::endianness &&
|
||||
header->os_abi == elf::os_abi &&
|
||||
header->machine == elf::machine &&
|
||||
header->header_version == elf::version;
|
||||
}
|
||||
|
||||
kernel::entrypoint
|
||||
load_elf(
|
||||
loaded_elf
|
||||
load(
|
||||
const void *data,
|
||||
size_t size,
|
||||
uefi::boot_services *bs)
|
||||
{
|
||||
status_line status(L"Loading kernel ELF binary");
|
||||
const elf::header *header = reinterpret_cast<const elf::header*>(data);
|
||||
|
||||
if (size < sizeof(elf::header) ||
|
||||
!is_elfheader_valid(reinterpret_cast<const elf::header*>(data)))
|
||||
if (size < sizeof(elf::header) || !is_elfheader_valid(header))
|
||||
error::raise(uefi::status::load_error, L"Kernel ELF not valid");
|
||||
|
||||
/*
|
||||
struct elf_program_header prog_header;
|
||||
for (int i = 0; i < header.ph_num; ++i) {
|
||||
uintptr_t kernel_start = 0;
|
||||
uintptr_t kernel_end = 0;
|
||||
for (int i = 0; i < header->ph_num; ++i) {
|
||||
ptrdiff_t offset = header->ph_offset + i * header->ph_entsize;
|
||||
const elf::program_header *pheader =
|
||||
offset_ptr<elf::program_header>(data, offset);
|
||||
|
||||
status = file->SetPosition(file, header.ph_offset + i * header.ph_entsize);
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position");
|
||||
|
||||
length = header.ph_entsize;
|
||||
status = file->Read(file, &length, &prog_header);
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading ELF program header");
|
||||
|
||||
if (prog_header.type != ELF_PT_LOAD) continue;
|
||||
|
||||
length = prog_header.mem_size;
|
||||
void *addr = (void *)(prog_header.vaddr - KERNEL_VIRT_ADDRESS);
|
||||
status = loader_alloc_pages(bootsvc, memtype_kernel, &length, &addr);
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, L"Allocating kernel pages");
|
||||
|
||||
if (data->kernel == 0)
|
||||
data->kernel = addr;
|
||||
data->kernel_length = (uint64_t)addr + length - (uint64_t)data->kernel;
|
||||
}
|
||||
con_debug(L"Read %d ELF program headers", header.ph_num);
|
||||
|
||||
struct elf_section_header sec_header;
|
||||
for (int i = 0; i < header.sh_num; ++i) {
|
||||
status = file->SetPosition(file, header.sh_offset + i * header.sh_entsize);
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position");
|
||||
|
||||
length = header.sh_entsize;
|
||||
status = file->Read(file, &length, &sec_header);
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading ELF section header");
|
||||
|
||||
if ((sec_header.flags & ELF_SHF_ALLOC) == 0) {
|
||||
if (pheader->type != elf::PT_LOAD)
|
||||
continue;
|
||||
}
|
||||
|
||||
void *addr = (void *)(sec_header.addr - KERNEL_VIRT_ADDRESS);
|
||||
if (kernel_start == 0 || pheader->vaddr < kernel_start)
|
||||
kernel_start = pheader->vaddr;
|
||||
|
||||
if (sec_header.type == ELF_ST_PROGBITS) {
|
||||
status = file->SetPosition(file, sec_header.offset);
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, L"Setting ELF file position");
|
||||
|
||||
length = sec_header.size;
|
||||
status = file->Read(file, &length, addr);
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, L"Reading file");
|
||||
} else if (sec_header.type == ELF_ST_NOBITS) {
|
||||
bootsvc->SetMem(addr, sec_header.size, 0);
|
||||
}
|
||||
if (pheader->vaddr + pheader->mem_size > kernel_end)
|
||||
kernel_end = pheader->vaddr + pheader->mem_size;
|
||||
}
|
||||
con_debug(L"Read %d ELF section headers", header.ph_num);
|
||||
|
||||
status = file->Close(file);
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, L"Closing file handle");
|
||||
void *pages = nullptr;
|
||||
size_t num_pages = memory::bytes_to_pages(kernel_end - kernel_start);
|
||||
try_or_raise(
|
||||
bs->allocate_pages(uefi::allocate_type::any_pages,
|
||||
memory::kernel_type, num_pages, &pages),
|
||||
L"Failed allocating space for kernel code");
|
||||
|
||||
return reinterpret_cast<kernel::entrypoint>(kernel.entrypoint());
|
||||
*/
|
||||
for (int i = 0; i < header->ph_num; ++i) {
|
||||
ptrdiff_t offset = header->ph_offset + i * header->ph_entsize;
|
||||
const elf::program_header *pheader =
|
||||
offset_ptr<elf::program_header>(data, offset);
|
||||
|
||||
return nullptr;
|
||||
if (pheader->type != elf::PT_LOAD)
|
||||
continue;
|
||||
|
||||
void *data_start = offset_ptr<void>(data, pheader->offset);
|
||||
void *program_start = offset_ptr<void>(pages, pheader->vaddr - kernel_start);
|
||||
bs->copy_mem(program_start, data_start, pheader->mem_size);
|
||||
}
|
||||
|
||||
loaded_elf result;
|
||||
result.data = pages;
|
||||
result.vaddr = kernel_start;
|
||||
result.entrypoint = header->entrypoint;
|
||||
console::print(L" Kernel loaded at: 0x%lx\r\n", result.data);
|
||||
console::print(L" Kernel virtual address: 0x%lx\r\n", result.vaddr);
|
||||
console::print(L" Kernel entrypoint: 0x%lx\r\n", result.entrypoint);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace loader
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "kernel_args.h"
|
||||
|
||||
namespace boot {
|
||||
namespace loader {
|
||||
|
||||
kernel::entrypoint load_elf(const void *data, size_t size, uefi::boot_services *bs);
|
||||
struct loaded_elf
|
||||
{
|
||||
void *data;
|
||||
uintptr_t vaddr;
|
||||
uintptr_t entrypoint;
|
||||
};
|
||||
|
||||
loaded_elf load(const void *data, size_t size, uefi::boot_services *bs);
|
||||
|
||||
} // namespace loader
|
||||
} // namespace boot
|
||||
|
||||
@@ -91,20 +91,20 @@ load_module(
|
||||
kernel::args::header *args,
|
||||
const wchar_t *name,
|
||||
const wchar_t *path,
|
||||
kernel::args::type type)
|
||||
kernel::args::mod_type type)
|
||||
{
|
||||
status_line status(L"Loading module", name);
|
||||
|
||||
fs::file file = disk.open(path);
|
||||
kernel::args::module &module = args->modules[args->num_modules++];
|
||||
module.type = type;
|
||||
module.location = file.load(&module.size);
|
||||
module.location = file.load(&module.size, memory::module_type);
|
||||
|
||||
console::print(L" Loaded at: 0x%lx, %d bytes\r\n", module.location, module.size);
|
||||
return &module;
|
||||
}
|
||||
|
||||
kernel::entrypoint
|
||||
loader::loaded_elf
|
||||
bootloader_main_uefi(uefi::handle image, uefi::system_table *st, console &con)
|
||||
{
|
||||
error::uefi_handler handler(con);
|
||||
@@ -123,13 +123,17 @@ bootloader_main_uefi(uefi::handle image, uefi::system_table *st, console &con)
|
||||
args->acpi_table = hw::find_acpi_table(st);
|
||||
|
||||
fs::file disk = fs::get_boot_volume(image, bs);
|
||||
load_module(disk, args, L"initrd", L"initrd.img", kernel::args::type::initrd);
|
||||
load_module(disk, args, L"initrd", L"initrd.img", kernel::args::mod_type::initrd);
|
||||
|
||||
kernel::args::module *kernel =
|
||||
load_module(disk, args, L"kernel", L"jsix.elf", kernel::args::type::kernel);
|
||||
load_module(disk, args, L"kernel", L"jsix.elf", kernel::args::mod_type::kernel);
|
||||
|
||||
kernel::entrypoint entry = loader::load_elf(kernel->location, kernel->size, bs);
|
||||
return entry;
|
||||
|
||||
loader::loaded_elf kernel_elf =
|
||||
loader::load(kernel->location, kernel->size, bs);
|
||||
|
||||
memory::get_mappings(bs);
|
||||
return kernel_elf;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -242,7 +246,7 @@ efi_main(uefi::handle image_handle, uefi::system_table *st)
|
||||
error::cpu_assert_handler handler;
|
||||
console con(st->boot_services, st->con_out);
|
||||
|
||||
kernel::entrypoint kernel_main =
|
||||
loader::loaded_elf kernel =
|
||||
bootloader_main_uefi(image_handle, st, con);
|
||||
|
||||
while(1);
|
||||
|
||||
@@ -8,53 +8,43 @@
|
||||
namespace boot {
|
||||
namespace memory {
|
||||
|
||||
/*
|
||||
const EFI_MEMORY_TYPE memtype_kernel = static_cast<EFI_MEMORY_TYPE>(0x80000000ul);
|
||||
const EFI_MEMORY_TYPE memtype_data = static_cast<EFI_MEMORY_TYPE>(0x80000001ul);
|
||||
const EFI_MEMORY_TYPE memtype_initrd = static_cast<EFI_MEMORY_TYPE>(0x80000002ul);
|
||||
const EFI_MEMORY_TYPE memtype_scratch = static_cast<EFI_MEMORY_TYPE>(0x80000003ul);
|
||||
|
||||
#define INCREMENT_DESC(p, b) (EFI_MEMORY_DESCRIPTOR*)(((uint8_t*)(p))+(b))
|
||||
*/
|
||||
|
||||
size_t fixup_pointer_index = 0;
|
||||
void **fixup_pointers[64];
|
||||
uint64_t *new_pml4 = 0;
|
||||
|
||||
/*
|
||||
const wchar_t *memory_type_names[] = {
|
||||
L"EfiReservedMemoryType",
|
||||
L"EfiLoaderCode",
|
||||
L"EfiLoaderData",
|
||||
L"EfiBootServicesCode",
|
||||
L"EfiBootServicesData",
|
||||
L"EfiRuntimeServicesCode",
|
||||
L"EfiRuntimeServicesData",
|
||||
L"EfiConventionalMemory",
|
||||
L"EfiUnusableMemory",
|
||||
L"EfiACPIReclaimMemory",
|
||||
L"EfiACPIMemoryNVS",
|
||||
L"EfiMemoryMappedIO",
|
||||
L"EfiMemoryMappedIOPortSpace",
|
||||
L"EfiPalCode",
|
||||
L"EfiPersistentMemory",
|
||||
static const wchar_t *memory_type_names[] = {
|
||||
L"reserved memory type",
|
||||
L"loader code",
|
||||
L"loader data",
|
||||
L"boot services code",
|
||||
L"boot services data",
|
||||
L"runtime services code",
|
||||
L"runtime services data",
|
||||
L"conventional memory",
|
||||
L"unusable memory",
|
||||
L"acpi reclaim memory",
|
||||
L"acpi memory nvs",
|
||||
L"memory mapped io",
|
||||
L"memory mapped io port space",
|
||||
L"pal code",
|
||||
L"persistent memory"
|
||||
};
|
||||
|
||||
static const wchar_t *
|
||||
memory_type_name(UINT32 value)
|
||||
memory_type_name(uefi::memory_type t)
|
||||
{
|
||||
if (value >= (sizeof(memory_type_names) / sizeof(wchar_t *))) {
|
||||
switch (value) {
|
||||
case memtype_kernel: return L"Kernel Data";
|
||||
case memtype_data: return L"Kernel Data";
|
||||
case memtype_initrd: return L"Initial Ramdisk";
|
||||
case memtype_scratch: return L"Kernel Scratch Space";
|
||||
default: return L"Bad Type Value";
|
||||
}
|
||||
if (t < uefi::memory_type::max_memory_type) {
|
||||
return memory_type_names[static_cast<uint32_t>(t)];
|
||||
}
|
||||
|
||||
switch(t) {
|
||||
case args_type: return L"jsix kernel args";
|
||||
case module_type: return L"jsix bootloader module";
|
||||
case kernel_type: return L"jsix kernel code";
|
||||
case table_type: return L"jsix page tables";
|
||||
default: return L"Bad Type Value";
|
||||
}
|
||||
return memory_type_names[value];
|
||||
}
|
||||
*/
|
||||
|
||||
void
|
||||
update_marked_addresses(uefi::event, void *context)
|
||||
@@ -84,15 +74,13 @@ init_pointer_fixup(uefi::boot_services *bs, uefi::runtime_services *rs)
|
||||
&event),
|
||||
L"Error creating memory virtualization event");
|
||||
|
||||
uefi::memory_type memtype = static_cast<uefi::memory_type>(0x80000003ul);
|
||||
|
||||
// Reserve a page for our replacement PML4, plus some pages for the kernel to use
|
||||
// as page tables while it gets started.
|
||||
void *addr = nullptr;
|
||||
try_or_raise(
|
||||
bs->allocate_pages(
|
||||
uefi::allocate_type::any_pages,
|
||||
memtype,
|
||||
table_type,
|
||||
64,
|
||||
&addr),
|
||||
L"Error allocating page table pages.");
|
||||
@@ -111,81 +99,6 @@ mark_pointer_fixup(void **p)
|
||||
}
|
||||
|
||||
/*
|
||||
void
|
||||
copy_desc(EFI_MEMORY_DESCRIPTOR *src, EFI_MEMORY_DESCRIPTOR *dst, size_t len)
|
||||
{
|
||||
uint8_t *srcb = (uint8_t *)src;
|
||||
uint8_t *dstb = (uint8_t *)dst;
|
||||
uint8_t *endb = srcb + len;
|
||||
while (srcb < endb)
|
||||
*dstb++ = *srcb++;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
memory_get_map_length(EFI_BOOT_SERVICES *bootsvc, size_t *size)
|
||||
{
|
||||
if (size == NULL)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
EFI_STATUS status;
|
||||
size_t key, desc_size;
|
||||
uint32_t desc_version;
|
||||
*size = 0;
|
||||
status = bootsvc->GetMemoryMap(size, 0, &key, &desc_size, &desc_version);
|
||||
if (status != EFI_BUFFER_TOO_SMALL) {
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, "Failed to get memory map size");
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
memory_get_map(EFI_BOOT_SERVICES *bootsvc, struct memory_map *map)
|
||||
{
|
||||
EFI_STATUS status;
|
||||
|
||||
if (map == NULL)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
size_t needs_size = 0;
|
||||
status = memory_get_map_length(bootsvc, &needs_size);
|
||||
if (EFI_ERROR(status)) return status;
|
||||
|
||||
if (map->length < needs_size)
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
|
||||
status = bootsvc->GetMemoryMap(&map->length, map->entries, &map->key, &map->size, &map->version);
|
||||
CHECK_EFI_STATUS_OR_RETURN(status, "Failed to load memory map");
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
memory_dump_map(struct memory_map *map)
|
||||
{
|
||||
if (map == NULL)
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
const size_t count = map->length / map->size;
|
||||
|
||||
console::print(L"Memory map:\n");
|
||||
console::print(L"\t Descriptor Count: %d (%d bytes)\n", count, map->length);
|
||||
console::print(L"\t Descriptor Size: %d bytes\n", map->size);
|
||||
console::print(L"\t Type offset: %d\n\n", offsetof(EFI_MEMORY_DESCRIPTOR, Type));
|
||||
|
||||
EFI_MEMORY_DESCRIPTOR *end = INCREMENT_DESC(map->entries, map->length);
|
||||
EFI_MEMORY_DESCRIPTOR *d = map->entries;
|
||||
while (d < end) {
|
||||
int runtime = (d->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME;
|
||||
console::print(L"%s%s ", memory_type_name(d->Type), runtime ? L"*" : L" ");
|
||||
console::print(L"%lx ", d->PhysicalStart);
|
||||
console::print(L"%lx ", d->VirtualStart);
|
||||
console::print(L"[%4d]\n", d->NumberOfPages);
|
||||
|
||||
d = INCREMENT_DESC(d, map->size);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
memory_virtualize(EFI_RUNTIME_SERVICES *runsvc, struct memory_map *map)
|
||||
{
|
||||
@@ -245,9 +158,7 @@ allocate_args_structure(uefi::boot_services *bs, size_t max_modules)
|
||||
max_modules * sizeof(kernel::args::module); // The module structures
|
||||
|
||||
try_or_raise(
|
||||
bs->allocate_pool(
|
||||
uefi::memory_type::loader_data,
|
||||
args_size,
|
||||
bs->allocate_pool(args_type, args_size,
|
||||
reinterpret_cast<void**>(&args)),
|
||||
L"Could not allocate argument memory");
|
||||
|
||||
@@ -260,6 +171,51 @@ allocate_args_structure(uefi::boot_services *bs, size_t max_modules)
|
||||
return args;
|
||||
}
|
||||
|
||||
efi_mem_map
|
||||
get_mappings(uefi::boot_services *bs)
|
||||
{
|
||||
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);
|
||||
|
||||
if (status != uefi::status::buffer_too_small)
|
||||
error::raise(status, L"Error getting memory map size");
|
||||
|
||||
console::print(L"memory map needs %lu bytes\r\n", needs_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");
|
||||
|
||||
try_or_raise(
|
||||
bs->get_memory_map(&buffer_size, buffer, &map_key, &desc_size, &desc_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;
|
||||
|
||||
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",
|
||||
desc->physical_start, desc->attribute, desc->type, memory_type_name(desc->type), desc->number_of_pages);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
} // namespace boot
|
||||
} // namespace memory
|
||||
|
||||
@@ -9,6 +9,16 @@ namespace memory {
|
||||
|
||||
constexpr size_t page_size = 0x1000;
|
||||
|
||||
constexpr uefi::memory_type args_type = static_cast<uefi::memory_type>(0x80000000);
|
||||
constexpr uefi::memory_type module_type = static_cast<uefi::memory_type>(0x80000001);
|
||||
constexpr uefi::memory_type kernel_type = static_cast<uefi::memory_type>(0x80000002);
|
||||
constexpr uefi::memory_type table_type = static_cast<uefi::memory_type>(0x80000003);
|
||||
|
||||
template <typename T, typename S>
|
||||
static T* offset_ptr(S* input, ptrdiff_t offset) {
|
||||
return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(input) + offset);
|
||||
}
|
||||
|
||||
inline constexpr size_t bytes_to_pages(size_t bytes) {
|
||||
return ((bytes - 1) / page_size) + 1;
|
||||
}
|
||||
@@ -21,20 +31,52 @@ void mark_pointer_fixup(void **p);
|
||||
|
||||
kernel::args::header * allocate_args_structure(uefi::boot_services *bs, size_t max_modules);
|
||||
|
||||
/*
|
||||
extern const EFI_MEMORY_TYPE memtype_kernel;
|
||||
extern const EFI_MEMORY_TYPE memtype_data;
|
||||
extern const EFI_MEMORY_TYPE memtype_initrd;
|
||||
extern const EFI_MEMORY_TYPE memtype_scratch;
|
||||
template <typename T>
|
||||
class offset_iterator
|
||||
{
|
||||
T* m_t;
|
||||
size_t m_off;
|
||||
public:
|
||||
offset_iterator(T* t, size_t offset=0) : m_t(t), m_off(offset) {}
|
||||
|
||||
struct memory_map {
|
||||
T* operator++() { m_t = offset_ptr<T>(m_t, m_off); return m_t; }
|
||||
T* operator++(int) { T* tmp = m_t; operator++(); return tmp; }
|
||||
bool operator==(T* p) { return p == m_t; }
|
||||
|
||||
T* operator*() const { return m_t; }
|
||||
operator T*() const { return m_t; }
|
||||
T* operator->() const { return m_t; }
|
||||
};
|
||||
|
||||
struct efi_mem_map {
|
||||
size_t length;
|
||||
size_t size;
|
||||
size_t key;
|
||||
uint32_t version;
|
||||
EFI_MEMORY_DESCRIPTOR *entries;
|
||||
uefi::memory_descriptor *entries;
|
||||
|
||||
inline size_t num_entries() const { return length / size; }
|
||||
|
||||
inline uefi::memory_descriptor * operator[](size_t i) {
|
||||
size_t offset = i * size;
|
||||
if (offset > length) return nullptr;
|
||||
return offset_ptr<uefi::memory_descriptor>(entries, offset);
|
||||
}
|
||||
|
||||
offset_iterator<uefi::memory_descriptor> begin() { return offset_iterator<uefi::memory_descriptor>(entries, size); }
|
||||
offset_iterator<uefi::memory_descriptor> end() { return offset_ptr<uefi::memory_descriptor>(entries, length); }
|
||||
};
|
||||
|
||||
efi_mem_map get_mappings(uefi::boot_services *bs);
|
||||
|
||||
enum class memory_type
|
||||
{
|
||||
free,
|
||||
loader_used,
|
||||
system_used
|
||||
};
|
||||
|
||||
/*
|
||||
EFI_STATUS memory_get_map_length(EFI_BOOT_SERVICES *bootsvc, size_t *size);
|
||||
EFI_STATUS memory_get_map(EFI_BOOT_SERVICES *bootsvc, struct memory_map *map);
|
||||
EFI_STATUS memory_dump_map(struct memory_map *map);
|
||||
|
||||
@@ -10,12 +10,12 @@ namespace args {
|
||||
constexpr uint32_t magic = 0x600dda7a;
|
||||
constexpr uint16_t version = 1;
|
||||
|
||||
enum class flags : uint32_t
|
||||
enum class mod_flags : uint32_t
|
||||
{
|
||||
debug = 0x00000001
|
||||
};
|
||||
|
||||
enum class type : uint32_t {
|
||||
enum class mod_type : uint32_t {
|
||||
unknown,
|
||||
|
||||
kernel,
|
||||
@@ -36,8 +36,8 @@ enum class mode : uint8_t {
|
||||
struct module {
|
||||
void *location;
|
||||
size_t size;
|
||||
type type;
|
||||
flags flags;
|
||||
mod_type type;
|
||||
mod_flags flags;
|
||||
};
|
||||
|
||||
struct header {
|
||||
|
||||
Reference in New Issue
Block a user