]> git.proxmox.com Git - mirror_edk2.git/commitdiff
EmbeddedPkg/FdtLib: Update FdtLib to v1.4.5
authorPankaj Bansal <pankaj.bansal@nxp.com>
Fri, 5 Jan 2018 11:17:37 +0000 (16:47 +0530)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Fri, 5 Jan 2018 12:03:27 +0000 (12:03 +0000)
Update the FdtLib so that new APIs provided by FdtLib like
fdt_address_cells, fdt_size_cells etc. can be used.

Reference code:
https://git.kernel.org/pub/scm/utils/dtc/dtc.git/tree/libfdt?h=v1.4.5

Cc: Leif Lindholm <leif.lindholm@linaro.org>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com>
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
14 files changed:
EmbeddedPkg/Include/libfdt.h
EmbeddedPkg/Include/libfdt_env.h
EmbeddedPkg/Library/FdtLib/FdtLib.inf
EmbeddedPkg/Library/FdtLib/Makefile.libfdt
EmbeddedPkg/Library/FdtLib/fdt.c
EmbeddedPkg/Library/FdtLib/fdt_addresses.c [new file with mode: 0644]
EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c
EmbeddedPkg/Library/FdtLib/fdt_ro.c
EmbeddedPkg/Library/FdtLib/fdt_rw.c
EmbeddedPkg/Library/FdtLib/fdt_strerror.c
EmbeddedPkg/Library/FdtLib/fdt_sw.c
EmbeddedPkg/Library/FdtLib/fdt_wip.c
EmbeddedPkg/Library/FdtLib/libfdt_internal.h
EmbeddedPkg/Library/FdtLib/version.lds

index 212cb995dfb30d366251285740f60f977111543c..1aabec37f665a0d03d5437f21c8ddd1010e93816 100644 (file)
@@ -61,7 +61,7 @@
 #define FDT_ERR_NOTFOUND       1\r
        /* FDT_ERR_NOTFOUND: The requested node or property does not exist */\r
 #define FDT_ERR_EXISTS         2\r
-       /* FDT_ERR_EXISTS: Attemped to create a node or property which\r
+       /* FDT_ERR_EXISTS: Attempted to create a node or property which\r
         * already exists */\r
 #define FDT_ERR_NOSPACE                3\r
        /* FDT_ERR_NOSPACE: Operation needed to expand the device\r
         * (e.g. missing a leading / for a function which requires an\r
         * absolute path) */\r
 #define FDT_ERR_BADPHANDLE     6\r
-       /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle\r
-        * value.  phandle values of 0 and -1 are not permitted. */\r
+       /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle.\r
+        * This can be caused either by an invalid phandle property\r
+        * length, or the phandle value was either 0 or -1, which are\r
+        * not permitted. */\r
 #define FDT_ERR_BADSTATE       7\r
        /* FDT_ERR_BADSTATE: Function was passed an incomplete device\r
         * tree created by the sequential-write functions, which is\r
         * Should never be returned, if it is, it indicates a bug in\r
         * libfdt itself. */\r
 \r
-#define FDT_ERR_MAX            13\r
+/* Errors in device tree content */\r
+#define FDT_ERR_BADNCELLS      14\r
+       /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells\r
+        * or similar property with a bad format or value */\r
+\r
+#define FDT_ERR_BADVALUE       15\r
+       /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected\r
+        * value. For example: a property expected to contain a string list\r
+        * is not NUL-terminated within the length of its value. */\r
+\r
+#define FDT_ERR_BADOVERLAY     16\r
+       /* FDT_ERR_BADOVERLAY: The device tree overlay, while\r
+        * correctly structured, cannot be applied due to some\r
+        * unexpected or missing value, property or node. */\r
+\r
+#define FDT_ERR_NOPHANDLES     17\r
+       /* FDT_ERR_NOPHANDLES: The device tree doesn't have any\r
+        * phandle available anymore without causing an overflow */\r
+\r
+#define FDT_ERR_MAX            17\r
 \r
 /**********************************************************************/\r
 /* Low-level functions (you probably don't need these)                */\r
 /**********************************************************************/\r
 \r
+#ifndef SWIG /* This function is not useful in Python */\r
 const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);\r
+#endif\r
 static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)\r
 {\r
        return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);\r
@@ -158,27 +181,54 @@ int fdt_first_subnode(const void *fdt, int offset);
  */\r
 int fdt_next_subnode(const void *fdt, int offset);\r
 \r
+/**\r
+ * fdt_for_each_subnode - iterate over all subnodes of a parent\r
+ *\r
+ * @node:      child node (int, lvalue)\r
+ * @fdt:       FDT blob (const void *)\r
+ * @parent:    parent node (int)\r
+ *\r
+ * This is actually a wrapper around a for loop and would be used like so:\r
+ *\r
+ *     fdt_for_each_subnode(node, fdt, parent) {\r
+ *             Use node\r
+ *             ...\r
+ *     }\r
+ *\r
+ *     if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) {\r
+ *             Error handling\r
+ *     }\r
+ *\r
+ * Note that this is implemented as a macro and @node is used as\r
+ * iterator in the loop. The parent variable be constant or even a\r
+ * literal.\r
+ *\r
+ */\r
+#define fdt_for_each_subnode(node, fdt, parent)                \\r
+       for (node = fdt_first_subnode(fdt, parent);     \\r
+            node >= 0;                                 \\r
+            node = fdt_next_subnode(fdt, node))\r
+\r
 /**********************************************************************/\r
 /* General functions                                                  */\r
 /**********************************************************************/\r
-\r
 #define fdt_get_header(fdt, field) \\r
        (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))\r
-#define fdt_magic(fdt)                         (fdt_get_header(fdt, magic))\r
+#define fdt_magic(fdt)                 (fdt_get_header(fdt, magic))\r
 #define fdt_totalsize(fdt)             (fdt_get_header(fdt, totalsize))\r
 #define fdt_off_dt_struct(fdt)         (fdt_get_header(fdt, off_dt_struct))\r
 #define fdt_off_dt_strings(fdt)                (fdt_get_header(fdt, off_dt_strings))\r
 #define fdt_off_mem_rsvmap(fdt)                (fdt_get_header(fdt, off_mem_rsvmap))\r
 #define fdt_version(fdt)               (fdt_get_header(fdt, version))\r
