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 v5 10/17] bootmenu: add distro boot entry
Date: Thu, 28 Apr 2022 17:09:43 +0900	[thread overview]
Message-ID: <20220428080950.23509-11-masahisa.kojima@linaro.org> (raw)
In-Reply-To: <20220428080950.23509-1-masahisa.kojima@linaro.org>

This commit adds the distro_boot entries into the bootmenu.
The bootmenu read the "boot_targets" U-Boot environment variable
and enumerate it.
User can select the distro boot entry, then bootmenu executes
"run bootcmd_xxx" command.

The bootmenu also checks the existing block devices and network
option("dhcp" and "pxe") availability, then filter out
the "boot_targets" appeared in bootmenu.

The bootmenu example is as follows, distro boot entry has the
"distro_boot" prefix.

  *** U-Boot Boot Menu ***

     distro_boot   : usb0
     distro_boot   : scsi0
     distro_boot   : virtio0
     distro_boot   : dhcp

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
---
Changes in v5:
- split into the separate patch
- add function description comment
- handle the case boot_targets variable is empty
- filter out the non-exist device entry

 cmd/bootmenu.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 177 insertions(+)

diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c
index da688e6213..afe42b8041 100644
--- a/cmd/bootmenu.c
+++ b/cmd/bootmenu.c
@@ -7,6 +7,7 @@
 #include <common.h>
 #include <command.h>
 #include <ansi.h>
+#include <dm.h>
 #include <efi_loader.h>
 #include <efi_variable.h>
 #include <env.h>
@@ -14,6 +15,7 @@
 #include <menu.h>
 #include <watchdog.h>
 #include <malloc.h>
+#include <linux/ctype.h>
 #include <linux/delay.h>
 #include <linux/string.h>
 
