1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-11 05:17:44 +03:00

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.
This commit is contained in:
Jan Janssen 2022-02-08 11:03:20 +01:00 committed by Luca Boccassi
parent 5c330b3682
commit acdf7d157b

View File

@ -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);