*ret_status = status;
}
-static int boot_entry_show(const BootEntry *e, bool show_as_default) {
+static int boot_entry_show(
+ const BootEntry *e,
+ bool show_as_default,
+ bool show_as_selected) {
+
int status = 0;
/* Returns 0 on success, negative on processing error, and positive if something is wrong with the
assert(e);
- printf(" title: %s%s%s" "%s%s%s\n",
+ printf(" title: %s%s%s" "%s%s%s" "%s%s%s\n",
ansi_highlight(), boot_entry_title(e), ansi_normal(),
- ansi_highlight_green(), show_as_default ? " (default)" : "", ansi_normal());
+ ansi_highlight_green(), show_as_default ? " (default)" : "", ansi_normal(),
+ ansi_highlight_magenta(), show_as_selected ? " (selected)" : "", ansi_normal());
if (e->id)
printf(" id: %s\n", e->id);
else {
printf("Default Boot Loader Entry:\n");
- r = boot_entry_show(config.entries + config.default_entry, false);
+ r = boot_entry_show(config.entries + config.default_entry, /* show_as_default= */ false, /* show_as_selected= */ false);
if (r > 0)
/* < 0 is already logged by the function itself, let's just emit an extra warning if
the default entry is broken */
printf("Boot Loader Entries:\n");
for (size_t n = 0; n < config.n_entries; n++) {
- r = boot_entry_show(config.entries + n, n == (size_t) config.default_entry);
+ r = boot_entry_show(
+ config.entries + n,
+ n == (size_t) config.default_entry,
+ n == (size_t) config.selected_entry);
if (r < 0)
return r;
free(config->entry_oneshot);
free(config->entry_default);
+ free(config->entry_selected);
for (i = 0; i < config->n_entries; i++)
boot_entry_free(config->entries + i);
return config->n_entries - 1;
}
+static int boot_entries_select_selected(const BootConfig *config) {
+
+ assert(config);
+ assert(config->entries || config->n_entries == 0);
+
+ if (!config->entry_selected || config->n_entries == 0)
+ return -1;
+
+ for (int i = config->n_entries - 1; i >= 0; i--)
+ if (streq(config->entry_selected, config->entries[i].id))
+ return i;
+
+ return -1;
+}
+
+static int boot_load_efi_entry_pointers(BootConfig *config) {
+ int r;
+
+ assert(config);
+
+ if (!is_efi_boot())
+ return 0;
+
+ /* Loads the three "pointers" to boot loader entries from their EFI variables */
+
+ r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryOneShot), &config->entry_oneshot);
+ if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
+ log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryOneShot\": %m");
+ if (r == -ENOMEM)
+ return r;
+ }
+
+ r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryDefault), &config->entry_default);
+ if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
+ log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryDefault\": %m");
+ if (r == -ENOMEM)
+ return r;
+ }
+
+ r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntrySelected), &config->entry_selected);
+ if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
+ log_warning_errno(r, "Failed to read EFI variable \"LoaderEntrySelected\": %m");
+ if (r == -ENOMEM)
+ return r;
+ }
+
+ return 1;
+}
+
int boot_entries_load_config(
const char *esp_path,
const char *xbootldr_path,
if (r < 0)
return log_error_errno(r, "Failed to uniquify boot entries: %m");
- if (is_efi_boot()) {
- r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryOneShot), &config->entry_oneshot);
- if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
- log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryOneShot\": %m");
- if (r == -ENOMEM)
- return r;
- }
-
- r = efi_get_variable_string(EFI_LOADER_VARIABLE(LoaderEntryDefault), &config->entry_default);
- if (r < 0 && !IN_SET(r, -ENOENT, -ENODATA)) {
- log_warning_errno(r, "Failed to read EFI variable \"LoaderEntryDefault\": %m");
- if (r == -ENOMEM)
- return r;
- }
- }
+ r = boot_load_efi_entry_pointers(config);
+ if (r < 0)
+ return r;
config->default_entry = boot_entries_select_default(config);
+ config->selected_entry = boot_entries_select_selected(config);
+
return 0;
}