[PATCH] ARM: zImage: Convert 32bits memory size and address from ATAG to 64bits DTB
Nicolas Pitre
nico at fluxnic.net
Tue May 14 13:08:03 EDT 2013
On Tue, 14 May 2013, Gregory CLEMENT wrote:
> When CONFIG_ARM_APPENDED_DTB is selected, if the bootloader provides
> an ATAG_MEM it replaces the memory size and the memory address in the
> memory node of the device tree. In the case of a system which can
> handle more than 4GB, the memory node cell size is 4: each data
> (memory size and memory address) are 64 bits and then use 2 cells.
>
> The current code in atags_to_fdt.c made the assumption of a cell size
> of 2 (one cell for the memory size and one cell for the memory
> address), this leads to an improper write of the data and ends with a
> boot hang.
>
> This patch writes the memory size and the memory address on the memory
> node in the device tree depending of the size of the memory node (32
> bits or 64 bits).
>
> It has been tested in the 2 cases:
> - with a dtb using skeleton.dtsi
> - and with a dtb using skeleton64.dtsi
>
> Signed-off-by: Gregory CLEMENT <gregory.clement at free-electrons.com>
Acked-by: Nicolas Pitre <nico at linaro.org>
Please send to RMK's patch system.
> ---
> arch/arm/boot/compressed/atags_to_fdt.c | 44 ++++++++++++++++++++++++++++-----
> 1 file changed, 38 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/boot/compressed/atags_to_fdt.c b/arch/arm/boot/compressed/atags_to_fdt.c
> index aabc02a..d1153c8 100644
> --- a/arch/arm/boot/compressed/atags_to_fdt.c
> +++ b/arch/arm/boot/compressed/atags_to_fdt.c
> @@ -53,6 +53,17 @@ static const void *getprop(const void *fdt, const char *node_path,
> return fdt_getprop(fdt, offset, property, len);
> }
>
> +static uint32_t get_cell_size(const void *fdt)
> +{
> + int len;
> + uint32_t cell_size = 1;
> + const uint32_t *size_len = getprop(fdt, "/", "#size-cells", &len);
> +
> + if (size_len)
> + cell_size = fdt32_to_cpu(*size_len);
> + return cell_size;
> +}
> +
> static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline)
> {
> char cmdline[COMMAND_LINE_SIZE];
> @@ -95,9 +106,11 @@ static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline)
> int atags_to_fdt(void *atag_list, void *fdt, int total_space)
> {
> struct tag *atag = atag_list;
> - uint32_t mem_reg_property[2 * NR_BANKS];
> + /* In the case of 64 bits memory size, need to reserve 2 cells for
> + * address and size for each bank */
> + uint32_t mem_reg_property[2 * 2 * NR_BANKS];
> int memcount = 0;
> - int ret;
> + int ret, memsize;
>
> /* make sure we've got an aligned pointer */
> if ((u32)atag_list & 0x3)
> @@ -137,8 +150,25 @@ int atags_to_fdt(void *atag_list, void *fdt, int total_space)
> continue;
> if (!atag->u.mem.size)
> continue;
> - mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.start);
> - mem_reg_property[memcount++] = cpu_to_fdt32(atag->u.mem.size);
> + memsize = get_cell_size(fdt);
> +
> + if (memsize == 2) {
> + /* if memsize is 2, that means that
> + * each data needs 2 cells of 32 bits,
> + * so the data are 64 bits */
> + uint64_t *mem_reg_prop64 =
> + (uint64_t *)mem_reg_property;
> + mem_reg_prop64[memcount++] =
> + cpu_to_fdt64(atag->u.mem.start);
> + mem_reg_prop64[memcount++] =
> + cpu_to_fdt64(atag->u.mem.size);
> + } else {
> + mem_reg_property[memcount++] =
> + cpu_to_fdt32(atag->u.mem.start);
> + mem_reg_property[memcount++] =
> + cpu_to_fdt32(atag->u.mem.size);
> + }
> +
> } else if (atag->hdr.tag == ATAG_INITRD2) {
> uint32_t initrd_start, initrd_size;
> initrd_start = atag->u.initrd.start;
> @@ -150,8 +180,10 @@ int atags_to_fdt(void *atag_list, void *fdt, int total_space)
> }
> }
>
> - if (memcount)
> - setprop(fdt, "/memory", "reg", mem_reg_property, 4*memcount);
> + if (memcount) {
> + setprop(fdt, "/memory", "reg", mem_reg_property,
> + 4 * memcount * memsize);
> + }
>
> return fdt_pack(fdt);
> }
> --
> 1.8.1.2
>
More information about the linux-arm-kernel
mailing list