From 140a8959d48f8ac3734d53b4c8b6b9b5596bc698 Mon Sep 17 00:00:00 2001 From: Masahisa Kojima Date: Fri, 2 Dec 2022 13:59:36 +0900 Subject: [PATCH] eficonfig: use efi_get_next_variable_name_int() eficonfig command reads all possible UEFI load options from 0x0000 to 0xFFFF to construct the menu. This takes too much time in some environment. This commit uses efi_get_next_variable_name_int() to read all existing UEFI load options to significantlly reduce the count of efi_get_var() call. Signed-off-by: Masahisa Kojima --- cmd/eficonfig.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 117 insertions(+), 24 deletions(-) diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c index 88d507d..394ae67 100644 --- a/cmd/eficonfig.c +++ b/cmd/eficonfig.c @@ -1683,7 +1683,8 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected) u32 i; u16 *bootorder; efi_status_t ret; - efi_uintn_t num, size; + u16 *var_name16 = NULL, *p; + efi_uintn_t num, size, buf_size; struct efimenu *efi_menu; struct list_head *pos, *n; struct eficonfig_entry *entry; @@ -1707,14 +1708,43 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected) } /* list the remaining load option not included in the BootOrder */ - for (i = 0; i <= 0xFFFF; i++) { - /* If the index is included in the BootOrder, skip it */ - if (search_bootorder(bootorder, num, i, NULL)) - continue; + buf_size = 128; + var_name16 = malloc(buf_size); + if (!var_name16) + return EFI_OUT_OF_RESOURCES; - ret = eficonfig_add_boot_selection_entry(efi_menu, i, selected); - if (ret != EFI_SUCCESS) - goto out; + var_name16[0] = 0; + for (;;) { + int index; + efi_guid_t guid; + + size = buf_size; + ret = efi_get_next_variable_name_int(&size, var_name16, &guid); + if (ret == EFI_NOT_FOUND) + break; + if (ret == EFI_BUFFER_TOO_SMALL) { + buf_size = size; + p = realloc(var_name16, buf_size); + if (!p) { + free(var_name16); + return EFI_OUT_OF_RESOURCES; + } + var_name16 = p; + ret = efi_get_next_variable_name_int(&size, var_name16, &guid); + } + if (ret != EFI_SUCCESS) { + free(var_name16); + return ret; + } + if (efi_varname_is_load_option(var_name16, &index)) { + /* If the index is included in the BootOrder, skip it */ + if (search_bootorder(bootorder, num, index, NULL)) + continue; + + ret = eficonfig_add_boot_selection_entry(efi_menu, index, selected); + if (ret != EFI_SUCCESS) + goto out; + } if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 1) break; @@ -1732,6 +1762,8 @@ out: } eficonfig_destroy(efi_menu); + free(var_name16); + return ret; } @@ -1994,6 +2026,8 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi u32 i; char *title; efi_status_t ret; + u16 *var_name16 = NULL, *p; + efi_uintn_t size, buf_size; /* list the load option in the order of BootOrder variable */ for (i = 0; i < num; i++) { @@ -2006,17 +2040,45 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi } /* list the remaining load option not included in the BootOrder */ - for (i = 0; i < 0xFFFF; i++) { + buf_size = 128; + var_name16 = malloc(buf_size); + if (!var_name16) + return EFI_OUT_OF_RESOURCES; + + var_name16[0] = 0; + for (;;) { + int index; + efi_guid_t guid; + if (efi_menu->count >= EFICONFIG_ENTRY_NUM_MAX - 2) break; - /* If the index is included in the BootOrder, skip it */ - if (search_bootorder(bootorder, num, i, NULL)) - continue; - - ret = eficonfig_add_change_boot_order_entry(efi_menu, i, false); + size = buf_size; + ret = efi_get_next_variable_name_int(&size, var_name16, &guid); + if (ret == EFI_NOT_FOUND) + break; + if (ret == EFI_BUFFER_TOO_SMALL) { + buf_size = size; + p = realloc(var_name16, buf_size); + if (!p) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + var_name16 = p; + ret = efi_get_next_variable_name_int(&size, var_name16, &guid); + } if (ret != EFI_SUCCESS) goto out; + + if (efi_varname_is_load_option(var_name16, &index)) { + /* If the index is included in the BootOrder, skip it */ + if (search_bootorder(bootorder, num, index, NULL)) + continue; + + ret = eficonfig_add_change_boot_order_entry(efi_menu, index, false); + if (ret != EFI_SUCCESS) + goto out; + } } /* add "Save" and "Quit" entries */ @@ -2035,9 +2097,9 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi goto out; efi_menu->active = 0; - - return EFI_SUCCESS; out: + free(var_name16); + return ret; } @@ -2270,17 +2332,48 @@ out: efi_status_t eficonfig_delete_invalid_boot_option(struct eficonfig_media_boot_option *opt, efi_status_t count) { - u32 i, j; + u32 i; efi_uintn_t size; void *load_option; struct efi_load_option lo; + u16 *var_name16 = NULL, *p; u16 varname[] = u"Boot####"; efi_status_t ret = EFI_SUCCESS; + efi_uintn_t varname_size, buf_size; - for (i = 0; i <= 0xFFFF; i++) { + buf_size = 128; + var_name16 = malloc(buf_size); + if (!var_name16) + return EFI_OUT_OF_RESOURCES; + + var_name16[0] = 0; + for (;;) { + int index; + efi_guid_t guid; efi_uintn_t tmp; - efi_create_indexed_name(varname, sizeof(varname), "Boot", i); + varname_size = buf_size; + ret = efi_get_next_variable_name_int(&varname_size, var_name16, &guid); + if (ret == EFI_NOT_FOUND) + break; + if (ret == EFI_BUFFER_TOO_SMALL) { + buf_size = varname_size; + p = realloc(var_name16, buf_size); + if (!p) { + free(var_name16); + return EFI_OUT_OF_RESOURCES; + } + var_name16 = p; + ret = efi_get_next_variable_name_int(&varname_size, var_name16, &guid); + } + if (ret != EFI_SUCCESS) { + free(var_name16); + return ret; + } + if (!efi_varname_is_load_option(var_name16, &index)) + continue; + + efi_create_indexed_name(varname, sizeof(varname), "Boot", index); load_option = efi_get_var(varname, &efi_global_variable_guid, &size); if (!load_option) continue; @@ -2292,15 +2385,15 @@ efi_status_t eficonfig_delete_invalid_boot_option(struct eficonfig_media_boot_op if (size >= sizeof(efi_guid_bootmenu_auto_generated)) { if (guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated) == 0) { - for (j = 0; j < count; j++) { - if (opt[j].size == tmp && - memcmp(opt[j].lo, load_option, tmp) == 0) { - opt[j].exist = true; + for (i = 0; i < count; i++) { + if (opt[i].size == tmp && + memcmp(opt[i].lo, load_option, tmp) == 0) { + opt[i].exist = true; break; } } - if (j == count) { + if (i == count) { ret = delete_boot_option(i); if (ret != EFI_SUCCESS) { free(load_option); -- 2.7.4