1 /* Copyright 2013-2014 IBM Corp.
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12 * implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <skiboot.h>
18 #include <stdlib.h>
19
20 /* Override this for testing. */
21 #define is_rodata(p) fake_is_rodata(p)
22
23 char __rodata_start[16];
24 #define __rodata_end (__rodata_start + sizeof(__rodata_start))
25
fake_is_rodata(const void * p)26 static inline bool fake_is_rodata(const void *p)
27 {
28 return ((char *)p >= __rodata_start && (char *)p < __rodata_end);
29 }
30
31 #define zalloc(bytes) calloc((bytes), 1)
32
33 #include "../device.c"
34 #include <assert.h>
35 #include "../../test/dt_common.c"
36 const char *prop_to_fix[] = {"something", NULL};
37 const char **props_to_fix(struct dt_node *node);
38
check_path(const struct dt_node * node,const char * expected_path)39 static void check_path(const struct dt_node *node, const char * expected_path)
40 {
41 char * path;
42 path = dt_get_path(node);
43 if (strcmp(path, expected_path) != 0) {
44 printf("check_path: expected %s, got %s\n", expected_path, path);
45 }
46 assert(strcmp(path, expected_path) == 0);
47 free(path);
48 }
49
50 /* constructs a random nodes only device tree */
build_tree(int max_depth,int min_depth,struct dt_node * parent)51 static void build_tree(int max_depth, int min_depth, struct dt_node *parent)
52 {
53 char name[64];
54 int i;
55
56 for (i = 0; i < max_depth; i++) {
57 struct dt_node *new;
58
59 snprintf(name, sizeof name, "prefix@%.8x", rand());
60
61 new = dt_new(parent, name);
62
63 if(max_depth > min_depth)
64 build_tree(max_depth - 1, min_depth, new);
65 }
66 }
67
is_sorted(const struct dt_node * root)68 static bool is_sorted(const struct dt_node *root)
69 {
70 struct dt_node *end = list_tail(&root->children, struct dt_node, list);
71 struct dt_node *node;
72
73 dt_for_each_child(root, node) {
74 struct dt_node *next =
75 list_entry(node->list.next, struct dt_node, list);
76
77 /* current node must be "less than" the next node */
78 if (node != end && dt_cmp_subnodes(node, next) != -1) {
79 printf("nodes '%s' and '%s' out of order\n",
80 node->name, next->name);
81
82 return false;
83 }
84
85 if (!is_sorted(node))
86 return false;
87 }
88
89 return true;
90 }
91
92 /*handler for phandle fixup test */
props_to_fix(struct dt_node * node)93 const char **props_to_fix(struct dt_node *node)
94 {
95 const struct dt_property *prop;
96
97 prop = dt_find_property(node, "something");
98 if (prop)
99 return prop_to_fix;
100
101 return NULL;
102 }
103
main(void)104 int main(void)
105 {
106 struct dt_node *root, *other_root, *c1, *c2, *c2_c, *gc1, *gc2, *gc3, *ggc1, *ggc2;
107 struct dt_node *addrs, *addr1, *addr2;
108 struct dt_node *i, *subtree, *ev1, *ut1, *ut2;
109 const struct dt_property *p;
110 struct dt_property *p2;
111 unsigned int n;
112 char *s;
113 size_t sz;
114 u32 phandle, ev1_ph, new_prop_ph;
115
116 root = dt_new_root("");
117 assert(!list_top(&root->properties, struct dt_property, list));
118 check_path(root, "/");
119
120 c1 = dt_new_check(root, "c1");
121 assert(!list_top(&c1->properties, struct dt_property, list));
122 check_path(c1, "/c1");
123 assert(dt_find_by_name(root, "c1") == c1);
124 assert(dt_find_by_path(root, "/c1") == c1);
125 assert(dt_new(root, "c1") == NULL);
126
127 c2 = dt_new(root, "c2");
128 c2_c = dt_new_check(root, "c2");
129 assert(c2 == c2_c);
130 assert(!list_top(&c2->properties, struct dt_property, list));
131 check_path(c2, "/c2");
132 assert(dt_find_by_name(root, "c2") == c2);
133 assert(dt_find_by_path(root, "/c2") == c2);
134
135 gc1 = dt_new(c1, "gc1");
136 assert(!list_top(&gc1->properties, struct dt_property, list));
137 check_path(gc1, "/c1/gc1");
138 assert(dt_find_by_name(root, "gc1") == gc1);
139 assert(dt_find_by_path(root, "/c1/gc1") == gc1);
140
141 gc2 = dt_new(c1, "gc2");
142 assert(!list_top(&gc2->properties, struct dt_property, list));
143 check_path(gc2, "/c1/gc2");
144 assert(dt_find_by_name(root, "gc2") == gc2);
145 assert(dt_find_by_path(root, "/c1/gc2") == gc2);
146
147 gc3 = dt_new(c1, "gc3");
148 assert(!list_top(&gc3->properties, struct dt_property, list));
149 check_path(gc3, "/c1/gc3");
150 assert(dt_find_by_name(root, "gc3") == gc3);
151 assert(dt_find_by_path(root, "/c1/gc3") == gc3);
152
153 ggc1 = dt_new(gc1, "ggc1");
154 assert(!list_top(&ggc1->properties, struct dt_property, list));
155 check_path(ggc1, "/c1/gc1/ggc1");
156 assert(dt_find_by_name(root, "ggc1") == ggc1);
157 assert(dt_find_by_path(root, "/c1/gc1/ggc1") == ggc1);
158
159 addrs = dt_new(root, "addrs");
160 assert(!list_top(&addrs->properties, struct dt_property, list));
161 check_path(addrs, "/addrs");
162 assert(dt_find_by_name(root, "addrs") == addrs);
163 assert(dt_find_by_path(root, "/addrs") == addrs);
164
165 addr1 = dt_new_addr(addrs, "addr", 0x1337);
166 assert(!list_top(&addr1->properties, struct dt_property, list));
167 check_path(addr1, "/addrs/addr@1337");
168 assert(dt_find_by_name(root, "addr@1337") == addr1);
169 assert(dt_find_by_name_addr(root, "addr", 0x1337) == addr1);
170 assert(dt_find_by_path(root, "/addrs/addr@1337") == addr1);
171 assert(dt_new_addr(addrs, "addr", 0x1337) == NULL);
172
173 addr2 = dt_new_2addr(addrs, "2addr", 0xdead, 0xbeef);
174 assert(!list_top(&addr2->properties, struct dt_property, list));
175 check_path(addr2, "/addrs/2addr@dead,beef");
176 assert(dt_find_by_name(root, "2addr@dead,beef") == addr2);
177 assert(dt_find_by_path(root, "/addrs/2addr@dead,beef") == addr2);
178 assert(dt_new_2addr(addrs, "2addr", 0xdead, 0xbeef) == NULL);
179
180 /* Test walking the tree, checking and setting values */
181 for (n = 0, i = dt_first(root); i; i = dt_next(root, i), n++) {
182 assert(!list_top(&i->properties, struct dt_property, list));
183 dt_add_property_cells(i, "visited", 1);
184 }
185 assert(n == 9);
186
187 for (n = 0, i = dt_first(root); i; i = dt_next(root, i), n++) {
188 p = list_top(&i->properties, struct dt_property, list);
189 assert(strcmp(p->name, "visited") == 0);
190 assert(p->len == sizeof(u32));
191 assert(fdt32_to_cpu(*(u32 *)p->prop) == 1);
192 }
193 assert(n == 9);
194
195 /* Test cells */
196 dt_add_property_cells(c1, "some-property", 1, 2, 3);
197 p = dt_find_property(c1, "some-property");
198 assert(p);
199 assert(strcmp(p->name, "some-property") == 0);
200 assert(p->len == sizeof(u32) * 3);
201 assert(fdt32_to_cpu(*(u32 *)p->prop) == 1);
202 assert(dt_prop_get_cell(c1, "some-property", 0) == 1);
203 assert(fdt32_to_cpu(*((u32 *)p->prop + 1)) == 2);
204 assert(dt_prop_get_cell(c1, "some-property", 1) == 2);
205 assert(fdt32_to_cpu(*((u32 *)p->prop + 2)) == 3);
206 assert(dt_prop_get_cell_def(c1, "some-property", 2, 42) == 3);
207
208 assert(dt_prop_get_cell_def(c1, "not-a-property", 2, 42) == 42);
209
210 /* Test u64s */
211 dt_add_property_u64s(c2, "some-property", (2LL << 33), (3LL << 33), (4LL << 33));
212 p = dt_find_property(c2, "some-property");
213 assert(p);
214 assert(p->len == sizeof(u64) * 3);
215 assert(fdt64_to_cpu(*(u64 *)p->prop) == (2LL << 33));
216 assert(fdt64_to_cpu(*((u64 *)p->prop + 1)) == (3LL << 33));
217 assert(fdt64_to_cpu(*((u64 *)p->prop + 2)) == (4LL << 33));
218
219 /* Test u32/u64 get defaults */
220 assert(dt_prop_get_u32_def(c1, "u32", 42) == 42);
221 dt_add_property_cells(c1, "u32", 1337);
222 assert(dt_prop_get_u32_def(c1, "u32", 42) == 1337);
223 assert(dt_prop_get_u32(c1, "u32") == 1337);
224
225 assert(dt_prop_get_u64_def(c1, "u64", (42LL << 42)) == (42LL << 42));
226 dt_add_property_u64s(c1, "u64", (1337LL << 42));
227 assert(dt_prop_get_u64_def(c1, "u64", (42LL << 42)) == (1337LL << 42));
228 assert(dt_prop_get_u64(c1, "u64") == (1337LL << 42));
229
230 /* Test freeing a single node */
231 assert(!list_empty(&gc1->children));
232 dt_free(ggc1);
233 assert(list_empty(&gc1->children));
234
235 /* Test rodata logic. */
236 assert(!is_rodata("hello"));
237 assert(is_rodata(__rodata_start));
238 strcpy(__rodata_start, "name");
239 ggc1 = dt_new(root, __rodata_start);
240 assert(ggc1->name == __rodata_start);
241
242 /* Test string node. */
243 dt_add_property_string(ggc1, "somestring", "someval");
244 assert(dt_has_node_property(ggc1, "somestring", "someval"));
245 assert(!dt_has_node_property(ggc1, "somestrin", "someval"));
246 assert(!dt_has_node_property(ggc1, "somestring", "someva"));
247 assert(!dt_has_node_property(ggc1, "somestring", "somevale"));
248
249 /* Test nstr, which allows for non-null-terminated inputs */
250 dt_add_property_nstr(ggc1, "nstring", "somevalue_long", 7);
251 assert(dt_has_node_property(ggc1, "nstring", "someval"));
252 assert(!dt_has_node_property(ggc1, "nstring", "someva"));
253 assert(!dt_has_node_property(ggc1, "nstring", "somevalue_long"));
254
255 /* Test multiple strings */
256 dt_add_property_strings(ggc1, "somestrings",
257 "These", "are", "strings!");
258 p = dt_find_property(ggc1, "somestrings");
259 assert(p);
260 assert(p->len == sizeof(char) * (6 + 4 + 9));
261 s = (char *)p->prop;
262 assert(strcmp(s, "These") == 0);
263 assert(strlen(s) == 5);
264 s += 6;
265 assert(strcmp(s, "are") == 0);
266 assert(strlen(s) == 3);
267 s += 4;
268 assert(strcmp(s, "strings!") == 0);
269 assert(strlen(s) == 8);
270 s += 9;
271 assert(s == (char *)p->prop + p->len);
272 assert(dt_prop_find_string(p, "These"));
273 /* dt_prop_find_string is case insensitve */
274 assert(dt_prop_find_string(p, "ARE"));
275 assert(!dt_prop_find_string(p, "integers!"));
276 /* And always returns false for NULL properties */
277 assert(!dt_prop_find_string(NULL, "anything!"));
278
279 /* Test more get/get_def varieties */
280 assert(dt_prop_get_def(c1, "does-not-exist", NULL) == NULL);
281 sz = 0xbad;
282 assert(dt_prop_get_def_size(c1, "does-not-exist", NULL, &sz) == NULL);
283 assert(sz == 0);
284 dt_add_property_string(c1, "another-property", "xyzzy");
285 assert(dt_prop_get_def(c1, "another-property", NULL) != NULL);
286 assert(strcmp(dt_prop_get(c1, "another-property"), "xyzzy") == 0);
287 n = 0xbad;
288 assert(dt_prop_get_def_size(c1, "another-property", NULL, &sz) != NULL);
289 assert(sz == strlen("xyzzy") + 1);
290
291 /* Test resizing property. */
292 p = p2 = __dt_find_property(c1, "some-property");
293 assert(p);
294 n = p2->len;
295 while (p2 == p) {
296 n *= 2;
297 dt_resize_property(&p2, n);
298 }
299
300 assert(dt_find_property(c1, "some-property") == p2);
301 list_check(&c1->properties, "properties after resizing");
302
303 dt_del_property(c1, p2);
304 list_check(&c1->properties, "properties after delete");
305
306 /* No leaks for valgrind! */
307 dt_free(root);
308
309 /* Test compatible and chip id. */
310 root = dt_new_root("");
311
312 c1 = dt_new(root, "chip1");
313 dt_add_property_cells(c1, "ibm,chip-id", 0xcafe);
314 assert(dt_get_chip_id(c1) == 0xcafe);
315 dt_add_property_strings(c1, "compatible",
316 "specific-fake-chip",
317 "generic-fake-chip");
318 assert(dt_node_is_compatible(c1, "specific-fake-chip"));
319 assert(dt_node_is_compatible(c1, "generic-fake-chip"));
320
321 c2 = dt_new(root, "chip2");
322 dt_add_property_cells(c2, "ibm,chip-id", 0xbeef);
323 assert(dt_get_chip_id(c2) == 0xbeef);
324 dt_add_property_strings(c2, "compatible",
325 "specific-fake-bus",
326 "generic-fake-bus");
327
328 gc1 = dt_new(c1, "coprocessor1");
329 dt_add_property_strings(gc1, "compatible",
330 "specific-fake-coprocessor");
331 gc2 = dt_new(gc1, "coprocessor2");
332 dt_add_property_strings(gc2, "compatible",
333 "specific-fake-coprocessor");
334 gc3 = dt_new(c1, "coprocessor3");
335 dt_add_property_strings(gc3, "compatible",
336 "specific-fake-coprocessor");
337
338
339 assert(dt_find_compatible_node(root, NULL, "generic-fake-bus") == c2);
340 assert(dt_find_compatible_node(root, c2, "generic-fake-bus") == NULL);
341
342 /* we can find all compatible nodes */
343 assert(dt_find_compatible_node(c1, NULL, "specific-fake-coprocessor") == gc1);
344 assert(dt_find_compatible_node(c1, gc1, "specific-fake-coprocessor") == gc2);
345 assert(dt_find_compatible_node(c1, gc2, "specific-fake-coprocessor") == gc3);
346 assert(dt_find_compatible_node(c1, gc3, "specific-fake-coprocessor") == NULL);
347 assert(dt_find_compatible_node(root, NULL, "specific-fake-coprocessor") == gc1);
348 assert(dt_find_compatible_node(root, gc1, "specific-fake-coprocessor") == gc2);
349 assert(dt_find_compatible_node(root, gc2, "specific-fake-coprocessor") == gc3);
350 assert(dt_find_compatible_node(root, gc3, "specific-fake-coprocessor") == NULL);
351
352 /* we can find the coprocessor once on the cpu */
353 assert(dt_find_compatible_node_on_chip(root,
354 NULL,
355 "specific-fake-coprocessor",
356 0xcafe) == gc1);
357 assert(dt_find_compatible_node_on_chip(root,
358 gc1,
359 "specific-fake-coprocessor",
360 0xcafe) == gc2);
361 assert(dt_find_compatible_node_on_chip(root,
362 gc2,
363 "specific-fake-coprocessor",
364 0xcafe) == gc3);
365 assert(dt_find_compatible_node_on_chip(root,
366 gc3,
367 "specific-fake-coprocessor",
368 0xcafe) == NULL);
369
370 /* we can't find the coprocessor on the bus */
371 assert(dt_find_compatible_node_on_chip(root,
372 NULL,
373 "specific-fake-coprocessor",
374 0xbeef) == NULL);
375
376 /* Test phandles. We override the automatically generated one. */
377 phandle = 0xf00;
378 dt_add_property(gc3, "phandle", (const void *)&phandle, 4);
379 assert(last_phandle == 0xf00);
380 assert(dt_find_by_phandle(root, 0xf00) == gc3);
381 assert(dt_find_by_phandle(root, 0xf0f) == NULL);
382
383 dt_free(root);
384
385 /* basic sorting */
386 root = dt_new_root("rewt");
387 dt_new(root, "a@1");
388 dt_new(root, "a@2");
389 dt_new(root, "a@3");
390 dt_new(root, "a@4");
391 dt_new(root, "b@4");
392 dt_new(root, "c@4");
393
394 assert(is_sorted(root));
395
396 /* Now test dt_attach_root */
397 other_root = dt_new_root("other_root");
398 dt_new(other_root, "d@1");
399
400 assert(dt_attach_root(root, other_root));
401 other_root = dt_new_root("other_root");
402 assert(!dt_attach_root(root, other_root));
403 dt_free(root);
404
405 /* Test child node sorting */
406 root = dt_new_root("test root");
407 build_tree(5, 3, root);
408
409 if (!is_sorted(root)) {
410 dump_dt(root, 1, false);
411 }
412 assert(is_sorted(root));
413
414 dt_free(root);
415
416 /* check dt_translate_address */
417
418 /* NB: the root bus has two address cells */
419 root = dt_new_root("");
420
421 c1 = dt_new_addr(root, "some-32bit-bus", 0x80000000);
422 dt_add_property_cells(c1, "#address-cells", 1);
423 dt_add_property_cells(c1, "#size-cells", 1);
424 dt_add_property_cells(c1, "ranges", 0x0, 0x8, 0x0, 0x1000);
425
426 gc1 = dt_new_addr(c1, "test", 0x0500);
427 dt_add_property_cells(gc1, "reg", 0x0500, 0x10);
428
429 assert(dt_translate_address(gc1, 0, NULL) == 0x800000500ul);
430
431 /* try three level translation */
432
433 gc2 = dt_new_addr(c1, "another-32bit-bus", 0x40000000);
434 dt_add_property_cells(gc2, "#address-cells", 1);
435 dt_add_property_cells(gc2, "#size-cells", 1);
436 dt_add_property_cells(gc2, "ranges", 0x0, 0x600, 0x100,
437 0x100, 0x800, 0x100);
438
439 ggc1 = dt_new_addr(gc2, "test", 0x50);
440 dt_add_property_cells(ggc1, "reg", 0x50, 0x10);
441 assert(dt_translate_address(ggc1, 0, NULL) == 0x800000650ul);
442
443 /* test multiple ranges work */
444 ggc2 = dt_new_addr(gc2, "test", 0x150);
445 dt_add_property_cells(ggc2, "reg", 0x150, 0x10);
446 assert(dt_translate_address(ggc2, 0, NULL) == 0x800000850ul);
447
448 /* try 64bit -> 64bit */
449
450 c2 = dt_new_addr(root, "some-64bit-bus", 0xe00000000);
451 dt_add_property_cells(c2, "#address-cells", 2);
452 dt_add_property_cells(c2, "#size-cells", 2);
453 dt_add_property_cells(c2, "ranges", 0x0, 0x0, 0xe, 0x0, 0x2, 0x0);
454
455 gc2 = dt_new_addr(c2, "test", 0x100000000ul);
456 dt_add_property_u64s(gc2, "reg", 0x100000000ul, 0x10ul);
457 assert(dt_translate_address(gc2, 0, NULL) == 0xf00000000ul);
458
459 dt_free(root);
460
461 /* phandle fixup test */
462 subtree = dt_new_root("subtree");
463 ev1 = dt_new(subtree, "ev@1");
464 ev1_ph = ev1->phandle;
465 dt_new(ev1,"a@1");
466 dt_new(ev1,"a@2");
467 dt_new(ev1,"a@3");
468 ut1 = dt_new(subtree, "ut@1");
469 dt_add_property(ut1, "something", (const void *)&ev1->phandle, 4);
470 ut2 = dt_new(subtree, "ut@2");
471 dt_add_property(ut2, "something", (const void *)&ev1->phandle, 4);
472
473 dt_adjust_subtree_phandle(subtree, props_to_fix);
474 assert(!(ev1->phandle == ev1_ph));
475 new_prop_ph = dt_prop_get_u32(ut1, "something");
476 assert(!(new_prop_ph == ev1_ph));
477 new_prop_ph = dt_prop_get_u32(ut2, "something");
478 assert(!(new_prop_ph == ev1_ph));
479 dt_free(subtree);
480 return 0;
481 }
482
483