-#define fdt_last_comp_version(fdt)     (fdt_get_header(fdt, last_comp_version))\r
-#define fdt_boot_cpuid_phys(fdt)       (fdt_get_header(fdt, boot_cpuid_phys))\r
-#define fdt_size_dt_strings(fdt)       (fdt_get_header(fdt, size_dt_strings))\r
+#define fdt_last_comp_version(fdt)     (fdt_get_header(fdt, last_comp_version))\r
+#define fdt_boot_cpuid_phys(fdt)       (fdt_get_header(fdt, boot_cpuid_phys))\r
+#define fdt_size_dt_strings(fdt)       (fdt_get_header(fdt, size_dt_strings))\r
 #define fdt_size_dt_struct(fdt)                (fdt_get_header(fdt, size_dt_struct))\r
 \r
 #define __fdt_set_hdr(name) \\r
        static inline void fdt_set_##name(void *fdt, uint32_t val) \\r
        { \\r
-               struct fdt_header *fdth = (struct fdt_header*)fdt; \\r
+               struct fdt_header *fdth = (struct fdt_header *)fdt; \\r
                fdth->name = cpu_to_fdt32(val); \\r
        }\r
 __fdt_set_hdr(magic);\r
@@ -248,6 +298,21 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
  */\r
 const char *fdt_string(const void *fdt, int stroffset);\r
 \r
+/**\r
+ * fdt_get_max_phandle - retrieves the highest phandle in a tree\r
+ * @fdt: pointer to the device tree blob\r
+ *\r
+ * fdt_get_max_phandle retrieves the highest phandle in the given\r
+ * device tree. This will ignore badly formatted phandles, or phandles\r
+ * with a value of 0 or -1.\r
+ *\r
+ * returns:\r
+ *      the highest phandle on success\r
+ *      0, if no phandle was found in the device tree\r
+ *      -1, if an error occurred\r
+ */\r
+uint32_t fdt_get_max_phandle(const void *fdt);\r
+\r
 /**\r
  * fdt_num_mem_rsv - retrieve the number of memory reserve map entries\r
  * @fdt: pointer to the device tree blob\r
@@ -290,8 +355,10 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
  * useful for finding subnodes based on a portion of a larger string,\r
  * such as a full path.\r
  */\r
+#ifndef SWIG /* Not available in Python */\r
 int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,\r
                               const char *name, int namelen);\r
+#endif\r
 /**\r
  * fdt_subnode_offset - find a subnode of a given node\r
  * @fdt: pointer to the device tree blob\r
@@ -308,8 +375,9 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
  * returns:\r
  *     structure block offset of the requested subnode (>=0), on success\r
  *     -FDT_ERR_NOTFOUND, if the requested subnode does not exist\r
- *     -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag\r
- *      -FDT_ERR_BADMAGIC,\r
+ *     -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE\r
+ *             tag\r
+ *     -FDT_ERR_BADMAGIC,\r
  *     -FDT_ERR_BADVERSION,\r
  *     -FDT_ERR_BADSTATE,\r
  *     -FDT_ERR_BADSTRUCTURE,\r
@@ -317,6 +385,19 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
  */\r
 int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);\r
 \r
+/**\r
+ * fdt_path_offset_namelen - find a tree node by its full path\r
+ * @fdt: pointer to the device tree blob\r
+ * @path: full path of the node to locate\r
+ * @namelen: number of characters of path to consider\r
+ *\r
+ * Identical to fdt_path_offset(), but only consider the first namelen\r
+ * characters of path as the path name.\r
+ */\r
+#ifndef SWIG /* Not available in Python */\r
+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);\r
+#endif\r
+\r
 /**\r
  * fdt_path_offset - find a tree node by its full path\r
  * @fdt: pointer to the device tree blob\r
@@ -330,7 +411,8 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
  * address).\r
  *\r
  * returns:\r
- *     structure block offset of the node with the requested path (>=0), on success\r
+ *     structure block offset of the node with the requested path (>=0), on\r
+ *             success\r
  *     -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid\r
  *     -FDT_ERR_NOTFOUND, if the requested node does not exist\r
  *      -FDT_ERR_BADMAGIC,\r
@@ -354,10 +436,12 @@ int fdt_path_offset(const void *fdt, const char *path);
  *\r
  * returns:\r
  *     pointer to the node's name, on success\r
- *             If lenp is non-NULL, *lenp contains the length of that name (>=0)\r
+ *             If lenp is non-NULL, *lenp contains the length of that name\r
+ *                     (>=0)\r
  *     NULL, on error\r
  *             if lenp is non-NULL *lenp contains an error code (<0):\r
- *             -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag\r
+ *             -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE\r
+ *                     tag\r
  *             -FDT_ERR_BADMAGIC,\r
  *             -FDT_ERR_BADVERSION,\r
  *             -FDT_ERR_BADSTATE, standard meanings\r
@@ -405,6 +489,33 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset);
  */\r
 int fdt_next_property_offset(const void *fdt, int offset);\r
 \r
+/**\r
+ * fdt_for_each_property_offset - iterate over all properties of a node\r
+ *\r
+ * @property_offset:   property offset (int, lvalue)\r
+ * @fdt:               FDT blob (const void *)\r
+ * @node:              node offset (int)\r
+ *\r
+ * This is actually a wrapper around a for loop and would be used like so:\r
+ *\r
+ *     fdt_for_each_property_offset(property, fdt, node) {\r
+ *             Use property\r
+ *             ...\r
+ *     }\r
+ *\r
+ *     if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) {\r
+ *             Error handling\r
+ *     }\r
+ *\r
+ * Note that this is implemented as a macro and property is used as\r
+ * iterator in the loop. The node variable can be constant or even a\r
+ * literal.\r
+ */\r
+#define fdt_for_each_property_offset(property, fdt, node)      \\r
+       for (property = fdt_first_property_offset(fdt, node);   \\r
+            property >= 0;                                     \\r
+            property = fdt_next_property_offset(fdt, property))\r
+\r
 /**\r
  * fdt_get_property_by_offset - retrieve the property at a given offset\r
  * @fdt: pointer to the device tree blob\r
@@ -441,13 +552,15 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
  * @namelen: number of characters of name to consider\r
  * @lenp: pointer to an integer variable (will be overwritten) or NULL\r
  *\r
- * Identical to fdt_get_property_namelen(), but only examine the first\r
- * namelen characters of name for matching the property name.\r
+ * Identical to fdt_get_property(), but only examine the first namelen\r
+ * characters of name for matching the property name.\r
  */\r
+#ifndef SWIG /* Not available in Python */\r
 const struct fdt_property *fdt_get_property_namelen(const void *fdt,\r
                                                    int nodeoffset,\r
                                                    const char *name,\r
                                                    int namelen, int *lenp);\r
+#endif\r
 \r
 /**\r
  * fdt_get_property - find a given property in a given node\r
@@ -469,7 +582,8 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
  *     NULL, on error\r
  *             if lenp is non-NULL, *lenp contains an error code (<0):\r
  *             -FDT_ERR_NOTFOUND, node does not have named property\r
- *             -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag\r
+ *             -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE\r
+ *                     tag\r
  *             -FDT_ERR_BADMAGIC,\r
  *             -FDT_ERR_BADVERSION,\r
  *             -FDT_ERR_BADSTATE,\r
@@ -517,8 +631,10 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
  *             -FDT_ERR_BADSTRUCTURE,\r
  *             -FDT_ERR_TRUNCATED, standard meanings\r
  */\r
