Allow larger initrd images
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user