Allow larger initrd images

This commit is contained in:
Justin C. Miller
2019-03-25 00:14:20 -07:00
parent ed3f9410a6
commit 39baec852b
3 changed files with 72 additions and 41 deletions

View File

@@ -9,31 +9,73 @@
static wchar_t kernel_name[] = KERNEL_FILENAME;
static wchar_t initrd_name[] = INITRD_FILENAME;
EFI_STATUS
loader_alloc_aligned(
EFI_BOOT_SERVICES *bootsvc,
EFI_MEMORY_TYPE mem_type,
size_t *length,
void **pages)
{
EFI_STATUS status;
EFI_PHYSICAL_ADDRESS addr;
size_t alignment = PAGE_SIZE;
while (alignment < *length)
alignment *= 2;
size_t page_count = alignment / PAGE_SIZE;
*length = alignment;
con_debug(L"Trying to find %d aligned pages for %x\n", page_count, mem_type);
status = bootsvc->AllocatePages(AllocateAnyPages, mem_type, page_count * 2, &addr);
CHECK_EFI_STATUS_OR_RETURN(status, L"Allocating %d pages for alignment", page_count * 2);
con_debug(L" Found %d pages at %lx\n", page_count * 2, addr);
EFI_PHYSICAL_ADDRESS aligned = addr;
aligned = ((aligned - 1) & ~(alignment - 1)) + alignment;
con_debug(L" Aligning %lx to %lx\n", addr, aligned);
size_t before =
(reinterpret_cast<uint64_t>(aligned) -
reinterpret_cast<uint64_t>(addr)) /
PAGE_SIZE;
if (before) {
con_debug(L" Freeing %d initial pages\n", before);
bootsvc->FreePages(addr, before);
}
size_t after = page_count - before;
if (after) {
EFI_PHYSICAL_ADDRESS end =
reinterpret_cast<EFI_PHYSICAL_ADDRESS>(
reinterpret_cast<uint64_t>(aligned) +
page_count * PAGE_SIZE);
con_debug(L" Freeing %d remaining pages\n", after);
bootsvc->FreePages(end, after);
}
*pages = (void *)aligned;
return EFI_SUCCESS;
}
EFI_STATUS
loader_alloc_pages(
EFI_BOOT_SERVICES *bootsvc,
EFI_MEMORY_TYPE mem_type,
size_t *length,
void **pages,
bool align)
void **pages)
{
EFI_STATUS status;
size_t page_count = ((*length - 1) / PAGE_SIZE) + 1;
EFI_PHYSICAL_ADDRESS addr = (EFI_PHYSICAL_ADDRESS)*pages;
if (align) {
// Align addr to the next multiple of N pages
size_t align_size = page_count * PAGE_SIZE;
addr = ((addr - 1) & ~(align_size - 1)) + align_size;
}
con_debug(L"Trying to find %d non-aligned pages for %x at %lx\n",
page_count, mem_type, addr);
status = bootsvc->AllocatePages(AllocateAddress, mem_type, page_count, &addr);
if (status == EFI_NOT_FOUND || status == EFI_OUT_OF_RESOURCES) {
// couldn't get the address we wanted, try loading the kernel anywhere
status =
bootsvc->AllocatePages(AllocateAnyPages, mem_type, page_count, &addr);
}
CHECK_EFI_STATUS_OR_RETURN(status,
L"Allocating %d kernel pages type %x",
page_count, mem_type);
@@ -69,12 +111,11 @@ loader_load_initrd(
data->initrd_length = ((EFI_FILE_INFO *)info)->FileSize;
status = loader_alloc_pages(
status = loader_alloc_aligned(
bootsvc,
memtype_initrd,
&data->initrd_length,
&data->initrd,
true);
&data->initrd);
CHECK_EFI_STATUS_OR_RETURN(status, L"Allocating pages");
status = file->Read(file, &data->initrd_length, data->initrd);
@@ -161,7 +202,7 @@ loader_load_elf(
length = prog_header.mem_size;
void *addr = (void *)(prog_header.vaddr - KERNEL_VIRT_ADDRESS);
status = loader_alloc_pages(bootsvc, memtype_kernel, &length, &addr, false);
status = loader_alloc_pages(bootsvc, memtype_kernel, &length, &addr);
CHECK_EFI_STATUS_OR_RETURN(status, L"Allocating kernel pages");
if (data->kernel == 0)
@@ -236,20 +277,19 @@ loader_load_kernel(
CHECK_EFI_STATUS_OR_RETURN(status, L"loader_load_elf: %s", kernel_name);
data->initrd = (void *)((uint64_t)data->kernel + data->kernel_length);
status = loader_load_initrd(bootsvc, root, data);
CHECK_EFI_STATUS_OR_RETURN(status, L"loader_load_file: %s", initrd_name);
data->data = (void *)((uint64_t)data->initrd + data->initrd_length);
data->data = (void *)((uint64_t)data->kernel + data->kernel_length);
data->data_length += PAGE_SIZE; // extra page for map growth
status = loader_alloc_pages(
status = loader_alloc_aligned(
bootsvc,
memtype_data,
&data->data_length,
&data->data,
true);
CHECK_EFI_STATUS_OR_RETURN(status, L"loader_alloc_pages: kernel data");
&data->data);
CHECK_EFI_STATUS_OR_RETURN(status, L"loader_alloc_aligned: kernel data");
data->initrd = (void *)((uint64_t)data->data + data->data_length);
status = loader_load_initrd(bootsvc, root, data);
CHECK_EFI_STATUS_OR_RETURN(status, L"loader_load_file: %s", initrd_name);
return EFI_SUCCESS;
}

View File

@@ -133,9 +133,9 @@ efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
status = loader_load_kernel(bootsvc, &load);
CHECK_EFI_STATUS_OR_FAIL(status);
console::print(L" %u image bytes at 0x%x\r\n", load.kernel_length, load.kernel);
console::print(L" %u initrd bytes at 0x%x\r\n", load.initrd_length, load.initrd);
console::print(L" %u data bytes at 0x%x\r\n", load.data_length, load.data);
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) {
@@ -145,7 +145,7 @@ efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
console::print(L" Kernel version %d.%d.%d %x%s\r\n",
version->major, version->minor, version->patch, version->gitsha & 0x0fffffff,
version->gitsha & 0xf0000000 ? "*" : "");
version->gitsha & 0xf0000000 ? L"*" : L"");
console::print(L" Entrypoint 0x%x\r\n", load.kernel_entry);
kernel_entry kernel_main =

View File

@@ -3,6 +3,7 @@ mymessage:
resq 1024
extern main
extern exit
section .text
global getpid
@@ -38,16 +39,6 @@ sleep:
pop rbp
ret
__localexit:
push rbp
mov rbp, rsp
mov rax, 9 ; exit syscall
syscall
jmp __localexit ; shouldn't get here
global _start
_start:
xor rbp, rbp ; Sentinel rbp
@@ -60,4 +51,4 @@ _start:
call main
mov rdi, rax
call __localexit
call exit