@@ -1190,6 +1190,175 @@ out:
return ret;
}
+static efi_status_t efimenu_process_boot_selected(void *data)
+{
+ struct efimenu_boot_selection_data *info = data;
+
+ if (info)
+ *info->selected = info->bootorder_index;
+
+ return EFI_SUCCESS;
+}
+
+static efi_status_t efimenu_show_boot_selection(u16 *bootorder, efi_uintn_t count,
+ int *selected)
+{
+ u32 i;
+ efi_status_t ret;
+ efi_uintn_t size, actual_count = 0;
+ void *load_option;
+ struct efi_load_option lo;
+ u16 varname[] = u"Boot####";
+ struct efimenu_item *menu_item, *iter;
+
+ menu_item = calloc(count + 1, sizeof(struct efimenu_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 efimenu_boot_selection_data *info;
+
+ info = calloc(1, sizeof(struct efimenu_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 = efimenu_process_boot_selected;
+ iter->data = info;
+ iter++;
+ actual_count++;
+ }
+ free(load_option);
+ }
+
+ /* add "Quit" entry */
+ iter->title = strdup("Quit");
+ iter->func = efimenu_process_quit;
+ iter->data = NULL;
+ actual_count += 1;
+
+ ret = efimenu_process_common(menu_item, actual_count, " ** Select Boot Order **");
+
+out:
+ iter = menu_item;
+ for (i = 0; i < actual_count; i++, iter++) {
+ free(iter->title);
+ free(iter->data);
+ }
+
+ free(menu_item);
+
+ return ret;
+}
+
+static efi_status_t efimenu_process_edit_boot_option(void *data)
+{
+ u16 *bootorder;
+ efi_status_t ret;
+ efi_uintn_t num, size;
+ struct efimenu_boot_option *bo = NULL;
+
+ bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size);
+ if (!bootorder) {
+ 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 = efimenu_show_boot_selection(bootorder, num, &selected);
+ if (ret != EFI_SUCCESS)
+ break;
+
+ bo = calloc(1, sizeof(struct efimenu_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 = efimenu_edit_boot_option(varname, bo, lo.label, lo.optional_data,
+ size, lo.file_path);
+
+ 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;
+}
+
static efi_status_t efimenu_init(void)
{
efi_status_t ret;
@@ -1223,6 +1392,7 @@ static efi_status_t efimenu_init(void)
static const struct efimenu_item maintenance_menu_items[] = {
{"Add Boot Option", efimenu_process_add_boot_option},
+ {"Edit Boot Option", efimenu_process_edit_boot_option},
{"Quit", efimenu_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 suppport 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> --- Newly created in v7 cmd/efimenu.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+)