From 39baec852b45d75c936a97dcc6a81bb15bc5b1e7 Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Mon, 25 Mar 2019 00:14:20 -0700 Subject: [PATCH] Allow larger initrd images --- src/boot/loader.cpp | 92 +++++++++++++++++++++++++++----------- src/boot/main.cpp | 8 ++-- src/drivers/nulldrv/main.s | 13 +----- 3 files changed, 72 insertions(+), 41 deletions(-) diff --git a/src/boot/loader.cpp b/src/boot/loader.cpp index 1261c5b..fc14385 100644 --- a/src/boot/loader.cpp +++ b/src/boot/loader.cpp @@ -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(aligned) - + reinterpret_cast(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( + reinterpret_cast(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; } diff --git a/src/boot/main.cpp b/src/boot/main.cpp index bc5e2bd..52519bf 100644 --- a/src/boot/main.cpp +++ b/src/boot/main.cpp @@ -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 = diff --git a/src/drivers/nulldrv/main.s b/src/drivers/nulldrv/main.s index b5e8254..37785c8 100644 --- a/src/drivers/nulldrv/main.s +++ b/src/drivers/nulldrv/main.s @@ -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