blob: 369c611d924b5c07378bdcc8ad97f929beb76c02 [file] [log] [blame]
Simon Glassfb1451b2022-04-24 23:31:24 -06001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Test for bootdev functions. All start with 'bootdev'
4 *
5 * Copyright 2021 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
7 */
8
Simon Glassfb1451b2022-04-24 23:31:24 -06009#include <bootstd.h>
10#include <dm.h>
11#include <bootdev.h>
12#include <bootflow.h>
13#include <mapmem.h>
14#include <os.h>
15#include <test/suites.h>
16#include <test/ut.h>
17#include "bootstd_common.h"
18
Simon Glassfb1451b2022-04-24 23:31:24 -060019/* Check 'bootdev list' command */
20static int bootdev_test_cmd_list(struct unit_test_state *uts)
21{
22 int probed;
23
Simon Glassfb1451b2022-04-24 23:31:24 -060024 for (probed = 0; probed < 2; probed++) {
25 int probe_ch = probed ? '+' : ' ';
26
27 ut_assertok(run_command(probed ? "bootdev list -p" :
28 "bootdev list", 0));
29 ut_assert_nextline("Seq Probed Status Uclass Name");
30 ut_assert_nextlinen("---");
31 ut_assert_nextline("%3x [ %c ] %6s %-8s %s", 0, probe_ch, "OK",
32 "mmc", "mmc2.bootdev");
33 ut_assert_nextline("%3x [ %c ] %6s %-8s %s", 1, probe_ch, "OK",
34 "mmc", "mmc1.bootdev");
35 ut_assert_nextline("%3x [ %c ] %6s %-8s %s", 2, probe_ch, "OK",
36 "mmc", "mmc0.bootdev");
37 ut_assert_nextlinen("---");
38 ut_assert_nextline("(3 bootdevs)");
39 ut_assert_console_end();
40 }
41
42 return 0;
43}
Simon Glassa6a80b32024-08-22 07:57:54 -060044BOOTSTD_TEST(bootdev_test_cmd_list, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassfb1451b2022-04-24 23:31:24 -060045
46/* Check 'bootdev select' and 'info' commands */
47static int bootdev_test_cmd_select(struct unit_test_state *uts)
48{
49 struct bootstd_priv *std;
50
51 /* get access to the CLI's cur_bootdev */
52 ut_assertok(bootstd_get_priv(&std));
53
Simon Glassfb1451b2022-04-24 23:31:24 -060054 ut_asserteq(1, run_command("bootdev info", 0));
55 ut_assert_nextlinen("Please use");
56 ut_assert_console_end();
57
58 /* select by sequence */
59 ut_assertok(run_command("bootdev select 0", 0));
60 ut_assert_console_end();
61
62 ut_assertok(run_command("bootdev info", 0));
63 ut_assert_nextline("Name: mmc2.bootdev");
64 ut_assert_nextline("Sequence: 0");
65 ut_assert_nextline("Status: Probed");
66 ut_assert_nextline("Uclass: mmc");
67 ut_assert_nextline("Bootflows: 0 (0 valid)");
68 ut_assert_console_end();
69
70 /* select by bootdev name */
71 ut_assertok(run_command("bootdev select mmc1.bootdev", 0));
72 ut_assert_console_end();
73 ut_assertnonnull(std->cur_bootdev);
74 ut_asserteq_str("mmc1.bootdev", std->cur_bootdev->name);
75
76 /* select by bootdev label*/
77 ut_assertok(run_command("bootdev select mmc1", 0));
78 ut_assert_console_end();
79 ut_assertnonnull(std->cur_bootdev);
80 ut_asserteq_str("mmc1.bootdev", std->cur_bootdev->name);
81
82 /* deselect */
83 ut_assertok(run_command("bootdev select", 0));
84 ut_assert_console_end();
85 ut_assertnull(std->cur_bootdev);
86
87 ut_asserteq(1, run_command("bootdev info", 0));
88 ut_assert_nextlinen("Please use");
89 ut_assert_console_end();
90
91 return 0;
92}
Simon Glassa6a80b32024-08-22 07:57:54 -060093BOOTSTD_TEST(bootdev_test_cmd_select, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassfb1451b2022-04-24 23:31:24 -060094
95/* Check bootdev labels */
96static int bootdev_test_labels(struct unit_test_state *uts)
97{
98 struct udevice *dev, *media;
Simon Glassd9f48572023-01-17 10:48:05 -070099 int mflags = 0;
Simon Glassfb1451b2022-04-24 23:31:24 -0600100
Simon Glassd9f48572023-01-17 10:48:05 -0700101 ut_assertok(bootdev_find_by_label("mmc2", &dev, &mflags));
Simon Glassfb1451b2022-04-24 23:31:24 -0600102 ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev));
Simon Glassd9f48572023-01-17 10:48:05 -0700103 ut_asserteq(0, mflags);
Simon Glassfb1451b2022-04-24 23:31:24 -0600104 media = dev_get_parent(dev);
105 ut_asserteq(UCLASS_MMC, device_get_uclass_id(media));
106 ut_asserteq_str("mmc2", media->name);
107
Simon Glassd9f48572023-01-17 10:48:05 -0700108 /* Check method flags */
109 ut_assertok(bootdev_find_by_label("pxe", &dev, &mflags));
Simon Glass66e3dce2023-01-17 10:48:09 -0700110 ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
111 mflags);
Simon Glassd9f48572023-01-17 10:48:05 -0700112 ut_assertok(bootdev_find_by_label("dhcp", &dev, &mflags));
Simon Glass66e3dce2023-01-17 10:48:09 -0700113 ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY,
114 mflags);
Simon Glassd9f48572023-01-17 10:48:05 -0700115
Simon Glassfb1451b2022-04-24 23:31:24 -0600116 /* Check invalid uclass */
Simon Glass1736b4a2023-04-24 13:49:47 +1200117 ut_asserteq(-EPFNOSUPPORT,
118 bootdev_find_by_label("fred0", &dev, &mflags));
Simon Glassfb1451b2022-04-24 23:31:24 -0600119
120 /* Check unknown sequence number */
Simon Glassd9f48572023-01-17 10:48:05 -0700121 ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev, &mflags));
Simon Glassfb1451b2022-04-24 23:31:24 -0600122
123 return 0;
124}
Simon Glass725c4382024-08-22 07:57:48 -0600125BOOTSTD_TEST(bootdev_test_labels, UTF_DM | UTF_SCAN_FDT | UTF_ETH_BOOTDEV);
Simon Glassfb1451b2022-04-24 23:31:24 -0600126
Simon Glass66e3dce2023-01-17 10:48:09 -0700127/* Check bootdev_find_by_any() */
128static int bootdev_test_any(struct unit_test_state *uts)
129{
130 struct udevice *dev, *media;
Jerome Forissier69aee0c2024-10-16 11:56:25 +0200131 char *seq;
Simon Glass66e3dce2023-01-17 10:48:09 -0700132 int mflags;
133
134 /*
135 * with ethernet enabled we have 8 devices ahead of the mmc ones:
136 *
137 * ut_assertok(run_command("bootdev list", 0));
138 * Seq Probed Status Uclass Name
139 * --- ------ ------ -------- ------------------
140 * 0 [ + ] OK ethernet eth@10002000.bootdev
141 * 1 [ ] OK ethernet eth@10003000.bootdev
142 * 2 [ ] OK ethernet sbe5.bootdev
143 * 3 [ ] OK ethernet eth@10004000.bootdev
144 * 4 [ ] OK ethernet phy-test-eth.bootdev
145 * 5 [ ] OK ethernet dsa-test-eth.bootdev
146 * 6 [ ] OK ethernet dsa-test@0.bootdev
147 * 7 [ ] OK ethernet dsa-test@1.bootdev
148 * 8 [ ] OK mmc mmc2.bootdev
149 * 9 [ + ] OK mmc mmc1.bootdev
150 * a [ ] OK mmc mmc0.bootdev
Jerome Forissier69aee0c2024-10-16 11:56:25 +0200151 *
152 * However if DSA_SANDBOX is disabled the dsa-test@{0,1} devices
153 * are not there.
Simon Glass66e3dce2023-01-17 10:48:09 -0700154 */
Jerome Forissier69aee0c2024-10-16 11:56:25 +0200155 if (CONFIG_IS_ENABLED(DSA_SANDBOX))
156 seq = "8";
157 else
158 seq = "6";
159
160 ut_assertok(bootdev_find_by_any(seq, &dev, &mflags));
Simon Glass66e3dce2023-01-17 10:48:09 -0700161 ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev));
162 ut_asserteq(BOOTFLOW_METHF_SINGLE_DEV, mflags);
163 media = dev_get_parent(dev);
164 ut_asserteq(UCLASS_MMC, device_get_uclass_id(media));
165 ut_asserteq_str("mmc2", media->name);
166 ut_assert_console_end();
167
168 /* there should not be this many bootdevs */
169 ut_asserteq(-ENODEV, bootdev_find_by_any("50", &dev, &mflags));
170 ut_assert_nextline("Cannot find '50' (err=-19)");
171 ut_assert_console_end();
172
173 /* Check method flags */
174 ut_assertok(bootdev_find_by_any("pxe", &dev, &mflags));
175 ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
176 mflags);
177
178 /* Check invalid uclass */
179 mflags = 123;
Simon Glass1736b4a2023-04-24 13:49:47 +1200180 ut_asserteq(-EPFNOSUPPORT, bootdev_find_by_any("fred0", &dev, &mflags));
181 ut_assert_nextline("Cannot find bootdev 'fred0' (err=-96)");
Simon Glass66e3dce2023-01-17 10:48:09 -0700182 ut_asserteq(123, mflags);
183 ut_assert_console_end();
184
185 return 0;
186}
Simon Glassa6a80b32024-08-22 07:57:54 -0600187BOOTSTD_TEST(bootdev_test_any, UTF_DM | UTF_SCAN_FDT | UTF_ETH_BOOTDEV |
188 UTF_CONSOLE);
Simon Glass66e3dce2023-01-17 10:48:09 -0700189
Simon Glass7ae83bf2023-10-23 00:02:11 -0700190/*
191 * Check bootdev ordering with the bootdev-order property and boot_targets
192 * environment variable
193 */
Simon Glassfb1451b2022-04-24 23:31:24 -0600194static int bootdev_test_order(struct unit_test_state *uts)
195{
196 struct bootflow_iter iter;
197 struct bootflow bflow;
198
Simon Glass7ae83bf2023-10-23 00:02:11 -0700199 test_set_skip_delays(true);
200
201 /* Start up USB which gives us three additional bootdevs */
Simon Glassa3fab7d2024-09-01 16:26:16 -0600202 bootstd_reset_usb();
Simon Glass7ae83bf2023-10-23 00:02:11 -0700203 ut_assertok(run_command("usb start", 0));
204
Simon Glassfb1451b2022-04-24 23:31:24 -0600205 /*
206 * First try the order set by the bootdev-order property
207 * Like all sandbox unit tests this relies on the devicetree setting up
208 * the required devices:
209 *
210 * mmc0 - nothing connected
211 * mmc1 - connected to mmc1.img file
212 * mmc2 - nothing connected
213 */
214 ut_assertok(env_set("boot_targets", NULL));
Simon Glass4b7cb052023-01-17 10:48:16 -0700215 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
Simon Glassfb1451b2022-04-24 23:31:24 -0600216 ut_asserteq(2, iter.num_devs);
Simon Glassa950f282023-01-17 10:48:17 -0700217 ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
218 ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
Simon Glassfb1451b2022-04-24 23:31:24 -0600219 bootflow_iter_uninit(&iter);
220
221 /* Use the environment variable to override it */
Simon Glass7ae83bf2023-10-23 00:02:11 -0700222 ut_assertok(env_set("boot_targets", "mmc1 mmc2 usb"));
Simon Glass4b7cb052023-01-17 10:48:16 -0700223 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
Simon Glassa950f282023-01-17 10:48:17 -0700224 ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
Simon Glass7a790f02023-10-23 00:02:13 -0700225 ut_asserteq(5, iter.num_devs);
Simon Glassa950f282023-01-17 10:48:17 -0700226 ut_asserteq_str("mmc1.bootdev", iter.dev_used[0]->name);
227 ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name);
Simon Glass7ae83bf2023-10-23 00:02:11 -0700228 ut_asserteq_str("usb_mass_storage.lun0.bootdev",
229 iter.dev_used[2]->name);
Simon Glassfb1451b2022-04-24 23:31:24 -0600230 bootflow_iter_uninit(&iter);
231
Simon Glass16e19352023-10-23 00:02:12 -0700232 /* Try a single uclass */
233 ut_assertok(env_set("boot_targets", NULL));
234 ut_assertok(bootflow_scan_first(NULL, "mmc", &iter, 0, &bflow));
235 ut_asserteq(2, iter.num_devs);
236
Simon Glass7a790f02023-10-23 00:02:13 -0700237 /* Now scan past mmc1 and make sure that only mmc0 shows up */
Simon Glass16e19352023-10-23 00:02:12 -0700238 ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
239 ut_asserteq(3, iter.num_devs);
240 ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
241 ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
242 ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
243 bootflow_iter_uninit(&iter);
244
Simon Glass7a790f02023-10-23 00:02:13 -0700245 /* Try a single uclass with boot_targets */
246 ut_assertok(env_set("boot_targets", "mmc"));
247 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
248 ut_asserteq(2, iter.num_devs);
249
250 /* Now scan past mmc1 and make sure that only mmc0 shows up */
251 ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
252 ut_asserteq(3, iter.num_devs);
253 ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
254 ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
255 ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
256 bootflow_iter_uninit(&iter);
257
258 /* Try a single uclass with boot_targets */
259 ut_assertok(env_set("boot_targets", "mmc usb"));
260 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
261 ut_asserteq(2, iter.num_devs);
262
263 /* Now scan past mmc1 and make sure that the 3 USB devices show up */
264 ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
265 ut_asserteq(6, iter.num_devs);
266 ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
267 ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
268 ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
269 ut_asserteq_str("usb_mass_storage.lun0.bootdev",
270 iter.dev_used[3]->name);
271 bootflow_iter_uninit(&iter);
272
Simon Glassa950f282023-01-17 10:48:17 -0700273 return 0;
274}
Simon Glass725c4382024-08-22 07:57:48 -0600275BOOTSTD_TEST(bootdev_test_order, UTF_DM | UTF_SCAN_FDT);
Simon Glassa950f282023-01-17 10:48:17 -0700276
277/* Check default bootdev ordering */
278static int bootdev_test_order_default(struct unit_test_state *uts)
279{
280 struct bootflow_iter iter;
281 struct bootflow bflow;
282
Simon Glassfb1451b2022-04-24 23:31:24 -0600283 /*
284 * Now drop both orderings, to check the default (prioriy/sequence)
285 * ordering
286 */
287 ut_assertok(env_set("boot_targets", NULL));
288 ut_assertok(bootstd_test_drop_bootdev_order(uts));
289
Simon Glass4b7cb052023-01-17 10:48:16 -0700290 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
Simon Glassa950f282023-01-17 10:48:17 -0700291 ut_asserteq(2, iter.num_devs);
292 ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
293 ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
Simon Glassfb1451b2022-04-24 23:31:24 -0600294
Simon Glassa950f282023-01-17 10:48:17 -0700295 ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
Simon Glassfb1451b2022-04-24 23:31:24 -0600296 ut_asserteq(3, iter.num_devs);
Simon Glassa950f282023-01-17 10:48:17 -0700297 ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
Simon Glassfb1451b2022-04-24 23:31:24 -0600298 bootflow_iter_uninit(&iter);
299
300 return 0;
301}
Simon Glass725c4382024-08-22 07:57:48 -0600302BOOTSTD_TEST(bootdev_test_order_default, UTF_DM | UTF_SCAN_FDT);
Simon Glassfb1451b2022-04-24 23:31:24 -0600303
304/* Check bootdev ordering with the uclass priority */
305static int bootdev_test_prio(struct unit_test_state *uts)
306{
307 struct bootdev_uc_plat *ucp;
308 struct bootflow_iter iter;
309 struct bootflow bflow;
310 struct udevice *blk;
311
Simon Glass04fb2b62023-01-17 10:47:37 -0700312 test_set_skip_delays(true);
313
Simon Glassa950f282023-01-17 10:48:17 -0700314 /* disable ethernet since the hunter will run dhcp */
315 test_set_eth_enable(false);
316
Simon Glassfb1451b2022-04-24 23:31:24 -0600317 /* Start up USB which gives us three additional bootdevs */
Simon Glassa3fab7d2024-09-01 16:26:16 -0600318 bootstd_reset_usb();
Simon Glassfb1451b2022-04-24 23:31:24 -0600319 ut_assertok(run_command("usb start", 0));
320
321 ut_assertok(bootstd_test_drop_bootdev_order(uts));
322
323 /* 3 MMC and 3 USB bootdevs: MMC should come before USB */
Simon Glass4b7cb052023-01-17 10:48:16 -0700324 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
Simon Glassa950f282023-01-17 10:48:17 -0700325 ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
Simon Glassfb1451b2022-04-24 23:31:24 -0600326 ut_asserteq(6, iter.num_devs);
Simon Glassa950f282023-01-17 10:48:17 -0700327 ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
Simon Glassfb1451b2022-04-24 23:31:24 -0600328 ut_asserteq_str("usb_mass_storage.lun0.bootdev",
Simon Glassa950f282023-01-17 10:48:17 -0700329 iter.dev_used[3]->name);
Simon Glassfb1451b2022-04-24 23:31:24 -0600330
Simon Glassa950f282023-01-17 10:48:17 -0700331 ut_assertok(bootdev_get_sibling_blk(iter.dev_used[3], &blk));
Simon Glassfb1451b2022-04-24 23:31:24 -0600332 ut_asserteq_str("usb_mass_storage.lun0", blk->name);
333
334 /* adjust the priority of the first USB bootdev to the highest */
Simon Glassa950f282023-01-17 10:48:17 -0700335 ucp = dev_get_uclass_plat(iter.dev_used[3]);
336 ucp->prio = BOOTDEVP_1_PRE_SCAN;
Simon Glassfb1451b2022-04-24 23:31:24 -0600337
Simon Glassa950f282023-01-17 10:48:17 -0700338 /* try again but enable hunting, which brings in SCSI */
Simon Glassfb1451b2022-04-24 23:31:24 -0600339 bootflow_iter_uninit(&iter);
Simon Glass4f806f32023-02-22 12:17:03 -0700340 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, BOOTFLOWIF_HUNT,
Simon Glass4b7cb052023-01-17 10:48:16 -0700341 &bflow));
Simon Glassa950f282023-01-17 10:48:17 -0700342 ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
343 ut_asserteq(7, iter.num_devs);
Simon Glassfb1451b2022-04-24 23:31:24 -0600344 ut_asserteq_str("usb_mass_storage.lun0.bootdev",
Simon Glassa950f282023-01-17 10:48:17 -0700345 iter.dev_used[0]->name);
346 ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name);
Simon Glassfb1451b2022-04-24 23:31:24 -0600347
348 return 0;
349}
Simon Glass725c4382024-08-22 07:57:48 -0600350BOOTSTD_TEST(bootdev_test_prio, UTF_DM | UTF_SCAN_FDT);
Simon Glassbd90b092023-01-17 10:47:33 -0700351
352/* Check listing hunters */
353static int bootdev_test_hunter(struct unit_test_state *uts)
354{
355 struct bootstd_priv *std;
356
Simon Glassa3fab7d2024-09-01 16:26:16 -0600357 bootstd_reset_usb();
Simon Glass04fb2b62023-01-17 10:47:37 -0700358 test_set_skip_delays(true);
359
Simon Glassbd90b092023-01-17 10:47:33 -0700360 /* get access to the used hunters */
361 ut_assertok(bootstd_get_priv(&std));
362
Simon Glassbd90b092023-01-17 10:47:33 -0700363 bootdev_list_hunters(std);
364 ut_assert_nextline("Prio Used Uclass Hunter");
365 ut_assert_nextlinen("----");
Simon Glasseacc2612023-01-17 10:48:08 -0700366 ut_assert_nextline(" 6 ethernet eth_bootdev");
Simon Glass18552d22023-01-17 10:48:13 -0700367 ut_assert_nextline(" 1 simple_bus (none)");
Simon Glasseacc2612023-01-17 10:48:08 -0700368 ut_assert_nextline(" 5 ide ide_bootdev");
369 ut_assert_nextline(" 2 mmc mmc_bootdev");
370 ut_assert_nextline(" 4 nvme nvme_bootdev");
Simon Glass662cfa02023-01-28 15:00:28 -0700371 ut_assert_nextline(" 4 qfw qfw_bootdev");
Simon Glasseacc2612023-01-17 10:48:08 -0700372 ut_assert_nextline(" 4 scsi scsi_bootdev");
373 ut_assert_nextline(" 4 spi_flash sf_bootdev");
374 ut_assert_nextline(" 5 usb usb_bootdev");
375 ut_assert_nextline(" 4 virtio virtio_bootdev");
Simon Glass662cfa02023-01-28 15:00:28 -0700376 ut_assert_nextline("(total hunters: 10)");
Simon Glassbd90b092023-01-17 10:47:33 -0700377 ut_assert_console_end();
378
Simon Glass04fb2b62023-01-17 10:47:37 -0700379 ut_assertok(bootdev_hunt("usb1", false));
380 ut_assert_nextline(
381 "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found");
Simon Glassc7b63d52023-01-17 10:47:34 -0700382 ut_assert_console_end();
383
Simon Glass662cfa02023-01-28 15:00:28 -0700384 /* USB is 7th in the list, so bit 8 */
385 ut_asserteq(BIT(8), std->hunters_used);
Simon Glass04fb2b62023-01-17 10:47:37 -0700386
Simon Glassbd90b092023-01-17 10:47:33 -0700387 return 0;
388}
Simon Glassa6a80b32024-08-22 07:57:54 -0600389BOOTSTD_TEST(bootdev_test_hunter, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassbd90b092023-01-17 10:47:33 -0700390
391/* Check 'bootdev hunt' command */
392static int bootdev_test_cmd_hunt(struct unit_test_state *uts)
393{
394 struct bootstd_priv *std;
395
Simon Glass04fb2b62023-01-17 10:47:37 -0700396 test_set_skip_delays(true);
Simon Glassa3fab7d2024-09-01 16:26:16 -0600397 bootstd_reset_usb();
Simon Glass04fb2b62023-01-17 10:47:37 -0700398
Simon Glassbd90b092023-01-17 10:47:33 -0700399 /* get access to the used hunters */
400 ut_assertok(bootstd_get_priv(&std));
401
Simon Glassbd90b092023-01-17 10:47:33 -0700402 ut_assertok(run_command("bootdev hunt -l", 0));
403 ut_assert_nextline("Prio Used Uclass Hunter");
404 ut_assert_nextlinen("----");
Simon Glasseacc2612023-01-17 10:48:08 -0700405 ut_assert_nextline(" 6 ethernet eth_bootdev");
Simon Glass662cfa02023-01-28 15:00:28 -0700406 ut_assert_skip_to_line("(total hunters: 10)");
Simon Glasseacc2612023-01-17 10:48:08 -0700407 ut_assert_console_end();
408
409 /* Use the MMC hunter and see that it updates */
410 ut_assertok(run_command("bootdev hunt mmc", 0));
411 ut_assertok(run_command("bootdev hunt -l", 0));
412 ut_assert_skip_to_line(" 5 ide ide_bootdev");
413 ut_assert_nextline(" 2 * mmc mmc_bootdev");
Simon Glass662cfa02023-01-28 15:00:28 -0700414 ut_assert_skip_to_line("(total hunters: 10)");
Simon Glassbd90b092023-01-17 10:47:33 -0700415 ut_assert_console_end();
416
417 /* Scan all hunters */
Simon Glasse4b69482023-01-17 10:48:10 -0700418 test_set_eth_enable(false);
Simon Glasseacc2612023-01-17 10:48:08 -0700419 test_set_skip_delays(true);
Simon Glassbd90b092023-01-17 10:47:33 -0700420 ut_assertok(run_command("bootdev hunt", 0));
Simon Glass4146c822023-01-17 10:47:40 -0700421 ut_assert_nextline("Hunting with: ethernet");
Simon Glass18552d22023-01-17 10:48:13 -0700422
423 /* This is the extension feature which has no uclass at present */
424 ut_assert_nextline("Hunting with: simple_bus");
425 ut_assert_nextline("Found 2 extension board(s).");
Simon Glass0d77f8f2023-01-17 10:47:46 -0700426 ut_assert_nextline("Hunting with: ide");
Simon Glasseacc2612023-01-17 10:48:08 -0700427
428 /* mmc hunter has already been used so should not run again */
429
Simon Glass758c7062023-01-17 10:47:47 -0700430 ut_assert_nextline("Hunting with: nvme");
Simon Glass662cfa02023-01-28 15:00:28 -0700431 ut_assert_nextline("Hunting with: qfw");
Simon Glass8f090b62023-01-17 10:47:45 -0700432 ut_assert_nextline("Hunting with: scsi");
433 ut_assert_nextline("scanning bus for devices...");
Simon Glass0c1f4a92023-01-17 10:48:03 -0700434 ut_assert_skip_to_line("Hunting with: spi_flash");
435 ut_assert_nextline("Hunting with: usb");
Simon Glass04fb2b62023-01-17 10:47:37 -0700436 ut_assert_nextline(
437 "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found");
Simon Glass0c1f4a92023-01-17 10:48:03 -0700438 ut_assert_nextline("Hunting with: virtio");
Simon Glassbd90b092023-01-17 10:47:33 -0700439 ut_assert_console_end();
440
441 /* List available hunters */
442 ut_assertok(run_command("bootdev hunt -l", 0));
443 ut_assert_nextlinen("Prio");
444 ut_assert_nextlinen("----");
Simon Glasseacc2612023-01-17 10:48:08 -0700445 ut_assert_nextline(" 6 * ethernet eth_bootdev");
Simon Glass18552d22023-01-17 10:48:13 -0700446 ut_assert_nextline(" 1 * simple_bus (none)");
Simon Glasseacc2612023-01-17 10:48:08 -0700447 ut_assert_nextline(" 5 * ide ide_bootdev");
448 ut_assert_nextline(" 2 * mmc mmc_bootdev");
449 ut_assert_nextline(" 4 * nvme nvme_bootdev");
Simon Glass662cfa02023-01-28 15:00:28 -0700450 ut_assert_nextline(" 4 * qfw qfw_bootdev");
Simon Glasseacc2612023-01-17 10:48:08 -0700451 ut_assert_nextline(" 4 * scsi scsi_bootdev");
452 ut_assert_nextline(" 4 * spi_flash sf_bootdev");
453 ut_assert_nextline(" 5 * usb usb_bootdev");
454 ut_assert_nextline(" 4 * virtio virtio_bootdev");
Simon Glass662cfa02023-01-28 15:00:28 -0700455 ut_assert_nextline("(total hunters: 10)");
Simon Glassbd90b092023-01-17 10:47:33 -0700456 ut_assert_console_end();
457
Simon Glass18552d22023-01-17 10:48:13 -0700458 ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used);
Simon Glassbd90b092023-01-17 10:47:33 -0700459
460 return 0;
461}
Simon Glassa6a80b32024-08-22 07:57:54 -0600462BOOTSTD_TEST(bootdev_test_cmd_hunt, UTF_DM | UTF_SCAN_FDT | UTF_ETH_BOOTDEV |
463 UTF_CONSOLE);
Simon Glassf0e358f2023-01-17 10:47:42 -0700464
Simon Glass47aedc22023-01-17 10:48:14 -0700465/* Check searching for bootdevs using the hunters */
466static int bootdev_test_hunt_scan(struct unit_test_state *uts)
467{
468 struct bootflow_iter iter;
469 struct bootstd_priv *std;
470 struct bootflow bflow;
471
472 /* get access to the used hunters */
473 ut_assertok(bootstd_get_priv(&std));
474
475 ut_assertok(bootstd_test_drop_bootdev_order(uts));
Simon Glass4b7cb052023-01-17 10:48:16 -0700476 ut_assertok(bootflow_scan_first(NULL, NULL, &iter,
Simon Glass4f806f32023-02-22 12:17:03 -0700477 BOOTFLOWIF_SHOW | BOOTFLOWIF_HUNT |
478 BOOTFLOWIF_SKIP_GLOBAL, &bflow));
Simon Glass47aedc22023-01-17 10:48:14 -0700479 ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used);
480
481 return 0;
482}
Simon Glass725c4382024-08-22 07:57:48 -0600483BOOTSTD_TEST(bootdev_test_hunt_scan, UTF_DM | UTF_SCAN_FDT);
Simon Glass47aedc22023-01-17 10:48:14 -0700484
Simon Glassf0e358f2023-01-17 10:47:42 -0700485/* Check that only bootable partitions are processed */
486static int bootdev_test_bootable(struct unit_test_state *uts)
487{
488 struct bootflow_iter iter;
489 struct bootflow bflow;
490 struct udevice *blk;
491
492 memset(&iter, '\0', sizeof(iter));
493 memset(&bflow, '\0', sizeof(bflow));
494 iter.part = 0;
495 ut_assertok(uclass_get_device_by_name(UCLASS_BLK, "mmc1.blk", &blk));
496 iter.dev = blk;
497 ut_assertok(device_find_next_child(&iter.dev));
498 uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
499
500 /*
501 * initially we don't have any knowledge of which partitions are
502 * bootable, but mmc1 has two partitions, with the first one being
503 * bootable
504 */
505 iter.part = 2;
506 ut_asserteq(-EINVAL, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
507 ut_asserteq(0, iter.first_bootable);
508
509 /* scan with part == 0 to get the partition info */
510 iter.part = 0;
511 ut_asserteq(-ENOENT, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
512 ut_asserteq(1, iter.first_bootable);
513
514 /* now it will refuse to use non-bootable partitions */
515 iter.part = 2;
516 ut_asserteq(-EINVAL, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
517
518 return 0;
519}
Simon Glass725c4382024-08-22 07:57:48 -0600520BOOTSTD_TEST(bootdev_test_bootable, UTF_DM | UTF_SCAN_FDT);
Simon Glass79a7d4a2023-01-17 10:48:07 -0700521
522/* Check hunting for bootdev of a particular priority */
523static int bootdev_test_hunt_prio(struct unit_test_state *uts)
524{
Simon Glassa3fab7d2024-09-01 16:26:16 -0600525 bootstd_reset_usb();
Simon Glass79a7d4a2023-01-17 10:48:07 -0700526 test_set_skip_delays(true);
527
Simon Glasseacc2612023-01-17 10:48:08 -0700528 ut_assertok(bootdev_hunt_prio(BOOTDEVP_4_SCAN_FAST, false));
Simon Glass79a7d4a2023-01-17 10:48:07 -0700529 ut_assert_nextline("scanning bus for devices...");
530 ut_assert_skip_to_line(" Type: Hard Disk");
531 ut_assert_nextlinen(" Capacity:");
532 ut_assert_console_end();
533
534 /* now try a different priority, verbosely */
Simon Glasseacc2612023-01-17 10:48:08 -0700535 ut_assertok(bootdev_hunt_prio(BOOTDEVP_5_SCAN_SLOW, true));
Simon Glass79a7d4a2023-01-17 10:48:07 -0700536 ut_assert_nextline("Hunting with: ide");
Simon Glass79a7d4a2023-01-17 10:48:07 -0700537 ut_assert_nextline("Hunting with: usb");
538 ut_assert_nextline(
539 "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found");
540 ut_assert_console_end();
541
542 return 0;
543}
Simon Glassa6a80b32024-08-22 07:57:54 -0600544BOOTSTD_TEST(bootdev_test_hunt_prio, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glass66e3dce2023-01-17 10:48:09 -0700545
546/* Check hunting for bootdevs with a particular label */
547static int bootdev_test_hunt_label(struct unit_test_state *uts)
548{
549 struct udevice *dev, *old;
550 struct bootstd_priv *std;
551 int mflags;
552
Simon Glassa3fab7d2024-09-01 16:26:16 -0600553 bootstd_reset_usb();
Simon Glass8c29b732023-05-05 20:03:04 -0600554
Simon Glass66e3dce2023-01-17 10:48:09 -0700555 /* get access to the used hunters */
556 ut_assertok(bootstd_get_priv(&std));
557
558 /* scan an unknown uclass */
Simon Glass66e3dce2023-01-17 10:48:09 -0700559 old = (void *)&mflags; /* arbitrary pointer to check against dev */
560 dev = old;
561 mflags = 123;
Simon Glass1736b4a2023-04-24 13:49:47 +1200562 ut_asserteq(-EPFNOSUPPORT,
Simon Glass66e3dce2023-01-17 10:48:09 -0700563 bootdev_hunt_and_find_by_label("fred", &dev, &mflags));
Simon Glass66e3dce2023-01-17 10:48:09 -0700564 ut_asserteq_ptr(old, dev);
565 ut_asserteq(123, mflags);
566 ut_assert_console_end();
567 ut_asserteq(0, std->hunters_used);
568
569 /* scan an invalid mmc controllers */
570 ut_asserteq(-ENOENT,
571 bootdev_hunt_and_find_by_label("mmc4", &dev, &mflags));
572 ut_asserteq_ptr(old, dev);
573 ut_asserteq(123, mflags);
Simon Glass66e3dce2023-01-17 10:48:09 -0700574 ut_assert_console_end();
575
576 ut_assertok(bootstd_test_check_mmc_hunter(uts));
577
578 /* scan for a particular mmc controller */
579 ut_assertok(bootdev_hunt_and_find_by_label("mmc1", &dev, &mflags));
580 ut_assertnonnull(dev);
581 ut_asserteq_str("mmc1.bootdev", dev->name);
582 ut_asserteq(0, mflags);
583 ut_assert_console_end();
584
585 /* scan all of usb */
586 test_set_skip_delays(true);
587 ut_assertok(bootdev_hunt_and_find_by_label("usb", &dev, &mflags));
588 ut_assertnonnull(dev);
589 ut_asserteq_str("usb_mass_storage.lun0.bootdev", dev->name);
590 ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags);
591 ut_assert_nextlinen("Bus usb@1: scanning bus usb@1");
592 ut_assert_console_end();
593
594 return 0;
595}
Simon Glassa6a80b32024-08-22 07:57:54 -0600596BOOTSTD_TEST(bootdev_test_hunt_label, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glasse4b69482023-01-17 10:48:10 -0700597
598/* Check iterating to the next label in a list */
599static int bootdev_test_next_label(struct unit_test_state *uts)
600{
601 const char *const labels[] = {"mmc0", "scsi", "dhcp", "pxe", NULL};
602 struct bootflow_iter iter;
603 struct bootstd_priv *std;
604 struct bootflow bflow;
605 struct udevice *dev;
606 int mflags;
607
608 test_set_eth_enable(false);
609
610 /* get access to the used hunters */
611 ut_assertok(bootstd_get_priv(&std));
612
613 memset(&iter, '\0', sizeof(iter));
614 memset(&bflow, '\0', sizeof(bflow));
615 iter.part = 0;
616 uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
617 iter.cur_label = -1;
618 iter.labels = labels;
619
620 dev = NULL;
621 mflags = 123;
622 ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
Simon Glasse4b69482023-01-17 10:48:10 -0700623 ut_assert_console_end();
624 ut_assertnonnull(dev);
625 ut_asserteq_str("mmc0.bootdev", dev->name);
626 ut_asserteq(0, mflags);
627
628 ut_assertok(bootstd_test_check_mmc_hunter(uts));
629
630 ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
631 ut_assert_nextline("scanning bus for devices...");
632 ut_assert_skip_to_line(
Julius Lehmann5f7c06b2024-10-26 20:06:44 +0200633 " Capacity: 2.0 MB = 0.0 GB (4096 x 512)");
Simon Glasse4b69482023-01-17 10:48:10 -0700634 ut_assert_console_end();
635 ut_assertnonnull(dev);
636 ut_asserteq_str("scsi.id0lun0.bootdev", dev->name);
637 ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags);
638
Simon Glass662cfa02023-01-28 15:00:28 -0700639 /* SCSI is 7th in the list, so bit 6 */
640 ut_asserteq(BIT(MMC_HUNTER) | BIT(6), std->hunters_used);
Simon Glasse4b69482023-01-17 10:48:10 -0700641
642 ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
643 ut_assert_console_end();
644 ut_assertnonnull(dev);
645 ut_asserteq_str("eth@10002000.bootdev", dev->name);
646 ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY,
647 mflags);
648
649 /* dhcp: Ethernet is first so bit 0 */
Simon Glass662cfa02023-01-28 15:00:28 -0700650 ut_asserteq(BIT(MMC_HUNTER) | BIT(6) | BIT(0), std->hunters_used);
Simon Glasse4b69482023-01-17 10:48:10 -0700651
652 ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
653 ut_assert_console_end();
654 ut_assertnonnull(dev);
655 ut_asserteq_str("eth@10002000.bootdev", dev->name);
656 ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
657 mflags);
658
659 /* pxe: Ethernet is first so bit 0 */
Simon Glass662cfa02023-01-28 15:00:28 -0700660 ut_asserteq(BIT(MMC_HUNTER) | BIT(6) | BIT(0), std->hunters_used);
Simon Glasse4b69482023-01-17 10:48:10 -0700661
662 mflags = 123;
663 ut_asserteq(-ENODEV, bootdev_next_label(&iter, &dev, &mflags));
664 ut_asserteq(123, mflags);
665 ut_assert_console_end();
666
667 /* no change */
Simon Glass662cfa02023-01-28 15:00:28 -0700668 ut_asserteq(BIT(MMC_HUNTER) | BIT(6) | BIT(0), std->hunters_used);
Simon Glasse4b69482023-01-17 10:48:10 -0700669
670 return 0;
671}
Simon Glass725c4382024-08-22 07:57:48 -0600672BOOTSTD_TEST(bootdev_test_next_label, UTF_DM | UTF_SCAN_FDT | UTF_ETH_BOOTDEV |
Simon Glassa6a80b32024-08-22 07:57:54 -0600673 UTF_SF_BOOTDEV | UTF_CONSOLE);
Simon Glass43e89a32023-01-17 10:48:11 -0700674
Simon Glass43e89a32023-01-17 10:48:11 -0700675/* Check iterating to the next prioirty in a list */
676static int bootdev_test_next_prio(struct unit_test_state *uts)
677{
678 struct bootflow_iter iter;
679 struct bootstd_priv *std;
680 struct bootflow bflow;
681 struct udevice *dev;
682 int ret;
683
Simon Glass91943ff2023-01-17 10:48:15 -0700684 test_set_eth_enable(false);
Simon Glass43e89a32023-01-17 10:48:11 -0700685 test_set_skip_delays(true);
686
687 /* get access to the used hunters */
688 ut_assertok(bootstd_get_priv(&std));
689
690 memset(&iter, '\0', sizeof(iter));
691 memset(&bflow, '\0', sizeof(bflow));
692 iter.part = 0;
693 uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
694 iter.cur_prio = 0;
Simon Glass4f806f32023-02-22 12:17:03 -0700695 iter.flags = BOOTFLOWIF_SHOW;
Simon Glass43e89a32023-01-17 10:48:11 -0700696
697 dev = NULL;
Simon Glass43e89a32023-01-17 10:48:11 -0700698 ut_assertok(bootdev_next_prio(&iter, &dev));
699 ut_assertnonnull(dev);
700 ut_asserteq_str("mmc2.bootdev", dev->name);
701
702 /* hunt flag not set, so this should not use any hunters */
703 ut_asserteq(0, std->hunters_used);
704 ut_assert_console_end();
705
706 /* now try again with hunting enabled */
Simon Glass4f806f32023-02-22 12:17:03 -0700707 iter.flags = BOOTFLOWIF_SHOW | BOOTFLOWIF_HUNT;
Simon Glass43e89a32023-01-17 10:48:11 -0700708 iter.cur_prio = 0;
709 iter.part = 0;
710
711 ut_assertok(bootdev_next_prio(&iter, &dev));
712 ut_asserteq_str("mmc2.bootdev", dev->name);
Simon Glass18552d22023-01-17 10:48:13 -0700713 ut_assert_nextline("Hunting with: simple_bus");
714 ut_assert_nextline("Found 2 extension board(s).");
Simon Glass43e89a32023-01-17 10:48:11 -0700715 ut_assert_nextline("Hunting with: mmc");
716 ut_assert_console_end();
717
Simon Glass18552d22023-01-17 10:48:13 -0700718 ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used);
Simon Glass43e89a32023-01-17 10:48:11 -0700719
720 ut_assertok(bootdev_next_prio(&iter, &dev));
721 ut_asserteq_str("mmc1.bootdev", dev->name);
722
723 ut_assertok(bootdev_next_prio(&iter, &dev));
724 ut_asserteq_str("mmc0.bootdev", dev->name);
725 ut_assert_console_end();
726
727 ut_assertok(bootdev_next_prio(&iter, &dev));
728 ut_asserteq_str("spi.bin@0.bootdev", dev->name);
729 ut_assert_skip_to_line("Hunting with: spi_flash");
730
731 /*
732 * this scans all bootdevs of priority BOOTDEVP_4_SCAN_FAST before it
733 * starts looking at the devices, so we se virtio as well
734 */
735 ut_assert_nextline("Hunting with: virtio");
736 ut_assert_nextlinen("SF: Detected m25p16");
737
738 ut_assertok(bootdev_next_prio(&iter, &dev));
739 ut_asserteq_str("spi.bin@1.bootdev", dev->name);
740 ut_assert_nextlinen("SF: Detected m25p16");
741 ut_assert_console_end();
742
743 /* keep going until there are no more bootdevs */
744 do {
745 ret = bootdev_next_prio(&iter, &dev);
746 } while (!ret);
747 ut_asserteq(-ENODEV, ret);
748 ut_assertnull(dev);
Simon Glass18552d22023-01-17 10:48:13 -0700749 ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used);
Simon Glass43e89a32023-01-17 10:48:11 -0700750
751 ut_assert_skip_to_line("Hunting with: ethernet");
752 ut_assert_console_end();
753
754 return 0;
755}
Simon Glassa6a80b32024-08-22 07:57:54 -0600756BOOTSTD_TEST(bootdev_test_next_prio, UTF_DM | UTF_SCAN_FDT | UTF_SF_BOOTDEV |
757 UTF_CONSOLE);