Commit 34153fa3af45d84f3221d9b67ba2ab7e8a220d28

Authored by Benjamin Herrenschmidt
Committed by Paul Mackerras
1 parent e28f7faf05

[PATCH] flattened device tree changes

This patch updates the format of the flattened device-tree passed
between the boot trampoline and the kernel to support a more compact
representation, for use by embedded systems mostly.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>

Showing 3 changed files with 209 additions and 68 deletions Side-by-side Diff

arch/ppc64/kernel/prom.c
... ... @@ -625,8 +625,8 @@
625 625  
626 626 static inline char *find_flat_dt_string(u32 offset)
627 627 {
628   - return ((char *)initial_boot_params) + initial_boot_params->off_dt_strings
629   - + offset;
  628 + return ((char *)initial_boot_params) +
  629 + initial_boot_params->off_dt_strings + offset;
630 630 }
631 631  
632 632 /**
633 633  
634 634  
635 635  
636 636  
... ... @@ -635,26 +635,33 @@
635 635 * unflatten the tree
636 636 */
637 637 static int __init scan_flat_dt(int (*it)(unsigned long node,
638   - const char *full_path, void *data),
  638 + const char *uname, int depth,
  639 + void *data),
639 640 void *data)
640 641 {
641 642 unsigned long p = ((unsigned long)initial_boot_params) +
642 643 initial_boot_params->off_dt_struct;
643 644 int rc = 0;
  645 + int depth = -1;
644 646  
645 647 do {
646 648 u32 tag = *((u32 *)p);
647 649 char *pathp;
648 650  
649 651 p += 4;
650   - if (tag == OF_DT_END_NODE)
  652 + if (tag == OF_DT_END_NODE) {
  653 + depth --;
651 654 continue;
  655 + }
  656 + if (tag == OF_DT_NOP)
  657 + continue;
652 658 if (tag == OF_DT_END)
653 659 break;
654 660 if (tag == OF_DT_PROP) {
655 661 u32 sz = *((u32 *)p);
656 662 p += 8;
657   - p = _ALIGN(p, sz >= 8 ? 8 : 4);
  663 + if (initial_boot_params->version < 0x10)
  664 + p = _ALIGN(p, sz >= 8 ? 8 : 4);
658 665 p += sz;
659 666 p = _ALIGN(p, 4);
660 667 continue;
661 668  
... ... @@ -664,9 +671,18 @@
664 671 " device tree !\n", tag);
665 672 return -EINVAL;
666 673 }
  674 + depth++;
667 675 pathp = (char *)p;
668 676 p = _ALIGN(p + strlen(pathp) + 1, 4);
669   - rc = it(p, pathp, data);
  677 + if ((*pathp) == '/') {
  678 + char *lp, *np;
  679 + for (lp = NULL, np = pathp; *np; np++)
  680 + if ((*np) == '/')
  681 + lp = np+1;
  682 + if (lp != NULL)
  683 + pathp = lp;
  684 + }
  685 + rc = it(p, pathp, depth, data);
670 686 if (rc != 0)
671 687 break;
672 688 } while(1);
673 689  
674 690  
... ... @@ -689,17 +705,21 @@
689 705 const char *nstr;
690 706  
691 707 p += 4;
  708 + if (tag == OF_DT_NOP)
  709 + continue;
692 710 if (tag != OF_DT_PROP)
693 711 return NULL;
694 712  
695 713 sz = *((u32 *)p);
696 714 noff = *((u32 *)(p + 4));
697 715 p += 8;
698   - p = _ALIGN(p, sz >= 8 ? 8 : 4);
  716 + if (initial_boot_params->version < 0x10)
  717 + p = _ALIGN(p, sz >= 8 ? 8 : 4);
699 718  
700 719 nstr = find_flat_dt_string(noff);
701 720 if (nstr == NULL) {
702   - printk(KERN_WARNING "Can't find property index name !\n");
  721 + printk(KERN_WARNING "Can't find property index"
  722 + " name !\n");
703 723 return NULL;
704 724 }
705 725 if (strcmp(name, nstr) == 0) {
... ... @@ -713,7 +733,7 @@
713 733 }
714 734  
715 735 static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
716   - unsigned long align)
  736 + unsigned long align)
