feat(libfdt): upgrade libfdt source files
Update the libfdt source files to the upstream commit e37c256 [1].
[1] https://github.com/dgibson/dtc/commit/e37c256
Change-Id: I00e29b467ff6f8c094f68245232a7cedeaa14aef
Signed-off-by: Daniel Boulby <daniel.boulby@arm.com>
diff --git a/lib/libfdt/fdt.c b/lib/libfdt/fdt.c
index 6cf2fa0..9fe7cf4 100644
--- a/lib/libfdt/fdt.c
+++ b/lib/libfdt/fdt.c
@@ -22,6 +22,10 @@
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 @@
{
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)) {
diff --git a/lib/libfdt/fdt_addresses.c b/lib/libfdt/fdt_addresses.c
index 9a82cd0..c40ba09 100644
--- a/lib/libfdt/fdt_addresses.c
+++ b/lib/libfdt/fdt_addresses.c
@@ -73,7 +73,7 @@
/* 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/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
index d217e79..5c0c398 100644
--- a/lib/libfdt/fdt_overlay.c
+++ b/lib/libfdt/fdt_overlay.c
@@ -40,37 +40,22 @@
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
@@ -636,7 +621,7 @@
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;
@@ -779,7 +764,7 @@
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;
@@ -801,7 +786,7 @@
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;
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 91cc6fe..9f6c551 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -181,8 +181,8 @@
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;
}
@@ -192,7 +192,7 @@
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;
@@ -370,7 +370,7 @@
prop = fdt_offset_ptr_(fdt, offset);
if (lenp)
- *lenp = fdt32_ld(&prop->len);
+ *lenp = fdt32_ld_(&prop->len);
return prop;
}
@@ -408,7 +408,7 @@
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;
@@ -461,7 +461,7 @@
/* 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;
}
@@ -479,22 +479,22 @@
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;
}
@@ -519,7 +519,7 @@
return 0;
}
- return fdt32_ld(php);
+ return fdt32_ld_(php);
}
const char *fdt_get_alias_namelen(const void *fdt,
diff --git a/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c
index 68887b9..3621d36 100644
--- a/lib/libfdt/fdt_rw.c
+++ b/lib/libfdt/fdt_rw.c
@@ -349,7 +349,10 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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/lib/libfdt/fdt_strerror.c b/lib/libfdt/fdt_strerror.c
index b435693..d852b77 100644
--- a/lib/libfdt/fdt_strerror.c
+++ b/lib/libfdt/fdt_strerror.c
@@ -39,6 +39,7 @@
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
FDT_ERRTABENT(FDT_ERR_BADFLAGS),
+ FDT_ERRTABENT(FDT_ERR_ALIGNMENT),
};
#define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0])))
diff --git a/lib/libfdt/fdt_sw.c b/lib/libfdt/fdt_sw.c
index 68b543c..4c569ee 100644
--- a/lib/libfdt/fdt_sw.c
+++ b/lib/libfdt/fdt_sw.c
@@ -377,7 +377,7 @@
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/lib/libfdt/libfdt_internal.h b/lib/libfdt/libfdt_internal.h
index d4e0bd4..16bda19 100644
--- a/lib/libfdt/libfdt_internal.h
+++ b/lib/libfdt/libfdt_internal.h
@@ -46,6 +46,25 @@
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)
/**********************************************************************/