+#ifndef SWIG /* This function is not useful in Python */\r
 const void *fdt_getprop_by_offset(const void *fdt, int offset,\r
                                  const char **namep, int *lenp);\r
+#endif\r
 \r
 /**\r
  * fdt_getprop_namelen - get property value based on substring\r
@@ -531,8 +647,17 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
  * Identical to fdt_getprop(), but only examine the first namelen\r
  * characters of name for matching the property name.\r
  */\r
+#ifndef SWIG /* Not available in Python */\r
 const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,\r
                                const char *name, int namelen, int *lenp);\r
+static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,\r
+                                         const char *name, int namelen,\r
+                                         int *lenp)\r
+{\r
+       return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,\r
+                                                     namelen, lenp);\r
+}\r
+#endif\r
 \r
 /**\r
  * fdt_getprop - retrieve the value of a given property\r
@@ -554,7 +679,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
  *     NULL, on error\r
  *             if lenp is non-NULL, *lenp contains an error code (<0):\r
  *             -FDT_ERR_NOTFOUND, node does not have named property\r
- *             -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag\r
+ *             -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE\r
+ *                     tag\r
  *             -FDT_ERR_BADMAGIC,\r
  *             -FDT_ERR_BADVERSION,\r
  *             -FDT_ERR_BADSTATE,\r
@@ -592,11 +718,13 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
  * Identical to fdt_get_alias(), but only examine the first namelen\r
  * characters of name for matching the alias name.\r
  */\r
+#ifndef SWIG /* Not available in Python */\r
 const char *fdt_get_alias_namelen(const void *fdt,\r
                                  const char *name, int namelen);\r
+#endif\r
 \r
 /**\r
- * fdt_get_alias - retreive the path referenced by a given alias\r
+ * fdt_get_alias - retrieve the path referenced by a given alias\r
  * @fdt: pointer to the device tree blob\r
  * @name: name of the alias th look up\r
  *\r
@@ -626,7 +754,7 @@ const char *fdt_get_alias(const void *fdt, const char *name);
  *     0, on success\r
  *             buf contains the absolute path of the node at\r
  *             nodeoffset, as a NUL-terminated string.\r
- *     -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag\r
+ *     -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag\r
  *     -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)\r
  *             characters and will not fit in the given buffer.\r
  *     -FDT_ERR_BADMAGIC,\r
@@ -656,11 +784,11 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
  * structure from the start to nodeoffset.\r
  *\r
  * returns:\r
-\r
  *     structure block offset of the node at node offset's ancestor\r
  *             of depth supernodedepth (>=0), on success\r
- *     -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag\r
-*      -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset\r
+ *     -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag\r
+ *     -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of\r
+ *             nodeoffset\r
  *     -FDT_ERR_BADMAGIC,\r
  *     -FDT_ERR_BADVERSION,\r
  *     -FDT_ERR_BADSTATE,\r
@@ -682,7 +810,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
  *\r
  * returns:\r
  *     depth of the node at nodeoffset (>=0), on success\r
- *     -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag\r
+ *     -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag\r
  *     -FDT_ERR_BADMAGIC,\r
  *     -FDT_ERR_BADVERSION,\r
  *     -FDT_ERR_BADSTATE,\r
@@ -705,7 +833,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset);
  * returns:\r
  *     structure block offset of the parent of the node at nodeoffset\r
  *             (>=0), on success\r
- *     -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag\r
+ *     -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag\r
  *     -FDT_ERR_BADMAGIC,\r
  *     -FDT_ERR_BADVERSION,\r
  *     -FDT_ERR_BADSTATE,\r
@@ -745,7 +873,7 @@ int fdt_parent_offset(const void *fdt, int nodeoffset);
  *              on success\r
  *     -FDT_ERR_NOTFOUND, no node matching the criterion exists in the\r
  *             tree after startoffset\r
- *     -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag\r
+ *     -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag\r
  *     -FDT_ERR_BADMAGIC,\r
  *     -FDT_ERR_BADVERSION,\r
  *     -FDT_ERR_BADSTATE,\r
@@ -792,7 +920,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
  *     1, if the node has a 'compatible' property, but it does not list\r
  *             the given string\r
  *     -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property\r
- *     -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag\r
+ *     -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag\r
  *     -FDT_ERR_BADMAGIC,\r
  *     -FDT_ERR_BADVERSION,\r
  *     -FDT_ERR_BADSTATE,\r
@@ -829,7 +957,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
  *              on success\r
  *     -FDT_ERR_NOTFOUND, no node matching the criterion exists in the\r
  *             tree after startoffset\r
- *     -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag\r
+ *     -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag\r
  *     -FDT_ERR_BADMAGIC,\r
  *     -FDT_ERR_BADVERSION,\r
  *     -FDT_ERR_BADSTATE,\r
@@ -852,10 +980,152 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
  */\r
 int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);\r
 \r
