fdt_support: fix an endian bug of fdt_fixup_memory_banks

Data written to DTB must be converted to big endian order.
It is usually done by using cpu_to_fdt32(), cpu_to_fdt64(), etc.

fdt_fixup_memory_banks() invoked write_cell(), which always
swaps byte order.
It means the function only worked on little endian architectures.

This commit adds and uses a new helper function, fdt_pack_reg(),
which works on both big endian and little endian architrectures.

Signed-off-by: Masahiro Yamada <yamada.m@jp.panasonic.com>
Acked-by: Simon Glass <sjg@chromium.org>
master
Masahiro Yamada 11 years ago committed by Tom Rini
parent f89d482fe5
commit 739a01ed8e
  1. 42
      common/fdt_support.c

@ -380,6 +380,34 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat,
do_fixup_by_compat(fdt, compat, prop, &tmp, 4, create); do_fixup_by_compat(fdt, compat, prop, &tmp, 4, create);
} }
/*
* fdt_pack_reg - pack address and size array into the "reg"-suitable stream
*/
static int fdt_pack_reg(const void *fdt, void *buf, uint64_t *address,
uint64_t *size, int n)
{
int i;
int address_len = get_cells_len(fdt, "#address-cells");
int size_len = get_cells_len(fdt, "#size-cells");
char *p = buf;
for (i = 0; i < n; i++) {
if (address_len == 8)
*(fdt64_t *)p = cpu_to_fdt64(address[i]);
else
*(fdt32_t *)p = cpu_to_fdt32(address[i]);
p += address_len;
if (size_len == 8)
*(fdt64_t *)p = cpu_to_fdt64(size[i]);
else
*(fdt32_t *)p = cpu_to_fdt32(size[i]);
p += size_len;
}
return p - (char *)buf;
}
#ifdef CONFIG_NR_DRAM_BANKS #ifdef CONFIG_NR_DRAM_BANKS
#define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS #define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS
#else #else
@ -388,9 +416,8 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat,
int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks) int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
{ {
int err, nodeoffset; int err, nodeoffset;
int addr_cell_len, size_cell_len, len; int len;
u8 tmp[MEMORY_BANKS_MAX * 16]; /* Up to 64-bit address + 64-bit size */ u8 tmp[MEMORY_BANKS_MAX * 16]; /* Up to 64-bit address + 64-bit size */
int bank;
if (banks > MEMORY_BANKS_MAX) { if (banks > MEMORY_BANKS_MAX) {
printf("%s: num banks %d exceeds hardcoded limit %d." printf("%s: num banks %d exceeds hardcoded limit %d."
@ -418,16 +445,7 @@ int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
return err; return err;
} }
addr_cell_len = get_cells_len(blob, "#address-cells"); len = fdt_pack_reg(blob, tmp, start, size, banks);
size_cell_len = get_cells_len(blob, "#size-cells");
for (bank = 0, len = 0; bank < banks; bank++) {
write_cell(tmp + len, start[bank], addr_cell_len);
len += addr_cell_len;
write_cell(tmp + len, size[bank], size_cell_len);
len += size_cell_len;
}
err = fdt_setprop(blob, nodeoffset, "reg", tmp, len); err = fdt_setprop(blob, nodeoffset, "reg", tmp, len);
if (err < 0) { if (err < 0) {

Loading…
Cancel
Save