
From: Paul Mackerras <paulus@samba.org>

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 <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 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;
_
