diff options
author | Tom Rini <trini@konsulko.com> | 2022-04-25 16:02:27 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2022-04-25 16:02:27 -0400 |
commit | 8cfac237b9814d52c843e939a05fc211ba3906de (patch) | |
tree | 975bba394b3c71a225283c2cb04ecda5c4bb189d /test | |
parent | bc9da9fb50ac3ba7603487a0366d4db60b984812 (diff) | |
parent | e7b2ce191ecab558b130b3b926dddcfc7231deb0 (diff) | |
download | u-boot-8cfac237b9814d52c843e939a05fc211ba3906de.zip u-boot-8cfac237b9814d52c843e939a05fc211ba3906de.tar.gz u-boot-8cfac237b9814d52c843e939a05fc211ba3906de.tar.bz2 |
Merge branch '2022-04-25-initial-implementation-of-stdboot'
To quote the author:
The bootflow feature provide a built-in way for U-Boot to automatically
boot an Operating System without custom scripting and other customisation.
This is called 'standard boot' since it provides a standard way for
U-Boot to boot a distro, without scripting.
It introduces the following concepts:
- bootdev - a device which can hold a distro
- bootmeth - a method to scan a bootdev to find bootflows (owned by
U-Boot)
- bootflow - a description of how to boot (owned by the distro)
This series provides an implementation of these, enabled to scan for
bootflows from MMC, USB and Ethernet. It supports the existing distro
boot as well as the EFI loader flow (bootefi/bootmgr). It works
similiarly to the existing script-based approach, but is native to
U-Boot.
With this we can boot on a Raspberry Pi 3 with just one command:
bootflow scan -lb
which means to scan, listing (-l) each bootflow and trying to boot each
one (-b). The final patch shows this.
With a standard way to identify boot devices, booting become easier. It
also should be possible to support U-Boot scripts, for backwards
compatibility only.
...
The design is described in these two documents:
https://drive.google.com/file/d/1ggW0KJpUOR__vBkj3l61L2dav4ZkNC12/view?usp=sharing
https://drive.google.com/file/d/1kTrflO9vvGlKp-ZH_jlgb9TY3WYG6FF9/view?usp=sharing
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile | 1 | ||||
-rw-r--r-- | test/boot/Makefile | 5 | ||||
-rw-r--r-- | test/boot/bootdev.c | 223 | ||||
-rw-r--r-- | test/boot/bootflow.c | 400 | ||||
-rw-r--r-- | test/boot/bootmeth.c | 122 | ||||
-rw-r--r-- | test/boot/bootstd_common.c | 35 | ||||
-rw-r--r-- | test/boot/bootstd_common.h | 27 | ||||
-rw-r--r-- | test/cmd_ut.c | 7 | ||||
-rw-r--r-- | test/dm/blk.c | 6 | ||||
-rw-r--r-- | test/dm/core.c | 17 | ||||
-rw-r--r-- | test/dm/fastboot.c | 4 | ||||
-rw-r--r-- | test/print_ut.c | 40 | ||||
-rw-r--r-- | test/py/tests/bootstd/mmc1.img.xz | bin | 0 -> 4448 bytes | |||
-rw-r--r-- | test/py/tests/test_ut.py | 103 | ||||
-rw-r--r-- | test/str_ut.c | 72 |
15 files changed, 1020 insertions, 42 deletions
diff --git a/test/Makefile b/test/Makefile index b3b2902..abd605a 100644 --- a/test/Makefile +++ b/test/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_UT_TIME) += time_ut.o obj-y += ut.o ifeq ($(CONFIG_SPL_BUILD),) +obj-$(CONFIG_UNIT_TEST) += boot/ obj-$(CONFIG_UNIT_TEST) += common/ obj-$(CONFIG_UNIT_TEST) += lib/ obj-y += log/ diff --git a/test/boot/Makefile b/test/boot/Makefile new file mode 100644 index 0000000..1730792 --- /dev/null +++ b/test/boot/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2021 Google LLC + +obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c new file mode 100644 index 0000000..1c2a79f --- /dev/null +++ b/test/boot/bootdev.c @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for bootdev functions. All start with 'bootdev' + * + * Copyright 2021 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <bootstd.h> +#include <dm.h> +#include <bootdev.h> +#include <bootflow.h> +#include <mapmem.h> +#include <os.h> +#include <test/suites.h> +#include <test/ut.h> +#include "bootstd_common.h" + +/* Allow reseting the USB-started flag */ +extern char usb_started; + +/* Check 'bootdev list' command */ +static int bootdev_test_cmd_list(struct unit_test_state *uts) +{ + int probed; + + console_record_reset_enable(); + for (probed = 0; probed < 2; probed++) { + int probe_ch = probed ? '+' : ' '; + + ut_assertok(run_command(probed ? "bootdev list -p" : + "bootdev list", 0)); + ut_assert_nextline("Seq Probed Status Uclass Name"); + ut_assert_nextlinen("---"); + ut_assert_nextline("%3x [ %c ] %6s %-8s %s", 0, probe_ch, "OK", + "mmc", "mmc2.bootdev"); + ut_assert_nextline("%3x [ %c ] %6s %-8s %s", 1, probe_ch, "OK", + "mmc", "mmc1.bootdev"); + ut_assert_nextline("%3x [ %c ] %6s %-8s %s", 2, probe_ch, "OK", + "mmc", "mmc0.bootdev"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(3 bootdevs)"); + ut_assert_console_end(); + } + + return 0; +} +BOOTSTD_TEST(bootdev_test_cmd_list, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootdev select' and 'info' commands */ +static int bootdev_test_cmd_select(struct unit_test_state *uts) +{ + struct bootstd_priv *std; + + /* get access to the CLI's cur_bootdev */ + ut_assertok(bootstd_get_priv(&std)); + + console_record_reset_enable(); + ut_asserteq(1, run_command("bootdev info", 0)); + ut_assert_nextlinen("Please use"); + ut_assert_console_end(); + + /* select by sequence */ + ut_assertok(run_command("bootdev select 0", 0)); + ut_assert_console_end(); + + ut_assertok(run_command("bootdev info", 0)); + ut_assert_nextline("Name: mmc2.bootdev"); + ut_assert_nextline("Sequence: 0"); + ut_assert_nextline("Status: Probed"); + ut_assert_nextline("Uclass: mmc"); + ut_assert_nextline("Bootflows: 0 (0 valid)"); + ut_assert_console_end(); + + /* select by bootdev name */ + ut_assertok(run_command("bootdev select mmc1.bootdev", 0)); + ut_assert_console_end(); + ut_assertnonnull(std->cur_bootdev); + ut_asserteq_str("mmc1.bootdev", std->cur_bootdev->name); + + /* select by bootdev label*/ + ut_assertok(run_command("bootdev select mmc1", 0)); + ut_assert_console_end(); + ut_assertnonnull(std->cur_bootdev); + ut_asserteq_str("mmc1.bootdev", std->cur_bootdev->name); + + /* deselect */ + ut_assertok(run_command("bootdev select", 0)); + ut_assert_console_end(); + ut_assertnull(std->cur_bootdev); + + ut_asserteq(1, run_command("bootdev info", 0)); + ut_assert_nextlinen("Please use"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootdev_test_cmd_select, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check bootdev labels */ +static int bootdev_test_labels(struct unit_test_state *uts) +{ + struct udevice *dev, *media; + + ut_assertok(bootdev_find_by_label("mmc2", &dev)); + ut_asserteq(UCLASS_BOOTDEV, device_get_uclass_id(dev)); + media = dev_get_parent(dev); + ut_asserteq(UCLASS_MMC, device_get_uclass_id(media)); + ut_asserteq_str("mmc2", media->name); + + /* Check invalid uclass */ + ut_asserteq(-EINVAL, bootdev_find_by_label("fred0", &dev)); + + /* Check unknown sequence number */ + ut_asserteq(-ENOENT, bootdev_find_by_label("mmc6", &dev)); + + return 0; +} +BOOTSTD_TEST(bootdev_test_labels, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check bootdev ordering with the bootdev-order property */ +static int bootdev_test_order(struct unit_test_state *uts) +{ + struct bootflow_iter iter; + struct bootflow bflow; + + /* + * First try the order set by the bootdev-order property + * Like all sandbox unit tests this relies on the devicetree setting up + * the required devices: + * + * mmc0 - nothing connected + * mmc1 - connected to mmc1.img file + * mmc2 - nothing connected + */ + ut_assertok(env_set("boot_targets", NULL)); + ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_asserteq(2, iter.num_devs); + ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name); + ut_asserteq_str("mmc1.bootdev", iter.dev_order[1]->name); + bootflow_iter_uninit(&iter); + + /* Use the environment variable to override it */ + ut_assertok(env_set("boot_targets", "mmc1 mmc2")); + ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_asserteq(2, iter.num_devs); + ut_asserteq_str("mmc1.bootdev", iter.dev_order[0]->name); + ut_asserteq_str("mmc2.bootdev", iter.dev_order[1]->name); + bootflow_iter_uninit(&iter); + + /* + * Now drop both orderings, to check the default (prioriy/sequence) + * ordering + */ + ut_assertok(env_set("boot_targets", NULL)); + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_asserteq(3, iter.num_devs); + ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name); + ut_asserteq_str("mmc1.bootdev", iter.dev_order[1]->name); + ut_asserteq_str("mmc0.bootdev", iter.dev_order[2]->name); + + /* + * Check that adding aliases for the bootdevs works. We just fake it by + * setting the sequence numbers directly. + */ + iter.dev_order[0]->seq_ = 0; + iter.dev_order[1]->seq_ = 3; + iter.dev_order[2]->seq_ = 2; + bootflow_iter_uninit(&iter); + + ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_asserteq(3, iter.num_devs); + ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name); + ut_asserteq_str("mmc0.bootdev", iter.dev_order[1]->name); + ut_asserteq_str("mmc1.bootdev", iter.dev_order[2]->name); + bootflow_iter_uninit(&iter); + + return 0; +} +BOOTSTD_TEST(bootdev_test_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check bootdev ordering with the uclass priority */ +static int bootdev_test_prio(struct unit_test_state *uts) +{ + struct bootdev_uc_plat *ucp; + struct bootflow_iter iter; + struct bootflow bflow; + struct udevice *blk; + + /* Start up USB which gives us three additional bootdevs */ + usb_started = false; + ut_assertok(run_command("usb start", 0)); + + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + /* 3 MMC and 3 USB bootdevs: MMC should come before USB */ + console_record_reset_enable(); + ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_asserteq(6, iter.num_devs); + ut_asserteq_str("mmc2.bootdev", iter.dev_order[0]->name); + ut_asserteq_str("usb_mass_storage.lun0.bootdev", + iter.dev_order[3]->name); + + ut_assertok(bootdev_get_sibling_blk(iter.dev_order[3], &blk)); + ut_asserteq_str("usb_mass_storage.lun0", blk->name); + + /* adjust the priority of the first USB bootdev to the highest */ + ucp = dev_get_uclass_plat(iter.dev_order[3]); + ucp->prio = 1; + + bootflow_iter_uninit(&iter); + ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_asserteq(6, iter.num_devs); + ut_asserteq_str("usb_mass_storage.lun0.bootdev", + iter.dev_order[0]->name); + ut_asserteq_str("mmc2.bootdev", iter.dev_order[1]->name); + + return 0; +} +BOOTSTD_TEST(bootdev_test_prio, UT_TESTF_DM | UT_TESTF_SCAN_FDT); diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c new file mode 100644 index 0000000..1ebb789 --- /dev/null +++ b/test/boot/bootflow.c @@ -0,0 +1,400 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for bootdev functions. All start with 'bootdev' + * + * Copyright 2021 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <bootdev.h> +#include <bootflow.h> +#include <bootstd.h> +#include <dm.h> +#include <dm/lists.h> +#include <test/suites.h> +#include <test/ut.h> +#include "bootstd_common.h" + +/* Check 'bootflow scan/list' commands */ +static int bootflow_cmd(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootdev select 1", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootflow scan -l", 0)); + ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'"); + ut_assert_nextline("Seq Method State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(1 bootflow, 1 valid)"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow list", 0)); + ut_assert_nextline("Showing bootflows for bootdev 'mmc1.bootdev'"); + ut_assert_nextline("Seq Method State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(1 bootflow, 1 valid)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow scan' with a name / label / seq */ +static int bootflow_cmd_label(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan -l mmc1", 0)); + ut_assert_nextline("Scanning for bootflows in bootdev 'mmc1.bootdev'"); + ut_assert_skip_to_line("(1 bootflow, 1 valid)"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow scan -l mmc0.bootdev", 0)); + ut_assert_nextline("Scanning for bootflows in bootdev 'mmc0.bootdev'"); + ut_assert_skip_to_line("(0 bootflows, 0 valid)"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow scan -l 0", 0)); + ut_assert_nextline("Scanning for bootflows in bootdev 'mmc2.bootdev'"); + ut_assert_skip_to_line("(0 bootflows, 0 valid)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd_label, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow scan/list' commands using all bootdevs */ +static int bootflow_cmd_glob(struct unit_test_state *uts) +{ + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan -l", 0)); + ut_assert_nextline("Scanning for bootflows in all bootdevs"); + ut_assert_nextline("Seq Method State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':"); + ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':"); + ut_assert_nextline(" 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); + ut_assert_nextline("Scanning bootdev 'mmc0.bootdev':"); + ut_assert_nextline("No more bootdevs"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(1 bootflow, 1 valid)"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow list", 0)); + ut_assert_nextline("Showing all bootflows"); + ut_assert_nextline("Seq Method State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(1 bootflow, 1 valid)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd_glob, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow scan -e' */ +static int bootflow_cmd_scan_e(struct unit_test_state *uts) +{ + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan -ale", 0)); + ut_assert_nextline("Scanning for bootflows in all bootdevs"); + ut_assert_nextline("Seq Method State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline("Scanning bootdev 'mmc2.bootdev':"); + ut_assert_nextline(" 0 syslinux media mmc 0 mmc2.bootdev.whole <NULL>"); + ut_assert_nextline(" ** No partition found, err=-93"); + ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole <NULL>"); + ut_assert_nextline(" ** No partition found, err=-93"); + + ut_assert_nextline("Scanning bootdev 'mmc1.bootdev':"); + ut_assert_nextline(" 2 syslinux media mmc 0 mmc1.bootdev.whole <NULL>"); + ut_assert_nextline(" ** No partition found, err=-2"); + ut_assert_nextline(" 3 efi media mmc 0 mmc1.bootdev.whole <NULL>"); + ut_assert_nextline(" ** No partition found, err=-2"); + ut_assert_nextline(" 4 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); + ut_assert_nextline(" 5 efi fs mmc 1 mmc1.bootdev.part_1 efi/boot/bootsbox.efi"); + + ut_assert_skip_to_line("Scanning bootdev 'mmc0.bootdev':"); + ut_assert_skip_to_line(" 3f efi media mmc 0 mmc0.bootdev.whole <NULL>"); + ut_assert_nextline(" ** No partition found, err=-93"); + ut_assert_nextline("No more bootdevs"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(64 bootflows, 1 valid)"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow list", 0)); + ut_assert_nextline("Showing all bootflows"); + ut_assert_nextline("Seq Method State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 syslinux media mmc 0 mmc2.bootdev.whole <NULL>"); + ut_assert_nextline(" 1 efi media mmc 0 mmc2.bootdev.whole <NULL>"); + ut_assert_skip_to_line(" 4 syslinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); + ut_assert_skip_to_line(" 3f efi media mmc 0 mmc0.bootdev.whole <NULL>"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(64 bootflows, 1 valid)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd_scan_e, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow info' */ +static int bootflow_cmd_info(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootdev select 1", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootflow scan", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootflow select 0", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootflow info", 0)); + ut_assert_nextline("Name: mmc1.bootdev.part_1"); + ut_assert_nextline("Device: mmc1.bootdev"); + ut_assert_nextline("Block dev: mmc1.blk"); + ut_assert_nextline("Method: syslinux"); + ut_assert_nextline("State: ready"); + ut_assert_nextline("Partition: 1"); + ut_assert_nextline("Subdir: (none)"); + ut_assert_nextline("Filename: /extlinux/extlinux.conf"); + ut_assert_nextlinen("Buffer: "); + ut_assert_nextline("Size: 253 (595 bytes)"); + ut_assert_nextline("Error: 0"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow info -d", 0)); + ut_assert_nextline("Name: mmc1.bootdev.part_1"); + ut_assert_skip_to_line("Error: 0"); + ut_assert_nextline("Contents:"); + ut_assert_nextline("%s", ""); + ut_assert_nextline("# extlinux.conf generated by appliance-creator"); + ut_assert_skip_to_line(" initrd /initramfs-5.3.7-301.fc31.armv7hl.img"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd_info, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow scan -b' to boot the first available bootdev */ +static int bootflow_scan_boot(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan -b", 0)); + ut_assert_nextline( + "** Booting bootflow 'mmc1.bootdev.part_1' with syslinux"); + ut_assert_nextline("Ignoring unknown command: ui"); + + /* + * We expect it to get through to boot although sandbox always returns + * -EFAULT as it cannot actually boot the kernel + */ + ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux"); + ut_assert_nextline("Boot failed (err=-14)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_scan_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check iterating through available bootflows */ +static int bootflow_iter(struct unit_test_state *uts) +{ + struct bootflow_iter iter; + struct bootflow bflow; + + bootstd_clear_glob(); + + /* The first device is mmc2.bootdev which has no media */ + ut_asserteq(-EPROTONOSUPPORT, + bootflow_scan_first(&iter, BOOTFLOWF_ALL, &bflow)); + ut_asserteq(2, iter.num_methods); + ut_asserteq(0, iter.cur_method); + ut_asserteq(0, iter.part); + ut_asserteq(0, iter.max_part); + ut_asserteq_str("syslinux", iter.method->name); + ut_asserteq(0, bflow.err); + + /* + * This shows MEDIA even though there is none, since int + * bootdev_find_in_blk() we call part_get_info() which returns + * -EPROTONOSUPPORT. Ideally it would return -EEOPNOTSUPP and we would + * know. + */ + ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); + + ut_asserteq(-EPROTONOSUPPORT, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(2, iter.num_methods); + ut_asserteq(1, iter.cur_method); + ut_asserteq(0, iter.part); + ut_asserteq(0, iter.max_part); + ut_asserteq_str("efi", iter.method->name); + ut_asserteq(0, bflow.err); + ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); + bootflow_free(&bflow); + + /* The next device is mmc1.bootdev - at first we use the whole device */ + ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(2, iter.num_methods); + ut_asserteq(0, iter.cur_method); + ut_asserteq(0, iter.part); + ut_asserteq(0x1e, iter.max_part); + ut_asserteq_str("syslinux", iter.method->name); + ut_asserteq(0, bflow.err); + ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); + bootflow_free(&bflow); + + ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(2, iter.num_methods); + ut_asserteq(1, iter.cur_method); + ut_asserteq(0, iter.part); + ut_asserteq(0x1e, iter.max_part); + ut_asserteq_str("efi", iter.method->name); + ut_asserteq(0, bflow.err); + ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); + bootflow_free(&bflow); + + /* Then more to partition 1 where we find something */ + ut_assertok(bootflow_scan_next(&iter, &bflow)); + ut_asserteq(2, iter.num_methods); + ut_asserteq(0, iter.cur_method); + ut_asserteq(1, iter.part); + ut_asserteq(0x1e, iter.max_part); + ut_asserteq_str("syslinux", iter.method->name); + ut_asserteq(0, bflow.err); + ut_asserteq(BOOTFLOWST_READY, bflow.state); + bootflow_free(&bflow); + + ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(2, iter.num_methods); + ut_asserteq(1, iter.cur_method); + ut_asserteq(1, iter.part); + ut_asserteq(0x1e, iter.max_part); + ut_asserteq_str("efi", iter.method->name); + ut_asserteq(0, bflow.err); + ut_asserteq(BOOTFLOWST_FS, bflow.state); + bootflow_free(&bflow); + + /* Then more to partition 2 which doesn't exist */ + ut_asserteq(-ENOENT, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(2, iter.num_methods); + ut_asserteq(0, iter.cur_method); + ut_asserteq(2, iter.part); + ut_asserteq(0x1e, iter.max_part); + ut_asserteq_str("syslinux", iter.method->name); + ut_asserteq(0, bflow.err); + ut_asserteq(BOOTFLOWST_MEDIA, bflow.state); + bootflow_free(&bflow); + + bootflow_iter_uninit(&iter); + + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_iter, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check using the system bootdev */ +static int bootflow_system(struct unit_test_state *uts) +{ + struct udevice *bootstd, *dev; + + /* Add the EFI bootmgr driver */ + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + ut_assertok(device_bind_driver(bootstd, "bootmeth_efi_mgr", "bootmgr", + &dev)); + + /* Add the system bootdev that it uses */ + ut_assertok(device_bind_driver(bootstd, "system_bootdev", + "system-bootdev", &dev)); + + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + /* We should get a single 'bootmgr' method right at the end */ + bootstd_clear_glob(); + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan -l", 0)); + ut_assert_skip_to_line(" 1 bootmgr ready bootstd 0 <NULL> <NULL>"); + ut_assert_nextline("No more bootdevs"); + ut_assert_skip_to_line("(2 bootflows, 2 valid)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_system, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check disabling a bootmethod if it requests it */ +static int bootflow_iter_disable(struct unit_test_state *uts) +{ + struct udevice *bootstd, *dev; + struct bootflow_iter iter; + struct bootflow bflow; + int i; + + /* Add the EFI bootmgr driver */ + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + ut_assertok(device_bind_driver(bootstd, "bootmeth_sandbox", "sandbox", + &dev)); + + /* Add the system bootdev that it uses */ + ut_assertok(device_bind_driver(bootstd, "system_bootdev", + "system-bootdev", &dev)); + + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + bootstd_clear_glob(); + ut_assertok(run_command("bootflow scan -lb", 0)); + + /* Try to boot the bootmgr flow, which will fail */ + console_record_reset_enable(); + ut_assertok(bootflow_scan_first(&iter, 0, &bflow)); + ut_asserteq(3, iter.num_methods); + ut_asserteq_str("sandbox", iter.method->name); + ut_asserteq(-ENOTSUPP, bootflow_run_boot(&iter, &bflow)); + + ut_assert_skip_to_line("Boot method 'sandbox' failed and will not be retried"); + ut_assert_console_end(); + + /* Check that the sandbox bootmeth has been removed */ + ut_asserteq(2, iter.num_methods); + for (i = 0; i < iter.num_methods; i++) + ut_assert(strcmp("sandbox", iter.method_order[i]->name)); + + return 0; +} +BOOTSTD_TEST(bootflow_iter_disable, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow boot' to boot a selected bootflow */ +static int bootflow_cmd_boot(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootdev select 1", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootflow scan", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootflow select 0", 0)); + ut_assert_console_end(); + ut_asserteq(1, run_command("bootflow boot", 0)); + ut_assert_nextline( + "** Booting bootflow 'mmc1.bootdev.part_1' with syslinux"); + ut_assert_nextline("Ignoring unknown command: ui"); + + /* + * We expect it to get through to boot although sandbox always returns + * -EFAULT as it cannot actually boot the kernel + */ + ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux"); + ut_assert_nextline("Boot failed (err=-14)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT); diff --git a/test/boot/bootmeth.c b/test/boot/bootmeth.c new file mode 100644 index 0000000..07776c5 --- /dev/null +++ b/test/boot/bootmeth.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for bootdev functions. All start with 'bootdev' + * + * Copyright 2021 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <bootstd.h> +#include <test/suites.h> +#include <test/ut.h> +#include "bootstd_common.h" + +/* Check 'bootmeth list' command */ +static int bootmeth_cmd_list(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootmeth list", 0)); + ut_assert_nextline("Order Seq Name Description"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 0 syslinux Syslinux boot from a block device"); + ut_assert_nextline(" 1 1 efi EFI boot from an .efi file"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(2 bootmeths)"); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootmeth_cmd_list, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootmeth order' command */ +static int bootmeth_cmd_order(struct unit_test_state *uts) +{ + /* Select just one bootmethod */ + console_record_reset_enable(); + ut_assertok(run_command("bootmeth order syslinux", 0)); + ut_assert_console_end(); + ut_assertnonnull(env_get("bootmeths")); + ut_asserteq_str("syslinux", env_get("bootmeths")); + + /* Only that one should be listed */ + ut_assertok(run_command("bootmeth list", 0)); + ut_assert_nextline("Order Seq Name Description"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 0 syslinux Syslinux boot from a block device"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(1 bootmeth)"); + ut_assert_console_end(); + + /* Check the -a flag, efi should show as not in the order ("-") */ + ut_assertok(run_command("bootmeth list -a", 0)); + ut_assert_nextline("Order Seq Name Description"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 0 syslinux Syslinux boot from a block device"); + ut_assert_nextline(" - 1 efi EFI boot from an .efi file"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(2 bootmeths)"); + ut_assert_console_end(); + + /* Check the -a flag with the reverse order */ + ut_assertok(run_command("bootmeth order \"efi syslinux\"", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootmeth list -a", 0)); + ut_assert_nextline("Order Seq Name Description"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 1 0 syslinux Syslinux boot from a block device"); + ut_assert_nextline(" 0 1 efi EFI boot from an .efi file"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(2 bootmeths)"); + ut_assert_console_end(); + + /* Now reset the order to empty, which should show all of them again */ + ut_assertok(run_command("bootmeth order", 0)); + ut_assert_console_end(); + ut_assertnull(env_get("bootmeths")); + ut_assertok(run_command("bootmeth list", 0)); + ut_assert_skip_to_line("(2 bootmeths)"); + + /* Try reverse order */ + ut_assertok(run_command("bootmeth order \"efi syslinux\"", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootmeth list", 0)); + ut_assert_nextline("Order Seq Name Description"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 1 efi EFI boot from an .efi file"); + ut_assert_nextline(" 1 0 syslinux Syslinux boot from a block device"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(2 bootmeths)"); + ut_assertnonnull(env_get("bootmeths")); + ut_asserteq_str("efi syslinux", env_get("bootmeths")); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootmeth_cmd_order, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootmeths' env var */ +static int bootmeth_env(struct unit_test_state *uts) +{ + struct bootstd_priv *std; + + ut_assertok(bootstd_get_priv(&std)); + + /* Select just one bootmethod */ + console_record_reset_enable(); + ut_assertok(env_set("bootmeths", "syslinux")); + ut_asserteq(1, std->bootmeth_count); + + /* Select an invalid bootmethod */ + ut_asserteq(1, run_command("setenv bootmeths fred", 0)); + ut_assert_nextline("Unknown bootmeth 'fred'"); + ut_assert_nextlinen("## Error inserting"); + ut_assert_console_end(); + + ut_assertok(env_set("bootmeths", "efi syslinux")); + ut_asserteq(2, std->bootmeth_count); + ut_assert_console_end(); + + return 0; +} +BOOTSTD_TEST(bootmeth_env, UT_TESTF_DM | UT_TESTF_SCAN_FDT); diff --git a/test/boot/bootstd_common.c b/test/boot/bootstd_common.c new file mode 100644 index 0000000..05347d8 --- /dev/null +++ b/test/boot/bootstd_common.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for bootdev functions. All start with 'bootdev' + * + * Copyright 2021 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <bootstd.h> +#include <dm.h> +#include <test/suites.h> +#include <test/ut.h> +#include "bootstd_common.h" + +int bootstd_test_drop_bootdev_order(struct unit_test_state *uts) +{ + struct bootstd_priv *priv; + struct udevice *bootstd; + + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + priv = dev_get_priv(bootstd); + priv->bootdev_order = NULL; + + return 0; +} + +int do_ut_bootstd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + struct unit_test *tests = UNIT_TEST_SUITE_START(bootstd_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(bootstd_test); + + return cmd_ut_category("bootstd", "bootstd_test_", + tests, n_ents, argc, argv); +} diff --git a/test/boot/bootstd_common.h b/test/boot/bootstd_common.h new file mode 100644 index 0000000..676ef0a --- /dev/null +++ b/test/boot/bootstd_common.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Common header file for bootdev, bootflow, bootmeth tests + * + * Copyright 2021 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#ifndef __bootstd_common_h +#define __bootstd_common_h + +/* Declare a new bootdev test */ +#define BOOTSTD_TEST(_name, _flags) \ + UNIT_TEST(_name, _flags, bootstd_test) + +struct unit_test_state; + +/** + * bootstd_test_drop_bootdev_order() - Remove the existing boot order + * + * Drop the boot order so that all bootdevs are used in their alias order + * + * @uts: Unit test state to use for ut_assert...() functions + */ +int bootstd_test_drop_bootdev_order(struct unit_test_state *uts); + +#endif diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 90b260f..67a13ee 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -28,6 +28,10 @@ int cmd_ut_category(const char *name, const char *prefix, static struct cmd_tbl cmd_ut_sub[] = { U_BOOT_CMD_MKENT(all, CONFIG_SYS_MAXARGS, 1, do_ut_all, "", ""), +#ifdef CONFIG_BOOTSTD + U_BOOT_CMD_MKENT(bootstd, CONFIG_SYS_MAXARGS, 1, do_ut_bootstd, + "", ""), +#endif U_BOOT_CMD_MKENT(common, CONFIG_SYS_MAXARGS, 1, do_ut_common, "", ""), #if defined(CONFIG_UT_DM) U_BOOT_CMD_MKENT(dm, CONFIG_SYS_MAXARGS, 1, do_ut_dm, "", ""), @@ -115,6 +119,9 @@ static char ut_help_text[] = "ut bloblist - Test bloblist implementation\n" "ut compression - Test compressors and bootm decompression\n" #endif +#ifdef CONFIG_BOOTSTD + "ut bootstd - Test standard boot implementation\n" +#endif #ifdef CONFIG_UT_DM "ut dm [test-name]\n" #endif diff --git a/test/dm/blk.c b/test/dm/blk.c index 8556cc7..85c3a3b 100644 --- a/test/dm/blk.c +++ b/test/dm/blk.c @@ -15,6 +15,9 @@ DECLARE_GLOBAL_DATA_PTR; +/* Allow resetting the USB-started flag */ +extern char usb_started; + /* Test that block devices can be created */ static int dm_test_blk_base(struct unit_test_state *uts) { @@ -66,8 +69,11 @@ static int dm_test_blk_usb(struct unit_test_state *uts) struct udevice *usb_dev, *dev; struct blk_desc *dev_desc; + usb_started = false; + /* Get a flash device */ state_set_skip_delays(true); + ut_assertok(usb_stop()); ut_assertok(usb_init()); ut_assertok(uclass_get_device(UCLASS_MASS_STORAGE, 0, &usb_dev)); ut_assertok(blk_get_device_by_str("usb", "0", &dev_desc)); diff --git a/test/dm/core.c b/test/dm/core.c index 0ce0b3c..ebd5044 100644 --- a/test/dm/core.c +++ b/test/dm/core.c @@ -1161,6 +1161,8 @@ static int dm_test_uclass_names(struct unit_test_state *uts) ut_asserteq_str("test", uclass_get_name(UCLASS_TEST)); ut_asserteq(UCLASS_TEST, uclass_get_by_name("test")); + ut_asserteq(UCLASS_SPI, uclass_get_by_name("spi")); + return 0; } DM_TEST(dm_test_uclass_names, UT_TESTF_SCAN_PDATA); @@ -1258,3 +1260,18 @@ static int dm_test_get_stats(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_get_stats, UT_TESTF_SCAN_FDT); + +/* Test uclass_find_device_by_name() */ +static int dm_test_uclass_find_device(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_find_device_by_name(UCLASS_I2C, "i2c@0", &dev)); + ut_asserteq(-ENODEV, + uclass_find_device_by_name(UCLASS_I2C, "i2c@0x", &dev)); + ut_assertok(uclass_find_device_by_namelen(UCLASS_I2C, "i2c@0x", 5, + &dev)); + + return 0; +} +DM_TEST(dm_test_uclass_find_device, UT_TESTF_SCAN_FDT); diff --git a/test/dm/fastboot.c b/test/dm/fastboot.c index e7f8c36..758538d 100644 --- a/test/dm/fastboot.c +++ b/test/dm/fastboot.c @@ -81,9 +81,9 @@ static int dm_test_fastboot_mmc_part(struct unit_test_state *uts) &part_info, response)); ut_asserteq(0, fastboot_mmc_get_part_info("0.0:0", &fb_dev_desc, &part_info, response)); - ut_asserteq(0, fastboot_mmc_get_part_info("1", &fb_dev_desc, + ut_asserteq(0, fastboot_mmc_get_part_info("2", &fb_dev_desc, &part_info, response)); - ut_asserteq(0, fastboot_mmc_get_part_info("1.0", &fb_dev_desc, + ut_asserteq(0, fastboot_mmc_get_part_info("2.0", &fb_dev_desc, &part_info, response)); ut_asserteq(1, fastboot_mmc_get_part_info(":1", &fb_dev_desc, &part_info, response)); diff --git a/test/print_ut.c b/test/print_ut.c index 247011f..47a6ce5 100644 --- a/test/print_ut.c +++ b/test/print_ut.c @@ -345,26 +345,6 @@ static int print_do_hex_dump(struct unit_test_state *uts) } PRINT_TEST(print_do_hex_dump, UT_TESTF_CONSOLE_REC); -static int print_itoa(struct unit_test_state *uts) -{ - ut_asserteq_str("123", simple_itoa(123)); - ut_asserteq_str("0", simple_itoa(0)); - ut_asserteq_str("2147483647", simple_itoa(0x7fffffff)); - ut_asserteq_str("4294967295", simple_itoa(0xffffffff)); - - /* Use #ifdef here to avoid a compiler warning on 32-bit machines */ -#ifdef CONFIG_PHYS_64BIT - if (sizeof(ulong) == 8) { - ut_asserteq_str("9223372036854775807", - simple_itoa((1UL << 63) - 1)); - ut_asserteq_str("18446744073709551615", simple_itoa(-1)); - } -#endif /* CONFIG_PHYS_64BIT */ - - return 0; -} -PRINT_TEST(print_itoa, 0); - static int snprint(struct unit_test_state *uts) { char buf[10] = "xxxxxxxxx"; @@ -391,26 +371,6 @@ static int snprint(struct unit_test_state *uts) } PRINT_TEST(snprint, 0); -static int print_xtoa(struct unit_test_state *uts) -{ - ut_asserteq_str("7f", simple_xtoa(127)); - ut_asserteq_str("00", simple_xtoa(0)); - ut_asserteq_str("7fffffff", simple_xtoa(0x7fffffff)); - ut_asserteq_str("ffffffff", simple_xtoa(0xffffffff)); - - /* Use #ifdef here to avoid a compiler warning on 32-bit machines */ -#ifdef CONFIG_PHYS_64BIT - if (sizeof(ulong) == 8) { - ut_asserteq_str("7fffffffffffffff", - simple_xtoa((1UL << 63) - 1)); - ut_asserteq_str("ffffffffffffffff", simple_xtoa(-1)); - } -#endif /* CONFIG_PHYS_64BIT */ - - return 0; -} -PRINT_TEST(print_xtoa, 0); - int do_ut_print(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct unit_test *tests = UNIT_TEST_SUITE_START(print_test); diff --git a/test/py/tests/bootstd/mmc1.img.xz b/test/py/tests/bootstd/mmc1.img.xz Binary files differnew file mode 100644 index 0000000..4e7f39b --- /dev/null +++ b/test/py/tests/bootstd/mmc1.img.xz diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index 01c2b3f..35fb393 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -1,9 +1,102 @@ # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. +import gzip +import os import os.path import pytest +import u_boot_utils + +def mkdir_cond(dirname): + """Create a directory if it doesn't already exist + + Args: + dirname: Name of directory to create + """ + if not os.path.exists(dirname): + os.mkdir(dirname) + +def setup_bootflow_image(u_boot_console): + """Create a 20MB disk image with a single FAT partition""" + cons = u_boot_console + fname = os.path.join(cons.config.source_dir, 'mmc1.img') + mnt = os.path.join(cons.config.persistent_data_dir, 'mnt') + mkdir_cond(mnt) + + u_boot_utils.run_and_log(cons, 'qemu-img create %s 20M' % fname) + u_boot_utils.run_and_log(cons, 'sudo sfdisk %s' % fname, + stdin=b'type=c') + + loop = None + mounted = False + complete = False + try: + out = u_boot_utils.run_and_log(cons, + 'sudo losetup --show -f -P %s' % fname) + loop = out.strip() + fatpart = '%sp1' % loop + u_boot_utils.run_and_log(cons, 'sudo mkfs.vfat %s' % fatpart) + u_boot_utils.run_and_log( + cons, 'sudo mount -o loop %s %s -o uid=%d,gid=%d' % + (fatpart, mnt, os.getuid(), os.getgid())) + mounted = True + + vmlinux = 'vmlinuz-5.3.7-301.fc31.armv7hl' + initrd = 'initramfs-5.3.7-301.fc31.armv7hl.img' + dtbdir = 'dtb-5.3.7-301.fc31.armv7hl' + script = '''# extlinux.conf generated by appliance-creator +ui menu.c32 +menu autoboot Welcome to Fedora-Workstation-armhfp-31-1.9. Automatic boot in # second{,s}. Press a key for options. +menu title Fedora-Workstation-armhfp-31-1.9 Boot Options. +menu hidden +timeout 20 +totaltimeout 600 + +label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + kernel /%s + append ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB + fdtdir /%s/ + initrd /%s''' % (vmlinux, dtbdir, initrd) + ext = os.path.join(mnt, 'extlinux') + mkdir_cond(ext) + + with open(os.path.join(ext, 'extlinux.conf'), 'w') as fd: + print(script, file=fd) + + inf = os.path.join(cons.config.persistent_data_dir, 'inf') + with open(inf, 'wb') as fd: + fd.write(gzip.compress(b'vmlinux')) + u_boot_utils.run_and_log(cons, 'mkimage -f auto -d %s %s' % + (inf, os.path.join(mnt, vmlinux))) + + with open(os.path.join(mnt, initrd), 'w') as fd: + print('initrd', file=fd) + + mkdir_cond(os.path.join(mnt, dtbdir)) + + dtb_file = os.path.join(mnt, '%s/sandbox.dtb' % dtbdir) + u_boot_utils.run_and_log( + cons, 'dtc -o %s' % dtb_file, stdin=b'/dts-v1/; / {};') + complete = True + except ValueError as exc: + print('Falled to create image, failing back to prepared copy: %s', + str(exc)) + finally: + if mounted: + u_boot_utils.run_and_log(cons, 'sudo umount %s' % mnt) + if loop: + u_boot_utils.run_and_log(cons, 'sudo losetup -d %s' % loop) + + if not complete: + # Use a prepared image since we cannot create one + infname = os.path.join(cons.config.source_dir, + 'test/py/tests/bootstd/mmc1.img.xz') + u_boot_utils.run_and_log( + cons, + ['sh', '-c', 'xz -dc %s >%s' % (infname, fname)]) + + @pytest.mark.buildconfigspec('ut_dm') def test_ut_dm_init(u_boot_console): """Initialize data for ut dm tests.""" @@ -21,6 +114,16 @@ def test_ut_dm_init(u_boot_console): with open(fn, 'wb') as fh: fh.write(data) +@pytest.mark.buildconfigspec('cmd_bootflow') +def test_ut_dm_init_bootstd(u_boot_console): + """Initialise data for bootflow tests""" + + setup_bootflow_image(u_boot_console) + + # Restart so that the new mmc1.img is picked up + u_boot_console.restart_uboot() + + def test_ut(u_boot_console, ut_subtest): """Execute a "ut" subtest. diff --git a/test/str_ut.c b/test/str_ut.c index d2840d5..5a84434 100644 --- a/test/str_ut.c +++ b/test/str_ut.c @@ -202,6 +202,78 @@ static int str_dectoul(struct unit_test_state *uts) } STR_TEST(str_dectoul, 0); +static int str_itoa(struct unit_test_state *uts) +{ + ut_asserteq_str("123", simple_itoa(123)); + ut_asserteq_str("0", simple_itoa(0)); + ut_asserteq_str("2147483647", simple_itoa(0x7fffffff)); + ut_asserteq_str("4294967295", simple_itoa(0xffffffff)); + + /* Use #ifdef here to avoid a compiler warning on 32-bit machines */ +#ifdef CONFIG_PHYS_64BIT + if (sizeof(ulong) == 8) { + ut_asserteq_str("9223372036854775807", + simple_itoa((1UL << 63) - 1)); + ut_asserteq_str("18446744073709551615", simple_itoa(-1)); + } +#endif /* CONFIG_PHYS_64BIT */ + + return 0; +} +STR_TEST(str_itoa, 0); + +static int str_xtoa(struct unit_test_state *uts) +{ + ut_asserteq_str("7f", simple_xtoa(127)); + ut_asserteq_str("00", simple_xtoa(0)); + ut_asserteq_str("7fffffff", simple_xtoa(0x7fffffff)); + ut_asserteq_str("ffffffff", simple_xtoa(0xffffffff)); + + /* Use #ifdef here to avoid a compiler warning on 32-bit machines */ +#ifdef CONFIG_PHYS_64BIT + if (sizeof(ulong) == 8) { + ut_asserteq_str("7fffffffffffffff", + simple_xtoa((1UL << 63) - 1)); + ut_asserteq_str("ffffffffffffffff", simple_xtoa(-1)); + } +#endif /* CONFIG_PHYS_64BIT */ + + return 0; +} +STR_TEST(str_xtoa, 0); + +static int str_trailing(struct unit_test_state *uts) +{ + const char str1[] = "abc123def"; + const char str2[] = "abc123def456"; + const char *end; + + ut_asserteq(-1, trailing_strtol("")); + ut_asserteq(-1, trailing_strtol("123")); + ut_asserteq(123, trailing_strtol("abc123")); + ut_asserteq(4, trailing_strtol("12c4")); + ut_asserteq(-1, trailing_strtol("abd")); + ut_asserteq(-1, trailing_strtol("abc123def")); + + ut_asserteq(-1, trailing_strtoln(str1, NULL)); + ut_asserteq(123, trailing_strtoln(str1, str1 + 6)); + ut_asserteq(-1, trailing_strtoln(str1, str1 + 9)); + + ut_asserteq(3, trailing_strtol("a3")); + + ut_asserteq(123, trailing_strtoln_end(str1, str1 + 6, &end)); + ut_asserteq(3, end - str1); + + ut_asserteq(-1, trailing_strtoln_end(str1, str1 + 7, &end)); + ut_asserteq(7, end - str1); + + ut_asserteq(456, trailing_strtoln_end(str2, NULL, &end)); + ut_asserteq(9, end - str2); + + return 0; +} +STR_TEST(str_trailing, 0); + int do_ut_str(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct unit_test *tests = UNIT_TEST_SUITE_START(str_test); |