All of lore.kernel.org
 help / color / mirror / Atom feed
From: Masahisa Kojima <masahisa.kojima@linaro.org>
To: u-boot@lists.denx.de
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>,
	Ilias Apalodimas <ilias.apalodimas@linaro.org>,
	Simon Glass <sjg@chromium.org>,
	Takahiro Akashi <takahiro.akashi@linaro.org>,
	Francois Ozog <francois.ozog@linaro.org>,
	Mark Kettenis <mark.kettenis@xs4all.nl>,
	Masahisa Kojima <masahisa.kojima@linaro.org>
Subject: [PATCH v8 5/9] eficonfig: add "Change Boot Order" menu entry
Date: Sun, 19 Jun 2022 13:56:03 +0900	[thread overview]
Message-ID: <20220619045607.1669-6-masahisa.kojima@linaro.org> (raw)
In-Reply-To: <20220619045607.1669-1-masahisa.kojima@linaro.org>

This commit adds the menu entry to update UEFI BootOrder variable.
User moves the entry with UP/DOWN key, changes the order
with PLUS/MINUS key, then finalizes the order by ENTER key.

The U-Boot menu framework is well designed for static menu,
this commit implements the own menu display and key handling
for dynamically change the order of menu entry.

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
---
Changes in v8:
- add "Save" and "Quit" entries

Changes in v7:
- use UP/DOWN and PLUS/MINUS key to change to order

no update in v6:

 cmd/eficonfig.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 237 insertions(+)

diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
index 0a58b83ea3..c4a18e6a2a 100644
--- a/cmd/eficonfig.c
+++ b/cmd/eficonfig.c
@@ -70,6 +70,13 @@ struct eficonfig_file_entry_data {
 	u16 *file_name;
 };
 
