@ -58,9 +58,10 @@
static int fdt_nodename_eq_(const void *fdt, int offset,
static int fdt_nodename_eq_(const void *fdt, int offset,
const char *s, int len)
const char *s, int len)
{
{
const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
int olen;
const char *p = fdt_get_name(fdt, offset, &olen);
if (!p)
if (!p || olen < len)
/* short match */
/* short match */
return 0;
return 0;
@ -233,16 +234,34 @@ int fdt_path_offset(const void *fdt, const char *path)
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
{
{
const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
const char *nameptr;
int err;
int err;
if (((err = fdt_check_header(fdt)) != 0)
if (((err = fdt_check_header(fdt)) != 0)
|| ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
|| ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
goto fail;
goto fail;
nameptr = nh->name;
if (fdt_version(fdt) < 0x10) {
/*
* For old FDT versions, match the naming conventions of V16:
* give only the leaf name (after all /). The actual tree
* contents are loosely checked.
*/
const char *leaf;
leaf = strrchr(nameptr, '/');
if (leaf == NULL) {
err = -FDT_ERR_BADSTRUCTURE;
goto fail;
}
nameptr = leaf+1;
}
if (len)
if (len)
*len = strlen(nh->name);
*len = strlen(nameptr);
return nh->name;
return nameptr;
fail:
fail:
if (len)
if (len)
@ -268,9 +287,9 @@ int fdt_next_property_offset(const void *fdt, int offset)
return nextprop_(fdt, offset);
return nextprop_(fdt, offset);
}
}
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
int offset,
int offset,
int *lenp)
int *lenp)
{
{
int err;
int err;
const struct fdt_property *prop;
const struct fdt_property *prop;
@ -289,23 +308,44 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
return prop;
return prop;
}
}
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
int offset,
int offset,
const char *name,
int *lenp)
int namelen, int *lenp)
{
/* Prior to version 16, properties may need realignment
* and this API does not work. fdt_getprop_*() will, however. */
if (fdt_version(fdt) < 0x10) {
if (lenp)
*lenp = -FDT_ERR_BADVERSION;
return NULL;
}
return fdt_get_property_by_offset_(fdt, offset, lenp);
}
static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
int offset,
const char *name,
int namelen,
int *lenp,
int *poffset)
{
{
for (offset = fdt_first_property_offset(fdt, offset);
for (offset = fdt_first_property_offset(fdt, offset);
(offset >= 0);
(offset >= 0);
(offset = fdt_next_property_offset(fdt, offset))) {
(offset = fdt_next_property_offset(fdt, offset))) {
const struct fdt_property *prop;
const struct fdt_property *prop;
if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
offset = -FDT_ERR_INTERNAL;
offset = -FDT_ERR_INTERNAL;
break;
break;
}
}
if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
name, namelen))
name, namelen)) {
if (poffset)
*poffset = offset;
return prop;
return prop;
}
}
}
if (lenp)
if (lenp)
@ -313,6 +353,25 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
return NULL;
return NULL;
}
}
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
int offset,
const char *name,
int namelen, int *lenp)
{
/* Prior to version 16, properties may need realignment
* and this API does not work. fdt_getprop_*() will, however. */
if (fdt_version(fdt) < 0x10) {
if (lenp)
*lenp = -FDT_ERR_BADVERSION;
return NULL;
}
return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
NULL);
}
const struct fdt_property *fdt_get_property(const void *fdt,
const struct fdt_property *fdt_get_property(const void *fdt,
int nodeoffset,
int nodeoffset,
const char *name, int *lenp)
const char *name, int *lenp)
@ -324,12 +383,18 @@ const struct fdt_property *fdt_get_property(const void *fdt,
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
const char *name, int namelen, int *lenp)
const char *name, int namelen, int *lenp)
{
{
int poffset;
const struct fdt_property *prop;
const struct fdt_property *prop;
prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
&poffset);
if (!prop)
if (!prop)
return NULL;
return NULL;
/* Handle realignment */
if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
fdt32_to_cpu(prop->len) >= 8)
return prop->data + 4;
return prop->data;
return prop->data;
}
}
@ -338,11 +403,16 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
{
{
const struct fdt_property *prop;
const struct fdt_property *prop;
prop = fdt_get_property_by_offset(fdt, offset, lenp);
prop = fdt_get_property_by_offset_(fdt, offset, lenp);
if (!prop)
if (!prop)
return NULL;
return NULL;
if (namep)
if (namep)
*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
/* Handle realignment */
if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
fdt32_to_cpu(prop->len) >= 8)
return prop->data + 4;
return prop->data;
return prop->data;
}
}