summaryrefslogtreecommitdiff
path: root/test/test-main.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2022-09-30 15:52:10 -0400
committerTom Rini <trini@konsulko.com>2022-09-30 15:52:10 -0400
commit6ee6e15975cad3c99fad3a66223f3fd9287a369b (patch)
tree2a1798758c85d3010640cf6bacb1ad7caaa29133 /test/test-main.c
parent01c88e3dcd667281cf3aa6f6b47f90900177aff9 (diff)
parentdb1ef1e12b993275e09f116ebc3d23d675c7e28c (diff)
Merge branch '2022-09-29-dm-core-support-multiple-device-trees-in-ofnode' into next
To quote the author: At present the ofnode interface is somewhat limited, in that it cannot access the device tree provided by the OS, only the one used by U-Boot itself (assuming these are separate). This prevents using ofnode functions to handle device tree fixups, i.e. ft_board_setup() and the like. The ofnode interface was introduced to allow a consistent API to access the device tree, whether a flat tree or a live tree (OF_LIVE) is in use. With the flat tree, adding nodes and properties at the start of the tree (as often happens when writing to the /chosen node) requires copying a lot of data for each operation. With live tree, such operations are quite a bit faster, since there is no memory copying required. This has to be weighed against the required memory allocation with OF_LIVE, as well as the cost of unflattening and flattening the device tree which U-Boot is running. This series enables support for access to multiple device trees with the ofnode interface. This is already available to some extent with OF_LIVE, but some of the ofnode functions need changes to allow the tree to be specified. The mechanism works by using the top 1-4 bits of the device tree offset. The sign bit is not affected, since negative values must be supported. With this implemented, it becomes possible to use the ofnode interface to do device tree fixups. The only current user is the EVT_FT_FIXUP event. This has two main benefits: - ofnode can now be used everywhere, in preference to the libfdt calls - live tree can eventually be used everywhere, with potential speed improvements when larger number of fixups are used This series is only a step along the way. Firstly, while it is possible to access the 'fix-up' tree using OF_LIVE, most of the fixup functions use flat tree directly, rather than the ofnode interface. These need to be updated. Also the tree must be flattened again before it is passed to the OS. This is not currently implemented. With OFNODE_MULTI_TREE disabled this has almost no effect on code size: around 4 bytes if EVENT is enabled, 0 if not. With the feature enabled, the increase is around 700 bytes, e.g. on venice2: $ buildman -b ofn2a venice2 -sS --step 0 Summary of 2 commits for 1 boards (1 thread, 64 jobs per thread) 01: image: Drop some other #ifdefs in image-board.c arm: w+ venice2 48: wip arm: (for 1/1 boards) all +668.0 text +668.0 This size increase is not too bad, considering the extra functionality, but is too large to enable everywhere. So for now this features needs to be opt-in only, based on EVENT.
Diffstat (limited to 'test/test-main.c')
-rw-r--r--test/test-main.c132
1 files changed, 127 insertions, 5 deletions
diff --git a/test/test-main.c b/test/test-main.c
index ae34002a3d4..d74df297c43 100644
--- a/test/test-main.c
+++ b/test/test-main.c
@@ -9,14 +9,53 @@
#include <cyclic.h>
#include <dm.h>
#include <event.h>
+#include <of_live.h>
+#include <os.h>
+#include <dm/ofnode.h>
#include <dm/root.h>
#include <dm/test.h>
#include <dm/uclass-internal.h>
#include <test/test.h>
#include <test/ut.h>
+#include <u-boot/crc.h>
DECLARE_GLOBAL_DATA_PTR;
+/**
+ * enum fdtchk_t - what to do with the device tree (gd->fdt_blob)
+ *
+ * This affects what happens with the device tree before and after a test
+ *
+ * @FDTCHK_NONE: Do nothing
+ * @FDTCHK_CHECKSUM: Take a checksum of the FDT before the test runs and
+ * compare it afterwards to detect any changes
+ * @FDTCHK_COPY: Make a copy of the FDT and restore it afterwards
+ */
+enum fdtchk_t {
+ FDTCHK_NONE,
+ FDTCHK_CHECKSUM,
+ FDTCHK_COPY,
+};
+
+/**
+ * fdt_action() - get the required action for the FDT
+ *
+ * @return the action that should be taken for this build
+ */
+static enum fdtchk_t fdt_action(void)
+{
+ /* Do a copy for sandbox (but only the U-Boot build, not SPL) */
+ if (CONFIG_IS_ENABLED(SANDBOX))
+ return FDTCHK_COPY;
+
+ /* For sandbox SPL builds, do nothing */
+ if (IS_ENABLED(CONFIG_SANDBOX))
+ return FDTCHK_NONE;
+
+ /* For all other boards, do a checksum */
+ return FDTCHK_CHECKSUM;
+}
+
/* This is valid when a test is running, NULL otherwise */
static struct unit_test_state *cur_test_state;
@@ -42,17 +81,26 @@ static int dm_test_pre_run(struct unit_test_state *uts)
{
bool of_live = uts->of_live;
+ if (of_live && (gd->flags & GD_FLG_FDT_CHANGED)) {
+ printf("Cannot run live tree test as device tree changed\n");
+ return -EFAULT;
+ }
uts->root = NULL;
uts->testdev = NULL;
uts->force_fail_alloc = false;
uts->skip_post_probe = false;
+ if (fdt_action() == FDTCHK_CHECKSUM)
+ uts->fdt_chksum = crc8(0, gd->fdt_blob,
+ fdt_totalsize(gd->fdt_blob));
gd->dm_root = NULL;
+ malloc_disable_testing();
if (CONFIG_IS_ENABLED(UT_DM) && !CONFIG_IS_ENABLED(OF_PLATDATA))
memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count));
arch_reset_for_test();
/* Determine whether to make the live tree available */
gd_set_of_root(of_live ? uts->of_root : NULL);
+ oftree_reset();
ut_assertok(dm_init(of_live));
uts->root = dm_root();
@@ -63,6 +111,33 @@ static int dm_test_post_run(struct unit_test_state *uts)
{
int id;
+ if (gd->fdt_blob) {
+ switch (fdt_action()) {
+ case FDTCHK_COPY:
+ memcpy((void *)gd->fdt_blob, uts->fdt_copy, uts->fdt_size);
+ break;
+ case FDTCHK_CHECKSUM: {
+ uint chksum;
+
+ chksum = crc8(0, gd->fdt_blob, fdt_totalsize(gd->fdt_blob));
+ if (chksum != uts->fdt_chksum) {
+ /*
+ * We cannot run any more tests that need the
+ * live tree, since its strings point into the
+ * flat tree, which has changed. This likely
+ * means that at least some of the pointers from
+ * the live tree point to different things
+ */
+ printf("Device tree changed: cannot run live tree tests\n");
+ gd->flags |= GD_FLG_FDT_CHANGED;
+ }
+ break;
+ }
+ case FDTCHK_NONE:
+ break;
+ }
+ }
+
/*
* With of-platdata-inst the uclasses are created at build time. If we
* destroy them we cannot get them back since uclass_add() is not
@@ -242,6 +317,20 @@ static int test_pre_run(struct unit_test_state *uts, struct unit_test *test)
(test->flags & UT_TESTF_SCAN_FDT))
ut_assertok(dm_extended_scan(false));
+ if (IS_ENABLED(CONFIG_SANDBOX) && (test->flags & UT_TESTF_OTHER_FDT)) {
+ /* make sure the other FDT is available */
+ ut_assertok(test_load_other_fdt(uts));
+
+ /*
+ * create a new live tree with it for every test, in case a
+ * test modifies the tree
+ */
+ if (of_live_active()) {
+ ut_assertok(unflatten_device_tree(uts->other_fdt,
+ &uts->of_other));
+ }
+ }
+
if (test->flags & UT_TESTF_CONSOLE_REC) {
int ret = console_record_reset_enable();
@@ -270,6 +359,9 @@ static int test_post_run(struct unit_test_state *uts, struct unit_test *test)
ut_assertok(cyclic_uninit());
ut_assertok(event_uninit());
+ free(uts->of_other);
+ uts->of_other = NULL;
+
return 0;
}
@@ -340,11 +432,13 @@ static int ut_run_test_live_flat(struct unit_test_state *uts,
{
int runs;
+ if ((test->flags & UT_TESTF_OTHER_FDT) && !IS_ENABLED(CONFIG_SANDBOX))
+ return -EAGAIN;
+
/* Run with the live tree if possible */
runs = 0;
if (CONFIG_IS_ENABLED(OF_LIVE)) {
- if (!(test->flags &
- (UT_TESTF_FLAT_TREE | UT_TESTF_LIVE_OR_FLAT))) {
+ if (!(test->flags & UT_TESTF_FLAT_TREE)) {
uts->of_live = true;
ut_assertok(ut_run_test(uts, test, test->name));
runs++;
@@ -352,11 +446,22 @@ static int ut_run_test_live_flat(struct unit_test_state *uts,
}
/*
- * Run with the flat tree if we couldn't run it with live tree,
- * or it is a core test.
+ * Run with the flat tree if:
+ * - it is not marked for live tree only
+ * - it doesn't require the 'other' FDT when OFNODE_MULTI_TREE_MAX is
+ * not enabled (since flat tree can only support a single FDT in that
+ * case
+ * - we couldn't run it with live tree,
+ * - it is a core test (dm tests except video)
+ * - the FDT is still valid and has not been updated by an earlier test
+ * (for sandbox we handle this by copying the tree, but not for other
+ * boards)
*/
if (!(test->flags & UT_TESTF_LIVE_TREE) &&
- (!runs || ut_test_run_on_flattree(test))) {
+ (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) ||
+ !(test->flags & UT_TESTF_OTHER_FDT)) &&
+ (!runs || ut_test_run_on_flattree(test)) &&
+ !(gd->flags & GD_FLG_FDT_CHANGED)) {
uts->of_live = false;
ut_assertok(ut_run_test(uts, test, test->name));
runs++;
@@ -443,8 +548,25 @@ int ut_run_list(const char *category, const char *prefix,
uts.of_root = gd_of_root();
uts.runs_per_test = runs_per_test;
+ if (fdt_action() == FDTCHK_COPY && gd->fdt_blob) {
+ uts.fdt_size = fdt_totalsize(gd->fdt_blob);
+ uts.fdt_copy = os_malloc(uts.fdt_size);
+ if (!uts.fdt_copy) {
+ printf("Out of memory for device tree copy\n");
+ return -ENOMEM;
+ }
+ memcpy(uts.fdt_copy, gd->fdt_blob, uts.fdt_size);
+ }
ret = ut_run_tests(&uts, prefix, tests, count, select_name);
+ /* Best efforts only...ignore errors */
+ if (has_dm_tests)
+ dm_test_restore(uts.of_root);
+ if (IS_ENABLED(CONFIG_SANDBOX)) {
+ os_free(uts.fdt_copy);
+ os_free(uts.other_fdt);
+ }
+
if (ret == -ENOENT)
printf("Test '%s' not found\n", select_name);
else