+struct eficonfig_boot_order {
+	u32 num;
+	u16 *description;
+	u32 prev_index;
+	struct list_head list;
+};
+
 /**
  * eficonfig_print_msg() - print message
  *
@@ -1368,6 +1375,235 @@ out:
 	return ret;
 }
 
+static void eficonfig_display_change_boot_order(struct list_head *bo_list,
+						struct efimenu *efi_menu)
+{
+	bool reverse;
+	struct list_head *pos, *n;
+	struct eficonfig_boot_order *entry;
+
+	printf(ANSI_CLEAR_CONSOLE
+	       ANSI_CURSOR_POSITION
+	      "\n  ** Change Boot Order **\n"
+	       ANSI_CURSOR_POSITION
+	       "\n"
+	       "  Press UP/DOWN to move, +/- to change order\n  ENTER to complete, ESC/CTRL+C to quit"
+	       ANSI_CURSOR_POSITION,
+	       0, 1, efi_menu->count + 5, 1, 4, 1);
+
+	/* draw boot order list */
+	list_for_each_safe(pos, n, bo_list) {
+		entry = list_entry(pos, struct eficonfig_boot_order, list);
+		reverse = (entry->num == efi_menu->active);
+		puts("     ");
+		if (reverse)
+			puts(ANSI_COLOR_REVERSE);
+
+		printf("%ls\n", entry->description);
+
+		if (reverse)
+			puts(ANSI_COLOR_RESET);
+	}
+}
+
+static efi_status_t eficonfig_choice_change_boot_order(struct list_head *bo_list,
+						       struct efimenu *efi_menu)
+{
+	int esc = 0;
+	struct list_head *pos, *n;
+	struct eficonfig_boot_order *tmp;
+	enum bootmenu_key key = KEY_NONE;
+	struct eficonfig_boot_order *entry;
+
+	while (1) {
+		bootmenu_loop(NULL, &key, &esc);
+
+		switch (key) {
+		case KEY_PLUS:
+			if (efi_menu->active > 0) {
+				list_for_each_safe(pos, n, bo_list) {
+					entry = list_entry(pos, struct eficonfig_boot_order, list);
+					if (entry->num == efi_menu->active)
+						break;
+				}
+				tmp = list_entry(pos->prev, struct eficonfig_boot_order, list);
+				entry->num--;
+				tmp->num++;
+				list_del(&tmp->list);
+				list_add(&tmp->list, &entry->list);
+			}
+			fallthrough;
+		case KEY_UP:
+			if (efi_menu->active > 0)
+				--efi_menu->active;
+			return EFI_NOT_READY;
+		case KEY_MINUS:
+			if (efi_menu->active < efi_menu->count - 3) {
+				list_for_each_safe(pos, n, bo_list) {
+					entry = list_entry(pos, struct eficonfig_boot_order, list);
+					if (entry->num == efi_menu->active)
+						break;
+				}
+				tmp = list_entry(pos->next, struct eficonfig_boot_order, list);
+				entry->num++;
+				tmp->num--;
+				list_del(&entry->list);
+				list_add(&entry->list, &tmp->list);
+
+				++efi_menu->active;
+			}
+			return EFI_NOT_READY;
+		case KEY_DOWN:
+			if (efi_menu->active < efi_menu->count - 1)
+				++efi_menu->active;
+			return EFI_NOT_READY;
+		case KEY_SELECT:
+			/* "Save" */
+			if (efi_menu->active == efi_menu->count - 2)
+				return EFI_SUCCESS;
+
+			/* "Quit" */
+			if (efi_menu->active == efi_menu->count - 1)
+				return EFI_ABORTED;
+
+			break;
+		case KEY_QUIT:
+			return EFI_ABORTED;
+		default:
+			break;
+		}
+	}
+}
+
+static efi_status_t eficonfig_process_change_boot_order(void *data)
+{
+	u32 i;
+	u16 *bootorder;
+	efi_status_t ret;
+	efi_uintn_t num, size;
+	struct list_head bo_list;
+	struct list_head *pos, *n;
+	struct eficonfig_boot_order *entry;
+	struct efimenu efi_menu;
+
+	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;
+	}
+
+	INIT_LIST_HEAD(&bo_list);
+
+	num = size / sizeof(u16);
+	for (i = 0; i < num; i++) {
+		void *load_option;
+		struct efi_load_option lo;
+		u16 varname[] = u"Boot####";
+
+		efi_create_indexed_name(varname, sizeof(varname),
+					"Boot", bootorder[i]);
+		load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
+		if (!load_option) {
+			ret = EFI_NOT_FOUND;
+			goto out;
+		}
+
+		ret = efi_deserialize_load_option(&lo, load_option, &size);
+		if (ret != EFI_SUCCESS) {
+			free(load_option);
+			goto out;
+		}
+
+		entry = calloc(1, sizeof(struct eficonfig_boot_order));
+		if (!entry) {
+			free(load_option);
+			goto out;
+		}
+		entry->num = i;
+		entry->description = u16_strdup(lo.label);
+		entry->prev_index = i;
+		list_add_tail(&entry->list, &bo_list);
+
+		free(load_option);
+	}
+
+	/* add "Save" and "Quit" entries */
+	entry = calloc(1, sizeof(struct eficonfig_boot_order));
+	if (!entry)
+		goto out;
+
+	entry->num = i++;
+	entry->description = u16_strdup(u"Save");
+	entry->prev_index = 0;
+	list_add_tail(&entry->list, &bo_list);
+
+	entry = calloc(1, sizeof(struct eficonfig_boot_order));
+	if (!entry)
+		goto out;
+
+	entry->num = i++;
+	entry->description = u16_strdup(u"Quit");
+	entry->prev_index = 0;
+	list_add_tail(&entry->list, &bo_list);
+
+	efi_menu.delay = -1;
+	efi_menu.active = 0;
+	efi_menu.count = i;
+
+	while (1) {
+		eficonfig_display_change_boot_order(&bo_list, &efi_menu);
+
+		ret = eficonfig_choice_change_boot_order(&bo_list, &efi_menu);
+		if (ret == EFI_SUCCESS) {
+			u32 i = 0;
+			u16 *new_bootorder;
+
+			/* update the BootOrder variable */
+			size = num * sizeof(u16);
+			new_bootorder = calloc(1, size);
+			if (!new_bootorder) {
+				ret = EFI_OUT_OF_RESOURCES;
+				goto out;
+			}
+
+			list_for_each_safe(pos, n, &bo_list) {
+				entry = list_entry(pos, struct eficonfig_boot_order, list);
+				new_bootorder[i] = bootorder[entry->prev_index];
+				i++;
+			}
+
+			ret = efi_set_variable_int(u"BootOrder", &efi_global_variable_guid,
+						   EFI_VARIABLE_NON_VOLATILE |
+						   EFI_VARIABLE_BOOTSERVICE_ACCESS |
+						   EFI_VARIABLE_RUNTIME_ACCESS,
+						   size, new_bootorder, false);
+
+			free(new_bootorder);
+			goto out;
+		} else if (ret == EFI_NOT_READY) {
+			continue;
+		} else {
+			goto out;
+		}
+	}
+
+out:
+	list_for_each_safe(pos, n, &bo_list) {
+		entry = list_entry(pos, struct eficonfig_boot_order, list);
+		list_del(&entry->list);
+		free(entry->description);
+		free(entry);
+	}
+
+	free(bootorder);
+
+	/* to stay the parent menu */
+	ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret;
+
+	return ret;
+}
+
 static efi_status_t eficonfig_init(void)
 {
 	efi_status_t ret;
@@ -1402,6 +1638,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},
+	{"Change Boot Order", eficonfig_process_change_boot_order},
 	{"Quit", eficonfig_process_quit},
 };
 