+/**\r
+ * fdt_stringlist_count - count the number of strings in a string list\r
+ * @fdt: pointer to the device tree blob\r
+ * @nodeoffset: offset of a tree node\r
+ * @property: name of the property containing the string list\r
+ * @return:\r
+ *   the number of strings in the given property\r
+ *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated\r
+ *   -FDT_ERR_NOTFOUND if the property does not exist\r
+ */\r
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);\r
+\r
+/**\r
+ * fdt_stringlist_search - find a string in a string list and return its index\r
+ * @fdt: pointer to the device tree blob\r
+ * @nodeoffset: offset of a tree node\r
+ * @property: name of the property containing the string list\r
+ * @string: string to look up in the string list\r
+ *\r
+ * Note that it is possible for this function to succeed on property values\r
+ * that are not NUL-terminated. That's because the function will stop after\r
+ * finding the first occurrence of @string. This can for example happen with\r
+ * small-valued cell properties, such as #address-cells, when searching for\r
+ * the empty string.\r
+ *\r
+ * @return:\r
+ *   the index of the string in the list of strings\r
+ *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated\r
+ *   -FDT_ERR_NOTFOUND if the property does not exist or does not contain\r
+ *                     the given string\r
+ */\r
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,\r
+                         const char *string);\r
+\r
+/**\r
+ * fdt_stringlist_get() - obtain the string at a given index in a string list\r
+ * @fdt: pointer to the device tree blob\r
+ * @nodeoffset: offset of a tree node\r
+ * @property: name of the property containing the string list\r
+ * @index: index of the string to return\r
+ * @lenp: return location for the string length or an error code on failure\r
+ *\r
+ * Note that this will successfully extract strings from properties with\r
+ * non-NUL-terminated values. For example on small-valued cell properties\r
+ * this function will return the empty string.\r
+ *\r
+ * If non-NULL, the length of the string (on success) or a negative error-code\r
+ * (on failure) will be stored in the integer pointer to by lenp.\r
+ *\r
+ * @return:\r
+ *   A pointer to the string at the given index in the string list or NULL on\r
+ *   failure. On success the length of the string will be stored in the memory\r
+ *   location pointed to by the lenp parameter, if non-NULL. On failure one of\r
+ *   the following negative error codes will be returned in the lenp parameter\r
+ *   (if non-NULL):\r
+ *     -FDT_ERR_BADVALUE if the property value is not NUL-terminated\r
+ *     -FDT_ERR_NOTFOUND if the property does not exist\r
+ */\r
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,\r
+                              const char *property, int index,\r
+                              int *lenp);\r
+\r
+/**********************************************************************/\r
+/* Read-only functions (addressing related)                           */\r
+/**********************************************************************/\r
+\r
+/**\r
+ * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells\r
+ *\r
+ * This is the maximum value for #address-cells, #size-cells and\r
+ * similar properties that will be processed by libfdt.  IEE1275\r
+ * requires that OF implementations handle values up to 4.\r
+ * Implementations may support larger values, but in practice higher\r
+ * values aren't used.\r
+ */\r
+#define FDT_MAX_NCELLS         4\r
+\r
+/**\r
+ * fdt_address_cells - retrieve address size for a bus represented in the tree\r
+ * @fdt: pointer to the device tree blob\r
+ * @nodeoffset: offset of the node to find the address size for\r
+ *\r
+ * When the node has a valid #address-cells property, returns its value.\r
+ *\r
+ * returns:\r
+ *     0 <= n < FDT_MAX_NCELLS, on success\r
+ *      2, if the node has no #address-cells property\r
+ *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid\r
+ *             #address-cells property\r
+ *     -FDT_ERR_BADMAGIC,\r
+ *     -FDT_ERR_BADVERSION,\r
+ *     -FDT_ERR_BADSTATE,\r
+ *     -FDT_ERR_BADSTRUCTURE,\r
+ *     -FDT_ERR_TRUNCATED, standard meanings\r
+ */\r
+int fdt_address_cells(const void *fdt, int nodeoffset);\r
+\r
+/**\r
+ * fdt_size_cells - retrieve address range size for a bus represented in the\r
+ *                  tree\r
+ * @fdt: pointer to the device tree blob\r
+ * @nodeoffset: offset of the node to find the address range size for\r
+ *\r
+ * When the node has a valid #size-cells property, returns its value.\r
+ *\r
+ * returns:\r
+ *     0 <= n < FDT_MAX_NCELLS, on success\r
+ *      2, if the node has no #address-cells property\r
+ *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid\r
+ *             #size-cells property\r
+ *     -FDT_ERR_BADMAGIC,\r
+ *     -FDT_ERR_BADVERSION,\r
+ *     -FDT_ERR_BADSTATE,\r
+ *     -FDT_ERR_BADSTRUCTURE,\r
+ *     -FDT_ERR_TRUNCATED, standard meanings\r
+ */\r
+int fdt_size_cells(const void *fdt, int nodeoffset);\r
+\r
+\r
 /**********************************************************************/\r
 /* Write-in-place functions                                           */\r
 /**********************************************************************/\r
 \r
+/**\r
+ * fdt_setprop_inplace_namelen_partial - change a property's value,\r
+ *                                       but not its size\r
+ * @fdt: pointer to the device tree blob\r
+ * @nodeoffset: offset of the node whose property to change\r
+ * @name: name of the property to change\r
+ * @namelen: number of characters of name to consider\r
+ * @idx: index of the property to change in the array\r
+ * @val: pointer to data to replace the property value with\r
+ * @len: length of the property value\r
+ *\r
+ * Identical to fdt_setprop_inplace(), but modifies the given property\r
+ * starting from the given index, and using only the first characters\r
+ * of the name. It is useful when you want to manipulate only one value of\r
+ * an array and you have a string that doesn't end with \0.\r
+ */\r
+#ifndef SWIG /* Not available in Python */\r
+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,\r
+                                       const char *name, int namelen,\r
+                                       uint32_t idx, const void *val,\r
+                                       int len);\r
+#endif\r
+\r
 /**\r
  * fdt_setprop_inplace - change a property's value, but not its size\r
  * @fdt: pointer to the device tree blob\r
@@ -884,8 +1154,10 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
  *     -FDT_ERR_BADSTRUCTURE,\r
  *     -FDT_ERR_TRUNCATED, standard meanings\r
  */\r
+#ifndef SWIG /* Not available in Python */\r
 int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,\r
                        const void *val, int len);\r
+#endif\r
 \r
 /**\r
  * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property\r
@@ -1023,6 +1295,7 @@ int fdt_nop_node(void *fdt, int nodeoffset);
 /**********************************************************************/\r
 \r
 int fdt_create(void *buf, int bufsize);\r
+int fdt_resize(void *fdt, void *buf, int bufsize);\r
 int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);\r
 int fdt_finish_reservemap(void *fdt);\r
 int fdt_begin_node(void *fdt, const char *name);\r
@@ -1041,6 +1314,22 @@ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
 {\r
        return fdt_property_u32(fdt, name, val);\r
 }\r
+\r
+/**\r
+ * fdt_property_placeholder - add a new property and return a ptr to its value\r
+ *\r
+ * @fdt: pointer to the device tree blob\r
+ * @name: name of property to add\r
+ * @len: length of property value in bytes\r
+ * @valp: returns a pointer to where where the value should be placed\r
+ *\r
+ * returns:\r
+ *     0, on success\r
+ *     -FDT_ERR_BADMAGIC,\r
+ *     -FDT_ERR_NOSPACE, standard meanings\r
+ */\r
+int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp);\r
+\r
 #define fdt_property_string(fdt, name, str) \\r
        fdt_property(fdt, name, str, strlen(str)+1)\r
 int fdt_end_node(void *fdt);\r
@@ -1159,6 +1448,37 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name);
 int fdt_setprop(void *fdt, int nodeoffset, const char *name,\r
                const void *val, int len);\r
 \r
