]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
[PATCH] flattened device tree changes
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 9 Aug 2005 08:36:34 +0000 (10:36 +0200)
committerPaul Mackerras <paulus@samba.org>
Mon, 29 Aug 2005 00:53:31 +0000 (10:53 +1000)
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>
arch/ppc64/kernel/prom.c
arch/ppc64/kernel/prom_init.c
include/asm-ppc64/prom.h

index 5aca01ddd81ff44272b896849dbc128d7d2bbb0a..255c39ae1b482ed9450ab1c0752e4c276b09a8f9 100644 (file)
@@ -625,8 +625,8 @@ void __init finish_device_tree(void)
 
 static inline char *find_flat_dt_string(u32 offset)
 {
-       return ((char *)initial_boot_params) + initial_boot_params->off_dt_strings
-               + offset;
+       return ((char *)initial_boot_params) +
+               initial_boot_params->off_dt_strings + offset;
 }
 
 /**
@@ -635,26 +635,33 @@ static inline char *find_flat_dt_string(u32 offset)
  * unflatten the tree
  */
 static int __init scan_flat_dt(int (*it)(unsigned long node,
-                                        const char *full_path, void *data),
+                                        const char *uname, int depth,
+                                        void *data),
                               void *data)
 {
        unsigned long p = ((unsigned long)initial_boot_params) +
                initial_boot_params->off_dt_struct;
        int rc = 0;
+       int depth = -1;
 
        do {
                u32 tag = *((u32 *)p);
                char *pathp;
                
                p += 4;
-               if (tag == OF_DT_END_NODE)
+               if (tag == OF_DT_END_NODE) {
+                       depth --;
+                       continue;
+               }
+               if (tag == OF_DT_NOP)
                        continue;
                if (tag == OF_DT_END)
                        break;
                if (tag == OF_DT_PROP) {
                        u32 sz = *((u32 *)p);
                        p += 8;
-                       p = _ALIGN(p, sz >= 8 ? 8 : 4);
+                       if (initial_boot_params->version < 0x10)
+                               p = _ALIGN(p, sz >= 8 ? 8 : 4);
                        p += sz;
                        p = _ALIGN(p, 4);
                        continue;
@@ -664,9 +671,18 @@ static int __init scan_flat_dt(int (*it)(unsigned long node,
                               " device tree !\n", tag);
                        return -EINVAL;
                }
+               depth++;
                pathp = (char *)p;
                p = _ALIGN(p + strlen(pathp) + 1, 4);
-               rc = it(p, pathp, data);
+               if ((*pathp) == '/') {
+                       char *lp, *np;
+                       for (lp = NULL, np = pathp; *np; np++)
+                               if ((*np) == '/')
+                                       lp = np+1;
+                       if (lp != NULL)
+                               pathp = lp;
+               }
+               rc = it(p, pathp, depth, data);
                if (rc != 0)
                        break;          
        } while(1);
@@ -689,17 +705,21 @@ static void* __init get_flat_dt_prop(unsigned long node, const char *name,
                const char *nstr;
 
                p += 4;
+               if (tag == OF_DT_NOP)
+                       continue;
                if (tag != OF_DT_PROP)
                        return NULL;
 
                sz = *((u32 *)p);
                noff = *((u32 *)(p + 4));
                p += 8;
-               p = _ALIGN(p, sz >= 8 ? 8 : 4);
+               if (initial_boot_params->version < 0x10)
+                       p = _ALIGN(p, sz >= 8 ? 8 : 4);
 
                nstr = find_flat_dt_string(noff);
                if (nstr == NULL) {
-                       printk(KERN_WARNING "Can't find property index name !\n");
+                       printk(KERN_WARNING "Can't find property index"
+                              " name !\n");
                        return NULL;
                }
                if (strcmp(name, nstr) == 0) {
@@ -713,7 +733,7 @@ static void* __init get_flat_dt_prop(unsigned long node, const char *name,
 }
 
 static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
-                                              unsigned long align)
+                                      unsigned long align)
 {
        void *res;
 
@@ -727,13 +747,16 @@ static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
 static unsigned long __init unflatten_dt_node(unsigned long mem,
                                              unsigned long *p,
                                              struct device_node *dad,
-                                             struct device_node ***allnextpp)
+                                             struct device_node ***allnextpp,
+                                             unsigned long fpsize)
 {
        struct device_node *np;
        struct property *pp, **prev_pp = NULL;
        char *pathp;
        u32 tag;
-       unsigned int l;
+       unsigned int l, allocl;
+       int has_name = 0;
+       int new_format = 0;
 
        tag = *((u32 *)(*p));
        if (tag != OF_DT_BEGIN_NODE) {
@@ -742,21 +765,62 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
        }
        *p += 4;
        pathp = (char *)*p;
-       l = strlen(pathp) + 1;
+       l = allocl = strlen(pathp) + 1;
        *p = _ALIGN(*p + l, 4);
 
-       np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + l,
+       /* version 0x10 has a more compact unit name here instead of the full
+        * path. we accumulate the full path size using "fpsize", we'll rebuild
+        * it later. We detect this because the first character of the name is
+        * not '/'.
+        */
+       if ((*pathp) != '/') {
+               new_format = 1;
+               if (fpsize == 0) {
+                       /* root node: special case. fpsize accounts for path
+                        * plus terminating zero. root node only has '/', so
+                        * fpsize should be 2, but we want to avoid the first
+                        * level nodes to have two '/' so we use fpsize 1 here
+                        */
+                       fpsize = 1;
+                       allocl = 2;
+               } else {
+                       /* account for '/' and path size minus terminal 0
+                        * already in 'l'
+                        */
+                       fpsize += l;
+                       allocl = fpsize;
+               }
+       }
+
+
+       np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
                                __alignof__(struct device_node));
        if (allnextpp) {
                memset(np, 0, sizeof(*np));
                np->full_name = ((char*)np) + sizeof(struct device_node);
-               memcpy(np->full_name, pathp, l);
+               if (new_format) {
+                       char *p = np->full_name;
+                       /* rebuild full path for new format */
+                       if (dad && dad->parent) {
+                               strcpy(p, dad->full_name);
+#ifdef DEBUG
+                               if ((strlen(p) + l + 1) != allocl) {
+                                       DBG("%s: p: %d, l: %d, a: %d\n",
+                                           pathp, strlen(p), l, allocl);
+                               }
+#endif
+                               p += strlen(p);
+                       }
+                       *(p++) = '/';
+                       memcpy(p, pathp, l);
+               } else
+                       memcpy(np->full_name, pathp, l);
                prev_pp = &np->properties;
                **allnextpp = np;
                *allnextpp = &np->allnext;
                if (dad != NULL) {
                        np->parent = dad;
-                       /* we temporarily use the `next' field as `last_child'. */
+                       /* we temporarily use the next field as `last_child'*/
                        if (dad->next == 0)
                                dad->child = np;
                        else
@@ -770,18 +834,26 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
                char *pname;
 
                tag = *((u32 *)(*p));
+               if (tag == OF_DT_NOP) {
+                       *p += 4;
+                       continue;
+               }
                if (tag != OF_DT_PROP)
                        break;
                *p += 4;
                sz = *((u32 *)(*p));
                noff = *((u32 *)((*p) + 4));
-               *p = _ALIGN((*p) + 8, sz >= 8 ? 8 : 4);
+               *p += 8;
+               if (initial_boot_params->version < 0x10)
+                       *p = _ALIGN(*p, sz >= 8 ? 8 : 4);
 
                pname = find_flat_dt_string(noff);
                if (pname == NULL) {
                        printk("Can't find property name in list !\n");
                        break;
                }
+               if (strcmp(pname, "name") == 0)
+                       has_name = 1;
                l = strlen(pname) + 1;
                pp = unflatten_dt_alloc(&mem, sizeof(struct property),
                                        __alignof__(struct property));
@@ -801,6 +873,36 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
                }
                *p = _ALIGN((*p) + sz, 4);
        }
+       /* with version 0x10 we may not have the name property, recreate
+        * it here from the unit name if absent
+        */
+       if (!has_name) {
+               char *p = pathp, *ps = pathp, *pa = NULL;
+               int sz;
+
+               while (*p) {
+                       if ((*p) == '@')
+                               pa = p;
+                       if ((*p) == '/')
+                               ps = p + 1;
+                       p++;
+               }
+               if (pa < ps)
+                       pa = p;
+               sz = (pa - ps) + 1;
+               pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
+                                       __alignof__(struct property));
+               if (allnextpp) {
+                       pp->name = "name";
+                       pp->length = sz;
+                       pp->value = (unsigned char *)(pp + 1);
+                       *prev_pp = pp;
+                       prev_pp = &pp->next;
+                       memcpy(pp->value, ps, sz - 1);
+                       ((char *)pp->value)[sz - 1] = 0;
+                       DBG("fixed up name for %s -> %s\n", pathp, pp->value);
+               }
+       }
        if (allnextpp) {
                *prev_pp = NULL;
                np->name = get_property(np, "name", NULL);
@@ -812,7 +914,7 @@ static unsigned long __init unflatten_dt_node(unsigned long mem,
                        np->type = "<NULL>";
        }
        while (tag == OF_DT_BEGIN_NODE) {
-               mem = unflatten_dt_node(mem, p, np, allnextpp);
+               mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
                tag = *((u32 *)(*p));
        }
        if (tag != OF_DT_END_NODE) {
@@ -842,21 +944,27 @@ void __init unflatten_device_tree(void)
        /* First pass, scan for size */
        start = ((unsigned long)initial_boot_params) +
                initial_boot_params->off_dt_struct;
-       size = unflatten_dt_node(0, &start, NULL, NULL);
+       size = unflatten_dt_node(0, &start, NULL, NULL, 0);
+       size = (size | 3) + 1;
 
        DBG("  size is %lx, allocating...\n", size);
 
        /* Allocate memory for the expanded device tree */
-       mem = (unsigned long)abs_to_virt(lmb_alloc(size,
+       mem = (unsigned long)abs_to_virt(lmb_alloc(size + 4,
                                                   __alignof__(struct device_node)));
+       ((u32 *)mem)[size / 4] = 0xdeadbeef;
+
        DBG("  unflattening...\n", mem);
 
        /* Second pass, do actual unflattening */
        start = ((unsigned long)initial_boot_params) +
                initial_boot_params->off_dt_struct;
-       unflatten_dt_node(mem, &start, NULL, &allnextp);
+       unflatten_dt_node(mem, &start, NULL, &allnextp, 0);
        if (*((u32 *)start) != OF_DT_END)
-               printk(KERN_WARNING "Weird tag at end of tree: %x\n", *((u32 *)start));
+               printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start));
+       if (((u32 *)mem)[size / 4] != 0xdeadbeef)
+               printk(KERN_WARNING "End of tree marker overwritten: %08x\n",
+                      ((u32 *)mem)[size / 4] );
        *allnextp = NULL;
 
        /* Get pointer to OF "/chosen" node for use everywhere */
@@ -880,7 +988,7 @@ void __init unflatten_device_tree(void)
 
 
 static int __init early_init_dt_scan_cpus(unsigned long node,
-                                         const char *full_path, void *data)
+                                         const char *uname, int depth, void *data)
 {
        char *type = get_flat_dt_prop(node, "device_type", NULL);
        u32 *prop;
@@ -947,13 +1055,15 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
 }
 
 static int __init early_init_dt_scan_chosen(unsigned long node,
-                                           const char *full_path, void *data)
+                                           const char *uname, int depth, void *data)
 {
        u32 *prop;
        u64 *prop64;
        extern unsigned long memory_limit, tce_alloc_start, tce_alloc_end;
 
-       if (strcmp(full_path, "/chosen") != 0)
+       DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
+
+       if (depth != 1 || strcmp(uname, "chosen") != 0)
                return 0;
 
        /* get platform type */
@@ -1003,18 +1113,20 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
 }
 
 static int __init early_init_dt_scan_root(unsigned long node,
-                                         const char *full_path, void *data)
+                                         const char *uname, int depth, void *data)
 {
        u32 *prop;
 
-       if (strcmp(full_path, "/") != 0)
+       if (depth != 0)
                return 0;
 
        prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL);
        dt_root_size_cells = (prop == NULL) ? 1 : *prop;
