diff --git a/usr.sbin/efibootmgr/efibootmgr.c b/usr.sbin/efibootmgr/efibootmgr.c index 0137fd9fb158..ef8b7f80cc6e 100644 --- a/usr.sbin/efibootmgr/efibootmgr.c +++ b/usr.sbin/efibootmgr/efibootmgr.c @@ -67,7 +67,7 @@ __FBSDID("$FreeBSD$"); #endif #define BAD_LENGTH ((size_t)-1) - + typedef struct _bmgr_opts { char *env; char *loader; @@ -130,7 +130,8 @@ struct entry { char *name; char *label; int idx; - int part; + int flags; +#define SEEN 1 LIST_ENTRY(entry) entries; }; @@ -758,6 +759,31 @@ get_descr(uint8_t *data) } +static bool +print_boot_var(const char *name, bool verbose, bool curboot) +{ + size_t size; + uint32_t load_attrs; + uint8_t *data; + int ret; + char *d; + + ret = efi_get_variable(EFI_GLOBAL_GUID, name, &data, &size, NULL); + if (ret < 0) + return false; + load_attrs = le32dec(data); + d = get_descr(data); + printf("%c%s%c %s", curboot ? '+' : ' ', name, + ((load_attrs & LOAD_OPTION_ACTIVE) ? '*': ' '), d); + free(d); + if (verbose) + print_loadopt_str(data, size); + else + printf("\n"); + return true; +} + + /* Cmd epilogue, or just the default with no args. * The order is [bootnext] bootcurrent, timeout, order, and the bootvars [-v] */ @@ -770,10 +796,10 @@ print_boot_vars(bool verbose) */ struct entry *v; uint8_t *data; - char *d; size_t size; - uint32_t attrs, load_attrs; - int ret; + uint32_t attrs; + int ret, bolen; + uint16_t *boot_order = NULL, current; ret = efi_get_variable(EFI_GLOBAL_GUID, "BootNext", &data, &size, &attrs); if (ret > 0) { @@ -781,39 +807,58 @@ print_boot_vars(bool verbose) } ret = efi_get_variable(EFI_GLOBAL_GUID, "BootCurrent", &data, &size,&attrs); - printf("BootCurrent: %04x\n", le16dec(data)); + current = le16dec(data); + printf("BootCurrent: %04x\n", current); ret = efi_get_variable(EFI_GLOBAL_GUID, "Timeout", &data, &size, &attrs); if (ret > 0) { - printf("Timeout : %d seconds\n", le16dec(data)); + printf("Timeout : %d seconds\n", le16dec(data)); } if (efi_get_variable(EFI_GLOBAL_GUID, "BootOrder", &data, &size, &attrs) > 0) { if (size % 2 == 1) warn("Bad BootOrder variable: odd length %d", (int)size); - printf("BootOrder : "); - for (size_t i = 0; i < size; i += 2) - printf("%04x%s", le16dec(data + i), i == size - 2 ? "\n" : ", "); + boot_order = malloc(size); + bolen = size / 2; + printf("BootOrder : "); + for (size_t i = 0; i < size; i += 2) { + boot_order[i / 2] = le16dec(data + i); + printf("%04X%s", boot_order[i / 2], i == size - 2 ? "\n" : ", "); + } } - /* now we want to fetch 'em all fresh again - * which possibly includes a newly created bootvar - */ - LIST_FOREACH(v, &efivars, entries) { - attrs = 0; - ret = efi_get_variable(EFI_GLOBAL_GUID, v->name, &data, - &size, &attrs); - if (ret < 0) - continue; /* we must have deleted it */ - load_attrs = le32dec(data); - d = get_descr(data); - printf("%s%c %s", v->name, - ((load_attrs & LOAD_OPTION_ACTIVE) ? '*': ' '), d); - free(d); - if (verbose) - print_loadopt_str(data, size); - else - printf("\n"); + if (boot_order == NULL) { + /* + * now we want to fetch 'em all fresh again + * which possibly includes a newly created bootvar + */ + LIST_FOREACH(v, &efivars, entries) { + print_boot_var(v->name, verbose, v->idx == current); + } + } else { + LIST_FOREACH(v, &efivars, entries) { + v->flags = 0; + } + for (int i = 0; i < bolen; i++) { + char buffer[10]; + + snprintf(buffer, sizeof(buffer), "Boot%04X", boot_order[i]); + if (!print_boot_var(buffer, verbose, boot_order[i] == current)) + printf("%s: MISSING!\n", buffer); + LIST_FOREACH(v, &efivars, entries) { + if (v->idx == boot_order[i]) { + v->flags |= SEEN; + break; + } + } + } + if (verbose) { + printf("\n\nUnreferenced Variables:\n"); + LIST_FOREACH(v, &efivars, entries) { + if (v->flags == 0) + print_boot_var(v->name, verbose, v->idx == current); + } + } } return 0; }