+/**\r
+ * fdt_setprop _placeholder - allocate space for a property\r
+ * @fdt: pointer to the device tree blob\r
+ * @nodeoffset: offset of the node whose property to change\r
+ * @name: name of the property to change\r
+ * @len: length of the property value\r
+ * @prop_data: return pointer to property data\r
+ *\r
+ * fdt_setprop_placeholer() allocates the named property in the given node.\r
+ * If the property exists it is resized. In either case a pointer to the\r
+ * property data is returned.\r
+ *\r
+ * This function may insert or delete data from the blob, and will\r
+ * therefore change the offsets of some existing nodes.\r
+ *\r
+ * returns:\r
+ *     0, on success\r
+ *     -FDT_ERR_NOSPACE, there is insufficient free space in the blob to\r
+ *             contain the new property value\r
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag\r
+ *     -FDT_ERR_BADLAYOUT,\r
+ *     -FDT_ERR_BADMAGIC,\r
+ *     -FDT_ERR_BADVERSION,\r
+ *     -FDT_ERR_BADSTATE,\r
+ *     -FDT_ERR_BADSTRUCTURE,\r
+ *     -FDT_ERR_BADLAYOUT,\r
+ *     -FDT_ERR_TRUNCATED, standard meanings\r
+ */\r
+int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,\r
+                           int len, void **prop_data);\r
+\r
 /**\r
  * fdt_setprop_u32 - set a property to a 32-bit integer\r
  * @fdt: pointer to the device tree blob\r
@@ -1271,6 +1591,36 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
 #define fdt_setprop_string(fdt, nodeoffset, name, str) \\r
        fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)\r
 \r
+\r
+/**\r
+ * fdt_setprop_empty - set a property to an empty value\r
+ * @fdt: pointer to the device tree blob\r
+ * @nodeoffset: offset of the node whose property to change\r
+ * @name: name of the property to change\r
+ *\r
+ * fdt_setprop_empty() sets the value of the named property in the\r
+ * given node to an empty (zero length) value, or creates a new empty\r
+ * property if it does not already exist.\r
+ *\r
+ * This function may insert or delete data from the blob, and will\r
+ * therefore change the offsets of some existing nodes.\r
+ *\r
+ * returns:\r
+ *     0, on success\r
+ *     -FDT_ERR_NOSPACE, there is insufficient free space in the blob to\r
+ *             contain the new property value\r
+ *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag\r
+ *     -FDT_ERR_BADLAYOUT,\r
+ *     -FDT_ERR_BADMAGIC,\r
+ *     -FDT_ERR_BADVERSION,\r
+ *     -FDT_ERR_BADSTATE,\r
+ *     -FDT_ERR_BADSTRUCTURE,\r
+ *     -FDT_ERR_BADLAYOUT,\r
+ *     -FDT_ERR_TRUNCATED, standard meanings\r
+ */\r
+#define fdt_setprop_empty(fdt, nodeoffset, name) \\r
+       fdt_setprop((fdt), (nodeoffset), (name), NULL, 0)\r
+\r
 /**\r
  * fdt_appendprop - append to or create a property\r
  * @fdt: pointer to the device tree blob\r
@@ -1448,8 +1798,10 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
  * creating subnodes based on a portion of a larger string, such as a\r
  * full path.\r
  */\r
+#ifndef SWIG /* Not available in Python */\r
 int fdt_add_subnode_namelen(void *fdt, int parentoffset,\r
                            const char *name, int namelen);\r
+#endif\r
 \r
 /**\r
  * fdt_add_subnode - creates a new node\r
@@ -1465,9 +1817,11 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
  * change the offsets of some existing nodes.\r
 \r
  * returns:\r
- *     structure block offset of the created nodeequested subnode (>=0), on success\r
+ *     structure block offset of the created nodeequested subnode (>=0), on\r
+ *             success\r
  *     -FDT_ERR_NOTFOUND, if the requested subnode does not exist\r
- *     -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag\r
+ *     -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE\r
+ *             tag\r
  *     -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of\r
  *             the given name\r
  *     -FDT_ERR_NOSPACE, if there is insufficient free space in the\r
index 3e24db94098c2651ea9c6f4484d2cd54b72fc8fa..d84a6a491481af6d574779d63ad78170ce14c1df 100644 (file)
@@ -78,4 +78,8 @@ static inline char *strchr(const char *s, int c) {
   return AsciiStrStr (s, pattern);\r
 }\r
 \r
+static inline size_t strnlen (const char* str, size_t strsz ) {\r
+  return AsciiStrnLenS (str, strsz);\r
+}\r
+\r
 #endif /* _LIBFDT_ENV_H */\r
index f3da231143a0aafd511a59ba504e73faaed10cba..b26d37422da23fdbfe43a163f98aad1de20f1811 100644 (file)
@@ -32,6 +32,7 @@
   fdt_sw.c\r
   fdt_wip.c\r
   fdt.c\r
+  fdt_addresses.c\r
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
index 91126c000a1ed82dbf58d1d2c7cd9ff59a4e96ae..5b74948d9e9d80b54c004b4ad75ae80a42b50c4f 100644 (file)
@@ -6,5 +6,6 @@
 LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
 LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
 LIBFDT_VERSION = version.lds
-LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c
+LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \\r
+       fdt_addresses.c\r
 LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
index 963952820bc6df992e80eac53a77f09ffc02a1fb..29756a8795f06979f8885fd2f8d4eb10321eeb36 100644 (file)
@@ -76,18 +76,19 @@ int fdt_check_header(const void *fdt)
 \r
 const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)\r
 {\r
-       const char *p;\r
+       unsigned absoffset = offset + fdt_off_dt_struct(fdt);\r
+\r
+       if ((absoffset < offset)\r
+           || ((absoffset + len) < absoffset)\r
+           || (absoffset + len) > fdt_totalsize(fdt))\r
+               return NULL;\r
 \r
        if (fdt_version(fdt) >= 0x11)\r
                if (((offset + len) < offset)\r
                    || ((offset + len) > fdt_size_dt_struct(fdt)))\r
                        return NULL;\r
 \r
-       p = _fdt_offset_ptr(fdt, offset);\r
-\r
-       if (p + len < p)\r
-               return NULL;\r
-       return p;\r
+       return _fdt_offset_ptr(fdt, offset);\r
 }\r
 \r
 uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)\r
