]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EmbeddedPkg/Library/FdtLib/fdt_ro.c
EmbeddedPkg/FdtLib: Update FdtLib to v1.4.5
[mirror_edk2.git] / EmbeddedPkg / Library / FdtLib / fdt_ro.c
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