From: Lennart Poettering Date: Wed, 26 Jun 2024 11:16:18 +0000 (+0200) Subject: stub: rework linux handover to take "struct iovec" X-Git-Tag: v257-rc1~1041^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4a3659c5f400cbcddbe251ec980798d43db66781;p=thirdparty%2Fsystemd.git stub: rework linux handover to take "struct iovec" --- diff --git a/src/boot/efi/linux.c b/src/boot/efi/linux.c index 65bc176df77..706648b49d3 100644 --- a/src/boot/efi/linux.c +++ b/src/boot/efi/linux.c @@ -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"); diff --git a/src/boot/efi/linux.h b/src/boot/efi/linux.h index 46b5f4f4d7c..1bee8907c40 100644 --- a/src/boot/efi/linux.h +++ b/src/boot/efi/linux.h @@ -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); diff --git a/src/boot/efi/linux_x86.c b/src/boot/efi/linux_x86.c index 757902daac5..c456209831d 100644 --- a/src/boot/efi/linux_x86.c +++ b/src/boot/efi/linux_x86.c @@ -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); diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index 98d31af3217..3e95eb17859 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -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; }