Commit 00f588bf authored by Antonio Nino Diaz's avatar Antonio Nino Diaz
Browse files

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 <aadd0b65c987> checks: centralize
printing of property names in failure messages.

Fixes ARM-software/tf-issues#643

Change-Id: I73c05f2b1f994bcdcc4366131ce0647553cdcfb8
Signed-off-by: default avatarAntonio Nino Diaz <antonio.ninodiaz@arm.com>
parent 40125315
...@@ -90,9 +90,8 @@ ...@@ -90,9 +90,8 @@
/* Error codes: codes for bad device tree blobs */ /* Error codes: codes for bad device tree blobs */
#define FDT_ERR_TRUNCATED 8 #define FDT_ERR_TRUNCATED 8
/* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly /* FDT_ERR_TRUNCATED: Structure block of the given device tree
* terminated (overflows, goes outside allowed bounds, or * ends without an FDT_END tag. */
* isn't properly terminated). */
#define FDT_ERR_BADMAGIC 9 #define FDT_ERR_BADMAGIC 9
/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
* device tree at all - it is missing the flattened device * 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) ...@@ -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); 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 */ /* Traversal functions */
/**********************************************************************/ /**********************************************************************/
...@@ -237,7 +213,7 @@ int fdt_next_subnode(const void *fdt, int offset); ...@@ -237,7 +213,7 @@ int fdt_next_subnode(const void *fdt, int offset);
/* General functions */ /* General functions */
/**********************************************************************/ /**********************************************************************/
#define fdt_get_header(fdt, field) \ #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_magic(fdt) (fdt_get_header(fdt, magic))
#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) #define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) #define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
...@@ -268,31 +244,18 @@ fdt_set_hdr_(size_dt_struct); ...@@ -268,31 +244,18 @@ fdt_set_hdr_(size_dt_struct);
#undef fdt_set_hdr_ #undef fdt_set_hdr_
/** /**
* fdt_header_size - return the size of the tree's header * fdt_check_header - sanity check a device tree or possible device tree
* @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: pointer to data which might be a flattened device tree * @fdt: pointer to data which might be a flattened device tree
* *
* fdt_check_header() checks that the given buffer contains what * fdt_check_header() checks that the given buffer contains what
* appears to be a flattened device tree, and that the header contains * appears to be a flattened device tree with sane information in its
* valid information (to the extent that can be determined from the * header.
* header alone).
* *
* returns: * returns:
* 0, if the buffer appears to contain a valid device tree * 0, if the buffer appears to contain a valid device tree
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION, * -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTATE, standard meanings, as above
* -FDT_ERR_TRUNCATED, standard meanings, as above
*/ */
int fdt_check_header(const void *fdt); int fdt_check_header(const void *fdt);
...@@ -321,24 +284,6 @@ int fdt_move(const void *fdt, void *buf, int bufsize); ...@@ -321,24 +284,6 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
/* Read-only functions */ /* 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_string - retrieve a string from the strings block of a device tree
* @fdt: pointer to the device tree blob * @fdt: pointer to the device tree blob
...@@ -349,7 +294,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); ...@@ -349,7 +294,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
* *
* returns: * returns:
* a pointer to the string, on success * 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); const char *fdt_string(const void *fdt, int stroffset);
...@@ -1145,7 +1090,7 @@ int fdt_address_cells(const void *fdt, int nodeoffset); ...@@ -1145,7 +1090,7 @@ int fdt_address_cells(const void *fdt, int nodeoffset);
* *
* returns: * returns:
* 0 <= n < FDT_MAX_NCELLS, on success * 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 * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
* #size-cells property * #size-cells property
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
...@@ -1368,13 +1313,10 @@ static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) ...@@ -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); fdt64_t tmp = cpu_to_fdt64(val);
return fdt_property(fdt, name, &tmp, sizeof(tmp)); 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) static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
{ {
return fdt_property_u32(fdt, name, val); return fdt_property_u32(fdt, name, val);
} }
#endif
/** /**
* fdt_property_placeholder - add a new property and return a ptr to its value * fdt_property_placeholder - add a new property and return a ptr to its value
......
...@@ -56,7 +56,6 @@ ...@@ -56,7 +56,6 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>
#ifdef __CHECKER__ #ifdef __CHECKER__
#define FDT_FORCE __attribute__((force)) #define FDT_FORCE __attribute__((force))
......
...@@ -55,12 +55,7 @@ ...@@ -55,12 +55,7 @@
#include "libfdt_internal.h" #include "libfdt_internal.h"
/* int fdt_check_header(const void *fdt)
* 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)
{ {
if (fdt_magic(fdt) == FDT_MAGIC) { if (fdt_magic(fdt) == FDT_MAGIC) {
/* Complete tree */ /* Complete tree */
...@@ -79,78 +74,6 @@ int fdt_ro_probe_(const void *fdt) ...@@ -79,78 +74,6 @@ int fdt_ro_probe_(const void *fdt)
return 0; 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) const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{ {
unsigned absoffset = offset + fdt_off_dt_struct(fdt); 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) ...@@ -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) int fdt_move(const void *fdt, void *buf, int bufsize)
{ {
FDT_RO_PROBE(fdt); FDT_CHECK_HEADER(fdt);
if (fdt_totalsize(fdt) > bufsize) if (fdt_totalsize(fdt) > bufsize)
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
......
/* /*
* libfdt - Flat Device Tree manipulation * libfdt - Flat Device Tree manipulation
* Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au> * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
* Copyright (C) 2018 embedded brains GmbH
* *
* libfdt is dual licensed: you can use it either under the terms of * libfdt is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option. * the GPL, or the BSD license, at your option.
...@@ -56,32 +55,42 @@ ...@@ -56,32 +55,42 @@
#include "libfdt_internal.h" #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 val;
int len; int len;
c = fdt_getprop(fdt, nodeoffset, name, &len); ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
if (!c) if (!ac)
return 2; return 2;
if (len != sizeof(*c)) if (len != sizeof(*ac))
return -FDT_ERR_BADNCELLS; return -FDT_ERR_BADNCELLS;
val = fdt32_to_cpu(*c); val = fdt32_to_cpu(*ac);
if ((val <= 0) || (val > FDT_MAX_NCELLS)) if ((val <= 0) || (val > FDT_MAX_NCELLS))
return -FDT_ERR_BADNCELLS; return -FDT_ERR_BADNCELLS;
return val; 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) 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;
} }
...@@ -697,7 +697,7 @@ static int get_path_len(const void *fdt, int nodeoffset) ...@@ -697,7 +697,7 @@ static int get_path_len(const void *fdt, int nodeoffset)
int len = 0, namelen; int len = 0, namelen;
const char *name; const char *name;
FDT_RO_PROBE(fdt); FDT_CHECK_HEADER(fdt);
for (;;) { for (;;) {
name = fdt_get_name(fdt, nodeoffset, &namelen); name = fdt_get_name(fdt, nodeoffset, &namelen);
...@@ -866,8 +866,8 @@ int fdt_overlay_apply(void *fdt, void *fdto) ...@@ -866,8 +866,8 @@ int fdt_overlay_apply(void *fdt, void *fdto)
uint32_t delta = fdt_get_max_phandle(fdt); uint32_t delta = fdt_get_max_phandle(fdt);
int ret; int ret;
FDT_RO_PROBE(fdt); FDT_CHECK_HEADER(fdt);
FDT_RO_PROBE(fdto); FDT_CHECK_HEADER(fdto);
ret = overlay_adjust_local_phandles(fdto, delta); ret = overlay_adjust_local_phandles(fdto, delta);
if (ret) if (ret)
......
...@@ -76,72 +76,17 @@ static int fdt_nodename_eq_(const void *fdt, int offset, ...@@ -76,72 +76,17 @@ static int fdt_nodename_eq_(const void *fdt, int offset,
return 0; 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) 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, static int fdt_string_eq_(const void *fdt, int stroffset,
const char *s, int len) const char *s, int len)
{ {
int slen; const char *p = fdt_string(fdt, stroffset);
const char *p = fdt_get_string(fdt, stroffset, &slen);
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) uint32_t fdt_get_max_phandle(const void *fdt)
...@@ -170,42 +115,21 @@ uint32_t fdt_get_max_phandle(const void *fdt) ...@@ -170,42 +115,21 @@ uint32_t fdt_get_max_phandle(const void *fdt)
return 0; 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) int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{ {
const struct fdt_reserve_entry *re; FDT_CHECK_HEADER(fdt);
*address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
FDT_RO_PROBE(fdt); *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
re = fdt_mem_rsv(fdt, n);
if (!re)
return -FDT_ERR_BADOFFSET;
*address = fdt64_ld(&re->address);
*size = fdt64_ld(&re->size);
return 0; return 0;
} }
int fdt_num_mem_rsv(const void *fdt) int fdt_num_mem_rsv(const void *fdt)
{ {
int i; int i = 0;
const struct fdt_reserve_entry *re;
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) { while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
if (fdt64_ld(&re->size) == 0) i++;
return i; return i;
}
return -FDT_ERR_TRUNCATED;
} }
static int nextprop_(const void *fdt, int offset) static int nextprop_(const void *fdt, int offset)
...@@ -237,7 +161,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset, ...@@ -237,7 +161,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
{ {
int depth; int depth;
FDT_RO_PROBE(fdt); FDT_CHECK_HEADER(fdt);
for (depth = 0; for (depth = 0;
(offset >= 0) && (depth >= 0); (offset >= 0) && (depth >= 0);
...@@ -263,7 +187,7 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) ...@@ -263,7 +187,7 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
const char *p = path; const char *p = path;
int offset = 0; int offset = 0;
FDT_RO_PROBE(fdt); FDT_CHECK_HEADER(fdt);
/* see if we have an alias */ /* see if we have an alias */
if (*path != '/') { if (*path != '/') {
...@@ -313,7 +237,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) ...@@ -313,7 +237,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
const char *nameptr; const char *nameptr;
int err; int err;
if (((err = fdt_ro_probe_(fdt)) != 0) if (((err = fdt_check_header(fdt)) != 0)
|| ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
goto fail; goto fail;
...@@ -379,7 +303,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, ...@@ -379,7 +303,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
prop = fdt_offset_ptr_(fdt, offset); prop = fdt_offset_ptr_(fdt, offset);
if (lenp) if (lenp)
*lenp = fdt32_ld(&prop->len); *lenp = fdt32_to_cpu(prop->len);
return prop; return prop;
} }
...@@ -416,7 +340,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, ...@@ -416,7 +340,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
offset = -FDT_ERR_INTERNAL; offset = -FDT_ERR_INTERNAL;
break; break;
} }
if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff), if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
name, namelen)) { name, namelen)) {
if (poffset) if (poffset)
*poffset = offset; *poffset = offset;
...@@ -469,7 +393,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, ...@@ -469,7 +393,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
/* Handle realignment */ /* Handle realignment */
if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 && 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 + 4;
return prop->data; return prop->data;
} }
...@@ -482,22 +406,12 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, ...@@ -482,22 +406,12 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
prop = fdt_get_property_by_offset_(fdt, offset, lenp); prop = fdt_get_property_by_offset_(fdt, offset, lenp);
if (!prop) if (!prop)
return NULL; return NULL;
if (namep) { if (namep)
const char *name; *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
int namelen;
name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
&namelen);
if (!name) {
if (lenp)
*lenp = namelen;
return NULL;
}
*namep = name;
}
/* Handle realignment */ /* Handle realignment */
if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 && 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 + 4;
return prop->data; return prop->data;
} }
...@@ -522,7 +436,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) ...@@ -522,7 +436,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
return 0; return 0;
} }
return fdt32_ld(php); return fdt32_to_cpu(*php);
} }
const char *fdt_get_alias_namelen(const void *fdt, 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) ...@@ -548,7 +462,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
int offset, depth, namelen; int offset, depth, namelen;
const char *name; const char *name;
FDT_RO_PROBE(fdt); FDT_CHECK_HEADER(fdt);
if (buflen < 2) if (buflen < 2)
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
...@@ -600,7 +514,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, ...@@ -600,7 +514,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
int offset, depth; int offset, depth;
int supernodeoffset = -FDT_ERR_INTERNAL; int supernodeoffset = -FDT_ERR_INTERNAL;
FDT_RO_PROBE(fdt); FDT_CHECK_HEADER(fdt);
if (supernodedepth < 0) if (supernodedepth < 0)
return -FDT_ERR_NOTFOUND; return -FDT_ERR_NOTFOUND;
...@@ -659,7 +573,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, ...@@ -659,7 +573,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
const void *val; const void *val;
int len; int len;
FDT_RO_PROBE(fdt); FDT_CHECK_HEADER(fdt);
/* FIXME: The algorithm here is pretty horrible: we scan each /* FIXME: The algorithm here is pretty horrible: we scan each
* property of a node in fdt_getprop(), then if that didn't * 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) ...@@ -685,7 +599,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
if ((phandle == 0) || (phandle == -1)) if ((phandle == 0) || (phandle == -1))
return -FDT_ERR_BADPHANDLE; return -FDT_ERR_BADPHANDLE;
FDT_RO_PROBE(fdt); FDT_CHECK_HEADER(fdt);
/* FIXME: The algorithm here is pretty horrible: we /* FIXME: The algorithm here is pretty horrible: we
* potentially scan each property of a node in * potentially scan each property of a node in
...@@ -838,7 +752,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset, ...@@ -838,7 +752,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
{ {
int offset, err; int offset, err;
FDT_RO_PROBE(fdt); FDT_CHECK_HEADER(fdt);
/* FIXME: The algorithm here is pretty horrible: we scan each /* FIXME: The algorithm here is pretty horrible: we scan each
* property of a node in fdt_node_check_compatible(), then if * 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, ...@@ -857,66 +771,3 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
return offset; /* error from fdt_next_node() */ 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;
}
}
}
...@@ -67,9 +67,9 @@ static int fdt_blocks_misordered_(const void *fdt, ...@@ -67,9 +67,9 @@ static int fdt_blocks_misordered_(const void *fdt,
(fdt_off_dt_strings(fdt) + fdt_size_dt_strings(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) if (fdt_version(fdt) < 17)
return -FDT_ERR_BADVERSION; return -FDT_ERR_BADVERSION;
...@@ -82,10 +82,10 @@ static int fdt_rw_probe_(void *fdt) ...@@ -82,10 +82,10 @@ static int fdt_rw_probe_(void *fdt)
return 0; return 0;
} }
#define FDT_RW_PROBE(fdt) \ #define FDT_RW_CHECK_HEADER(fdt) \
{ \ { \
int err_; \ int err_; \
if ((err_ = fdt_rw_probe_(fdt)) != 0) \ if ((err_ = fdt_rw_check_header_(fdt)) != 0) \
return err_; \ return err_; \
} }
...@@ -176,7 +176,7 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) ...@@ -176,7 +176,7 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
struct fdt_reserve_entry *re; struct fdt_reserve_entry *re;
int err; int err;
FDT_RW_PROBE(fdt); FDT_RW_CHECK_HEADER(fdt);
re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt)); re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
err = fdt_splice_mem_rsv_(fdt, re, 0, 1); err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
...@@ -192,7 +192,7 @@ int fdt_del_mem_rsv(void *fdt, int n) ...@@ -192,7 +192,7 @@ int fdt_del_mem_rsv(void *fdt, int n)
{ {
struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, 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)) if (n >= fdt_num_mem_rsv(fdt))
return -FDT_ERR_NOTFOUND; return -FDT_ERR_NOTFOUND;
...@@ -252,7 +252,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name) ...@@ -252,7 +252,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
int oldlen, newlen; int oldlen, newlen;
int err; int err;
FDT_RW_PROBE(fdt); FDT_RW_CHECK_HEADER(fdt);
namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
if (!namep) if (!namep)
...@@ -275,7 +275,7 @@ int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, ...@@ -275,7 +275,7 @@ int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
struct fdt_property *prop; struct fdt_property *prop;
int err; int err;
FDT_RW_PROBE(fdt); FDT_RW_CHECK_HEADER(fdt);
err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop); err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
if (err == -FDT_ERR_NOTFOUND) if (err == -FDT_ERR_NOTFOUND)
...@@ -308,7 +308,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name, ...@@ -308,7 +308,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
struct fdt_property *prop; struct fdt_property *prop;
int err, oldlen, newlen; int err, oldlen, newlen;
FDT_RW_PROBE(fdt); FDT_RW_CHECK_HEADER(fdt);
prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
if (prop) { if (prop) {
...@@ -334,7 +334,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name) ...@@ -334,7 +334,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
struct fdt_property *prop; struct fdt_property *prop;
int len, proplen; int len, proplen;
FDT_RW_PROBE(fdt); FDT_RW_CHECK_HEADER(fdt);
prop = fdt_get_property_w(fdt, nodeoffset, name, &len); prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
if (!prop) if (!prop)
...@@ -354,7 +354,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset, ...@@ -354,7 +354,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
uint32_t tag; uint32_t tag;
fdt32_t *endtag; fdt32_t *endtag;
FDT_RW_PROBE(fdt); FDT_RW_CHECK_HEADER(fdt);
offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
if (offset >= 0) if (offset >= 0)
...@@ -394,7 +394,7 @@ int fdt_del_node(void *fdt, int nodeoffset) ...@@ -394,7 +394,7 @@ int fdt_del_node(void *fdt, int nodeoffset)
{ {
int endoffset; int endoffset;
FDT_RW_PROBE(fdt); FDT_RW_CHECK_HEADER(fdt);
endoffset = fdt_node_end_offset_(fdt, nodeoffset); endoffset = fdt_node_end_offset_(fdt, nodeoffset);
if (endoffset < 0) if (endoffset < 0)
...@@ -435,7 +435,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize) ...@@ -435,7 +435,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
const char *fdtend = fdtstart + fdt_totalsize(fdt); const char *fdtend = fdtstart + fdt_totalsize(fdt);
char *tmp; char *tmp;
FDT_RO_PROBE(fdt); FDT_CHECK_HEADER(fdt);
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry); * sizeof(struct fdt_reserve_entry);
...@@ -494,7 +494,7 @@ int fdt_pack(void *fdt) ...@@ -494,7 +494,7 @@ int fdt_pack(void *fdt)
{ {
int mem_rsv_size; int mem_rsv_size;
FDT_RW_PROBE(fdt); FDT_RW_CHECK_HEADER(fdt);
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
* sizeof(struct fdt_reserve_entry); * sizeof(struct fdt_reserve_entry);
......
...@@ -55,77 +55,21 @@ ...@@ -55,77 +55,21 @@
#include "libfdt_internal.h" #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) if (fdt_magic(fdt) != FDT_SW_MAGIC)
return -FDT_ERR_BADSTATE;
else if (fdt_magic(fdt) != FDT_SW_MAGIC)
return -FDT_ERR_BADMAGIC; return -FDT_ERR_BADMAGIC;
/* FIXME: should check more details about the header state */
return 0; return 0;
} }
#define FDT_SW_PROBE(fdt) \ #define FDT_SW_CHECK_HEADER(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) \
{ \ { \
int err; \ int err; \
if ((err = fdt_sw_probe_struct_(fdt)) != 0) \ if ((err = fdt_sw_check_header_(fdt)) != 0) \
return err; \ return err; \
} }
/* 'complete' state: Enter this state after fdt_finish()
*
* Allowed functions: none
*/
static void *fdt_grab_space_(void *fdt, size_t len) static void *fdt_grab_space_(void *fdt, size_t len)
{ {
int offset = fdt_size_dt_struct(fdt); int offset = fdt_size_dt_struct(fdt);
...@@ -143,11 +87,9 @@ static void *fdt_grab_space_(void *fdt, size_t len) ...@@ -143,11 +87,9 @@ static void *fdt_grab_space_(void *fdt, size_t len)
int fdt_create(void *buf, int bufsize) 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; void *fdt = buf;
if (bufsize < hdrsize) if (bufsize < sizeof(struct fdt_header))
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
memset(buf, 0, bufsize); memset(buf, 0, bufsize);
...@@ -157,9 +99,10 @@ int fdt_create(void *buf, int bufsize) ...@@ -157,9 +99,10 @@ int fdt_create(void *buf, int bufsize)
fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
fdt_set_totalsize(fdt, bufsize); 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_struct(fdt, fdt_off_mem_rsvmap(fdt));
fdt_set_off_dt_strings(fdt, 0); fdt_set_off_dt_strings(fdt, bufsize);
return 0; return 0;
} }
...@@ -169,14 +112,11 @@ int fdt_resize(void *fdt, void *buf, int bufsize) ...@@ -169,14 +112,11 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
size_t headsize, tailsize; size_t headsize, tailsize;
char *oldtail, *newtail; 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); tailsize = fdt_size_dt_strings(fdt);
if ((headsize + tailsize) > fdt_totalsize(fdt))
return -FDT_ERR_INTERNAL;
if ((headsize + tailsize) > bufsize) if ((headsize + tailsize) > bufsize)
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
...@@ -193,9 +133,8 @@ int fdt_resize(void *fdt, void *buf, int bufsize) ...@@ -193,9 +133,8 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
memmove(buf, fdt, headsize); memmove(buf, fdt, headsize);
} }
fdt_set_totalsize(buf, bufsize);
if (fdt_off_dt_strings(buf))
fdt_set_off_dt_strings(buf, bufsize); fdt_set_off_dt_strings(buf, bufsize);
fdt_set_totalsize(buf, bufsize);
return 0; return 0;
} }
...@@ -205,7 +144,10 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) ...@@ -205,7 +144,10 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
struct fdt_reserve_entry *re; struct fdt_reserve_entry *re;
int offset; 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); offset = fdt_off_dt_struct(fdt);
if ((offset + sizeof(*re)) > fdt_totalsize(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) ...@@ -222,23 +164,16 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
int fdt_finish_reservemap(void *fdt) int fdt_finish_reservemap(void *fdt)
{ {
int err = fdt_add_reservemap_entry(fdt, 0, 0); return fdt_add_reservemap_entry(fdt, 0, 0);
if (err)
return err;
fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
return 0;
} }
int fdt_begin_node(void *fdt, const char *name) int fdt_begin_node(void *fdt, const char *name)
{ {
struct fdt_node_header *nh; 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)); nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
if (! nh) if (! nh)
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
...@@ -252,7 +187,7 @@ int fdt_end_node(void *fdt) ...@@ -252,7 +187,7 @@ int fdt_end_node(void *fdt)
{ {
fdt32_t *en; fdt32_t *en;
FDT_SW_PROBE_STRUCT(fdt); FDT_SW_CHECK_HEADER(fdt);
en = fdt_grab_space_(fdt, FDT_TAGSIZE); en = fdt_grab_space_(fdt, FDT_TAGSIZE);
if (! en) if (! en)
...@@ -290,7 +225,7 @@ int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) ...@@ -290,7 +225,7 @@ int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
struct fdt_property *prop; struct fdt_property *prop;
int nameoff; int nameoff;
FDT_SW_PROBE_STRUCT(fdt); FDT_SW_CHECK_HEADER(fdt);
nameoff = fdt_find_add_string_(fdt, name); nameoff = fdt_find_add_string_(fdt, name);
if (nameoff == 0) if (nameoff == 0)
...@@ -327,7 +262,7 @@ int fdt_finish(void *fdt) ...@@ -327,7 +262,7 @@ int fdt_finish(void *fdt)
uint32_t tag; uint32_t tag;
int offset, nextoffset; int offset, nextoffset;
FDT_SW_PROBE_STRUCT(fdt); FDT_SW_CHECK_HEADER(fdt);
/* Add terminator */ /* Add terminator */
end = fdt_grab_space_(fdt, sizeof(*end)); end = fdt_grab_space_(fdt, sizeof(*end));
......
...@@ -55,11 +55,10 @@ ...@@ -55,11 +55,10 @@
#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
int fdt_ro_probe_(const void *fdt); #define FDT_CHECK_HEADER(fdt) \
#define FDT_RO_PROBE(fdt) \
{ \ { \
int err_; \ int err_; \
if ((err_ = fdt_ro_probe_(fdt)) != 0) \ if ((err_ = fdt_check_header(fdt)) != 0) \
return err_; \ return err_; \
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment