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