1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-02-08 05:57:26 +03:00

sd-boot: introduce and use efivar_unset()

Currently some of the code base check for the variable presence before
removing it, and some do not.

More so, in all cases (being updated) we're dealing with non-volatile
variables where changing those attribute to NVRAM wear out.

From what information I could find, there is no definitive answer if the
UEFI implementation will write to the NVRAM even when the variable is
missing.

So add a simple helper that checks for the variable presence before
removing it. While also having a bit cleaner API than the current
efivar_set(..., NULL, ...);

efivar_unset() follows the design from efivar_set*() where it returns an
EFI_STATUS even though its (presently) unused.

v2:
 - add inline comment, use early return

v3:
 - typos? typos!

Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
(cherry picked from commit 5ee3c914a4e904567e66654177b07777dde0d100)
(cherry picked from commit 917569e3c1e1361d2c7bac584b99e075a4cb0b0d)
This commit is contained in:
Emil Velikov 2023-10-04 11:51:47 +01:00 committed by Luca Boccassi
parent a8b7bf4e3d
commit 9163d0a4e7
3 changed files with 22 additions and 5 deletions

View File

@ -1049,7 +1049,7 @@ static bool menu_run(
if (console_mode_efivar_saved != config->console_mode_efivar) {
if (config->console_mode_efivar == CONSOLE_MODE_KEEP)
efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderConfigConsoleMode", NULL, EFI_VARIABLE_NON_VOLATILE);
efivar_unset(MAKE_GUID_PTR(LOADER), u"LoaderConfigConsoleMode", EFI_VARIABLE_NON_VOLATILE);
else
efivar_set_uint_string(MAKE_GUID_PTR(LOADER), u"LoaderConfigConsoleMode",
config->console_mode_efivar, EFI_VARIABLE_NON_VOLATILE);
@ -1058,7 +1058,7 @@ static bool menu_run(
if (timeout_efivar_saved != config->timeout_sec_efivar) {
switch (config->timeout_sec_efivar) {
case TIMEOUT_UNSET:
efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderConfigTimeout", NULL, EFI_VARIABLE_NON_VOLATILE);
efivar_unset(MAKE_GUID_PTR(LOADER), u"LoaderConfigTimeout", EFI_VARIABLE_NON_VOLATILE);
break;
case TIMEOUT_MENU_FORCE:
efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderConfigTimeout", u"menu-force", EFI_VARIABLE_NON_VOLATILE);
@ -1609,7 +1609,7 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
err = efivar_get_timeout(u"LoaderConfigTimeoutOneShot", &config->timeout_sec);
if (err == EFI_SUCCESS) {
/* Unset variable now, after all it's "one shot". */
(void) efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderConfigTimeoutOneShot", NULL, EFI_VARIABLE_NON_VOLATILE);
(void) efivar_unset(MAKE_GUID_PTR(LOADER), u"LoaderConfigTimeoutOneShot", EFI_VARIABLE_NON_VOLATILE);
config->force_menu = true; /* force the menu when this is set */
} else if (err != EFI_NOT_FOUND)
@ -1622,7 +1622,7 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
err = efivar_get(MAKE_GUID_PTR(LOADER), u"LoaderEntryOneShot", &config->entry_oneshot);
if (err == EFI_SUCCESS)
/* Unset variable now, after all it's "one shot". */
(void) efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderEntryOneShot", NULL, EFI_VARIABLE_NON_VOLATILE);
(void) efivar_unset(MAKE_GUID_PTR(LOADER), u"LoaderEntryOneShot", EFI_VARIABLE_NON_VOLATILE);
(void) efivar_get(MAKE_GUID_PTR(LOADER), u"LoaderEntryDefault", &config->entry_default_efivar);
@ -2488,7 +2488,7 @@ static void save_selected_entry(const Config *config, const ConfigEntry *entry)
(void) efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderEntryLastBooted", entry->id, EFI_VARIABLE_NON_VOLATILE);
} else
/* Delete the non-volatile var if not needed. */
(void) efivar_set(MAKE_GUID_PTR(LOADER), u"LoaderEntryLastBooted", NULL, EFI_VARIABLE_NON_VOLATILE);
(void) efivar_unset(MAKE_GUID_PTR(LOADER), u"LoaderEntryLastBooted", EFI_VARIABLE_NON_VOLATILE);
}
static EFI_STATUS secure_boot_discover_keys(Config *config, EFI_FILE *root_dir) {

View File

@ -84,6 +84,21 @@ EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, const char16_t *name, ui
return efivar_set_raw(vendor, name, buf, sizeof(buf), flags);
}
EFI_STATUS efivar_unset(const EFI_GUID *vendor, const char16_t *name, uint32_t flags) {
EFI_STATUS err;
assert(vendor);
assert(name);
/* We could be wiping a non-volatile variable here and the spec makes no guarantees that won't incur
* in an extra write (and thus wear out). So check and clear only if needed. */
err = efivar_get_raw(vendor, name, NULL, NULL);
if (err == EFI_SUCCESS)
return efivar_set_raw(vendor, name, NULL, 0, flags);
return err;
}
EFI_STATUS efivar_get(const EFI_GUID *vendor, const char16_t *name, char16_t **ret) {
_cleanup_free_ char16_t *buf = NULL;
EFI_STATUS err;

View File

@ -88,6 +88,8 @@ EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, const char16_t *NAME, ui
EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, const char16_t *name, uint64_t value, uint32_t flags);
void efivar_set_time_usec(const EFI_GUID *vendor, const char16_t *name, uint64_t usec);
EFI_STATUS efivar_unset(const EFI_GUID *vendor, const char16_t *name, uint32_t flags);
EFI_STATUS efivar_get(const EFI_GUID *vendor, const char16_t *name, char16_t **ret);
EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const char16_t *name, char **ret, size_t *ret_size);
EFI_STATUS efivar_get_uint_string(const EFI_GUID *vendor, const char16_t *name, size_t *ret);