[U-Boot] [PATCH - resend due to bounce] libfdt: Add fdt functionality for more intuitive
Peter Feuerer
peter.feuerer at sysgo.com
Mon May 7 15:52:36 CEST 2012
libfdt: Add fdt functionality for more intuitive fdt handling
New functions:
fdt_read - retrieve the value of a property by full path
fdt_write - create or change a property with full path and create subnodes if needed
fdt_create_path - create subnode path with parents
Signed-off-by: Peter Feuerer <peter.feuerer at sysgo.com>
CC: David Gibson <david at gibson.dropbear.id.au>
CC: Gerald Van Baren <gvb at unssw.com>
---
include/libfdt.h | 93 ++++++++++++++++++++++++++++++++++++++++
lib/libfdt/fdt_ro.c | 30 +++++++++++++
lib/libfdt/fdt_rw.c | 97 ++++++++++++++++++++++++++++++++++++++++++
lib/libfdt/libfdt_internal.h | 4 ++
4 files changed, 224 insertions(+), 0 deletions(-)
diff --git a/include/libfdt.h b/include/libfdt.h
index de82ed5..822ab18 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -548,6 +548,37 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
}
/**
+ * fdt_read - retrieve the value of a property by full path
+ * @fdt: pointer to the device tree blob
+ * @path: string containing the absolute path of the property
+ * @name: name of the property
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop() retrieves a pointer to the value of the property
+ * named 'name' of the node at offset nodeoffset (this will be a
+ * pointer to within the device blob itself, not a copy of the value).
+ * If lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ * pointer to the property's value
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_NOTFOUND, node does not have named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADPATH,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_read(const void *fdt, const char *path,
+ const char *name, int *lenp);
+
+/**
* fdt_get_phandle - retrieve the phandle of a given node
* @fdt: pointer to the device tree blob
* @nodeoffset: structure block offset of the node
@@ -1066,6 +1097,38 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name);
*/
int fdt_setprop(void *fdt, int nodeoffset, const char *name,
const void *val, int len);
+/**
+ * fdt_write - create or change a property with full path and create
+ * all subnodes to the property if needed
+ * @fdt: pointer to the device tree blob
+ * @path: string containing the absolute path of the property
+ * @name: name of the property to change
+ * @val: pointer to data to set the property value to
+ * @len: length of the property value
+ *
+ * fdt_write() sets the value of the named property in the given
+ * node to the given value and length, creating the property if it
+ * does not already exist. Additionally it creates all parent nodes if
+ * not yet existing.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_write(void *fdt, const char *path, const char *name,
+ const void *val, int len);
/**
* fdt_setprop_cell - set a property to a single cell value
@@ -1204,6 +1267,36 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
/**
+ * fdt_create_path - create subnode path with parents
+ * @fdt: pointer to the device tree blob
+ * @path: absolute path of subnodes to create
+ *
+ * fdt_create_path() creates absolute subnode path with all needed
+ * parents, if they don't exist.
+ *
+ * This function will insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * structure block offset of the created nodeequested subnode (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
+ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
+ * the given name
+ * -FDT_ERR_NOSPACE, if there is insufficient free space in the
+ * blob to contain the new node
+ * -FDT_ERR_NOSPACE,
+ * -FDT_ERR_BADPATH,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_create_path(struct fdt_header *fdt, const char *path);
+
+/**
* fdt_del_node - delete a node (subtree)
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node to nop
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 1933010..9a08200 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -324,6 +324,36 @@ const void *fdt_getprop(const void *fdt, int nodeoffset,
return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
}
+const void *fdt_read(const void *fdt, const char *path,
+ const char *name, int *lenp)
+{
+ int nodeoffset;
+ int len;
+ const void *nodep ;
+
+ if (fdt_check_header(fdt) != 0) {
+ if (lenp)
+ *lenp = -FDT_ERR_BADSTRUCTURE;
+ return NULL;
+ }
+
+ nodeoffset = fdt_path_offset(fdt, path);
+
+ if (nodeoffset < 0) {
+ if (lenp)
+ *lenp = -FDT_ERR_BADPATH;
+ return NULL;
+ } else {
+ nodep = fdt_getprop(fdt, nodeoffset, name, &len);
+ if (len <= 0)
+ return NULL;
+ if (lenp)
+ *lenp = len;
+ }
+ return nodep;
+}
+
+
uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
{
const uint32_t *php;
diff --git a/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c
index 5c27a67..ccebafb 100644
--- a/lib/libfdt/fdt_rw.c
+++ b/lib/libfdt/fdt_rw.c
@@ -293,6 +293,21 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
return 0;
}
+int fdt_write(void *fdt, const char *path, const char *name,
+ const void *val, int len)
+{
+ int nodeoffset;
+
+ FDT_CHECK_HEADER(fdt);
+
+ nodeoffset = fdt_create_path(fdt, path);
+
+ if (nodeoffset < 0)
+ return nodeoffset;
+
+ return fdt_setprop(fdt, nodeoffset, name, val, len);
+}
+
int fdt_delprop(void *fdt, int nodeoffset, const char *name)
{
struct fdt_property *prop;
@@ -354,6 +369,88 @@ int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
}
+int fdt_create_path_internal(struct fdt_header *fdt, char *path)
+{
+ int offset = 0;
+ char *p = NULL;
+ char *last_slash = NULL;
+ char *path2 = path;
+ int ret = 0;
+
+ /* search for last slash */
+ for (p = path; *p != 0; ++p)
+ if (*p == '/')
+ last_slash = p;
+
+ /* if path ends with "/" then, error */
+ if (*(last_slash + 1) == 0)
+ return -FDT_ERR_BADPATH;
+
+ /*
+ * if last_slash is root, use "/" instead of string
+ * otherwise terminate string at slash
+ */
+ if (last_slash == path)
+ path2 = "/";
+ else
+ *last_slash = 0;
+
+ /*
+ * test if the parent path is valid, if not valid,
+ * recursively add paths
+ */
+ offset = fdt_path_offset(fdt, path2);
+ if (offset == -FDT_ERR_NOTFOUND)
+ offset = fdt_create_path_internal(fdt, path2);
+
+ if (offset < 0)
+ return offset;
+
+ /* path valid, create subnode */
+ ret = fdt_add_subnode(fdt, offset, last_slash + 1);
+
+ /* undo termination */
+ if (last_slash && last_slash != path)
+ *last_slash = '/';
+
+ return ret;
+}
+
+int fdt_create_path(struct fdt_header *fdt, const char *path)
+{
+ int offset = 0;
+ int ret = 0;
+ int size = 0;
+#ifndef FDT_USE_MALLOC
+ char path_mem[FDT_MAX_PATHLEN] = {0};
+ size = FDT_MAX_PATHLEN;
+#else
+ char *path_mem;
+ size = strlen(path);
+ path_mem = calloc(size, 1);
+ if (!path_mem)
+ return -FDT_ERR_NOSPACE;
+#endif
+
+ /* if full path already exists, return the offset */
+ offset = fdt_path_offset(fdt, path);
+ if (offset >= 0) {
+ ret = offset;
+ goto end;
+ }
+
+ /* copy path to local path variable, so that we can modify it */
+ strncpy(path_mem, path, size - 1);
+
+ ret = fdt_create_path_internal(fdt, path_mem);
+end:
+#ifdef FDT_USE_MALLOC
+ free(path_mem);
+#endif
+ return ret;
+
+}
+
int fdt_del_node(void *fdt, int nodeoffset)
{
int endoffset;
diff --git a/lib/libfdt/libfdt_internal.h b/lib/libfdt/libfdt_internal.h
index 381133b..786a052 100644
--- a/lib/libfdt/libfdt_internal.h
+++ b/lib/libfdt/libfdt_internal.h
@@ -55,6 +55,10 @@
#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
+#ifndef FDT_USE_MALLOC
+#define FDT_MAX_PATHLEN 2048
+#endif
+
#define FDT_CHECK_HEADER(fdt) \
{ \
int err; \
--
1.7.3
More information about the U-Boot
mailing list