aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2012-08-17 15:15:00 +0100
committerPeter Maydell <peter.maydell@linaro.org>2012-08-17 15:15:00 +0100
commitd5457748b4c7a84bc6000ac4873d0b0f3f505f50 (patch)
treef1005dec2ebc1940c62a3636d17faa382272eea0
parentad44d2cc6569a6f54fd23b69937b042c49d7ffd1 (diff)
semi_loader: Handle dtbs with 64 bit addresses
ARM board device tree blobs have moved to specifying addresses and sizes as 64 bit values (2 cells) rather than 32 bit (1 cell); update bootwrapper so it can handle these rather than stopping with an error. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Acked-by: Dave Martin <dave.martin@linaro.org>
-rw-r--r--semi_loader.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/semi_loader.c b/semi_loader.c
index 6677527..2a30c5a 100644
--- a/semi_loader.c
+++ b/semi_loader.c
@@ -103,6 +103,7 @@ static void update_fdt(void **dest, struct loader_info *info)
int _chosen;
void *fdt;
uint32_t const *p;
+ int addrcells, sizecells;
if(!info->fdt_start)
return;
@@ -113,17 +114,21 @@ static void update_fdt(void **dest, struct loader_info *info)
/*
* Sanity-check address sizes, since addresses and sizes which do
- * not take up exactly 4 bytes are not supported.
+ * not take up exactly 4 or 8 bytes are not supported.
*/
{
if(!(p = fdt_getprop(fdt, 0, "#address-cells", &e)))
goto libfdt_error;
- else if(e != 4 || fdt32_to_cpu(*p) != 1)
+ else if(e != 4)
goto size_error;
-
+ addrcells = fdt32_to_cpu(*p);
if(!(p = fdt_getprop(fdt, 0, "#size-cells", &e)))
goto libfdt_error;
- else if(e != 4 || fdt32_to_cpu(*p) != 1)
+ else if(e != 4)
+ goto size_error;
+ sizecells = fdt32_to_cpu(*p);
+ if ((addrcells != 1 && addrcells != 2) ||
+ (sizecells != 1 && sizecells != 2))
goto size_error;
}
@@ -137,7 +142,7 @@ static void update_fdt(void **dest, struct loader_info *info)
{
int offset, depth = 0;
int _memory;
- uint32_t reg[2];
+ uint32_t reg[4];
for(offset = fdt_next_node(fdt, 0, &depth); offset >= 0;
offset = fdt_next_node(fdt, offset, &depth)) {
@@ -153,7 +158,10 @@ static void update_fdt(void **dest, struct loader_info *info)
if(e < 0)
goto libfdt_error;
- if(fdt32_to_cpu(p[1]) != 0)
+ /* Check whether the <size> part of the <addr>,<size> tuple is nonzero */
+ if(fdt32_to_cpu(p[addrcells]) != 0)
+ goto no_add_memory;
+ if(sizecells == 2 && fdt32_to_cpu(p[addrcells + 1]) != 0)
goto no_add_memory;
}
}
@@ -162,9 +170,15 @@ static void update_fdt(void **dest, struct loader_info *info)
goto libfdt_error;
_memory = e;
- reg[0] = cpu_to_fdt32(PHYS_OFFSET);
- reg[1] = cpu_to_fdt32(PHYS_SIZE);
- if((e = fdt_setprop(fdt, _memory, "reg", &reg, sizeof reg)) < 0)
+ /* This assumes PHYS_OFFSET and PHYS_SIZE are 32 bits, though
+ * the fdt cells we put them in may not be.
+ */
+ reg[0] = reg[1] = reg[2] = reg[3] = 0;
+ reg[addrcells - 1] = cpu_to_fdt32(PHYS_OFFSET);
+ reg[addrcells + sizecells - 1] = cpu_to_fdt32(PHYS_SIZE);
+
+ if((e = fdt_setprop(fdt, _memory, "reg", &reg,
+ sizeof(reg[0]) * (addrcells + sizecells))) < 0)
goto libfdt_error;
if((e = fdt_setprop_string(fdt, _memory, "device_type",
@@ -186,7 +200,10 @@ no_add_memory:
if(info->initrd_start) {
uint32_t initrd_end = info->initrd_start + info->initrd_size;
-
+ /* It's not documented whether these cells should honour
+ * #address-cells. Currently the kernel accepts them as being
+ * addresses of either size, so we leave them as 32 bits for now.
+ */
if((e = fdt_setprop_cell(fdt, _chosen, "linux,initrd-start",
info->initrd_start)) < 0)
goto libfdt_error;