-               
+       DBG("dt_root_size_cells = %x\n", dt_root_size_cells);
+
        prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL);
        dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
+       DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);
        
        /* break now */
        return 1;
@@ -1042,7 +1154,7 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp)
 
 
 static int __init early_init_dt_scan_memory(unsigned long node,
-                                           const char *full_path, void *data)
+                                           const char *uname, int depth, void *data)
 {
        char *type = get_flat_dt_prop(node, "device_type", NULL);
        cell_t *reg, *endp;
@@ -1058,7 +1170,9 @@ static int __init early_init_dt_scan_memory(unsigned long node,
 
        endp = reg + (l / sizeof(cell_t));
 
-       DBG("memory scan node %s ...\n", full_path);
+       DBG("memory scan node %s ..., reg size %ld, data: %x %x %x %x, ...\n",
+           uname, l, reg[0], reg[1], reg[2], reg[3]);
+
        while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
                unsigned long base, size;
 
@@ -1469,10 +1583,11 @@ struct device_node *of_find_node_by_path(const char *path)
        struct device_node *np = allnodes;
 
        read_lock(&devtree_lock);
-       for (; np != 0; np = np->allnext)
+       for (; np != 0; np = np->allnext) {
                if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0
                    && of_node_get(np))
                        break;
+       }
        read_unlock(&devtree_lock);
        return np;
 }
