libfdt: Bring in upstream stringlist functions
authorSimon Glass <sjg@chromium.org>
Sun, 2 Oct 2016 23:59:28 +0000 (17:59 -0600)
committerSimon Glass <sjg@chromium.org>
Thu, 13 Oct 2016 19:54:10 +0000 (13:54 -0600)
These have now landed upstream. The naming is different and in one case the
function signature has changed. Update the code to match.

This applies the following upstream commits by
Thierry Reding <treding@nvidia.com> :

   604e61e fdt: Add functions to retrieve strings
   8702bd1 fdt: Add a function to get the index of a string
   2218387 fdt: Add a function to count strings

Signed-off-by: Simon Glass <sjg@chromium.org>
21 files changed:
arch/arm/mach-tegra/xusb-padctl-common.c
arch/arm/mach-uniphier/board_late_init.c
arch/x86/cpu/irq.c
common/image-fit.c
common/image.c
drivers/clk/clk-uclass.c
drivers/core/device.c
drivers/gpio/dwapb_gpio.c
drivers/i2c/mxc_i2c.c
drivers/mailbox/mailbox-uclass.c
drivers/net/sun8i_emac.c
drivers/pinctrl/exynos/pinctrl-exynos.c
drivers/pinctrl/meson/pinctrl-meson.c
drivers/pinctrl/pinctrl-generic.c
drivers/pinctrl/pinctrl-uclass.c
drivers/reset/reset-uclass.c
drivers/video/sunxi_display.c
include/libfdt.h
lib/fdtdec.c
lib/libfdt/fdt_ro.c
test/overlay/cmd_ut_overlay.c

