• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2007.
4  */
5 
6 #include "dtc.h"
7 #include "srcpos.h"
8 
9 #ifdef TRACE_CHECKS
10 #define TRACE(c, ...)                                                                                                  \
11     do {                                                                                                               \
12         fprintf(stderr, "=== %s: ", (c)->name);                                                                        \
13         fprintf(stderr, __VA_ARGS__);                                                                                  \
14         fprintf(stderr, "\n");                                                                                         \
15     } while (0)
16 #else
17 #define TRACE(c, fmt, ...)                                                                                             \
18     do {                                                                                                               \
19     } while (0)
20 #endif
21 
22 enum checkstatus {
23     UNCHECKED = 0,
24     PREREQ,
25     PASSED,
26     FAILED,
27 };
28 
29 struct check;
30 
31 typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node);
32 
33 struct check {
34     const char *name;
35     check_fn fn;
36     void *data;
37     bool warn, error;
38     enum checkstatus status;
39     bool inprogress;
40     int num_prereqs;
41     struct check **prereq;
42 };
43 
44 #define CHECK_ENTRY(nm_, fn_, d_, w_, e_, ...)                                                                         \
45     static struct check *nm_##_prereqs[] = {__VA_ARGS__};                                                              \
46     static struct check nm_ = {                                                                                        \
47         .name = #nm_,                                                                                                  \
48         .fn = (fn_),                                                                                                   \
49         .data = (d_),                                                                                                  \
50         .warn = (w_),                                                                                                  \
51         .error = (e_),                                                                                                 \
52         .status = UNCHECKED,                                                                                           \
53         .num_prereqs = ARRAY_SIZE(nm_##_prereqs),                                                                      \
54         .prereq = nm_##_prereqs,                                                                                       \
55     };
56 #define WARNING(nm_, fn_, d_, ...) CHECK_ENTRY(nm_, fn_, d_, true, false, __VA_ARGS__)
57 #define ERROR(nm_, fn_, d_, ...) CHECK_ENTRY(nm_, fn_, d_, false, true, __VA_ARGS__)
58 #define CHECK(nm_, fn_, d_, ...) CHECK_ENTRY(nm_, fn_, d_, false, false, __VA_ARGS__)
59 
60 static inline void PRINTF(5, 6)
check_msg(struct check * c,struct dt_info * dti,struct node * node,struct property * prop,const char * fmt,...)61     check_msg(struct check *c, struct dt_info *dti, struct node *node, struct property *prop, const char *fmt, ...)
62 {
63     va_list ap;
64     char *str = NULL;
65     struct srcpos *pos = NULL;
66     char *file_str;
67 
68     if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2))) {
69         return;
70     }
71 
72     if (prop && prop->srcpos) {
73         pos = prop->srcpos;
74     } else if (node && node->srcpos) {
75         pos = node->srcpos;
76     }
77 
78     if (pos) {
79         file_str = srcpos_string(pos);
80         xasprintf(&str, "%s", file_str);
81         free(file_str);
82     } else if (streq(dti->outname, "-")) {
83         xasprintf(&str, "<stdout>");
84     } else {
85         xasprintf(&str, "%s", dti->outname);
86     }
87 
88     xasprintf_append(&str, ": %s (%s): ", (c->error) ? "ERROR" : "Warning", c->name);
89 
90     if (node) {
91         if (prop) {
92             xasprintf_append(&str, "%s:%s: ", node->fullpath, prop->name);
93         } else {
94             xasprintf_append(&str, "%s: ", node->fullpath);
95         }
96     }
97 
98     va_start(ap, fmt);
99     xavsprintf_append(&str, fmt, ap);
100     va_end(ap);
101 
102     xasprintf_append(&str, "\n");
103 
104     if (!prop && pos) {
105         pos = node->srcpos;
106         while (pos->next) {
107             pos = pos->next;
108 
109             file_str = srcpos_string(pos);
110             xasprintf_append(&str, "  also defined at %s\n", file_str);
111             free(file_str);
112         }
113     }
114 
115     fputs(str, stderr);
116 }
117 
118 #define FAIL(c, dti, node, ...)                                                                                        \
119     do {                                                                                                               \
120         TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__);                                                         \
121         (c)->status = FAILED;                                                                                          \
122         check_msg((c), dti, node, NULL, __VA_ARGS__);                                                                  \
123     } while (0)
124 
125 #define FAIL_PROP(c, dti, node, prop, ...)                                                                             \
126     do {                                                                                                               \
127         TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__);                                                         \
128         (c)->status = FAILED;                                                                                          \
129         check_msg((c), dti, node, prop, __VA_ARGS__);                                                                  \
130     } while (0)
131 
check_nodes_props(struct check * c,struct dt_info * dti,struct node * node)132 static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node)
133 {
134     struct node *child;
135 
136     TRACE(c, "%s", node->fullpath);
137     if (c->fn) {
138         c->fn(c, dti, node);
139     }
140 
141     for_each_child(node, child) check_nodes_props(c, dti, child);
142 }
143 
run_check(struct check * c,struct dt_info * dti)144 static bool run_check(struct check *c, struct dt_info *dti)
145 {
146     struct node *dt = dti->dt;
147     bool error = false;
148     int i;
149 
150     assert(!c->inprogress);
151 
152     if (c->status != UNCHECKED) {
153         goto out;
154     }
155 
156     c->inprogress = true;
157 
158     for (i = 0; i < c->num_prereqs; i++) {
159         struct check *prq = c->prereq[i];
160         error = error || run_check(prq, dti);
161         if (prq->status != PASSED) {
162             c->status = PREREQ;
163             check_msg(c, dti, NULL, NULL, "Failed prerequisite '%s'", c->prereq[i]->name);
164         }
165     }
166 
167     if (c->status != UNCHECKED) {
168         goto out;
169     }
170 
171     check_nodes_props(c, dti, dt);
172 
173     if (c->status == UNCHECKED) {
174         c->status = PASSED;
175     }
176 
177     TRACE(c, "\tCompleted, status %d", c->status);
178 
179 out:
180     c->inprogress = false;
181     if ((c->status != PASSED) && (c->error)) {
182         error = true;
183     }
184     return error;
185 }
186 
187 /*
188  * Utility check functions
189  */
190 
191 /* A check which always fails, for testing purposes only */
check_always_fail(struct check * c,struct dt_info * dti,struct node * node)192 static inline void check_always_fail(struct check *c, struct dt_info *dti, struct node *node)
193 {
194     FAIL(c, dti, node, "always_fail check");
195 }
196 CHECK(always_fail, check_always_fail, NULL);
197 
check_is_string(struct check * c,struct dt_info * dti,struct node * node)198 static void check_is_string(struct check *c, struct dt_info *dti, struct node *node)
199 {
200     struct property *prop;
201     char *propname = c->data;
202 
203     prop = get_property(node, propname);
204     if (!prop) {
205         return; /* Not present, assumed ok */
206     }
207 
208     if (!data_is_one_string(prop->val)) {
209         FAIL_PROP(c, dti, node, prop, "property is not a string");
210     }
211 }
212 #define WARNING_IF_NOT_STRING(nm, propname) WARNING(nm, check_is_string, (propname))
213 #define ERROR_IF_NOT_STRING(nm, propname) ERROR(nm, check_is_string, (propname))
214 
check_is_string_list(struct check * c,struct dt_info * dti,struct node * node)215 static void check_is_string_list(struct check *c, struct dt_info *dti, struct node *node)
216 {
217     int rem, l;
218     struct property *prop;
219     char *propname = c->data;
220     char *str;
221 
222     prop = get_property(node, propname);
223     if (!prop) {
224         return; /* Not present, assumed ok */
225     }
226 
227     str = prop->val.val;
228     rem = prop->val.len;
229     while (rem > 0) {
230         l = strnlen(str, rem);
231         if (l == rem) {
232             FAIL_PROP(c, dti, node, prop, "property is not a string list");
233             break;
234         }
235         rem -= l + 1;
236         str += l + 1;
237     }
238 }
239 #define WARNING_IF_NOT_STRING_LIST(nm, propname) WARNING(nm, check_is_string_list, (propname))
240 #define ERROR_IF_NOT_STRING_LIST(nm, propname) ERROR(nm, check_is_string_list, (propname))
241 
check_is_cell(struct check * c,struct dt_info * dti,struct node * node)242 static void check_is_cell(struct check *c, struct dt_info *dti, struct node *node)
243 {
244     struct property *prop;
245     char *propname = c->data;
246 
247     prop = get_property(node, propname);
248     if (!prop) {
249         return; /* Not present, assumed ok */
250     }
251 
252     if (prop->val.len != sizeof(cell_t)) {
253         FAIL_PROP(c, dti, node, prop, "property is not a single cell");
254     }
255 }
256 #define WARNING_IF_NOT_CELL(nm, propname) WARNING(nm, check_is_cell, (propname))
257 #define ERROR_IF_NOT_CELL(nm, propname) ERROR(nm, check_is_cell, (propname))
258 
259 /*
260  * Structural check functions
261  */
262 
check_duplicate_node_names(struct check * c,struct dt_info * dti,struct node * node)263 static void check_duplicate_node_names(struct check *c, struct dt_info *dti, struct node *node)
264 {
265     struct node *child, *child2;
266 
267     for_each_child(node, child) {
268         for (child2 = child->next_sibling; child2;
269                                      child2 = child2->next_sibling) {
270             if (streq(child->name, child2->name))
271                 FAIL(c, dti, child2, "Duplicate node name");
272         }
273     }
274 }
275 ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
276 
check_duplicate_property_names(struct check * c,struct dt_info * dti,struct node * node)277 static void check_duplicate_property_names(struct check *c, struct dt_info *dti, struct node *node)
278 {
279     struct property *prop, *prop2;
280 
281     for_each_property(node, prop)
282     {
283         for (prop2 = prop->next; prop2; prop2 = prop2->next) {
284             if (prop2->deleted) {
285                 continue;
286             }
287             if (streq(prop->name, prop2->name)) {
288                 FAIL_PROP(c, dti, node, prop, "Duplicate property name");
289             }
290         }
291     }
292 }
293 ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
294 
295 #define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
296 #define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
297 #define DIGITS "0123456789"
298 #define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
299 #define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
300 
check_node_name_chars(struct check * c,struct dt_info * dti,struct node * node)301 static void check_node_name_chars(struct check *c, struct dt_info *dti, struct node *node)
302 {
303     int n = strspn(node->name, c->data);
304     if (n < strlen(node->name)) {
305         FAIL(c, dti, node, "Bad character '%c' in node name", node->name[n]);
306     }
307 }
308 ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
309 
check_node_name_chars_strict(struct check * c,struct dt_info * dti,struct node * node)310 static void check_node_name_chars_strict(struct check *c, struct dt_info *dti, struct node *node)
311 {
312     int n = strspn(node->name, c->data);
313     if (n < node->basenamelen) {
314         FAIL(c, dti, node, "Character '%c' not recommended in node name", node->name[n]);
315     }
316 }
317 CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT);
318 
check_node_name_format(struct check * c,struct dt_info * dti,struct node * node)319 static void check_node_name_format(struct check *c, struct dt_info *dti, struct node *node)
320 {
321     if (strchr(get_unitname(node), '@')) {
322         FAIL(c, dti, node, "multiple '@' characters in node name");
323     }
324 }
325 ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
326 
check_unit_address_vs_reg(struct check * c,struct dt_info * dti,struct node * node)327 static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti, struct node *node)
328 {
329     const char *unitname = get_unitname(node);
330     struct property *prop = get_property(node, "reg");
331 
332     if (get_subnode(node, "__overlay__")) {
333         /* HACK: Overlay fragments are a special case */
334         return;
335     }
336 
337     if (!prop) {
338         prop = get_property(node, "ranges");
339         if (prop && !prop->val.len) {
340             prop = NULL;
341         }
342     }
343 
344     if (prop) {
345         if (!unitname[0]) {
346             FAIL(c, dti, node, "node has a reg or ranges property, but no unit name");
347         }
348     } else {
349         if (unitname[0]) {
350             FAIL(c, dti, node, "node has a unit name, but no reg or ranges property");
351         }
352     }
353 }
354 WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
355 
check_property_name_chars(struct check * c,struct dt_info * dti,struct node * node)356 static void check_property_name_chars(struct check *c, struct dt_info *dti, struct node *node)
357 {
358     struct property *prop;
359 
360     for_each_property(node, prop)
361     {
362         int n = strspn(prop->name, c->data);
363         if (n < strlen(prop->name)) {
364             FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name", prop->name[n]);
365         }
366     }
367 }
368 ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
369 
check_property_name_chars_strict(struct check * c,struct dt_info * dti,struct node * node)370 static void check_property_name_chars_strict(struct check *c, struct dt_info *dti, struct node *node)
371 {
372     struct property *prop;
373 
374     for_each_property(node, prop)
375     {
376         const char *name = prop->name;
377         int n = strspn(name, c->data);
378         if (n == strlen(prop->name)) {
379             continue;
380         }
381 
382         /* Certain names are whitelisted */
383         if (streq(name, "device_type")) {
384             continue;
385         }
386 
387         /*
388          * # is only allowed at the beginning of property names not counting
389          * the vendor prefix.
390          */
391         if (name[n] == '#' && ((n == 0) || (name[n - 1] == ','))) {
392             name += n + 1;
393             n = strspn(name, c->data);
394         }
395         if (n < strlen(name)) {
396             FAIL_PROP(c, dti, node, prop, "Character '%c' not recommended in property name", name[n]);
397         }
398     }
399 }
400 CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT);
401 
402 #define DESCLABEL_FMT "%s%s%s%s%s"
403 #define DESCLABEL_ARGS(node, prop, mark)                                                                               \
404     ((mark) ? "value of " : ""), ((prop) ? "'" : ""), ((prop) ? (prop)->name : ""), ((prop) ? "' in " : ""),           \
405         (node)->fullpath
406 
check_duplicate_label(struct check * c,struct dt_info * dti,const char * label,struct node * node,struct property * prop,struct marker * mark)407 static void check_duplicate_label(struct check *c, struct dt_info *dti, const char *label, struct node *node,
408                                   struct property *prop, struct marker *mark)
409 {
410     struct node *dt = dti->dt;
411     struct node *othernode = NULL;
412     struct property *otherprop = NULL;
413     struct marker *othermark = NULL;
414 
415     othernode = get_node_by_label(dt, label);
416     if (!othernode) {
417         otherprop = get_property_by_label(dt, label, &othernode);
418     }
419     if (!othernode) {
420         othermark = get_marker_label(dt, label, &othernode, &otherprop);
421     }
422 
423     if (!othernode) {
424         return;
425     }
426 
427     if ((othernode != node) || (otherprop != prop) || (othermark != mark)) {
428         FAIL(c, dti, node, "Duplicate label '%s' on " DESCLABEL_FMT " and " DESCLABEL_FMT, label,
429              DESCLABEL_ARGS(node, prop, mark), DESCLABEL_ARGS(othernode, otherprop, othermark));
430     }
431 }
432 
check_duplicate_label_node(struct check * c,struct dt_info * dti,struct node * node)433 static void check_duplicate_label_node(struct check *c, struct dt_info *dti, struct node *node)
434 {
435     struct label *l;
436     struct property *prop;
437 
438     for_each_label(node->labels, l) check_duplicate_label(c, dti, l->label, node, NULL, NULL);
439 
440     for_each_property(node, prop)
441     {
442         struct marker *m = prop->val.markers;
443 
444         for_each_label(prop->labels, l) check_duplicate_label(c, dti, l->label, node, prop, NULL);
445 
446         for_each_marker_of_type(m, LABEL) check_duplicate_label(c, dti, m->ref, node, prop, m);
447     }
448 }
449 ERROR(duplicate_label, check_duplicate_label_node, NULL);
450 
check_phandle_prop(struct check * c,struct dt_info * dti,struct node * node,const char * propname)451 static cell_t check_phandle_prop(struct check *c, struct dt_info *dti, struct node *node, const char *propname)
452 {
453     struct node *root = dti->dt;
454     struct property *prop;
455     struct marker *m;
456     cell_t phandle;
457 
458     prop = get_property(node, propname);
459     if (!prop) {
460         return 0;
461     }
462 
463     if (prop->val.len != sizeof(cell_t)) {
464         FAIL_PROP(c, dti, node, prop, "bad length (%d) %s property", prop->val.len, prop->name);
465         return 0;
466     }
467 
468     m = prop->val.markers;
469     for_each_marker_of_type(m, REF_PHANDLE)
470     {
471         assert(m->offset == 0);
472         if (node != get_node_by_ref(root, m->ref)) {
473         /* "Set this node's phandle equal to some
474          * other node's phandle".  That's nonsensical
475          * by construction. */
476             FAIL(c, dti, node, "%s is a reference to another node", prop->name);
477         }
478         /* But setting this node's phandle equal to its own
479          * phandle is allowed - that means allocate a unique
480          * phandle for this node, even if it's not otherwise
481          * referenced.  The value will be filled in later, so
482          * we treat it as having no phandle data for now. */
483         return 0;
484     }
485 
486     phandle = propval_cell(prop);
487     if ((phandle == 0) || (phandle == -1)) {
488         FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property", phandle, prop->name);
489         return 0;
490     }
491 
492     return phandle;
493 }
494 
check_explicit_phandles(struct check * c,struct dt_info * dti,struct node * node)495 static void check_explicit_phandles(struct check *c, struct dt_info *dti, struct node *node)
496 {
497     struct node *root = dti->dt;
498     struct node *other;
499     cell_t phandle, linux_phandle;
500 
501     /* Nothing should have assigned phandles yet */
502     assert(!node->phandle);
503 
504     phandle = check_phandle_prop(c, dti, node, "phandle");
505 
506     linux_phandle = check_phandle_prop(c, dti, node, "linux,phandle");
507     if (!phandle && !linux_phandle) {
508         /* No valid phandles; nothing further to check */
509         return;
510     }
511 
512     if (linux_phandle && phandle && (phandle != linux_phandle)) {
513         FAIL(c, dti, node,
514              "mismatching 'phandle' and 'linux,phandle'"
515              " properties");
516     }
517 
518     if (linux_phandle && !phandle) {
519         phandle = linux_phandle;
520     }
521 
522     other = get_node_by_phandle(root, phandle);
523     if (other && (other != node)) {
524         FAIL(c, dti, node, "duplicated phandle 0x%x (seen before at %s)", phandle, other->fullpath);
525         return;
526     }
527 
528     node->phandle = phandle;
529 }
530 ERROR(explicit_phandles, check_explicit_phandles, NULL);
531 
check_name_properties(struct check * c,struct dt_info * dti,struct node * node)532 static void check_name_properties(struct check *c, struct dt_info *dti, struct node *node)
533 {
534     struct property **pp, *prop = NULL;
535 
536     for (pp = &node->proplist; *pp; pp = &((*pp)->next)) {
537         if (streq((*pp)->name, "name")) {
538             prop = *pp;
539             break;
540         }
541     }
542 
543     if (!prop) {
544         return; /* No name property, that's fine */
545     }
546 
547     if ((prop->val.len != node->basenamelen + 1) || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
548         FAIL(c, dti, node,
549              "\"name\" property is incorrect (\"%s\" instead"
550              " of base node name)",
551              prop->val.val);
552     } else {
553         /* The name property is correct, and therefore redundant.
554          * Delete it */
555         *pp = prop->next;
556         free(prop->name);
557         data_free(prop->val);
558         free(prop);
559     }
560 }
561 ERROR_IF_NOT_STRING(name_is_string, "name");
562 ERROR(name_properties, check_name_properties, NULL, &name_is_string);
563 
564 /*
565  * Reference fixup functions
566  */
567 
fixup_phandle_references(struct check * c,struct dt_info * dti,struct node * node)568 static void fixup_phandle_references(struct check *c, struct dt_info *dti, struct node *node)
569 {
570     struct node *dt = dti->dt;
571     struct property *prop;
572 
573     for_each_property(node, prop)
574     {
575         struct marker *m = prop->val.markers;
576         struct node *refnode;
577         cell_t phandle;
578 
579         for_each_marker_of_type(m, REF_PHANDLE)
580         {
581             assert(m->offset + sizeof(cell_t) <= prop->val.len);
582 
583             refnode = get_node_by_ref(dt, m->ref);
584             if (!refnode) {
585                 if (!(dti->dtsflags & DTSF_PLUGIN)) {
586                     FAIL(c, dti, node,
587                          "Reference to non-existent node or "
588                          "label \"%s\"\n",
589                          m->ref);
590                 } else { /* mark the entry as unresolved */
591                     *((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(0xffffffff);
592                 }
593                 continue;
594             }
595 
596             phandle = get_node_phandle(dt, refnode);
597             *((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
598 
599             reference_node(refnode);
600         }
601     }
602 }
603 ERROR(phandle_references, fixup_phandle_references, NULL, &duplicate_node_names, &explicit_phandles);
604 
fixup_path_references(struct check * c,struct dt_info * dti,struct node * node)605 static void fixup_path_references(struct check *c, struct dt_info *dti, struct node *node)
606 {
607     struct node *dt = dti->dt;
608     struct property *prop;
609 
610     for_each_property(node, prop)
611     {
612         struct marker *m = prop->val.markers;
613         struct node *refnode;
614         char *path;
615 
616         for_each_marker_of_type(m, REF_PATH)
617         {
618             assert(m->offset <= prop->val.len);
619 
620             refnode = get_node_by_ref(dt, m->ref);
621             if (!refnode) {
622                 FAIL(c, dti, node, "Reference to non-existent node or label \"%s\"\n", m->ref);
623                 continue;
624             }
625 
626             path = refnode->fullpath;
627             prop->val = data_insert_at_marker(prop->val, m, path, strlen(path) + 1);
628 
629             reference_node(refnode);
630         }
631     }
632 }
633 ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names);
634 
fixup_omit_unused_nodes(struct check * c,struct dt_info * dti,struct node * node)635 static void fixup_omit_unused_nodes(struct check *c, struct dt_info *dti, struct node *node)
636 {
637     if (generate_symbols && node->labels) {
638         return;
639     }
640     if (node->omit_if_unused && !node->is_referenced) {
641         delete_node(node);
642     }
643 
644     if (node->deleted) {
645         struct node *parent = node->parent;
646         struct node *child;
647         struct label *label;
648         struct property *prop;
649 
650         for_each_label(parent->labels, label) return;
651 
652         for_each_property(parent, prop) return;
653 
654         for_each_child(parent, child) return;
655 
656         delete_node(parent);
657     }
658 }
659 ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &path_references);
660 
661 /*
662  * Semantic checks
663  */
664 WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
665 WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
666 WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
667 
668 WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
669 WARNING_IF_NOT_STRING(model_is_string, "model");
670 WARNING_IF_NOT_STRING(status_is_string, "status");
671 WARNING_IF_NOT_STRING(label_is_string, "label");
672 
673 WARNING_IF_NOT_STRING_LIST(compatible_is_string_list, "compatible");
674 
check_names_is_string_list(struct check * c,struct dt_info * dti,struct node * node)675 static void check_names_is_string_list(struct check *c, struct dt_info *dti, struct node *node)
676 {
677     struct property *prop;
678 
679     for_each_property(node, prop)
680     {
681         const char *s = strrchr(prop->name, '-');
682         if (!s || !streq(s, "-names")) {
683             continue;
684         }
685 
686         c->data = prop->name;
687         check_is_string_list(c, dti, node);
688     }
689 }
690 WARNING(names_is_string_list, check_names_is_string_list, NULL);
691 
check_alias_paths(struct check * c,struct dt_info * dti,struct node * node)692 static void check_alias_paths(struct check *c, struct dt_info *dti, struct node *node)
693 {
694     struct property *prop;
695 
696     if (!streq(node->name, "aliases")) {
697         return;
698     }
699 
700     for_each_property(node, prop)
701     {
702         if (streq(prop->name, "phandle") || streq(prop->name, "linux,phandle")) {
703             continue;
704         }
705 
706         if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) {
707             FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)", prop->val.val);
708             continue;
709         }
710         if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name)) {
711             FAIL(c, dti, node, "aliases property name must include only lowercase and '-'");
712         }
713     }
714 }
715 WARNING(alias_paths, check_alias_paths, NULL);
716 
fixup_addr_size_cells(struct check * c,struct dt_info * dti,struct node * node)717 static void fixup_addr_size_cells(struct check *c, struct dt_info *dti, struct node *node)
718 {
719     struct property *prop;
720 
721     node->addr_cells = -1;
722     node->size_cells = -1;
723 
724     prop = get_property(node, "#address-cells");
725     if (prop) {
726         node->addr_cells = propval_cell(prop);
727     }
728 
729     prop = get_property(node, "#size-cells");
730     if (prop) {
731         node->size_cells = propval_cell(prop);
732     }
733 }
734 WARNING(addr_size_cells, fixup_addr_size_cells, NULL, &address_cells_is_cell, &size_cells_is_cell);
735 #define PCI_ADDRESS_CELLS_START 0
736 #define PCI_ADDRESS_CELLS_ONE 1
737 #define PCI_ADDRESS_CELLS_TWO 2
738 #define PCI_ADDRESS_CELLS_THREE 3
739 
740 #define CELLS_BUS_NUMBER_MASK 0x00ff0000
741 #define CELLS_NOT_CONFIG_SPACE_MASK 0xff000000
742 #define CELLS_CONFIG_SPACE_ADDRESS_MASK 0x000000ff
743 #define CELLS_BUS_NUMBER_SHIFT(cells) (fdt32_to_cpu(cells) & CELLS_BUS_NUMBER_MASK) >> 16
744 
745 #define CELLS_UNIT_DEVICE_MASK 0xf800
746 #define CELLS_UNIT_DEVICE_SHIFT(reg) (reg & CELLS_UNIT_DEVICE_MASK) >> 11
747 #define CELLS_UNIT_FUNCTION_MASK 0x700
748 #define CELLS_UNIT_FUNCTION_SHIFT(reg) (reg & CELLS_UNIT_FUNCTION_MASK) >> 8
749 #define CELLS_UINT_SIZE 32
750 #define CELLS_UINT_ADDRESS_SIZE 4
751 #define CELLS_UINT_HEX_HEAD "0x"
752 #define CELLS_UINT_HEX_HEAD_SIZE 2
753 #define CELLS_UINT_OCTAL_HEAD '0'
754 #define CELLS_UINT_OCTAL_HEAD_SIZE 1
755 
756 #define CELLS_UNIT_ADDRESS_TO_LONG(reg, cells) fdt32_to_cpu(*(cells++)) | ((reg) << CELLS_UINT_SIZE)
757 
758 #define CELLS_UINT_CHECKS_NO_NAME "no_"
759 #define CELLS_UINT_CHECKS_NOS_NAME "no-"
760 #define CELLS_UINT_CHECKS_NAME_SIZE 3
761 #define CHECK_OUTPUT_ABORTING 2
762 
763 #define node_addr_cells(n) (((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
764 #define node_size_cells(n) (((n)->size_cells == -1) ? 1 : (n)->size_cells)
765 
check_reg_format(struct check * c,struct dt_info * dti,struct node * node)766 static void check_reg_format(struct check *c, struct dt_info *dti, struct node *node)
767 {
768     struct property *prop;
769     int addr_cells, size_cells, entrylen;
770 
771     prop = get_property(node, "reg");
772     if (!prop) {
773         return; /* No "reg", that's fine */
774     }
775 
776     if (!node->parent) {
777         FAIL(c, dti, node, "Root node has a \"reg\" property");
778         return;
779     }
780 
781     if (prop->val.len == 0) {
782         FAIL_PROP(c, dti, node, prop, "property is empty");
783     }
784 
785     addr_cells = node_addr_cells(node->parent);
786     size_cells = node_size_cells(node->parent);
787     entrylen = (addr_cells + size_cells) * sizeof(cell_t);
788 
789     if (!entrylen || (prop->val.len % entrylen) != 0) {
790         FAIL_PROP(c, dti, node, prop,
791                   "property has invalid length (%d bytes) "
792                   "(#address-cells == %d, #size-cells == %d)",
793                   prop->val.len, addr_cells, size_cells);
794     }
795 }
796 WARNING(reg_format, check_reg_format, NULL, &addr_size_cells);
797 
check_ranges_format(struct check * c,struct dt_info * dti,struct node * node)798 static void check_ranges_format(struct check *c, struct dt_info *dti, struct node *node)
799 {
800     struct property *prop;
801     int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen;
802     const char *ranges = c->data;
803 
804     prop = get_property(node, ranges);
805     if (!prop) {
806         return;
807     }
808 
809     if (!node->parent) {
810         FAIL_PROP(c, dti, node, prop, "Root node has a \"%s\" property", ranges);
811         return;
812     }
813 
814     p_addr_cells = node_addr_cells(node->parent);
815     p_size_cells = node_size_cells(node->parent);
816     c_addr_cells = node_addr_cells(node);
817     c_size_cells = node_size_cells(node);
818     entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t);
819 
820     if (prop->val.len == 0) {
821         if (p_addr_cells != c_addr_cells) {
822             FAIL_PROP(c, dti, node, prop,
823                       "empty \"%s\" property but its "
824                       "#address-cells (%d) differs from %s (%d)",
825                       ranges, c_addr_cells, node->parent->fullpath, p_addr_cells);
826         }
827         if (p_size_cells != c_size_cells) {
828             FAIL_PROP(c, dti, node, prop,
829                       "empty \"%s\" property but its "
830                       "#size-cells (%d) differs from %s (%d)",
831                       ranges, c_size_cells, node->parent->fullpath, p_size_cells);
832         }
833     } else if ((prop->val.len % entrylen) != 0) {
834         FAIL_PROP(c, dti, node, prop,
835                   "\"%s\" property has invalid length (%d bytes) "
836                   "(parent #address-cells == %d, child #address-cells == %d, "
837                   "#size-cells == %d)",
838                   ranges, prop->val.len, p_addr_cells, c_addr_cells, c_size_cells);
839     }
840 }
841 WARNING(ranges_format, check_ranges_format, "ranges", &addr_size_cells);
842 WARNING(dma_ranges_format, check_ranges_format, "dma-ranges", &addr_size_cells);
843 
844 static const struct bus_type pci_bus = {
845     .name = "PCI",
846 };
847 
check_pci_bridge(struct check * c,struct dt_info * dti,struct node * node)848 static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *node)
849 {
850     struct property *prop;
851     cell_t *cells;
852 
853     prop = get_property(node, "device_type");
854     if (!prop || !streq(prop->val.val, "pci")) {
855         return;
856     }
857 
858     node->bus = &pci_bus;
859 
860     if (!strprefixeq(node->name, node->basenamelen, "pci") && !strprefixeq(node->name, node->basenamelen, "pcie")) {
861         FAIL(c, dti, node, "node name is not \"pci\" or \"pcie\"");
862     }
863 
864     prop = get_property(node, "ranges");
865     if (!prop) {
866         FAIL(c, dti, node, "missing ranges for PCI bridge (or not a bridge)");
867     }
868 
869     if (node_addr_cells(node) != PCI_ADDRESS_CELLS_THREE) {
870         FAIL(c, dti, node, "incorrect #address-cells for PCI bridge");
871     }
872     if (node_size_cells(node) != PCI_ADDRESS_CELLS_TWO) {
873         FAIL(c, dti, node, "incorrect #size-cells for PCI bridge");
874     }
875 
876     prop = get_property(node, "bus-range");
877     if (!prop) {
878         return;
879     }
880 
881     if (prop->val.len != (sizeof(cell_t) * PCI_ADDRESS_CELLS_TWO)) {
882         FAIL_PROP(c, dti, node, prop, "value must be 2 cells");
883         return;
884     }
885     cells = (cell_t *)prop->val.val;
886     if (fdt32_to_cpu(cells[PCI_ADDRESS_CELLS_START]) > fdt32_to_cpu(cells[PCI_ADDRESS_CELLS_ONE])) {
887         FAIL_PROP(c, dti, node, prop, "1st cell must be less than or equal to 2nd cell");
888     }
889     if (fdt32_to_cpu(cells[PCI_ADDRESS_CELLS_ONE]) > 0xff) {
890         FAIL_PROP(c, dti, node, prop, "maximum bus number must be less than 256");
891     }
892 }
893 WARNING(pci_bridge, check_pci_bridge, NULL, &device_type_is_string, &addr_size_cells);
894 
check_pci_device_bus_num(struct check * c,struct dt_info * dti,struct node * node)895 static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struct node *node)
896 {
897     struct property *prop;
898     unsigned int bus_num, min_bus, max_bus;
899     cell_t *cells;
900 
901     if (!node->parent || (node->parent->bus != &pci_bus)) {
902         return;
903     }
904 
905     prop = get_property(node, "reg");
906     if (!prop) {
907         return;
908     }
909 
910     cells = (cell_t *)prop->val.val;
911     bus_num = CELLS_BUS_NUMBER_SHIFT(cells[PCI_ADDRESS_CELLS_START]);
912 
913     prop = get_property(node->parent, "bus-range");
914     if (!prop) {
915         min_bus = max_bus = 0;
916     } else {
917         cells = (cell_t *)prop->val.val;
918         min_bus = fdt32_to_cpu(cells[PCI_ADDRESS_CELLS_START]);
919         max_bus = fdt32_to_cpu(cells[PCI_ADDRESS_CELLS_START]);
920     }
921     if ((bus_num < min_bus) || (bus_num > max_bus)) {
922         FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)", bus_num, min_bus, max_bus);
923     }
924 }
925 WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, &reg_format, &pci_bridge);
926 
check_pci_device_reg(struct check * c,struct dt_info * dti,struct node * node)927 static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct node *node)
928 {
929     struct property *prop;
930     const char *unitname = get_unitname(node);
931     char unit_addr[5];
932     unsigned int dev, func, reg;
933     cell_t *cells;
934 
935     if (!node->parent || (node->parent->bus != &pci_bus)) {
936         return;
937     }
938 
939     prop = get_property(node, "reg");
940     if (!prop) {
941         return;
942     }
943 
944     cells = (cell_t *)prop->val.val;
945     if (cells[PCI_ADDRESS_CELLS_ONE] || cells[PCI_ADDRESS_CELLS_TWO]) {
946         FAIL_PROP(c, dti, node, prop, "PCI reg config space address cells 2 and 3 must be 0");
947     }
948 
949     reg = fdt32_to_cpu(cells[PCI_ADDRESS_CELLS_START]);
950     dev = CELLS_UNIT_DEVICE_SHIFT(reg);
951     func = CELLS_UNIT_FUNCTION_SHIFT(reg);
952 
953     if (reg & CELLS_NOT_CONFIG_SPACE_MASK) {
954         FAIL_PROP(c, dti, node, prop, "PCI reg address is not configuration space");
955     }
956     if (reg & CELLS_CONFIG_SPACE_ADDRESS_MASK) {
957         FAIL_PROP(c, dti, node, prop, "PCI reg config space address register number must be 0");
958     }
959 
960     if (func == 0) {
961         snprintf(unit_addr, sizeof(unit_addr), "%x", dev);
962         if (streq(unitname, unit_addr)) {
963             return;
964         }
965     }
966 
967     (void)snprintf(unit_addr, sizeof(unit_addr), "%x,%x", dev, func);
968     if (streq(unitname, unit_addr)) {
969         return;
970     }
971 
972     FAIL(c, dti, node, "PCI unit address format error, expected \"%s\"", unit_addr);
973 }
974 WARNING(pci_device_reg, check_pci_device_reg, NULL, &reg_format, &pci_bridge);
975 
976 static const struct bus_type simple_bus = {
977     .name = "simple-bus",
978 };
979 
node_is_compatible(struct node * node,const char * compat)980 static bool node_is_compatible(struct node *node, const char *compat)
981 {
982     struct property *prop;
983     const char *str, *end;
984 
985     prop = get_property(node, "compatible");
986     if (!prop) {
987         return false;
988     }
989 
990     for (str = prop->val.val, end = str + prop->val.len; str < end; str += strnlen(str, end - str) + 1) {
991         if (streq(str, compat)) {
992             return true;
993         }
994     }
995     return false;
996 }
997 
check_simple_bus_bridge(struct check * c,struct dt_info * dti,struct node * node)998 static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
999 {
1000     if (node_is_compatible(node, "simple-bus")) {
1001         node->bus = &simple_bus;
1002     }
1003 }
1004 WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells, &compatible_is_string_list);
1005 
check_simple_bus_reg(struct check * c,struct dt_info * dti,struct node * node)1006 static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
1007 {
1008     struct property *prop;
1009     const char *unitname = get_unitname(node);
1010     char unit_addr[17];
1011     unsigned int size;
1012     uint64_t reg = 0;
1013     cell_t *cells = NULL;
1014 
1015     if (!node->parent || (node->parent->bus != &simple_bus)) {
1016         return;
1017     }
1018 
1019     prop = get_property(node, "reg");
1020     if (prop) {
1021         cells = (cell_t *)prop->val.val;
1022     } else {
1023         prop = get_property(node, "ranges");
1024         if (prop && prop->val.len) {
1025             /* skip of child address */
1026             cells = ((cell_t *)prop->val.val) + node_addr_cells(node);
1027         }
1028     }
1029 
1030     if (!cells) {
1031         if (node->parent->parent && !(node->bus == &simple_bus)) {
1032             FAIL(c, dti, node, "missing or empty reg/ranges property");
1033         }
1034         return;
1035     }
1036 
1037     size = node_addr_cells(node->parent);
1038     while (size--) {
1039         reg = CELLS_UNIT_ADDRESS_TO_LONG(reg, cells);
1040     }
1041 
1042     snprintf(unit_addr, sizeof(unit_addr), "%" PRIx64, reg);
1043     if (!streq(unitname, unit_addr)) {
1044         FAIL(c, dti, node, "simple-bus unit address format error, expected \"%s\"", unit_addr);
1045     }
1046 }
1047 WARNING(simple_bus_reg, check_simple_bus_reg, NULL, &reg_format, &simple_bus_bridge);
1048 
1049 static const struct bus_type i2c_bus = {
1050     .name = "i2c-bus",
1051 };
1052 
check_i2c_bus_bridge(struct check * c,struct dt_info * dti,struct node * node)1053 static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
1054 {
1055     if (strprefixeq(node->name, node->basenamelen, "i2c-bus") ||
1056         strprefixeq(node->name, node->basenamelen, "i2c-arb")) {
1057         node->bus = &i2c_bus;
1058     } else if (strprefixeq(node->name, node->basenamelen, "i2c")) {
1059         struct node *child;
1060         for_each_child(node, child)
1061         {
1062             if (strprefixeq(child->name, node->basenamelen, "i2c-bus")) {
1063                 return;
1064             }
1065         }
1066         node->bus = &i2c_bus;
1067     } else {
1068         return;
1069     }
1070 
1071     if (!node->children) {
1072         return;
1073     }
1074 
1075     if (node_addr_cells(node) != 1) {
1076         FAIL(c, dti, node, "incorrect #address-cells for I2C bus");
1077     }
1078     if (node_size_cells(node) != 0) {
1079         FAIL(c, dti, node, "incorrect #size-cells for I2C bus");
1080     }
1081 }
1082 WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells);
1083 
1084 #define I2C_OWN_SLAVE_ADDRESS (1U << 30)
1085 #define I2C_TEN_BIT_ADDRESS (1U << 31)
1086 
check_i2c_bus_reg(struct check * c,struct dt_info * dti,struct node * node)1087 static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
1088 {
1089     struct property *prop;
1090     const char *unitname = get_unitname(node);
1091     char unit_addr[17];
1092     uint32_t reg = 0;
1093     int len;
1094     cell_t *cells = NULL;
1095 
1096     if (!node->parent || (node->parent->bus != &i2c_bus)) {
1097         return;
1098     }
1099 
1100     prop = get_property(node, "reg");
1101     if (prop) {
1102         cells = (cell_t *)prop->val.val;
1103     }
1104 
1105     if (!cells) {
1106         FAIL(c, dti, node, "missing or empty reg property");
1107         return;
1108     }
1109 
1110     reg = fdt32_to_cpu(*cells);
1111     /* Ignore I2C_OWN_SLAVE_ADDRESS */
1112     reg &= ~I2C_OWN_SLAVE_ADDRESS;
1113     (void)snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
1114     if (!streq(unitname, unit_addr)) {
1115         FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"", unit_addr);
1116     }
1117 
1118     for (len = prop->val.len; len > 0; len -= CELLS_UINT_ADDRESS_SIZE) {
1119         reg = fdt32_to_cpu(*(cells++));
1120         /* Ignore I2C_OWN_SLAVE_ADDRESS */
1121         reg &= ~I2C_OWN_SLAVE_ADDRESS;
1122 
1123         if ((reg & I2C_TEN_BIT_ADDRESS) && ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff)) {
1124             FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"", reg);
1125         } else if (reg > 0x7f) {
1126             FAIL_PROP(c, dti, node, prop,
1127                       "I2C address must be less than 7-bits, got \"0x%x\". Set I2C_TEN_BIT_ADDRESS for 10 bit "
1128                       "addresses or fix the property",
1129                       reg);
1130         }
1131     }
1132 }
1133 WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, &reg_format, &i2c_bus_bridge);
1134 
1135 static const struct bus_type spi_bus = {
1136     .name = "spi-bus",
1137 };
1138 
check_spi_bus_bridge(struct check * c,struct dt_info * dti,struct node * node)1139 static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
1140 {
1141     int spi_addr_cells = 1;
1142 
1143     if (strprefixeq(node->name, node->basenamelen, "spi")) {
1144         node->bus = &spi_bus;
1145     } else {
1146         /* Try to detect SPI buses which don't have proper node name */
1147         struct node *child;
1148 
1149         if (node_addr_cells(node) != 1 || node_size_cells(node) != 0) {
1150             return;
1151         }
1152 
1153         for_each_child(node, child)
1154         {
1155             struct property *prop;
1156             for_each_property(child, prop)
1157             {
1158                 if (strprefixeq(prop->name, CELLS_UINT_ADDRESS_SIZE, "spi-")) {
1159                     node->bus = &spi_bus;
1160                     break;
1161                 }
1162             }
1163             if (node->bus == &spi_bus) {
1164                 break;
1165             }
1166         }
1167 
1168         if (node->bus == &spi_bus && get_property(node, "reg")) {
1169             FAIL(c, dti, node, "node name for SPI buses should be 'spi'");
1170         }
1171     }
1172     if (node->bus != &spi_bus || !node->children) {
1173         return;
1174     }
1175 
1176     if (get_property(node, "spi-slave")) {
1177         spi_addr_cells = 0;
1178     }
1179     if (node_addr_cells(node) != spi_addr_cells) {
1180         FAIL(c, dti, node, "incorrect #address-cells for SPI bus");
1181     }
1182     if (node_size_cells(node) != 0) {
1183         FAIL(c, dti, node, "incorrect #size-cells for SPI bus");
1184     }
1185 }
1186 WARNING(spi_bus_bridge, check_spi_bus_bridge, NULL, &addr_size_cells);
1187 
check_spi_bus_reg(struct check * c,struct dt_info * dti,struct node * node)1188 static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
1189 {
1190     struct property *prop;
1191     const char *unitname = get_unitname(node);
1192     char unit_addr[9];
1193     uint32_t reg = 0;
1194     cell_t *cells = NULL;
1195 
1196     if (!node->parent || (node->parent->bus != &spi_bus)) {
1197         return;
1198     }
1199 
1200     if (get_property(node->parent, "spi-slave")) {
1201         return;
1202     }
1203 
1204     prop = get_property(node, "reg");
1205     if (prop) {
1206         cells = (cell_t *)prop->val.val;
1207     }
1208 
1209     if (!cells) {
1210         FAIL(c, dti, node, "missing or empty reg property");
1211         return;
1212     }
1213 
1214     reg = fdt32_to_cpu(*cells);
1215     (void)snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
1216     if (!streq(unitname, unit_addr)) {
1217         FAIL(c, dti, node, "SPI bus unit address format error, expected \"%s\"", unit_addr);
1218     }
1219 }
1220 WARNING(spi_bus_reg, check_spi_bus_reg, NULL, &reg_format, &spi_bus_bridge);
1221 
check_unit_address_format(struct check * c,struct dt_info * dti,struct node * node)1222 static void check_unit_address_format(struct check *c, struct dt_info *dti, struct node *node)
1223 {
1224     const char *unitname = get_unitname(node);
1225 
1226     if (node->parent && node->parent->bus) {
1227         return;
1228     }
1229 
1230     if (!unitname[PCI_ADDRESS_CELLS_START]) {
1231         return;
1232     }
1233 
1234     if (!strncmp(unitname, CELLS_UINT_HEX_HEAD, CELLS_UINT_HEX_HEAD_SIZE)) {
1235         FAIL(c, dti, node, "unit name should not have leading \"0x\"");
1236         /* skip over 0x for next test */
1237         unitname += CELLS_UINT_HEX_HEAD_SIZE;
1238     }
1239     if ((unitname[PCI_ADDRESS_CELLS_START] == CELLS_UINT_OCTAL_HEAD) &&
1240         (isxdigit(unitname[CELLS_UINT_OCTAL_HEAD_SIZE]))) {
1241         FAIL(c, dti, node, "unit name should not have leading 0s");
1242     }
1243 }
1244 WARNING(unit_address_format, check_unit_address_format, NULL, &node_name_format, &pci_bridge, &simple_bus_bridge);
1245 
1246 /*
1247  * Style checks
1248  */
check_avoid_default_addr_size(struct check * c,struct dt_info * dti,struct node * node)1249 static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti, struct node *node)
1250 {
1251     struct property *reg, *ranges;
1252 
1253     if (!node->parent) {
1254         return; /* Ignore root node */
1255     }
1256 
1257     reg = get_property(node, "reg");
1258     ranges = get_property(node, "ranges");
1259     if (!reg && !ranges) {
1260         return;
1261     }
1262 
1263     if (node->parent->addr_cells == -1) {
1264         FAIL(c, dti, node, "Relying on default #address-cells value");
1265     }
1266 
1267     if (node->parent->size_cells == -1) {
1268         FAIL(c, dti, node, "Relying on default #size-cells value");
1269     }
1270 }
1271 WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL, &addr_size_cells);
1272 
check_avoid_unnecessary_addr_size(struct check * c,struct dt_info * dti,struct node * node)1273 static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *dti, struct node *node)
1274 {
1275     struct property *prop;
1276     struct node *child;
1277     bool has_reg = false;
1278 
1279     if (!node->parent || node->addr_cells < 0 || node->size_cells < 0) {
1280         return;
1281     }
1282 
1283     if (get_property(node, "ranges") || !node->children) {
1284         return;
1285     }
1286 
1287     for_each_child(node, child)
1288     {
1289         prop = get_property(child, "reg");
1290         if (prop) {
1291             has_reg = true;
1292         }
1293     }
1294 
1295     if (!has_reg) {
1296         FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property");
1297     }
1298 }
1299 WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
1300 
node_is_disabled(struct node * node)1301 static bool node_is_disabled(struct node *node)
1302 {
1303     struct property *prop;
1304 
1305     prop = get_property(node, "status");
1306     if (prop) {
1307         char *str = prop->val.val;
1308         if (streq("disabled", str)) {
1309             return true;
1310         }
1311     }
1312 
1313     return false;
1314 }
1315 
check_unique_unit_address_common(struct check * c,struct dt_info * dti,struct node * node,bool disable_check)1316 static void check_unique_unit_address_common(struct check *c, struct dt_info *dti, struct node *node,
1317                                              bool disable_check)
1318 {
1319     struct node *childa;
1320 
1321     if (node->addr_cells < 0 || node->size_cells < 0) {
1322         return;
1323     }
1324 
1325     if (!node->children) {
1326         return;
1327     }
1328 
1329     for_each_child(node, childa)
1330     {
1331         struct node *childb;
1332         const char *addr_a = get_unitname(childa);
1333 
1334         if (!strlen(addr_a)) {
1335             continue;
1336         }
1337 
1338         if (disable_check && node_is_disabled(childa)) {
1339             continue;
1340         }
1341 
1342         for_each_child(node, childb)
1343         {
1344             const char *addr_b = get_unitname(childb);
1345             if (childa == childb) {
1346                 break;
1347             }
1348 
1349             if (disable_check && node_is_disabled(childb)) {
1350                 continue;
1351             }
1352 
1353             if (streq(addr_a, addr_b)) {
1354                 FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath);
1355             }
1356         }
1357     }
1358 }
1359 
check_unique_unit_address(struct check * c,struct dt_info * dti,struct node * node)1360 static void check_unique_unit_address(struct check *c, struct dt_info *dti, struct node *node)
1361 {
1362     check_unique_unit_address_common(c, dti, node, false);
1363 }
1364 WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size);
1365 
check_unique_unit_address_if_enabled(struct check * c,struct dt_info * dti,struct node * node)1366 static void check_unique_unit_address_if_enabled(struct check *c, struct dt_info *dti, struct node *node)
1367 {
1368     check_unique_unit_address_common(c, dti, node, true);
1369 }
1370 CHECK_ENTRY(unique_unit_address_if_enabled, check_unique_unit_address_if_enabled, NULL, false, false,
1371             &avoid_default_addr_size);
1372 
check_obsolete_chosen_interrupt_controller(struct check * c,struct dt_info * dti,struct node * node)1373 static void check_obsolete_chosen_interrupt_controller(struct check *c, struct dt_info *dti, struct node *node)
1374 {
1375     struct node *dt = dti->dt;
1376     struct node *chosen;
1377     struct property *prop;
1378 
1379     if (node != dt) {
1380         return;
1381     }
1382 
1383     chosen = get_node_by_path(dt, "/chosen");
1384     if (!chosen) {
1385         return;
1386     }
1387 
1388     prop = get_property(chosen, "interrupt-controller");
1389     if (prop) {
1390         FAIL_PROP(c, dti, node, prop, "/chosen has obsolete \"interrupt-controller\" property");
1391     }
1392 }
1393 WARNING(obsolete_chosen_interrupt_controller, check_obsolete_chosen_interrupt_controller, NULL);
1394 
check_chosen_node_is_root(struct check * c,struct dt_info * dti,struct node * node)1395 static void check_chosen_node_is_root(struct check *c, struct dt_info *dti, struct node *node)
1396 {
1397     if (!streq(node->name, "chosen")) {
1398         return;
1399     }
1400 
1401     if (node->parent != dti->dt) {
1402         FAIL(c, dti, node, "chosen node must be at root node");
1403     }
1404 }
1405 WARNING(chosen_node_is_root, check_chosen_node_is_root, NULL);
1406 
check_chosen_node_bootargs(struct check * c,struct dt_info * dti,struct node * node)1407 static void check_chosen_node_bootargs(struct check *c, struct dt_info *dti, struct node *node)
1408 {
1409     struct property *prop;
1410 
1411     if (!streq(node->name, "chosen")) {
1412         return;
1413     }
1414 
1415     prop = get_property(node, "bootargs");
1416     if (!prop) {
1417         return;
1418     }
1419 
1420     c->data = prop->name;
1421     check_is_string(c, dti, node);
1422 }
1423 WARNING(chosen_node_bootargs, check_chosen_node_bootargs, NULL);
1424 
check_chosen_node_stdout_path(struct check * c,struct dt_info * dti,struct node * node)1425 static void check_chosen_node_stdout_path(struct check *c, struct dt_info *dti, struct node *node)
1426 {
1427     struct property *prop;
1428 
1429     if (!streq(node->name, "chosen")) {
1430         return;
1431     }
1432 
1433     prop = get_property(node, "stdout-path");
1434     if (!prop) {
1435         prop = get_property(node, "linux,stdout-path");
1436         if (!prop) {
1437             return;
1438         }
1439         FAIL_PROP(c, dti, node, prop, "Use 'stdout-path' instead");
1440     }
1441 
1442     c->data = prop->name;
1443     check_is_string(c, dti, node);
1444 }
1445 WARNING(chosen_node_stdout_path, check_chosen_node_stdout_path, NULL);
1446 
1447 struct provider {
1448     const char *prop_name;
1449     const char *cell_name;
1450     bool optional;
1451 };
1452 
check_property_phandle_args(struct check * c,struct dt_info * dti,struct node * node,struct property * prop,const struct provider * provider)1453 static void check_property_phandle_args(struct check *c, struct dt_info *dti, struct node *node, struct property *prop,
1454                                         const struct provider *provider)
1455 {
1456     struct node *root = dti->dt;
1457     int cell, cellsize = 0;
1458 
1459     if (prop->val.len % sizeof(cell_t)) {
1460         FAIL_PROP(c, dti, node, prop, "property size (%d) is invalid, expected multiple of %zu", prop->val.len,
1461                   sizeof(cell_t));
1462         return;
1463     }
1464 
1465     for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) {
1466         struct node *provider_node;
1467         struct property *cellprop;
1468         int phandle;
1469 
1470         phandle = propval_cell_n(prop, cell);
1471         /*
1472          * Some bindings use a cell value 0 or -1 to skip over optional
1473          * entries when each index position has a specific definition.
1474          */
1475         if (phandle == 0 || phandle == -1) {
1476             /* Give up if this is an overlay with external references */
1477             if (dti->dtsflags & DTSF_PLUGIN) {
1478                 break;
1479             }
1480 
1481             cellsize = 0;
1482             continue;
1483         }
1484 
1485         /* If we have markers, verify the current cell is a phandle */
1486         if (prop->val.markers) {
1487             struct marker *m = prop->val.markers;
1488             for_each_marker_of_type(m, REF_PHANDLE)
1489             {
1490                 if (m->offset == (cell * sizeof(cell_t))) {
1491                     break;
1492                 }
1493             }
1494             if (!m) {
1495                 FAIL_PROP(c, dti, node, prop, "cell %d is not a phandle reference", cell);
1496             }
1497         }
1498 
1499         provider_node = get_node_by_phandle(root, phandle);
1500         if (!provider_node) {
1501             FAIL_PROP(c, dti, node, prop, "Could not get phandle node for (cell %d)", cell);
1502             break;
1503         }
1504 
1505         cellprop = get_property(provider_node, provider->cell_name);
1506         if (cellprop) {
1507             cellsize = propval_cell(cellprop);
1508         } else if (provider->optional) {
1509             cellsize = 0;
1510         } else {
1511             FAIL(c, dti, node, "Missing property '%s' in node %s or bad phandle (referred from %s[%d])",
1512                  provider->cell_name, provider_node->fullpath, prop->name, cell);
1513             break;
1514         }
1515 
1516         if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
1517             FAIL_PROP(c, dti, node, prop, "property size (%d) too small for cell size %d", prop->val.len, cellsize);
1518         }
1519     }
1520 }
1521 
check_provider_cells_property(struct check * c,struct dt_info * dti,struct node * node)1522 static void check_provider_cells_property(struct check *c, struct dt_info *dti, struct node *node)
1523 {
1524     struct provider *provider = c->data;
1525     struct property *prop;
1526 
1527     prop = get_property(node, provider->prop_name);
1528     if (!prop) {
1529         return;
1530     }
1531 
1532     check_property_phandle_args(c, dti, node, prop, provider);
1533 }
1534 #define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...)                                                  \
1535     static struct provider nm##_provider = {(propname), (cells_name), __VA_ARGS__};                                    \
1536     WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references)
1537 
1538 WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
1539 WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
1540 WARNING_PROPERTY_PHANDLE_CELLS(dmas, "dmas", "#dma-cells");
1541 WARNING_PROPERTY_PHANDLE_CELLS(hwlocks, "hwlocks", "#hwlock-cells");
1542 WARNING_PROPERTY_PHANDLE_CELLS(interrupts_extended, "interrupts-extended", "#interrupt-cells");
1543 WARNING_PROPERTY_PHANDLE_CELLS(io_channels, "io-channels", "#io-channel-cells");
1544 WARNING_PROPERTY_PHANDLE_CELLS(iommus, "iommus", "#iommu-cells");
1545 WARNING_PROPERTY_PHANDLE_CELLS(mboxes, "mboxes", "#mbox-cells");
1546 WARNING_PROPERTY_PHANDLE_CELLS(msi_parent, "msi-parent", "#msi-cells", true);
1547 WARNING_PROPERTY_PHANDLE_CELLS(mux_controls, "mux-controls", "#mux-control-cells");
1548 WARNING_PROPERTY_PHANDLE_CELLS(phys, "phys", "#phy-cells");
1549 WARNING_PROPERTY_PHANDLE_CELLS(power_domains, "power-domains", "#power-domain-cells");
1550 WARNING_PROPERTY_PHANDLE_CELLS(pwms, "pwms", "#pwm-cells");
1551 WARNING_PROPERTY_PHANDLE_CELLS(resets, "resets", "#reset-cells");
1552 WARNING_PROPERTY_PHANDLE_CELLS(sound_dai, "sound-dai", "#sound-dai-cells");
1553 WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sensor-cells");
1554 
prop_is_gpio(struct property * prop)1555 static bool prop_is_gpio(struct property *prop)
1556 {
1557     char *str;
1558 
1559     /*
1560      * *-gpios and *-gpio can appear in property names,
1561      * so skip over any false matches (only one known ATM)
1562      */
1563     if (strstr(prop->name, "nr-gpio")) {
1564         return false;
1565     }
1566 
1567     str = strrchr(prop->name, '-');
1568     if (str) {
1569         str++;
1570     } else {
1571         str = prop->name;
1572     }
1573     if (!(streq(str, "gpios") || streq(str, "gpio"))) {
1574         return false;
1575     }
1576 
1577     return true;
1578 }
1579 
check_gpios_property(struct check * c,struct dt_info * dti,struct node * node)1580 static void check_gpios_property(struct check *c, struct dt_info *dti, struct node *node)
1581 {
1582     struct property *prop;
1583 
1584     /* Skip GPIO hog nodes which have 'gpios' property */
1585     if (get_property(node, "gpio-hog")) {
1586         return;
1587     }
1588 
1589     for_each_property(node, prop)
1590     {
1591         struct provider provider;
1592 
1593         if (!prop_is_gpio(prop)) {
1594             continue;
1595         }
1596 
1597         provider.prop_name = prop->name;
1598         provider.cell_name = "#gpio-cells";
1599         provider.optional = false;
1600         check_property_phandle_args(c, dti, node, prop, &provider);
1601     }
1602 }
1603 WARNING(gpios_property, check_gpios_property, NULL, &phandle_references);
1604 
check_deprecated_gpio_property(struct check * c,struct dt_info * dti,struct node * node)1605 static void check_deprecated_gpio_property(struct check *c, struct dt_info *dti, struct node *node)
1606 {
1607     struct property *prop;
1608 
1609     for_each_property(node, prop)
1610     {
1611         char *str;
1612 
1613         if (!prop_is_gpio(prop)) {
1614             continue;
1615         }
1616 
1617         str = strstr(prop->name, "gpio");
1618         if (!streq(str, "gpio")) {
1619             continue;
1620         }
1621 
1622         FAIL_PROP(c, dti, node, prop, "'[*-]gpio' is deprecated, use '[*-]gpios' instead");
1623     }
1624 }
1625 CHECK(deprecated_gpio_property, check_deprecated_gpio_property, NULL);
1626 
node_is_interrupt_provider(struct node * node)1627 static bool node_is_interrupt_provider(struct node *node)
1628 {
1629     struct property *prop;
1630 
1631     prop = get_property(node, "interrupt-controller");
1632     if (prop) {
1633         return true;
1634     }
1635 
1636     prop = get_property(node, "interrupt-map");
1637     if (prop) {
1638         return true;
1639     }
1640 
1641     return false;
1642 }
1643 
check_interrupt_provider(struct check * c,struct dt_info * dti,struct node * node)1644 static void check_interrupt_provider(struct check *c, struct dt_info *dti, struct node *node)
1645 {
1646     struct property *prop;
1647 
1648     if (!node_is_interrupt_provider(node)) {
1649         return;
1650     }
1651 
1652     prop = get_property(node, "#interrupt-cells");
1653     if (!prop) {
1654         FAIL(c, dti, node, "Missing #interrupt-cells in interrupt provider");
1655     }
1656 
1657     prop = get_property(node, "#address-cells");
1658     if (!prop) {
1659         FAIL(c, dti, node, "Missing #address-cells in interrupt provider");
1660     }
1661 }
1662 WARNING(interrupt_provider, check_interrupt_provider, NULL);
1663 
check_interrupts_property(struct check * c,struct dt_info * dti,struct node * node)1664 static void check_interrupts_property(struct check *c, struct dt_info *dti, struct node *node)
1665 {
1666     struct node *root = dti->dt;
1667     struct node *irq_node = NULL, *parent = node;
1668     struct property *irq_prop, *prop = NULL;
1669     int irq_cells, phandle;
1670 
1671     irq_prop = get_property(node, "interrupts");
1672     if (!irq_prop) {
1673         return;
1674     }
1675 
1676     if (irq_prop->val.len % sizeof(cell_t)) {
1677         FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu", irq_prop->val.len,
1678                   sizeof(cell_t));
1679     }
1680 
1681     while (parent && !prop) {
1682         if (parent != node && node_is_interrupt_provider(parent)) {
1683             irq_node = parent;
1684             break;
1685         }
1686 
1687         prop = get_property(parent, "interrupt-parent");
1688         if (prop) {
1689             phandle = propval_cell(prop);
1690             if ((phandle == 0) || (phandle == -1)) {
1691                 /* Give up if this is an overlay with
1692                  * external references */
1693                 if (dti->dtsflags & DTSF_PLUGIN) {
1694                     return;
1695                 }
1696                 FAIL_PROP(c, dti, parent, prop, "Invalid phandle");
1697                 continue;
1698             }
1699 
1700             irq_node = get_node_by_phandle(root, phandle);
1701             if (!irq_node) {
1702                 FAIL_PROP(c, dti, parent, prop, "Bad phandle");
1703                 return;
1704             }
1705             if (!node_is_interrupt_provider(irq_node)) {
1706                 FAIL(c, dti, irq_node, "Missing interrupt-controller or interrupt-map property");
1707             }
1708 
1709             break;
1710         }
1711 
1712         parent = parent->parent;
1713     }
1714 
1715     if (!irq_node) {
1716         FAIL(c, dti, node, "Missing interrupt-parent");
1717         return;
1718     }
1719 
1720     prop = get_property(irq_node, "#interrupt-cells");
1721     if (!prop) {
1722         /* We warn about that already in another test. */
1723         return;
1724     }
1725 
1726     irq_cells = propval_cell(prop);
1727     if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) {
1728         FAIL_PROP(c, dti, node, prop, "size is (%d), expected multiple of %d", irq_prop->val.len,
1729                   (int)(irq_cells * sizeof(cell_t)));
1730     }
1731 }
1732 WARNING(interrupts_property, check_interrupts_property, &phandle_references);
1733 
1734 static const struct bus_type graph_port_bus = {
1735     .name = "graph-port",
1736 };
1737 
1738 static const struct bus_type graph_ports_bus = {
1739     .name = "graph-ports",
1740 };
1741 
check_graph_nodes(struct check * c,struct dt_info * dti,struct node * node)1742 static void check_graph_nodes(struct check *c, struct dt_info *dti, struct node *node)
1743 {
1744     struct node *child;
1745 
1746     for_each_child(node, child)
1747     {
1748         if (!(strprefixeq(child->name, child->basenamelen, "endpoint") || get_property(child, "remote-endpoint"))) {
1749             continue;
1750         }
1751 
1752         node->bus = &graph_port_bus;
1753 
1754         /* The parent of 'port' nodes can be either 'ports' or a device */
1755         if (!node->parent->bus && (streq(node->parent->name, "ports") || get_property(node, "reg"))) {
1756             node->parent->bus = &graph_ports_bus;
1757         }
1758 
1759         break;
1760     }
1761 }
1762 WARNING(graph_nodes, check_graph_nodes, NULL);
1763 
check_graph_child_address(struct check * c,struct dt_info * dti,struct node * node)1764 static void check_graph_child_address(struct check *c, struct dt_info *dti, struct node *node)
1765 {
1766     int cnt = 0;
1767     struct node *child;
1768 
1769     if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus) {
1770         return;
1771     }
1772 
1773     for_each_child(node, child)
1774     {
1775         struct property *prop = get_property(child, "reg");
1776 
1777         /* No error if we have any non-zero unit address */
1778         if (prop && propval_cell(prop) != 0) {
1779             return;
1780         }
1781 
1782         cnt++;
1783     }
1784 
1785     if (cnt == 1 && node->addr_cells != -1) {
1786         FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary",
1787              node->children->name);
1788     }
1789 }
1790 WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes);
1791 
check_graph_reg(struct check * c,struct dt_info * dti,struct node * node)1792 static void check_graph_reg(struct check *c, struct dt_info *dti, struct node *node)
1793 {
1794     char unit_addr[9];
1795     const char *unitname = get_unitname(node);
1796     struct property *prop;
1797 
1798     prop = get_property(node, "reg");
1799     if (!prop || !unitname) {
1800         return;
1801     }
1802 
1803     if (!(prop->val.val && prop->val.len == sizeof(cell_t))) {
1804         FAIL(c, dti, node, "graph node malformed 'reg' property");
1805         return;
1806     }
1807 
1808     (void)snprintf(unit_addr, sizeof(unit_addr), "%x", propval_cell(prop));
1809     if (!streq(unitname, unit_addr)) {
1810         FAIL(c, dti, node, "graph node unit address error, expected \"%s\"", unit_addr);
1811     }
1812 
1813     if (node->parent->addr_cells != 1) {
1814         FAIL_PROP(c, dti, node, get_property(node, "#address-cells"), "graph node '#address-cells' is %d, must be 1",
1815                   node->parent->addr_cells);
1816     }
1817     if (node->parent->size_cells != 0) {
1818         FAIL_PROP(c, dti, node, get_property(node, "#size-cells"), "graph node '#size-cells' is %d, must be 0",
1819                   node->parent->size_cells);
1820     }
1821 }
1822 
check_graph_port(struct check * c,struct dt_info * dti,struct node * node)1823 static void check_graph_port(struct check *c, struct dt_info *dti, struct node *node)
1824 {
1825     if (node->bus != &graph_port_bus) {
1826         return;
1827     }
1828 
1829     if (!strprefixeq(node->name, node->basenamelen, "port")) {
1830         FAIL(c, dti, node, "graph port node name should be 'port'");
1831     }
1832 
1833     check_graph_reg(c, dti, node);
1834 }
1835 WARNING(graph_port, check_graph_port, NULL, &graph_nodes);
1836 
get_remote_endpoint(struct check * c,struct dt_info * dti,struct node * endpoint)1837 static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti, struct node *endpoint)
1838 {
1839     int phandle;
1840     struct node *node;
1841     struct property *prop;
1842 
1843     prop = get_property(endpoint, "remote-endpoint");
1844     if (!prop) {
1845         return NULL;
1846     }
1847 
1848     phandle = propval_cell(prop);
1849     /* Give up if this is an overlay with external references */
1850     if (phandle == 0 || phandle == -1) {
1851         return NULL;
1852     }
1853 
1854     node = get_node_by_phandle(dti->dt, phandle);
1855     if (!node) {
1856         FAIL_PROP(c, dti, endpoint, prop, "graph phandle is not valid");
1857     }
1858 
1859     return node;
1860 }
1861 
check_graph_endpoint(struct check * c,struct dt_info * dti,struct node * node)1862 static void check_graph_endpoint(struct check *c, struct dt_info *dti, struct node *node)
1863 {
1864     struct node *remote_node;
1865 
1866     if (!node->parent || node->parent->bus != &graph_port_bus) {
1867         return;
1868     }
1869 
1870     if (!strprefixeq(node->name, node->basenamelen, "endpoint")) {
1871         FAIL(c, dti, node, "graph endpoint node name should be 'endpoint'");
1872     }
1873 
1874     check_graph_reg(c, dti, node);
1875 
1876     remote_node = get_remote_endpoint(c, dti, node);
1877     if (!remote_node) {
1878         return;
1879     }
1880 
1881     if (get_remote_endpoint(c, dti, remote_node) != node) {
1882         FAIL(c, dti, node, "graph connection to node '%s' is not bidirectional", remote_node->fullpath);
1883     }
1884 }
1885 WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
1886 
1887 static struct check *check_table[] = {
1888     &duplicate_node_names,
1889     &duplicate_property_names,
1890     &node_name_chars,
1891     &node_name_format,
1892     &property_name_chars,
1893     &name_is_string,
1894     &name_properties,
1895 
1896     &duplicate_label,
1897 
1898     &explicit_phandles,
1899     &phandle_references,
1900     &path_references,
1901     &omit_unused_nodes,
1902 
1903     &address_cells_is_cell,
1904     &size_cells_is_cell,
1905     &interrupt_cells_is_cell,
1906     &device_type_is_string,
1907     &model_is_string,
1908     &status_is_string,
1909     &label_is_string,
1910 
1911     &compatible_is_string_list,
1912     &names_is_string_list,
1913 
1914     &property_name_chars_strict,
1915     &node_name_chars_strict,
1916 
1917     &addr_size_cells,
1918     &reg_format,
1919     &ranges_format,
1920     &dma_ranges_format,
1921 
1922     &unit_address_vs_reg,
1923     &unit_address_format,
1924 
1925     &pci_bridge,
1926     &pci_device_reg,
1927     &pci_device_bus_num,
1928 
1929     &simple_bus_bridge,
1930     &simple_bus_reg,
1931 
1932     &i2c_bus_bridge,
1933     &i2c_bus_reg,
1934 
1935     &spi_bus_bridge,
1936     &spi_bus_reg,
1937 
1938     &avoid_default_addr_size,
1939     &avoid_unnecessary_addr_size,
1940     &unique_unit_address,
1941     &unique_unit_address_if_enabled,
1942     &obsolete_chosen_interrupt_controller,
1943     &chosen_node_is_root,
1944     &chosen_node_bootargs,
1945     &chosen_node_stdout_path,
1946 
1947     &clocks_property,
1948     &cooling_device_property,
1949     &dmas_property,
1950     &hwlocks_property,
1951     &interrupts_extended_property,
1952     &io_channels_property,
1953     &iommus_property,
1954     &mboxes_property,
1955     &msi_parent_property,
1956     &mux_controls_property,
1957     &phys_property,
1958     &power_domains_property,
1959     &pwms_property,
1960     &resets_property,
1961     &sound_dai_property,
1962     &thermal_sensors_property,
1963 
1964     &deprecated_gpio_property,
1965     &gpios_property,
1966     &interrupts_property,
1967     &interrupt_provider,
1968 
1969     &alias_paths,
1970 
1971     &graph_nodes,
1972     &graph_child_address,
1973     &graph_port,
1974     &graph_endpoint,
1975 
1976     &always_fail,
1977 };
1978 
enable_warning_error(struct check * c,bool warn,bool error)1979 static void enable_warning_error(struct check *c, bool warn, bool error)
1980 {
1981     int i;
1982 
1983     /* Raising level, also raise it for prereqs */
1984     if ((warn && !c->warn) || (error && !c->error)) {
1985         for (i = 0; i < c->num_prereqs; i++) {
1986             enable_warning_error(c->prereq[i], warn, error);
1987         }
1988     }
1989 
1990     c->warn = c->warn || warn;
1991     c->error = c->error || error;
1992 }
1993 
disable_warning_error(struct check * c,bool warn,bool error)1994 static void disable_warning_error(struct check *c, bool warn, bool error)
1995 {
1996     int i;
1997 
1998     /* Lowering level, also lower it for things this is the prereq
1999      * for */
2000     if ((warn && c->warn) || (error && c->error)) {
2001         for (i = 0; i < ARRAY_SIZE(check_table); i++) {
2002             struct check *cc = check_table[i];
2003             int j;
2004 
2005             for (j = 0; j < cc->num_prereqs; j++) {
2006                 if (cc->prereq[j] == c) {
2007                     disable_warning_error(cc, warn, error);
2008                 }
2009             }
2010         }
2011     }
2012 
2013     c->warn = c->warn && !warn;
2014     c->error = c->error && !error;
2015 }
2016 
parse_checks_option(bool warn,bool error,const char * arg)2017 void parse_checks_option(bool warn, bool error, const char *arg)
2018 {
2019     int i;
2020     const char *name = arg;
2021     bool enable = true;
2022 
2023     if ((strncmp(arg, CELLS_UINT_CHECKS_NO_NAME, CELLS_UINT_CHECKS_NAME_SIZE) == 0) ||
2024         (strncmp(arg, CELLS_UINT_CHECKS_NOS_NAME, CELLS_UINT_CHECKS_NAME_SIZE) == 0)) {
2025         name = arg + CELLS_UINT_CHECKS_NAME_SIZE;
2026         enable = false;
2027     }
2028 
2029     for (i = 0; i < ARRAY_SIZE(check_table); i++) {
2030         struct check *c = check_table[i];
2031 
2032         if (streq(c->name, name)) {
2033             if (enable) {
2034                 enable_warning_error(c, warn, error);
2035             } else {
2036                 disable_warning_error(c, warn, error);
2037             }
2038             return;
2039         }
2040     }
2041 
2042     die("Unrecognized check name \"%s\"\n", name);
2043 }
2044 
process_checks(bool force,struct dt_info * dti)2045 void process_checks(bool force, struct dt_info *dti)
2046 {
2047     int i;
2048     int error = 0;
2049 
2050     for (i = 0; i < ARRAY_SIZE(check_table); i++) {
2051         struct check *c = check_table[i];
2052 
2053         if (c->warn || c->error) {
2054             error = error || run_check(c, dti);
2055         }
2056     }
2057 
2058     if (error) {
2059         if (!force) {
2060             fprintf(stderr, "ERROR: Input tree has errors, aborting "
2061                             "(use -f to force output)\n");
2062             exit(CHECK_OUTPUT_ABORTING);
2063         }
2064     }
2065 }
2066