index dbbe6c79d8dac4f1b5a370380635aa36a7b57912..adcf972711fc1c8a24d81279173c0fa1823ee064 100644 (file)
@@ -1534,7 +1534,8 @@ static unsigned long __init dt_find_string(char *str)
  */
 #define MAX_PROPERTY_NAME 64
 
-static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
+static void __init scan_dt_build_strings(phandle node,
+                                        unsigned long *mem_start,
                                         unsigned long *mem_end)
 {
        unsigned long offset = reloc_offset();
@@ -1547,16 +1548,21 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
        /* get and store all property names */
        prev_name = RELOC("");
        for (;;) {
-               int rc;
-
                /* 64 is max len of name including nul. */
                namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
-               rc = call_prom("nextprop", 3, 1, node, prev_name, namep);
-               if (rc != 1) {
+               if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
                        /* No more nodes: unwind alloc */
                        *mem_start = (unsigned long)namep;
                        break;
                }
+
+               /* skip "name" */
+               if (strcmp(namep, RELOC("name")) == 0) {
+                       *mem_start = (unsigned long)namep;
+                       prev_name = RELOC("name");
+                       continue;
+               }
+               /* get/create string entry */
                soff = dt_find_string(namep);
                if (soff != 0) {
                        *mem_start = (unsigned long)namep;
@@ -1571,7 +1577,7 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
 
        /* do all our children */
        child = call_prom("child", 1, 1, node);
-       while (child != (phandle)0) {
+       while (child != 0) {
                scan_dt_build_strings(child, mem_start, mem_end);
                child = call_prom("peer", 1, 1, child);
        }
@@ -1580,16 +1586,13 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
 static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
                                        unsigned long *mem_end)
 {
-       int l, align;
        phandle child;
-       char *namep, *prev_name, *sstart, *p, *ep;
+       char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
        unsigned long soff;
        unsigned char *valp;
        unsigned long offset = reloc_offset();
-       char pname[MAX_PROPERTY_NAME];
-       char *path;
-
-       path = RELOC(prom_scratch);
+       static char pname[MAX_PROPERTY_NAME];
+       int l;
 
        dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
 
@@ -1599,23 +1602,33 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
                      namep, *mem_end - *mem_start);
        if (l >= 0) {
                /* Didn't fit?  Get more room. */
-               if (l+1 > *mem_end - *mem_start) {
+               if ((l+1) > (*mem_end - *mem_start)) {
                        namep = make_room(mem_start, mem_end, l+1, 1);
                        call_prom("package-to-path", 3, 1, node, namep, l);
                }
                namep[l] = '\0';
+
                /* Fixup an Apple bug where they have bogus \0 chars in the
                 * middle of the path in some properties
                 */
                for (p = namep, ep = namep + l; p < ep; p++)
                        if (*p == '\0') {
                                memmove(p, p+1, ep - p);
-                               ep--; l--;
+                               ep--; l--; p--;
                        }
-               *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4);
+
+               /* now try to extract the unit name in that mess */
+               for (p = namep, lp = NULL; *p; p++)
+                       if (*p == '/')
+                               lp = p + 1;
+               if (lp != NULL)
+                       memmove(namep, lp, strlen(lp) + 1);
+               *mem_start = _ALIGN(((unsigned long) namep) +
+                                   strlen(namep) + 1, 4);
        }
 
        /* get it again for debugging */
+       path = RELOC(prom_scratch);
        memset(path, 0, PROM_SCRATCH_SIZE);
        call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
 
@@ -1623,23 +1636,27 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
        prev_name = RELOC("");
        sstart = (char *)RELOC(dt_string_start);
        for (;;) {
-               int rc;
-
-               rc = call_prom("nextprop", 3, 1, node, prev_name, pname);
-               if (rc != 1)
+               if (call_prom("nextprop", 3, 1, node, prev_name,
+                             RELOC(pname)) != 1)
                        break;
 
+               /* skip "name" */
+               if (strcmp(RELOC(pname), RELOC("name")) == 0) {
+                       prev_name = RELOC("name");
+                       continue;
+               }
+
                /* find string offset */
-               soff = dt_find_string(pname);
+               soff = dt_find_string(RELOC(pname));
                if (soff == 0) {
-                       prom_printf("WARNING: Can't find string index for <%s>, node %s\n",
-                                   pname, path);
+                       prom_printf("WARNING: Can't find string index for"
+                                   " <%s>, node %s\n", RELOC(pname), path);
                        break;
                }
                prev_name = sstart + soff;
 
                /* get length */
-               l = call_prom("getproplen", 2, 1, node, pname);
+               l = call_prom("getproplen", 2, 1, node, RELOC(pname));
 
                /* sanity checks */
                if (l == PROM_ERROR)
@@ -1648,7 +1665,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
                        prom_printf("WARNING: ignoring large property ");
                        /* It seems OF doesn't null-terminate the path :-( */
                        prom_printf("[%s] ", path);
-                       prom_printf("%s length 0x%x\n", pname, l);
+                       prom_printf("%s length 0x%x\n", RELOC(pname), l);
                        continue;
                }
 
@@ -1658,17 +1675,16 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
                dt_push_token(soff, mem_start, mem_end);
 
                /* push property content */
-               align = (l >= 8) ? 8 : 4;
-               valp = make_room(mem_start, mem_end, l, align);
-               call_prom("getprop", 4, 1, node, pname, valp, l);
+               valp = make_room(mem_start, mem_end, l, 4);
+               call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
                *mem_start = _ALIGN(*mem_start, 4);
        }
 
        /* Add a "linux,phandle" property. */
        soff = dt_find_string(RELOC("linux,phandle"));
        if (soff == 0)
-               prom_printf("WARNING: Can't find string index for <linux-phandle>"
-                           " node %s\n", path);
+               prom_printf("WARNING: Can't find string index for"
+                           " <linux-phandle> node %s\n", path);
        else {
                dt_push_token(OF_DT_PROP, mem_start, mem_end);
                dt_push_token(4, mem_start, mem_end);
@@ -1679,7 +1695,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
 
        /* do all our children */
        child = call_prom("child", 1, 1, node);
-       while (child != (phandle)0) {
+       while (child != 0) {
                scan_dt_build_struct(child, mem_start, mem_end);
                child = call_prom("peer", 1, 1, child);
        }
@@ -1718,7 +1734,8 @@ static void __init flatten_device_tree(void)
 
        /* Build header and make room for mem rsv map */ 
        mem_start = _ALIGN(mem_start, 4);
-       hdr = make_room(&mem_start, &mem_end, sizeof(struct boot_param_header), 4);
+       hdr = make_room(&mem_start, &mem_end,
+                       sizeof(struct boot_param_header), 4);
        RELOC(dt_header_start) = (unsigned long)hdr;
        rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
 
@@ -1731,11 +1748,11 @@ static void __init flatten_device_tree(void)
        namep = make_room(&mem_start, &mem_end, 16, 1);
        strcpy(namep, RELOC("linux,phandle"));
        mem_start = (unsigned long)namep + strlen(namep) + 1;
-       RELOC(dt_string_end) = mem_start;
 
        /* Build string array */
        prom_printf("Building dt strings...\n"); 
        scan_dt_build_strings(root, &mem_start, &mem_end);
+       RELOC(dt_string_end) = mem_start;
 
        /* Build structure */
        mem_start = PAGE_ALIGN(mem_start);
@@ -1750,9 +1767,11 @@ static void __init flatten_device_tree(void)
        hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);
        hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);
        hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start);
+       hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start);
        hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start);
        hdr->version = OF_DT_VERSION;
