Re: [PATCH] Add limited read-only support for older (V2 and V3) device tree to libfdt.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



On Fri, Dec 29, 2017 at 10:12:04AM -0800, Nathan Whitehorn wrote:
> Has anyone had a chance to look at this? We need it, or something like it,
> to support some older firmwares with the FreeBSD kernel and I would like to
> make sure that our copy of libfdt does not diverge from upstream.

Sorry, I've been busy and haven't had a chance to look at it.  I
haven't forgotten..

> 
> Thanks,
> Nathan
> 
> On 12/07/17 22:31, Nathan Whitehorn wrote:
> > This can be useful in particular in the kernel when booting on systems
> > with FDT-emitting firmware that is out of date. Releases of kexec-tools
> > on ppc64 prior to the end of 2014 are notable examples of such.
> > 
> > Signed-off-by: Nathan Whitehorn <nwhitehorn@xxxxxxxxxxx>
> > ---
> >   fdtget.c        |  4 +--
> >   libfdt/fdt.c    |  8 ++++--
> >   libfdt/fdt_ro.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
> >   libfdt/libfdt.h |  5 +++-
> >   4 files changed, 79 insertions(+), 15 deletions(-)
> > 
> > diff --git a/fdtget.c b/fdtget.c
> > index 6cc5242..34d8194 100644
> > --- a/fdtget.c
> > +++ b/fdtget.c
> > @@ -140,7 +140,6 @@ static int show_data(struct display_info *disp, const char *data, int len)
> >    */
> >   static int list_properties(const void *blob, int node)
> >   {
> > -	const struct fdt_property *data;
> >   	const char *name;
> >   	int prop;
> > @@ -149,8 +148,7 @@ static int list_properties(const void *blob, int node)
> >   		/* Stop silently when there are no more properties */
> >   		if (prop < 0)
> >   			return prop == -FDT_ERR_NOTFOUND ? 0 : prop;
> > -		data = fdt_get_property_by_offset(blob, prop, NULL);
> > -		name = fdt_string(blob, fdt32_to_cpu(data->nameoff));
> > +		fdt_getprop_by_offset(blob, prop, &name, NULL);
> >   		if (name)
> >   			puts(name);
> >   		prop = fdt_next_property_offset(blob, prop);
> > diff --git a/libfdt/fdt.c b/libfdt/fdt.c
> > index fd13236..e783e6a 100644
> > --- a/libfdt/fdt.c
> > +++ b/libfdt/fdt.c
> > @@ -84,8 +84,9 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
> >   		return NULL;
> >   	if (fdt_version(fdt) >= 0x11)
> > -		if (((offset + len) < offset)
> > -		    || ((offset + len) > fdt_size_dt_struct(fdt)))
> > +		if (((offset + len) < offset) ||
> > +		    (fdt_version(fdt) >= 0x10 &&
> > +		     (offset + len) > fdt_size_dt_struct(fdt)))
> >   			return NULL;
> >   	return fdt_offset_ptr_(fdt, offset);
> > @@ -123,6 +124,9 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
> >   		/* skip-name offset, length and value */
> >   		offset += sizeof(struct fdt_property) - FDT_TAGSIZE
> >   			+ fdt32_to_cpu(*lenp);
> > +		if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) > 8 &&
> > +		    ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
> > +			offset += 4;
> >   		break;
> >   	case FDT_END:
> > diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
> > index ce17814..025dd0f 100644
> > --- a/libfdt/fdt_ro.c
> > +++ b/libfdt/fdt_ro.c
> > @@ -233,16 +233,26 @@ int fdt_path_offset(const void *fdt, const char *path)
> >   const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
> >   {
> >   	const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
> > +	const char *nameptr;
> >   	int err;
> >   	if (((err = fdt_check_header(fdt)) != 0)
> >   	    || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
> >   			goto fail;
> > +	nameptr = nh->name;
> > +
> > +	if (fdt_version(fdt) < 0x10) {
> > +		const char *leaf;
> > +		leaf = strrchr(nameptr, '/');
> > +		if (leaf != NULL)
> > +			nameptr = leaf+1;
> > +	}
> > +
> >   	if (len)
> > -		*len = strlen(nh->name);
> > +		*len = strlen(nameptr);
> > -	return nh->name;
> > +	return nameptr;
> >    fail:
> >   	if (len)
> > @@ -268,9 +278,9 @@ int fdt_next_property_offset(const void *fdt, int offset)
> >   	return nextprop_(fdt, offset);
> >   }
> > -const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
> > -						      int offset,
> > -						      int *lenp)
> > +static const struct fdt_property *_fdt_get_property_by_offset(const void *fdt,
> > +						              int offset,
> > +						              int *lenp)
> >   {
> >   	int err;
> >   	const struct fdt_property *prop;
> > @@ -289,11 +299,35 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
> >   	return prop;
> >   }
> > +const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
> > +						      int offset,
> > +						      int *lenp)
> > +{
> > +	/* Prior to version 16, properties may need realignment
> > +	 * and this API does not work. fdt_getprop_*() will, however. */
> > +
> > +	if (fdt_version(fdt) < 0x10) {
> > +		if (lenp)
> > +			*lenp = -FDT_ERR_BADVERSION;
> > +		return NULL;
> > +	}
> > +
> > +	return _fdt_get_property_by_offset(fdt, offset, lenp);
> > +}
> > +
> >   const struct fdt_property *fdt_get_property_namelen(const void *fdt,
> >   						    int offset,
> >   						    const char *name,
> >   						    int namelen, int *lenp)
> >   {
> > +	/* Prior to version 16, properties may need realignment
> > +	 * and this API does not work. fdt_getprop_*() will, however. */
> > +	if (fdt_version(fdt) < 0x10) {
> > +		if (lenp)
> > +			*lenp = -FDT_ERR_BADVERSION;
> > +		return NULL;
> > +	}
> > +
> >   	for (offset = fdt_first_property_offset(fdt, offset);
> >   	     (offset >= 0);
> >   	     (offset = fdt_next_property_offset(fdt, offset))) {
> > @@ -324,12 +358,33 @@ const struct fdt_property *fdt_get_property(const void *fdt,
> >   const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
> >   				const char *name, int namelen, int *lenp)
> >   {
> > -	const struct fdt_property *prop;
> > +	const struct fdt_property *prop = NULL;
> > +	int offset = nodeoffset;
> > -	prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
> > -	if (!prop)
> > +	for (offset = fdt_first_property_offset(fdt, offset);
> > +	     (offset >= 0);
> > +	     (offset = fdt_next_property_offset(fdt, offset))) {
> > +		if (!(prop = _fdt_get_property_by_offset(fdt, offset, lenp))) {
> > +			if (lenp)
> > +				*lenp = -FDT_ERR_INTERNAL;
> > +			return NULL;
> > +		}
> > +
> > +		if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
> > +				   name, namelen))
> > +			break;
> > +	}
> > +
> > +	if (lenp && offset < 0)
> > +		*lenp = offset;
> > +
> > +	if (!prop || offset < 0)
> >   		return NULL;
> > +	/* Handle realignment */
> > +	if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
> > +	    fdt32_to_cpu(prop->len) > 8)
> > +		return prop->data + 4;
> >   	return prop->data;
> >   }
> > @@ -338,11 +393,15 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
> >   {
> >   	const struct fdt_property *prop;
> > -	prop = fdt_get_property_by_offset(fdt, offset, lenp);
> > +	prop = _fdt_get_property_by_offset(fdt, offset, lenp);
> >   	if (!prop)
> >   		return NULL;
> >   	if (namep)
> >   		*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
> > +
> > +	if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
> > +	    fdt32_to_cpu(prop->len) > 8)
> > +		return prop->data + 4;
> >   	return prop->data;
> >   }
> > diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
> > index baa882c..7ac3e8a 100644
> > --- a/libfdt/libfdt.h
> > +++ b/libfdt/libfdt.h
> > @@ -54,7 +54,7 @@
> >   #include <libfdt_env.h>
> >   #include <fdt.h>
> > -#define FDT_FIRST_SUPPORTED_VERSION	0x10
> > +#define FDT_FIRST_SUPPORTED_VERSION	0x02
> >   #define FDT_LAST_SUPPORTED_VERSION	0x11
> >   /* Error codes: informative error codes */
> > @@ -526,6 +526,9 @@ int fdt_next_property_offset(const void *fdt, int offset);
> >    * fdt_property structure within the device tree blob at the given
> >    * offset.  If lenp is non-NULL, the length of the property value is
> >    * also returned, in the integer pointed to by lenp.
> > + *
> > + * Note that this code only works on device tree versions >= 16. fdt_getprop()
> > + * works on all versions.
> >    *
> >    * returns:
> >    *	pointer to the structure representing the property
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Device Tree]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux