summaryrefslogtreecommitdiffstats
path: root/scripts/dtc/libfdt/fdt.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-03 18:44:08 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-03 18:44:08 +0200
commita54dfb1a845c38a97686268d8c4086a63d9493aa (patch)
tree3b31c81672fa89102aae929cc6c1e48e6e9382f4 /scripts/dtc/libfdt/fdt.c
parentMerge tag 'jfs-3.7' of git://github.com/kleikamp/linux-shaggy (diff)
parentMAINTAINERS: add scripts/dtc under Devicetree maintainers (diff)
downloadlinux-a54dfb1a845c38a97686268d8c4086a63d9493aa.tar.xz
linux-a54dfb1a845c38a97686268d8c4086a63d9493aa.zip
Merge tag 'dt-for-3.7' of git://sources.calxeda.com/kernel/linux
Pull devicetree updates from Rob Herring: - Import of latest upstream device tree compiler (dtc) - New function of_get_child_by_name - Support for #size-cells of 0 and #addr-cells of >2 - Couple of DT binding documentation updates Fix up trivial conflicts due to of_get_child_by_name() having been added next to the new of_get_next_available_child(). * tag 'dt-for-3.7' of git://sources.calxeda.com/kernel/linux: MAINTAINERS: add scripts/dtc under Devicetree maintainers dtc: import latest upstream dtc dt: Document general interrupt controller bindings dt/s3c64xx/spi: Use of_get_child_by_name to get a named child dt: introduce of_get_child_by_name to get child node by name of: i2c: add support for wakeup-source property of/address: Handle #address-cells > 2 specially DT: export of_irq_to_resource_table() devicetree: serial: Add documentation for imx serial devicetree: pwm: mxs-pwm.txt: Fix reg field annotation of: Allow busses with #size-cells=0
Diffstat (limited to 'scripts/dtc/libfdt/fdt.c')
-rw-r--r--scripts/dtc/libfdt/fdt.c61
1 files changed, 41 insertions, 20 deletions
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 2acaec5923ae..e56833ae9b6f 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -74,7 +74,7 @@ int fdt_check_header(const void *fdt)
return 0;
}
-const void *fdt_offset_ptr(const void *fdt, int offset, int len)
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
const char *p;
@@ -90,42 +90,53 @@ const void *fdt_offset_ptr(const void *fdt, int offset, int len)
return p;
}
-uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
+uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
const uint32_t *tagp, *lenp;
uint32_t tag;
+ int offset = startoffset;
const char *p;
- if (offset % FDT_TAGSIZE)
- return -1;
-
+ *nextoffset = -FDT_ERR_TRUNCATED;
tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
- if (! tagp)
+ if (!tagp)
return FDT_END; /* premature end */
tag = fdt32_to_cpu(*tagp);
offset += FDT_TAGSIZE;
+ *nextoffset = -FDT_ERR_BADSTRUCTURE;
switch (tag) {
case FDT_BEGIN_NODE:
/* skip name */
do {
p = fdt_offset_ptr(fdt, offset++, 1);
} while (p && (*p != '\0'));
- if (! p)
- return FDT_END;
+ if (!p)
+ return FDT_END; /* premature end */
break;
+
case FDT_PROP:
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
- if (! lenp)
- return FDT_END;
- /* skip name offset, length and value */
- offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
+ if (!lenp)
+ return FDT_END; /* premature end */
+ /* skip-name offset, length and value */
+ offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ + fdt32_to_cpu(*lenp);
+ break;
+
+ case FDT_END:
+ case FDT_END_NODE:
+ case FDT_NOP:
break;
+
+ default:
+ return FDT_END;
}
- if (nextoffset)
- *nextoffset = FDT_TAGALIGN(offset);
+ if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
+ return FDT_END; /* premature end */
+ *nextoffset = FDT_TAGALIGN(offset);
return tag;
}
@@ -138,6 +149,15 @@ int _fdt_check_node_offset(const void *fdt, int offset)
return offset;
}
+int _fdt_check_prop_offset(const void *fdt, int offset)
+{
+ if ((offset < 0) || (offset % FDT_TAGSIZE)
+ || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
+ return -FDT_ERR_BADOFFSET;
+
+ return offset;
+}
+
int fdt_next_node(const void *fdt, int offset, int *depth)
{
int nextoffset = 0;
@@ -162,15 +182,16 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
break;
case FDT_END_NODE:
- if (depth)
- (*depth)--;
+ if (depth && ((--(*depth)) < 0))
+ return nextoffset;
break;
case FDT_END:
- return -FDT_ERR_NOTFOUND;
-
- default:
- return -FDT_ERR_BADSTRUCTURE;
+ if ((nextoffset >= 0)
+ || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth))
+ return -FDT_ERR_NOTFOUND;
+ else
+ return nextoffset;
}
} while (tag != FDT_BEGIN_NODE);