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