All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
To: nwhitehorn-h+KGxgPPiopAfugRpC6u6w@public.gmane.org
Cc: devicetree-compiler-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH v2] Add limited read-only support for older (V2 and V3) device tree to libfdt.
Date: Thu, 18 Jan 2018 15:59:03 +1100	[thread overview]
Message-ID: <20180118045903.GL30352@umbus.fritz.box> (raw)
In-Reply-To: <20171231022858.10834-1-nwhitehorn-h+KGxgPPiopAfugRpC6u6w@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 9648 bytes --]

On Sat, Dec 30, 2017 at 06:28:58PM -0800, nwhitehorn-h+KGxgPPiopAfugRpC6u6w@public.gmane.org wrote:
> From: Nathan Whitehorn <nwhitehorn-h+KGxgPPiopAfugRpC6u6w@public.gmane.org>
> 
> This can be useful in particular in the kernel when booting on systems
> with FDT-emitting firmware that is out of date.

Hrm, really, *really* out of date.  V2 and V3 are positively ancient.

> Releases of kexec-tools
> on ppc64 prior to the end of 2014 are notable examples of such.

Good grief, that's ridiculous.  They were also using dts-v0 years and
years after it should have been gotten rid of.


Anyway that said, the changes below don't look too bad.  There's a few
nits, but in principle I'd be ok to apply

> 
> Signed-off-by: Nathan Whitehorn <nwhitehorn-h+KGxgPPiopAfugRpC6u6w@public.gmane.org>
> ---
> 
> This fixes some minor bugs in the original version of the patch with name
> matching and properties that were exactly 8 bytes long. Tested and running
> (though uncommitted for now, to prevent divergence from upstream) in the
> FreeBSD kernel.
> 
>  fdtget.c        |  4 +--
>  libfdt/fdt.c    |  8 ++++--
>  libfdt/fdt_ro.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++--------
>  libfdt/libfdt.h |  5 +++-
>  4 files changed, 87 insertions(+), 17 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..b1cc253 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 &&

This doesn't make sense - you're already guarded by an fdt_version > 0x11
above.

> +		     (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..d011bd3 100644
> --- a/libfdt/fdt_ro.c
> +++ b/libfdt/fdt_ro.c
> @@ -58,9 +58,10 @@
>  static int fdt_nodename_eq_(const void *fdt, int offset,
>  			    const char *s, int len)
>  {
> -	const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
> +	int olen;
> +	const char *p = fdt_get_name(fdt, offset, &olen);
>  
> -	if (!p)
> +	if (!p || olen < len)
>  		/* short match */
>  		return 0;
>  
> @@ -233,16 +234,31 @@ 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 && nodeoffset != 0) {
> +		/*
> +		 * For old FDT versions, match the naming conventions of V16:
> +		 * give only the leaf name (after all /) except for the 
> +		 * root node, where we should still return / rather than ""

What's the rationale for returning "/" rather than "" on the root
node?  a V16 file will return "", typically.

> +		 */
> +		const char *leaf;
> +		leaf = strrchr(nameptr, '/');
> +		if (leaf != NULL)
> +			nameptr = leaf+1;

If leaf is NULL (no '/') I think that indicates a badly formed V3 or
less tree, the full path should already have at least one /.

> +	}
> +
>  	if (len)
> -		*len = strlen(nh->name);
> +		*len = strlen(nameptr);
>  
> -	return nh->name;
> +	return nameptr;
>  
>   fail:
>  	if (len)
> @@ -268,9 +284,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)

I've been trying to get rid of symbols starting with _ since they're
technically reserved for the system and can cause problems in some
compilation environments.  Go to alternative is ending with a _ instead.

>  {
>  	int err;
>  	const struct fdt_property *prop;
> @@ -289,11 +305,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 +364,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);

Couldn't you use an fdt_get_property_namelen_() here instead of having
to duplicate most of its logic.

> -	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 +399,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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  parent reply	other threads:[~2018-01-18  4:59 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-08  6:31 [PATCH] Add limited read-only support for older (V2 and V3) device tree to libfdt Nathan Whitehorn
     [not found] ` <20171208063149.76523-1-nwhitehorn-h+KGxgPPiopAfugRpC6u6w@public.gmane.org>
2017-12-29 18:12   ` Nathan Whitehorn
     [not found]     ` <9c383dc9-c8c2-2b65-b527-ffc9b922b7dc-h+KGxgPPiopAfugRpC6u6w@public.gmane.org>
2018-01-03  0:40       ` David Gibson
     [not found]         ` <20180103004027.GI24581-K0bRW+63XPQe6aEkudXLsA@public.gmane.org>
2018-01-08 18:33           ` Nathan Whitehorn
2017-12-31  2:28   ` [PATCH v2] " nwhitehorn-h+KGxgPPiopAfugRpC6u6w
     [not found]     ` <20171231022858.10834-1-nwhitehorn-h+KGxgPPiopAfugRpC6u6w@public.gmane.org>
2018-01-18  4:59       ` David Gibson [this message]
     [not found]         ` <20180118045903.GL30352-K0bRW+63XPQe6aEkudXLsA@public.gmane.org>
2018-01-18 20:41           ` Nathan Whitehorn
     [not found]             ` <cfa9f549-b63b-3642-32ab-a2e21898d16e-h+KGxgPPiopAfugRpC6u6w@public.gmane.org>
2018-01-18 23:25               ` David Gibson
     [not found]                 ` <20180118232519.GW30352-K0bRW+63XPQe6aEkudXLsA@public.gmane.org>
2018-01-19 22:01                   ` Nathan Whitehorn
2018-01-19 21:48   ` [PATCH v3] " nwhitehorn-h+KGxgPPiopAfugRpC6u6w
     [not found]     ` <20180119214803.24934-1-nwhitehorn-h+KGxgPPiopAfugRpC6u6w@public.gmane.org>
2018-01-21  9:40       ` David Gibson
2018-01-22 19:16         ` Nathan Whitehorn
2018-01-25  5:13   ` [PATCH v4] " nwhitehorn-h+KGxgPPiopAfugRpC6u6w
     [not found]     ` <20180125051340.22391-1-nwhitehorn-h+KGxgPPiopAfugRpC6u6w@public.gmane.org>
2018-01-27  7:46       ` David Gibson
2018-01-30  1:05         ` Nathan Whitehorn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180118045903.GL30352@umbus.fritz.box \
    --to=david-xt8fgy+axnrb3ne2bgzf6laj5h9x9tb+@public.gmane.org \
    --cc=devicetree-compiler-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=nwhitehorn-h+KGxgPPiopAfugRpC6u6w@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.