Commit b02e4044 authored by Simon Glass's avatar Simon Glass

libfdt: Bring in upstream stringlist functions

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: default avatarSimon Glass <sjg@chromium.org>
parent 9c07b987
......@@ -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;
}
......
......@@ -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)))
......
......@@ -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
......
......@@ -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 {
......
......@@ -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,
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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;
......
......@@ -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 {
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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)
......
......@@ -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;
/*
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -121,12 +121,17 @@
/* 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) */
......
......@@ -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;
......
......@@ -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,
......
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment