From: Jan Janssen Date: Tue, 8 Feb 2022 10:03:20 +0000 (+0100) Subject: boot: Keep initrds separate from cmdline options X-Git-Tag: v252-rc1~946^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=acdf7d157b4df8a6ed9a6a5cbf51b304593b3c22;p=thirdparty%2Fsystemd.git boot: Keep initrds separate from cmdline options This is in preparation for LINUX_INITRD_MEDIA support in boot.c. One downside is that adding or changing the used initrds by command line editing is not possible anymore. --- diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index 7eb8b0dc18c..7b0fcf20ffc 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -12,6 +12,7 @@ #include "drivers.h" #include "efivars-fundamental.h" #include "graphics.h" +#include "initrd.h" #include "linux.h" #include "measure.h" #include "pe.h" @@ -61,6 +62,7 @@ typedef struct { CHAR16 *loader; CHAR16 *devicetree; CHAR16 *options; + CHAR16 **initrd; CHAR16 key; EFI_STATUS (*call)(void); UINTN tries_done; @@ -559,6 +561,8 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) { if (entry->device) Print(L" device: %D\n", DevicePathFromHandle(entry->device)); ps_string(L" loader: %s\n", entry->loader); + STRV_FOREACH(initrd, entry->initrd) + Print(L" initrd: %s\n", *initrd); ps_string(L" devicetree: %s\n", entry->devicetree); ps_string(L" options: %s\n", entry->options); ps_bool(L" internal call: %s\n", !!entry->call); @@ -1055,6 +1059,7 @@ static void config_entry_free(ConfigEntry *entry) { FreePool(entry->loader); FreePool(entry->devicetree); FreePool(entry->options); + strv_free(entry->initrd); FreePool(entry->path); FreePool(entry->current_name); FreePool(entry->next_name); @@ -1427,10 +1432,9 @@ static void config_entry_add_from_file( _cleanup_(config_entry_freep) ConfigEntry *entry = NULL; CHAR8 *line; - UINTN pos = 0; + UINTN pos = 0, n_initrd = 0; CHAR8 *key, *value; EFI_STATUS err; - _cleanup_freepool_ CHAR16 *initrd = NULL; assert(config); assert(device); @@ -1507,18 +1511,12 @@ static void config_entry_add_from_file( } if (strcmpa((CHAR8 *)"initrd", key) == 0) { - _cleanup_freepool_ CHAR16 *new = NULL; - - new = xstra_to_path(value); - if (initrd) { - CHAR16 *s; - - s = xpool_print(L"%s initrd=%s", initrd, new); - FreePool(initrd); - initrd = s; - } else - initrd = xpool_print(L"initrd=%s", new); - + entry->initrd = xreallocate_pool( + entry->initrd, + n_initrd == 0 ? 0 : (n_initrd + 1) * sizeof(UINT16 *), + (n_initrd + 2) * sizeof(UINT16 *)); + entry->initrd[n_initrd++] = xstra_to_path(value); + entry->initrd[n_initrd] = NULL; continue; } @@ -1548,18 +1546,6 @@ static void config_entry_add_from_file( if (EFI_ERROR(err)) return; - /* add initrd= to options */ - if (entry->type == LOADER_LINUX && initrd) { - if (entry->options) { - CHAR16 *s; - - s = xpool_print(L"%s %s", initrd, entry->options); - FreePool(entry->options); - entry->options = s; - } else - entry->options = TAKE_PTR(initrd); - } - entry->device = device; entry->id = xstrdup(file); StrLwr(entry->id); @@ -2313,6 +2299,41 @@ static void config_load_xbootldr( config_load_entries(config, new_device, root_dir, NULL); } +static EFI_STATUS initrd_prepare( + EFI_FILE *root, + const ConfigEntry *entry, + CHAR16 **ret_options) { + + assert(root); + assert(entry); + assert(ret_options); + + if (entry->type != LOADER_LINUX || !entry->initrd) { + ret_options = NULL; + return EFI_SUCCESS; + } + + /* Add initrd= to options for older kernels that do not support LINUX_INITRD_MEDIA. Should be dropped + * if linux_x86.c is dropped. */ + _cleanup_freepool_ CHAR16 *options = NULL; + + STRV_FOREACH(i, entry->initrd) { + _cleanup_freepool_ CHAR16 *o = options; + if (o) + options = xpool_print(L"%s initrd=%s", o, *i); + else + options = xpool_print(L"initrd=%s", *i); + } + + if (entry->options) { + _cleanup_freepool_ CHAR16 *o = options; + options = xpool_print(L"%s %s", o, entry->options); + } + + *ret_options = TAKE_PTR(options); + return EFI_SUCCESS; +} + static EFI_STATUS image_start( EFI_HANDLE parent_image, const ConfigEntry *entry) { @@ -2336,6 +2357,11 @@ static EFI_STATUS image_start( if (!path) return log_error_status_stall(EFI_INVALID_PARAMETER, L"Error getting device path."); + _cleanup_freepool_ CHAR16 *options_initrd = NULL; + err = initrd_prepare(image_root, entry, &options_initrd); + if (EFI_ERROR(err)) + return log_error_status_stall(err, L"Error preparing initrd: %r", err); + err = BS->LoadImage(FALSE, parent_image, path, NULL, 0, &image); if (EFI_ERROR(err)) return log_error_status_stall(err, L"Error loading %s: %r", entry->loader, err); @@ -2346,18 +2372,19 @@ static EFI_STATUS image_start( return log_error_status_stall(err, L"Error loading %s: %r", entry->devicetree, err); } - if (entry->options) { + CHAR16 *options = options_initrd ?: entry->options; + if (options) { EFI_LOADED_IMAGE *loaded_image; err = BS->OpenProtocol(image, &LoadedImageProtocol, (void **)&loaded_image, parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR(err)) return log_error_status_stall(err, L"Error getting LoadedImageProtocol handle: %r", err); - loaded_image->LoadOptions = entry->options; - loaded_image->LoadOptionsSize = StrSize(loaded_image->LoadOptions); + loaded_image->LoadOptions = options; + loaded_image->LoadOptionsSize = StrSize(options); /* Try to log any options to the TPM, especially to catch manually edited options */ - (void) tpm_log_load_options(entry->options); + (void) tpm_log_load_options(options); } efivar_set_time_usec(LOADER_GUID, L"LoaderTimeExecUSec", 0);