]>
Commit | Line | Data |
---|---|---|
fb1451be SG |
1 | // 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 <[email protected]> | |
7 | */ | |
8 | ||
d678a59d | 9 | #include <common.h> |
fb1451be SG |
10 | #include <bootstd.h> |
11 | #include <dm.h> | |
12 | #include <bootdev.h> | |
13 | #include <bootflow.h> | |
14 | #include <mapmem.h> | |
15 | #include <os.h> | |
16 | #include <test/suites.h> | |
17 | #include <test/ut.h> | |
18 | #include "bootstd_common.h" | |
19 | ||
20 | /* Allow reseting the USB-started flag */ | |
0c1413f6 | 21 | #if defined(CONFIG_USB_HOST) || defined(CONFIG_USB_GADGET) |
9fea3a79 | 22 | extern bool usb_started; |
0c1413f6 | 23 | #else |
9fea3a79 | 24 | #include <usb.h> |
0c1413f6 | 25 | #endif |
fb1451be SG |
26 | |
27 | /* Check 'bootdev list' command */ | |
28 | static int bootdev_test_cmd_list(struct unit_test_state *uts) | |
29 | { | |
30 | int probed; | |
31 | ||
32 | console_record_reset_enable(); | |
33 | for (probed = 0; probed < 2; probed++) { | |
34 | int probe_ch = probed ? '+' : ' '; | |
35 | ||
36 | ut_assertok(run_command(probed ? "bootdev list -p" : | |
37 | "bootdev list", 0)); | |
38 | ut_assert_nextline("Seq Probed Status Uclass Name"); | |
39 | ut_assert_nextlinen("---"); | |
40 | ut_assert_nextline("%3x [ %c ] %6s %-8s %s", 0, probe_ch, "OK", | |
41 | "mmc", "mmc2.bootdev"); | |
42 | ut_assert_nextline("%3x [ %c ] %6s %-8s %s", 1, probe_ch, "OK", | |
43 | "mmc", "mmc1.bootdev"); | |
44 | ut_assert_nextline("%3x [ %c ] %6s %-8s %s", 2, probe_ch, "OK", | |
45 | "mmc", "mmc0.bootdev"); | |
46 | ut_assert_nextlinen("---"); | |
47 | ut_assert_nextline("(3 bootdevs)"); | |
48 | ut_assert_console_end(); | |
49 | } | |
50 | ||
51 | return 0; | |
52 | } | |
53 | BOOTSTD_TEST(bootdev_test_cmd_list, UT_TESTF_DM | UT_TESTF_SCAN_FDT); | |
54 | ||
55 | /* Check 'bootdev select' and 'info' commands */ | |
56 | static int bootdev_test_cmd_select(struct unit_test_state *uts) | |
57 | { | |
58 | struct bootstd_priv *std; | |
59 | ||
60 | /* get access to the CLI's cur_bootdev */ | |
61 | ut_assertok(bootstd_get_priv(&std)); | |
62 | ||
63 | console_record_reset_enable(); | |
64 | ut_asserteq(1, run_command("bootdev info", 0)); | |
65 | ut_assert_nextlinen("Please use"); | |
66 | ut_assert_console_end(); | |
67 | ||
68 | /* select by sequence */ | |
69 | ut_assertok(run_command("bootdev select 0", 0)); | |
70 | ut_assert_console_end(); | |
71 | ||
72 | ut_assertok(run_command("bootdev info", 0)); | |
73 | ut_assert_nextline("Name: mmc2.bootdev"); | |
74 | ut_assert_nextline("Sequence: 0"); | |
75 | ut_assert_nextline("Status: Probed"); | |
76 | ut_assert_nextline("Uclass: mmc"); | |
77 | ut_assert_nextline("Bootflows: 0 (0 valid)"); | |
78 | ut_assert_console_end(); | |
79 | ||
80 | /* select by bootdev name */ | |
81 | ut_assertok(run_command("bootdev select mmc1.bootdev", 0)); | |
82 | ut_assert_console_end(); | |
83 | ut_assertnonnull(std->cur_bootdev); | |
84 | ut_asserteq_str("mmc1.bootdev", std->cur_bootdev->name); | |
85 | ||
86 | /* select by bootdev label*/ | |
87 | ut_assertok(run_command("bootdev select mmc1", 0)); | |
88 | ut_assert_console_end(); | |
89 | ut_assertnonnull(std->cur_bootdev); | |
90 | ut_asserteq_str("mmc1.bootdev", std->cur_bootdev->name); | |
91 | ||
92 | /* deselect */ | |
93 | ut_assertok(run_command("bootdev select", 0)); | |
94 | ut_assert_console_end(); | |
95 | ut_assertnull(std->cur_bootdev); | |
96 | ||
97 | ut_asserteq(1, run_command("bootdev info", 0)); | |
98 | ut_assert_nextlinen("Please use"); | |
99 | ut_assert_console_end(); | |
100 | ||
101 | return 0; | |
102 | } | |
103 | BOOTSTD_TEST(bootdev_test_cmd_select, UT_TESTF_DM | UT_TESTF_SCAN_FDT); | |
104 | ||
105 | /* Check bootdev labels */ | |
106 | static int bootdev_test_labels(struct unit_test_state *uts) | |
107 | { | |
108 | struct udevice *dev, *media; | |
d9f48579 | 109 | int mflags = 0; |
fb1451be | 110 | |
d9f48579 | 111 | ut_assertok(bootdev_find_by_label("mmc2", &dev, &mflags)); |
fb1451be | 112 | ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev)); |
d9f48579 | 113 | ut_asserteq(0, mflags); |
fb1451be SG |
114 | media = dev_get_parent(dev); |
115 | ut_asserteq(UCLASS_MMC, device_get_uclass_id(media)); | |
116 | ut_asserteq_str("mmc2", media->name); | |
117 | ||
d9f48579 SG |
118 | /* Check method flags */ |
119 | ut_assertok(bootdev_find_by_label("pxe", &dev, &mflags)); | |
66e3dce7 SG |
120 | ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY, |
121 | mflags); | |
d9f48579 | 122 | ut_assertok(bootdev_find_by_label("dhcp", &dev, &mflags)); |
66e3dce7 SG |
123 | ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY, |
124 | mflags); | |
d9f48579 | 125 | |
fb1451be | 126 | /* Check invalid uclass */ |
1736b4af SG |
127 | ut_asserteq(-EPFNOSUPPORT, |
128 | bootdev_find_by_label("fred0", &dev, &mflags)); | |
fb1451be SG |
129 | |
130 | /* Check unknown sequence number */ | |
d9f48579 | 131 | ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev, &mflags)); |
fb1451be SG |
132 | |
133 | return 0; | |
134 | } | |
d9f48579 SG |
135 | BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT | |
136 | UT_TESTF_ETH_BOOTDEV); | |
fb1451be | 137 | |
66e3dce7 SG |
138 | /* Check bootdev_find_by_any() */ |
139 | static int bootdev_test_any(struct unit_test_state *uts) | |
140 | { | |
141 | struct udevice *dev, *media; | |
142 | int mflags; | |
143 | ||
144 | /* | |
145 | * with ethernet enabled we have 8 devices ahead of the mmc ones: | |
146 | * | |
147 | * ut_assertok(run_command("bootdev list", 0)); | |
148 | * Seq Probed Status Uclass Name | |
149 | * --- ------ ------ -------- ------------------ | |
150 | * 0 [ + ] OK ethernet [email protected] | |
151 | * 1 [ ] OK ethernet [email protected] | |
152 | * 2 [ ] OK ethernet sbe5.bootdev | |
153 | * 3 [ ] OK ethernet [email protected] | |
154 | * 4 [ ] OK ethernet phy-test-eth.bootdev | |
155 | * 5 [ ] OK ethernet dsa-test-eth.bootdev | |
156 | * 6 [ ] OK ethernet [email protected] | |
157 | * 7 [ ] OK ethernet [email protected] | |
158 | * 8 [ ] OK mmc mmc2.bootdev | |
159 | * 9 [ + ] OK mmc mmc1.bootdev | |
160 | * a [ ] OK mmc mmc0.bootdev | |
161 | */ | |
162 | console_record_reset_enable(); | |
163 | ut_assertok(bootdev_find_by_any("8", &dev, &mflags)); | |
164 | ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev)); | |
165 | ut_asserteq(BOOTFLOW_METHF_SINGLE_DEV, mflags); | |
166 | media = dev_get_parent(dev); | |
167 | ut_asserteq(UCLASS_MMC, device_get_uclass_id(media)); | |
168 | ut_asserteq_str("mmc2", media->name); | |
169 | ut_assert_console_end(); | |
170 | ||
171 | /* there should not be this many bootdevs */ | |
172 | ut_asserteq(-ENODEV, bootdev_find_by_any("50", &dev, &mflags)); | |
173 | ut_assert_nextline("Cannot find '50' (err=-19)"); | |
174 | ut_assert_console_end(); | |
175 | ||
176 | /* Check method flags */ | |
177 | ut_assertok(bootdev_find_by_any("pxe", &dev, &mflags)); | |
178 | ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY, | |
179 | mflags); | |
180 | ||
181 | /* Check invalid uclass */ | |
182 | mflags = 123; | |
1736b4af SG |
183 | ut_asserteq(-EPFNOSUPPORT, bootdev_find_by_any("fred0", &dev, &mflags)); |
184 | ut_assert_nextline("Cannot find bootdev 'fred0' (err=-96)"); | |
66e3dce7 SG |
185 | ut_asserteq(123, mflags); |
186 | ut_assert_console_end(); | |
187 | ||
188 | return 0; | |
189 | } | |
190 | BOOTSTD_TEST(bootdev_test_any, UT_TESTF_DM | UT_TESTF_SCAN_FDT | | |
191 | UT_TESTF_ETH_BOOTDEV); | |
192 | ||
7ae83bfa SG |
193 | /* |
194 | * Check bootdev ordering with the bootdev-order property and boot_targets | |
195 | * environment variable | |
196 | */ | |
fb1451be SG |
197 | static int bootdev_test_order(struct unit_test_state *uts) |
198 | { | |
199 | struct bootflow_iter iter; | |
200 | struct bootflow bflow; | |
201 | ||
7ae83bfa SG |
202 | test_set_skip_delays(true); |
203 | ||
204 | /* Start up USB which gives us three additional bootdevs */ | |
205 | usb_started = false; | |
206 | ut_assertok(run_command("usb start", 0)); | |
207 | ||
fb1451be SG |
208 | /* |
209 | * First try the order set by the bootdev-order property | |
210 | * Like all sandbox unit tests this relies on the devicetree setting up | |
211 | * the required devices: | |
212 | * | |
213 | * mmc0 - nothing connected | |
214 | * mmc1 - connected to mmc1.img file | |
215 | * mmc2 - nothing connected | |
216 | */ | |
217 | ut_assertok(env_set("boot_targets", NULL)); | |
4b7cb058 | 218 | ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); |
fb1451be | 219 | ut_asserteq(2, iter.num_devs); |
a950f285 SG |
220 | ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); |
221 | ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name); | |
fb1451be SG |
222 | bootflow_iter_uninit(&iter); |
223 | ||
224 | /* Use the environment variable to override it */ | |
7ae83bfa | 225 | ut_assertok(env_set("boot_targets", "mmc1 mmc2 usb")); |
4b7cb058 | 226 | ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); |
a950f285 | 227 | ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); |
7a790f01 | 228 | ut_asserteq(5, iter.num_devs); |
a950f285 SG |
229 | ut_asserteq_str("mmc1.bootdev", iter.dev_used[0]->name); |
230 | ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name); | |
7ae83bfa SG |
231 | ut_asserteq_str("usb_mass_storage.lun0.bootdev", |
232 | iter.dev_used[2]->name); | |
fb1451be SG |
233 | bootflow_iter_uninit(&iter); |
234 | ||
16e19350 SG |
235 | /* Try a single uclass */ |
236 | ut_assertok(env_set("boot_targets", NULL)); | |
237 | ut_assertok(bootflow_scan_first(NULL, "mmc", &iter, 0, &bflow)); | |
238 | ut_asserteq(2, iter.num_devs); | |
239 | ||
7a790f01 SG |
240 | /* Now scan past mmc1 and make sure that only mmc0 shows up */ |
241 | ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); | |
242 | ut_asserteq(3, iter.num_devs); | |
243 | ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); | |
244 | ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name); | |
245 | ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name); | |
246 | bootflow_iter_uninit(&iter); | |
247 | ||
248 | /* Try a single uclass with boot_targets */ | |
249 | ut_assertok(env_set("boot_targets", "mmc")); | |
250 | ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); | |
251 | ut_asserteq(2, iter.num_devs); | |
252 | ||
253 | /* Now scan past mmc1 and make sure that only mmc0 shows up */ | |
16e19350 SG |
254 | ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); |
255 | ut_asserteq(3, iter.num_devs); | |
256 | ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); | |
257 | ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name); | |
258 | ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name); | |
259 | bootflow_iter_uninit(&iter); | |
260 | ||
7a790f01 SG |
261 | /* Try a single uclass with boot_targets */ |
262 | ut_assertok(env_set("boot_targets", "mmc usb")); | |
263 | ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); | |
264 | ut_asserteq(2, iter.num_devs); | |
265 | ||
266 | /* Now scan past mmc1 and make sure that the 3 USB devices show up */ | |
267 | ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); | |
268 | ut_asserteq(6, iter.num_devs); | |
269 | ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); | |
270 | ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name); | |
271 | ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name); | |
272 | ut_asserteq_str("usb_mass_storage.lun0.bootdev", | |
273 | iter.dev_used[3]->name); | |
274 | bootflow_iter_uninit(&iter); | |
275 | ||
a950f285 SG |
276 | return 0; |
277 | } | |
278 | BOOTSTD_TEST(bootdev_test_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT); | |
279 | ||
280 | /* Check default bootdev ordering */ | |
281 | static int bootdev_test_order_default(struct unit_test_state *uts) | |
282 | { | |
283 | struct bootflow_iter iter; | |
284 | struct bootflow bflow; | |
285 | ||
fb1451be SG |
286 | /* |
287 | * Now drop both orderings, to check the default (prioriy/sequence) | |
288 | * ordering | |
289 | */ | |
290 | ut_assertok(env_set("boot_targets", NULL)); | |
291 | ut_assertok(bootstd_test_drop_bootdev_order(uts)); | |
292 | ||
4b7cb058 | 293 | ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); |
a950f285 SG |
294 | ut_asserteq(2, iter.num_devs); |
295 | ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); | |
296 | ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name); | |
fb1451be | 297 | |
a950f285 | 298 | ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); |
fb1451be | 299 | ut_asserteq(3, iter.num_devs); |
a950f285 | 300 | ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name); |
fb1451be SG |
301 | bootflow_iter_uninit(&iter); |
302 | ||
303 | return 0; | |
304 | } | |
a950f285 | 305 | BOOTSTD_TEST(bootdev_test_order_default, UT_TESTF_DM | UT_TESTF_SCAN_FDT); |
fb1451be SG |
306 | |
307 | /* Check bootdev ordering with the uclass priority */ | |
308 | static int bootdev_test_prio(struct unit_test_state *uts) | |
309 | { | |
310 | struct bootdev_uc_plat *ucp; | |
311 | struct bootflow_iter iter; | |
312 | struct bootflow bflow; | |
313 | struct udevice *blk; | |
314 | ||
04fb2b6e SG |
315 | test_set_skip_delays(true); |
316 | ||
a950f285 SG |
317 | /* disable ethernet since the hunter will run dhcp */ |
318 | test_set_eth_enable(false); | |
319 | ||
fb1451be SG |
320 | /* Start up USB which gives us three additional bootdevs */ |
321 | usb_started = false; | |
322 | ut_assertok(run_command("usb start", 0)); | |
323 | ||
324 | ut_assertok(bootstd_test_drop_bootdev_order(uts)); | |
325 | ||
326 | /* 3 MMC and 3 USB bootdevs: MMC should come before USB */ | |
327 | console_record_reset_enable(); | |
4b7cb058 | 328 | ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); |
a950f285 | 329 | ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); |
fb1451be | 330 | ut_asserteq(6, iter.num_devs); |
a950f285 | 331 | ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); |
fb1451be | 332 | ut_asserteq_str("usb_mass_storage.lun0.bootdev", |
a950f285 | 333 | iter.dev_used[3]->name); |
fb1451be | 334 | |
a950f285 | 335 | ut_assertok(bootdev_get_sibling_blk(iter.dev_used[3], &blk)); |
fb1451be SG |
336 | ut_asserteq_str("usb_mass_storage.lun0", blk->name); |
337 | ||
338 | /* adjust the priority of the first USB bootdev to the highest */ | |
a950f285 SG |
339 | ucp = dev_get_uclass_plat(iter.dev_used[3]); |
340 | ucp->prio = BOOTDEVP_1_PRE_SCAN; | |
fb1451be | 341 | |
a950f285 | 342 | /* try again but enable hunting, which brings in SCSI */ |
fb1451be | 343 | bootflow_iter_uninit(&iter); |
4f806f31 | 344 | ut_assertok(bootflow_scan_first(NULL, NULL, &iter, BOOTFLOWIF_HUNT, |
4b7cb058 | 345 | &bflow)); |
a950f285 SG |
346 | ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); |
347 | ut_asserteq(7, iter.num_devs); | |
fb1451be | 348 | ut_asserteq_str("usb_mass_storage.lun0.bootdev", |
a950f285 SG |
349 | iter.dev_used[0]->name); |
350 | ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name); | |
fb1451be SG |
351 | |
352 | return 0; | |
353 | } | |
354 | BOOTSTD_TEST(bootdev_test_prio, UT_TESTF_DM | UT_TESTF_SCAN_FDT); | |
bd90b092 SG |
355 | |
356 | /* Check listing hunters */ | |
357 | static int bootdev_test_hunter(struct unit_test_state *uts) | |
358 | { | |
359 | struct bootstd_priv *std; | |
360 | ||
8c29b732 | 361 | usb_started = false; |
04fb2b6e SG |
362 | test_set_skip_delays(true); |
363 | ||
bd90b092 SG |
364 | /* get access to the used hunters */ |
365 | ut_assertok(bootstd_get_priv(&std)); | |
366 | ||
367 | console_record_reset_enable(); | |
368 | bootdev_list_hunters(std); | |
369 | ut_assert_nextline("Prio Used Uclass Hunter"); | |
370 | ut_assert_nextlinen("----"); | |
eacc2611 | 371 | ut_assert_nextline(" 6 ethernet eth_bootdev"); |
18552d2a | 372 | ut_assert_nextline(" 1 simple_bus (none)"); |
eacc2611 SG |
373 | ut_assert_nextline(" 5 ide ide_bootdev"); |
374 | ut_assert_nextline(" 2 mmc mmc_bootdev"); | |
375 | ut_assert_nextline(" 4 nvme nvme_bootdev"); | |
662cfa03 | 376 | ut_assert_nextline(" 4 qfw qfw_bootdev"); |
eacc2611 SG |
377 | ut_assert_nextline(" 4 scsi scsi_bootdev"); |
378 | ut_assert_nextline(" 4 spi_flash sf_bootdev"); | |
379 | ut_assert_nextline(" 5 usb usb_bootdev"); | |
380 | ut_assert_nextline(" 4 virtio virtio_bootdev"); | |
662cfa03 | 381 | ut_assert_nextline("(total hunters: 10)"); |
bd90b092 SG |
382 | ut_assert_console_end(); |
383 | ||
04fb2b6e SG |
384 | ut_assertok(bootdev_hunt("usb1", false)); |
385 | ut_assert_nextline( | |
386 | "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found"); | |
c7b63d50 SG |
387 | ut_assert_console_end(); |
388 | ||
662cfa03 SG |
389 | /* USB is 7th in the list, so bit 8 */ |
390 | ut_asserteq(BIT(8), std->hunters_used); | |
04fb2b6e | 391 | |
bd90b092 SG |
392 | return 0; |
393 | } | |
394 | BOOTSTD_TEST(bootdev_test_hunter, UT_TESTF_DM | UT_TESTF_SCAN_FDT); | |
395 | ||
396 | /* Check 'bootdev hunt' command */ | |
397 | static int bootdev_test_cmd_hunt(struct unit_test_state *uts) | |
398 | { | |
399 | struct bootstd_priv *std; | |
400 | ||
04fb2b6e | 401 | test_set_skip_delays(true); |
8c29b732 | 402 | usb_started = false; |
04fb2b6e | 403 | |
bd90b092 SG |
404 | /* get access to the used hunters */ |
405 | ut_assertok(bootstd_get_priv(&std)); | |
406 | ||
407 | console_record_reset_enable(); | |
408 | ut_assertok(run_command("bootdev hunt -l", 0)); | |
409 | ut_assert_nextline("Prio Used Uclass Hunter"); | |
410 | ut_assert_nextlinen("----"); | |
eacc2611 | 411 | ut_assert_nextline(" 6 ethernet eth_bootdev"); |
662cfa03 | 412 | ut_assert_skip_to_line("(total hunters: 10)"); |
eacc2611 SG |
413 | ut_assert_console_end(); |
414 | ||
415 | /* Use the MMC hunter and see that it updates */ | |
416 | ut_assertok(run_command("bootdev hunt mmc", 0)); | |
417 | ut_assertok(run_command("bootdev hunt -l", 0)); | |
418 | ut_assert_skip_to_line(" 5 ide ide_bootdev"); | |
419 | ut_assert_nextline(" 2 * mmc mmc_bootdev"); | |
662cfa03 | 420 | ut_assert_skip_to_line("(total hunters: 10)"); |
bd90b092 SG |
421 | ut_assert_console_end(); |
422 | ||
423 | /* Scan all hunters */ | |
e4b69489 | 424 | test_set_eth_enable(false); |
eacc2611 | 425 | test_set_skip_delays(true); |
bd90b092 | 426 | ut_assertok(run_command("bootdev hunt", 0)); |
4146c823 | 427 | ut_assert_nextline("Hunting with: ethernet"); |
18552d2a SG |
428 | |
429 | /* This is the extension feature which has no uclass at present */ | |
430 | ut_assert_nextline("Hunting with: simple_bus"); | |
431 | ut_assert_nextline("Found 2 extension board(s)."); | |
0d77f8f1 | 432 | ut_assert_nextline("Hunting with: ide"); |
eacc2611 SG |
433 | |
434 | /* mmc hunter has already been used so should not run again */ | |
435 | ||
758c706c | 436 | ut_assert_nextline("Hunting with: nvme"); |
662cfa03 | 437 | ut_assert_nextline("Hunting with: qfw"); |
8f090b67 SG |
438 | ut_assert_nextline("Hunting with: scsi"); |
439 | ut_assert_nextline("scanning bus for devices..."); | |
0c1f4a9f SG |
440 | ut_assert_skip_to_line("Hunting with: spi_flash"); |
441 | ut_assert_nextline("Hunting with: usb"); | |
04fb2b6e SG |
442 | ut_assert_nextline( |
443 | "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found"); | |
0c1f4a9f | 444 | ut_assert_nextline("Hunting with: virtio"); |
bd90b092 SG |
445 | ut_assert_console_end(); |
446 | ||
447 | /* List available hunters */ | |
448 | ut_assertok(run_command("bootdev hunt -l", 0)); | |
449 | ut_assert_nextlinen("Prio"); | |
450 | ut_assert_nextlinen("----"); | |
eacc2611 | 451 | ut_assert_nextline(" 6 * ethernet eth_bootdev"); |
18552d2a | 452 | ut_assert_nextline(" 1 * simple_bus (none)"); |
eacc2611 SG |
453 | ut_assert_nextline(" 5 * ide ide_bootdev"); |
454 | ut_assert_nextline(" 2 * mmc mmc_bootdev"); | |
455 | ut_assert_nextline(" 4 * nvme nvme_bootdev"); | |
662cfa03 | 456 | ut_assert_nextline(" 4 * qfw qfw_bootdev"); |
eacc2611 SG |
457 | ut_assert_nextline(" 4 * scsi scsi_bootdev"); |
458 | ut_assert_nextline(" 4 * spi_flash sf_bootdev"); | |
459 | ut_assert_nextline(" 5 * usb usb_bootdev"); | |
460 | ut_assert_nextline(" 4 * virtio virtio_bootdev"); | |
662cfa03 | 461 | ut_assert_nextline("(total hunters: 10)"); |
bd90b092 SG |
462 | ut_assert_console_end(); |
463 | ||
18552d2a | 464 | ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used); |
bd90b092 SG |
465 | |
466 | return 0; | |
467 | } | |
468 | BOOTSTD_TEST(bootdev_test_cmd_hunt, UT_TESTF_DM | UT_TESTF_SCAN_FDT | | |
469 | UT_TESTF_ETH_BOOTDEV); | |
f0e358f0 | 470 | |
47aedc29 SG |
471 | /* Check searching for bootdevs using the hunters */ |
472 | static int bootdev_test_hunt_scan(struct unit_test_state *uts) | |
473 | { | |
474 | struct bootflow_iter iter; | |
475 | struct bootstd_priv *std; | |
476 | struct bootflow bflow; | |
477 | ||
478 | /* get access to the used hunters */ | |
479 | ut_assertok(bootstd_get_priv(&std)); | |
480 | ||
481 | ut_assertok(bootstd_test_drop_bootdev_order(uts)); | |
4b7cb058 | 482 | ut_assertok(bootflow_scan_first(NULL, NULL, &iter, |
4f806f31 SG |
483 | BOOTFLOWIF_SHOW | BOOTFLOWIF_HUNT | |
484 | BOOTFLOWIF_SKIP_GLOBAL, &bflow)); | |
47aedc29 SG |
485 | ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used); |
486 | ||
487 | return 0; | |
488 | } | |
489 | BOOTSTD_TEST(bootdev_test_hunt_scan, UT_TESTF_DM | UT_TESTF_SCAN_FDT); | |
490 | ||
f0e358f0 SG |
491 | /* Check that only bootable partitions are processed */ |
492 | static int bootdev_test_bootable(struct unit_test_state *uts) | |
493 | { | |
494 | struct bootflow_iter iter; | |
495 | struct bootflow bflow; | |
496 | struct udevice *blk; | |
497 | ||
498 | memset(&iter, '\0', sizeof(iter)); | |
499 | memset(&bflow, '\0', sizeof(bflow)); | |
500 | iter.part = 0; | |
501 | ut_assertok(uclass_get_device_by_name(UCLASS_BLK, "mmc1.blk", &blk)); | |
502 | iter.dev = blk; | |
503 | ut_assertok(device_find_next_child(&iter.dev)); | |
504 | uclass_first_device(UCLASS_BOOTMETH, &bflow.method); | |
505 | ||
506 | /* | |
507 | * initially we don't have any knowledge of which partitions are | |
508 | * bootable, but mmc1 has two partitions, with the first one being | |
509 | * bootable | |
510 | */ | |
511 | iter.part = 2; | |
512 | ut_asserteq(-EINVAL, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow)); | |
513 | ut_asserteq(0, iter.first_bootable); | |
514 | ||
515 | /* scan with part == 0 to get the partition info */ | |
516 | iter.part = 0; | |
517 | ut_asserteq(-ENOENT, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow)); | |
518 | ut_asserteq(1, iter.first_bootable); | |
519 | ||
520 | /* now it will refuse to use non-bootable partitions */ | |
521 | iter.part = 2; | |
522 | ut_asserteq(-EINVAL, bootdev_find_in_blk(iter.dev, blk, &iter, &bflow)); | |
523 | ||
524 | return 0; | |
525 | } | |
526 | BOOTSTD_TEST(bootdev_test_bootable, UT_TESTF_DM | UT_TESTF_SCAN_FDT); | |
79a7d4a6 SG |
527 | |
528 | /* Check hunting for bootdev of a particular priority */ | |
529 | static int bootdev_test_hunt_prio(struct unit_test_state *uts) | |
530 | { | |
8c29b732 | 531 | usb_started = false; |
79a7d4a6 SG |
532 | test_set_skip_delays(true); |
533 | ||
534 | console_record_reset_enable(); | |
eacc2611 | 535 | ut_assertok(bootdev_hunt_prio(BOOTDEVP_4_SCAN_FAST, false)); |
79a7d4a6 SG |
536 | ut_assert_nextline("scanning bus for devices..."); |
537 | ut_assert_skip_to_line(" Type: Hard Disk"); | |
538 | ut_assert_nextlinen(" Capacity:"); | |
539 | ut_assert_console_end(); | |
540 | ||
541 | /* now try a different priority, verbosely */ | |
eacc2611 | 542 | ut_assertok(bootdev_hunt_prio(BOOTDEVP_5_SCAN_SLOW, true)); |
79a7d4a6 | 543 | ut_assert_nextline("Hunting with: ide"); |
79a7d4a6 SG |
544 | ut_assert_nextline("Hunting with: usb"); |
545 | ut_assert_nextline( | |
546 | "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found"); | |
547 | ut_assert_console_end(); | |
548 | ||
549 | return 0; | |
550 | } | |
551 | BOOTSTD_TEST(bootdev_test_hunt_prio, UT_TESTF_DM | UT_TESTF_SCAN_FDT); | |
66e3dce7 SG |
552 | |
553 | /* Check hunting for bootdevs with a particular label */ | |
554 | static int bootdev_test_hunt_label(struct unit_test_state *uts) | |
555 | { | |
556 | struct udevice *dev, *old; | |
557 | struct bootstd_priv *std; | |
558 | int mflags; | |
559 | ||
8c29b732 SG |
560 | usb_started = false; |
561 | ||
66e3dce7 SG |
562 | /* get access to the used hunters */ |
563 | ut_assertok(bootstd_get_priv(&std)); | |
564 | ||
565 | /* scan an unknown uclass */ | |
566 | console_record_reset_enable(); | |
567 | old = (void *)&mflags; /* arbitrary pointer to check against dev */ | |
568 | dev = old; | |
569 | mflags = 123; | |
1736b4af | 570 | ut_asserteq(-EPFNOSUPPORT, |
66e3dce7 | 571 | bootdev_hunt_and_find_by_label("fred", &dev, &mflags)); |
66e3dce7 SG |
572 | ut_asserteq_ptr(old, dev); |
573 | ut_asserteq(123, mflags); | |
574 | ut_assert_console_end(); | |
575 | ut_asserteq(0, std->hunters_used); | |
576 | ||
577 | /* scan an invalid mmc controllers */ | |
578 | ut_asserteq(-ENOENT, | |
579 | bootdev_hunt_and_find_by_label("mmc4", &dev, &mflags)); | |
580 | ut_asserteq_ptr(old, dev); | |
581 | ut_asserteq(123, mflags); | |
66e3dce7 SG |
582 | ut_assert_console_end(); |
583 | ||
584 | ut_assertok(bootstd_test_check_mmc_hunter(uts)); | |
585 | ||
586 | /* scan for a particular mmc controller */ | |
587 | ut_assertok(bootdev_hunt_and_find_by_label("mmc1", &dev, &mflags)); | |
588 | ut_assertnonnull(dev); | |
589 | ut_asserteq_str("mmc1.bootdev", dev->name); | |
590 | ut_asserteq(0, mflags); | |
591 | ut_assert_console_end(); | |
592 | ||
593 | /* scan all of usb */ | |
594 | test_set_skip_delays(true); | |
595 | ut_assertok(bootdev_hunt_and_find_by_label("usb", &dev, &mflags)); | |
596 | ut_assertnonnull(dev); | |
597 | ut_asserteq_str("usb_mass_storage.lun0.bootdev", dev->name); | |
598 | ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags); | |
599 | ut_assert_nextlinen("Bus usb@1: scanning bus usb@1"); | |
600 | ut_assert_console_end(); | |
601 | ||
602 | return 0; | |
603 | } | |
604 | BOOTSTD_TEST(bootdev_test_hunt_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT); | |
e4b69489 SG |
605 | |
606 | /* Check iterating to the next label in a list */ | |
607 | static int bootdev_test_next_label(struct unit_test_state *uts) | |
608 | { | |
609 | const char *const labels[] = {"mmc0", "scsi", "dhcp", "pxe", NULL}; | |
610 | struct bootflow_iter iter; | |
611 | struct bootstd_priv *std; | |
612 | struct bootflow bflow; | |
613 | struct udevice *dev; | |
614 | int mflags; | |
615 | ||
616 | test_set_eth_enable(false); | |
617 | ||
618 | /* get access to the used hunters */ | |
619 | ut_assertok(bootstd_get_priv(&std)); | |
620 | ||
621 | memset(&iter, '\0', sizeof(iter)); | |
622 | memset(&bflow, '\0', sizeof(bflow)); | |
623 | iter.part = 0; | |
624 | uclass_first_device(UCLASS_BOOTMETH, &bflow.method); | |
625 | iter.cur_label = -1; | |
626 | iter.labels = labels; | |
627 | ||
628 | dev = NULL; | |
629 | mflags = 123; | |
630 | ut_assertok(bootdev_next_label(&iter, &dev, &mflags)); | |
631 | console_record_reset_enable(); | |
632 | ut_assert_console_end(); | |
633 | ut_assertnonnull(dev); | |
634 | ut_asserteq_str("mmc0.bootdev", dev->name); | |
635 | ut_asserteq(0, mflags); | |
636 | ||
637 | ut_assertok(bootstd_test_check_mmc_hunter(uts)); | |
638 | ||
639 | ut_assertok(bootdev_next_label(&iter, &dev, &mflags)); | |
640 | ut_assert_nextline("scanning bus for devices..."); | |
641 | ut_assert_skip_to_line( | |
642 | " Capacity: 1.9 MB = 0.0 GB (4095 x 512)"); | |
643 | ut_assert_console_end(); | |
644 | ut_assertnonnull(dev); | |
645 | ut_asserteq_str("scsi.id0lun0.bootdev", dev->name); | |
646 | ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags); | |
647 | ||
662cfa03 SG |
648 | /* SCSI is 7th in the list, so bit 6 */ |
649 | ut_asserteq(BIT(MMC_HUNTER) | BIT(6), std->hunters_used); | |
e4b69489 SG |
650 | |
651 | ut_assertok(bootdev_next_label(&iter, &dev, &mflags)); | |
652 | ut_assert_console_end(); | |
653 | ut_assertnonnull(dev); | |
654 | ut_asserteq_str("[email protected]", dev->name); | |
655 | ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY, | |
656 | mflags); | |
657 | ||
658 | /* dhcp: Ethernet is first so bit 0 */ | |
662cfa03 | 659 | ut_asserteq(BIT(MMC_HUNTER) | BIT(6) | BIT(0), std->hunters_used); |
e4b69489 SG |
660 | |
661 | ut_assertok(bootdev_next_label(&iter, &dev, &mflags)); | |
662 | ut_assert_console_end(); | |
663 | ut_assertnonnull(dev); | |
664 | ut_asserteq_str("[email protected]", dev->name); | |
665 | ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY, | |
666 | mflags); | |
667 | ||
668 | /* pxe: Ethernet is first so bit 0 */ | |
662cfa03 | 669 | ut_asserteq(BIT(MMC_HUNTER) | BIT(6) | BIT(0), std->hunters_used); |
e4b69489 SG |
670 | |
671 | mflags = 123; | |
672 | ut_asserteq(-ENODEV, bootdev_next_label(&iter, &dev, &mflags)); | |
673 | ut_asserteq(123, mflags); | |
674 | ut_assert_console_end(); | |
675 | ||
676 | /* no change */ | |
662cfa03 | 677 | ut_asserteq(BIT(MMC_HUNTER) | BIT(6) | BIT(0), std->hunters_used); |
e4b69489 SG |
678 | |
679 | return 0; | |
680 | } | |
681 | BOOTSTD_TEST(bootdev_test_next_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT | | |
682 | UT_TESTF_ETH_BOOTDEV | UT_TESTF_SF_BOOTDEV); | |
43e89a30 SG |
683 | |
684 | ||
685 | /* Check iterating to the next prioirty in a list */ | |
686 | static int bootdev_test_next_prio(struct unit_test_state *uts) | |
687 | { | |
688 | struct bootflow_iter iter; | |
689 | struct bootstd_priv *std; | |
690 | struct bootflow bflow; | |
691 | struct udevice *dev; | |
692 | int ret; | |
693 | ||
91943ff7 | 694 | test_set_eth_enable(false); |
43e89a30 SG |
695 | test_set_skip_delays(true); |
696 | ||
697 | /* get access to the used hunters */ | |
698 | ut_assertok(bootstd_get_priv(&std)); | |
699 | ||
700 | memset(&iter, '\0', sizeof(iter)); | |
701 | memset(&bflow, '\0', sizeof(bflow)); | |
702 | iter.part = 0; | |
703 | uclass_first_device(UCLASS_BOOTMETH, &bflow.method); | |
704 | iter.cur_prio = 0; | |
4f806f31 | 705 | iter.flags = BOOTFLOWIF_SHOW; |
43e89a30 SG |
706 | |
707 | dev = NULL; | |
708 | console_record_reset_enable(); | |
709 | ut_assertok(bootdev_next_prio(&iter, &dev)); | |
710 | ut_assertnonnull(dev); | |
711 | ut_asserteq_str("mmc2.bootdev", dev->name); | |
712 | ||
713 | /* hunt flag not set, so this should not use any hunters */ | |
714 | ut_asserteq(0, std->hunters_used); | |
715 | ut_assert_console_end(); | |
716 | ||
717 | /* now try again with hunting enabled */ | |
4f806f31 | 718 | iter.flags = BOOTFLOWIF_SHOW | BOOTFLOWIF_HUNT; |
43e89a30 SG |
719 | iter.cur_prio = 0; |
720 | iter.part = 0; | |
721 | ||
722 | ut_assertok(bootdev_next_prio(&iter, &dev)); | |
723 | ut_asserteq_str("mmc2.bootdev", dev->name); | |
18552d2a SG |
724 | ut_assert_nextline("Hunting with: simple_bus"); |
725 | ut_assert_nextline("Found 2 extension board(s)."); | |
43e89a30 SG |
726 | ut_assert_nextline("Hunting with: mmc"); |
727 | ut_assert_console_end(); | |
728 | ||
18552d2a | 729 | ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used); |
43e89a30 SG |
730 | |
731 | ut_assertok(bootdev_next_prio(&iter, &dev)); | |
732 | ut_asserteq_str("mmc1.bootdev", dev->name); | |
733 | ||
734 | ut_assertok(bootdev_next_prio(&iter, &dev)); | |
735 | ut_asserteq_str("mmc0.bootdev", dev->name); | |
736 | ut_assert_console_end(); | |
737 | ||
738 | ut_assertok(bootdev_next_prio(&iter, &dev)); | |
739 | ut_asserteq_str("[email protected]", dev->name); | |
740 | ut_assert_skip_to_line("Hunting with: spi_flash"); | |
741 | ||
742 | /* | |
743 | * this scans all bootdevs of priority BOOTDEVP_4_SCAN_FAST before it | |
744 | * starts looking at the devices, so we se virtio as well | |
745 | */ | |
746 | ut_assert_nextline("Hunting with: virtio"); | |
747 | ut_assert_nextlinen("SF: Detected m25p16"); | |
748 | ||
749 | ut_assertok(bootdev_next_prio(&iter, &dev)); | |
750 | ut_asserteq_str("[email protected]", dev->name); | |
751 | ut_assert_nextlinen("SF: Detected m25p16"); | |
752 | ut_assert_console_end(); | |
753 | ||
754 | /* keep going until there are no more bootdevs */ | |
755 | do { | |
756 | ret = bootdev_next_prio(&iter, &dev); | |
757 | } while (!ret); | |
758 | ut_asserteq(-ENODEV, ret); | |
759 | ut_assertnull(dev); | |
18552d2a | 760 | ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used); |
43e89a30 SG |
761 | |
762 | ut_assert_skip_to_line("Hunting with: ethernet"); | |
763 | ut_assert_console_end(); | |
764 | ||
765 | return 0; | |
766 | } | |
767 | BOOTSTD_TEST(bootdev_test_next_prio, UT_TESTF_DM | UT_TESTF_SCAN_FDT | | |
768 | UT_TESTF_SF_BOOTDEV); |