]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
stub: rework linux handover to take "struct iovec"
authorLennart Poettering <lennart@poettering.net>
Wed, 26 Jun 2024 11:16:18 +0000 (13:16 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 26 Jun 2024 15:09:45 +0000 (17:09 +0200)
src/boot/efi/linux.c
src/boot/efi/linux.h
src/boot/efi/linux_x86.c
src/boot/efi/stub.c

index 65bc176df779e7f0f41a1fc0051062f62f097028..706648b49d32de507f9978f46a03dc920afd2398 100644 (file)
@@ -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");
 
index 46b5f4f4d7c3a8a1de0df854b40c593bd60bff19..1bee8907c407fb1abb810e99925b8304d87100a1 100644 (file)
@@ -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);
index 757902daac580b12984174c375c4b6d2a3c533eb..c456209831d5017ac508b3c8f7a4c9fead2c46b4 100644 (file)
@@ -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);
index 98d31af321704fb7ab5826e6fa6fab198c849fd6..3e95eb17859fcf0f7c3160cc86791adbee6365ba 100644 (file)
@@ -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;
 }