]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
bootstd: Treat DHCP and PXE as bootdev labels
authorSimon Glass <sjg@chromium.org>
Tue, 17 Jan 2023 17:48:05 +0000 (10:48 -0700)
committerTom Rini <trini@konsulko.com>
Mon, 23 Jan 2023 23:11:41 +0000 (18:11 -0500)
These are associated with the ethernet boot device but do not match its
uclass name, so handle them as special cases.

Provide a way to pass flags through with the bootdev so that we know
how to process it. The flags are checked by the bootmeths, to ensure that
only the selected bootmeth is used.

While these both use the network device, they work quite differently. It
is common to run only one of these, or to run PXE before DHCP. Provide
bootflow flags to control which methods are used. Check these in the two
bootmeths so that only the chosen one is used.

Signed-off-by: Simon Glass <sjg@chromium.org>
boot/bootdev-uclass.c
boot/bootmeth_efi.c
boot/bootmeth_pxe.c
boot/bootmeth_script.c
boot/vbe_simple_fw.c
cmd/bootdev.c
cmd/bootflow.c
include/bootdev.h
include/bootflow.h
test/boot/bootdev.c

index dd9ec668e16079fbeed32e2ec36067610e9b58d2..7ac42afd7b3cb450ddb005088951c6e5406cb111 100644 (file)
@@ -359,14 +359,17 @@ int bootdev_unbind_dev(struct udevice *parent)
  *
  * @label: Label to look up (e.g. "mmc1" or "mmc0")
  * @seqp: Returns the sequence number, or -1 if none
+ * @method_flagsp: If non-NULL, returns any flags implied by the label
+ * (enum bootflow_meth_flags_t), 0 if none
  * Returns: sequence number on success, else -ve error code
  */
