From ac2a1030e3aba3deba7f5c3f6d3c4faf6e9506f8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 29 Mar 2016 20:18:45 +0900 Subject: ARM: uniphier: adjust dram_init() and dram_init_banksize() for ARM64 Currently, these functions assume #address-cells and #size-cells are both one. Fix them to support 64bit DTB. Also, I am fixing a buffer overrun bug while I am here. The array size of gd->bd->bd_dram is CONFIG_NR_DRAM_BANKS. The number of iteration in the loop should be limited by that CONFIG. Signed-off-by: Masahiro Yamada --- arch/arm/mach-uniphier/dram_init.c | 45 +++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 10 deletions(-) (limited to 'arch/arm/mach-uniphier') diff --git a/arch/arm/mach-uniphier/dram_init.c b/arch/arm/mach-uniphier/dram_init.c index cffdfc9841..815f2433f3 100644 --- a/arch/arm/mach-uniphier/dram_init.c +++ b/arch/arm/mach-uniphier/dram_init.c @@ -23,14 +23,25 @@ static const void *get_memory_reg_prop(const void *fdt, int *lenp) int dram_init(void) { + const void *fdt = gd->fdt_blob; const fdt32_t *val; - int len; + int ac, sc, len; - val = get_memory_reg_prop(gd->fdt_blob, &len); - if (len < sizeof(*val)) + ac = fdt_address_cells(fdt, 0); + sc = fdt_size_cells(fdt, 0); + if (ac < 0 || sc < 1 || sc > 2) { + printf("invalid address/size cells\n"); return -EINVAL; + } + + val = get_memory_reg_prop(fdt, &len); + if (len / sizeof(*val) < ac + sc) + return -EINVAL; + + val += ac; - gd->ram_size = fdt32_to_cpu(*(val + 1)); + gd->ram_size = sc == 2 ? fdt64_to_cpu(*(fdt64_t *)val) : + fdt32_to_cpu(*val); debug("DRAM size = %08lx\n", (unsigned long)gd->ram_size); @@ -39,19 +50,33 @@ int dram_init(void) void dram_init_banksize(void) { + const void *fdt = gd->fdt_blob; const fdt32_t *val; - int len, i; + int ac, sc, cells, len, i; - val = get_memory_reg_prop(gd->fdt_blob, &len); + val = get_memory_reg_prop(fdt, &len); if (len < 0) return; + ac = fdt_address_cells(fdt, 0); + sc = fdt_size_cells(fdt, 0); + if (ac < 1 || sc > 2 || sc < 1 || sc > 2) { + printf("invalid address/size cells\n"); + return; + } + + cells = ac + sc; + len /= sizeof(*val); - len /= 2; - for (i = 0; i < len; i++) { - gd->bd->bi_dram[i].start = fdt32_to_cpu(*val++); - gd->bd->bi_dram[i].size = fdt32_to_cpu(*val++); + for (i = 0; i < CONFIG_NR_DRAM_BANKS && len >= cells; + i++, len -= cells) { + gd->bd->bi_dram[i].start = ac == 2 ? + fdt64_to_cpu(*(fdt64_t *)val) : fdt32_to_cpu(*val); + val += ac; + gd->bd->bi_dram[i].size = sc == 2 ? + fdt64_to_cpu(*(fdt64_t *)val) : fdt32_to_cpu(*val); + val += sc; debug("DRAM bank %d: start = %08lx, size = %08lx\n", i, (unsigned long)gd->bd->bi_dram[i].start, -- cgit v1.2.1