common/image.c fix length calculation in boot_relocate_fdt
authorJohn Rigby <john.rigby@linaro.org>
Wed, 13 Oct 2010 19:57:31 +0000 (13:57 -0600)
committerWolfgang Denk <wd@denx.de>
Mon, 18 Oct 2010 20:49:47 +0000 (22:49 +0200)
boot_relocate_fdt is called on platforms with CONFIG_SYS_BOOTMAPSZ
defined to relocate the device tree blob to be inside the
boot map area between bootmap_base and bootmap_base+CONFIG_SYS_BOOTMAPSZ.

For the case where the blob needs to be relocated, space is
allocated inside the bootmap by calling lmb_alloc_base with
size passed in plus some padding:

    of_len = *of_size + CONFIG_SYS_FDT_PAD;

For the case where the blob is already inside the bounds of the boot map
area, lmb_reserve is called to reserve the the space where the blob is
already residing.  The calculation for this case is currently:

    of_len = (CONFIG_SYS_BOOTMAPSZ + bootmap_base) - (ulong)fdt_blob;

This is wrong because it reserves all the space in the boot map area
from the blob to the end ignoring completely the actual size. The
worst case is where the blob is at the beginning and the entire boot map
area get reserved. Fix this by changing the length calculation to this:

    of_len = *of_size + CONFIG_SYS_FDT_PAD;

This bug has likely never manifested itself because bootm has never
been called with the fdt blob already in the bootmap area.  In my
testing on an OMAP3 beagle board I initially worked around the bug
by simply moving the initial location of the fdt blob.  I have tested
with the new calculation with the fdt blob both inside and outside
the boot map area.

Signed-off-by: John Rigby <john.rigby@linaro.org>
common/image.c

index 3a2f25e5af4de7f64e9e3e31bc61ef456e9e97c3..f59904d3aadc8d667f6bc6fedcb1c0c80ba1cc9a 100644 (file)
@@ -1252,7 +1252,7 @@ int boot_relocate_fdt (struct lmb *lmb, ulong bootmap_base,
                *of_size = of_len;
        } else {
                *of_flat_tree = fdt_blob;
-               of_len = (CONFIG_SYS_BOOTMAPSZ + bootmap_base) - (ulong)fdt_blob;
+               of_len = *of_size + CONFIG_SYS_FDT_PAD;
                lmb_reserve(lmb, (ulong)fdt_blob, of_len);
                fdt_set_totalsize(*of_flat_tree, of_len);