717 737 {
718 738 void *res;
719 739  
720 740  
... ... @@ -727,13 +747,16 @@
727 747 static unsigned long __init unflatten_dt_node(unsigned long mem,
728 748 unsigned long *p,
729 749 struct device_node *dad,
730   - struct device_node ***allnextpp)
  750 + struct device_node ***allnextpp,
  751 + unsigned long fpsize)
731 752 {
732 753 struct device_node *np;
733 754 struct property *pp, **prev_pp = NULL;
734 755 char *pathp;
735 756 u32 tag;
736   - unsigned int l;
  757 + unsigned int l, allocl;
  758 + int has_name = 0;
  759 + int new_format = 0;
737 760  
738 761 tag = *((u32 *)(*p));
739 762 if (tag != OF_DT_BEGIN_NODE) {
740 763  
741 764  
742 765  
... ... @@ -742,21 +765,62 @@
742 765 }
743 766 *p += 4;
744 767 pathp = (char *)*p;
745   - l = strlen(pathp) + 1;
  768 + l = allocl = strlen(pathp) + 1;
746 769 *p = _ALIGN(*p + l, 4);
747 770  
748   - np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + l,
  771 + /* version 0x10 has a more compact unit name here instead of the full
  772 + * path. we accumulate the full path size using "fpsize", we'll rebuild
  773 + * it later. We detect this because the first character of the name is
  774 + * not '/'.
  775 + */
  776 + if ((*pathp) != '/') {
  777 + new_format = 1;
  778 + if (fpsize == 0) {
  779 + /* root node: special case. fpsize accounts for path
  780 + * plus terminating zero. root node only has '/', so
  781 + * fpsize should be 2, but we want to avoid the first
  782 + * level nodes to have two '/' so we use fpsize 1 here
  783 + */
  784 + fpsize = 1;
  785 + allocl = 2;
  786 + } else {
  787 + /* account for '/' and path size minus terminal 0
  788 + * already in 'l'
  789 + */
  790 + fpsize += l;
  791 + allocl = fpsize;
  792 + }
  793 + }
  794 +
  795 +
  796 + np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
749 797 __alignof__(struct device_node));
750 798 if (allnextpp) {
751 799 memset(np, 0, sizeof(*np));
752 800 np->full_name = ((char*)np) + sizeof(struct device_node);
753   - memcpy(np->full_name, pathp, l);
  801 + if (new_format) {
  802 + char *p = np->full_name;
  803 + /* rebuild full path for new format */
  804 + if (dad && dad->parent) {
  805 + strcpy(p, dad->full_name);
  806 +#ifdef DEBUG
  807 + if ((strlen(p) + l + 1) != allocl) {
  808 + DBG("%s: p: %d, l: %d, a: %d\n",
  809 + pathp, strlen(p), l, allocl);
  810 + }
  811 +#endif
  812 + p += strlen(p);
  813 + }
  814 + *(p++) = '/';
  815 + memcpy(p, pathp, l);
  816 + } else
  817 + memcpy(np->full_name, pathp, l);
754 818 prev_pp = &np->properties;
755 819 **allnextpp = np;
756 820 *allnextpp = &np->allnext;
757 821 if (dad != NULL) {
758 822 np->parent = dad;
759   - /* we temporarily use the `next' field as `last_child'. */
  823 + /* we temporarily use the next field as `last_child'*/
760 824 if (dad->next == 0)
761 825 dad->child = np;
762 826 else
763 827  
764 828  
... ... @@ -770,18 +834,26 @@
770 834 char *pname;
771 835  
772 836 tag = *((u32 *)(*p));
  837 + if (tag == OF_DT_NOP) {
  838 + *p += 4;
  839 + continue;
  840 + }
773 841 if (tag != OF_DT_PROP)
774 842 break;
775 843 *p += 4;
776 844 sz = *((u32 *)(*p));
777 845 noff = *((u32 *)((*p) + 4));
778   - *p = _ALIGN((*p) + 8, sz >= 8 ? 8 : 4);
  846 + *p += 8;
  847 + if (initial_boot_params->version < 0x10)
  848 + *p = _ALIGN(*p, sz >= 8 ? 8 : 4);
779 849  
780 850 pname = find_flat_dt_string(noff);
781 851 if (pname == NULL) {
782 852 printk("Can't find property name in list !\n");
783 853 break;
784 854 }
  855 + if (strcmp(pname, "name") == 0)
  856 + has_name = 1;
785 857 l = strlen(pname) + 1;
786 858 pp = unflatten_dt_alloc(&mem, sizeof(struct property),
787 859 __alignof__(struct property));
... ... @@ -801,6 +873,36 @@
801 873 }
802 874 *p = _ALIGN((*p) + sz, 4);
803 875 }
  876 + /* with version 0x10 we may not have the name property, recreate
  877 + * it here from the unit name if absent
  878 + */
  879 + if (!has_name) {
  880 + char *p = pathp, *ps = pathp, *pa = NULL;
  881 + int sz;
  882 +
  883 + while (*p) {
  884 + if ((*p) == '@')
  885 + pa = p;
  886 + if ((*p) == '/')
  887 + ps = p + 1;
  888 + p++;
  889 + }
  890 + if (pa < ps)
  891 + pa = p;
  892 + sz = (pa - ps) + 1;
  893 + pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
  894 + __alignof__(struct property));
  895 + if (allnextpp) {
  896 + pp->name = "name";
  897 + pp->length = sz;
  898 + pp->value = (unsigned char *)(pp + 1);
  899 + *prev_pp = pp;
  900 + prev_pp = &pp->next;
  901 + memcpy(pp->value, ps, sz - 1);
  902 + ((char *)pp->value)[sz - 1] = 0;
  903 + DBG("fixed up name for %s -> %s\n", pathp, pp->value);
  904 + }
  905 + }
