]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
efi: cache LoaderEntries EFI variable
authorLennart Poettering <lennart@poettering.net>
Tue, 26 May 2020 20:24:02 +0000 (22:24 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 29 May 2020 13:40:01 +0000 (15:40 +0200)
Based-on:

https://github.com/systemd/systemd/issues/14828#issuecomment-634202054

src/boot/bootctl.c
src/login/logind-core.c
src/login/logind-dbus.c
src/login/logind.c
src/login/logind.h
src/shared/bootspec.c
src/shared/bootspec.h

index a197668ce96e287998d31a6b2131ec4a9ae43612..ab145d65f5bcad3a9a3baab64c6991e911b1319a 100644 (file)
@@ -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.");
index c160f546bca7cc95e96eb5d0505d0781c0fdac3e..1375f438e4be893885859cf84d50e4534a88d9e6 100644 (file)
@@ -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
+}
index a88605232c40428c8441604e681ab38719184059..7fed32c3b416bf6f60ce13c12c7ab4c4378a704c 100644 (file)
@@ -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)
index d167080c2665ff7028d15c83644974cc137c2cc2..5a556f9ea4ad074de26847b906e89b4dd6a81050 100644 (file)
@@ -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);
 }
 
index e1d57277fa1bd20adea1fc90a3b79d292119d924..7dbf0c28e18ad18c1734b99d15006a4a2dc656ea 100644 (file)
@@ -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);
index 13d7b2f16075ae37cfea2d8e82d39d3e04d473eb..11bba2c7edfadd737d7be627fcc26432f10f4f9b 100644 (file)
@@ -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
 
 /********************************************************************************/
 
index b40680b643b3b3ff39419ec763e9cbc016f09f44..1075a41d54151d70a237a67eca524020fd796ed3 100644 (file)
@@ -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;