powerpc/boot: Compare _start against ei.loadsize instead ei.memsize
authorSebastian Siewior <bigeasy@linutronix.de>
Sun, 12 Oct 2008 23:15:26 +0000 (23:15 +0000)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 21 Oct 2008 04:17:47 +0000 (15:17 +1100)
If the vmlinux binary in memory is larger than 4 MiB than it collides
with the initial boot code which is linked at 4 MiB in case of cuBoot.
If the the uncompressed image size (on disk size) is less than 4 MiB
then it would fit. The difference between those two sizes is the bss
section. In cuBoot we have the dtb embedded right after the data
section so it is very likely that the reset of the bss section (in
kernel's start up code) will overwrite the dtb blob. Therefore we
reallocate the dtb. Something similar is allready done to the initrd.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/boot/libfdt-wrapper.c
arch/powerpc/boot/main.c

index c541fd8a95d4966369aa79fbc3557122fd7a36d8..1daa73f08ba8bf3c425dab7906c7741e20303acc 100644 (file)
@@ -165,6 +165,7 @@ static unsigned long fdt_wrapper_finalize(void)
 void fdt_init(void *blob)
 {
        int err;
+       int bufsize;
 
        dt_ops.finddevice = fdt_wrapper_finddevice;
        dt_ops.getprop = fdt_wrapper_getprop;
@@ -178,16 +179,15 @@ void fdt_init(void *blob)
 
        /* Make sure the dt blob is the right version and so forth */
        fdt = blob;
-       err = fdt_open_into(fdt, fdt, fdt_totalsize(blob));
-       if (err == -FDT_ERR_NOSPACE) {
-               int bufsize = fdt_totalsize(fdt) + 4;
-               buf = malloc(bufsize);
-               err = fdt_open_into(fdt, buf, bufsize);
-       }
+       bufsize = fdt_totalsize(fdt) + 4;
+       buf = malloc(bufsize);
+       if(!buf)
+               fatal("malloc failed. can't relocate the device tree\n\r");
+
+       err = fdt_open_into(fdt, buf, bufsize);
 
        if (err != 0)
                fatal("fdt_init(): %s\n\r", fdt_strerror(err));
 
-       if (buf)
-               fdt = buf;
+       fdt = buf;
 }
index 9e7f3ddd99131523c275f468ea26cc3f974a2e83..ae32801ebd69de64fee9e4946f569ebb81813b95 100644 (file)
@@ -56,9 +56,19 @@ static struct addr_range prep_kernel(void)
        if (platform_ops.vmlinux_alloc) {
                addr = platform_ops.vmlinux_alloc(ei.memsize);
        } else {
-               if ((unsigned long)_start < ei.memsize)
+               /*
+                * Check if the kernel image (without bss) would overwrite the
+                * bootwrapper. The device tree has been moved in fdt_init()
+                * to an area allocated with malloc() (somewhere past _end).
+                */
+               if ((unsigned long)_start < ei.loadsize)
                        fatal("Insufficient memory for kernel at address 0!"
-                              " (_start=%p)\n\r", _start);
+                              " (_start=%p, uncomressed size=%08x)\n\r",
+                              _start, ei.loadsize);
+
+               if ((unsigned long)_end < ei.memsize)
+                       fatal("The final kernel image would overwrite the "
+                                       "device tree\n\r");
        }
 
        /* Finally, gunzip the kernel */