[U-Boot] cmd/fdt: support single value replacement within an array

Laurent Pinchart laurent.pinchart at ideasonboard.com
Fri Aug 4 21:23:19 UTC 2017


Hi Hannes,

(I'm not subscribed to the list, please keep me CC'ed on replies)

On Tuesday 30 May 2017 13:05:00 Hannes Schmelzer wrote:
> With this commit we can modify single values within an array of a dts
> property.

But with this commit U-Boot crashes if you try to create a new property with 
the fdt set command :-/

I've tested v2017.07 with the commit reverted, and fdt set works again for me. 
The issue is that your fdt_getprop() call fails and return NULL with len set 
to -1. You can easily imagine what the memcpy() following it will do.

> This is useful if we have for example a pwm-backlight where we want to
> modifiy the pwm frequency per u-boot script.
> 
> The pwm is described in dts like this:
> 
> backlight {
> 	pwms = <0x0000002b 0x00000000 0x004c4b40>;
> };
> 
> For changing the frequency, here the 3rd parameter, we simply type:
> 
> fdt set /backlight pwms <? ? 0x1E8480>;
> 
> For doing all this we:
> - backup the property content into our 'SCRATCHPAD'
> - only modify the array-cell if the new content doesn't start with '?'
> 
> Signed-off-by: Hannes Schmelzer <hannes.schmelzer at br-automation.com>
> 
> ---
> 
>  cmd/fdt.c | 29 +++++++++++++++++++++--------
>  1 file changed, 21 insertions(+), 8 deletions(-)
> 
> diff --git a/cmd/fdt.c b/cmd/fdt.c
> index a21415d..e55102a 100644
> --- a/cmd/fdt.c
> +++ b/cmd/fdt.c
> @@ -257,6 +257,7 @@  static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc,
> char * const argv[])> 
>  		char *prop;		/* property */
>  		int  nodeoffset;	/* node offset from libfdt */
>  		static char data[SCRATCHPAD];	/* storage for the property */
> +		const void *ptmp;
>  		int  len;		/* new length of the property */
>  		int  ret;		/* return value */
> 
> @@ -268,13 +269,6 @@  static int do_fdt(cmd_tbl_t *cmdtp, int flag, int
> argc, char * const argv[])> 
>  		pathp  = argv[2];
>  		prop   = argv[3];
> 
> -		if (argc == 4) {
> -			len = 0;
> -		} else {
> -			ret = fdt_parse_prop(&argv[4], argc - 4, data, &len);
> -			if (ret != 0)
> -				return ret;
> -		}
> 
>  		nodeoffset = fdt_path_offset (working_fdt, pathp);
>  		if (nodeoffset < 0) {
> @@ -286,6 +280,21 @@  static int do_fdt(cmd_tbl_t *cmdtp, int flag, int
> argc, char * const argv[])
>  			return 1;
>  		}
> 
> +		if (argc == 4) {
> +			len = 0;
> +		} else {
> +			ptmp = fdt_getprop(working_fdt, nodeoffset, prop,
> &len);
> +			if (len > SCRATCHPAD) {
> +				printf("prop (%d) doesn't fit in scratchpad!
> \n",
> +				       len);
> +				return 1;
> +			}
> +			memcpy(data, ptmp, len);
> +			ret = fdt_parse_prop(&argv[4], argc - 4, data, &len);
> +			if (ret != 0)
> +				return ret;
> +		}
> +
>  		ret = fdt_setprop(working_fdt, nodeoffset, prop, data, len);
>  		if (ret < 0) {
>  			printf ("libfdt fdt_setprop(): %s\n",
> fdt_strerror(ret));
> @@ -766,7 +775,11 @@  static int fdt_parse_prop(char * const *newval, int
> count, char *data, int *len)
>  			cp = newp;
>  			tmp = simple_strtoul(cp, &newp, 0);
> 
> -			*(fdt32_t *)data = cpu_to_fdt32(tmp);
> +			if (*cp != '?')
> +				*(fdt32_t *)data = cpu_to_fdt32(tmp);
> +			else
> +				newp++;
> +
> 
>  			data  += 4;
>  			*len += 4;
-- 
Regards,

Laurent Pinchart



More information about the U-Boot mailing list