
Add a set of combined tests for these two commands.
Expand the sandbox console-recording limit so that these can work.
These tests rely on a filesystem script which is not yet added to the Python tests. It is included here as a shell script.
Signed-off-by: Simon Glass sjg@chromium.org ---
MAINTAINERS | 1 + configs/sandbox_defconfig | 2 +- include/test/suites.h | 2 + test/Makefile | 1 + test/boot/Makefile | 5 + test/boot/bootmethod.c | 271 ++++++++++++++++++++++++++++++++++++++ test/cmd_ut.c | 4 + try.sh | 131 ++++++++++++++++++ 8 files changed, 416 insertions(+), 1 deletion(-) create mode 100644 test/boot/Makefile create mode 100644 test/boot/bootmethod.c create mode 100755 try.sh
diff --git a/MAINTAINERS b/MAINTAINERS index 367193358b7..2f74f7dbb19 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -639,6 +639,7 @@ F: cmd/bootflow.c F: cmd/bootmethod.c F: include/bootmethod.h F: include/distro.h +F: test/boot/bootmethod.c
BTRFS M: Marek Behun marek.behun@nic.cz diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 952d430304c..31a8d6a1d90 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -26,7 +26,7 @@ CONFIG_AUTOBOOT_NEVER_TIMEOUT=y CONFIG_AUTOBOOT_STOP_STR_ENABLE=y CONFIG_AUTOBOOT_STOP_STR_CRYPT="$5$rounds=640000$HrpE65IkB8CM5nCL$BKT3QdF98Bo8fJpTr9tjZLZQyzqPASBY20xuK5Rent9" CONFIG_CONSOLE_RECORD=y -CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000 +CONFIG_CONSOLE_RECORD_OUT_SIZE=0x2000 CONFIG_PRE_CONSOLE_BUFFER=y CONFIG_LOG=y CONFIG_DISPLAY_BOARDINFO_LATE=y diff --git a/include/test/suites.h b/include/test/suites.h index d35cd83a4eb..c36aa568e78 100644 --- a/include/test/suites.h +++ b/include/test/suites.h @@ -29,6 +29,8 @@ int cmd_ut_category(const char *name, const char *prefix, int do_ut_addrmap(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); +int do_ut_bootmethod(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]); int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_ut_common(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); diff --git a/test/Makefile b/test/Makefile index b3b2902e2e7..abd605a4351 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 00000000000..bb1599b9c0d --- /dev/null +++ b/test/boot/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2021 Google LLC + +obj-$(CONFIG_BOOTMETHOD) += bootmethod.o diff --git a/test/boot/bootmethod.c b/test/boot/bootmethod.c new file mode 100644 index 00000000000..4467625c0fd --- /dev/null +++ b/test/boot/bootmethod.c @@ -0,0 +1,271 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2021 Google LLC + * Written by Simon Glass sjg@chromium.org + */ + +#include <common.h> +#include <dm.h> +#include <bootmethod.h> +#include <test/suites.h> +#include <test/ut.h> + +/* Declare a new bootmethod test */ +#define BOOTMETHOD_TEST(_name, _flags) \ + UNIT_TEST(_name, _flags, bootmethod_test) + +/* Check 'bootmethod list' command */ +static int bootmethod_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 ? "bootmethod list -p" : + "bootmethod 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.bootmethod"); + ut_assert_nextline("%3x [ %c ] %6s %-8s %s", 1, probe_ch, "OK", + "mmc", "mmc1.bootmethod"); + ut_assert_nextline("%3x [ %c ] %6s %-8s %s", 2, probe_ch, "OK", + "mmc", "mmc0.bootmethod"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(3 devices)"); + ut_assert_console_end(); + } + + return 0; +} +BOOTMETHOD_TEST(bootmethod_test_cmd_list, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootmethod select' and 'info' commands */ +static int bootmethod_test_cmd_select(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_asserteq(1, run_command("bootmethod info", 0)); + ut_assert_nextlinen("Please use"); + ut_assert_console_end(); + + ut_assertok(run_command("bootmethod select 0", 0)); + ut_assert_console_end(); + + ut_assertok(run_command("bootmethod info", 0)); + ut_assert_nextline("Name: mmc2.bootmethod"); + ut_assert_nextline("Uclass: mmc"); + ut_assert_console_end(); + + return 0; +} +BOOTMETHOD_TEST(bootmethod_test_cmd_select, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow scan/list' commands */ +static int bootmethod_test_cmd_bootflow(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootmethod select 2", 0)); + ut_assert_console_end(); + ut_assertok(run_command("bootflow scan -l", 0)); + ut_assert_nextline("Scanning for bootflows in bootmethod 'mmc0.bootmethod'"); + ut_assert_nextline("Seq Type State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 distro-boot loaded mmc 1 mmc0.bootmethod.part_1 extlinux/extlinux.conf"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(21 bootflows, 1 valid)"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow list", 0)); + ut_assert_nextline("Showing bootflows for bootmethod 'mmc0.bootmethod'"); + ut_assert_nextline("Seq Type State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 distro-boot loaded mmc 1 mmc0.bootmethod.part_1 extlinux/extlinux.conf"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(1 bootflow, 1 valid)"); + ut_assert_console_end(); + + return 0; +} +BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow scan/list' commands using all bootmethods */ +static int bootmethod_test_cmd_bootflow_glob(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan -l", 0)); + ut_assert_nextline("Scanning for bootflows in all bootmethods"); + ut_assert_nextline("Seq Type State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline("Scanning bootmethod 'mmc2.bootmethod':"); + ut_assert_nextline("Scanning bootmethod 'mmc1.bootmethod':"); + ut_assert_nextline("Scanning bootmethod 'mmc0.bootmethod':"); + ut_assert_nextline(" 0 distro-boot loaded mmc 1 mmc0.bootmethod.part_1 extlinux/extlinux.conf"); + ut_assert_nextline("No more bootmethods"); + 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 Type State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 distro-boot loaded mmc 1 mmc0.bootmethod.part_1 extlinux/extlinux.conf"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(1 bootflow, 1 valid)"); + ut_assert_console_end(); + + return 0; +} +BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_glob, + UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow scan -e' */ +static int bootmethod_test_cmd_bootflow_scan_e(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootflow scan -ale", 0)); + ut_assert_nextline("Scanning for bootflows in all bootmethods"); + ut_assert_nextline("Seq Type State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline("Scanning bootmethod 'mmc2.bootmethod':"); + ut_assert_nextline(" 0 distro-boot media mmc 0 mmc2.bootmethod.part_1 <NULL>"); + ut_assert_nextline(" ** No partition found, err=-93"); + ut_assert_nextline(" 1 distro-boot media mmc 0 mmc2.bootmethod.part_2 <NULL>"); + + ut_assert_skip_to_line("Scanning bootmethod 'mmc1.bootmethod':"); + ut_assert_skip_to_line("Scanning bootmethod 'mmc0.bootmethod':"); + ut_assert_nextline(" 28 distro-boot loaded mmc 1 mmc0.bootmethod.part_1 extlinux/extlinux.conf"); + ut_assert_nextline(" 29 distro-boot media mmc 0 mmc0.bootmethod.part_2 <NULL>"); + ut_assert_skip_to_line(" 3b distro-boot media mmc 0 mmc0.bootmethod.part_14 <NULL>"); + ut_assert_nextline(" ** No partition found, err=-2"); + ut_assert_nextline("No more bootmethods"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(60 bootflows, 1 valid)"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow list", 0)); + ut_assert_nextline("Showing all bootflows"); + ut_assert_nextline("Seq Type State Uclass Part Name Filename"); + ut_assert_nextlinen("---"); + ut_assert_nextline(" 0 distro-boot media mmc 0 mmc2.bootmethod.part_1 <NULL>"); + ut_assert_skip_to_line(" 28 distro-boot loaded mmc 1 mmc0.bootmethod.part_1 extlinux/extlinux.conf"); + ut_assert_skip_to_line(" 3b distro-boot media mmc 0 mmc0.bootmethod.part_14 <NULL>"); + ut_assert_nextlinen("---"); + ut_assert_nextline("(60 bootflows, 1 valid)"); + ut_assert_console_end(); + + return 0; +} +BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_scan_e, + UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow info' */ +static int bootmethod_test_cmd_bootflow_info(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootmethod select 2", 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: mmc0.bootmethod.part_1"); + ut_assert_nextline("Device: mmc0.bootmethod"); + ut_assert_nextline("Block dev: mmc0.blk"); + ut_assert_nextline("Sequence: 0"); + ut_assert_nextline("Type: distro-boot"); + ut_assert_nextline("State: loaded"); + 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: 237 (567 bytes)"); + ut_assert_nextline("Error: 0"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow info -d", 0)); + ut_assert_nextline("Name: mmc0.bootmethod.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; +} +BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_info, + UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow scan -b' to boot the first available bootmethod */ +static int bootmethod_test_cmd_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 'mmc0.bootmethod.part_1'"); + 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; +} +BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_scan_boot, + UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check 'bootflow boot' to boot a selected bootflow */ +static int bootmethod_test_cmd_bootflow_boot(struct unit_test_state *uts) +{ + console_record_reset_enable(); + ut_assertok(run_command("bootmethod select 2", 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 boot", 0)); + ut_assert_nextline("** Booting bootflow 'mmc0.bootmethod.part_1'"); + 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; +} +BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_boot, + UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +/* Check we can get a bootmethod */ +static int bootmethod_test_get(struct unit_test_state *uts) +{ + struct bootmethod_iter iter; + struct bootflow bflow; + + ut_assertok(bootmethod_scan_first_bootflow(&iter, 0, &bflow)); + + return 0; +} +BOOTMETHOD_TEST(bootmethod_test_get, UT_TESTF_DM | UT_TESTF_SCAN_FDT); + +int do_ut_bootmethod(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + struct unit_test *tests = UNIT_TEST_SUITE_START(bootmethod_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(bootmethod_test); + + return cmd_ut_category("bootmethod", "bootmethod_test_", + tests, n_ents, argc, argv); +} diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 90b260f72d6..c71f5575a04 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_BOOTMETHOD + U_BOOT_CMD_MKENT(bootmethod, CONFIG_SYS_MAXARGS, 1, do_ut_bootmethod, + "", ""), +#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, "", ""), diff --git a/try.sh b/try.sh new file mode 100755 index 00000000000..14519c3144c --- /dev/null +++ b/try.sh @@ -0,0 +1,131 @@ +#!/bin/bash + +set -e + +file=mmc.img +mnt=/mnt/x +fat=/mnt/y +dstdir=$fat/extlinux + +vmlinux=vmlinuz-5.3.7-301.fc31.armv7hl +initrd=initramfs-5.3.7-301.fc31.armv7hl.img +dtb=dtb-5.3.7-301.fc31.armv7hl/sandbox.dtb + +old() { + mkfs.vfat $file + sudo mount -o loop $file $mnt + #sudo cp /tmp/b/efi-x86_payload64/u-boot-payload.efi /mnt/x + #sudo cp /tmp/efi64/startup.nsh $mnt + #sudo cp /tmp/efi64/vmlinuz $mnt + echo >>/tmp/extlinux.conf <<EOF +ui menu.c32 + +menu autoboot Arch Boot. Automatic boot in # second{,s}. Press a key for options. +menu title Arch Boot Options. +menu hidden + +timeout 50 + +default Arch + +label Arch + kernel /zImage + append root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait consoleblank=0 no_console_suspend=1 console=ttymxc0,115200n8 + fdtdir /dtbs + initrd /initramfs-linux.img +EOF + sudo cp /tmp/extlinux.conf $mnt + ls $mnt + sudo umount $mnt +} + + +fat_setup() { + echo 'type=c' | sudo sfdisk $file + #sudo kpartx -a $file + loop=$(sudo losetup --show -f -P $file) + echo "Mounted to $loop" + fatpart="${loop}p1" + sudo mkfs.vfat $fatpart + sudo mount -o loop ${fatpart} $fat +} + + +fat_finish() { + sudo mkdir -p $dstdir + sudo cp /tmp/extlinux.conf $dstdir + + echo "vmlinux" | gzip >/tmp/inf + mkimage -f auto -d /tmp/inf /tmp/$vmlinux + + sudo cp /tmp/$vmlinux $fat + + echo "initd" >/tmp/$initrd + sudo cp /tmp/$initrd $fat + + dtb_dir="$(dirname /tmp/$dtb)" + mkdir -p $dtb_dir + echo "/dts-v1/; / {};" | dtc >/tmp/$dtb + sudo cp -r $dtb_dir $fat + + ls $dstdir + + sudo umount $fat + + losetup -d $loop +} + + +new() { + fat_setup + cat >/tmp/extlinux.conf << EOF +ui menu.c32 + +menu autoboot Arch Boot. Automatic boot in # second{,s}. Press a key for options. +menu title Arch Boot Options. +menu hidden + +timeout 50 + +default Arch + +label Arch + kernel /zImage + append root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait consoleblank=0 no_console_suspend=1 console=ttymxc0,115200n8 + fdtdir /dtbs + initrd /initramfs-linux.img +EOF + fat_finish +} + + +fedora31() { + fat_setup + cat >/tmp/extlinux.conf << EOF +# 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 /$vmlinux + append ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB + fdtdir /dtb-5.3.7-301.fc31.armv7hl/ + initrd /$initrd +EOF + fat_finish +} + +# Remove old devices +for dev in $(losetup |grep $file | awk '{print $1}'); do + echo "Remove $dev" + losetup -d $dev +done + +qemu-img create $file 20M +#old +#new +fedora31