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: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass 2016-10-02 17:59:28 -06:00
parent 9c07b9877c
commit b02e4044ff
21 changed files with 176 additions and 132 deletions

View 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;
}

View 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)))

View 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

View 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 {

View 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,

View 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;
}

View 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;

View 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;

View 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 {

View 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;
}

View 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;

View 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);

View 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;

View 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)

View 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;
/*

View 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;
}

View 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;

View file

@ -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,
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
* @lenp: return location for the string length or an error code on failure
*
* This is a shortcut for:
* 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.
*
* fdt_get_string_index(fdt, node, property, 0, output).
* 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
*/
int fdt_get_string(const void *fdt, int node, const char *property,
const char **output);
const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
const char *property, int index,
int *lenp);
/**********************************************************************/
/* Read-only functions (addressing related) */

View 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;

View 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;
for (i = 0; i < length; i++) {
int len = strlen(list);
end = list + length;
list += len + 1;
i += len;
while (list < end) {
length = strnlen(list, end - list) + 1;
/* Abort if the last string isn't properly NUL-terminated. */
if (list + length > end)
return -FDT_ERR_BADVALUE;
list += length;
count++;
}
return count;
}
int fdt_find_string(const void *fdt, int node, const char *property,
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;
if (l == len && memcmp(list, string, len) == 0)
return index;
/* Abort if the last string isn't properly NUL-terminated. */
if (list + length > end)
return -FDT_ERR_BADVALUE;
list += l + 1;
index++;
if (length == len && memcmp(list, string, length) == 0)
return idx;
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, node, property, &length);
list = fdt_getprop(fdt, nodeoffset, property, &length);
if (!list) {
if (lenp)
*lenp = length;
for (i = 0; i < length; i++) {
int len = strlen(list);
if (index == 0) {
*output = list;
return 0;
return NULL;
}
list += len + 1;
i += len;
index--;
end = list + length;
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;
}
return -FDT_ERR_NOTFOUND;
}
if (idx == 0) {
if (lenp)
*lenp = length - 1;
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 list;
}
list += length;
idx--;
}
if (lenp)
*lenp = -FDT_ERR_NOTFOUND;
return NULL;
}
int fdt_node_check_compatible(const void *fdt, int nodeoffset,

View 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)