@@ -31,6 +33,7 @@ enum boot_type {
 	BOOTMENU_TYPE_NONE = 0,
 	BOOTMENU_TYPE_BOOTMENU,
 	BOOTMENU_TYPE_UEFI_BOOT_OPTION,
+	BOOTMENU_TYPE_DISTRO_BOOT,
 };
 
 struct bootmenu_entry {
@@ -90,6 +93,8 @@ static void bootmenu_print_entry(void *data)
 		printf("bootmenu_%02d   : %ls", entry->bootorder, entry->title);
 	else if (entry->type == BOOTMENU_TYPE_UEFI_BOOT_OPTION)
 		printf("UEFI BOOT%04X : %ls", entry->bootorder, entry->title);
+	else if (entry->type == BOOTMENU_TYPE_DISTRO_BOOT)
+		printf("distro_boot   : %ls", entry->title);
 	else
 		printf("%ls", entry->title);
 
@@ -465,6 +470,172 @@ static int prepare_uefi_bootorder_entry(struct bootmenu_data *menu,
 	return 1;
 }
 
+static int is_blk_device_available(char *token)
+{
+	struct driver *d = ll_entry_start(struct driver, driver);
+	const int n_ents = ll_entry_count(struct driver, driver);
+	struct driver *entry;
+	struct udevice *udev;
+	struct uclass *uc;
+	struct blk_desc *desc;
+	int ret, i;
+	const char *if_type_name;
+
+	ret = uclass_get(UCLASS_BLK, &uc);
+	if (ret)
+		return -ENODEV;
+
+	for (entry = d; entry < d + n_ents; entry++) {
+		if (entry->id != UCLASS_BLK)
+			continue;
+		i = 0;
+		uclass_foreach_dev(udev, uc) {
+			if (udev->driver != entry)
+				continue;
+			desc = dev_get_uclass_plat(udev);
+			if_type_name = blk_get_if_type_name(desc->if_type);
+			if (strncmp(token, if_type_name, strlen(if_type_name)) == 0) {
+				char *p;
+				int j, len;
+				int devnum = 0;
+
+				p = token + strlen(if_type_name);
+				len = strlen(p);
+				if (!len)
+					continue; /* no device number */
+
+				for (j = 0; j < len; j++) {
+					if (!isdigit(*p)) {
+						/* invalid device number */
+						devnum = INT_MAX;
+						break;
+					}
+					devnum = (devnum * 10) + (*p++ - '0');
+				}
+
+				if (devnum == INT_MAX)
+					continue;
+
+				if (devnum == desc->devnum)
+					return 1;
+			}
+		}
+	}
+
+	if (strncmp(token, "dhcp", strlen("dhcp")) == 0) {
+		if (IS_ENABLED(CONFIG_CMD_DHCP))
+			return 1;
+	}
+
+	if (strncmp(token, "pxe", strlen("pxe")) == 0) {
+		if (IS_ENABLED(CONFIG_CMD_PXE))
+			return 1;
+	}
+
+	return -ENODEV;
+}
+
+/**
+ * prepare_distro_boot_entry() - generate the distro boot entries
+ *
+ * This function read the "boot_targets" U-Boot environment variable
+ * and generate the bootmenu entries.
+ *
+ * @menu:	pointer to the bootmenu structure
+ * @current:	pointer to the last bootmenu entry list
+ * @index:	pointer to the index of the last bootmenu entry,
+ *		the number of uefi entry is added by this function
+ * Return:	1 on success, negative value on error
+ */
+static int prepare_distro_boot_entry(struct bootmenu_data *menu,
+				     struct bootmenu_entry **current,
+				     unsigned short int *index)
+{
+	char *p;
+	int len;
+	char *token;
+	char *boot_targets;
+	unsigned short int i = *index;
+	struct bootmenu_entry *entry = NULL;
+	struct bootmenu_entry *iter = *current;
+
+	/* list the distro boot "boot_targets" */
+	boot_targets = env_get("boot_targets");
+	if (!boot_targets)
+		return -ENOENT;
+
+	len = strlen(boot_targets);
+	if (!len)
+		return -ENOENT;
+
+	p = calloc(1, len + 1);
+	strlcpy(p, boot_targets, len);
+
+	token = strtok(p, " ");
+
+	do {
+		u16 *buf;
+		char *command;
+		int command_size;
+
+		if (is_blk_device_available(token) != 1) {
+			token = strtok(NULL, " ");
+			continue;
+		}
+
+		entry = malloc(sizeof(struct bootmenu_entry));
+		if (!entry) {
+			free(p);
+			return -ENOMEM;
+		}
+
+		len = strlen(token);
+		buf = calloc(1, (len + 1) * sizeof(u16));
+		entry->title = buf;
+		if (!entry->title) {
+			free(entry);
+			free(p);
+			return -ENOMEM;
+		}
+		utf8_utf16_strncpy(&buf, token, len);
+		sprintf(entry->key, "%d", i);
+		entry->num = i;
+		entry->menu = menu;
+
+		command_size = sizeof("run bootcmd_") + len;
+		command = calloc(1, command_size);
+		if (!command) {
+			free(entry->title);
+			free(entry);
+			free(p);
+			return -ENOMEM;
+		}
+		snprintf(command, command_size, "run bootcmd_%s", token);
+		entry->command = command;
+		entry->type = BOOTMENU_TYPE_DISTRO_BOOT;
+		entry->next = NULL;
+
+		if (!iter)
+			menu->first = entry;
+		else
+			iter->next = entry;
+
+		iter = entry;
+		i++;
+
+		if (i == MAX_COUNT - 1)
+			break;
+
+		token = strtok(NULL, " ");
+	} while (token);
+
+	free(p);
+	*index = i;
+	*current = iter;
+
+	return 1;
+}
+
 static struct bootmenu_data *bootmenu_create(int delay)
 {
 	int ret;
@@ -498,6 +669,12 @@ static struct bootmenu_data *bootmenu_create(int delay)
 		}
 	}
 
