summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/Kconfig2
-rw-r--r--test/Makefile5
-rw-r--r--test/boot/Makefile1
-rw-r--r--test/boot/bootdev.c58
-rw-r--r--test/boot/bootflow.c84
-rw-r--r--test/boot/cedit.c30
-rw-r--r--test/boot/expo.c2
-rw-r--r--test/boot/files/expo_ids.h3
-rw-r--r--test/boot/files/expo_layout.dts8
-rw-r--r--test/boot/measurement.c66
-rw-r--r--test/cmd/Makefile2
-rw-r--r--test/cmd/history.c49
-rw-r--r--test/cmd/mbr.c479
-rw-r--r--test/cmd_ut.c14
-rw-r--r--test/common/cread.c12
-rw-r--r--test/dm/Makefile3
-rw-r--r--test/dm/blk.c7
-rw-r--r--test/dm/eth.c12
-rw-r--r--test/dm/host.c26
-rw-r--r--test/dm/mux-emul.c2
-rw-r--r--test/dm/mux-mmio.c2
-rw-r--r--test/dm/nand.c104
-rw-r--r--test/dm/nop.c2
-rw-r--r--test/dm/ofnode.c258
-rw-r--r--test/dm/pci.c14
-rw-r--r--test/dm/phy.c2
-rw-r--r--test/dm/remoteproc.c2
-rw-r--r--test/dm/rkmtd.c200
-rw-r--r--test/dm/scmi.c391
-rw-r--r--test/dm/serial.c1
-rw-r--r--test/dm/sm.c65
-rw-r--r--test/dm/soc.c2
-rw-r--r--test/dm/sysreset.c6
-rw-r--r--test/dm/wdt.c4
-rw-r--r--test/fuzz/cmd_fuzz.c7
-rw-r--r--test/image/Kconfig60
-rw-r--r--test/image/Makefile8
-rw-r--r--test/image/spl_load.c677
-rw-r--r--test/image/spl_load_fs.c442
-rw-r--r--test/image/spl_load_nand.c56
-rw-r--r--test/image/spl_load_net.c254
-rw-r--r--test/image/spl_load_nor.c41
-rw-r--r--test/image/spl_load_os.c74
-rw-r--r--test/image/spl_load_spi.c42
-rw-r--r--test/lib/kconfig.c4
-rw-r--r--test/lib/lmb.c13
-rw-r--r--test/py/tests/fs_helper.py11
-rw-r--r--test/py/tests/test_efi_secboot/test_signed.py42
-rw-r--r--test/py/tests/test_efi_secboot/test_signed_intca.py14
-rw-r--r--test/py/tests/test_efi_secboot/test_unsigned.py14
-rw-r--r--test/py/tests/test_fs/conftest.py53
-rw-r--r--test/py/tests/test_fs/test_erofs.py9
-rw-r--r--test/py/tests/test_fs/test_fs_fat.py25
-rw-r--r--test/py/tests/test_fs/test_squashfs/test_sqfs_ls.py9
-rw-r--r--test/py/tests/test_net.py137
-rw-r--r--test/py/tests/test_sandbox_opts.py30
-rw-r--r--test/py/tests/test_sleep.py18
-rw-r--r--test/py/tests/test_spl.py10
-rw-r--r--test/py/tests/test_tpm2.py20
-rw-r--r--test/py/tests/test_ut.py7
-rw-r--r--test/test-main.c5
61 files changed, 3757 insertions, 243 deletions
diff --git a/test/Kconfig b/test/Kconfig
index 830245b6f9a..c3db727c58e 100644
--- a/test/Kconfig
+++ b/test/Kconfig
@@ -2,6 +2,7 @@ menu "Testing"
config UNIT_TEST
bool "Unit tests"
+ depends on CMDLINE
help
Select this to compile in unit tests for various parts of
U-Boot. Test suites will be subcommands of the "ut" command.
@@ -101,6 +102,7 @@ config UT_UNICODE
source "test/dm/Kconfig"
source "test/env/Kconfig"
+source "test/image/Kconfig"
source "test/lib/Kconfig"
source "test/optee/Kconfig"
source "test/overlay/Kconfig"
diff --git a/test/Makefile b/test/Makefile
index 178773647a8..8e1fed2c28b 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -3,9 +3,6 @@
# (C) Copyright 2012 The Chromium Authors
obj-y += test-main.o
-ifdef CONFIG_SPL_LOAD_FIT
-obj-$(CONFIG_SANDBOX) += image/
-endif
ifneq ($(CONFIG_$(SPL_)BLOBLIST),)
obj-$(CONFIG_$(SPL_)CMDLINE) += bloblist.o
@@ -30,4 +27,6 @@ obj-$(CONFIG_UNIT_TEST) += boot/
obj-$(CONFIG_UNIT_TEST) += common/
obj-y += log/
obj-$(CONFIG_$(SPL_)UT_UNICODE) += unicode_ut.o
+else
+obj-$(CONFIG_SPL_UT_LOAD) += image/
endif
diff --git a/test/boot/Makefile b/test/boot/Makefile
index 52947580ae6..068522cb9e0 100644
--- a/test/boot/Makefile
+++ b/test/boot/Makefile
@@ -4,6 +4,7 @@
obj-$(CONFIG_BOOTSTD) += bootdev.o bootstd_common.o bootflow.o bootmeth.o
obj-$(CONFIG_FIT) += image.o
+obj-$(CONFIG_MEASURED_BOOT) += measurement.o
obj-$(CONFIG_EXPO) += expo.o
obj-$(CONFIG_CEDIT) += cedit.o
diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c
index 6b29213416d..0702fccdae6 100644
--- a/test/boot/bootdev.c
+++ b/test/boot/bootdev.c
@@ -190,12 +190,21 @@ static int bootdev_test_any(struct unit_test_state *uts)
BOOTSTD_TEST(bootdev_test_any, UT_TESTF_DM | UT_TESTF_SCAN_FDT |
UT_TESTF_ETH_BOOTDEV);
-/* Check bootdev ordering with the bootdev-order property */
+/*
+ * Check bootdev ordering with the bootdev-order property and boot_targets
+ * environment variable
+ */
static int bootdev_test_order(struct unit_test_state *uts)
{
struct bootflow_iter iter;
struct bootflow bflow;
+ test_set_skip_delays(true);
+
+ /* Start up USB which gives us three additional bootdevs */
+ usb_started = false;
+ ut_assertok(run_command("usb start", 0));
+
/*
* First try the order set by the bootdev-order property
* Like all sandbox unit tests this relies on the devicetree setting up
@@ -213,12 +222,55 @@ static int bootdev_test_order(struct unit_test_state *uts)
bootflow_iter_uninit(&iter);
/* Use the environment variable to override it */
- ut_assertok(env_set("boot_targets", "mmc1 mmc2"));
+ ut_assertok(env_set("boot_targets", "mmc1 mmc2 usb"));
ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
- ut_asserteq(2, iter.num_devs);
+ ut_asserteq(5, iter.num_devs);
ut_asserteq_str("mmc1.bootdev", iter.dev_used[0]->name);
ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name);
+ ut_asserteq_str("usb_mass_storage.lun0.bootdev",
+ iter.dev_used[2]->name);
+ bootflow_iter_uninit(&iter);
+
+ /* Try a single uclass */
+ ut_assertok(env_set("boot_targets", NULL));
+ ut_assertok(bootflow_scan_first(NULL, "mmc", &iter, 0, &bflow));
+ ut_asserteq(2, iter.num_devs);
+
+ /* Now scan past mmc1 and make sure that only mmc0 shows up */
+ ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
+ ut_asserteq(3, iter.num_devs);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
+ ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
+ ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
+ bootflow_iter_uninit(&iter);
+
+ /* Try a single uclass with boot_targets */
+ ut_assertok(env_set("boot_targets", "mmc"));
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
+ ut_asserteq(2, iter.num_devs);
+
+ /* Now scan past mmc1 and make sure that only mmc0 shows up */
+ ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
+ ut_asserteq(3, iter.num_devs);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
+ ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
+ ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
+ bootflow_iter_uninit(&iter);
+
+ /* Try a single uclass with boot_targets */
+ ut_assertok(env_set("boot_targets", "mmc usb"));
+ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow));
+ ut_asserteq(2, iter.num_devs);
+
+ /* Now scan past mmc1 and make sure that the 3 USB devices show up */
+ ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow));
+ ut_asserteq(6, iter.num_devs);
+ ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name);
+ ut_asserteq_str("mmc1.bootdev", iter.dev_used[1]->name);
+ ut_asserteq_str("mmc0.bootdev", iter.dev_used[2]->name);
+ ut_asserteq_str("usb_mass_storage.lun0.bootdev",
+ iter.dev_used[3]->name);
bootflow_iter_uninit(&iter);
return 0;
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index f5b2059140a..b97c566f000 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -511,19 +511,27 @@ BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
/**
* prep_mmc_bootdev() - Set up an mmc bootdev so we can access other distros
*
+ * After calling this function, set std->bootdev_order to *@old_orderp to
+ * restore normal operation of bootstd (i.e. with the original bootdev order)
+ *
* @uts: Unit test state
- * @mmc_dev: MMC device to use, e.g. "mmc4"
+ * @mmc_dev: MMC device to use, e.g. "mmc4". Note that this must remain valid
+ * in the caller until
+ * @bind_cros: true to bind the ChromiumOS bootmeth
+ * @old_orderp: Returns the original bootdev order, which must be restored
* Returns 0 on success, -ve on failure
*/
static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
- bool bind_cros)
+ bool bind_cros, const char ***old_orderp)
{
- const char *order[] = {"mmc2", "mmc1", mmc_dev, NULL};
+ static const char *order[] = {"mmc2", "mmc1", NULL, NULL};
struct udevice *dev, *bootstd;
struct bootstd_priv *std;
const char **old_order;
ofnode root, node;
+ order[2] = mmc_dev;
+
/* Enable the mmc4 node since we need a second bootflow */
root = oftree_root(oftree_default());
node = ofnode_find_subnode(root, mmc_dev);
@@ -546,26 +554,49 @@ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
std = dev_get_priv(bootstd);
old_order = std->bootdev_order;
std->bootdev_order = order;
+ *old_orderp = old_order;
+
+ return 0;
+}
+
+/**
+ * scan_mmc_bootdev() - Set up an mmc bootdev so we can access other distros
+ *
+ * @uts: Unit test state
+ * @mmc_dev: MMC device to use, e.g. "mmc4"
+ * @bind_cros: true to bind the ChromiumOS bootmeth
+ * Returns 0 on success, -ve on failure
+ */
+static int scan_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
+ bool bind_cros)
+{
+ struct bootstd_priv *std;
+ struct udevice *bootstd;
+ const char **old_order;
+
+ ut_assertok(prep_mmc_bootdev(uts, mmc_dev, bind_cros, &old_order));
console_record_reset_enable();
ut_assertok(run_command("bootflow scan", 0));
ut_assert_console_end();
/* Restore the order used by the device tree */
+ ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
+ std = dev_get_priv(bootstd);
std->bootdev_order = old_order;
return 0;
}
/**
- * prep_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian
+ * scan_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian
*
* @uts: Unit test state
* Returns 0 on success, -ve on failure
*/
-static int prep_mmc4_bootdev(struct unit_test_state *uts)
+static int scan_mmc4_bootdev(struct unit_test_state *uts)
{
- ut_assertok(prep_mmc_bootdev(uts, "mmc4", false));
+ ut_assertok(scan_mmc_bootdev(uts, "mmc4", false));
return 0;
}
@@ -573,9 +604,13 @@ static int prep_mmc4_bootdev(struct unit_test_state *uts)
/* Check 'bootflow menu' to select a bootflow */
static int bootflow_cmd_menu(struct unit_test_state *uts)
{
+ struct bootstd_priv *std;
char prev[3];
- ut_assertok(prep_mmc4_bootdev(uts));
+ /* get access to the current bootflow */
+ ut_assertok(bootstd_get_priv(&std));
+
+ ut_assertok(scan_mmc4_bootdev(uts));
/* Add keypresses to move to and select the second one in the list */
prev[0] = CTL_CH('n');
@@ -585,6 +620,17 @@ static int bootflow_cmd_menu(struct unit_test_state *uts)
ut_assertok(run_command("bootflow menu", 0));
ut_assert_nextline("Selected: Armbian");
+ ut_assertnonnull(std->cur_bootflow);
+ ut_assert_console_end();
+
+ /* Check not selecting anything */
+ prev[0] = '\e';
+ prev[1] = '\0';
+ ut_asserteq(1, console_in_puts(prev));
+
+ ut_asserteq(1, run_command("bootflow menu", 0));
+ ut_assertnull(std->cur_bootflow);
+ ut_assert_nextline("Nothing chosen");
ut_assert_console_end();
return 0;
@@ -681,7 +727,7 @@ static int bootflow_menu_theme(struct unit_test_state *uts)
ofnode node;
int i;
- ut_assertok(prep_mmc4_bootdev(uts));
+ ut_assertok(scan_mmc4_bootdev(uts));
ut_assertok(bootflow_menu_new(&exp));
node = ofnode_path("/bootstd/theme");
@@ -973,10 +1019,30 @@ static int bootflow_cmdline(struct unit_test_state *uts)
}
BOOTSTD_TEST(bootflow_cmdline, 0);
+/* test a few special changes to a long command line */
+static int bootflow_cmdline_special(struct unit_test_state *uts)
+{
+ char buf[500];
+ int pos;
+
+ /*
+ * check handling of an argument which has an embedded '=', as well as
+ * handling of a argument which partially matches ("ro" and "root")
+ */
+ ut_asserteq(32, cmdline_set_arg(
+ buf, sizeof(buf),
+ "loglevel=7 root=PARTUUID=d68352e3 rootwait ro noinitrd",
+ "root", NULL, &pos));
+ ut_asserteq_str("loglevel=7 rootwait ro noinitrd", buf);
+
+ return 0;
+}
+BOOTSTD_TEST(bootflow_cmdline_special, 0);
+
/* Test ChromiumOS bootmeth */
static int bootflow_cros(struct unit_test_state *uts)
{
- ut_assertok(prep_mmc_bootdev(uts, "mmc5", true));
+ ut_assertok(scan_mmc_bootdev(uts, "mmc5", true));
ut_assertok(run_command("bootflow list", 0));
ut_assert_nextlinen("Showing all");
diff --git a/test/boot/cedit.c b/test/boot/cedit.c
index ab2b8a1f9ff..aa417190486 100644
--- a/test/boot/cedit.c
+++ b/test/boot/cedit.c
@@ -58,6 +58,7 @@ BOOTSTD_TEST(cedit_base, 0);
/* Check the cedit write_fdt and read_fdt commands */
static int cedit_fdt(struct unit_test_state *uts)
{
+ struct scene_obj_textline *tline;
struct video_priv *vid_priv;
extern struct expo *cur_exp;
struct scene_obj_menu *menu;
@@ -66,6 +67,7 @@ static int cedit_fdt(struct unit_test_state *uts)
struct scene *scn;
oftree tree;
ofnode node;
+ char *str;
void *fdt;
int i;
@@ -79,6 +81,12 @@ static int cedit_fdt(struct unit_test_state *uts)
ut_assertnonnull(menu);
menu->cur_item_id = ID_CPU_SPEED_2;
+ /* get a textline to fiddle with too */
+ tline = scene_obj_find(scn, ID_MACHINE_NAME, SCENEOBJT_TEXTLINE);
+ ut_assertnonnull(tline);
+ str = abuf_data(&tline->buf);
+ strcpy(str, "my-machine");
+
ut_assertok(run_command("cedit write_fdt hostfs - settings.dtb", 0));
ut_assertok(run_commandf("load hostfs - %lx settings.dtb", addr));
ut_assert_nextlinen("1024 bytes read");
@@ -86,26 +94,29 @@ static int cedit_fdt(struct unit_test_state *uts)
fdt = map_sysmem(addr, 1024);
tree = oftree_from_fdt(fdt);
node = ofnode_find_subnode(oftree_root(tree), CEDIT_NODE_NAME);
+ ut_assert(ofnode_valid(node));
ut_asserteq(ID_CPU_SPEED_2,
ofnode_read_u32_default(node, "cpu-speed", 0));
ut_asserteq_str("2.5 GHz", ofnode_read_string(node, "cpu-speed-str"));
- ut_assert(ofnode_valid(node));
+ ut_asserteq_str("my-machine", ofnode_read_string(node, "machine-name"));
- /* There should only be 4 properties */
+ /* There should only be 5 properties */
for (i = 0, ofnode_first_property(node, &prop); ofprop_valid(&prop);
i++, ofnode_next_property(&prop))
;
- ut_asserteq(4, i);
+ ut_asserteq(5, i);
ut_assert_console_end();
/* reset the expo */
menu->cur_item_id = ID_CPU_SPEED_1;
+ *str = '\0';
/* load in the settings and make sure they update */
ut_assertok(run_command("cedit read_fdt hostfs - settings.dtb", 0));
ut_asserteq(ID_CPU_SPEED_2, menu->cur_item_id);
+ ut_asserteq_str("my-machine", ofnode_read_string(node, "machine-name"));
ut_assertnonnull(menu);
ut_assert_console_end();
@@ -117,10 +128,12 @@ BOOTSTD_TEST(cedit_fdt, 0);
/* Check the cedit write_env and read_env commands */
static int cedit_env(struct unit_test_state *uts)
{
+ struct scene_obj_textline *tline;
struct video_priv *vid_priv;
extern struct expo *cur_exp;
struct scene_obj_menu *menu;
struct scene *scn;
+ char *str;
console_record_reset_enable();
ut_assertok(run_command("cedit load hostfs - cedit.dtb", 0));
@@ -132,25 +145,36 @@ static int cedit_env(struct unit_test_state *uts)
ut_assertnonnull(menu);
menu->cur_item_id = ID_CPU_SPEED_2;
+ /* get a textline to fiddle with too */
+ tline = scene_obj_find(scn, ID_MACHINE_NAME, SCENEOBJT_TEXTLINE);
+ ut_assertnonnull(tline);
+ str = abuf_data(&tline->buf);
+ strcpy(str, "my-machine");
+
ut_assertok(run_command("cedit write_env -v", 0));
ut_assert_nextlinen("c.cpu-speed=7");
ut_assert_nextlinen("c.cpu-speed-str=2.5 GHz");
ut_assert_nextlinen("c.power-loss=10");
ut_assert_nextlinen("c.power-loss-str=Always Off");
+ ut_assert_nextlinen("c.machine-name=my-machine");
ut_assert_console_end();
ut_asserteq(7, env_get_ulong("c.cpu-speed", 10, 0));
ut_asserteq_str("2.5 GHz", env_get("c.cpu-speed-str"));
+ ut_asserteq_str("my-machine", env_get("c.machine-name"));
/* reset the expo */
menu->cur_item_id = ID_CPU_SPEED_1;
+ *str = '\0';
ut_assertok(run_command("cedit read_env -v", 0));
ut_assert_nextlinen("c.cpu-speed=7");
ut_assert_nextlinen("c.power-loss=10");
+ ut_assert_nextlinen("c.machine-name=my-machine");
ut_assert_console_end();
ut_asserteq(ID_CPU_SPEED_2, menu->cur_item_id);
+ ut_asserteq_str("my-machine", env_get("c.machine-name"));
return 0;
}
diff --git a/test/boot/expo.c b/test/boot/expo.c
index 90027409c81..714fdfa415d 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -654,7 +654,7 @@ static int expo_test_build(struct unit_test_state *uts)
ut_asserteq_str("name", exp->name);
ut_asserteq(0, exp->scene_id);
- ut_asserteq(ID_DYNAMIC_START + 20, exp->next_id);
+ ut_asserteq(ID_DYNAMIC_START + 24, exp->next_id);
ut_asserteq(false, exp->popup);
/* check the scene */
diff --git a/test/boot/files/expo_ids.h b/test/boot/files/expo_ids.h
index 027d44bf38c..a86e0d06f6b 100644
--- a/test/boot/files/expo_ids.h
+++ b/test/boot/files/expo_ids.h
@@ -21,5 +21,8 @@ enum {
ID_AC_ON,
ID_AC_MEMORY,
+ ID_MACHINE_NAME,
+ ID_MACHINE_NAME_EDIT,
+
ID_DYNAMIC_START,
};
diff --git a/test/boot/files/expo_layout.dts b/test/boot/files/expo_layout.dts
index cb2a674d9d5..bed552288f4 100644
--- a/test/boot/files/expo_layout.dts
+++ b/test/boot/files/expo_layout.dts
@@ -55,6 +55,14 @@
start-bit = <0x422>;
bit-length = <2>;
};
+
+ machine-name {
+ id = <ID_MACHINE_NAME>;
+ type = "textline";
+ max-chars = <20>;
+ title = "Machine name";
+ edit-id = <ID_MACHINE_NAME_EDIT>;
+ };
};
};
diff --git a/test/boot/measurement.c b/test/boot/measurement.c
new file mode 100644
index 00000000000..9db2ed324c2
--- /dev/null
+++ b/test/boot/measurement.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Test for measured boot functions
+ *
+ * Copyright 2023 IBM Corp.
+ * Written by Eddie James <eajames@linux.ibm.com>
+ */
+
+#include <common.h>
+#include <bootm.h>
+#include <malloc.h>
+#include <test/suites.h>
+#include <test/test.h>
+#include <test/ut.h>
+#include <asm/io.h>
+
+#define MEASUREMENT_TEST(_name, _flags) \
+ UNIT_TEST(_name, _flags, measurement_test)
+
+static int measure(struct unit_test_state *uts)
+{
+ struct bootm_headers images;
+ const size_t size = 1024;
+ u8 *kernel;
+ u8 *initrd;
+ size_t i;
+
+ kernel = malloc(size);
+ initrd = malloc(size);
+
+ images.os.image_start = map_to_sysmem(kernel);
+ images.os.image_len = size;
+
+ images.rd_start = map_to_sysmem(initrd);
+ images.rd_end = images.rd_start + size;
+
+ images.ft_addr = malloc(size);
+ images.ft_len = size;
+
+ env_set("bootargs", "measurement testing");
+
+ for (i = 0; i < size; ++i) {
+ kernel[i] = 0xf0 | (i & 0xf);
+ initrd[i] = (i & 0xf0) | 0xf;
+ images.ft_addr[i] = i & 0xff;
+ }
+
+ ut_assertok(bootm_measure(&images));
+
+ free(images.ft_addr);
+ free(initrd);
+ free(kernel);
+
+ return 0;
+}
+MEASUREMENT_TEST(measure, 0);
+
+int do_ut_measurement(struct cmd_tbl *cmdtp, int flag, int argc,
+ char *const argv[])
+{
+ struct unit_test *tests = UNIT_TEST_SUITE_START(measurement_test);
+ const int n_ents = UNIT_TEST_SUITE_COUNT(measurement_test);
+
+ return cmd_ut_category("measurement", "measurement_test_", tests,
+ n_ents, argc, argv);
+}
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index 6e3d7e919ef..e296ba1192b 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o
obj-$(CONFIG_CMD_BDI) += bdinfo.o
obj-$(CONFIG_CMD_FDT) += fdt.o
obj-$(CONFIG_CONSOLE_TRUETYPE) += font.o
+obj-$(CONFIG_CMD_HISTORY) += history.o
obj-$(CONFIG_CMD_LOADM) += loadm.o
obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o
ifdef CONFIG_CMD_PCI
@@ -23,6 +24,7 @@ obj-$(CONFIG_CMD_PINMUX) += pinmux.o
obj-$(CONFIG_CMD_PWM) += pwm.o
obj-$(CONFIG_CMD_SEAMA) += seama.o
ifdef CONFIG_SANDBOX
+obj-$(CONFIG_CMD_MBR) += mbr.o
obj-$(CONFIG_CMD_READ) += rw.o
obj-$(CONFIG_CMD_SETEXPR) += setexpr.o
obj-$(CONFIG_ARM_FFA_TRANSPORT) += armffa.o
diff --git a/test/cmd/history.c b/test/cmd/history.c
new file mode 100644
index 00000000000..06517fcdbb5
--- /dev/null
+++ b/test/cmd/history.c
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Tests for history command
+ *
+ * Copyright 2023 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <cli.h>
+#include <command.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+static int lib_test_history(struct unit_test_state *uts)
+{
+ static const char cmd1[] = "setenv fred hello";
+ static const char cmd2[] = "print fred";
+
+ /* running commands directly does not add to history */
+ ut_assertok(run_command(cmd1, 0));
+ ut_assert_console_end();
+ ut_assertok(run_command("history", 0));
+ ut_assert_console_end();
+
+ /* enter commands via the console */
+ console_in_puts(cmd1);
+ console_in_puts("\n");
+ ut_asserteq(strlen(cmd1), cli_readline(""));
+ ut_assert_nextline(cmd1);
+
+ console_in_puts(cmd2);
+ console_in_puts("\n");
+ ut_asserteq(strlen(cmd2), cli_readline(""));
+ ut_assert_nextline(cmd2);
+
+ ut_assertok(run_command("print fred", 0));
+ ut_assert_nextline("fred=hello");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("history", 0));
+ ut_assert_nextline(cmd1);
+ ut_assert_nextline(cmd2);
+ ut_assert_console_end();
+
+ return 0;
+}
+LIB_TEST(lib_test_history, UT_TESTF_CONSOLE_REC);
diff --git a/test/cmd/mbr.c b/test/cmd/mbr.c
new file mode 100644
index 00000000000..46b78e706ca
--- /dev/null
+++ b/test/cmd/mbr.c
@@ -0,0 +1,479 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Tests for mbr command
+ *
+ * Copyright 2023 Matrox Video
+ * Written by Alex Gendin <agendin@matrox.com>
+ */
+
+#include <dm.h>
+#include <console.h>
+#include <dm/test.h>
+#include <mapmem.h>
+#include <part.h>
+#include <asm/global_data.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <test/suites.h>
+#include <test/ut.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+/*
+ * Requirements for running test manually:
+ * mmc6.img - File size needs to be at least 12 MiB
+ *
+ * Command to create mmc6.img:
+ * $ dd if=/dev/zero of=mmc6.img bs=12M count=1
+ *
+ * To run this test manually, place mmc6.img into the same directory as u-boot,
+ * then run:
+ * $ ./u-boot -Tc 'ut mbr'
+ *
+ * To run this test as part of U-Boot test:
+ * $ ./test/py/test.py --bd sandbox --build -k ut_dm -v
+ * Note: mmc6.img will be created by the test suit.
+ */
+
+static char * mbr_parts_header = "setenv mbr_parts '";
+static char * mbr_parts_p1 = "uuid_disk=0x12345678;name=p1,start=8M,bootable,size=1M,id=0x0e";
+static char * mbr_parts_p2 = ";name=p2,size=1M,id=0x0e";
+static char * mbr_parts_p3 = ";name=p3,size=1M,id=0x0e";
+static char * mbr_parts_p4 = ";name=p4,size=1M,id=0x0e";
+static char * mbr_parts_p5 = ";name=[ext],size=2M,id=0x05;name=p5,size=1M,id=0x0e";
+static char * mbr_parts_tail = "'";
+
+/*
+ * One MBR partition
+000001b0 00 00 00 00 00 00 00 00 78 56 34 12 00 00 80 05 |........xV4.....|
+000001c0 05 01 0e 25 24 01 00 40 00 00 00 08 00 00 00 00 |...%$..@........|
+000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+*/
+static unsigned mbr_cmp_start = 0x1B8;
+static unsigned mbr_cmp_size = 0x48;
+static unsigned char mbr_parts_ref_p1[] = {
+ 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x80, 0x05,
+0x05, 0x01, 0x0e, 0x25, 0x24, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
+};
+
+/*
+ * Two MBR partitions
+000001b0 00 00 00 00 00 00 00 00 78 56 34 12 00 00 80 05 |........xV4.....|
+000001c0 05 01 0e 25 24 01 00 40 00 00 00 08 00 00 00 25 |...%$..@.......%|
+000001d0 25 01 0e 46 05 01 00 48 00 00 00 08 00 00 00 00 |%..F...H........|
+000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+*/
+static unsigned char mbr_parts_ref_p2[] = {
+ 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x80, 0x05,
+0x05, 0x01, 0x0e, 0x25, 0x24, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x25,
+0x25, 0x01, 0x0e, 0x46, 0x05, 0x01, 0x00, 0x48, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
+};
+
+/*
+ * Three MBR partitions
+000001b0 00 00 00 00 00 00 00 00 78 56 34 12 00 00 80 05 |........xV4.....|
+000001c0 05 01 0e 25 24 01 00 40 00 00 00 08 00 00 00 25 |...%$..@.......%|
+000001d0 25 01 0e 46 05 01 00 48 00 00 00 08 00 00 00 46 |%..F...H.......F|
+000001e0 06 01 0e 66 25 01 00 50 00 00 00 08 00 00 00 00 |...f%..P........|
+000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+*/
+static unsigned char mbr_parts_ref_p3[] = {
+ 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x80, 0x05,
+0x05, 0x01, 0x0e, 0x25, 0x24, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x25,
+0x25, 0x01, 0x0e, 0x46, 0x05, 0x01, 0x00, 0x48, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x46,
+0x06, 0x01, 0x0e, 0x66, 0x25, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
+};
+
+/*
+ * Four MBR partitions
+000001b0 00 00 00 00 00 00 00 00 78 56 34 12 00 00 80 05 |........xV4.....|
+000001c0 05 01 0e 25 24 01 00 40 00 00 00 08 00 00 00 25 |...%$..@.......%|
+000001d0 25 01 0e 46 05 01 00 48 00 00 00 08 00 00 00 46 |%..F...H.......F|
+000001e0 06 01 0e 66 25 01 00 50 00 00 00 08 00 00 00 66 |...f%..P.......f|
+000001f0 26 01 0e 87 06 01 00 58 00 00 00 08 00 00 55 aa |&......X......U.|
+*/
+static unsigned char mbr_parts_ref_p4[] = {
+ 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x80, 0x05,
+0x05, 0x01, 0x0e, 0x25, 0x24, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x25,
+0x25, 0x01, 0x0e, 0x46, 0x05, 0x01, 0x00, 0x48, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x46,
+0x06, 0x01, 0x0e, 0x66, 0x25, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x66,
+0x26, 0x01, 0x0e, 0x87, 0x06, 0x01, 0x00, 0x58, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x55, 0xaa
+};
+
+/*
+ * Five MBR partitions
+000001b0 00 00 00 00 00 00 00 00 78 56 34 12 00 00 80 05 |........xV4.....|
+000001c0 05 01 0e 25 24 01 00 40 00 00 00 08 00 00 00 25 |...%$..@.......%|
+000001d0 25 01 0e 46 05 01 00 48 00 00 00 08 00 00 00 46 |%..F...H.......F|
+000001e0 06 01 0e 66 25 01 00 50 00 00 00 08 00 00 00 66 |...f%..P.......f|
+000001f0 26 01 05 a7 26 01 00 58 00 00 00 10 00 00 55 aa |&...&..X......U.|
+*/
+static unsigned char mbr_parts_ref_p5[] = {
+ 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x80, 0x05,
+0x05, 0x01, 0x0e, 0x25, 0x24, 0x01, 0x00, 0x40, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x25,
+0x25, 0x01, 0x0e, 0x46, 0x05, 0x01, 0x00, 0x48, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x46,
+0x06, 0x01, 0x0e, 0x66, 0x25, 0x01, 0x00, 0x50, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x66,
+0x26, 0x01, 0x05, 0xa7, 0x26, 0x01, 0x00, 0x58, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x55, 0xaa
+};
+static unsigned ebr_cmp_start = 0x1B8;
+static unsigned ebr_cmp_size = 0x48;
+/*
+ * EBR
+00b001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 87 |................|
+00b001c0 07 01 0e a7 26 01 00 08 00 00 00 08 00 00 00 00 |....&...........|
+00b001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00b001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+00b001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+*/
+static unsigned char ebr_parts_ref_p5[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87,
+0x07, 0x01, 0x0e, 0xa7, 0x26, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa
+};
+
+/* Fill write buffers with pseudo-random data */
+static void init_write_buffers(char *mbr_wb, size_t mbr_wb_size,
+ char *ebr_wb, size_t ebr_wb_size, unsigned seed)
+{
+ while (mbr_wb_size--) {
+ *mbr_wb++ = seed;
+ seed *= 43;
+ seed += 17 + mbr_wb_size/4;
+ }
+ while (ebr_wb_size--) {
+ *ebr_wb++ = seed;
+ seed *= 43;
+ seed += 17 + ebr_wb_size/4;
+ }
+}
+
+/* Build string with MBR partition(s) layout */
+static unsigned build_mbr_parts(char *buf, size_t buf_size, unsigned num_parts)
+{
+ size_t bytes_remaining, cur_str_size;
+ char * cur_buf;
+
+ if (!num_parts || num_parts > 5 || !buf)
+ return 1;
+
+ cur_buf = buf;
+ *cur_buf = '\0';
+ bytes_remaining = buf_size;
+
+ cur_str_size = sizeof(mbr_parts_header);
+ if (cur_str_size + 1 > bytes_remaining)
+ return 1;
+ strcat(cur_buf, mbr_parts_header);
+ bytes_remaining -= cur_str_size;
+
+ if (num_parts >= 1) {
+ cur_str_size = sizeof(mbr_parts_p1);
+ if (cur_str_size + 1 > bytes_remaining)
+ return 1;
+ strcat(cur_buf, mbr_parts_p1);
+ bytes_remaining -= cur_str_size;
+
+ if (num_parts >= 2) {
+ cur_str_size = sizeof(mbr_parts_p2);
+ if (cur_str_size + 1 > bytes_remaining)
+ return 1;
+ strcat(cur_buf, mbr_parts_p2);
+ bytes_remaining -= cur_str_size;
+
+ if (num_parts >= 3) {
+ cur_str_size = sizeof(mbr_parts_p3);
+ if (cur_str_size + 1 > bytes_remaining)
+ return 1;
+ strcat(cur_buf, mbr_parts_p3);
+ bytes_remaining -= cur_str_size;
+
+ if (num_parts == 4) {
+ cur_str_size = sizeof(mbr_parts_p4);
+ if (cur_str_size + 1 > bytes_remaining)
+ return 1;
+ strcat(cur_buf, mbr_parts_p4);
+ bytes_remaining -= cur_str_size;
+
+ }
+ else if (num_parts == 5) {
+ cur_str_size = sizeof(mbr_parts_p5);
+ if (cur_str_size + 1 > bytes_remaining)
+ return 1;
+ strcat(cur_buf, mbr_parts_p5);
+ bytes_remaining -= cur_str_size;
+
+ }
+ }
+ }
+ }
+
+ cur_str_size = sizeof(mbr_parts_tail);
+ if (cur_str_size + 1 > bytes_remaining)
+ return 1;
+ strcat(cur_buf, mbr_parts_tail);
+
+ return 0;
+}
+
+static int mbr_test_run(struct unit_test_state *uts)
+{
+ struct blk_desc *mmc_dev_desc;
+ unsigned char mbr_wbuf[512], ebr_wbuf[512], rbuf[512];
+ char mbr_parts_buf[256];
+ ulong mbr_wa, ebr_wa, ra, ebr_blk, mbr_parts_max;
+ struct udevice *dev;
+ ofnode root, node;
+
+ /* Enable the mmc6 node for this test */
+ root = oftree_root(oftree_default());
+ node = ofnode_find_subnode(root, "mmc6");
+ ut_assert(ofnode_valid(node));
+ ut_assertok(lists_bind_fdt(gd->dm_root, node, &dev, NULL, false));
+
+ mbr_parts_max = sizeof('\0') + 2 +
+ strlen(mbr_parts_header) +
+ strlen(mbr_parts_p1) +
+ strlen(mbr_parts_p2) +
+ strlen(mbr_parts_p3) +
+ max(strlen(mbr_parts_p4), strlen(mbr_parts_p5)) +
+ strlen(mbr_parts_tail);
+ ut_assertf(sizeof(mbr_parts_buf) >= mbr_parts_max, "Buffer avail: %ld; buffer req: %ld\n",
+ sizeof(mbr_parts_buf), mbr_parts_max);
+
+ mbr_wa = map_to_sysmem(mbr_wbuf);
+ ebr_wa = map_to_sysmem(ebr_wbuf);
+ ra = map_to_sysmem(rbuf);
+ ebr_blk = (ulong)0xB00000 / 0x200;
+
+ /* Make sure mmc6 exists */
+ ut_asserteq(6, blk_get_device_by_str("mmc", "6", &mmc_dev_desc));
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("mmc dev 6"));
+ ut_assert_nextline("switch to partitions #0, OK");
+ ut_assert_nextline("mmc6 is current device");
+ ut_assertok(ut_check_console_end(uts));
+
+ /* Make sure mmc6 is 12+ MiB in size */
+ ut_assertok(run_commandf("mmc read 0x%lx 0x%lx 1", ra, (ulong)0xBFFE00 / 0x200));
+
+ /* Test one MBR partition */
+ init_write_buffers(mbr_wbuf, sizeof(mbr_wbuf), ebr_wbuf, sizeof(ebr_wbuf), __LINE__);
+ ut_assertok(build_mbr_parts(mbr_parts_buf, sizeof(mbr_parts_buf), 1));
+ ut_assertok(run_commandf("write mmc 6:0 0x%lx 0 1", mbr_wa));
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
+ ut_assertok(memcmp(mbr_wbuf, rbuf, 512));
+ ut_assertok(run_commandf("write mmc 6:0 0x%lx 0x%lx 1", ebr_wa, ebr_blk));
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
+ ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
+ ut_assertok(console_record_reset_enable());
+ ut_assertf(0 == run_commandf(mbr_parts_buf), "Invalid partitions string: %s\n", mbr_parts_buf);
+ ut_assertok(run_commandf("mbr write mmc 6"));
+ ut_assert_nextline("MBR: write success!");
+ ut_assertok(run_commandf("mbr verify mmc 6"));
+ ut_assert_nextline("MBR: verify success!");
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
+ ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
+ ut_assertok(ut_check_console_end(uts));
+ /*
+ 000001b0 00 00 00 00 00 00 00 00 78 56 34 12 00 00 80 05 |........xV4.....|
+ 000001c0 05 01 0e 25 24 01 00 40 00 00 00 08 00 00 00 00 |...%$..@........|
+ 000001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+ 000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+ 000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+ */
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
+ for (unsigned i = 0; i < mbr_cmp_size; i++) {
+ ut_assertf(rbuf[mbr_cmp_start + i] == mbr_parts_ref_p1[i],
+ "1P MBR+0x%04X: expected 0x%02X, actual: 0x%02X\n",
+ mbr_cmp_start + i, mbr_parts_ref_p1[i], rbuf[mbr_cmp_start + i]);
+ }
+
+ /* Test two MBR partitions */
+ init_write_buffers(mbr_wbuf, sizeof(mbr_wbuf), ebr_wbuf, sizeof(ebr_wbuf), __LINE__);
+ ut_assertok(build_mbr_parts(mbr_parts_buf, sizeof(mbr_parts_buf), 2));
+ ut_assertok(run_commandf("write mmc 6:0 0x%lx 0 1", mbr_wa));
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
+ ut_assertok(memcmp(mbr_wbuf, rbuf, 512));
+ ut_assertok(run_commandf("write mmc 6:0 0x%lx 0x%lx 1", ebr_wa, ebr_blk));
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
+ ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
+ ut_assertok(console_record_reset_enable());
+ ut_assertf(0 == run_commandf(mbr_parts_buf), "Invalid partitions string: %s\n", mbr_parts_buf);
+ ut_assertok(run_commandf("mbr write mmc 6"));
+ ut_assert_nextline("MBR: write success!");
+ ut_assertok(run_commandf("mbr verify mmc 6"));
+ ut_assert_nextline("MBR: verify success!");
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
+ ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
+ ut_assertok(ut_check_console_end(uts));
+ /*
+ 000001b0 00 00 00 00 00 00 00 00 78 56 34 12 00 00 80 05 |........xV4.....|
+ 000001c0 05 01 0e 25 24 01 00 40 00 00 00 08 00 00 00 25 |...%$..@.......%|
+ 000001d0 25 01 0e 46 05 01 00 48 00 00 00 08 00 00 00 00 |%..F...H........|
+ 000001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+ 000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+ */
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
+ for (unsigned i = 0; i < mbr_cmp_size; i++) {
+ ut_assertf(rbuf[mbr_cmp_start + i] == mbr_parts_ref_p2[i],
+ "2P MBR+0x%04X: expected 0x%02X, actual: 0x%02X\n",
+ mbr_cmp_start + i, mbr_parts_ref_p2[i], rbuf[mbr_cmp_start + i]);
+ }
+
+ /* Test three MBR partitions */
+ init_write_buffers(mbr_wbuf, sizeof(mbr_wbuf), ebr_wbuf, sizeof(ebr_wbuf), __LINE__);
+ ut_assertok(build_mbr_parts(mbr_parts_buf, sizeof(mbr_parts_buf), 3));
+ ut_assertok(run_commandf("write mmc 6:0 0x%lx 0 1", mbr_wa));
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
+ ut_assertok(memcmp(mbr_wbuf, rbuf, 512));
+ ut_assertok(run_commandf("write mmc 6:0 0x%lx 0x%lx 1", ebr_wa, ebr_blk));
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
+ ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
+ ut_assertok(console_record_reset_enable());
+ ut_assertf(0 == run_commandf(mbr_parts_buf), "Invalid partitions string: %s\n", mbr_parts_buf);
+ ut_assertok(run_commandf("mbr write mmc 6"));
+ ut_assert_nextline("MBR: write success!");
+ ut_assertok(run_commandf("mbr verify mmc 6"));
+ ut_assert_nextline("MBR: verify success!");
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
+ ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
+ ut_assertok(ut_check_console_end(uts));
+ /*
+ 000001b0 00 00 00 00 00 00 00 00 78 56 34 12 00 00 80 05 |........xV4.....|
+ 000001c0 05 01 0e 25 24 01 00 40 00 00 00 08 00 00 00 25 |...%$..@.......%|
+ 000001d0 25 01 0e 46 05 01 00 48 00 00 00 08 00 00 00 46 |%..F...H.......F|
+ 000001e0 06 01 0e 66 25 01 00 50 00 00 00 08 00 00 00 00 |...f%..P........|
+ 000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+ */
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
+ for (unsigned i = 0; i < mbr_cmp_size; i++) {
+ ut_assertf(rbuf[mbr_cmp_start + i] == mbr_parts_ref_p3[i],
+ "3P MBR+0x%04X: expected 0x%02X, actual: 0x%02X\n",
+ mbr_cmp_start + i, mbr_parts_ref_p3[i], rbuf[mbr_cmp_start + i]);
+ }
+
+ /* Test four MBR partitions */
+ init_write_buffers(mbr_wbuf, sizeof(mbr_wbuf), ebr_wbuf, sizeof(ebr_wbuf), __LINE__);
+ ut_assertok(build_mbr_parts(mbr_parts_buf, sizeof(mbr_parts_buf), 4));
+ ut_assertok(run_commandf("write mmc 6:0 0x%lx 0 1", mbr_wa));
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
+ ut_assertok(memcmp(mbr_wbuf, rbuf, 512));
+ ut_assertok(run_commandf("write mmc 6:0 0x%lx 0x%lx 1", ebr_wa, ebr_blk));
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
+ ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
+ ut_assertok(console_record_reset_enable());
+ ut_assertf(0 == run_commandf(mbr_parts_buf), "Invalid partitions string: %s\n", mbr_parts_buf);
+ ut_assertok(run_commandf("mbr write mmc 6"));
+ ut_assert_nextline("MBR: write success!");
+ ut_assertok(run_commandf("mbr verify mmc 6"));
+ ut_assert_nextline("MBR: verify success!");
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
+ ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
+ ut_assertok(ut_check_console_end(uts));
+ /*
+ 000001b0 00 00 00 00 00 00 00 00 78 56 34 12 00 00 80 05 |........xV4.....|
+ 000001c0 05 01 0e 25 24 01 00 40 00 00 00 08 00 00 00 25 |...%$..@.......%|
+ 000001d0 25 01 0e 46 05 01 00 48 00 00 00 08 00 00 00 46 |%..F...H.......F|
+ 000001e0 06 01 0e 66 25 01 00 50 00 00 00 08 00 00 00 66 |...f%..P.......f|
+ 000001f0 26 01 0e 87 06 01 00 58 00 00 00 08 00 00 55 aa |&......X......U.|
+ */
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
+ for (unsigned i = 0; i < mbr_cmp_size; i++) {
+ ut_assertf(rbuf[mbr_cmp_start + i] == mbr_parts_ref_p4[i],
+ "4P MBR+0x%04X: expected 0x%02X, actual: 0x%02X\n",
+ mbr_cmp_start + i, mbr_parts_ref_p4[i], rbuf[mbr_cmp_start + i]);
+ }
+
+ /* Test five MBR partitions */
+ init_write_buffers(mbr_wbuf, sizeof(mbr_wbuf), ebr_wbuf, sizeof(ebr_wbuf), __LINE__);
+ ut_assertok(build_mbr_parts(mbr_parts_buf, sizeof(mbr_parts_buf), 5));
+ ut_assertok(run_commandf("write mmc 6:0 0x%lx 0 1", mbr_wa));
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
+ ut_assertok(memcmp(mbr_wbuf, rbuf, 512));
+ ut_assertok(run_commandf("write mmc 6:0 0x%lx 0x%lx 1", ebr_wa, ebr_blk));
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
+ ut_assertok(memcmp(ebr_wbuf, rbuf, 512));
+ ut_assertok(console_record_reset_enable());
+ ut_assertf(0 == run_commandf(mbr_parts_buf), "Invalid partitions string: %s\n", mbr_parts_buf);
+ ut_assertf(0 == run_commandf("mbr write mmc 6"), "Invalid partitions string: %s\n", mbr_parts_buf);
+ ut_assert_nextline("MBR: write success!");
+ ut_assertok(run_commandf("mbr verify mmc 6"));
+ ut_assert_nextline("MBR: verify success!");
+ ut_assertok(ut_check_console_end(uts));
+ /*
+ 000001b0 00 00 00 00 00 00 00 00 78 56 34 12 00 00 80 05 |........xV4.....|
+ 000001c0 05 01 0e 25 24 01 00 40 00 00 00 08 00 00 00 25 |...%$..@.......%|
+ 000001d0 25 01 0e 46 05 01 00 48 00 00 00 08 00 00 00 46 |%..F...H.......F|
+ 000001e0 06 01 0e 66 25 01 00 50 00 00 00 08 00 00 00 66 |...f%..P.......f|
+ 000001f0 26 01 05 a7 26 01 00 58 00 00 00 10 00 00 55 aa |&...&..X......U.|
+ */
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0 1", ra));
+ for (unsigned i = 0; i < mbr_cmp_size; i++) {
+ ut_assertf(rbuf[mbr_cmp_start + i] == mbr_parts_ref_p5[i],
+ "5P MBR+0x%04X: expected 0x%02X, actual: 0x%02X\n",
+ mbr_cmp_start + i, mbr_parts_ref_p5[i], rbuf[mbr_cmp_start + i]);
+ }
+ /*
+ 00b001b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 87 |................|
+ 00b001c0 07 01 0e a7 26 01 00 08 00 00 00 08 00 00 00 00 |....&...........|
+ 00b001d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+ 00b001e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
+ 00b001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.|
+ */
+ memset(rbuf, 0, sizeof(rbuf));
+ ut_assertok(run_commandf("read mmc 6:0 0x%lx 0x%lx 1", ra, ebr_blk));
+ for (unsigned i = 0; i < ebr_cmp_size; i++) {
+ ut_assertf(rbuf[ebr_cmp_start + i] == ebr_parts_ref_p5[i],
+ "5P EBR+0x%04X: expected 0x%02X, actual: 0x%02X\n",
+ ebr_cmp_start + i, ebr_parts_ref_p5[i], rbuf[ebr_cmp_start + i]);
+ }
+
+ return 0;
+}
+
+/* Declare mbr test */
+UNIT_TEST(mbr_test_run, UT_TESTF_CONSOLE_REC, mbr_test);
+
+int do_ut_mbr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct unit_test *tests = UNIT_TEST_SUITE_START(mbr_test);
+ const int n_ents = UNIT_TEST_SUITE_COUNT(mbr_test);
+
+ return cmd_ut_category("mbr", "mbr_test_", tests, n_ents, argc, argv);
+}
+
+static int dm_test_cmd_mbr(struct unit_test_state *uts)
+{
+ return mbr_test_run(uts);
+}
+
+DM_TEST(dm_test_cmd_mbr, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 0f56409e803..2d5b80f992e 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -87,6 +87,10 @@ static struct cmd_tbl cmd_ut_sub[] = {
#ifdef CONFIG_UT_LOG
U_BOOT_CMD_MKENT(log, CONFIG_SYS_MAXARGS, 1, do_ut_log, "", ""),
#endif
+#if defined(CONFIG_SANDBOX) && defined(CONFIG_CMD_MBR) && defined(CONFIG_CMD_MMC) \
+ && defined(CONFIG_MMC_SANDBOX) && defined(CONFIG_MMC_WRITE)
+ U_BOOT_CMD_MKENT(mbr, CONFIG_SYS_MAXARGS, 1, do_ut_mbr, "", ""),
+#endif
U_BOOT_CMD_MKENT(mem, CONFIG_SYS_MAXARGS, 1, do_ut_mem, "", ""),
#if defined(CONFIG_SANDBOX) && defined(CONFIG_CMD_SETEXPR)
U_BOOT_CMD_MKENT(setexpr, CONFIG_SYS_MAXARGS, 1, do_ut_setexpr, "",
@@ -99,6 +103,10 @@ static struct cmd_tbl cmd_ut_sub[] = {
#if CONFIG_IS_ENABLED(UT_UNICODE) && !defined(API_BUILD)
U_BOOT_CMD_MKENT(unicode, CONFIG_SYS_MAXARGS, 1, do_ut_unicode, "", ""),
#endif
+#ifdef CONFIG_MEASURED_BOOT
+ U_BOOT_CMD_MKENT(measurement, CONFIG_SYS_MAXARGS, 1, do_ut_measurement,
+ "", ""),
+#endif
#ifdef CONFIG_SANDBOX
U_BOOT_CMD_MKENT(compression, CONFIG_SYS_MAXARGS, 1, do_ut_compression,
"", ""),
@@ -166,8 +174,7 @@ static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
return CMD_RET_USAGE;
}
-#ifdef CONFIG_SYS_LONGHELP
-static char ut_help_text[] =
+U_BOOT_LONGHELP(ut,
"[-r] [-f] [<suite>] - run unit tests\n"
" -r<runs> Number of times to run each test\n"
" -f Force 'manual' tests to run as well\n"
@@ -237,8 +244,7 @@ static char ut_help_text[] =
!defined(CONFIG_SPL_BUILD) && !defined(API_BUILD)
"\nunicode - Unicode functions"
#endif
- ;
-#endif /* CONFIG_SYS_LONGHELP */
+ );
U_BOOT_CMD(
ut, CONFIG_SYS_MAXARGS, 1, do_ut,
diff --git a/test/common/cread.c b/test/common/cread.c
index 2fdd29a265f..4edc7739604 100644
--- a/test/common/cread.c
+++ b/test/common/cread.c
@@ -43,6 +43,12 @@ static int cli_ch_test(struct unit_test_state *uts)
ut_asserteq('a', cli_ch_process(cch, 'a'));
ut_asserteq(0, cli_ch_process(cch, 0));
+ /* unexpected 'Esc' */
+ ut_asserteq('a', cli_ch_process(cch, 'a'));
+ ut_asserteq(0, cli_ch_process(cch, '\e'));
+ ut_asserteq('b', cli_ch_process(cch, 'b'));
+ ut_asserteq(0, cli_ch_process(cch, 0));
+
return 0;
}
COMMON_TEST(cli_ch_test, 0);
@@ -80,6 +86,12 @@ static int cread_test(struct unit_test_state *uts)
ut_asserteq(7, cli_readline_into_buffer("-> ", buf, 1));
ut_asserteq_str("abc\e[Xx", buf);
+ /* unexpected 'Esc' */
+ *buf = '\0';
+ ut_asserteq(7, console_in_puts("abc\eXx\n"));
+ ut_asserteq(5, cli_readline_into_buffer("-> ", buf, 1));
+ ut_asserteq_str("abcXx", buf);
+
/* check timeout, should be between 1000 and 1050ms */
start = get_timer(0);
*buf = '\0';
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 7ed00733c1a..a3ce7b3889f 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -73,6 +73,7 @@ obj-$(CONFIG_CMD_MUX) += mux-cmd.o
obj-$(CONFIG_MULTIPLEXER) += mux-emul.o
obj-$(CONFIG_MUX_MMIO) += mux-mmio.o
obj-y += fdtdec.o
+obj-$(CONFIG_MTD_RAW_NAND) += nand.o
obj-$(CONFIG_UT_DM) += nop.o
obj-y += ofnode.o
obj-y += ofread.o
@@ -100,6 +101,7 @@ obj-$(CONFIG_REMOTEPROC) += remoteproc.o
obj-$(CONFIG_DM_RESET) += reset.o
obj-$(CONFIG_SYSRESET) += sysreset.o
obj-$(CONFIG_DM_REGULATOR) += regulator.o
+obj-$(CONFIG_CMD_RKMTD) += rkmtd.o
obj-$(CONFIG_DM_RNG) += rng.o
obj-$(CONFIG_DM_RTC) += rtc.o
obj-$(CONFIG_SCMI_FIRMWARE) += scmi.o
@@ -115,6 +117,7 @@ obj-$(CONFIG_DM_SPI) += spi.o
obj-$(CONFIG_SPMI) += spmi.o
obj-y += syscon.o
obj-$(CONFIG_RESET_SYSCON) += syscon-reset.o
+obj-$(CONFIG_SM) += sm.o
obj-$(CONFIG_SYSINFO) += sysinfo.o
obj-$(CONFIG_SYSINFO_GPIO) += sysinfo-gpio.o
obj-$(CONFIG_UT_DM) += tag.o
diff --git a/test/dm/blk.c b/test/dm/blk.c
index 446c4423e6f..799f1e4dc75 100644
--- a/test/dm/blk.c
+++ b/test/dm/blk.c
@@ -4,6 +4,7 @@
*/
#include <common.h>
+#include <blk.h>
#include <dm.h>
#include <part.h>
#include <sandbox_host.h>
@@ -22,8 +23,8 @@ static int dm_test_blk_base(struct unit_test_state *uts)
struct udevice *blk0, *blk1, *dev0, *dev1, *dev, *chk0, *chk1;
/* Create two, one the parent of the other */
- ut_assertok(host_create_device("test0", false, &dev0));
- ut_assertok(host_create_device("test1", false, &dev1));
+ ut_assertok(host_create_device("test0", false, DEFAULT_BLKSZ, &dev0));
+ ut_assertok(host_create_device("test1", false, DEFAULT_BLKSZ, &dev1));
/* Check we can find them */
ut_assertok(blk_get_device(UCLASS_HOST, 0, &blk0));
@@ -99,7 +100,7 @@ static int dm_test_blk_find(struct unit_test_state *uts)
{
struct udevice *blk, *chk, *dev;
- ut_assertok(host_create_device("test0", false, &dev));
+ ut_assertok(host_create_device("test0", false, DEFAULT_BLKSZ, &dev));
ut_assertok(blk_find_device(UCLASS_HOST, 0, &chk));
ut_assertok(device_find_first_child_by_uclass(dev, UCLASS_BLK, &blk));
diff --git a/test/dm/eth.c b/test/dm/eth.c
index d05d2a9abe1..bb3dcc6b954 100644
--- a/test/dm/eth.c
+++ b/test/dm/eth.c
@@ -263,12 +263,16 @@ static int dm_test_eth_act(struct unit_test_state *uts)
/* Prepare the test scenario */
for (i = 0; i < DM_TEST_ETH_NUM; i++) {
+ char *addr;
+
ut_assertok(uclass_find_device_by_name(UCLASS_ETH,
ethname[i], &dev[i]));
ut_assertok(device_remove(dev[i], DM_REMOVE_NORMAL));
/* Invalidate MAC address */
- strncpy(ethaddr[i], env_get(addrname[i]), 17);
+ addr = env_get(addrname[i]);
+ ut_assertnonnull(addr);
+ strncpy(ethaddr[i], addr, 17);
/* Must disable access protection for ethaddr before clearing */
env_set(".flags", addrname[i]);
env_set(addrname[i], NULL);
@@ -312,12 +316,16 @@ static int dm_test_ethaddr(struct unit_test_state *uts)
for (i = 0; i < ARRAY_SIZE(addr); i++) {
char addrname[10];
+ char *env_addr;
if (i)
snprintf(addrname, sizeof(addrname), "eth%daddr", i + 1);
else
strcpy(addrname, "ethaddr");
- ut_asserteq_str(addr[i], env_get(addrname));
+
+ env_addr = env_get(addrname);
+ ut_assertnonnull(env_addr);
+ ut_asserteq_str(addr[i], env_addr);
}
return 0;
diff --git a/test/dm/host.c b/test/dm/host.c
index 85f21f9839e..ca05a36b313 100644
--- a/test/dm/host.c
+++ b/test/dm/host.c
@@ -31,7 +31,7 @@ static int dm_test_host(struct unit_test_state *uts)
ut_asserteq(-ENODEV, uclass_first_device_err(UCLASS_PARTITION, &part));
mem_start = ut_check_delta(0);
- ut_assertok(host_create_device(label, true, &dev));
+ ut_assertok(host_create_device(label, true, DEFAULT_BLKSZ, &dev));
/* Check that the plat data has been allocated */
plat = dev_get_plat(dev);
@@ -83,7 +83,7 @@ static int dm_test_host_dup(struct unit_test_state *uts)
char fname[256];
ut_asserteq(0, uclass_id_count(UCLASS_HOST));
- ut_assertok(host_create_device(label, true, &dev));
+ ut_assertok(host_create_device(label, true, DEFAULT_BLKSZ, &dev));
/* Attach a file created in test_ut_dm_init */
ut_assertok(os_persistent_file(fname, sizeof(fname), "2MB.ext2.img"));
@@ -93,7 +93,7 @@ static int dm_test_host_dup(struct unit_test_state *uts)
ut_asserteq(1, uclass_id_count(UCLASS_HOST));
/* Create another device with the same label (should remove old one) */
- ut_assertok(host_create_device(label, true, &dev));
+ ut_assertok(host_create_device(label, true, DEFAULT_BLKSZ, &dev));
/* Attach a different file created in test_ut_dm_init */
ut_assertok(os_persistent_file(fname, sizeof(fname), "1MB.fat32.img"));
@@ -120,7 +120,7 @@ static int dm_test_cmd_host(struct unit_test_state *uts)
/* first check 'host info' with binding */
ut_assertok(run_command("host info", 0));
- ut_assert_nextline("dev blocks label path");
+ ut_assert_nextline("dev blocks blksz label path");
ut_assert_console_end();
ut_assertok(os_persistent_file(fname, sizeof(fname), "2MB.ext2.img"));
@@ -133,8 +133,8 @@ static int dm_test_cmd_host(struct unit_test_state *uts)
ut_asserteq(true, desc->removable);
ut_assertok(run_command("host info", 0));
- ut_assert_nextline("dev blocks label path");
- ut_assert_nextlinen(" 0 4096 test2");
+ ut_assert_nextline("dev blocks blksz label path");
+ ut_assert_nextlinen(" 0 4096 512 test2");
ut_assert_console_end();
ut_assertok(os_persistent_file(fname, sizeof(fname), "1MB.fat32.img"));
@@ -147,9 +147,9 @@ static int dm_test_cmd_host(struct unit_test_state *uts)
ut_asserteq(false, desc->removable);
ut_assertok(run_command("host info", 0));
- ut_assert_nextline("dev blocks label path");
- ut_assert_nextlinen(" 0 4096 test2");
- ut_assert_nextlinen(" 1 2048 fat");
+ ut_assert_nextline("dev blocks blksz label path");
+ ut_assert_nextlinen(" 0 4096 512 test2");
+ ut_assert_nextlinen(" 1 2048 512 fat");
ut_assert_console_end();
ut_asserteq(1, run_command("host info test", 0));
@@ -157,8 +157,8 @@ static int dm_test_cmd_host(struct unit_test_state *uts)
ut_assert_console_end();
ut_assertok(run_command("host info fat", 0));
- ut_assert_nextline("dev blocks label path");
- ut_assert_nextlinen(" 1 2048 fat");
+ ut_assert_nextline("dev blocks blksz label path");
+ ut_assert_nextlinen(" 1 2048 512 fat");
ut_assert_console_end();
/* check 'host dev' */
@@ -194,8 +194,8 @@ static int dm_test_cmd_host(struct unit_test_state *uts)
ut_assert_console_end();
ut_assertok(run_command("host info", 0));
- ut_assert_nextline("dev blocks label path");
- ut_assert_nextlinen(" 1 2048 fat");
+ ut_assert_nextline("dev blocks blksz label path");
+ ut_assert_nextlinen(" 1 2048 512 fat");
ut_assert_console_end();
return 0;
diff --git a/test/dm/mux-emul.c b/test/dm/mux-emul.c
index 58233edc9b2..c6aeeb7e1f1 100644
--- a/test/dm/mux-emul.c
+++ b/test/dm/mux-emul.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com/
* Pratyush Yadav <p.yadav@ti.com>
*/
#include <common.h>
diff --git a/test/dm/mux-mmio.c b/test/dm/mux-mmio.c
index fd353d8b155..27c881dabde 100644
--- a/test/dm/mux-mmio.c
+++ b/test/dm/mux-mmio.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2017-2018 Texas Instruments Incorporated - https://www.ti.com/
* Jean-Jacques Hiblot <jjhiblot@ti.com>
*/
diff --git a/test/dm/nand.c b/test/dm/nand.c
new file mode 100644
index 00000000000..0b992fdce1c
--- /dev/null
+++ b/test/dm/nand.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <nand.h>
+#include <part.h>
+#include <rand.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/rawnand.h>
+
+static int dm_test_nand(struct unit_test_state *uts, int dev, bool end)
+{
+ nand_erase_options_t opts = { };
+ struct mtd_info *mtd;
+ size_t length;
+ loff_t size;
+ char *buf;
+ int *gold;
+ u8 oob[NAND_MAX_OOBSIZE];
+ int i;
+ loff_t off = 0;
+ mtd_oob_ops_t ops = { };
+
+ /* Seed RNG for bit errors */
+ srand((off >> 32) ^ off ^ ~dev);
+
+ mtd = get_nand_dev_by_index(dev);
+ ut_assertnonnull(mtd);
+ size = mtd->erasesize * 4;
+ length = size;
+
+ buf = malloc(size);
+ ut_assertnonnull(buf);
+ gold = malloc(size);
+ ut_assertnonnull(gold);
+
+ /* Mark a block as bad */
+ ut_assertok(mtd_block_markbad(mtd, off + mtd->erasesize));
+
+ /* Erase some stuff */
+ if (end)
+ off = mtd->size - size - mtd->erasesize;
+ opts.offset = off;
+ opts.length = size;
+ opts.spread = 1;
+ opts.lim = U32_MAX;
+ ut_assertok(nand_erase_opts(mtd, &opts));
+
+ /* Make sure everything is erased */
+ memset(gold, 0xff, size);
+ ut_assertok(nand_read_skip_bad(mtd, off, &length, NULL, U64_MAX, buf));
+ ut_asserteq(size, length);
+ ut_asserteq_mem(gold, buf, size);
+
+ /* ...but our bad block marker is still there */
+ ops.oobbuf = oob;
+ ops.ooblen = mtd->oobsize;
+ ut_assertok(mtd_read_oob(mtd, mtd->erasesize, &ops));
+ ut_asserteq(0, oob[mtd_to_nand(mtd)->badblockpos]);
+
+ /* Generate some data and write it */
+ for (i = 0; i < size / sizeof(int); i++)
+ gold[i] = rand();
+ ut_assertok(nand_write_skip_bad(mtd, off, &length, NULL, U64_MAX,
+ (void *)gold, 0));
+ ut_asserteq(size, length);
+
+ /* Verify */
+ ut_assertok(nand_read_skip_bad(mtd, off, &length, NULL, U64_MAX, buf));
+ ut_asserteq(size, length);
+ ut_asserteq_mem(gold, buf, size);
+
+ /* Erase some blocks */
+ memset(((char *)gold) + mtd->erasesize, 0xff, mtd->erasesize * 2);
+ opts.offset = off + mtd->erasesize;
+ opts.length = mtd->erasesize * 2;
+ ut_assertok(nand_erase_opts(mtd, &opts));
+
+ /* Verify */
+ ut_assertok(nand_read_skip_bad(mtd, off, &length, NULL, U64_MAX, buf));
+ ut_asserteq(size, length);
+ ut_asserteq_mem(gold, buf, size);
+
+ return 0;
+}
+
+#define DM_NAND_TEST(dev) \
+static int dm_test_nand##dev##_start(struct unit_test_state *uts) \
+{ \
+ return dm_test_nand(uts, dev, false); \
+} \
+DM_TEST(dm_test_nand##dev##_start, UT_TESTF_SCAN_FDT); \
+static int dm_test_nand##dev##_end(struct unit_test_state *uts) \
+{ \
+ return dm_test_nand(uts, dev, true); \
+} \
+DM_TEST(dm_test_nand##dev##_end, UT_TESTF_SCAN_FDT)
+
+DM_NAND_TEST(0);
+DM_NAND_TEST(1);
diff --git a/test/dm/nop.c b/test/dm/nop.c
index 75b9e7b6cc0..f7d9a0f3df3 100644
--- a/test/dm/nop.c
+++ b/test/dm/nop.c
@@ -2,7 +2,7 @@
/*
* Test for the NOP uclass
*
- * (C) Copyright 2019 - Texas Instruments Incorporated - http://www.ti.com/
+ * (C) Copyright 2019 - Texas Instruments Incorporated - https://www.ti.com/
* Jean-Jacques Hiblot <jjhiblot@ti.com>
*/
diff --git a/test/dm/ofnode.c b/test/dm/ofnode.c
index d71faac0ee4..a5bc43aea4e 100644
--- a/test/dm/ofnode.c
+++ b/test/dm/ofnode.c
@@ -17,6 +17,7 @@
*/
#include <common.h>
+#include <abuf.h>
#include <dm.h>
#include <log.h>
#include <of_live.h>
@@ -26,6 +27,7 @@
#include <dm/root.h>
#include <dm/test.h>
#include <dm/uclass-internal.h>
+#include <linux/sizes.h>
#include <test/test.h>
#include <test/ut.h>
@@ -91,6 +93,7 @@ void free_oftree(oftree tree)
free(tree.np);
}
+/* test ofnode_device_is_compatible() */
static int dm_test_ofnode_compatible(struct unit_test_state *uts)
{
ofnode root_node = ofnode_path("/");
@@ -114,7 +117,7 @@ static int dm_test_ofnode_compatible_ot(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_ofnode_compatible_ot, UT_TESTF_OTHER_FDT);
+DM_TEST(dm_test_ofnode_compatible_ot, UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT);
static int dm_test_ofnode_get_by_phandle(struct unit_test_state *uts)
{
@@ -134,6 +137,7 @@ static int dm_test_ofnode_get_by_phandle(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_get_by_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+/* test oftree_get_by_phandle() with a the 'other' oftree */
static int dm_test_ofnode_get_by_phandle_ot(struct unit_test_state *uts)
{
oftree otree = get_other_oftree(uts);
@@ -146,7 +150,8 @@ static int dm_test_ofnode_get_by_phandle_ot(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_ofnode_get_by_phandle_ot, UT_TESTF_OTHER_FDT);
+DM_TEST(dm_test_ofnode_get_by_phandle_ot,
+ UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT);
static int check_prop_values(struct unit_test_state *uts, ofnode start,
const char *propname, const char *propval,
@@ -187,6 +192,7 @@ static int dm_test_ofnode_by_prop_value(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_by_prop_value, UT_TESTF_SCAN_FDT);
+/* test ofnode_by_prop_value() with a the 'other' oftree */
static int dm_test_ofnode_by_prop_value_ot(struct unit_test_state *uts)
{
oftree otree = get_other_oftree(uts);
@@ -196,8 +202,10 @@ static int dm_test_ofnode_by_prop_value_ot(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_ofnode_by_prop_value_ot, UT_TESTF_OTHER_FDT);
+DM_TEST(dm_test_ofnode_by_prop_value_ot,
+ UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT);
+/* test ofnode_read_fmap_entry() */
static int dm_test_ofnode_fmap(struct unit_test_state *uts)
{
struct fmap_entry entry;
@@ -213,12 +221,16 @@ static int dm_test_ofnode_fmap(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_fmap, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+/* test ofnode_read_prop() */
static int dm_test_ofnode_read(struct unit_test_state *uts)
{
const u32 *val;
ofnode node;
int size;
+ node = oftree_path(oftree_default(), "/");
+ ut_assert(ofnode_valid(node));
+
node = ofnode_path("/a-test");
ut_assert(ofnode_valid(node));
@@ -237,8 +249,9 @@ static int dm_test_ofnode_read(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_ofnode_read, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+DM_TEST(dm_test_ofnode_read, UT_TESTF_SCAN_FDT);
+/* test ofnode_read_prop() with the 'other' tree */
static int dm_test_ofnode_read_ot(struct unit_test_state *uts)
{
oftree otree = get_other_oftree(uts);
@@ -246,6 +259,9 @@ static int dm_test_ofnode_read_ot(struct unit_test_state *uts)
ofnode node;
int size;
+ node = oftree_path(otree, "/");
+ ut_assert(ofnode_valid(node));
+
node = oftree_path(otree, "/node/subnode");
ut_assert(ofnode_valid(node));
@@ -256,8 +272,9 @@ static int dm_test_ofnode_read_ot(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_ofnode_read_ot, UT_TESTF_OTHER_FDT);
+DM_TEST(dm_test_ofnode_read_ot, UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT);
+/* test ofnode_count_/parse_phandle_with_args() */
static int dm_test_ofnode_phandle(struct unit_test_state *uts)
{
struct ofnode_phandle_args args;
@@ -333,6 +350,7 @@ static int dm_test_ofnode_phandle(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_phandle, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+/* test ofnode_count_/parse_phandle_with_args() with 'other' tree */
static int dm_test_ofnode_phandle_ot(struct unit_test_state *uts)
{
oftree otree = get_other_oftree(uts);
@@ -361,6 +379,7 @@ static int dm_test_ofnode_phandle_ot(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_phandle_ot, UT_TESTF_OTHER_FDT);
+/* test ofnode_read_chosen_string/node/prop() */
static int dm_test_ofnode_read_chosen(struct unit_test_state *uts)
{
const char *str;
@@ -390,6 +409,7 @@ static int dm_test_ofnode_read_chosen(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_read_chosen, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+/* test ofnode_get_aliases_node/prop() */
static int dm_test_ofnode_read_aliases(struct unit_test_state *uts)
{
const void *val;
@@ -433,6 +453,7 @@ static int dm_test_ofnode_get_child_count(struct unit_test_state *uts)
DM_TEST(dm_test_ofnode_get_child_count,
UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+/* test ofnode_get_child_count() with 'other' tree */
static int dm_test_ofnode_get_child_count_ot(struct unit_test_state *uts)
{
oftree otree = get_other_oftree(uts);
@@ -452,7 +473,8 @@ static int dm_test_ofnode_get_child_count_ot(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_ofnode_get_child_count_ot, UT_TESTF_OTHER_FDT);
+DM_TEST(dm_test_ofnode_get_child_count_ot,
+ UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT);
static int dm_test_ofnode_is_enabled(struct unit_test_state *uts)
{
@@ -466,6 +488,7 @@ static int dm_test_ofnode_is_enabled(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_is_enabled, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+/* test ofnode_is_enabled() with 'other' tree */
static int dm_test_ofnode_is_enabled_ot(struct unit_test_state *uts)
{
oftree otree = get_other_oftree(uts);
@@ -479,6 +502,7 @@ static int dm_test_ofnode_is_enabled_ot(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_is_enabled_ot, UT_TESTF_OTHER_FDT);
+/* test ofnode_get_addr/size() */
static int dm_test_ofnode_get_reg(struct unit_test_state *uts)
{
ofnode node;
@@ -515,6 +539,7 @@ static int dm_test_ofnode_get_reg(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_get_reg, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+/* test ofnode_get_addr() with 'other' tree */
static int dm_test_ofnode_get_reg_ot(struct unit_test_state *uts)
{
oftree otree = get_other_oftree(uts);
@@ -526,7 +551,7 @@ static int dm_test_ofnode_get_reg_ot(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_ofnode_get_reg_ot, UT_TESTF_OTHER_FDT);
+DM_TEST(dm_test_ofnode_get_reg_ot, UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT);
static int dm_test_ofnode_get_path(struct unit_test_state *uts)
{
@@ -549,6 +574,7 @@ static int dm_test_ofnode_get_path(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_get_path, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+/* test ofnode_get_path() with 'other' tree */
static int dm_test_ofnode_get_path_ot(struct unit_test_state *uts)
{
oftree otree = get_other_oftree(uts);
@@ -566,8 +592,9 @@ static int dm_test_ofnode_get_path_ot(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_ofnode_get_path_ot, UT_TESTF_OTHER_FDT);
+DM_TEST(dm_test_ofnode_get_path_ot, UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT);
+/* test ofnode_conf_read_bool/int/str() */
static int dm_test_ofnode_conf(struct unit_test_state *uts)
{
ut_assert(!ofnode_conf_read_bool("missing"));
@@ -581,7 +608,7 @@ static int dm_test_ofnode_conf(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_ofnode_conf, 0);
+DM_TEST(dm_test_ofnode_conf, UT_TESTF_SCAN_FDT);
static int dm_test_ofnode_options(struct unit_test_state *uts)
{
@@ -620,6 +647,7 @@ static int dm_test_ofnode_for_each_compatible_node(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_for_each_compatible_node, UT_TESTF_SCAN_FDT);
+/* test dm_test_ofnode_string_count/index/list() */
static int dm_test_ofnode_string(struct unit_test_state *uts)
{
const char **val;
@@ -665,8 +693,9 @@ static int dm_test_ofnode_string(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_ofnode_string, 0);
+DM_TEST(dm_test_ofnode_string, UT_TESTF_SCAN_FDT);
+/* test error returns from ofnode_read_string_count/index/list() */
static int dm_test_ofnode_string_err(struct unit_test_state *uts)
{
const char **val;
@@ -716,7 +745,7 @@ static int dm_test_ofnode_string_err(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_string_err, UT_TESTF_LIVE_TREE);
-static int dm_test_ofnode_get_phy(struct unit_test_state *uts)
+static int dm_test_ofnode_read_phy_mode(struct unit_test_state *uts)
{
ofnode eth_node, phy_node;
phy_interface_t mode;
@@ -736,7 +765,7 @@ static int dm_test_ofnode_get_phy(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_ofnode_get_phy, 0);
+DM_TEST(dm_test_ofnode_read_phy_mode, UT_TESTF_SCAN_FDT);
/**
* make_ofnode_fdt() - Create an FDT for testing with ofnode
@@ -770,11 +799,11 @@ static int make_ofnode_fdt(struct unit_test_state *uts, void *fdt, int size,
return 0;
}
-static int dm_test_ofnode_root(struct unit_test_state *uts)
+/* Check that aliases work on the control FDT */
+static int dm_test_ofnode_aliases(struct unit_test_state *uts)
{
ofnode node;
- /* Check that aliases work on the control FDT */
node = ofnode_get_aliases_node("ethernet3");
ut_assert(ofnode_valid(node));
ut_asserteq_str("sbe5", ofnode_get_name(node));
@@ -783,8 +812,15 @@ static int dm_test_ofnode_root(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_ofnode_root, UT_TESTF_SCAN_FDT);
+DM_TEST(dm_test_ofnode_aliases, UT_TESTF_SCAN_FDT);
+/**
+ * dm_test_ofnode_root_mult() - Check aliaes on control and 'other' tree
+ *
+ * Check that aliases work only with the control FDT, not with 'other' tree.
+ * This is not actually the desired behaviour. If aliases are implemented for
+ * any tree, then this test should be changed.
+ */
static int dm_test_ofnode_root_mult(struct unit_test_state *uts)
{
char fdt[256];
@@ -817,6 +853,7 @@ static int dm_test_ofnode_root_mult(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_root_mult, UT_TESTF_SCAN_FDT);
+/* test ofnode_set_enabled(), ofnode_write_prop() on a livetree */
static int dm_test_ofnode_livetree_writing(struct unit_test_state *uts)
{
struct udevice *dev;
@@ -906,6 +943,7 @@ static int dm_test_ofnode_write_copy(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_write_copy, UT_TESTF_SCAN_FDT);
+/* test writing a property to the 'other' tree */
static int dm_test_ofnode_write_copy_ot(struct unit_test_state *uts)
{
oftree otree = get_other_oftree(uts);
@@ -920,8 +958,9 @@ static int dm_test_ofnode_write_copy_ot(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_ofnode_write_copy_ot, UT_TESTF_OTHER_FDT);
+DM_TEST(dm_test_ofnode_write_copy_ot, UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT);
+/* test ofnode_read_u32_index/default() */
static int dm_test_ofnode_u32(struct unit_test_state *uts)
{
ofnode node;
@@ -949,6 +988,7 @@ static int dm_test_ofnode_u32(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_u32, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+/* test ofnode_read_u32_array() */
static int dm_test_ofnode_u32_array(struct unit_test_state *uts)
{
ofnode node;
@@ -975,6 +1015,7 @@ static int dm_test_ofnode_u32_array(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_u32_array, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+/* test ofnode_read_u64() and ofnode_write_u64() */
static int dm_test_ofnode_u64(struct unit_test_state *uts)
{
ofnode node;
@@ -984,6 +1025,10 @@ static int dm_test_ofnode_u64(struct unit_test_state *uts)
ut_assert(ofnode_valid(node));
ut_assertok(ofnode_read_u64(node, "int64-value", &val));
ut_asserteq_64(0x1111222233334444, val);
+ ut_assertok(ofnode_write_u64(node, "new-int64-value", 0x9876543210));
+ ut_assertok(ofnode_read_u64(node, "new-int64-value", &val));
+ ut_asserteq_64(0x9876543210, val);
+
ut_asserteq(-EINVAL, ofnode_read_u64(node, "missing", &val));
ut_assertok(ofnode_read_u64_index(node, "int64-array", 0, &val));
@@ -994,6 +1039,12 @@ static int dm_test_ofnode_u64(struct unit_test_state *uts)
ofnode_read_u64_index(node, "int64-array", 2, &val));
ut_asserteq(-EINVAL, ofnode_read_u64_index(node, "missing", 0, &val));
+ ut_assertok(ofnode_write_u64(node, "int64-array", 0x9876543210));
+ ut_assertok(ofnode_read_u64_index(node, "int64-array", 0, &val));
+ ut_asserteq_64(0x9876543210, val);
+ ut_asserteq(-EOVERFLOW,
+ ofnode_read_u64_index(node, "int64-array", 1, &val));
+
return 0;
}
DM_TEST(dm_test_ofnode_u64, UT_TESTF_SCAN_FDT);
@@ -1107,6 +1158,7 @@ static int dm_test_ofnode_by_compatible(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_by_compatible, UT_TESTF_SCAN_FDT);
+/* check ofnode_by_compatible() on the 'other' tree */
static int dm_test_ofnode_by_compatible_ot(struct unit_test_state *uts)
{
const char *compat = "sandbox-other2";
@@ -1122,7 +1174,7 @@ static int dm_test_ofnode_by_compatible_ot(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_ofnode_by_compatible_ot, UT_TESTF_OTHER_FDT);
+DM_TEST(dm_test_ofnode_by_compatible_ot, UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT);
static int dm_test_ofnode_find_subnode(struct unit_test_state *uts)
{
@@ -1141,6 +1193,7 @@ static int dm_test_ofnode_find_subnode(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_find_subnode, UT_TESTF_SCAN_FDT);
+/* test ofnode_find_subnode() on the 'other' tree */
static int dm_test_ofnode_find_subnode_ot(struct unit_test_state *uts)
{
oftree otree = get_other_oftree(uts);
@@ -1209,12 +1262,11 @@ static int dm_test_ofnode_too_many(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_too_many, UT_TESTF_SCAN_FDT);
-static int check_copy_props(struct unit_test_state *uts, ofnode src,
- ofnode dst)
+static int check_copy_props(struct unit_test_state *uts, ofnode dst, ofnode src)
{
u32 reg[2], val;
- ut_assertok(ofnode_copy_props(src, dst));
+ ut_assertok(ofnode_copy_props(dst, src));
ut_assertok(ofnode_read_u32(dst, "ping-expect", &val));
ut_asserteq(3, val);
@@ -1246,7 +1298,7 @@ static int dm_test_ofnode_copy_props(struct unit_test_state *uts)
src = ofnode_path("/b-test");
dst = ofnode_path("/some-bus");
- ut_assertok(check_copy_props(uts, src, dst));
+ ut_assertok(check_copy_props(uts, dst, src));
/* check a property that is in the destination already */
ut_asserteq_str("mux0", ofnode_read_string(dst, "mux-control-names"));
@@ -1255,6 +1307,7 @@ static int dm_test_ofnode_copy_props(struct unit_test_state *uts)
}
DM_TEST(dm_test_ofnode_copy_props, UT_TESTF_SCAN_FDT);
+/* test ofnode_copy_props() with the 'other' tree */
static int dm_test_ofnode_copy_props_ot(struct unit_test_state *uts)
{
ofnode src, dst;
@@ -1262,7 +1315,7 @@ static int dm_test_ofnode_copy_props_ot(struct unit_test_state *uts)
src = ofnode_path("/b-test");
dst = oftree_path(otree, "/node/subnode2");
- ut_assertok(check_copy_props(uts, src, dst));
+ ut_assertok(check_copy_props(uts, dst, src));
return 0;
}
@@ -1292,7 +1345,7 @@ static int dm_test_livetree_align(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_livetree_align, UT_TESTF_LIVE_TREE);
+DM_TEST(dm_test_livetree_align, UT_TESTF_SCAN_FDT | UT_TESTF_LIVE_TREE);
/* check that it is possible to load an arbitrary livetree */
static int dm_test_livetree_ensure(struct unit_test_state *uts)
@@ -1311,4 +1364,161 @@ static int dm_test_livetree_ensure(struct unit_test_state *uts)
return 0;
}
-DM_TEST(dm_test_livetree_ensure, 0);
+DM_TEST(dm_test_livetree_ensure, UT_TESTF_SCAN_FDT);
+
+static int dm_test_oftree_new(struct unit_test_state *uts)
+{
+ ofnode node, subnode, check;
+ oftree tree;
+
+ ut_assertok(oftree_new(&tree));
+ node = oftree_root(tree);
+ ut_assert(ofnode_valid(node));
+ ut_assertok(ofnode_add_subnode(node, "edmund", &subnode));
+ check = ofnode_find_subnode(node, "edmund");
+ ut_asserteq(check.of_offset, subnode.of_offset);
+
+ return 0;
+}
+DM_TEST(dm_test_oftree_new, UT_TESTF_SCAN_FDT);
+
+static int check_copy_node(struct unit_test_state *uts, ofnode dst, ofnode src,
+ ofnode *nodep)
+{
+ u32 reg[2], val;
+ ofnode node;
+
+ ut_assertok(ofnode_copy_node(dst, "copy-test", src, &node));
+
+ ut_assertok(ofnode_read_u32(node, "ping-expect", &val));
+ ut_asserteq(3, val);
+
+ ut_asserteq_str("denx,u-boot-fdt-test",
+ ofnode_read_string(node, "compatible"));
+
+ /* check that a property with the same name is overwritten */
+ ut_assertok(ofnode_read_u32_array(node, "reg", reg, ARRAY_SIZE(reg)));
+ ut_asserteq(3, reg[0]);
+ ut_asserteq(1, reg[1]);
+
+ /* reset the compatible so the live tree does not change */
+ ut_assertok(ofnode_write_string(node, "compatible", "nothing"));
+ *nodep = node;
+
+ return 0;
+}
+
+static int dm_test_ofnode_copy_node(struct unit_test_state *uts)
+{
+ ofnode src, dst, node, try;
+
+ /*
+ * These nodes are chosen so that the src node is before the destination
+ * node in the tree. This doesn't matter with livetree, but with
+ * flattree any attempt to insert a property earlier in the tree will
+ * mess up the offsets after it.
+ */
+ src = ofnode_path("/b-test");
+ dst = ofnode_path("/some-bus");
+
+ ut_assertok(check_copy_node(uts, dst, src, &node));
+
+ /* check trying to copy over an existing node */
+ ut_asserteq(-EEXIST, ofnode_copy_node(dst, "copy-test", src, &try));
+ ut_asserteq(try.of_offset, node.of_offset);
+
+ return 0;
+}
+DM_TEST(dm_test_ofnode_copy_node, UT_TESTF_SCAN_FDT);
+
+/* test ofnode_copy_node() with the 'other' tree */
+static int dm_test_ofnode_copy_node_ot(struct unit_test_state *uts)
+{
+ oftree otree = get_other_oftree(uts);
+ ofnode src, dst, node;
+
+ src = ofnode_path("/b-test");
+ dst = oftree_path(otree, "/node/subnode2");
+ ut_assertok(check_copy_node(uts, dst, src, &node));
+
+ return 0;
+}
+DM_TEST(dm_test_ofnode_copy_node_ot, UT_TESTF_SCAN_FDT | UT_TESTF_OTHER_FDT);
+
+static int dm_test_ofnode_delete(struct unit_test_state *uts)
+{
+ ofnode node;
+
+ /*
+ * At present the livetree is not restored after changes made in tests.
+ * See test_pre_run() for how this is done with the other FDT and
+ * dm_test_pre_run() where it sets up the root-tree pointer. So use
+ * nodes which don't matter to other tests.
+ *
+ * We could fix this by detecting livetree changes and regenerating it
+ * before the next test if needed.
+ */
+ node = ofnode_path("/leds/iracibble");
+ ut_assert(ofnode_valid(node));
+ ut_assertok(ofnode_delete(&node));
+ ut_assert(!ofnode_valid(node));
+ ut_assert(!ofnode_valid(ofnode_path("/leds/iracibble")));
+
+ node = ofnode_path("/leds/default_on");
+ ut_assert(ofnode_valid(node));
+ ut_assertok(ofnode_delete(&node));
+ ut_assert(!ofnode_valid(node));
+ ut_assert(!ofnode_valid(ofnode_path("/leds/default_on")));
+
+ ut_asserteq(2, ofnode_get_child_count(ofnode_path("/leds")));
+
+ return 0;
+}
+DM_TEST(dm_test_ofnode_delete, UT_TESTF_SCAN_FDT);
+
+static int dm_test_oftree_to_fdt(struct unit_test_state *uts)
+{
+ oftree tree, check;
+ struct abuf buf, buf2;
+
+ tree = oftree_default();
+ ut_assertok(oftree_to_fdt(tree, &buf));
+ ut_assert(abuf_size(&buf) > SZ_16K);
+
+ /* convert it back to a tree and see if it looks OK */
+ check = oftree_from_fdt(abuf_data(&buf));
+ ut_assert(oftree_valid(check));
+
+ ut_assertok(oftree_to_fdt(check, &buf2));
+ ut_assert(abuf_size(&buf2) > SZ_16K);
+ ut_asserteq(abuf_size(&buf), abuf_size(&buf2));
+ ut_asserteq_mem(abuf_data(&buf), abuf_data(&buf2), abuf_size(&buf));
+
+ return 0;
+}
+DM_TEST(dm_test_oftree_to_fdt, UT_TESTF_SCAN_FDT);
+
+/* test ofnode_read_bool() and ofnode_write_bool() */
+static int dm_test_bool(struct unit_test_state *uts)
+{
+ const char *propname = "missing-bool-value";
+ ofnode node;
+
+ node = ofnode_path("/a-test");
+ ut_assert(ofnode_read_bool(node, "bool-value"));
+ ut_assert(!ofnode_read_bool(node, propname));
+ ut_assert(!ofnode_has_property(node, propname));
+
+ ut_assertok(ofnode_write_bool(node, propname, true));
+ ut_assert(ofnode_read_bool(node, propname));
+ ut_assert(ofnode_has_property(node, propname));
+ ut_assert(ofnode_read_bool(node, "bool-value"));
+
+ ut_assertok(ofnode_write_bool(node, propname, false));
+ ut_assert(!ofnode_read_bool(node, propname));
+ ut_assert(!ofnode_has_property(node, propname));
+ ut_assert(ofnode_read_bool(node, "bool-value"));
+
+ return 0;
+}
+DM_TEST(dm_test_bool, UT_TESTF_SCAN_FDT);
diff --git a/test/dm/pci.c b/test/dm/pci.c
index 70a736cfdb8..8c5e7da9e62 100644
--- a/test/dm/pci.c
+++ b/test/dm/pci.c
@@ -301,10 +301,12 @@ static int dm_test_pci_addr_flat(struct unit_test_state *uts)
{
struct udevice *swap1f, *swap1;
ulong io_addr, mem_addr;
+ fdt_addr_t size;
ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap1f));
io_addr = dm_pci_read_bar32(swap1f, 0);
- ut_asserteq(io_addr, dev_read_addr_pci(swap1f));
+ ut_asserteq(io_addr, dev_read_addr_pci(swap1f, &size));
+ ut_asserteq(0, size);
/*
* This device has both I/O and MEM spaces but the MEM space appears
@@ -312,7 +314,8 @@ static int dm_test_pci_addr_flat(struct unit_test_state *uts)
*/
ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1, 0), &swap1));
mem_addr = dm_pci_read_bar32(swap1, 1);
- ut_asserteq(mem_addr, dev_read_addr_pci(swap1));
+ ut_asserteq(mem_addr, dev_read_addr_pci(swap1, &size));
+ ut_asserteq(0, size);
return 0;
}
@@ -329,12 +332,15 @@ DM_TEST(dm_test_pci_addr_flat, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT |
static int dm_test_pci_addr_live(struct unit_test_state *uts)
{
struct udevice *swap1f, *swap1;
+ fdt_size_t size;
ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1f, 0), &swap1f));
- ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1f));
+ ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1f, &size));
+ ut_asserteq(0, size);
ut_assertok(dm_pci_bus_find_bdf(PCI_BDF(0, 0x1, 0), &swap1));
- ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1));
+ ut_asserteq_64(FDT_ADDR_T_NONE, dev_read_addr_pci(swap1, &size));
+ ut_asserteq(0, size);
return 0;
}
diff --git a/test/dm/phy.c b/test/dm/phy.c
index 4f91abca3a0..0cf3689fdec 100644
--- a/test/dm/phy.c
+++ b/test/dm/phy.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2017 Texas Instruments Incorporated - https://www.ti.com/
* Written by Jean-Jacques Hiblot <jjhiblot@ti.com>
*/
diff --git a/test/dm/remoteproc.c b/test/dm/remoteproc.c
index 7a8ff47fa14..f6f9e509e27 100644
--- a/test/dm/remoteproc.c
+++ b/test/dm/remoteproc.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2015
- * Texas Instruments Incorporated - http://www.ti.com/
+ * Texas Instruments Incorporated - https://www.ti.com/
*/
#include <common.h>
#include <dm.h>
diff --git a/test/dm/rkmtd.c b/test/dm/rkmtd.c
new file mode 100644
index 00000000000..3c3e8efa92f
--- /dev/null
+++ b/test/dm/rkmtd.c
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
+/*
+ * Test derived from:
+ * /test/dm/host.c
+ * Copyright 2022 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * Copyright (C) 2023 Johan Jonker <jbx6244@gmail.com>
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <dm.h>
+#include <fs.h>
+#include <rkmtd.h>
+#include <asm/test.h>
+#include <dm/device-internal.h>
+#include <dm/test.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define RW_BUF_SIZE 12 * 512
+
+/* Basic test of the RKMTD interface */
+static int dm_test_rkmtd(struct unit_test_state *uts)
+{
+ struct udevice *dev, *part, *chk, *blk;
+ char write[RW_BUF_SIZE], read[RW_BUF_SIZE];
+ static const char label[] = "test";
+ struct rkmtd_dev *plat;
+ struct blk_desc *desc;
+ struct sector0 *sec0;
+ int i;
+
+ ut_asserteq(-ENODEV, uclass_first_device_err(UCLASS_RKMTD, &dev));
+ ut_asserteq(-ENODEV, uclass_first_device_err(UCLASS_PARTITION, &part));
+
+ ut_assertok(rkmtd_create_device(label, &dev));
+
+ /* Check that the plat data has been allocated */
+ plat = dev_get_plat(dev);
+ ut_asserteq_str("test", plat->label);
+ ut_assert(label != plat->label);
+
+ /* Attach RKMTD driver */
+ ut_assertok(rkmtd_attach(dev));
+ ut_assertok(uclass_first_device_err(UCLASS_RKMTD, &chk));
+ ut_asserteq_ptr(chk, dev);
+
+ /* Get RKMTD block device */
+ ut_assertok(blk_get_from_parent(dev, &blk));
+ ut_assertok(device_probe(blk));
+
+ /* There should be a GPT partition table in this device */
+ ut_asserteq(0, uclass_first_device_err(UCLASS_PARTITION, &part));
+
+ /* Write a boot block and verify that we get the same data back */
+ desc = dev_get_uclass_plat(blk);
+ ut_asserteq(true, desc->removable);
+ ut_asserteq(LBA, desc->lba);
+
+ memset(write, '\0', BLK_SIZE);
+
+ for (i = BLK_SIZE; i < sizeof(write); i++)
+ write[i] = i;
+
+ sec0 = (struct sector0 *)write;
+ sec0->magic = 0x0FF0AA55;
+ sec0->rc4_flag = 0;
+ sec0->boot_code1_offset = 4;
+ sec0->boot_code2_offset = 4;
+ sec0->flash_data_size = 4;
+ sec0->flash_boot_size = 8;
+
+ rkmtd_rc4(write, 512);
+ ut_asserteq(RK_TAG, sec0->magic);
+
+ ut_asserteq(12, blk_dwrite(desc, 64, 12, write));
+ ut_asserteq(12, blk_dread(desc, 64, 12, read));
+ ut_asserteq_mem(write, read, RW_BUF_SIZE);
+
+ ut_assertok(rkmtd_detach(dev));
+
+ ut_asserteq(-ENODEV, blk_get_from_parent(dev, &blk));
+ ut_assertok(device_unbind(dev));
+
+ return 0;
+}
+DM_TEST(dm_test_rkmtd, UT_TESTF_SCAN_FDT);
+
+/* Reusing the same label should work */
+static int dm_test_rkmtd_dup(struct unit_test_state *uts)
+{
+ static const char label[] = "test";
+ struct udevice *dev, *chk;
+
+ /* Create a RKMTD device with label "test" */
+ ut_asserteq(0, uclass_id_count(UCLASS_RKMTD));
+ ut_assertok(rkmtd_create_device(label, &dev));
+ ut_assertok(rkmtd_attach(dev));
+ ut_assertok(uclass_first_device_err(UCLASS_RKMTD, &chk));
+ ut_asserteq_ptr(chk, dev);
+ ut_asserteq(1, uclass_id_count(UCLASS_RKMTD));
+
+ /* Create another device with the same label (should remove old one) */
+ ut_assertok(rkmtd_create_device(label, &dev));
+ ut_assertok(rkmtd_attach(dev));
+ ut_assertok(uclass_first_device_err(UCLASS_RKMTD, &chk));
+ ut_asserteq_ptr(chk, dev);
+
+ /* Make sure there is still only one device */
+ ut_asserteq(1, uclass_id_count(UCLASS_RKMTD));
+
+ return 0;
+}
+DM_TEST(dm_test_rkmtd_dup, UT_TESTF_SCAN_FDT);
+
+/* Basic test of the 'rkmtd' command */
+static int dm_test_rkmtd_cmd(struct unit_test_state *uts)
+{
+ struct udevice *dev, *blk;
+ struct blk_desc *desc;
+
+ /* First check 'rkmtd info' with binding */
+ ut_assertok(run_command("rkmtd info", 0));
+ ut_assert_nextline("dev blocks label ");
+ ut_assert_console_end();
+
+ /* Bind device 1 */
+ ut_assertok(run_commandf("rkmtd bind test1"));
+ ut_assertok(uclass_first_device_err(UCLASS_RKMTD, &dev));
+ ut_assertok(blk_get_from_parent(dev, &blk));
+ desc = dev_get_uclass_plat(blk);
+
+ ut_assertok(run_command("rkmtd info", 0));
+ ut_assert_nextline("dev blocks label ");
+ ut_assert_nextline(" 0 609 test1 ");
+ ut_assert_console_end();
+
+ /* Bind device 2 */
+ ut_assertok(run_commandf("rkmtd bind test2"));
+ ut_assertok(uclass_next_device_err(&dev));
+ ut_assertok(blk_get_from_parent(dev, &blk));
+ desc = dev_get_uclass_plat(blk);
+
+ ut_assertok(run_command("rkmtd info", 0));
+ ut_assert_nextline("dev blocks label ");
+ ut_assert_nextline(" 0 609 test1 ");
+ ut_assert_nextline(" 1 609 test2 ");
+ ut_assert_console_end();
+
+ ut_asserteq(1, run_command("rkmtd info test", 0));
+ ut_assert_nextline("No such device 'test'");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("rkmtd info test2", 0));
+ ut_assert_nextline("dev blocks label ");
+ ut_assert_nextline(" 1 609 test2 ");
+ ut_assert_console_end();
+
+ /* Check 'rkmtd dev' */
+ ut_asserteq(1, run_command("rkmtd dev", 0));
+ ut_assert_nextline("No current rkmtd device");
+ ut_assert_console_end();
+
+ ut_asserteq(1, run_command("rkmtd dev missing", 0));
+ ut_assert_nextline("No such device 'missing'");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("rkmtd dev test2", 0));
+ ut_assert_console_end();
+
+ ut_assertok(run_command("rkmtd dev", 0));
+ ut_assert_nextline("Current rkmtd device: 1: test2");
+ ut_assert_console_end();
+
+ /* Try a numerical label */
+ ut_assertok(run_command("rkmtd dev 0", 0));
+ ut_assert_console_end();
+
+ ut_assertok(run_command("rkmtd dev", 0));
+ ut_assert_nextline("Current rkmtd device: 0: test1");
+ ut_assert_console_end();
+
+ /* Remove one of the bindings */
+ ut_assertok(run_commandf("rkmtd unbind test1"));
+
+ /* There should now be no current device */
+ ut_asserteq(1, run_command("rkmtd dev", 0));
+ ut_assert_nextline("No current rkmtd device");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("rkmtd info", 0));
+ ut_assert_nextline("dev blocks label ");
+ ut_assert_nextline(" 1 609 test2 ");
+ ut_assert_console_end();
+
+ return 0;
+}
+DM_TEST(dm_test_rkmtd_cmd, UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
diff --git a/test/dm/scmi.c b/test/dm/scmi.c
index d87e2731ce4..e80667ef72a 100644
--- a/test/dm/scmi.c
+++ b/test/dm/scmi.c
@@ -16,6 +16,10 @@
#include <clk.h>
#include <dm.h>
#include <reset.h>
+#include <scmi_agent.h>
+#include <scmi_agent-uclass.h>
+#include <scmi_protocols.h>
+#include <vsprintf.h>
#include <asm/scmi_test.h>
#include <dm/device-internal.h>
#include <dm/test.h>
@@ -23,22 +27,11 @@
#include <power/regulator.h>
#include <test/ut.h>
-static int ut_assert_scmi_state_preprobe(struct unit_test_state *uts)
-{
- struct sandbox_scmi_service *scmi_ctx = sandbox_scmi_service_ctx();
-
- ut_assertnonnull(scmi_ctx);
- ut_assertnull(scmi_ctx->agent);
-
- return 0;
-}
-
static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts,
+ struct sandbox_scmi_agent *agent,
struct udevice *dev)
{
struct sandbox_scmi_devices *scmi_devices;
- struct sandbox_scmi_service *scmi_ctx;
- struct sandbox_scmi_agent *agent;
/* Device references to check context against test sequence */
scmi_devices = sandbox_scmi_devices_ctx(dev);
@@ -48,10 +41,6 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts,
ut_asserteq(2, scmi_devices->regul_count);
/* State of the simulated SCMI server exposed */
- scmi_ctx = sandbox_scmi_service_ctx();
- ut_assertnonnull(scmi_ctx);
- agent = scmi_ctx->agent;
- ut_assertnonnull(agent);
ut_asserteq(3, agent->clk_count);
ut_assertnonnull(agent->clk);
ut_asserteq(1, agent->reset_count);
@@ -63,27 +52,32 @@ static int ut_assert_scmi_state_postprobe(struct unit_test_state *uts,
}
static int load_sandbox_scmi_test_devices(struct unit_test_state *uts,
+ struct sandbox_scmi_agent **ctx,
struct udevice **dev)
{
- int ret;
+ struct udevice *agent_dev;
- ret = ut_assert_scmi_state_preprobe(uts);
- if (ret)
- return ret;
+ ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
+ &agent_dev));
+ ut_assertnonnull(agent_dev);
+ *ctx = sandbox_scmi_agent_ctx(agent_dev);
+ ut_assertnonnull(*ctx);
+
+ /* probe */
ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "sandbox_scmi",
dev));
ut_assertnonnull(*dev);
- return ut_assert_scmi_state_postprobe(uts, *dev);
+ return ut_assert_scmi_state_postprobe(uts, *ctx, *dev);
}
static int release_sandbox_scmi_test_devices(struct unit_test_state *uts,
struct udevice *dev)
{
+ /* un-probe */
ut_assertok(device_remove(dev, DM_REMOVE_NORMAL));
- /* Not sure test devices are fully removed, agent may not be visible */
return 0;
}
@@ -93,10 +87,11 @@ static int release_sandbox_scmi_test_devices(struct unit_test_state *uts,
*/
static int dm_test_scmi_sandbox_agent(struct unit_test_state *uts)
{
+ struct sandbox_scmi_agent *ctx;
struct udevice *dev = NULL;
int ret;
- ret = load_sandbox_scmi_test_devices(uts, &dev);
+ ret = load_sandbox_scmi_test_devices(uts, &ctx, &dev);
if (!ret)
ret = release_sandbox_scmi_test_devices(uts, dev);
@@ -104,25 +99,325 @@ static int dm_test_scmi_sandbox_agent(struct unit_test_state *uts)
}
DM_TEST(dm_test_scmi_sandbox_agent, UT_TESTF_SCAN_FDT);
-static int dm_test_scmi_clocks(struct unit_test_state *uts)
+static int dm_test_scmi_base(struct unit_test_state *uts)
+{
+ struct udevice *agent_dev, *base;
+ struct scmi_agent_priv *priv;
+ u32 version, num_agents, num_protocols, impl_version;
+ u32 attributes, agent_id;
+ u8 *vendor, *agent_name, *protocols;
+ int ret;
+
+ /* preparation */
+ ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
+ &agent_dev));
+ ut_assertnonnull(agent_dev);
+ ut_assertnonnull(priv = dev_get_uclass_plat(agent_dev));
+ ut_assertnonnull(base = scmi_get_protocol(agent_dev,
+ SCMI_PROTOCOL_ID_BASE));
+
+ /* version */
+ ret = scmi_base_protocol_version(base, &version);
+ ut_assertok(ret);
+ ut_asserteq(priv->version, version);
+
+ /* protocol attributes */
+ ret = scmi_base_protocol_attrs(base, &num_agents, &num_protocols);
+ ut_assertok(ret);
+ ut_asserteq(priv->num_agents, num_agents);
+ ut_asserteq(priv->num_protocols, num_protocols);
+
+ /* discover vendor */
+ ret = scmi_base_discover_vendor(base, &vendor);
+ ut_assertok(ret);
+ ut_asserteq_str(priv->vendor, vendor);
+ free(vendor);
+
+ /* message attributes */
+ ret = scmi_base_protocol_message_attrs(base,
+ SCMI_BASE_DISCOVER_SUB_VENDOR,
+ &attributes);
+ ut_assertok(ret);
+ ut_assertok(attributes);
+
+ /* discover sub vendor */
+ ret = scmi_base_discover_sub_vendor(base, &vendor);
+ ut_assertok(ret);
+ ut_asserteq_str(priv->sub_vendor, vendor);
+ free(vendor);
+
+ /* impl version */
+ ret = scmi_base_discover_impl_version(base, &impl_version);
+ ut_assertok(ret);
+ ut_asserteq(priv->impl_version, impl_version);
+
+ /* discover agent (my self) */
+ ret = scmi_base_discover_agent(base, 0xffffffff, &agent_id,
+ &agent_name);
+ ut_assertok(ret);
+ ut_asserteq(priv->agent_id, agent_id);
+ ut_asserteq_str(priv->agent_name, agent_name);
+ free(agent_name);
+
+ /* discover protocols */
+ ret = scmi_base_discover_list_protocols(base, &protocols);
+ ut_asserteq(num_protocols, ret);
+ ut_asserteq_mem(priv->protocols, protocols, sizeof(u8) * num_protocols);
+ free(protocols);
+
+ /*
+ * NOTE: Sandbox SCMI driver handles device-0 only. It supports setting
+ * access and protocol permissions, but doesn't allow unsetting them nor
+ * resetting the configurations.
+ */
+ /* set device permissions */
+ ret = scmi_base_set_device_permissions(base, agent_id, 0,
+ SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS);
+ ut_assertok(ret); /* SCMI_SUCCESS */
+ ret = scmi_base_set_device_permissions(base, agent_id, 1,
+ SCMI_BASE_SET_DEVICE_PERMISSIONS_ACCESS);
+ ut_asserteq(-ENOENT, ret); /* SCMI_NOT_FOUND */
+ ret = scmi_base_set_device_permissions(base, agent_id, 0, 0);
+ ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
+
+ /* set protocol permissions */
+ ret = scmi_base_set_protocol_permissions(base, agent_id, 0,
+ SCMI_PROTOCOL_ID_CLOCK,
+ SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS);
+ ut_assertok(ret); /* SCMI_SUCCESS */
+ ret = scmi_base_set_protocol_permissions(base, agent_id, 1,
+ SCMI_PROTOCOL_ID_CLOCK,
+ SCMI_BASE_SET_PROTOCOL_PERMISSIONS_ACCESS);
+ ut_asserteq(-ENOENT, ret); /* SCMI_NOT_FOUND */
+ ret = scmi_base_set_protocol_permissions(base, agent_id, 0,
+ SCMI_PROTOCOL_ID_CLOCK, 0);
+ ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
+
+ /* reset agent configuration */
+ ret = scmi_base_reset_agent_configuration(base, agent_id, 0);
+ ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
+ ret = scmi_base_reset_agent_configuration(base, agent_id,
+ SCMI_BASE_RESET_ALL_ACCESS_PERMISSIONS);
+ ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
+ ret = scmi_base_reset_agent_configuration(base, agent_id, 0);
+ ut_asserteq(-EACCES, ret); /* SCMI_DENIED */
+
+ return 0;
+}
+
+DM_TEST(dm_test_scmi_base, UT_TESTF_SCAN_FDT);
+
+static int dm_test_scmi_cmd(struct unit_test_state *uts)
{
+ struct udevice *agent_dev;
+ int num_proto = 0;
+ char cmd_out[30];
+
+ if (!CONFIG_IS_ENABLED(CMD_SCMI))
+ return -EAGAIN;
+
+ /* preparation */
+ ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
+ &agent_dev));
+ ut_assertnonnull(agent_dev);
+
+ /*
+ * Estimate the number of provided protocols.
+ * This estimation is correct as far as a corresponding
+ * protocol support is added to sandbox fake serer.
+ */
+ if (CONFIG_IS_ENABLED(POWER_DOMAIN))
+ num_proto++;
+ if (CONFIG_IS_ENABLED(CLK_SCMI))
+ num_proto++;
+ if (CONFIG_IS_ENABLED(RESET_SCMI))
+ num_proto++;
+ if (CONFIG_IS_ENABLED(DM_REGULATOR_SCMI))
+ num_proto++;
+
+ /* scmi info */
+ ut_assertok(run_command("scmi info", 0));
+
+ ut_assert_nextline("SCMI device: scmi");
+ snprintf(cmd_out, 30, " protocol version: 0x%x",
+ SCMI_BASE_PROTOCOL_VERSION);
+ ut_assert_nextline(cmd_out);
+ ut_assert_nextline(" # of agents: 2");
+ ut_assert_nextline(" 0: platform");
+ ut_assert_nextline(" > 1: OSPM");
+ snprintf(cmd_out, 30, " # of protocols: %d", num_proto);
+ ut_assert_nextline(cmd_out);
+ if (CONFIG_IS_ENABLED(SCMI_POWER_DOMAIN))
+ ut_assert_nextline(" Power domain management");
+ if (CONFIG_IS_ENABLED(CLK_SCMI))
+ ut_assert_nextline(" Clock management");
+ if (CONFIG_IS_ENABLED(RESET_SCMI))
+ ut_assert_nextline(" Reset domain management");
+ if (CONFIG_IS_ENABLED(DM_REGULATOR_SCMI))
+ ut_assert_nextline(" Voltage domain management");
+ ut_assert_nextline(" vendor: U-Boot");
+ ut_assert_nextline(" sub vendor: Sandbox");
+ ut_assert_nextline(" impl version: 0x1");
+
+ ut_assert_console_end();
+
+ /* scmi perm_dev */
+ ut_assertok(run_command("scmi perm_dev 1 0 1", 0));
+ ut_assert_console_end();
+
+ ut_assert(run_command("scmi perm_dev 1 0 0", 0));
+ ut_assert_nextline("Denying access to device:0 failed (-13)");
+ ut_assert_console_end();
+
+ /* scmi perm_proto */
+ ut_assertok(run_command("scmi perm_proto 1 0 14 1", 0));
+ ut_assert_console_end();
+
+ ut_assert(run_command("scmi perm_proto 1 0 14 0", 0));
+ ut_assert_nextline("Denying access to protocol:0x14 on device:0 failed (-13)");
+ ut_assert_console_end();
+
+ /* scmi reset */
+ ut_assert(run_command("scmi reset 1 1", 0));
+ ut_assert_nextline("Reset failed (-13)");
+ ut_assert_console_end();
+
+ return 0;
+}
+
+DM_TEST(dm_test_scmi_cmd, UT_TESTF_SCAN_FDT);
+
+static int dm_test_scmi_power_domains(struct unit_test_state *uts)
+{
+ struct sandbox_scmi_agent *agent;
struct sandbox_scmi_devices *scmi_devices;
- struct sandbox_scmi_service *scmi_ctx;
+ struct udevice *agent_dev, *pwd, *dev;
+ u32 version, count, attributes, pstate;
+ u64 stats_addr;
+ size_t stats_len;
+ u8 *name;
+ int ret;
+
+ if (!CONFIG_IS_ENABLED(SCMI_POWER_DOMAIN))
+ return -EAGAIN;
+
+ /* preparation */
+ ut_assertok(load_sandbox_scmi_test_devices(uts, &agent, &dev));
+ ut_assertnonnull(agent);
+ scmi_devices = sandbox_scmi_devices_ctx(dev);
+ ut_assertnonnull(scmi_devices);
+ ut_asserteq(2, scmi_devices->pwdom->id); /* in test.dts */
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
+ &agent_dev));
+ ut_assertnonnull(agent_dev);
+ pwd = scmi_get_protocol(agent_dev, SCMI_PROTOCOL_ID_POWER_DOMAIN);
+ ut_assertnonnull(pwd);
+
+ /*
+ * SCMI Power domain management protocol interfaces
+ */
+ /* version */
+ ret = scmi_generic_protocol_version(pwd, SCMI_PROTOCOL_ID_POWER_DOMAIN,
+ &version);
+ ut_assertok(ret);
+ ut_asserteq(agent->pwdom_version, version);
+
+ /* protocol attributes */
+ ret = scmi_pwd_protocol_attrs(pwd, &count, &stats_addr, &stats_len);
+ ut_assertok(ret);
+ ut_asserteq(agent->pwdom_count, count);
+ ut_asserteq(0, stats_len);
+
+ /* protocol message attributes */
+ ret = scmi_pwd_protocol_message_attrs(pwd, SCMI_PWD_STATE_SET,
+ &attributes);
+ ut_assertok(ret);
+ ret = scmi_pwd_protocol_message_attrs(pwd, SCMI_PWD_STATE_NOTIFY,
+ &attributes);
+ ut_asserteq(-ENOENT, ret); /* the protocol not supported */
+
+ /* power domain attributes */
+ ret = scmi_pwd_attrs(pwd, 0, &attributes, &name);
+ ut_assertok(ret);
+ ut_asserteq_str("power-domain--0", name);
+ free(name);
+
+ ret = scmi_pwd_attrs(pwd, 10, &attributes, &name);
+ ut_asserteq(-ENOENT, ret); /* domain-10 doesn't exist */
+
+ /* power domain state set/get */
+ ret = scmi_pwd_state_set(pwd, 0, 0, 0);
+ ut_assertok(ret);
+ ret = scmi_pwd_state_get(pwd, 0, &pstate);
+ ut_assertok(ret);
+ ut_asserteq(0, pstate); /* ON */
+
+ ret = scmi_pwd_state_set(pwd, 0, 0, SCMI_PWD_PSTATE_TYPE_LOST);
+ ut_assertok(ret);
+ ret = scmi_pwd_state_get(pwd, 0, &pstate);
+ ut_assertok(ret);
+ ut_asserteq(SCMI_PWD_PSTATE_TYPE_LOST, pstate); /* OFF */
+
+ ret = scmi_pwd_state_set(pwd, 0, 10, 0);
+ ut_asserteq(-ENOENT, ret);
+
+ /* power domain name get */
+ ret = scmi_pwd_name_get(pwd, 0, &name);
+ ut_assertok(ret);
+ ut_asserteq_str("power-domain--0-extended", name);
+ free(name);
+
+ ret = scmi_pwd_name_get(pwd, 10, &name);
+ ut_asserteq(-ENOENT, ret); /* domain-10 doesn't exist */
+
+ /*
+ * U-Boot driver model interfaces
+ */
+ /* power_domain_on */
+ ret = power_domain_on(scmi_devices->pwdom);
+ ut_assertok(ret);
+ ret = scmi_pwd_state_get(pwd, scmi_devices->pwdom->id, &pstate);
+ ut_assertok(ret);
+ ut_asserteq(0, pstate); /* ON */
+
+ /* power_domain_off */
+ ret = power_domain_off(scmi_devices->pwdom);
+ ut_assertok(ret);
+ ret = scmi_pwd_state_get(pwd, scmi_devices->pwdom->id, &pstate);
+ ut_assertok(ret);
+ ut_asserteq(SCMI_PWD_PSTATE_TYPE_LOST, pstate); /* OFF */
+
+ return release_sandbox_scmi_test_devices(uts, dev);
+}
+
+DM_TEST(dm_test_scmi_power_domains, UT_TESTF_SCAN_FDT);
+
+static int dm_test_scmi_clocks(struct unit_test_state *uts)
+{
struct sandbox_scmi_agent *agent;
- struct udevice *dev;
+ struct sandbox_scmi_devices *scmi_devices;
+ struct udevice *agent_dev, *clock_dev, *dev;
int ret_dev;
int ret;
- ret = load_sandbox_scmi_test_devices(uts, &dev);
+ if (!CONFIG_IS_ENABLED(CLK_SCMI))
+ return -EAGAIN;
+
+ ret = load_sandbox_scmi_test_devices(uts, &agent, &dev);
if (ret)
return ret;
scmi_devices = sandbox_scmi_devices_ctx(dev);
ut_assertnonnull(scmi_devices);
- scmi_ctx = sandbox_scmi_service_ctx();
- ut_assertnonnull(scmi_ctx);
- agent = scmi_ctx->agent;
- ut_assertnonnull(agent);
+
+ /* Sandbox SCMI clock protocol has its own channel */
+ ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
+ &agent_dev));
+ ut_assertnonnull(agent_dev);
+ clock_dev = scmi_get_protocol(agent_dev, SCMI_PROTOCOL_ID_CLOCK);
+ ut_assertnonnull(clock_dev);
+ ut_asserteq(0x14, sandbox_scmi_channel_id(clock_dev));
/* Test SCMI clocks rate manipulation */
ut_asserteq(333, agent->clk[0].rate);
@@ -169,22 +464,28 @@ DM_TEST(dm_test_scmi_clocks, UT_TESTF_SCAN_FDT);
static int dm_test_scmi_resets(struct unit_test_state *uts)
{
- struct sandbox_scmi_devices *scmi_devices;
- struct sandbox_scmi_service *scmi_ctx;
struct sandbox_scmi_agent *agent;
- struct udevice *dev = NULL;
+ struct sandbox_scmi_devices *scmi_devices;
+ struct udevice *agent_dev, *reset_dev, *dev = NULL;
int ret;
- ret = load_sandbox_scmi_test_devices(uts, &dev);
+ if (!CONFIG_IS_ENABLED(RESET_SCMI))
+ return -EAGAIN;
+
+ ret = load_sandbox_scmi_test_devices(uts, &agent, &dev);
if (ret)
return ret;
scmi_devices = sandbox_scmi_devices_ctx(dev);
ut_assertnonnull(scmi_devices);
- scmi_ctx = sandbox_scmi_service_ctx();
- ut_assertnonnull(scmi_ctx);
- agent = scmi_ctx->agent;
- ut_assertnonnull(agent);
+
+ /* Sandbox SCMI reset protocol doesn't have its own channel */
+ ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
+ &agent_dev));
+ ut_assertnonnull(agent_dev);
+ reset_dev = scmi_get_protocol(agent_dev, SCMI_PROTOCOL_ID_RESET_DOMAIN);
+ ut_assertnonnull(reset_dev);
+ ut_asserteq(0x0, sandbox_scmi_channel_id(reset_dev));
/* Test SCMI resect controller manipulation */
ut_assert(!agent->reset[0].asserted);
@@ -201,21 +502,19 @@ DM_TEST(dm_test_scmi_resets, UT_TESTF_SCAN_FDT);
static int dm_test_scmi_voltage_domains(struct unit_test_state *uts)
{
- struct sandbox_scmi_devices *scmi_devices;
- struct sandbox_scmi_service *scmi_ctx;
struct sandbox_scmi_agent *agent;
+ struct sandbox_scmi_devices *scmi_devices;
struct dm_regulator_uclass_plat *uc_pdata;
struct udevice *dev;
struct udevice *regul0_dev;
- ut_assertok(load_sandbox_scmi_test_devices(uts, &dev));
+ if (!CONFIG_IS_ENABLED(DM_REGULATOR_SCMI))
+ return -EAGAIN;
+
+ ut_assertok(load_sandbox_scmi_test_devices(uts, &agent, &dev));
scmi_devices = sandbox_scmi_devices_ctx(dev);
ut_assertnonnull(scmi_devices);
- scmi_ctx = sandbox_scmi_service_ctx();
- ut_assertnonnull(scmi_ctx);
- agent = scmi_ctx->agent;
- ut_assertnonnull(agent);
/* Set/Get an SCMI voltage domain level */
regul0_dev = scmi_devices->regul[0];
diff --git a/test/dm/serial.c b/test/dm/serial.c
index 37d17a65f16..34b783e062e 100644
--- a/test/dm/serial.c
+++ b/test/dm/serial.c
@@ -29,6 +29,7 @@ static int dm_test_serial(struct unit_test_state *uts)
&dev_serial));
ut_assertok(serial_tstc());
+ ut_asserteq(115200, fetch_baud_from_dtb());
/*
* test with default config which is the only one supported by
* sandbox_serial driver
diff --git a/test/dm/sm.c b/test/dm/sm.c
new file mode 100644
index 00000000000..7ebb0c9c85e
--- /dev/null
+++ b/test/dm/sm.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 SberDevices, Inc.
+ *
+ * Author: Alexey Romanov <avromanov@salutedevices.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <sm.h>
+#include <sandbox-sm.h>
+#include <asm/ptrace.h>
+#include <dm/device-internal.h>
+#include <dm/test.h>
+#include <test/ut.h>
+#include <linux/sizes.h>
+
+static int dm_test_sm(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct pt_regs regs;
+ char buffer[128] = { 0 };
+ char test_string[] = "secure-monitor";
+ int ret, val;
+
+ ut_assertok(uclass_get_device_by_name(UCLASS_SM,
+ "secure-monitor", &dev));
+
+ ret = sm_call(dev, SANDBOX_SMC_CMD_COUNT, NULL, &regs);
+ ut_asserteq(ret, -EINVAL);
+
+ ret = sm_call(dev, SANDBOX_SMC_CMD_COMMON, &val, &regs);
+ ut_asserteq(ret, 0);
+ ut_asserteq(val, 0);
+
+ ret = sm_call_write(dev, buffer, sizeof(buffer),
+ SANDBOX_SMC_CMD_COUNT, &regs);
+ ut_asserteq(ret, -EINVAL);
+
+ ret = sm_call_write(dev, buffer, SZ_4K + 1,
+ SANDBOX_SMC_CMD_WRITE_MEM, &regs);
+ ut_asserteq(ret, -EINVAL);
+
+ ret = sm_call_write(dev, buffer, sizeof(buffer),
+ SANDBOX_SMC_CMD_COUNT, &regs);
+ ut_asserteq(ret, -EINVAL);
+
+ ret = sm_call_write(dev, buffer, SZ_4K + 1,
+ SANDBOX_SMC_CMD_READ_MEM, &regs);
+ ut_asserteq(ret, -EINVAL);
+
+ ret = sm_call_write(dev, test_string, sizeof(test_string),
+ SANDBOX_SMC_CMD_WRITE_MEM, &regs);
+ ut_asserteq(ret, sizeof(test_string));
+
+ ret = sm_call_read(dev, buffer, sizeof(buffer),
+ SANDBOX_SMC_CMD_READ_MEM, &regs);
+ ut_asserteq(ret, sizeof(buffer));
+
+ ut_asserteq_str(buffer, test_string);
+
+ return 0;
+}
+
+DM_TEST(dm_test_sm, UT_TESTF_SCAN_FDT);
diff --git a/test/dm/soc.c b/test/dm/soc.c
index 17e1b5ba012..8f6c97fa790 100644
--- a/test/dm/soc.c
+++ b/test/dm/soc.c
@@ -2,7 +2,7 @@
/*
* Test for the SOC uclass
*
- * (C) Copyright 2020 - Texas Instruments Incorporated - http://www.ti.com/
+ * (C) Copyright 2020 - Texas Instruments Incorporated - https://www.ti.com/
* Dave Gerlach <d-gerlach@ti.com>
*/
diff --git a/test/dm/sysreset.c b/test/dm/sysreset.c
index 691683c5674..5aa69e04618 100644
--- a/test/dm/sysreset.c
+++ b/test/dm/sysreset.c
@@ -27,8 +27,8 @@ static int dm_test_sysreset_base(struct unit_test_state *uts)
/* Device 1 is the warm sysreset device */
ut_assertok(uclass_get_device(UCLASS_SYSRESET, 1, &dev));
ut_asserteq(-EACCES, sysreset_request(dev, SYSRESET_WARM));
- ut_asserteq(-ENOSYS, sysreset_request(dev, SYSRESET_COLD));
- ut_asserteq(-ENOSYS, sysreset_request(dev, SYSRESET_POWER));
+ ut_asserteq(-EPROTONOSUPPORT, sysreset_request(dev, SYSRESET_COLD));
+ ut_asserteq(-EPROTONOSUPPORT, sysreset_request(dev, SYSRESET_POWER));
state->sysreset_allowed[SYSRESET_WARM] = true;
ut_asserteq(-EINPROGRESS, sysreset_request(dev, SYSRESET_WARM));
@@ -36,7 +36,7 @@ static int dm_test_sysreset_base(struct unit_test_state *uts)
/* Device 2 is the cold sysreset device */
ut_assertok(uclass_get_device(UCLASS_SYSRESET, 2, &dev));
- ut_asserteq(-ENOSYS, sysreset_request(dev, SYSRESET_WARM));
+ ut_asserteq(-EPROTONOSUPPORT, sysreset_request(dev, SYSRESET_WARM));
state->sysreset_allowed[SYSRESET_COLD] = false;
ut_asserteq(-EACCES, sysreset_request(dev, SYSRESET_COLD));
state->sysreset_allowed[SYSRESET_COLD] = true;
diff --git a/test/dm/wdt.c b/test/dm/wdt.c
index 653d7b1c8b3..2bbebcdbf28 100644
--- a/test/dm/wdt.c
+++ b/test/dm/wdt.c
@@ -54,7 +54,7 @@ static int dm_test_wdt_gpio_toggle(struct unit_test_state *uts)
*/
struct udevice *wdt, *gpio;
const u64 timeout = 42;
- const int offset = 7;
+ const int offset = 8;
int val;
ut_assertok(uclass_get_device_by_name(UCLASS_WDT,
@@ -115,7 +115,7 @@ static int dm_test_wdt_watchdog_reset(struct unit_test_state *uts)
struct udevice *gpio_wdt, *sandbox_wdt;
struct udevice *gpio;
const u64 timeout = 42;
- const int offset = 7;
+ const int offset = 8;
uint reset_count;
int val;
diff --git a/test/fuzz/cmd_fuzz.c b/test/fuzz/cmd_fuzz.c
index e2f44f3ecb6..d0bc7b8d7b7 100644
--- a/test/fuzz/cmd_fuzz.c
+++ b/test/fuzz/cmd_fuzz.c
@@ -70,11 +70,8 @@ static int do_fuzz(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]
return 1;
}
-#ifdef CONFIG_SYS_LONGHELP
-static char fuzz_help_text[] =
- "[fuzz-test-name] - execute the named fuzz test\n"
- ;
-#endif /* CONFIG_SYS_LONGHELP */
+U_BOOT_LONGHELP(fuzz,
+ "[fuzz-test-name] - execute the named fuzz test\n");
U_BOOT_CMD(
fuzz, CONFIG_SYS_MAXARGS, 1, do_fuzz,
diff --git a/test/image/Kconfig b/test/image/Kconfig
new file mode 100644
index 00000000000..45b6e8c52e6
--- /dev/null
+++ b/test/image/Kconfig
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
+
+config SPL_UT_LOAD
+ bool "Unit tests for SPL load methods"
+ depends on SPL_UNIT_TEST
+ default y if SANDBOX
+ help
+ Test various SPL load methods.
+
+if SPL_UT_LOAD
+
+config SPL_UT_LOAD_FS
+ bool "Unit tests for filesystems"
+ depends on SANDBOX && SPL_OF_REAL
+ depends on FS_LOADER
+ depends on SPL_BLK_FS
+ depends on SPL_FS_FAT
+ depends on SPL_FS_EXT4
+ depends on SPL_MMC_WRITE
+ depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
+ default y
+ help
+ Test filesystems and the various load methods which use them.
+
+config SPL_UT_LOAD_NAND
+ bool "Test loading from NAND flash"
+ depends on SANDBOX && SPL_OF_REAL
+ depends on SPL_NAND_SUPPORT
+ depends on SPL_MTD
+ default y
+ help
+ Test the NAND flash load method.
+
+config SPL_UT_LOAD_NET
+ bool "Test loading over TFTP"
+ depends on SANDBOX && SPL_OF_REAL
+ depends on SPL_ETH
+ depends on USE_BOOTFILE
+ default y
+ help
+ Test loading images over TFTP using the NET image load method.
+
+config SPL_UT_LOAD_SPI
+ bool "Test loading from SPI Flash"
+ depends on SANDBOX && SPL_OF_REAL
+ depends on SPL_SPI_LOAD
+ default y
+ help
+ Test the SPI flash image load metod.
+
+config SPL_UT_LOAD_OS
+ bool "Test loading from the host OS"
+ depends on SANDBOX && SPL_LOAD_FIT
+ select SPL_LOAD_BLOCK
+ default y
+ help
+ Smoke test to ensure that loading U-boot works in sandbox.
+
+endif
diff --git a/test/image/Makefile b/test/image/Makefile
index c4039df707f..11ed25734e8 100644
--- a/test/image/Makefile
+++ b/test/image/Makefile
@@ -2,4 +2,10 @@
#
# Copyright 2021 Google LLC
-obj-$(CONFIG_SPL_BUILD) += spl_load.o
+obj-y += spl_load.o
+obj-$(CONFIG_SPL_UT_LOAD_FS) += spl_load_fs.o
+obj-$(CONFIG_SPL_UT_LOAD_NAND) += spl_load_nand.o
+obj-$(CONFIG_SPL_UT_LOAD_NET) += spl_load_net.o
+obj-$(CONFIG_SPL_NOR_SUPPORT) += spl_load_nor.o
+obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o
+obj-$(CONFIG_SPL_UT_LOAD_SPI) += spl_load_spi.o
diff --git a/test/image/spl_load.c b/test/image/spl_load.c
index 4e27ff460ab..e1036eff28c 100644
--- a/test/image/spl_load.c
+++ b/test/image/spl_load.c
@@ -1,91 +1,662 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Copyright 2021 Google LLC
- * Written by Simon Glass <sjg@chromium.org>
+ * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
*/
#include <common.h>
#include <image.h>
+#include <imx_container.h>
#include <mapmem.h>
-#include <os.h>
+#include <memalign.h>
+#include <rand.h>
+#include <spi_flash.h>
#include <spl.h>
+#include <test/spl.h>
#include <test/ut.h>
+#include <u-boot/crc.h>
-/* Declare a new SPL test */
-#define SPL_TEST(_name, _flags) UNIT_TEST(_name, _flags, spl_test)
+int board_fit_config_name_match(const char *name)
+{
+ return 0;
+}
-/* Context used for this test */
-struct text_ctx {
- int fd;
-};
+struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size)
+{
+ return map_sysmem(0x100000, 0);
+}
+
+/* Try to reuse the load buffer to conserve memory */
+void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len)
+{
+ static void *buf;
+ static size_t size;
+
+ if (size < sectors * bl_len) {
+ free(buf);
+ size = sectors * bl_len;
+ buf = malloc_cache_aligned(size);
+ }
+ return buf;
+}
+
+/* Local flags for spl_image; start from the "top" to avoid conflicts */
+#define SPL_IMX_CONTAINER 0x80000000
+#define SPL_COMP_LZMA 0x40000000
+
+void generate_data(char *data, size_t size, const char *test_name)
+{
+ int i;
+ unsigned int seed = 1;
+
+ while (*test_name) {
+ seed += *test_name++;
+ rand_r(&seed);
+ }
+
+ for (i = 0; i < size; i++)
+ data[i] = (i & 0xf) << 4 | (rand_r(&seed) & 0xf);
+}
+
+static size_t create_legacy(void *dst, struct spl_image_info *spl_image,
+ size_t *data_offset)
+{
+ struct legacy_img_hdr *hdr = dst;
+ void *data = dst + sizeof(*hdr);
+
+ if (data_offset)
+ *data_offset = data - dst;
+
+ if (!dst)
+ goto out;
+
+ image_set_magic(hdr, IH_MAGIC);
+ image_set_time(hdr, 0);
+ image_set_size(hdr, spl_image->size);
+ image_set_load(hdr, spl_image->load_addr);
+ image_set_ep(hdr, spl_image->entry_point);
+ image_set_dcrc(hdr, crc32(0, data, spl_image->size));
+ image_set_os(hdr, spl_image->os);
+ image_set_arch(hdr, IH_ARCH_DEFAULT);
+ image_set_type(hdr, IH_TYPE_FIRMWARE);
+ image_set_comp(hdr, spl_image->flags & SPL_COMP_LZMA ? IH_COMP_LZMA :
+ IH_COMP_NONE);
+ image_set_name(hdr, spl_image->name);
+ image_set_hcrc(hdr, crc32(0, (void *)hdr, sizeof(*hdr)));
+
+out:
+ return sizeof(*hdr) + spl_image->size;
+}
+
+static size_t create_imx8(void *dst, struct spl_image_info *spl_image,
+ size_t *data_offset)
+{
+ struct container_hdr *hdr = dst;
+ struct boot_img_t *img = dst + sizeof(*hdr);
+ size_t length = sizeof(*hdr) + sizeof(*img);
+ /* Align to MMC block size for now */
+ void *data = dst + 512;
+
+ if (data_offset)
+ *data_offset = data - dst;
+
+ if (!dst)
+ goto out;
+
+ hdr->version = CONTAINER_HDR_VERSION;
+ hdr->length_lsb = length & 0xff;
+ hdr->length_msb = length >> 8;
+ hdr->tag = CONTAINER_HDR_TAG;
+ hdr->num_images = 1;
+
+ /* spl_load_imx_container doesn't handle endianness; whoops! */
+ img->offset = data - dst;
+ img->size = spl_image->size;
+ img->dst = spl_image->load_addr;
+ img->entry = spl_image->entry_point;
+
+out:
+ return data - dst + spl_image->size;
+}
+
+#define ADDRESS_CELLS (sizeof(uintptr_t) / sizeof(u32))
-static ulong read_fit_image(struct spl_load_info *load, ulong sector,
- ulong count, void *buf)
+static inline int fdt_property_addr(void *fdt, const char *name, uintptr_t val)
{
- struct text_ctx *text_ctx = load->priv;
- off_t offset, ret;
- ssize_t res;
+ if (sizeof(uintptr_t) == sizeof(u32))
+ return fdt_property_u32(fdt, name, val);
+ return fdt_property_u64(fdt, name, val);
+}
+
+static size_t start_fit(void *dst, size_t fit_size, size_t data_size,
+ bool external)
+{
+ void *data;
- offset = sector * load->bl_len;
- ret = os_lseek(text_ctx->fd, offset, OS_SEEK_SET);
- if (ret != offset) {
- printf("Failed to seek to %zx, got %zx (errno=%d)\n", offset,
- ret, errno);
+ if (fdt_create(dst, fit_size))
+ return 0;
+ if (fdt_finish_reservemap(dst))
+ return 0;
+ if (fdt_begin_node(dst, ""))
+ return 0;
+ if (fdt_property_u32(dst, FIT_TIMESTAMP_PROP, 0))
+ return 0;
+ if (fdt_property_u32(dst, "#address-cells", ADDRESS_CELLS))
return 0;
+ if (fdt_property_string(dst, FIT_DESC_PROP, ""))
+ return 0;
+
+ if (fdt_begin_node(dst, "images"))
+ return 0;
+ if (fdt_begin_node(dst, "u-boot"))
+ return 0;
+
+ if (external) {
+ if (fdt_property_u32(dst, FIT_DATA_OFFSET_PROP, 0))
+ return 0;
+ return fit_size;
}
- res = os_read(text_ctx->fd, buf, count * load->bl_len);
- if (res == -1) {
- printf("Failed to read %lx bytes, got %ld (errno=%d)\n",
- count * load->bl_len, res, errno);
+ if (fdt_property_placeholder(dst, FIT_DATA_PROP, data_size, &data))
return 0;
+ return data - dst;
+}
+
+static size_t create_fit(void *dst, struct spl_image_info *spl_image,
+ size_t *data_offset, bool external)
+{
+ size_t prop_size = 596, total_size = prop_size + spl_image->size;
+ size_t off, size;
+
+ if (external) {
+ size = prop_size;
+ off = size;
+ } else {
+ char tmp[256];
+
+ size = total_size;
+ off = start_fit(tmp, sizeof(tmp), 0, false);
+ if (!off)
+ return 0;
}
- return count;
+ if (data_offset)
+ *data_offset = off;
+
+ if (!dst)
+ goto out;
+
+ if (start_fit(dst, size, spl_image->size, external) != off)
+ return 0;
+
+ if (fdt_property_string(dst, FIT_DESC_PROP, spl_image->name))
+ return 0;
+ if (fdt_property_string(dst, FIT_TYPE_PROP, "firmware"))
+ return 0;
+ if (fdt_property_string(dst, FIT_COMP_PROP, "none"))
+ return 0;
+ if (fdt_property_u32(dst, FIT_DATA_SIZE_PROP, spl_image->size))
+ return 0;
+ if (fdt_property_string(dst, FIT_OS_PROP,
+ genimg_get_os_short_name(spl_image->os)))
+ return 0;
+ if (fdt_property_string(dst, FIT_ARCH_PROP,
+ genimg_get_arch_short_name(IH_ARCH_DEFAULT)))
+ return 0;
+ if (fdt_property_addr(dst, FIT_ENTRY_PROP, spl_image->entry_point))
+ return 0;
+ if (fdt_property_addr(dst, FIT_LOAD_PROP, spl_image->load_addr))
+ return 0;
+ if (fdt_end_node(dst)) /* u-boot */
+ return 0;
+ if (fdt_end_node(dst)) /* images */
+ return 0;
+
+ if (fdt_begin_node(dst, "configurations"))
+ return 0;
+ if (fdt_property_string(dst, FIT_DEFAULT_PROP, "config-1"))
+ return 0;
+ if (fdt_begin_node(dst, "config-1"))
+ return 0;
+ if (fdt_property_string(dst, FIT_DESC_PROP, spl_image->name))
+ return 0;
+ if (fdt_property_string(dst, FIT_FIRMWARE_PROP, "u-boot"))
+ return 0;
+ if (fdt_end_node(dst)) /* configurations */
+ return 0;
+ if (fdt_end_node(dst)) /* config-1 */
+ return 0;
+
+ if (fdt_end_node(dst)) /* root */
+ return 0;
+ if (fdt_finish(dst))
+ return 0;
+
+ if (external) {
+ if (fdt_totalsize(dst) > size)
+ return 0;
+ fdt_set_totalsize(dst, size);
+ }
+
+out:
+ return total_size;
}
-int board_fit_config_name_match(const char *name)
+size_t create_image(void *dst, enum spl_test_image type,
+ struct spl_image_info *info, size_t *data_offset)
{
+ bool external = false;
+
+ info->os = IH_OS_U_BOOT;
+ info->load_addr = CONFIG_TEXT_BASE;
+ info->entry_point = CONFIG_TEXT_BASE + 0x100;
+ info->flags = 0;
+
+ switch (type) {
+ case LEGACY_LZMA:
+ info->flags = SPL_COMP_LZMA;
+ case LEGACY:
+ return create_legacy(dst, info, data_offset);
+ case IMX8:
+ info->flags = SPL_IMX_CONTAINER;
+ return create_imx8(dst, info, data_offset);
+ case FIT_EXTERNAL:
+ /*
+ * spl_fit_append_fdt will clobber external images with U-Boot's
+ * FDT if the image doesn't have one. Just set the OS to
+ * something which doesn't take a devicetree.
+ */
+ if (!IS_ENABLED(CONFIG_LOAD_FIT_FULL))
+ info->os = IH_OS_TEE;
+ external = true;
+ case FIT_INTERNAL:
+ info->flags = SPL_FIT_FOUND;
+ return create_fit(dst, info, data_offset, external);
+ }
+
return 0;
}
-struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size)
+int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1,
+ struct spl_image_info *info2)
{
- return map_sysmem(0x100000, 0);
+ if (info2->name) {
+ if (info1->flags & SPL_FIT_FOUND)
+ ut_asserteq_str(genimg_get_os_name(info1->os),
+ info2->name);
+ else
+ ut_asserteq_str(info1->name, info2->name);
+ }
+
+ if (info1->flags & SPL_IMX_CONTAINER)
+ ut_asserteq(IH_OS_INVALID, info2->os);
+ else
+ ut_asserteq(info1->os, info2->os);
+
+ ut_asserteq(info1->entry_point, info2->entry_point);
+ if (info1->flags & (SPL_FIT_FOUND | SPL_IMX_CONTAINER) ||
+ info2->flags & SPL_COPY_PAYLOAD_ONLY) {
+ ut_asserteq(info1->load_addr, info2->load_addr);
+ if (info1->flags & SPL_IMX_CONTAINER)
+ ut_asserteq(0, info2->size);
+ else if (!(info1->flags & SPL_COMP_LZMA))
+ ut_asserteq(info1->size, info2->size);
+ } else {
+ ut_asserteq(info1->load_addr - sizeof(struct legacy_img_hdr),
+ info2->load_addr);
+ ut_asserteq(info1->size + sizeof(struct legacy_img_hdr),
+ info2->size);
+ }
+
+ return 0;
}
-static int spl_test_load(struct unit_test_state *uts)
+static ulong spl_test_read(struct spl_load_info *load, ulong sector,
+ ulong count, void *buf)
{
- struct spl_image_info image;
- struct legacy_img_hdr *header;
- struct text_ctx text_ctx;
- struct spl_load_info load;
- char fname[256];
- int ret;
- int fd;
-
- memset(&load, '\0', sizeof(load));
- load.bl_len = 512;
- load.read = read_fit_image;
-
- ret = sandbox_find_next_phase(fname, sizeof(fname), true);
- if (ret) {
- printf("(%s not found, error %d)\n", fname, ret);
- return ret;
+ memcpy(buf, load->priv + sector, count);
+ return count;
+}
+
+static int spl_test_image(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type)
+{
+ size_t img_size, img_data, data_size = SPL_TEST_DATA_SIZE;
+ struct spl_image_info info_write = {
+ .name = test_name,
+ .size = data_size,
+ }, info_read = { };
+ char *data;
+ void *img;
+
+ img_size = create_image(NULL, type, &info_write, &img_data);
+ ut_assert(img_size);
+ img = calloc(img_size, 1);
+ ut_assertnonnull(img);
+
+ data = img + img_data;
+ generate_data(data, data_size, test_name);
+ ut_asserteq(img_size, create_image(img, type, &info_write, NULL));
+
+ if (type == LEGACY) {
+ ut_assertok(spl_parse_image_header(&info_read, NULL, img));
+ if (check_image_info(uts, &info_write, &info_read))
+ return CMD_RET_FAILURE;
+ } else {
+ struct spl_load_info load;
+
+ spl_set_bl_len(&load, 1);
+ load.priv = img;
+ load.read = spl_test_read;
+ if (type == IMX8)
+ ut_assertok(spl_load_imx_container(&info_read, &load,
+ 0));
+ else if (IS_ENABLED(CONFIG_SPL_FIT_FULL))
+ ut_assertok(spl_parse_image_header(&info_read, NULL,
+ img));
+ else
+ ut_assertok(spl_load_simple_fit(&info_read, &load, 0,
+ img));
+ if (check_image_info(uts, &info_write, &info_read))
+ return CMD_RET_FAILURE;
+ ut_asserteq_mem(data, phys_to_virt(info_write.load_addr),
+ data_size);
}
- load.filename = fname;
- header = spl_get_load_buffer(-sizeof(*header), sizeof(*header));
+ free(img);
+ return 0;
+}
+SPL_IMG_TEST(spl_test_image, LEGACY, 0);
+SPL_IMG_TEST(spl_test_image, IMX8, 0);
+SPL_IMG_TEST(spl_test_image, FIT_INTERNAL, 0);
+SPL_IMG_TEST(spl_test_image, FIT_EXTERNAL, 0);
+
+/*
+ * LZMA is too complex to generate on the fly, so let's use some data I put in
+ * the oven^H^H^H^H compressed earlier
+ */
+const char lzma_compressed[] = {
+ 0x5d, 0x00, 0x00, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x02, 0x05, 0x55, 0x4e, 0x82, 0xbc, 0xc2, 0x42, 0xf6, 0x88,
+ 0x6c, 0x99, 0xd6, 0x82, 0x48, 0xa6, 0x06, 0x67, 0xf8, 0x46, 0x7c, 0xe9,
+ 0x41, 0x79, 0xfe, 0x90, 0x0b, 0x31, 0x7b, 0x79, 0x91, 0xb8, 0x5f, 0x33,
+ 0x11, 0x04, 0xc3, 0x4f, 0xf5, 0x71, 0xd1, 0xfb, 0x94, 0x6b, 0x5f, 0x78,
+ 0xe2, 0xfa, 0x6a, 0x21, 0xb6, 0x1d, 0x11, 0x0e, 0x5b, 0x56, 0x6a, 0x5b,
+ 0xe9, 0x56, 0x5f, 0x8b, 0x87, 0x61, 0x96, 0x6d, 0xce, 0x66, 0xbb, 0xb6,
+ 0xe7, 0x13, 0x5a, 0xd8, 0x84, 0x29, 0x60, 0xa0, 0x80, 0x43, 0xdd, 0x0f,
+ 0x4b, 0x85, 0xb0, 0x04, 0x9d, 0x9f, 0x28, 0x97, 0x0a, 0x1e, 0x16, 0xb0,
+ 0x45, 0x33, 0x5e, 0x79, 0x4f, 0xaa, 0xee, 0x79, 0x6e, 0xc3, 0x4e, 0x3d,
+ 0xe8, 0x67, 0x7c, 0xe0, 0xd0, 0xcc, 0x05, 0x40, 0xae, 0x6b, 0x97, 0x82,
+ 0x97, 0x02, 0x01, 0xe2, 0xe3, 0xbc, 0xe4, 0x9b, 0xb3, 0x28, 0xed, 0x5e,
+ 0x0d, 0x68, 0x6e, 0xe5, 0x17, 0x0a, 0x86, 0x5a, 0xcd, 0x8d, 0x46, 0x2d,
+ 0x06, 0x10, 0xa6, 0x90, 0x44, 0xa1, 0xfc, 0x66, 0x6d, 0x7c, 0x57, 0x57,
+ 0x07, 0xbc, 0x95, 0xb2, 0x8d, 0xf0, 0x9f, 0x4d, 0x90, 0x04, 0xaf, 0x0c,
+ 0x23, 0x51, 0x1b, 0x34, 0xd5, 0x5c, 0x5d, 0x87, 0x5e, 0x10, 0x2b, 0x71,
+ 0xc2, 0xcf, 0xc5, 0x9d, 0x4b, 0x89, 0x01, 0xc4, 0x97, 0xf2, 0xea, 0x83,
+ 0x97, 0xfa, 0xe0, 0x51, 0x96, 0x78, 0x4f, 0x44, 0xb8, 0xa8, 0x9d, 0x03,
+ 0x1c, 0x6e, 0xb7, 0xc6, 0xd7, 0xc5, 0x3e, 0x32, 0x65, 0xa7, 0x06, 0xab,
+ 0x86, 0xfb, 0xd2, 0x9b, 0xd7, 0x86, 0xa8, 0xfe, 0x46, 0x41, 0x2e, 0xc2,
+ 0x4e, 0xed, 0xa2, 0x9b, 0x79, 0x36, 0x37, 0x49, 0x90, 0xfc, 0xa6, 0x14,
+ 0x93, 0x17, 0x82, 0x62, 0x3f, 0x79, 0x6b, 0x86, 0xc2, 0xeb, 0x82, 0xfe,
+ 0x87, 0x49, 0xa5, 0x7e, 0x41, 0xe3, 0x59, 0x60, 0x15, 0x61, 0x4e, 0x3b,
+ 0x16, 0xcf, 0xdb, 0x49, 0x2c, 0x84, 0x92, 0x26, 0x40, 0x04, 0x78, 0xd3,
+ 0xd6, 0xa6, 0xed, 0x6e, 0x63, 0x49, 0xcb, 0xea, 0xfe, 0x43, 0x85, 0x21,
+ 0x1a, 0x28, 0x36, 0x0a, 0x3e, 0x2a, 0xad, 0xba, 0xfc, 0x8a, 0x37, 0x18,
+ 0xb4, 0x80, 0xbe, 0x6a, 0x36, 0x14, 0x03, 0xdd, 0xa3, 0x37, 0xbd, 0xc1,
+ 0x8a, 0xbb, 0x2d, 0xd4, 0x08, 0xd7, 0x4b, 0xc4, 0xe9, 0xb8, 0xb4, 0x65,
+ 0xdd, 0xf6, 0xe8, 0x17, 0x2c, 0x2c, 0x9b, 0x1e, 0x92, 0x0b, 0xcb, 0x22,
+ 0x7c, 0x1b, 0x74, 0x8d, 0x65, 0x11, 0x5f, 0xfe, 0xf5, 0x2a, 0xc2, 0xbe,
+ 0xea, 0xa2, 0xf1, 0x7b, 0xe8, 0xaf, 0x32, 0x5a, 0x0a, 0x5b, 0xd2, 0x5a,
+ 0x11, 0x22, 0x79, 0xfa, 0xae, 0x2d, 0xe8, 0xc6, 0x17, 0xba, 0x17, 0x81,
+ 0x6a, 0x63, 0xb5, 0x26, 0xd7, 0x8d, 0xd0, 0x66, 0x0c, 0x4a, 0x0c, 0x22,
+ 0x1b, 0x20, 0x9f, 0x3d, 0x0b, 0x1b, 0x59, 0x53, 0x89, 0x9b, 0x5e, 0xbd,
+ 0x3d, 0xd1, 0xdd, 0xff, 0xca, 0xb2, 0xb7, 0x12, 0x8d, 0x03, 0xaa, 0xc3,
+ 0x1d, 0x56, 0x76, 0x14, 0xf8, 0xee, 0xb3, 0xeb, 0x80, 0x38, 0xc1, 0xc1,
+ 0x1a, 0xef, 0x4a, 0xd5, 0x16, 0x1f, 0x5e, 0x21, 0x5d, 0x46, 0x01, 0xb3,
+ 0xa4, 0xf7, 0x99, 0x94, 0x05, 0xc6, 0xc8, 0x06, 0xd8, 0x1c, 0xac, 0x47,
+ 0x13, 0x54, 0x13, 0x1b, 0x1f, 0xb6, 0x23, 0x9c, 0x73, 0x2b, 0x57, 0x32,
+ 0x94, 0x92, 0xf1, 0x71, 0x44, 0x40, 0x02, 0xc3, 0x21, 0x4a, 0x2f, 0x36,
+ 0x5e, 0x8a, 0xd0, 0x4b, 0x02, 0xc7, 0x6e, 0xcf, 0xed, 0xa2, 0xdb, 0xce,
+ 0x0a, 0x0f, 0x66, 0x4f, 0xb2, 0x3d, 0xb6, 0xcc, 0x75, 0x45, 0x80, 0x0a,
+ 0x49, 0x4a, 0xe7, 0xe7, 0x24, 0x62, 0x65, 0xc7, 0x02, 0x22, 0x13, 0xbe,
+ 0x6c, 0xa9, 0x9a, 0x8b, 0xa9, 0x1b, 0x2b, 0x3a, 0xde, 0x5e, 0x37, 0xbd,
+ 0x7f, 0x85, 0xd1, 0x32, 0x1d, 0xbf, 0x03, 0x8a, 0x3b, 0xe5, 0xb3, 0xfd,
+ 0x01, 0xca, 0xde, 0x0d, 0x7a, 0x5b, 0x01, 0x05, 0x1d, 0x3c, 0x23, 0x00,
+ 0x60, 0xb7, 0x50, 0xfd, 0x0d, 0xd7, 0x63, 0x92, 0xd6, 0xb0, 0x48, 0x3a,
+ 0x2d, 0xa3, 0xf8, 0xf6, 0x44, 0xe1, 0xda, 0x3b, 0xf4, 0x39, 0x47, 0xc4,
+ 0x4d, 0x8f, 0x54, 0x78, 0xec, 0x27, 0x7b, 0xc6, 0xe4, 0x81, 0x3a, 0x3f,
+ 0xa5, 0x61, 0x9d, 0xcb, 0x71, 0x0b, 0x0d, 0x55, 0xea, 0x5b, 0xeb, 0x58,
+ 0xa5, 0x49, 0xb5, 0x44, 0x1b, 0xb0, 0x0d, 0x1f, 0x58, 0xfb, 0x7a, 0xd4,
+ 0x09, 0x1e, 0x9a, 0x7e, 0x21, 0xba, 0xb3, 0x36, 0xa6, 0x04, 0x74, 0xe1,
+ 0xd0, 0xca, 0x02, 0x11, 0x84, 0x93, 0x8f, 0x86, 0x3d, 0x79, 0xbf, 0xa8,
+ 0xec, 0x0a, 0x23, 0x5e, 0xde, 0xc4, 0xc6, 0xda, 0x45, 0xbd, 0x95, 0x74,
+ 0x7b, 0xbf, 0xc1, 0x80, 0x48, 0x3f, 0x10, 0xb6, 0xb9, 0x5c, 0x31, 0x52,
+ 0x06, 0x5a, 0xac, 0xec, 0x94, 0x21, 0x80, 0x51, 0xba, 0x64, 0xed, 0x9d,
+ 0x27, 0x72, 0x8d, 0x17, 0x43, 0x5f, 0xf1, 0x60, 0xfa, 0xb5, 0x65, 0xd4,
+ 0xb9, 0xf8, 0xfc, 0x48, 0x7b, 0xe3, 0xfe, 0xae, 0xe4, 0x71, 0x4a, 0x3d,
+ 0x8c, 0xf5, 0x72, 0x8b, 0xbf, 0x60, 0xd8, 0x6a, 0x8f, 0x51, 0x82, 0xae,
+ 0x98, 0xd0, 0x56, 0xf9, 0xa8, 0x3a, 0xad, 0x86, 0x26, 0xa8, 0x5a, 0xf8,
+ 0x63, 0x87, 0x2c, 0x74, 0xbf, 0xf9, 0x7d, 0x00, 0xa0, 0x2f, 0x17, 0x23,
+ 0xb7, 0x62, 0x94, 0x19, 0x47, 0x57, 0xf9, 0xa8, 0xe7, 0x4b, 0xe9, 0x2b,
+ 0xe8, 0xb4, 0x03, 0xbf, 0x23, 0x75, 0xfe, 0xc3, 0x94, 0xc0, 0xa9, 0x5b,
+ 0x07, 0xb5, 0x75, 0x87, 0xcc, 0xa5, 0xb5, 0x9b, 0x35, 0x29, 0xe4, 0xb1,
+ 0xaa, 0x04, 0x57, 0xe9, 0xa3, 0xd0, 0xa3, 0xe4, 0x11, 0xe1, 0xaa, 0x3b,
+ 0x67, 0x09, 0x60, 0x83, 0x23, 0x72, 0xa6, 0x7b, 0x73, 0x22, 0x5b, 0x4a,
+ 0xe0, 0xf0, 0xa3, 0xeb, 0x9c, 0x91, 0xda, 0xba, 0x8b, 0xc1, 0x32, 0xa9,
+ 0x24, 0x13, 0x51, 0xe4, 0x67, 0x49, 0x4a, 0xd9, 0x3d, 0xae, 0x80, 0xfd,
+ 0x0a, 0x0d, 0x56, 0x98, 0x66, 0xa2, 0x6d, 0x92, 0x54, 0x7f, 0x82, 0xe5,
+ 0x17, 0x39, 0xd3, 0xaa, 0xc4, 0x4e, 0x6f, 0xe1, 0x2e, 0xfe, 0x03, 0x44,
+ 0x8a, 0xdd, 0xeb, 0xc0, 0x74, 0x79, 0x63, 0x33, 0x2b, 0x4b, 0xb5, 0x62,
+ 0xdd, 0x47, 0xba, 0x6e, 0xfc, 0x91, 0x08, 0xa9, 0x17, 0x8c, 0x47, 0x61,
+ 0xd9, 0x32, 0xe9, 0xa0, 0xb3, 0xa2, 0x82, 0xc9, 0xa6, 0x32, 0xa1, 0xca,
+ 0x7c, 0x41, 0xa6, 0x5a, 0xe2, 0x46, 0xb6, 0x45, 0x53, 0x72, 0x55, 0x9e,
+ 0xdf, 0xac, 0x96, 0x68, 0xe5, 0xdc, 0x4e, 0x2d, 0xa8, 0x1e, 0x7a, 0x8e,
+ 0xff, 0x54, 0xe4, 0x0a, 0x33, 0x5d, 0x97, 0xdf, 0x4e, 0x36, 0x96, 0xba,
+ 0x52, 0xd9, 0xa9, 0xec, 0x52, 0xe5, 0x1d, 0x94, 0xfe, 0x1c, 0x46, 0x54,
+ 0xa6, 0x8e, 0x85, 0x47, 0xba, 0xeb, 0x4b, 0x8d, 0x57, 0xe4, 0x34, 0x24,
+ 0x9e, 0x80, 0xb5, 0xc9, 0xa9, 0x94, 0x1d, 0xe4, 0x18, 0xb6, 0x07, 0x1e,
+ 0xfa, 0xe0, 0x1c, 0x88, 0x06, 0x84, 0xaa, 0xcb, 0x5e, 0xfa, 0x15, 0x5a,
+ 0xdd, 0x10, 0x43, 0x81, 0xf2, 0x50, 0x3e, 0x93, 0x26, 0x77, 0x1c, 0x77,
+ 0xe9, 0x0c, 0xfc, 0x5f, 0xdd, 0x67, 0x31, 0x02, 0xc6, 0xdd, 0xf4, 0x30,
+ 0x76, 0x51, 0xce, 0x56, 0xba, 0x7f, 0x44, 0xbd, 0x42, 0x9f, 0x10, 0x8c,
+ 0x56, 0x49, 0x48, 0xa2, 0xcb, 0xc4, 0xdd, 0x29, 0xae, 0xf0, 0x33, 0x35,
+ 0x46, 0x69, 0x1d, 0xae, 0xde, 0xde, 0x98, 0x82, 0x79, 0xa6, 0x50, 0x28,
+ 0xb3, 0x5f, 0x10, 0x24, 0x63, 0xee, 0x9a, 0x22, 0xbe, 0xf8, 0x3a, 0xf4,
+ 0xab, 0x98, 0xfe, 0xdf, 0x30, 0x03, 0xe8, 0x45, 0x8c, 0xf4, 0x85, 0xc6,
+ 0x98, 0x7b, 0x35, 0xb8, 0x30, 0x9c, 0x15, 0xa6, 0x45, 0xbd, 0x39, 0x84,
+ 0xe7, 0x43, 0x4b, 0x05, 0xa4, 0x8f, 0x52, 0x8e, 0x4a, 0xe4, 0x87, 0xc1,
+ 0xdc, 0xdf, 0x25, 0x9c, 0x5c, 0x37, 0xd0, 0x66, 0x12, 0x41, 0x66, 0x8c,
+ 0x28, 0xd0, 0x3f, 0x5c, 0x7f, 0x15, 0x9b, 0xcf, 0xa0, 0xae, 0x29, 0x33,
+ 0xb0, 0xe4, 0xb7, 0x36, 0x2a, 0x45, 0x83, 0xff, 0x86, 0x75, 0xcf, 0xa7,
+ 0x4d, 0x5c, 0xa8, 0xcf, 0x3f, 0xf2, 0xc8, 0xde, 0xdd, 0xad, 0x42, 0x8f,
+ 0x0e, 0xd0, 0x11, 0x24, 0x42, 0x86, 0x51, 0x52, 0x76, 0x21, 0x68, 0xf1,
+ 0xa7, 0x8f, 0xdb, 0x5b, 0x78, 0xfa, 0x44, 0x5f, 0xee, 0x31, 0xda, 0x62,
+ 0x5f, 0xfe, 0x69, 0xae, 0x97, 0xc9, 0xb5, 0x04, 0x76, 0x79, 0x2e, 0xb9,
+ 0xd9, 0x1b, 0xdd, 0xb7, 0xc4, 0x12, 0x78, 0xb2, 0x4d, 0xab, 0xd2, 0x29,
+ 0x25, 0x8c, 0xd5, 0x52, 0x4a, 0xd7, 0x2e, 0x18, 0x9d, 0xa2, 0xee, 0x7b,
+ 0xa5, 0xe5, 0x35, 0x3c, 0xb5, 0x54, 0x1c, 0x7f, 0x87, 0x4b, 0xc0, 0xbb,
+ 0x1a, 0x85, 0x19, 0xc0, 0xa9, 0x2b, 0x4d, 0xed, 0x71, 0xc0, 0x15, 0xb3,
+ 0x49, 0x2c, 0x46, 0xfc, 0x37, 0x40, 0xc0, 0x60, 0xd0, 0x00, 0x96, 0xfa,
+ 0x7f, 0xbb, 0x30, 0x94, 0x6b, 0x81, 0x61, 0xc5, 0x13, 0x93, 0x95, 0xaa,
+ 0xf3, 0x8d, 0x1d, 0xac, 0xdb, 0xbd, 0xc3, 0x90, 0xf3, 0xd2, 0x5f, 0x3a,
+ 0x08, 0xb1, 0xc9, 0x3a, 0xe8, 0x25, 0x4d, 0x20, 0x2a, 0xe9, 0x4c, 0xaf,
+ 0x9b, 0x54, 0x7b, 0xaf, 0x89, 0x44, 0x3a, 0x60, 0x23, 0xd3, 0x02, 0xb1,
+ 0xb3, 0x9a, 0x3a, 0xb0, 0xa0, 0xdb, 0x61, 0x0b, 0xac, 0x55, 0xa1, 0x36,
+ 0x55, 0x5b, 0xc4, 0xc5, 0xbd, 0x2a, 0x16, 0xe9, 0xe7, 0x86, 0x7f, 0xdb,
+ 0xee, 0x90, 0xfa, 0xfd, 0x08, 0x7f, 0x1a, 0x43, 0xe0, 0xb8, 0x21, 0xb3,
+ 0xe3, 0xdf, 0x27, 0x56, 0x61, 0xc4, 0xe8, 0xd5, 0x60, 0xe9, 0x6d, 0x49,
+ 0xd9, 0xa8, 0xf5, 0xd9, 0xfc, 0x66, 0x82, 0xe9, 0x80, 0x5b, 0x85, 0x16,
+ 0x55, 0x2b, 0xef, 0x50, 0x90, 0x6c, 0x5d, 0x81, 0x00, 0x00, 0x88, 0x9b,
+ 0xb4, 0x62, 0x49, 0x46, 0x2e, 0x5d, 0x71, 0x95, 0xff, 0x63, 0xfb, 0x93,
+ 0x23, 0xf8, 0x9f, 0xa2, 0x55, 0x56, 0xd4, 0xd5, 0xf7, 0xae, 0xaf, 0xd3,
+ 0xf6, 0x82, 0xc8, 0xdd, 0x89, 0x0f, 0x7e, 0x89, 0x0d, 0x0d, 0x7f, 0x4f,
+ 0x84, 0xa7, 0x16, 0xe8, 0xaf, 0xf2, 0x95, 0xd7, 0xc3, 0x66, 0xd6, 0x85,
+ 0x5b, 0xa1, 0xbb, 0xea, 0x31, 0x02, 0xac, 0xa2, 0x7b, 0x50, 0xf4, 0x78,
+ 0x29, 0x49, 0x59, 0xf6, 0x41, 0x42, 0x52, 0xa8, 0x19, 0xfb, 0x3d, 0xda,
+ 0xa9, 0x8d, 0xac, 0xe1, 0x25, 0xd4, 0x12, 0x1e, 0x2b, 0x48, 0x44, 0xb0,
+ 0xf6, 0x29, 0xd0, 0x55, 0x22, 0xb4, 0xe7, 0xbc, 0x22, 0x97, 0x1f, 0xe2,
+ 0xe1, 0x73, 0x16, 0x13, 0x7a, 0x00, 0x62, 0x14, 0xcb, 0x25, 0x9b, 0x21,
+ 0x98, 0x9d, 0xb8, 0xd8, 0xf4, 0x65, 0xf6, 0x8f, 0x39, 0xe4, 0x76, 0xf7,
+ 0x30, 0xaf, 0xbc, 0x3a, 0xfe, 0x0e, 0xf1, 0x81, 0xa7, 0xff, 0x4d, 0xa7,
+ 0xff, 0xbf, 0x15, 0x60, 0x0b, 0xcd, 0x69, 0xd5, 0x77, 0xba, 0xcb, 0x7b,
+ 0x5a, 0xfb, 0x34, 0xc7, 0x5d, 0x13, 0x33, 0xd7, 0x86, 0x02, 0x43, 0x57,
+ 0x52, 0x2c, 0x74, 0x61, 0x21, 0xa3, 0x34, 0xf5, 0x89, 0x51, 0x44, 0x89,
+ 0xfc, 0xbb, 0x57, 0x5c, 0x6d, 0xb0, 0x2e, 0x8c, 0xff, 0x73, 0xe5, 0x09,
+ 0x13, 0x3b, 0x45, 0x5b, 0x27, 0x88, 0xee, 0x9b, 0xab, 0x57, 0x7c, 0x9b,
+ 0xb9, 0x78, 0x73, 0xd2, 0x2d, 0x98, 0x6f, 0xd2, 0x78, 0xb3, 0xeb, 0xaa,
+ 0x18, 0x44, 0x87, 0x6d, 0x51, 0x1e, 0x9b, 0x73, 0xaa, 0x91, 0x1a, 0x4f,
+ 0x69, 0x78, 0xef, 0x3f, 0xb1, 0x2d, 0x39, 0x3e, 0xda, 0x31, 0xfc, 0x99,
+ 0xf6, 0xa2, 0x8c, 0xe5, 0xfd, 0x97, 0x95, 0x77, 0x37, 0xef, 0xf5, 0xd1,
+ 0xc8, 0x74, 0x2c, 0x9a, 0x1f, 0x23, 0x8f, 0x72, 0x96, 0x3d, 0xb5, 0xad,
+ 0x28, 0xa0, 0x6c, 0x66, 0xe8, 0xee, 0xaa, 0x9d, 0xc2, 0x8a, 0x56, 0x54,
+ 0x89, 0x74, 0x56, 0xdc, 0x57, 0x49, 0xc3, 0x8e, 0xb9, 0x3a, 0x91, 0x34,
+ 0xc4, 0x5e, 0x0b, 0x13, 0x63, 0x5e, 0xeb, 0xc5, 0xef, 0xc7, 0xe9, 0x7f,
+ 0x27, 0xe8, 0xe7, 0xe5, 0x0d, 0x83, 0x95, 0x5f, 0x8a, 0xf2, 0xb2, 0x22,
+ 0x03, 0x8d, 0x71, 0x4f, 0x62, 0xb7, 0xf1, 0x87, 0xf5, 0x3f, 0xc4, 0x23,
+ 0x21, 0x40, 0x35, 0xcf, 0x79, 0x7a, 0x5b, 0x9d, 0x76, 0xb2, 0xdc, 0x6a,
+ 0xb5, 0x1d, 0x8b, 0xb6, 0x9a, 0x19, 0xe4, 0x87, 0xf5, 0xce, 0x38, 0xf3,
+ 0x70, 0xbf, 0x9e, 0x86, 0xa6, 0x07, 0x53, 0xdd, 0x5d, 0xc7, 0x72, 0x84,
+ 0x47, 0x38, 0xd0, 0xe2, 0xeb, 0x64, 0x4c, 0x3a, 0x1e, 0xf6, 0x56, 0x79,
+ 0x75, 0x75, 0x14, 0x5d, 0xe4, 0x1d, 0x9d, 0xbb, 0xe1, 0x35, 0x03, 0x5e,
+ 0x4f, 0x8f, 0xea, 0x95, 0xde, 0x19, 0x57, 0x98, 0xe9, 0x2c, 0x42, 0x22,
+ 0xcb, 0x0f, 0x15, 0x7a, 0x6b, 0x53, 0xc3, 0xec, 0xdc, 0xa0, 0x66, 0x26,
+ 0x91, 0x04, 0x83, 0x75, 0x09, 0x0c, 0x22, 0x05, 0xec, 0x3a, 0x2d, 0x39,
+ 0xea, 0x19, 0xf2, 0x1d, 0xdb, 0xba, 0x5c, 0x46, 0x47, 0xd4, 0x94, 0x6d,
+ 0x51, 0xdb, 0x68, 0xde, 0x0c, 0xa0, 0x36, 0x8f, 0xbc, 0xfd, 0x9b, 0x8f,
+ 0xfe, 0x04, 0x1f, 0xde, 0x1e, 0x77, 0xb5, 0x80, 0xb9, 0x9c, 0x1b, 0x24,
+ 0x61, 0xfc, 0x2b, 0xc0, 0x42, 0x2b, 0xc5, 0x90, 0x58, 0xa2, 0xb1, 0x38,
+ 0x58, 0xf2, 0x8b, 0x65, 0xbf, 0xe8, 0xe6, 0x79, 0xcf, 0x65, 0x35, 0xa5,
+ 0xe1, 0xb7, 0x8b, 0x95, 0x54, 0xd7, 0x1d, 0xf0, 0x91, 0x18, 0xc0, 0x5d,
+ 0x2c, 0xb5, 0xca, 0x1a, 0x7f, 0x8d, 0xfb, 0x9e, 0x57, 0x1c, 0x5c, 0xf0,
+ 0x94, 0x36, 0x51, 0x95, 0x27, 0x62, 0xca, 0x92, 0x96, 0xe5, 0x00, 0x2e,
+ 0xa4, 0x41, 0x97, 0xbf, 0x28, 0x3c, 0x6d, 0xc1, 0xb7, 0xe9, 0x1c, 0x2e,
+ 0x3e, 0xe0, 0x5e, 0x89, 0x0c, 0x78, 0x88, 0x80, 0xb8, 0x30, 0xd2, 0x22,
+ 0xf9, 0x71, 0xb4, 0xc8, 0xee, 0xe6, 0x80, 0x04, 0x04, 0x9a, 0xfb, 0x0c,
+ 0x36, 0xcb, 0xea, 0x66, 0xf9, 0x52, 0x8c, 0x66, 0xbf, 0x4c, 0x0f, 0xf4,
+ 0xf8, 0x1e, 0x7e, 0x39, 0x80, 0xe8, 0x82, 0x4b, 0x0e, 0x66, 0x1d, 0x51,
+ 0x16, 0xa9, 0x8d, 0xd6, 0xea, 0x33, 0xb0, 0x2c, 0x36, 0x25, 0xf5, 0x01,
+ 0x30, 0x7e, 0x03, 0x7f, 0xae, 0x8e, 0xd6, 0x25, 0x62, 0x6d, 0x99, 0x8c,
+ 0x1f, 0xc1, 0x22, 0xf0, 0x94, 0x80, 0xbf, 0x82, 0x51, 0xea, 0xc2, 0x5a,
+ 0x3c, 0x85, 0x2a, 0x5d, 0xbe, 0xae, 0xe1, 0xe3, 0x07, 0x92, 0xd2, 0x40,
+ 0x47, 0xe8, 0x0f, 0x1a, 0xa5, 0x73, 0x64, 0x26, 0xc4, 0xac, 0xca, 0xc2,
+ 0x83, 0x5a, 0x56, 0xbc, 0x81, 0x21, 0xcb, 0x72, 0xf3, 0xe7, 0x82, 0x1e,
+ 0xc8, 0x54, 0x18, 0x42, 0xfe, 0xd6, 0xfc, 0x96, 0x0e, 0x03, 0x29, 0x98,
+ 0x4f, 0xd1, 0xd2, 0x98, 0x7c, 0x9e, 0x4e, 0x1a, 0x0f, 0xd6, 0x4e, 0xa4,
+ 0x52, 0x1b, 0xd1, 0xd8, 0x36, 0xf7, 0x47, 0x5f, 0xce, 0xcb, 0x87, 0x36,
+ 0xc8, 0x9b, 0x44, 0xc6, 0x7a, 0xf3, 0x45, 0x28, 0xae, 0x96, 0x5a, 0x85,
+ 0x62, 0x8b, 0x10, 0xc2, 0x7b, 0x39, 0x51, 0xdf, 0xf4, 0x21, 0xc2, 0x6b,
+ 0x6f, 0x93, 0x27, 0xed, 0xf6, 0xea, 0xff, 0x2a, 0x21, 0x70, 0x84, 0x4e,
+ 0x21, 0xac, 0xbc, 0x06, 0x41, 0xd3, 0x59, 0xa0, 0xa1, 0x50, 0xa6, 0x87,
+ 0xa2, 0x48, 0xad, 0x94, 0x44, 0x8d, 0x2f, 0xa8, 0xc6, 0x10, 0xb5, 0xeb,
+ 0x66, 0x82, 0x94, 0x5f, 0xae, 0x6a, 0x56, 0xb4, 0x8d, 0xf4, 0x62, 0x80,
+ 0xe4, 0x42, 0xc4, 0xbc, 0xe7, 0xee, 0xa6, 0x96, 0x3b, 0xfd, 0xc0, 0x92,
+ 0x7d, 0xcd, 0xe7, 0x0c, 0x99, 0x9a, 0xb6, 0x83, 0xcf, 0x45, 0xe5, 0x74,
+ 0xb3, 0xbc, 0xc0, 0x40, 0xad, 0x4d, 0xfc, 0xa7, 0x92, 0x35, 0x13, 0x81,
+ 0x5c, 0x9c, 0x21, 0x00, 0xa4, 0x37, 0x07, 0x1d, 0x19, 0xfc, 0x88, 0x4d,
+ 0x71, 0x43, 0x7d, 0x94, 0xf7, 0x32, 0xb8, 0x4b, 0x8a, 0x54, 0xd6, 0xe4,
+ 0x37, 0x4f, 0x27, 0x1f, 0xfd, 0x45, 0x83, 0xb9, 0x14, 0x5a, 0xf7, 0x36,
+ 0xdc, 0x98, 0xad, 0x99, 0xb9, 0x38, 0x69, 0xac, 0x18, 0x7e, 0x47, 0xd0,
+ 0x63, 0x27, 0xba, 0xe7, 0xd5, 0x1d, 0x7b, 0x6e, 0xde, 0x28, 0x7b, 0xf1,
+ 0x84, 0x4d, 0x2d, 0x7c, 0x16, 0x38, 0x4b, 0x16, 0xa9, 0x10, 0x83, 0xfb,
+ 0xe0, 0xe0, 0x6f, 0xdd, 0x03, 0x0a, 0xb8, 0x81, 0xf5, 0x8c, 0x98, 0xc3,
+ 0xf4, 0xc8, 0x31, 0x3a, 0xed, 0x14, 0x83, 0x89, 0xc3, 0x0e, 0xf7, 0xba,
+ 0x84, 0xb0, 0x49, 0xdf, 0xc6, 0x6b, 0xed, 0xbe, 0xd4, 0xa3, 0x83, 0x3a,
+ 0xe6, 0x6d, 0xa3, 0x83, 0x17, 0x43, 0x5e, 0x3a, 0x83, 0xda, 0x81, 0xe3,
+ 0x26, 0x95, 0x6b, 0xe5, 0x30, 0x28, 0x6d, 0xec, 0xd7, 0xd7, 0x35, 0xfa,
+ 0x1a, 0xad, 0x86, 0x04, 0x05, 0x2c, 0x76, 0x3f, 0xb2, 0x83, 0x92, 0x4e,
+ 0xef, 0x05, 0xde, 0x13, 0x26, 0x68, 0x80, 0x57, 0xee, 0x92, 0x80, 0xa3,
+ 0x99, 0xb4, 0xac, 0x98, 0x31, 0xd4, 0xf3, 0xe2, 0x60, 0xd9, 0xb9, 0x8d,
+ 0x20, 0xf7, 0x97, 0x70, 0x10, 0xd6, 0xba, 0x86, 0xb8, 0x9c, 0xb8, 0xf8,
+ 0x49, 0x71, 0x28, 0x9d, 0x05, 0x38, 0x1f, 0x63, 0xba, 0xf7, 0x15, 0x60,
+ 0x96, 0x61, 0x84, 0x68, 0xeb, 0x5d, 0x28, 0x51, 0xe3, 0x51, 0xdd, 0x69,
+ 0x8a, 0xdd, 0xba, 0xec, 0xbd, 0xd3, 0xa1, 0x42, 0x83, 0x59, 0x77, 0x11,
+ 0x12, 0x86, 0x5b, 0x8d, 0x30, 0xcf, 0xdf, 0x6f, 0xea, 0x9d, 0x31, 0xa2,
+ 0x65, 0xa5, 0x61, 0xc0, 0xde, 0x52, 0x6c, 0x72, 0x71, 0x0b, 0x4c, 0x7a,
+ 0x4c, 0x9f, 0x75, 0x74, 0x38, 0xc8, 0xdd, 0x12, 0xba, 0x21, 0x57, 0x1b,
+ 0x45, 0xb3, 0x02, 0x1d, 0x67, 0x22, 0x66, 0x53, 0x18, 0x48, 0xed, 0x60,
+ 0x40, 0x55, 0xd1, 0x25, 0x3b, 0xbc, 0x08, 0x7b, 0x19, 0x8a, 0x30, 0x5b,
+ 0x02, 0x4f, 0x65, 0x42, 0xff, 0xce, 0x87, 0xe8, 0x97, 0x2b, 0xbb, 0xfe,
+ 0x52, 0x52, 0x72, 0xe8, 0xb5, 0x77, 0xb7, 0x8e, 0x94, 0x34, 0xbc, 0x46,
+ 0xf1, 0xe1, 0x94, 0x98, 0x19, 0xbe, 0x7c, 0x3f, 0xf6, 0x0e, 0xe4, 0xbb,
+ 0x88, 0x32, 0x07, 0x83, 0x64, 0xad, 0xd7, 0xd1, 0xe8, 0x35, 0x8d, 0x5d,
+ 0x70, 0x16, 0xc8, 0x11, 0x94, 0x39, 0xc9, 0xac, 0xd6, 0xed, 0x6b, 0xdf,
+ 0xc8, 0xf3, 0x1d, 0x5e, 0x37, 0xd8, 0xb5, 0x86, 0x9b, 0xc2, 0xdc, 0x3c,
+ 0x5c, 0x04, 0x52, 0x5c, 0x11, 0x88, 0x0a, 0x2b, 0x78, 0x48, 0x9e, 0x5e,
+ 0x98, 0x57, 0x5a, 0xd1, 0x77, 0x1c, 0x7d, 0x5f, 0x60, 0xbb, 0x61, 0x7e,
+ 0x7e, 0x2a, 0xaf, 0x44, 0x14, 0x88, 0xfc, 0xa5, 0x31, 0xb7, 0xd4, 0x44,
+ 0x48, 0xda, 0xb5, 0x71, 0xa8, 0xd8, 0x4f, 0x79, 0xcd, 0xe4, 0xbe, 0xb6,
+ 0x1a, 0x61, 0x74, 0x4b, 0xd8, 0xec, 0xd7, 0xbf, 0xad, 0x57, 0x00, 0x42,
+ 0x04, 0xe8, 0xb3, 0xec, 0x47, 0x1d, 0x2a, 0x0a, 0xde, 0x7c, 0x6e, 0x5e,
+ 0xf8, 0xaa, 0x44, 0x05, 0x10, 0xab, 0xe9, 0x4e, 0xd7, 0x44, 0x0b, 0x97,
+ 0x6f, 0x1a, 0xc1, 0x59, 0x2b, 0xe4, 0xe1, 0x8a, 0x13, 0x82, 0x65, 0xd8,
+ 0xae, 0x5f, 0x2b, 0xbc, 0xa6, 0x14, 0x39, 0xaf, 0x38, 0x41, 0x26, 0x74,
+ 0xdb, 0x55, 0x6b, 0xe2, 0x21, 0x80, 0x5d, 0x20, 0xc3, 0xf5, 0x82, 0xee,
+ 0xcc, 0x3c, 0xc9, 0xb4, 0xeb, 0x52, 0xe9, 0x13, 0x8a, 0xea, 0xc6, 0x19,
+ 0x70, 0x37, 0x1b, 0xb8, 0x2e, 0x86, 0xa2, 0xe9, 0x9d, 0xb6, 0xd5, 0xd6,
+ 0xf3, 0xa8, 0x31, 0xf3, 0x02, 0xaa, 0x10, 0x33, 0x3f, 0xba, 0xf8, 0xf9,
+ 0x46, 0x5b, 0xe1, 0xd7, 0x34, 0x9f, 0x94, 0xcb, 0xfb, 0xb1, 0x3d, 0x60,
+ 0x77, 0x85, 0x14, 0xd4, 0xcf, 0x55, 0x60, 0x5d, 0x47, 0x6c, 0x07, 0xb4,
+ 0xc7, 0x73, 0xbd, 0x49, 0xbd, 0xa5, 0x31, 0xa1, 0xfa, 0x34, 0x3a, 0x8b,
+ 0x77, 0x1b, 0xaa, 0xaf, 0xa5, 0x87, 0x12, 0x4e, 0x36, 0x06, 0x14, 0xe7,
+ 0xb3, 0xb8, 0x87, 0x6c, 0x4b, 0x50, 0xc9, 0x52, 0x1b, 0x19, 0x48, 0x69,
+ 0x5b, 0x7f, 0xd8, 0xc9, 0x14, 0xb8, 0x11, 0xa0, 0x51, 0x09, 0xbd, 0x42,
+ 0x5a, 0x50, 0x32, 0x57, 0x69, 0x39, 0x30, 0xdb, 0xbf, 0x8b, 0x93, 0x54,
+ 0x43, 0x80, 0x4e, 0xd0, 0xc6, 0xf2, 0x81, 0x15, 0x6d, 0xef, 0x5a, 0xb6,
+ 0x4d, 0x70, 0x93, 0x88, 0x8d, 0xce, 0x0d, 0xb8, 0xe9, 0xac, 0xa2, 0xcd,
+ 0xc7, 0x18, 0xa5, 0x95, 0xb7, 0xf6, 0x0c, 0x6f, 0xe1, 0x10, 0x7b, 0x22,
+ 0xf8, 0x81, 0x18, 0x42, 0x6a, 0x09, 0x75, 0x20, 0xb4, 0x2f, 0x67, 0x7a,
+ 0xda, 0x55, 0x28, 0xc3, 0x81, 0xf7, 0xc1, 0xf0, 0xe6, 0x1b, 0x29, 0x9c,
+ 0x72, 0x87, 0xe5, 0x4c, 0xa9, 0x5b, 0x5b, 0x62, 0xb5, 0xb7, 0x1e, 0x82,
+ 0xc3, 0x7b, 0xaf, 0xe9, 0x6f, 0x37, 0x31, 0x9f, 0x79, 0xe7, 0x4f, 0x06,
+ 0x1e, 0xff, 0xff, 0x80, 0x8e, 0x00, 0x00
+};
+
+const size_t lzma_compressed_size = sizeof(lzma_compressed);
- fd = os_open(fname, OS_O_RDONLY);
- ut_assert(fd >= 0);
- ut_asserteq(512, os_read(fd, header, 512));
- text_ctx.fd = fd;
+int do_spl_test_load(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type, struct spl_image_loader *loader,
+ int (*write_image)(struct unit_test_state *, void *, size_t))
+{
+ size_t img_size, img_data, plain_size = SPL_TEST_DATA_SIZE;
+ struct spl_image_info info_write = {
+ .name = test_name,
+ .size = type == LEGACY_LZMA ? sizeof(lzma_compressed) :
+ plain_size,
+ }, info_read = { };
+ struct spl_boot_device bootdev = {
+ .boot_device = loader->boot_device,
+ };
+ char *data, *plain;
+ void *img;
+
+ img_size = create_image(NULL, type, &info_write, &img_data);
+ ut_assert(img_size);
+ img = calloc(img_size, 1);
+ ut_assertnonnull(img);
+
+ data = img + img_data;
+ if (type == LEGACY_LZMA) {
+ plain = malloc(plain_size);
+ ut_assertnonnull(plain);
+ generate_data(plain, plain_size, "lzma");
+ memcpy(data, lzma_compressed, sizeof(lzma_compressed));
+ } else {
+ plain = data;
+ generate_data(plain, plain_size, test_name);
+ }
+ ut_asserteq(img_size, create_image(img, type, &info_write, NULL));
- load.priv = &text_ctx;
+ if (write_image(uts, img, img_size))
+ return CMD_RET_FAILURE;
- ut_assertok(spl_load_simple_fit(&image, &load, 0, header));
+ ut_assertok(loader->load_image(&info_read, &bootdev));
+ if (check_image_info(uts, &info_write, &info_read))
+ return CMD_RET_FAILURE;
+ if (type == LEGACY_LZMA)
+ ut_asserteq(plain_size, info_read.size);
+ ut_asserteq_mem(plain, phys_to_virt(info_write.load_addr), plain_size);
+ if (type == LEGACY_LZMA)
+ free(plain);
+ free(img);
return 0;
}
-SPL_TEST(spl_test_load, 0);
diff --git a/test/image/spl_load_fs.c b/test/image/spl_load_fs.c
new file mode 100644
index 00000000000..a89189e1124
--- /dev/null
+++ b/test/image/spl_load_fs.c
@@ -0,0 +1,442 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <common.h>
+#include <blk.h>
+#include <ext_common.h>
+#include <ext4fs.h>
+#include <fat.h>
+#include <fs.h>
+#include <memalign.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <linux/stat.h>
+#include <test/spl.h>
+#include <test/ut.h>
+
+/**
+ * create_ext2() - Create an "ext2" filesystem with a single file
+ * @dst: The location of the new filesystem; MUST be zeroed
+ * @size: The size of the file
+ * @filename: The name of the file
+ * @data_offset: Filled with the offset of the file data from @dst
+ *
+ * Budget mke2fs. We use 1k blocks (to reduce overhead) with a single block
+ * group, which limits us to 8M of data. Almost every feature which increases
+ * complexity (checksums, hash tree directories, etc.) is disabled. We do cheat
+ * a little and use extents from ext4 to save having to deal with indirects, but
+ * U-Boot doesn't care.
+ *
+ * If @dst is %NULL, nothing is copied.
+ *
+ * Return: The size of the filesystem in bytes
+ */
+static size_t create_ext2(void *dst, size_t size, const char *filename,
+ size_t *data_offset)
+{
+ u32 super_block = 1;
+ u32 group_block = 2;
+ u32 block_bitmap_block = 3;
+ u32 inode_bitmap_block = 4;
+ u32 inode_table_block = 5;
+ u32 root_block = 6;
+ u32 file_block = 7;
+
+ u32 root_ino = EXT2_ROOT_INO;
+ u32 file_ino = EXT2_BOOT_LOADER_INO;
+
+ u32 block_size = EXT2_MIN_BLOCK_SIZE;
+ u32 inode_size = sizeof(struct ext2_inode);
+
+ u32 file_blocks = (size + block_size - 1) / block_size;
+ u32 blocks = file_block + file_blocks;
+ u32 inodes = block_size / inode_size;
+ u32 filename_len = strlen(filename);
+ u32 dirent_len = ALIGN(filename_len, sizeof(struct ext2_dirent)) +
+ sizeof(struct ext2_dirent);
+
+ struct ext2_sblock *sblock = dst + super_block * block_size;
+ struct ext2_block_group *bg = dst + group_block * block_size;
+ struct ext2_inode *inode_table = dst + inode_table_block * block_size;
+ struct ext2_inode *root_inode = &inode_table[root_ino - 1];
+ struct ext2_inode *file_inode = &inode_table[file_ino - 1];
+ struct ext4_extent_header *ext_block = (void *)&file_inode->b;
+ struct ext4_extent *extent = (void *)(ext_block + 1);
+ struct ext2_dirent *dot = dst + root_block * block_size;
+ struct ext2_dirent *dotdot = dot + 2;
+ struct ext2_dirent *dirent = dotdot + 2;
+ struct ext2_dirent *last = ((void *)dirent) + dirent_len;
+
+ /* Make sure we fit in one block group */
+ if (blocks > block_size * 8)
+ return 0;
+
+ if (filename_len > EXT2_NAME_LEN)
+ return 0;
+
+ if (data_offset)
+ *data_offset = file_block * block_size;
+
+ if (!dst)
+ goto out;
+
+ sblock->total_inodes = cpu_to_le32(inodes);
+ sblock->total_blocks = cpu_to_le32(blocks);
+ sblock->first_data_block = cpu_to_le32(super_block);
+ sblock->blocks_per_group = cpu_to_le32(blocks);
+ sblock->fragments_per_group = cpu_to_le32(blocks);
+ sblock->inodes_per_group = cpu_to_le32(inodes);
+ sblock->magic = cpu_to_le16(EXT2_MAGIC);
+ /* Done mostly so we can pretend to be (in)compatible */
+ sblock->revision_level = cpu_to_le32(EXT2_DYNAMIC_REV);
+ /* Not really accurate but it doesn't matter */
+ sblock->first_inode = cpu_to_le32(EXT2_GOOD_OLD_FIRST_INO);
+ sblock->inode_size = cpu_to_le32(inode_size);
+ sblock->feature_incompat = cpu_to_le32(EXT4_FEATURE_INCOMPAT_EXTENTS);
+
+ bg->block_id = cpu_to_le32(block_bitmap_block);
+ bg->inode_id = cpu_to_le32(inode_bitmap_block);
+ bg->inode_table_id = cpu_to_le32(inode_table_block);
+
+ /*
+ * All blocks/inodes are in-use. I don't want to have to deal with
+ * endianness, so just fill everything in.
+ */
+ memset(dst + block_bitmap_block * block_size, 0xff, block_size * 2);
+
+ root_inode->mode = cpu_to_le16(S_IFDIR | 0755);
+ root_inode->size = cpu_to_le32(block_size);
+ root_inode->nlinks = cpu_to_le16(3);
+ root_inode->blockcnt = cpu_to_le32(1);
+ root_inode->flags = cpu_to_le32(EXT4_TOPDIR_FL);
+ root_inode->b.blocks.dir_blocks[0] = root_block;
+
+ file_inode->mode = cpu_to_le16(S_IFREG | 0644);
+ file_inode->size = cpu_to_le32(size);
+ file_inode->nlinks = cpu_to_le16(1);
+ file_inode->blockcnt = cpu_to_le32(file_blocks);
+ file_inode->flags = cpu_to_le32(EXT4_EXTENTS_FL);
+ ext_block->eh_magic = cpu_to_le16(EXT4_EXT_MAGIC);
+ ext_block->eh_entries = cpu_to_le16(1);
+ ext_block->eh_max = cpu_to_le16(sizeof(file_inode->b) /
+ sizeof(*ext_block) - 1);
+ extent->ee_len = cpu_to_le16(file_blocks);
+ extent->ee_start_lo = cpu_to_le16(file_block);
+
+ /* I'm not sure we need these, but it can't hurt */
+ dot->inode = cpu_to_le32(root_ino);
+ dot->direntlen = cpu_to_le16(2 * sizeof(*dot));
+ dot->namelen = 1;
+ dot->filetype = FILETYPE_DIRECTORY;
+ memcpy(dot + 1, ".", dot->namelen);
+
+ dotdot->inode = cpu_to_le32(root_ino);
+ dotdot->direntlen = cpu_to_le16(2 * sizeof(*dotdot));
+ dotdot->namelen = 2;
+ dotdot->filetype = FILETYPE_DIRECTORY;
+ memcpy(dotdot + 1, "..", dotdot->namelen);
+
+ dirent->inode = cpu_to_le32(file_ino);
+ dirent->direntlen = cpu_to_le16(dirent_len);
+ dirent->namelen = filename_len;
+ dirent->filetype = FILETYPE_REG;
+ memcpy(dirent + 1, filename, filename_len);
+
+ last->direntlen = block_size - dirent_len;
+
+out:
+ return (size_t)blocks * block_size;
+}
+
+/**
+ * create_fat() - Create a FAT32 filesystem with a single file
+ * @dst: The location of the new filesystem; MUST be zeroed
+ * @size: The size of the file
+ * @filename: The name of the file
+ * @data_offset: Filled with the offset of the file data from @dst
+ *
+ * Budget mkfs.fat. We use FAT32 (so I don't have to deal with FAT12) with no
+ * info sector, and a single one-sector FAT. This limits us to 64k of data
+ * (enough for anyone). The filename must fit in 8.3.
+ *
+ * If @dst is %NULL, nothing is copied.
+ *
+ * Return: The size of the filesystem in bytes
+ */
+static size_t create_fat(void *dst, size_t size, const char *filename,
+ size_t *data_offset)
+{
+ u16 boot_sector = 0;
+ u16 fat_sector = 1;
+ u32 root_sector = 2;
+ u32 file_sector = 3;
+
+ u16 sector_size = 512;
+ u32 file_sectors = (size + sector_size - 1) / sector_size;
+ u32 sectors = file_sector + file_sectors;
+
+ char *ext;
+ size_t filename_len, ext_len;
+ int i;
+
+ struct boot_sector *bs = dst + boot_sector * sector_size;
+ struct volume_info *vi = (void *)(bs + 1);
+ __le32 *fat = dst + fat_sector * sector_size;
+ struct dir_entry *dirent = dst + root_sector * sector_size;
+
+ /* Make sure we fit in the FAT */
+ if (sectors > sector_size / sizeof(u32))
+ return 0;
+
+ ext = strchr(filename, '.');
+ if (ext) {
+ filename_len = ext - filename;
+ ext++;
+ ext_len = strlen(ext);
+ } else {
+ filename_len = strlen(filename);
+ ext_len = 0;
+ }
+
+ if (filename_len > 8 || ext_len > 3)
+ return 0;
+
+ if (data_offset)
+ *data_offset = file_sector * sector_size;
+
+ if (!dst)
+ goto out;
+
+ bs->sector_size[0] = sector_size & 0xff;
+ bs->sector_size[1] = sector_size >> 8;
+ bs->cluster_size = 1;
+ bs->reserved = cpu_to_le16(fat_sector);
+ bs->fats = 1;
+ bs->media = 0xf8;
+ bs->total_sect = cpu_to_le32(sectors);
+ bs->fat32_length = cpu_to_le32(1);
+ bs->root_cluster = cpu_to_le32(root_sector);
+
+ vi->ext_boot_sign = 0x29;
+ memcpy(vi->fs_type, "FAT32 ", sizeof(vi->fs_type));
+
+ memcpy(dst + 0x1fe, "\x55\xAA", 2);
+
+ fat[0] = cpu_to_le32(0x0ffffff8);
+ fat[1] = cpu_to_le32(0x0fffffff);
+ fat[2] = cpu_to_le32(0x0ffffff8);
+ for (i = file_sector; file_sectors > 1; file_sectors--, i++)
+ fat[i] = cpu_to_le32(i + 1);
+ fat[i] = cpu_to_le32(0x0ffffff8);
+
+ for (i = 0; i < sizeof(dirent->nameext.name); i++) {
+ if (i < filename_len)
+ dirent->nameext.name[i] = toupper(filename[i]);
+ else
+ dirent->nameext.name[i] = ' ';
+ }
+
+ for (i = 0; i < sizeof(dirent->nameext.ext); i++) {
+ if (i < ext_len)
+ dirent->nameext.ext[i] = toupper(ext[i]);
+ else
+ dirent->nameext.ext[i] = ' ';
+ }
+
+ dirent->start = cpu_to_le16(file_sector);
+ dirent->size = cpu_to_le32(size);
+
+out:
+ return sectors * sector_size;
+}
+
+typedef size_t (*create_fs_t)(void *, size_t, const char *, size_t *);
+
+static int spl_test_fs(struct unit_test_state *uts, const char *test_name,
+ create_fs_t create)
+{
+ const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME;
+ struct blk_desc *dev_desc;
+ char *data_write, *data_read;
+ void *fs;
+ size_t fs_size, fs_data, fs_blocks, data_size = SPL_TEST_DATA_SIZE;
+ loff_t actread;
+
+ fs_size = create(NULL, data_size, filename, &fs_data);
+ ut_assert(fs_size);
+ fs = calloc(fs_size, 1);
+ ut_assertnonnull(fs);
+
+ data_write = fs + fs_data;
+ generate_data(data_write, data_size, test_name);
+ ut_asserteq(fs_size, create(fs, data_size, filename, NULL));
+
+ dev_desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0);
+ ut_assertnonnull(dev_desc);
+ ut_asserteq(512, dev_desc->blksz);
+ fs_blocks = fs_size / dev_desc->blksz;
+ ut_asserteq(fs_blocks, blk_dwrite(dev_desc, 0, fs_blocks, fs));
+
+ /* We have to use malloc so we can call virt_to_phys */
+ data_read = malloc_cache_aligned(data_size);
+ ut_assertnonnull(data_read);
+ ut_assertok(fs_set_blk_dev_with_part(dev_desc, 0));
+ ut_assertok(fs_read("/" CONFIG_SPL_FS_LOAD_PAYLOAD_NAME,
+ virt_to_phys(data_read), 0, data_size, &actread));
+ ut_asserteq(data_size, actread);
+ ut_asserteq_mem(data_write, data_read, data_size);
+
+ free(data_read);
+ free(fs);
+ return 0;
+}
+
+static int spl_test_ext(struct unit_test_state *uts)
+{
+ return spl_test_fs(uts, __func__, create_ext2);
+}
+SPL_TEST(spl_test_ext, DM_FLAGS);
+
+static int spl_test_fat(struct unit_test_state *uts)
+{
+ spl_fat_force_reregister();
+ return spl_test_fs(uts, __func__, create_fat);
+}
+SPL_TEST(spl_test_fat, DM_FLAGS);
+
+static bool spl_mmc_raw;
+
+u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
+{
+ return spl_mmc_raw ? MMCSD_MODE_RAW : MMCSD_MODE_FS;
+}
+
+static int spl_test_mmc_fs(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type, create_fs_t create_fs,
+ bool blk_mode)
+{
+ const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME;
+ struct blk_desc *dev_desc;
+ size_t fs_size, fs_data, img_size, img_data,
+ plain_size = SPL_TEST_DATA_SIZE;
+ struct spl_image_info info_write = {
+ .name = test_name,
+ .size = type == LEGACY_LZMA ? lzma_compressed_size :
+ plain_size,
+ }, info_read = { };
+ struct disk_partition part = {
+ .start = 1,
+ .sys_ind = 0x83,
+ };
+ struct spl_image_loader *loader =
+ SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_MMC1, spl_mmc_load_image);
+ struct spl_boot_device bootdev = {
+ .boot_device = loader->boot_device,
+ };
+ void *fs;
+ char *data, *plain;
+
+ img_size = create_image(NULL, type, &info_write, &img_data);
+ ut_assert(img_size);
+ fs_size = create_fs(NULL, img_size, filename, &fs_data);
+ ut_assert(fs_size);
+ fs = calloc(fs_size, 1);
+ ut_assertnonnull(fs);
+
+ data = fs + fs_data + img_data;
+ if (type == LEGACY_LZMA) {
+ plain = malloc(plain_size);
+ ut_assertnonnull(plain);
+ generate_data(plain, plain_size, "lzma");
+ memcpy(data, lzma_compressed, lzma_compressed_size);
+ } else {
+ plain = data;
+ generate_data(plain, plain_size, test_name);
+ }
+ ut_asserteq(img_size, create_image(fs + fs_data, type, &info_write,
+ NULL));
+ ut_asserteq(fs_size, create_fs(fs, img_size, filename, NULL));
+
+ dev_desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0);
+ ut_assertnonnull(dev_desc);
+
+ ut_asserteq(512, dev_desc->blksz);
+ part.size = fs_size / dev_desc->blksz;
+ ut_assertok(write_mbr_partitions(dev_desc, &part, 1, 0));
+ ut_asserteq(part.size, blk_dwrite(dev_desc, part.start, part.size, fs));
+
+ spl_mmc_raw = false;
+ if (blk_mode)
+ ut_assertok(spl_blk_load_image(&info_read, &bootdev, UCLASS_MMC,
+ 0, 1));
+ else
+ ut_assertok(loader->load_image(&info_read, &bootdev));
+ if (check_image_info(uts, &info_write, &info_read))
+ return CMD_RET_FAILURE;
+ if (type == LEGACY_LZMA)
+ ut_asserteq(plain_size, info_read.size);
+ ut_asserteq_mem(plain, phys_to_virt(info_write.load_addr), plain_size);
+
+ if (type == LEGACY_LZMA)
+ free(plain);
+ free(fs);
+ return 0;
+}
+
+static int spl_test_blk(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type)
+{
+ spl_fat_force_reregister();
+ if (spl_test_mmc_fs(uts, test_name, type, create_fat, true))
+ return CMD_RET_FAILURE;
+
+ return spl_test_mmc_fs(uts, test_name, type, create_ext2, true);
+}
+SPL_IMG_TEST(spl_test_blk, LEGACY, DM_FLAGS);
+SPL_IMG_TEST(spl_test_blk, LEGACY_LZMA, DM_FLAGS);
+SPL_IMG_TEST(spl_test_blk, IMX8, DM_FLAGS);
+SPL_IMG_TEST(spl_test_blk, FIT_EXTERNAL, DM_FLAGS);
+SPL_IMG_TEST(spl_test_blk, FIT_INTERNAL, DM_FLAGS);
+
+static int spl_test_mmc_write_image(struct unit_test_state *uts, void *img,
+ size_t img_size)
+{
+ struct blk_desc *dev_desc;
+ size_t img_blocks;
+
+ dev_desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0);
+ ut_assertnonnull(dev_desc);
+
+ img_blocks = DIV_ROUND_UP(img_size, dev_desc->blksz);
+ ut_asserteq(img_blocks, blk_dwrite(dev_desc,
+ CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR,
+ img_blocks, img));
+
+ spl_mmc_raw = true;
+ return 0;
+}
+
+static int spl_test_mmc(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type)
+{
+ spl_mmc_clear_cache();
+ spl_fat_force_reregister();
+
+ if (spl_test_mmc_fs(uts, test_name, type, create_ext2, false))
+ return CMD_RET_FAILURE;
+
+ if (spl_test_mmc_fs(uts, test_name, type, create_fat, false))
+ return CMD_RET_FAILURE;
+
+ return do_spl_test_load(uts, test_name, type,
+ SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_MMC1,
+ spl_mmc_load_image),
+ spl_test_mmc_write_image);
+}
+SPL_IMG_TEST(spl_test_mmc, LEGACY, DM_FLAGS);
+SPL_IMG_TEST(spl_test_mmc, LEGACY_LZMA, DM_FLAGS);
+SPL_IMG_TEST(spl_test_mmc, IMX8, DM_FLAGS);
+SPL_IMG_TEST(spl_test_mmc, FIT_EXTERNAL, DM_FLAGS);
+SPL_IMG_TEST(spl_test_mmc, FIT_INTERNAL, DM_FLAGS);
diff --git a/test/image/spl_load_nand.c b/test/image/spl_load_nand.c
new file mode 100644
index 00000000000..ec242207948
--- /dev/null
+++ b/test/image/spl_load_nand.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <nand.h>
+#include <spl.h>
+#include <test/spl.h>
+#include <test/ut.h>
+
+uint32_t spl_nand_get_uboot_raw_page(void);
+
+static int spl_test_nand_write_image(struct unit_test_state *uts, void *img,
+ size_t img_size)
+{
+ uint32_t off = spl_nand_get_uboot_raw_page();
+ struct mtd_info *mtd;
+ struct erase_info erase = { };
+ size_t length;
+
+ nand_reinit();
+ mtd = get_nand_dev_by_index(0);
+ ut_assertnonnull(mtd);
+
+ /* Mark the first block as bad to test that it gets skipped */
+ ut_assertok(mtd_block_markbad(mtd, off & ~mtd->erasesize_mask));
+ off += mtd->erasesize;
+
+ erase.mtd = mtd;
+ erase.len = img_size + (off & mtd->erasesize_mask);
+ erase.len += mtd->erasesize_mask;
+ erase.len &= ~mtd->erasesize_mask;
+ erase.addr = off & ~mtd->erasesize_mask;
+ erase.scrub = 1;
+ ut_assertok(mtd_erase(mtd, &erase));
+
+ ut_assertok(mtd_write(mtd, off, img_size, &length, img));
+
+ return 0;
+}
+
+static int spl_test_nand(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type)
+{
+ return do_spl_test_load(uts, test_name, type,
+ SPL_LOAD_IMAGE_GET(1, BOOT_DEVICE_NAND,
+ spl_nand_load_image),
+ spl_test_nand_write_image);
+}
+SPL_IMG_TEST(spl_test_nand, LEGACY, DM_FLAGS);
+SPL_IMG_TEST(spl_test_nand, LEGACY_LZMA, DM_FLAGS);
+SPL_IMG_TEST(spl_test_nand, IMX8, DM_FLAGS);
+SPL_IMG_TEST(spl_test_nand, FIT_INTERNAL, DM_FLAGS);
+#if !IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL)
+SPL_IMG_TEST(spl_test_nand, FIT_EXTERNAL, DM_FLAGS);
+#endif
diff --git a/test/image/spl_load_net.c b/test/image/spl_load_net.c
new file mode 100644
index 00000000000..9d067a7a592
--- /dev/null
+++ b/test/image/spl_load_net.c
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spl.h>
+#include <test/spl.h>
+#include <asm/eth.h>
+#include <test/ut.h>
+#include "../../net/bootp.h"
+
+/*
+ * sandbox_eth_bootp_req_to_reply()
+ *
+ * Check if a BOOTP request was sent. If so, inject a reply
+ *
+ * returns 0 if injected, -EAGAIN if not
+ */
+static int sandbox_eth_bootp_req_to_reply(struct udevice *dev, void *packet,
+ unsigned int len)
+{
+ struct eth_sandbox_priv *priv = dev_get_priv(dev);
+ struct ethernet_hdr *eth = packet;
+ struct ip_udp_hdr *ip;
+ struct bootp_hdr *bp;
+ struct ethernet_hdr *eth_recv;
+ struct ip_udp_hdr *ipr;
+ struct bootp_hdr *bpr;
+
+ if (ntohs(eth->et_protlen) != PROT_IP)
+ return -EAGAIN;
+
+ ip = packet + ETHER_HDR_SIZE;
+ if (ip->ip_p != IPPROTO_UDP)
+ return -EAGAIN;
+
+ if (ntohs(ip->udp_dst) != PORT_BOOTPS)
+ return -EAGAIN;
+
+ bp = (void *)ip + IP_UDP_HDR_SIZE;
+ if (bp->bp_op != OP_BOOTREQUEST)
+ return -EAGAIN;
+
+ /* Don't allow the buffer to overrun */
+ if (priv->recv_packets >= PKTBUFSRX)
+ return 0;
+
+ /* reply to the request */
+ eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets];
+ memcpy(eth_recv, packet, len);
+ ipr = (void *)eth_recv + ETHER_HDR_SIZE;
+ bpr = (void *)ipr + IP_UDP_HDR_SIZE;
+ memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
+ memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN);
+ ipr->ip_sum = 0;
+ ipr->ip_off = 0;
+ net_write_ip(&ipr->ip_dst, net_ip);
+ net_write_ip(&ipr->ip_src, priv->fake_host_ipaddr);
+ ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE);
+ ipr->udp_src = ip->udp_dst;
+ ipr->udp_dst = ip->udp_src;
+
+ bpr->bp_op = OP_BOOTREPLY;
+ net_write_ip(&bpr->bp_yiaddr, net_ip);
+ net_write_ip(&bpr->bp_siaddr, priv->fake_host_ipaddr);
+ copy_filename(bpr->bp_file, CONFIG_BOOTFILE, sizeof(CONFIG_BOOTFILE));
+ memset(&bpr->bp_vend, 0, sizeof(bpr->bp_vend));
+
+ priv->recv_packet_length[priv->recv_packets] = len;
+ ++priv->recv_packets;
+
+ return 0;
+}
+
+struct spl_test_net_priv {
+ struct unit_test_state *uts;
+ void *img;
+ size_t img_size;
+ u16 port;
+};
+
+/* Well known TFTP port # */
+#define TFTP_PORT 69
+/* Transaction ID, chosen at random */
+#define TFTP_TID 21313
+
+/*
+ * TFTP operations.
+ */
+#define TFTP_RRQ 1
+#define TFTP_DATA 3
+#define TFTP_ACK 4
+
+/* default TFTP block size */
+#define TFTP_BLOCK_SIZE 512
+
+struct tftp_hdr {
+ u16 opcode;
+ u16 block;
+};
+
+#define TFTP_HDR_SIZE sizeof(struct tftp_hdr)
+
+/*
+ * sandbox_eth_tftp_req_to_reply()
+ *
+ * Check if a TFTP request was sent. If so, inject a reply. We don't support
+ * options, and we don't check for rollover, so we are limited files of less
+ * than 32M.
+ *
+ * returns 0 if injected, -EAGAIN if not
+ */
+static int sandbox_eth_tftp_req_to_reply(struct udevice *dev, void *packet,
+ unsigned int len)
+{
+ struct eth_sandbox_priv *priv = dev_get_priv(dev);
+ struct spl_test_net_priv *test_priv = priv->priv;
+ struct ethernet_hdr *eth = packet;
+ struct ip_udp_hdr *ip;
+ struct tftp_hdr *tftp;
+ struct ethernet_hdr *eth_recv;
+ struct ip_udp_hdr *ipr;
+ struct tftp_hdr *tftpr;
+ size_t size;
+ u16 block;
+
+ if (ntohs(eth->et_protlen) != PROT_IP)
+ return -EAGAIN;
+
+ ip = packet + ETHER_HDR_SIZE;
+ if (ip->ip_p != IPPROTO_UDP)
+ return -EAGAIN;
+
+ if (ntohs(ip->udp_dst) == TFTP_PORT) {
+ tftp = (void *)ip + IP_UDP_HDR_SIZE;
+ if (htons(tftp->opcode) != TFTP_RRQ)
+ return -EAGAIN;
+
+ block = 0;
+ } else if (ntohs(ip->udp_dst) == TFTP_TID) {
+ tftp = (void *)ip + IP_UDP_HDR_SIZE;
+ if (htons(tftp->opcode) != TFTP_ACK)
+ return -EAGAIN;
+
+ block = htons(tftp->block);
+ } else {
+ return -EAGAIN;
+ }
+
+ if (block * TFTP_BLOCK_SIZE > test_priv->img_size)
+ return 0;
+
+ size = min(test_priv->img_size - block * TFTP_BLOCK_SIZE,
+ (size_t)TFTP_BLOCK_SIZE);
+
+ /* Don't allow the buffer to overrun */
+ if (priv->recv_packets >= PKTBUFSRX)
+ return 0;
+
+ /* reply to the request */
+ eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets];
+ memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN);
+ memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN);
+ eth_recv->et_protlen = htons(PROT_IP);
+
+ ipr = (void *)eth_recv + ETHER_HDR_SIZE;
+ ipr->ip_hl_v = 0x45;
+ ipr->ip_len = htons(IP_UDP_HDR_SIZE + TFTP_HDR_SIZE + size);
+ ipr->ip_off = htons(IP_FLAGS_DFRAG);
+ ipr->ip_ttl = 255;
+ ipr->ip_p = IPPROTO_UDP;
+ ipr->ip_sum = 0;
+ net_copy_ip(&ipr->ip_dst, &ip->ip_src);
+ net_copy_ip(&ipr->ip_src, &ip->ip_dst);
+ ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE);
+
+ ipr->udp_src = htons(TFTP_TID);
+ ipr->udp_dst = ip->udp_src;
+ ipr->udp_len = htons(UDP_HDR_SIZE + TFTP_HDR_SIZE + size);
+ ipr->udp_xsum = 0;
+
+ tftpr = (void *)ipr + IP_UDP_HDR_SIZE;
+ tftpr->opcode = htons(TFTP_DATA);
+ tftpr->block = htons(block + 1);
+ memcpy((void *)tftpr + TFTP_HDR_SIZE,
+ test_priv->img + block * TFTP_BLOCK_SIZE, size);
+
+ priv->recv_packet_length[priv->recv_packets] =
+ ETHER_HDR_SIZE + IP_UDP_HDR_SIZE + TFTP_HDR_SIZE + size;
+ ++priv->recv_packets;
+
+ return 0;
+}
+
+static int spl_net_handler(struct udevice *dev, void *packet,
+ unsigned int len)
+{
+ struct eth_sandbox_priv *priv = dev_get_priv(dev);
+ int old_packets = priv->recv_packets;
+
+ priv->fake_host_ipaddr = string_to_ip("1.1.2.4");
+ net_ip = string_to_ip("1.1.2.2");
+
+ sandbox_eth_arp_req_to_reply(dev, packet, len);
+ sandbox_eth_bootp_req_to_reply(dev, packet, len);
+ sandbox_eth_tftp_req_to_reply(dev, packet, len);
+
+ if (old_packets == priv->recv_packets)
+ return 0;
+
+ return 0;
+}
+
+static int spl_test_net_write_image(struct unit_test_state *uts, void *img,
+ size_t img_size)
+{
+ struct spl_test_net_priv *test_priv = malloc(sizeof(*test_priv));
+
+ ut_assertnonnull(test_priv);
+ test_priv->uts = uts;
+ test_priv->img = img;
+ test_priv->img_size = img_size;
+
+ sandbox_eth_set_tx_handler(0, spl_net_handler);
+ sandbox_eth_set_priv(0, test_priv);
+ return 0;
+}
+
+static int spl_test_net(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type)
+{
+ struct eth_sandbox_priv *priv;
+ struct udevice *dev;
+ int ret;
+
+ net_server_ip = string_to_ip("1.1.2.4");
+ ret = do_spl_test_load(uts, test_name, type,
+ SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_CPGMAC,
+ spl_net_load_image_cpgmac),
+ spl_test_net_write_image);
+
+ sandbox_eth_set_tx_handler(0, NULL);
+ ut_assertok(uclass_get_device(UCLASS_ETH, 0, &dev));
+ priv = dev_get_priv(dev);
+ free(priv->priv);
+ return ret;
+}
+SPL_IMG_TEST(spl_test_net, LEGACY, DM_FLAGS);
+SPL_IMG_TEST(spl_test_net, LEGACY_LZMA, DM_FLAGS);
+SPL_IMG_TEST(spl_test_net, IMX8, DM_FLAGS);
+SPL_IMG_TEST(spl_test_net, FIT_INTERNAL, DM_FLAGS);
+SPL_IMG_TEST(spl_test_net, FIT_EXTERNAL, DM_FLAGS);
diff --git a/test/image/spl_load_nor.c b/test/image/spl_load_nor.c
new file mode 100644
index 00000000000..de5686343b9
--- /dev/null
+++ b/test/image/spl_load_nor.c
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spl.h>
+#include <asm/io.h>
+#include <test/spl.h>
+#include <test/ut.h>
+
+static void *spl_test_nor_base;
+
+unsigned long spl_nor_get_uboot_base(void)
+{
+ return virt_to_phys(spl_test_nor_base);
+}
+
+static int spl_test_nor_write_image(struct unit_test_state *uts, void *img,
+ size_t img_size)
+{
+ spl_test_nor_base = img;
+ return 0;
+}
+
+static int spl_test_nor(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type)
+{
+ return do_spl_test_load(uts, test_name, type,
+ SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_NOR,
+ spl_nor_load_image),
+ spl_test_nor_write_image);
+}
+SPL_IMG_TEST(spl_test_nor, LEGACY, 0);
+SPL_IMG_TEST(spl_test_nor, LEGACY_LZMA, 0);
+SPL_IMG_TEST(spl_test_nor, IMX8, 0);
+SPL_IMG_TEST(spl_test_nor, FIT_INTERNAL, 0);
+#if !IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL)
+SPL_IMG_TEST(spl_test_nor, FIT_EXTERNAL, 0);
+#endif
diff --git a/test/image/spl_load_os.c b/test/image/spl_load_os.c
new file mode 100644
index 00000000000..26228a8a4a9
--- /dev/null
+++ b/test/image/spl_load_os.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <image.h>
+#include <os.h>
+#include <spl.h>
+#include <test/spl.h>
+#include <test/ut.h>
+
+/* Context used for this test */
+struct text_ctx {
+ int fd;
+};
+
+static ulong read_fit_image(struct spl_load_info *load, ulong offset,
+ ulong size, void *buf)
+{
+ struct text_ctx *text_ctx = load->priv;
+ off_t ret;
+ ssize_t res;
+
+ ret = os_lseek(text_ctx->fd, offset, OS_SEEK_SET);
+ if (ret != offset) {
+ printf("Failed to seek to %zx, got %zx (errno=%d)\n", offset,
+ ret, errno);
+ return 0;
+ }
+
+ res = os_read(text_ctx->fd, buf, size);
+ if (res == -1) {
+ printf("Failed to read %lx bytes, got %ld (errno=%d)\n",
+ size, res, errno);
+ return 0;
+ }
+
+ return size;
+}
+
+static int spl_test_load(struct unit_test_state *uts)
+{
+ struct spl_image_info image;
+ struct legacy_img_hdr *header;
+ struct text_ctx text_ctx;
+ struct spl_load_info load;
+ char fname[256];
+ int ret;
+ int fd;
+
+ memset(&load, '\0', sizeof(load));
+ spl_set_bl_len(&load, 512);
+ load.read = read_fit_image;
+
+ ret = sandbox_find_next_phase(fname, sizeof(fname), true);
+ if (ret)
+ ut_assertf(0, "%s not found, error %d\n", fname, ret);
+
+ header = spl_get_load_buffer(-sizeof(*header), sizeof(*header));
+
+ fd = os_open(fname, OS_O_RDONLY);
+ ut_assert(fd >= 0);
+ ut_asserteq(512, os_read(fd, header, 512));
+ text_ctx.fd = fd;
+
+ load.priv = &text_ctx;
+
+ ut_assertok(spl_load_simple_fit(&image, &load, 0, header));
+
+ return 0;
+}
+SPL_TEST(spl_test_load, 0);
diff --git a/test/image/spl_load_spi.c b/test/image/spl_load_spi.c
new file mode 100644
index 00000000000..54a95465e23
--- /dev/null
+++ b/test/image/spl_load_spi.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spi_flash.h>
+#include <spl.h>
+#include <test/spl.h>
+#include <test/ut.h>
+
+static int spl_test_spi_write_image(struct unit_test_state *uts, void *img,
+ size_t img_size)
+{
+ struct spi_flash *flash;
+
+ flash = spi_flash_probe(spl_spi_boot_bus(), spl_spi_boot_cs(),
+ CONFIG_SF_DEFAULT_SPEED,
+ CONFIG_SF_DEFAULT_MODE);
+ ut_assertnonnull(flash);
+ ut_assertok(spi_flash_write(flash, spl_spi_get_uboot_offs(flash),
+ img_size, img));
+
+ return 0;
+}
+
+static int spl_test_spi(struct unit_test_state *uts, const char *test_name,
+ enum spl_test_image type)
+{
+ return do_spl_test_load(uts, test_name, type,
+ SPL_LOAD_IMAGE_GET(1, BOOT_DEVICE_SPI,
+ spl_spi_load_image),
+ spl_test_spi_write_image);
+}
+SPL_IMG_TEST(spl_test_spi, LEGACY, DM_FLAGS);
+SPL_IMG_TEST(spl_test_spi, LEGACY_LZMA, DM_FLAGS);
+SPL_IMG_TEST(spl_test_spi, IMX8, DM_FLAGS);
+SPL_IMG_TEST(spl_test_spi, FIT_INTERNAL, DM_FLAGS);
+#if !IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL)
+SPL_IMG_TEST(spl_test_spi, FIT_EXTERNAL, DM_FLAGS);
+#endif
diff --git a/test/lib/kconfig.c b/test/lib/kconfig.c
index 76225ba8ffa..3914f699659 100644
--- a/test/lib/kconfig.c
+++ b/test/lib/kconfig.c
@@ -22,9 +22,9 @@ static int lib_test_is_enabled(struct unit_test_state *uts)
ut_asserteq(0, CONFIG_IS_ENABLED(OF_PLATDATA));
ut_asserteq(0, CONFIG_IS_ENABLED(_UNDEFINED));
- ut_asserteq(0xc000,
+ ut_asserteq(0xb000,
IF_ENABLED_INT(CONFIG_BLOBLIST_FIXED, CONFIG_BLOBLIST_ADDR));
- ut_asserteq(0xc000,
+ ut_asserteq(0xb000,
CONFIG_IF_ENABLED_INT(BLOBLIST_FIXED, BLOBLIST_ADDR));
/*
diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index 16288750358..15c68ce3961 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -451,12 +451,23 @@ static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts)
ut_asserteq(ret, 0);
ASSERT_LMB(&lmb, ram, ram_size, 2, 0x40010000, 0x10000,
0x40030000, 0x10000, 0, 0);
- /* allocate 2nd region */
+ /* allocate 2nd region , This should coalesced all region into one */
ret = lmb_reserve(&lmb, 0x40020000, 0x10000);
ut_assert(ret >= 0);
ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40010000, 0x30000,
0, 0, 0, 0);
+ /* allocate 2nd region, which should be added as first region */
+ ret = lmb_reserve(&lmb, 0x40000000, 0x8000);
+ ut_assert(ret >= 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 2, 0x40000000, 0x8000,
+ 0x40010000, 0x30000, 0, 0);
+
+ /* allocate 3rd region, coalesce with first and overlap with second */
+ ret = lmb_reserve(&lmb, 0x40008000, 0x10000);
+ ut_assert(ret >= 0);
+ ASSERT_LMB(&lmb, ram, ram_size, 1, 0x40000000, 0x40000,
+ 0, 0, 0, 0);
return 0;
}
diff --git a/test/py/tests/fs_helper.py b/test/py/tests/fs_helper.py
index 9882ddb1daa..380f4c4dca3 100644
--- a/test/py/tests/fs_helper.py
+++ b/test/py/tests/fs_helper.py
@@ -9,7 +9,7 @@ import re
import os
from subprocess import call, check_call, check_output, CalledProcessError
-def mk_fs(config, fs_type, size, prefix):
+def mk_fs(config, fs_type, size, prefix, size_gran = 0x100000):
"""Create a file system volume
Args:
@@ -17,6 +17,7 @@ def mk_fs(config, fs_type, size, prefix):
fs_type (str): File system type, e.g. 'ext4'
size (int): Size of file system in bytes
prefix (str): Prefix string of volume's file name
+ size_gran (int): Size granularity of file system image in bytes
Raises:
CalledProcessError: if any error occurs when creating the filesystem
@@ -24,7 +25,9 @@ def mk_fs(config, fs_type, size, prefix):
fs_img = f'{prefix}.{fs_type}.img'
fs_img = os.path.join(config.persistent_data_dir, fs_img)
- if fs_type == 'fat16':
+ if fs_type == 'fat12':
+ mkfs_opt = '-F 12'
+ elif fs_type == 'fat16':
mkfs_opt = '-F 16'
elif fs_type == 'fat32':
mkfs_opt = '-F 32'
@@ -36,7 +39,7 @@ def mk_fs(config, fs_type, size, prefix):
else:
fs_lnxtype = fs_type
- count = (size + 0x100000 - 1) // 0x100000
+ count = (size + size_gran - 1) // size_gran
# Some distributions do not add /sbin to the default PATH, where mkfs lives
if '/sbin' not in os.environ["PATH"].split(os.pathsep):
@@ -44,7 +47,7 @@ def mk_fs(config, fs_type, size, prefix):
try:
check_call(f'rm -f {fs_img}', shell=True)
- check_call(f'dd if=/dev/zero of={fs_img} bs=1M count={count}',
+ check_call(f'dd if=/dev/zero of={fs_img} bs={size_gran} count={count}',
shell=True)
check_call(f'mkfs.{fs_lnxtype} {mkfs_opt} {fs_img}', shell=True)
if fs_type == 'ext4':
diff --git a/test/py/tests/test_efi_secboot/test_signed.py b/test/py/tests/test_efi_secboot/test_signed.py
index ca52e853d8f..2f862a259ad 100644
--- a/test/py/tests/test_efi_secboot/test_signed.py
+++ b/test/py/tests/test_efi_secboot/test_signed.py
@@ -29,7 +29,7 @@ class TestEfiSignedImage(object):
output = u_boot_console.run_command_list([
'host bind 0 %s' % disk_img,
'efidebug boot add -b 1 HELLO1 host 0:1 /helloworld.efi.signed -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'bootefi bootmgr'])
assert 'Hello, world!' in ''.join(output)
@@ -37,7 +37,7 @@ class TestEfiSignedImage(object):
# Test Case 1b, run unsigned image if no PK
output = u_boot_console.run_command_list([
'efidebug boot add -b 2 HELLO2 host 0:1 /helloworld.efi -s ""',
- 'efidebug boot next 2',
+ 'efidebug boot order 2',
'bootefi bootmgr'])
assert 'Hello, world!' in ''.join(output)
@@ -59,13 +59,13 @@ class TestEfiSignedImage(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO1 host 0:1 /helloworld.efi.signed -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert('\'HELLO1\' failed' in ''.join(output))
assert('efi_start_image() returned: 26' in ''.join(output))
output = u_boot_console.run_command_list([
'efidebug boot add -b 2 HELLO2 host 0:1 /helloworld.efi -s ""',
- 'efidebug boot next 2',
+ 'efidebug boot order 2',
'efidebug test bootmgr'])
assert '\'HELLO2\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
@@ -77,12 +77,12 @@ class TestEfiSignedImage(object):
'setenv -e -nv -bs -rt -at -i 4000000:$filesize db'])
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot next 2',
+ 'efidebug boot order 2',
'efidebug test bootmgr'])
assert '\'HELLO2\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'bootefi bootmgr'])
assert 'Hello, world!' in ''.join(output)
@@ -105,7 +105,7 @@ class TestEfiSignedImage(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
@@ -117,7 +117,7 @@ class TestEfiSignedImage(object):
'setenv -e -nv -bs -rt -at -i 4000000:$filesize db'])
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
@@ -143,7 +143,7 @@ class TestEfiSignedImage(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
@@ -170,7 +170,7 @@ class TestEfiSignedImage(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed_2sigs -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert 'Hello, world!' in ''.join(output)
@@ -181,7 +181,7 @@ class TestEfiSignedImage(object):
'setenv -e -nv -bs -rt -at -a -i 4000000:$filesize db'])
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert 'Hello, world!' in ''.join(output)
@@ -193,7 +193,7 @@ class TestEfiSignedImage(object):
'setenv -e -nv -bs -rt -at -i 4000000:$filesize dbx'])
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
@@ -205,7 +205,7 @@ class TestEfiSignedImage(object):
'setenv -e -nv -bs -rt -at -a -i 4000000:$filesize dbx'])
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
@@ -230,7 +230,7 @@ class TestEfiSignedImage(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed_2sigs -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
@@ -254,7 +254,7 @@ class TestEfiSignedImage(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'bootefi bootmgr'])
assert 'Hello, world!' in ''.join(output)
@@ -265,7 +265,7 @@ class TestEfiSignedImage(object):
'setenv -e -nv -bs -rt -at -i 4000000:$filesize dbx'])
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
@@ -279,7 +279,7 @@ class TestEfiSignedImage(object):
'setenv -e -nv -bs -rt -at -i 4000000:$filesize dbx'])
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
@@ -307,7 +307,7 @@ class TestEfiSignedImage(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed_2sigs -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
@@ -330,7 +330,7 @@ class TestEfiSignedImage(object):
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi.signed_2sigs -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
@@ -349,7 +349,7 @@ class TestEfiSignedImage(object):
output = u_boot_console.run_command_list([
'host bind 0 %s' % disk_img,
'efidebug boot add -b 1 HELLO1 host 0:1 /helloworld_forged.efi.signed -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert('hELLO, world!' in ''.join(output))
@@ -364,7 +364,7 @@ class TestEfiSignedImage(object):
'setenv -e -nv -bs -rt -at -i 4000000:$filesize PK'])
assert 'Failed to set EFI variable' not in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert(not 'hELLO, world!' in ''.join(output))
assert('\'HELLO1\' failed' in ''.join(output))
diff --git a/test/py/tests/test_efi_secboot/test_signed_intca.py b/test/py/tests/test_efi_secboot/test_signed_intca.py
index d8d599d22f3..8d9a5f3e7fe 100644
--- a/test/py/tests/test_efi_secboot/test_signed_intca.py
+++ b/test/py/tests/test_efi_secboot/test_signed_intca.py
@@ -40,7 +40,7 @@ class TestEfiSignedImageIntca(object):
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO_a host 0:1 /helloworld.efi.signed_a -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert '\'HELLO_a\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
@@ -49,7 +49,7 @@ class TestEfiSignedImageIntca(object):
# Test Case 1b, signed and authenticated by root CA
output = u_boot_console.run_command_list([
'efidebug boot add -b 2 HELLO_ab host 0:1 /helloworld.efi.signed_ab -s ""',
- 'efidebug boot next 2',
+ 'efidebug boot order 2',
'bootefi bootmgr'])
assert 'Hello, world!' in ''.join(output)
@@ -71,7 +71,7 @@ class TestEfiSignedImageIntca(object):
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO_abc host 0:1 /helloworld.efi.signed_abc -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert '\'HELLO_abc\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
@@ -81,7 +81,7 @@ class TestEfiSignedImageIntca(object):
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 db_b.auth',
'setenv -e -nv -bs -rt -at -i 4000000:$filesize db',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert '\'HELLO_abc\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
@@ -91,7 +91,7 @@ class TestEfiSignedImageIntca(object):
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 db_c.auth',
'setenv -e -nv -bs -rt -at -i 4000000:$filesize db',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert 'Hello, world!' in ''.join(output)
@@ -117,7 +117,7 @@ class TestEfiSignedImageIntca(object):
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO_abc host 0:1 /helloworld.efi.signed_abc -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert 'Hello, world!' in ''.join(output)
# Or,
@@ -129,7 +129,7 @@ class TestEfiSignedImageIntca(object):
output = u_boot_console.run_command_list([
'fatload host 0:1 4000000 dbx_c.auth',
'setenv -e -nv -bs -rt -at -i 4000000:$filesize dbx',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert '\'HELLO_abc\' failed' in ''.join(output)
assert 'efi_start_image() returned: 26' in ''.join(output)
diff --git a/test/py/tests/test_efi_secboot/test_unsigned.py b/test/py/tests/test_efi_secboot/test_unsigned.py
index df63f0df081..7c078f220d0 100644
--- a/test/py/tests/test_efi_secboot/test_unsigned.py
+++ b/test/py/tests/test_efi_secboot/test_unsigned.py
@@ -36,11 +36,11 @@ class TestEfiUnsignedImage(object):
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'bootefi bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert 'efi_start_image() returned: 26' in ''.join(output)
assert 'Hello, world!' not in ''.join(output)
@@ -65,7 +65,7 @@ class TestEfiUnsignedImage(object):
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'bootefi bootmgr'])
assert 'Hello, world!' in ''.join(output)
@@ -89,11 +89,11 @@ class TestEfiUnsignedImage(object):
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'bootefi bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert 'efi_start_image() returned: 26' in ''.join(output)
assert 'Hello, world!' not in ''.join(output)
@@ -107,11 +107,11 @@ class TestEfiUnsignedImage(object):
output = u_boot_console.run_command_list([
'efidebug boot add -b 1 HELLO host 0:1 /helloworld.efi -s ""',
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'bootefi bootmgr'])
assert '\'HELLO\' failed' in ''.join(output)
output = u_boot_console.run_command_list([
- 'efidebug boot next 1',
+ 'efidebug boot order 1',
'efidebug test bootmgr'])
assert 'efi_start_image() returned: 26' in ''.join(output)
assert 'Hello, world!' not in ''.join(output)
diff --git a/test/py/tests/test_fs/conftest.py b/test/py/tests/test_fs/conftest.py
index 0d87d180c7b..fdd138d6ee4 100644
--- a/test/py/tests/test_fs/conftest.py
+++ b/test/py/tests/test_fs/conftest.py
@@ -12,9 +12,10 @@ import u_boot_utils as util
from tests import fs_helper
supported_fs_basic = ['fat16', 'fat32', 'ext4']
-supported_fs_ext = ['fat16', 'fat32']
-supported_fs_mkdir = ['fat16', 'fat32']
-supported_fs_unlink = ['fat16', 'fat32']
+supported_fs_ext = ['fat12', 'fat16', 'fat32']
+supported_fs_fat = ['fat12', 'fat16']
+supported_fs_mkdir = ['fat12', 'fat16', 'fat32']
+supported_fs_unlink = ['fat12', 'fat16', 'fat32']
supported_fs_symlink = ['ext4']
#
@@ -49,6 +50,7 @@ def pytest_configure(config):
"""
global supported_fs_basic
global supported_fs_ext
+ global supported_fs_fat
global supported_fs_mkdir
global supported_fs_unlink
global supported_fs_symlink
@@ -61,6 +63,7 @@ def pytest_configure(config):
print('*** FS TYPE modified: %s' % supported_fs)
supported_fs_basic = intersect(supported_fs, supported_fs_basic)
supported_fs_ext = intersect(supported_fs, supported_fs_ext)
+ supported_fs_fat = intersect(supported_fs, supported_fs_fat)
supported_fs_mkdir = intersect(supported_fs, supported_fs_mkdir)
supported_fs_unlink = intersect(supported_fs, supported_fs_unlink)
supported_fs_symlink = intersect(supported_fs, supported_fs_symlink)
@@ -83,6 +86,9 @@ def pytest_generate_tests(metafunc):
if 'fs_obj_ext' in metafunc.fixturenames:
metafunc.parametrize('fs_obj_ext', supported_fs_ext,
indirect=True, scope='module')
+ if 'fs_obj_fat' in metafunc.fixturenames:
+ metafunc.parametrize('fs_obj_fat', supported_fs_fat,
+ indirect=True, scope='module')
if 'fs_obj_mkdir' in metafunc.fixturenames:
metafunc.parametrize('fs_obj_mkdir', supported_fs_mkdir,
indirect=True, scope='module')
@@ -624,3 +630,44 @@ def fs_obj_symlink(request, u_boot_config):
finally:
call('rmdir %s' % mount_dir, shell=True)
call('rm -f %s' % fs_img, shell=True)
+
+#
+# Fixture for fat test
+#
+@pytest.fixture()
+def fs_obj_fat(request, u_boot_config):
+ """Set up a file system to be used in fat test.
+
+ Args:
+ request: Pytest request object.
+ u_boot_config: U-Boot configuration.
+
+ Return:
+ A fixture for fat test, i.e. a duplet of file system type and
+ volume file name.
+ """
+
+ # the maximum size of a FAT12 filesystem resulting in 4084 clusters
+ MAX_FAT12_SIZE = 261695 * 1024
+
+ # the minimum size of a FAT16 filesystem that can be created with
+ # mkfs.vfat resulting in 4087 clusters
+ MIN_FAT16_SIZE = 8208 * 1024
+
+ fs_type = request.param
+ fs_img = ''
+
+ fs_ubtype = fstype_to_ubname(fs_type)
+ check_ubconfig(u_boot_config, fs_ubtype)
+
+ fs_size = MAX_FAT12_SIZE if fs_type == 'fat12' else MIN_FAT16_SIZE
+
+ try:
+ # the volume size depends on the filesystem
+ fs_img = fs_helper.mk_fs(u_boot_config, fs_type, fs_size, f'{fs_size}', 1024)
+ except:
+ pytest.skip('Setup failed for filesystem: ' + fs_type)
+ return
+ else:
+ yield [fs_ubtype, fs_img]
+ call('rm -f %s' % fs_img, shell=True)
diff --git a/test/py/tests/test_fs/test_erofs.py b/test/py/tests/test_fs/test_erofs.py
index 458a52ba79d..87ad8f2d5fd 100644
--- a/test/py/tests/test_fs/test_erofs.py
+++ b/test/py/tests/test_fs/test_erofs.py
@@ -196,6 +196,15 @@ def test_erofs(u_boot_console):
"""
build_dir = u_boot_console.config.build_dir
+ # If the EFI subsystem is enabled and initialized, EFI subsystem tries to
+ # add EFI boot option when the new disk is detected. If there is no EFI
+ # System Partition exists, EFI subsystem outputs error messages and
+ # it ends up with test failure.
+ # Restart U-Boot to clear the previous state.
+ # TODO: Ideally EFI test cases need to be fixed, but it will
+ # increase the number of system reset.
+ u_boot_console.restart_uboot()
+
try:
# setup test environment
make_erofs_image(build_dir)
diff --git a/test/py/tests/test_fs/test_fs_fat.py b/test/py/tests/test_fs/test_fs_fat.py
new file mode 100644
index 00000000000..4009d0b63a3
--- /dev/null
+++ b/test/py/tests/test_fs/test_fs_fat.py
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2023 Weidmüller Interface GmbH & Co. KG
+# Author: Christian Taedcke <christian.taedcke@weidmueller.com>
+#
+# U-Boot File System: FAT Test
+
+"""
+This test verifies fat specific file system behaviour.
+"""
+
+import pytest
+import re
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.slow
+class TestFsFat(object):
+ def test_fs_fat1(self, u_boot_console, fs_obj_fat):
+ """Test that `fstypes` prints a result which includes `sandbox`."""
+ fs_type,fs_img = fs_obj_fat
+ with u_boot_console.log.section('Test Case 1 - fatinfo'):
+ # Test Case 1 - ls
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ 'fatinfo host 0:0'])
+ assert(re.search('Filesystem: %s' % fs_type.upper(), ''.join(output)))
diff --git a/test/py/tests/test_fs/test_squashfs/test_sqfs_ls.py b/test/py/tests/test_fs/test_squashfs/test_sqfs_ls.py
index 527a556ed80..a20a7d1a663 100644
--- a/test/py/tests/test_fs/test_squashfs/test_sqfs_ls.py
+++ b/test/py/tests/test_fs/test_squashfs/test_sqfs_ls.py
@@ -118,6 +118,15 @@ def test_sqfs_ls(u_boot_console):
"""
build_dir = u_boot_console.config.build_dir
+ # If the EFI subsystem is enabled and initialized, EFI subsystem tries to
+ # add EFI boot option when the new disk is detected. If there is no EFI
+ # System Partition exists, EFI subsystem outputs error messages and
+ # it ends up with test failure.
+ # Restart U-Boot to clear the previous state.
+ # TODO: Ideally EFI test cases need to be fixed, but it will
+ # increase the number of system reset.
+ u_boot_console.restart_uboot()
+
# setup test environment
check_mksquashfs_version()
generate_sqfs_src_dir(build_dir)
diff --git a/test/py/tests/test_net.py b/test/py/tests/test_net.py
index cd4b4dc53cb..2495608786d 100644
--- a/test/py/tests/test_net.py
+++ b/test/py/tests/test_net.py
@@ -6,6 +6,8 @@
import pytest
import u_boot_utils
+import uuid
+import datetime
"""
Note: This test relies on boardenv_* containing configuration values to define
@@ -50,6 +52,8 @@ env__net_tftp_readable_file = {
'addr': 0x10000000,
'size': 5058624,
'crc32': 'c2244b26',
+ 'timeout': 50000,
+ 'fnu': 'ubtest-upload.bin',
}
# Details regarding a file that may be read from a NFS server. This variable
@@ -61,6 +65,16 @@ env__net_nfs_readable_file = {
'crc32': 'c2244b26',
}
+# Details regarding a file that may be read from a TFTP server. This variable
+# may be omitted or set to None if PXE testing is not possible or desired.
+env__net_pxe_readable_file = {
+ 'fn': 'default',
+ 'addr': 0x2000000,
+ 'size': 74,
+ 'timeout': 50000,
+ 'pattern': 'Linux',
+}
+
# True if a router advertisement service is connected to the network, and should
# be tested. If router advertisement testing is not possible or desired, this
variable may be omitted or set to False.
@@ -260,3 +274,126 @@ def test_net_nfs(u_boot_console):
output = u_boot_console.run_command('crc32 %x $filesize' % addr)
assert expected_crc in output
+
+@pytest.mark.buildconfigspec("cmd_net")
+@pytest.mark.buildconfigspec("cmd_pxe")
+def test_net_pxe_get(u_boot_console):
+ """Test the pxe get command.
+
+ A pxe configuration file is downloaded from the TFTP server and interpreted
+ to boot the images mentioned in pxe configuration file.
+
+ The details of the file to download are provided by the boardenv_* file;
+ see the comment at the beginning of this file.
+ """
+
+ if not net_set_up:
+ pytest.skip("Network not initialized")
+
+ test_net_setup_static(u_boot_console)
+
+ f = u_boot_console.config.env.get("env__net_pxe_readable_file", None)
+ if not f:
+ pytest.skip("No PXE readable file to read")
+
+ addr = f.get("addr", None)
+ timeout = f.get("timeout", u_boot_console.p.timeout)
+
+ pxeuuid = uuid.uuid1()
+ u_boot_console.run_command(f"setenv pxeuuid {pxeuuid}")
+ expected_text_uuid = f"Retrieving file: pxelinux.cfg/{pxeuuid}"
+
+ ethaddr = u_boot_console.run_command("echo $ethaddr")
+ ethaddr = ethaddr.replace(':', '-')
+ expected_text_ethaddr = f"Retrieving file: pxelinux.cfg/01-{ethaddr}"
+
+ ip = u_boot_console.run_command("echo $ipaddr")
+ ip = ip.split('.')
+ ipaddr_file = "".join(['%02x' % int(x) for x in ip]).upper()
+ expected_text_ipaddr = f"Retrieving file: pxelinux.cfg/{ipaddr_file}"
+ expected_text_default = f"Retrieving file: pxelinux.cfg/default"
+
+ with u_boot_console.temporary_timeout(timeout):
+ output = u_boot_console.run_command("pxe get")
+
+ assert "TIMEOUT" not in output
+ assert expected_text_uuid in output
+ assert expected_text_ethaddr in output
+ assert expected_text_ipaddr in output
+
+ i = 1
+ for i in range(0, len(ipaddr_file) - 1):
+ expected_text_ip = f"Retrieving file: pxelinux.cfg/{ipaddr_file[:-i]}"
+ assert expected_text_ip in output
+ i += 1
+
+ assert expected_text_default in output
+ assert "Config file 'default.boot' found" in output
+
+@pytest.mark.buildconfigspec("cmd_crc32")
+@pytest.mark.buildconfigspec("cmd_net")
+@pytest.mark.buildconfigspec("cmd_tftpput")
+def test_net_tftpput(u_boot_console):
+ """Test the tftpput command.
+
+ A file is downloaded from the TFTP server and then uploaded to the TFTP
+ server, its size and its CRC32 are validated.
+
+ The details of the file to download are provided by the boardenv_* file;
+ see the comment at the beginning of this file.
+ """
+
+ if not net_set_up:
+ pytest.skip("Network not initialized")
+
+ f = u_boot_console.config.env.get("env__net_tftp_readable_file", None)
+ if not f:
+ pytest.skip("No TFTP readable file to read")
+
+ addr = f.get("addr", None)
+ if not addr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ sz = f.get("size", None)
+ timeout = f.get("timeout", u_boot_console.p.timeout)
+ fn = f["fn"]
+ fnu = f.get("fnu", "_".join([datetime.datetime.now().strftime("%y%m%d%H%M%S"), fn]))
+ expected_text = "Bytes transferred = "
+ if sz:
+ expected_text += "%d" % sz
+
+ with u_boot_console.temporary_timeout(timeout):
+ output = u_boot_console.run_command("tftpboot %x %s" % (addr, fn))
+
+ assert "TIMEOUT" not in output
+ assert expected_text in output
+
+ expected_tftpb_crc = f.get("crc32", None)
+
+ output = u_boot_console.run_command("crc32 $fileaddr $filesize")
+ assert expected_tftpb_crc in output
+
+ with u_boot_console.temporary_timeout(timeout):
+ output = u_boot_console.run_command(
+ "tftpput $fileaddr $filesize $serverip:%s" % (fnu)
+ )
+
+ expected_text = "Bytes transferred = "
+ if sz:
+ expected_text += "%d" % sz
+ addr = addr + sz
+ assert "TIMEOUT" not in output
+ assert "Access violation" not in output
+ assert expected_text in output
+
+ with u_boot_console.temporary_timeout(timeout):
+ output = u_boot_console.run_command("tftpboot %x %s" % (addr, fnu))
+
+ expected_text = "Bytes transferred = "
+ if sz:
+ expected_text += "%d" % sz
+ assert "TIMEOUT" not in output
+ assert expected_text in output
+
+ output = u_boot_console.run_command("crc32 $fileaddr $filesize")
+ assert expected_tftpb_crc in output
diff --git a/test/py/tests/test_sandbox_opts.py b/test/py/tests/test_sandbox_opts.py
new file mode 100644
index 00000000000..422b43cb3bc
--- /dev/null
+++ b/test/py/tests/test_sandbox_opts.py
@@ -0,0 +1,30 @@
+# SPDX-License-Identifier: GPL-2.0
+# Copyright 2022 Google LLC
+# Written by Simon Glass <sjg@chromium.org>
+
+import pytest
+
+import u_boot_utils as util
+
+# This is needed for Azure, since the default '..' directory is not writeable
+TMPDIR = '/tmp/test_cmdline'
+
+@pytest.mark.slow
+@pytest.mark.boardspec('sandbox')
+def test_sandbox_cmdline(u_boot_console):
+ """Test building sandbox without CONFIG_CMDLINE"""
+ cons = u_boot_console
+
+ out = util.run_and_log(
+ cons, ['./tools/buildman/buildman', '-m', '--board', 'sandbox',
+ '-a', '~CMDLINE', '-o', TMPDIR])
+
+@pytest.mark.slow
+@pytest.mark.boardspec('sandbox')
+def test_sandbox_lto(u_boot_console):
+ """Test building sandbox without CONFIG_LTO"""
+ cons = u_boot_console
+
+ out = util.run_and_log(
+ cons, ['./tools/buildman/buildman', '-m', '--board', 'sandbox',
+ '-a', '~LTO', '-o', TMPDIR])
diff --git a/test/py/tests/test_sleep.py b/test/py/tests/test_sleep.py
index 392af29db22..66a57434bff 100644
--- a/test/py/tests/test_sleep.py
+++ b/test/py/tests/test_sleep.py
@@ -41,3 +41,21 @@ def test_sleep(u_boot_console):
if not u_boot_console.config.gdbserver:
# margin is hopefully enough to account for any system overhead.
assert elapsed < (sleep_time + sleep_margin)
+
+@pytest.mark.buildconfigspec("cmd_misc")
+def test_time(u_boot_console):
+ """Test the time command, and validate that it gives approximately the
+ correct amount of command execution time."""
+
+ sleep_skip = u_boot_console.config.env.get("env__sleep_accurate", True)
+ if not sleep_skip:
+ pytest.skip("sleep is not accurate")
+
+ sleep_time = u_boot_console.config.env.get("env__sleep_time", 10)
+ sleep_margin = u_boot_console.config.env.get("env__sleep_margin", 0.25)
+ output = u_boot_console.run_command("time sleep %d" % sleep_time)
+ execute_time = float(output.split()[1])
+ assert sleep_time >= (execute_time - 0.01)
+ if not u_boot_console.config.gdbserver:
+ # margin is hopefully enough to account for any system overhead.
+ assert sleep_time < (execute_time + sleep_margin)
diff --git a/test/py/tests/test_spl.py b/test/py/tests/test_spl.py
index bd273dad893..42e4c4342b2 100644
--- a/test/py/tests/test_spl.py
+++ b/test/py/tests/test_spl.py
@@ -5,6 +5,16 @@
import os.path
import pytest
+@pytest.mark.buildconfigspec('spl_unit_test')
+def test_ut_spl_init(u_boot_console):
+ """Initialize data for ut spl tests."""
+
+ fn = u_boot_console.config.source_dir + '/spi.bin'
+ if not os.path.exists(fn):
+ data = b'\x00' * (2 * 1024 * 1024)
+ with open(fn, 'wb') as fh:
+ fh.write(data)
+
def test_spl(u_boot_console, ut_spl_subtest):
"""Execute a "ut" subtest.
diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py
index c2579fa02c5..1d654cd4a23 100644
--- a/test/py/tests/test_tpm2.py
+++ b/test/py/tests/test_tpm2.py
@@ -61,7 +61,7 @@ def test_tpm2_init(u_boot_console):
skip_test = u_boot_console.config.env.get('env__tpm_device_test_skip', False)
if skip_test:
pytest.skip('skip TPM device test')
- u_boot_console.run_command('tpm2 init')
+ u_boot_console.run_command('tpm2 autostart')
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@@ -100,7 +100,7 @@ def test_tpm2_sandbox_self_test_full(u_boot_console):
"""
if is_sandbox(u_boot_console):
u_boot_console.restart_uboot()
- u_boot_console.run_command('tpm2 init')
+ u_boot_console.run_command('tpm2 autostart')
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@@ -239,7 +239,7 @@ def test_tpm2_dam_parameters(u_boot_console):
def test_tpm2_pcr_read(u_boot_console):
"""Execute a TPM2_PCR_Read command.
- Perform a PCR read of the 0th PCR. Must be zero.
+ Perform a PCR read of the 10th PCR. Must be zero.
"""
if is_sandbox(u_boot_console):
tpm2_sandbox_init(u_boot_console)
@@ -247,7 +247,7 @@ def test_tpm2_pcr_read(u_boot_console):
force_init(u_boot_console)
ram = u_boot_utils.find_ram_base(u_boot_console)
- read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % ram)
+ read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % ram)
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
@@ -257,7 +257,7 @@ def test_tpm2_pcr_read(u_boot_console):
updates = int(re.findall(r'\d+', str)[0])
# Check the output value
- assert 'PCR #0 content' in read_pcr
+ assert 'PCR #10 content' in read_pcr
assert '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00' in read_pcr
@pytest.mark.buildconfigspec('cmd_tpm_v2')
@@ -275,19 +275,19 @@ def test_tpm2_pcr_extend(u_boot_console):
force_init(u_boot_console)
ram = u_boot_utils.find_ram_base(u_boot_console)
- read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20))
+ read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20))
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
str = re.findall(r'\d+ known updates', read_pcr)[0]
updates = int(re.findall(r'\d+', str)[0])
- u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
+ u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram)
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
# Read the value back into a different place so we can still use 'ram' as
# our zero bytes
- read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20))
+ read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20))
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
assert 'f5 a5 fd 42 d1 6a 20 30 27 98 ef 6e d3 09 97 9b' in read_pcr
@@ -297,11 +297,11 @@ def test_tpm2_pcr_extend(u_boot_console):
new_updates = int(re.findall(r'\d+', str)[0])
assert (updates + 1) == new_updates
- u_boot_console.run_command('tpm2 pcr_extend 0 0x%x' % ram)
+ u_boot_console.run_command('tpm2 pcr_extend 10 0x%x' % ram)
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
- read_pcr = u_boot_console.run_command('tpm2 pcr_read 0 0x%x' % (ram + 0x20))
+ read_pcr = u_boot_console.run_command('tpm2 pcr_read 10 0x%x' % (ram + 0x20))
output = u_boot_console.run_command('echo $?')
assert output.endswith('0')
assert '7a 05 01 f5 95 7b df 9c b3 a8 ff 49 66 f0 22 65' in read_pcr
diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py
index 82932a662bf..1d9149a3f68 100644
--- a/test/py/tests/test_ut.py
+++ b/test/py/tests/test_ut.py
@@ -433,7 +433,6 @@ def setup_cedit_file(cons):
u_boot_utils.run_and_log(
cons, f'{expo_tool} -e {inhname} -l {infname} -o {outfname}')
-
@pytest.mark.buildconfigspec('ut_dm')
def test_ut_dm_init(u_boot_console):
"""Initialize data for ut dm tests."""
@@ -463,6 +462,12 @@ def test_ut_dm_init(u_boot_console):
fs_helper.mk_fs(u_boot_console.config, 'ext2', 0x200000, '2MB')
fs_helper.mk_fs(u_boot_console.config, 'fat32', 0x100000, '1MB')
+ mmc_dev = 6
+ fn = os.path.join(u_boot_console.config.source_dir, f'mmc{mmc_dev}.img')
+ data = b'\x00' * (12 * 1024 * 1024)
+ 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"""
diff --git a/test/test-main.c b/test/test-main.c
index 778bf0a18a0..b7015d9f38d 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -303,7 +303,7 @@ static int test_pre_run(struct unit_test_state *uts, struct unit_test *test)
if (test->flags & UT_TESTF_PROBE_TEST)
ut_assertok(do_autoprobe(uts));
- if (!CONFIG_IS_ENABLED(OF_PLATDATA) &&
+ if (CONFIG_IS_ENABLED(OF_REAL) &&
(test->flags & UT_TESTF_SCAN_FDT)) {
/*
* only set this if we know the ethernet uclass will be created
@@ -476,7 +476,8 @@ static int ut_run_test_live_flat(struct unit_test_state *uts,
* (for sandbox we handle this by copying the tree, but not for other
* boards)
*/
- if ((test->flags & UT_TESTF_SCAN_FDT) &&
+ if ((!CONFIG_IS_ENABLED(OF_LIVE) ||
+ (test->flags & UT_TESTF_SCAN_FDT)) &&
!(test->flags & UT_TESTF_LIVE_TREE) &&
(CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) ||
!(test->flags & UT_TESTF_OTHER_FDT)) &&