summaryrefslogtreecommitdiff
path: root/scripts/dtc/libfdt
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/dtc/libfdt')
-rw-r--r--scripts/dtc/libfdt/fdt.c59
-rw-r--r--scripts/dtc/libfdt/fdt.h4
-rw-r--r--scripts/dtc/libfdt/fdt_addresses.c2
-rw-r--r--scripts/dtc/libfdt/fdt_overlay.c381
-rw-r--r--scripts/dtc/libfdt/fdt_ro.c79
-rw-r--r--scripts/dtc/libfdt/fdt_rw.c24
-rw-r--r--scripts/dtc/libfdt/fdt_strerror.c5
-rw-r--r--scripts/dtc/libfdt/fdt_sw.c29
-rw-r--r--scripts/dtc/libfdt/fdt_wip.c2
-rw-r--r--scripts/dtc/libfdt/libfdt.h223
-rw-r--r--scripts/dtc/libfdt/libfdt_internal.h19
11 files changed, 634 insertions, 193 deletions
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index c28fcc115771..20c6415b9ced 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -22,6 +22,10 @@ int32_t fdt_ro_probe_(const void *fdt)
if (can_assume(VALID_DTB))
return totalsize;
+ /* The device tree must be at an 8-byte aligned address */
+ if ((uintptr_t)fdt & 7)
+ return -FDT_ERR_ALIGNMENT;
+
if (fdt_magic(fdt) == FDT_MAGIC) {
/* Complete tree */
if (!can_assume(LATEST)) {
@@ -86,6 +90,10 @@ int fdt_check_header(const void *fdt)
{
size_t hdrsize;
+ /* The device tree must be at an 8-byte aligned address */
+ if ((uintptr_t)fdt & 7)
+ return -FDT_ERR_ALIGNMENT;
+
if (fdt_magic(fdt) != FDT_MAGIC)
return -FDT_ERR_BADMAGIC;
if (!can_assume(LATEST)) {
@@ -98,7 +106,6 @@ int fdt_check_header(const void *fdt)
}
hdrsize = fdt_header_size(fdt);
if (!can_assume(VALID_DTB)) {
-
if ((fdt_totalsize(fdt) < hdrsize)
|| (fdt_totalsize(fdt) > INT_MAX))
return -FDT_ERR_TRUNCATED;
@@ -107,9 +114,7 @@ int fdt_check_header(const void *fdt)
if (!check_off_(hdrsize, fdt_totalsize(fdt),
fdt_off_mem_rsvmap(fdt)))
return -FDT_ERR_TRUNCATED;
- }
- if (!can_assume(VALID_DTB)) {
/* Bounds check structure block */
if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
if (!check_off_(hdrsize, fdt_totalsize(fdt),
@@ -134,16 +139,20 @@ int fdt_check_header(const void *fdt)
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
- unsigned absoffset = offset + fdt_off_dt_struct(fdt);
+ unsigned int uoffset = offset;
+ unsigned int absoffset = offset + fdt_off_dt_struct(fdt);
+
+ if (offset < 0)
+ return NULL;
if (!can_assume(VALID_INPUT))
- if ((absoffset < offset)
+ if ((absoffset < uoffset)
|| ((absoffset + len) < absoffset)
|| (absoffset + len) > fdt_totalsize(fdt))
return NULL;
if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
- if (((offset + len) < offset)
+ if (((uoffset + len) < uoffset)
|| ((offset + len) > fdt_size_dt_struct(fdt)))
return NULL;
@@ -153,7 +162,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
const fdt32_t *tagp, *lenp;
- uint32_t tag;
+ uint32_t tag, len, sum;
int offset = startoffset;
const char *p;
@@ -179,12 +188,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
if (!can_assume(VALID_DTB) && !lenp)
return FDT_END; /* premature end */
+
+ len = fdt32_to_cpu(*lenp);
+ sum = len + offset;
+ if (!can_assume(VALID_DTB) &&
+ (INT_MAX <= sum || sum < (uint32_t) offset))
+ return FDT_END; /* premature end */
+
/* skip-name offset, length and value */
- offset += sizeof(struct fdt_property) - FDT_TAGSIZE
- + fdt32_to_cpu(*lenp);
+ offset += sizeof(struct fdt_property) - FDT_TAGSIZE + len;
+
if (!can_assume(LATEST) &&
- fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
- ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
+ fdt_version(fdt) < 0x10 && len >= 8 &&
+ ((offset - len) % 8) != 0)
offset += 4;
break;
@@ -206,10 +222,11 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
int fdt_check_node_offset_(const void *fdt, int offset)
{
- if (can_assume(VALID_INPUT))
- return offset;
- if ((offset < 0) || (offset % FDT_TAGSIZE)
- || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
+ if (!can_assume(VALID_INPUT)
+ && ((offset < 0) || (offset % FDT_TAGSIZE)))
+ return -FDT_ERR_BADOFFSET;
+
+ if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)
return -FDT_ERR_BADOFFSET;
return offset;
@@ -217,8 +234,11 @@ int fdt_check_node_offset_(const void *fdt, int 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))
+ if (!can_assume(VALID_INPUT)
+ && ((offset < 0) || (offset % FDT_TAGSIZE)))
+ return -FDT_ERR_BADOFFSET;
+
+ if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)
return -FDT_ERR_BADOFFSET;
return offset;
@@ -306,9 +326,12 @@ const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)
int fdt_move(const void *fdt, void *buf, int bufsize)
{
+ if (!can_assume(VALID_INPUT) && bufsize < 0)
+ return -FDT_ERR_NOSPACE;
+
FDT_RO_PROBE(fdt);
- if (fdt_totalsize(fdt) > bufsize)
+ if (fdt_totalsize(fdt) > (unsigned int)bufsize)
return -FDT_ERR_NOSPACE;
memmove(buf, fdt, fdt_totalsize(fdt));
diff --git a/scripts/dtc/libfdt/fdt.h b/scripts/dtc/libfdt/fdt.h
index f2e68807f277..0c91aa7f67b5 100644
--- a/scripts/dtc/libfdt/fdt.h
+++ b/scripts/dtc/libfdt/fdt.h
@@ -35,14 +35,14 @@ struct fdt_reserve_entry {
struct fdt_node_header {
fdt32_t tag;
- char name[0];
+ char name[];
};
struct fdt_property {
fdt32_t tag;
fdt32_t len;
fdt32_t nameoff;
- char data[0];
+ char data[];
};
#endif /* !__ASSEMBLY */
diff --git a/scripts/dtc/libfdt/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c
index 9a82cd0ba2f9..c40ba094f1f8 100644
--- a/scripts/dtc/libfdt/fdt_addresses.c
+++ b/scripts/dtc/libfdt/fdt_addresses.c
@@ -73,7 +73,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
/* check validity of address */
prop = data;
if (addr_cells == 1) {
- if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
+ if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size))
return -FDT_ERR_BADVALUE;
fdt32_st(prop, (uint32_t)addr);
diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c
index b310e49a698e..28b667ffc490 100644
--- a/scripts/dtc/libfdt/fdt_overlay.c
+++ b/scripts/dtc/libfdt/fdt_overlay.c
@@ -40,37 +40,22 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
return fdt32_to_cpu(*val);
}
-/**
- * overlay_get_target - retrieves the offset of a fragment's target
- * @fdt: Base device tree blob
- * @fdto: Device tree overlay blob
- * @fragment: node offset of the fragment in the overlay
- * @pathp: pointer which receives the path of the target (or NULL)
- *
- * overlay_get_target() retrieves the target offset in the base
- * device tree of a fragment, no matter how the actual targeting is
- * done (through a phandle or a path)
- *
- * returns:
- * the targeted node offset in the base device tree
- * Negative error code on error
- */
-static int overlay_get_target(const void *fdt, const void *fdto,
- int fragment, char const **pathp)
+int fdt_overlay_target_offset(const void *fdt, const void *fdto,
+ int fragment_offset, char const **pathp)
{
uint32_t phandle;
const char *path = NULL;
int path_len = 0, ret;
/* Try first to do a phandle based lookup */
- phandle = overlay_get_target_phandle(fdto, fragment);
+ phandle = overlay_get_target_phandle(fdto, fragment_offset);
if (phandle == (uint32_t)-1)
return -FDT_ERR_BADPHANDLE;
/* no phandle, try path */
if (!phandle) {
/* And then a path based lookup */
- path = fdt_getprop(fdto, fragment, "target-path", &path_len);
+ path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len);
if (path)
ret = fdt_path_offset(fdt, path);
else
@@ -116,26 +101,22 @@ static int overlay_get_target(const void *fdt, const void *fdto,
static int overlay_phandle_add_offset(void *fdt, int node,
const char *name, uint32_t delta)
{
- const fdt32_t *val;
- uint32_t adj_val;
+ fdt32_t *valp, val;
int len;
- val = fdt_getprop(fdt, node, name, &len);
- if (!val)
+ valp = fdt_getprop_w(fdt, node, name, &len);
+ if (!valp)
return len;
- if (len != sizeof(*val))
+ if (len != sizeof(val))
return -FDT_ERR_BADPHANDLE;
- adj_val = fdt32_to_cpu(*val);
- if ((adj_val + delta) < adj_val)
- return -FDT_ERR_NOPHANDLES;
-
- adj_val += delta;
- if (adj_val == (uint32_t)-1)
+ val = fdt32_ld(valp);
+ if (val + delta < val || val + delta == (uint32_t)-1)
return -FDT_ERR_NOPHANDLES;
- return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
+ fdt32_st(valp, val + delta);
+ return 0;
}
/**
@@ -228,8 +209,8 @@ static int overlay_update_local_node_references(void *fdto,
fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
const fdt32_t *fixup_val;
- const char *tree_val;
const char *name;
+ char *tree_val;
int fixup_len;
int tree_len;
int i;
@@ -241,8 +222,9 @@ static int overlay_update_local_node_references(void *fdto,
if (fixup_len % sizeof(uint32_t))
return -FDT_ERR_BADOVERLAY;
+ fixup_len /= sizeof(uint32_t);
- tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
+ tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);
if (!tree_val) {
if (tree_len == -FDT_ERR_NOTFOUND)
return -FDT_ERR_BADOVERLAY;
@@ -250,34 +232,16 @@ static int overlay_update_local_node_references(void *fdto,
return tree_len;
}
- for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) {
- fdt32_t adj_val;
- uint32_t poffset;
+ for (i = 0; i < fixup_len; i++) {
+ fdt32_t *refp;
- poffset = fdt32_to_cpu(fixup_val[i]);
+ refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
/*
- * phandles to fixup can be unaligned.
- *
- * Use a memcpy for the architectures that do
- * not support unaligned accesses.
+ * phandles to fixup can be unaligned, so use
+ * fdt32_{ld,st}() to read/write them.
*/
- memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
-
- adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);
-
- ret = fdt_setprop_inplace_namelen_partial(fdto,
- tree_node,
- name,
- strlen(name),
- poffset,
- &adj_val,
- sizeof(adj_val));
- if (ret == -FDT_ERR_NOSPACE)
- return -FDT_ERR_BADOVERLAY;
-
- if (ret)
- return ret;
+ fdt32_st(refp, fdt32_ld(refp) + delta);
}
}
@@ -351,7 +315,7 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
* @name: Name of the property holding the phandle reference in the overlay
* @name_len: number of name characters to consider
* @poffset: Offset within the overlay property where the phandle is stored
- * @label: Label of the node referenced by the phandle
+ * @phandle: Phandle referencing the node
*
* overlay_fixup_one_phandle() resolves an overlay phandle pointing to
* a node in the base device tree.
@@ -368,30 +332,14 @@ static int overlay_fixup_one_phandle(void *fdt, void *fdto,
int symbols_off,
const char *path, uint32_t path_len,
const char *name, uint32_t name_len,
- int poffset, const char *label)
+ int poffset, uint32_t phandle)
{
- const char *symbol_path;
- uint32_t phandle;
fdt32_t phandle_prop;
- int symbol_off, fixup_off;
- int prop_len;
+ int fixup_off;
if (symbols_off < 0)
return symbols_off;
- symbol_path = fdt_getprop(fdt, symbols_off, label,
- &prop_len);
- if (!symbol_path)
- return prop_len;
-
- symbol_off = fdt_path_offset(fdt, symbol_path);
- if (symbol_off < 0)
- return symbol_off;
-
- phandle = fdt_get_phandle(fdt, symbol_off);
- if (!phandle)
- return -FDT_ERR_NOTFOUND;
-
fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
if (fixup_off == -FDT_ERR_NOTFOUND)
return -FDT_ERR_BADOVERLAY;
@@ -430,6 +378,10 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
const char *value;
const char *label;
int len;
+ const char *symbol_path;
+ int prop_len;
+ int symbol_off;
+ uint32_t phandle;
value = fdt_getprop_by_offset(fdto, property,
&label, &len);
@@ -440,6 +392,18 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
return len;
}
+ symbol_path = fdt_getprop(fdt, symbols_off, label, &prop_len);
+ if (!symbol_path)
+ return prop_len;
+
+ symbol_off = fdt_path_offset(fdt, symbol_path);
+ if (symbol_off < 0)
+ return symbol_off;
+
+ phandle = fdt_get_phandle(fdt, symbol_off);
+ if (!phandle)
+ return -FDT_ERR_NOTFOUND;
+
do {
const char *path, *name, *fixup_end;
const char *fixup_str = value;
@@ -481,7 +445,7 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
path, path_len, name, name_len,
- poffset, label);
+ poffset, phandle);
if (ret)
return ret;
} while (len > 0);
@@ -535,6 +499,255 @@ static int overlay_fixup_phandles(void *fdt, void *fdto)
}
/**
+ * overlay_adjust_local_conflicting_phandle: Changes a phandle value
+ * @fdto: Device tree overlay
+ * @node: The node the phandle is set for
+ * @fdt_phandle: The new value for the phandle
+ *
+ * returns:
+ * 0 on success
+ * Negative error code on failure
+ */
+static int overlay_adjust_local_conflicting_phandle(void *fdto, int node,
+ uint32_t fdt_phandle)
+{
+ const fdt32_t *php;
+ int len, ret;
+
+ php = fdt_getprop(fdto, node, "phandle", &len);
+ if (php && len == sizeof(*php)) {
+ ret = fdt_setprop_inplace_u32(fdto, node, "phandle", fdt_phandle);
+ if (ret)
+ return ret;
+ }
+
+ php = fdt_getprop(fdto, node, "linux,phandle", &len);
+ if (php && len == sizeof(*php)) {
+ ret = fdt_setprop_inplace_u32(fdto, node, "linux,phandle", fdt_phandle);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * overlay_update_node_conflicting_references - Recursively replace phandle values
+ * @fdto: Device tree overlay blob
+ * @tree_node: Node to recurse into
+ * @fixup_node: Node offset of the matching local fixups node
+ * @fdt_phandle: Value to replace phandles with
+ * @fdto_phandle: Value to be replaced
+ *
+ * Replaces all phandles with value @fdto_phandle by @fdt_phandle.
+ *
+ * returns:
+ * 0 on success
+ * Negative error code on failure
+ */
+static int overlay_update_node_conflicting_references(void *fdto, int tree_node,
+ int fixup_node,
+ uint32_t fdt_phandle,
+ uint32_t fdto_phandle)
+{
+ int fixup_prop;
+ int fixup_child;
+ int ret;
+
+ fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
+ const fdt32_t *fixup_val;
+ const char *name;
+ char *tree_val;
+ int fixup_len;
+ int tree_len;
+ int i;
+
+ fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
+ &name, &fixup_len);
+ if (!fixup_val)
+ return fixup_len;
+
+ if (fixup_len % sizeof(uint32_t))
+ return -FDT_ERR_BADOVERLAY;
+ fixup_len /= sizeof(uint32_t);
+
+ tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);
+ if (!tree_val) {
+ if (tree_len == -FDT_ERR_NOTFOUND)
+ return -FDT_ERR_BADOVERLAY;
+
+ return tree_len;
+ }
+
+ for (i = 0; i < fixup_len; i++) {
+ fdt32_t *refp;
+ uint32_t valp;
+
+ refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
+ valp = fdt32_ld(refp);
+
+ if (valp == fdto_phandle)
+ fdt32_st(refp, fdt_phandle);
+ }
+ }
+
+ fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
+ const char *fixup_child_name = fdt_get_name(fdto, fixup_child, NULL);
+ int tree_child;
+
+ tree_child = fdt_subnode_offset(fdto, tree_node, fixup_child_name);
+
+ if (tree_child == -FDT_ERR_NOTFOUND)
+ return -FDT_ERR_BADOVERLAY;
+ if (tree_child < 0)
+ return tree_child;
+
+ ret = overlay_update_node_conflicting_references(fdto, tree_child,
+ fixup_child,
+ fdt_phandle,
+ fdto_phandle);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * overlay_update_local_conflicting_references - Recursively replace phandle values
+ * @fdto: Device tree overlay blob
+ * @fdt_phandle: Value to replace phandles with
+ * @fdto_phandle: Value to be replaced
+ *
+ * Replaces all phandles with value @fdto_phandle by @fdt_phandle.
+ *
+ * returns:
+ * 0 on success
+ * Negative error code on failure
+ */
+static int overlay_update_local_conflicting_references(void *fdto,
+ uint32_t fdt_phandle,
+ uint32_t fdto_phandle)
+{
+ int fixups;
+
+ fixups = fdt_path_offset(fdto, "/__local_fixups__");
+ if (fixups == -FDT_ERR_NOTFOUND)
+ return 0;
+ if (fixups < 0)
+ return fixups;
+
+ return overlay_update_node_conflicting_references(fdto, 0, fixups,
+ fdt_phandle,
+ fdto_phandle);
+}
+
+/**
+ * overlay_prevent_phandle_overwrite_node - Helper function for overlay_prevent_phandle_overwrite
+ * @fdt: Base Device tree blob
+ * @fdtnode: Node in fdt that is checked for an overwrite
+ * @fdto: Device tree overlay blob
+ * @fdtonode: Node in fdto matching @fdtnode
+ *
+ * returns:
+ * 0 on success
+ * Negative error code on failure
+ */
+static int overlay_prevent_phandle_overwrite_node(void *fdt, int fdtnode,
+ void *fdto, int fdtonode)
+{
+ uint32_t fdt_phandle, fdto_phandle;
+ int fdtochild;
+
+ fdt_phandle = fdt_get_phandle(fdt, fdtnode);
+ fdto_phandle = fdt_get_phandle(fdto, fdtonode);
+
+ if (fdt_phandle && fdto_phandle) {
+ int ret;
+
+ ret = overlay_adjust_local_conflicting_phandle(fdto, fdtonode,
+ fdt_phandle);
+ if (ret)
+ return ret;
+
+ ret = overlay_update_local_conflicting_references(fdto,
+ fdt_phandle,
+ fdto_phandle);
+ if (ret)
+ return ret;
+ }
+
+ fdt_for_each_subnode(fdtochild, fdto, fdtonode) {
+ const char *name = fdt_get_name(fdto, fdtochild, NULL);
+ int fdtchild;
+ int ret;
+
+ fdtchild = fdt_subnode_offset(fdt, fdtnode, name);
+ if (fdtchild == -FDT_ERR_NOTFOUND)
+ /*
+ * no further overwrites possible here as this node is
+ * new
+ */
+ continue;
+
+ ret = overlay_prevent_phandle_overwrite_node(fdt, fdtchild,
+ fdto, fdtochild);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * overlay_prevent_phandle_overwrite - Fixes overlay phandles to not overwrite base phandles
+ * @fdt: Base Device Tree blob
+ * @fdto: Device tree overlay blob
+ *
+ * Checks recursively if applying fdto overwrites phandle values in the base
+ * dtb. When such a phandle is found, the fdto is changed to use the fdt's
+ * phandle value to not break references in the base.
+ *
+ * returns:
+ * 0 on success
+ * Negative error code on failure
+ */
+static int overlay_prevent_phandle_overwrite(void *fdt, void *fdto)
+{
+ int fragment;
+
+ fdt_for_each_subnode(fragment, fdto, 0) {
+ int overlay;
+ int target;
+ int ret;
+
+ overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
+ if (overlay == -FDT_ERR_NOTFOUND)
+ continue;
+
+ if (overlay < 0)
+ return overlay;
+
+ target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
+ if (target == -FDT_ERR_NOTFOUND)
+ /*
+ * The subtree doesn't exist in the base, so nothing
+ * will be overwritten.
+ */
+ continue;
+ else if (target < 0)
+ return target;
+
+ ret = overlay_prevent_phandle_overwrite_node(fdt, target,
+ fdto, overlay);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
* overlay_apply_node - Merges a node into the base device tree
* @fdt: Base Device Tree blob
* @target: Node offset in the base device tree to apply the fragment to
@@ -635,7 +848,7 @@ static int overlay_merge(void *fdt, void *fdto)
if (overlay < 0)
return overlay;
- target = overlay_get_target(fdt, fdto, fragment, NULL);
+ target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
if (target < 0)
return target;
@@ -778,7 +991,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
return -FDT_ERR_BADOVERLAY;
/* get the target of the fragment */
- ret = overlay_get_target(fdt, fdto, fragment, &target_path);
+ ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
if (ret < 0)
return ret;
target = ret;
@@ -800,7 +1013,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
if (!target_path) {
/* again in case setprop_placeholder changed it */
- ret = overlay_get_target(fdt, fdto, fragment, &target_path);
+ ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
if (ret < 0)
return ret;
target = ret;
@@ -838,18 +1051,26 @@ int fdt_overlay_apply(void *fdt, void *fdto)
if (ret)
goto err;
+ /* Increase all phandles in the fdto by delta */
ret = overlay_adjust_local_phandles(fdto, delta);
if (ret)
goto err;
+ /* Adapt the phandle values in fdto to the above increase */
ret = overlay_update_local_references(fdto, delta);
if (ret)
goto err;
+ /* Update fdto's phandles using symbols from fdt */
ret = overlay_fixup_phandles(fdt, fdto);
if (ret)
goto err;
+ /* Don't overwrite phandles in fdt */
+ ret = overlay_prevent_phandle_overwrite(fdt, fdto);
+ if (ret)
+ goto err;
+
ret = overlay_merge(fdt, fdto);
if (ret)
goto err;
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index e03570a56eb5..b78c4e48f1cb 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -53,7 +53,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
err = -FDT_ERR_BADOFFSET;
absoffset = stroffset + fdt_off_dt_strings(fdt);
- if (absoffset >= totalsize)
+ if (absoffset >= (unsigned)totalsize)
goto fail;
len = totalsize - absoffset;
@@ -61,17 +61,19 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
if (stroffset < 0)
goto fail;
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
- if (stroffset >= fdt_size_dt_strings(fdt))
+ if ((unsigned)stroffset >= fdt_size_dt_strings(fdt))
goto fail;
if ((fdt_size_dt_strings(fdt) - stroffset) < len)
len = fdt_size_dt_strings(fdt) - stroffset;
}
} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
- if ((stroffset >= 0)
- || (stroffset < -fdt_size_dt_strings(fdt)))
+ unsigned int sw_stroffset = -stroffset;
+
+ if ((stroffset >= 0) ||
+ (sw_stroffset > fdt_size_dt_strings(fdt)))
goto fail;
- if ((-stroffset) < len)
- len = -stroffset;
+ if (sw_stroffset < len)
+ len = sw_stroffset;
} else {
err = -FDT_ERR_INTERNAL;
goto fail;
@@ -157,8 +159,8 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
{
- int offset = n * sizeof(struct fdt_reserve_entry);
- int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
+ unsigned int offset = n * sizeof(struct fdt_reserve_entry);
+ unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
if (!can_assume(VALID_INPUT)) {
if (absoffset < fdt_off_mem_rsvmap(fdt))
@@ -179,8 +181,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
if (!can_assume(VALID_INPUT) && !re)
return -FDT_ERR_BADOFFSET;
- *address = fdt64_ld(&re->address);
- *size = fdt64_ld(&re->size);
+ *address = fdt64_ld_(&re->address);
+ *size = fdt64_ld_(&re->size);
return 0;
}
@@ -190,7 +192,7 @@ int fdt_num_mem_rsv(const void *fdt)
const struct fdt_reserve_entry *re;
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
- if (fdt64_ld(&re->size) == 0)
+ if (fdt64_ld_(&re->size) == 0)
return i;
}
return -FDT_ERR_TRUNCATED;
@@ -253,6 +255,9 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
FDT_RO_PROBE(fdt);
+ if (!can_assume(VALID_INPUT) && namelen <= 0)
+ return -FDT_ERR_BADPATH;
+
/* see if we have an alias */
if (*path != '/') {
const char *q = memchr(path, '/', end - p);
@@ -368,7 +373,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
prop = fdt_offset_ptr_(fdt, offset);
if (lenp)
- *lenp = fdt32_ld(&prop->len);
+ *lenp = fdt32_ld_(&prop->len);
return prop;
}
@@ -406,7 +411,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
offset = -FDT_ERR_INTERNAL;
break;
}
- if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
+ if (fdt_string_eq_(fdt, fdt32_ld_(&prop->nameoff),
name, namelen)) {
if (poffset)
*poffset = offset;
@@ -459,7 +464,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
- (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
+ (poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@@ -477,22 +482,22 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
int namelen;
if (!can_assume(VALID_INPUT)) {
- name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
+ name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff),
&namelen);
+ *namep = name;
if (!name) {
if (lenp)
*lenp = namelen;
return NULL;
}
- *namep = name;
} else {
- *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
+ *namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
}
}
/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
- (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
+ (offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@@ -517,19 +522,34 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
return 0;
}
- return fdt32_ld(php);
+ return fdt32_ld_(php);
+}
+
+static const void *fdt_path_getprop_namelen(const void *fdt, const char *path,
+ const char *propname, int propnamelen,
+ int *lenp)
+{
+ int offset = fdt_path_offset(fdt, path);
+
+ if (offset < 0)
+ return NULL;
+
+ return fdt_getprop_namelen(fdt, offset, propname, propnamelen, lenp);
}
const char *fdt_get_alias_namelen(const void *fdt,
const char *name, int namelen)
{
- int aliasoffset;
+ int len;
+ const char *alias;
+
+ alias = fdt_path_getprop_namelen(fdt, "/aliases", name, namelen, &len);
- aliasoffset = fdt_path_offset(fdt, "/aliases");
- if (aliasoffset < 0)
+ if (!can_assume(VALID_DTB) &&
+ !(alias && len > 0 && alias[len - 1] == '\0' && *alias == '/'))
return NULL;
- return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
+ return alias;
}
const char *fdt_get_alias(const void *fdt, const char *name)
@@ -537,6 +557,17 @@ const char *fdt_get_alias(const void *fdt, const char *name)
return fdt_get_alias_namelen(fdt, name, strlen(name));
}
+const char *fdt_get_symbol_namelen(const void *fdt,
+ const char *name, int namelen)
+{
+ return fdt_path_getprop_namelen(fdt, "/__symbols__", name, namelen, NULL);
+}
+
+const char *fdt_get_symbol(const void *fdt, const char *name)
+{
+ return fdt_get_symbol_namelen(fdt, name, strlen(name));
+}
+
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
{
int pdepth = 0, p = 0;
@@ -680,7 +711,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
{
int offset;
- if ((phandle == 0) || (phandle == -1))
+ if ((phandle == 0) || (phandle == ~0U))
return -FDT_ERR_BADPHANDLE;
FDT_RO_PROBE(fdt);
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 93e4a2b56348..3621d3651d3f 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -59,7 +59,7 @@ static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
return -FDT_ERR_BADOFFSET;
- if ((p < (char *)fdt) || (dsize + newlen < oldlen))
+ if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen))
return -FDT_ERR_BADOFFSET;
if (dsize - oldlen + newlen > fdt_totalsize(fdt))
return -FDT_ERR_NOSPACE;
@@ -349,7 +349,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
return offset;
/* Try to place the new node after the parent's properties */
- fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
+ tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
+ /* the fdt_subnode_offset_namelen() should ensure this never hits */
+ if (!can_assume(LIBFDT_FLAWLESS) && (tag != FDT_BEGIN_NODE))
+ return -FDT_ERR_INTERNAL;
do {
offset = nextoffset;
tag = fdt_next_tag(fdt, offset, &nextoffset);
@@ -391,7 +394,9 @@ int fdt_del_node(void *fdt, int nodeoffset)
}
static void fdt_packblocks_(const char *old, char *new,
- int mem_rsv_size, int struct_size)
+ int mem_rsv_size,
+ int struct_size,
+ int strings_size)
{
int mem_rsv_off, struct_off, strings_off;
@@ -406,8 +411,7 @@ static void fdt_packblocks_(const char *old, char *new,
fdt_set_off_dt_struct(new, struct_off);
fdt_set_size_dt_struct(new, struct_size);
- memmove(new + strings_off, old + fdt_off_dt_strings(old),
- fdt_size_dt_strings(old));
+ memmove(new + strings_off, old + fdt_off_dt_strings(old), strings_size);
fdt_set_off_dt_strings(new, strings_off);
fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
}
@@ -428,12 +432,14 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
struct_size = fdt_size_dt_struct(fdt);
- } else {
+ } else if (fdt_version(fdt) == 16) {
struct_size = 0;
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
;
if (struct_size < 0)
return struct_size;
+ } else {
+ return -FDT_ERR_BADVERSION;
}
if (can_assume(LIBFDT_ORDER) ||
@@ -465,7 +471,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
return -FDT_ERR_NOSPACE;
}
- fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size);
+ fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size,
+ fdt_size_dt_strings(fdt));
memmove(buf, tmp, newsize);
fdt_set_magic(buf, FDT_MAGIC);
@@ -485,7 +492,8 @@ int fdt_pack(void *fdt)
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry);
- fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
+ fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt),
+ fdt_size_dt_strings(fdt));
fdt_set_totalsize(fdt, fdt_data_size_(fdt));
return 0;
diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c
index 768db66eada5..d852b77e81e7 100644
--- a/scripts/dtc/libfdt/fdt_strerror.c
+++ b/scripts/dtc/libfdt/fdt_strerror.c
@@ -39,8 +39,9 @@ static struct fdt_errtabent fdt_errtable[] = {
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
FDT_ERRTABENT(FDT_ERR_BADFLAGS),
+ FDT_ERRTABENT(FDT_ERR_ALIGNMENT),
};
-#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
+#define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0])))
const char *fdt_strerror(int errval)
{
@@ -48,7 +49,7 @@ const char *fdt_strerror(int errval)
return "<valid offset/length>";
else if (errval == 0)
return "<no error>";
- else if (errval > -FDT_ERRTABSIZE) {
+ else if (-errval < FDT_ERRTABSIZE) {
const char *s = fdt_errtable[-errval].str;
if (s)
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
index 94ce4bb91a00..4c569ee7eb0d 100644
--- a/scripts/dtc/libfdt/fdt_sw.c
+++ b/scripts/dtc/libfdt/fdt_sw.c
@@ -93,8 +93,8 @@ static inline uint32_t sw_flags(void *fdt)
static void *fdt_grab_space_(void *fdt, size_t len)
{
- int offset = fdt_size_dt_struct(fdt);
- int spaceleft;
+ unsigned int offset = fdt_size_dt_struct(fdt);
+ unsigned int spaceleft;
spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
- fdt_size_dt_strings(fdt);
@@ -108,8 +108,8 @@ static void *fdt_grab_space_(void *fdt, size_t len)
int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
{
- const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
- sizeof(struct fdt_reserve_entry));
+ const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
+ sizeof(struct fdt_reserve_entry));
void *fdt = buf;
if (bufsize < hdrsize)
@@ -152,6 +152,9 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
FDT_SW_PROBE(fdt);
+ if (bufsize < 0)
+ return -FDT_ERR_NOSPACE;
+
headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
tailsize = fdt_size_dt_strings(fdt);
@@ -159,7 +162,7 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
headsize + tailsize > fdt_totalsize(fdt))
return -FDT_ERR_INTERNAL;
- if ((headsize + tailsize) > bufsize)
+ if ((headsize + tailsize) > (unsigned)bufsize)
return -FDT_ERR_NOSPACE;
oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
@@ -247,18 +250,18 @@ int fdt_end_node(void *fdt)
static int fdt_add_string_(void *fdt, const char *s)
{
char *strtab = (char *)fdt + fdt_totalsize(fdt);
- int strtabsize = fdt_size_dt_strings(fdt);
- int len = strlen(s) + 1;
- int struct_top, offset;
+ unsigned int strtabsize = fdt_size_dt_strings(fdt);
+ unsigned int len = strlen(s) + 1;
+ unsigned int struct_top, offset;
- offset = -strtabsize - len;
+ offset = strtabsize + len;
struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
- if (fdt_totalsize(fdt) + offset < struct_top)
+ if (fdt_totalsize(fdt) - offset < struct_top)
return 0; /* no more room :( */
- memcpy(strtab + offset, s, len);
+ memcpy(strtab - offset, s, len);
fdt_set_size_dt_strings(fdt, strtabsize + len);
- return offset;
+ return -offset;
}
/* Must only be used to roll back in case of error */
@@ -374,7 +377,7 @@ int fdt_finish(void *fdt)
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
/* And fix up fields that were keeping intermediate state. */
- fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+ fdt_set_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION);
fdt_set_magic(fdt, FDT_MAGIC);
return 0;
diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c
index f64139e0b3dc..c2d7566a67dc 100644
--- a/scripts/dtc/libfdt/fdt_wip.c
+++ b/scripts/dtc/libfdt/fdt_wip.c
@@ -23,7 +23,7 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
if (!propval)
return proplen;
- if (proplen < (len + idx))
+ if ((unsigned)proplen < (len + idx))
return -FDT_ERR_NOSPACE;
memcpy((char *)propval + idx, val, len);
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index fe49b5d78938..2d409d8e829b 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -14,6 +14,7 @@ extern "C" {
#endif
#define FDT_FIRST_SUPPORTED_VERSION 0x02
+#define FDT_LAST_COMPATIBLE_VERSION 0x10
#define FDT_LAST_SUPPORTED_VERSION 0x11
/* Error codes: informative error codes */
@@ -101,7 +102,11 @@ extern "C" {
/* FDT_ERR_BADFLAGS: The function was passed a flags field that
* contains invalid flags or an invalid combination of flags. */
-#define FDT_ERR_MAX 18
+#define FDT_ERR_ALIGNMENT 19
+ /* FDT_ERR_ALIGNMENT: The device tree base address is not 8-byte
+ * aligned. */
+
+#define FDT_ERR_MAX 19
/* constants */
#define FDT_MAX_PHANDLE 0xfffffffe
@@ -122,11 +127,16 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
/*
- * Alignment helpers:
- * These helpers access words from a device tree blob. They're
- * built to work even with unaligned pointers on platforms (ike
- * ARM) that don't like unaligned loads and stores
+ * External helpers to access words from a device tree blob. They're built
+ * to work even with unaligned pointers on platforms (such as ARMv5) that don't
+ * like unaligned loads and stores.
*/
+static inline uint16_t fdt16_ld(const fdt16_t *p)
+{
+ const uint8_t *bp = (const uint8_t *)p;
+
+ return ((uint16_t)bp[0] << 8) | bp[1];
+}
static inline uint32_t fdt32_ld(const fdt32_t *p)
{
@@ -184,23 +194,23 @@ int fdt_next_node(const void *fdt, int offset, int *depth);
/**
* fdt_first_subnode() - get offset of first direct subnode
- *
* @fdt: FDT blob
* @offset: Offset of node to check
- * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
+ *
+ * Return: offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
*/
int fdt_first_subnode(const void *fdt, int offset);
/**
* fdt_next_subnode() - get offset of next direct subnode
+ * @fdt: FDT blob
+ * @offset: Offset of previous subnode
*
* After first calling fdt_first_subnode(), call this function repeatedly to
* get direct subnodes of a parent node.
*
- * @fdt: FDT blob
- * @offset: Offset of previous subnode
- * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
- * subnodes
+ * Return: offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
+ * subnodes
*/
int fdt_next_subnode(const void *fdt, int offset);
@@ -225,7 +235,6 @@ int fdt_next_subnode(const void *fdt, int offset);
* Note that this is implemented as a macro and @node is used as
* iterator in the loop. The parent variable be constant or even a
* literal.
- *
*/
#define fdt_for_each_subnode(node, fdt, parent) \
for (node = fdt_first_subnode(fdt, parent); \
@@ -269,17 +278,21 @@ fdt_set_hdr_(size_dt_struct);
/**
* fdt_header_size - return the size of the tree's header
* @fdt: pointer to a flattened device tree
+ *
+ * Return: size of DTB header in bytes
*/
size_t fdt_header_size(const void *fdt);
/**
- * fdt_header_size_ - internal function which takes a version number
+ * fdt_header_size_ - internal function to get header size from a version number
+ * @version: devicetree version number
+ *
+ * Return: size of DTB header in bytes
*/
size_t fdt_header_size_(uint32_t version);
/**
* fdt_check_header - sanity check a device tree header
-
* @fdt: pointer to data which might be a flattened device tree
*
* fdt_check_header() checks that the given buffer contains what
@@ -404,8 +417,7 @@ static inline uint32_t fdt_get_max_phandle(const void *fdt)
* highest phandle value in the device tree blob) will be returned in the
* @phandle parameter.
*
- * Returns:
- * 0 on success or a negative error-code on failure
+ * Return: 0 on success or a negative error-code on failure
*/
int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
@@ -425,9 +437,11 @@ int fdt_num_mem_rsv(const void *fdt);
/**
* fdt_get_mem_rsv - retrieve one memory reserve map entry
* @fdt: pointer to the device tree blob
- * @address, @size: pointers to 64-bit variables
+ * @n: index of reserve map entry
+ * @address: pointer to 64-bit variable to hold the start address
+ * @size: pointer to 64-bit variable to hold the size of the entry
*
- * On success, *address and *size will contain the address and size of
+ * On success, @address and @size will contain the address and size of
* the n-th reserve map entry from the device tree blob, in
* native-endian format.
*
@@ -450,6 +464,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
* namelen characters of name for matching the subnode name. This is
* useful for finding subnodes based on a portion of a larger string,
* such as a full path.
+ *
+ * Return: offset of the subnode or -FDT_ERR_NOTFOUND if name not found.
*/
#ifndef SWIG /* Not available in Python */
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
@@ -489,6 +505,8 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
*
* Identical to fdt_path_offset(), but only consider the first namelen
* characters of path as the path name.
+ *
+ * Return: offset of the node or negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
@@ -506,10 +524,35 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
* level matching the given component, differentiated only by unit
* address).
*
+ * If the path is not absolute (i.e. does not begin with '/'), the
+ * first component is treated as an alias. That is, the property by
+ * that name is looked up in the /aliases node, and the value of that
+ * property used in place of that first component.
+ *
+ * For example, for this small fragment
+ *
+ * / {
+ * aliases {
+ * i2c2 = &foo; // RHS compiles to "/soc@0/i2c@30a40000/eeprom@52"
+ * };
+ * soc@0 {
+ * foo: i2c@30a40000 {
+ * bar: eeprom@52 {
+ * };
+ * };
+ * };
+ * };
+ *
+ * these would be equivalent:
+ *
+ * /soc@0/i2c@30a40000/eeprom@52
+ * i2c2/eeprom@52
+ *
* returns:
* structure block offset of the node with the requested path (>=0), on
* success
- * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
+ * -FDT_ERR_BADPATH, given path does not begin with '/' and the first
+ * component is not a valid alias
* -FDT_ERR_NOTFOUND, if the requested node does not exist
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
@@ -588,9 +631,9 @@ int fdt_next_property_offset(const void *fdt, int offset);
/**
* fdt_for_each_property_offset - iterate over all properties of a node
*
- * @property_offset: property offset (int, lvalue)
- * @fdt: FDT blob (const void *)
- * @node: node offset (int)
+ * @property: property offset (int, lvalue)
+ * @fdt: FDT blob (const void *)
+ * @node: node offset (int)
*
* This is actually a wrapper around a for loop and would be used like so:
*
@@ -642,6 +685,13 @@ int fdt_next_property_offset(const void *fdt, int offset);
const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
int offset,
int *lenp);
+static inline struct fdt_property *fdt_get_property_by_offset_w(void *fdt,
+ int offset,
+ int *lenp)
+{
+ return (struct fdt_property *)(uintptr_t)
+ fdt_get_property_by_offset(fdt, offset, lenp);
+}
/**
* fdt_get_property_namelen - find a property based on substring
@@ -653,6 +703,9 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
*
* Identical to fdt_get_property(), but only examine the first namelen
* characters of name for matching the property name.
+ *
+ * Return: pointer to the structure representing the property, or NULL
+ * if not found
*/
#ifndef SWIG /* Not available in Python */
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
@@ -745,6 +798,8 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
*
* Identical to fdt_getprop(), but only examine the first namelen
* characters of name for matching the property name.
+ *
+ * Return: pointer to the property's value or NULL on error
*/
#ifndef SWIG /* Not available in Python */
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
@@ -766,10 +821,10 @@ static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
* @lenp: pointer to an integer variable (will be overwritten) or NULL
*
* fdt_getprop() retrieves a pointer to the value of the property
- * named 'name' of the node at offset nodeoffset (this will be a
+ * named @name of the node at offset @nodeoffset (this will be a
* pointer to within the device blob itself, not a copy of the value).
- * If lenp is non-NULL, the length of the property value is also
- * returned, in the integer pointed to by lenp.
+ * If @lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by @lenp.
*
* returns:
* pointer to the property's value
@@ -814,8 +869,11 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
* @name: name of the alias th look up
* @namelen: number of characters of name to consider
*
- * Identical to fdt_get_alias(), but only examine the first namelen
- * characters of name for matching the alias name.
+ * Identical to fdt_get_alias(), but only examine the first @namelen
+ * characters of @name for matching the alias name.
+ *
+ * Return: a pointer to the expansion of the alias named @name, if it exists,
+ * NULL otherwise
*/
#ifndef SWIG /* Not available in Python */
const char *fdt_get_alias_namelen(const void *fdt,
@@ -828,7 +886,7 @@ const char *fdt_get_alias_namelen(const void *fdt,
* @name: name of the alias th look up
*
* fdt_get_alias() retrieves the value of a given alias. That is, the
- * value of the property named 'name' in the node /aliases.
+ * value of the property named @name in the node /aliases.
*
* returns:
* a pointer to the expansion of the alias named 'name', if it exists
@@ -837,6 +895,42 @@ const char *fdt_get_alias_namelen(const void *fdt,
const char *fdt_get_alias(const void *fdt, const char *name);
/**
+ * fdt_get_symbol_namelen - get symbol based on substring
+ * @fdt: pointer to the device tree blob
+ * @name: name of the symbol to look up
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_get_symbol(), but only examine the first @namelen
+ * characters of @name for matching the symbol name.
+ *
+ * Return: a pointer to the expansion of the symbol named @name, if it exists,
+ * NULL otherwise
+ */
+#ifndef SWIG /* Not available in Python */
+const char *fdt_get_symbol_namelen(const void *fdt,
+ const char *name, int namelen);
+#endif
+
+/**
+ * fdt_get_symbol - retrieve the path referenced by a given symbol
+ * @fdt: pointer to the device tree blob
+ * @name: name of the symbol to look up
+ *
+ * fdt_get_symbol() retrieves the value of a given symbol. That is,
+ * the value of the property named @name in the node
+ * /__symbols__. Such a node exists only for a device tree blob that
+ * has been compiled with the -@ dtc option. Each property corresponds
+ * to a label appearing in the device tree source, with the name of
+ * the property being the label and the value being the full path of
+ * the node it is attached to.
+ *
+ * returns:
+ * a pointer to the expansion of the symbol named 'name', if it exists
+ * NULL, if the given symbol or the /__symbols__ node does not exist
+ */
+const char *fdt_get_symbol(const void *fdt, const char *name);
+
+/**
* fdt_get_path - determine the full path of a node
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose path to find
@@ -1004,14 +1098,13 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
/**
- * fdt_node_check_compatible: check a node's compatible property
+ * fdt_node_check_compatible - check a node's compatible property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @compatible: string to match against
*
- *
* fdt_node_check_compatible() returns 0 if the given node contains a
- * 'compatible' property with the given string as one of its elements,
+ * @compatible property with the given string as one of its elements,
* it returns non-zero otherwise, or on error.
*
* returns:
@@ -1075,7 +1168,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
* one or more strings, each terminated by \0, as is found in a device tree
* "compatible" property.
*
- * @return: 1 if the string is found in the list, 0 not found, or invalid list
+ * Return: 1 if the string is found in the list, 0 not found, or invalid list
*/
int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
@@ -1084,7 +1177,8 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of a tree node
* @property: name of the property containing the string list
- * @return:
+ *
+ * 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
@@ -1104,7 +1198,7 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
* small-valued cell properties, such as #address-cells, when searching for
* the empty string.
*
- * @return:
+ * 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
@@ -1128,7 +1222,7 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
* 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:
+ * 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
@@ -1217,6 +1311,8 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
* starting from the given index, and using only the first characters
* of the name. It is useful when you want to manipulate only one value of
* an array and you have a string that doesn't end with \0.
+ *
+ * Return: 0 on success, negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
@@ -1330,8 +1426,13 @@ static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
/**
* fdt_setprop_inplace_cell - change the value of a single-cell property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node containing the property
+ * @name: name of the property to change the value of
+ * @val: new value of the 32-bit cell
*
* This is an alternative name for fdt_setprop_inplace_u32()
+ * Return: 0 on success, negative libfdt error number otherwise.
*/
static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
const char *name, uint32_t val)
@@ -1403,14 +1504,14 @@ int fdt_nop_node(void *fdt, int nodeoffset);
/**
* fdt_create_with_flags - begin creation of a new fdt
- * @fdt: pointer to memory allocated where fdt will be created
+ * @buf: pointer to memory allocated where fdt will be created
* @bufsize: size of the memory space at fdt
* @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
*
* fdt_create_with_flags() begins the process of creating a new fdt with
* the sequential write interface.
*
- * fdt creation process must end with fdt_finished() to produce a valid fdt.
+ * fdt creation process must end with fdt_finish() to produce a valid fdt.
*
* returns:
* 0, on success
@@ -1421,7 +1522,7 @@ int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
/**
* fdt_create - begin creation of a new fdt
- * @fdt: pointer to memory allocated where fdt will be created
+ * @buf: pointer to memory allocated where fdt will be created
* @bufsize: size of the memory space at fdt
*
* fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
@@ -1486,7 +1587,8 @@ int fdt_pack(void *fdt);
/**
* fdt_add_mem_rsv - add one memory reserve map entry
* @fdt: pointer to the device tree blob
- * @address, @size: 64-bit values (native endian)
+ * @address: 64-bit start address of the reserve map entry
+ * @size: 64-bit size of the reserved region
*
* Adds a reserve map entry to the given blob reserving a region at
* address address of length size.
@@ -1691,8 +1793,14 @@ static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
/**
* fdt_setprop_cell - set a property to a single cell value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value for the property (native endian)
*
* This is an alternative name for fdt_setprop_u32()
+ *
+ * Return: 0 on success, negative libfdt error value otherwise.
*/
static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
uint32_t val)
@@ -1863,8 +1971,14 @@ static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
/**
* fdt_appendprop_cell - append a single cell value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value to append to the property (native endian)
*
* This is an alternative name for fdt_appendprop_u32()
+ *
+ * Return: 0 on success, negative libfdt error value otherwise.
*/
static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
const char *name, uint32_t val)
@@ -1915,7 +2029,7 @@ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
* address and size) to the value of the named property in the given
* node, or creates a new property with that value if it does not
* already exist.
- * If "name" is not specified, a default "reg" is used.
+ *
* Cell sizes are determined by parent's #address-cells and #size-cells.
*
* This function may insert data into the blob, and will therefore
@@ -1967,13 +2081,16 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
* fdt_add_subnode_namelen - creates a new node based on substring
* @fdt: pointer to the device tree blob
* @parentoffset: structure block offset of a node
- * @name: name of the subnode to locate
+ * @name: name of the subnode to create
* @namelen: number of characters of name to consider
*
- * Identical to fdt_add_subnode(), but use only the first namelen
- * characters of name as the name of the new node. This is useful for
+ * Identical to fdt_add_subnode(), but use only the first @namelen
+ * characters of @name as the name of the new node. This is useful for
* creating subnodes based on a portion of a larger string, such as a
* full path.
+ *
+ * Return: structure block offset of the created subnode (>=0),
+ * negative libfdt error value otherwise
*/
#ifndef SWIG /* Not available in Python */
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
@@ -1992,7 +2109,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
*
* This function will insert data into the blob, and will therefore
* change the offsets of some existing nodes.
-
+ *
* returns:
* structure block offset of the created nodeequested subnode (>=0), on
* success
@@ -2067,6 +2184,24 @@ int fdt_del_node(void *fdt, int nodeoffset);
*/
int fdt_overlay_apply(void *fdt, void *fdto);
+/**
+ * fdt_overlay_target_offset - retrieves the offset of a fragment's target
+ * @fdt: Base device tree blob
+ * @fdto: Device tree overlay blob
+ * @fragment_offset: node offset of the fragment in the overlay
+ * @pathp: pointer which receives the path of the target (or NULL)
+ *
+ * fdt_overlay_target_offset() retrieves the target offset in the base
+ * device tree of a fragment, no matter how the actual targeting is
+ * done (through a phandle or a path)
+ *
+ * returns:
+ * the targeted node offset in the base device tree
+ * Negative error code on error
+ */
+int fdt_overlay_target_offset(const void *fdt, const void *fdto,
+ int fragment_offset, char const **pathp);
+
/**********************************************************************/
/* Debugging / informational functions */
/**********************************************************************/
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
index d4e0bd49c037..16bda1906a7b 100644
--- a/scripts/dtc/libfdt/libfdt_internal.h
+++ b/scripts/dtc/libfdt/libfdt_internal.h
@@ -46,6 +46,25 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
}
+/*
+ * Internal helpers to access tructural elements of the device tree
+ * blob (rather than for exaple reading integers from within property
+ * values). We assume that we are either given a naturally aligned
+ * address for the platform or if we are not, we are on a platform
+ * where unaligned memory reads will be handled in a graceful manner.
+ * If not the external helpers fdtXX_ld() from libfdt.h can be used
+ * instead.
+ */
+static inline uint32_t fdt32_ld_(const fdt32_t *p)
+{
+ return fdt32_to_cpu(*p);
+}
+
+static inline uint64_t fdt64_ld_(const fdt64_t *p)
+{
+ return fdt64_to_cpu(*p);
+}
+
#define FDT_SW_MAGIC (~FDT_MAGIC)
/**********************************************************************/