aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/boot/dtc-src/checks.c
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2008-08-06 22:24:17 -0400
committerPaul Mackerras <paulus@samba.org>2008-08-20 02:34:58 -0400
commited95d7450dcbfeb45ffc9d39b1747aee82b49a51 (patch)
treefaca7d89e2907e1407161f967477ed2ae21d46bb /arch/powerpc/boot/dtc-src/checks.c
parent0ec27c049d80535f77901654a310b090106b046c (diff)
powerpc: Update in-kernel dtc and libfdt to version 1.2.0
Some time ago, a copies of the upstream dtc and libfdt sources were included in the kernel tree to avoid having these as external dependencies for building the kernel. Since then development on the upstream dtc and libfdt has continued. This updates the in-kernel versions to match the recently released upstream dtc version 1.2.0. This includes a number of bugfixes, many cleanups and a few new features. Signed-off-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/boot/dtc-src/checks.c')
-rw-r--r--arch/powerpc/boot/dtc-src/checks.c305
1 files changed, 71 insertions, 234 deletions
diff --git a/arch/powerpc/boot/dtc-src/checks.c b/arch/powerpc/boot/dtc-src/checks.c
index 2ce961cd414d..95485796f253 100644
--- a/arch/powerpc/boot/dtc-src/checks.c
+++ b/arch/powerpc/boot/dtc-src/checks.c
@@ -242,6 +242,42 @@ static void check_duplicate_property_names(struct check *c, struct node *dt,
242} 242}
243NODE_CHECK(duplicate_property_names, NULL, ERROR); 243NODE_CHECK(duplicate_property_names, NULL, ERROR);
244 244
245#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
246#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
247#define DIGITS "0123456789"
248#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
249
250static void check_node_name_chars(struct check *c, struct node *dt,
251 struct node *node)
252{
253 int n = strspn(node->name, c->data);
254
255 if (n < strlen(node->name))
256 FAIL(c, "Bad character '%c' in node %s",
257 node->name[n], node->fullpath);
258}
259NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);
260
261static void check_node_name_format(struct check *c, struct node *dt,
262 struct node *node)
263{
264 if (strchr(get_unitname(node), '@'))
265 FAIL(c, "Node %s has multiple '@' characters in name",
266 node->fullpath);
267}
268NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);
269
270static void check_property_name_chars(struct check *c, struct node *dt,
271 struct node *node, struct property *prop)
272{
273 int n = strspn(prop->name, c->data);
274
275 if (n < strlen(prop->name))
276 FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
277 prop->name[n], prop->name, node->fullpath);
278}
279PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);
280
245static void check_explicit_phandles(struct check *c, struct node *root, 281static void check_explicit_phandles(struct check *c, struct node *root,
246 struct node *node) 282 struct node *node)
247{ 283{
@@ -280,16 +316,29 @@ NODE_CHECK(explicit_phandles, NULL, ERROR);
280static void check_name_properties(struct check *c, struct node *root, 316static void check_name_properties(struct check *c, struct node *root,
281 struct node *node) 317 struct node *node)
282{ 318{
283 struct property *prop; 319 struct property **pp, *prop = NULL;
320
321 for (pp = &node->proplist; *pp; pp = &((*pp)->next))
322 if (streq((*pp)->name, "name")) {
323 prop = *pp;
324 break;
325 }
284 326
285 prop = get_property(node, "name");
286 if (!prop) 327 if (!prop)
287 return; /* No name property, that's fine */ 328 return; /* No name property, that's fine */
288 329
289 if ((prop->val.len != node->basenamelen+1) 330 if ((prop->val.len != node->basenamelen+1)
290 || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) 331 || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
291 FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead" 332 FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
292 " of base node name)", node->fullpath, prop->val.val); 333 " of base node name)", node->fullpath, prop->val.val);
334 } else {
335 /* The name property is correct, and therefore redundant.
336 * Delete it */
337 *pp = prop->next;
338 free(prop->name);
339 data_free(prop->val);
340 free(prop);
341 }
293} 342}
294CHECK_IS_STRING(name_is_string, "name", ERROR); 343CHECK_IS_STRING(name_is_string, "name", ERROR);
295NODE_CHECK(name_properties, NULL, ERROR, &name_is_string); 344NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
@@ -301,23 +350,23 @@ NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
301static void fixup_phandle_references(struct check *c, struct node *dt, 350static void fixup_phandle_references(struct check *c, struct node *dt,
302 struct node *node, struct property *prop) 351 struct node *node, struct property *prop)
303{ 352{
304 struct marker *m = prop->val.markers; 353 struct marker *m = prop->val.markers;
305 struct node *refnode; 354 struct node *refnode;
306 cell_t phandle; 355 cell_t phandle;
307 356
308 for_each_marker_of_type(m, REF_PHANDLE) { 357 for_each_marker_of_type(m, REF_PHANDLE) {
309 assert(m->offset + sizeof(cell_t) <= prop->val.len); 358 assert(m->offset + sizeof(cell_t) <= prop->val.len);
310 359
311 refnode = get_node_by_ref(dt, m->ref); 360 refnode = get_node_by_ref(dt, m->ref);
312 if (! refnode) { 361 if (! refnode) {
313 FAIL(c, "Reference to non-existent node or label \"%s\"\n", 362 FAIL(c, "Reference to non-existent node or label \"%s\"\n",
314 m->ref); 363 m->ref);
315 continue; 364 continue;
316 } 365 }
317 366
318 phandle = get_node_phandle(dt, refnode); 367 phandle = get_node_phandle(dt, refnode);
319 *((cell_t *)(prop->val.val + m->offset)) = cpu_to_be32(phandle); 368 *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
320 } 369 }
321} 370}
322CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR, 371CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
323 &duplicate_node_names, &explicit_phandles); 372 &duplicate_node_names, &explicit_phandles);
@@ -498,6 +547,7 @@ TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
498 547
499static struct check *check_table[] = { 548static struct check *check_table[] = {
500 &duplicate_node_names, &duplicate_property_names, 549 &duplicate_node_names, &duplicate_property_names,
550 &node_name_chars, &node_name_format, &property_name_chars,
501 &name_is_string, &name_properties, 551 &name_is_string, &name_properties,
502 &explicit_phandles, 552 &explicit_phandles,
503 &phandle_references, &path_references, 553 &phandle_references, &path_references,
@@ -511,10 +561,7 @@ static struct check *check_table[] = {
511 &obsolete_chosen_interrupt_controller, 561 &obsolete_chosen_interrupt_controller,
512}; 562};
513 563
514int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys); 564void process_checks(int force, struct boot_info *bi)
515
516void process_checks(int force, struct boot_info *bi,
517 int checkflag, int outversion, int boot_cpuid_phys)
518{ 565{
519 struct node *dt = bi->dt; 566 struct node *dt = bi->dt;
520 int i; 567 int i;
@@ -537,214 +584,4 @@ void process_checks(int force, struct boot_info *bi,
537 "output forced\n"); 584 "output forced\n");
538 } 585 }
539 } 586 }
540
541 if (checkflag) {
542 if (error) {
543 fprintf(stderr, "Warning: Skipping semantic checks due to structural errors\n");
544 } else {
545 if (!check_semantics(bi->dt, outversion,
546 boot_cpuid_phys))
547 fprintf(stderr, "Warning: Input tree has semantic errors\n");
548 }
549 }
550}
551
552/*
553 * Semantic check functions
554 */
555
556#define ERRMSG(...) if (quiet < 2) fprintf(stderr, "ERROR: " __VA_ARGS__)
557#define WARNMSG(...) if (quiet < 1) fprintf(stderr, "Warning: " __VA_ARGS__)
558
559#define DO_ERR(...) do {ERRMSG(__VA_ARGS__); ok = 0; } while (0)
560
561#define CHECK_HAVE(node, propname) \
562 do { \
563 if (! (prop = get_property((node), (propname)))) \
564 DO_ERR("Missing \"%s\" property in %s\n", (propname), \
565 (node)->fullpath); \
566 } while (0);
567
568#define CHECK_HAVE_WARN(node, propname) \
569 do { \
570 if (! (prop = get_property((node), (propname)))) \
571 WARNMSG("%s has no \"%s\" property\n", \
572 (node)->fullpath, (propname)); \
573 } while (0)
574
575#define CHECK_HAVE_STRING(node, propname) \
576 do { \
577 CHECK_HAVE((node), (propname)); \
578 if (prop && !data_is_one_string(prop->val)) \
579 DO_ERR("\"%s\" property in %s is not a string\n", \
580 (propname), (node)->fullpath); \
581 } while (0)
582
583#define CHECK_HAVE_STREQ(node, propname, value) \
584 do { \
585 CHECK_HAVE_STRING((node), (propname)); \
586 if (prop && !streq(prop->val.val, (value))) \
587 DO_ERR("%s has wrong %s, %s (should be %s\n", \
588 (node)->fullpath, (propname), \
589 prop->val.val, (value)); \
590 } while (0)
591
592#define CHECK_HAVE_ONECELL(node, propname) \
593 do { \
594 CHECK_HAVE((node), (propname)); \
595 if (prop && (prop->val.len != sizeof(cell_t))) \
596 DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \
597 } while (0)
598
599#define CHECK_HAVE_WARN_ONECELL(node, propname) \
600 do { \
601 CHECK_HAVE_WARN((node), (propname)); \
602 if (prop && (prop->val.len != sizeof(cell_t))) \
603 DO_ERR("\"%s\" property in %s has wrong size %d (should be 1 cell)\n", (propname), (node)->fullpath, prop->val.len); \
604 } while (0)
605
606#define CHECK_HAVE_WARN_PHANDLE(xnode, propname, root) \
607 do { \
608 struct node *ref; \
609 CHECK_HAVE_WARN_ONECELL((xnode), (propname)); \
610 if (prop) {\
611 cell_t phandle = propval_cell(prop); \
612 if ((phandle == 0) || (phandle == -1)) { \
613 DO_ERR("\"%s\" property in %s contains an invalid phandle %x\n", (propname), (xnode)->fullpath, phandle); \
614 } else { \
615 ref = get_node_by_phandle((root), propval_cell(prop)); \
616 if (! ref) \
617 DO_ERR("\"%s\" property in %s refers to non-existant phandle %x\n", (propname), (xnode)->fullpath, propval_cell(prop)); \
618 } \
619 } \
620 } while (0)
621
622#define CHECK_HAVE_WARN_STRING(node, propname) \
623 do { \
624 CHECK_HAVE_WARN((node), (propname)); \
625 if (prop && !data_is_one_string(prop->val)) \
626 DO_ERR("\"%s\" property in %s is not a string\n", \
627 (propname), (node)->fullpath); \
628 } while (0)
629
630static int check_root(struct node *root)
631{
632 struct property *prop;
633 int ok = 1;
634
635 CHECK_HAVE_STRING(root, "model");
636 CHECK_HAVE_WARN(root, "compatible");
637
638 return ok;
639}
640
641static int check_cpus(struct node *root, int outversion, int boot_cpuid_phys)
642{
643 struct node *cpus, *cpu;
644 struct property *prop;
645 struct node *bootcpu = NULL;
646 int ok = 1;
647
648 cpus = get_subnode(root, "cpus");
649 if (! cpus) {
650 ERRMSG("Missing /cpus node\n");
651 return 0;
652 }
653
654 if (cpus->addr_cells != 1)
655 DO_ERR("%s has bad #address-cells value %d (should be 1)\n",
656 cpus->fullpath, cpus->addr_cells);
657 if (cpus->size_cells != 0)
658 DO_ERR("%s has bad #size-cells value %d (should be 0)\n",
659 cpus->fullpath, cpus->size_cells);
660
661 for_each_child(cpus, cpu) {
662 CHECK_HAVE_STREQ(cpu, "device_type", "cpu");
663
664 CHECK_HAVE_ONECELL(cpu, "reg");
665 if (prop) {
666 cell_t unitnum;
667 char *eptr;
668
669 unitnum = strtol(get_unitname(cpu), &eptr, 16);
670 if (*eptr) {
671 WARNMSG("%s has bad format unit name %s (should be CPU number\n",
672 cpu->fullpath, get_unitname(cpu));
673 } else if (unitnum != propval_cell(prop)) {
674 WARNMSG("%s unit name \"%s\" does not match \"reg\" property <%x>\n",
675 cpu->fullpath, get_unitname(cpu),
676 propval_cell(prop));
677 }
678 }
679
680/* CHECK_HAVE_ONECELL(cpu, "d-cache-line-size"); */
681/* CHECK_HAVE_ONECELL(cpu, "i-cache-line-size"); */
682 CHECK_HAVE_ONECELL(cpu, "d-cache-size");
683 CHECK_HAVE_ONECELL(cpu, "i-cache-size");
684
685 CHECK_HAVE_WARN_ONECELL(cpu, "clock-frequency");
686 CHECK_HAVE_WARN_ONECELL(cpu, "timebase-frequency");
687
688 prop = get_property(cpu, "linux,boot-cpu");
689 if (prop) {
690 if (prop->val.len)
691 WARNMSG("\"linux,boot-cpu\" property in %s is non-empty\n",
692 cpu->fullpath);
693 if (bootcpu)
694 DO_ERR("Multiple boot cpus (%s and %s)\n",
695 bootcpu->fullpath, cpu->fullpath);
696 else
697 bootcpu = cpu;
698 }
699 }
700
701 if (outversion < 2) {
702 if (! bootcpu)
703 WARNMSG("No cpu has \"linux,boot-cpu\" property\n");
704 } else {
705 if (bootcpu)
706 WARNMSG("\"linux,boot-cpu\" property is deprecated in blob version 2 or higher\n");
707 if (boot_cpuid_phys == 0xfeedbeef)
708 WARNMSG("physical boot CPU not set. Use -b option to set\n");
709 }
710
711 return ok;
712}
713
714static int check_memory(struct node *root)
715{
716 struct node *mem;
717 struct property *prop;
718 int nnodes = 0;
719 int ok = 1;
720
721 for_each_child(root, mem) {
722 if (! strneq(mem->name, "memory", mem->basenamelen))
723 continue;
724
725 nnodes++;
726
727 CHECK_HAVE_STREQ(mem, "device_type", "memory");
728 CHECK_HAVE(mem, "reg");
729 }
730
731 if (nnodes == 0) {
732 ERRMSG("No memory nodes\n");
733 return 0;
734 }
735
736 return ok;
737}
738
739int check_semantics(struct node *dt, int outversion, int boot_cpuid_phys)
740{
741 int ok = 1;
742
743 ok = ok && check_root(dt);
744 ok = ok && check_cpus(dt, outversion, boot_cpuid_phys);
745 ok = ok && check_memory(dt);
746 if (! ok)
747 return 0;
748
749 return 1;
750} 587}