libfdt: Add new maximum phandle lookup function

The fdt_get_max_phandle() function has some shortcomings. On one hand
it returns just a uint32_t which means to check for the "negative"
error code a caller has to explicitly check 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@nvidia.com>
Message-Id: <20190326153302.17109-1-thierry.reding@gmail.com>
[dwg: Reword for some inaccuracies in the commit message]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
main
Thierry Reding 2019-03-26 16:33:00 +01:00 committed by David Gibson
parent 7fcf8208b8
commit 2bc5b66d7f
5 changed files with 56 additions and 15 deletions

View File

@ -144,32 +144,46 @@ static int fdt_string_eq_(const void *fdt, int stroffset,
return p && (slen == len) && (memcmp(p, s, len) == 0); 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; uint32_t max = 0;
int offset; int offset = -1;


for (offset = fdt_next_node(fdt, -1, NULL);; while (true) {
offset = fdt_next_node(fdt, offset, NULL)) { uint32_t value;
uint32_t phandle;


if (offset == -FDT_ERR_NOTFOUND) offset = fdt_next_node(fdt, offset, NULL);
return max_phandle; if (offset < 0) {
if (offset == -FDT_ERR_NOTFOUND)
break;


if (offset < 0) return offset;
return (uint32_t)-1; }


phandle = fdt_get_phandle(fdt, offset); value = fdt_get_phandle(fdt, offset);
if (phandle == (uint32_t)-1)
continue;


if (phandle > max_phandle) if (value > max)
max_phandle = phandle; max = value;
} }


if (phandle)
*phandle = max;

return 0; 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) static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
{ {
int offset = n * sizeof(struct fdt_reserve_entry); int offset = n * sizeof(struct fdt_reserve_entry);

View File

@ -385,6 +385,20 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
*/ */
const char *fdt_string(const void *fdt, int stroffset); 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_get_max_phandle - retrieves the highest phandle in a tree
* @fdt: pointer to the device tree blob * @fdt: pointer to the device tree blob
@ -393,6 +407,8 @@ const char *fdt_string(const void *fdt, int stroffset);
* device tree. This will ignore badly formatted phandles, or phandles * device tree. This will ignore badly formatted phandles, or phandles
* with a value of 0 or -1. * with a value of 0 or -1.
* *
* This function is deprecated in favour of fdt_find_max_phandle().
*
* returns: * returns:
* the highest phandle on success * the highest phandle on success
* 0, if no phandle was found in the device tree * 0, if no phandle was found in the device tree

View File

@ -52,6 +52,7 @@
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */


#include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>

View File

@ -66,6 +66,7 @@ LIBFDT_1.2 {
fdt_resize; fdt_resize;
fdt_overlay_apply; fdt_overlay_apply;
fdt_get_string; fdt_get_string;
fdt_find_max_phandle;
fdt_get_max_phandle; fdt_get_max_phandle;
fdt_check_full; fdt_check_full;
fdt_setprop_placeholder; fdt_setprop_placeholder;

View File

@ -46,6 +46,7 @@ int main(int argc, char *argv[])
{ {
uint32_t max; uint32_t max;
void *fdt; void *fdt;
int err;


test_init(argc, argv); test_init(argc, argv);
fdt = load_blob_arg(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", PHANDLE_1);
check_phandle(fdt, "/subnode@2/subsubnode@0", PHANDLE_2); 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); max = fdt_get_max_phandle(fdt);
if (max != PHANDLE_2) if (max != PHANDLE_2)
FAIL("fdt_get_max_phandle returned 0x%x instead of 0x%x\n", FAIL("fdt_get_max_phandle returned 0x%x instead of 0x%x\n",