From: Mark Bellon <mbellon@mvista.com>

In PPC64 there are number of problems in arch/ppc64/boot/main.c that
prevent a kernel from making use of a large (greater than ~16MB) INITRD. 
This is 64 bit architecture and really large INITRD images should be
possible.

Simply put the existing code has a fixed reservation (claim) address and
once the kernel plus initrd image are large enough to pass this address all
sorts of bad things occur.  The fix is the dynamically establish the first
claim address above the loaded kernel plus initrd (plus some "padding" and
rounding)

Signed-off-by: Mark Bellon <mbellon@mvista.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Anton Blanchard <anton@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 arch/ppc64/boot/main.c |   30 ++++++++++++++++++++++--------
 1 files changed, 22 insertions(+), 8 deletions(-)

diff -puN arch/ppc64/boot/main.c~ppc64-large-initrd-causes-kernel-not-to-boot arch/ppc64/boot/main.c
--- devel/arch/ppc64/boot/main.c~ppc64-large-initrd-causes-kernel-not-to-boot	2005-08-08 11:11:40.000000000 -0700
+++ devel-akpm/arch/ppc64/boot/main.c	2005-08-08 11:12:48.000000000 -0700
@@ -20,7 +20,7 @@ extern int getprop(void *, const char *,
 extern void printf(const char *fmt, ...);
 extern int sprintf(char *buf, const char *fmt, ...);
 void gunzip(void *, int, unsigned char *, int *);
-void *claim(unsigned int, unsigned int, unsigned int);
+void *claim(unsigned long, unsigned long, unsigned long);
 void flush_cache(void *, unsigned long);
 void pause(void);
 extern void exit(void);
@@ -29,9 +29,8 @@ unsigned long strlen(const char *s);
 void *memmove(void *dest, const void *src, unsigned long n);
 void *memcpy(void *dest, const void *src, unsigned long n);
 
-/* Value picked to match that used by yaboot */
-#define PROG_START	0x01400000
-#define RAM_END		(256<<20) // Fixme: use OF */
+#define	ONE_MB		0x100000
+#define RAM_END		(512<<20) // Fixme: use OF */
 
 char *avail_ram;
 char *begin_avail, *end_avail;
@@ -73,13 +72,13 @@ void *stderr;
 
 #undef DEBUG
 
-static unsigned long claim_base = PROG_START;
+static unsigned long claim_base;
 
 static unsigned long try_claim(unsigned long size)
 {
 	unsigned long addr = 0;
 
-	for(; claim_base < RAM_END; claim_base += 0x100000) {
+	for(; claim_base < RAM_END; claim_base += ONE_MB) {
 #ifdef DEBUG
 		printf("    trying: 0x%08lx\n\r", claim_base);
 #endif
@@ -110,7 +109,22 @@ void start(unsigned long a1, unsigned lo
 	if (getprop(chosen_handle, "stdin", &stdin, sizeof(stdin)) != 4)
 		exit();
 
-	printf("\n\rzImage starting: loaded at 0x%x\n\r", (unsigned)_start);
+	printf("\n\rzImage starting: loaded at 0x%lx\n\r",
+			(unsigned long)_start);
+
+	/*
+	 * The first available claim_base must be "out of the way" -
+	 * well above _start + kernel_size + initrd + overhead.
+	 */
+	claim_base = ((unsigned long) _start) +
+				((unsigned long) vmlinux_filesize) +
+				(unsigned long)(_initrd_end - _initrd_start) +
+				ONE_MB;
+
+	/*
+	 * Now round up the claim_base to a nice 1 MB boundary.
+	 */
+	claim_base = ((claim_base + ONE_MB - 1) / ONE_MB) * ONE_MB;
 
 	/*
 	 * Now we try to claim some memory for the kernel itself
@@ -120,7 +134,7 @@ void start(unsigned long a1, unsigned lo
 	 * size... In practice we add 1Mb, that is enough, but we should really
 	 * consider fixing the Makefile to put a _raw_ kernel in there !
 	 */
-	vmlinux_memsize += 0x100000;
+	vmlinux_memsize += ONE_MB;
 	printf("Allocating 0x%lx bytes for kernel ...\n\r", vmlinux_memsize);
 	vmlinux.addr = try_claim(vmlinux_memsize);
 	if (vmlinux.addr == 0) {
_