"Das U-Boot" Source Tree
at master 1415 lines 48 kB view raw
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 9#include <bootdev.h> 10#include <bootflow.h> 11#include <bootmeth.h> 12#include <bootstd.h> 13#include <cli.h> 14#include <dm.h> 15#include <efi.h> 16#include <efi_loader.h> 17#include <expo.h> 18#include <mapmem.h> 19#ifdef CONFIG_SANDBOX 20#include <asm/test.h> 21#endif 22#include <dm/device-internal.h> 23#include <dm/lists.h> 24#include <test/suites.h> 25#include <test/ut.h> 26#include "bootstd_common.h" 27#include "../../boot/bootflow_internal.h" 28#include "../../boot/scene_internal.h" 29 30DECLARE_GLOBAL_DATA_PTR; 31 32extern U_BOOT_DRIVER(bootmeth_android); 33extern U_BOOT_DRIVER(bootmeth_cros); 34extern U_BOOT_DRIVER(bootmeth_2script); 35 36/* Use this as the vendor for EFI to tell the app to exit boot services */ 37static u16 __efi_runtime_data test_vendor[] = u"U-Boot testing"; 38 39static int inject_response(struct unit_test_state *uts) 40{ 41 /* 42 * The image being booted presents a menu of options: 43 * 44 * Fedora-Workstation-armhfp-31-1.9 Boot Options. 45 * 1: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) 46 * Enter choice: 47 * 48 * Provide input for this, to avoid waiting two seconds for a timeout. 49 */ 50 ut_asserteq(2, console_in_puts("1\n")); 51 52 return 0; 53} 54 55/* Check 'bootflow scan/list' commands */ 56static int bootflow_cmd(struct unit_test_state *uts) 57{ 58 ut_assertok(run_command("bootdev select 1", 0)); 59 ut_assert_console_end(); 60 ut_assertok(run_command("bootflow scan -lH", 0)); 61 ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'"); 62 ut_assert_nextline("Seq Method State Uclass Part Name Filename"); 63 ut_assert_nextlinen("---"); 64 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':"); 65 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':"); 66 ut_assert_nextline(" 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); 67 ut_assert_nextline("No more bootdevs"); 68 ut_assert_nextlinen("---"); 69 ut_assert_nextline("(1 bootflow, 1 valid)"); 70 ut_assert_console_end(); 71 72 ut_assertok(run_command("bootflow list", 0)); 73 ut_assert_nextline("Showing bootflows for bootdev 'mmc1.bootdev'"); 74 ut_assert_nextline("Seq Method State Uclass Part Name Filename"); 75 ut_assert_nextlinen("---"); 76 ut_assert_nextline(" 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); 77 ut_assert_nextlinen("---"); 78 ut_assert_nextline("(1 bootflow, 1 valid)"); 79 ut_assert_console_end(); 80 81 ut_assertok(run_command("bootstd images", 0)); 82 ut_assert_nextlinen("Seq"); 83 ut_assert_nextlinen("---"); 84 ut_assert_nextlinen(" 0 mmc1.bootdev.part_1 extlinux_cfg"); 85 ut_assert_nextlinen("---"); 86 ut_assert_nextline("(1 image)"); 87 ut_assert_console_end(); 88 89 return 0; 90} 91BOOTSTD_TEST(bootflow_cmd, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); 92 93/* Check 'bootflow scan' with a label / seq */ 94static int bootflow_cmd_label(struct unit_test_state *uts) 95{ 96 test_set_eth_enable(false); 97 98 ut_assertok(run_command("bootflow scan -lH mmc1", 0)); 99 ut_assert_nextline("Scanning for bootflows with label 'mmc1'"); 100 ut_assert_skip_to_line("(1 bootflow, 1 valid)"); 101 ut_assert_console_end(); 102 103 ut_assertok(run_command("bootflow scan -lH 0", 0)); 104 ut_assert_nextline("Scanning for bootflows with label '0'"); 105 ut_assert_skip_to_line("(0 bootflows, 0 valid)"); 106 ut_assert_console_end(); 107 108 /* 109 * with ethernet enabled we have 8 devices ahead of the mmc ones: 110 * 111 * ut_assertok(run_command("bootdev list", 0)); 112 * Seq Probed Status Uclass Name 113 * --- ------ ------ -------- ------------------ 114 * 0 [ + ] OK ethernet eth@10002000.bootdev 115 * 1 [ ] OK ethernet eth@10003000.bootdev 116 * 2 [ ] OK ethernet sbe5.bootdev 117 * 3 [ ] OK ethernet eth@10004000.bootdev 118 * 4 [ ] OK ethernet phy-test-eth.bootdev 119 * 5 [ ] OK ethernet dsa-test-eth.bootdev 120 * 6 [ ] OK ethernet dsa-test@0.bootdev 121 * 7 [ ] OK ethernet dsa-test@1.bootdev 122 * 8 [ ] OK mmc mmc2.bootdev 123 * 9 [ + ] OK mmc mmc1.bootdev 124 * a [ ] OK mmc mmc0.bootdev 125 * 126 * However with CONFIG_DSA_SANDBOX=n we have two fewer (dsa-test@0 and 127 * dsa-test@1). 128 */ 129 if (CONFIG_IS_ENABLED(DSA_SANDBOX)) { 130 ut_assertok(run_command("bootflow scan -lH 9", 0)); 131 ut_assert_nextline("Scanning for bootflows with label '9'"); 132 } else { 133 ut_assertok(run_command("bootflow scan -lH 7", 0)); 134 ut_assert_nextline("Scanning for bootflows with label '7'"); 135 } 136 ut_assert_skip_to_line("(1 bootflow, 1 valid)"); 137 138 ut_assertok(run_command("bootflow scan -lH 0", 0)); 139 ut_assert_nextline("Scanning for bootflows with label '0'"); 140 ut_assert_skip_to_line("(0 bootflows, 0 valid)"); 141 ut_assert_console_end(); 142 143 return 0; 144} 145BOOTSTD_TEST(bootflow_cmd_label, UTF_DM | UTF_SCAN_FDT | UTF_ETH_BOOTDEV | 146 UTF_CONSOLE); 147 148/* Check 'bootflow scan/list' commands using all bootdevs */ 149static int bootflow_cmd_glob(struct unit_test_state *uts) 150{ 151 ut_assertok(bootstd_test_drop_bootdev_order(uts)); 152 153 ut_assertok(run_command("bootflow scan -lGH", 0)); 154 ut_assert_nextline("Scanning for bootflows in all bootdevs"); 155 ut_assert_nextline("Seq Method State Uclass Part Name Filename"); 156 ut_assert_nextlinen("---"); 157 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':"); 158 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':"); 159 ut_assert_nextline(" 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); 160 ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':"); 161 ut_assert_nextline("No more bootdevs"); 162 ut_assert_nextlinen("---"); 163 ut_assert_nextline("(1 bootflow, 1 valid)"); 164 ut_assert_console_end(); 165 166 ut_assertok(run_command("bootflow list", 0)); 167 ut_assert_nextline("Showing all bootflows"); 168 ut_assert_nextline("Seq Method State Uclass Part Name Filename"); 169 ut_assert_nextlinen("---"); 170 ut_assert_nextline(" 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); 171 ut_assert_nextlinen("---"); 172 ut_assert_nextline("(1 bootflow, 1 valid)"); 173 ut_assert_console_end(); 174 175 return 0; 176} 177BOOTSTD_TEST(bootflow_cmd_glob, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); 178 179/* Check 'bootflow scan -e' */ 180static int bootflow_cmd_scan_e(struct unit_test_state *uts) 181{ 182 ut_assertok(bootstd_test_drop_bootdev_order(uts)); 183 184 ut_assertok(run_command("bootflow scan -aleGH", 0)); 185 ut_assert_nextline("Scanning for bootflows in all bootdevs"); 186 ut_assert_nextline("Seq Method State Uclass Part Name Filename"); 187 ut_assert_nextlinen("---"); 188 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':"); 189 ut_assert_nextline(" 0 extlinux media mmc 0 mmc2.bootdev.whole "); 190 ut_assert_nextline(" ** No partition found, err=-93: Protocol not supported"); 191 ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole "); 192 ut_assert_nextline(" ** No partition found, err=-93: Protocol not supported"); 193 194 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':"); 195 ut_assert_nextline(" 2 extlinux media mmc 0 mmc1.bootdev.whole "); 196 ut_assert_nextline(" ** No partition found, err=-2: No such file or directory"); 197 ut_assert_nextline(" 3 efi media mmc 0 mmc1.bootdev.whole "); 198 ut_assert_nextline(" ** No partition found, err=-2: No such file or directory"); 199 ut_assert_nextline(" 4 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); 200 ut_assert_nextline( 201 " 5 efi fs mmc 1 mmc1.bootdev.part_1 /EFI/BOOT/%s", 202 efi_get_basename()); 203 204 ut_assert_skip_to_line("Scanning bootdev 'mmc0.bootdev':"); 205 ut_assert_skip_to_line( 206 " 3f efi media mmc 0 mmc0.bootdev.whole "); 207 ut_assert_nextline(" ** No partition found, err=-93: Protocol not supported"); 208 ut_assert_nextline("No more bootdevs"); 209 ut_assert_nextlinen("---"); 210 ut_assert_nextline("(64 bootflows, 1 valid)"); 211 ut_assert_console_end(); 212 213 ut_assertok(run_command("bootflow list", 0)); 214 ut_assert_nextline("Showing all bootflows"); 215 ut_assert_nextline("Seq Method State Uclass Part Name Filename"); 216 ut_assert_nextlinen("---"); 217 ut_assert_nextline(" 0 extlinux media mmc 0 mmc2.bootdev.whole "); 218 ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole "); 219 ut_assert_skip_to_line( 220 " 4 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); 221 ut_assert_skip_to_line(" 3f efi media mmc 0 mmc0.bootdev.whole "); 222 ut_assert_nextlinen("---"); 223 ut_assert_nextline("(64 bootflows, 1 valid)"); 224 ut_assert_console_end(); 225 226 return 0; 227} 228BOOTSTD_TEST(bootflow_cmd_scan_e, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); 229 230/* Check 'bootflow info' */ 231static int bootflow_cmd_info(struct unit_test_state *uts) 232{ 233 ut_assertok(run_command("bootdev select 1", 0)); 234 ut_assert_console_end(); 235 ut_assertok(run_command("bootflow scan", 0)); 236 ut_assert_console_end(); 237 ut_assertok(run_command("bootflow select 0", 0)); 238 ut_assert_console_end(); 239 ut_assertok(run_command("bootflow info", 0)); 240 ut_assert_nextline("Name: mmc1.bootdev.part_1"); 241 ut_assert_nextline("Device: mmc1.bootdev"); 242 ut_assert_nextline("Block dev: mmc1.blk"); 243 ut_assert_nextline("Method: extlinux"); 244 ut_assert_nextline("State: ready"); 245 ut_assert_nextline("Partition: 1"); 246 ut_assert_nextline("Subdir: (none)"); 247 ut_assert_nextline("Filename: /extlinux/extlinux.conf"); 248 ut_assert_nextlinen("Buffer: "); 249 ut_assert_nextline("Size: 253 (595 bytes)"); 250 ut_assert_nextline("OS: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)"); 251 ut_assert_nextline("Cmdline: (none)"); 252 ut_assert_nextline("Logo: (none)"); 253 ut_assert_nextline("FDT: <NULL>"); 254 ut_assert_nextline("Error: 0"); 255 ut_assert_console_end(); 256 257 ut_assertok(run_command("bootflow info -d", 0)); 258 ut_assert_nextline("Name: mmc1.bootdev.part_1"); 259 ut_assert_skip_to_line("Error: 0"); 260 ut_assert_nextline("Contents:"); 261 ut_assert_nextline("%s", ""); 262 ut_assert_nextline("# extlinux.conf generated by appliance-creator"); 263 ut_assert_skip_to_line(" initrd /initramfs-5.3.7-301.fc31.armv7hl.img"); 264 ut_assert_console_end(); 265 266 return 0; 267} 268BOOTSTD_TEST(bootflow_cmd_info, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); 269 270/* Check 'bootflow scan -b' to boot the first available bootdev */ 271static int bootflow_scan_boot(struct unit_test_state *uts) 272{ 273 ut_assertok(inject_response(uts)); 274 ut_assertok(run_command("bootflow scan -b", 0)); 275 ut_assert_nextline( 276 "** Booting bootflow 'mmc1.bootdev.part_1' with extlinux"); 277 ut_assert_nextline("Ignoring unknown command: ui"); 278 279 /* 280 * We expect it to get through to boot although sandbox always returns 281 * -EFAULT as it cannot actually boot the kernel 282 */ 283 ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux"); 284 ut_assert_nextline("Boot failed (err=-14)"); 285 ut_assert_console_end(); 286 287 return 0; 288} 289BOOTSTD_TEST(bootflow_scan_boot, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); 290 291/* Check iterating through available bootflows */ 292static int bootflow_iter(struct unit_test_state *uts) 293{ 294 struct bootflow_iter iter; 295 struct bootflow bflow; 296 297 bootstd_clear_glob(); 298 299 /* The first device is mmc2.bootdev which has no media */ 300 ut_asserteq(-EPROTONOSUPPORT, 301 bootflow_scan_first(NULL, NULL, &iter, 302 BOOTFLOWIF_ALL | BOOTFLOWIF_SKIP_GLOBAL, &bflow)); 303 ut_asserteq(2, iter.num_methods); 304 ut_asserteq(0, iter.cur_method); 305 ut_asserteq(0, iter.part); 306 ut_asserteq(0, iter.max_part); 307 ut_asserteq_str("extlinux", iter.method->name); 308 ut_asserteq(0, bflow.err); 309 310 /* 311 * This shows MEDIA even though there is none, since in 312 * bootdev_find_in_blk() we call part_get_info() which returns 313 * -EPROTONOSUPPORT. Ideally it would return -EEOPNOTSUPP and we would 314 * know. 315 */ 316 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); 317 318 ut_asserteq(-EPROTONOSUPPORT, bootflow_scan_next(&iter, &bflow)); 319 ut_asserteq(2, iter.num_methods); 320 ut_asserteq(1, iter.cur_method); 321 ut_asserteq(0, iter.part); 322 ut_asserteq(0, iter.max_part); 323 ut_asserteq_str("efi", iter.method->name); 324 ut_asserteq(0, bflow.err); 325 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); 326 bootflow_free(&bflow); 327 328 /* The next device is mmc1.bootdev - at first we use the whole device */ 329 ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow)); 330 ut_asserteq(2, iter.num_methods); 331 ut_asserteq(0, iter.cur_method); 332 ut_asserteq(0, iter.part); 333 ut_asserteq(0x1e, iter.max_part); 334 ut_asserteq_str("extlinux", iter.method->name); 335 ut_asserteq(0, bflow.err); 336 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); 337 bootflow_free(&bflow); 338 339 ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow)); 340 ut_asserteq(2, iter.num_methods); 341 ut_asserteq(1, iter.cur_method); 342 ut_asserteq(0, iter.part); 343 ut_asserteq(0x1e, iter.max_part); 344 ut_asserteq_str("efi", iter.method->name); 345 ut_asserteq(0, bflow.err); 346 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); 347 bootflow_free(&bflow); 348 349 /* Then more to partition 1 where we find something */ 350 ut_assertok(bootflow_scan_next(&iter, &bflow)); 351 ut_asserteq(2, iter.num_methods); 352 ut_asserteq(0, iter.cur_method); 353 ut_asserteq(1, iter.part); 354 ut_asserteq(0x1e, iter.max_part); 355 ut_asserteq_str("extlinux", iter.method->name); 356 ut_asserteq(0, bflow.err); 357 ut_asserteq(BOOTFLOWST_READY, bflow.state); 358 bootflow_free(&bflow); 359 360 ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow)); 361 ut_asserteq(2, iter.num_methods); 362 ut_asserteq(1, iter.cur_method); 363 ut_asserteq(1, iter.part); 364 ut_asserteq(0x1e, iter.max_part); 365 ut_asserteq_str("efi", iter.method->name); 366 ut_asserteq(0, bflow.err); 367 ut_asserteq(BOOTFLOWST_FS, bflow.state); 368 bootflow_free(&bflow); 369 370 /* Then more to partition 2 which exists but is not bootable */ 371 ut_asserteq(-EINVAL, bootflow_scan_next(&iter, &bflow)); 372 ut_asserteq(2, iter.num_methods); 373 ut_asserteq(0, iter.cur_method); 374 ut_asserteq(2, iter.part); 375 ut_asserteq(0x1e, iter.max_part); 376 ut_asserteq_str("extlinux", iter.method->name); 377 ut_asserteq(0, bflow.err); 378 ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); 379 bootflow_free(&bflow); 380 381 bootflow_iter_uninit(&iter); 382 383 ut_assert_console_end(); 384 385 return 0; 386} 387BOOTSTD_TEST(bootflow_iter, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); 388 389#if defined(CONFIG_SANDBOX) && defined(CONFIG_BOOTMETH_GLOBAL) 390/* Check using the system bootdev */ 391static int bootflow_system(struct unit_test_state *uts) 392{ 393 struct udevice *bootstd, *dev; 394 395 if (!IS_ENABLED(CONFIG_EFI_BOOTMGR)) 396 return -EAGAIN; 397 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); 398 ut_assertok(device_bind(bootstd, DM_DRIVER_GET(bootmeth_3efi_mgr), 399 "efi_mgr", 0, ofnode_null(), &dev)); 400 ut_assertok(device_probe(dev)); 401 sandbox_set_fake_efi_mgr_dev(dev, true); 402 403 /* We should get a single 'bootmgr' method right at the end */ 404 bootstd_clear_glob(); 405 ut_assertok(run_command("bootflow scan -lH", 0)); 406 ut_assert_skip_to_line( 407 " 0 efi_mgr ready (none) 0 <NULL> "); 408 ut_assert_skip_to_line("No more bootdevs"); 409 ut_assert_skip_to_line("(2 bootflows, 2 valid)"); 410 ut_assert_console_end(); 411 412 return 0; 413} 414BOOTSTD_TEST(bootflow_system, UTF_DM | UTF_SCAN_PDATA | UTF_SCAN_FDT | 415 UTF_CONSOLE); 416#endif 417 418/* Check disabling a bootmethod if it requests it */ 419static int bootflow_iter_disable(struct unit_test_state *uts) 420{ 421 struct udevice *bootstd, *dev; 422 struct bootflow_iter iter; 423 struct bootflow bflow; 424 int i; 425 426 /* Add the EFI bootmgr driver */ 427 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); 428 ut_assertok(device_bind_driver(bootstd, "bootmeth_sandbox", "sandbox", 429 &dev)); 430 431 ut_assertok(bootstd_test_drop_bootdev_order(uts)); 432 433 bootstd_clear_glob(); 434 ut_assertok(inject_response(uts)); 435 ut_assertok(run_command("bootflow scan -lbH", 0)); 436 437 /* Try to boot the bootmgr flow, which will fail */ 438 console_record_reset_enable(); 439 ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); 440 ut_asserteq(3, iter.num_methods); 441 ut_asserteq_str("sandbox", iter.method->name); 442 ut_assertok(inject_response(uts)); 443 ut_asserteq(-ENOTSUPP, bootflow_run_boot(&iter, &bflow)); 444 445 ut_assert_skip_to_line("Boot method 'sandbox' failed and will not be retried"); 446 ut_assert_console_end(); 447 448 /* Check that the sandbox bootmeth has been removed */ 449 ut_asserteq(2, iter.num_methods); 450 for (i = 0; i < iter.num_methods; i++) 451 ut_assert(strcmp("sandbox", iter.method_order[i]->name)); 452 453 return 0; 454} 455BOOTSTD_TEST(bootflow_iter_disable, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); 456 457/* Check 'bootflow scan' with a bootmeth ordering including a global bootmeth */ 458static int bootflow_scan_glob_bootmeth(struct unit_test_state *uts) 459{ 460 if (!IS_ENABLED(CONFIG_BOOTMETH_GLOBAL)) 461 return -EAGAIN; 462 463 ut_assertok(bootstd_test_drop_bootdev_order(uts)); 464 465 /* 466 * Make sure that the -G flag makes the scan fail, since this is not 467 * supported when an ordering is provided 468 */ 469 ut_assertok(bootmeth_set_order("efi firmware0")); 470 ut_assertok(run_command("bootflow scan -lGH", 0)); 471 ut_assert_nextline("Scanning for bootflows in all bootdevs"); 472 ut_assert_nextline( 473 "Seq Method State Uclass Part Name Filename"); 474 ut_assert_nextlinen("---"); 475 ut_assert_nextlinen("---"); 476 ut_assert_nextline("(0 bootflows, 0 valid)"); 477 ut_assert_console_end(); 478 479 ut_assertok(run_command("bootflow scan -lH", 0)); 480 ut_assert_nextline("Scanning for bootflows in all bootdevs"); 481 ut_assert_nextline( 482 "Seq Method State Uclass Part Name Filename"); 483 ut_assert_nextlinen("---"); 484 ut_assert_nextline("Scanning global bootmeth 'firmware0':"); 485 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':"); 486 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':"); 487 ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':"); 488 ut_assert_nextline("No more bootdevs"); 489 ut_assert_nextlinen("---"); 490 ut_assert_nextline("(0 bootflows, 0 valid)"); 491 ut_assert_console_end(); 492 493 return 0; 494} 495BOOTSTD_TEST(bootflow_scan_glob_bootmeth, UTF_DM | UTF_SCAN_FDT | 496 UTF_CONSOLE); 497 498/* Check 'bootflow boot' to boot a selected bootflow */ 499static int bootflow_cmd_boot(struct unit_test_state *uts) 500{ 501 ut_assertok(run_command("bootdev select 1", 0)); 502 ut_assert_console_end(); 503 ut_assertok(run_command("bootflow scan", 0)); 504 ut_assert_console_end(); 505 ut_assertok(run_command("bootflow select 0", 0)); 506 ut_assert_console_end(); 507 508 ut_assertok(inject_response(uts)); 509 ut_asserteq(1, run_command("bootflow boot", 0)); 510 ut_assert_nextline( 511 "** Booting bootflow 'mmc1.bootdev.part_1' with extlinux"); 512 ut_assert_nextline("Ignoring unknown command: ui"); 513 514 /* 515 * We expect it to get through to boot although sandbox always returns 516 * -EFAULT as it cannot actually boot the kernel 517 */ 518 ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux"); 519 ut_assert_nextline("Boot failed (err=-14)"); 520 ut_assert_console_end(); 521 522 return 0; 523} 524BOOTSTD_TEST(bootflow_cmd_boot, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); 525 526/** 527 * prep_mmc_bootdev() - Set up an mmc bootdev so we can access other distros 528 * 529 * After calling this function, set std->bootdev_order to *@old_orderp to 530 * restore normal operation of bootstd (i.e. with the original bootdev order) 531 * 532 * @uts: Unit test state 533 * @mmc_dev: MMC device to use, e.g. "mmc4". Note that this must remain valid 534 * in the caller until 535 * @bind_cros: true to bind the ChromiumOS and Android bootmeths 536 * @old_orderp: Returns the original bootdev order, which must be restored 537 * Returns 0 on success, -ve on failure 538 */ 539static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, 540 bool bind_cros_android, const char ***old_orderp) 541{ 542 static const char *order[] = {"mmc2", "mmc1", NULL, NULL}; 543 struct udevice *dev, *bootstd; 544 struct bootstd_priv *std; 545 const char **old_order; 546 ofnode root, node; 547 548 order[2] = mmc_dev; 549 550 /* Enable the requested mmc node since we need a second bootflow */ 551 root = oftree_root(oftree_default()); 552 node = ofnode_find_subnode(root, mmc_dev); 553 ut_assert(ofnode_valid(node)); 554 ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false)); 555 556 /* Enable the script bootmeth too */ 557 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); 558 ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_2script), 559 "script", 0, ofnode_null(), &dev)); 560 561 /* Enable the cros bootmeth if needed */ 562 if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros_android) { 563 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); 564 ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_cros), 565 "cros", 0, ofnode_null(), &dev)); 566 } 567 568 /* Enable the android bootmeths if needed */ 569 if (IS_ENABLED(CONFIG_BOOTMETH_ANDROID) && bind_cros_android) { 570 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); 571 ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_android), 572 "android", 0, ofnode_null(), &dev)); 573 } 574 575 /* Change the order to include the device */ 576 std = dev_get_priv(bootstd); 577 old_order = std->bootdev_order; 578 std->bootdev_order = order; 579 *old_orderp = old_order; 580 581 return 0; 582} 583 584/** 585 * scan_mmc_bootdev() - Set up an mmc bootdev so we can access other distros 586 * 587 * @uts: Unit test state 588 * @mmc_dev: MMC device to use, e.g. "mmc4" 589 * @bind_cros: true to bind the ChromiumOS bootmeth 590 * Returns 0 on success, -ve on failure 591 */ 592static int scan_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, 593 bool bind_cros) 594{ 595 struct bootstd_priv *std; 596 struct udevice *bootstd; 597 const char **old_order; 598 599 ut_assertok(prep_mmc_bootdev(uts, mmc_dev, bind_cros, &old_order)); 600 601 ut_assertok(run_command("bootflow scan", 0)); 602 ut_assert_console_end(); 603 604 /* Restore the order used by the device tree */ 605 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); 606 std = dev_get_priv(bootstd); 607 std->bootdev_order = old_order; 608 609 return 0; 610} 611 612/** 613 * scan_mmc_android_bootdev() - Set up an mmc bootdev so we can access other 614 * distros. Android bootflow might print "ANDROID:*" while scanning 615 * 616 * @uts: Unit test state 617 * @mmc_dev: MMC device to use, e.g. "mmc4" 618 * Returns 0 on success, -ve on failure 619 */ 620static int scan_mmc_android_bootdev(struct unit_test_state *uts, const char *mmc_dev) 621{ 622 struct bootstd_priv *std; 623 struct udevice *bootstd; 624 const char **old_order; 625 626 ut_assertok(prep_mmc_bootdev(uts, mmc_dev, true, &old_order)); 627 628 ut_assertok(run_command("bootflow scan", 0)); 629 /* Android bootflow might print one or two 'ANDROID:*' logs */ 630 ut_check_skipline(uts); 631 ut_check_skipline(uts); 632 ut_assert_console_end(); 633 634 /* Restore the order used by the device tree */ 635 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); 636 std = dev_get_priv(bootstd); 637 std->bootdev_order = old_order; 638 639 return 0; 640} 641 642/** 643 * scan_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian 644 * 645 * @uts: Unit test state 646 * Returns 0 on success, -ve on failure 647 */ 648static int scan_mmc4_bootdev(struct unit_test_state *uts) 649{ 650 ut_assertok(scan_mmc_bootdev(uts, "mmc4", false)); 651 652 return 0; 653} 654 655/* Check 'bootflow menu' to select a bootflow */ 656static int bootflow_cmd_menu(struct unit_test_state *uts) 657{ 658 struct bootstd_priv *std; 659 char prev[3]; 660 661 /* get access to the current bootflow */ 662 ut_assertok(bootstd_get_priv(&std)); 663 664 ut_assertok(scan_mmc4_bootdev(uts)); 665 666 /* Add keypresses to move to and select the second one in the list */ 667 prev[0] = CTL_CH('n'); 668 prev[1] = '\r'; 669 prev[2] = '\0'; 670 ut_asserteq(2, console_in_puts(prev)); 671 672 ut_assertok(run_command("bootflow menu", 0)); 673 ut_assert_nextline("Selected: Armbian"); 674 ut_assertnonnull(std->cur_bootflow); 675 ut_assert_console_end(); 676 677 /* Check not selecting anything */ 678 prev[0] = '\e'; 679 prev[1] = '\0'; 680 ut_asserteq(1, console_in_puts(prev)); 681 682 ut_asserteq(1, run_command("bootflow menu", 0)); 683 ut_assertnull(std->cur_bootflow); 684 ut_assert_nextline("Nothing chosen"); 685 ut_assert_console_end(); 686 687 return 0; 688} 689BOOTSTD_TEST(bootflow_cmd_menu, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); 690 691/* Check 'bootflow scan -m' to select a bootflow using a menu */ 692static int bootflow_scan_menu(struct unit_test_state *uts) 693{ 694 struct bootstd_priv *std; 695 const char **old_order, **new_order; 696 char prev[3]; 697 698 /* get access to the current bootflow */ 699 ut_assertok(bootstd_get_priv(&std)); 700 701 ut_assertok(prep_mmc_bootdev(uts, "mmc4", false, &old_order)); 702 703 /* Add keypresses to move to and select the second one in the list */ 704 prev[0] = CTL_CH('n'); 705 prev[1] = '\r'; 706 prev[2] = '\0'; 707 ut_asserteq(2, console_in_puts(prev)); 708 709 ut_assertok(run_command("bootflow scan -lm", 0)); 710 new_order = std->bootdev_order; 711 std->bootdev_order = old_order; 712 713 ut_assert_skip_to_line("No more bootdevs"); 714 ut_assert_nextlinen("--"); 715 ut_assert_nextline("(2 bootflows, 2 valid)"); 716 717 ut_assert_nextline("Selected: Armbian"); 718 ut_assertnonnull(std->cur_bootflow); 719 ut_assert_console_end(); 720 721 /* Check not selecting anything */ 722 prev[0] = '\e'; 723 prev[1] = '\0'; 724 ut_asserteq(1, console_in_puts(prev)); 725 726 std->bootdev_order = new_order; /* Blue Monday */ 727 ut_assertok(run_command("bootflow scan -lm", 0)); 728 std->bootdev_order = old_order; 729 730 ut_assertnull(std->cur_bootflow); 731 ut_assert_skip_to_line("(2 bootflows, 2 valid)"); 732 ut_assert_nextline("Nothing chosen"); 733 ut_assert_console_end(); 734 735 return 0; 736} 737BOOTSTD_TEST(bootflow_scan_menu, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); 738 739/* Check 'bootflow scan -mb' to select and boot a bootflow using a menu */ 740static int bootflow_scan_menu_boot(struct unit_test_state *uts) 741{ 742 struct bootstd_priv *std; 743 const char **old_order; 744 char prev[3]; 745 746 /* get access to the current bootflow */ 747 ut_assertok(bootstd_get_priv(&std)); 748 749 ut_assertok(prep_mmc_bootdev(uts, "mmc4", false, &old_order)); 750 751 /* Add keypresses to move to and select the second one in the list */ 752 prev[0] = CTL_CH('n'); 753 prev[1] = '\r'; 754 prev[2] = '\0'; 755 ut_asserteq(2, console_in_puts(prev)); 756 757 ut_assertok(run_command("bootflow scan -lmb", 0)); 758 std->bootdev_order = old_order; 759 760 ut_assert_skip_to_line("(2 bootflows, 2 valid)"); 761 762 ut_assert_nextline("Selected: Armbian"); 763 764 if (gd->flags & GD_FLG_HUSH_OLD_PARSER) { 765 /* 766 * With old hush, despite booti failing to boot, i.e. returning 767 * CMD_RET_FAILURE, run_command() returns 0 which leads bootflow_boot(), as 768 * we are using bootmeth_script here, to return -EFAULT. 769 */ 770 ut_assert_skip_to_line("Boot failed (err=-14)"); 771 } else if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) { 772 /* 773 * While with modern one, run_command() propagates CMD_RET_FAILURE returned 774 * by booti, so we get 1 here. 775 */ 776 ut_assert_skip_to_line("Boot failed (err=1)"); 777 } 778 ut_assertnonnull(std->cur_bootflow); 779 ut_assert_console_end(); 780 781 return 0; 782} 783BOOTSTD_TEST(bootflow_scan_menu_boot, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); 784 785/* Check searching for a single bootdev using the hunters */ 786static int bootflow_cmd_hunt_single(struct unit_test_state *uts) 787{ 788 struct bootstd_priv *std; 789 790 /* get access to the used hunters */ 791 ut_assertok(bootstd_get_priv(&std)); 792 793 ut_assertok(bootstd_test_drop_bootdev_order(uts)); 794 795 ut_assertok(run_command("bootflow scan -l mmc1", 0)); 796 ut_assert_nextline("Scanning for bootflows with label 'mmc1'"); 797 ut_assert_skip_to_line("(1 bootflow, 1 valid)"); 798 ut_assert_console_end(); 799 800 /* check that the hunter was used */ 801 ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used); 802 803 return 0; 804} 805BOOTSTD_TEST(bootflow_cmd_hunt_single, UTF_DM | UTF_SCAN_FDT | 806 UTF_CONSOLE); 807 808/* Check searching for a uclass label using the hunters */ 809static int bootflow_cmd_hunt_label(struct unit_test_state *uts) 810{ 811 struct bootstd_priv *std; 812 813 /* get access to the used hunters */ 814 ut_assertok(bootstd_get_priv(&std)); 815 816 test_set_skip_delays(true); 817 test_set_eth_enable(false); 818 ut_assertok(bootstd_test_drop_bootdev_order(uts)); 819 820 ut_assertok(run_command("bootflow scan -l mmc", 0)); 821 822 /* check that the hunter was used */ 823 ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used); 824 825 /* check that we got the mmc1 bootflow */ 826 ut_assert_nextline("Scanning for bootflows with label 'mmc'"); 827 ut_assert_nextlinen("Seq"); 828 ut_assert_nextlinen("---"); 829 ut_assert_nextline("Hunting with: simple_bus"); 830 ut_assert_nextline("Found 2 extension board(s)."); 831 ut_assert_nextline("Hunting with: mmc"); 832 ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':"); 833 ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':"); 834 ut_assert_nextline( 835 " 0 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); 836 ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':"); 837 ut_assert_skip_to_line("(1 bootflow, 1 valid)"); 838 ut_assert_console_end(); 839 840 return 0; 841} 842BOOTSTD_TEST(bootflow_cmd_hunt_label, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); 843 844/** 845 * check_font() - Check that the font size for an item matches expectations 846 * 847 * @uts: Unit test state 848 * @scn: Scene containing the text object 849 * @id: ID of the text object 850 * Returns 0 on success, -ve on failure 851 */ 852static int check_font(struct unit_test_state *uts, struct scene *scn, uint id, 853 int font_size) 854{ 855 struct scene_obj_txt *txt; 856 857 txt = scene_obj_find(scn, id, SCENEOBJT_TEXT); 858 ut_assertnonnull(txt); 859 860 ut_asserteq(font_size, txt->font_size); 861 862 return 0; 863} 864 865/* Check themes work with a bootflow menu */ 866static int bootflow_menu_theme(struct unit_test_state *uts) 867{ 868 const int font_size = 30; 869 struct scene *scn; 870 struct expo *exp; 871 ofnode node; 872 int i; 873 874 if (!CONFIG_IS_ENABLED(BOOTSTD_MENU)) 875 return -EAGAIN; 876 877 ut_assertok(scan_mmc4_bootdev(uts)); 878 879 ut_assertok(bootflow_menu_new(&exp)); 880 node = ofnode_path("/bootstd/theme"); 881 ut_assert(ofnode_valid(node)); 882 ut_assertok(bootflow_menu_apply_theme(exp, node)); 883 884 scn = expo_lookup_scene_id(exp, MAIN); 885 ut_assertnonnull(scn); 886 887 /* 888 * Check that the txt objects have the correct font size from the 889 * device tree node: bootstd/theme 890 * 891 * Check both menu items, since there are two bootflows 892 */ 893 ut_assertok(check_font(uts, scn, OBJ_PROMPT, font_size)); 894 ut_assertok(check_font(uts, scn, OBJ_POINTER, font_size)); 895 for (i = 0; i < 2; i++) { 896 ut_assertok(check_font(uts, scn, ITEM_DESC + i, font_size)); 897 ut_assertok(check_font(uts, scn, ITEM_KEY + i, font_size)); 898 ut_assertok(check_font(uts, scn, ITEM_LABEL + i, font_size)); 899 } 900 901 expo_destroy(exp); 902 903 return 0; 904} 905BOOTSTD_TEST(bootflow_menu_theme, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); 906 907/** 908 * check_arg() - Check both the normal case and the buffer-overflow case 909 * 910 * @uts: Unit-test state 911 * @expect_ret: Expected return value (i.e. buffer length) 912 * @expect_str: String expected to be returned 913 * @buf: Buffer to use 914 * @from: Original cmdline to update 915 * @arg: Argument to update (e.g. "console") 916 * @val: Value to set (e.g. "ttyS2") or NULL to delete the argument if present, 917 * "" to set it to an empty value (e.g. "console=") and BOOTFLOWCL_EMPTY to add 918 * it without any value ("initrd") 919 */ 920static int check_arg(struct unit_test_state *uts, int expect_ret, 921 const char *expect_str, char *buf, const char *from, 922 const char *arg, const char *val) 923{ 924 /* check for writing outside the reported bounds */ 925 buf[expect_ret] = '['; 926 ut_asserteq(expect_ret, 927 cmdline_set_arg(buf, expect_ret, from, arg, val, NULL)); 928 ut_asserteq_str(expect_str, buf); 929 ut_asserteq('[', buf[expect_ret]); 930 931 /* do the test again but with one less byte in the buffer */ 932 ut_asserteq(-E2BIG, cmdline_set_arg(buf, expect_ret - 1, from, arg, 933 val, NULL)); 934 935 return 0; 936} 937 938/* Test of bootflow_cmdline_set_arg() */ 939static int test_bootflow_cmdline_set(struct unit_test_state *uts) 940{ 941 char buf[50]; 942 const int size = sizeof(buf); 943 944 /* 945 * note that buffer-overflow tests are immediately each test case, just 946 * top keep the code together 947 */ 948 949 /* add an arg that doesn't already exist, starting from empty */ 950 ut_asserteq(-ENOENT, cmdline_set_arg(buf, size, NULL, "me", NULL, 951 NULL)); 952 953 ut_assertok(check_arg(uts, 3, "me", buf, NULL, "me", BOOTFLOWCL_EMPTY)); 954 ut_assertok(check_arg(uts, 4, "me=", buf, NULL, "me", "")); 955 ut_assertok(check_arg(uts, 8, "me=fred", buf, NULL, "me", "fred")); 956 957 /* add an arg that doesn't already exist, starting from non-empty */ 958 ut_assertok(check_arg(uts, 11, "arg=123 me", buf, "arg=123", "me", 959 BOOTFLOWCL_EMPTY)); 960 ut_assertok(check_arg(uts, 12, "arg=123 me=", buf, "arg=123", "me", 961 "")); 962 ut_assertok(check_arg(uts, 16, "arg=123 me=fred", buf, "arg=123", "me", 963 "fred")); 964 965 /* update an arg at the start */ 966 ut_assertok(check_arg(uts, 1, "", buf, "arg=123", "arg", NULL)); 967 ut_assertok(check_arg(uts, 4, "arg", buf, "arg=123", "arg", 968 BOOTFLOWCL_EMPTY)); 969 ut_assertok(check_arg(uts, 5, "arg=", buf, "arg=123", "arg", "")); 970 ut_assertok(check_arg(uts, 6, "arg=1", buf, "arg=123", "arg", "1")); 971 ut_assertok(check_arg(uts, 9, "arg=1234", buf, "arg=123", "arg", 972 "1234")); 973 974 /* update an arg at the end */ 975 ut_assertok(check_arg(uts, 5, "mary", buf, "mary arg=123", "arg", 976 NULL)); 977 ut_assertok(check_arg(uts, 9, "mary arg", buf, "mary arg=123", "arg", 978 BOOTFLOWCL_EMPTY)); 979 ut_assertok(check_arg(uts, 10, "mary arg=", buf, "mary arg=123", "arg", 980 "")); 981 ut_assertok(check_arg(uts, 11, "mary arg=1", buf, "mary arg=123", "arg", 982 "1")); 983 ut_assertok(check_arg(uts, 14, "mary arg=1234", buf, "mary arg=123", 984 "arg", "1234")); 985 986 /* update an arg in the middle */ 987 ut_assertok(check_arg(uts, 16, "mary=abc john=2", buf, 988 "mary=abc arg=123 john=2", "arg", NULL)); 989 ut_assertok(check_arg(uts, 20, "mary=abc arg john=2", buf, 990 "mary=abc arg=123 john=2", "arg", 991 BOOTFLOWCL_EMPTY)); 992 ut_assertok(check_arg(uts, 21, "mary=abc arg= john=2", buf, 993 "mary=abc arg=123 john=2", "arg", "")); 994 ut_assertok(check_arg(uts, 22, "mary=abc arg=1 john=2", buf, 995 "mary=abc arg=123 john=2", "arg", "1")); 996 ut_assertok(check_arg(uts, 25, "mary=abc arg=1234 john=2", buf, 997 "mary=abc arg=123 john=2", "arg", "1234")); 998 999 /* handle existing args with quotes */ 1000 ut_assertok(check_arg(uts, 16, "mary=\"abc\" john", buf, 1001 "mary=\"abc\" arg=123 john", "arg", NULL)); 1002 1003 /* handle existing args with quoted spaces */ 1004 ut_assertok(check_arg(uts, 20, "mary=\"abc def\" john", buf, 1005 "mary=\"abc def\" arg=123 john", "arg", NULL)); 1006 1007 ut_assertok(check_arg(uts, 34, "mary=\"abc def\" arg=123 john def=4", 1008 buf, "mary=\"abc def\" arg=123 john", "def", 1009 "4")); 1010 1011 /* quote at the start */ 1012 ut_asserteq(-EBADF, cmdline_set_arg(buf, size, 1013 "mary=\"abc def\" arg=\"123 456\"", 1014 "arg", "\"4 5 6", NULL)); 1015 1016 /* quote at the end */ 1017 ut_asserteq(-EBADF, cmdline_set_arg(buf, size, 1018 "mary=\"abc def\" arg=\"123 456\"", 1019 "arg", "4 5 6\"", NULL)); 1020 1021 /* quote in the middle */ 1022 ut_asserteq(-EBADF, cmdline_set_arg(buf, size, 1023 "mary=\"abc def\" arg=\"123 456\"", 1024 "arg", "\"4 \"5 6\"", NULL)); 1025 1026 /* handle updating a quoted arg */ 1027 ut_assertok(check_arg(uts, 27, "mary=\"abc def\" arg=\"4 5 6\"", buf, 1028 "mary=\"abc def\" arg=\"123 456\"", "arg", 1029 "4 5 6")); 1030 1031 /* changing a quoted arg to a non-quoted arg */ 1032 ut_assertok(check_arg(uts, 23, "mary=\"abc def\" arg=789", buf, 1033 "mary=\"abc def\" arg=\"123 456\"", "arg", 1034 "789")); 1035 1036 /* changing a non-quoted arg to a quoted arg */ 1037 ut_assertok(check_arg(uts, 29, "mary=\"abc def\" arg=\"456 789\"", buf, 1038 "mary=\"abc def\" arg=123", "arg", "456 789")); 1039 1040 /* handling of spaces */ 1041 ut_assertok(check_arg(uts, 8, "arg=123", buf, " ", "arg", "123")); 1042 ut_assertok(check_arg(uts, 8, "arg=123", buf, " ", "arg", "123")); 1043 ut_assertok(check_arg(uts, 13, "john arg=123", buf, " john ", "arg", 1044 "123")); 1045 ut_assertok(check_arg(uts, 13, "john arg=123", buf, " john arg=123 ", 1046 "arg", "123")); 1047 ut_assertok(check_arg(uts, 18, "john arg=123 mary", buf, 1048 " john arg=123 mary ", "arg", "123")); 1049 1050 /* unchanged arg */ 1051 ut_assertok(check_arg(uts, 3, "me", buf, "me", "me", BOOTFLOWCL_EMPTY)); 1052 1053 /* arg which starts with the same name */ 1054 ut_assertok(check_arg(uts, 28, "mary=abc johnathon=2 john=3", buf, 1055 "mary=abc johnathon=2 john=1", "john", "3")); 1056 1057 return 0; 1058} 1059BOOTSTD_TEST(test_bootflow_cmdline_set, 0); 1060 1061/* Test of bootflow_cmdline_set_arg() */ 1062static int bootflow_set_arg(struct unit_test_state *uts) 1063{ 1064 struct bootflow s_bflow, *bflow = &s_bflow; 1065 ulong mem_start; 1066 1067 ut_assertok(env_set("bootargs", NULL)); 1068 1069 mem_start = ut_check_delta(0); 1070 1071 /* Do a simple sanity check. Rely on bootflow_cmdline() for the rest */ 1072 bflow->cmdline = NULL; 1073 ut_assertok(bootflow_cmdline_set_arg(bflow, "fred", "123", false)); 1074 ut_asserteq_str(bflow->cmdline, "fred=123"); 1075 1076 ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", "and here", false)); 1077 ut_asserteq_str(bflow->cmdline, "fred=123 mary=\"and here\""); 1078 1079 ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", NULL, false)); 1080 ut_asserteq_str(bflow->cmdline, "fred=123"); 1081 ut_assertok(bootflow_cmdline_set_arg(bflow, "fred", NULL, false)); 1082 ut_asserteq_ptr(bflow->cmdline, NULL); 1083 1084 ut_asserteq(0, ut_check_delta(mem_start)); 1085 1086 ut_assertok(bootflow_cmdline_set_arg(bflow, "mary", "here", true)); 1087 ut_asserteq_str("mary=here", env_get("bootargs")); 1088 ut_assertok(env_set("bootargs", NULL)); 1089 1090 return 0; 1091} 1092BOOTSTD_TEST(bootflow_set_arg, 0); 1093 1094/* Test of bootflow_cmdline_get_arg() */ 1095static int bootflow_cmdline_get(struct unit_test_state *uts) 1096{ 1097 int pos; 1098 1099 /* empty string */ 1100 ut_asserteq(-ENOENT, cmdline_get_arg("", "fred", &pos)); 1101 1102 /* arg with empty value */ 1103 ut_asserteq(0, cmdline_get_arg("fred= mary", "fred", &pos)); 1104 ut_asserteq(5, pos); 1105 1106 /* arg with a value */ 1107 ut_asserteq(2, cmdline_get_arg("fred=23", "fred", &pos)); 1108 ut_asserteq(5, pos); 1109 1110 /* arg with a value */ 1111 ut_asserteq(3, cmdline_get_arg("mary=1 fred=234", "fred", &pos)); 1112 ut_asserteq(12, pos); 1113 1114 /* arg with a value, after quoted arg */ 1115 ut_asserteq(3, cmdline_get_arg("mary=\"1 2\" fred=234", "fred", &pos)); 1116 ut_asserteq(16, pos); 1117 1118 /* arg in the middle */ 1119 ut_asserteq(0, cmdline_get_arg("mary=\"1 2\" fred john=23", "fred", 1120 &pos)); 1121 ut_asserteq(15, pos); 1122 1123 /* quoted arg */ 1124 ut_asserteq(3, cmdline_get_arg("mary=\"1 2\" fred=\"3 4\" john=23", 1125 "fred", &pos)); 1126 ut_asserteq(17, pos); 1127 1128 /* args starting with the same prefix */ 1129 ut_asserteq(1, cmdline_get_arg("mary=abc johnathon=3 john=1", "john", 1130 &pos)); 1131 ut_asserteq(26, pos); 1132 1133 return 0; 1134} 1135BOOTSTD_TEST(bootflow_cmdline_get, 0); 1136 1137static int bootflow_cmdline(struct unit_test_state *uts) 1138{ 1139 ut_assertok(run_command("bootflow scan mmc", 0)); 1140 ut_assertok(run_command("bootflow sel 0", 0)); 1141 1142 ut_asserteq(1, run_command("bootflow cmdline get fred", 0)); 1143 ut_assert_nextline("Argument not found"); 1144 ut_assert_console_end(); 1145 1146 ut_asserteq(0, run_command("bootflow cmdline set fred 123", 0)); 1147 ut_asserteq(0, run_command("bootflow cmdline get fred", 0)); 1148 ut_assert_nextline("123"); 1149 1150 ut_asserteq(0, run_command("bootflow cmdline set mary abc", 0)); 1151 ut_asserteq(0, run_command("bootflow cmdline get mary", 0)); 1152 ut_assert_nextline("abc"); 1153 1154 ut_asserteq(0, run_command("bootflow cmdline delete fred", 0)); 1155 ut_asserteq(1, run_command("bootflow cmdline get fred", 0)); 1156 ut_assert_nextline("Argument not found"); 1157 1158 ut_asserteq(0, run_command("bootflow cmdline clear mary", 0)); 1159 ut_asserteq(0, run_command("bootflow cmdline get mary", 0)); 1160 ut_assert_nextline_empty(); 1161 1162 ut_asserteq(0, run_command("bootflow cmdline set mary abc", 0)); 1163 ut_asserteq(0, run_command("bootflow cmdline set mary", 0)); 1164 ut_assert_console_end(); 1165 1166 return 0; 1167} 1168BOOTSTD_TEST(bootflow_cmdline, UTF_CONSOLE); 1169 1170/* test a few special changes to a long command line */ 1171static int bootflow_cmdline_special(struct unit_test_state *uts) 1172{ 1173 char buf[500]; 1174 int pos; 1175 1176 /* 1177 * check handling of an argument which has an embedded '=', as well as 1178 * handling of a argument which partially matches ("ro" and "root") 1179 */ 1180 ut_asserteq(32, cmdline_set_arg( 1181 buf, sizeof(buf), 1182 "loglevel=7 root=PARTUUID=d68352e3 rootwait ro noinitrd", 1183 "root", NULL, &pos)); 1184 ut_asserteq_str("loglevel=7 rootwait ro noinitrd", buf); 1185 1186 return 0; 1187} 1188BOOTSTD_TEST(bootflow_cmdline_special, 0); 1189 1190/* Test ChromiumOS bootmeth */ 1191static int bootflow_cros(struct unit_test_state *uts) 1192{ 1193 ut_assertok(scan_mmc_bootdev(uts, "mmc5", true)); 1194 ut_assertok(run_command("bootflow list", 0)); 1195 1196 ut_assert_nextlinen("Showing all"); 1197 ut_assert_nextlinen("Seq"); 1198 ut_assert_nextlinen("---"); 1199 ut_assert_nextlinen(" 0 extlinux"); 1200 ut_assert_nextlinen(" 1 cros ready mmc 2 mmc5.bootdev.part_2 "); 1201 ut_assert_nextlinen(" 2 cros ready mmc 4 mmc5.bootdev.part_4 "); 1202 ut_assert_nextlinen("---"); 1203 ut_assert_skip_to_line("(3 bootflows, 3 valid)"); 1204 1205 ut_assertok(run_command("bootstd images", 0)); 1206 ut_assert_nextlinen("Seq"); 1207 ut_assert_nextlinen("---"); 1208 ut_assert_nextlinen(" 0 mmc1.bootdev.part_1 extlinux_cfg"); 1209 ut_assert_nextlinen(" 1 mmc5.bootdev.part_2 x86_setup"); 1210 ut_assert_nextlinen(" 1 mmc5.bootdev.part_2 cmdline"); 1211 ut_assert_nextlinen(" 1 mmc5.bootdev.part_2 kernel - 4000 kernel"); 1212 ut_assert_nextlinen(" 2 mmc5.bootdev.part_4 x86_setup"); 1213 ut_assert_nextlinen(" 2 mmc5.bootdev.part_4 cmdline"); 1214 ut_assert_nextlinen(" 2 mmc5.bootdev.part_4 kernel - 4000 kernel"); 1215 ut_assert_nextlinen("---"); 1216 ut_assert_nextline("(7 images)"); 1217 1218 ut_assert_console_end(); 1219 1220 return 0; 1221} 1222BOOTSTD_TEST(bootflow_cros, UTF_CONSOLE | UTF_DM | UTF_SCAN_FDT); 1223 1224/* Test Android bootmeth with boot image version 4 */ 1225static int bootflow_android_image_v4(struct unit_test_state *uts) 1226{ 1227 if (!IS_ENABLED(CONFIG_BOOTMETH_ANDROID)) 1228 return -EAGAIN; 1229 1230 ut_assertok(scan_mmc_android_bootdev(uts, "mmc7")); 1231 ut_assertok(run_command("bootflow list", 0)); 1232 1233 ut_assert_nextlinen("Showing all"); 1234 ut_assert_nextlinen("Seq"); 1235 ut_assert_nextlinen("---"); 1236 ut_assert_nextlinen(" 0 extlinux"); 1237 ut_assert_nextlinen(" 1 android ready mmc 0 mmc7.bootdev.whole "); 1238 ut_assert_nextlinen("---"); 1239 ut_assert_skip_to_line("(2 bootflows, 2 valid)"); 1240 1241 ut_assert_console_end(); 1242 1243 return 0; 1244} 1245BOOTSTD_TEST(bootflow_android_image_v4, UTF_CONSOLE | UTF_DM | UTF_SCAN_FDT); 1246 1247/* Test Android bootmeth with boot image version 2 */ 1248static int bootflow_android_image_v2(struct unit_test_state *uts) 1249{ 1250 if (!IS_ENABLED(CONFIG_BOOTMETH_ANDROID)) 1251 return -EAGAIN; 1252 1253 ut_assertok(scan_mmc_android_bootdev(uts, "mmc8")); 1254 ut_assertok(run_command("bootflow list", 0)); 1255 1256 ut_assert_nextlinen("Showing all"); 1257 ut_assert_nextlinen("Seq"); 1258 ut_assert_nextlinen("---"); 1259 ut_assert_nextlinen(" 0 extlinux"); 1260 ut_assert_nextlinen(" 1 android ready mmc 0 mmc8.bootdev.whole "); 1261 ut_assert_nextlinen("---"); 1262 ut_assert_skip_to_line("(2 bootflows, 2 valid)"); 1263 1264 ut_assert_console_end(); 1265 1266 return 0; 1267} 1268BOOTSTD_TEST(bootflow_android_image_v2, UTF_CONSOLE | UTF_DM | UTF_SCAN_FDT); 1269 1270/* Test EFI bootmeth */ 1271static int bootflow_efi(struct unit_test_state *uts) 1272{ 1273 static const char *order[] = {"mmc1", "usb", NULL}; 1274 struct bootstd_priv *std; 1275 struct udevice *bootstd; 1276 const char **old_order; 1277 1278 ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); 1279 std = dev_get_priv(bootstd); 1280 old_order = std->bootdev_order; 1281 std->bootdev_order = order; 1282 1283 /* disable ethernet since the hunter will run dhcp */ 1284 test_set_eth_enable(false); 1285 1286 /* make USB scan without delays */ 1287 test_set_skip_delays(true); 1288 1289 bootstd_reset_usb(); 1290 1291 ut_assertok(run_command("bootflow scan", 0)); 1292 ut_assert_skip_to_line( 1293 "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found"); 1294 1295 ut_assertok(run_command("bootflow list", 0)); 1296 1297 ut_assert_nextlinen("Showing all"); 1298 ut_assert_nextlinen("Seq"); 1299 ut_assert_nextlinen("---"); 1300 ut_assert_nextlinen(" 0 extlinux"); 1301 ut_assert_nextlinen( 1302 " 1 efi ready usb_mass_ 1 usb_mass_storage.lun0.boo /EFI/BOOT/BOOTSBOX.EFI"); 1303 ut_assert_nextlinen("---"); 1304 ut_assert_skip_to_line("(2 bootflows, 2 valid)"); 1305 ut_assert_console_end(); 1306 1307 ut_assertok(run_command("bootflow select 1", 0)); 1308 ut_assert_console_end(); 1309 1310 systab.fw_vendor = test_vendor; 1311 1312 ut_asserteq(1, run_command("bootflow boot", 0)); 1313 ut_assert_nextline( 1314 "** Booting bootflow 'usb_mass_storage.lun0.bootdev.part_1' with efi"); 1315 if (IS_ENABLED(CONFIG_LOGF_FUNC)) 1316 ut_assert_skip_to_line(" efi_run_image() Booting /\\EFI\\BOOT\\BOOTSBOX.EFI"); 1317 else 1318 ut_assert_skip_to_line("Booting /\\EFI\\BOOT\\BOOTSBOX.EFI"); 1319 1320 /* TODO: Why the \r ? */ 1321 ut_assert_nextline("U-Boot test app for EFI_LOADER\r"); 1322 ut_assert_nextline("Exiting test app"); 1323 ut_assert_nextline("Boot failed (err=-14)"); 1324 1325 ut_assert_console_end(); 1326 1327 ut_assertok(bootstd_test_drop_bootdev_order(uts)); 1328 1329 return 0; 1330} 1331BOOTSTD_TEST(bootflow_efi, UTF_CONSOLE); 1332 1333/* Check 'bootflow scan' provides a list of images */ 1334static int bootstd_images(struct unit_test_state *uts) 1335{ 1336 static const char *order[] = {"mmc2", "mmc1", "mmc4", "mmc5", NULL}; 1337 const struct legacy_img_hdr *hdr; 1338 const struct bootflow_img *img; 1339 const struct bootflow *bflow; 1340 struct bootstd_priv *std; 1341 const char **old_order; 1342 struct udevice *dev; 1343 ofnode root, node; 1344 ulong data, len; 1345 char *ptr; 1346 1347 /* get access to the current bootflow */ 1348 ut_assertok(bootstd_get_priv(&std)); 1349 1350 ut_assertok(prep_mmc_bootdev(uts, "mmc4", true, &old_order)); 1351 1352 /* bind mmc5 too, for cros */ 1353 root = oftree_root(oftree_default()); 1354 node = ofnode_find_subnode(root, "mmc5"); 1355 ut_assert(ofnode_valid(node)); 1356 ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false)); 1357 1358 std->bootdev_order = order; 1359 ut_assertok(run_command("bootflow scan", 0)); 1360 ut_assert_console_end(); 1361 std->bootdev_order = old_order; 1362 1363 ut_assertok(run_command("bootflow list", 0)); 1364 ut_assert_skip_to_line("(4 bootflows, 4 valid)"); 1365 1366 ut_assertok(run_command("bootstd images", 0)); 1367 ut_assert_nextlinen("Seq"); 1368 ut_assert_nextlinen("---"); 1369 ut_assert_nextlinen(" 0 mmc1.bootdev.part_1 extlinux_cfg"); 1370 ut_assert_nextlinen(" 1 mmc4.bootdev.part_1 script"); 1371 ut_assert_nextlinen(" 1 mmc4.bootdev.part_1 logo"); 1372 ut_assert_nextlinen(" 2 mmc5.bootdev.part_2 x86_setup"); 1373 ut_assert_nextlinen(" 2 mmc5.bootdev.part_2 cmdline"); 1374 ut_assert_nextlinen(" 2 mmc5.bootdev.part_2 kernel -"); 1375 ut_assert_nextlinen(" 3 mmc5.bootdev.part_4 x86_setup"); 1376 ut_assert_nextlinen(" 3 mmc5.bootdev.part_4 cmdline"); 1377 ut_assert_nextlinen(" 3 mmc5.bootdev.part_4 kernel -"); 1378 ut_assert_nextlinen("---"); 1379 ut_assert_nextline("(9 images)"); 1380 1381 /* check the first image */ 1382 bflow = alist_get(&std->bootflows, 0, struct bootflow); 1383 img = alist_get(&bflow->images, 0, struct bootflow_img); 1384 ut_asserteq_strn("# extlinux.conf", map_sysmem(img->addr, 0)); 1385 1386 /* check the second image */ 1387 bflow = alist_get(&std->bootflows, 1, struct bootflow); 1388 img = alist_get(&bflow->images, 0, struct bootflow_img); 1389 1390 /* this is the length of the script in bytes */ 1391 hdr = map_sysmem(img->addr, 0); 1392 image_multi_getimg(hdr, 0, &data, &len); 1393 ptr = (void *)data; 1394 ut_asserteq_strn("# DO NOT EDIT THIS FILE", ptr); 1395 1396 /* check the ChromiumOS images */ 1397 bflow = alist_get(&std->bootflows, 2, struct bootflow); 1398 img = alist_get(&bflow->images, 1, struct bootflow_img); 1399 ptr = map_sysmem(img->addr, 0); 1400 ut_asserteq_strn("BOOT_IMAGE=/vmlinuz-5.15.0-121-generic root=", ptr); 1401 1402 /* 1403 * the x86 setup is not a real binary, so just check that it is empty, 1404 * so that if this changes in the future someone will notice and update 1405 * this test 1406 */ 1407 img = alist_get(&bflow->images, 0, struct bootflow_img); 1408 ptr = map_sysmem(img->addr, 0); 1409 ut_asserteq(0, *(ulong *)ptr); 1410 1411 ut_assert_console_end(); 1412 1413 return 0; 1414} 1415BOOTSTD_TEST(bootstd_images, UTF_CONSOLE);