Skip to content

Commit d9f4857

Browse files
sjg20trini
authored andcommitted
bootstd: Treat DHCP and PXE as bootdev labels
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>
1 parent 5143a41 commit d9f4857

10 files changed

Lines changed: 81 additions & 34 deletions

File tree

boot/bootdev-uclass.c

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -359,14 +359,17 @@ int bootdev_unbind_dev(struct udevice *parent)
359359
*
360360
* @label: Label to look up (e.g. "mmc1" or "mmc0")
361361
* @seqp: Returns the sequence number, or -1 if none
362+
* @method_flagsp: If non-NULL, returns any flags implied by the label
363+
* (enum bootflow_meth_flags_t), 0 if none
362364
* Returns: sequence number on success, else -ve error code
363365
*/
364-
static int label_to_uclass(const char *label, int *seqp)
366+
static int label_to_uclass(const char *label, int *seqp, int *method_flagsp)
365367
{
368+
int seq, len, method_flags;
366369
enum uclass_id id;
367370
const char *end;
368-
int seq, len;
369371

372+
method_flags = 0;
370373
seq = trailing_strtoln_end(label, NULL, &end);
371374
len = end - label;
372375
if (!len)
@@ -379,6 +382,14 @@ static int label_to_uclass(const char *label, int *seqp)
379382
if (IS_ENABLED(CONFIG_BOOTDEV_SPI_FLASH) &&
380383
!strncmp("spi", label, len)) {
381384
id = UCLASS_SPI_FLASH;
385+
} else if (IS_ENABLED(CONFIG_BOOTDEV_ETH) &&
386+
!strncmp("pxe", label, len)) {
387+
id = UCLASS_ETH;
388+
method_flags |= BOOTFLOW_METHF_PXE_ONLY;
389+
} else if (IS_ENABLED(CONFIG_BOOTDEV_ETH) &&
390+
!strncmp("dhcp", label, len)) {
391+
id = UCLASS_ETH;
392+
method_flags |= BOOTFLOW_METHF_DHCP_ONLY;
382393
} else {
383394
log_warning("Unknown uclass '%s' in label\n", label);
384395
return -EINVAL;
@@ -387,31 +398,21 @@ static int label_to_uclass(const char *label, int *seqp)
387398
if (id == UCLASS_USB)
388399
id = UCLASS_MASS_STORAGE;
389400
*seqp = seq;
401+
if (method_flagsp)
402+
*method_flagsp = method_flags;
390403

391404
return id;
392405
}
393406

394-
/**
395-
* bootdev_find_by_label() - Convert a label string to a bootdev device
396-
*
397-
* Looks up a label name to find the associated bootdev. For example, if the
398-
* label name is "mmc2", this will find a bootdev for an mmc device whose
399-
* sequence number is 2.
400-
*
401-
* @label: Label string to convert, e.g. "mmc2"
402-
* @devp: Returns bootdev device corresponding to that boot label
403-
* Return: 0 if OK, -EINVAL if the label name (e.g. "mmc") does not refer to a
404-
* uclass, -ENOENT if no bootdev for that media has the sequence number
405-
* (e.g. 2)
406-
*/
407-
int bootdev_find_by_label(const char *label, struct udevice **devp)
407+
int bootdev_find_by_label(const char *label, struct udevice **devp,
408+
int *method_flagsp)
408409
{
410+
int seq, ret, method_flags = 0;
409411
struct udevice *media;
410412
struct uclass *uc;
411413
enum uclass_id id;
412-
int seq, ret;
413414

414-
ret = label_to_uclass(label, &seq);
415+
ret = label_to_uclass(label, &seq, &method_flags);
415416
if (ret < 0)
416417
return log_msg_ret("uc", ret);
417418
id = ret;
@@ -441,6 +442,8 @@ int bootdev_find_by_label(const char *label, struct udevice **devp)
441442
if (!ret) {
442443
log_debug("- found %s\n", bdev->name);
443444
*devp = bdev;
445+
if (method_flagsp)
446+
*method_flagsp = method_flags;
444447
return 0;
445448
}
446449
log_debug("- no device in %s\n", media->name);
@@ -450,9 +453,11 @@ int bootdev_find_by_label(const char *label, struct udevice **devp)
450453
return -ENOENT;
451454
}
452455

453-
int bootdev_find_by_any(const char *name, struct udevice **devp)
456+
int bootdev_find_by_any(const char *name, struct udevice **devp,
457+
int *method_flagsp)
454458
{
455459
struct udevice *dev;
460+
int method_flags = 0;
456461
int ret, seq;
457462
char *endp;
458463

@@ -462,18 +467,18 @@ int bootdev_find_by_any(const char *name, struct udevice **devp)
462467
if (*endp) {
463468
ret = uclass_get_device_by_name(UCLASS_BOOTDEV, name, &dev);
464469
if (ret == -ENODEV) {
465-
ret = bootdev_find_by_label(name, &dev);
470+
ret = bootdev_find_by_label(name, &dev, &method_flags);
466471
if (ret) {
467472
printf("Cannot find bootdev '%s' (err=%d)\n",
468473
name, ret);
469-
return ret;
474+
return log_msg_ret("lab", ret);
470475
}
471476
ret = device_probe(dev);
472477
}
473478
if (ret) {
474479
printf("Cannot probe bootdev '%s' (err=%d)\n", name,
475480
ret);
476-
return ret;
481+
return log_msg_ret("pro", ret);
477482
}
478483
} else {
479484
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)
484489
}
485490

486491
*devp = dev;
492+
if (method_flagsp)
493+
*method_flagsp = method_flags;
487494

488495
return 0;
489496
}
@@ -593,7 +600,7 @@ static int build_order(struct udevice *bootstd, struct udevice **order,
593600

594601
upto = 0;
595602
for (i = 0; labels[i]; i++) {
596-
ret = bootdev_find_by_label(labels[i], &dev);
603+
ret = bootdev_find_by_label(labels[i], &dev, NULL);
597604
if (!ret) {
598605
if (upto == max_count) {
599606
overflow_target = labels[i];

boot/bootmeth_efi.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,10 @@ static int distro_efi_check(struct udevice *dev, struct bootflow_iter *iter)
140140
if (bootflow_iter_check_blk(iter) && bootflow_iter_check_net(iter))
141141
return log_msg_ret("blk", -ENOTSUPP);
142142

143+
/* This works on block devices and network devices */
144+
if (iter->method_flags & BOOTFLOW_METHF_PXE_ONLY)
145+
return log_msg_ret("pxe", -ENOTSUPP);
146+
143147
return 0;
144148
}
145149

boot/bootmeth_pxe.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ static int distro_pxe_check(struct udevice *dev, struct bootflow_iter *iter)
4848
if (ret)
4949
return log_msg_ret("net", ret);
5050

51+
if (iter->method_flags & BOOTFLOW_METHF_DHCP_ONLY)
52+
return log_msg_ret("dhcp", -ENOTSUPP);
53+
5154
return 0;
5255
}
5356

boot/bootmeth_script.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
static int script_check(struct udevice *dev, struct bootflow_iter *iter)
2828
{
2929
/* This works on block devices, network devices and SPI Flash */
30+
if (iter->method_flags & BOOTFLOW_METHF_PXE_ONLY)
31+
return log_msg_ret("pxe", -ENOTSUPP);
3032

3133
return 0;
3234
}

boot/vbe_simple_fw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ static int simple_load_from_image(struct spl_image_info *spl_image,
176176

177177
priv = dev_get_priv(meth);
178178
log_debug("simple %s\n", priv->storage);
179-
ret = bootdev_find_by_label(priv->storage, &bdev);
179+
ret = bootdev_find_by_label(priv->storage, &bdev, NULL);
180180
if (ret)
181181
return log_msg_ret("bd", ret);
182182
log_debug("bootdev %s\n", bdev->name);

cmd/bootdev.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ static int do_bootdev_select(struct cmd_tbl *cmdtp, int flag, int argc,
5757
std->cur_bootdev = NULL;
5858
return 0;
5959
}
60-
if (bootdev_find_by_any(argv[1], &dev))
60+
if (bootdev_find_by_any(argv[1], &dev, NULL))
6161
return CMD_RET_FAILURE;
6262

6363
std->cur_bootdev = dev;

cmd/bootflow.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ static int do_bootflow_scan(struct cmd_tbl *cmdtp, int flag, int argc,
121121
if (argc > 1) {
122122
const char *label = argv[1];
123123

124-
if (bootdev_find_by_any(label, &dev))
124+
if (bootdev_find_by_any(label, &dev, NULL))
125125
return CMD_RET_FAILURE;
126126
}
127127
} else {

include/bootdev.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,19 +222,26 @@ int bootdev_next_bootflow(struct bootflow **bflowp);
222222
* @label: Label to look up (e.g. "mmc1" or "mmc0")
223223
* @devp: Returns the bootdev device found, or NULL if none (note it does not
224224
* return the media device, but its bootdev child)
225+
* @method_flagsp: If non-NULL, returns any flags implied by the label
226+
* (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
225227
* Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
226-
* -ENOENT if there is no device with that number
228+
* -ENOENT if there is no device with that number
227229
*/
228-
int bootdev_find_by_label(const char *label, struct udevice **devp);
230+
int bootdev_find_by_label(const char *label, struct udevice **devp,
231+
int *method_flagsp);
229232

230233
/**
231234
* bootdev_find_by_any() - Find a bootdev by name, label or sequence
232235
*
233236
* @name: name (e.g. "mmc2.bootdev"), label ("mmc2"), or sequence ("2") to find
234237
* @devp: returns the device found, on success
235-
* Return: 0 if OK, -ve on error
238+
* @method_flagsp: If non-NULL, returns any flags implied by the label
239+
* (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
240+
* Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
241+
* -ENOENT if there is no device with that number
236242
*/
237-
int bootdev_find_by_any(const char *name, struct udevice **devp);
243+
int bootdev_find_by_any(const char *name, struct udevice **devp,
244+
int *method_flagsp);
238245

239246
/**
240247
* bootdev_setup_iter_order() - Set up the ordering of bootdevs to scan

include/bootflow.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,21 @@ enum bootflow_flags_t {
104104
BOOTFLOWF_SKIP_GLOBAL = 1 << 4,
105105
};
106106

107+
/**
108+
* enum bootflow_meth_flags_t - flags controlling which bootmeths are used
109+
*
110+
* Used during iteration, e.g. by bootdev_find_by_label(), to determine which
111+
* bootmeths are used for the current bootdev. The flags reset when the bootdev
112+
* changes
113+
*
114+
* @BOOTFLOW_METHF_DHCP_ONLY: Only use dhcp (scripts and EFI)
115+
* @BOOTFLOW_METHF_PXE_ONLY: Only use pxe (PXE boot)
116+
*/
117+
enum bootflow_meth_flags_t {
118+
BOOTFLOW_METHF_DHCP_ONLY = 1 << 0,
119+
BOOTFLOW_METHF_PXE_ONLY = 1 << 1,
120+
};
121+
107122
/**
108123
* struct bootflow_iter - state for iterating through bootflows
109124
*

test/boot/bootdev.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,22 +102,31 @@ BOOTSTD_TEST(bootdev_test_cmd_select, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
102102
static int bootdev_test_labels(struct unit_test_state *uts)
103103
{
104104
struct udevice *dev, *media;
105+
int mflags = 0;
105106

106-
ut_assertok(bootdev_find_by_label("mmc2", &dev));
107+
ut_assertok(bootdev_find_by_label("mmc2", &dev, &mflags));
107108
ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev));
109+
ut_asserteq(0, mflags);
108110
media = dev_get_parent(dev);
109111
ut_asserteq(UCLASS_MMC, device_get_uclass_id(media));
110112
ut_asserteq_str("mmc2", media->name);
111113

114+
/* Check method flags */
115+
ut_assertok(bootdev_find_by_label("pxe", &dev, &mflags));
116+
ut_asserteq(BOOTFLOW_METHF_PXE_ONLY, mflags);
117+
ut_assertok(bootdev_find_by_label("dhcp", &dev, &mflags));
118+
ut_asserteq(BOOTFLOW_METHF_DHCP_ONLY, mflags);
119+
112120
/* Check invalid uclass */
113-
ut_asserteq(-EINVAL, bootdev_find_by_label("fred0", &dev));
121+
ut_asserteq(-EINVAL, bootdev_find_by_label("fred0", &dev, &mflags));
114122

115123
/* Check unknown sequence number */
116-
ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev));
124+
ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev, &mflags));
117125

118126
return 0;
119127
}
120-
BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
128+
BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
129+
UT_TESTF_ETH_BOOTDEV);
121130

122131
/* Check bootdev ordering with the bootdev-order property */
123132
static int bootdev_test_order(struct unit_test_state *uts)

0 commit comments

Comments
 (0)