804 906 if (allnextpp) {
805 907 *prev_pp = NULL;
806 908 np->name = get_property(np, "name", NULL);
... ... @@ -812,7 +914,7 @@
812 914 np->type = "<NULL>";
813 915 }
814 916 while (tag == OF_DT_BEGIN_NODE) {
815   - mem = unflatten_dt_node(mem, p, np, allnextpp);
  917 + mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
816 918 tag = *((u32 *)(*p));
817 919 }
818 920 if (tag != OF_DT_END_NODE) {
819 921  
820 922  
821 923  
822 924  
... ... @@ -842,21 +944,27 @@
842 944 /* First pass, scan for size */
843 945 start = ((unsigned long)initial_boot_params) +
844 946 initial_boot_params->off_dt_struct;
845   - size = unflatten_dt_node(0, &start, NULL, NULL);
  947 + size = unflatten_dt_node(0, &start, NULL, NULL, 0);
  948 + size = (size | 3) + 1;
846 949  
847 950 DBG(" size is %lx, allocating...\n", size);
848 951  
849 952 /* Allocate memory for the expanded device tree */
850   - mem = (unsigned long)abs_to_virt(lmb_alloc(size,
  953 + mem = (unsigned long)abs_to_virt(lmb_alloc(size + 4,
851 954 __alignof__(struct device_node)));
  955 + ((u32 *)mem)[size / 4] = 0xdeadbeef;
  956 +
852 957 DBG(" unflattening...\n", mem);
853 958  
854 959 /* Second pass, do actual unflattening */
855 960 start = ((unsigned long)initial_boot_params) +
856 961 initial_boot_params->off_dt_struct;
857   - unflatten_dt_node(mem, &start, NULL, &allnextp);
  962 + unflatten_dt_node(mem, &start, NULL, &allnextp, 0);
858 963 if (*((u32 *)start) != OF_DT_END)
859   - printk(KERN_WARNING "Weird tag at end of tree: %x\n", *((u32 *)start));
  964 + printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start));
  965 + if (((u32 *)mem)[size / 4] != 0xdeadbeef)
  966 + printk(KERN_WARNING "End of tree marker overwritten: %08x\n",
  967 + ((u32 *)mem)[size / 4] );
860 968 *allnextp = NULL;
861 969  
862 970 /* Get pointer to OF "/chosen" node for use everywhere */
... ... @@ -880,7 +988,7 @@
880 988  
881 989  
882 990 static int __init early_init_dt_scan_cpus(unsigned long node,
883   - const char *full_path, void *data)
  991 + const char *uname, int depth, void *data)
