On Tue, Mar 26, 2019 at 04:33:00PM +0100, Thierry Reding wrote: > From: Thierry Reding <treding@xxxxxxxxxx> > > The fdt_get_max_phandle() function has some shortcomings. On one hand it > returns a uint32_t phandle value via a signed return value. Uh.. no it doesn't.. > This means a > caller has to explicitly cast the return value to a uint32_t and perform > explicit checks against the error code (uint32_t)-1. In addition, the -1 > is the only error code that can be returned, so a caller cannot tell the > difference between the various failures. > > Fix this by adding a new fdt_find_max_phandle() function that returns an > error code on failure and 0 on success, just like other APIs, and stores > the maximum phandle value in an output argument on success. > > This also refactors fdt_get_max_phandle() to use the new function. Add a > note pointing out that the new fdt_find_max_phandle() function should be > preferred over fdt_get_max_phandle(). > > Signed-off-by: Thierry Reding <treding@xxxxxxxxxx> I've applied the series, but adjusted the commit message above for accuracy. I'm also planning on some followup cleanups which may change things up a bit more. > --- > Changes in v4: > - new patch > > libfdt/fdt_ro.c | 44 +++++++++++++++++++++++++++++--------------- > libfdt/libfdt.h | 16 ++++++++++++++++ > libfdt/libfdt_env.h | 1 + > libfdt/version.lds | 1 + > tests/get_phandle.c | 9 +++++++++ > 5 files changed, 56 insertions(+), 15 deletions(-) > > diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c > index eafc14282892..1d0335ee7188 100644 > --- a/libfdt/fdt_ro.c > +++ b/libfdt/fdt_ro.c > @@ -144,32 +144,46 @@ static int fdt_string_eq_(const void *fdt, int stroffset, > return p && (slen == len) && (memcmp(p, s, len) == 0); > } > > -uint32_t fdt_get_max_phandle(const void *fdt) > +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle) > { > - uint32_t max_phandle = 0; > - int offset; > + uint32_t max = 0; > + int offset = -1; > > - for (offset = fdt_next_node(fdt, -1, NULL);; > - offset = fdt_next_node(fdt, offset, NULL)) { > - uint32_t phandle; > + while (true) { > + uint32_t value; > > - if (offset == -FDT_ERR_NOTFOUND) > - return max_phandle; > + offset = fdt_next_node(fdt, offset, NULL); > + if (offset < 0) { > + if (offset == -FDT_ERR_NOTFOUND) > + break; > > - if (offset < 0) > - return (uint32_t)-1; > + return offset; > + } > > - phandle = fdt_get_phandle(fdt, offset); > - if (phandle == (uint32_t)-1) > - continue; > + value = fdt_get_phandle(fdt, offset); > > - if (phandle > max_phandle) > - max_phandle = phandle; > + if (value > max) > + max = value; > } > > + if (phandle) > + *phandle = max; > + > return 0; > } > > +uint32_t fdt_get_max_phandle(const void *fdt) > +{ > + uint32_t phandle; > + int err; > + > + err = fdt_find_max_phandle(fdt, &phandle); > + if (err < 0) > + return (uint32_t)-1; > + > + return phandle; > +} > + > static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) > { > int offset = n * sizeof(struct fdt_reserve_entry); > diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h > index a470d1df6d2a..6fce659fd279 100644 > --- a/libfdt/libfdt.h > +++ b/libfdt/libfdt.h > @@ -361,6 +361,20 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); > */ > const char *fdt_string(const void *fdt, int stroffset); > > +/** > + * fdt_find_max_phandle - find and return the highest phandle in a tree > + * @fdt: pointer to the device tree blob > + * @phandle: return location for the highest phandle value found in the tree > + * > + * fdt_find_max_phandle() finds the highest phandle value in the given device > + * tree. The value returned in @phandle is only valid if the function returns > + * success. > + * > + * returns: > + * 0 on success or a negative error code on failure > + */ > +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle); > + > /** > * fdt_get_max_phandle - retrieves the highest phandle in a tree > * @fdt: pointer to the device tree blob > @@ -369,6 +383,8 @@ const char *fdt_string(const void *fdt, int stroffset); > * device tree. This will ignore badly formatted phandles, or phandles > * with a value of 0 or -1. > * > + * This function is deprecated in favour of fdt_find_max_phandle(). > + * > * returns: > * the highest phandle on success > * 0, if no phandle was found in the device tree > diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h > index eb2053845c9c..4d1cdfa58547 100644 > --- a/libfdt/libfdt_env.h > +++ b/libfdt/libfdt_env.h > @@ -52,6 +52,7 @@ > * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > */ > > +#include <stdbool.h> > #include <stddef.h> > #include <stdint.h> > #include <stdlib.h> > diff --git a/libfdt/version.lds b/libfdt/version.lds > index a5fe62d5c5ff..87bbb2fe54d3 100644 > --- a/libfdt/version.lds > +++ b/libfdt/version.lds > @@ -66,6 +66,7 @@ LIBFDT_1.2 { > fdt_resize; > fdt_overlay_apply; > fdt_get_string; > + fdt_find_max_phandle; > fdt_get_max_phandle; > fdt_check_full; > fdt_setprop_placeholder; > diff --git a/tests/get_phandle.c b/tests/get_phandle.c > index 22bd7b81b3f0..6973ee4caa17 100644 > --- a/tests/get_phandle.c > +++ b/tests/get_phandle.c > @@ -46,6 +46,7 @@ int main(int argc, char *argv[]) > { > uint32_t max; > void *fdt; > + int err; > > test_init(argc, argv); > fdt = load_blob_arg(argc, argv); > @@ -54,6 +55,14 @@ int main(int argc, char *argv[]) > check_phandle(fdt, "/subnode@2", PHANDLE_1); > check_phandle(fdt, "/subnode@2/subsubnode@0", PHANDLE_2); > > + err = fdt_find_max_phandle(fdt, &max); > + if (err < 0) > + FAIL("fdt_find_max_phandle returned %d instead of 0\n", err); > + > + if (max != PHANDLE_2) > + FAIL("fdt_find_max_phandle found 0x%x instead of 0x%x", max, > + PHANDLE_2); > + > max = fdt_get_max_phandle(fdt); > if (max != PHANDLE_2) > FAIL("fdt_get_max_phandle returned 0x%x instead of 0x%x\n", -- 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