static int boot_entry_show(const BootEntry *e, bool show_as_default) {
assert(e);
- printf(" title: %s%s%s%s%s%s\n",
+ printf(" title: %s%s%s%s%s%s\n"
+ " type: %s\n",
ansi_highlight(),
boot_entry_title(e),
ansi_normal(),
ansi_highlight_green(),
show_as_default ? " (default)" : "",
- ansi_normal());
+ ansi_normal(),
+ boot_entry_type_to_string(e->type));
if (e->id)
printf(" id: %s\n", e->id);
static int verb_list(int argc, char *argv[], void *userdata) {
_cleanup_(boot_config_free) BootConfig config = {};
- _cleanup_free_ char **found_by_loader = NULL;
int r;
/* If we lack privileges we invoke find_esp_and_warn() in "unprivileged mode" here, which does two things: turn
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");
+ (void) boot_entries_augment_from_loader(&config, false);
if (config.n_entries == 0)
log_info("No boot loader entries found.");
if (n+1 < config.n_entries)
putchar('\n');
-
- strv_remove(found_by_loader, config.entries[n].id);
}
}
- if (!strv_isempty(found_by_loader)) {
- char **i;
-
- printf("\nAutomatic/Other Entries Found by Boot Loader:\n\n");
-
- STRV_FOREACH(i, found_by_loader)
- puts(*i);
- }
-
return 0;
}
#include "path-util.h"
#include "pe-header.h"
#include "stat-util.h"
+#include "string-table.h"
#include "string-util.h"
#include "strv.h"
#include "unaligned.h"
const char *path,
BootEntry *entry) {
- _cleanup_(boot_entry_free) BootEntry tmp = {};
+ _cleanup_(boot_entry_free) BootEntry tmp = {
+ .type = BOOT_ENTRY_CONF,
+ };
+
_cleanup_fclose_ FILE *f = NULL;
unsigned line = 1;
char *b, *c;
BootEntry *ret) {
_cleanup_free_ char *os_pretty_name = NULL, *os_id = NULL, *version_id = NULL, *build_id = NULL;
- _cleanup_(boot_entry_free) BootEntry tmp = {};
+ _cleanup_(boot_entry_free) BootEntry tmp = {
+ .type = BOOT_ENTRY_UNIFIED,
+ };
_cleanup_fclose_ FILE *f = NULL;
const char *k;
int r;
return 0;
}
+int boot_entries_augment_from_loader(BootConfig *config, 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",
+ "auto-efi-shell", "EFI Shell",
+ "auto-efi-default", "EFI Default Loader",
+ "auto-reboot-to-firmware-setup", "Reboot Into Firmware Interface",
+ };
+
+ _cleanup_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) {
+ _cleanup_free_ char *c = NULL, *t = NULL;
+ char **a, **b;
+
+ if (boot_config_has_entry(config, *i))
+ continue;
+
+ if (only_auto && !startswith(*i, "auto-"))
+ continue;
+
+ c = strdup(*i);
+ if (!c)
+ return log_oom();
+
+ STRV_FOREACH_PAIR(a, b, (char**) title_table)
+ if (streq(*a, *i)) {
+ t = strdup(*b);
+ if (!t)
+ return log_oom();
+ break;
+ }
+
+ if (!GREEDY_REALLOC0(config->entries, n_allocated, config->n_entries + 1))
+ return log_oom();
+
+ config->entries[config->n_entries++] = (BootEntry) {
+ .type = BOOT_ENTRY_LOADER,
+ .id = TAKE_PTR(c),
+ .title = TAKE_PTR(t),
+ };
+ }
+
+ return 0;
+}
+
/********************************************************************************/
static int verify_esp_blkid(
return 0;
}
+
+static const char* const boot_entry_type_table[_BOOT_ENTRY_MAX] = {
+ [BOOT_ENTRY_CONF] = "conf",
+ [BOOT_ENTRY_UNIFIED] = "unified",
+ [BOOT_ENTRY_LOADER] = "loader",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(boot_entry_type, BootEntryType);
#include "sd-id128.h"
+#include "string-util.h"
+
+typedef enum BootEntryType {
+ BOOT_ENTRY_CONF, /* Type #1 entries: *.conf files */
+ BOOT_ENTRY_UNIFIED, /* Type #2 entries: *.efi files */
+ BOOT_ENTRY_LOADER, /* Additional entries augmented from LoaderEntries EFI var */
+ _BOOT_ENTRY_MAX,
+ _BOOT_ENTRY_INVALID = -1,
+} BootEntryType;
+
typedef struct BootEntry {
+ BootEntryType type;
char *id; /* This is the file basename without extension */
char *path; /* This is the full path to the drop-in file */
char *root; /* The root path in which the drop-in was found, i.e. to which 'kernel', 'efi' and 'initrd' are relative */
ssize_t default_entry;
} BootConfig;
+static inline bool boot_config_has_entry(BootConfig *config, const char *id) {
+ size_t j;
+
+ for (j = 0; j < config->n_entries; j++)
+ if (streq(config->entries[j].id, id))
+ return true;
+
+ return false;
+}
+
void boot_config_free(BootConfig *config);
int boot_entries_load_config(const char *esp_path, const char *xbootldr_path, BootConfig *config);
+int boot_entries_augment_from_loader(BootConfig *config, bool only_auto);
static inline const char* boot_entry_title(const BootEntry *entry) {
return entry->show_title ?: entry->title ?: entry->id;
int find_xbootldr_and_warn(const char *path, bool unprivileged_mode, char **ret_path,sd_id128_t *ret_uuid);
int find_default_boot_entry(BootConfig *config, const BootEntry **e);
+
+const char* boot_entry_type_to_string(BootEntryType t) _const_;
+BootEntryType boot_entry_type_from_string(const char *s) _pure_;