blob: d7b96bc572554fb5cbad4b951bc95cf85e625e84 [file] [log] [blame]
Simon Glass74724482022-07-13 06:06:59 -06001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Tests for fdt command
4 *
Marek Vasutf53e9732023-04-22 14:59:58 +02005 * Copyright 2022 Google LLC
Simon Glass74724482022-07-13 06:06:59 -06006 */
7
Simon Glass74724482022-07-13 06:06:59 -06008#include <console.h>
9#include <fdt_support.h>
10#include <mapmem.h>
11#include <asm/global_data.h>
12#include <linux/libfdt.h>
13#include <test/suites.h>
14#include <test/ut.h>
15
16DECLARE_GLOBAL_DATA_PTR;
Marek Vasut3998b452023-03-02 04:08:45 +010017/*
18 * Missing tests:
19 * fdt boardsetup - Do board-specific set up
20 * fdt checksign [<addr>] - check FIT signature
21 * <addr> - address of key blob
22 * default gd->fdt_blob
23 */
Simon Glass74724482022-07-13 06:06:59 -060024
25/* Declare a new fdt test */
26#define FDT_TEST(_name, _flags) UNIT_TEST(_name, _flags, fdt_test)
27
28/**
29 * make_test_fdt() - Create an FDT with just a root node
30 *
Simon Glass2b60f8c2024-08-22 07:57:56 -060031 * The size is set to the minimum needed. This also sets the working FDT and
32 * checks that the expected output is received from doing so.
Simon Glass74724482022-07-13 06:06:59 -060033 *
34 * @uts: Test state
35 * @fdt: Place to write FDT
36 * @size: Maximum size of space for fdt
Simon Glass2b60f8c2024-08-22 07:57:56 -060037 * @addrp: Returns address of the devicetree
Simon Glass74724482022-07-13 06:06:59 -060038 */
Simon Glass2b60f8c2024-08-22 07:57:56 -060039static int make_test_fdt(struct unit_test_state *uts, void *fdt, int size,
40 ulong *addrp)
Simon Glass74724482022-07-13 06:06:59 -060041{
Simon Glass2b60f8c2024-08-22 07:57:56 -060042 ulong addr;
43
Simon Glass74724482022-07-13 06:06:59 -060044 ut_assertok(fdt_create(fdt, size));
45 ut_assertok(fdt_finish_reservemap(fdt));
46 ut_assert(fdt_begin_node(fdt, "") >= 0);
47 ut_assertok(fdt_end_node(fdt));
48 ut_assertok(fdt_finish(fdt));
49
Simon Glass2b60f8c2024-08-22 07:57:56 -060050 addr = map_to_sysmem(fdt);
51 set_working_fdt_addr(addr);
52 ut_assert_nextline("Working FDT set to %lx", addr);
53 *addrp = addr;
54
Simon Glass74724482022-07-13 06:06:59 -060055 return 0;
56}
57
Marek Vasutd6729762023-03-02 04:08:27 +010058/**
59 * make_fuller_fdt() - Create an FDT with root node and properties
60 *
Simon Glass2b60f8c2024-08-22 07:57:56 -060061 * The size is set to the minimum needed. This also sets the working FDT and
62 * checks that the expected output is received from doing so.
Marek Vasutd6729762023-03-02 04:08:27 +010063 *
64 * @uts: Test state
65 * @fdt: Place to write FDT
66 * @size: Maximum size of space for fdt
Simon Glass2b60f8c2024-08-22 07:57:56 -060067 * @addrp: Returns address of the devicetree
Marek Vasutd6729762023-03-02 04:08:27 +010068 */
Simon Glass2b60f8c2024-08-22 07:57:56 -060069static int make_fuller_fdt(struct unit_test_state *uts, void *fdt, int size,
70 ulong *addrp)
Marek Vasutd6729762023-03-02 04:08:27 +010071{
72 fdt32_t regs[2] = { cpu_to_fdt32(0x1234), cpu_to_fdt32(0x1000) };
Simon Glass2b60f8c2024-08-22 07:57:56 -060073 ulong addr;
Marek Vasutd6729762023-03-02 04:08:27 +010074
75 /*
76 * Assemble the following DT for test purposes:
77 *
78 * / {
79 * #address-cells = <0x00000001>;
80 * #size-cells = <0x00000001>;
81 * compatible = "u-boot,fdt-test";
82 * model = "U-Boot FDT test";
83 *
84 * aliases {
85 * badalias = "/bad/alias";
86 * subnodealias = "/test-node@1234/subnode";
87 * testnodealias = "/test-node@1234";
88 * };
89 *
90 * test-node@1234 {
91 * #address-cells = <0x00000000>;
92 * #size-cells = <0x00000000>;
93 * compatible = "u-boot,fdt-test-device1";
94 * clock-names = "fixed", "i2c", "spi", "uart2", "uart1";
95 * u-boot,empty-property;
96 * clock-frequency = <0x00fde800>;
97 * regs = <0x00001234 0x00001000>;
98 *
99 * subnode {
100 * #address-cells = <0x00000000>;
101 * #size-cells = <0x00000000>;
102 * compatible = "u-boot,fdt-subnode-test-device";
103 * };
104 * };
105 * };
106 */
107
108 ut_assertok(fdt_create(fdt, size));
109 ut_assertok(fdt_finish_reservemap(fdt));
110 ut_assert(fdt_begin_node(fdt, "") >= 0);
111
112 ut_assertok(fdt_property_u32(fdt, "#address-cells", 1));
113 ut_assertok(fdt_property_u32(fdt, "#size-cells", 1));
114 /* <string> */
115 ut_assertok(fdt_property_string(fdt, "compatible", "u-boot,fdt-test"));
116 /* <string> */
117 ut_assertok(fdt_property_string(fdt, "model", "U-Boot FDT test"));
118
119 ut_assert(fdt_begin_node(fdt, "aliases") >= 0);
120 /* <string> */
121 ut_assertok(fdt_property_string(fdt, "badalias", "/bad/alias"));
122 /* <string> */
123 ut_assertok(fdt_property_string(fdt, "subnodealias", "/test-node@1234/subnode"));
124 /* <string> */
125 ut_assertok(fdt_property_string(fdt, "testnodealias", "/test-node@1234"));
126 ut_assertok(fdt_end_node(fdt));
127
128 ut_assert(fdt_begin_node(fdt, "test-node@1234") >= 0);
129 ut_assertok(fdt_property_cell(fdt, "#address-cells", 0));
130 ut_assertok(fdt_property_cell(fdt, "#size-cells", 0));
131 /* <string> */
132 ut_assertok(fdt_property_string(fdt, "compatible", "u-boot,fdt-test-device1"));
133 /* <stringlist> */
134 ut_assertok(fdt_property(fdt, "clock-names", "fixed\0i2c\0spi\0uart2\0uart1\0", 26));
135 /* <empty> */
136 ut_assertok(fdt_property(fdt, "u-boot,empty-property", NULL, 0));
137 /*
138 * <u32>
139 * This value is deliberate as it used to break cmd/fdt.c
140 * is_printable_string() implementation.
141 */
142 ut_assertok(fdt_property_u32(fdt, "clock-frequency", 16640000));
143 /* <prop-encoded-array> */
144 ut_assertok(fdt_property(fdt, "regs", &regs, sizeof(regs)));
145 ut_assert(fdt_begin_node(fdt, "subnode") >= 0);
146 ut_assertok(fdt_property_cell(fdt, "#address-cells", 0));
147 ut_assertok(fdt_property_cell(fdt, "#size-cells", 0));
148 ut_assertok(fdt_property_string(fdt, "compatible", "u-boot,fdt-subnode-test-device"));
149 ut_assertok(fdt_end_node(fdt));
150 ut_assertok(fdt_end_node(fdt));
151
152 ut_assertok(fdt_end_node(fdt));
153 ut_assertok(fdt_finish(fdt));
154
Simon Glass2b60f8c2024-08-22 07:57:56 -0600155 addr = map_to_sysmem(fdt);
156 set_working_fdt_addr(addr);
157 ut_assert_nextline("Working FDT set to %lx", addr);
158 *addrp = addr;
159
Marek Vasutd6729762023-03-02 04:08:27 +0100160 return 0;
161}
162
Simon Glass74724482022-07-13 06:06:59 -0600163/* Test 'fdt addr' getting/setting address */
164static int fdt_test_addr(struct unit_test_state *uts)
165{
166 const void *fdt_blob, *new_fdt;
167 char fdt[256];
168 ulong addr;
169 int ret;
170
171 ut_assertok(console_record_reset_enable());
172 ut_assertok(run_command("fdt addr -c", 0));
173 ut_assert_nextline("Control fdt: %08lx",
174 (ulong)map_to_sysmem(gd->fdt_blob));
175 ut_assertok(ut_check_console_end(uts));
176
177 /* The working fdt is not set, so this should fail */
178 set_working_fdt_addr(0);
Simon Glassbaf41412022-10-11 09:47:12 -0600179 ut_assert_nextline("Working FDT set to 0");
Simon Glass74724482022-07-13 06:06:59 -0600180 ut_asserteq(CMD_RET_FAILURE, run_command("fdt addr", 0));
Simon Glass40565bb2023-10-01 19:15:18 -0600181
182 /*
183 * sandbox fails the check for !blob since the 0 pointer is mapped to
184 * memory somewhere other than at 0x0
185 */
186 if (IS_ENABLED(CONFIG_SANDBOX))
187 ut_assert_nextline("libfdt fdt_check_header(): FDT_ERR_BADMAGIC");
Simon Glass74724482022-07-13 06:06:59 -0600188 ut_assertok(ut_check_console_end(uts));
189
190 /* Set up a working FDT and try again */
Simon Glass2b60f8c2024-08-22 07:57:56 -0600191 ut_assertok(make_test_fdt(uts, fdt, sizeof(fdt), &addr));
Simon Glass74724482022-07-13 06:06:59 -0600192 ut_assertok(run_command("fdt addr", 0));
193 ut_assert_nextline("Working fdt: %08lx", (ulong)map_to_sysmem(fdt));
194 ut_assertok(ut_check_console_end(uts));
195
196 /* Set the working FDT */
197 set_working_fdt_addr(0);
Simon Glassbaf41412022-10-11 09:47:12 -0600198 ut_assert_nextline("Working FDT set to 0");
Evgeny Bachinin0d73c232023-03-20 11:23:13 +0300199 ut_assertok(run_commandf("fdt addr %08lx", addr));
Simon Glassbaf41412022-10-11 09:47:12 -0600200 ut_assert_nextline("Working FDT set to %lx", addr);
Simon Glass74724482022-07-13 06:06:59 -0600201 ut_asserteq(addr, map_to_sysmem(working_fdt));
202 ut_assertok(ut_check_console_end(uts));
203 set_working_fdt_addr(0);
Simon Glassbaf41412022-10-11 09:47:12 -0600204 ut_assert_nextline("Working FDT set to 0");
Simon Glass74724482022-07-13 06:06:59 -0600205
Simon Glassbaf41412022-10-11 09:47:12 -0600206 /* Set the control FDT */
Simon Glass74724482022-07-13 06:06:59 -0600207 fdt_blob = gd->fdt_blob;
208 gd->fdt_blob = NULL;
Evgeny Bachinin0d73c232023-03-20 11:23:13 +0300209 ret = run_commandf("fdt addr -c %08lx", addr);
Simon Glass74724482022-07-13 06:06:59 -0600210 new_fdt = gd->fdt_blob;
211 gd->fdt_blob = fdt_blob;
212 ut_assertok(ret);
213 ut_asserteq(addr, map_to_sysmem(new_fdt));
214 ut_assertok(ut_check_console_end(uts));
215
216 /* Test setting an invalid FDT */
217 fdt[0] = 123;
Evgeny Bachinin0d73c232023-03-20 11:23:13 +0300218 ut_asserteq(1, run_commandf("fdt addr %08lx", addr));
Simon Glass74724482022-07-13 06:06:59 -0600219 ut_assert_nextline("libfdt fdt_check_header(): FDT_ERR_BADMAGIC");
220 ut_assertok(ut_check_console_end(uts));
221
222 /* Test detecting an invalid FDT */
223 fdt[0] = 123;
224 set_working_fdt_addr(addr);
Simon Glassbaf41412022-10-11 09:47:12 -0600225 ut_assert_nextline("Working FDT set to %lx", addr);
Simon Glass74724482022-07-13 06:06:59 -0600226 ut_asserteq(1, run_commandf("fdt addr"));
227 ut_assert_nextline("libfdt fdt_check_header(): FDT_ERR_BADMAGIC");
228 ut_assertok(ut_check_console_end(uts));
229
230 return 0;
231}
Simon Glass9b997622024-08-22 07:57:50 -0600232FDT_TEST(fdt_test_addr, UTF_CONSOLE);
Simon Glass74724482022-07-13 06:06:59 -0600233
234/* Test 'fdt addr' resizing an fdt */
Marek Vasutab40faf2023-03-02 04:08:25 +0100235static int fdt_test_addr_resize(struct unit_test_state *uts)
Simon Glass74724482022-07-13 06:06:59 -0600236{
237 char fdt[256];
238 const int newsize = sizeof(fdt) / 2;
239 ulong addr;
240
Simon Glass2b60f8c2024-08-22 07:57:56 -0600241 ut_assertok(make_test_fdt(uts, fdt, sizeof(fdt), &addr));
Simon Glass74724482022-07-13 06:06:59 -0600242
243 /* Test setting and resizing the working FDT to a larger size */
244 ut_assertok(console_record_reset_enable());
Evgeny Bachinin0d73c232023-03-20 11:23:13 +0300245 ut_assertok(run_commandf("fdt addr %08lx %x", addr, newsize));
Simon Glassbaf41412022-10-11 09:47:12 -0600246 ut_assert_nextline("Working FDT set to %lx", addr);
Simon Glass74724482022-07-13 06:06:59 -0600247 ut_assertok(ut_check_console_end(uts));
248
249 /* Try shrinking it */
Evgeny Bachinin0d73c232023-03-20 11:23:13 +0300250 ut_assertok(run_commandf("fdt addr %08lx %zx", addr, sizeof(fdt) / 4));
Simon Glassbaf41412022-10-11 09:47:12 -0600251 ut_assert_nextline("Working FDT set to %lx", addr);
Simon Glass74724482022-07-13 06:06:59 -0600252 ut_assert_nextline("New length %d < existing length %d, ignoring",
253 (int)sizeof(fdt) / 4, newsize);
254 ut_assertok(ut_check_console_end(uts));
255
256 /* ...quietly */
Evgeny Bachinin0d73c232023-03-20 11:23:13 +0300257 ut_assertok(run_commandf("fdt addr -q %08lx %zx", addr, sizeof(fdt) / 4));
Simon Glass74724482022-07-13 06:06:59 -0600258 ut_assertok(ut_check_console_end(uts));
259
260 /* We cannot easily provoke errors in fdt_open_into(), so ignore that */
261
262 return 0;
263}
Simon Glass9b997622024-08-22 07:57:50 -0600264FDT_TEST(fdt_test_addr_resize, UTF_CONSOLE);
Simon Glass74724482022-07-13 06:06:59 -0600265
Marek Vasut05728722023-03-02 04:08:30 +0100266static int fdt_test_move(struct unit_test_state *uts)
267{
268 char fdt[256];
269 ulong addr, newaddr = 0x10000;
270 const int size = sizeof(fdt);
271 uint32_t ts;
272 void *buf;
273
274 /* Original source DT */
Simon Glass2b60f8c2024-08-22 07:57:56 -0600275 ut_assertok(make_test_fdt(uts, fdt, size, &addr));
Marek Vasut05728722023-03-02 04:08:30 +0100276 ts = fdt_totalsize(fdt);
Marek Vasut05728722023-03-02 04:08:30 +0100277
278 /* Moved target DT location */
279 buf = map_sysmem(newaddr, size);
280 memset(buf, 0, size);
281
282 /* Test moving the working FDT to a new location */
283 ut_assertok(console_record_reset_enable());
Evgeny Bachinin0d73c232023-03-20 11:23:13 +0300284 ut_assertok(run_commandf("fdt move %08lx %08lx %x", addr, newaddr, ts));
Marek Vasut05728722023-03-02 04:08:30 +0100285 ut_assert_nextline("Working FDT set to %lx", newaddr);
286 ut_assertok(ut_check_console_end(uts));
287
288 /* Compare the source and destination DTs */
289 ut_assertok(console_record_reset_enable());
Evgeny Bachinin0d73c232023-03-20 11:23:13 +0300290 ut_assertok(run_commandf("cmp.b %08lx %08lx %x", addr, newaddr, ts));
Marek Vasut05728722023-03-02 04:08:30 +0100291 ut_assert_nextline("Total of %d byte(s) were the same", ts);
292 ut_assertok(ut_check_console_end(uts));
293
294 return 0;
295}
Simon Glass9b997622024-08-22 07:57:50 -0600296FDT_TEST(fdt_test_move, UTF_CONSOLE);
Marek Vasut05728722023-03-02 04:08:30 +0100297
Marek Vasut8fa28352023-03-02 04:08:31 +0100298static int fdt_test_resize(struct unit_test_state *uts)
299{
300 char fdt[256];
301 const unsigned int newsize = 0x2000;
302 uint32_t ts;
303 ulong addr;
304
305 /* Original source DT */
Simon Glass2b60f8c2024-08-22 07:57:56 -0600306 ut_assertok(make_test_fdt(uts, fdt, sizeof(fdt), &addr));
Marek Vasut8fa28352023-03-02 04:08:31 +0100307 fdt_shrink_to_minimum(fdt, 0); /* Resize with 0 extra bytes */
308 ts = fdt_totalsize(fdt);
Marek Vasut8fa28352023-03-02 04:08:31 +0100309
310 /* Test resizing the working FDT and verify the new space was added */
311 ut_assertok(console_record_reset_enable());
312 ut_assertok(run_commandf("fdt resize %x", newsize));
313 ut_asserteq(ts + newsize, fdt_totalsize(fdt));
314 ut_assertok(ut_check_console_end(uts));
315
316 return 0;
317}
Simon Glass9b997622024-08-22 07:57:50 -0600318FDT_TEST(fdt_test_resize, UTF_CONSOLE);
Marek Vasut8fa28352023-03-02 04:08:31 +0100319
Marek Vasutb0cd7cc2023-03-02 04:08:32 +0100320static int fdt_test_print_list_common(struct unit_test_state *uts,
321 const char *opc, const char *node)
322{
323 /*
324 * Test printing/listing the working FDT
325 * subnode $node/subnode
326 */
327 ut_assertok(console_record_reset_enable());
328 ut_assertok(run_commandf("fdt %s %s/subnode", opc, node));
329 ut_assert_nextline("subnode {");
330 ut_assert_nextline("\t#address-cells = <0x00000000>;");
331 ut_assert_nextline("\t#size-cells = <0x00000000>;");
332 ut_assert_nextline("\tcompatible = \"u-boot,fdt-subnode-test-device\";");
333 ut_assert_nextline("};");
334 ut_assertok(ut_check_console_end(uts));
335
336 /*
337 * Test printing/listing the working FDT
338 * path / string property model
339 */
340 ut_assertok(console_record_reset_enable());
341 ut_assertok(run_commandf("fdt %s / model", opc));
342 ut_assert_nextline("model = \"U-Boot FDT test\"");
343 ut_assertok(ut_check_console_end(uts));
344
345 /*
346 * Test printing/listing the working FDT
347 * path $node string property compatible
348 */
349 ut_assertok(console_record_reset_enable());
350 ut_assertok(run_commandf("fdt %s %s compatible", opc, node));
351 ut_assert_nextline("compatible = \"u-boot,fdt-test-device1\"");
352 ut_assertok(ut_check_console_end(uts));
353
354 /*
355 * Test printing/listing the working FDT
356 * path $node stringlist property clock-names
357 */
358 ut_assertok(console_record_reset_enable());
359 ut_assertok(run_commandf("fdt %s %s clock-names", opc, node));
360 ut_assert_nextline("clock-names = \"fixed\", \"i2c\", \"spi\", \"uart2\", \"uart1\"");
361 ut_assertok(ut_check_console_end(uts));
362
363 /*
364 * Test printing/listing the working FDT
365 * path $node u32 property clock-frequency
366 */
367 ut_assertok(console_record_reset_enable());
368 ut_assertok(run_commandf("fdt %s %s clock-frequency", opc, node));
369 ut_assert_nextline("clock-frequency = <0x00fde800>");
370 ut_assertok(ut_check_console_end(uts));
371
372 /*
373 * Test printing/listing the working FDT
374 * path $node empty property u-boot,empty-property
375 */
376 ut_assertok(console_record_reset_enable());
377 ut_assertok(run_commandf("fdt %s %s u-boot,empty-property", opc, node));
378 /*
379 * This is the only 'fdt print' / 'fdt list' incantation which
380 * prefixes the property with node path. This has been in U-Boot
381 * since the beginning of the command 'fdt', keep it.
382 */
383 ut_assert_nextline("%s u-boot,empty-property", node);
384 ut_assertok(ut_check_console_end(uts));
385
386 /*
387 * Test printing/listing the working FDT
388 * path $node prop-encoded array property regs
389 */
390 ut_assertok(console_record_reset_enable());
391 ut_assertok(run_commandf("fdt %s %s regs", opc, node));
392 ut_assert_nextline("regs = <0x00001234 0x00001000>");
393 ut_assertok(ut_check_console_end(uts));
394
395 return 0;
396}
397
398static int fdt_test_print_list(struct unit_test_state *uts, bool print)
399{
400 const char *opc = print ? "print" : "list";
401 char fdt[4096];
402 ulong addr;
403 int ret;
404
405 /* Original source DT */
Simon Glass2b60f8c2024-08-22 07:57:56 -0600406 ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt), &addr));
Marek Vasutb0cd7cc2023-03-02 04:08:32 +0100407
408 /* Test printing/listing the working FDT -- node / */
409 ut_assertok(console_record_reset_enable());
410 ut_assertok(run_commandf("fdt %s", opc));
411 ut_assert_nextline("/ {");
412 ut_assert_nextline("\t#address-cells = <0x00000001>;");
413 ut_assert_nextline("\t#size-cells = <0x00000001>;");
414 ut_assert_nextline("\tcompatible = \"u-boot,fdt-test\";");
415 ut_assert_nextline("\tmodel = \"U-Boot FDT test\";");
416 ut_assert_nextline("\taliases {");
417 if (print) {
418 ut_assert_nextline("\t\tbadalias = \"/bad/alias\";");
419 ut_assert_nextline("\t\tsubnodealias = \"/test-node@1234/subnode\";");
420 ut_assert_nextline("\t\ttestnodealias = \"/test-node@1234\";");
421 }
422 ut_assert_nextline("\t};");
423 ut_assert_nextline("\ttest-node@1234 {");
424 if (print) {
425 ut_assert_nextline("\t\t#address-cells = <0x00000000>;");
426 ut_assert_nextline("\t\t#size-cells = <0x00000000>;");
427 ut_assert_nextline("\t\tcompatible = \"u-boot,fdt-test-device1\";");
428 ut_assert_nextline("\t\tclock-names = \"fixed\", \"i2c\", \"spi\", \"uart2\", \"uart1\";");
429 ut_assert_nextline("\t\tu-boot,empty-property;");
430 ut_assert_nextline("\t\tclock-frequency = <0x00fde800>;");
431 ut_assert_nextline("\t\tregs = <0x00001234 0x00001000>;");
432 ut_assert_nextline("\t\tsubnode {");
433 ut_assert_nextline("\t\t\t#address-cells = <0x00000000>;");
434 ut_assert_nextline("\t\t\t#size-cells = <0x00000000>;");
435 ut_assert_nextline("\t\t\tcompatible = \"u-boot,fdt-subnode-test-device\";");
436 ut_assert_nextline("\t\t};");
437 }
438 ut_assert_nextline("\t};");
439 ut_assert_nextline("};");
440 ut_assertok(ut_check_console_end(uts));
441
442 ret = fdt_test_print_list_common(uts, opc, "/test-node@1234");
443 if (!ret)
444 ret = fdt_test_print_list_common(uts, opc, "testnodealias");
445
446 return 0;
447}
448
449static int fdt_test_print(struct unit_test_state *uts)
450{
451 return fdt_test_print_list(uts, true);
452}
Simon Glass9b997622024-08-22 07:57:50 -0600453FDT_TEST(fdt_test_print, UTF_CONSOLE);
Marek Vasutb0cd7cc2023-03-02 04:08:32 +0100454
455static int fdt_test_list(struct unit_test_state *uts)
456{
457 return fdt_test_print_list(uts, false);
458}
Simon Glass9b997622024-08-22 07:57:50 -0600459FDT_TEST(fdt_test_list, UTF_CONSOLE);
Marek Vasutb0cd7cc2023-03-02 04:08:32 +0100460
Marek Vasut025b9d82023-03-02 04:08:26 +0100461/* Test 'fdt get value' reading an fdt */
Marek Vasutf1df20a2023-03-02 04:08:29 +0100462static int fdt_test_get_value_string(struct unit_test_state *uts,
463 const char *node, const char *prop,
464 const char *idx, const char *strres,
465 const int intres)
466{
467 ut_assertok(console_record_reset_enable());
468 ut_assertok(run_commandf("fdt get value var %s %s %s",
469 node, prop, idx ? : ""));
Simon Glassb8133032024-08-22 07:57:55 -0600470 if (strres)
Marek Vasutf1df20a2023-03-02 04:08:29 +0100471 ut_asserteq_str(strres, env_get("var"));
Simon Glassb8133032024-08-22 07:57:55 -0600472 else
Marek Vasutf1df20a2023-03-02 04:08:29 +0100473 ut_asserteq(intres, env_get_hex("var", 0x1234));
Marek Vasutf1df20a2023-03-02 04:08:29 +0100474 ut_assertok(ut_check_console_end(uts));
475
476 return 0;
477}
478
Marek Vasut39e07272023-03-02 04:08:28 +0100479static int fdt_test_get_value_common(struct unit_test_state *uts,
480 const char *node)
481{
482 /* Test getting default element of $node node clock-names property */
Simon Glassb8133032024-08-22 07:57:55 -0600483 ut_assertok(fdt_test_get_value_string(uts, node, "clock-names", NULL,
484 "fixed", 0));
Marek Vasut39e07272023-03-02 04:08:28 +0100485
486 /* Test getting 0th element of $node node clock-names property */
Simon Glassb8133032024-08-22 07:57:55 -0600487 ut_assertok(fdt_test_get_value_string(uts, node, "clock-names", "0",
488 "fixed", 0));
Marek Vasut39e07272023-03-02 04:08:28 +0100489
490 /* Test getting 1st element of $node node clock-names property */
Simon Glassb8133032024-08-22 07:57:55 -0600491 ut_assertok(fdt_test_get_value_string(uts, node, "clock-names", "1",
492 "i2c", 0));
Marek Vasut39e07272023-03-02 04:08:28 +0100493
494 /* Test getting 2nd element of $node node clock-names property */
Simon Glassb8133032024-08-22 07:57:55 -0600495 ut_assertok(fdt_test_get_value_string(uts, node, "clock-names", "2",
496 "spi", 0));
Marek Vasutf1df20a2023-03-02 04:08:29 +0100497
498 /*
499 * Test getting default element of $node node regs property.
500 * The result here is highly unusual, the non-index value read from
501 * integer array is a string of concatenated values from the array,
502 * but only if the array is shorter than 40 characters. Anything
503 * longer is an error. This is a special case for handling hashes.
504 */
Simon Glassb8133032024-08-22 07:57:55 -0600505 ut_assertok(fdt_test_get_value_string(uts, node, "regs", NULL,
506 "3412000000100000", 0));
Marek Vasutf1df20a2023-03-02 04:08:29 +0100507
508 /* Test getting 0th element of $node node regs property */
Simon Glassb8133032024-08-22 07:57:55 -0600509 ut_assertok(fdt_test_get_value_string(uts, node, "regs", "0", NULL,
510 0x1234));
Marek Vasutf1df20a2023-03-02 04:08:29 +0100511
512 /* Test getting 1st element of $node node regs property */
Simon Glassb8133032024-08-22 07:57:55 -0600513 ut_assertok(fdt_test_get_value_string(uts, node, "regs", "1", NULL,
514 0x1000));
Marek Vasut39e07272023-03-02 04:08:28 +0100515
516 /* Test missing 10th element of $node node clock-names property */
517 ut_assertok(console_record_reset_enable());
518 ut_asserteq(1, run_commandf("fdt get value ften %s clock-names 10", node));
519 ut_assertok(ut_check_console_end(uts));
520
Marek Vasutf1df20a2023-03-02 04:08:29 +0100521 /* Test missing 10th element of $node node regs property */
522 ut_assertok(console_record_reset_enable());
523 ut_asserteq(1, run_commandf("fdt get value ften %s regs 10", node));
524 ut_assertok(ut_check_console_end(uts));
525
Marek Vasut39e07272023-03-02 04:08:28 +0100526 /* Test getting default element of $node node nonexistent property */
527 ut_assertok(console_record_reset_enable());
528 ut_asserteq(1, run_commandf("fdt get value fnone %s nonexistent", node));
529 ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND");
530 ut_assertok(ut_check_console_end(uts));
531
532 return 0;
533}
534
Marek Vasut025b9d82023-03-02 04:08:26 +0100535static int fdt_test_get_value(struct unit_test_state *uts)
Marek Vasutd83615b2022-11-14 22:50:00 +0100536{
Marek Vasutd6729762023-03-02 04:08:27 +0100537 char fdt[4096];
Marek Vasutd83615b2022-11-14 22:50:00 +0100538 ulong addr;
539
Simon Glass2b60f8c2024-08-22 07:57:56 -0600540 ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt), &addr));
Marek Vasutd83615b2022-11-14 22:50:00 +0100541
Simon Glassb8133032024-08-22 07:57:55 -0600542 ut_assertok(fdt_test_get_value_common(uts, "/test-node@1234"));
543 ut_assertok(fdt_test_get_value_common(uts, "testnodealias"));
Marek Vasutd83615b2022-11-14 22:50:00 +0100544
545 /* Test getting default element of /nonexistent node */
546 ut_assertok(console_record_reset_enable());
547 ut_asserteq(1, run_command("fdt get value fnode /nonexistent nonexistent", 1));
548 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
549 ut_assertok(ut_check_console_end(uts));
550
Marek Vasut39e07272023-03-02 04:08:28 +0100551 /* Test getting default element of bad alias */
552 ut_assertok(console_record_reset_enable());
553 ut_asserteq(1, run_command("fdt get value vbadalias badalias nonexistent", 1));
554 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
555 ut_assertok(ut_check_console_end(uts));
556
557 /* Test getting default element of nonexistent alias */
558 ut_assertok(console_record_reset_enable());
559 ut_asserteq(1, run_command("fdt get value vnoalias noalias nonexistent", 1));
560 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_BADPATH");
561 ut_assertok(ut_check_console_end(uts));
562
Marek Vasutd83615b2022-11-14 22:50:00 +0100563 return 0;
564}
Simon Glass9b997622024-08-22 07:57:50 -0600565FDT_TEST(fdt_test_get_value, UTF_CONSOLE);
Marek Vasutd83615b2022-11-14 22:50:00 +0100566
Marek Vasut890d3fc2023-03-02 04:08:33 +0100567static int fdt_test_get_name(struct unit_test_state *uts)
568{
569 char fdt[4096];
570 ulong addr;
571
Simon Glass2b60f8c2024-08-22 07:57:56 -0600572 ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt), &addr));
Marek Vasut890d3fc2023-03-02 04:08:33 +0100573
574 /* Test getting name of node 0 in /, which is /aliases node */
575 ut_assertok(console_record_reset_enable());
576 ut_assertok(run_command("fdt get name nzero / 0", 0));
577 ut_asserteq_str("aliases", env_get("nzero"));
578 ut_assertok(ut_check_console_end(uts));
579
580 /* Test getting name of node 1 in /, which is /test-node@1234 node */
581 ut_assertok(console_record_reset_enable());
582 ut_assertok(run_command("fdt get name none / 1", 0));
583 ut_asserteq_str("test-node@1234", env_get("none"));
584 ut_assertok(ut_check_console_end(uts));
585
586 /* Test getting name of node -1 in /, which is /aliases node, same as 0 */
587 ut_assertok(console_record_reset_enable());
588 ut_assertok(run_command("fdt get name nmone / -1", 0));
589 ut_asserteq_str("aliases", env_get("nmone"));
590 ut_assertok(ut_check_console_end(uts));
591
592 /* Test getting name of node 2 in /, which does not exist */
593 ut_assertok(console_record_reset_enable());
594 ut_asserteq(1, run_command("fdt get name ntwo / 2", 1));
595 ut_assert_nextline("libfdt node not found");
596 ut_assertok(ut_check_console_end(uts));
597
598 /* Test getting name of node 0 in /test-node@1234, which is /subnode node */
599 ut_assertok(console_record_reset_enable());
600 ut_assertok(run_command("fdt get name snzero /test-node@1234 0", 0));
601 ut_asserteq_str("subnode", env_get("snzero"));
602 ut_assertok(run_command("fdt get name asnzero testnodealias 0", 0));
603 ut_asserteq_str("subnode", env_get("asnzero"));
604 ut_assertok(ut_check_console_end(uts));
605
606 /* Test getting name of node 1 in /test-node@1234, which does not exist */
607 ut_assertok(console_record_reset_enable());
608 ut_asserteq(1, run_command("fdt get name snone /test-node@1234 1", 1));
609 ut_assert_nextline("libfdt node not found");
610 ut_asserteq(1, run_command("fdt get name asnone testnodealias 1", 1));
611 ut_assert_nextline("libfdt node not found");
612 ut_assertok(ut_check_console_end(uts));
613
614 /* Test getting name of node -1 in /test-node@1234, which is /subnode node, same as 0 */
615 ut_assertok(console_record_reset_enable());
616 ut_assertok(run_command("fdt get name snmone /test-node@1234 -1", 0));
617 ut_asserteq_str("subnode", env_get("snmone"));
618 ut_assertok(run_command("fdt get name asnmone testnodealias -1", 0));
619 ut_asserteq_str("subnode", env_get("asnmone"));
620 ut_assertok(ut_check_console_end(uts));
621
622 /* Test getting name of nonexistent node */
623 ut_assertok(console_record_reset_enable());
624 ut_asserteq(1, run_command("fdt get name nonode /nonexistent 0", 1));
625 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
626 ut_assertok(ut_check_console_end(uts));
627
628 /* Test getting name of bad alias */
629 ut_assertok(console_record_reset_enable());
630 ut_asserteq(1, run_command("fdt get name vbadalias badalias 0", 1));
631 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
632 ut_assertok(ut_check_console_end(uts));
633
634 /* Test getting name of nonexistent alias */
635 ut_assertok(console_record_reset_enable());
636 ut_asserteq(1, run_command("fdt get name vnoalias noalias 0", 1));
637 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_BADPATH");
638 ut_assertok(ut_check_console_end(uts));
639
640 return 0;
641}
Simon Glass9b997622024-08-22 07:57:50 -0600642FDT_TEST(fdt_test_get_name, UTF_CONSOLE);
Marek Vasut890d3fc2023-03-02 04:08:33 +0100643
Marek Vasutb6d1dec2023-03-02 04:08:34 +0100644static int fdt_test_get_addr_common(struct unit_test_state *uts, char *fdt,
645 const char *path, const char *prop)
646{
647 unsigned int offset;
648 int path_offset;
649 void *prop_ptr;
650 int len = 0;
651
652 path_offset = fdt_path_offset(fdt, path);
653 ut_assert(path_offset >= 0);
654 prop_ptr = (void *)fdt_getprop(fdt, path_offset, prop, &len);
655 ut_assertnonnull(prop_ptr);
656 offset = (char *)prop_ptr - fdt;
657
658 ut_assertok(console_record_reset_enable());
659 ut_assertok(run_commandf("fdt get addr pstr %s %s", path, prop));
660 ut_asserteq((ulong)map_sysmem(env_get_hex("fdtaddr", 0x1234), 0),
661 (ulong)(map_sysmem(env_get_hex("pstr", 0x1234), 0) - offset));
662 ut_assertok(ut_check_console_end(uts));
663
664 return 0;
665}
666
667static int fdt_test_get_addr(struct unit_test_state *uts)
668{
669 char fdt[4096];
670 ulong addr;
671
Simon Glass2b60f8c2024-08-22 07:57:56 -0600672 ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt), &addr));
Marek Vasutb6d1dec2023-03-02 04:08:34 +0100673
674 /* Test getting address of root node / string property "compatible" */
Simon Glassb8133032024-08-22 07:57:55 -0600675 ut_assertok(fdt_test_get_addr_common(uts, fdt, "/", "compatible"));
Marek Vasutb6d1dec2023-03-02 04:08:34 +0100676
677 /* Test getting address of node /test-node@1234 stringlist property "clock-names" */
Simon Glassb8133032024-08-22 07:57:55 -0600678 ut_assertok(fdt_test_get_addr_common(uts, fdt, "/test-node@1234",
679 "clock-names"));
680 ut_assertok(fdt_test_get_addr_common(uts, fdt, "testnodealias",
681 "clock-names"));
Marek Vasutb6d1dec2023-03-02 04:08:34 +0100682
683 /* Test getting address of node /test-node@1234 u32 property "clock-frequency" */
Simon Glassb8133032024-08-22 07:57:55 -0600684 ut_assertok(fdt_test_get_addr_common(uts, fdt, "/test-node@1234",
685 "clock-frequency"));
686 ut_assertok(fdt_test_get_addr_common(uts, fdt, "testnodealias",
687 "clock-frequency"));
Marek Vasutb6d1dec2023-03-02 04:08:34 +0100688
689 /* Test getting address of node /test-node@1234 empty property "u-boot,empty-property" */
Simon Glassb8133032024-08-22 07:57:55 -0600690 ut_assertok(fdt_test_get_addr_common(uts, fdt, "/test-node@1234",
691 "u-boot,empty-property"));
692 ut_assertok(fdt_test_get_addr_common(uts, fdt, "testnodealias",
693 "u-boot,empty-property"));
Marek Vasutb6d1dec2023-03-02 04:08:34 +0100694
695 /* Test getting address of node /test-node@1234 array property "regs" */
Simon Glassb8133032024-08-22 07:57:55 -0600696 ut_assertok(fdt_test_get_addr_common(uts, fdt, "/test-node@1234",
697 "regs"));
698 ut_assertok(fdt_test_get_addr_common(uts, fdt, "testnodealias",
699 "regs"));
Marek Vasutb6d1dec2023-03-02 04:08:34 +0100700
701 /* Test getting address of node /test-node@1234/subnode non-existent property "noprop" */
702 ut_assertok(console_record_reset_enable());
703 ut_asserteq(1, run_command("fdt get addr pnoprop /test-node@1234/subnode noprop", 1));
704 ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND");
705 ut_assertok(ut_check_console_end(uts));
706
707 /* Test getting address of non-existent node /test-node@1234/nonode@1 property "noprop" */
708 ut_assertok(console_record_reset_enable());
709 ut_asserteq(1, run_command("fdt get addr pnonode /test-node@1234/nonode@1 noprop", 1));
710 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
711 ut_assertok(ut_check_console_end(uts));
712
713 return 0;
714}
Simon Glass9b997622024-08-22 07:57:50 -0600715FDT_TEST(fdt_test_get_addr, UTF_CONSOLE);
Marek Vasutb6d1dec2023-03-02 04:08:34 +0100716
Marek Vasut66e975a2023-03-02 04:08:35 +0100717static int fdt_test_get_size_common(struct unit_test_state *uts,
718 const char *path, const char *prop,
719 const unsigned int val)
720{
721 ut_assertok(console_record_reset_enable());
722 if (prop) {
723 ut_assertok(run_commandf("fdt get size sstr %s %s", path, prop));
724 } else {
725 ut_assertok(run_commandf("fdt get size sstr %s", path));
726 }
727 ut_asserteq(val, env_get_hex("sstr", 0x1234));
728 ut_assertok(ut_check_console_end(uts));
729
730 return 0;
731}
732
733static int fdt_test_get_size(struct unit_test_state *uts)
734{
735 char fdt[4096];
736 ulong addr;
737
Simon Glass2b60f8c2024-08-22 07:57:56 -0600738 ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt), &addr));
Marek Vasut66e975a2023-03-02 04:08:35 +0100739
740 /* Test getting size of root node / string property "compatible" */
Simon Glassb8133032024-08-22 07:57:55 -0600741 ut_assertok(fdt_test_get_size_common(uts, "/", "compatible", 16));
Marek Vasut66e975a2023-03-02 04:08:35 +0100742
743 /* Test getting size of node /test-node@1234 stringlist property "clock-names" */
Simon Glassb8133032024-08-22 07:57:55 -0600744 ut_assertok(fdt_test_get_size_common(uts, "/test-node@1234",
745 "clock-names", 26));
746 ut_assertok(fdt_test_get_size_common(uts, "testnodealias",
747 "clock-names", 26));
Marek Vasut66e975a2023-03-02 04:08:35 +0100748
749 /* Test getting size of node /test-node@1234 u32 property "clock-frequency" */
Simon Glassb8133032024-08-22 07:57:55 -0600750 ut_assertok(fdt_test_get_size_common(uts, "/test-node@1234",
751 "clock-frequency", 4));
752 ut_assertok(fdt_test_get_size_common(uts, "testnodealias",
753 "clock-frequency", 4));
Marek Vasut66e975a2023-03-02 04:08:35 +0100754
755 /* Test getting size of node /test-node@1234 empty property "u-boot,empty-property" */
Simon Glassb8133032024-08-22 07:57:55 -0600756 ut_assertok(fdt_test_get_size_common(uts, "/test-node@1234",
757 "u-boot,empty-property", 0));
758 ut_assertok(fdt_test_get_size_common(uts, "testnodealias",
759 "u-boot,empty-property", 0));
Marek Vasut66e975a2023-03-02 04:08:35 +0100760
761 /* Test getting size of node /test-node@1234 array property "regs" */
Simon Glassb8133032024-08-22 07:57:55 -0600762 ut_assertok(fdt_test_get_size_common(uts, "/test-node@1234", "regs",
763 8));
764 ut_assertok(fdt_test_get_size_common(uts, "testnodealias", "regs", 8));
Marek Vasut66e975a2023-03-02 04:08:35 +0100765
766 /* Test getting node count of node / */
Simon Glassb8133032024-08-22 07:57:55 -0600767 ut_assertok(fdt_test_get_size_common(uts, "/", NULL, 2));
Marek Vasut66e975a2023-03-02 04:08:35 +0100768
769 /* Test getting node count of node /test-node@1234/subnode */
Simon Glassb8133032024-08-22 07:57:55 -0600770 ut_assertok(fdt_test_get_size_common(uts, "/test-node@1234/subnode",
771 NULL, 0));
772 ut_assertok(fdt_test_get_size_common(uts, "subnodealias", NULL, 0));
Marek Vasut66e975a2023-03-02 04:08:35 +0100773
774 /* Test getting size of node /test-node@1234/subnode non-existent property "noprop" */
775 ut_assertok(console_record_reset_enable());
776 ut_asserteq(1, run_command("fdt get size pnoprop /test-node@1234/subnode noprop", 1));
777 ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND");
778 ut_asserteq(1, run_command("fdt get size pnoprop subnodealias noprop", 1));
779 ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND");
780 ut_assertok(ut_check_console_end(uts));
781
782 /* Test getting size of non-existent node /test-node@1234/nonode@1 property "noprop" */
783 ut_assertok(console_record_reset_enable());
784 ut_asserteq(1, run_command("fdt get size pnonode /test-node@1234/nonode@1 noprop", 1));
785 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
786 ut_assertok(ut_check_console_end(uts));
787
788 /* Test getting node count of non-existent node /test-node@1234/nonode@1 */
789 ut_assertok(console_record_reset_enable());
790 ut_asserteq(1, run_command("fdt get size pnonode /test-node@1234/nonode@1", 1));
791 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
792 ut_assertok(ut_check_console_end(uts));
793
794 /* Test getting node count of bad alias badalias */
795 ut_assertok(console_record_reset_enable());
796 ut_asserteq(1, run_command("fdt get size pnonode badalias noprop", 1));
797 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
798 ut_assertok(ut_check_console_end(uts));
799
800 /* Test getting node count of non-existent alias noalias */
801 ut_assertok(console_record_reset_enable());
802 ut_asserteq(1, run_command("fdt get size pnonode noalias", 1));
803 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_BADPATH");
804 ut_assertok(ut_check_console_end(uts));
805
806 return 0;
807}
Simon Glass9b997622024-08-22 07:57:50 -0600808FDT_TEST(fdt_test_get_size, UTF_CONSOLE);
Marek Vasut66e975a2023-03-02 04:08:35 +0100809
Marek Vasut8bd49a82023-03-02 04:08:36 +0100810static int fdt_test_set_single(struct unit_test_state *uts,
811 const char *path, const char *prop,
812 const char *sval, int ival, bool integer)
813{
814 /*
815 * Set single element string/integer/<empty> property into DT, that is:
816 * => fdt set /path property string
817 * => fdt set /path property integer
818 * => fdt set /path property
819 */
820 ut_assertok(console_record_reset_enable());
Marek Vasuta96dea22023-03-10 04:33:14 +0100821 if (sval)
Marek Vasut8bd49a82023-03-02 04:08:36 +0100822 ut_assertok(run_commandf("fdt set %s %s %s", path, prop, sval));
Marek Vasuta96dea22023-03-10 04:33:14 +0100823 else if (integer)
Marek Vasut8bd49a82023-03-02 04:08:36 +0100824 ut_assertok(run_commandf("fdt set %s %s <%d>", path, prop, ival));
Marek Vasuta96dea22023-03-10 04:33:14 +0100825 else
Marek Vasut8bd49a82023-03-02 04:08:36 +0100826 ut_assertok(run_commandf("fdt set %s %s", path, prop));
Marek Vasut8bd49a82023-03-02 04:08:36 +0100827
828 /* Validate the property is present and has correct value. */
829 ut_assertok(run_commandf("fdt get value svar %s %s", path, prop));
Marek Vasuta96dea22023-03-10 04:33:14 +0100830 if (sval)
Marek Vasut8bd49a82023-03-02 04:08:36 +0100831 ut_asserteq_str(sval, env_get("svar"));
Marek Vasuta96dea22023-03-10 04:33:14 +0100832 else if (integer)
Marek Vasut8bd49a82023-03-02 04:08:36 +0100833 ut_asserteq(ival, env_get_hex("svar", 0x1234));
Marek Vasuta96dea22023-03-10 04:33:14 +0100834 else
Marek Vasut8bd49a82023-03-02 04:08:36 +0100835 ut_assertnull(env_get("svar"));
Marek Vasut8bd49a82023-03-02 04:08:36 +0100836 ut_assertok(ut_check_console_end(uts));
837
838 return 0;
839}
840
841static int fdt_test_set_multi(struct unit_test_state *uts,
842 const char *path, const char *prop,
843 const char *sval1, const char *sval2,
844 int ival1, int ival2)
845{
846 /*
847 * Set multi element string/integer array property in DT, that is:
848 * => fdt set /path property <string1 string2>
849 * => fdt set /path property <integer1 integer2>
850 *
851 * The set is done twice in here deliberately, The first set adds
852 * the property with an extra trailing element in its array to make
853 * the array longer, the second set is the expected final content of
854 * the array property. The longer array is used to verify that the
855 * new array is correctly sized and read past the new array length
856 * triggers failure.
857 */
858 ut_assertok(console_record_reset_enable());
859 if (sval1 && sval2) {
860 ut_assertok(run_commandf("fdt set %s %s %s %s end", path, prop, sval1, sval2));
861 ut_assertok(run_commandf("fdt set %s %s %s %s", path, prop, sval1, sval2));
862 } else {
863 ut_assertok(run_commandf("fdt set %s %s <%d %d 10>", path, prop, ival1, ival2));
864 ut_assertok(run_commandf("fdt set %s %s <%d %d>", path, prop, ival1, ival2));
865 }
866
867 /*
868 * Validate the property is present and has correct value.
869 *
870 * The "end/10" above and "svarn" below is used to validate that
871 * previous 'fdt set' to longer array does not polute newly set
872 * shorter array.
873 */
874 ut_assertok(run_commandf("fdt get value svar1 %s %s 0", path, prop));
875 ut_assertok(run_commandf("fdt get value svar2 %s %s 1", path, prop));
876 ut_asserteq(1, run_commandf("fdt get value svarn %s %s 2", path, prop));
877 if (sval1 && sval2) {
878 ut_asserteq_str(sval1, env_get("svar1"));
879 ut_asserteq_str(sval2, env_get("svar2"));
880 ut_assertnull(env_get("svarn"));
881 } else {
882 ut_asserteq(ival1, env_get_hex("svar1", 0x1234));
883 ut_asserteq(ival2, env_get_hex("svar2", 0x1234));
884 ut_assertnull(env_get("svarn"));
885 }
886 ut_assertok(ut_check_console_end(uts));
887
888 return 0;
889}
890
891static int fdt_test_set_node(struct unit_test_state *uts,
892 const char *path, const char *prop)
893{
Simon Glassb8133032024-08-22 07:57:55 -0600894 ut_assertok(fdt_test_set_single(uts, path, prop, "new", 0, false));
895 ut_assertok(fdt_test_set_single(uts, path, prop, "rewrite", 0, false));
896 ut_assertok(fdt_test_set_single(uts, path, prop, NULL, 42, true));
897 ut_assertok(fdt_test_set_single(uts, path, prop, NULL, 0, false));
898 ut_assertok(fdt_test_set_multi(uts, path, prop, NULL, NULL, 42, 1701));
899 ut_assertok(fdt_test_set_multi(uts, path, prop, NULL, NULL, 74656, 9));
900 ut_assertok(fdt_test_set_multi(uts, path, prop, "42", "1701", 0, 0));
901 ut_assertok(fdt_test_set_multi(uts, path, prop, "74656", "9", 0, 0));
Marek Vasut8bd49a82023-03-02 04:08:36 +0100902
903 return 0;
904}
905
906static int fdt_test_set(struct unit_test_state *uts)
907{
908 char fdt[8192];
909 ulong addr;
910
Simon Glass2b60f8c2024-08-22 07:57:56 -0600911 ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt), &addr));
Marek Vasut8bd49a82023-03-02 04:08:36 +0100912 fdt_shrink_to_minimum(fdt, 4096); /* Resize with 4096 extra bytes */
Marek Vasut8bd49a82023-03-02 04:08:36 +0100913
914 /* Test setting of root node / existing property "compatible" */
Simon Glassb8133032024-08-22 07:57:55 -0600915 ut_assertok(fdt_test_set_node(uts, "/", "compatible"));
Marek Vasut8bd49a82023-03-02 04:08:36 +0100916
917 /* Test setting of root node / new property "newproperty" */
Simon Glassb8133032024-08-22 07:57:55 -0600918 ut_assertok(fdt_test_set_node(uts, "/", "newproperty"));
Marek Vasut8bd49a82023-03-02 04:08:36 +0100919
920 /* Test setting of subnode existing property "compatible" */
Simon Glassb8133032024-08-22 07:57:55 -0600921 ut_assertok(fdt_test_set_node(uts, "/test-node@1234/subnode",
922 "compatible"));
923 ut_assertok(fdt_test_set_node(uts, "subnodealias", "compatible"));
Marek Vasut8bd49a82023-03-02 04:08:36 +0100924
925 /* Test setting of subnode new property "newproperty" */
Simon Glassb8133032024-08-22 07:57:55 -0600926 ut_assertok(fdt_test_set_node(uts, "/test-node@1234/subnode",
927 "newproperty"));
928 ut_assertok(fdt_test_set_node(uts, "subnodealias", "newproperty"));
Marek Vasut8bd49a82023-03-02 04:08:36 +0100929
930 /* Test setting property of non-existent node */
931 ut_assertok(console_record_reset_enable());
932 ut_asserteq(1, run_command("fdt set /no-node noprop", 1));
933 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
934 ut_assertok(ut_check_console_end(uts));
935
936 /* Test setting property of non-existent alias */
937 ut_assertok(console_record_reset_enable());
938 ut_asserteq(1, run_command("fdt set noalias noprop", 1));
939 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_BADPATH");
940 ut_assertok(ut_check_console_end(uts));
941
942 /* Test setting property of bad alias */
943 ut_assertok(console_record_reset_enable());
944 ut_asserteq(1, run_command("fdt set badalias noprop", 1));
945 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
946 ut_assertok(ut_check_console_end(uts));
947
948 return 0;
949}
Simon Glass9b997622024-08-22 07:57:50 -0600950FDT_TEST(fdt_test_set, UTF_CONSOLE);
Marek Vasut8bd49a82023-03-02 04:08:36 +0100951
Marek Vasut6c285942023-03-02 04:08:37 +0100952static int fdt_test_mknode(struct unit_test_state *uts)
953{
954 char fdt[8192];
955 ulong addr;
956
Simon Glass2b60f8c2024-08-22 07:57:56 -0600957 ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt), &addr));
Marek Vasut6c285942023-03-02 04:08:37 +0100958 fdt_shrink_to_minimum(fdt, 4096); /* Resize with 4096 extra bytes */
Marek Vasut6c285942023-03-02 04:08:37 +0100959
960 /* Test creation of new node in / */
961 ut_assertok(console_record_reset_enable());
962 ut_assertok(run_commandf("fdt mknode / newnode"));
963 ut_assertok(run_commandf("fdt list /newnode"));
964 ut_assert_nextline("newnode {");
965 ut_assert_nextline("};");
966 ut_assertok(ut_check_console_end(uts));
967
968 /* Test creation of new node in /test-node@1234 */
969 ut_assertok(console_record_reset_enable());
970 ut_assertok(run_commandf("fdt mknode /test-node@1234 newsubnode"));
971 ut_assertok(run_commandf("fdt list /test-node@1234/newsubnode"));
972 ut_assert_nextline("newsubnode {");
973 ut_assert_nextline("};");
974 ut_assertok(ut_check_console_end(uts));
975
976 /* Test creation of new node in /test-node@1234 by alias */
977 ut_assertok(console_record_reset_enable());
978 ut_assertok(run_commandf("fdt mknode testnodealias newersubnode"));
979 ut_assertok(run_commandf("fdt list testnodealias/newersubnode"));
980 ut_assert_nextline("newersubnode {");
981 ut_assert_nextline("};");
982 ut_assertok(ut_check_console_end(uts));
983
984 /* Test creation of new node in /test-node@1234 over existing node */
985 ut_assertok(console_record_reset_enable());
986 ut_asserteq(1, run_commandf("fdt mknode testnodealias newsubnode"));
987 ut_assert_nextline("libfdt fdt_add_subnode(): FDT_ERR_EXISTS");
988 ut_assertok(ut_check_console_end(uts));
989
990 /* Test creation of new node in /test-node@1234 by alias over existing node */
991 ut_assertok(console_record_reset_enable());
992 ut_asserteq(1, run_commandf("fdt mknode testnodealias newersubnode"));
993 ut_assert_nextline("libfdt fdt_add_subnode(): FDT_ERR_EXISTS");
994 ut_assertok(ut_check_console_end(uts));
995
996 /* Test creation of new node in non-existent node */
997 ut_assertok(console_record_reset_enable());
998 ut_asserteq(1, run_commandf("fdt mknode /no-node newnosubnode"));
999 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
1000 ut_assertok(ut_check_console_end(uts));
1001
1002 /* Test creation of new node in non-existent alias */
1003 ut_assertok(console_record_reset_enable());
1004 ut_asserteq(1, run_commandf("fdt mknode noalias newfailsubnode"));
1005 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_BADPATH");
1006 ut_assertok(ut_check_console_end(uts));
1007
1008 /* Test creation of new node in bad alias */
1009 ut_assertok(console_record_reset_enable());
1010 ut_asserteq(1, run_commandf("fdt mknode badalias newbadsubnode"));
1011 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
1012 ut_assertok(ut_check_console_end(uts));
1013
1014 return 0;
1015}
Simon Glass9b997622024-08-22 07:57:50 -06001016FDT_TEST(fdt_test_mknode, UTF_CONSOLE);
Marek Vasut6c285942023-03-02 04:08:37 +01001017
Marek Vasute46a4382023-03-02 04:08:38 +01001018static int fdt_test_rm(struct unit_test_state *uts)
1019{
1020 char fdt[4096];
1021 ulong addr;
1022
Simon Glass2b60f8c2024-08-22 07:57:56 -06001023 ut_assertok(make_fuller_fdt(uts, fdt, sizeof(fdt), &addr));
Marek Vasute46a4382023-03-02 04:08:38 +01001024
1025 /* Test removal of property in root node / */
1026 ut_assertok(console_record_reset_enable());
1027 ut_assertok(run_commandf("fdt print / compatible"));
1028 ut_assert_nextline("compatible = \"u-boot,fdt-test\"");
1029 ut_assertok(run_commandf("fdt rm / compatible"));
1030 ut_asserteq(1, run_commandf("fdt print / compatible"));
1031 ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND");
1032 ut_assertok(ut_check_console_end(uts));
1033
1034 /* Test removal of property clock-names in subnode /test-node@1234 */
1035 ut_assertok(console_record_reset_enable());
1036 ut_assertok(run_commandf("fdt print /test-node@1234 clock-names"));
1037 ut_assert_nextline("clock-names = \"fixed\", \"i2c\", \"spi\", \"uart2\", \"uart1\"");
1038 ut_assertok(run_commandf("fdt rm /test-node@1234 clock-names"));
1039 ut_asserteq(1, run_commandf("fdt print /test-node@1234 clock-names"));
1040 ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND");
1041 ut_assertok(ut_check_console_end(uts));
1042
1043 /* Test removal of property u-boot,empty-property in subnode /test-node@1234 by alias */
1044 ut_assertok(console_record_reset_enable());
1045 ut_assertok(run_commandf("fdt print testnodealias u-boot,empty-property"));
1046 ut_assert_nextline("testnodealias u-boot,empty-property");
1047 ut_assertok(run_commandf("fdt rm testnodealias u-boot,empty-property"));
1048 ut_asserteq(1, run_commandf("fdt print testnodealias u-boot,empty-property"));
1049 ut_assert_nextline("libfdt fdt_getprop(): FDT_ERR_NOTFOUND");
1050 ut_assertok(ut_check_console_end(uts));
1051
1052 /* Test removal of non-existent property noprop in subnode /test-node@1234 */
1053 ut_assertok(console_record_reset_enable());
1054 ut_asserteq(1, run_commandf("fdt rm /test-node@1234 noprop"));
1055 ut_assert_nextline("libfdt fdt_delprop(): FDT_ERR_NOTFOUND");
1056 ut_assertok(ut_check_console_end(uts));
1057
1058 /* Test removal of non-existent node /no-node@5678 */
1059 ut_assertok(console_record_reset_enable());
1060 ut_asserteq(1, run_commandf("fdt rm /no-node@5678"));
1061 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
1062 ut_assertok(ut_check_console_end(uts));
1063
1064 /* Test removal of subnode /test-node@1234/subnode by alias */
1065 ut_assertok(console_record_reset_enable());
1066 ut_assertok(run_commandf("fdt rm subnodealias"));
1067 ut_asserteq(1, run_commandf("fdt print /test-node@1234/subnode"));
1068 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
1069 ut_assertok(ut_check_console_end(uts));
1070
1071 /* Test removal of node by non-existent alias */
1072 ut_assertok(console_record_reset_enable());
1073 ut_asserteq(1, run_commandf("fdt rm noalias"));
1074 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_BADPATH");
1075 ut_assertok(ut_check_console_end(uts));
1076
1077 /* Test removal of node by bad alias */
1078 ut_assertok(console_record_reset_enable());
1079 ut_asserteq(1, run_commandf("fdt rm noalias"));
1080 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_BADPATH");
1081 ut_assertok(ut_check_console_end(uts));
1082
1083 /* Test removal of node /test-node@1234 */
1084 ut_assertok(console_record_reset_enable());
1085 ut_assertok(run_commandf("fdt rm /test-node@1234"));
1086 ut_asserteq(1, run_commandf("fdt print /test-node@1234"));
1087 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
1088 ut_assertok(ut_check_console_end(uts));
1089
1090 /* Test removal of node / */
1091 ut_assertok(console_record_reset_enable());
1092 ut_assertok(run_commandf("fdt rm /"));
1093 ut_asserteq(1, run_commandf("fdt print /"));
1094 ut_assertok(ut_check_console_end(uts));
1095
1096 return 0;
1097}
Simon Glass9b997622024-08-22 07:57:50 -06001098FDT_TEST(fdt_test_rm, UTF_CONSOLE);
Marek Vasute46a4382023-03-02 04:08:38 +01001099
Marek Vasut26281512023-03-02 04:08:40 +01001100static int fdt_test_bootcpu(struct unit_test_state *uts)
1101{
1102 char fdt[256];
1103 ulong addr;
1104 int i;
1105
Simon Glass2b60f8c2024-08-22 07:57:56 -06001106 ut_assertok(make_test_fdt(uts, fdt, sizeof(fdt), &addr));
Marek Vasut26281512023-03-02 04:08:40 +01001107
1108 /* Test getting default bootcpu entry */
1109 ut_assertok(console_record_reset_enable());
1110 ut_assertok(run_commandf("fdt header get bootcpu boot_cpuid_phys"));
1111 ut_asserteq(0, env_get_ulong("bootcpu", 10, 0x1234));
1112 ut_assertok(ut_check_console_end(uts));
1113
1114 /* Test setting and getting new bootcpu entry, twice, to test overwrite */
1115 for (i = 42; i <= 43; i++) {
1116 ut_assertok(console_record_reset_enable());
1117 ut_assertok(run_commandf("fdt bootcpu %d", i));
1118 ut_assertok(ut_check_console_end(uts));
1119
1120 /* Test getting new bootcpu entry */
1121 ut_assertok(console_record_reset_enable());
1122 ut_assertok(run_commandf("fdt header get bootcpu boot_cpuid_phys"));
1123 ut_asserteq(i, env_get_ulong("bootcpu", 10, 0x1234));
1124 ut_assertok(ut_check_console_end(uts));
1125 }
1126
1127 return 0;
1128}
Simon Glass9b997622024-08-22 07:57:50 -06001129FDT_TEST(fdt_test_bootcpu, UTF_CONSOLE);
Marek Vasut26281512023-03-02 04:08:40 +01001130
Marek Vasut927e03b2023-03-02 04:08:39 +01001131static int fdt_test_header_get(struct unit_test_state *uts,
1132 const char *field, const unsigned long val)
1133{
1134 /* Test getting valid header entry */
1135 ut_assertok(console_record_reset_enable());
1136 ut_assertok(run_commandf("fdt header get fvar %s", field));
1137 ut_asserteq(val, env_get_hex("fvar", 0x1234));
1138 ut_assertok(ut_check_console_end(uts));
1139
1140 /* Test getting malformed header entry */
1141 ut_assertok(console_record_reset_enable());
1142 ut_asserteq(1, run_commandf("fdt header get fvar typo%stypo", field));
1143 ut_assertok(ut_check_console_end(uts));
1144
1145 return 0;
1146}
1147
1148static int fdt_test_header(struct unit_test_state *uts)
1149{
1150 char fdt[256];
1151 ulong addr;
1152
Simon Glass2b60f8c2024-08-22 07:57:56 -06001153 ut_assertok(make_test_fdt(uts, fdt, sizeof(fdt), &addr));
Marek Vasut927e03b2023-03-02 04:08:39 +01001154
1155 /* Test header print */
1156 ut_assertok(console_record_reset_enable());
1157 ut_assertok(run_commandf("fdt header"));
1158 ut_assert_nextline("magic:\t\t\t0x%x", fdt_magic(fdt));
1159 ut_assert_nextline("totalsize:\t\t0x%x (%d)", fdt_totalsize(fdt), fdt_totalsize(fdt));
1160 ut_assert_nextline("off_dt_struct:\t\t0x%x", fdt_off_dt_struct(fdt));
1161 ut_assert_nextline("off_dt_strings:\t\t0x%x", fdt_off_dt_strings(fdt));
1162 ut_assert_nextline("off_mem_rsvmap:\t\t0x%x", fdt_off_mem_rsvmap(fdt));
1163 ut_assert_nextline("version:\t\t%d", fdt_version(fdt));
1164 ut_assert_nextline("last_comp_version:\t%d", fdt_last_comp_version(fdt));
1165 ut_assert_nextline("boot_cpuid_phys:\t0x%x", fdt_boot_cpuid_phys(fdt));
1166 ut_assert_nextline("size_dt_strings:\t0x%x", fdt_size_dt_strings(fdt));
1167 ut_assert_nextline("size_dt_struct:\t\t0x%x", fdt_size_dt_struct(fdt));
1168 ut_assert_nextline("number mem_rsv:\t\t0x%x", fdt_num_mem_rsv(fdt));
1169 ut_assert_nextline_empty();
1170 ut_assertok(ut_check_console_end(uts));
1171
1172 /* Test header get */
Simon Glassb8133032024-08-22 07:57:55 -06001173 ut_assertok(fdt_test_header_get(uts, "magic", fdt_magic(fdt)));
1174 ut_assertok(fdt_test_header_get(uts, "totalsize", fdt_totalsize(fdt)));
1175 ut_assertok(fdt_test_header_get(uts, "off_dt_struct",
1176 fdt_off_dt_struct(fdt)));
1177 ut_assertok(fdt_test_header_get(uts, "off_dt_strings",
1178 fdt_off_dt_strings(fdt)));
1179 ut_assertok(fdt_test_header_get(uts, "off_mem_rsvmap",
1180 fdt_off_mem_rsvmap(fdt)));
1181 ut_assertok(fdt_test_header_get(uts, "version", fdt_version(fdt)));
1182 ut_assertok(fdt_test_header_get(uts, "last_comp_version",
1183 fdt_last_comp_version(fdt)));
1184 ut_assertok(fdt_test_header_get(uts, "boot_cpuid_phys",
1185 fdt_boot_cpuid_phys(fdt)));
1186 ut_assertok(fdt_test_header_get(uts, "size_dt_strings",
1187 fdt_size_dt_strings(fdt)));
1188 ut_assertok(fdt_test_header_get(uts, "size_dt_struct",
1189 fdt_size_dt_struct(fdt)));
Marek Vasut927e03b2023-03-02 04:08:39 +01001190
1191 return 0;
1192}
Simon Glass9b997622024-08-22 07:57:50 -06001193FDT_TEST(fdt_test_header, UTF_CONSOLE);
Marek Vasut927e03b2023-03-02 04:08:39 +01001194
Marek Vasutd9b4c9f2023-03-02 04:08:41 +01001195static int fdt_test_memory_cells(struct unit_test_state *uts,
1196 const unsigned int cells)
1197{
1198 unsigned char *pada, *pads;
1199 unsigned char *seta, *sets;
1200 char fdt[8192];
1201 const int size = sizeof(fdt);
1202 fdt32_t *regs;
1203 ulong addr;
1204 char *spc;
1205 int i;
1206
1207 /* Create DT with node /memory { regs = <0x100 0x200>; } and #*cells */
1208 ut_assertnonnull(regs = calloc(2 * cells, sizeof(*regs)));
1209 ut_assertnonnull(pada = calloc(12, cells));
1210 ut_assertnonnull(pads = calloc(12, cells));
1211 ut_assertnonnull(seta = calloc(12, cells));
1212 ut_assertnonnull(sets = calloc(12, cells));
1213 for (i = cells; i >= 1; i--) {
1214 regs[cells - 1] = cpu_to_fdt32(i * 0x10000);
1215 regs[(cells * 2) - 1] = cpu_to_fdt32(~i);
1216 snprintf(seta + (8 * (cells - i)), 9, "%08x", i * 0x10000);
1217 snprintf(sets + (8 * (cells - i)), 9, "%08x", ~i);
1218 spc = (i != 1) ? " " : "";
1219 snprintf(pada + (11 * (cells - i)), 12, "0x%08x%s", i * 0x10000, spc);
1220 snprintf(pads + (11 * (cells - i)), 12, "0x%08x%s", ~i, spc);
1221 }
1222
1223 ut_assertok(fdt_create(fdt, size));
1224 ut_assertok(fdt_finish_reservemap(fdt));
1225 ut_assert(fdt_begin_node(fdt, "") >= 0);
1226 ut_assertok(fdt_property_u32(fdt, "#address-cells", cells));
1227 ut_assertok(fdt_property_u32(fdt, "#size-cells", cells));
1228 ut_assert(fdt_begin_node(fdt, "memory") >= 0);
1229 ut_assertok(fdt_property_string(fdt, "device_type", "memory"));
1230 ut_assertok(fdt_property(fdt, "reg", &regs, cells * 2));
1231 ut_assertok(fdt_end_node(fdt));
1232 ut_assertok(fdt_end_node(fdt));
1233 ut_assertok(fdt_finish(fdt));
1234 fdt_shrink_to_minimum(fdt, 4096); /* Resize with 4096 extra bytes */
1235 addr = map_to_sysmem(fdt);
1236 set_working_fdt_addr(addr);
1237
1238 /* Test updating the memory node */
1239 ut_assertok(console_record_reset_enable());
1240 ut_assertok(run_commandf("fdt memory 0x%s 0x%s", seta, sets));
1241 ut_assertok(run_commandf("fdt print /memory"));
1242 ut_assert_nextline("memory {");
1243 ut_assert_nextline("\tdevice_type = \"memory\";");
1244 ut_assert_nextline("\treg = <%s %s>;", pada, pads);
1245 ut_assert_nextline("};");
1246 ut_assertok(ut_check_console_end(uts));
1247
1248 free(sets);
1249 free(seta);
1250 free(pads);
1251 free(pada);
1252 free(regs);
1253
1254 return 0;
1255}
1256
1257static int fdt_test_memory(struct unit_test_state *uts)
1258{
1259 /*
1260 * Test memory fixup for 32 and 64 bit systems, anything bigger is
1261 * so far unsupported and fails because of simple_stroull() being
1262 * 64bit tops in the 'fdt memory' command implementation.
1263 */
Simon Glassb8133032024-08-22 07:57:55 -06001264 ut_assertok(fdt_test_memory_cells(uts, 1));
1265 ut_assertok(fdt_test_memory_cells(uts, 2));
Marek Vasutd9b4c9f2023-03-02 04:08:41 +01001266
1267 /*
1268 * The 'fdt memory' command is limited to /memory node, it does
1269 * not support any other valid DT memory node format, which is
1270 * either one or multiple /memory@adresss nodes. Therefore, this
1271 * DT variant is not tested here.
1272 */
1273
1274 return 0;
1275}
Simon Glass9b997622024-08-22 07:57:50 -06001276FDT_TEST(fdt_test_memory, UTF_CONSOLE);
Marek Vasutd9b4c9f2023-03-02 04:08:41 +01001277
Marek Vasut50daa2e2023-03-02 04:08:42 +01001278static int fdt_test_rsvmem(struct unit_test_state *uts)
1279{
1280 char fdt[8192];
1281 ulong addr;
1282
Simon Glass2b60f8c2024-08-22 07:57:56 -06001283 ut_assertok(make_test_fdt(uts, fdt, sizeof(fdt), &addr));
Marek Vasut50daa2e2023-03-02 04:08:42 +01001284 fdt_shrink_to_minimum(fdt, 4096); /* Resize with 4096 extra bytes */
1285 fdt_add_mem_rsv(fdt, 0x42, 0x1701);
1286 fdt_add_mem_rsv(fdt, 0x74656, 0x9);
Marek Vasut50daa2e2023-03-02 04:08:42 +01001287
1288 /* Test default reserved memory node presence */
1289 ut_assertok(console_record_reset_enable());
1290 ut_assertok(run_commandf("fdt rsvmem print"));
1291 ut_assert_nextline("index\t\t start\t\t size");
1292 ut_assert_nextline("------------------------------------------------");
1293 ut_assert_nextline(" %x\t%016x\t%016x", 0, 0x42, 0x1701);
1294 ut_assert_nextline(" %x\t%016x\t%016x", 1, 0x74656, 0x9);
1295 ut_assertok(ut_check_console_end(uts));
1296
1297 /* Test add new reserved memory node */
1298 ut_assertok(console_record_reset_enable());
1299 ut_assertok(run_commandf("fdt rsvmem add 0x1234 0x5678"));
1300 ut_assertok(run_commandf("fdt rsvmem print"));
1301 ut_assert_nextline("index\t\t start\t\t size");
1302 ut_assert_nextline("------------------------------------------------");
1303 ut_assert_nextline(" %x\t%016x\t%016x", 0, 0x42, 0x1701);
1304 ut_assert_nextline(" %x\t%016x\t%016x", 1, 0x74656, 0x9);
1305 ut_assert_nextline(" %x\t%016x\t%016x", 2, 0x1234, 0x5678);
1306 ut_assertok(ut_check_console_end(uts));
1307
1308 /* Test delete reserved memory node */
1309 ut_assertok(console_record_reset_enable());
1310 ut_assertok(run_commandf("fdt rsvmem delete 0"));
1311 ut_assertok(run_commandf("fdt rsvmem print"));
1312 ut_assert_nextline("index\t\t start\t\t size");
1313 ut_assert_nextline("------------------------------------------------");
1314 ut_assert_nextline(" %x\t%016x\t%016x", 0, 0x74656, 0x9);
1315 ut_assert_nextline(" %x\t%016x\t%016x", 1, 0x1234, 0x5678);
1316 ut_assertok(ut_check_console_end(uts));
1317
1318 /* Test re-add new reserved memory node */
1319 ut_assertok(console_record_reset_enable());
1320 ut_assertok(run_commandf("fdt rsvmem add 0x42 0x1701"));
1321 ut_assertok(run_commandf("fdt rsvmem print"));
1322 ut_assert_nextline("index\t\t start\t\t size");
1323 ut_assert_nextline("------------------------------------------------");
1324 ut_assert_nextline(" %x\t%016x\t%016x", 0, 0x74656, 0x9);
1325 ut_assert_nextline(" %x\t%016x\t%016x", 1, 0x1234, 0x5678);
1326 ut_assert_nextline(" %x\t%016x\t%016x", 2, 0x42, 0x1701);
1327 ut_assertok(ut_check_console_end(uts));
1328
1329 /* Test delete nonexistent reserved memory node */
1330 ut_assertok(console_record_reset_enable());
1331 ut_asserteq(1, run_commandf("fdt rsvmem delete 10"));
1332 ut_assert_nextline("libfdt fdt_del_mem_rsv(): FDT_ERR_NOTFOUND");
1333 ut_assertok(ut_check_console_end(uts));
1334
1335 return 0;
1336}
Simon Glass9b997622024-08-22 07:57:50 -06001337FDT_TEST(fdt_test_rsvmem, UTF_CONSOLE);
Marek Vasut50daa2e2023-03-02 04:08:42 +01001338
Marek Vasut77291e62023-03-02 04:08:43 +01001339static int fdt_test_chosen(struct unit_test_state *uts)
1340{
1341 const char *env_bootargs = env_get("bootargs");
1342 char fdt[8192];
1343 ulong addr;
1344
Simon Glass2b60f8c2024-08-22 07:57:56 -06001345 ut_assertok(make_test_fdt(uts, fdt, sizeof(fdt), &addr));
Marek Vasut77291e62023-03-02 04:08:43 +01001346 fdt_shrink_to_minimum(fdt, 4096); /* Resize with 4096 extra bytes */
Marek Vasut77291e62023-03-02 04:08:43 +01001347
1348 /* Test default chosen node presence, fail as there is no /chosen node */
1349 ut_assertok(console_record_reset_enable());
1350 ut_asserteq(1, run_commandf("fdt print /chosen"));
1351 ut_assert_nextline("libfdt fdt_path_offset() returned FDT_ERR_NOTFOUND");
1352 ut_assertok(ut_check_console_end(uts));
1353
1354 /* Test add new chosen node without initrd */
1355 ut_assertok(console_record_reset_enable());
1356 ut_assertok(run_commandf("fdt chosen"));
1357 ut_assertok(run_commandf("fdt print /chosen"));
1358 ut_assert_nextline("chosen {");
1359 ut_assert_nextlinen("\tu-boot,version = "); /* Ignore the version string */
1360 if (env_bootargs)
1361 ut_assert_nextline("\tbootargs = \"%s\";", env_bootargs);
Tim Harveyf485a992024-06-18 14:06:09 -07001362 if (IS_ENABLED(CONFIG_DM_RNG) &&
1363 !IS_ENABLED(CONFIG_MEASURED_BOOT) &&
1364 !IS_ENABLED(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT))
1365 ut_assert_nextlinen("\tkaslr-seed = ");
Marek Vasut77291e62023-03-02 04:08:43 +01001366 ut_assert_nextline("};");
1367 ut_assertok(ut_check_console_end(uts));
1368
1369 /* Test add new chosen node with initrd */
1370 ut_assertok(console_record_reset_enable());
1371 ut_assertok(run_commandf("fdt chosen 0x1234 0x5678"));
1372 ut_assertok(run_commandf("fdt print /chosen"));
1373 ut_assert_nextline("chosen {");
1374 ut_assert_nextline("\tlinux,initrd-end = <0x%08x 0x%08x>;",
1375 upper_32_bits(0x1234 + 0x5678 - 1),
1376 lower_32_bits(0x1234 + 0x5678 - 1));
1377 ut_assert_nextline("\tlinux,initrd-start = <0x%08x 0x%08x>;",
1378 upper_32_bits(0x1234), lower_32_bits(0x1234));
1379 ut_assert_nextlinen("\tu-boot,version = "); /* Ignore the version string */
1380 if (env_bootargs)
1381 ut_assert_nextline("\tbootargs = \"%s\";", env_bootargs);
Tim Harveyf485a992024-06-18 14:06:09 -07001382 if (IS_ENABLED(CONFIG_DM_RNG) &&
1383 !IS_ENABLED(CONFIG_MEASURED_BOOT) &&
1384 !IS_ENABLED(CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT))
1385 ut_assert_nextlinen("\tkaslr-seed = ");
Marek Vasut77291e62023-03-02 04:08:43 +01001386 ut_assert_nextline("};");
1387 ut_assertok(ut_check_console_end(uts));
1388
1389 return 0;
1390}
Simon Glass9b997622024-08-22 07:57:50 -06001391FDT_TEST(fdt_test_chosen, UTF_CONSOLE);
Marek Vasut77291e62023-03-02 04:08:43 +01001392
Marek Vasutc5fe73e2023-03-02 04:08:44 +01001393static int fdt_test_apply(struct unit_test_state *uts)
1394{
1395 char fdt[8192], fdto[8192];
1396 ulong addr, addro;
1397
1398 /* Create base DT with __symbols__ node */
1399 ut_assertok(fdt_create(fdt, sizeof(fdt)));
1400 ut_assertok(fdt_finish_reservemap(fdt));
1401 ut_assert(fdt_begin_node(fdt, "") >= 0);
1402 ut_assert(fdt_begin_node(fdt, "__symbols__") >= 0);
1403 ut_assertok(fdt_end_node(fdt));
1404 ut_assertok(fdt_end_node(fdt));
1405 ut_assertok(fdt_finish(fdt));
1406 fdt_shrink_to_minimum(fdt, 4096); /* Resize with 4096 extra bytes */
1407 addr = map_to_sysmem(fdt);
1408 set_working_fdt_addr(addr);
1409
1410 /* Create DTO which adds single property to root node / */
1411 ut_assertok(fdt_create(fdto, sizeof(fdto)));
1412 ut_assertok(fdt_finish_reservemap(fdto));
1413 ut_assert(fdt_begin_node(fdto, "") >= 0);
1414 ut_assert(fdt_begin_node(fdto, "fragment") >= 0);
1415 ut_assertok(fdt_property_string(fdto, "target-path", "/"));
1416 ut_assert(fdt_begin_node(fdto, "__overlay__") >= 0);
1417 ut_assertok(fdt_property_string(fdto, "newstring", "newvalue"));
1418 ut_assertok(fdt_end_node(fdto));
1419 ut_assertok(fdt_end_node(fdto));
1420 ut_assertok(fdt_finish(fdto));
1421 addro = map_to_sysmem(fdto);
1422
1423 /* Test default DT print */
1424 ut_assertok(console_record_reset_enable());
1425 ut_assertok(run_commandf("fdt print /"));
1426 ut_assert_nextline("/ {");
1427 ut_assert_nextline("\t__symbols__ {");
1428 ut_assert_nextline("\t};");
1429 ut_assert_nextline("};");
1430 ut_assertok(ut_check_console_end(uts));
1431
1432 /* Test simple DTO application */
1433 ut_assertok(console_record_reset_enable());
Evgeny Bachinin0d73c232023-03-20 11:23:13 +03001434 ut_assertok(run_commandf("fdt apply 0x%08lx", addro));
Marek Vasutc5fe73e2023-03-02 04:08:44 +01001435 ut_assertok(run_commandf("fdt print /"));
1436 ut_assert_nextline("/ {");
1437 ut_assert_nextline("\tnewstring = \"newvalue\";");
1438 ut_assert_nextline("\t__symbols__ {");
1439 ut_assert_nextline("\t};");
1440 ut_assert_nextline("};");
1441 ut_assertok(ut_check_console_end(uts));
1442
1443 /*
1444 * Create complex DTO which:
1445 * - modifies newstring property in root node /
1446 * - adds new properties to root node /
1447 * - adds new subnode with properties to root node /
1448 * - adds phandle to the subnode and therefore __symbols__ node
1449 */
1450 ut_assertok(fdt_create(fdto, sizeof(fdto)));
1451 ut_assertok(fdt_finish_reservemap(fdto));
1452 ut_assert(fdt_begin_node(fdto, "") >= 0);
1453 ut_assertok(fdt_property_cell(fdto, "#address-cells", 1));
1454 ut_assertok(fdt_property_cell(fdto, "#size-cells", 0));
1455
1456 ut_assert(fdt_begin_node(fdto, "fragment@0") >= 0);
1457 ut_assertok(fdt_property_string(fdto, "target-path", "/"));
1458 ut_assert(fdt_begin_node(fdto, "__overlay__") >= 0);
1459 ut_assertok(fdt_property_string(fdto, "newstring", "newervalue"));
1460 ut_assertok(fdt_property_u32(fdto, "newu32", 0x12345678));
1461 ut_assertok(fdt_property(fdto, "empty-property", NULL, 0));
1462 ut_assert(fdt_begin_node(fdto, "subnode") >= 0);
1463 ut_assertok(fdt_property_string(fdto, "subnewstring", "newervalue"));
1464 ut_assertok(fdt_property_u32(fdto, "subnewu32", 0x12345678));
1465 ut_assertok(fdt_property(fdto, "subempty-property", NULL, 0));
1466 ut_assertok(fdt_property_u32(fdto, "phandle", 0x01));
1467 ut_assertok(fdt_end_node(fdto));
1468 ut_assertok(fdt_end_node(fdto));
1469 ut_assertok(fdt_end_node(fdto));
1470
1471 ut_assert(fdt_begin_node(fdto, "__symbols__") >= 0);
1472 ut_assertok(fdt_property_string(fdto, "subnodephandle", "/fragment@0/__overlay__/subnode"));
1473 ut_assertok(fdt_end_node(fdto));
1474 ut_assertok(fdt_finish(fdto));
1475 addro = map_to_sysmem(fdto);
1476
1477 /* Test complex DTO application */
1478 ut_assertok(console_record_reset_enable());
Evgeny Bachinin0d73c232023-03-20 11:23:13 +03001479 ut_assertok(run_commandf("fdt apply 0x%08lx", addro));
Marek Vasutc5fe73e2023-03-02 04:08:44 +01001480 ut_assertok(run_commandf("fdt print /"));
1481 ut_assert_nextline("/ {");
1482 ut_assert_nextline("\tempty-property;");
1483 ut_assert_nextline("\tnewu32 = <0x12345678>;");
1484 ut_assert_nextline("\tnewstring = \"newervalue\";");
1485 ut_assert_nextline("\tsubnode {");
1486 ut_assert_nextline("\t\tphandle = <0x00000001>;");
1487 ut_assert_nextline("\t\tsubempty-property;");
1488 ut_assert_nextline("\t\tsubnewu32 = <0x12345678>;");
1489 ut_assert_nextline("\t\tsubnewstring = \"newervalue\";");
1490 ut_assert_nextline("\t};");
1491 ut_assert_nextline("\t__symbols__ {");
1492 ut_assert_nextline("\t\tsubnodephandle = \"/subnode\";");
1493 ut_assert_nextline("\t};");
1494 ut_assert_nextline("};");
1495 ut_assertok(ut_check_console_end(uts));
1496
1497 /*
1498 * Create complex DTO which:
1499 * - modifies subnewu32 property in subnode via phandle and uses __fixups__ node
1500 */
1501 ut_assertok(fdt_create(fdto, sizeof(fdto)));
1502 ut_assertok(fdt_finish_reservemap(fdto));
1503 ut_assert(fdt_begin_node(fdto, "") >= 0);
1504 ut_assertok(fdt_property_cell(fdto, "#address-cells", 1));
1505 ut_assertok(fdt_property_cell(fdto, "#size-cells", 0));
1506
1507 ut_assert(fdt_begin_node(fdto, "fragment@0") >= 0);
1508 ut_assertok(fdt_property_u32(fdto, "target", 0xffffffff));
1509 ut_assert(fdt_begin_node(fdto, "__overlay__") >= 0);
1510 ut_assertok(fdt_property_u32(fdto, "subnewu32", 0xabcdef01));
1511 ut_assertok(fdt_end_node(fdto));
1512 ut_assertok(fdt_end_node(fdto));
1513
1514 ut_assert(fdt_begin_node(fdto, "__fixups__") >= 0);
1515 ut_assertok(fdt_property_string(fdto, "subnodephandle", "/fragment@0:target:0"));
1516 ut_assertok(fdt_end_node(fdto));
1517 ut_assertok(fdt_end_node(fdto));
1518 ut_assertok(fdt_finish(fdto));
1519 addro = map_to_sysmem(fdto);
1520
1521 /* Test complex DTO application */
1522 ut_assertok(console_record_reset_enable());
Evgeny Bachinin0d73c232023-03-20 11:23:13 +03001523 ut_assertok(run_commandf("fdt apply 0x%08lx", addro));
Marek Vasutc5fe73e2023-03-02 04:08:44 +01001524 ut_assertok(run_commandf("fdt print /"));
1525 ut_assert_nextline("/ {");
1526 ut_assert_nextline("\tempty-property;");
1527 ut_assert_nextline("\tnewu32 = <0x12345678>;");
1528 ut_assert_nextline("\tnewstring = \"newervalue\";");
1529 ut_assert_nextline("\tsubnode {");
1530 ut_assert_nextline("\t\tphandle = <0x00000001>;");
1531 ut_assert_nextline("\t\tsubempty-property;");
1532 ut_assert_nextline("\t\tsubnewu32 = <0xabcdef01>;");
1533 ut_assert_nextline("\t\tsubnewstring = \"newervalue\";");
1534 ut_assert_nextline("\t};");
1535 ut_assert_nextline("\t__symbols__ {");
1536 ut_assert_nextline("\t\tsubnodephandle = \"/subnode\";");
1537 ut_assert_nextline("\t};");
1538 ut_assert_nextline("};");
1539 ut_assertok(ut_check_console_end(uts));
1540
1541 return 0;
1542}
Simon Glass9b997622024-08-22 07:57:50 -06001543FDT_TEST(fdt_test_apply, UTF_CONSOLE);
Marek Vasutc5fe73e2023-03-02 04:08:44 +01001544
Simon Glass74724482022-07-13 06:06:59 -06001545int do_ut_fdt(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
1546{
1547 struct unit_test *tests = UNIT_TEST_SUITE_START(fdt_test);
1548 const int n_ents = UNIT_TEST_SUITE_COUNT(fdt_test);
1549
1550 return cmd_ut_category("fdt", "fdt_test_", tests, n_ents, argc, argv);
1551}