]>
Commit | Line | Data |
---|---|---|
dc254f38 SG |
1 | /* |
2 | * Some very basic tests for fdtdec, accessed through test_fdtdec command. | |
3 | * They are easiest to use with sandbox. | |
4 | * | |
5 | * Copyright (c) 2011 The Chromium OS Authors. | |
1a459660 | 6 | * SPDX-License-Identifier: GPL-2.0+ |
dc254f38 SG |
7 | */ |
8 | ||
9 | #include <common.h> | |
10 | #include <fdtdec.h> | |
11 | #include <libfdt.h> | |
12 | #include <malloc.h> | |
13 | #include <os.h> | |
14 | ||
15 | /* The size of our test fdt blob */ | |
16 | #define FDT_SIZE (16 * 1024) | |
17 | ||
18 | /** | |
19 | * Check if an operation failed, and if so, print an error | |
20 | * | |
21 | * @param oper_name Name of operation | |
22 | * @param err Error code to check | |
23 | * | |
24 | * @return 0 if ok, -1 if there was an error | |
25 | */ | |
26 | static int fdt_checkerr(const char *oper_name, int err) | |
27 | { | |
28 | if (err) { | |
29 | printf("%s: %s: %s\n", __func__, oper_name, fdt_strerror(err)); | |
30 | return -1; | |
31 | } | |
32 | ||
33 | return 0; | |
34 | } | |
35 | ||
36 | /** | |
37 | * Check the result of an operation and if incorrect, print an error | |
38 | * | |
39 | * @param oper_name Name of operation | |
40 | * @param expected Expected value | |
41 | * @param value Actual value | |
42 | * | |
43 | * @return 0 if ok, -1 if there was an error | |
44 | */ | |
45 | static int checkval(const char *oper_name, int expected, int value) | |
46 | { | |
47 | if (expected != value) { | |
48 | printf("%s: %s: expected %d, but returned %d\n", __func__, | |
49 | oper_name, expected, value); | |
50 | return -1; | |
51 | } | |
52 | ||
53 | return 0; | |
54 | } | |
55 | ||
56 | #define CHECK(op) if (fdt_checkerr(#op, op)) return -1 | |
57 | #define CHECKVAL(op, expected) \ | |
58 | if (checkval(#op, expected, op)) \ | |
59 | return -1 | |
60 | #define CHECKOK(op) CHECKVAL(op, 0) | |
61 | ||
62 | /* maximum number of nodes / aliases to generate */ | |
63 | #define MAX_NODES 20 | |
64 | ||
65 | /* | |
66 | * Make a test fdt | |
67 | * | |
68 | * @param fdt Device tree pointer | |
69 | * @param size Size of device tree blob | |
70 | * @param aliases Specifies alias assignments. Format is a list of items | |
71 | * separated by space. Items are #a where | |
72 | * # is the alias number | |
73 | * a is the node to point to | |
74 | * @param nodes Specifies nodes to generate (a=0, b=1), upper case | |
75 | * means to create a disabled node | |
76 | */ | |
77 | static int make_fdt(void *fdt, int size, const char *aliases, | |
78 | const char *nodes) | |
79 | { | |
80 | char name[20], value[20]; | |
81 | const char *s; | |
82 | int fd; | |
83 | ||
84 | CHECK(fdt_create(fdt, size)); | |
85 | CHECK(fdt_finish_reservemap(fdt)); | |
86 | CHECK(fdt_begin_node(fdt, "")); | |
87 | ||
88 | CHECK(fdt_begin_node(fdt, "aliases")); | |
89 | for (s = aliases; *s;) { | |
90 | sprintf(name, "i2c%c", *s); | |
91 | sprintf(value, "/i2c%d@0", s[1] - 'a'); | |
92 | CHECK(fdt_property_string(fdt, name, value)); | |
93 | s += 2 + (s[2] != '\0'); | |
94 | } | |
95 | CHECK(fdt_end_node(fdt)); | |
96 | ||
97 | for (s = nodes; *s; s++) { | |
98 | sprintf(value, "i2c%d@0", (*s & 0xdf) - 'A'); | |
99 | CHECK(fdt_begin_node(fdt, value)); | |
100 | CHECK(fdt_property_string(fdt, "compatible", | |
101 | fdtdec_get_compatible(COMPAT_UNKNOWN))); | |
102 | if (*s <= 'Z') | |
103 | CHECK(fdt_property_string(fdt, "status", "disabled")); | |
104 | CHECK(fdt_end_node(fdt)); | |
105 | } | |
106 | ||
107 | CHECK(fdt_end_node(fdt)); | |
108 | CHECK(fdt_finish(fdt)); | |
109 | CHECK(fdt_pack(fdt)); | |
110 | #if defined(DEBUG) && defined(CONFIG_SANDBOX) | |
111 | fd = os_open("/tmp/fdtdec-text.dtb", OS_O_CREAT | OS_O_WRONLY); | |
112 | if (fd == -1) { | |
113 | printf("Could not open .dtb file to write\n"); | |
114 | return -1; | |
115 | } | |
116 | os_write(fd, fdt, size); | |
117 | os_close(fd); | |
118 | #endif | |
119 | return 0; | |
120 | } | |
121 | ||
122 | static int run_test(const char *aliases, const char *nodes, const char *expect) | |
123 | { | |
124 | int list[MAX_NODES]; | |
125 | const char *s; | |
126 | void *blob; | |
127 | int i; | |
128 | ||
129 | blob = malloc(FDT_SIZE); | |
130 | if (!blob) { | |
131 | printf("%s: out of memory\n", __func__); | |
132 | return 1; | |
133 | } | |
134 | ||
135 | printf("aliases=%s, nodes=%s, expect=%s: ", aliases, nodes, expect); | |
136 | CHECKVAL(make_fdt(blob, FDT_SIZE, aliases, nodes), 0); | |
137 | CHECKVAL(fdtdec_find_aliases_for_id(blob, "i2c", | |
138 | COMPAT_UNKNOWN, | |
139 | list, ARRAY_SIZE(list)), strlen(expect)); | |
140 | ||
141 | /* Check we got the right ones */ | |
142 | for (i = 0, s = expect; *s; s++, i++) { | |
143 | int want = *s; | |
144 | const char *name; | |
145 | int got = ' '; | |
146 | ||
147 | name = list[i] ? fdt_get_name(blob, list[i], NULL) : NULL; | |
148 | if (name) | |
149 | got = name[3] + 'a' - '0'; | |
150 | ||
151 | if (got != want) { | |
152 | printf("Position %d: Expected '%c', got '%c' ('%s')\n", | |
153 | i, want, got, name); | |
154 | return 1; | |
155 | } | |
156 | } | |
157 | ||
158 | printf("pass\n"); | |
159 | return 0; | |
160 | } | |
161 | ||
162 | static int do_test_fdtdec(cmd_tbl_t *cmdtp, int flag, int argc, | |
163 | char * const argv[]) | |
164 | { | |
165 | /* basic tests */ | |
166 | CHECKOK(run_test("", "", "")); | |
167 | CHECKOK(run_test("1e 3d", "", "")); | |
168 | ||
169 | /* | |
170 | * 'a' represents 0, 'b' represents 1, etc. | |
171 | * The first character is the alias number, the second is the node | |
172 | * number. So the params mean: | |
173 | * 0a 1b : point alias 0 to node 0 (a), alias 1 to node 1(b) | |
174 | * ab : to create nodes 0 and 1 (a and b) | |
175 | * ab : we expect the function to return two nodes, in | |
176 | * the order 0, 1 | |
177 | */ | |
178 | CHECKOK(run_test("0a 1b", "ab", "ab")); | |
179 | ||
180 | CHECKOK(run_test("0a 1c", "ab", "ab")); | |
181 | CHECKOK(run_test("1c", "ab", "ab")); | |
182 | CHECKOK(run_test("1b", "ab", "ab")); | |
183 | CHECKOK(run_test("0b", "ab", "ba")); | |
184 | CHECKOK(run_test("0b 2d", "dbc", "bcd")); | |
185 | CHECKOK(run_test("0d 3a 1c 2b", "dbac", "dcba")); | |
186 | ||
187 | /* things with holes */ | |
188 | CHECKOK(run_test("1b 3d", "dbc", "cb d")); | |
189 | CHECKOK(run_test("1e 3d", "dbc", "bc d")); | |
190 | ||
191 | /* no aliases */ | |
192 | CHECKOK(run_test("", "dbac", "dbac")); | |
193 | ||
194 | /* disabled nodes */ | |
195 | CHECKOK(run_test("0d 3a 1c 2b", "dBac", "dc a")); | |
196 | CHECKOK(run_test("0b 2d", "DBc", "c")); | |
197 | CHECKOK(run_test("0b 4d 2c", "DBc", " c")); | |
198 | ||
199 | /* conflicting aliases - first one gets it */ | |
200 | CHECKOK(run_test("2a 1a 0a", "a", " a")); | |
201 | CHECKOK(run_test("0a 1a 2a", "a", "a")); | |
202 | ||
203 | printf("Test passed\n"); | |
204 | return 0; | |
205 | } | |
206 | ||
207 | U_BOOT_CMD( | |
208 | test_fdtdec, 3, 1, do_test_fdtdec, | |
209 | "test_fdtdec", | |
210 | "Run tests for fdtdec library"); |