-- 
2.17.1


  parent reply	other threads:[~2022-06-19  4:56 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-19  4:55 [PATCH v8 0/9] enable menu-driven UEFI variable maintenance Masahisa Kojima
2022-06-19  4:55 ` [PATCH v8 1/9] efi_loader: expose END device path node Masahisa Kojima
2022-07-10  9:10   ` Heinrich Schuchardt
2022-07-11 11:32     ` Ilias Apalodimas
2022-06-19  4:56 ` [PATCH v8 2/9] eficonfig: menu-driven addition of UEFI boot option Masahisa Kojima
2022-07-10  9:03   ` Heinrich Schuchardt
2022-07-12  1:55     ` Takahiro Akashi
2022-07-12  6:25       ` Heinrich Schuchardt
2022-07-12 10:59     ` Masahisa Kojima
2022-07-15 14:02       ` Masahisa Kojima
2022-07-14  2:07     ` Takahiro Akashi
2022-06-19  4:56 ` [PATCH v8 3/9] eficonfig: add "Edit Boot Option" menu entry Masahisa Kojima
2022-07-10  9:08   ` Heinrich Schuchardt
2022-07-12  7:04     ` Masahisa Kojima
2022-06-19  4:56 ` [PATCH v8 4/9] menu: add KEY_PLUS and KEY_MINUS handling Masahisa Kojima
2022-07-10  9:09   ` Heinrich Schuchardt
2022-06-19  4:56 ` Masahisa Kojima [this message]
2022-06-19  4:56 ` [PATCH v8 6/9] eficonfig: add "Delete Boot Option" menu entry Masahisa Kojima
2022-06-19  4:56 ` [PATCH v8 7/9] bootmenu: add removable media entries Masahisa Kojima
2022-06-19  4:56 ` [PATCH v8 8/9] doc:bootmenu: add description for UEFI boot support Masahisa Kojima
2022-06-19  4:56 ` [PATCH v8 9/9] doc:eficonfig: add documentation for eficonfig command Masahisa Kojima
2022-06-20  4:14 ` [PATCH v8 0/9] enable menu-driven UEFI variable maintenance Takahiro Akashi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220619045607.1669-6-masahisa.kojima@linaro.org \
    --to=masahisa.kojima@linaro.org \
    --cc=francois.ozog@linaro.org \
    --cc=ilias.apalodimas@linaro.org \
    --cc=mark.kettenis@xs4all.nl \
    --cc=sjg@chromium.org \
    --cc=takahiro.akashi@linaro.org \
    --cc=u-boot@lists.denx.de \
    --cc=xypron.glpk@gmx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.