[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