Commit f858927f authored by Rob Herring's avatar Rob Herring

scripts/dtc: Update to upstream version v1.4.7-14-gc86da84d30e4

Major changes are I2C and SPI bus checks, YAML output format (for
future validation), some new libfdt functions, and more libfdt
validation of dtbs.

The YAML addition adds an optional dependency on libyaml. pkg-config is
used to test for it and pkg-config became a kconfig dependency in 4.18.

This adds the following commits from upstream:

c86da84d30e4 Add support for YAML encoded output
361b5e7d8067 Make type_marker_length helper public
bfbfab047e45 pylibfdt: Add a means to add and delete notes
9005f4108e7c pylibfdt: Allow delprop() to return errors
b94c056b137e Make valgrind optional
fd06c54d4711 tests: Better testing of dtc -I fs mode
c3f50c9a86d9 tests: Allow dtbs_equal_unordered to ignore mem reserves
0ac9fdee37c7 dtc: trivial '-I fs -O dts' test
0fd1c8c783f3 pylibfdt: fdt_get_mem_rsv returns 2 uint64_t values
04853cad18f4 pylibfdt: Don't incorrectly / unnecessarily override uint64_t typemap
9619c8619c37 Kill bogus TYPE_BLOB marker type
ac68ff92ae20 parser: add TYPE_STRING marker to path references
90a190eb04d9 checks: add SPI bus checks
53a1bd546905 checks: add I2C bus checks
88f18909db73 dtc: Bump version to v1.4.7
85bce8b2f06d tests: Correction to vg_prepare_blob()
57f7f9e7bc7c tests: Don't call memcmp() with NULL arguments
c12b2b0c20eb libfdt: fdt_address_cells() and fdt_size_cells()
3fe0eeda0b7f livetree: Set phandle properties type to uint32
853649acceba pylibfdt: Support the sequential-write interface
9b0e4fe26093 tests: Improve fdt_resize() tests
1087504bb3e8 libfdt: Add necessary header padding in fdt_create()
c72fa777e613 libfdt: Copy the struct region in fdt_resize()
32b9c6130762 Preserve datatype markers when emitting dts format
6dcb8ba408ec libfdt: Add helpers for accessing unaligned words
42607f21d43e tests: Fix incorrect check name 'prop_name_chars'
9d78c33bf8a1 tests: fix grep for checks error messages
b770f3d1c13f pylibfdt: Support setting the name of a node
2f0d07e678e0 pylibfdt: Add functions to set and get properties as strings
354d3dc55939 pylibfdt: Update the bytearray size with pack()
3c374d46acce pylibfdt: Allow reading integer values from properties
49d32ce40bb4 pylibfdt: Use an unsigned type for fdt32_t
481246a0c13a pylibfdt: Avoid accessing the internal _fdt member in tests
9aafa33d99ed pylibfdt: Add functions to update properties
5a598671fdbf pylibfdt: Support device-tree creation/expansion
483e170625e1 pylibfdt: Add support for reading the memory reserve map
29bb05aa4200 pylibfdt: Add support for the rest of the header functions
582a7159a5d0 pylibfdt: Add support for fdt_next_node()
f0f8c9169819 pylibfdt: Reorder functions to match libfdt.h
64a69d123935 pylibfdt: Return string instead of bytearray from getprop()
4d09a83420df fdtput: Add documentation
e617cbe1bd67 fdtget: Add documentation
180a93924014 Use <inttypes.h> format specifiers in a bunch of places we should
b9af3b396576 scripts/dtc: Fixed format mismatch in fprintf
4b8fcc3d015c libfdt: Add fdt_check_full() function
c14223fb2292 tests: Use valgrind client requests for better checking
5b67d2b955a3 tests: Better handling of valgrind errors saving blobs
e2556aaeb506 tests: Remove unused #define
fb9c6abddaa8 Use size_t for blob lengths in utilfdt_read*
0112fda03bf6 libfdt: Add fdt_header_size()
6473a21d8bfe Consolidate utilfdt_read_len() variants
d5db5382c5e5 libfdt: Safer access to memory reservations
719d582e98ec libfdt: Propagate name errors in fdt_getprop_by_offset()
70166d62a27f libfdt: Safer access to strings section
eb890c0f77dc libfdt: Make fdt_check_header() more thorough
899d6fad93f3 libfdt: Improve sequential write state checking
04b5b4062ccd libfdt: Clean up header checking functions
44d3efedc816 Preserve datatype information when parsing dts
f0be81bd8de0 Make Property a subclass of bytearray
24b1f3f064d4 pylibfdt: Add a method to access the device tree directly
Signed-off-by: default avatarRob Herring <robh@kernel.org>
parent c36d5a6c
......@@ -11,6 +11,13 @@ dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
# Source files need to get at the userspace version of libfdt_env.h to compile
HOST_EXTRACFLAGS := -I$(src)/libfdt
ifeq ($(wildcard /usr/include/yaml.h),)
HOST_EXTRACFLAGS += -DNO_YAML
else
dtc-objs += yamltree.o
HOSTLDLIBS_dtc := -lyaml
endif
# Generated files need one more search path to include headers in source tree
HOSTCFLAGS_dtc-lexer.lex.o := -I$(src)
HOSTCFLAGS_dtc-parser.tab.o := -I$(src)
......
......@@ -14,5 +14,9 @@ DTC_SRCS = \
treesource.c \
util.c
ifneq ($(NO_YAML),1)
DTC_SRCS += yamltree.c
endif
DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
......@@ -962,6 +962,143 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no
}
WARNING(simple_bus_reg, check_simple_bus_reg, NULL, &reg_format, &simple_bus_bridge);
static const struct bus_type i2c_bus = {
.name = "i2c-bus",
};
static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
{
if (strprefixeq(node->name, node->basenamelen, "i2c-bus") ||
strprefixeq(node->name, node->basenamelen, "i2c-arb")) {
node->bus = &i2c_bus;
} else if (strprefixeq(node->name, node->basenamelen, "i2c")) {
struct node *child;
for_each_child(node, child) {
if (strprefixeq(child->name, node->basenamelen, "i2c-bus"))
return;
}
node->bus = &i2c_bus;
} else
return;
if (!node->children)
return;
if (node_addr_cells(node) != 1)
FAIL(c, dti, node, "incorrect #address-cells for I2C bus");
if (node_size_cells(node) != 0)
FAIL(c, dti, node, "incorrect #size-cells for I2C bus");
}
WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells);
static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
{
struct property *prop;
const char *unitname = get_unitname(node);
char unit_addr[17];
uint32_t reg = 0;
int len;
cell_t *cells = NULL;
if (!node->parent || (node->parent->bus != &i2c_bus))
return;
prop = get_property(node, "reg");
if (prop)
cells = (cell_t *)prop->val.val;
if (!cells) {
FAIL(c, dti, node, "missing or empty reg property");
return;
}
reg = fdt32_to_cpu(*cells);
snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
if (!streq(unitname, unit_addr))
FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"",
unit_addr);
for (len = prop->val.len; len > 0; len -= 4) {
reg = fdt32_to_cpu(*(cells++));
if (reg > 0x3ff)
FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"",
reg);
}
}
WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, &reg_format, &i2c_bus_bridge);
static const struct bus_type spi_bus = {
.name = "spi-bus",
};
static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
{
if (strprefixeq(node->name, node->basenamelen, "spi")) {
node->bus = &spi_bus;
} else {
/* Try to detect SPI buses which don't have proper node name */
struct node *child;
if (node_addr_cells(node) != 1 || node_size_cells(node) != 0)
return;
for_each_child(node, child) {
struct property *prop;
for_each_property(child, prop) {
if (strprefixeq(prop->name, 4, "spi-")) {
node->bus = &spi_bus;
break;
}
}
if (node->bus == &spi_bus)
break;
}
if (node->bus == &spi_bus && get_property(node, "reg"))
FAIL(c, dti, node, "node name for SPI buses should be 'spi'");
}
if (node->bus != &spi_bus || !node->children)
return;
if (node_addr_cells(node) != 1)
FAIL(c, dti, node, "incorrect #address-cells for SPI bus");
if (node_size_cells(node) != 0)
FAIL(c, dti, node, "incorrect #size-cells for SPI bus");
}
WARNING(spi_bus_bridge, check_spi_bus_bridge, NULL, &addr_size_cells);
static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
{
struct property *prop;
const char *unitname = get_unitname(node);
char unit_addr[9];
uint32_t reg = 0;
cell_t *cells = NULL;
if (!node->parent || (node->parent->bus != &spi_bus))
return;
prop = get_property(node, "reg");
if (prop)
cells = (cell_t *)prop->val.val;
if (!cells) {
FAIL(c, dti, node, "missing or empty reg property");
return;
}
reg = fdt32_to_cpu(*cells);
snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
if (!streq(unitname, unit_addr))
FAIL(c, dti, node, "SPI bus unit address format error, expected \"%s\"",
unit_addr);
}
WARNING(spi_bus_reg, check_spi_bus_reg, NULL, &reg_format, &spi_bus_bridge);
static void check_unit_address_format(struct check *c, struct dt_info *dti,
struct node *node)
{
......@@ -1582,6 +1719,12 @@ static struct check *check_table[] = {
&simple_bus_bridge,
&simple_bus_reg,
&i2c_bus_bridge,
&i2c_bus_reg,
&spi_bus_bridge,
&spi_bus_reg,
&avoid_default_addr_size,
&avoid_unnecessary_addr_size,
&unique_unit_address,
......
......@@ -74,7 +74,8 @@ struct data data_copy_escape_string(const char *s, int len)
struct data d;
char *q;
d = data_grow_for(empty_data, len + 1);
d = data_add_marker(empty_data, TYPE_STRING, NULL);
d = data_grow_for(d, len + 1);
q = d.val;
while (i < len) {
......@@ -94,6 +95,7 @@ struct data data_copy_file(FILE *f, size_t maxlen)
{
struct data d = empty_data;
d = data_add_marker(d, TYPE_NONE, NULL);
while (!feof(f) && (d.len < maxlen)) {
size_t chunksize, ret;
......
......@@ -287,6 +287,7 @@ propdata:
}
| propdataprefix DT_REF
{
$1 = data_add_marker($1, TYPE_STRING, $2);
$$ = data_add_marker($1, REF_PATH, $2);
}
| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
......@@ -340,22 +341,27 @@ arrayprefix:
DT_BITS DT_LITERAL '<'
{
unsigned long long bits;
enum markertype type = TYPE_UINT32;
bits = $2;
if ((bits != 8) && (bits != 16) &&
(bits != 32) && (bits != 64)) {
switch (bits) {
case 8: type = TYPE_UINT8; break;
case 16: type = TYPE_UINT16; break;
case 32: type = TYPE_UINT32; break;
case 64: type = TYPE_UINT64; break;
default:
ERROR(&@2, "Array elements must be"
" 8, 16, 32 or 64-bits");
bits = 32;
}
$$.data = empty_data;
$$.data = data_add_marker(empty_data, type, NULL);
$$.bits = bits;
}
| '<'
{
$$.data = empty_data;
$$.data = data_add_marker(empty_data, TYPE_UINT32, NULL);
$$.bits = 32;
}
| arrayprefix integer_prim
......@@ -499,7 +505,7 @@ integer_unary:
bytestring:
/* empty */
{
$$ = empty_data;
$$ = data_add_marker(empty_data, TYPE_UINT8, NULL);
}
| bytestring DT_BYTE
{
......
......@@ -95,6 +95,9 @@ static const char * const usage_opts_help[] = {
"\n\tOutput formats are:\n"
"\t\tdts - device tree source text\n"
"\t\tdtb - device tree blob\n"
#ifndef NO_YAML
"\t\tyaml - device tree encoded as YAML\n"
#endif
"\t\tasm - assembler source",
"\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
"\n\tOutput dependency file",
......@@ -128,6 +131,8 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
return fallback;
if (!strcasecmp(s, ".dts"))
return "dts";
if (!strcasecmp(s, ".yaml"))
return "yaml";
if (!strcasecmp(s, ".dtb"))
return "dtb";
return fallback;
......@@ -350,6 +355,12 @@ int main(int argc, char *argv[])
if (streq(outform, "dts")) {
dt_to_source(outf, dti);
#ifndef NO_YAML
} else if (streq(outform, "yaml")) {
if (!streq(inform, "dts"))
die("YAML output format requires dts input format\n");
dt_to_yaml(outf, dti);
#endif
} else if (streq(outform, "dtb")) {
dt_to_blob(outf, dti, outversion);
} else if (streq(outform, "asm")) {
......
......@@ -74,10 +74,17 @@ typedef uint32_t cell_t;
/* Data blobs */
enum markertype {
TYPE_NONE,
REF_PHANDLE,
REF_PATH,
LABEL,
TYPE_UINT8,
TYPE_UINT16,
TYPE_UINT32,
TYPE_UINT64,
TYPE_STRING,
};
extern const char *markername(enum markertype markertype);
struct marker {
enum markertype type;
......@@ -101,6 +108,8 @@ struct data {
for_each_marker(m) \
if ((m)->type == (t))
size_t type_marker_length(struct marker *m);
void data_free(struct data d);
struct data data_grow_for(struct data d, int xlen);
......@@ -290,6 +299,10 @@ struct dt_info *dt_from_blob(const char *fname);
void dt_to_source(FILE *f, struct dt_info *dti);
struct dt_info *dt_from_source(const char *f);
/* YAML source */
void dt_to_yaml(FILE *f, struct dt_info *dti);
/* FS trees */
struct dt_info *dt_from_fs(const char *dirname);
......
......@@ -393,7 +393,7 @@ void dt_to_blob(FILE *f, struct dt_info *dti, int version)
padlen = 0;
if (quiet < 1)
fprintf(stderr,
"Warning: blob size %d >= minimum size %d\n",
"Warning: blob size %"PRIu32" >= minimum size %d\n",
fdt32_to_cpu(fdt.totalsize), minsize);
}
}
......
......@@ -55,7 +55,12 @@
#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) {
/* Complete tree */
......@@ -74,6 +79,78 @@ int fdt_check_header(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);
......@@ -244,7 +321,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_CHECK_HEADER(fdt);
FDT_RO_PROBE(fdt);
if (fdt_totalsize(fdt) > bufsize)
return -FDT_ERR_NOSPACE;
......
/*
* libfdt - Flat Device Tree manipulation
* 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
* the GPL, or the BSD license, at your option.
......@@ -55,42 +56,32 @@
#include "libfdt_internal.h"
int fdt_address_cells(const void *fdt, int nodeoffset)
static int fdt_cells(const void *fdt, int nodeoffset, const char *name)
{
const fdt32_t *ac;
const fdt32_t *c;
int val;
int len;
ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
if (!ac)
c = fdt_getprop(fdt, nodeoffset, name, &len);
if (!c)
return 2;
if (len != sizeof(*ac))
if (len != sizeof(*c))
return -FDT_ERR_BADNCELLS;
val = fdt32_to_cpu(*ac);
val = fdt32_to_cpu(*c);
if ((val <= 0) || (val > FDT_MAX_NCELLS))
return -FDT_ERR_BADNCELLS;
return val;
}
int fdt_size_cells(const void *fdt, int nodeoffset)
int fdt_address_cells(const void *fdt, int nodeoffset)
{
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 fdt_cells(fdt, nodeoffset, "#address-cells");
}
return val;
int fdt_size_cells(const void *fdt, int nodeoffset)
{
return fdt_cells(fdt, nodeoffset, "#size-cells");
}
......@@ -697,7 +697,7 @@ static int get_path_len(const void *fdt, int nodeoffset)
int len = 0, namelen;
const char *name;
FDT_CHECK_HEADER(fdt);
FDT_RO_PROBE(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_CHECK_HEADER(fdt);
FDT_CHECK_HEADER(fdto);
FDT_RO_PROBE(fdt);
FDT_RO_PROBE(fdto);
ret = overlay_adjust_local_phandles(fdto, delta);
if (ret)
......
......@@ -76,17 +76,72 @@ 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 (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
return fdt_get_string(fdt, stroffset, NULL);
}
static int fdt_string_eq_(const void *fdt, int stroffset,
const char *s, int len)
{
const char *p = fdt_string(fdt, stroffset);
int slen;
const char *p = fdt_get_string(fdt, stroffset, &slen);
return (strlen(p) == len) && (memcmp(p, s, len) == 0);
return p && (slen == len) && (memcmp(p, s, len) == 0);
}
uint32_t fdt_get_max_phandle(const void *fdt)
......@@ -115,21 +170,42 @@ 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)
{
FDT_CHECK_HEADER(fdt);
*address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
*size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->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);
return 0;
}
int fdt_num_mem_rsv(const void *fdt)
{
int i = 0;
int i;
const struct fdt_reserve_entry *re;
while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
i++;
return i;
for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
if (fdt64_ld(&re->size) == 0)
return i;
}
return -FDT_ERR_TRUNCATED;
}
static int nextprop_(const void *fdt, int offset)
......@@ -161,7 +237,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
{
int depth;
FDT_CHECK_HEADER(fdt);
FDT_RO_PROBE(fdt);
for (depth = 0;
(offset >= 0) && (depth >= 0);
......@@ -187,7 +263,7 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
const char *p = path;
int offset = 0;
FDT_CHECK_HEADER(fdt);
FDT_RO_PROBE(fdt);
/* see if we have an alias */
if (*path != '/') {
......@@ -237,7 +313,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
const char *nameptr;
int err;
if (((err = fdt_check_header(fdt)) != 0)
if (((err = fdt_ro_probe_(fdt)) != 0)
|| ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
goto fail;
......@@ -303,7 +379,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
prop = fdt_offset_ptr_(fdt, offset);
if (lenp)
*lenp = fdt32_to_cpu(prop->len);
*lenp = fdt32_ld(&prop->len);
return prop;
}
......@@ -340,7 +416,7 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
offset = -FDT_ERR_INTERNAL;
break;
}
if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
name, namelen)) {
if (poffset)
*poffset = offset;
......@@ -393,7 +469,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
/* Handle realignment */
if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
fdt32_to_cpu(prop->len) >= 8)
fdt32_ld(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
......@@ -406,12 +482,22 @@ 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)
*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
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;
}
/* Handle realignment */
if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
fdt32_to_cpu(prop->len) >= 8)
fdt32_ld(