884 992 {
885 993 char *type = get_flat_dt_prop(node, "device_type", NULL);
886 994 u32 *prop;
887 995  
... ... @@ -947,13 +1055,15 @@
947 1055 }
948 1056  
949 1057 static int __init early_init_dt_scan_chosen(unsigned long node,
950   - const char *full_path, void *data)
  1058 + const char *uname, int depth, void *data)
951 1059 {
952 1060 u32 *prop;
953 1061 u64 *prop64;
954 1062 extern unsigned long memory_limit, tce_alloc_start, tce_alloc_end;
955 1063  
956   - if (strcmp(full_path, "/chosen") != 0)
  1064 + DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
  1065 +
  1066 + if (depth != 1 || strcmp(uname, "chosen") != 0)
957 1067 return 0;
958 1068  
959 1069 /* get platform type */
960 1070  
961 1071  
962 1072  
... ... @@ -1003,18 +1113,20 @@
1003 1113 }
1004 1114  
1005 1115 static int __init early_init_dt_scan_root(unsigned long node,
1006   - const char *full_path, void *data)
  1116 + const char *uname, int depth, void *data)
1007 1117 {
1008 1118 u32 *prop;
1009 1119  
1010   - if (strcmp(full_path, "/") != 0)
  1120 + if (depth != 0)
1011 1121 return 0;
1012 1122  
1013 1123 prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL);
1014 1124 dt_root_size_cells = (prop == NULL) ? 1 : *prop;
1015   -
  1125 + DBG("dt_root_size_cells = %x\n", dt_root_size_cells);
  1126 +
1016 1127 prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL);
1017 1128 dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
  1129 + DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);
1018 1130  
1019 1131 /* break now */
1020 1132 return 1;
... ... @@ -1042,7 +1154,7 @@
1042 1154  
1043 1155  
1044 1156 static int __init early_init_dt_scan_memory(unsigned long node,
1045   - const char *full_path, void *data)
  1157 + const char *uname, int depth, void *data)
1046 1158 {
1047 1159 char *type = get_flat_dt_prop(node, "device_type", NULL);
1048 1160 cell_t *reg, *endp;
... ... @@ -1058,7 +1170,9 @@
1058 1170  
1059 1171 endp = reg + (l / sizeof(cell_t));
1060 1172  
1061   - DBG("memory scan node %s ...\n", full_path);
  1173 + DBG("memory scan node %s ..., reg size %ld, data: %x %x %x %x, ...\n",
  1174 + uname, l, reg[0], reg[1], reg[2], reg[3]);
  1175 +
1062 1176 while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
1063 1177 unsigned long base, size;
1064 1178  
1065 1179  
... ... @@ -1469,10 +1583,11 @@
1469 1583 struct device_node *np = allnodes;
1470 1584  
1471 1585 read_lock(&devtree_lock);
1472   - for (; np != 0; np = np->allnext)
  1586 + for (; np != 0; np = np->allnext) {
1473 1587 if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0
1474 1588 && of_node_get(np))
1475 1589 break;
  1590 + }
