From: Jan Janssen Date: Thu, 28 Oct 2021 08:40:39 +0000 (+0200) Subject: sd-boot: Keep all EFI var loading together X-Git-Tag: v250-rc1~359^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bbe51db6648c630f2557c874cb7a758ecf40a6e8;p=thirdparty%2Fsystemd.git sd-boot: Keep all EFI var loading together This also delays the last remaining EFI var write in menu_run. --- diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index 729e199fcc4..14f42c36c59 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -68,6 +68,7 @@ typedef struct { UINT32 timeout_sec_config; UINT32 timeout_sec_efivar; CHAR16 *entry_default_pattern; + CHAR16 *entry_default_efivar; CHAR16 *entry_oneshot; CHAR16 *options_edit; BOOLEAN editor; @@ -435,7 +436,7 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) { UINT64 key; UINTN x_max, y_max; SecureBootMode secure; - _cleanup_freepool_ CHAR16 *device_part_uuid = NULL, *default_efivar = NULL; + _cleanup_freepool_ CHAR16 *device_part_uuid = NULL; assert(config); assert(loaded_image_path); @@ -445,7 +446,6 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) { secure = secure_boot_mode(); (void) efivar_get(LOADER_GUID, L"LoaderDevicePartUUID", &device_part_uuid); - (void) efivar_get(LOADER_GUID, L"LoaderEntryDefault", &default_efivar); /* We employ some unusual indentation here for readability. */ @@ -487,8 +487,8 @@ static void print_status(Config *config, CHAR16 *loaded_image_path) { } ps_string(L" default: %s\n", config->entry_default_pattern); + ps_string(L" default (EFI var): %s\n", config->entry_default_efivar); ps_string(L" default (one-shot): %s\n", config->entry_oneshot); - ps_string(L" default (EFI var): %s\n", default_efivar); ps_bool(L" editor: %s\n", config->editor); ps_bool(L" auto-entries: %s\n", config->auto_entries); ps_bool(L" auto-firmware: %s\n", config->auto_firmware); @@ -586,6 +586,7 @@ static BOOLEAN menu_run( INT16 idx; BOOLEAN exit = FALSE, run = TRUE, firmware_setup = FALSE; INT64 console_mode_initial = ST->ConOut->Mode->Mode, console_mode_efivar_saved = config->console_mode_efivar; + INTN default_efivar_saved = config->idx_default_efivar; graphics_mode(FALSE); ST->ConIn->Reset(ST->ConIn, FALSE); @@ -831,17 +832,16 @@ static BOOLEAN menu_run( case KEYPRESS(0, 0, 'd'): case KEYPRESS(0, 0, 'D'): if (config->idx_default_efivar != (INTN)idx_highlight) { - /* store the selected entry in a persistent EFI variable */ - efivar_set( - LOADER_GUID, - L"LoaderEntryDefault", - config->entries[idx_highlight]->id, - EFI_VARIABLE_NON_VOLATILE); + FreePool(config->entry_default_efivar); + config->entry_default_efivar = StrDuplicate(config->entries[idx_highlight]->id); + if (!config->entry_default_efivar) { + log_oom(); + return FALSE; + } config->idx_default_efivar = idx_highlight; status = StrDuplicate(L"Default boot entry selected."); } else { - /* clear the default entry EFI variable */ - efivar_set(LOADER_GUID, L"LoaderEntryDefault", NULL, EFI_VARIABLE_NON_VOLATILE); + config->entry_default_efivar = mfree(config->entry_default_efivar); config->idx_default_efivar = -1; status = StrDuplicate(L"Default boot entry cleared."); } @@ -954,6 +954,9 @@ static BOOLEAN menu_run( /* Update EFI vars after we left the menu to reduce NVRAM writes. */ + if (default_efivar_saved != config->idx_default_efivar) + efivar_set(LOADER_GUID, L"LoaderEntryDefault", config->entry_default_efivar, EFI_VARIABLE_NON_VOLATILE); + if (console_mode_efivar_saved != config->console_mode_efivar) { if (config->console_mode_efivar == CONSOLE_MODE_KEEP) efivar_set(LOADER_GUID, L"LoaderConfigConsoleMode", NULL, EFI_VARIABLE_NON_VOLATILE); @@ -1537,6 +1540,13 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) { err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigConsoleMode", &value); if (!EFI_ERROR(err)) config->console_mode_efivar = value; + + err = efivar_get(LOADER_GUID, L"LoaderEntryOneShot", &config->entry_oneshot); + if (!EFI_ERROR(err)) + /* Unset variable now, after all it's "one shot". */ + (void) efivar_set(LOADER_GUID, L"LoaderEntryOneShot", NULL, EFI_VARIABLE_NON_VOLATILE); + + (void) efivar_get(LOADER_GUID, L"LoaderEntryDefault", &config->entry_default_efivar); } static void config_load_entries( @@ -1624,7 +1634,9 @@ static void config_sort_entries(Config *config) { static INTN config_entry_find(Config *config, CHAR16 *id) { assert(config); - assert(id); + + if (!id) + return -1; for (UINTN i = 0; i < config->entry_count; i++) if (StrCmp(config->entries[i]->id, id) == 0) @@ -1634,40 +1646,21 @@ static INTN config_entry_find(Config *config, CHAR16 *id) { } static void config_default_entry_select(Config *config) { - _cleanup_freepool_ CHAR16 *entry_default = NULL; - EFI_STATUS err; INTN i; assert(config); - /* - * The EFI variable to specify a boot entry for the next, and only the - * next reboot. The variable is always cleared directly after it is read. - */ - err = efivar_get(LOADER_GUID, L"LoaderEntryOneShot", &config->entry_oneshot); - if (!EFI_ERROR(err)) { - efivar_set(LOADER_GUID, L"LoaderEntryOneShot", NULL, EFI_VARIABLE_NON_VOLATILE); - - i = config_entry_find(config, config->entry_oneshot); - if (i >= 0) { - config->idx_default = i; - return; - } + i = config_entry_find(config, config->entry_oneshot); + if (i >= 0) { + config->idx_default = i; + return; } - /* - * The EFI variable to select the default boot entry overrides the - * configured pattern. The variable can be set and cleared by pressing - * the 'd' key in the loader selection menu. - */ - err = efivar_get(LOADER_GUID, L"LoaderEntryDefault", &entry_default); - if (!EFI_ERROR(err)) { - i = config_entry_find(config, entry_default); - if (i >= 0) { - config->idx_default = i; - config->idx_default_efivar = i; - return; - } + i = config_entry_find(config, config->entry_default_efivar); + if (i >= 0) { + config->idx_default = i; + config->idx_default_efivar = i; + return; } if (config->entry_count == 0)