]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
bootstd: Support bootflows with global bootmeths
authorSimon Glass <sjg@chromium.org>
Sat, 30 Jul 2022 21:52:25 +0000 (15:52 -0600)
committerTom Rini <trini@konsulko.com>
Fri, 12 Aug 2022 12:17:11 +0000 (08:17 -0400)
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@chromium.org>
boot/bootflow.c
cmd/bootflow.c
include/bootflow.h

index 37bccb823a1405c9f9e21f4431a0d98ed6fb3a04..08ea03363244e408b9cb5c9eee4f6a4181912267 100644 (file)
@@ -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) {
index 47899245ee804a082dc90d51ccd2ca0ca241fb7b..313103d277545f8454d435feec555d6721ef4205 100644 (file)
@@ -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"
index 4fa482a6784aaa96c974ebe0677479798918ade3..6aa3d1fff8d30c6a55af97234a0d209309c1d364 100644 (file)
@@ -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;
 };
 
 /**