diff --git a/EmbeddedPkg/Library/FdtLib/fdt_addresses.c b/EmbeddedPkg/Library/FdtLib/fdt_addresses.c
new file mode 100644 (file)
index 0000000..f48da28
--- /dev/null
@@ -0,0 +1,96 @@
+/*\r
+ * libfdt - Flat Device Tree manipulation\r
+ * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>\r
+ *\r
+ * libfdt is dual licensed: you can use it either under the terms of\r
+ * the GPL, or the BSD license, at your option.\r
+ *\r
+ *  a) This library is free software; you can redistribute it and/or\r
+ *     modify it under the terms of the GNU General Public License as\r
+ *     published by the Free Software Foundation; either version 2 of the\r
+ *     License, or (at your option) any later version.\r
+ *\r
+ *     This library is distributed in the hope that it will be useful,\r
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ *     GNU General Public License for more details.\r
+ *\r
+ *     You should have received a copy of the GNU General Public\r
+ *     License along with this library; if not, write to the Free\r
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,\r
+ *     MA 02110-1301 USA\r
+ *\r
+ * Alternatively,\r
+ *\r
+ *  b) Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *     1. Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *     2. Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\r
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,\r
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+#include "libfdt_env.h"\r
+\r
+#include <fdt.h>\r
+#include <libfdt.h>\r
+\r
+#include "libfdt_internal.h"\r
+\r
+int fdt_address_cells(const void *fdt, int nodeoffset)\r
+{\r
+       const fdt32_t *ac;\r
+       int val;\r
+       int len;\r
+\r
+       ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);\r
+       if (!ac)\r
+               return 2;\r
+\r
+       if (len != sizeof(*ac))\r
+               return -FDT_ERR_BADNCELLS;\r
+\r
+       val = fdt32_to_cpu(*ac);\r
+       if ((val <= 0) || (val > FDT_MAX_NCELLS))\r
+               return -FDT_ERR_BADNCELLS;\r
+\r
+       return val;\r
+}\r
+\r
+int fdt_size_cells(const void *fdt, int nodeoffset)\r
+{\r
+       const fdt32_t *sc;\r
+       int val;\r
+       int len;\r
+\r
+       sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);\r
+       if (!sc)\r
+               return 2;\r
+\r
+       if (len != sizeof(*sc))\r
+               return -FDT_ERR_BADNCELLS;\r
+\r
+       val = fdt32_to_cpu(*sc);\r
+       if ((val < 0) || (val > FDT_MAX_NCELLS))\r
+               return -FDT_ERR_BADNCELLS;\r
+\r
+       return val;\r
+}\r
index f00a8991d44f4cd9c4b0f719c65b5c7aa0bf9474..634b436f525729653e4bf68cd24a28eb2383d13d 100644 (file)
@@ -81,4 +81,3 @@ int fdt_create_empty_tree(void *buf, int bufsize)
 \r
        return fdt_open_into(buf, buf, bufsize);\r
 }\r
-\r
index 2055891e71463265b47aa8d63fb6dd032d4dc813..9413f50a110f4174fb59274a48b3d5e0f2845b68 100644 (file)
@@ -60,7 +60,7 @@ static int _fdt_nodename_eq(const void *fdt, int offset,
 {\r
        const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);\r
 \r
-       if (! p)\r
+       if (!p)\r
                /* short match */\r
                return 0;\r
 \r
@@ -88,6 +88,32 @@ static int _fdt_string_eq(const void *fdt, int stroffset,
        return (strlen(p) == len) && (memcmp(p, s, len) == 0);\r
 }\r
 \r
+uint32_t fdt_get_max_phandle(const void *fdt)\r
+{\r
+       uint32_t max_phandle = 0;\r
+       int offset;\r
+\r
+       for (offset = fdt_next_node(fdt, -1, NULL);;\r
+            offset = fdt_next_node(fdt, offset, NULL)) {\r
+               uint32_t phandle;\r
+\r
+               if (offset == -FDT_ERR_NOTFOUND)\r
+                       return max_phandle;\r
+\r
+               if (offset < 0)\r
+                       return (uint32_t)-1;\r
+\r
+               phandle = fdt_get_phandle(fdt, offset);\r
+               if (phandle == (uint32_t)-1)\r
+                       continue;\r
+\r
+               if (phandle > max_phandle)\r
+                       max_phandle = phandle;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)\r
 {\r
        FDT_CHECK_HEADER(fdt);\r
@@ -154,9 +180,9 @@ int fdt_subnode_offset(const void *fdt, int parentoffset,
        return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));\r
 }\r
 \r
-int fdt_path_offset(const void *fdt, const char *path)\r
+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)\r
 {\r
-       const char *end = path + strlen(path);\r
+       const char *end = path + namelen;\r
        const char *p = path;\r
        int offset = 0;\r
 \r
@@ -164,7 +190,7 @@ int fdt_path_offset(const void *fdt, const char *path)
 \r
        /* see if we have an alias */\r
        if (*path != '/') {\r
-               const char *q = strchr(path, '/');\r
+               const char *q = memchr(path, '/', end - p);\r
 \r
                if (!q)\r
                        q = end;\r
@@ -177,14 +203,15 @@ int fdt_path_offset(const void *fdt, const char *path)
                p = q;\r
        }\r
 \r
-       while (*p) {\r
+       while (p < end) {\r
                const char *q;\r
 \r
-               while (*p == '/')\r
+               while (*p == '/') {\r
                        p++;\r
-               if (! *p)\r
-                       return offset;\r
-               q = strchr(p, '/');\r
+                       if (p == end)\r
+                               return offset;\r
+               }\r
+               q = memchr(p, '/', end - p);\r
                if (! q)\r
                        q = end;\r
 \r
@@ -198,6 +225,11 @@ int fdt_path_offset(const void *fdt, const char *path)
        return offset;\r
 }\r
 \r
+int fdt_path_offset(const void *fdt, const char *path)\r
+{\r
+       return fdt_path_offset_namelen(fdt, path, strlen(path));\r
+}\r
+\r
 const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)\r
 {\r
        const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);\r
@@ -267,8 +299,7 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
             (offset = fdt_next_property_offset(fdt, offset))) {\r
                const struct fdt_property *prop;\r
 \r
-               prop = fdt_get_property_by_offset(fdt, offset, lenp);\r
-               if (!prop) {\r
+               if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {\r
                        offset = -FDT_ERR_INTERNAL;\r
                        break;\r
                }\r
@@ -296,7 +327,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
        const struct fdt_property *prop;\r
 \r
        prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);\r
-       if (! prop)\r
+       if (!prop)\r
                return NULL;\r
 \r
        return prop->data;\r
@@ -495,7 +526,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
 {\r
        int offset;\r
 \r
-       if ((phandle == 0) || (phandle == (uint32_t)-1))\r
+       if ((phandle == 0) || (phandle == -1))\r
                return -FDT_ERR_BADPHANDLE;\r
 \r
        FDT_CHECK_HEADER(fdt);\r
@@ -533,6 +564,106 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
        return 0;\r
 }\r
 \r
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)\r
+{\r
+       const char *list, *end;\r
+       int length, count = 0;\r
+\r
+       list = fdt_getprop(fdt, nodeoffset, property, &length);\r
+       if (!list)\r
+               return length;\r
+\r
+       end = list + length;\r
+\r
+       while (list < end) {\r
+               length = strnlen(list, end - list) + 1;\r
+\r
+               /* Abort if the last string isn't properly NUL-terminated. */\r
+               if (list + length > end)\r
+                       return -FDT_ERR_BADVALUE;\r
+\r
+               list += length;\r
+               count++;\r
+       }\r
+\r
+       return count;\r
+}\r
+\r
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,\r
+                         const char *string)\r
+{\r
+       int length, len, idx = 0;\r
+       const char *list, *end;\r
+\r
+       list = fdt_getprop(fdt, nodeoffset, property, &length);\r
+       if (!list)\r
+               return length;\r
+\r
+       len = strlen(string) + 1;\r
+       end = list + length;\r
+\r
+       while (list < end) {\r
+               length = strnlen(list, end - list) + 1;\r
+\r
+               /* Abort if the last string isn't properly NUL-terminated. */\r
+               if (list + length > end)\r
+                       return -FDT_ERR_BADVALUE;\r
+\r
+               if (length == len && memcmp(list, string, length) == 0)\r
+                       return idx;\r
+\r
+               list += length;\r
+               idx++;\r
+       }\r
+\r
+       return -FDT_ERR_NOTFOUND;\r
+}\r
+\r
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,\r
+                              const char *property, int idx,\r
+                              int *lenp)\r
+{\r
+       const char *list, *end;\r
+       int length;\r
+\r
+       list = fdt_getprop(fdt, nodeoffset, property, &length);\r
+       if (!list) {\r
+               if (lenp)\r
+                       *lenp = length;\r
+\r
+               return NULL;\r
+       }\r
+\r
+       end = list + length;\r
+\r
+       while (list < end) {\r
+               length = strnlen(list, end - list) + 1;\r
+\r
+               /* Abort if the last string isn't properly NUL-terminated. */\r
+               if (list + length > end) {\r
+                       if (lenp)\r
+                               *lenp = -FDT_ERR_BADVALUE;\r
+\r
+                       return NULL;\r
+               }\r
+\r
+               if (idx == 0) {\r
+                       if (lenp)\r
+                               *lenp = length - 1;\r
+\r
+                       return list;\r
+               }\r
+\r
+               list += length;\r
+               idx--;\r
+       }\r
+\r
+       if (lenp)\r
+               *lenp = -FDT_ERR_NOTFOUND;\r
+\r
+       return NULL;\r
+}\r
+\r
 int fdt_node_check_compatible(const void *fdt, int nodeoffset,\r
                              const char *compatible)\r
 {\r
@@ -542,10 +673,8 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
        prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);\r
        if (!prop)\r
                return len;\r
