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