blob: 8c44afd929710845737eae75b5bbee139ec908ab [file] [log] [blame]
Simon Glassb255efc2022-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 Glassb255efc2022-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 Glassb255efc2022-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 Glassb255efc2022-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 Glassf0425022024-08-22 07:57:54 -060044BOOTSTD_TEST(bootdev_test_cmd_list, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassb255efc2022-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 Glassb255efc2022-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 Glassf0425022024-08-22 07:57:54 -060093BOOTSTD_TEST(bootdev_test_cmd_select, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassb255efc2022-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 Glasse22fe922023-01-17 10:48:05 -070099 int mflags = 0;
Simon Glassb255efc2022-04-24 23:31:24 -0600100
Simon Glasse22fe922023-01-17 10:48:05 -0700101 ut_assertok(bootdev_find_by_label("mmc2", &dev, &mflags));
Simon Glassb255efc2022-04-24 23:31:24 -0600102 ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev));
Simon Glasse22fe922023-01-17 10:48:05 -0700103 ut_asserteq(0, mflags);
Simon Glassb255efc2022-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 Glasse22fe922023-01-17 10:48:05 -0700108 /* Check method flags */
109 ut_assertok(bootdev_find_by_label("pxe", &dev, &mflags));
Simon Glassde567b12023-01-17 10:48:09 -0700110 ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
111 mflags);
Simon Glasse22fe922023-01-17 10:48:05 -0700112 ut_assertok(bootdev_find_by_label("dhcp", &dev, &mflags));
Simon Glassde567b12023-01-17 10:48:09 -0700113 ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY,
114 mflags);
Simon Glasse22fe922023-01-17 10:48:05 -0700115
Simon Glassb255efc2022-04-24 23:31:24 -0600116 /* Check invalid uclass */
Simon Glass4108c6b2023-04-24 13:49:47 +1200117 ut_asserteq(-EPFNOSUPPORT,
118 bootdev_find_by_label("fred0", &dev, &mflags));
Simon Glassb255efc2022-04-24 23:31:24 -0600119
120 /* Check unknown sequence number */
Simon Glasse22fe922023-01-17 10:48:05 -0700121 ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev, &mflags));
Simon Glassb255efc2022-04-24 23:31:24 -0600122
123 return 0;
124}
Simon Glass1a92f832024-08-22 07:57:48 -0600125BOOTSTD_TEST(bootdev_test_labels, UTF_DM | UTF_SCAN_FDT | UTF_ETH_BOOTDEV);
Simon Glassb255efc2022-04-24 23:31:24 -0600126
Simon Glassde567b12023-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 Forissier70ff9942024-10-16 11:56:25 +0200131 char *seq;
Simon Glassde567b12023-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 Forissier70ff9942024-10-16 11:56:25 +0200151 *
152 * However if DSA_SANDBOX is disabled the dsa-test@{0,1} devices
153 * are not there.
Simon Glassde567b12023-01-17 10:48:09 -0700154 */
Jerome Forissier70ff9942024-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 Glassde567b12023-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 Glass4108c6b2023-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 Glassde567b12023-01-17 10:48:09 -0700182 ut_asserteq(123, mflags);
183 ut_assert_console_end();
184
185 return 0;
186}
Simon Glassf0425022024-08-22 07:57:54 -0600187BOOTSTD_TEST(bootdev_test_any, UTF_DM | UTF_SCAN_FDT | UTF_ETH_BOOTDEV |
188 UTF_CONSOLE);
Simon Glassde567b12023-01-17 10:48:09 -0700189
Simon Glassfd5a5192023-10-23 00:02:11 -0700190/*
191 * Check bootdev ordering with the bootdev-order property and boot_targets
192 * environment variable
193 */
Simon Glassb255efc2022-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 Glassfd5a5192023-10-23 00:02:11 -0700199 test_set_skip_delays(true);
200
201 /* Start up USB which gives us three additional bootdevs */
Simon Glass22c93da2024-09-01 16:26:16 -0600202 bootstd_reset_usb();
Simon Glassfd5a5192023-10-23 00:02:11 -0700203 ut_assertok(run_command("usb start", 0));
204
Simon Glassb255efc2022-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 Glass5d3d44f2023-01-17 10:48:16 -0700215 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
Simon Glassb255efc2022-04-24 23:31:24 -0600216 ut_asserteq(2, iter.num_devs);
Simon Glasscb2a5cd2023-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 Glassb255efc2022-04-24 23:31:24 -0600219 bootflow_iter_uninit(&iter);
220
221 /* Use the environment variable to override it */
Simon Glassfd5a5192023-10-23 00:02:11 -0700222 ut_assertok(env_set("boot_targets", "mmc1 mmc2 usb"));
Simon Glass5d3d44f2023-01-17 10:48:16 -0700223 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
Simon Glass64c63252024-11-07 14:31:49 -0700224
225 /* get the usb device which has a backing file (flash1.img) */
226 ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
227
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700228 ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
Simon Glassb51f01d2023-10-23 00:02:13 -0700229 ut_asserteq(5, iter.num_devs);
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700230 ut_asserteq_str("mmc1.bootdev", iter.dev_used[0]->name);
231 ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name);
Simon Glassfd5a5192023-10-23 00:02:11 -0700232 ut_asserteq_str("usb_mass_storage.lun0.bootdev",
233 iter.dev_used[2]->name);
Simon Glassb255efc2022-04-24 23:31:24 -0600234 bootflow_iter_uninit(&iter);
235
Simon Glass33795a92023-10-23 00:02:12 -0700236 /* Try a single uclass */
237 ut_assertok(env_set("boot_targets", NULL));
238 ut_assertok(bootflow_scan_first(NULL, "mmc", &iter, 0, &bflow));
239 ut_asserteq(2, iter.num_devs);
240
Simon Glassb51f01d2023-10-23 00:02:13 -0700241 /* Now scan past mmc1 and make sure that only mmc0 shows up */
242 ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
243 ut_asserteq(3, iter.num_devs);
244 ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
245 ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
246 ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
247 bootflow_iter_uninit(&iter);
248
249 /* Try a single uclass with boot_targets */
250 ut_assertok(env_set("boot_targets", "mmc"));
251 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
252 ut_asserteq(2, iter.num_devs);
253
254 /* Now scan past mmc1 and make sure that only mmc0 shows up */
Simon Glass33795a92023-10-23 00:02:12 -0700255 ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
256 ut_asserteq(3, iter.num_devs);
257 ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
258 ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
259 ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
260 bootflow_iter_uninit(&iter);
261
Simon Glassb51f01d2023-10-23 00:02:13 -0700262 /* Try a single uclass with boot_targets */
263 ut_assertok(env_set("boot_targets", "mmc usb"));
264 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
265 ut_asserteq(2, iter.num_devs);
266
Simon Glass64c63252024-11-07 14:31:49 -0700267 /*
268 * Now scan past mmc1 and make sure that the 3 USB devices show up. The
269 * first one has a backing file so returns success
270 */
271 ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
Simon Glassb51f01d2023-10-23 00:02:13 -0700272 ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
273 ut_asserteq(6, iter.num_devs);
274 ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
275 ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
276 ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
277 ut_asserteq_str("usb_mass_storage.lun0.bootdev",
278 iter.dev_used[3]->name);
279 bootflow_iter_uninit(&iter);
280
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700281 return 0;
282}
Simon Glass1a92f832024-08-22 07:57:48 -0600283BOOTSTD_TEST(bootdev_test_order, UTF_DM | UTF_SCAN_FDT);
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700284
285/* Check default bootdev ordering */
286static int bootdev_test_order_default(struct unit_test_state *uts)
287{
288 struct bootflow_iter iter;
289 struct bootflow bflow;
290
Simon Glassb255efc2022-04-24 23:31:24 -0600291 /*
292 * Now drop both orderings, to check the default (prioriy/sequence)
293 * ordering
294 */
295 ut_assertok(env_set("boot_targets", NULL));
296 ut_assertok(bootstd_test_drop_bootdev_order(uts));
297
Simon Glass5d3d44f2023-01-17 10:48:16 -0700298 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700299 ut_asserteq(2, iter.num_devs);
300 ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
301 ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
Simon Glassb255efc2022-04-24 23:31:24 -0600302
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700303 ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
Simon Glassb255efc2022-04-24 23:31:24 -0600304 ut_asserteq(3, iter.num_devs);
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700305 ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
Simon Glassb255efc2022-04-24 23:31:24 -0600306 bootflow_iter_uninit(&iter);
307
308 return 0;
309}
Simon Glass1a92f832024-08-22 07:57:48 -0600310BOOTSTD_TEST(bootdev_test_order_default, UTF_DM | UTF_SCAN_FDT);
Simon Glassb255efc2022-04-24 23:31:24 -0600311
312/* Check bootdev ordering with the uclass priority */
313static int bootdev_test_prio(struct unit_test_state *uts)
314{
315 struct bootdev_uc_plat *ucp;
316 struct bootflow_iter iter;
317 struct bootflow bflow;
318 struct udevice *blk;
319
Simon Glassf3cb89f2023-01-17 10:47:37 -0700320 test_set_skip_delays(true);
321
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700322 /* disable ethernet since the hunter will run dhcp */
323 test_set_eth_enable(false);
324
Simon Glassb255efc2022-04-24 23:31:24 -0600325 /* Start up USB which gives us three additional bootdevs */
Simon Glass22c93da2024-09-01 16:26:16 -0600326 bootstd_reset_usb();
Simon Glassb255efc2022-04-24 23:31:24 -0600327 ut_assertok(run_command("usb start", 0));
328
329 ut_assertok(bootstd_test_drop_bootdev_order(uts));
330
331 /* 3 MMC and 3 USB bootdevs: MMC should come before USB */
Simon Glass5d3d44f2023-01-17 10:48:16 -0700332 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
Simon Glass64c63252024-11-07 14:31:49 -0700333
334 /* get the usb device which has a backing file (flash1.img) */
335 ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
336
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700337 ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
Simon Glassb255efc2022-04-24 23:31:24 -0600338 ut_asserteq(6, iter.num_devs);
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700339 ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
Simon Glassb255efc2022-04-24 23:31:24 -0600340 ut_asserteq_str("usb_mass_storage.lun0.bootdev",
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700341 iter.dev_used[3]->name);
Simon Glassb255efc2022-04-24 23:31:24 -0600342
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700343 ut_assertok(bootdev_get_sibling_blk(iter.dev_used[3], &blk));
Simon Glassb255efc2022-04-24 23:31:24 -0600344 ut_asserteq_str("usb_mass_storage.lun0", blk->name);
345
346 /* adjust the priority of the first USB bootdev to the highest */
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700347 ucp = dev_get_uclass_plat(iter.dev_used[3]);
348 ucp->prio = BOOTDEVP_1_PRE_SCAN;
Simon Glassb255efc2022-04-24 23:31:24 -0600349
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700350 /* try again but enable hunting, which brings in SCSI */
Simon Glassb255efc2022-04-24 23:31:24 -0600351 bootflow_iter_uninit(&iter);
Simon Glass99e68182023-02-22 12:17:03 -0700352 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, BOOTFLOWIF_HUNT,
Simon Glass5d3d44f2023-01-17 10:48:16 -0700353 &bflow));
Simon Glass64c63252024-11-07 14:31:49 -0700354
355 /* get the usb device which has a backing file (flash1.img) */
356 ut_asserteq(0, bootflow_scan_next(&iter, &bflow));
357
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700358 ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
359 ut_asserteq(7, iter.num_devs);
Simon Glassb255efc2022-04-24 23:31:24 -0600360 ut_asserteq_str("usb_mass_storage.lun0.bootdev",
Simon Glasscb2a5cd2023-01-17 10:48:17 -0700361 iter.dev_used[0]->name);
362 ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name);
Simon Glassb255efc2022-04-24 23:31:24 -0600363
364 return 0;
365}
Simon Glass1a92f832024-08-22 07:57:48 -0600366BOOTSTD_TEST(bootdev_test_prio, UTF_DM | UTF_SCAN_FDT);
Simon Glass5acb97a2023-01-17 10:47:33 -0700367
368/* Check listing hunters */
369static int bootdev_test_hunter(struct unit_test_state *uts)
370{
371 struct bootstd_priv *std;
372
Simon Glass22c93da2024-09-01 16:26:16 -0600373 bootstd_reset_usb();
Simon Glassf3cb89f2023-01-17 10:47:37 -0700374 test_set_skip_delays(true);
375
Simon Glass5acb97a2023-01-17 10:47:33 -0700376 /* get access to the used hunters */
377 ut_assertok(bootstd_get_priv(&std));
378
Simon Glass5acb97a2023-01-17 10:47:33 -0700379 bootdev_list_hunters(std);
380 ut_assert_nextline("Prio Used Uclass Hunter");
381 ut_assert_nextlinen("----");
Simon Glass7e1f6a42023-01-17 10:48:08 -0700382 ut_assert_nextline(" 6 ethernet eth_bootdev");
Simon Glasse4cf1062023-01-17 10:48:13 -0700383 ut_assert_nextline(" 1 simple_bus (none)");
Simon Glass7e1f6a42023-01-17 10:48:08 -0700384 ut_assert_nextline(" 5 ide ide_bootdev");
385 ut_assert_nextline(" 2 mmc mmc_bootdev");
386 ut_assert_nextline(" 4 nvme nvme_bootdev");
Simon Glassdeffa692023-01-28 15:00:28 -0700387 ut_assert_nextline(" 4 qfw qfw_bootdev");
Simon Glass7e1f6a42023-01-17 10:48:08 -0700388 ut_assert_nextline(" 4 scsi scsi_bootdev");
389 ut_assert_nextline(" 4 spi_flash sf_bootdev");
390 ut_assert_nextline(" 5 usb usb_bootdev");
391 ut_assert_nextline(" 4 virtio virtio_bootdev");
Simon Glassdeffa692023-01-28 15:00:28 -0700392 ut_assert_nextline("(total hunters: 10)");
Simon Glass5acb97a2023-01-17 10:47:33 -0700393 ut_assert_console_end();
394
Simon Glassf3cb89f2023-01-17 10:47:37 -0700395 ut_assertok(bootdev_hunt("usb1", false));
396 ut_assert_nextline(
397 "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found");
Simon Glass1248d2b2023-01-17 10:47:34 -0700398 ut_assert_console_end();
399
Simon Glassdeffa692023-01-28 15:00:28 -0700400 /* USB is 7th in the list, so bit 8 */
401 ut_asserteq(BIT(8), std->hunters_used);
Simon Glassf3cb89f2023-01-17 10:47:37 -0700402
Simon Glass5acb97a2023-01-17 10:47:33 -0700403 return 0;
404}
Simon Glassf0425022024-08-22 07:57:54 -0600405BOOTSTD_TEST(bootdev_test_hunter, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glass5acb97a2023-01-17 10:47:33 -0700406
407/* Check 'bootdev hunt' command */
408static int bootdev_test_cmd_hunt(struct unit_test_state *uts)
409{
410 struct bootstd_priv *std;
411
Simon Glassf3cb89f2023-01-17 10:47:37 -0700412 test_set_skip_delays(true);
Simon Glass22c93da2024-09-01 16:26:16 -0600413 bootstd_reset_usb();
Simon Glassf3cb89f2023-01-17 10:47:37 -0700414
Simon Glass5acb97a2023-01-17 10:47:33 -0700415 /* get access to the used hunters */
416 ut_assertok(bootstd_get_priv(&std));
417
Simon Glass5acb97a2023-01-17 10:47:33 -0700418 ut_assertok(run_command("bootdev hunt -l", 0));
419 ut_assert_nextline("Prio Used Uclass Hunter");
420 ut_assert_nextlinen("----");
Simon Glass7e1f6a42023-01-17 10:48:08 -0700421 ut_assert_nextline(" 6 ethernet eth_bootdev");
Simon Glassdeffa692023-01-28 15:00:28 -0700422 ut_assert_skip_to_line("(total hunters: 10)");
Simon Glass5acb97a2023-01-17 10:47:33 -0700423 ut_assert_console_end();
424
Simon Glass7e1f6a42023-01-17 10:48:08 -0700425 /* Use the MMC hunter and see that it updates */
426 ut_assertok(run_command("bootdev hunt mmc", 0));
427 ut_assertok(run_command("bootdev hunt -l", 0));
428 ut_assert_skip_to_line(" 5 ide ide_bootdev");
429 ut_assert_nextline(" 2 * mmc mmc_bootdev");
Simon Glassdeffa692023-01-28 15:00:28 -0700430 ut_assert_skip_to_line("(total hunters: 10)");
Simon Glass7e1f6a42023-01-17 10:48:08 -0700431 ut_assert_console_end();
432
Simon Glass5acb97a2023-01-17 10:47:33 -0700433 /* Scan all hunters */
Simon Glassac06b26a2023-01-17 10:48:10 -0700434 test_set_eth_enable(false);
Simon Glass7e1f6a42023-01-17 10:48:08 -0700435 test_set_skip_delays(true);
Simon Glass5acb97a2023-01-17 10:47:33 -0700436 ut_assertok(run_command("bootdev hunt", 0));
Simon Glass5ea0a8d2023-01-17 10:47:40 -0700437 ut_assert_nextline("Hunting with: ethernet");
Simon Glasse4cf1062023-01-17 10:48:13 -0700438
439 /* This is the extension feature which has no uclass at present */
440 ut_assert_nextline("Hunting with: simple_bus");
441 ut_assert_nextline("Found 2 extension board(s).");
Simon Glassbe7c6662023-01-17 10:47:46 -0700442 ut_assert_nextline("Hunting with: ide");
Simon Glass7e1f6a42023-01-17 10:48:08 -0700443
444 /* mmc hunter has already been used so should not run again */
445
Simon Glass08382872023-01-17 10:47:47 -0700446 ut_assert_nextline("Hunting with: nvme");
Simon Glassdeffa692023-01-28 15:00:28 -0700447 ut_assert_nextline("Hunting with: qfw");
Simon Glass9985e9c2023-01-17 10:47:45 -0700448 ut_assert_nextline("Hunting with: scsi");
449 ut_assert_nextline("scanning bus for devices...");
Simon Glass215be682023-01-17 10:48:03 -0700450 ut_assert_skip_to_line("Hunting with: spi_flash");
451 ut_assert_nextline("Hunting with: usb");
Simon Glassf3cb89f2023-01-17 10:47:37 -0700452 ut_assert_nextline(
453 "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found");
Simon Glass215be682023-01-17 10:48:03 -0700454 ut_assert_nextline("Hunting with: virtio");
Simon Glass5acb97a2023-01-17 10:47:33 -0700455 ut_assert_console_end();
456
457 /* List available hunters */
458 ut_assertok(run_command("bootdev hunt -l", 0));
459 ut_assert_nextlinen("Prio");
460 ut_assert_nextlinen("----");
Simon Glass7e1f6a42023-01-17 10:48:08 -0700461 ut_assert_nextline(" 6 * ethernet eth_bootdev");
Simon Glasse4cf1062023-01-17 10:48:13 -0700462 ut_assert_nextline(" 1 * simple_bus (none)");
Simon Glass7e1f6a42023-01-17 10:48:08 -0700463 ut_assert_nextline(" 5 * ide ide_bootdev");
464 ut_assert_nextline(" 2 * mmc mmc_bootdev");
465 ut_assert_nextline(" 4 * nvme nvme_bootdev");
Simon Glassdeffa692023-01-28 15:00:28 -0700466 ut_assert_nextline(" 4 * qfw qfw_bootdev");
Simon Glass7e1f6a42023-01-17 10:48:08 -0700467 ut_assert_nextline(" 4 * scsi scsi_bootdev");
468 ut_assert_nextline(" 4 * spi_flash sf_bootdev");
469 ut_assert_nextline(" 5 * usb usb_bootdev");
470 ut_assert_nextline(" 4 * virtio virtio_bootdev");
Simon Glassdeffa692023-01-28 15:00:28 -0700471 ut_assert_nextline("(total hunters: 10)");
Simon Glass5acb97a2023-01-17 10:47:33 -0700472 ut_assert_console_end();
473
Simon Glasse4cf1062023-01-17 10:48:13 -0700474 ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used);
Simon Glass5acb97a2023-01-17 10:47:33 -0700475
476 return 0;
477}
Simon Glassf0425022024-08-22 07:57:54 -0600478BOOTSTD_TEST(bootdev_test_cmd_hunt, UTF_DM | UTF_SCAN_FDT | UTF_ETH_BOOTDEV |
479 UTF_CONSOLE);
Simon Glass64cbc5c2023-01-17 10:47:42 -0700480
Simon Glass484e4072023-01-17 10:48:14 -0700481/* Check searching for bootdevs using the hunters */
482static int bootdev_test_hunt_scan(struct unit_test_state *uts)
483{
484 struct bootflow_iter iter;
485 struct bootstd_priv *std;
486 struct bootflow bflow;
487
488 /* get access to the used hunters */
489 ut_assertok(bootstd_get_priv(&std));
490
491 ut_assertok(bootstd_test_drop_bootdev_order(uts));
Simon Glass5d3d44f2023-01-17 10:48:16 -0700492 ut_assertok(bootflow_scan_first(NULL, NULL, &iter,
Simon Glass99e68182023-02-22 12:17:03 -0700493 BOOTFLOWIF_SHOW | BOOTFLOWIF_HUNT |
494 BOOTFLOWIF_SKIP_GLOBAL, &bflow));
Simon Glass484e4072023-01-17 10:48:14 -0700495 ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used);
496
497 return 0;
498}
Simon Glass1a92f832024-08-22 07:57:48 -0600499BOOTSTD_TEST(bootdev_test_hunt_scan, UTF_DM | UTF_SCAN_FDT);
Simon Glass484e4072023-01-17 10:48:14 -0700500
Simon Glass64cbc5c2023-01-17 10:47:42 -0700501/* Check that only bootable partitions are processed */
502static int bootdev_test_bootable(struct unit_test_state *uts)
503{
504 struct bootflow_iter iter;
505 struct bootflow bflow;
506 struct udevice *blk;
507
508 memset(&iter, '\0', sizeof(iter));
509 memset(&bflow, '\0', sizeof(bflow));
510 iter.part = 0;
511 ut_assertok(uclass_get_device_by_name(UCLASS_BLK, "mmc1.blk", &blk));
512 iter.dev = blk;
513 ut_assertok(device_find_next_child(&iter.dev));
514 uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
515
516 /*
517 * initially we don't have any knowledge of which partitions are
518 * bootable, but mmc1 has two partitions, with the first one being
519 * bootable
520 */
521 iter.part = 2;
522 ut_asserteq(-EINVAL, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
523 ut_asserteq(0, iter.first_bootable);
524
525 /* scan with part == 0 to get the partition info */
526 iter.part = 0;
527 ut_asserteq(-ENOENT, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
528 ut_asserteq(1, iter.first_bootable);
529
530 /* now it will refuse to use non-bootable partitions */
531 iter.part = 2;
532 ut_asserteq(-EINVAL, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow));
533
534 return 0;
535}
Simon Glass1a92f832024-08-22 07:57:48 -0600536BOOTSTD_TEST(bootdev_test_bootable, UTF_DM | UTF_SCAN_FDT);
Simon Glass3e9f6be2023-01-17 10:48:07 -0700537
538/* Check hunting for bootdev of a particular priority */
539static int bootdev_test_hunt_prio(struct unit_test_state *uts)
540{
Simon Glass22c93da2024-09-01 16:26:16 -0600541 bootstd_reset_usb();
Simon Glass3e9f6be2023-01-17 10:48:07 -0700542 test_set_skip_delays(true);
543
Simon Glass7e1f6a42023-01-17 10:48:08 -0700544 ut_assertok(bootdev_hunt_prio(BOOTDEVP_4_SCAN_FAST, false));
Simon Glass3e9f6be2023-01-17 10:48:07 -0700545 ut_assert_nextline("scanning bus for devices...");
546 ut_assert_skip_to_line(" Type: Hard Disk");
547 ut_assert_nextlinen(" Capacity:");
548 ut_assert_console_end();
549
550 /* now try a different priority, verbosely */
Simon Glass7e1f6a42023-01-17 10:48:08 -0700551 ut_assertok(bootdev_hunt_prio(BOOTDEVP_5_SCAN_SLOW, true));
Simon Glass3e9f6be2023-01-17 10:48:07 -0700552 ut_assert_nextline("Hunting with: ide");
Simon Glass3e9f6be2023-01-17 10:48:07 -0700553 ut_assert_nextline("Hunting with: usb");
554 ut_assert_nextline(
555 "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found");
556 ut_assert_console_end();
557
558 return 0;
559}
Simon Glassf0425022024-08-22 07:57:54 -0600560BOOTSTD_TEST(bootdev_test_hunt_prio, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassde567b12023-01-17 10:48:09 -0700561
562/* Check hunting for bootdevs with a particular label */
563static int bootdev_test_hunt_label(struct unit_test_state *uts)
564{
565 struct udevice *dev, *old;
566 struct bootstd_priv *std;
567 int mflags;
568
Simon Glass22c93da2024-09-01 16:26:16 -0600569 bootstd_reset_usb();
Simon Glass4bb7c162023-05-05 20:03:04 -0600570
Simon Glassde567b12023-01-17 10:48:09 -0700571 /* get access to the used hunters */
572 ut_assertok(bootstd_get_priv(&std));
573
574 /* scan an unknown uclass */
Simon Glassde567b12023-01-17 10:48:09 -0700575 old = (void *)&mflags; /* arbitrary pointer to check against dev */
576 dev = old;
577 mflags = 123;
Simon Glass4108c6b2023-04-24 13:49:47 +1200578 ut_asserteq(-EPFNOSUPPORT,
Simon Glassde567b12023-01-17 10:48:09 -0700579 bootdev_hunt_and_find_by_label("fred", &dev, &mflags));
Simon Glassde567b12023-01-17 10:48:09 -0700580 ut_asserteq_ptr(old, dev);
581 ut_asserteq(123, mflags);
582 ut_assert_console_end();
583 ut_asserteq(0, std->hunters_used);
584
585 /* scan an invalid mmc controllers */
586 ut_asserteq(-ENOENT,
587 bootdev_hunt_and_find_by_label("mmc4", &dev, &mflags));
588 ut_asserteq_ptr(old, dev);
589 ut_asserteq(123, mflags);
Simon Glassde567b12023-01-17 10:48:09 -0700590 ut_assert_console_end();
591
592 ut_assertok(bootstd_test_check_mmc_hunter(uts));
593
594 /* scan for a particular mmc controller */
595 ut_assertok(bootdev_hunt_and_find_by_label("mmc1", &dev, &mflags));
596 ut_assertnonnull(dev);
597 ut_asserteq_str("mmc1.bootdev", dev->name);
598 ut_asserteq(0, mflags);
599 ut_assert_console_end();
600
601 /* scan all of usb */
602 test_set_skip_delays(true);
603 ut_assertok(bootdev_hunt_and_find_by_label("usb", &dev, &mflags));
604 ut_assertnonnull(dev);
605 ut_asserteq_str("usb_mass_storage.lun0.bootdev", dev->name);
606 ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags);
607 ut_assert_nextlinen("Bus usb@1: scanning bus usb@1");
608 ut_assert_console_end();
609
610 return 0;
611}
Simon Glassf0425022024-08-22 07:57:54 -0600612BOOTSTD_TEST(bootdev_test_hunt_label, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
Simon Glassac06b26a2023-01-17 10:48:10 -0700613
614/* Check iterating to the next label in a list */
615static int bootdev_test_next_label(struct unit_test_state *uts)
616{
617 const char *const labels[] = {"mmc0", "scsi", "dhcp", "pxe", NULL};
618 struct bootflow_iter iter;
619 struct bootstd_priv *std;
620 struct bootflow bflow;
621 struct udevice *dev;
622 int mflags;
623
624 test_set_eth_enable(false);
625
626 /* get access to the used hunters */
627 ut_assertok(bootstd_get_priv(&std));
628
629 memset(&iter, '\0', sizeof(iter));
630 memset(&bflow, '\0', sizeof(bflow));
631 iter.part = 0;
632 uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
633 iter.cur_label = -1;
634 iter.labels = labels;
635
636 dev = NULL;
637 mflags = 123;
638 ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
Simon Glassac06b26a2023-01-17 10:48:10 -0700639 ut_assert_console_end();
640 ut_assertnonnull(dev);
641 ut_asserteq_str("mmc0.bootdev", dev->name);
642 ut_asserteq(0, mflags);
643
644 ut_assertok(bootstd_test_check_mmc_hunter(uts));
645
646 ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
647 ut_assert_nextline("scanning bus for devices...");
648 ut_assert_skip_to_line(
Julius Lehmann18afb602024-10-26 20:06:44 +0200649 " Capacity: 2.0 MB = 0.0 GB (4096 x 512)");
Simon Glassac06b26a2023-01-17 10:48:10 -0700650 ut_assert_console_end();
651 ut_assertnonnull(dev);
652 ut_asserteq_str("scsi.id0lun0.bootdev", dev->name);
653 ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags);
654
Simon Glassdeffa692023-01-28 15:00:28 -0700655 /* SCSI is 7th in the list, so bit 6 */
656 ut_asserteq(BIT(MMC_HUNTER) | BIT(6), std->hunters_used);
Simon Glassac06b26a2023-01-17 10:48:10 -0700657
658 ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
659 ut_assert_console_end();
660 ut_assertnonnull(dev);
661 ut_asserteq_str("eth@10002000.bootdev", dev->name);
662 ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY,
663 mflags);
664
665 /* dhcp: Ethernet is first so bit 0 */
Simon Glassdeffa692023-01-28 15:00:28 -0700666 ut_asserteq(BIT(MMC_HUNTER) | BIT(6) | BIT(0), std->hunters_used);
Simon Glassac06b26a2023-01-17 10:48:10 -0700667
668 ut_assertok(bootdev_next_label(&iter, &dev, &mflags));
669 ut_assert_console_end();
670 ut_assertnonnull(dev);
671 ut_asserteq_str("eth@10002000.bootdev", dev->name);
672 ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY,
673 mflags);
674
675 /* pxe: Ethernet is first so bit 0 */
Simon Glassdeffa692023-01-28 15:00:28 -0700676 ut_asserteq(BIT(MMC_HUNTER) | BIT(6) | BIT(0), std->hunters_used);
Simon Glassac06b26a2023-01-17 10:48:10 -0700677
678 mflags = 123;
679 ut_asserteq(-ENODEV, bootdev_next_label(&iter, &dev, &mflags));
680 ut_asserteq(123, mflags);
681 ut_assert_console_end();
682
683 /* no change */
Simon Glassdeffa692023-01-28 15:00:28 -0700684 ut_asserteq(BIT(MMC_HUNTER) | BIT(6) | BIT(0), std->hunters_used);
Simon Glassac06b26a2023-01-17 10:48:10 -0700685
686 return 0;
687}
Simon Glass1a92f832024-08-22 07:57:48 -0600688BOOTSTD_TEST(bootdev_test_next_label, UTF_DM | UTF_SCAN_FDT | UTF_ETH_BOOTDEV |
Simon Glassf0425022024-08-22 07:57:54 -0600689 UTF_SF_BOOTDEV | UTF_CONSOLE);
Simon Glass660a9952023-01-17 10:48:11 -0700690
Simon Glass660a9952023-01-17 10:48:11 -0700691/* Check iterating to the next prioirty in a list */
692static int bootdev_test_next_prio(struct unit_test_state *uts)
693{
694 struct bootflow_iter iter;
695 struct bootstd_priv *std;
696 struct bootflow bflow;
697 struct udevice *dev;
698 int ret;
699
Simon Glassba3d5372023-01-17 10:48:15 -0700700 test_set_eth_enable(false);
Simon Glass660a9952023-01-17 10:48:11 -0700701 test_set_skip_delays(true);
702
703 /* get access to the used hunters */
704 ut_assertok(bootstd_get_priv(&std));
705
706 memset(&iter, '\0', sizeof(iter));
707 memset(&bflow, '\0', sizeof(bflow));
708 iter.part = 0;
709 uclass_first_device(UCLASS_BOOTMETH, &bflow.method);
710 iter.cur_prio = 0;
Simon Glass99e68182023-02-22 12:17:03 -0700711 iter.flags = BOOTFLOWIF_SHOW;
Simon Glass660a9952023-01-17 10:48:11 -0700712
713 dev = NULL;
Simon Glass660a9952023-01-17 10:48:11 -0700714 ut_assertok(bootdev_next_prio(&iter, &dev));
715 ut_assertnonnull(dev);
716 ut_asserteq_str("mmc2.bootdev", dev->name);
717
718 /* hunt flag not set, so this should not use any hunters */
719 ut_asserteq(0, std->hunters_used);
720 ut_assert_console_end();
721
722 /* now try again with hunting enabled */
Simon Glass99e68182023-02-22 12:17:03 -0700723 iter.flags = BOOTFLOWIF_SHOW | BOOTFLOWIF_HUNT;
Simon Glass660a9952023-01-17 10:48:11 -0700724 iter.cur_prio = 0;
725 iter.part = 0;
726
727 ut_assertok(bootdev_next_prio(&iter, &dev));
728 ut_asserteq_str("mmc2.bootdev", dev->name);
Simon Glasse4cf1062023-01-17 10:48:13 -0700729 ut_assert_nextline("Hunting with: simple_bus");
730 ut_assert_nextline("Found 2 extension board(s).");
Simon Glass660a9952023-01-17 10:48:11 -0700731 ut_assert_nextline("Hunting with: mmc");
732 ut_assert_console_end();
733
Simon Glasse4cf1062023-01-17 10:48:13 -0700734 ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used);
Simon Glass660a9952023-01-17 10:48:11 -0700735
736 ut_assertok(bootdev_next_prio(&iter, &dev));
737 ut_asserteq_str("mmc1.bootdev", dev->name);
738
739 ut_assertok(bootdev_next_prio(&iter, &dev));
740 ut_asserteq_str("mmc0.bootdev", dev->name);
741 ut_assert_console_end();
742
743 ut_assertok(bootdev_next_prio(&iter, &dev));
744 ut_asserteq_str("spi.bin@0.bootdev", dev->name);
745 ut_assert_skip_to_line("Hunting with: spi_flash");
746
747 /*
748 * this scans all bootdevs of priority BOOTDEVP_4_SCAN_FAST before it
749 * starts looking at the devices, so we se virtio as well
750 */
751 ut_assert_nextline("Hunting with: virtio");
752 ut_assert_nextlinen("SF: Detected m25p16");
753
754 ut_assertok(bootdev_next_prio(&iter, &dev));
755 ut_asserteq_str("spi.bin@1.bootdev", dev->name);
756 ut_assert_nextlinen("SF: Detected m25p16");
757 ut_assert_console_end();
758
759 /* keep going until there are no more bootdevs */
760 do {
761 ret = bootdev_next_prio(&iter, &dev);
762 } while (!ret);
763 ut_asserteq(-ENODEV, ret);
764 ut_assertnull(dev);
Simon Glasse4cf1062023-01-17 10:48:13 -0700765 ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used);
Simon Glass660a9952023-01-17 10:48:11 -0700766
767 ut_assert_skip_to_line("Hunting with: ethernet");
768 ut_assert_console_end();
769
770 return 0;
771}
Simon Glassf0425022024-08-22 07:57:54 -0600772BOOTSTD_TEST(bootdev_test_next_prio, UTF_DM | UTF_SCAN_FDT | UTF_SF_BOOTDEV |
773 UTF_CONSOLE);