Commit c10c178a92b032ea3dd7259dcbbd1b9331c05c41

Authored by Sebastian Siewior
Committed by Benjamin Herrenschmidt
1 parent c1075fb7ec

powerpc/boot: Compare _start against ei.loadsize instead ei.memsize

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>

Showing 2 changed files with 20 additions and 10 deletions Side-by-side Diff

arch/powerpc/boot/libfdt-wrapper.c
... ... @@ -165,6 +165,7 @@
165 165 void fdt_init(void *blob)
166 166 {
167 167 int err;
  168 + int bufsize;
168 169  
169 170 dt_ops.finddevice = fdt_wrapper_finddevice;
170 171 dt_ops.getprop = fdt_wrapper_getprop;
171 172  
172 173  
... ... @@ -178,17 +179,16 @@
178 179  
179 180 /* Make sure the dt blob is the right version and so forth */
180 181 fdt = blob;
181   - err = fdt_open_into(fdt, fdt, fdt_totalsize(blob));
182   - if (err == -FDT_ERR_NOSPACE) {
183   - int bufsize = fdt_totalsize(fdt) + 4;
184   - buf = malloc(bufsize);
185   - err = fdt_open_into(fdt, buf, bufsize);
186   - }
  182 + bufsize = fdt_totalsize(fdt) + 4;
  183 + buf = malloc(bufsize);
  184 + if(!buf)
  185 + fatal("malloc failed. can't relocate the device tree\n\r");
187 186  
  187 + err = fdt_open_into(fdt, buf, bufsize);
  188 +
188 189 if (err != 0)
189 190 fatal("fdt_init(): %s\n\r", fdt_strerror(err));
190 191  
191   - if (buf)
192   - fdt = buf;
  192 + fdt = buf;
193 193 }
arch/powerpc/boot/main.c
... ... @@ -56,9 +56,19 @@
56 56 if (platform_ops.vmlinux_alloc) {
57 57 addr = platform_ops.vmlinux_alloc(ei.memsize);
58 58 } else {
59   - if ((unsigned long)_start < ei.memsize)
  59 + /*
  60 + * Check if the kernel image (without bss) would overwrite the
  61 + * bootwrapper. The device tree has been moved in fdt_init()
  62 + * to an area allocated with malloc() (somewhere past _end).
  63 + */
  64 + if ((unsigned long)_start < ei.loadsize)
60 65 fatal("Insufficient memory for kernel at address 0!"
61   - " (_start=%p)\n\r", _start);
  66 + " (_start=%p, uncomressed size=%08x)\n\r",
  67 + _start, ei.loadsize);
  68 +
  69 + if ((unsigned long)_end < ei.memsize)
  70 + fatal("The final kernel image would overwrite the "
  71 + "device tree\n\r");
62 72 }
63 73  
64 74 /* Finally, gunzip the kernel */