[PATCH v2 23/35] bootstd: Support bootflows with global bootmeths

Simon Glass sjg at chromium.org
Sat Jul 30 23:52:25 CEST 2022


Add support for handling this concept in bootflows. Update the 'bootflow'
command to allow only the normal bootmeths to be used. This alllows
skipping EFI bootmgr and VBE, for example.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

(no changes since v1)

 boot/bootflow.c    | 58 +++++++++++++++++++++++++++++++++++++++-------
 cmd/bootflow.c     |  8 +++++--
 include/bootflow.h | 16 ++++++++++---
 3 files changed, 69 insertions(+), 13 deletions(-)

diff --git a/boot/bootflow.c b/boot/bootflow.c
index 37bccb823a1..08ea0336324 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -86,6 +86,7 @@ int bootflow_next_glob(struct bootflow **bflowp)
 void bootflow_iter_init(struct bootflow_iter *iter, int flags)
 {
 	memset(iter, '\0', sizeof(*iter));
+	iter->first_glob_method = -1;
 	iter->flags = flags;
 }
 
@@ -115,11 +116,17 @@ int bootflow_iter_drop_bootmeth(struct bootflow_iter *iter,
 static void bootflow_iter_set_dev(struct bootflow_iter *iter,
 				  struct udevice *dev)
 {
+	struct bootmeth_uc_plat *ucp = dev_get_uclass_plat(iter->method);
+
 	iter->dev = dev;
 	if ((iter->flags & (BOOTFLOWF_SHOW | BOOTFLOWF_SINGLE_DEV)) ==
 	    BOOTFLOWF_SHOW) {
 		if (dev)
 			printf("Scanning bootdev '%s':\n", dev->name);
+		else if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) &&
+			 ucp->flags & BOOTMETHF_GLOBAL)
+			printf("Scanning global bootmeth '%s':\n",
+			       iter->method->name);
 		else
 			printf("No more bootdevs\n");
 	}
@@ -133,8 +140,12 @@ static void bootflow_iter_set_dev(struct bootflow_iter *iter,
 static int iter_incr(struct bootflow_iter *iter)
 {
 	struct udevice *dev;
+	bool inc_dev = true;
+	bool global;
 	int ret;
 
+	global = iter->doing_global;
+
 	if (iter->err == BF_NO_MORE_DEVICES)
 		return BF_NO_MORE_DEVICES;
 
@@ -144,6 +155,21 @@ static int iter_incr(struct bootflow_iter *iter)
 			iter->method = iter->method_order[iter->cur_method];
 			return 0;
 		}
+
+		/*
+		 * If we have finished scanning the global bootmeths, start the
+		 * normal bootdev scan
+		 */
+		if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && global) {
+			iter->num_methods = iter->first_glob_method;
+			iter->doing_global = false;
+
+			/*
+			 * Don't move to the next dev as we haven't tried this
+			 * one yet!
+			 */
+			inc_dev = false;
+		}
 	}
 
 	/* No more bootmeths; start at the first one, and... */
@@ -169,14 +195,18 @@ static int iter_incr(struct bootflow_iter *iter)
 	/* ...select next bootdev */
 	if (iter->flags & BOOTFLOWF_SINGLE_DEV) {
 		ret = -ENOENT;
-	} else if (++iter->cur_dev == iter->num_devs) {
-		ret = -ENOENT;
-		bootflow_iter_set_dev(iter, NULL);
 	} else {
-		dev = iter->dev_order[iter->cur_dev];
-		ret = device_probe(dev);
-		if (!log_msg_ret("probe", ret))
-			bootflow_iter_set_dev(iter, dev);
+		if (inc_dev)
+			iter->cur_dev++;
+		if (iter->cur_dev == iter->num_devs) {
+			ret = -ENOENT;
+			bootflow_iter_set_dev(iter, NULL);
+		} else {
+			dev = iter->dev_order[iter->cur_dev];
+			ret = device_probe(dev);
+			if (!log_msg_ret("probe", ret))
+				bootflow_iter_set_dev(iter, dev);
+		}
 	}
 
 	/* if there are no more bootdevs, give up */
@@ -199,6 +229,15 @@ static int bootflow_check(struct bootflow_iter *iter, struct bootflow *bflow)
 	struct udevice *dev;
 	int ret;
 
+	if (IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) && iter->doing_global) {
+		bootflow_iter_set_dev(iter, NULL);
+		ret = bootmeth_get_bootflow(iter->method, bflow);
+		if (ret)
+			return log_msg_ret("glob", ret);
+
+		return 0;
+	}
+
 	dev = iter->dev;
 	ret = bootdev_get_bootflow(dev, iter, bflow);
 