+	if (i < MAX_COUNT - 1) {
+		ret = prepare_distro_boot_entry(menu, &iter, &i);
+		if (ret < 0 && ret != -ENOENT)
+			goto cleanup;
+	}
+
 	/* Add U-Boot console entry at the end */
 	if (i <= MAX_COUNT - 1) {
 		entry = malloc(sizeof(struct bootmenu_entry));
-- 
2.17.1


  parent reply	other threads:[~2022-04-28  8:12 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-28  8:09 [PATCH v5 00/17] enable menu-driven boot device selection Masahisa Kojima
2022-04-28  8:09 ` [PATCH v5 01/17] lib/charset: add u16_strlcat() function Masahisa Kojima
2022-04-29 19:36   ` Heinrich Schuchardt
2022-04-28  8:09 ` [PATCH v5 02/17] test: unit test for u16_strlcat() Masahisa Kojima
2022-04-28  8:09 ` [PATCH v5 03/17] menu: always show the menu regardless of the number of entry Masahisa Kojima
2022-05-01 15:37   ` Heinrich Schuchardt
2022-04-28  8:09 ` [PATCH v5 04/17] menu: menu_get_choice() return -ENOENT if menu item is empty Masahisa Kojima
2022-04-29 19:38   ` Heinrich Schuchardt
2022-04-28  8:09 ` [PATCH v5 05/17] efi_loader: export efi_locate_device_handle() Masahisa Kojima
2022-05-01 18:53   ` Heinrich Schuchardt
2022-05-04  9:17     ` Ilias Apalodimas
2022-04-28  8:09 ` [PATCH v5 06/17] efi_loader: bootmgr: add booting from removable media Masahisa Kojima
2022-04-29 17:03   ` Heinrich Schuchardt
2022-05-05 12:05     ` Mark Kettenis
2022-05-05 12:20       ` Heinrich Schuchardt
2022-05-05 12:35         ` Heinrich Schuchardt
2022-05-05 13:25           ` Mark Kettenis
2022-05-05 12:47       ` Mark Kettenis
2022-05-12  9:12         ` AKASHI Takahiro
2022-05-12 10:34           ` Heinrich Schuchardt
2022-04-28  8:09 ` [PATCH v5 07/17] bootmenu: flush input buffer before waiting user key input Masahisa Kojima
2022-04-29 19:46   ` Heinrich Schuchardt
2022-05-09  8:33     ` Masahisa Kojima
2022-04-28  8:09 ` [PATCH v5 08/17] bootmenu: update bootmenu_entry structure Masahisa Kojima
2022-04-29 19:51   ` Heinrich Schuchardt
2022-05-01 20:54     ` Heinrich Schuchardt
2022-05-09  8:54       ` Masahisa Kojima
2022-04-28  8:09 ` [PATCH v5 09/17] bootmenu: add UEFI boot entry into bootmenu Masahisa Kojima
2022-05-01 21:44   ` Heinrich Schuchardt
2022-05-09  8:59     ` Masahisa Kojima
2022-04-28  8:09 ` Masahisa Kojima [this message]
2022-05-01 21:48   ` [PATCH v5 10/17] bootmenu: add distro boot entry Heinrich Schuchardt
2022-05-12  8:44     ` Takahiro Akashi
2022-05-12 10:39       ` Heinrich Schuchardt
2022-05-12 11:42         ` Mark Kettenis
2022-04-28  8:09 ` [PATCH v5 11/17] bootmenu: add Kconfig option not to enter U-Boot console Masahisa Kojima
2022-04-29  8:50   ` Mark Kettenis
2022-04-28  8:09 ` [PATCH v5 12/17] bootmenu: factor out the user input handling Masahisa Kojima
2022-04-28  8:09 ` [PATCH v5 13/17] efi_loader: menu-driven addition of UEFI boot option Masahisa Kojima
2022-04-28 16:33   ` Heinrich Schuchardt
2022-04-29 10:56     ` Heinrich Schuchardt
2022-04-30 12:49       ` Heinrich Schuchardt
2022-05-06 17:30         ` Heinrich Schuchardt
2022-05-06 18:10           ` Mark Kettenis
2022-05-06 18:16             ` Heinrich Schuchardt
2022-05-09  9:27               ` Masahisa Kojima
2022-05-09 12:56                 ` Heinrich Schuchardt
2022-04-28  8:09 ` [PATCH v5 14/17] efi_loader: menu-driven deletion of UEFI boot variable Masahisa Kojima
2022-04-28  8:09 ` [PATCH v5 15/17] efi_loader: menu-driven update of UEFI bootorder variable Masahisa Kojima
2022-04-28  8:09 ` [PATCH v5 16/17] bootmenu: add removable media entries Masahisa Kojima
2022-04-28 16:53   ` Heinrich Schuchardt
2022-05-09  8:23     ` Masahisa Kojima
2022-05-09 13:01       ` Heinrich Schuchardt
2022-05-16  9:20         ` Masahisa Kojima
2022-04-28  8:09 ` [PATCH v5 17/17] doc:bootmenu: add UEFI boot and distro boot support description Masahisa Kojima
2022-04-28 16:31 ` [PATCH v5 00/17] enable menu-driven boot device selection Heinrich Schuchardt
2022-04-28 16:58   ` Heinrich Schuchardt
2022-04-29  8:45 ` Mark Kettenis

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=20220428080950.23509-11-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.