bootdev.c 22 KB

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