@@ -231,12 +270,13 @@ int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter,
 {
 	int ret;
 
+	if (dev)
+		flags |= BOOTFLOWF_SKIP_GLOBAL;
 	bootflow_iter_init(iter, flags);
 
 	ret = bootdev_setup_iter_order(iter, &dev);
 	if (ret)
 		return log_msg_ret("obdev", -ENODEV);
-	bootflow_iter_set_dev(iter, dev);
 
 	ret = bootmeth_setup_iter_order(iter);
 	if (ret)
@@ -244,6 +284,8 @@ int bootflow_scan_bootdev(struct udevice *dev, struct bootflow_iter *iter,
 
 	/* Find the first bootmeth (there must be at least one!) */
 	iter->method = iter->method_order[iter->cur_method];
+	if (!IS_ENABLED(CONFIG_BOOTMETH_GLOBAL) || !iter->doing_global)
+		bootflow_iter_set_dev(iter, dev);
 
 	ret = bootflow_check(iter, bflow);
 	if (ret) {
diff --git a/cmd/bootflow.c b/cmd/bootflow.c
index 47899245ee8..313103d2775 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -95,7 +95,8 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
 	struct bootflow_iter iter;
 	struct udevice *dev;
 	struct bootflow bflow;
-	bool all = false, boot = false, errors = false, list = false;
+	bool all = false, boot = false, errors = false, no_global = false;
+	bool list = false;
 	int num_valid = 0;
 	bool has_args;
 	int ret, i;
@@ -112,6 +113,7 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
 			all = strchr(argv[1], 'a');
 			boot = strchr(argv[1], 'b');
 			errors = strchr(argv[1], 'e');
+			no_global = strchr(argv[1], 'G');
 			list = strchr(argv[1], 'l');
 			argc--;
 			argv++;
@@ -137,6 +139,8 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
 		flags |= BOOTFLOWF_SHOW;
 	if (all)
 		flags |= BOOTFLOWF_ALL;
+	if (no_global)
+		flags |= BOOTFLOWF_SKIP_GLOBAL;
 
 	/*
 	 * If we have a device, just scan for bootflows attached to that device
@@ -383,7 +387,7 @@ static int do_bootflow_boot(struct cmd_tbl *cmdtp, int flag, int argc,
 #ifdef CONFIG_SYS_LONGHELP
 static char bootflow_help_text[] =
 #ifdef CONFIG_CMD_BOOTFLOW_FULL
-	"scan [-abel] [bdev]   - scan for valid bootflows (-l list, -a all, -e errors, -b boot)\n"
+	"scan [-abeGl] [bdev]  - scan for valid bootflows (-l list, -a all, -e errors, -b boot, -G no global)\n"
 	"bootflow list [-e]             - list scanned bootflows (-e errors)\n"
 	"bootflow select [<num>|<name>] - select a bootflow\n"
 	"bootflow info [-d]             - show info on current bootflow (-d dump bootflow)\n"
diff --git a/include/bootflow.h b/include/bootflow.h
index 4fa482a6784..6aa3d1fff8d 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -77,12 +77,14 @@ struct bootflow {
  * @BOOTFLOWF_SHOW: Show each bootdev before scanning it
  * @BOOTFLOWF_ALL: Return bootflows with errors as well
  * @BOOTFLOWF_SINGLE_DEV: Just scan one bootmeth
+ * @BOOTFLOWF_SKIP_GLOBAL: Don't scan global bootmeths
  */
 enum bootflow_flags_t {
 	BOOTFLOWF_FIXED		= 1 << 0,
 	BOOTFLOWF_SHOW		= 1 << 1,
 	BOOTFLOWF_ALL		= 1 << 2,
 	BOOTFLOWF_SINGLE_DEV	= 1 << 3,
+	BOOTFLOWF_SKIP_GLOBAL	= 1 << 4,
 };
 
 /**
@@ -102,8 +104,10 @@ enum bootflow_flags_t {
  * updated to a larger value, no less than the number of available partitions.
  * This ensures that iteration works through all partitions on the bootdev.
  *
- * @flags: Flags to use (see enum bootflow_flags_t)
- * @dev: Current bootdev
+ * @flags: Flags to use (see enum bootflow_flags_t). If BOOTFLOWF_GLOBAL_FIRST is
+ *	enabled then the global bootmeths are being scanned, otherwise we have
+ *	moved onto the bootdevs
+ * @dev: Current bootdev, NULL if none
  * @part: Current partition number (0 for whole device)
  * @method: Current bootmeth
  * @max_part: Maximum hardware partition number in @dev, 0 if there is no
@@ -117,7 +121,11 @@ enum bootflow_flags_t {
  *	with the first one on the list
  * @num_methods: Number of bootmeth devices in @method_order
  * @cur_method: Current method number, an index into @method_order
- * @method_order: List of bootmeth devices to use, in order
+ * @first_glob_method: First global method, if any, else -1
+ * @method_order: List of bootmeth devices to use, in order. The normal methods
+ *	appear first, then the global ones, if any
+ * @doing_global: true if we are iterating through the global bootmeths (which
+ *	happens before the normal ones)
  */
 struct bootflow_iter {
 	int flags;
@@ -131,7 +139,9 @@ struct bootflow_iter {
 	struct udevice **dev_order;
 	int num_methods;
 	int cur_method;
+	int first_glob_method;
 	struct udevice **method_order;
+	bool doing_global;
 };
 
 /**
-- 
2.37.1.455.g008518b4e5-goog



More information about the U-Boot mailing list