libfdt: Implement fdt_get_property_namelen() and fdt_getprop_namelen()

As well as fdt_subnode_offset(), libfdt includes an
fdt_subnode_offset_namelen() function that takes the subnode name to
look up not as a NUL-terminated string, but as a string with an
explicit length.  This can be useful when the caller has the name as
part of a longer string, such as a full path.

However, we don't have corresponding 'namelen' versions for
fdt_get_property() and fdt_getprop().  There are less obvious use
cases for these variants on property names, but there are
circumstances where they can be useful e.g. looking up property names
which need to be parsed from a longer string buffer such as user input
or a configuration file, or looking up an alias in a path with
IEEE1275 style aliases.

So, since it's very easy to implement such variants, this patch does
so.  The original NUL-terminated variants are, of course, implemented
in terms of the namelen versions.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
David Gibson 2008-08-06 14:50:49 +10:00 committed by Jon Loeliger
parent 01a2d8a3e9
commit cb650ae143
2 changed files with 60 additions and 7 deletions

View file

@ -80,6 +80,14 @@ const char *fdt_string(const void *fdt, int stroffset)
return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
} }
static int _fdt_string_eq(const void *fdt, int stroffset,
const char *s, int len)
{
const char *p = fdt_string(fdt, stroffset);
return (strlen(p) == len) && (memcmp(p, s, len) == 0);
}
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{ {
FDT_CHECK_HEADER(fdt); FDT_CHECK_HEADER(fdt);
@ -175,9 +183,10 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
return NULL; return NULL;
} }
const struct fdt_property *fdt_get_property(const void *fdt, const struct fdt_property *fdt_get_property_namelen(const void *fdt,
int nodeoffset, int nodeoffset,
const char *name, int *lenp) const char *name,
int namelen, int *lenp)
{ {
uint32_t tag; uint32_t tag;
const struct fdt_property *prop; const struct fdt_property *prop;
@ -210,7 +219,7 @@ const struct fdt_property *fdt_get_property(const void *fdt,
if (! prop) if (! prop)
goto fail; goto fail;
namestroff = fdt32_to_cpu(prop->nameoff); namestroff = fdt32_to_cpu(prop->nameoff);
if (strcmp(fdt_string(fdt, namestroff), name) == 0) { if (_fdt_string_eq(fdt, namestroff, name, namelen)) {
/* Found it! */ /* Found it! */
int len = fdt32_to_cpu(prop->len); int len = fdt32_to_cpu(prop->len);
prop = fdt_offset_ptr(fdt, offset, prop = fdt_offset_ptr(fdt, offset,
@ -238,18 +247,32 @@ const struct fdt_property *fdt_get_property(const void *fdt,
return NULL; return NULL;
} }
const void *fdt_getprop(const void *fdt, int nodeoffset, const struct fdt_property *fdt_get_property(const void *fdt,
const char *name, int *lenp) int nodeoffset,
const char *name, int *lenp)
{
return fdt_get_property_namelen(fdt, nodeoffset, name,
strlen(name), lenp);
}
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;
prop = fdt_get_property(fdt, nodeoffset, name, lenp); prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
if (! prop) if (! prop)
return NULL; return NULL;
return prop->data; return prop->data;
} }
const void *fdt_getprop(const void *fdt, int nodeoffset,
const char *name, int *lenp)
{
return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
}
uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
{ {
const uint32_t *php; const uint32_t *php;

View file

@ -342,6 +342,22 @@ int fdt_path_offset(const void *fdt, const char *path);
*/ */
const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
/**
* fdt_get_property_namelen - find a property based on substring
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to find
* @name: name of the property to find
* @namelen: number of characters of name to consider
* @lenp: pointer to an integer variable (will be overwritten) or NULL
*
* Identical to fdt_get_property_namelen(), but only examine the first
* namelen characters of name for matching the property name.
*/
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
int nodeoffset,
const char *name,
int namelen, int *lenp);
/** /**
* fdt_get_property - find a given property in a given node * fdt_get_property - find a given property in a given node
* @fdt: pointer to the device tree blob * @fdt: pointer to the device tree blob
@ -379,6 +395,20 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
fdt_get_property(fdt, nodeoffset, name, lenp); fdt_get_property(fdt, nodeoffset, name, lenp);
} }
/**
* fdt_getprop_namelen - get property value based on substring
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to find
* @name: name of the property to find
* @namelen: number of characters of name to consider
* @lenp: pointer to an integer variable (will be overwritten) or NULL
*
* Identical to fdt_getprop(), but only examine the first namelen
* characters of name for matching the property name.
*/
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
const char *name, int namelen, int *lenp);
/** /**
* fdt_getprop - retrieve the value of a given property * fdt_getprop - retrieve the value of a given property
* @fdt: pointer to the device tree blob * @fdt: pointer to the device tree blob