summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--boot/bootdev-uclass.c53
-rw-r--r--boot/bootmeth_efi.c4
-rw-r--r--boot/bootmeth_pxe.c3
-rw-r--r--boot/bootmeth_script.c2
-rw-r--r--boot/vbe_simple_fw.c2
-rw-r--r--cmd/bootdev.c2
-rw-r--r--cmd/bootflow.c2
-rw-r--r--include/bootdev.h15
-rw-r--r--include/bootflow.h15
-rw-r--r--test/boot/bootdev.c17
10 files changed, 81 insertions, 34 deletions
diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c
index dd9ec668e16..7ac42afd7b3 100644
--- a/boot/bootdev-uclass.c
+++ b/boot/bootdev-uclass.c
@@ -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];
diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c
index 53a0489b93c..67c972e3fe4 100644
--- a/boot/bootmeth_efi.c
+++ b/boot/bootmeth_efi.c
@@ -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;
}
diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c
index 13e2ff486dc..ecf8557af83 100644
--- a/boot/bootmeth_pxe.c
+++ b/boot/bootmeth_pxe.c
@@ -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;
}
diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c
index a14c750ff61..225eb18ee6c 100644
--- a/boot/bootmeth_script.c
+++ b/boot/bootmeth_script.c
@@ -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;
}
diff --git a/boot/vbe_simple_fw.c b/boot/vbe_simple_fw.c
index 0a49d286703..d59a704ddba 100644
--- a/boot/vbe_simple_fw.c
+++ b/boot/vbe_simple_fw.c
@@ -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);
diff --git a/cmd/bootdev.c b/cmd/bootdev.c
index 28866faac76..5b1efaaee87 100644
--- a/cmd/bootdev.c
+++ b/cmd/bootdev.c
@@ -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;
diff --git a/cmd/bootflow.c b/cmd/bootflow.c
index 56dd35b69cf..c8b2f5efdeb 100644
--- a/cmd/bootflow.c
+++ b/cmd/bootflow.c
@@ -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 {
diff --git a/include/bootdev.h b/include/bootdev.h
index deef7890489..db03c5c032e 100644
--- a/include/bootdev.h
+++ b/include/bootdev.h
@@ -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
diff --git a/include/bootflow.h b/include/bootflow.h
index 319dda8e0be..9c6610bb922 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -105,6 +105,21 @@ enum bootflow_flags_t {
};
/**
+ * 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
*
* This starts at with the first bootdev/partition/bootmeth and can be used to
diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c
index ea0703fa5c8..e6045b05d81 100644
--- a/test/boot/bootdev.c
+++ b/test/boot/bootdev.c
@@ -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)