-       hdr->last_comp_version = 1;
+       /* Version 16 is not backward compatible */
+       hdr->last_comp_version = 0x10;
 
        /* Reserve the whole thing and copy the reserve map in, we
         * also bump mem_reserve_cnt to cause further reservations to
@@ -1808,6 +1827,9 @@ static void __init fixup_device_tree(void)
        /* does it need fixup ? */
        if (prom_getproplen(i2c, "interrupts") > 0)
                return;
+
+       prom_printf("fixing up bogus interrupts for u3 i2c...\n");
+
        /* interrupt on this revision of u3 is number 0 and level */
        interrupts[0] = 0;
        interrupts[1] = 1;
index 04b1a84f7ca390c5f6c3ad6f5ea9bb22f44f2d40..dc5330b3950963266887091034cb82b53b7e1135 100644 (file)
 #define RELOC(x)        (*PTRRELOC(&(x)))
 
 /* Definitions used by the flattened device tree */
-#define OF_DT_HEADER           0xd00dfeed      /* 4: version, 4: total size */
-#define OF_DT_BEGIN_NODE       0x1             /* Start node: full name */
+#define OF_DT_HEADER           0xd00dfeed      /* marker */
+#define OF_DT_BEGIN_NODE       0x1             /* Start of node, full name */
 #define OF_DT_END_NODE         0x2             /* End node */
-#define OF_DT_PROP             0x3             /* Property: name off, size, content */
+#define OF_DT_PROP             0x3             /* Property: name off, size,
+                                                * content */
+#define OF_DT_NOP              0x4             /* nop */
 #define OF_DT_END              0x9
 
-#define OF_DT_VERSION          1
+#define OF_DT_VERSION          0x10
 
 /*
  * This is what gets passed to the kernel by prom_init or kexec
@@ -54,7 +56,9 @@ struct boot_param_header
        u32     version;                /* format version */
        u32     last_comp_version;      /* last compatible version */
        /* version 2 fields below */
-       u32     boot_cpuid_phys;        /* Which physical CPU id we're booting on */
+       u32     boot_cpuid_phys;        /* Physical CPU id we're booting on */
+       /* version 3 fields below */
+       u32     dt_strings_size;        /* size of the DT strings block */
 };