-       if (fdt_stringlist_contains(prop, len, compatible))\r
-               return 0;\r
-       else\r
-               return 1;\r
+\r
+       return !fdt_stringlist_contains(prop, len, compatible);\r
 }\r
 \r
 int fdt_node_offset_by_compatible(const void *fdt, int startoffset,\r
index 7a2bcf3d07f8e19436a6673735d7db1ca037fdb3..863f2b2e0fc10080dc3a4ba05f8fcd44dddb9dba 100644 (file)
@@ -84,9 +84,9 @@ static int _fdt_rw_check_header(void *fdt)
 \r
 #define FDT_RW_CHECK_HEADER(fdt) \\r
        { \\r
-               int err; \\r
-               if ((err = _fdt_rw_check_header(fdt)) != 0) \\r
-                       return err; \\r
+               int __err; \\r
+               if ((__err = _fdt_rw_check_header(fdt)) != 0) \\r
+                       return __err; \\r
        }\r
 \r
 static inline int _fdt_data_size(void *fdt)\r
@@ -101,6 +101,8 @@ static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
 \r
        if (((p + oldlen) < p) || ((p + oldlen) > end))\r
                return -FDT_ERR_BADOFFSET;\r
+       if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))\r
+               return -FDT_ERR_BADOFFSET;\r
        if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))\r
                return -FDT_ERR_NOSPACE;\r
        memmove(p + newlen, p + oldlen, end - p - oldlen);\r
@@ -126,8 +128,7 @@ static int _fdt_splice_struct(void *fdt, void *p,
        int delta = newlen - oldlen;\r
        int err;\r
 \r
-       err = _fdt_splice(fdt, p, oldlen, newlen);\r
-       if (err)\r
+       if ((err = _fdt_splice(fdt, p, oldlen, newlen)))\r
                return err;\r
 \r
        fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);\r
@@ -141,8 +142,7 @@ static int _fdt_splice_string(void *fdt, int newlen)
                + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);\r
        int err;\r
 \r
-       err = _fdt_splice(fdt, p, 0, newlen);\r
-       if (err)\r
+       if ((err = _fdt_splice(fdt, p, 0, newlen)))\r
                return err;\r
 \r
        fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);\r
@@ -191,17 +191,13 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
 int fdt_del_mem_rsv(void *fdt, int n)\r
 {\r
        struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);\r
-       int err;\r
 \r
        FDT_RW_CHECK_HEADER(fdt);\r
 \r
        if (n >= fdt_num_mem_rsv(fdt))\r
                return -FDT_ERR_NOTFOUND;\r
 \r
-       err = _fdt_splice_mem_rsv(fdt, re, 1, 0);\r
-       if (err)\r
-               return err;\r
-       return 0;\r
+       return _fdt_splice_mem_rsv(fdt, re, 1, 0);\r
 }\r
 \r
 static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,\r
@@ -211,12 +207,11 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
        int err;\r
 \r
        *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);\r
-       if (! (*prop))\r
+       if (!*prop)\r
                return oldlen;\r
 \r
-       err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),\r
-                     FDT_TAGALIGN(len));\r
-       if (err)\r
+       if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),\r
+                                     FDT_TAGALIGN(len))))\r
                return err;\r
 \r
        (*prop)->len = cpu_to_fdt32(len);\r
@@ -274,8 +269,8 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
        return 0;\r
 }\r
 \r
-int fdt_setprop(void *fdt, int nodeoffset, const char *name,\r
-               const void *val, int len)\r
+int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,\r
+                           int len, void **prop_data)\r
 {\r
        struct fdt_property *prop;\r
        int err;\r
@@ -288,7 +283,22 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
        if (err)\r
                return err;\r
 \r
-       memcpy(prop->data, val, len);\r
+       *prop_data = prop->data;\r
+       return 0;\r
+}\r
+\r
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,\r
+               const void *val, int len)\r
+{\r
+       void *prop_data;\r
+       int err;\r
+\r
+       err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data);\r
+       if (err)\r
+               return err;\r
+\r
+       if (len)\r
+               memcpy(prop_data, val, len);\r
        return 0;\r
 }\r
 \r
@@ -327,7 +337,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
        FDT_RW_CHECK_HEADER(fdt);\r
 \r
        prop = fdt_get_property_w(fdt, nodeoffset, name, &len);\r
-       if (! prop)\r
+       if (!prop)\r
                return len;\r
 \r
        proplen = sizeof(*prop) + FDT_TAGALIGN(len);\r