1476 1591 read_unlock(&devtree_lock);
1477 1592 return np;
1478 1593 }
arch/ppc64/kernel/prom_init.c
... ... @@ -1534,7 +1534,8 @@
1534 1534 */
1535 1535 #define MAX_PROPERTY_NAME 64
1536 1536  
1537   -static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
  1537 +static void __init scan_dt_build_strings(phandle node,
  1538 + unsigned long *mem_start,
1538 1539 unsigned long *mem_end)
1539 1540 {
1540 1541 unsigned long offset = reloc_offset();
1541 1542  
1542 1543  
... ... @@ -1547,16 +1548,21 @@
1547 1548 /* get and store all property names */
1548 1549 prev_name = RELOC("");
1549 1550 for (;;) {
1550   - int rc;
1551   -
1552 1551 /* 64 is max len of name including nul. */
1553 1552 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
1554   - rc = call_prom("nextprop", 3, 1, node, prev_name, namep);
1555   - if (rc != 1) {
  1553 + if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
1556 1554 /* No more nodes: unwind alloc */
1557 1555 *mem_start = (unsigned long)namep;
1558 1556 break;
1559 1557 }
  1558 +
  1559 + /* skip "name" */
  1560 + if (strcmp(namep, RELOC("name")) == 0) {
  1561 + *mem_start = (unsigned long)namep;
  1562 + prev_name = RELOC("name");
  1563 + continue;
  1564 + }
  1565 + /* get/create string entry */
1560 1566 soff = dt_find_string(namep);
1561 1567 if (soff != 0) {
1562 1568 *mem_start = (unsigned long)namep;
... ... @@ -1571,7 +1577,7 @@
1571 1577  
1572 1578 /* do all our children */
1573 1579 child = call_prom("child", 1, 1, node);
1574   - while (child != (phandle)0) {
  1580 + while (child != 0) {
1575 1581 scan_dt_build_strings(child, mem_start, mem_end);
1576 1582 child = call_prom("peer", 1, 1, child);
1577 1583 }
1578 1584  
1579 1585  
1580 1586  
... ... @@ -1580,17 +1586,14 @@
1580 1586 static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1581 1587 unsigned long *mem_end)
1582 1588 {
1583   - int l, align;
1584 1589 phandle child;
1585   - char *namep, *prev_name, *sstart, *p, *ep;
  1590 + char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
1586 1591 unsigned long soff;
1587 1592 unsigned char *valp;
1588 1593 unsigned long offset = reloc_offset();
1589   - char pname[MAX_PROPERTY_NAME];
1590   - char *path;
  1594 + static char pname[MAX_PROPERTY_NAME];
  1595 + int l;
1591 1596  
1592   - path = RELOC(prom_scratch);
1593   -
1594 1597 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
1595 1598  
1596 1599 /* get the node's full name */
1597 1600  
1598 1601  
1599 1602  
1600 1603  
... ... @@ -1599,23 +1602,33 @@
1599 1602 namep, *mem_end - *mem_start);
1600 1603 if (l >= 0) {
1601 1604 /* Didn't fit? Get more room. */
1602   - if (l+1 > *mem_end - *mem_start) {
  1605 + if ((l+1) > (*mem_end - *mem_start)) {
1603 1606 namep = make_room(mem_start, mem_end, l+1, 1);
1604 1607 call_prom("package-to-path", 3, 1, node, namep, l);
1605 1608 }
1606 1609 namep[l] = '\0';
  1610 +
1607 1611 /* Fixup an Apple bug where they have bogus \0 chars in the
1608 1612 * middle of the path in some properties
1609 1613 */
1610 1614 for (p = namep, ep = namep + l; p < ep; p++)
1611 1615 if (*p == '\0') {
1612 1616 memmove(p, p+1, ep - p);
1613   - ep--; l--;
  1617 + ep--; l--; p--;
1614 1618 }
1615   - *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4);
  1619 +
  1620 + /* now try to extract the unit name in that mess */
  1621 + for (p = namep, lp = NULL; *p; p++)
  1622 + if (*p == '/')
  1623 + lp = p + 1;
  1624 + if (lp != NULL)
  1625 + memmove(namep, lp, strlen(lp) + 1);
  1626 + *mem_start = _ALIGN(((unsigned long) namep) +
  1627 + strlen(namep) + 1, 4);
1616 1628 }
1617 1629  
1618 1630 /* get it again for debugging */
  1631 + path = RELOC(prom_scratch);
1619 1632 memset(path, 0, PROM_SCRATCH_SIZE);
1620 1633 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
1621 1634  
1622 1635  
1623 1636  
1624 1637  
1625 1638  
... ... @@ -1623,23 +1636,27 @@
1623 1636 prev_name = RELOC("");
1624 1637 sstart = (char *)RELOC(dt_string_start);
1625 1638 for (;;) {
1626   - int rc;
1627   -
1628   - rc = call_prom("nextprop", 3, 1, node, prev_name, pname);
1629   - if (rc != 1)
  1639 + if (call_prom("nextprop", 3, 1, node, prev_name,
  1640 + RELOC(pname)) != 1)
1630 1641 break;
1631 1642  
  1643 + /* skip "name" */
  1644 + if (strcmp(RELOC(pname), RELOC("name")) == 0) {
  1645 + prev_name = RELOC("name");
  1646 + continue;
  1647 + }
  1648 +
1632 1649 /* find string offset */
1633   - soff = dt_find_string(pname);
  1650 + soff = dt_find_string(RELOC(pname));
1634 1651 if (soff == 0) {
1635   - prom_printf("WARNING: Can't find string index for <%s>, node %s\n",
1636   - pname, path);
  1652 + prom_printf("WARNING: Can't find string index for"
  1653 + " <%s>, node %s\n", RELOC(pname), path);
1637 1654 break;
1638 1655 }
1639 1656 prev_name = sstart + soff;
1640 1657  
1641 1658 /* get length */
1642   - l = call_prom("getproplen", 2, 1, node, pname);
  1659 + l = call_prom("getproplen", 2, 1, node, RELOC(pname));
1643 1660  
1644 1661 /* sanity checks */
1645 1662 if (l == PROM_ERROR)
... ... @@ -1648,7 +1665,7 @@
1648 1665 prom_printf("WARNING: ignoring large property ");
1649 1666 /* It seems OF doesn't null-terminate the path :-( */
1650 1667 prom_printf("[%s] ", path);
1651   - prom_printf("%s length 0x%x\n", pname, l);
  1668 + prom_printf("%s length 0x%x\n", RELOC(pname), l);
1652 1669 continue;
1653 1670 }
1654 1671  
1655 1672  
... ... @@ -1658,17 +1675,16 @@
1658 1675 dt_push_token(soff, mem_start, mem_end);
1659 1676  
1660 1677 /* push property content */
1661   - align = (l >= 8) ? 8 : 4;
1662   - valp = make_room(mem_start, mem_end, l, align);
1663   - call_prom("getprop", 4, 1, node, pname, valp, l);
  1678 + valp = make_room(mem_start, mem_end, l, 4);
  1679 + call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
1664 1680 *mem_start = _ALIGN(*mem_start, 4);
1665 1681 }
1666 1682  
1667 1683 /* Add a "linux,phandle" property. */
1668 1684 soff = dt_find_string(RELOC("linux,phandle"));
1669 1685 if (soff == 0)
1670   - prom_printf("WARNING: Can't find string index for <linux-phandle>"
1671   - " node %s\n", path);
  1686 + prom_printf("WARNING: Can't find string index for"
  1687 + " <linux-phandle> node %s\n", path);
1672 1688 else {
1673 1689 dt_push_token(OF_DT_PROP, mem_start, mem_end);
1674 1690 dt_push_token(4, mem_start, mem_end);
... ... @@ -1679,7 +1695,7 @@
1679 1695  
1680 1696 /* do all our children */
1681 1697 child = call_prom("child", 1, 1, node);
1682   - while (child != (phandle)0) {
  1698 + while (child != 0) {
1683 1699 scan_dt_build_struct(child, mem_start, mem_end);
1684 1700 child = call_prom("peer", 1, 1, child);
1685 1701 }
... ... @@ -1718,7 +1734,8 @@
1718 1734  
1719 1735 /* Build header and make room for mem rsv map */
1720 1736 mem_start = _ALIGN(mem_start, 4);
1721   - hdr = make_room(&mem_start, &mem_end, sizeof(struct boot_param_header), 4);
  1737 + hdr = make_room(&mem_start, &mem_end,
  1738 + sizeof(struct boot_param_header), 4);
1722 1739 RELOC(dt_header_start) = (unsigned long)hdr;
1723 1740 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
1724 1741  
1725 1742  
... ... @@ -1731,11 +1748,11 @@
1731 1748 namep = make_room(&mem_start, &mem_end, 16, 1);
1732 1749 strcpy(namep, RELOC("linux,phandle"));
1733 1750 mem_start = (unsigned long)namep + strlen(namep) + 1;
1734   - RELOC(dt_string_end) = mem_start;
1735 1751  
1736 1752 /* Build string array */
1737 1753 prom_printf("Building dt strings...\n");
1738 1754 scan_dt_build_strings(root, &mem_start, &mem_end);
  1755 + RELOC(dt_string_end) = mem_start;
1739 1756  
1740 1757 /* Build structure */
1741 1758 mem_start = PAGE_ALIGN(mem_start);
1742 1759  
... ... @@ -1750,9 +1767,11 @@
1750 1767 hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);
1751 1768 hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);
1752 1769 hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start);
  1770 + hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start);
