@@ -78,6 +78,17 @@ struct eficonfig_file_entry_data {
u16 *file_name;
};
+/**
+ * struct eficonfig_boot_selection_data - structure to be used to select the boot option entry
+ *
+ * @bootorder_index: index in the BootOrder variable
+ * @selected: pointer to store the selected index in the BootOrder variable
+ */
+struct eficonfig_boot_selection_data {
+ u16 bootorder_index;
+ int *selected;
+};
+
/**
* eficonfig_print_msg() - print message
*
@@ -1246,6 +1257,196 @@ out:
return ret;
}
+/**
+ * eficonfig_process_boot_selected() - handler to select boot option entry
+ *
+ * @data: pointer to the data for each entry
+ * Return: status code
+ */
+static efi_status_t eficonfig_process_boot_selected(void *data)
+{
+ struct eficonfig_boot_selection_data *info = data;
+
+ if (info)
+ *info->selected = info->bootorder_index;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ * eficonfig_show_boot_selection() - construct boot option menu entry
+ *
+ * @bootorder: pointer to the BootOrder variable
+ * @count: the number of BootOrder
+ * @selected: pointer to store the selected index of BootOrder variable
+ * Return: status code
+ */
+static efi_status_t eficonfig_show_boot_selection(u16 *bootorder, efi_uintn_t count,
+ int *selected)
+{
+ u32 i;
+ efi_status_t ret;
+ efi_uintn_t size, actual_count = 1; /* include "Quit" entry */
+ void *load_option;
+ struct efi_load_option lo;
+ u16 varname[] = u"Boot####";
+ struct eficonfig_item *menu_item, *iter;
+
+ menu_item = calloc(count + 1, sizeof(struct eficonfig_item));
+ if (!menu_item) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
+ iter = menu_item;
+ for (i = 0; i < count; i++) {
+ efi_create_indexed_name(varname, sizeof(varname),
+ "Boot", bootorder[i]);
+ load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
+ if (!load_option)
+ continue;
+
+ ret = efi_deserialize_load_option(&lo, load_option, &size);
+ if (ret != EFI_SUCCESS) {
+ log_warning("Invalid load option for %ls\n", varname);
+ free(load_option);
+ continue;
+ }
+
+ if (size >= sizeof(efi_guid_t) &&
+ !guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated)) {
+ /*
+ * auto generated entry has GUID in optional_data,
+ * skip auto generated entry because it will be generated
+ * again even if it is edited or deleted.
+ */
+ free(load_option);
+ continue;
+ }
+
+ if (lo.attributes & LOAD_OPTION_ACTIVE) {
+ char *buf, *p;
+ struct eficonfig_boot_selection_data *info;
+
+ info = calloc(1, sizeof(struct eficonfig_boot_selection_data));
+ if (!info) {
+ free(load_option);
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
+ buf = calloc(1, utf16_utf8_strlen(lo.label) + 1);
+ if (!buf) {
+ free(load_option);
+ free(info);
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+ p = buf;
+ utf16_utf8_strcpy(&p, lo.label);
+ info->bootorder_index = i;
+ info->selected = selected;
+ iter->title = buf;
+ iter->func = eficonfig_process_boot_selected;
+ iter->data = info;
+ iter++;
+ actual_count++;
+ }
+ free(load_option);
+ }
+
+ /* add "Quit" entry */
+ iter->title = strdup("Quit");
+ iter->func = eficonfig_process_quit;
+ iter->data = NULL;
+
+ ret = eficonfig_process_common(menu_item, actual_count, " ** Select Boot Option **");
+
+out:
+ iter = menu_item;
+ for (i = 0; i < actual_count; i++, iter++) {
+ free(iter->title);
+ free(iter->data);
+ }
+
+ free(menu_item);
+
+ return ret;
+}
+
+/**
+ * eficonfig_process_edit_boot_option() - handler to edit boot option
+ *
+ * @data: pointer to the data for each entry
+ * Return: status code
+ */
+static efi_status_t eficonfig_process_edit_boot_option(void *data)
+{
+ u16 *bootorder;
+ efi_status_t ret;
+ efi_uintn_t num, size;
+ struct eficonfig_boot_option *bo = NULL;
+
+ bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size);
+ if (!bootorder) {
+ eficonfig_print_msg("BootOrder is not defined!");
+ ret = EFI_NOT_FOUND;
+ return ret;
+ }
+
+ num = size / sizeof(u16);
+ while (1) {
+ int selected;
+ void *load_option;
+ struct efi_load_option lo;
+ u16 varname[] = u"Boot####";
+
+ ret = eficonfig_show_boot_selection(bootorder, num, &selected);
+ if (ret != EFI_SUCCESS)
+ break;
+
+ bo = calloc(1, sizeof(struct eficonfig_boot_option));
+ if (!bo) {
+ ret = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
+ bo->boot_index = selected;
+ efi_create_indexed_name(varname, sizeof(varname),
+ "Boot", bootorder[selected]);
+ load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
+ if (!load_option) {
+ free(bo);
+ ret = EFI_NOT_FOUND;
+ goto out;
+ }
+
+ ret = efi_deserialize_load_option(&lo, load_option, &size);
+ if (ret != EFI_SUCCESS) {
+ free(bo);
+ free(load_option);
+ goto out;
+ }
+
+ ret = eficonfig_edit_boot_option(varname, bo, lo.label, lo.optional_data,
+ size, lo.file_path,
+ " ** Edit Boot Option ** ");
+
+ free(load_option);
+ free(bo);
+ if (ret != EFI_SUCCESS && ret != EFI_ABORTED)
+ break;
+ }
+
+out:
+ free(bootorder);
+
+ /* to stay the parent menu */
+ ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
+
+ return ret;
+}
+
/**
* eficonfig_init() - do required initialization for eficonfig command
*
@@ -1275,6 +1476,7 @@ static efi_status_t eficonfig_init(void)
static const struct eficonfig_item maintenance_menu_items[] = {
{"Add Boot Option", eficonfig_process_add_boot_option},
+ {"Edit Boot Option", eficonfig_process_edit_boot_option},
{"Quit", eficonfig_process_quit},
};
This commit adds the menu entry to edit the existing BOOT#### variable contents. User selects the item from the boot option list, then user can edit the description, file path and optional_data. Note that automatically generated boot option entry by bootmenu to support the removable media device is filtered out and user can not edit the automatically generated entry. Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org> --- Changes in v9: - add function comment Changes in v8: - fix menu header string - fix function and structure prefix to "eficonfig" Newly created in v7 cmd/eficonfig.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+)