From: Paul Mackerras This patch fixes a couple of bugs in arch/ppc64/kernel/prom.c. We were missing a couple of places where we needed to use RELOC(). I added the RELOC in one case, and in the other, moved the variable that we were accessing onto the stack (and reduced its size). (We use the variable to get a property value, but we aren't interested in the value, just in whether the property exists or not. Since we pass the size of the variable to the OF getprop call, it won't overflow.) The effect of missing the RELOCs would be that random memory locations get used on IBM pSeries systems (possibly causing random boot failures). The other thing that this does is add a linux,phandle property to each node, containing the phandle for the node, which is the token that OF uses to identify the node. Some nodes reference other nodes by means of their phandle. Without the linux,phandle property, userspace code looking at the OF device-tree image in /proc/device-tree has no way of knowing which other node is being referenced. Signed-off-by: Paul Mackerras Signed-off-by: Andrew Morton --- 25-akpm/arch/ppc64/kernel/prom.c | 41 +++++++++++++++++++-------------------- 1 files changed, 21 insertions(+), 20 deletions(-) diff -puN arch/ppc64/kernel/prom.c~ppc64-fix-missing-relocs-add-linuxphandle-property arch/ppc64/kernel/prom.c --- 25/arch/ppc64/kernel/prom.c~ppc64-fix-missing-relocs-add-linuxphandle-property 2004-05-31 21:35:36.319854896 -0700 +++ 25-akpm/arch/ppc64/kernel/prom.c 2004-05-31 21:35:36.324854136 -0700 @@ -647,8 +647,6 @@ static void __init prom_initialize_lmb(v #endif /* DEBUG_PROM */ } -static char hypertas_funcs[1024]; - static void __init prom_instantiate_rtas(void) { @@ -658,6 +656,7 @@ prom_instantiate_rtas(void) struct systemcfg *_systemcfg = RELOC(systemcfg); ihandle prom_rtas; u32 getprop_rval; + char hypertas_funcs[4]; #ifdef DEBUG_PROM prom_print(RELOC("prom_instantiate_rtas: start...\n")); @@ -1549,7 +1548,7 @@ static void __init *__make_room(unsigned if (*mem_end != RELOC(initrd_start)) prom_panic(RELOC("No memory for copy_device_tree")); - prom_print("Huge device_tree: moving initrd\n"); + prom_print(RELOC("Huge device_tree: moving initrd\n")); /* Move by 4M. */ initrd_len = RELOC(initrd_end) - RELOC(initrd_start); *mem_end = RELOC(initrd_start) + 4 * 1024 * 1024; @@ -1583,6 +1582,7 @@ inspect_node(phandle node, struct device char *prev_name, *namep; unsigned char *valp; unsigned long offset = reloc_offset(); + phandle ibm_phandle; np = make_room(mem_start, mem_end, struct device_node); memset(np, 0, sizeof(*np)); @@ -1645,23 +1645,24 @@ inspect_node(phandle node, struct device prev_propp = &pp->next; } - /* Add a "linux_phandle" value */ - if (np->node) { - u32 ibm_phandle = 0; - int len; - - /* First see if "ibm,phandle" exists and use its value */ - len = (int) - call_prom(RELOC("getprop"), 4, 1, node, RELOC("ibm,phandle"), - &ibm_phandle, sizeof(ibm_phandle)); - if (len < 0) { - np->linux_phandle = np->node; - } else { - np->linux_phandle = ibm_phandle; - } - } - - *prev_propp = 0; + /* Add a "linux,phandle" property. */ + namep = make_room(mem_start, mem_end, char[16]); + strcpy(namep, RELOC("linux,phandle")); + pp = make_room(mem_start, mem_end, struct property); + pp->name = PTRUNRELOC(namep); + pp->length = sizeof(phandle); + valp = make_room(mem_start, mem_end, phandle); + pp->value = PTRUNRELOC(valp); + *(phandle *)valp = node; + *prev_propp = PTRUNRELOC(pp); + pp->next = NULL; + + /* Set np->linux_phandle to the value of the ibm,phandle property + if it exists, otherwise to the phandle for this node. */ + np->linux_phandle = node; + if ((int)call_prom(RELOC("getprop"), 4, 1, node, RELOC("ibm,phandle"), + &ibm_phandle, sizeof(ibm_phandle)) > 0) + np->linux_phandle = ibm_phandle; /* get the node's full name */ namep = (char *)*mem_start; _