]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
bootctl: include boot entries discovered by the boot loader but not in $BOOT in the... 10175/head
authorLennart Poettering <lennart@poettering.net>
Mon, 25 Jun 2018 19:09:37 +0000 (21:09 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 8 Oct 2018 19:40:44 +0000 (21:40 +0200)
Let's use the new LoaderEntries efi var for this, and show all entries
we couldn't find via the config snippets.

man/bootctl.xml
src/boot/bootctl.c
src/shared/efivars.c
src/shared/efivars.h

index 45ea93252cffe5f796b7ef8d61529f8a74d8b063..816b618087425d8de4b6d5fd72b9687b8034ecef 100644 (file)
 
         <listitem><para>Shows all available boot loader entries implementing the <ulink
         url="https://github.com/systemd/systemd/blob/master/docs/BOOT_LOADER_SPECIFICATION.md">Boot Loader
-        Specification</ulink></para></listitem>
+        Specification</ulink>, as well as any other entries discovered or automatically generated by the boot
+        loader.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 955453d119aa3b6d381c9159bcb6d5b4c4e5574d..c97d21c22862301f1de40a2cddc4fa1498899098 100644 (file)
@@ -1027,6 +1027,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_free_ char **found_by_loader = NULL;
         sd_id128_t uuid = SD_ID128_NULL;
         int r;
 
@@ -1044,6 +1045,10 @@ static int verb_list(int argc, char *argv[], void *userdata) {
         if (r < 0)
                 return r;
 
+        r = efi_loader_get_entries(&found_by_loader);
+        if (r < 0 && !IN_SET(r, -ENOENT, -EOPNOTSUPP))
+                log_debug_errno(r, "Failed to acquire boot loader discovered entries: %m");
+
         if (config.n_entries == 0)
                 log_info("No boot loader entries found.");
         else {
@@ -1059,9 +1064,20 @@ static int verb_list(int argc, char *argv[], void *userdata) {
                                 return r;
 
                         puts("");
+
+                        strv_remove(found_by_loader, config.entries[n].id);
                 }
         }
 
+        if (!strv_isempty(found_by_loader)) {
+                char **i;
+
+                printf("Automatic/Other Entries Found by Boot Loader:\n\n");
+
+                STRV_FOREACH(i, found_by_loader)
+                        puts(*i);
+        }
+
         return 0;
 }
 
index e4b16a57431e746497cb113c8bfdd0dea62339ab..3931bee559867ebda53719f267cfcd59e4ed1199 100644 (file)
@@ -22,6 +22,7 @@
 #include "macro.h"
 #include "parse-util.h"
 #include "stdio-util.h"
+#include "strv.h"
 #include "time-util.h"
 #include "utf8.h"
 #include "util.h"
@@ -753,6 +754,56 @@ int efi_loader_get_device_part_uuid(sd_id128_t *u) {
         return 0;
 }
 
+int efi_loader_get_entries(char ***ret) {
+        _cleanup_free_ char16_t *entries = NULL;
+        _cleanup_strv_free_ char **l = NULL;
+        size_t size, i, start;
+        int r;
+
+        assert(ret);
+
+        if (!is_efi_boot())
+                return -EOPNOTSUPP;
+
+        r = efi_get_variable(EFI_VENDOR_LOADER, "LoaderEntries", NULL, (void**) &entries, &size);
+        if (r < 0)
+                return r;
+
+        /* The variable contains a series of individually NUL terminated UTF-16 strings. */
+
+        for (i = 0, start = 0;; i++) {
+                char *decoded;
+                bool end;
+
+                /* Is this the end of the variable's data? */
+                end = i * sizeof(char16_t) >= size;
+
+                /* Are we in the middle of a string? (i.e. not at the end of the variable, nor at a NUL terminator?) If
+                 * so, let's go to the next entry. */
+                if (!end && entries[i] != 0)
+                        continue;
+
+                /* We reached the end of a string, let's decode it into UTF-8 */
+                decoded = utf16_to_utf8(entries + start, (i - start) * sizeof(char16_t));
+                if (!decoded)
+                        return -ENOMEM;
+
+                r = strv_consume(&l, decoded);
+                if (r < 0)
+                        return r;
+
+                /* We reached the end of the variable */
+                if (end)
+                        break;
+
+                /* Continue after the NUL byte */
+                start = i + 1;
+        }
+
+        *ret = TAKE_PTR(l);
+        return 0;
+}
+
 #endif
 
 char *efi_tilt_backslashes(char *s) {
index dac66da9f8ac9a4a23c0c49860e54db50f300ca1..9b5ab39fee2d3616032e3bd2836df7ad000aa729 100644 (file)
@@ -41,6 +41,8 @@ int efi_get_boot_options(uint16_t **options);
 int efi_loader_get_device_part_uuid(sd_id128_t *u);
 int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader);
 
+int efi_loader_get_entries(char ***ret);
+
 #else
 
 static inline bool is_efi_boot(void) {
@@ -111,6 +113,10 @@ static inline int efi_loader_get_boot_usec(usec_t *firmware, usec_t *loader) {
         return -EOPNOTSUPP;
 }
 
+static inline int efi_loader_get_entries(char ***ret) {
+        return -EOPNOTSUPP;
+}
+
 #endif
 
 char *efi_tilt_backslashes(char *s);