index 18ad7bfbdc0f7fa862bb735c4fb29827b3c9b83f..6867065790f40ee3f709648c3b6d37fe8f179ec0 100644 (file)
@@ -78,11 +78,11 @@ tegra_xusb_padctl_group_parse_dt(struct tegra_xusb_padctl *padctl,
                                 const void *fdt, int node)
 {
        unsigned int i;
-       int len, err;
+       int len;
 
        group->name = fdt_get_name(fdt, node, &len);
 
-       len = fdt_count_strings(fdt, node, "nvidia,lanes");
+       len =  fdt_stringlist_count(fdt, node, "nvidia,lanes");
        if (len < 0) {
                error("failed to parse \"nvidia,lanes\" property");
                return -EINVAL;
@@ -91,9 +91,9 @@ tegra_xusb_padctl_group_parse_dt(struct tegra_xusb_padctl *padctl,
        group->num_pins = len;
 
        for (i = 0; i < group->num_pins; i++) {
-               err = fdt_get_string_index(fdt, node, "nvidia,lanes", i,
-                                          &group->pins[i]);
-               if (err < 0) {
+               group->pins[i] = fdt_stringlist_get(fdt, node, "nvidia,lanes",
+                                                   i, NULL);
+               if (!group->pins[i]) {
                        error("failed to read string from \"nvidia,lanes\" property");
                        return -EINVAL;
                }
@@ -101,8 +101,8 @@ tegra_xusb_padctl_group_parse_dt(struct tegra_xusb_padctl *padctl,
 
        group->num_pins = len;
 
-       err = fdt_get_string(fdt, node, "nvidia,function", &group->func);
-       if (err < 0) {
+       group->func = fdt_stringlist_get(fdt, node, "nvidia,function", 0, NULL);
+       if (!group->func) {
                error("failed to parse \"nvidia,func\" property");
                return -EINVAL;
        }
index a45412677a0ffcfad93ca01f7a6ee222471f90ce..f23295fbd2128016318a72368d62facba60e6e2a 100644 (file)
@@ -37,13 +37,12 @@ static int uniphier_set_fdt_file(void)
        const char *compat;
        char dtb_name[256];
        int buf_len = 256;
-       int ret;
 
        if (getenv("fdt_file"))
                return 0;       /* do nothing if it is already set */
 
-       ret = fdt_get_string(gd->fdt_blob, 0, "compatible", &compat);
-       if (ret)
+       compat = fdt_stringlist_get(gd->fdt_blob, 0, "compatible", 0, NULL);
+       if (!compat)
                return -EINVAL;
 
        if (strncmp(compat, VENDOR_PREFIX, strlen(VENDOR_PREFIX)))
index df3cd0abc7771bef450f70c458ad13613d2162e4..9364410a0f83728854df8b01c40e2d369334bf4b 100644 (file)
@@ -103,11 +103,12 @@ static int create_pirq_routing_table(struct udevice *dev)
        /* extract the bdf from fdt_pci_addr */
        priv->bdf = dm_pci_get_bdf(dev->parent);
 
-       ret = fdt_find_string(blob, node, "intel,pirq-config", "pci");
+       ret = fdt_stringlist_search(blob, node, "intel,pirq-config", "pci");
        if (!ret) {
                priv->config = PIRQ_VIA_PCI;
        } else {
-               ret = fdt_find_string(blob, node, "intel,pirq-config", "ibase");
+               ret = fdt_stringlist_search(blob, node, "intel,pirq-config",
+                                           "ibase");
                if (!ret)
                        priv->config = PIRQ_VIA_IBASE;
                else
index 1b0234a90cb1eefcc7533f630491e8a68098292a..d67678a6dd56bd57623e2a90820328125c89491a 100644 (file)
@@ -1457,7 +1457,7 @@ int fit_conf_get_prop_node(const void *fit, int noffset,
 void fit_conf_print(const void *fit, int noffset, const char *p)
 {
        char *desc;
-       char *uname;
+       const char *uname;
        int ret;
        int loadables_index;
 
@@ -1469,7 +1469,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
        else
                printf("%s\n", desc);
 
-       uname = (char *)fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
+       uname = fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
        printf("%s  Kernel:       ", p);
        if (uname == NULL)
                printf("unavailable\n");
@@ -1477,26 +1477,23 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
                printf("%s\n", uname);
 
        /* Optional properties */
-       uname = (char *)fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
+       uname = fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
        if (uname)
                printf("%s  Init Ramdisk: %s\n", p, uname);
 
-       uname = (char *)fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL);
+       uname = fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL);
        if (uname)
                printf("%s  FDT:          %s\n", p, uname);
 
-       uname = (char *)fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL);
+       uname = fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL);
        if (uname)
                printf("%s  FPGA:         %s\n", p, uname);
 
        /* Print out all of the specified loadables */
        for (loadables_index = 0;
-            fdt_get_string_index(fit, noffset,
-                       FIT_LOADABLE_PROP,
-                       loadables_index,
-                       (const char **)&uname) == 0;
-            loadables_index++)
-       {
+            uname = fdt_stringlist_get(fit, noffset, FIT_LOADABLE_PROP,
+                                       loadables_index, NULL), uname;
+            loadables_index++) {
                if (loadables_index == 0) {
                        printf("%s  Loadables:    ", p);
                } else {
index c0ad36a60f8a90c6ef31d65816dae30441b3de8d..0e86c13a88aa827415d98740894abe12440ed91f 100644 (file)
@@ -1305,7 +1305,7 @@ int boot_get_fpga(int argc, char * const argv[], bootm_headers_t *images,
        void *buf;
        int conf_noffset;
        int fit_img_result;
-       char *uname, *name;
+       const char *uname, *name;
        int err;
        int devnum = 0; /* TODO support multi fpga platforms */
        const fpga_desc * const desc = fpga_get_desc(devnum);
@@ -1332,9 +1332,9 @@ int boot_get_fpga(int argc, char * const argv[], bootm_headers_t *images,
        case IMAGE_FORMAT_FIT:
                conf_noffset = fit_conf_get_node(buf, images->fit_uname_cfg);
 
-               err = fdt_get_string_index(buf, conf_noffset, FIT_FPGA_PROP, 0,
-                                          (const char **)&uname);
-               if (err < 0) {
+               uname = fdt_stringlist_get(buf, conf_noffset, FIT_FPGA_PROP, 0,
+                                          NULL);
+               if (!uname) {
                        debug("## FPGA image is not specified\n");
                        return 0;
                }
@@ -1404,7 +1404,7 @@ int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images,
        int loadables_index;
        int conf_noffset;
        int fit_img_result;
-       char *uname;
+       const char *uname;
 
        /* Check to see if the images struct has a FIT configuration */
        if (!genimg_has_config(images)) {
@@ -1428,15 +1428,14 @@ int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images,
                conf_noffset = fit_conf_get_node(buf, images->fit_uname_cfg);
 
                for (loadables_index = 0;
-                    fdt_get_string_index(buf, conf_noffset,
-                               FIT_LOADABLE_PROP,
-                               loadables_index,
-                               (const char **)&uname) == 0;
+                    uname = fdt_stringlist_get(buf, conf_noffset,
+                                       FIT_LOADABLE_PROP, loadables_index,
+                                       NULL), uname;
                     loadables_index++)
                {
                        fit_img_result = fit_image_load(images,
                                tmp_img_addr,
-                               (const char **)&uname,
+                               &uname,
                                &(images->fit_uname_cfg), arch,
                                IH_TYPE_LOADABLE,
                                BOOTSTAGE_ID_FIT_LOADABLE_START,
index 4d78e3fcac43d586ea5f2dc02cd5bb7fb48ab51c..c42fff6ec2908ba801d8420011b7e55f4346da9a 100644 (file)
@@ -101,10 +101,10 @@ int clk_get_by_name(struct udevice *dev, const char *name, struct clk *clk)
 
        debug("%s(dev=%p, name=%s, clk=%p)\n", __func__, dev, name, clk);
 
-       index = fdt_find_string(gd->fdt_blob, dev->of_offset, "clock-names",
-                               name);
+       index = fdt_stringlist_search(gd->fdt_blob, dev->of_offset,
+                                     "clock-names", name);
        if (index < 0) {
-               debug("fdt_find_string() failed: %d\n", index);
+               debug("fdt_stringlist_search() failed: %d\n", index);
                return index;
        }
 
index b737f1c78907ada6e7538ed9262f2a49d9246386..1935b8d46f1eefe20f6a4cb009f2b2a56f122da1 100644 (file)
@@ -698,7 +698,7 @@ fdt_addr_t dev_get_addr_name(struct udevice *dev, const char *name)
 #if CONFIG_IS_ENABLED(OF_CONTROL)
        int index;
 
-       index = fdt_find_string(gd->fdt_blob, dev->of_offset, "reg-names",
+       index = fdt_stringlist_search(gd->fdt_blob, dev->of_offset, "reg-names",
                                name);
        if (index < 0)
                return index;
index 72cec488009597900d287ea3ed5eaf9e38565e2d..471e18aeaa0b3c54091a100214dab6ab735ff69c 100644 (file)
@@ -132,7 +132,8 @@ static int gpio_dwapb_bind(struct udevice *dev)
                plat->base = base;
                plat->bank = bank;
                plat->pins = fdtdec_get_int(blob, node, "snps,nr-gpios", 0);
-               ret = fdt_get_string(blob, node, "bank-name", &plat->name);
+               plat->name = fdt_stringlist_get(blob, node, "bank-name", 0,
+                                               NULL);
                if (ret)
                        goto err;
 
index a26f44e1e60edb8f4dceb701f14f335fea75406c..6247d334a0b21b8dd6a9402365c5551e9319b4b6 100644 (file)
@@ -773,7 +773,7 @@ static int mxc_i2c_probe(struct udevice *bus)
         * See Documentation/devicetree/bindings/i2c/i2c-imx.txt
         * Use gpio to force bus idle when necessary.
         */
-       ret = fdt_find_string(fdt, node, "pinctrl-names", "gpio");
+       ret = fdt_stringlist_search(fdt, node, "pinctrl-names", "gpio");
        if (ret < 0) {
                dev_info(dev, "i2c bus %d at %lu, no gpio pinctrl state.\n", bus->seq, i2c_bus->base);
        } else {
index 40f851d915490e793326588b2831c66523802c7b..a7fcde51d593a105a3f49db713993958b533bea8 100644 (file)
@@ -85,10 +85,10 @@ int mbox_get_by_name(struct udevice *dev, const char *name,
 
        debug("%s(dev=%p, name=%s, chan=%p)\n", __func__, dev, name, chan);
 
-       index = fdt_find_string(gd->fdt_blob, dev->of_offset, "mbox-names",
-                               name);
+       index = fdt_stringlist_search(gd->fdt_blob, dev->of_offset,
+                                     "mbox-names", name);
        if (index < 0) {
-               debug("fdt_find_string() failed: %d\n", index);
+               debug("fdt_stringlist_search() failed: %d\n", index);
                return index;
        }
 
index 4c149e1bdf2c1aa78e8680c0a8b119bd4b72a4b2..91570a29106f6d5ccd8ba80be7c976d097c8e8d9 100644 (file)
@@ -456,8 +456,9 @@ static int parse_phy_pins(struct udevice *dev)
        for (i = 0; ; i++) {
                int pin;
 
-               if (fdt_get_string_index(gd->fdt_blob, offset,
-                                        "allwinner,pins", i, &pin_name))
+               pin_name = fdt_stringlist_get(gd->fdt_blob, offset,
+                                        "allwinner,pins", i, NULL);
+               if (!pin_name)
                        break;
                if (pin_name[0] != 'P')
                        continue;
index a28405fc155fbbdeecc612ff8d7a5a06c499c7de..c9c13e68028f6272b8ceb27516ece0b369447901 100644 (file)
@@ -71,7 +71,7 @@ int exynos_pinctrl_set_state(struct udevice *dev, struct udevice *config)
 {
        const void *fdt = gd->fdt_blob;
        int node = config->of_offset;
-       unsigned int count, idx, pin_num, ret;
+       unsigned int count, idx, pin_num;
        unsigned int pinfunc, pinpud, pindrv;
        unsigned long reg, value;
        const char *name;
@@ -80,7 +80,7 @@ int exynos_pinctrl_set_state(struct udevice *dev, struct udevice *config)
         * refer to the following document for the pinctrl bindings
         * linux/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
         */
-       count = fdt_count_strings(fdt, node, "samsung,pins");
+       count =  fdt_stringlist_count(fdt, node, "samsung,pins");
        if (count <= 0)
                return -EINVAL;
 
@@ -89,9 +89,8 @@ int exynos_pinctrl_set_state(struct udevice *dev, struct udevice *config)
        pindrv = fdtdec_get_int(fdt, node, "samsung,pin-drv", -1);
 
        for (idx = 0; idx < count; idx++) {
-               ret = fdt_get_string_index(fdt, node, "samsung,pins",
-                                               idx, &name);
-               if (ret < 0)
+               name = fdt_stringlist_get(fdt, node, "samsung,pins", idx, NULL);
+               if (!name)
                        continue;
                reg = pin_to_bank_base(dev, name, &pin_num);
 
index d21a3dd75522cb012ea98f2c9ceccfb1b5b04446..46470eaae94f97a6894bb7bb2684875bd95c42cd 100644 (file)
@@ -122,7 +122,7 @@ static fdt_addr_t parse_address(int offset, const char *name, int na, int ns)
        int index, len = 0;
        const fdt32_t *reg;
 
-       index = fdt_find_string(gd->fdt_blob, offset, "reg-names", name);
+       index = fdt_stringlist_search(gd->fdt_blob, offset, "reg-names", name);
        if (index < 0)
                return FDT_ADDR_T_NONE;
 
index baff40f1f0d4141c6af80718009e22453855d733..482db295fee1c8eaf995d4c869f4d0a026e858bc 100644 (file)
@@ -306,11 +306,11 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev,
        const char *name;
        int strings_count, selector, i, ret;
 
-       strings_count = fdt_count_strings(fdt, node, subnode_target_type);
+       strings_count =  fdt_stringlist_count(fdt, node, subnode_target_type);
        if (strings_count < 0) {
                subnode_target_type = "groups";
                is_group = true;
-               strings_count = fdt_count_strings(fdt, node,
+               strings_count =  fdt_stringlist_count(fdt, node,
                                                  subnode_target_type);
                if (strings_count < 0) {
                        /* skip this node; may contain config child nodes */
@@ -319,9 +319,9 @@ static int pinctrl_generic_set_state_subnode(struct udevice *dev,
        }
 
        for (i = 0; i < strings_count; i++) {
-               ret = fdt_get_string_index(fdt, node, subnode_target_type,
-                                          i, &name);
-               if (ret < 0)
+               name = fdt_stringlist_get(fdt, node, subnode_target_type, i,
+                                         NULL);
+               if (!name)
                        return -EINVAL;
 
                if (is_group)
index 7397de28c0142fb63f03403f63b0786703dbbc65..02ab9b4afde6499ad9deee4b68fcd6b4b7947cd7 100644 (file)
@@ -72,7 +72,7 @@ static int pinctrl_select_state_full(struct udevice *dev, const char *statename)
        struct udevice *config;
        int state, size, i, ret;
 
-       state = fdt_find_string(fdt, node, "pinctrl-names", statename);
+       state = fdt_stringlist_search(fdt, node, "pinctrl-names", statename);
        if (state < 0) {
                char *end;
                /*
index edaecfbc99b1ee9ca2bad669101038d811b0020a..d3744ef703cbb1f7976f3ca6a778a6f094ff62b7 100644 (file)
@@ -88,10 +88,10 @@ int reset_get_by_name(struct udevice *dev, const char *name,
        debug("%s(dev=%p, name=%s, reset_ctl=%p)\n", __func__, dev, name,
              reset_ctl);
 
-       index = fdt_find_string(gd->fdt_blob, dev->of_offset, "reset-names",
-                               name);
+       index = fdt_stringlist_search(gd->fdt_blob, dev->of_offset,
+                                     "reset-names", name);
        if (index < 0) {
-               debug("fdt_find_string() failed: %d\n", index);
+               debug("fdt_stringlist_search() failed: %d\n", index);
                return index;
        }
 
index 50b16a9129f8e10aa19bc9507ce2ed33d2e41444..6cba1b95a110528dbda9d29d9370a7613f60d6d6 100644 (file)
@@ -1562,7 +1562,7 @@ int sunxi_simplefb_setup(void *blob)
        offset = fdt_node_offset_by_compatible(blob, -1,
                                               "allwinner,simple-framebuffer");
        while (offset >= 0) {
-               ret = fdt_find_string(blob, offset, "allwinner,pipeline",
+               ret = fdt_stringlist_search(blob, offset, "allwinner,pipeline",
                                      pipeline);
                if (ret == 0)
                        break;
index 3b1c788f492718c022091f69846ae262b1ea40e6..f3b61c94271ad57cd4d5395fa155ff7fa0cb4d70 100644 (file)
        /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells
         * or similar property with a bad format or value */
 
-#define FDT_ERR_TOODEEP                15
+#define FDT_ERR_BADVALUE       15
+       /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected
+        * value. For example: a property expected to contain a string list
+        * is not NUL-terminated within the length of its value. */
+
+#define FDT_ERR_TOODEEP                16
        /* FDT_ERR_TOODEEP: The depth of a node has exceeded the internal
         * libfdt limit. This can happen if you have more than
         * FDT_MAX_DEPTH nested nodes. */
 
-#define FDT_ERR_MAX            15
+#define FDT_ERR_MAX            16
 
 /**********************************************************************/
 /* Low-level functions (you probably don't need these)                */
@@ -957,51 +962,66 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
 int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
 
 /**
- * fdt_count_strings - count the number of strings in a string list
+ * fdt_stringlist_count - count the number of strings in a string list
  * @fdt: pointer to the device tree blob
- * @node: offset of the node
+ * @nodeoffset: offset of a tree node
  * @property: name of the property containing the string list
- * @return: the number of strings in the given property
+ * @return:
+ *   the number of strings in the given property
+ *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *   -FDT_ERR_NOTFOUND if the property does not exist
  */
-int fdt_count_strings(const void *fdt, int node, const char *property);
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
 
 /**
- * fdt_find_string - find a string in a string list and return its index
+ * fdt_stringlist_search - find a string in a string list and return its index
  * @fdt: pointer to the device tree blob
- * @node: offset of the node
+ * @nodeoffset: offset of a tree node
  * @property: name of the property containing the string list
  * @string: string to look up in the string list
- * @return: the index of the string or negative on error
+ *
+ * Note that it is possible for this function to succeed on property values
+ * that are not NUL-terminated. That's because the function will stop after
+ * finding the first occurrence of @string. This can for example happen with
+ * small-valued cell properties, such as #address-cells, when searching for
+ * the empty string.
+ *
+ * @return:
+ *   the index of the string in the list of strings
+ *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *   -FDT_ERR_NOTFOUND if the property does not exist or does not contain
+ *                     the given string
  */
-int fdt_find_string(const void *fdt, int node, const char *property,
-                   const char *string);
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
+                         const char *string);
 
 /**
- * fdt_get_string_index() - obtain the string at a given index in a string list
+ * fdt_stringlist_get() - obtain the string at a given index in a string list
  * @fdt: pointer to the device tree blob
- * @node: offset of the node
+ * @nodeoffset: offset of a tree node
  * @property: name of the property containing the string list
  * @index: index of the string to return
- * @output: return location for the string
- * @return: 0 if the string was found or a negative error code otherwise
- */
-int fdt_get_string_index(const void *fdt, int node, const char *property,
-                        int index, const char **output);
-
-/**
- * fdt_get_string() - obtain the first string in a string list
- * @fdt: pointer to the device tree blob
- * @node: offset of the node
- * @property: name of the property containing the string list
- * @output: return location for the string
- * @return: 0 if the string was found or a negative error code otherwise
- *
- * This is a shortcut for:
- *
- *     fdt_get_string_index(fdt, node, property, 0, output).
- */
-int fdt_get_string(const void *fdt, int node, const char *property,
-                  const char **output);
+ * @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)                           */
index 4defb902b87297d03f891ea18b26647bd19fccc9..adc9975c3610f6b8d480f9ec0ff8eb7cb6865be5 100644 (file)
@@ -1014,7 +1014,7 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property,
 {
        int index;
 
-       index = fdt_find_string(fdt, node, prop_names, name);
+       index = fdt_stringlist_search(fdt, node, prop_names, name);
        if (index < 0)
                return index;
 
index 005f26736f8f2c7f37c1985a1c24daa703a9f02a..e38aaa4ccf9ace9f3544a291180dcc359f9ebedb 100644 (file)
@@ -538,80 +538,104 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
        return 0;
 }
 
-int fdt_count_strings(const void *fdt, int node, const char *property)
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
 {
-       int length, i, count = 0;
-       const char *list;
+       const char *list, *end;
+       int length, count = 0;
 
-       list = fdt_getprop(fdt, node, property, &length);
+       list = fdt_getprop(fdt, nodeoffset, property, &length);
        if (!list)
-               return length;
+               return -length;
+
+       end = list + length;
+
+       while (list < end) {
+               length = strnlen(list, end - list) + 1;
 
-       for (i = 0; i < length; i++) {
-               int len = strlen(list);
+               /* Abort if the last string isn't properly NUL-terminated. */
+               if (list + length > end)
+                       return -FDT_ERR_BADVALUE;
 
-               list += len + 1;
-               i += len;
+               list += length;
                count++;
        }
 
        return count;
 }
 
-int fdt_find_string(const void *fdt, int node, const char *property,
-                   const char *string)
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
+                         const char *string)
 {
+       int length, len, idx = 0;
        const char *list, *end;
-       int len, index = 0;
 
-       list = fdt_getprop(fdt, node, property, &len);
+       list = fdt_getprop(fdt, nodeoffset, property, &length);
        if (!list)
-               return len;
+               return -length;
 
-       end = list + len;
-       len = strlen(string);
+       len = strlen(string) + 1;
+       end = list + length;
 
        while (list < end) {
-               int l = strlen(list);
+               length = strnlen(list, end - list) + 1;
+
+               /* Abort if the last string isn't properly NUL-terminated. */
+               if (list + length > end)
+                       return -FDT_ERR_BADVALUE;
 
-               if (l == len && memcmp(list, string, len) == 0)
-                       return index;
+               if (length == len && memcmp(list, string, length) == 0)
+                       return idx;
 
-               list += l + 1;
-               index++;
+               list += length;
+               idx++;
        }
 
        return -FDT_ERR_NOTFOUND;
 }
 
-int fdt_get_string_index(const void *fdt, int node, const char *property,
-                        int index, const char **output)
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
+                              const char *property, int idx,
+                              int *lenp)
 {
-       const char *list;
-       int length, i;
+       const char *list, *end;
+       int length;
+
+       list = fdt_getprop(fdt, nodeoffset, property, &length);
+       if (!list) {
+               if (lenp)
+                       *lenp = length;
 
-       list = fdt_getprop(fdt, node, property, &length);
+               return NULL;
+       }
 
-       for (i = 0; i < length; i++) {
-               int len = strlen(list);
+       end = list + length;
 
-               if (index == 0) {
-                       *output = list;
-                       return 0;
+       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 += len + 1;
-               i += len;
-               index--;
+               list += length;
+               idx--;
        }
 
-       return -FDT_ERR_NOTFOUND;
-}
+       if (lenp)
+               *lenp = -FDT_ERR_NOTFOUND;
 
-int fdt_get_string(const void *fdt, int node, const char *property,
-                  const char **output)
-{
-       return fdt_get_string_index(fdt, node, property, 0, output);
+       return NULL;
 }
 
 int fdt_node_check_compatible(const void *fdt, int nodeoffset,
index 87dc9328c674bda7f13773e3183b7b2ba9983208..cbef720b4c091fd0b8075e0c60ca852b582032ff 100644 (file)
@@ -52,12 +52,15 @@ static int fdt_getprop_str(void *fdt, const char *path, const char *name,
                           const char **out)
 {
        int node_off;
+       int len;
 
        node_off = fdt_path_offset(fdt, path);
        if (node_off < 0)
                return node_off;
 
-       return fdt_get_string(fdt, node_off, name, out);
+       *out = fdt_stringlist_get(fdt, node_off, name, 0, &len);
+
+       return len < 0 ? len : 0;
 }
 
 static int fdt_overlay_change_int_property(struct unit_test_state *uts)