stub: rework linux handover to take "struct iovec"
This commit is contained in:
+9
-13
@@ -93,19 +93,17 @@ static EFI_STATUS load_image(EFI_HANDLE parent, const void *source, size_t len,
|
||||
EFI_STATUS linux_exec(
|
||||
EFI_HANDLE parent,
|
||||
const char16_t *cmdline,
|
||||
const void *linux_buffer,
|
||||
size_t linux_length,
|
||||
const void *initrd_buffer,
|
||||
size_t initrd_length) {
|
||||
const struct iovec *kernel,
|
||||
const struct iovec *initrd) {
|
||||
|
||||
uint32_t compat_address;
|
||||
EFI_STATUS err;
|
||||
|
||||
assert(parent);
|
||||
assert(linux_buffer && linux_length > 0);
|
||||
assert(initrd_buffer || initrd_length == 0);
|
||||
assert(iovec_is_set(kernel));
|
||||
assert(iovec_is_valid(initrd));
|
||||
|
||||
err = pe_kernel_info(linux_buffer, &compat_address);
|
||||
err = pe_kernel_info(kernel->iov_base, &compat_address);
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
if (err == EFI_UNSUPPORTED)
|
||||
/* Kernel is too old to support LINUX_INITRD_MEDIA_GUID, try the deprecated EFI handover
|
||||
@@ -113,16 +111,14 @@ EFI_STATUS linux_exec(
|
||||
return linux_exec_efi_handover(
|
||||
parent,
|
||||
cmdline,
|
||||
linux_buffer,
|
||||
linux_length,
|
||||
initrd_buffer,
|
||||
initrd_length);
|
||||
kernel,
|
||||
initrd);
|
||||
#endif
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Bad kernel image: %m");
|
||||
|
||||
_cleanup_(unload_imagep) EFI_HANDLE kernel_image = NULL;
|
||||
err = load_image(parent, linux_buffer, linux_length, &kernel_image);
|
||||
err = load_image(parent, kernel->iov_base, kernel->iov_len, &kernel_image);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error loading kernel image: %m");
|
||||
|
||||
@@ -138,7 +134,7 @@ EFI_STATUS linux_exec(
|
||||
}
|
||||
|
||||
_cleanup_(cleanup_initrd) EFI_HANDLE initrd_handle = NULL;
|
||||
err = initrd_register(initrd_buffer, initrd_length, &initrd_handle);
|
||||
err = initrd_register(initrd->iov_base, initrd->iov_len, &initrd_handle);
|
||||
if (err != EFI_SUCCESS)
|
||||
return log_error_status(err, "Error registering initrd: %m");
|
||||
|
||||
|
||||
@@ -2,18 +2,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "efi.h"
|
||||
#include "iovec-util-fundamental.h"
|
||||
|
||||
EFI_STATUS linux_exec(
|
||||
EFI_HANDLE parent,
|
||||
const char16_t *cmdline,
|
||||
const void *linux_buffer,
|
||||
size_t linux_length,
|
||||
const void *initrd_buffer,
|
||||
size_t initrd_length);
|
||||
const struct iovec *kernel,
|
||||
const struct iovec *initrd);
|
||||
EFI_STATUS linux_exec_efi_handover(
|
||||
EFI_HANDLE parent,
|
||||
const char16_t *cmdline,
|
||||
const void *linux_buffer,
|
||||
size_t linux_length,
|
||||
const void *initrd_buffer,
|
||||
size_t initrd_length);
|
||||
const struct iovec *kernel,
|
||||
const struct iovec *initrd);
|
||||
|
||||
+21
-19
@@ -123,19 +123,17 @@ static void linux_efi_handover(EFI_HANDLE parent, uintptr_t kernel, BootParams *
|
||||
EFI_STATUS linux_exec_efi_handover(
|
||||
EFI_HANDLE parent,
|
||||
const char16_t *cmdline,
|
||||
const void *linux_buffer,
|
||||
size_t linux_length,
|
||||
const void *initrd_buffer,
|
||||
size_t initrd_length) {
|
||||
const struct iovec *kernel,
|
||||
const struct iovec *initrd) {
|
||||
|
||||
assert(parent);
|
||||
assert(linux_buffer);
|
||||
assert(initrd_buffer || initrd_length == 0);
|
||||
assert(iovec_is_set(kernel));
|
||||
assert(iovec_is_valid(initrd));
|
||||
|
||||
if (linux_length < sizeof(BootParams))
|
||||
if (kernel->iov_len < sizeof(BootParams))
|
||||
return EFI_LOAD_ERROR;
|
||||
|
||||
const BootParams *image_params = (const BootParams *) linux_buffer;
|
||||
const BootParams *image_params = (const BootParams *) kernel->iov_base;
|
||||
if (image_params->hdr.header != SETUP_MAGIC || image_params->hdr.boot_flag != BOOT_FLAG_MAGIC)
|
||||
return log_error_status(EFI_UNSUPPORTED, "Unsupported kernel image.");
|
||||
if (image_params->hdr.version < SETUP_VERSION_2_11)
|
||||
@@ -155,22 +153,26 @@ EFI_STATUS linux_exec_efi_handover(
|
||||
/* There is no way to pass the high bits of code32_start. Newer kernels seems to handle this
|
||||
* just fine, but older kernels will fail even if they otherwise have above 4G boot support. */
|
||||
_cleanup_pages_ Pages linux_relocated = {};
|
||||
if (POINTER_TO_PHYSICAL_ADDRESS(linux_buffer) + linux_length > UINT32_MAX) {
|
||||
const void *linux_buffer;
|
||||
if (POINTER_TO_PHYSICAL_ADDRESS(kernel->iov_base) + kernel->iov_len > UINT32_MAX) {
|
||||
linux_relocated = xmalloc_pages(
|
||||
AllocateMaxAddress, EfiLoaderCode, EFI_SIZE_TO_PAGES(linux_length), UINT32_MAX);
|
||||
AllocateMaxAddress, EfiLoaderCode, EFI_SIZE_TO_PAGES(kernel->iov_len), UINT32_MAX);
|
||||
linux_buffer = memcpy(
|
||||
PHYSICAL_ADDRESS_TO_POINTER(linux_relocated.addr), linux_buffer, linux_length);
|
||||
}
|
||||
PHYSICAL_ADDRESS_TO_POINTER(linux_relocated.addr), kernel->iov_base, kernel->iov_len);
|
||||
} else
|
||||
linux_buffer = kernel->iov_base;
|
||||
|
||||
_cleanup_pages_ Pages initrd_relocated = {};
|
||||
if (!can_4g && POINTER_TO_PHYSICAL_ADDRESS(initrd_buffer) + initrd_length > UINT32_MAX) {
|
||||
const void *initrd_buffer;
|
||||
if (!can_4g && POINTER_TO_PHYSICAL_ADDRESS(initrd->iov_base) + initrd->iov_len > UINT32_MAX) {
|
||||
initrd_relocated = xmalloc_pages(
|
||||
AllocateMaxAddress, EfiLoaderData, EFI_SIZE_TO_PAGES(initrd_length), UINT32_MAX);
|
||||
AllocateMaxAddress, EfiLoaderData, EFI_SIZE_TO_PAGES(initrd->iov_len), UINT32_MAX);
|
||||
initrd_buffer = memcpy(
|
||||
PHYSICAL_ADDRESS_TO_POINTER(initrd_relocated.addr),
|
||||
initrd_buffer,
|
||||
initrd_length);
|
||||
}
|
||||
initrd->iov_base,
|
||||
initrd->iov_len);
|
||||
} else
|
||||
initrd_buffer = initrd->iov_base;
|
||||
|
||||
_cleanup_pages_ Pages boot_params_page = xmalloc_pages(
|
||||
can_4g ? AllocateAnyPages : AllocateMaxAddress,
|
||||
@@ -215,8 +217,8 @@ EFI_STATUS linux_exec_efi_handover(
|
||||
|
||||
boot_params->hdr.ramdisk_image = (uintptr_t) initrd_buffer;
|
||||
boot_params->ext_ramdisk_image = POINTER_TO_PHYSICAL_ADDRESS(initrd_buffer) >> 32;
|
||||
boot_params->hdr.ramdisk_size = initrd_length;
|
||||
boot_params->ext_ramdisk_size = ((uint64_t) initrd_length) >> 32;
|
||||
boot_params->hdr.ramdisk_size = initrd->iov_len;
|
||||
boot_params->ext_ramdisk_size = ((uint64_t) initrd->iov_len) >> 32;
|
||||
|
||||
log_wait();
|
||||
linux_efi_handover(parent, (uintptr_t) linux_buffer, boot_params);
|
||||
|
||||
+1
-3
@@ -974,9 +974,7 @@ static EFI_STATUS run(EFI_HANDLE image) {
|
||||
(const uint8_t*) loaded_image->ImageBase + sections[UNIFIED_SECTION_LINUX].memory_offset,
|
||||
sections[UNIFIED_SECTION_LINUX].size);
|
||||
|
||||
err = linux_exec(image, cmdline,
|
||||
kernel.iov_base, kernel.iov_len,
|
||||
final_initrd.iov_base, final_initrd.iov_len);
|
||||
err = linux_exec(image, cmdline, &kernel, &final_initrd);
|
||||
graphics_mode(false);
|
||||
return err;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user