Browse Source

fdt: Add functions to retrieve strings

Given a device tree node, a property name and an index, the new function
fdt_stringlist_get() will return a pointer to the index'th string in the
property's value and return its length (or an error code on failure) in
an output argument.

Signed-off-by: Thierry Reding <treding@nvidia.com>
[Fix some -Wshadow warnings --dwg]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
main
Thierry Reding 9 years ago committed by David Gibson
parent
commit
604e61e081
  1. 45
      libfdt/fdt_ro.c
  2. 28
      libfdt/libfdt.h
  3. 32
      tests/stringlist.c

45
libfdt/fdt_ro.c

@ -593,6 +593,51 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, @@ -593,6 +593,51 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
return -FDT_ERR_NOTFOUND;
}

const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
const char *property, int idx,
int *lenp)
{
const char *list, *end;
int length;

list = fdt_getprop(fdt, nodeoffset, property, &length);
if (!list) {
if (lenp)
*lenp = length;

return NULL;
}

end = list + length;

while (list < end) {
length = strnlen(list, end - list) + 1;

/* Abort if the last string isn't properly NUL-terminated. */
if (list + length > end) {
if (lenp)
*lenp = -FDT_ERR_BADVALUE;

return NULL;
}

if (idx == 0) {
if (lenp)
*lenp = length - 1;

return list;
}

list += length;
idx--;
}

if (lenp)
*lenp = -FDT_ERR_NOTFOUND;

return NULL;
}

int fdt_node_check_compatible(const void *fdt, int nodeoffset,
const char *compatible)
{

28
libfdt/libfdt.h

@ -907,6 +907,34 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); @@ -907,6 +907,34 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
const char *string);

/**
* fdt_stringlist_get() - obtain the string at a given index in a string list
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @property: name of the property containing the string list
* @index: index of the string to return
* @lenp: return location for the string length or an error code on failure
*
* Note that this will successfully extract strings from properties with
* non-NUL-terminated values. For example on small-valued cell properties
* this function will return the empty string.
*
* If non-NULL, the length of the string (on success) or a negative error-code
* (on failure) will be stored in the integer pointer to by lenp.
*
* @return:
* A pointer to the string at the given index in the string list or NULL on
* failure. On success the length of the string will be stored in the memory
* location pointed to by the lenp parameter, if non-NULL. On failure one of
* the following negative error codes will be returned in the lenp parameter
* (if non-NULL):
* -FDT_ERR_BADVALUE if the property value is not NUL-terminated
* -FDT_ERR_NOTFOUND if the property does not exist
*/
const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
const char *property, int index,
int *lenp);

/**********************************************************************/
/* Read-only functions (addressing related) */
/**********************************************************************/

32
tests/stringlist.c

@ -58,6 +58,13 @@ static void check_expected_failure(const void *fdt, const char *path, @@ -58,6 +58,13 @@ static void check_expected_failure(const void *fdt, const char *path,
err = fdt_stringlist_search(fdt, offset, "#address-cells", "");
if (err != 0)
FAIL("empty string not found in #address-cells: %d\n", err);

/*
* fdt_get_string() can successfully extract strings from non-string
* properties. This is because it doesn't necessarily parse the whole
* property value, which would be necessary for it to determine if a
* valid string or string list is present.
*/
}

static void check_string_count(const void *fdt, const char *path,
@ -96,6 +103,27 @@ static void check_string_index(const void *fdt, const char *path, @@ -96,6 +103,27 @@ static void check_string_index(const void *fdt, const char *path,
string, property, path, err, idx);
}

static void check_string(const void *fdt, const char *path,
const char *property, int idx,
const char *string)
{
const char *result;
int offset, len;

offset = fdt_path_offset(fdt, path);
if (offset < 0)
FAIL("Couldn't find path %s", path);

result = fdt_stringlist_get(fdt, offset, property, idx, &len);
if (!result)
FAIL("Couldn't extract string %d from property %s of node %s: %d\n",
idx, property, path, len);

if (strcmp(string, result) != 0)
FAIL("String %d in property %s of node %s is %s, expected %s\n",
idx, property, path, result, string);
}

int main(int argc, char *argv[])
{
void *fdt;
@ -118,5 +146,9 @@ int main(int argc, char *argv[]) @@ -118,5 +146,9 @@ int main(int argc, char *argv[])
check_string_index(fdt, "/device", "compatible", "bar", 1);
check_string_index(fdt, "/device", "big-endian", "baz", -1);

check_string(fdt, "/", "compatible", 0, "test-strings");
check_string(fdt, "/device", "compatible", 0, "foo");
check_string(fdt, "/device", "compatible", 1, "bar");

PASS();
}

Loading…
Cancel
Save