On Thu, Nov 18, 2010 at 03:54:59PM -0800, Stephen Neuendorffer wrote:
> In preparation for providing run-time handling of device trees, factor
> out some of the basic functions so that they take an arbitrary blob,
> rather than relying on the single boot-time tree.
>
> Signed-off-by: Stephen Neuendorffer <[email protected]>
Thanks. Merged, but one comment below. Please fix with a followup patch.
g.
>
> --
>
> V2: functions have of_fdt_* names
> removed find_flat_dt_string
> blob argument is first
> ---
> drivers/of/fdt.c | 133 ++++++++++++++++++++++++++++-------------------
> include/linux/of_fdt.h | 11 ++++
> 2 files changed, 90 insertions(+), 54 deletions(-)
>
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index 4d71b29..190e26c 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -22,6 +22,82 @@
>
> #include <asm/page.h>
>
> +char *of_fdt_get_string(struct boot_param_header *blob, u32 offset)
> +{
> + return ((char *)blob) +
> + be32_to_cpu(blob->off_dt_strings) + offset;
> +}
> +
> +/**
> + * of_fdt_get_property - Given a node in the given flat blob, return
> + * the property ptr
> + */
> +void *of_fdt_get_property(struct boot_param_header *blob,
> + unsigned long node, const char *name,
> + unsigned long *size)
> +{
> + unsigned long p = node;
> +
> + do {
> + u32 tag = be32_to_cpup((__be32 *)p);
> + u32 sz, noff;
> + const char *nstr;
> +
> + p += 4;
> + if (tag == OF_DT_NOP)
> + continue;
> + if (tag != OF_DT_PROP)
> + return NULL;
> +
> + sz = be32_to_cpup((__be32 *)p);
> + noff = be32_to_cpup((__be32 *)(p + 4));
> + p += 8;
> + if (be32_to_cpu(blob->version) < 0x10)
> + p = ALIGN(p, sz >= 8 ? 8 : 4);
> +
> + nstr = of_fdt_get_string(blob, noff);
> + if (nstr == NULL) {
> + pr_warning("Can't find property index name !\n");
> + return NULL;
> + }
> + if (strcmp(name, nstr) == 0) {
> + if (size)
> + *size = sz;
> + return (void *)p;
> + }
> + p += sz;
> + p = ALIGN(p, 4);
> + } while (1);
> +}
> +
> +/**
> + * of_fdt_is_compatible - Return true if given node from the given blob has
> + * compat in its compatible list
> + * @blob: A device tree blob
> + * @node: node to test
> + * @compat: compatible string to compare with compatible list.
> + */
> +int of_fdt_is_compatible(struct boot_param_header *blob,
> + unsigned long node, const char *compat)
> +{
> + const char *cp;
> + unsigned long cplen, l;
> +
> + cp = of_fdt_get_property(blob, node, "compatible", &cplen);
> + if (cp == NULL)
> + return 0;
> + while (cplen > 0) {
> + if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
> + return 1;
Need to verify that strlen(cp) + 1 is not larger than cplen.
Otherwise cplen could wrap around and the loop won't terminate because
cplen is an unsigned long.
> + l = strlen(cp) + 1;
> + cp += l;
> + cplen -= l;
> + }
> +
> + return 0;
> +}
> +
> +/* Everything below here references initial_boot_params directly. */
> int __initdata dt_root_addr_cells;
> int __initdata dt_root_size_cells;
>
> @@ -29,12 +105,6 @@ struct boot_param_header *initial_boot_params;
>
> #ifdef CONFIG_EARLY_FLATTREE
>
> -char *find_flat_dt_string(u32 offset)
> -{
> - return ((char *)initial_boot_params) +
> - be32_to_cpu(initial_boot_params->off_dt_strings) + offset;
> -}
> -
> /**
> * of_scan_flat_dt - scan flattened tree blob and call callback on each.
> * @it: callback function
> @@ -123,38 +193,7 @@ unsigned long __init of_get_flat_dt_root(void)
> void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
> unsigned long *size)
> {
> - unsigned long p = node;
> -
> - do {
> - u32 tag = be32_to_cpup((__be32 *)p);
> - u32 sz, noff;
> - const char *nstr;
> -
> - p += 4;
> - if (tag == OF_DT_NOP)
> - continue;
> - if (tag != OF_DT_PROP)
> - return NULL;
> -
> - sz = be32_to_cpup((__be32 *)p);
> - noff = be32_to_cpup((__be32 *)(p + 4));
> - p += 8;
> - if (be32_to_cpu(initial_boot_params->version) < 0x10)
> - p = ALIGN(p, sz >= 8 ? 8 : 4);
> -
> - nstr = find_flat_dt_string(noff);
> - if (nstr == NULL) {
> - pr_warning("Can't find property index name !\n");
> - return NULL;
> - }
> - if (strcmp(name, nstr) == 0) {
> - if (size)
> - *size = sz;
> - return (void *)p;
> - }
> - p += sz;
> - p = ALIGN(p, 4);
> - } while (1);
> + return of_fdt_get_property(initial_boot_params, node, name, size);
> }
>
> /**
> @@ -164,21 +203,7 @@ void *__init of_get_flat_dt_prop(unsigned long node,
> const char *name,
> */
> int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
> {
> - const char *cp;
> - unsigned long cplen, l;
> -
> - cp = of_get_flat_dt_prop(node, "compatible", &cplen);
> - if (cp == NULL)
> - return 0;
> - while (cplen > 0) {
> - if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
> - return 1;
> - l = strlen(cp) + 1;
> - cp += l;
> - cplen -= l;
> - }
> -
> - return 0;
> + return of_fdt_is_compatible(initial_boot_params, node, compat);
> }
>
> static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long
> size,
> @@ -303,7 +328,7 @@ unsigned long __init unflatten_dt_node(unsigned long mem,
> if (be32_to_cpu(initial_boot_params->version) < 0x10)
> *p = ALIGN(*p, sz >= 8 ? 8 : 4);
>
> - pname = find_flat_dt_string(noff);
> + pname = of_fdt_get_string(initial_boot_params, noff);
> if (pname == NULL) {
> pr_info("Can't find property name in list !\n");
> break;
> diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
> index 7bbf5b3..70c5b73 100644
> --- a/include/linux/of_fdt.h
> +++ b/include/linux/of_fdt.h
> @@ -58,6 +58,17 @@ struct boot_param_header {
> };
>
> #if defined(CONFIG_OF_FLATTREE)
> +
> +/* For scanning an arbitrary device-tree at any time */
> +extern char *of_fdt_get_string(struct boot_param_header *blob, u32 offset);
> +extern void *of_fdt_get_property(struct boot_param_header *blob,
> + unsigned long node,
> + const char *name,
> + unsigned long *size);
> +extern int of_fdt_is_compatible(struct boot_param_header *blob,
> + unsigned long node,
> + const char *compat);
> +
> /* TBD: Temporary export of fdt globals - remove when code fully merged */
> extern int __initdata dt_root_addr_cells;
> extern int __initdata dt_root_size_cells;
> --
> 1.5.6.6
>
>
>
> This email and any attachments are intended for the sole use of the named
> recipient(s) and contain(s) confidential information that may be proprietary,
> privileged or copyrighted under applicable law. If you are not the intended
> recipient, do not read, copy, or forward this email message or any
> attachments. Delete this email message and any attachments immediately.
>
>
_______________________________________________
devicetree-discuss mailing list
[email protected]
https://lists.ozlabs.org/listinfo/devicetree-discuss