From 78e20a7f4e8b544e4d949ae3199ae979a6fe7b6c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:14 +0100 Subject: cmd: fdt: Import is_printable_string() from DTC to fix u32 misprint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Import is_printable_string() implementation from DTC 1.7.0 as of DTC commit 039a994 ("Bump version to v1.7.0") . This fixes a print of u32 property which so far used to be printed as string by U-Boot fdt print command. We might see the case where the parsed property value, in this case it is a 32-bit integer, identified as a printable string or a null byte (concatenated strings) because of its last character happens to be: 0x00 (null character), 0xB (vertical tab character) or 0x10 (line feed character) In this situation, if the string is identified as printable string, it will be displayed as character instead of hex value When the isprint() condition is true, there are two possibilities: 1) The character is ASCII character (except the first 32) 2) The character is extended ASCII character For example, NG property in device tree: clock-frequency = <16640000>; by default, would be displayed as clock-frequency = "", "ýè"; and with this patch applied, would be displayed as clock-frequency = <0x00fde800>; Full investigation was done by Nam and Hai, patch reworked by Marek to use common code from DTC. Signed-off-by: Hai Pham Signed-off-by: Nam Nguyen Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- cmd/fdt.c | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/cmd/fdt.c b/cmd/fdt.c index 1972490..bf24156 100644 --- a/cmd/fdt.c +++ b/cmd/fdt.c @@ -878,41 +878,33 @@ static int fdt_parse_prop(char * const *newval, int count, char *data, int *len) static int is_printable_string(const void *data, int len) { const char *s = data; + const char *ss, *se; /* zero length is not */ if (len == 0) return 0; - /* must terminate with zero or '\n' */ - if (s[len - 1] != '\0' && s[len - 1] != '\n') + /* must terminate with zero */ + if (s[len - 1] != '\0') return 0; - /* printable or a null byte (concatenated strings) */ - while (((*s == '\0') || isprint(*s) || isspace(*s)) && (len > 0)) { - /* - * If we see a null, there are three possibilities: - * 1) If len == 1, it is the end of the string, printable - * 2) Next character also a null, not printable. - * 3) Next character not a null, continue to check. - */ - if (s[0] == '\0') { - if (len == 1) - return 1; - if (s[1] == '\0') - return 0; - } + se = s + len; + + while (s < se) { + ss = s; + while (s < se && *s && isprint((unsigned char)*s)) + s++; + + /* not zero, or not done yet */ + if (*s != '\0' || s == ss) + return 0; + s++; - len--; } - /* Not the null termination, or not done yet: not printable */ - if (*s != '\0' || (len != 0)) - return 0; - return 1; } - /* * Print the property in the best format, a heuristic guess. Print as * a string, concatenated strings, a byte, word, double word, or (if all -- cgit v1.1 From 0655b9e6210221a60657a4865163ef2f1da4bbf7 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:15 +0100 Subject: cmd: fdt: Fix handling of empty properties for fdt get addr and fdt get size It is perfectly valid to request an address or size of FDT property without value, the only special case if requesting of the value of FDT property without value. Invert the test such, that properties without value still set the variable from 'fdt get addr/size' to address of the property or size of the property, where the later is 0. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- cmd/fdt.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/cmd/fdt.c b/cmd/fdt.c index bf24156..56b3585 100644 --- a/cmd/fdt.c +++ b/cmd/fdt.c @@ -446,15 +446,17 @@ static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) } else { nodep = fdt_getprop( working_fdt, nodeoffset, prop, &len); - if (len == 0) { - /* no property value */ - env_set(var, ""); - return 0; - } else if (nodep && len > 0) { + if (nodep && len >= 0) { if (subcmd[0] == 'v') { int index = 0; int ret; + if (len == 0) { + /* no property value */ + env_set(var, ""); + return 0; + } + if (argc == 7) index = simple_strtoul(argv[6], NULL, 10); -- cgit v1.1 From 15195d6a54877447c194972c616f8fdc882248e9 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:16 +0100 Subject: cmd: fdt: Fix fdt rm behavior on non-existent property and error message space In case an FDT contains a node '/test-node@1234' , with no property called 'noprop' in that node, the following command triggers a print of help message for 'fdt' command instead of erroring out: => fdt rm /test-node@1234 noprop This is because the subcommand errornously returns 'err' instead of CMD_RET_FAILURE, fix it. Furthermore, align the number of spaces past fdt_delprop() in error message with the rest of the code. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- cmd/fdt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/fdt.c b/cmd/fdt.c index 56b3585..644b58a 100644 --- a/cmd/fdt.c +++ b/cmd/fdt.c @@ -547,16 +547,16 @@ static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) if (argc > 3) { err = fdt_delprop(working_fdt, nodeoffset, argv[3]); if (err < 0) { - printf("libfdt fdt_delprop(): %s\n", + printf("libfdt fdt_delprop(): %s\n", fdt_strerror(err)); - return err; + return CMD_RET_FAILURE; } } else { err = fdt_del_node(working_fdt, nodeoffset); if (err < 0) { - printf("libfdt fdt_del_node(): %s\n", + printf("libfdt fdt_del_node(): %s\n", fdt_strerror(err)); - return err; + return CMD_RET_FAILURE; } } -- cgit v1.1 From 7a5aa5c14e1a162776655425510cf78b5d07aa98 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:17 +0100 Subject: cmd: fdt: Fix fdt rsvmem behavior on non-existent index and error message space In case 'fdt rsvmem delete index' is passed a non-existent index, one which does not exist in 'fdt rsvmem print', then the following command triggers a print of help message for 'fdt' command instead of erroring out: => fdt rsvmem delete 1234 This is because the subcommand errornously returns 'err' instead of CMD_RET_FAILURE, fix it. Furthermore, align the number of spaces past fdt_del_mem_rsv() and fdt_add_mem_rsv() in error message with the rest of the code. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- cmd/fdt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/fdt.c b/cmd/fdt.c index 644b58a..29d7488 100644 --- a/cmd/fdt.c +++ b/cmd/fdt.c @@ -644,18 +644,18 @@ static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) err = fdt_add_mem_rsv(working_fdt, addr, size); if (err < 0) { - printf("libfdt fdt_add_mem_rsv(): %s\n", + printf("libfdt fdt_add_mem_rsv(): %s\n", fdt_strerror(err)); - return err; + return CMD_RET_FAILURE; } } else if (argv[2][0] == 'd') { unsigned long idx = hextoul(argv[3], NULL); int err = fdt_del_mem_rsv(working_fdt, idx); if (err < 0) { - printf("libfdt fdt_del_mem_rsv(): %s\n", + printf("libfdt fdt_del_mem_rsv(): %s\n", fdt_strerror(err)); - return err; + return CMD_RET_FAILURE; } } else { /* Unrecognized command */ -- cgit v1.1 From c8786b6db6b39771949161bf8bdd3671dae33b16 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:18 +0100 Subject: cmd: fdt: Check argc before accessing argv in fdt bootcpu On case 'fdt bootcpu' is invoked without parameters, argv[2] is not valid and this command would SEGFAULT in sandbox environment. Add missing argc test to avoid the crash and rather print usage help message. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- cmd/fdt.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/fdt.c b/cmd/fdt.c index 29d7488..734c9b3 100644 --- a/cmd/fdt.c +++ b/cmd/fdt.c @@ -597,7 +597,12 @@ static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) * Set boot cpu id */ } else if (strncmp(argv[1], "boo", 3) == 0) { - unsigned long tmp = hextoul(argv[2], NULL); + unsigned long tmp; + + if (argc != 3) + return CMD_RET_USAGE; + + tmp = hextoul(argv[2], NULL); fdt_set_boot_cpuid_phys(working_fdt, tmp); /* -- cgit v1.1 From 5e0462757c636745dbe16aaf72d659271595626b Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:19 +0100 Subject: cmd: fdt: Check argc before accessing argv in fdt memory On case 'fdt memory' is invoked without parameters, argv[2]/argv[3] is not valid and this command would SEGFAULT in sandbox environment. Add missing argc test to avoid the crash and rather print usage help message. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- cmd/fdt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/fdt.c b/cmd/fdt.c index 734c9b3..f257bee 100644 --- a/cmd/fdt.c +++ b/cmd/fdt.c @@ -611,6 +611,10 @@ static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) } else if (strncmp(argv[1], "me", 2) == 0) { uint64_t addr, size; int err; + + if (argc != 4) + return CMD_RET_USAGE; + addr = simple_strtoull(argv[2], NULL, 16); size = simple_strtoull(argv[3], NULL, 16); err = fdt_fixup_memory(working_fdt, addr, size); -- cgit v1.1 From 068b7d9ed379e5376550709bd3c238d2777a3cfe Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:20 +0100 Subject: cmd: fdt: Align checksign parameter names in help text The help text references 'addr' as an optional key start address, but the explanation references the same as 'start', make sure they both read as 'addr'. Also update the abbreviated 'addr' in the explanation to 'address'. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- cmd/fdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/fdt.c b/cmd/fdt.c index f257bee..279dad9 100644 --- a/cmd/fdt.c +++ b/cmd/fdt.c @@ -1138,8 +1138,8 @@ static char fdt_help_text[] = " / - initrd start addr/size\n" #if defined(CONFIG_FIT_SIGNATURE) "fdt checksign [] - check FIT signature\n" - " - addr of key blob\n" - " default gd->fdt_blob\n" + " - address of key blob\n" + " default gd->fdt_blob\n" #endif "NOTE: Dereference aliases by omitting the leading '/', " "e.g. fdt print ethernet0."; -- cgit v1.1 From 98d114e75c888ed7a8313a14e778f45d388199c4 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:21 +0100 Subject: cmd: fdt: Handle 64bit pointers in fdt get addr The command assumed 32bit pointers so far, with 64bit pointer the command would overwrite a piece of stack. Fix it by extending the array size to cater for 64bit pointer, and use snprintf() to avoid writing past the end of the array ever again. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- cmd/fdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/fdt.c b/cmd/fdt.c index 279dad9..bc19303 100644 --- a/cmd/fdt.c +++ b/cmd/fdt.c @@ -466,9 +466,9 @@ static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) return ret; } else if (subcmd[0] == 'a') { /* Get address */ - char buf[11]; + char buf[19]; - sprintf(buf, "0x%p", nodep); + snprintf(buf, sizeof(buf), "0x%p", nodep); env_set(var, buf); } else if (subcmd[0] == 's') { /* Get size */ -- cgit v1.1 From b363da1c26c96a831d3ffcbd1d4997ec3d340009 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:22 +0100 Subject: cmd: fdt: Map address returned from fdt get addr to sysmem The address returned from 'fdt get addr' command must be mapped into sysmem, as this is a working FDT. Access to this address without mapping it would lead to crash e.g. in sandbox. The following command triggers the crash: " ./u-boot -Dc 'fdt addr $fdtcontroladdr ; fdt get addr var / compatible ; md $var' " Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- cmd/fdt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/fdt.c b/cmd/fdt.c index bc19303..f2576ab 100644 --- a/cmd/fdt.c +++ b/cmd/fdt.c @@ -468,7 +468,8 @@ static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) /* Get address */ char buf[19]; - snprintf(buf, sizeof(buf), "0x%p", nodep); + snprintf(buf, sizeof(buf), "0x%lx", + (ulong)map_to_sysmem(nodep)); env_set(var, buf); } else if (subcmd[0] == 's') { /* Get size */ -- cgit v1.1 From 4e6d0305506ccb347401f770bed8f35e4c56aac2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:23 +0100 Subject: cmd: fdt: Add support for integer arrays in fdt get value with index Currently any integer array value is set as long up-to-40 character hexadecimal string into environment variable when extracted from an FDT using 'fdt get value path prop index', because the support for handling integer arrays is not implemented, and fdt_value_env_set() code falls back into the hash handling behavior instead. Implement this support simply by checking whether user supplied any index. If index is set and the property length is multiple of four, then this is an integer array, and the code would extract value at specified index. There is a subtle change where default index is set to -1 instead of 0. This is OK, since the only place which checks for index to be less or equal zero is the string array handling code in fdt_value_env_set() and that code would work perfectly well with index -1 too. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- cmd/fdt.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/cmd/fdt.c b/cmd/fdt.c index f2576ab..f38fe90 100644 --- a/cmd/fdt.c +++ b/cmd/fdt.c @@ -77,7 +77,17 @@ static int fdt_value_env_set(const void *nodep, int len, sprintf(buf, "0x%08X", fdt32_to_cpu(*(fdt32_t *)nodep)); env_set(var, buf); - } else if (len%4 == 0 && len <= 20) { + } else if (len % 4 == 0 && index >= 0) { + /* Needed to print integer arrays. */ + const unsigned int *nodec = (const unsigned int *)nodep; + char buf[11]; + + if (index * 4 >= len) + return 1; + + sprintf(buf, "0x%08X", fdt32_to_cpu(*(nodec + index))); + env_set(var, buf); + } else if (len % 4 == 0 && len <= 20) { /* Needed to print things like sha1 hashes. */ char buf[41]; int i; @@ -448,7 +458,7 @@ static int do_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) working_fdt, nodeoffset, prop, &len); if (nodep && len >= 0) { if (subcmd[0] == 'v') { - int index = 0; + int index = -1; int ret; if (len == 0) { -- cgit v1.1 From 967e7078b77f8bfcc3374dba057140b4433b9bd2 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:24 +0100 Subject: test: Add ut_assert_nextline_empty() empty line helper Add helper macro to test for empty lines, which is an inobvious wrapper around ut_assert_nextline("%s", "") . Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- include/test/ut.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/test/ut.h b/include/test/ut.h index 4d00b4e..2b0dab3 100644 --- a/include/test/ut.h +++ b/include/test/ut.h @@ -334,6 +334,10 @@ int ut_check_console_dump(struct unit_test_state *uts, int total_bytes); return CMD_RET_FAILURE; \ } \ +/* Assert that the next console output line is empty */ +#define ut_assert_nextline_empty() \ + ut_assert_nextline("%s", "") + /** * ut_check_free() - Return the number of bytes free in the malloc() pool * -- cgit v1.1 From 4a9fe8cbe66018f3f6131797d897ad2711ac5424 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:25 +0100 Subject: test: cmd: fdt: Rename fdt_test_resize() to fdt_test_addr_resize() The 'fdt' command has a 'resize' subcommand, rename the fdt_test_resize() to fdt_test_addr_resize() to avoid confusion about what it is testing. There is currently no resize test. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- test/cmd/fdt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index 7974c88..a50285e 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -108,7 +108,7 @@ static int fdt_test_addr(struct unit_test_state *uts) FDT_TEST(fdt_test_addr, UT_TESTF_CONSOLE_REC); /* Test 'fdt addr' resizing an fdt */ -static int fdt_test_resize(struct unit_test_state *uts) +static int fdt_test_addr_resize(struct unit_test_state *uts) { char fdt[256]; const int newsize = sizeof(fdt) / 2; @@ -140,7 +140,7 @@ static int fdt_test_resize(struct unit_test_state *uts) return 0; } -FDT_TEST(fdt_test_resize, UT_TESTF_CONSOLE_REC); +FDT_TEST(fdt_test_addr_resize, UT_TESTF_CONSOLE_REC); /* Test 'fdt get' reading an fdt */ static int fdt_test_get(struct unit_test_state *uts) -- cgit v1.1 From 38805e03f08b69bbb72f7761ffa4b4c169df0a37 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:26 +0100 Subject: test: cmd: fdt: Rename fdt_test_get() to fdt_test_get_value() The 'fdt get' command has a 'get value' subcommand, rename the fdt_test_get() to fdt_test_get_value() to avoid confusion about what it is testing. There is currently no get 'get name', 'get addr', 'get size' subcommand test. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- test/cmd/fdt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index a50285e..03a29c6 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -142,8 +142,8 @@ static int fdt_test_addr_resize(struct unit_test_state *uts) } FDT_TEST(fdt_test_addr_resize, UT_TESTF_CONSOLE_REC); -/* Test 'fdt get' reading an fdt */ -static int fdt_test_get(struct unit_test_state *uts) +/* Test 'fdt get value' reading an fdt */ +static int fdt_test_get_value(struct unit_test_state *uts) { ulong addr; @@ -193,7 +193,7 @@ static int fdt_test_get(struct unit_test_state *uts) return 0; } -FDT_TEST(fdt_test_get, UT_TESTF_CONSOLE_REC); +FDT_TEST(fdt_test_get_value, UT_TESTF_CONSOLE_REC); int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { -- cgit v1.1 From 21e1d93b143be163be14edf45b3c9223bcc428e6 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:27 +0100 Subject: test: cmd: fdt: Generate fuller DT internally and switch fdt get value to it Implement function to generate internal test DT fragment and switch the 'fdt get value' test to this instead of depending on the sandbox DT. Rename clk-test node to test-node node. This FDT fragment will be reused by other tests. No functional change. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- test/cmd/fdt.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 111 insertions(+), 13 deletions(-) diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index 03a29c6..21553a2 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -39,6 +39,102 @@ static int make_test_fdt(struct unit_test_state *uts, void *fdt, int size) return 0; } +/** + * make_fuller_fdt() - Create an FDT with root node and properties + * + * The size is set to the minimum needed + * + * @uts: Test state + * @fdt: Place to write FDT + * @size: Maximum size of space for fdt + */ +static int make_fuller_fdt(struct unit_test_state *uts, void *fdt, int size) +{ + fdt32_t regs[2] = { cpu_to_fdt32(0x1234), cpu_to_fdt32(0x1000) }; + + /* + * Assemble the following DT for test purposes: + * + * / { + * #address-cells = <0x00000001>; + * #size-cells = <0x00000001>; + * compatible = "u-boot,fdt-test"; + * model = "U-Boot FDT test"; + * + * aliases { + * badalias = "/bad/alias"; + * subnodealias = "/test-node@1234/subnode"; + * testnodealias = "/test-node@1234"; + * }; + * + * test-node@1234 { + * #address-cells = <0x00000000>; + * #size-cells = <0x00000000>; + * compatible = "u-boot,fdt-test-device1"; + * clock-names = "fixed", "i2c", "spi", "uart2", "uart1"; + * u-boot,empty-property; + * clock-frequency = <0x00fde800>; + * regs = <0x00001234 0x00001000>; + * + * subnode { + * #address-cells = <0x00000000>; + * #size-cells = <0x00000000>; + * compatible = "u-boot,fdt-subnode-test-device"; + * }; + * }; + * }; + */ + + ut_assertok(fdt_create(fdt, size)); + ut_assertok(fdt_finish_reservemap(fdt)); + ut_assert(fdt_begin_node(fdt, "") >= 0); + + ut_assertok(fdt_property_u32(fdt, "#address-cells", 1)); + ut_assertok(fdt_property_u32(fdt, "#size-cells", 1)); + /* */ + ut_assertok(fdt_property_string(fdt, "compatible", "u-boot,fdt-test")); + /* */ + ut_assertok(fdt_property_string(fdt, "model", "U-Boot FDT test")); + + ut_assert(fdt_begin_node(fdt, "aliases") >= 0); + /* */ + ut_assertok(fdt_property_string(fdt, "badalias", "/bad/alias")); + /* */ + ut_assertok(fdt_property_string(fdt, "subnodealias", "/test-node@1234/subnode")); + /* */ + ut_assertok(fdt_property_string(fdt, "testnodealias", "/test-node@1234")); + ut_assertok(fdt_end_node(fdt)); + + ut_assert(fdt_begin_node(fdt, "test-node@1234") >= 0); + ut_assertok(fdt_property_cell(fdt, "#address-cells", 0)); + ut_assertok(fdt_property_cell(fdt, "#size-cells", 0)); + /* */ + ut_assertok(fdt_property_string(fdt, "compatible", "u-boot,fdt-test-device1")); + /* */ + ut_assertok(fdt_property(fdt, "clock-names", "fixed\0i2c\0spi\0uart2\0uart1\0", 26)); + /* */ + ut_assertok(fdt_property(fdt, "u-boot,empty-property", NULL, 0)); + /* + * + * This value is deliberate as it used to break cmd/fdt.c + * is_printable_string() implementation. + */ + ut_assertok(fdt_property_u32(fdt, "clock-frequency", 16640000)); + /* */ + ut_assertok(fdt_property(fdt, "regs", ®s, sizeof(regs))); + ut_assert(fdt_begin_node(fdt, "subnode") >= 0); + ut_assertok(fdt_property_cell(fdt, "#address-cells", 0)); + ut_assertok(fdt_property_cell(fdt, "#size-cells", 0)); + ut_assertok(fdt_property_string(fdt, "compatible", "u-boot,fdt-subnode-test-device")); + ut_assertok(fdt_end_node(fdt)); + ut_assertok(fdt_end_node(fdt)); + + ut_assertok(fdt_end_node(fdt)); + ut_assertok(fdt_finish(fdt)); + + return 0; +} + /* Test 'fdt addr' getting/setting address */ static int fdt_test_addr(struct unit_test_state *uts) { @@ -145,43 +241,45 @@ FDT_TEST(fdt_test_addr_resize, UT_TESTF_CONSOLE_REC); /* Test 'fdt get value' reading an fdt */ static int fdt_test_get_value(struct unit_test_state *uts) { + char fdt[4096]; ulong addr; - addr = map_to_sysmem(gd->fdt_blob); + ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt))); + addr = map_to_sysmem(fdt); set_working_fdt_addr(addr); - /* Test getting default element of /clk-test node clock-names property */ + /* Test getting default element of /test-node@1234 node clock-names property */ ut_assertok(console_record_reset_enable()); - ut_assertok(run_command("fdt get value fdflt /clk-test clock-names", 0)); + ut_assertok(run_command("fdt get value fdflt /test-node@1234 clock-names", 0)); ut_asserteq_str("fixed", env_get("fdflt")); ut_assertok(ut_check_console_end(uts)); - /* Test getting 0th element of /clk-test node clock-names property */ + /* Test getting 0th element of /test-node@1234 node clock-names property */ ut_assertok(console_record_reset_enable()); - ut_assertok(run_command("fdt get value fzero /clk-test clock-names 0", 0)); + ut_assertok(run_command("fdt get value fzero /test-node@1234 clock-names 0", 0)); ut_asserteq_str("fixed", env_get("fzero")); ut_assertok(ut_check_console_end(uts)); - /* Test getting 1st element of /clk-test node clock-names property */ + /* Test getting 1st element of /test-node@1234 node clock-names property */ ut_assertok(console_record_reset_enable()); - ut_assertok(run_command("fdt get value fone /clk-test clock-names 1", 0)); + ut_assertok(run_command("fdt get value fone /test-node@1234 clock-names 1", 0)); ut_asserteq_str("i2c", env_get("fone")); ut_assertok(ut_check_console_end(uts)); - /* Test getting 2nd element of /clk-test node clock-names property */ + /* Test getting 2nd element of /test-node@1234 node clock-names property */ ut_assertok(console_record_reset_enable()); - ut_assertok(run_command("fdt get value ftwo /clk-test clock-names 2", 0)); + ut_assertok(run_command("fdt get value ftwo /test-node@1234 clock-names 2", 0)); ut_asserteq_str("spi", env_get("ftwo")); ut_assertok(ut_check_console_end(uts)); - /* Test missing 10th element of /clk-test node clock-names property */ + /* Test missing 10th element of /test-node@1234 node clock-names property */ ut_assertok(console_record_reset_enable()); - ut_asserteq(1, run_command("fdt get value ftwo /clk-test clock-names 10", 0)); + ut_asserteq(1, run_command("fdt get value ften /test-node@1234 clock-names 10", 0)); ut_assertok(ut_check_console_end(uts)); - /* Test getting default element of /clk-test node nonexistent property */ + /* Test getting default element of /test-node@1234 node nonexistent property */ ut_assertok(console_record_reset_enable()); - ut_asserteq(1, run_command("fdt get value fnone /clk-test nonexistent", 1)); + ut_asserteq(1, run_command("fdt get value fnone /test-node@1234 nonexistent", 1)); ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND"); ut_assertok(ut_check_console_end(uts)); -- cgit v1.1 From ed14576b59c4e2e2d608ffddd30e272872adcd74 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:28 +0100 Subject: test: cmd: fdt: Test alias resolution in 'fdt get value' The 'fdt' command help contains the following note: " Dereference aliases by omitting the leading '/', e.g. fdt print ethernet0. " Add test for it. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- test/cmd/fdt.c | 65 ++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index 21553a2..e04ba37 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -239,56 +239,81 @@ static int fdt_test_addr_resize(struct unit_test_state *uts) FDT_TEST(fdt_test_addr_resize, UT_TESTF_CONSOLE_REC); /* Test 'fdt get value' reading an fdt */ -static int fdt_test_get_value(struct unit_test_state *uts) +static int fdt_test_get_value_common(struct unit_test_state *uts, + const char *node) { - char fdt[4096]; - ulong addr; - - ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt))); - addr = map_to_sysmem(fdt); - set_working_fdt_addr(addr); - - /* Test getting default element of /test-node@1234 node clock-names property */ + /* Test getting default element of $node node clock-names property */ ut_assertok(console_record_reset_enable()); - ut_assertok(run_command("fdt get value fdflt /test-node@1234 clock-names", 0)); + ut_assertok(run_commandf("fdt get value fdflt %s clock-names", node)); ut_asserteq_str("fixed", env_get("fdflt")); ut_assertok(ut_check_console_end(uts)); - /* Test getting 0th element of /test-node@1234 node clock-names property */ + /* Test getting 0th element of $node node clock-names property */ ut_assertok(console_record_reset_enable()); - ut_assertok(run_command("fdt get value fzero /test-node@1234 clock-names 0", 0)); + ut_assertok(run_commandf("fdt get value fzero %s clock-names 0", node)); ut_asserteq_str("fixed", env_get("fzero")); ut_assertok(ut_check_console_end(uts)); - /* Test getting 1st element of /test-node@1234 node clock-names property */ + /* Test getting 1st element of $node node clock-names property */ ut_assertok(console_record_reset_enable()); - ut_assertok(run_command("fdt get value fone /test-node@1234 clock-names 1", 0)); + ut_assertok(run_commandf("fdt get value fone %s clock-names 1", node)); ut_asserteq_str("i2c", env_get("fone")); ut_assertok(ut_check_console_end(uts)); - /* Test getting 2nd element of /test-node@1234 node clock-names property */ + /* Test getting 2nd element of $node node clock-names property */ ut_assertok(console_record_reset_enable()); - ut_assertok(run_command("fdt get value ftwo /test-node@1234 clock-names 2", 0)); + ut_assertok(run_commandf("fdt get value ftwo %s clock-names 2", node)); ut_asserteq_str("spi", env_get("ftwo")); ut_assertok(ut_check_console_end(uts)); - /* Test missing 10th element of /test-node@1234 node clock-names property */ + /* Test missing 10th element of $node node clock-names property */ ut_assertok(console_record_reset_enable()); - ut_asserteq(1, run_command("fdt get value ften /test-node@1234 clock-names 10", 0)); + ut_asserteq(1, run_commandf("fdt get value ften %s clock-names 10", node)); ut_assertok(ut_check_console_end(uts)); - /* Test getting default element of /test-node@1234 node nonexistent property */ + /* Test getting default element of $node node nonexistent property */ ut_assertok(console_record_reset_enable()); - ut_asserteq(1, run_command("fdt get value fnone /test-node@1234 nonexistent", 1)); + ut_asserteq(1, run_commandf("fdt get value fnone %s nonexistent", node)); ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND"); ut_assertok(ut_check_console_end(uts)); + return 0; +} + +static int fdt_test_get_value(struct unit_test_state *uts) +{ + char fdt[4096]; + ulong addr; + int ret; + + ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt))); + addr = map_to_sysmem(fdt); + set_working_fdt_addr(addr); + + ret = fdt_test_get_value_common(uts, "/test-node@1234"); + if (!ret) + ret = fdt_test_get_value_common(uts, "testnodealias"); + if (ret) + return ret; + /* Test getting default element of /nonexistent node */ ut_assertok(console_record_reset_enable()); ut_asserteq(1, run_command("fdt get value fnode /nonexistent nonexistent", 1)); ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); ut_assertok(ut_check_console_end(uts)); + /* Test getting default element of bad alias */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt get value vbadalias badalias nonexistent", 1)); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting default element of nonexistent alias */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt get value vnoalias noalias nonexistent", 1)); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_BADPATH"); + ut_assertok(ut_check_console_end(uts)); + return 0; } FDT_TEST(fdt_test_get_value, UT_TESTF_CONSOLE_REC); -- cgit v1.1 From e2d7daa6c932646c25fadbf52ac68462de60e2f9 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:29 +0100 Subject: test: cmd: fdt: Test both string and integer arrays in 'fdt get value' The 'fdt get value' subcommand now supports extraction of integer value from integer arrays, add test for it, including a test for special case unindexed integer array read, which is handled as hash and treated as a long string instead of integer. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- test/cmd/fdt.c | 58 ++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index e04ba37..69a69c5 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -239,38 +239,64 @@ static int fdt_test_addr_resize(struct unit_test_state *uts) FDT_TEST(fdt_test_addr_resize, UT_TESTF_CONSOLE_REC); /* Test 'fdt get value' reading an fdt */ +static int fdt_test_get_value_string(struct unit_test_state *uts, + const char *node, const char *prop, + const char *idx, const char *strres, + const int intres) +{ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt get value var %s %s %s", + node, prop, idx ? : "")); + if (strres) { + ut_asserteq_str(strres, env_get("var")); + } else { + ut_asserteq(intres, env_get_hex("var", 0x1234)); + } + ut_assertok(ut_check_console_end(uts)); + + return 0; +} + static int fdt_test_get_value_common(struct unit_test_state *uts, const char *node) { /* Test getting default element of $node node clock-names property */ - ut_assertok(console_record_reset_enable()); - ut_assertok(run_commandf("fdt get value fdflt %s clock-names", node)); - ut_asserteq_str("fixed", env_get("fdflt")); - ut_assertok(ut_check_console_end(uts)); + fdt_test_get_value_string(uts, node, "clock-names", NULL, "fixed", 0); /* Test getting 0th element of $node node clock-names property */ - ut_assertok(console_record_reset_enable()); - ut_assertok(run_commandf("fdt get value fzero %s clock-names 0", node)); - ut_asserteq_str("fixed", env_get("fzero")); - ut_assertok(ut_check_console_end(uts)); + fdt_test_get_value_string(uts, node, "clock-names", "0", "fixed", 0); /* Test getting 1st element of $node node clock-names property */ - ut_assertok(console_record_reset_enable()); - ut_assertok(run_commandf("fdt get value fone %s clock-names 1", node)); - ut_asserteq_str("i2c", env_get("fone")); - ut_assertok(ut_check_console_end(uts)); + fdt_test_get_value_string(uts, node, "clock-names", "1", "i2c", 0); /* Test getting 2nd element of $node node clock-names property */ - ut_assertok(console_record_reset_enable()); - ut_assertok(run_commandf("fdt get value ftwo %s clock-names 2", node)); - ut_asserteq_str("spi", env_get("ftwo")); - ut_assertok(ut_check_console_end(uts)); + fdt_test_get_value_string(uts, node, "clock-names", "2", "spi", 0); + + /* + * Test getting default element of $node node regs property. + * The result here is highly unusual, the non-index value read from + * integer array is a string of concatenated values from the array, + * but only if the array is shorter than 40 characters. Anything + * longer is an error. This is a special case for handling hashes. + */ + fdt_test_get_value_string(uts, node, "regs", NULL, "3412000000100000", 0); + + /* Test getting 0th element of $node node regs property */ + fdt_test_get_value_string(uts, node, "regs", "0", NULL, 0x1234); + + /* Test getting 1st element of $node node regs property */ + fdt_test_get_value_string(uts, node, "regs", "1", NULL, 0x1000); /* Test missing 10th element of $node node clock-names property */ ut_assertok(console_record_reset_enable()); ut_asserteq(1, run_commandf("fdt get value ften %s clock-names 10", node)); ut_assertok(ut_check_console_end(uts)); + /* Test missing 10th element of $node node regs property */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_commandf("fdt get value ften %s regs 10", node)); + ut_assertok(ut_check_console_end(uts)); + /* Test getting default element of $node node nonexistent property */ ut_assertok(console_record_reset_enable()); ut_asserteq(1, run_commandf("fdt get value fnone %s nonexistent", node)); -- cgit v1.1 From 79bcd809f49ccb9ab7bc9712904475fbf5fb048c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:30 +0100 Subject: test: cmd: fdt: Test fdt move Add 'fdt move' test which works as follows: - Create simple FDT, map it to sysmem - 'move' the FDT into new zeroed out sysmem location - Verify newly active FDT is in the new location - Compare both locations The test case can be triggered using: " ./u-boot -Dc 'ut fdt' " To dump the full output from commands used during test, add '-v' flag. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- test/cmd/fdt.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index 69a69c5..023b83e 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -238,6 +238,40 @@ static int fdt_test_addr_resize(struct unit_test_state *uts) } FDT_TEST(fdt_test_addr_resize, UT_TESTF_CONSOLE_REC); +static int fdt_test_move(struct unit_test_state *uts) +{ + char fdt[256]; + ulong addr, newaddr = 0x10000; + const int size = sizeof(fdt); + uint32_t ts; + void *buf; + + /* Original source DT */ + ut_assertok(make_test_fdt(uts, fdt, size)); + ts = fdt_totalsize(fdt); + addr = map_to_sysmem(fdt); + set_working_fdt_addr(addr); + + /* Moved target DT location */ + buf = map_sysmem(newaddr, size); + memset(buf, 0, size); + + /* Test moving the working FDT to a new location */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt move %08x %08x %x", addr, newaddr, ts)); + ut_assert_nextline("Working FDT set to %lx", newaddr); + ut_assertok(ut_check_console_end(uts)); + + /* Compare the source and destination DTs */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("cmp.b %08x %08x %x", addr, newaddr, ts)); + ut_assert_nextline("Total of %d byte(s) were the same", ts); + ut_assertok(ut_check_console_end(uts)); + + return 0; +} +FDT_TEST(fdt_test_move, UT_TESTF_CONSOLE_REC); + /* Test 'fdt get value' reading an fdt */ static int fdt_test_get_value_string(struct unit_test_state *uts, const char *node, const char *prop, -- cgit v1.1 From 4efea813ef3a2f30917b0d14f07b5e072985830e Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:31 +0100 Subject: test: cmd: fdt: Test fdt resize Add 'fdt resize' test which works as follows: - Create simple FDT with extra size 0, map it to sysmem - 'resize' the FDT by 0x2000 bytes - Verify the new space has been added to the FDT The test case can be triggered using: " ./u-boot -Dc 'ut fdt' " To dump the full output from commands used during test, add '-v' flag. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- test/cmd/fdt.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index 023b83e..266fb6e 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -272,6 +272,30 @@ static int fdt_test_move(struct unit_test_state *uts) } FDT_TEST(fdt_test_move, UT_TESTF_CONSOLE_REC); +static int fdt_test_resize(struct unit_test_state *uts) +{ + char fdt[256]; + const unsigned int newsize = 0x2000; + uint32_t ts; + ulong addr; + + /* Original source DT */ + ut_assertok(make_test_fdt(uts, fdt, sizeof(fdt))); + fdt_shrink_to_minimum(fdt, 0); /* Resize with 0 extra bytes */ + ts = fdt_totalsize(fdt); + addr = map_to_sysmem(fdt); + set_working_fdt_addr(addr); + + /* Test resizing the working FDT and verify the new space was added */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt resize %x", newsize)); + ut_asserteq(ts + newsize, fdt_totalsize(fdt)); + ut_assertok(ut_check_console_end(uts)); + + return 0; +} +FDT_TEST(fdt_test_resize, UT_TESTF_CONSOLE_REC); + /* Test 'fdt get value' reading an fdt */ static int fdt_test_get_value_string(struct unit_test_state *uts, const char *node, const char *prop, -- cgit v1.1 From 4e22e12e3f57657c01b4c4f4451670b05b803cfd Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:33 +0100 Subject: test: cmd: fdt: Test fdt get name Add 'fdt get name' test which works as follows: - Create fuller FDT, map it to sysmem - Get name of / node 0, 1 and /clk-test node 0 - Compare output and validate the node name - Get name of / node 2 and /clk-test node 1 - Compare output and validate the node is not present - Get name of / node -1 and /clk-test node -1 - Compare output and validate the node name equals node 0 name - Check nonexistent node, verify the command errors out The test case can be triggered using: " ./u-boot -Dc 'ut fdt' " To dump the full output from commands used during test, add '-v' flag. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- test/cmd/fdt.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index 266fb6e..6af8cfe 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -402,6 +402,85 @@ static int fdt_test_get_value(struct unit_test_state *uts) } FDT_TEST(fdt_test_get_value, UT_TESTF_CONSOLE_REC); +static int fdt_test_get_name(struct unit_test_state *uts) +{ + char fdt[4096]; + ulong addr; + + ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt))); + addr = map_to_sysmem(fdt); + set_working_fdt_addr(addr); + + /* Test getting name of node 0 in /, which is /aliases node */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_command("fdt get name nzero / 0", 0)); + ut_asserteq_str("aliases", env_get("nzero")); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting name of node 1 in /, which is /test-node@1234 node */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_command("fdt get name none / 1", 0)); + ut_asserteq_str("test-node@1234", env_get("none")); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting name of node -1 in /, which is /aliases node, same as 0 */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_command("fdt get name nmone / -1", 0)); + ut_asserteq_str("aliases", env_get("nmone")); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting name of node 2 in /, which does not exist */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt get name ntwo / 2", 1)); + ut_assert_nextline("libfdt node not found"); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting name of node 0 in /test-node@1234, which is /subnode node */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_command("fdt get name snzero /test-node@1234 0", 0)); + ut_asserteq_str("subnode", env_get("snzero")); + ut_assertok(run_command("fdt get name asnzero testnodealias 0", 0)); + ut_asserteq_str("subnode", env_get("asnzero")); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting name of node 1 in /test-node@1234, which does not exist */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt get name snone /test-node@1234 1", 1)); + ut_assert_nextline("libfdt node not found"); + ut_asserteq(1, run_command("fdt get name asnone testnodealias 1", 1)); + ut_assert_nextline("libfdt node not found"); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting name of node -1 in /test-node@1234, which is /subnode node, same as 0 */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_command("fdt get name snmone /test-node@1234 -1", 0)); + ut_asserteq_str("subnode", env_get("snmone")); + ut_assertok(run_command("fdt get name asnmone testnodealias -1", 0)); + ut_asserteq_str("subnode", env_get("asnmone")); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting name of nonexistent node */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt get name nonode /nonexistent 0", 1)); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting name of bad alias */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt get name vbadalias badalias 0", 1)); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting name of nonexistent alias */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt get name vnoalias noalias 0", 1)); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_BADPATH"); + ut_assertok(ut_check_console_end(uts)); + + return 0; +} +FDT_TEST(fdt_test_get_name, UT_TESTF_CONSOLE_REC); + int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct unit_test *tests = UNIT_TEST_SUITE_START(fdt_test); -- cgit v1.1 From 1b025afca4ca303772a24c2a926cf9e75a1151bb Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:34 +0100 Subject: test: cmd: fdt: Test fdt get addr Add 'fdt get addr' test which works as follows: - Create fuller FDT, map it to sysmem - Get address of various properties - Compare addresses calculated by UT and fdt command This test is special in that it has to go through gruesome remapping scheme where the test calculates: - pointer offsets of the generated FDT root and the property being tested - map_sysmem() result of environment variable "fdtaddr" and the one set by the test matching address of property being tested - difference between the later and the former, to obtain offset of the DT property from start of DT The offsets must match in both the UT and the tested U-Boot, if they do not, the test fails. The test case can be triggered using: " ./u-boot -Dc 'ut fdt' " To dump the full output from commands used during test, add '-v' flag. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- test/cmd/fdt.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index 6af8cfe..ac2a1c7 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -481,6 +481,73 @@ static int fdt_test_get_name(struct unit_test_state *uts) } FDT_TEST(fdt_test_get_name, UT_TESTF_CONSOLE_REC); +static int fdt_test_get_addr_common(struct unit_test_state *uts, char *fdt, + const char *path, const char *prop) +{ + unsigned int offset; + int path_offset; + void *prop_ptr; + int len = 0; + + path_offset = fdt_path_offset(fdt, path); + ut_assert(path_offset >= 0); + prop_ptr = (void *)fdt_getprop(fdt, path_offset, prop, &len); + ut_assertnonnull(prop_ptr); + offset = (char *)prop_ptr - fdt; + + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt get addr pstr %s %s", path, prop)); + ut_asserteq((ulong)map_sysmem(env_get_hex("fdtaddr", 0x1234), 0), + (ulong)(map_sysmem(env_get_hex("pstr", 0x1234), 0) - offset)); + ut_assertok(ut_check_console_end(uts)); + + return 0; +} + +static int fdt_test_get_addr(struct unit_test_state *uts) +{ + char fdt[4096]; + ulong addr; + + ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt))); + addr = map_to_sysmem(fdt); + set_working_fdt_addr(addr); + + /* Test getting address of root node / string property "compatible" */ + fdt_test_get_addr_common(uts, fdt, "/", "compatible"); + + /* Test getting address of node /test-node@1234 stringlist property "clock-names" */ + fdt_test_get_addr_common(uts, fdt, "/test-node@1234", "clock-names"); + fdt_test_get_addr_common(uts, fdt, "testnodealias", "clock-names"); + + /* Test getting address of node /test-node@1234 u32 property "clock-frequency" */ + fdt_test_get_addr_common(uts, fdt, "/test-node@1234", "clock-frequency"); + fdt_test_get_addr_common(uts, fdt, "testnodealias", "clock-frequency"); + + /* Test getting address of node /test-node@1234 empty property "u-boot,empty-property" */ + fdt_test_get_addr_common(uts, fdt, "/test-node@1234", "u-boot,empty-property"); + fdt_test_get_addr_common(uts, fdt, "testnodealias", "u-boot,empty-property"); + + /* Test getting address of node /test-node@1234 array property "regs" */ + fdt_test_get_addr_common(uts, fdt, "/test-node@1234", "regs"); + fdt_test_get_addr_common(uts, fdt, "testnodealias", "regs"); + + /* Test getting address of node /test-node@1234/subnode non-existent property "noprop" */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt get addr pnoprop /test-node@1234/subnode noprop", 1)); + ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting address of non-existent node /test-node@1234/nonode@1 property "noprop" */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt get addr pnonode /test-node@1234/nonode@1 noprop", 1)); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + return 0; +} +FDT_TEST(fdt_test_get_addr, UT_TESTF_CONSOLE_REC); + int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct unit_test *tests = UNIT_TEST_SUITE_START(fdt_test); -- cgit v1.1 From 55d0f982f3b2fb732769f8ae5797e57b92d965e4 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:35 +0100 Subject: test: cmd: fdt: Test fdt get size Add 'fdt get size' test which works as follows: - Create fuller FDT, map it to sysmem - Get size of various properties - Get node count of available nodes - Test non-existent nodes and properties The test case can be triggered using: " ./u-boot -Dc 'ut fdt' " To dump the full output from commands used during test, add '-v' flag. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- test/cmd/fdt.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index ac2a1c7..fef15b5 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -548,6 +548,93 @@ static int fdt_test_get_addr(struct unit_test_state *uts) } FDT_TEST(fdt_test_get_addr, UT_TESTF_CONSOLE_REC); +static int fdt_test_get_size_common(struct unit_test_state *uts, + const char *path, const char *prop, + const unsigned int val) +{ + ut_assertok(console_record_reset_enable()); + if (prop) { + ut_assertok(run_commandf("fdt get size sstr %s %s", path, prop)); + } else { + ut_assertok(run_commandf("fdt get size sstr %s", path)); + } + ut_asserteq(val, env_get_hex("sstr", 0x1234)); + ut_assertok(ut_check_console_end(uts)); + + return 0; +} + +static int fdt_test_get_size(struct unit_test_state *uts) +{ + char fdt[4096]; + ulong addr; + + ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt))); + addr = map_to_sysmem(fdt); + set_working_fdt_addr(addr); + + /* Test getting size of root node / string property "compatible" */ + fdt_test_get_size_common(uts, "/", "compatible", 16); + + /* Test getting size of node /test-node@1234 stringlist property "clock-names" */ + fdt_test_get_size_common(uts, "/test-node@1234", "clock-names", 26); + fdt_test_get_size_common(uts, "testnodealias", "clock-names", 26); + + /* Test getting size of node /test-node@1234 u32 property "clock-frequency" */ + fdt_test_get_size_common(uts, "/test-node@1234", "clock-frequency", 4); + fdt_test_get_size_common(uts, "testnodealias", "clock-frequency", 4); + + /* Test getting size of node /test-node@1234 empty property "u-boot,empty-property" */ + fdt_test_get_size_common(uts, "/test-node@1234", "u-boot,empty-property", 0); + fdt_test_get_size_common(uts, "testnodealias", "u-boot,empty-property", 0); + + /* Test getting size of node /test-node@1234 array property "regs" */ + fdt_test_get_size_common(uts, "/test-node@1234", "regs", 8); + fdt_test_get_size_common(uts, "testnodealias", "regs", 8); + + /* Test getting node count of node / */ + fdt_test_get_size_common(uts, "/", NULL, 2); + + /* Test getting node count of node /test-node@1234/subnode */ + fdt_test_get_size_common(uts, "/test-node@1234/subnode", NULL, 0); + fdt_test_get_size_common(uts, "subnodealias", NULL, 0); + + /* Test getting size of node /test-node@1234/subnode non-existent property "noprop" */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt get size pnoprop /test-node@1234/subnode noprop", 1)); + ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND"); + ut_asserteq(1, run_command("fdt get size pnoprop subnodealias noprop", 1)); + ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting size of non-existent node /test-node@1234/nonode@1 property "noprop" */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt get size pnonode /test-node@1234/nonode@1 noprop", 1)); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting node count of non-existent node /test-node@1234/nonode@1 */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt get size pnonode /test-node@1234/nonode@1", 1)); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting node count of bad alias badalias */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt get size pnonode badalias noprop", 1)); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting node count of non-existent alias noalias */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt get size pnonode noalias", 1)); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_BADPATH"); + ut_assertok(ut_check_console_end(uts)); + + return 0; +} +FDT_TEST(fdt_test_get_size, UT_TESTF_CONSOLE_REC); + int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct unit_test *tests = UNIT_TEST_SUITE_START(fdt_test); -- cgit v1.1 From a6bcd977f94c45d3b3f5615d4aeeb6f3ff3b45fc Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:36 +0100 Subject: test: cmd: fdt: Test fdt set Add 'fdt set' test which works as follows: - Create fuller FDT, map it to sysmem - Set either existing property to overwrite it, or new property - Test setting both single properties as well as string and integer arrays - Test setting to non-existent nodes and aliases - Verify set values using 'fdt get value' The test case can be triggered using: " ./u-boot -Dc 'ut fdt' " To dump the full output from commands used during test, add '-v' flag. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- test/cmd/fdt.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index fef15b5..dabd35f 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -635,6 +635,150 @@ static int fdt_test_get_size(struct unit_test_state *uts) } FDT_TEST(fdt_test_get_size, UT_TESTF_CONSOLE_REC); +static int fdt_test_set_single(struct unit_test_state *uts, + const char *path, const char *prop, + const char *sval, int ival, bool integer) +{ + /* + * Set single element string/integer/ property into DT, that is: + * => fdt set /path property string + * => fdt set /path property integer + * => fdt set /path property + */ + ut_assertok(console_record_reset_enable()); + if (sval) { + ut_assertok(run_commandf("fdt set %s %s %s", path, prop, sval)); + } else if (integer) { + ut_assertok(run_commandf("fdt set %s %s <%d>", path, prop, ival)); + } else { + ut_assertok(run_commandf("fdt set %s %s", path, prop)); + } + + /* Validate the property is present and has correct value. */ + ut_assertok(run_commandf("fdt get value svar %s %s", path, prop)); + if (sval) { + ut_asserteq_str(sval, env_get("svar")); + } else if (integer) { + ut_asserteq(ival, env_get_hex("svar", 0x1234)); + } else { + ut_assertnull(env_get("svar")); + } + ut_assertok(ut_check_console_end(uts)); + + return 0; +} + +static int fdt_test_set_multi(struct unit_test_state *uts, + const char *path, const char *prop, + const char *sval1, const char *sval2, + int ival1, int ival2) +{ + /* + * Set multi element string/integer array property in DT, that is: + * => fdt set /path property + * => fdt set /path property + * + * The set is done twice in here deliberately, The first set adds + * the property with an extra trailing element in its array to make + * the array longer, the second set is the expected final content of + * the array property. The longer array is used to verify that the + * new array is correctly sized and read past the new array length + * triggers failure. + */ + ut_assertok(console_record_reset_enable()); + if (sval1 && sval2) { + ut_assertok(run_commandf("fdt set %s %s %s %s end", path, prop, sval1, sval2)); + ut_assertok(run_commandf("fdt set %s %s %s %s", path, prop, sval1, sval2)); + } else { + ut_assertok(run_commandf("fdt set %s %s <%d %d 10>", path, prop, ival1, ival2)); + ut_assertok(run_commandf("fdt set %s %s <%d %d>", path, prop, ival1, ival2)); + } + + /* + * Validate the property is present and has correct value. + * + * The "end/10" above and "svarn" below is used to validate that + * previous 'fdt set' to longer array does not polute newly set + * shorter array. + */ + ut_assertok(run_commandf("fdt get value svar1 %s %s 0", path, prop)); + ut_assertok(run_commandf("fdt get value svar2 %s %s 1", path, prop)); + ut_asserteq(1, run_commandf("fdt get value svarn %s %s 2", path, prop)); + if (sval1 && sval2) { + ut_asserteq_str(sval1, env_get("svar1")); + ut_asserteq_str(sval2, env_get("svar2")); + ut_assertnull(env_get("svarn")); + } else { + ut_asserteq(ival1, env_get_hex("svar1", 0x1234)); + ut_asserteq(ival2, env_get_hex("svar2", 0x1234)); + ut_assertnull(env_get("svarn")); + } + ut_assertok(ut_check_console_end(uts)); + + return 0; +} + +static int fdt_test_set_node(struct unit_test_state *uts, + const char *path, const char *prop) +{ + fdt_test_set_single(uts, path, prop, "new", 0, false); + fdt_test_set_single(uts, path, prop, "rewrite", 0, false); + fdt_test_set_single(uts, path, prop, NULL, 42, true); + fdt_test_set_single(uts, path, prop, NULL, 0, false); + fdt_test_set_multi(uts, path, prop, NULL, NULL, 42, 1701); + fdt_test_set_multi(uts, path, prop, NULL, NULL, 74656, 9); + fdt_test_set_multi(uts, path, prop, "42", "1701", 0, 0); + fdt_test_set_multi(uts, path, prop, "74656", "9", 0, 0); + + return 0; +} + +static int fdt_test_set(struct unit_test_state *uts) +{ + char fdt[8192]; + ulong addr; + + ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt))); + fdt_shrink_to_minimum(fdt, 4096); /* Resize with 4096 extra bytes */ + addr = map_to_sysmem(fdt); + set_working_fdt_addr(addr); + + /* Test setting of root node / existing property "compatible" */ + fdt_test_set_node(uts, "/", "compatible"); + + /* Test setting of root node / new property "newproperty" */ + fdt_test_set_node(uts, "/", "newproperty"); + + /* Test setting of subnode existing property "compatible" */ + fdt_test_set_node(uts, "/test-node@1234/subnode", "compatible"); + fdt_test_set_node(uts, "subnodealias", "compatible"); + + /* Test setting of subnode new property "newproperty" */ + fdt_test_set_node(uts, "/test-node@1234/subnode", "newproperty"); + fdt_test_set_node(uts, "subnodealias", "newproperty"); + + /* Test setting property of non-existent node */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt set /no-node noprop", 1)); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test setting property of non-existent alias */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt set noalias noprop", 1)); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_BADPATH"); + ut_assertok(ut_check_console_end(uts)); + + /* Test setting property of bad alias */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_command("fdt set badalias noprop", 1)); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + return 0; +} +FDT_TEST(fdt_test_set, UT_TESTF_CONSOLE_REC); + int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct unit_test *tests = UNIT_TEST_SUITE_START(fdt_test); -- cgit v1.1 From e7c7878455ec29806e1775ce37129e5a8e5dfb0d Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:37 +0100 Subject: test: cmd: fdt: Test fdt mknode Add 'fdt mknode' test which works as follows: - Create fuller FDT, map it to sysmem - Create node either in / or subnode - Attempt to create node over existing node, which fails - Attempt to create subnodes in non-existing nodes or aliases - Verify created nodes using fdt list command The test case can be triggered using: " ./u-boot -Dc 'ut fdt' " To dump the full output from commands used during test, add '-v' flag. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- test/cmd/fdt.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index dabd35f..4d45afa 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -779,6 +779,74 @@ static int fdt_test_set(struct unit_test_state *uts) } FDT_TEST(fdt_test_set, UT_TESTF_CONSOLE_REC); +static int fdt_test_mknode(struct unit_test_state *uts) +{ + char fdt[8192]; + ulong addr; + + ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt))); + fdt_shrink_to_minimum(fdt, 4096); /* Resize with 4096 extra bytes */ + addr = map_to_sysmem(fdt); + set_working_fdt_addr(addr); + + /* Test creation of new node in / */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt mknode / newnode")); + ut_assertok(run_commandf("fdt list /newnode")); + ut_assert_nextline("newnode {"); + ut_assert_nextline("};"); + ut_assertok(ut_check_console_end(uts)); + + /* Test creation of new node in /test-node@1234 */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt mknode /test-node@1234 newsubnode")); + ut_assertok(run_commandf("fdt list /test-node@1234/newsubnode")); + ut_assert_nextline("newsubnode {"); + ut_assert_nextline("};"); + ut_assertok(ut_check_console_end(uts)); + + /* Test creation of new node in /test-node@1234 by alias */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt mknode testnodealias newersubnode")); + ut_assertok(run_commandf("fdt list testnodealias/newersubnode")); + ut_assert_nextline("newersubnode {"); + ut_assert_nextline("};"); + ut_assertok(ut_check_console_end(uts)); + + /* Test creation of new node in /test-node@1234 over existing node */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_commandf("fdt mknode testnodealias newsubnode")); + ut_assert_nextline("libfdt fdt_add_subnode(): FDT_ERR_EXISTS"); + ut_assertok(ut_check_console_end(uts)); + + /* Test creation of new node in /test-node@1234 by alias over existing node */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_commandf("fdt mknode testnodealias newersubnode")); + ut_assert_nextline("libfdt fdt_add_subnode(): FDT_ERR_EXISTS"); + ut_assertok(ut_check_console_end(uts)); + + /* Test creation of new node in non-existent node */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_commandf("fdt mknode /no-node newnosubnode")); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test creation of new node in non-existent alias */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_commandf("fdt mknode noalias newfailsubnode")); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_BADPATH"); + ut_assertok(ut_check_console_end(uts)); + + /* Test creation of new node in bad alias */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_commandf("fdt mknode badalias newbadsubnode")); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + return 0; +} +FDT_TEST(fdt_test_mknode, UT_TESTF_CONSOLE_REC); + int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct unit_test *tests = UNIT_TEST_SUITE_START(fdt_test); -- cgit v1.1 From caec1be706ac4e36d55e6343893a956f6ccf7464 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:38 +0100 Subject: test: cmd: fdt: Test fdt rm Add 'fdt rm' test which works as follows: - Create fuller FDT, map it to sysmem - Selectively delete nodes or properties by both path and aliases - Verify created nodes or properties using fdt print command The test case can be triggered using: " ./u-boot -Dc 'ut fdt' " To dump the full output from commands used during test, add '-v' flag. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- test/cmd/fdt.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index 4d45afa..cb86fc0 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -847,6 +847,90 @@ static int fdt_test_mknode(struct unit_test_state *uts) } FDT_TEST(fdt_test_mknode, UT_TESTF_CONSOLE_REC); +static int fdt_test_rm(struct unit_test_state *uts) +{ + char fdt[4096]; + ulong addr; + + ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt))); + addr = map_to_sysmem(fdt); + set_working_fdt_addr(addr); + + /* Test removal of property in root node / */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt print / compatible")); + ut_assert_nextline("compatible = \"u-boot,fdt-test\""); + ut_assertok(run_commandf("fdt rm / compatible")); + ut_asserteq(1, run_commandf("fdt print / compatible")); + ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test removal of property clock-names in subnode /test-node@1234 */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt print /test-node@1234 clock-names")); + ut_assert_nextline("clock-names = \"fixed\", \"i2c\", \"spi\", \"uart2\", \"uart1\""); + ut_assertok(run_commandf("fdt rm /test-node@1234 clock-names")); + ut_asserteq(1, run_commandf("fdt print /test-node@1234 clock-names")); + ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test removal of property u-boot,empty-property in subnode /test-node@1234 by alias */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt print testnodealias u-boot,empty-property")); + ut_assert_nextline("testnodealias u-boot,empty-property"); + ut_assertok(run_commandf("fdt rm testnodealias u-boot,empty-property")); + ut_asserteq(1, run_commandf("fdt print testnodealias u-boot,empty-property")); + ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test removal of non-existent property noprop in subnode /test-node@1234 */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_commandf("fdt rm /test-node@1234 noprop")); + ut_assert_nextline("libfdt fdt_delprop(): FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test removal of non-existent node /no-node@5678 */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_commandf("fdt rm /no-node@5678")); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test removal of subnode /test-node@1234/subnode by alias */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt rm subnodealias")); + ut_asserteq(1, run_commandf("fdt print /test-node@1234/subnode")); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test removal of node by non-existent alias */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_commandf("fdt rm noalias")); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_BADPATH"); + ut_assertok(ut_check_console_end(uts)); + + /* Test removal of node by bad alias */ + ut_assertok(console_record_reset_enable()); + ut_asserteq(1, run_commandf("fdt rm noalias")); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_BADPATH"); + ut_assertok(ut_check_console_end(uts)); + + /* Test removal of node /test-node@1234 */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt rm /test-node@1234")); + ut_asserteq(1, run_commandf("fdt print /test-node@1234")); + ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND"); + ut_assertok(ut_check_console_end(uts)); + + /* Test removal of node / */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt rm /")); + ut_asserteq(1, run_commandf("fdt print /")); + ut_assertok(ut_check_console_end(uts)); + + return 0; +} +FDT_TEST(fdt_test_rm, UT_TESTF_CONSOLE_REC); + int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct unit_test *tests = UNIT_TEST_SUITE_START(fdt_test); -- cgit v1.1 From aa89aebb17531a3e8b6729c812a68d5e37008730 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Thu, 2 Mar 2023 04:08:40 +0100 Subject: test: cmd: fdt: Test fdt bootcpu Add 'fdt bootcpu' test which works as follows: - Create basic FDT, map it to sysmem - Print the FDT bootcpu - Set the FDT bootcpu and read the value back using 'fdt header get' - Perform the previous step twice to validate bootcpu overwrite The test case can be triggered using: " ./u-boot -Dc 'ut fdt' " To dump the full output from commands used during test, add '-v' flag. Signed-off-by: Marek Vasut Reviewed-by: Simon Glass --- test/cmd/fdt.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c index cb86fc0..cdbaf8c 100644 --- a/test/cmd/fdt.c +++ b/test/cmd/fdt.c @@ -931,6 +931,39 @@ static int fdt_test_rm(struct unit_test_state *uts) } FDT_TEST(fdt_test_rm, UT_TESTF_CONSOLE_REC); +static int fdt_test_bootcpu(struct unit_test_state *uts) +{ + char fdt[256]; + ulong addr; + int i; + + ut_assertok(make_test_fdt(uts, fdt, sizeof(fdt))); + addr = map_to_sysmem(fdt); + set_working_fdt_addr(addr); + + /* Test getting default bootcpu entry */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt header get bootcpu boot_cpuid_phys")); + ut_asserteq(0, env_get_ulong("bootcpu", 10, 0x1234)); + ut_assertok(ut_check_console_end(uts)); + + /* Test setting and getting new bootcpu entry, twice, to test overwrite */ + for (i = 42; i <= 43; i++) { + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt bootcpu %d", i)); + ut_assertok(ut_check_console_end(uts)); + + /* Test getting new bootcpu entry */ + ut_assertok(console_record_reset_enable()); + ut_assertok(run_commandf("fdt header get bootcpu boot_cpuid_phys")); + ut_asserteq(i, env_get_ulong("bootcpu", 10, 0x1234)); + ut_assertok(ut_check_console_end(uts)); + } + + return 0; +} +FDT_TEST(fdt_test_bootcpu, UT_TESTF_CONSOLE_REC); + int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { struct unit_test *tests = UNIT_TEST_SUITE_START(fdt_test); -- cgit v1.1