Re: [PATCH v3 1/2] libfdt: Introduce fdt_create_with_flags()

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



On Mon, May 06, 2019 at 08:13:58PM +1000, Nicholas Piggin wrote:
> There is a need to be able to specify some options when building an FDT
> with the SW interface. This can be accomplished with minimal changes by
> storing intermediate data in the fdt header itself, in fields that are
> not otherwise needed during the creation process and can be set by
> fdt_finish().
> 
> The fdt.magic field is already used exactly this way, as a state to
> check with callers that the FDT has been created but not yet finished.
> 
> fdt.version and fdt.last_comp_version are used to make room for more
> intermediate state. These are adjacent and unused during the building
> process. last_comp_version is not yet used for intermediate state, but
> it is zeroed and treated as used, so as to allow future growth easily.
> 
> A new interface, fdt_create_with_flags() is added, which takes 32-bit
> flag value to control creation.
> 
> Signed-off-by: Nicholas Piggin <npiggin@xxxxxxxxx>

Reviewed-by: David Gibson <david@xxxxxxxxxxxxxxxxxxxxx>

> ---
> v3:
> - re-name flag from _FAST to _NO_NAME_DEDUP
> - added strerror
> 
>  libfdt/fdt_strerror.c |  1 +
>  libfdt/fdt_sw.c       | 30 ++++++++++++++++++++++++++++--
>  libfdt/libfdt.h       | 38 +++++++++++++++++++++++++++++++++++++-
>  libfdt/version.lds    |  1 +
>  4 files changed, 67 insertions(+), 3 deletions(-)
> 
> diff --git a/libfdt/fdt_strerror.c b/libfdt/fdt_strerror.c
> index 9677a18..0e6b4fd 100644
> --- a/libfdt/fdt_strerror.c
> +++ b/libfdt/fdt_strerror.c
> @@ -82,6 +82,7 @@ static struct fdt_errtabent fdt_errtable[] = {
>  	FDT_ERRTABENT(FDT_ERR_BADVALUE),
>  	FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
>  	FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
> +	FDT_ERRTABENT(FDT_ERR_BADFLAGS),
>  };
>  #define FDT_ERRTABSIZE	(sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
>  
> diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c
> index 9fa4a94..5811dc1 100644
> --- a/libfdt/fdt_sw.c
> +++ b/libfdt/fdt_sw.c
> @@ -121,6 +121,12 @@ static int fdt_sw_probe_struct_(void *fdt)
>  			return err; \
>  	}
>  
> +static inline uint32_t sw_flags(void *fdt)
> +{
> +	/* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
> +	return fdt_last_comp_version(fdt);
> +}
> +
>  /* 'complete' state:	Enter this state after fdt_finish()
>   *
>   * Allowed functions: none
> @@ -141,7 +147,7 @@ static void *fdt_grab_space_(void *fdt, size_t len)
>  	return fdt_offset_ptr_w_(fdt, offset);
>  }
>  
> -int fdt_create(void *buf, int bufsize)
> +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
>  {
>  	const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
>  					 sizeof(struct fdt_reserve_entry));
> @@ -150,11 +156,22 @@ int fdt_create(void *buf, int bufsize)
>  	if (bufsize < hdrsize)
>  		return -FDT_ERR_NOSPACE;
>  
> +	if (flags & ~FDT_CREATE_FLAGS_ALL)
> +		return -FDT_ERR_BADFLAGS;
> +
>  	memset(buf, 0, bufsize);
>  
> +	/*
> +	 * magic and last_comp_version keep intermediate state during the fdt
> +	 * creation process, which is replaced with the proper FDT format by
> +	 * fdt_finish().
> +	 *
> +	 * flags should be accessed with sw_flags().
> +	 */
>  	fdt_set_magic(fdt, FDT_SW_MAGIC);
>  	fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
> -	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
> +	fdt_set_last_comp_version(fdt, flags);
> +
>  	fdt_set_totalsize(fdt,  bufsize);
>  
>  	fdt_set_off_mem_rsvmap(fdt, hdrsize);
> @@ -164,6 +181,11 @@ int fdt_create(void *buf, int bufsize)
>  	return 0;
>  }
>  
> +int fdt_create(void *buf, int bufsize)
> +{
> +	return fdt_create_with_flags(buf, bufsize, 0);
> +}
> +
>  int fdt_resize(void *fdt, void *buf, int bufsize)
>  {
>  	size_t headsize, tailsize;
> @@ -360,6 +382,10 @@ int fdt_finish(void *fdt)
>  
>  	/* Finally, adjust the header */
>  	fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
> +
> +	/* And fix up fields that were keeping intermediate state. */
> +	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
>  	fdt_set_magic(fdt, FDT_MAGIC);
> +
>  	return 0;
>  }
> diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
> index 1f44177..c2dee3e 100644
> --- a/libfdt/libfdt.h
> +++ b/libfdt/libfdt.h
> @@ -138,7 +138,11 @@
>  	/* FDT_ERR_NOPHANDLES: The device tree doesn't have any
>  	 * phandle available anymore without causing an overflow */
>  
> -#define FDT_ERR_MAX		17
> +#define FDT_ERR_BADFLAGS	18
> +	/* FDT_ERR_BADFLAGS: The function was passed a flags field that
> +	 * contains invalid flags or an invalid combination of flags. */
> +
> +#define FDT_ERR_MAX		18
>  
>  /* constants */
>  #define FDT_MAX_PHANDLE 0xfffffffe
> @@ -1429,7 +1433,39 @@ int fdt_nop_node(void *fdt, int nodeoffset);
>  /* Sequential write functions                                         */
>  /**********************************************************************/
>  
> +#define FDT_CREATE_FLAGS_ALL	0
> +
> +/**
> + * fdt_create_with_flags - begin creation of a new fdt
> + * @fdt: pointer to memory allocated where fdt will be created
> + * @bufsize: size of the memory space at fdt
> + * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
> + *
> + * fdt_create_with_flags() begins the process of creating a new fdt with
> + * the sequential write interface.
> + *
> + * fdt creation process must end with fdt_finished() to produce a valid fdt.
> + *
> + * returns:
> + *	0, on success
> + *	-FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
> + *	-FDT_ERR_BADFLAGS, flags is not valid
> + */
> +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
> +
> +/**
> + * fdt_create - begin creation of a new fdt
> + * @fdt: pointer to memory allocated where fdt will be created
> + * @bufsize: size of the memory space at fdt
> + *
> + * fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
> + *
> + * returns:
> + *	0, on success
> + *	-FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
> + */
>  int fdt_create(void *buf, int bufsize);
> +
>  int fdt_resize(void *fdt, void *buf, int bufsize);
>  int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
>  int fdt_finish_reservemap(void *fdt);
> diff --git a/libfdt/version.lds b/libfdt/version.lds
> index 9a92652..0d52217 100644
> --- a/libfdt/version.lds
> +++ b/libfdt/version.lds
> @@ -74,6 +74,7 @@ LIBFDT_1.2 {
>  		fdt_header_size_;
>  		fdt_appendprop_addrrange;
>  		fdt_setprop_inplace_namelen_partial;
> +		fdt_create_with_flags;
>  	local:
>  		*;
>  };

-- 
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