From 00f588bf2cc5298db67f8dde561b046998756a3f Mon Sep 17 00:00:00 2001 From: Antonio Nino Diaz Date: Mon, 29 Oct 2018 15:08:50 +0000 Subject: [PATCH] libfdt: Downgrade to version 1.4.6-9 Version 1.4.7 introduces a big performance hit to functions that access the FDT. Downgrade the library to version 1.4.6-9, before the changes that introduce the problem. Version 1.4.6 isn't used because one of the libfdt files (fdt_overlay.c) is missing the license header. This problem is also fixed in 1.4.6-9. This version corresponds to commit checks: centralize printing of property names in failure messages. Fixes ARM-software/tf-issues#643 Change-Id: I73c05f2b1f994bcdcc4366131ce0647553cdcfb8 Signed-off-by: Antonio Nino Diaz --- include/lib/libfdt/libfdt.h | 76 ++---------- include/lib/libfdt/libfdt_env.h | 1 - lib/libfdt/fdt.c | 81 +------------ lib/libfdt/fdt_addresses.c | 35 +++--- lib/libfdt/fdt_overlay.c | 6 +- lib/libfdt/fdt_ro.c | 199 ++++---------------------------- lib/libfdt/fdt_rw.c | 28 ++--- lib/libfdt/fdt_sw.c | 109 ++++------------- lib/libfdt/libfdt_internal.h | 5 +- 9 files changed, 99 insertions(+), 441 deletions(-) diff --git a/include/lib/libfdt/libfdt.h b/include/lib/libfdt/libfdt.h index 830b77e4..c8c00fa8 100644 --- a/include/lib/libfdt/libfdt.h +++ b/include/lib/libfdt/libfdt.h @@ -90,9 +90,8 @@ /* Error codes: codes for bad device tree blobs */ #define FDT_ERR_TRUNCATED 8 - /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly - * terminated (overflows, goes outside allowed bounds, or - * isn't properly terminated). */ + /* FDT_ERR_TRUNCATED: Structure block of the given device tree + * ends without an FDT_END tag. */ #define FDT_ERR_BADMAGIC 9 /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a * device tree at all - it is missing the flattened device @@ -154,29 +153,6 @@ 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 - */ - -static inline uint32_t fdt32_ld(const fdt32_t *p) -{ - fdt32_t v; - - memcpy(&v, p, sizeof(v)); - return fdt32_to_cpu(v); -} - -static inline uint64_t fdt64_ld(const fdt64_t *p) -{ - fdt64_t v; - - memcpy(&v, p, sizeof(v)); - return fdt64_to_cpu(v); -} - /**********************************************************************/ /* Traversal functions */ /**********************************************************************/ @@ -237,7 +213,7 @@ int fdt_next_subnode(const void *fdt, int offset); /* General functions */ /**********************************************************************/ #define fdt_get_header(fdt, field) \ - (fdt32_ld(&((const struct fdt_header *)(fdt))->field)) + (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) #define fdt_magic(fdt) (fdt_get_header(fdt, magic)) #define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) #define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) @@ -268,31 +244,18 @@ fdt_set_hdr_(size_dt_struct); #undef fdt_set_hdr_ /** - * fdt_header_size - return the size of the tree's header - * @fdt: pointer to a flattened device tree - */ -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_check_header - sanity check a device tree or possible device tree * @fdt: pointer to data which might be a flattened device tree * * fdt_check_header() checks that the given buffer contains what - * appears to be a flattened device tree, and that the header contains - * valid information (to the extent that can be determined from the - * header alone). + * appears to be a flattened device tree with sane information in its + * header. * * returns: * 0, if the buffer appears to contain a valid device tree * -FDT_ERR_BADMAGIC, * -FDT_ERR_BADVERSION, - * -FDT_ERR_BADSTATE, - * -FDT_ERR_TRUNCATED, standard meanings, as above + * -FDT_ERR_BADSTATE, standard meanings, as above */ int fdt_check_header(const void *fdt); @@ -321,24 +284,6 @@ int fdt_move(const void *fdt, void *buf, int bufsize); /* Read-only functions */ /**********************************************************************/ -int fdt_check_full(const void *fdt, size_t bufsize); - -/** - * fdt_get_string - retrieve a string from the strings block of a device tree - * @fdt: pointer to the device tree blob - * @stroffset: offset of the string within the strings block (native endian) - * @lenp: optional pointer to return the string's length - * - * fdt_get_string() retrieves a pointer to a single string from the - * strings block of the device tree blob at fdt, and optionally also - * returns the string's length in *lenp. - * - * returns: - * a pointer to the string, on success - * NULL, if stroffset is out of bounds, or doesn't point to a valid string - */ -const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); - /** * fdt_string - retrieve a string from the strings block of a device tree * @fdt: pointer to the device tree blob @@ -349,7 +294,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); * * returns: * a pointer to the string, on success - * NULL, if stroffset is out of bounds, or doesn't point to a valid string + * NULL, if stroffset is out of bounds */ const char *fdt_string(const void *fdt, int stroffset); @@ -1145,7 +1090,7 @@ int fdt_address_cells(const void *fdt, int nodeoffset); * * returns: * 0 <= n < FDT_MAX_NCELLS, on success - * 2, if the node has no #size-cells property + * 2, if the node has no #address-cells property * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid * #size-cells property * -FDT_ERR_BADMAGIC, @@ -1368,13 +1313,10 @@ static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) fdt64_t tmp = cpu_to_fdt64(val); return fdt_property(fdt, name, &tmp, sizeof(tmp)); } - -#ifndef SWIG /* Not available in Python */ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) { return fdt_property_u32(fdt, name, val); } -#endif /** * fdt_property_placeholder - add a new property and return a ptr to its value diff --git a/include/lib/libfdt/libfdt_env.h b/include/lib/libfdt/libfdt_env.h index eb205384..bd247462 100644 --- a/include/lib/libfdt/libfdt_env.h +++ b/include/lib/libfdt/libfdt_env.h @@ -56,7 +56,6 @@ #include #include #include -#include #ifdef __CHECKER__ #define FDT_FORCE __attribute__((force)) diff --git a/lib/libfdt/fdt.c b/lib/libfdt/fdt.c index ae03b111..7855a178 100644 --- a/lib/libfdt/fdt.c +++ b/lib/libfdt/fdt.c @@ -55,12 +55,7 @@ #include "libfdt_internal.h" -/* - * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks - * that the given buffer contains what appears to be a flattened - * device tree with sane information in its header. - */ -int fdt_ro_probe_(const void *fdt) +int fdt_check_header(const void *fdt) { if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ @@ -79,78 +74,6 @@ int fdt_ro_probe_(const void *fdt) return 0; } -static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off) -{ - return (off >= hdrsize) && (off <= totalsize); -} - -static int check_block_(uint32_t hdrsize, uint32_t totalsize, - uint32_t base, uint32_t size) -{ - if (!check_off_(hdrsize, totalsize, base)) - return 0; /* block start out of bounds */ - if ((base + size) < base) - return 0; /* overflow */ - if (!check_off_(hdrsize, totalsize, base + size)) - return 0; /* block end out of bounds */ - return 1; -} - -size_t fdt_header_size_(uint32_t version) -{ - if (version <= 1) - return FDT_V1_SIZE; - else if (version <= 2) - return FDT_V2_SIZE; - else if (version <= 3) - return FDT_V3_SIZE; - else if (version <= 16) - return FDT_V16_SIZE; - else - return FDT_V17_SIZE; -} - -int fdt_check_header(const void *fdt) -{ - size_t hdrsize; - - if (fdt_magic(fdt) != FDT_MAGIC) - return -FDT_ERR_BADMAGIC; - 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; - - /* Bounds check memrsv block */ - if (!check_off_(hdrsize, fdt_totalsize(fdt), fdt_off_mem_rsvmap(fdt))) - return -FDT_ERR_TRUNCATED; - - /* Bounds check structure block */ - if (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_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); @@ -321,7 +244,7 @@ const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) int fdt_move(const void *fdt, void *buf, int bufsize) { - FDT_RO_PROBE(fdt); + FDT_CHECK_HEADER(fdt); if (fdt_totalsize(fdt) > bufsize) return -FDT_ERR_NOSPACE; diff --git a/lib/libfdt/fdt_addresses.c b/lib/libfdt/fdt_addresses.c index 49537b57..eff4dbcc 100644 --- a/lib/libfdt/fdt_addresses.c +++ b/lib/libfdt/fdt_addresses.c @@ -1,7 +1,6 @@ /* * libfdt - Flat Device Tree manipulation * Copyright (C) 2014 David Gibson - * Copyright (C) 2018 embedded brains GmbH * * libfdt is dual licensed: you can use it either under the terms of * the GPL, or the BSD license, at your option. @@ -56,32 +55,42 @@ #include "libfdt_internal.h" -static int fdt_cells(const void *fdt, int nodeoffset, const char *name) +int fdt_address_cells(const void *fdt, int nodeoffset) { - const fdt32_t *c; + const fdt32_t *ac; int val; int len; - c = fdt_getprop(fdt, nodeoffset, name, &len); - if (!c) + ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len); + if (!ac) return 2; - if (len != sizeof(*c)) + if (len != sizeof(*ac)) return -FDT_ERR_BADNCELLS; - val = fdt32_to_cpu(*c); + val = fdt32_to_cpu(*ac); if ((val <= 0) || (val > FDT_MAX_NCELLS)) return -FDT_ERR_BADNCELLS; return val; } -int fdt_address_cells(const void *fdt, int nodeoffset) -{ - return fdt_cells(fdt, nodeoffset, "#address-cells"); -} - int fdt_size_cells(const void *fdt, int nodeoffset) { - return fdt_cells(fdt, nodeoffset, "#size-cells"); + const fdt32_t *sc; + int val; + int len; + + sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len); + if (!sc) + return 2; + + if (len != sizeof(*sc)) + return -FDT_ERR_BADNCELLS; + + val = fdt32_to_cpu(*sc); + if ((val < 0) || (val > FDT_MAX_NCELLS)) + return -FDT_ERR_BADNCELLS; + + return val; } diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c index 5fdab6c6..bf75388e 100644 --- a/lib/libfdt/fdt_overlay.c +++ b/lib/libfdt/fdt_overlay.c @@ -697,7 +697,7 @@ static int get_path_len(const void *fdt, int nodeoffset) int len = 0, namelen; const char *name; - FDT_RO_PROBE(fdt); + FDT_CHECK_HEADER(fdt); for (;;) { name = fdt_get_name(fdt, nodeoffset, &namelen); @@ -866,8 +866,8 @@ int fdt_overlay_apply(void *fdt, void *fdto) uint32_t delta = fdt_get_max_phandle(fdt); int ret; - FDT_RO_PROBE(fdt); - FDT_RO_PROBE(fdto); + FDT_CHECK_HEADER(fdt); + FDT_CHECK_HEADER(fdto); ret = overlay_adjust_local_phandles(fdto, delta); if (ret) diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c index eafc1428..dfb3236d 100644 --- a/lib/libfdt/fdt_ro.c +++ b/lib/libfdt/fdt_ro.c @@ -76,72 +76,17 @@ static int fdt_nodename_eq_(const void *fdt, int offset, return 0; } -const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) -{ - uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt); - size_t len; - int err; - const char *s, *n; - - err = fdt_ro_probe_(fdt); - if (err != 0) - goto fail; - - err = -FDT_ERR_BADOFFSET; - if (absoffset >= fdt_totalsize(fdt)) - goto fail; - len = fdt_totalsize(fdt) - absoffset; - - if (fdt_magic(fdt) == FDT_MAGIC) { - if (stroffset < 0) - goto fail; - if (fdt_version(fdt) >= 17) { - if (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))) - goto fail; - if ((-stroffset) < len) - len = -stroffset; - } else { - err = -FDT_ERR_INTERNAL; - goto fail; - } - - s = (const char *)fdt + absoffset; - n = memchr(s, '\0', len); - if (!n) { - /* missing terminating NULL */ - err = -FDT_ERR_TRUNCATED; - goto fail; - } - - if (lenp) - *lenp = n - s; - return s; - -fail: - if (lenp) - *lenp = err; - return NULL; -} - const char *fdt_string(const void *fdt, int stroffset) { - return fdt_get_string(fdt, stroffset, NULL); + return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; } static int fdt_string_eq_(const void *fdt, int stroffset, const char *s, int len) { - int slen; - const char *p = fdt_get_string(fdt, stroffset, &slen); + const char *p = fdt_string(fdt, stroffset); - return p && (slen == len) && (memcmp(p, s, len) == 0); + return (strlen(p) == len) && (memcmp(p, s, len) == 0); } uint32_t fdt_get_max_phandle(const void *fdt) @@ -170,42 +115,21 @@ uint32_t fdt_get_max_phandle(const void *fdt) return 0; } -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; - - 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); -} - int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) { - const struct fdt_reserve_entry *re; - - FDT_RO_PROBE(fdt); - re = fdt_mem_rsv(fdt, n); - if (!re) - return -FDT_ERR_BADOFFSET; - - *address = fdt64_ld(&re->address); - *size = fdt64_ld(&re->size); + FDT_CHECK_HEADER(fdt); + *address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address); + *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size); return 0; } int fdt_num_mem_rsv(const void *fdt) { - int i; - const struct fdt_reserve_entry *re; + int i = 0; - for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) { - if (fdt64_ld(&re->size) == 0) - return i; - } - return -FDT_ERR_TRUNCATED; + while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0) + i++; + return i; } static int nextprop_(const void *fdt, int offset) @@ -237,7 +161,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset, { int depth; - FDT_RO_PROBE(fdt); + FDT_CHECK_HEADER(fdt); for (depth = 0; (offset >= 0) && (depth >= 0); @@ -263,7 +187,7 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) const char *p = path; int offset = 0; - FDT_RO_PROBE(fdt); + FDT_CHECK_HEADER(fdt); /* see if we have an alias */ if (*path != '/') { @@ -313,7 +237,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) const char *nameptr; int err; - if (((err = fdt_ro_probe_(fdt)) != 0) + if (((err = fdt_check_header(fdt)) != 0) || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) goto fail; @@ -379,7 +303,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_to_cpu(prop->len); return prop; } @@ -416,7 +340,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_to_cpu(prop->nameoff), name, namelen)) { if (poffset) *poffset = offset; @@ -469,7 +393,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, /* Handle realignment */ if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 && - fdt32_ld(&prop->len) >= 8) + fdt32_to_cpu(prop->len) >= 8) return prop->data + 4; return prop->data; } @@ -482,22 +406,12 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, prop = fdt_get_property_by_offset_(fdt, offset, lenp); if (!prop) return NULL; - 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; - } - *namep = name; - } + if (namep) + *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); /* Handle realignment */ if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 && - fdt32_ld(&prop->len) >= 8) + fdt32_to_cpu(prop->len) >= 8) return prop->data + 4; return prop->data; } @@ -522,7 +436,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) return 0; } - return fdt32_ld(php); + return fdt32_to_cpu(*php); } const char *fdt_get_alias_namelen(const void *fdt, @@ -548,7 +462,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) int offset, depth, namelen; const char *name; - FDT_RO_PROBE(fdt); + FDT_CHECK_HEADER(fdt); if (buflen < 2) return -FDT_ERR_NOSPACE; @@ -600,7 +514,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, int offset, depth; int supernodeoffset = -FDT_ERR_INTERNAL; - FDT_RO_PROBE(fdt); + FDT_CHECK_HEADER(fdt); if (supernodedepth < 0) return -FDT_ERR_NOTFOUND; @@ -659,7 +573,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, const void *val; int len; - FDT_RO_PROBE(fdt); + FDT_CHECK_HEADER(fdt); /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_getprop(), then if that didn't @@ -685,7 +599,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) if ((phandle == 0) || (phandle == -1)) return -FDT_ERR_BADPHANDLE; - FDT_RO_PROBE(fdt); + FDT_CHECK_HEADER(fdt); /* FIXME: The algorithm here is pretty horrible: we * potentially scan each property of a node in @@ -838,7 +752,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, { int offset, err; - FDT_RO_PROBE(fdt); + FDT_CHECK_HEADER(fdt); /* FIXME: The algorithm here is pretty horrible: we scan each * property of a node in fdt_node_check_compatible(), then if @@ -857,66 +771,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/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c index 2e49855d..9b829051 100644 --- a/lib/libfdt/fdt_rw.c +++ b/lib/libfdt/fdt_rw.c @@ -67,9 +67,9 @@ static int fdt_blocks_misordered_(const void *fdt, (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); } -static int fdt_rw_probe_(void *fdt) +static int fdt_rw_check_header_(void *fdt) { - FDT_RO_PROBE(fdt); + FDT_CHECK_HEADER(fdt); if (fdt_version(fdt) < 17) return -FDT_ERR_BADVERSION; @@ -82,10 +82,10 @@ static int fdt_rw_probe_(void *fdt) return 0; } -#define FDT_RW_PROBE(fdt) \ +#define FDT_RW_CHECK_HEADER(fdt) \ { \ int err_; \ - if ((err_ = fdt_rw_probe_(fdt)) != 0) \ + if ((err_ = fdt_rw_check_header_(fdt)) != 0) \ return err_; \ } @@ -176,7 +176,7 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) struct fdt_reserve_entry *re; int err; - FDT_RW_PROBE(fdt); + FDT_RW_CHECK_HEADER(fdt); re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt)); err = fdt_splice_mem_rsv_(fdt, re, 0, 1); @@ -192,7 +192,7 @@ int fdt_del_mem_rsv(void *fdt, int n) { struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n); - FDT_RW_PROBE(fdt); + FDT_RW_CHECK_HEADER(fdt); if (n >= fdt_num_mem_rsv(fdt)) return -FDT_ERR_NOTFOUND; @@ -252,7 +252,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name) int oldlen, newlen; int err; - FDT_RW_PROBE(fdt); + FDT_RW_CHECK_HEADER(fdt); namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); if (!namep) @@ -275,7 +275,7 @@ int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, struct fdt_property *prop; int err; - FDT_RW_PROBE(fdt); + FDT_RW_CHECK_HEADER(fdt); err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop); if (err == -FDT_ERR_NOTFOUND) @@ -308,7 +308,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name, struct fdt_property *prop; int err, oldlen, newlen; - FDT_RW_PROBE(fdt); + FDT_RW_CHECK_HEADER(fdt); prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); if (prop) { @@ -334,7 +334,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name) struct fdt_property *prop; int len, proplen; - FDT_RW_PROBE(fdt); + FDT_RW_CHECK_HEADER(fdt); prop = fdt_get_property_w(fdt, nodeoffset, name, &len); if (!prop) @@ -354,7 +354,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, uint32_t tag; fdt32_t *endtag; - FDT_RW_PROBE(fdt); + FDT_RW_CHECK_HEADER(fdt); offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); if (offset >= 0) @@ -394,7 +394,7 @@ int fdt_del_node(void *fdt, int nodeoffset) { int endoffset; - FDT_RW_PROBE(fdt); + FDT_RW_CHECK_HEADER(fdt); endoffset = fdt_node_end_offset_(fdt, nodeoffset); if (endoffset < 0) @@ -435,7 +435,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) const char *fdtend = fdtstart + fdt_totalsize(fdt); char *tmp; - FDT_RO_PROBE(fdt); + FDT_CHECK_HEADER(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); @@ -494,7 +494,7 @@ int fdt_pack(void *fdt) { int mem_rsv_size; - FDT_RW_PROBE(fdt); + FDT_RW_CHECK_HEADER(fdt); mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) * sizeof(struct fdt_reserve_entry); diff --git a/lib/libfdt/fdt_sw.c b/lib/libfdt/fdt_sw.c index 9fa4a94d..6d33cc29 100644 --- a/lib/libfdt/fdt_sw.c +++ b/lib/libfdt/fdt_sw.c @@ -55,77 +55,21 @@ #include "libfdt_internal.h" -static int fdt_sw_probe_(void *fdt) +static int fdt_sw_check_header_(void *fdt) { - if (fdt_magic(fdt) == FDT_MAGIC) - return -FDT_ERR_BADSTATE; - else if (fdt_magic(fdt) != FDT_SW_MAGIC) + if (fdt_magic(fdt) != FDT_SW_MAGIC) return -FDT_ERR_BADMAGIC; + /* FIXME: should check more details about the header state */ return 0; } -#define FDT_SW_PROBE(fdt) \ - { \ - int err; \ - if ((err = fdt_sw_probe_(fdt)) != 0) \ - return err; \ - } - -/* 'memrsv' state: Initial state after fdt_create() - * - * Allowed functions: - * fdt_add_reservmap_entry() - * fdt_finish_reservemap() [moves to 'struct' state] - */ -static int fdt_sw_probe_memrsv_(void *fdt) -{ - int err = fdt_sw_probe_(fdt); - if (err) - return err; - - if (fdt_off_dt_strings(fdt) != 0) - return -FDT_ERR_BADSTATE; - return 0; -} - -#define FDT_SW_PROBE_MEMRSV(fdt) \ - { \ - int err; \ - if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \ - return err; \ - } - -/* 'struct' state: Enter this state after fdt_finish_reservemap() - * - * Allowed functions: - * fdt_begin_node() - * fdt_end_node() - * fdt_property*() - * fdt_finish() [moves to 'complete' state] - */ -static int fdt_sw_probe_struct_(void *fdt) -{ - int err = fdt_sw_probe_(fdt); - if (err) - return err; - - if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) - return -FDT_ERR_BADSTATE; - return 0; -} - -#define FDT_SW_PROBE_STRUCT(fdt) \ +#define FDT_SW_CHECK_HEADER(fdt) \ { \ int err; \ - if ((err = fdt_sw_probe_struct_(fdt)) != 0) \ + if ((err = fdt_sw_check_header_(fdt)) != 0) \ return err; \ } -/* 'complete' state: Enter this state after fdt_finish() - * - * Allowed functions: none - */ - static void *fdt_grab_space_(void *fdt, size_t len) { int offset = fdt_size_dt_struct(fdt); @@ -143,11 +87,9 @@ static void *fdt_grab_space_(void *fdt, size_t len) int fdt_create(void *buf, int bufsize) { - const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header), - sizeof(struct fdt_reserve_entry)); void *fdt = buf; - if (bufsize < hdrsize) + if (bufsize < sizeof(struct fdt_header)) return -FDT_ERR_NOSPACE; memset(buf, 0, bufsize); @@ -157,9 +99,10 @@ int fdt_create(void *buf, int bufsize) fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); fdt_set_totalsize(fdt, bufsize); - fdt_set_off_mem_rsvmap(fdt, hdrsize); + fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry))); fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); - fdt_set_off_dt_strings(fdt, 0); + fdt_set_off_dt_strings(fdt, bufsize); return 0; } @@ -169,14 +112,11 @@ int fdt_resize(void *fdt, void *buf, int bufsize) size_t headsize, tailsize; char *oldtail, *newtail; - FDT_SW_PROBE(fdt); + FDT_SW_CHECK_HEADER(fdt); - headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + headsize = fdt_off_dt_struct(fdt); tailsize = fdt_size_dt_strings(fdt); - if ((headsize + tailsize) > fdt_totalsize(fdt)) - return -FDT_ERR_INTERNAL; - if ((headsize + tailsize) > bufsize) return -FDT_ERR_NOSPACE; @@ -193,9 +133,8 @@ int fdt_resize(void *fdt, void *buf, int bufsize) memmove(buf, fdt, headsize); } + fdt_set_off_dt_strings(buf, bufsize); fdt_set_totalsize(buf, bufsize); - if (fdt_off_dt_strings(buf)) - fdt_set_off_dt_strings(buf, bufsize); return 0; } @@ -205,7 +144,10 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) struct fdt_reserve_entry *re; int offset; - FDT_SW_PROBE_MEMRSV(fdt); + FDT_SW_CHECK_HEADER(fdt); + + if (fdt_size_dt_struct(fdt)) + return -FDT_ERR_BADSTATE; offset = fdt_off_dt_struct(fdt); if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) @@ -222,23 +164,16 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) int fdt_finish_reservemap(void *fdt) { - int err = fdt_add_reservemap_entry(fdt, 0, 0); - - if (err) - return err; - - fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt)); - return 0; + return fdt_add_reservemap_entry(fdt, 0, 0); } int fdt_begin_node(void *fdt, const char *name) { struct fdt_node_header *nh; - int namelen; + int namelen = strlen(name) + 1; - FDT_SW_PROBE_STRUCT(fdt); + FDT_SW_CHECK_HEADER(fdt); - namelen = strlen(name) + 1; nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); if (! nh) return -FDT_ERR_NOSPACE; @@ -252,7 +187,7 @@ int fdt_end_node(void *fdt) { fdt32_t *en; - FDT_SW_PROBE_STRUCT(fdt); + FDT_SW_CHECK_HEADER(fdt); en = fdt_grab_space_(fdt, FDT_TAGSIZE); if (! en) @@ -290,7 +225,7 @@ int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) struct fdt_property *prop; int nameoff; - FDT_SW_PROBE_STRUCT(fdt); + FDT_SW_CHECK_HEADER(fdt); nameoff = fdt_find_add_string_(fdt, name); if (nameoff == 0) @@ -327,7 +262,7 @@ int fdt_finish(void *fdt) uint32_t tag; int offset, nextoffset; - FDT_SW_PROBE_STRUCT(fdt); + FDT_SW_CHECK_HEADER(fdt); /* Add terminator */ end = fdt_grab_space_(fdt, sizeof(*end)); diff --git a/lib/libfdt/libfdt_internal.h b/lib/libfdt/libfdt_internal.h index 4109f890..7681e192 100644 --- a/lib/libfdt/libfdt_internal.h +++ b/lib/libfdt/libfdt_internal.h @@ -55,11 +55,10 @@ #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) -int fdt_ro_probe_(const void *fdt); -#define FDT_RO_PROBE(fdt) \ +#define FDT_CHECK_HEADER(fdt) \ { \ int err_; \ - if ((err_ = fdt_ro_probe_(fdt)) != 0) \ + if ((err_ = fdt_check_header(fdt)) != 0) \ return err_; \ } -- 2.30.2