1753 1771 hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start);
1754 1772 hdr->version = OF_DT_VERSION;
1755   - hdr->last_comp_version = 1;
  1773 + /* Version 16 is not backward compatible */
  1774 + hdr->last_comp_version = 0x10;
1756 1775  
1757 1776 /* Reserve the whole thing and copy the reserve map in, we
1758 1777 * also bump mem_reserve_cnt to cause further reservations to
... ... @@ -1808,6 +1827,9 @@
1808 1827 /* does it need fixup ? */
1809 1828 if (prom_getproplen(i2c, "interrupts") > 0)
1810 1829 return;
  1830 +
  1831 + prom_printf("fixing up bogus interrupts for u3 i2c...\n");
  1832 +
1811 1833 /* interrupt on this revision of u3 is number 0 and level */
1812 1834 interrupts[0] = 0;
1813 1835 interrupts[1] = 1;
include/asm-ppc64/prom.h
... ... @@ -22,13 +22,15 @@
22 22 #define RELOC(x) (*PTRRELOC(&(x)))
23 23  
24 24 /* Definitions used by the flattened device tree */
25   -#define OF_DT_HEADER 0xd00dfeed /* 4: version, 4: total size */
26   -#define OF_DT_BEGIN_NODE 0x1 /* Start node: full name */
  25 +#define OF_DT_HEADER 0xd00dfeed /* marker */
  26 +#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
27 27 #define OF_DT_END_NODE 0x2 /* End node */
28   -#define OF_DT_PROP 0x3 /* Property: name off, size, content */
  28 +#define OF_DT_PROP 0x3 /* Property: name off, size,
  29 + * content */
  30 +#define OF_DT_NOP 0x4 /* nop */
29 31 #define OF_DT_END 0x9
30 32  
31   -#define OF_DT_VERSION 1
  33 +#define OF_DT_VERSION 0x10
32 34  
33 35 /*
34 36 * This is what gets passed to the kernel by prom_init or kexec
... ... @@ -54,7 +56,9 @@
54 56 u32 version; /* format version */
55 57 u32 last_comp_version; /* last compatible version */
56 58 /* version 2 fields below */
57   - u32 boot_cpuid_phys; /* Which physical CPU id we're booting on */
  59 + u32 boot_cpuid_phys; /* Physical CPU id we're booting on */
  60 + /* version 3 fields below */
  61 + u32 dt_strings_size; /* size of the DT strings block */
58 62 };
59 63  
60 64