Branch data Line data Source code
1 : : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 : : /*
3 : : * Manipulate the device tree
4 : : *
5 : : * Copyright 2013-2019 IBM Corp.
6 : : */
7 : :
8 : : #include <stdarg.h>
9 : : #include <device.h>
10 : : #include <stdlib.h>
11 : : #include <skiboot.h>
12 : : #include <libfdt/libfdt.h>
13 : : #include <libfdt/libfdt_internal.h>
14 : : #include <ccan/str/str.h>
15 : : #include <ccan/endian/endian.h>
16 : : #include <inttypes.h>
17 : :
18 : : /* Used to give unique handles. */
19 : : u32 last_phandle = 0;
20 : :
21 : : struct dt_node *dt_root;
22 : : struct dt_node *dt_chosen;
23 : :
24 : 3472 : static const char *take_name(const char *name)
25 : : {
26 : 3472 : if (!is_rodata(name) && !(name = strdup(name))) {
27 : 0 : prerror("Failed to allocate copy of name");
28 : 0 : abort();
29 : : }
30 : 3472 : return name;
31 : : }
32 : :
33 : 3353 : static void free_name(const char *name)
34 : : {
35 : 3295 : if (!is_rodata(name))
36 : 3352 : free((char *)name);
37 : 3353 : }
38 : :
39 : 736 : static struct dt_node *new_node(const char *name)
40 : : {
41 : 736 : struct dt_node *node = malloc(sizeof *node);
42 : 736 : if (!node) {
43 : 0 : prerror("Failed to allocate node\n");
44 : 0 : abort();
45 : : }
46 : :
47 : 736 : node->name = take_name(name);
48 : 736 : node->parent = NULL;
49 : 736 : list_head_init(&node->properties);
50 : 736 : list_head_init(&node->children);
51 : : /* FIXME: locking? */
52 : 736 : node->phandle = new_phandle();
53 : 736 : return node;
54 : : }
55 : :
56 : 49 : struct dt_node *dt_new_root(const char *name)
57 : : {
58 : 49 : return new_node(name);
59 : : }
60 : :
61 : 13085 : static const char *get_unitname(const struct dt_node *node)
62 : : {
63 : 13085 : const char *c = strchr(node->name, '@');
64 : :
65 : 13085 : if (!c)
66 : 11247 : return NULL;
67 : :
68 : 1838 : return c + 1;
69 : : }
70 : :
71 : 6151 : int dt_cmp_subnodes(const struct dt_node *a, const struct dt_node *b)
72 : : {
73 : 6151 : const char *a_unit = get_unitname(a);
74 : 6151 : const char *b_unit = get_unitname(b);
75 : :
76 : 6151 : ptrdiff_t basenamelen = a_unit - a->name;
77 : :
78 : : /* sort hex unit addresses by number */
79 : 6151 : if (a_unit && b_unit && !strncmp(a->name, b->name, basenamelen)) {
80 : : unsigned long long a_num, b_num;
81 : : char *a_end, *b_end;
82 : :
83 : 295 : a_num = strtoul(a_unit, &a_end, 16);
84 : 295 : b_num = strtoul(b_unit, &b_end, 16);
85 : :
86 : : /* only compare if the unit addr parsed correctly */
87 : 295 : if (*a_end == 0 && *b_end == 0)
88 : 294 : return (a_num > b_num) - (a_num < b_num);
89 : : }
90 : :
91 : 5857 : return strcmp(a->name, b->name);
92 : : }
93 : :
94 : 696 : bool dt_attach_root(struct dt_node *parent, struct dt_node *root)
95 : : {
96 : : struct dt_node *node;
97 : :
98 : 696 : assert(!root->parent);
99 : :
100 : 696 : if (list_empty(&parent->children)) {
101 : 110 : list_add(&parent->children, &root->list);
102 : 110 : root->parent = parent;
103 : :
104 : 110 : return true;
105 : : }
106 : :
107 : 6133 : dt_for_each_child(parent, node) {
108 : 6028 : int cmp = dt_cmp_subnodes(node, root);
109 : :
110 : : /* Look for duplicates */
111 : 6028 : if (cmp == 0) {
112 : 4 : prerror("DT: %s failed, duplicate %s\n",
113 : : __func__, root->name);
114 : 4 : return false;
115 : : }
116 : :
117 : : /* insert before the first node that's larger
118 : : * the the node we're inserting */
119 : 6024 : if (cmp > 0)
120 : 477 : break;
121 : : }
122 : :
123 : 582 : list_add_before(&parent->children, &node->list, &root->list);
124 : 582 : root->parent = parent;
125 : :
126 : 582 : return true;
127 : : }
128 : :
129 : 705 : static inline void dt_destroy(struct dt_node *dn)
130 : : {
131 : 705 : if (!dn)
132 : 0 : return;
133 : :
134 : 705 : free_name(dn->name);
135 : 705 : free(dn);
136 : : }
137 : :
138 : 598 : struct dt_node *dt_new(struct dt_node *parent, const char *name)
139 : : {
140 : : struct dt_node *new;
141 : 598 : assert(parent);
142 : :
143 : 598 : new = new_node(name);
144 : 598 : if (!dt_attach_root(parent, new)) {
145 : 1 : dt_destroy(new);
146 : 1 : return NULL;
147 : : }
148 : 597 : return new;
149 : : }
150 : :
151 : : /*
152 : : * low level variant, we export this because there are "weird" address
153 : : * formats, such as LPC/ISA bus addresses which have a letter to identify
154 : : * which bus space the address is inside of.
155 : : */
156 : 634 : struct dt_node *__dt_find_by_name_addr(struct dt_node *parent, const char *name,
157 : : const char *addr)
158 : : {
159 : : struct dt_node *node;
160 : :
161 : 634 : if (list_empty(&parent->children))
162 : 413 : return NULL;
163 : :
164 : 963 : dt_for_each_child(parent, node) {
165 : 783 : const char *unit = get_unitname(node);
166 : : int len;
167 : :
168 : 783 : if (!unit)
169 : 15 : continue;
170 : :
171 : : /* match the name */
172 : 768 : len = (int) (unit - node->name) - 1;
173 : 768 : if (strncmp(node->name, name, len))
174 : 697 : continue;
175 : :
176 : : /* match the unit */
177 : 71 : if (strcmp(unit, addr) == 0)
178 : 41 : return node;
179 : : }
180 : :
181 : 671 : dt_for_each_child(parent, node) {
182 : 563 : struct dt_node *ret = __dt_find_by_name_addr(node, name, addr);
183 : :
184 : 563 : if (ret)
185 : 72 : return ret;
186 : : }
187 : :
188 : 108 : return NULL;
189 : : }
190 : :
191 : 71 : struct dt_node *dt_find_by_name_addr(struct dt_node *parent, const char *name,
192 : : uint64_t addr)
193 : : {
194 : : char addr_str[16 + 1]; /* max size of a 64bit int */
195 : 71 : snprintf(addr_str, sizeof(addr_str), "%" PRIx64, addr);
196 : :
197 : 71 : return __dt_find_by_name_addr(parent, name, addr_str);
198 : : }
199 : :
200 : 87 : struct dt_node *dt_new_addr(struct dt_node *parent, const char *name,
201 : : uint64_t addr)
202 : : {
203 : : char *lname;
204 : : struct dt_node *new;
205 : : size_t len;
206 : :
207 : 87 : assert(parent);
208 : 87 : len = strlen(name) + STR_MAX_CHARS(addr) + 2;
209 : 87 : lname = malloc(len);
210 : 87 : if (!lname)
211 : 0 : return NULL;
212 : 87 : snprintf(lname, len, "%s@%llx", name, (long long)addr);
213 : 87 : new = new_node(lname);
214 : 87 : free(lname);
215 : 87 : if (!dt_attach_root(parent, new)) {
216 : 1 : dt_destroy(new);
217 : 1 : return NULL;
218 : : }
219 : 86 : return new;
220 : : }
221 : :
222 : 2 : struct dt_node *dt_new_2addr(struct dt_node *parent, const char *name,
223 : : uint64_t addr0, uint64_t addr1)
224 : : {
225 : : char *lname;
226 : : struct dt_node *new;
227 : : size_t len;
228 : 2 : assert(parent);
229 : :
230 : 2 : len = strlen(name) + 2*STR_MAX_CHARS(addr0) + 3;
231 : 2 : lname = malloc(len);
232 : 2 : if (!lname)
233 : 0 : return NULL;
234 : 2 : snprintf(lname, len, "%s@%llx,%llx",
235 : : name, (long long)addr0, (long long)addr1);
236 : 2 : new = new_node(lname);
237 : 2 : free(lname);
238 : 2 : if (!dt_attach_root(parent, new)) {
239 : 1 : dt_destroy(new);
240 : 1 : return NULL;
241 : : }
242 : 1 : return new;
243 : : }
244 : :
245 : 0 : static struct dt_node *__dt_copy(struct dt_node *node, struct dt_node *parent,
246 : : bool root)
247 : : {
248 : : struct dt_property *prop, *new_prop;
249 : : struct dt_node *new_node, *child;
250 : :
251 : 0 : new_node = dt_new(parent, node->name);
252 : 0 : if (!new_node)
253 : 0 : return NULL;
254 : :
255 : 0 : list_for_each(&node->properties, prop, list) {
256 : 0 : new_prop = dt_add_property(new_node, prop->name, prop->prop,
257 : : prop->len);
258 : 0 : if (!new_prop)
259 : 0 : goto fail;
260 : : }
261 : :
262 : 0 : list_for_each(&node->children, child, list) {
263 : 0 : child = __dt_copy(child, new_node, false);
264 : 0 : if (!child)
265 : 0 : goto fail;
266 : : }
267 : :
268 : 0 : return new_node;
269 : :
270 : 0 : fail:
271 : : /* dt_free will recurse for us, so only free when we unwind to the
272 : : * top-level failure */
273 : 0 : if (root)
274 : 0 : dt_free(new_node);
275 : 0 : return NULL;
276 : : }
277 : :
278 : 0 : struct dt_node *dt_copy(struct dt_node *node, struct dt_node *parent)
279 : : {
280 : 0 : return __dt_copy(node, parent, true);
281 : : }
282 : :
283 : 10 : char *dt_get_path(const struct dt_node *node)
284 : : {
285 : 10 : unsigned int len = 0;
286 : : const struct dt_node *n;
287 : : char *path, *p;
288 : :
289 : : /* Dealing with NULL is for test/debug purposes */
290 : 10 : if (!node)
291 : 0 : return strdup("<NULL>");
292 : :
293 : 36 : for (n = node; n; n = n->parent) {
294 : 26 : len += strlen(n->name);
295 : 26 : if (n->parent || n == node)
296 : 17 : len++;
297 : : }
298 : 10 : path = zalloc(len + 1);
299 : 10 : assert(path);
300 : 10 : p = path + len;
301 : 36 : for (n = node; n; n = n->parent) {
302 : 26 : len = strlen(n->name);
303 : 26 : p -= len;
304 : 26 : memcpy(p, n->name, len);
305 : 26 : if (n->parent || n == node)
306 : 17 : *(--p) = '/';
307 : : }
308 : 10 : assert(p == path);
309 : :
310 : 10 : return p;
311 : : }
312 : :
313 : 1589 : static const char *__dt_path_split(const char *p,
314 : : const char **namep, unsigned int *namel,
315 : : const char **addrp, unsigned int *addrl)
316 : : {
317 : : const char *at, *sl;
318 : :
319 : 1589 : *namel = *addrl = 0;
320 : :
321 : : /* Skip initial '/' */
322 : 1715 : while (*p == '/')
323 : 126 : p++;
324 : :
325 : : /* Check empty path */
326 : 1589 : if (*p == 0)
327 : 0 : return p;
328 : :
329 : 1589 : at = strchr(p, '@');
330 : 1589 : sl = strchr(p, '/');
331 : 1589 : if (sl == NULL)
332 : 1503 : sl = p + strlen(p);
333 : 1589 : if (sl < at)
334 : 2 : at = NULL;
335 : 1589 : if (at) {
336 : 144 : *addrp = at + 1;
337 : 144 : *addrl = sl - at - 1;
338 : : }
339 : 1589 : *namep = p;
340 : 1589 : *namel = at ? (at - p) : (sl - p);
341 : :
342 : 1589 : return sl;
343 : : }
344 : :
345 : 93 : struct dt_node *dt_find_by_path(struct dt_node *root, const char *path)
346 : : {
347 : : struct dt_node *n;
348 : 93 : const char *pn, *pa, *p = path, *nn, *na;
349 : : unsigned int pnl, pal, nnl, nal;
350 : : bool match;
351 : :
352 : : /* Walk path components */
353 : 192 : while (*p) {
354 : : /* Extract next path component */
355 : 160 : p = __dt_path_split(p, &pn, &pnl, &pa, &pal);
356 : 160 : if (pnl == 0 && pal == 0)
357 : 0 : break;
358 : :
359 : : /* Compare with each child node */
360 : 160 : match = false;
361 : 1490 : list_for_each(&root->children, n, list) {
362 : 1429 : match = true;
363 : 1429 : __dt_path_split(n->name, &nn, &nnl, &na, &nal);
364 : 1429 : if (pnl && (pnl != nnl || strncmp(pn, nn, pnl)))
365 : 1330 : match = false;
366 : 1429 : if (pal && (pal != nal || strncmp(pa, na, pal)))
367 : 0 : match = false;
368 : 1429 : if (match) {
369 : 99 : root = n;
370 : 99 : break;
371 : : }
372 : : }
373 : :
374 : : /* No child match */
375 : 160 : if (!match)
376 : 61 : return NULL;
377 : : }
378 : 32 : return root;
379 : : }
380 : :
381 : 38 : struct dt_node *dt_find_by_name(struct dt_node *root, const char *name)
382 : : {
383 : : struct dt_node *child, *match;
384 : :
385 : 45 : list_for_each(&root->children, child, list) {
386 : 27 : if (!strcmp(child->name, name))
387 : 13 : return child;
388 : :
389 : 14 : match = dt_find_by_name(child, name);
390 : 14 : if (match)
391 : 7 : return match;
392 : : }
393 : :
394 : 18 : return NULL;
395 : : }
396 : :
397 : 9 : struct dt_node *dt_find_by_name_before_addr(struct dt_node *root, const char *name)
398 : : {
399 : : struct dt_node *child, *match;
400 : : char *child_name;
401 : :
402 : 14 : list_for_each(&root->children, child, list) {
403 : 7 : child_name = strdup(child->name);
404 : 7 : if (!child_name)
405 : 0 : return NULL;
406 : :
407 : 7 : child_name = strtok(child_name, "@");
408 : 7 : if (!strcmp(child_name, name))
409 : 2 : match = child;
410 : : else
411 : 5 : match = dt_find_by_name_before_addr(child, name);
412 : :
413 : 7 : free(child_name);
414 : 7 : if (match)
415 : 2 : return match;
416 : : }
417 : :
418 : 7 : return NULL;
419 : : }
420 : :
421 : 12 : struct dt_node *dt_new_check(struct dt_node *parent, const char *name)
422 : : {
423 : 12 : struct dt_node *node = dt_find_by_name(parent, name);
424 : :
425 : 12 : if (!node) {
426 : 11 : node = dt_new(parent, name);
427 : 11 : assert(node);
428 : : }
429 : :
430 : 12 : return node;
431 : : }
432 : :
433 : :
434 : 2 : struct dt_node *dt_find_by_phandle(struct dt_node *root, u32 phandle)
435 : : {
436 : : struct dt_node *node;
437 : :
438 : 10 : dt_for_each_node(root, node)
439 : 9 : if (node->phandle == phandle)
440 : 1 : return node;
441 : 1 : return NULL;
442 : : }
443 : :
444 : 2736 : static struct dt_property *new_property(struct dt_node *node,
445 : : const char *name, size_t size)
446 : : {
447 : 2736 : struct dt_property *p = malloc(sizeof(*p) + size);
448 : : char *path;
449 : :
450 : 2736 : if (!p) {
451 : 0 : path = dt_get_path(node);
452 : 0 : prerror("Failed to allocate property \"%s\" for %s of %zu bytes\n",
453 : : name, path, size);
454 : 0 : free(path);
455 : 0 : abort();
456 : : }
457 : 2736 : if (dt_find_property(node, name)) {
458 : 0 : path = dt_get_path(node);
459 : 0 : prerror("Duplicate property \"%s\" in node %s\n",
460 : : name, path);
461 : 0 : free(path);
462 : 0 : abort();
463 : :
464 : : }
465 : :
466 : 2736 : p->name = take_name(name);
467 : 2736 : p->len = size;
468 : 2736 : list_add_tail(&node->properties, &p->list);
469 : 2736 : return p;
470 : : }
471 : :
472 : 587 : struct dt_property *dt_add_property(struct dt_node *node,
473 : : const char *name,
474 : : const void *val, size_t size)
475 : : {
476 : : struct dt_property *p;
477 : :
478 : : /*
479 : : * Filter out phandle properties, we re-generate them
480 : : * when flattening
481 : : */
482 : 587 : if (strcmp(name, "linux,phandle") == 0 ||
483 : 587 : strcmp(name, "phandle") == 0) {
484 : 9 : assert(size == 4);
485 : 9 : node->phandle = *(const u32 *)val;
486 : 9 : if (node->phandle >= last_phandle)
487 : 4 : set_last_phandle(node->phandle);
488 : 9 : return NULL;
489 : : }
490 : :
491 : 578 : p = new_property(node, name, size);
492 : 578 : if (size)
493 : 413 : memcpy(p->prop, val, size);
494 : 578 : return p;
495 : : }
496 : :
497 : 112 : void dt_resize_property(struct dt_property **prop, size_t len)
498 : : {
499 : 112 : size_t new_len = sizeof(**prop) + len;
500 : :
501 : 112 : *prop = realloc(*prop, new_len);
502 : 112 : (*prop)->len = len;
503 : :
504 : : /* Fix up linked lists in case we moved. (note: not an empty list). */
505 : 112 : (*prop)->list.next->prev = &(*prop)->list;
506 : 112 : (*prop)->list.prev->next = &(*prop)->list;
507 : 112 : }
508 : :
509 : 275 : struct dt_property *dt_add_property_string(struct dt_node *node,
510 : : const char *name,
511 : : const char *value)
512 : : {
513 : 275 : size_t len = 0;
514 : 275 : if (value)
515 : 275 : len = strlen(value) + 1;
516 : 275 : return dt_add_property(node, name, value, len);
517 : : }
518 : :
519 : 3 : struct dt_property *dt_add_property_nstr(struct dt_node *node,
520 : : const char *name,
521 : : const char *value, unsigned int vlen)
522 : : {
523 : : struct dt_property *p;
524 : 3 : char *tmp = zalloc(vlen + 1);
525 : :
526 : 3 : if (!tmp)
527 : 0 : return NULL;
528 : :
529 : 3 : strncpy(tmp, value, vlen);
530 : 3 : p = dt_add_property(node, name, tmp, strlen(tmp)+1);
531 : 3 : free(tmp);
532 : :
533 : 3 : return p;
534 : : }
535 : :
536 : 2109 : struct dt_property *__dt_add_property_cells(struct dt_node *node,
537 : : const char *name,
538 : : int count, ...)
539 : : {
540 : : struct dt_property *p;
541 : : fdt32_t *val;
542 : : unsigned int i;
543 : : va_list args;
544 : :
545 : 2109 : p = new_property(node, name, count * sizeof(u32));
546 : 2109 : val = (fdt32_t *)p->prop;
547 : 2109 : va_start(args, count);
548 : 4482 : for (i = 0; i < count; i++)
549 : 2373 : val[i] = cpu_to_fdt32(va_arg(args, u32));
550 : 2109 : va_end(args);
551 : 2109 : return p;
552 : : }
553 : :
554 : 18 : struct dt_property *__dt_add_property_u64s(struct dt_node *node,
555 : : const char *name,
556 : : int count, ...)
557 : : {
558 : : struct dt_property *p;
559 : : fdt64_t *val;
560 : : unsigned int i;
561 : : va_list args;
562 : :
563 : 18 : p = new_property(node, name, count * sizeof(u64));
564 : 18 : val = (fdt64_t *)p->prop;
565 : 18 : va_start(args, count);
566 : 62 : for (i = 0; i < count; i++)
567 : 44 : val[i] = cpu_to_fdt64(va_arg(args, u64));
568 : 18 : va_end(args);
569 : 18 : return p;
570 : : }
571 : :
572 : 31 : struct dt_property *__dt_add_property_strings(struct dt_node *node,
573 : : const char *name,
574 : : int count, ...)
575 : : {
576 : : struct dt_property *p;
577 : : unsigned int i, size;
578 : : va_list args;
579 : : const char *sstr;
580 : : char *s;
581 : :
582 : 31 : va_start(args, count);
583 : 82 : for (i = size = 0; i < count; i++) {
584 : 51 : sstr = va_arg(args, const char *);
585 : 51 : if (sstr)
586 : 51 : size += strlen(sstr) + 1;
587 : : }
588 : 31 : va_end(args);
589 : 31 : if (!size)
590 : 0 : size = 1;
591 : 31 : p = new_property(node, name, size);
592 : 31 : s = (char *)p->prop;
593 : 31 : *s = 0;
594 : 31 : va_start(args, count);
595 : 82 : for (i = 0; i < count; i++) {
596 : 51 : sstr = va_arg(args, const char *);
597 : 51 : if (sstr) {
598 : 51 : strcpy(s, sstr);
599 : 51 : s = s + strlen(sstr) + 1;
600 : : }
601 : : }
602 : 31 : va_end(args);
603 : 31 : return p;
604 : : }
605 : :
606 : 1 : void dt_del_property(struct dt_node *node, struct dt_property *prop)
607 : : {
608 : 1 : list_del_from(&node->properties, &prop->list);
609 : 1 : free_name(prop->name);
610 : 1 : free(prop);
611 : 1 : }
612 : :
613 : 134 : u32 dt_property_get_cell(const struct dt_property *prop, u32 index)
614 : : {
615 : 134 : assert(prop->len >= (index+1)*sizeof(u32));
616 : : /* Always aligned, so this works. */
617 : 134 : return fdt32_to_cpu(((const fdt32_t *)prop->prop)[index]);
618 : : }
619 : :
620 : 0 : u64 dt_property_get_u64(const struct dt_property *prop, u32 index)
621 : : {
622 : 0 : assert(prop->len >= (index+1)*sizeof(u64));
623 : : /* Always aligned, so this works. */
624 : 0 : return fdt64_to_cpu(((const fdt64_t *)prop->prop)[index]);
625 : : }
626 : :
627 : 125 : void dt_property_set_cell(struct dt_property *prop, u32 index, u32 val)
628 : : {
629 : 125 : assert(prop->len >= (index+1)*sizeof(u32));
630 : : /* Always aligned, so this works. */
631 : 125 : ((fdt32_t *)prop->prop)[index] = cpu_to_fdt32(val);
632 : 125 : }
633 : :
634 : : /* First child of this node. */
635 : 324 : struct dt_node *dt_first(const struct dt_node *root)
636 : : {
637 : 324 : return list_top(&root->children, struct dt_node, list);
638 : : }
639 : :
640 : : /* Return next node, or NULL. */
641 : 4339 : struct dt_node *dt_next(const struct dt_node *root,
642 : : const struct dt_node *prev)
643 : : {
644 : 4339 : if (!prev) {
645 : 12 : struct dt_node *first = dt_first(root);
646 : :
647 : 12 : if (!first)
648 : 0 : return NULL;
649 : : else
650 : 12 : return first;
651 : : }
652 : :
653 : : /* Children? */
654 : 4327 : if (!list_empty(&prev->children))
655 : 133 : return dt_first(prev);
656 : :
657 : : do {
658 : : /* More siblings? */
659 : 4325 : if (prev->list.next != &prev->parent->children.n)
660 : 4136 : return list_entry(prev->list.next, struct dt_node,list);
661 : :
662 : : /* No more siblings, move up to parent. */
663 : 189 : prev = prev->parent;
664 : 189 : } while (prev != root);
665 : :
666 : 58 : return NULL;
667 : : }
668 : :
669 : 518 : struct dt_property *__dt_find_property(struct dt_node *node, const char *name)
670 : : {
671 : : struct dt_property *i;
672 : :
673 : 2947 : list_for_each(&node->properties, i, list)
674 : 2543 : if (strcmp(i->name, name) == 0)
675 : 114 : return i;
676 : 404 : return NULL;
677 : : }
678 : :
679 : 4126 : const struct dt_property *dt_find_property(const struct dt_node *node,
680 : : const char *name)
681 : : {
682 : : const struct dt_property *i;
683 : :
684 : 22750 : list_for_each(&node->properties, i, list)
685 : 19036 : if (strcmp(i->name, name) == 0)
686 : 412 : return i;
687 : 3714 : return NULL;
688 : : }
689 : :
690 : 0 : void dt_check_del_prop(struct dt_node *node, const char *name)
691 : : {
692 : : struct dt_property *p;
693 : :
694 : 0 : p = __dt_find_property(node, name);
695 : 0 : if (p)
696 : 0 : dt_del_property(node, p);
697 : 0 : }
698 : 55 : const struct dt_property *dt_require_property(const struct dt_node *node,
699 : : const char *name, int wanted_len)
700 : : {
701 : 55 : const struct dt_property *p = dt_find_property(node, name);
702 : :
703 : 55 : if (!p) {
704 : 0 : const char *path = dt_get_path(node);
705 : :
706 : 0 : prerror("DT: Missing required property %s/%s\n",
707 : : path, name);
708 : 0 : assert(false);
709 : : }
710 : 55 : if (wanted_len >= 0 && p->len != wanted_len) {
711 : 0 : const char *path = dt_get_path(node);
712 : :
713 : 0 : prerror("DT: Unexpected property length %s/%s\n",
714 : : path, name);
715 : 0 : prerror("DT: Expected len: %d got len: %zu\n",
716 : : wanted_len, p->len);
717 : 0 : assert(false);
718 : : }
719 : :
720 : 55 : return p;
721 : : }
722 : :
723 : 289 : bool dt_has_node_property(const struct dt_node *node,
724 : : const char *name, const char *val)
725 : : {
726 : 289 : const struct dt_property *p = dt_find_property(node, name);
727 : :
728 : 289 : if (!p)
729 : 172 : return false;
730 : 117 : if (!val)
731 : 0 : return true;
732 : :
733 : 117 : return p->len == strlen(val) + 1 && memcmp(p->prop, val, p->len) == 0;
734 : : }
735 : :
736 : 448 : bool dt_prop_find_string(const struct dt_property *p, const char *s)
737 : : {
738 : : const char *c, *end;
739 : :
740 : 448 : if (!p)
741 : 350 : return false;
742 : 98 : c = p->prop;
743 : 98 : end = c + p->len;
744 : :
745 : 234 : while(c < end) {
746 : 160 : if (!strcasecmp(s, c))
747 : 24 : return true;
748 : 136 : c += strlen(c) + 1;
749 : : }
750 : 74 : return false;
751 : : }
752 : :
753 : 444 : bool dt_node_is_compatible(const struct dt_node *node, const char *compat)
754 : : {
755 : 444 : const struct dt_property *p = dt_find_property(node, "compatible");
756 : :
757 : 444 : return dt_prop_find_string(p, compat);
758 : : }
759 : :
760 : 19 : struct dt_node *dt_find_compatible_node(struct dt_node *root,
761 : : struct dt_node *prev,
762 : : const char *compat)
763 : : {
764 : 19 : struct dt_node *node = prev;
765 : :
766 : 431 : while ((node = dt_next(root, node)))
767 : 428 : if (dt_node_is_compatible(node, compat))
768 : 16 : return node;
769 : 3 : return NULL;
770 : : }
771 : :
772 : 1 : u64 dt_prop_get_u64(const struct dt_node *node, const char *prop)
773 : : {
774 : 1 : const struct dt_property *p = dt_require_property(node, prop, 8);
775 : :
776 : 1 : return ((u64)dt_property_get_cell(p, 0) << 32)
777 : 1 : | dt_property_get_cell(p, 1);
778 : : }
779 : :
780 : 4 : u64 dt_prop_get_u64_def(const struct dt_node *node, const char *prop, u64 def)
781 : : {
782 : 4 : const struct dt_property *p = dt_find_property(node, prop);
783 : :
784 : 4 : if (!p)
785 : 1 : return def;
786 : :
787 : 3 : return ((u64)dt_property_get_cell(p, 0) << 32)
788 : 3 : | dt_property_get_cell(p, 1);
789 : : }
790 : :
791 : 5 : u32 dt_prop_get_u32(const struct dt_node *node, const char *prop)
792 : : {
793 : 5 : const struct dt_property *p = dt_require_property(node, prop, 4);
794 : :
795 : 5 : return dt_property_get_cell(p, 0);
796 : : }
797 : :
798 : 86 : u32 dt_prop_get_u32_def(const struct dt_node *node, const char *prop, u32 def)
799 : : {
800 : 86 : const struct dt_property *p = dt_find_property(node, prop);
801 : :
802 : 86 : if (!p)
803 : 5 : return def;
804 : :
805 : 81 : return dt_property_get_cell(p, 0);
806 : : }
807 : :
808 : 5 : const void *dt_prop_get(const struct dt_node *node, const char *prop)
809 : : {
810 : 5 : const struct dt_property *p = dt_require_property(node, prop, -1);
811 : :
812 : 5 : return p->prop;
813 : : }
814 : :
815 : 2 : const void *dt_prop_get_def(const struct dt_node *node, const char *prop,
816 : : void *def)
817 : : {
818 : 2 : const struct dt_property *p = dt_find_property(node, prop);
819 : :
820 : 2 : return p ? p->prop : def;
821 : : }
822 : :
823 : 2 : const void *dt_prop_get_def_size(const struct dt_node *node, const char *prop,
824 : : void *def, size_t *len)
825 : : {
826 : 2 : const struct dt_property *p = dt_find_property(node, prop);
827 : 2 : *len = 0;
828 : 2 : if (p)
829 : 1 : *len = p->len;
830 : :
831 : 2 : return p ? p->prop : def;
832 : : }
833 : :
834 : 4 : u32 dt_prop_get_cell(const struct dt_node *node, const char *prop, u32 cell)
835 : : {
836 : 4 : const struct dt_property *p = dt_require_property(node, prop, -1);
837 : :
838 : 4 : return dt_property_get_cell(p, cell);
839 : : }
840 : :
841 : 2 : u32 dt_prop_get_cell_def(const struct dt_node *node, const char *prop,
842 : : u32 cell, u32 def)
843 : : {
844 : 2 : const struct dt_property *p = dt_find_property(node, prop);
845 : :
846 : 2 : if (!p)
847 : 1 : return def;
848 : :
849 : 1 : return dt_property_get_cell(p, cell);
850 : : }
851 : :
852 : 702 : void dt_free(struct dt_node *node)
853 : : {
854 : : struct dt_node *child;
855 : : struct dt_property *p;
856 : :
857 : 1378 : while ((child = list_top(&node->children, struct dt_node, list)))
858 : 676 : dt_free(child);
859 : :
860 : 3349 : while ((p = list_pop(&node->properties, struct dt_property, list))) {
861 : 2647 : free_name(p->name);
862 : 2647 : free(p);
863 : : }
864 : :
865 : 702 : if (node->parent)
866 : 677 : list_del_from(&node->parent->children, &node->list);
867 : 702 : dt_destroy(node);
868 : 702 : }
869 : :
870 : 8 : int dt_expand_node(struct dt_node *node, const void *fdt, int fdt_node)
871 : : {
872 : : const struct fdt_property *prop;
873 : : int offset, nextoffset, err;
874 : : struct dt_node *child;
875 : : const char *name;
876 : : uint32_t tag;
877 : :
878 : 8 : if (((err = fdt_check_header(fdt)) != 0)
879 : 8 : || ((err = fdt_check_node_offset_(fdt, fdt_node)) < 0)) {
880 : 0 : prerror("FDT: Error %d parsing node 0x%x\n", err, fdt_node);
881 : 0 : return -1;
882 : : }
883 : :
884 : 8 : nextoffset = err;
885 : : do {
886 : 47 : offset = nextoffset;
887 : :
888 : 47 : tag = fdt_next_tag(fdt, offset, &nextoffset);
889 : 47 : switch (tag) {
890 : 32 : case FDT_PROP:
891 : 32 : prop = fdt_offset_ptr_(fdt, offset);
892 : 32 : name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
893 : 32 : dt_add_property(node, name, prop->data,
894 : 32 : fdt32_to_cpu(prop->len));
895 : 32 : break;
896 : 7 : case FDT_BEGIN_NODE:
897 : 7 : name = fdt_get_name(fdt, offset, NULL);
898 : 7 : child = dt_new_root(name);
899 : 7 : assert(child);
900 : 7 : nextoffset = dt_expand_node(child, fdt, offset);
901 : :
902 : : /*
903 : : * This may fail in case of duplicate, keep it
904 : : * going for now, we may ultimately want to
905 : : * assert
906 : : */
907 : 7 : if (!dt_attach_root(node, child))
908 : : /**
909 : : * @fwts-label DTHasDuplicateNodeID
910 : : * @fwts-advice OPAL will parse the Flattened
911 : : * Device Tree(FDT), which can be generated
912 : : * from different firmware sources. During
913 : : * expansion of FDT, OPAL observed a node
914 : : * assigned multiple times (a duplicate). This
915 : : * indicates either a Hostboot bug *OR*, more
916 : : * likely, a bug in the platform XML. Check
917 : : * the platform XML for duplicate IDs for
918 : : * this type of device. Because of this
919 : : * duplicate node, OPAL won't add the hardware
920 : : * device found with a duplicate node ID into
921 : : * DT, rendering the corresponding device not
922 : : * functional.
923 : : */
924 : 0 : prlog(PR_ERR, "DT: Found duplicate node: %s\n",
925 : : child->name);
926 : 7 : break;
927 : 0 : case FDT_END:
928 : 0 : return -1;
929 : : }
930 : 47 : } while (tag != FDT_END_NODE);
931 : :
932 : 8 : return nextoffset;
933 : : }
934 : :
935 : 0 : void dt_expand(const void *fdt)
936 : : {
937 : 0 : prlog(PR_DEBUG, "FDT: Parsing fdt @%p\n", fdt);
938 : :
939 : 0 : if (dt_expand_node(dt_root, fdt, 0) < 0)
940 : 0 : abort();
941 : 0 : }
942 : :
943 : 97 : u64 dt_get_number(const void *pdata, unsigned int cells)
944 : : {
945 : 97 : const __be32 *p = pdata;
946 : 97 : u64 ret = 0;
947 : :
948 : 273 : while(cells--)
949 : 176 : ret = (ret << 32) | be32_to_cpu(*(p++));
950 : 97 : return ret;
951 : : }
952 : :
953 : 39 : u32 dt_n_address_cells(const struct dt_node *node)
954 : : {
955 : 39 : if (!node->parent)
956 : 0 : return 0;
957 : 39 : return dt_prop_get_u32_def(node->parent, "#address-cells", 2);
958 : : }
959 : :
960 : 33 : u32 dt_n_size_cells(const struct dt_node *node)
961 : : {
962 : 33 : if (!node->parent)
963 : 0 : return 0;
964 : 33 : return dt_prop_get_u32_def(node->parent, "#size-cells", 1);
965 : : }
966 : :
967 : 33 : u64 dt_get_address(const struct dt_node *node, unsigned int index,
968 : : u64 *out_size)
969 : : {
970 : : const struct dt_property *p;
971 : 33 : u32 na = dt_n_address_cells(node);
972 : 33 : u32 ns = dt_n_size_cells(node);
973 : : u32 pos, n;
974 : :
975 : 33 : p = dt_require_property(node, "reg", -1);
976 : 33 : n = (na + ns) * sizeof(u32);
977 : 33 : pos = n * index;
978 : 33 : assert((pos + n) <= p->len);
979 : 33 : if (out_size)
980 : 29 : *out_size = dt_get_number(p->prop + pos + na * sizeof(u32), ns);
981 : 33 : return dt_get_number(p->prop + pos, na);
982 : : }
983 : :
984 : 89 : u32 __dt_get_chip_id(const struct dt_node *node)
985 : : {
986 : : const struct dt_property *prop;
987 : :
988 : 313 : for (; node; node = node->parent) {
989 : 258 : prop = dt_find_property(node, "ibm,chip-id");
990 : 258 : if (prop)
991 : 34 : return dt_property_get_cell(prop, 0);
992 : : }
993 : 55 : return 0xffffffff;
994 : : }
995 : :
996 : 11 : u32 dt_get_chip_id(const struct dt_node *node)
997 : : {
998 : 11 : u32 id = __dt_get_chip_id(node);
999 : 11 : assert(id != 0xffffffff);
1000 : 11 : return id;
1001 : : }
1002 : :
1003 : 6 : struct dt_node *dt_find_compatible_node_on_chip(struct dt_node *root,
1004 : : struct dt_node *prev,
1005 : : const char *compat,
1006 : : uint32_t chip_id)
1007 : : {
1008 : 6 : struct dt_node *node = prev;
1009 : :
1010 : 80 : while ((node = dt_next(root, node))) {
1011 : 78 : u32 cid = __dt_get_chip_id(node);
1012 : 92 : if (cid == chip_id &&
1013 : 14 : dt_node_is_compatible(node, compat))
1014 : 4 : return node;
1015 : : }
1016 : 2 : return NULL;
1017 : : }
1018 : :
1019 : 0 : unsigned int dt_count_addresses(const struct dt_node *node)
1020 : : {
1021 : : const struct dt_property *p;
1022 : 0 : u32 na = dt_n_address_cells(node);
1023 : 0 : u32 ns = dt_n_size_cells(node);
1024 : : u32 n;
1025 : :
1026 : 0 : p = dt_require_property(node, "reg", -1);
1027 : 0 : n = (na + ns) * sizeof(u32);
1028 : :
1029 : 0 : if (n == 0)
1030 : 0 : return 0;
1031 : :
1032 : 0 : return p->len / n;
1033 : : }
1034 : :
1035 : : /* Translates an address from the given bus into its parent's address space */
1036 : 6 : static u64 dt_translate_one(const struct dt_node *bus, u64 addr)
1037 : : {
1038 : : u32 ranges_count, na, ns, parent_na;
1039 : : const struct dt_property *p;
1040 : : const u32 *ranges;
1041 : : int i, stride;
1042 : :
1043 : 6 : assert(bus->parent);
1044 : :
1045 : 6 : na = dt_prop_get_u32_def(bus, "#address-cells", 2);
1046 : 6 : ns = dt_prop_get_u32_def(bus, "#size-cells", 2);
1047 : 6 : parent_na = dt_n_address_cells(bus);
1048 : :
1049 : 6 : stride = na + ns + parent_na;
1050 : :
1051 : : /*
1052 : : * FIXME: We should handle arbitrary length addresses, rather than
1053 : : * limiting it to 64bit. If someone wants/needs that they
1054 : : * can implement the bignum math for it :)
1055 : : */
1056 : 6 : assert(na <= 2);
1057 : 6 : assert(parent_na <= 2);
1058 : :
1059 : : /* We should never be trying to translate an address without a ranges */
1060 : 6 : p = dt_require_property(bus, "ranges", -1);
1061 : :
1062 : 6 : ranges = (u32 *) &p->prop;
1063 : 6 : ranges_count = (p->len / 4) / (na + parent_na + ns);
1064 : :
1065 : : /* An empty ranges property implies 1-1 translation */
1066 : 6 : if (ranges_count == 0)
1067 : 0 : return addr;
1068 : :
1069 : 7 : for (i = 0; i < ranges_count; i++, ranges += stride) {
1070 : : /* ranges format: <child base> <parent base> <size> */
1071 : 7 : u64 child_base = dt_get_number(ranges, na);
1072 : 7 : u64 parent_base = dt_get_number(ranges + na, parent_na);
1073 : 7 : u64 size = dt_get_number(ranges + na + parent_na, ns);
1074 : :
1075 : 7 : if (addr >= child_base && addr < child_base + size)
1076 : 6 : return (addr - child_base) + parent_base;
1077 : : }
1078 : :
1079 : : /* input address was outside the any of our mapped ranges */
1080 : 0 : return 0;
1081 : : }
1082 : :
1083 : 4 : u64 dt_translate_address(const struct dt_node *node, unsigned int index,
1084 : : u64 *out_size)
1085 : : {
1086 : 4 : u64 addr = dt_get_address(node, index, NULL);
1087 : 4 : struct dt_node *bus = node->parent;
1088 : :
1089 : : /* FIXME: One day we will probably want to use this, but for now just
1090 : : * force it it to be zero since we only support returning a u64 or u32
1091 : : */
1092 : 4 : assert(!out_size);
1093 : :
1094 : : /* apply each translation until we hit the root bus */
1095 : 10 : while (bus->parent) {
1096 : 6 : addr = dt_translate_one(bus, addr);
1097 : 6 : bus = bus->parent;
1098 : : }
1099 : :
1100 : 4 : return addr;
1101 : : }
1102 : :
1103 : 0 : bool dt_node_is_enabled(struct dt_node *node)
1104 : : {
1105 : 0 : const struct dt_property *p = dt_find_property(node, "status");
1106 : :
1107 : 0 : if (!p)
1108 : 0 : return true;
1109 : :
1110 : 0 : return p->len > 1 && p->prop[0] == 'o' && p->prop[1] == 'k';
1111 : : }
1112 : :
1113 : : /*
1114 : : * Function to fixup the phandle in the subtree.
1115 : : */
1116 : 1 : void dt_adjust_subtree_phandle(struct dt_node *dev,
1117 : : const char** (get_properties_to_fix)(struct dt_node *n))
1118 : : {
1119 : : struct dt_node *node;
1120 : : struct dt_property *prop;
1121 : 1 : u32 phandle, max_phandle = 0, import_phandle = new_phandle();
1122 : : __be32 p;
1123 : : const char **name;
1124 : :
1125 : 7 : dt_for_each_node(dev, node) {
1126 : : const char **props_to_update;
1127 : 6 : node->phandle += import_phandle;
1128 : :
1129 : : /*
1130 : : * calculate max_phandle(new_tree), needed to update
1131 : : * last_phandle.
1132 : : */
1133 : 6 : if (node->phandle >= max_phandle)
1134 : 6 : max_phandle = node->phandle;
1135 : :
1136 : 6 : props_to_update = get_properties_to_fix(node);
1137 : 6 : if (!props_to_update)
1138 : 4 : continue;
1139 : 4 : for (name = props_to_update; *name != NULL; name++) {
1140 : 2 : prop = __dt_find_property(node, *name);
1141 : 2 : if (!prop)
1142 : 0 : continue;
1143 : 2 : phandle = dt_prop_get_u32(node, *name);
1144 : 2 : phandle += import_phandle;
1145 : 2 : p = cpu_to_be32(phandle);
1146 : 2 : memcpy((char *)&prop->prop, &p, prop->len);
1147 : : }
1148 : : }
1149 : :
1150 : 1 : set_last_phandle(max_phandle);
1151 : 1 : }
|