efi: cache LoaderEntries EFI variable
Based-on: https://github.com/systemd/systemd/issues/14828#issuecomment-634202054
This commit is contained in:
parent
ceae629564
commit
d4bd786d69
|
@ -1311,6 +1311,7 @@ static int verb_status(int argc, char *argv[], void *userdata) {
|
|||
|
||||
static int verb_list(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(boot_config_free) BootConfig config = {};
|
||||
_cleanup_strv_free_ char **efi_entries = NULL;
|
||||
int r;
|
||||
|
||||
/* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn
|
||||
|
@ -1333,7 +1334,13 @@ static int verb_list(int argc, char *argv[], void *userdata) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) boot_entries_augment_from_loader(&config, false);
|
||||
r = efi_loader_get_entries(&efi_entries);
|
||||
if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r))
|
||||
log_debug_errno(r, "Boot loader reported no entries.");
|
||||
else if (r < 0)
|
||||
log_warning_errno(r, "Failed to determine entries reported by boot loader, ignoring: %m");
|
||||
else
|
||||
(void) boot_entries_augment_from_loader(&config, efi_entries, false);
|
||||
|
||||
if (config.n_entries == 0)
|
||||
log_info("No boot loader entries found.");
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "cgroup-util.h"
|
||||
#include "conf-parser.h"
|
||||
#include "device-util.h"
|
||||
#include "efi-loader.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "limits-util.h"
|
||||
|
@ -817,3 +818,27 @@ void manager_reconnect_utmp(Manager *m) {
|
|||
manager_connect_utmp(m);
|
||||
#endif
|
||||
}
|
||||
|
||||
int manager_read_efi_boot_loader_entries(Manager *m) {
|
||||
#if ENABLE_EFI
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
if (m->efi_boot_loader_entries_set)
|
||||
return 0;
|
||||
|
||||
r = efi_loader_get_entries(&m->efi_boot_loader_entries);
|
||||
if (r == -ENOENT || ERRNO_IS_NOT_SUPPORTED(r)) {
|
||||
log_debug_errno(r, "Boot loader reported no entries.");
|
||||
m->efi_boot_loader_entries_set = true;
|
||||
return 0;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine entries reported by boot loader: %m");
|
||||
|
||||
m->efi_boot_loader_entries_set = true;
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -2969,17 +2969,20 @@ static int property_get_reboot_to_boot_loader_entry(
|
|||
return sd_bus_message_append(reply, "s", v);
|
||||
}
|
||||
|
||||
static int boot_loader_entry_exists(const char *id) {
|
||||
static int boot_loader_entry_exists(Manager *m, const char *id) {
|
||||
_cleanup_(boot_config_free) BootConfig config = {};
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(id);
|
||||
|
||||
r = boot_entries_load_config_auto(NULL, NULL, &config);
|
||||
if (r < 0 && r != -ENOKEY) /* don't complain if no GPT is found, hence skip ENOKEY */
|
||||
return r;
|
||||
|
||||
(void) boot_entries_augment_from_loader(&config, true);
|
||||
r = manager_read_efi_boot_loader_entries(m);
|
||||
if (r >= 0)
|
||||
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries, true);
|
||||
|
||||
return boot_config_has_entry(&config, id);
|
||||
}
|
||||
|
@ -3004,7 +3007,7 @@ static int method_set_reboot_to_boot_loader_entry(
|
|||
if (isempty(v))
|
||||
v = NULL;
|
||||
else if (efi_loader_entry_name_valid(v)) {
|
||||
r = boot_loader_entry_exists(v);
|
||||
r = boot_loader_entry_exists(m, v);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
|
@ -3123,18 +3126,21 @@ static int property_get_boot_loader_entries(
|
|||
sd_bus_error *error) {
|
||||
|
||||
_cleanup_(boot_config_free) BootConfig config = {};
|
||||
Manager *m = userdata;
|
||||
size_t i;
|
||||
int r;
|
||||
|
||||
assert(bus);
|
||||
assert(reply);
|
||||
assert(userdata);
|
||||
assert(m);
|
||||
|
||||
r = boot_entries_load_config_auto(NULL, NULL, &config);
|
||||
if (r < 0 && r != -ENOKEY) /* don't complain if there's no GPT found */
|
||||
return r;
|
||||
|
||||
(void) boot_entries_augment_from_loader(&config, true);
|
||||
r = manager_read_efi_boot_loader_entries(m);
|
||||
if (r >= 0)
|
||||
(void) boot_entries_augment_from_loader(&config, m->efi_boot_loader_entries, true);
|
||||
|
||||
r = sd_bus_message_open_container(reply, 'a', "s");
|
||||
if (r < 0)
|
||||
|
|
|
@ -166,6 +166,8 @@ static Manager* manager_unref(Manager *m) {
|
|||
free(m->wall_message);
|
||||
free(m->action_job);
|
||||
|
||||
strv_free(m->efi_boot_loader_entries);
|
||||
|
||||
return mfree(m);
|
||||
}
|
||||
|
||||
|
|
|
@ -123,6 +123,9 @@ struct Manager {
|
|||
uint64_t runtime_dir_inodes;
|
||||
uint64_t sessions_max;
|
||||
uint64_t inhibitors_max;
|
||||
|
||||
char **efi_boot_loader_entries;
|
||||
bool efi_boot_loader_entries_set;
|
||||
};
|
||||
|
||||
void manager_reset_config(Manager *m);
|
||||
|
@ -168,3 +171,5 @@ CONFIG_PARSER_PROTOTYPE(config_parse_tmpfs_size);
|
|||
|
||||
int manager_setup_wall_message_timer(Manager *m);
|
||||
bool logind_wall_tty_filter(const char *tty, void *userdata);
|
||||
|
||||
int manager_read_efi_boot_loader_entries(Manager *m);
|
||||
|
|
|
@ -735,9 +735,12 @@ int boot_entries_load_config_auto(
|
|||
return boot_entries_load_config(esp_where, xbootldr_where, config);
|
||||
}
|
||||
|
||||
#if ENABLE_EFI
|
||||
int boot_entries_augment_from_loader(BootConfig *config, bool only_auto) {
|
||||
static const char * const title_table[] = {
|
||||
int boot_entries_augment_from_loader(
|
||||
BootConfig *config,
|
||||
char **found_by_loader,
|
||||
bool only_auto) {
|
||||
|
||||
static const char *const title_table[] = {
|
||||
/* Pretty names for a few well-known automatically discovered entries. */
|
||||
"auto-osx", "macOS",
|
||||
"auto-windows", "Windows Boot Manager",
|
||||
|
@ -746,22 +749,14 @@ int boot_entries_augment_from_loader(BootConfig *config, bool only_auto) {
|
|||
"auto-reboot-to-firmware-setup", "Reboot Into Firmware Interface",
|
||||
};
|
||||
|
||||
_cleanup_strv_free_ char **found_by_loader = NULL;
|
||||
size_t n_allocated;
|
||||
char **i;
|
||||
int r;
|
||||
|
||||
assert(config);
|
||||
|
||||
/* Let's add the entries discovered by the boot loader to the end of our list, unless they are
|
||||
* already included there. */
|
||||
|
||||
r = efi_loader_get_entries(&found_by_loader);
|
||||
if (IN_SET(r, -ENOENT, -EOPNOTSUPP))
|
||||
return log_debug_errno(r, "Boot loader reported no entries.");
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine entries reported by boot loader: %m");
|
||||
|
||||
n_allocated = config->n_entries;
|
||||
|
||||
STRV_FOREACH(i, found_by_loader) {
|
||||
|
@ -803,7 +798,6 @@ int boot_entries_augment_from_loader(BootConfig *config, bool only_auto) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/********************************************************************************/
|
||||
|
||||
|
|
|
@ -76,13 +76,7 @@ static inline BootEntry* boot_config_default_entry(BootConfig *config) {
|
|||
void boot_config_free(BootConfig *config);
|
||||
int boot_entries_load_config(const char *esp_path, const char *xbootldr_path, BootConfig *config);
|
||||
int boot_entries_load_config_auto(const char *override_esp_path, const char *override_xbootldr_path, BootConfig *config);
|
||||
#if ENABLE_EFI
|
||||
int boot_entries_augment_from_loader(BootConfig *config, bool only_auto);
|
||||
#else
|
||||
static inline int boot_entries_augment_from_loader(BootConfig *config, bool only_auto) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
int boot_entries_augment_from_loader(BootConfig *config, char **list, bool only_auto);
|
||||
|
||||
static inline const char* boot_entry_title(const BootEntry *entry) {
|
||||
return entry->show_title ?: entry->title ?: entry->id;
|
||||
|
|
Loading…
Reference in a new issue