diff options
Diffstat (limited to 'scripts/dtc/libfdt')
-rw-r--r-- | scripts/dtc/libfdt/Makefile.libfdt | 18 | ||||
-rw-r--r-- | scripts/dtc/libfdt/fdt.c | 130 | ||||
-rw-r--r-- | scripts/dtc/libfdt/fdt.h | 4 | ||||
-rw-r--r-- | scripts/dtc/libfdt/fdt_overlay.c | 3 | ||||
-rw-r--r-- | scripts/dtc/libfdt/fdt_ro.c | 175 | ||||
-rw-r--r-- | scripts/dtc/libfdt/fdt_rw.c | 64 | ||||
-rw-r--r-- | scripts/dtc/libfdt/fdt_strerror.c | 5 | ||||
-rw-r--r-- | scripts/dtc/libfdt/fdt_sw.c | 50 | ||||
-rw-r--r-- | scripts/dtc/libfdt/fdt_wip.c | 2 | ||||
-rw-r--r-- | scripts/dtc/libfdt/libfdt.h | 146 | ||||
-rw-r--r-- | scripts/dtc/libfdt/libfdt_internal.h | 141 |
11 files changed, 479 insertions, 259 deletions
diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt deleted file mode 100644 index e54639738c8e..000000000000 --- a/scripts/dtc/libfdt/Makefile.libfdt +++ /dev/null @@ -1,18 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) -# Makefile.libfdt -# -# This is not a complete Makefile of itself. Instead, it is designed to -# be easily embeddable into other systems of Makefiles. -# -LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 -LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h -LIBFDT_VERSION = version.lds -LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \ - fdt_addresses.c fdt_overlay.c -LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) -LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT) - -libfdt_clean: - @$(VECHO) CLEAN "(libfdt)" - rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%) - rm -f $(LIBFDT_dir)/$(LIBFDT_soname) diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c index d6ce7c052dc8..9fe7cf4b747d 100644 --- a/scripts/dtc/libfdt/fdt.c +++ b/scripts/dtc/libfdt/fdt.c @@ -19,15 +19,25 @@ int32_t fdt_ro_probe_(const void *fdt) { uint32_t totalsize = fdt_totalsize(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 (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) - return -FDT_ERR_BADVERSION; - if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION) - return -FDT_ERR_BADVERSION; + if (!can_assume(LATEST)) { + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + if (fdt_last_comp_version(fdt) > + FDT_LAST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + } } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { /* Unfinished sequential-write blob */ - if (fdt_size_dt_struct(fdt) == 0) + if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0) return -FDT_ERR_BADSTATE; } else { return -FDT_ERR_BADMAGIC; @@ -70,58 +80,82 @@ size_t fdt_header_size_(uint32_t version) return FDT_V17_SIZE; } +size_t fdt_header_size(const void *fdt) +{ + return can_assume(LATEST) ? FDT_V17_SIZE : + fdt_header_size_(fdt_version(fdt)); +} + 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)) { + if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + || (fdt_last_comp_version(fdt) > + FDT_LAST_SUPPORTED_VERSION)) + return -FDT_ERR_BADVERSION; + if (fdt_version(fdt) < fdt_last_comp_version(fdt)) + return -FDT_ERR_BADVERSION; + } hdrsize = fdt_header_size(fdt); - if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) - || (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)) - return -FDT_ERR_BADVERSION; - if (fdt_version(fdt) < fdt_last_comp_version(fdt)) - return -FDT_ERR_BADVERSION; - - if ((fdt_totalsize(fdt) < hdrsize) - || (fdt_totalsize(fdt) > INT_MAX)) - return -FDT_ERR_TRUNCATED; + if (!can_assume(VALID_DTB)) { - /* Bounds check memrsv block */ - if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt))) - return -FDT_ERR_TRUNCATED; + if ((fdt_totalsize(fdt) < hdrsize) + || (fdt_totalsize(fdt) > INT_MAX)) + return -FDT_ERR_TRUNCATED; - /* Bounds check structure block */ - if (fdt_version(fdt) < 17) { + /* Bounds check memrsv block */ if (!check_off_(hdrsize, fdt_totalsize(fdt), - fdt_off_dt_struct(fdt))) + fdt_off_mem_rsvmap(fdt))) return -FDT_ERR_TRUNCATED; - } else { + } + + if (!can_assume(VALID_DTB)) { + /* Bounds check structure block */ + if (!can_assume(LATEST) && fdt_version(fdt) < 17) { + if (!check_off_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_struct(fdt))) + return -FDT_ERR_TRUNCATED; + } else { + if (!check_block_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_struct(fdt), + fdt_size_dt_struct(fdt))) + return -FDT_ERR_TRUNCATED; + } + + /* Bounds check strings block */ if (!check_block_(hdrsize, fdt_totalsize(fdt), - fdt_off_dt_struct(fdt), - fdt_size_dt_struct(fdt))) + fdt_off_dt_strings(fdt), + fdt_size_dt_strings(fdt))) return -FDT_ERR_TRUNCATED; } - /* Bounds check strings block */ - if (!check_block_(hdrsize, fdt_totalsize(fdt), - fdt_off_dt_strings(fdt), fdt_size_dt_strings(fdt))) - return -FDT_ERR_TRUNCATED; - return 0; } 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 ((absoffset < offset) - || ((absoffset + len) < absoffset) - || (absoffset + len) > fdt_totalsize(fdt)) + if (offset < 0) return NULL; - if (fdt_version(fdt) >= 0x11) - if (((offset + len) < offset) + if (!can_assume(VALID_INPUT)) + if ((absoffset < uoffset) + || ((absoffset + len) < absoffset) + || (absoffset + len) > fdt_totalsize(fdt)) + return NULL; + + if (can_assume(LATEST) || fdt_version(fdt) >= 0x11) + if (((uoffset + len) < uoffset) || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; @@ -137,7 +171,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) *nextoffset = -FDT_ERR_TRUNCATED; tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); - if (!tagp) + if (!can_assume(VALID_DTB) && !tagp) return FDT_END; /* premature end */ tag = fdt32_to_cpu(*tagp); offset += FDT_TAGSIZE; @@ -149,18 +183,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) do { p = fdt_offset_ptr(fdt, offset++, 1); } while (p && (*p != '\0')); - if (!p) + if (!can_assume(VALID_DTB) && !p) return FDT_END; /* premature end */ break; case FDT_PROP: lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); - if (!lenp) + if (!can_assume(VALID_DTB) && !lenp) return FDT_END; /* premature end */ /* skip-name offset, length and value */ offset += sizeof(struct fdt_property) - FDT_TAGSIZE + fdt32_to_cpu(*lenp); - if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && + if (!can_assume(LATEST) && + fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) offset += 4; break; @@ -183,8 +218,11 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) int fdt_check_node_offset_(const void *fdt, int 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; @@ -192,8 +230,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; @@ -281,9 +322,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_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c index b310e49a698e..d217e79b6722 100644 --- a/scripts/dtc/libfdt/fdt_overlay.c +++ b/scripts/dtc/libfdt/fdt_overlay.c @@ -241,6 +241,7 @@ 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); if (!tree_val) { @@ -250,7 +251,7 @@ static int overlay_update_local_node_references(void *fdto, return tree_len; } - for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) { + for (i = 0; i < fixup_len; i++) { fdt32_t adj_val; uint32_t poffset; diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index a5c2797cde65..17584da25760 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -33,36 +33,47 @@ static int fdt_nodename_eq_(const void *fdt, int offset, const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) { - int32_t totalsize = fdt_ro_probe_(fdt); - uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt); + int32_t totalsize; + uint32_t absoffset; size_t len; int err; const char *s, *n; + if (can_assume(VALID_INPUT)) { + s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; + + if (lenp) + *lenp = strlen(s); + return s; + } + totalsize = fdt_ro_probe_(fdt); err = totalsize; if (totalsize < 0) goto fail; err = -FDT_ERR_BADOFFSET; - if (absoffset >= totalsize) + absoffset = stroffset + fdt_off_dt_strings(fdt); + if (absoffset >= (unsigned)totalsize) goto fail; len = totalsize - absoffset; if (fdt_magic(fdt) == FDT_MAGIC) { if (stroffset < 0) goto fail; - if (fdt_version(fdt) >= 17) { - if (stroffset >= fdt_size_dt_strings(fdt)) + if (can_assume(LATEST) || fdt_version(fdt) >= 17) { + 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; @@ -148,13 +159,16 @@ 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 (absoffset < fdt_off_mem_rsvmap(fdt)) - return NULL; - if (absoffset > fdt_totalsize(fdt) - sizeof(struct fdt_reserve_entry)) - return NULL; + if (!can_assume(VALID_INPUT)) { + if (absoffset < fdt_off_mem_rsvmap(fdt)) + return NULL; + if (absoffset > fdt_totalsize(fdt) - + sizeof(struct fdt_reserve_entry)) + return NULL; + } return fdt_mem_rsv_(fdt, n); } @@ -164,11 +178,11 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) FDT_RO_PROBE(fdt); re = fdt_mem_rsv(fdt, n); - if (!re) + 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; } @@ -178,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; @@ -295,7 +309,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) nameptr = nh->name; - if (fdt_version(fdt) < 0x10) { + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { /* * For old FDT versions, match the naming conventions of V16: * give only the leaf name (after all /). The actual tree @@ -346,7 +360,8 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, int err; const struct fdt_property *prop; - if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) { + if (!can_assume(VALID_INPUT) && + (err = fdt_check_prop_offset_(fdt, offset)) < 0) { if (lenp) *lenp = err; return NULL; @@ -355,7 +370,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; } @@ -367,7 +382,7 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt, /* Prior to version 16, properties may need realignment * and this API does not work. fdt_getprop_*() will, however. */ - if (fdt_version(fdt) < 0x10) { + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { if (lenp) *lenp = -FDT_ERR_BADVERSION; return NULL; @@ -388,11 +403,12 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, (offset = fdt_next_property_offset(fdt, offset))) { const struct fdt_property *prop; - if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) { + prop = fdt_get_property_by_offset_(fdt, offset, lenp); + if (!can_assume(LIBFDT_FLAWLESS) && !prop) { 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; @@ -413,7 +429,7 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt, { /* Prior to version 16, properties may need realignment * and this API does not work. fdt_getprop_*() will, however. */ - if (fdt_version(fdt) < 0x10) { + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { if (lenp) *lenp = -FDT_ERR_BADVERSION; return NULL; @@ -444,8 +460,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, return NULL; /* Handle realignment */ - if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 && - fdt32_ld(&prop->len) >= 8) + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && + (poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8) return prop->data + 4; return prop->data; } @@ -461,19 +477,24 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, if (namep) { const char *name; int namelen; - name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), - &namelen); - if (!name) { - if (lenp) - *lenp = namelen; - return NULL; + + if (!can_assume(VALID_INPUT)) { + name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff), + &namelen); + if (!name) { + if (lenp) + *lenp = namelen; + return NULL; + } + *namep = name; + } else { + *namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff)); } - *namep = name; } /* Handle realignment */ - if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 && - fdt32_ld(&prop->len) >= 8) + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && + (offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8) return prop->data + 4; return prop->data; } @@ -498,7 +519,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) return 0; } - return fdt32_ld(php); + return fdt32_ld_(php); } const char *fdt_get_alias_namelen(const void *fdt, @@ -598,10 +619,12 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, } } - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) - return -FDT_ERR_BADOFFSET; - else if (offset == -FDT_ERR_BADOFFSET) - return -FDT_ERR_BADSTRUCTURE; + if (!can_assume(VALID_INPUT)) { + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; + } return offset; /* error from fdt_next_node() */ } @@ -613,7 +636,8 @@ int fdt_node_depth(const void *fdt, int nodeoffset) err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); if (err) - return (err < 0) ? err : -FDT_ERR_INTERNAL; + return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err : + -FDT_ERR_INTERNAL; return nodedepth; } @@ -658,7 +682,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); @@ -833,66 +857,3 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, return offset; /* error from fdt_next_node() */ } - -int fdt_check_full(const void *fdt, size_t bufsize) -{ - int err; - int num_memrsv; - int offset, nextoffset = 0; - uint32_t tag; - unsigned depth = 0; - const void *prop; - const char *propname; - - if (bufsize < FDT_V1_SIZE) - return -FDT_ERR_TRUNCATED; - err = fdt_check_header(fdt); - if (err != 0) - return err; - if (bufsize < fdt_totalsize(fdt)) - return -FDT_ERR_TRUNCATED; - - num_memrsv = fdt_num_mem_rsv(fdt); - if (num_memrsv < 0) - return num_memrsv; - - while (1) { - offset = nextoffset; - tag = fdt_next_tag(fdt, offset, &nextoffset); - - if (nextoffset < 0) - return nextoffset; - - switch (tag) { - case FDT_NOP: - break; - - case FDT_END: - if (depth != 0) - return -FDT_ERR_BADSTRUCTURE; - return 0; - - case FDT_BEGIN_NODE: - depth++; - if (depth > INT_MAX) - return -FDT_ERR_BADSTRUCTURE; - break; - - case FDT_END_NODE: - if (depth == 0) - return -FDT_ERR_BADSTRUCTURE; - depth--; - break; - - case FDT_PROP: - prop = fdt_getprop_by_offset(fdt, offset, &propname, - &err); - if (!prop) - return err; - break; - - default: - return -FDT_ERR_INTERNAL; - } - } -} diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c index 8795947c00dd..3621d3651d3f 100644 --- a/scripts/dtc/libfdt/fdt_rw.c +++ b/scripts/dtc/libfdt/fdt_rw.c @@ -24,14 +24,16 @@ static int fdt_blocks_misordered_(const void *fdt, static int fdt_rw_probe_(void *fdt) { + if (can_assume(VALID_DTB)) + return 0; FDT_RO_PROBE(fdt); - if (fdt_version(fdt) < 17) + if (!can_assume(LATEST) && fdt_version(fdt) < 17) return -FDT_ERR_BADVERSION; if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), fdt_size_dt_struct(fdt))) return -FDT_ERR_BADLAYOUT; - if (fdt_version(fdt) > 17) + if (!can_assume(LATEST) && fdt_version(fdt) > 17) fdt_set_version(fdt, 17); return 0; @@ -44,7 +46,7 @@ static int fdt_rw_probe_(void *fdt) return err_; \ } -static inline int fdt_data_size_(void *fdt) +static inline unsigned int fdt_data_size_(void *fdt) { return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); } @@ -52,15 +54,16 @@ static inline int fdt_data_size_(void *fdt) static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) { char *p = splicepoint; - char *end = (char *)fdt + fdt_data_size_(fdt); + unsigned int dsize = fdt_data_size_(fdt); + size_t soff = p - (char *)fdt; - if (((p + oldlen) < p) || ((p + oldlen) > end)) + if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize)) return -FDT_ERR_BADOFFSET; - if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) + if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen)) return -FDT_ERR_BADOFFSET; - if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) + if (dsize - oldlen + newlen > fdt_totalsize(fdt)) return -FDT_ERR_NOSPACE; - memmove(p + newlen, p + oldlen, end - p - oldlen); + memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen)); return 0; } @@ -112,6 +115,15 @@ static int fdt_splice_string_(void *fdt, int newlen) return 0; } +/** + * fdt_find_add_string_() - Find or allocate a string + * + * @fdt: pointer to the device tree to check/adjust + * @s: string to find/add + * @allocated: Set to 0 if the string was found, 1 if not found and so + * allocated. Ignored if can_assume(NO_ROLLBACK) + * @return offset of string in the string table (whether found or added) + */ static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) { char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); @@ -120,7 +132,8 @@ static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) int len = strlen(s) + 1; int err; - *allocated = 0; + if (!can_assume(NO_ROLLBACK)) + *allocated = 0; p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); if (p) @@ -132,7 +145,8 @@ static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) if (err) return err; - *allocated = 1; + if (!can_assume(NO_ROLLBACK)) + *allocated = 1; memcpy(new, s, len); return (new - strtab); @@ -206,7 +220,8 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, err = fdt_splice_struct_(fdt, *prop, 0, proplen); if (err) { - if (allocated) + /* Delete the string if we failed to add it */ + if (!can_assume(NO_ROLLBACK) && allocated) fdt_del_last_string_(fdt, name); return err; } @@ -334,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); @@ -376,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; @@ -391,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)); } @@ -411,17 +430,20 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); - if (fdt_version(fdt) >= 17) { + 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 (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { + if (can_assume(LIBFDT_ORDER) || + !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { /* no further work necessary */ err = fdt_move(fdt, buf, bufsize); if (err) @@ -449,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); @@ -469,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 76bea22f734f..4c569ee7eb0d 100644 --- a/scripts/dtc/libfdt/fdt_sw.c +++ b/scripts/dtc/libfdt/fdt_sw.c @@ -12,10 +12,13 @@ static int fdt_sw_probe_(void *fdt) { - if (fdt_magic(fdt) == FDT_MAGIC) - return -FDT_ERR_BADSTATE; - else if (fdt_magic(fdt) != FDT_SW_MAGIC) - return -FDT_ERR_BADMAGIC; + if (!can_assume(VALID_INPUT)) { + if (fdt_magic(fdt) == FDT_MAGIC) + return -FDT_ERR_BADSTATE; + else if (fdt_magic(fdt) != FDT_SW_MAGIC) + return -FDT_ERR_BADMAGIC; + } + return 0; } @@ -29,7 +32,7 @@ static int fdt_sw_probe_(void *fdt) /* 'memrsv' state: Initial state after fdt_create() * * Allowed functions: - * fdt_add_reservmap_entry() + * fdt_add_reservemap_entry() * fdt_finish_reservemap() [moves to 'struct' state] */ static int fdt_sw_probe_memrsv_(void *fdt) @@ -38,7 +41,7 @@ static int fdt_sw_probe_memrsv_(void *fdt) if (err) return err; - if (fdt_off_dt_strings(fdt) != 0) + if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0) return -FDT_ERR_BADSTATE; return 0; } @@ -64,7 +67,8 @@ static int fdt_sw_probe_struct_(void *fdt) if (err) return err; - if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) + if (!can_assume(VALID_INPUT) && + fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) return -FDT_ERR_BADSTATE; return 0; } @@ -89,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); @@ -104,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) @@ -148,13 +152,17 @@ 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); - if ((headsize + tailsize) > fdt_totalsize(fdt)) + if (!can_assume(VALID_DTB) && + 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; @@ -242,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 */ @@ -369,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 8907b09b86cc..ce31e844856a 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h @@ -9,7 +9,12 @@ #include "libfdt_env.h" #include "fdt.h" +#ifdef __cplusplus +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 */ @@ -97,7 +102,11 @@ /* 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 @@ -118,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) { @@ -180,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); @@ -221,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); \ @@ -265,16 +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 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); -static inline size_t fdt_header_size(const void *fdt) -{ - return fdt_header_size_(fdt_version(fdt)); -} /** * 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 @@ -399,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); @@ -420,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. * @@ -445,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, @@ -484,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); @@ -583,9 +606,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: * @@ -648,6 +671,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, @@ -740,6 +766,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, @@ -761,10 +789,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 @@ -809,8 +837,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, @@ -823,7 +854,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 @@ -999,14 +1030,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: @@ -1070,7 +1100,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); @@ -1079,7 +1109,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 @@ -1099,7 +1130,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 @@ -1123,7 +1154,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 @@ -1212,6 +1243,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, @@ -1325,8 +1358,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) @@ -1398,7 +1436,7 @@ 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. * @@ -1416,7 +1454,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. @@ -1481,7 +1519,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. @@ -1686,8 +1725,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) @@ -1858,8 +1903,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) @@ -1962,13 +2013,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, @@ -1987,7 +2041,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 @@ -2068,4 +2122,8 @@ int fdt_overlay_apply(void *fdt, void *fdto); const char *fdt_strerror(int errval); +#ifdef __cplusplus +} +#endif + #endif /* LIBFDT_H */ diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h index 058c7358d441..16bda1906a7b 100644 --- a/scripts/dtc/libfdt/libfdt_internal.h +++ b/scripts/dtc/libfdt/libfdt_internal.h @@ -46,6 +46,147 @@ 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) +/**********************************************************************/ +/* Checking controls */ +/**********************************************************************/ + +#ifndef FDT_ASSUME_MASK +#define FDT_ASSUME_MASK 0 +#endif + +/* + * Defines assumptions which can be enabled. Each of these can be enabled + * individually. For maximum safety, don't enable any assumptions! + * + * For minimal code size and no safety, use ASSUME_PERFECT at your own risk. + * You should have another method of validating the device tree, such as a + * signature or hash check before using libfdt. + * + * For situations where security is not a concern it may be safe to enable + * ASSUME_SANE. + */ +enum { + /* + * This does essentially no checks. Only the latest device-tree + * version is correctly handled. Inconsistencies or errors in the device + * tree may cause undefined behaviour or crashes. Invalid parameters + * passed to libfdt may do the same. + * + * If an error occurs when modifying the tree it may leave the tree in + * an intermediate (but valid) state. As an example, adding a property + * where there is insufficient space may result in the property name + * being added to the string table even though the property itself is + * not added to the struct section. + * + * Only use this if you have a fully validated device tree with + * the latest supported version and wish to minimise code size. + */ + ASSUME_PERFECT = 0xff, + + /* + * This assumes that the device tree is sane. i.e. header metadata + * and basic hierarchy are correct. + * + * With this assumption enabled, normal device trees produced by libfdt + * and the compiler should be handled safely. Malicious device trees and + * complete garbage may cause libfdt to behave badly or crash. Truncated + * device trees (e.g. those only partially loaded) can also cause + * problems. + * + * Note: Only checks that relate exclusively to the device tree itself + * (not the parameters passed to libfdt) are disabled by this + * assumption. This includes checking headers, tags and the like. + */ + ASSUME_VALID_DTB = 1 << 0, + + /* + * This builds on ASSUME_VALID_DTB and further assumes that libfdt + * functions are called with valid parameters, i.e. not trigger + * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any + * extensive checking of parameters and the device tree, making various + * assumptions about correctness. + * + * It doesn't make sense to enable this assumption unless + * ASSUME_VALID_DTB is also enabled. + */ + ASSUME_VALID_INPUT = 1 << 1, + + /* + * This disables checks for device-tree version and removes all code + * which handles older versions. + * + * Only enable this if you know you have a device tree with the latest + * version. + */ + ASSUME_LATEST = 1 << 2, + + /* + * This assumes that it is OK for a failed addition to the device tree, + * due to lack of space or some other problem, to skip any rollback + * steps (such as dropping the property name from the string table). + * This is safe to enable in most circumstances, even though it may + * leave the tree in a sub-optimal state. + */ + ASSUME_NO_ROLLBACK = 1 << 3, + + /* + * This assumes that the device tree components appear in a 'convenient' + * order, i.e. the memory reservation block first, then the structure + * block and finally the string block. + * + * This order is not specified by the device-tree specification, + * but is expected by libfdt. The device-tree compiler always created + * device trees with this order. + * + * This assumption disables a check in fdt_open_into() and removes the + * ability to fix the problem there. This is safe if you know that the + * device tree is correctly ordered. See fdt_blocks_misordered_(). + */ + ASSUME_LIBFDT_ORDER = 1 << 4, + + /* + * This assumes that libfdt itself does not have any internal bugs. It + * drops certain checks that should never be needed unless libfdt has an + * undiscovered bug. + * + * This can generally be considered safe to enable. + */ + ASSUME_LIBFDT_FLAWLESS = 1 << 5, +}; + +/** + * can_assume_() - check if a particular assumption is enabled + * + * @mask: Mask to check (ASSUME_...) + * @return true if that assumption is enabled, else false + */ +static inline bool can_assume_(int mask) +{ + return FDT_ASSUME_MASK & mask; +} + +/** helper macros for checking assumptions */ +#define can_assume(_assume) can_assume_(ASSUME_ ## _assume) + #endif /* LIBFDT_INTERNAL_H */ |