-static int label_to_uclass(const char *label, int *seqp)
+static int label_to_uclass(const char *label, int *seqp, int *method_flagsp)
 {
+       int seq, len, method_flags;
        enum uclass_id id;
        const char *end;
-       int seq, len;
 
+       method_flags = 0;
        seq = trailing_strtoln_end(label, NULL, &end);
        len = end - label;
        if (!len)
@@ -379,6 +382,14 @@ static int label_to_uclass(const char *label, int *seqp)
                if (IS_ENABLED(CONFIG_BOOTDEV_SPI_FLASH) &&
                    !strncmp("spi", label, len)) {
                        id = UCLASS_SPI_FLASH;
+               } else if (IS_ENABLED(CONFIG_BOOTDEV_ETH) &&
+                   !strncmp("pxe", label, len)) {
+                       id = UCLASS_ETH;
+                       method_flags |= BOOTFLOW_METHF_PXE_ONLY;
+               } else if (IS_ENABLED(CONFIG_BOOTDEV_ETH) &&
+                   !strncmp("dhcp", label, len)) {
+                       id = UCLASS_ETH;
+                       method_flags |= BOOTFLOW_METHF_DHCP_ONLY;
                } else {
                        log_warning("Unknown uclass '%s' in label\n", label);
                        return -EINVAL;
@@ -387,31 +398,21 @@ static int label_to_uclass(const char *label, int *seqp)
        if (id == UCLASS_USB)
                id = UCLASS_MASS_STORAGE;
        *seqp = seq;
+       if (method_flagsp)
+               *method_flagsp = method_flags;
 
        return id;
 }
 
-/**
- * bootdev_find_by_label() - Convert a label string to a bootdev device
- *
- * Looks up a label name to find the associated bootdev. For example, if the
- * label name is "mmc2", this will find a bootdev for an mmc device whose
- * sequence number is 2.
- *
- * @label: Label string to convert, e.g. "mmc2"
- * @devp: Returns bootdev device corresponding to that boot label
- * Return: 0 if OK, -EINVAL if the label name (e.g. "mmc") does not refer to a
- *     uclass, -ENOENT if no bootdev for that media has the sequence number
- *     (e.g. 2)
- */
-int bootdev_find_by_label(const char *label, struct udevice **devp)
+int bootdev_find_by_label(const char *label, struct udevice **devp,
+                         int *method_flagsp)
 {
+       int seq, ret, method_flags = 0;
        struct udevice *media;
        struct uclass *uc;
        enum uclass_id id;
-       int seq, ret;
 
-       ret = label_to_uclass(label, &seq);
+       ret = label_to_uclass(label, &seq, &method_flags);
        if (ret < 0)
                return log_msg_ret("uc", ret);
        id = ret;
@@ -441,6 +442,8 @@ int bootdev_find_by_label(const char *label, struct udevice **devp)
                if (!ret) {
                        log_debug("- found %s\n", bdev->name);
                        *devp = bdev;
+                       if (method_flagsp)
+                               *method_flagsp = method_flags;
                        return 0;
                }
                log_debug("- no device in %s\n", media->name);
@@ -450,9 +453,11 @@ int bootdev_find_by_label(const char *label, struct udevice **devp)
        return -ENOENT;
 }
 
-int bootdev_find_by_any(const char *name, struct udevice **devp)
+int bootdev_find_by_any(const char *name, struct udevice **devp,
+                       int *method_flagsp)
 {
        struct udevice *dev;
+       int method_flags = 0;
        int ret, seq;
        char *endp;
 
@@ -462,18 +467,18 @@ int bootdev_find_by_any(const char *name, struct udevice **devp)
        if (*endp) {
                ret = uclass_get_device_by_name(UCLASS_BOOTDEV, name, &dev);
                if (ret == -ENODEV) {
-                       ret = bootdev_find_by_label(name, &dev);
+                       ret = bootdev_find_by_label(name, &dev, &method_flags);
                        if (ret) {
                                printf("Cannot find bootdev '%s' (err=%d)\n",
                                       name, ret);
-                               return ret;
+                               return log_msg_ret("lab", ret);
                        }
                        ret = device_probe(dev);
                }
                if (ret) {
                        printf("Cannot probe bootdev '%s' (err=%d)\n", name,
                               ret);
-                       return ret;
+                       return log_msg_ret("pro", ret);
                }
        } else {
                ret = uclass_get_device_by_seq(UCLASS_BOOTDEV, seq, &dev);
@@ -484,6 +489,8 @@ int bootdev_find_by_any(const char *name, struct udevice **devp)
        }
 
        *devp = dev;
+       if (method_flagsp)
+               *method_flagsp = method_flags;
 
        return 0;
 }
@@ -593,7 +600,7 @@ static int build_order(struct udevice *bootstd, struct udevice **order,
 
                upto = 0;
                for (i = 0; labels[i]; i++) {
-                       ret = bootdev_find_by_label(labels[i], &dev);
+                       ret = bootdev_find_by_label(labels[i], &dev, NULL);
                        if (!ret) {
                                if (upto == max_count) {
                                        overflow_target = labels[i];
index 53a0489b93ca91f8d5edc7a5618a07b4c4e9d62e..67c972e3fe42e6a67007e7bd7d898d5c855dbcf9 100644 (file)
@@ -140,6 +140,10 @@ static int distro_efi_check(struct udevice *dev, struct bootflow_iter *iter)
        if (bootflow_iter_check_blk(iter) && bootflow_iter_check_net(iter))
                return log_msg_ret("blk", -ENOTSUPP);
 
+       /* This works on block devices and network devices */
+       if (iter->method_flags & BOOTFLOW_METHF_PXE_ONLY)
+               return log_msg_ret("pxe", -ENOTSUPP);
+
        return 0;
 }
 
index 13e2ff486dcb10f922bd95af43ab2bad1bfed16c..ecf8557af83fe7ad5d6b77dabca01beefe2f9869 100644 (file)
@@ -48,6 +48,9 @@ static int distro_pxe_check(struct udevice *dev, struct bootflow_iter *iter)
        if (ret)
                return log_msg_ret("net", ret);
 
+       if (iter->method_flags & BOOTFLOW_METHF_DHCP_ONLY)
+               return log_msg_ret("dhcp", -ENOTSUPP);
+
        return 0;
 }
 
index a14c750ff61e3a70ae144a3a2998a2446fec0735..225eb18ee6ca7ddeec22ffaa08a7bad4d735f5de 100644 (file)
@@ -27,6 +27,8 @@
 static int script_check(struct udevice *dev, struct bootflow_iter *iter)
 {
        /* This works on block devices, network devices and SPI Flash */
+       if (iter->method_flags & BOOTFLOW_METHF_PXE_ONLY)
+               return log_msg_ret("pxe", -ENOTSUPP);
 
        return 0;
 }
index 0a49d28670334a965f4d02c74267c732afbc234d..d59a704ddbade4708aceb025b66c57996357f459 100644 (file)
@@ -176,7 +176,7 @@ static int simple_load_from_image(struct spl_image_info *spl_image,
 
        priv = dev_get_priv(meth);
        log_debug("simple %s\n", priv->storage);
-       ret = bootdev_find_by_label(priv->storage, &bdev);
+       ret = bootdev_find_by_label(priv->storage, &bdev, NULL);
        if (ret)
                return log_msg_ret("bd", ret);
        log_debug("bootdev %s\n", bdev->name);
index 28866faac766f7a0cac69fdd7d98303f886c3ebf..5b1efaaee876d2349b97e2a656676544a614bc62 100644 (file)
@@ -57,7 +57,7 @@ static int do_bootdev_select(struct cmd_tbl *cmdtp, int flag, int argc,
                std->cur_bootdev = NULL;
                return 0;
        }
-       if (bootdev_find_by_any(argv[1], &dev))
+       if (bootdev_find_by_any(argv[1], &dev, NULL))
                return CMD_RET_FAILURE;
 
        std->cur_bootdev = dev;
index 56dd35b69cf49be6064db266e4336a0924e769ba..c8b2f5efdebb7532a5d9eff2e1a57e9e6abcbb70 100644 (file)
@@ -121,7 +121,7 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
                if (argc > 1) {
                        const char *label = argv[1];
 
-                       if (bootdev_find_by_any(label, &dev))
+                       if (bootdev_find_by_any(label, &dev, NULL))
                                return CMD_RET_FAILURE;
                }
        } else {
index deef7890489855797716c9b6f70f9852efed712e..db03c5c032e0b954d61e43069df6a9a4c32536d5 100644 (file)
@@ -222,19 +222,26 @@ int bootdev_next_bootflow(struct bootflow **bflowp);
  * @label: Label to look up (e.g. "mmc1" or "mmc0")
  * @devp: Returns the bootdev device found, or NULL if none (note it does not
  *     return the media device, but its bootdev child)
+ * @method_flagsp: If non-NULL, returns any flags implied by the label
+ * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
  * Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
- *     -ENOENT if there is no device with that number
+ * -ENOENT if there is no device with that number
  */
-int bootdev_find_by_label(const char *label, struct udevice **devp);
+int bootdev_find_by_label(const char *label, struct udevice **devp,
+                         int *method_flagsp);
 
 /**
  * bootdev_find_by_any() - Find a bootdev by name, label or sequence
  *
  * @name: name (e.g. "mmc2.bootdev"), label ("mmc2"), or sequence ("2") to find
  * @devp: returns the device found, on success
- * Return: 0 if OK, -ve on error
+ * @method_flagsp: If non-NULL, returns any flags implied by the label
+ * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
+ * Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
+ * -ENOENT if there is no device with that number
  */
-int bootdev_find_by_any(const char *name, struct udevice **devp);
+int bootdev_find_by_any(const char *name, struct udevice **devp,
+                       int *method_flagsp);
 
 /**
  * bootdev_setup_iter_order() - Set up the ordering of bootdevs to scan
index 319dda8e0be2b10d681813f3afd726de4aab9e57..9c6610bb922d7fd57eaca7736c83d0dca6fafaf0 100644 (file)
@@ -104,6 +104,21 @@ enum bootflow_flags_t {
        BOOTFLOWF_SKIP_GLOBAL   = 1 << 4,
 };
 
+/**
+ * enum bootflow_meth_flags_t - flags controlling which bootmeths are used
+ *
+ * Used during iteration, e.g. by bootdev_find_by_label(), to determine which
+ * bootmeths are used for the current bootdev. The flags reset when the bootdev
+ * changes
+ *
+ * @BOOTFLOW_METHF_DHCP_ONLY: Only use dhcp (scripts and EFI)
+ * @BOOTFLOW_METHF_PXE_ONLY: Only use pxe (PXE boot)
+ */
+enum bootflow_meth_flags_t {
+       BOOTFLOW_METHF_DHCP_ONLY        = 1 << 0,
+       BOOTFLOW_METHF_PXE_ONLY         = 1 << 1,
+};
+
 /**
  * struct bootflow_iter - state for iterating through bootflows
  *
index ea0703fa5c84e870e15398b91fc1f2e8c8c28601..e6045b05d8190e99c93b251ee7ec19498b971126 100644 (file)
@@ -102,22 +102,31 @@ BOOTSTD_TEST(bootdev_test_cmd_select, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
 static int bootdev_test_labels(struct unit_test_state *uts)
 {
        struct udevice *dev, *media;
+       int mflags = 0;
 
-       ut_assertok(bootdev_find_by_label("mmc2", &dev));
+       ut_assertok(bootdev_find_by_label("mmc2", &dev, &mflags));
        ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev));
+       ut_asserteq(0, mflags);
        media = dev_get_parent(dev);
        ut_asserteq(UCLASS_MMC, device_get_uclass_id(media));
        ut_asserteq_str("mmc2", media->name);
 
+       /* Check method flags */
+       ut_assertok(bootdev_find_by_label("pxe", &dev, &mflags));
+       ut_asserteq(BOOTFLOW_METHF_PXE_ONLY, mflags);
+       ut_assertok(bootdev_find_by_label("dhcp", &dev, &mflags));
+       ut_asserteq(BOOTFLOW_METHF_DHCP_ONLY, mflags);
+
        /* Check invalid uclass */
-       ut_asserteq(-EINVAL, bootdev_find_by_label("fred0", &dev));
+       ut_asserteq(-EINVAL, bootdev_find_by_label("fred0", &dev, &mflags));
 
        /* Check unknown sequence number */
-       ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev));
+       ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev, &mflags));
 
        return 0;
 }
-BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
+            UT_TESTF_ETH_BOOTDEV);
 
 /* Check bootdev ordering with the bootdev-order property */
 static int bootdev_test_order(struct unit_test_state *uts)