index a49793d9361b0185b4b605320b944435e5aa40f9..3041e2ecfbca80b917d93613f55acea4a9e874bd 100644 (file)
@@ -69,6 +69,7 @@ static struct fdt_errtabent fdt_errtable[] = {
 \r
        FDT_ERRTABENT(FDT_ERR_BADOFFSET),\r
        FDT_ERRTABENT(FDT_ERR_BADPATH),\r
+       FDT_ERRTABENT(FDT_ERR_BADPHANDLE),\r
        FDT_ERRTABENT(FDT_ERR_BADSTATE),\r
 \r
        FDT_ERRTABENT(FDT_ERR_TRUNCATED),\r
@@ -76,6 +77,11 @@ static struct fdt_errtabent fdt_errtable[] = {
        FDT_ERRTABENT(FDT_ERR_BADVERSION),\r
        FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),\r
        FDT_ERRTABENT(FDT_ERR_BADLAYOUT),\r
+       FDT_ERRTABENT(FDT_ERR_INTERNAL),\r
+       FDT_ERRTABENT(FDT_ERR_BADNCELLS),\r
+       FDT_ERRTABENT(FDT_ERR_BADVALUE),\r
+       FDT_ERRTABENT(FDT_ERR_BADOVERLAY),\r
+       FDT_ERRTABENT(FDT_ERR_NOPHANDLES),\r
 };\r
 #define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))\r
 \r
index 991919b4364f807ae3d7d9959baf39ee7f98e58b..3c2c71018622e6820cb678c0be10ce174871d6ff 100644 (file)
@@ -107,6 +107,38 @@ int fdt_create(void *buf, int bufsize)
        return 0;\r
 }\r
 \r
+int fdt_resize(void *fdt, void *buf, int bufsize)\r
+{\r
+       size_t headsize, tailsize;\r
+       char *oldtail, *newtail;\r
+\r
+       FDT_SW_CHECK_HEADER(fdt);\r
+\r
+       headsize = fdt_off_dt_struct(fdt);\r
+       tailsize = fdt_size_dt_strings(fdt);\r
+\r
+       if ((headsize + tailsize) > bufsize)\r
+               return -FDT_ERR_NOSPACE;\r
+\r
+       oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;\r
+       newtail = (char *)buf + bufsize - tailsize;\r
+\r
+       /* Two cases to avoid clobbering data if the old and new\r
+        * buffers partially overlap */\r
+       if (buf <= fdt) {\r
+               memmove(buf, fdt, headsize);\r
+               memmove(newtail, oldtail, tailsize);\r
+       } else {\r
+               memmove(newtail, oldtail, tailsize);\r
+               memmove(buf, fdt, headsize);\r
+       }\r
+\r
+       fdt_set_off_dt_strings(buf, bufsize);\r
+       fdt_set_totalsize(buf, bufsize);\r
+\r
+       return 0;\r
+}\r
+\r
 int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)\r
 {\r
        struct fdt_reserve_entry *re;\r
@@ -188,7 +220,7 @@ static int _fdt_find_add_string(void *fdt, const char *s)
        return offset;\r
 }\r
 \r
-int fdt_property(void *fdt, const char *name, const void *val, int len)\r
+int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)\r
 {\r
        struct fdt_property *prop;\r
        int nameoff;\r
@@ -206,7 +238,19 @@ int fdt_property(void *fdt, const char *name, const void *val, int len)
        prop->tag = cpu_to_fdt32(FDT_PROP);\r
        prop->nameoff = cpu_to_fdt32(nameoff);\r
        prop->len = cpu_to_fdt32(len);\r
-       memcpy(prop->data, val, len);\r
+       *valp = prop->data;\r
+       return 0;\r
+}\r
+\r
+int fdt_property(void *fdt, const char *name, const void *val, int len)\r
+{\r
+       void *ptr;\r
+       int ret;\r
+\r
+       ret = fdt_property_placeholder(fdt, name, len, &ptr);\r
+       if (ret)\r
+               return ret;\r
+       memcpy(ptr, val, len);\r
        return 0;\r
 }\r
 \r
index 3f2b58172b4dfdb083e6015be63e5374849f9920..6e39807b87826b3cbed35defa7ee57cc7faa0a37 100644 (file)
 \r
 #include "libfdt_internal.h"\r
 \r
+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,\r
+                                       const char *name, int namelen,\r
+                                       uint32_t idx, const void *val,\r
+                                       int len)\r
+{\r
+       void *propval;\r
+       int proplen;\r
+\r
+       propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen,\r
+                                       &proplen);\r
+       if (!propval)\r
+               return proplen;\r
+\r
+       if (proplen < (len + idx))\r
+               return -FDT_ERR_NOSPACE;\r
+\r
+       memcpy((char *)propval + idx, val, len);\r
+       return 0;\r
+}\r
+\r
 int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,\r
                        const void *val, int len)\r
 {\r
-       void *propval;\r
+       const void *propval;\r
        int proplen;\r
 \r
-       propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);\r
-       if (! propval)\r
+       propval = fdt_getprop(fdt, nodeoffset, name, &proplen);\r
+       if (!propval)\r
                return proplen;\r
 \r
        if (proplen != len)\r
                return -FDT_ERR_NOSPACE;\r
 \r
-       memcpy(propval, val, len);\r
-       return 0;\r
+       return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name,\r
+                                                  strlen(name), 0,\r
+                                                  val, len);\r
 }\r
 \r
 static void _fdt_nop_region(void *start, int len)\r
@@ -86,7 +107,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
        int len;\r
 \r
        prop = fdt_get_property_w(fdt, nodeoffset, name, &len);\r
-       if (! prop)\r
+       if (!prop)\r
                return len;\r
 \r
        _fdt_nop_region(prop, len + sizeof(*prop));\r
index 15456110a34e18fff9870eb9657ef9c28e6b8176..f82227a32c35f8544280542507f5ac7c20728428 100644 (file)
@@ -57,9 +57,9 @@
 \r
 #define FDT_CHECK_HEADER(fdt) \\r
        { \\r
-               int err; \\r
-               if ((err = fdt_check_header(fdt)) != 0) \\r
-                       return err; \\r
+               int __err; \\r
+               if ((__err = fdt_check_header(fdt)) != 0) \\r
+                       return __err; \\r
        }\r
 \r
 int _fdt_check_node_offset(const void *fdt, int offset);\r
index 80b322bed6b9a3bfa5a8c9f3654543f9f68a3551..84538f697d6d62c504ed5d00fcdab9221b8b6296 100644 (file)
@@ -8,6 +8,7 @@ LIBFDT_1.2 {
                fdt_get_mem_rsv;
                fdt_subnode_offset_namelen;
                fdt_subnode_offset;
+               fdt_path_offset_namelen;\r
                fdt_path_offset;
                fdt_get_name;
                fdt_get_property_namelen;
@@ -54,6 +55,12 @@ LIBFDT_1.2 {
                fdt_get_property_by_offset;
                fdt_getprop_by_offset;
                fdt_next_property_offset;
+               fdt_first_subnode;\r
+               fdt_next_subnode;\r
+               fdt_address_cells;\r
+               fdt_size_cells;\r
+               fdt_stringlist_contains;\r
+               fdt_resize;\r
 
        local:
                *;