ANDROID: Merge upstream ed310803ea (v1.6.1)

Upgrade to the latest master from

    git://git.kernel.org/pub/scm/utils/dtc/dtc.git.

at commit ed310803ea.

Bug: 221191119
Bug: 222320399
Bug: 230794395
Bug: 234413190
Change-Id: I6cc623e217641d7db3d4f2c4873cda472da08ef4
(cherry picked from commit 9c26cc838f)
Merged-In: I6cc623e217641d7db3d4f2c4873cda472da08ef4
This commit is contained in:
Pierre-Clément Tosi 2022-05-30 20:57:34 +01:00 committed by Cherrypicker Worker
parent 8c0093a65c
commit ef1978abee
81 changed files with 1691 additions and 576 deletions

View file

@ -1,9 +1,9 @@
env:
CIRRUS_CLONE_DEPTH: 1
freebsd_12_task:
freebsd_13_task:
freebsd_instance:
image: freebsd-12-1-release-amd64
image: freebsd-13-0-release-amd64
install_script:
pkg install -y bison gmake pkgconf
build_script:

9
.gitignore vendored
View file

@ -8,6 +8,7 @@
*.tab.[ch]
lex.yy.c
*.lex.c
.*.swp
/dtc
/fdtdump
/convert-dtsv0
@ -17,3 +18,11 @@ lex.yy.c
/fdtoverlay
/patches
/.pc
# cscope files
cscope.*
ncscope.*
.eggs/
build/
dist/

View file

@ -45,7 +45,7 @@ The gitweb interface for the upstream repository is:
Patches should be sent to the maintainers:
David Gibson <david@gibson.dropbear.id.au>
Jon Loeliger <jdl@jdl.com>
Jon Loeliger <loeliger@gmail.com>
and CCed to <devicetree-compiler@vger.kernel.org>.
2) Description
@ -712,7 +712,7 @@ The syntax of the fdtget command is:
where options are:
<type> s=string, i=int, u=unsigned, x=hex
<type> s=string, i=int, u=unsigned, x=hex, r=raw
Optional modifier prefix:
hh or b=byte, h=2 byte, l=4 byte (default)

11
MANIFEST.in Normal file
View file

@ -0,0 +1,11 @@
# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
global-exclude *
include README
include GPL
include BSD-2-Clause
include setup.py
include pylibfdt/libfdt.i
include libfdt/libfdt.h
include libfdt/fdt.h
include libfdt/libfdt_env.h

View file

@ -11,7 +11,7 @@
#
VERSION = 1
PATCHLEVEL = 6
SUBLEVEL = 0
SUBLEVEL = 1
EXTRAVERSION =
LOCAL_VERSION =
CONFIG_LOCALVERSION =
@ -21,7 +21,7 @@ CONFIG_LOCALVERSION =
ASSUME_MASK ?= 0
CPPFLAGS = -I libfdt -I . -DFDT_ASSUME_MASK=$(ASSUME_MASK)
WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
WARNINGS = -Wall -Wpointer-arith -Wcast-qual -Wnested-externs -Wsign-compare \
-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls -Wshadow
CFLAGS = -g -Os $(SHAREDLIB_CFLAGS) -Werror $(WARNINGS) $(EXTRA_CFLAGS)
@ -59,6 +59,7 @@ ifeq ($(NO_YAML),1)
CFLAGS += -DNO_YAML
else
LDLIBS_dtc += $(shell $(PKG_CONFIG) --libs yaml-0.1)
CFLAGS += $(shell $(PKG_CONFIG) --cflags yaml-0.1)
endif
ifeq ($(HOSTOS),darwin)

31
README
View file

@ -5,7 +5,7 @@ utility library for reading and manipulating the binary format.
DTC and LIBFDT are maintained by:
David Gibson <david@gibson.dropbear.id.au>
Jon Loeliger <jdl@jdl.com>
Jon Loeliger <loeliger@gmail.com>
Python library
@ -48,18 +48,24 @@ If you add new features, please check code coverage:
# Open 'htmlcov/index.html' in your browser
To install the library via the normal setup.py method, use:
The library can be installed with pip from a local source tree:
./pylibfdt/setup.py install [--prefix=/path/to/install_dir]
pip install . [--user|--prefix=/path/to/install_dir]
If --prefix is not provided, the default prefix is used, typically '/usr'
or '/usr/local'. See Python's distutils documentation for details. You can
also install via the Makefile if you like, but the above is more common.
Or directly from a remote git repo:
pip install git+git://git.kernel.org/pub/scm/utils/dtc/dtc.git@main
The install depends on libfdt shared library being installed on the host system
first. Generally, using --user or --prefix is not necessary and pip will use the
default location for the Python installation which varies if the user is root or
not.
You can also install everything via make if you like, but pip is recommended.
To install both libfdt and pylibfdt you can use:
make install [SETUP_PREFIX=/path/to/install_dir] \
[PREFIX=/path/to/install_dir]
make install [PREFIX=/path/to/install_dir]
To disable building the python library, even if swig and Python are available,
use:
@ -71,6 +77,15 @@ More work remains to support all of libfdt, including access to numeric
values.
Adding a new function to libfdt.h
---------------------------------
The shared library uses libfdt/version.lds to list the exported functions, so
add your new function there. Check that your function works with pylibfdt. If
it cannot be supported, put the declaration in libfdt.h behind #ifndef SWIG so
that swig ignores it.
Tests
-----

243
checks.c
View file

@ -143,6 +143,14 @@ static void check_nodes_props(struct check *c, struct dt_info *dti, struct node
check_nodes_props(c, dti, child);
}
static bool is_multiple_of(int multiple, int divisor)
{
if (divisor == 0)
return multiple == 0;
else
return (multiple % divisor) == 0;
}
static bool run_check(struct check *c, struct dt_info *dti)
{
struct node *dt = dti->dt;
@ -297,19 +305,20 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define DIGITS "0123456789"
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
#define NODECHARS LOWERCASE UPPERCASE DIGITS ",._+-@"
#define PROPCHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
#define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
static void check_node_name_chars(struct check *c, struct dt_info *dti,
struct node *node)
{
int n = strspn(node->name, c->data);
size_t n = strspn(node->name, c->data);
if (n < strlen(node->name))
FAIL(c, dti, node, "Bad character '%c' in node name",
node->name[n]);
}
ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
ERROR(node_name_chars, check_node_name_chars, NODECHARS);
static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
struct node *node)
@ -330,6 +339,20 @@ static void check_node_name_format(struct check *c, struct dt_info *dti,
}
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
static void check_node_name_vs_property_name(struct check *c,
struct dt_info *dti,
struct node *node)
{
if (!node->parent)
return;
if (get_property(node->parent, node->name)) {
FAIL(c, dti, node, "node name and property name conflict");
}
}
WARNING(node_name_vs_property_name, check_node_name_vs_property_name,
NULL, &node_name_chars);
static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
struct node *node)
{
@ -363,14 +386,14 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
struct property *prop;
for_each_property(node, prop) {
int n = strspn(prop->name, c->data);
size_t n = strspn(prop->name, c->data);
if (n < strlen(prop->name))
FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name",
prop->name[n]);
}
}
ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
ERROR(property_name_chars, check_property_name_chars, PROPCHARS);
static void check_property_name_chars_strict(struct check *c,
struct dt_info *dti,
@ -380,7 +403,7 @@ static void check_property_name_chars_strict(struct check *c,
for_each_property(node, prop) {
const char *name = prop->name;
int n = strspn(name, c->data);
size_t n = strspn(name, c->data);
if (n == strlen(prop->name))
continue;
@ -497,7 +520,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
phandle = propval_cell(prop);
if ((phandle == 0) || (phandle == -1)) {
if (!phandle_is_valid(phandle)) {
FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
phandle, prop->name);
return 0;
@ -556,7 +579,7 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
if (!prop)
return; /* No name property, that's fine */
if ((prop->val.len != node->basenamelen+1)
if ((prop->val.len != node->basenamelen + 1U)
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
" of base node name)", prop->val.val);
@ -657,7 +680,6 @@ ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &pa
*/
WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
WARNING_IF_NOT_STRING(model_is_string, "model");
@ -672,8 +694,7 @@ static void check_names_is_string_list(struct check *c, struct dt_info *dti,
struct property *prop;
for_each_property(node, prop) {
const char *s = strrchr(prop->name, '-');
if (!s || !streq(s, "-names"))
if (!strends(prop->name, "-names"))
continue;
c->data = prop->name;
@ -753,7 +774,7 @@ static void check_reg_format(struct check *c, struct dt_info *dti,
size_cells = node_size_cells(node->parent);
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
if (!entrylen || (prop->val.len % entrylen) != 0)
if (!is_multiple_of(prop->val.len, entrylen))
FAIL_PROP(c, dti, node, prop, "property has invalid length (%d bytes) "
"(#address-cells == %d, #size-cells == %d)",
prop->val.len, addr_cells, size_cells);
@ -794,7 +815,7 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
"#size-cells (%d) differs from %s (%d)",
ranges, c_size_cells, node->parent->fullpath,
p_size_cells);
} else if ((prop->val.len % entrylen) != 0) {
} else if (!is_multiple_of(prop->val.len, entrylen)) {
FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) "
"(parent #address-cells == %d, child #address-cells == %d, "
"#size-cells == %d)", ranges, prop->val.len,
@ -871,7 +892,7 @@ static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struc
} else {
cells = (cell_t *)prop->val.val;
min_bus = fdt32_to_cpu(cells[0]);
max_bus = fdt32_to_cpu(cells[0]);
max_bus = fdt32_to_cpu(cells[1]);
}
if ((bus_num < min_bus) || (bus_num > max_bus))
FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)",
@ -891,10 +912,8 @@ static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct no
return;
prop = get_property(node, "reg");
if (!prop) {
FAIL(c, dti, node, "missing PCI reg property");
if (!prop)
return;
}
cells = (cell_t *)prop->val.val;
if (cells[1] || cells[2])
@ -1363,15 +1382,15 @@ struct provider {
};
static void check_property_phandle_args(struct check *c,
struct dt_info *dti,
struct node *node,
struct property *prop,
const struct provider *provider)
struct dt_info *dti,
struct node *node,
struct property *prop,
const struct provider *provider)
{
struct node *root = dti->dt;
int cell, cellsize = 0;
unsigned int cell, cellsize = 0;
if (prop->val.len % sizeof(cell_t)) {
if (!is_multiple_of(prop->val.len, sizeof(cell_t))) {
FAIL_PROP(c, dti, node, prop,
"property size (%d) is invalid, expected multiple of %zu",
prop->val.len, sizeof(cell_t));
@ -1381,14 +1400,15 @@ static void check_property_phandle_args(struct check *c,
for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) {
struct node *provider_node;
struct property *cellprop;
int phandle;
cell_t phandle;
unsigned int expected;
phandle = propval_cell_n(prop, cell);
/*
* Some bindings use a cell value 0 or -1 to skip over optional
* entries when each index position has a specific definition.
*/
if (phandle == 0 || phandle == -1) {
if (!phandle_is_valid(phandle)) {
/* Give up if this is an overlay with external references */
if (dti->dtsflags & DTSF_PLUGIN)
break;
@ -1431,10 +1451,12 @@ static void check_property_phandle_args(struct check *c,
break;
}
if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
expected = (cell + cellsize + 1) * sizeof(cell_t);
if ((expected <= cell) || prop->val.len < expected) {
FAIL_PROP(c, dti, node, prop,
"property size (%d) too small for cell size %d",
"property size (%d) too small for cell size %u",
prop->val.len, cellsize);
break;
}
}
}
@ -1454,7 +1476,8 @@ static void check_provider_cells_property(struct check *c,
}
#define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \
static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \
WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references);
WARNING_IF_NOT_CELL(nm##_is_cell, cells_name); \
WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &nm##_is_cell, &phandle_references);
WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
@ -1475,24 +1498,17 @@ WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sen
static bool prop_is_gpio(struct property *prop)
{
char *str;
/*
* *-gpios and *-gpio can appear in property names,
* so skip over any false matches (only one known ATM)
*/
if (strstr(prop->name, "nr-gpio"))
if (strends(prop->name, ",nr-gpios"))
return false;
str = strrchr(prop->name, '-');
if (str)
str++;
else
str = prop->name;
if (!(streq(str, "gpios") || streq(str, "gpio")))
return false;
return true;
return strends(prop->name, "-gpios") ||
streq(prop->name, "gpios") ||
strends(prop->name, "-gpio") ||
streq(prop->name, "gpio");
}
static void check_gpios_property(struct check *c,
@ -1527,13 +1543,10 @@ static void check_deprecated_gpio_property(struct check *c,
struct property *prop;
for_each_property(node, prop) {
char *str;
if (!prop_is_gpio(prop))
continue;
str = strstr(prop->name, "gpio");
if (!streq(str, "gpio"))
if (!strends(prop->name, "gpio"))
continue;
FAIL_PROP(c, dti, node, prop,
@ -1563,21 +1576,106 @@ static void check_interrupt_provider(struct check *c,
struct node *node)
{
struct property *prop;
if (!node_is_interrupt_provider(node))
return;
bool irq_provider = node_is_interrupt_provider(node);
prop = get_property(node, "#interrupt-cells");
if (!prop)
if (irq_provider && !prop) {
FAIL(c, dti, node,
"Missing #interrupt-cells in interrupt provider");
"Missing '#interrupt-cells' in interrupt provider");
return;
}
prop = get_property(node, "#address-cells");
if (!prop)
if (!irq_provider && prop) {
FAIL(c, dti, node,
"Missing #address-cells in interrupt provider");
"'#interrupt-cells' found, but node is not an interrupt provider");
return;
}
}
WARNING(interrupt_provider, check_interrupt_provider, NULL);
WARNING(interrupt_provider, check_interrupt_provider, NULL, &interrupts_extended_is_cell);
static void check_interrupt_map(struct check *c,
struct dt_info *dti,
struct node *node)
{
struct node *root = dti->dt;
struct property *prop, *irq_map_prop;
size_t cellsize, cell, map_cells;
irq_map_prop = get_property(node, "interrupt-map");
if (!irq_map_prop)
return;
if (node->addr_cells < 0) {
FAIL(c, dti, node,
"Missing '#address-cells' in interrupt-map provider");
return;
}
cellsize = node_addr_cells(node);
cellsize += propval_cell(get_property(node, "#interrupt-cells"));
prop = get_property(node, "interrupt-map-mask");
if (prop && (prop->val.len != (cellsize * sizeof(cell_t))))
FAIL_PROP(c, dti, node, prop,
"property size (%d) is invalid, expected %zu",
prop->val.len, cellsize * sizeof(cell_t));
if (!is_multiple_of(irq_map_prop->val.len, sizeof(cell_t))) {
FAIL_PROP(c, dti, node, irq_map_prop,
"property size (%d) is invalid, expected multiple of %zu",
irq_map_prop->val.len, sizeof(cell_t));
return;
}
map_cells = irq_map_prop->val.len / sizeof(cell_t);
for (cell = 0; cell < map_cells; ) {
struct node *provider_node;
struct property *cellprop;
int phandle;
size_t parent_cellsize;
if ((cell + cellsize) >= map_cells) {
FAIL_PROP(c, dti, node, irq_map_prop,
"property size (%d) too small, expected > %zu",
irq_map_prop->val.len, (cell + cellsize) * sizeof(cell_t));
break;
}
cell += cellsize;
phandle = propval_cell_n(irq_map_prop, cell);
if (!phandle_is_valid(phandle)) {
/* Give up if this is an overlay with external references */
if (!(dti->dtsflags & DTSF_PLUGIN))
FAIL_PROP(c, dti, node, irq_map_prop,
"Cell %zu is not a phandle(%d)",
cell, phandle);
break;
}
provider_node = get_node_by_phandle(root, phandle);
if (!provider_node) {
FAIL_PROP(c, dti, node, irq_map_prop,
"Could not get phandle(%d) node for (cell %zu)",
phandle, cell);
break;
}
cellprop = get_property(provider_node, "#interrupt-cells");
if (cellprop) {
parent_cellsize = propval_cell(cellprop);
} else {
FAIL(c, dti, node, "Missing property '#interrupt-cells' in node %s or bad phandle (referred from interrupt-map[%zu])",
provider_node->fullpath, cell);
break;
}
cellprop = get_property(provider_node, "#address-cells");
if (cellprop)
parent_cellsize += propval_cell(cellprop);
cell += 1 + parent_cellsize;
}
}
WARNING(interrupt_map, check_interrupt_map, NULL, &phandle_references, &addr_size_cells, &interrupt_provider);
static void check_interrupts_property(struct check *c,
struct dt_info *dti,
@ -1586,13 +1684,13 @@ static void check_interrupts_property(struct check *c,
struct node *root = dti->dt;
struct node *irq_node = NULL, *parent = node;
struct property *irq_prop, *prop = NULL;
int irq_cells, phandle;
cell_t irq_cells, phandle;
irq_prop = get_property(node, "interrupts");
if (!irq_prop)
return;
if (irq_prop->val.len % sizeof(cell_t))
if (!is_multiple_of(irq_prop->val.len, sizeof(cell_t)))
FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu",
irq_prop->val.len, sizeof(cell_t));
@ -1605,7 +1703,7 @@ static void check_interrupts_property(struct check *c,
prop = get_property(parent, "interrupt-parent");
if (prop) {
phandle = propval_cell(prop);
if ((phandle == 0) || (phandle == -1)) {
if (!phandle_is_valid(phandle)) {
/* Give up if this is an overlay with
* external references */
if (dti->dtsflags & DTSF_PLUGIN)
@ -1641,7 +1739,7 @@ static void check_interrupts_property(struct check *c,
}
irq_cells = propval_cell(prop);
if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) {
if (!is_multiple_of(irq_prop->val.len, irq_cells * sizeof(cell_t))) {
FAIL_PROP(c, dti, node, prop,
"size is (%d), expected multiple of %d",
irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)));
@ -1752,7 +1850,7 @@ WARNING(graph_port, check_graph_port, NULL, &graph_nodes);
static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
struct node *endpoint)
{
int phandle;
cell_t phandle;
struct node *node;
struct property *prop;
@ -1762,7 +1860,7 @@ static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
phandle = propval_cell(prop);
/* Give up if this is an overlay with external references */
if (phandle == 0 || phandle == -1)
if (!phandle_is_valid(phandle))
return NULL;
node = get_node_by_phandle(dti->dt, phandle);
@ -1798,7 +1896,7 @@ WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
&node_name_chars, &node_name_format, &property_name_chars,
&name_is_string, &name_properties,
&name_is_string, &name_properties, &node_name_vs_property_name,
&duplicate_label,
@ -1806,7 +1904,7 @@ static struct check *check_table[] = {
&phandle_references, &path_references,
&omit_unused_nodes,
&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
&address_cells_is_cell, &size_cells_is_cell,
&device_type_is_string, &model_is_string, &status_is_string,
&label_is_string,
@ -1841,26 +1939,43 @@ static struct check *check_table[] = {
&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
&clocks_property,
&clocks_is_cell,
&cooling_device_property,
&cooling_device_is_cell,
&dmas_property,
&dmas_is_cell,
&hwlocks_property,
&hwlocks_is_cell,
&interrupts_extended_property,
&interrupts_extended_is_cell,
&io_channels_property,
&io_channels_is_cell,
&iommus_property,
&iommus_is_cell,
&mboxes_property,
&mboxes_is_cell,
&msi_parent_property,
&msi_parent_is_cell,
&mux_controls_property,
&mux_controls_is_cell,
&phys_property,
&phys_is_cell,
&power_domains_property,
&power_domains_is_cell,
&pwms_property,
&pwms_is_cell,
&resets_property,
&resets_is_cell,
&sound_dai_property,
&sound_dai_is_cell,
&thermal_sensors_property,
&thermal_sensors_is_cell,
&deprecated_gpio_property,
&gpios_property,
&interrupts_property,
&interrupt_provider,
&interrupt_map,
&alias_paths,
@ -1884,7 +1999,7 @@ static void enable_warning_error(struct check *c, bool warn, bool error)
static void disable_warning_error(struct check *c, bool warn, bool error)
{
int i;
unsigned int i;
/* Lowering level, also lower it for things this is the prereq
* for */
@ -1905,7 +2020,7 @@ static void disable_warning_error(struct check *c, bool warn, bool error)
void parse_checks_option(bool warn, bool error, const char *arg)
{
int i;
unsigned int i;
const char *name = arg;
bool enable = true;
@ -1932,7 +2047,7 @@ void parse_checks_option(bool warn, bool error, const char *arg)
void process_checks(bool force, struct dt_info *dti)
{
int i;
unsigned int i;
int error = 0;
for (i = 0; i < ARRAY_SIZE(check_table); i++) {

View file

@ -94,7 +94,7 @@ static const struct {
<INITIAL>[0-9a-fA-F]+ {
unsigned long long val;
int obase = 16, width = 0;
int i;
unsigned int i;
val = strtoull(yytext, NULL, cbase);

6
data.c
View file

@ -21,10 +21,10 @@ void data_free(struct data d)
free(d.val);
}
struct data data_grow_for(struct data d, int xlen)
struct data data_grow_for(struct data d, unsigned int xlen)
{
struct data nd;
int newsize;
unsigned int newsize;
if (xlen == 0)
return d;
@ -84,7 +84,7 @@ struct data data_copy_file(FILE *f, size_t maxlen)
while (!feof(f) && (d.len < maxlen)) {
size_t chunksize, ret;
if (maxlen == -1)
if (maxlen == (size_t)-1)
chunksize = 4096;
else
chunksize = maxlen - d.len;

View file

@ -57,7 +57,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
push_input_file(name);
}
<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)* {
char *line, *fnstart, *fnend;
struct data fn;
/* skip text before line # */
@ -200,7 +200,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
return DT_LABEL_REF;
}
<*>"&{/"{PATHCHAR}*\} { /* new-style path reference */
<*>"&{"{PATHCHAR}*\} { /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
yylval.labelref = xstrdup(yytext+2);

View file

@ -23,6 +23,12 @@ extern void yyerror(char const *s);
extern struct dt_info *parser_output;
extern bool treesource_error;
static bool is_ref_relative(const char *ref)
{
return ref[0] != '/' && strchr(&ref[1], '/');
}
%}
%union {
@ -169,6 +175,8 @@ devicetree:
*/
if (!($<flags>-1 & DTSF_PLUGIN))
ERROR(&@2, "Label or path %s not found", $1);
else if (is_ref_relative($1))
ERROR(&@2, "Label-relative reference %s not supported in plugin", $1);
$$ = add_orphan_node(
name_node(build_node(NULL, NULL, NULL),
""),
@ -178,6 +186,9 @@ devicetree:
{
struct node *target = get_node_by_ref($1, $3);
if (($<flags>-1 & DTSF_PLUGIN) && is_ref_relative($3))
ERROR(&@2, "Label-relative reference %s not supported in plugin", $3);
if (target) {
add_label(&target->labels, $2);
merge_nodes(target, $4);
@ -193,6 +204,8 @@ devicetree:
* so $-1 is what we want (plugindecl)
*/
if ($<flags>-1 & DTSF_PLUGIN) {
if (is_ref_relative($2))
ERROR(&@2, "Label-relative reference %s not supported in plugin", $2);
add_orphan_node($1, $3, $2);
} else {
struct node *target = get_node_by_ref($1, $2);
@ -481,8 +494,8 @@ integer_rela:
;
integer_shift:
integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
| integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; }
| integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; }
| integer_add
;

6
dtc.c
View file

@ -12,7 +12,7 @@
* Command line options
*/
int quiet; /* Level of quietness */
int reservenum; /* Number of memory reservation slots */
unsigned int reservenum;/* Number of memory reservation slots */
int minsize; /* Minimum blob size */
int padsize; /* Additional padding to blob */
int alignsize; /* Additional padding to blob accroding to the alignsize */
@ -122,6 +122,8 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
return "dts";
if (!strcasecmp(s, ".yaml"))
return "yaml";
if (!strcasecmp(s, ".dtbo"))
return "dtb";
if (!strcasecmp(s, ".dtb"))
return "dtb";
return fallback;
@ -195,7 +197,7 @@ int main(int argc, char *argv[])
depname = optarg;
break;
case 'R':
reservenum = strtol(optarg, NULL, 0);
reservenum = strtoul(optarg, NULL, 0);
break;
case 'S':
minsize = strtol(optarg, NULL, 0);

48
dtc.h
View file

@ -35,7 +35,7 @@
* Command line options
*/
extern int quiet; /* Level of quietness */
extern int reservenum; /* Number of memory reservation slots */
extern unsigned int reservenum; /* Number of memory reservation slots */
extern int minsize; /* Minimum blob size */
extern int padsize; /* Additional padding to blob */
extern int alignsize; /* Additional padding to blob accroding to the alignsize */
@ -51,6 +51,11 @@ extern int annotate; /* annotate .dts with input source location */
typedef uint32_t cell_t;
static inline bool phandle_is_valid(cell_t phandle)
{
return phandle != 0 && phandle != ~0U;
}
static inline uint16_t dtb_ld16(const void *p)
{
const uint8_t *bp = (const uint8_t *)p;
@ -86,6 +91,16 @@ static inline uint64_t dtb_ld64(const void *p)
#define streq(a, b) (strcmp((a), (b)) == 0)
#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0)
#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0))
static inline bool strends(const char *str, const char *suffix)
{
unsigned int len, suffix_len;
len = strlen(str);
suffix_len = strlen(suffix);
if (len < suffix_len)
return false;
return streq(str + len - suffix_len, suffix);
}
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
@ -101,17 +116,23 @@ enum markertype {
TYPE_UINT64,
TYPE_STRING,
};
static inline bool is_type_marker(enum markertype type)
{
return type >= TYPE_UINT8;
}
extern const char *markername(enum markertype markertype);
struct marker {
enum markertype type;
int offset;
unsigned int offset;
char *ref;
struct marker *next;
};
struct data {
int len;
unsigned int len;
char *val;
struct marker *markers;
};
@ -125,11 +146,26 @@ struct data {
for_each_marker(m) \
if ((m)->type == (t))
size_t type_marker_length(struct marker *m);
static inline struct marker *next_type_marker(struct marker *m)
{
for_each_marker(m)
if (is_type_marker(m->type))
break;
return m;
}
static inline size_t type_marker_length(struct marker *m)
{
struct marker *next = next_type_marker(m->next);
if (next)
return next->offset - m->offset;
return 0;
}
void data_free(struct data d);
struct data data_grow_for(struct data d, int xlen);
struct data data_grow_for(struct data d, unsigned int xlen);
struct data data_copy_mem(const char *mem, int len);
struct data data_copy_escape_string(const char *s, int len);
@ -253,7 +289,7 @@ void append_to_property(struct node *node,
const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname);
cell_t propval_cell(struct property *prop);
cell_t propval_cell_n(struct property *prop, int n);
cell_t propval_cell_n(struct property *prop, unsigned int n);
struct property *get_property_by_label(struct node *tree, const char *label,
struct node **node);
struct marker *get_marker_label(struct node *tree, const char *label,

View file

@ -18,10 +18,10 @@
#include "util.h"
#define FDT_MAGIC_SIZE 4
#define MAX_VERSION 17
#define MAX_VERSION 17U
#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
#define PALIGN(p, a) ((void *)(ALIGN((uintptr_t)(p), (a))))
#define GET_CELL(p) (p += 4, *((const fdt32_t *)(p-4)))
static const char *tagname(uint32_t tag)
@ -163,7 +163,7 @@ static const char * const usage_opts_help[] = {
USAGE_COMMON_OPTS_HELP
};
static bool valid_header(char *p, off_t len)
static bool valid_header(char *p, size_t len)
{
if (len < sizeof(struct fdt_header) ||
fdt_magic(p) != FDT_MAGIC ||
@ -217,7 +217,7 @@ int main(int argc, char *argv[])
char *p = buf;
char *endp = buf + len;
fdt_set_magic(smagic, FDT_MAGIC);
fdt32_st(smagic, FDT_MAGIC);
/* poor man's memmem */
while ((endp - p) >= FDT_MAGIC_SIZE) {
@ -235,7 +235,7 @@ int main(int argc, char *argv[])
}
++p;
}
if (!p || endp - p < sizeof(struct fdt_header))
if (!p || (size_t)(endp - p) < sizeof(struct fdt_header))
die("%s: could not locate fdt magic\n", file);
printf("%s: found fdt at offset %#tx\n", file, p - buf);
buf = p;

View file

@ -62,8 +62,14 @@ static int show_cell_list(struct display_info *disp, const char *data, int len,
for (i = 0; i < len; i += size, p += size) {
if (i)
printf(" ");
value = size == 4 ? fdt32_ld((const fdt32_t *)p) :
size == 2 ? (*p << 8) | p[1] : *p;
switch (size) {
case 4: value = fdt32_ld((const fdt32_t *)p); break;
case 2: value = fdt16_ld((const fdt16_t *)p); break;
case 1:
default:
value = *p;
break;
}
printf(fmt, value);
}
@ -91,6 +97,11 @@ static int show_data(struct display_info *disp, const char *data, int len)
if (len == 0)
return 0;
if (disp->type == 'r') {
fwrite(data, 1, len, stdout);
return 0;
}
is_string = (disp->type) == 's' ||
(!disp->type && util_is_printable_string(data, len));
if (is_string) {

View file

@ -433,6 +433,8 @@ int main(int argc, char *argv[])
if (utilfdt_decode_type(optarg, &disp.type,
&disp.size))
usage("Invalid type string");
if (disp.type == 'r')
usage("Unsupported raw data type");
break;
case 'v':

View file

@ -124,7 +124,8 @@ static void asm_emit_cell(void *e, cell_t val)
{
FILE *f = e;
fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n",
fprintf(f, "\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n"
"\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n",
(val >> 24) & 0xff, (val >> 16) & 0xff,
(val >> 8) & 0xff, val & 0xff);
}
@ -134,9 +135,9 @@ static void asm_emit_string(void *e, const char *str, int len)
FILE *f = e;
if (len != 0)
fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
fprintf(f, "\t.asciz\t\"%.*s\"\n", len, str);
else
fprintf(f, "\t.string\t\"%s\"\n", str);
fprintf(f, "\t.asciz\t\"%s\"\n", str);
}
static void asm_emit_align(void *e, int a)
@ -149,7 +150,7 @@ static void asm_emit_align(void *e, int a)
static void asm_emit_data(void *e, struct data d)
{
FILE *f = e;
int off = 0;
unsigned int off = 0;
struct marker *m = d.markers;
for_each_marker_of_type(m, LABEL)
@ -219,7 +220,7 @@ static struct emitter asm_emitter = {
static int stringtable_insert(struct data *d, const char *str)
{
int i;
unsigned int i;
/* FIXME: do this more efficiently? */
@ -295,7 +296,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
{
struct reserve_info *re;
struct data d = empty_data;
int j;
unsigned int j;
for (re = reservelist; re; re = re->next) {
d = data_append_re(d, re->address, re->size);
@ -345,7 +346,7 @@ static void make_fdt_header(struct fdt_header *fdt,
void dt_to_blob(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
int i;
unsigned int i;
struct data blob = empty_data;
struct data reservebuf = empty_data;
struct data dtbuf = empty_data;
@ -438,7 +439,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
while (p < (strbuf.val + strbuf.len)) {
len = strlen(p);
fprintf(f, "\t.string \"%s\"\n", p);
fprintf(f, "\t.asciz \"%s\"\n", p);
p += len+1;
}
}
@ -446,7 +447,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
void dt_to_asm(FILE *f, struct dt_info *dti, int version)
{
struct version_info *vi = NULL;
int i;
unsigned int i;
struct data strbuf = empty_data;
struct reserve_info *re;
const char *symprefix = "dt";

View file

@ -22,6 +22,10 @@ int32_t fdt_ro_probe_(const void *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 (!can_assume(LATEST)) {
@ -86,6 +90,10 @@ 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)) {
@ -134,16 +142,20 @@ int fdt_check_header(const void *fdt)
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 (offset < 0)
return NULL;
if (!can_assume(VALID_INPUT))
if ((absoffset < offset)
if ((absoffset < uoffset)
|| ((absoffset + len) < absoffset)
|| (absoffset + len) > fdt_totalsize(fdt))
return NULL;
if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
if (((offset + len) < offset)
if (((uoffset + len) < uoffset)
|| ((offset + len) > fdt_size_dt_struct(fdt)))
return NULL;
@ -206,10 +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 (can_assume(VALID_INPUT))
return 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;
@ -217,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;
@ -306,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));

View file

@ -73,7 +73,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
/* check validity of address */
prop = data;
if (addr_cells == 1) {
if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size))
return -FDT_ERR_BADVALUE;
fdt32_st(prop, (uint32_t)addr);

View file

@ -19,9 +19,12 @@ int fdt_check_full(const void *fdt, size_t bufsize)
unsigned int depth = 0;
const void *prop;
const char *propname;
bool expect_end = false;
if (bufsize < FDT_V1_SIZE)
return -FDT_ERR_TRUNCATED;
if (bufsize < fdt_header_size(fdt))
return -FDT_ERR_TRUNCATED;
err = fdt_check_header(fdt);
if (err != 0)
return err;
@ -39,6 +42,10 @@ int fdt_check_full(const void *fdt, size_t bufsize)
if (nextoffset < 0)
return nextoffset;
/* If we see two root nodes, something is wrong */
if (expect_end && tag != FDT_END)
return -FDT_ERR_BADSTRUCTURE;
switch (tag) {
case FDT_NOP:
break;
@ -52,12 +59,24 @@ int fdt_check_full(const void *fdt, size_t bufsize)
depth++;
if (depth > INT_MAX)
return -FDT_ERR_BADSTRUCTURE;
/* The root node must have an empty name */
if (depth == 1) {
const char *name;
int len;
name = fdt_get_name(fdt, offset, &len);
if (*name || len)
return -FDT_ERR_BADSTRUCTURE;
}
break;
case FDT_END_NODE:
if (depth == 0)
return -FDT_ERR_BADSTRUCTURE;
depth--;
if (depth == 0)
expect_end = true;
break;
case FDT_PROP:

View file

@ -40,37 +40,22 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
return fdt32_to_cpu(*val);
}
/**
* overlay_get_target - retrieves the offset of a fragment's target
* @fdt: Base device tree blob
* @fdto: Device tree overlay blob
* @fragment: node offset of the fragment in the overlay
* @pathp: pointer which receives the path of the target (or NULL)
*
* overlay_get_target() retrieves the target offset in the base
* device tree of a fragment, no matter how the actual targeting is
* done (through a phandle or a path)
*
* returns:
* the targeted node offset in the base device tree
* Negative error code on error
*/
static int overlay_get_target(const void *fdt, const void *fdto,
int fragment, char const **pathp)
int fdt_overlay_target_offset(const void *fdt, const void *fdto,
int fragment_offset, char const **pathp)
{
uint32_t phandle;
const char *path = NULL;
int path_len = 0, ret;
/* Try first to do a phandle based lookup */
phandle = overlay_get_target_phandle(fdto, fragment);
phandle = overlay_get_target_phandle(fdto, fragment_offset);
if (phandle == (uint32_t)-1)
return -FDT_ERR_BADPHANDLE;
/* no phandle, try path */
if (!phandle) {
/* And then a path based lookup */
path = fdt_getprop(fdto, fragment, "target-path", &path_len);
path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len);
if (path)
ret = fdt_path_offset(fdt, path);
else
@ -241,6 +226,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 +236,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;
@ -635,7 +621,7 @@ static int overlay_merge(void *fdt, void *fdto)
if (overlay < 0)
return overlay;
target = overlay_get_target(fdt, fdto, fragment, NULL);
target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
if (target < 0)
return target;
@ -778,7 +764,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
return -FDT_ERR_BADOVERLAY;
/* get the target of the fragment */
ret = overlay_get_target(fdt, fdto, fragment, &target_path);
ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
if (ret < 0)
return ret;
target = ret;
@ -800,7 +786,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
if (!target_path) {
/* again in case setprop_placeholder changed it */
ret = overlay_get_target(fdt, fdto, fragment, &target_path);
ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
if (ret < 0)
return ret;
target = ret;

View file

@ -53,7 +53,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
err = -FDT_ERR_BADOFFSET;
absoffset = stroffset + fdt_off_dt_strings(fdt);
if (absoffset >= totalsize)
if (absoffset >= (unsigned)totalsize)
goto fail;
len = totalsize - absoffset;
@ -61,17 +61,19 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
if (stroffset < 0)
goto fail;
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
if (stroffset >= fdt_size_dt_strings(fdt))
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;
@ -157,8 +159,8 @@ 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 (!can_assume(VALID_INPUT)) {
if (absoffset < fdt_off_mem_rsvmap(fdt))
@ -179,8 +181,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
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;
}
@ -190,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;
@ -368,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;
}
@ -406,7 +408,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_ld_(&prop->nameoff),
name, namelen)) {
if (poffset)
*poffset = offset;
@ -459,7 +461,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
(poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
(poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@ -477,22 +479,22 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
int namelen;
if (!can_assume(VALID_INPUT)) {
name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff),
&namelen);
*namep = name;
if (!name) {
if (lenp)
*lenp = namelen;
return NULL;
}
*namep = name;
} else {
*namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
*namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
}
}
/* Handle realignment */
if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
(offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
(offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
return prop->data + 4;
return prop->data;
}
@ -517,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,
@ -680,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);

View file

@ -59,7 +59,7 @@ static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
return -FDT_ERR_BADOFFSET;
if ((p < (char *)fdt) || (dsize + newlen < oldlen))
if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen))
return -FDT_ERR_BADOFFSET;
if (dsize - oldlen + newlen > fdt_totalsize(fdt))
return -FDT_ERR_NOSPACE;
@ -349,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);
@ -391,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;
@ -406,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));
}
@ -428,12 +432,14 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
struct_size = fdt_size_dt_struct(fdt);
} else {
} else if (fdt_version(fdt) == 16) {
struct_size = 0;
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
;
if (struct_size < 0)
return struct_size;
} else {
return -FDT_ERR_BADVERSION;
}
if (can_assume(LIBFDT_ORDER) ||
@ -465,7 +471,8 @@ 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);
@ -485,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;

View file

@ -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)

View file

@ -93,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);
@ -108,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)
@ -152,6 +152,9 @@ 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);
@ -159,7 +162,7 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
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;
@ -247,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 */
@ -374,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;

View file

@ -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);

View file

@ -14,6 +14,7 @@ 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 */
@ -101,7 +102,11 @@ extern "C" {
/* 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
@ -122,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)
{
@ -184,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);
@ -225,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); \
@ -269,17 +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 which takes a version number
* 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);
/**
* 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
@ -404,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);
@ -425,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.
*
@ -450,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,
@ -489,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);
@ -588,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:
*
@ -653,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,
@ -745,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,
@ -766,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
@ -814,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,
@ -828,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
@ -1004,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:
@ -1075,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);
@ -1084,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
@ -1104,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
@ -1128,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
@ -1217,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,
@ -1330,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)
@ -1403,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.
*
@ -1421,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.
@ -1486,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.
@ -1691,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)
@ -1863,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)
@ -1967,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,
@ -1992,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
@ -2067,6 +2116,24 @@ int fdt_del_node(void *fdt, int nodeoffset);
*/
int fdt_overlay_apply(void *fdt, void *fdto);
/**
* fdt_overlay_target_offset - retrieves the offset of a fragment's target
* @fdt: Base device tree blob
* @fdto: Device tree overlay blob
* @fragment_offset: node offset of the fragment in the overlay
* @pathp: pointer which receives the path of the target (or NULL)
*
* fdt_overlay_target_offset() retrieves the target offset in the base
* device tree of a fragment, no matter how the actual targeting is
* done (through a phandle or a path)
*
* returns:
* the targeted node offset in the base device tree
* Negative error code on error
*/
int fdt_overlay_target_offset(const void *fdt, const void *fdto,
int fragment_offset, char const **pathp);
/**********************************************************************/
/* Debugging / informational functions */
/**********************************************************************/

View file

@ -46,6 +46,25 @@ 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)
/**********************************************************************/

55
libfdt/meson.build Normal file
View file

@ -0,0 +1,55 @@
version_script = '-Wl,--version-script=@0@'.format(meson.current_source_dir() / 'version.lds')
if not cc.has_link_argument(version_script)
version_script = []
endif
sources = files(
'fdt.c',
'fdt_addresses.c',
'fdt_check.c',
'fdt_empty_tree.c',
'fdt_overlay.c',
'fdt_ro.c',
'fdt_rw.c',
'fdt_strerror.c',
'fdt_sw.c',
'fdt_wip.c',
)
libfdt = library(
'fdt', sources,
version: '1.6.0',
link_args: ['-Wl,--no-undefined', version_script],
link_depends: 'version.lds',
install: true,
)
libfdt_a = static_library(
'fdt', sources,
install: true,
)
libfdt_inc = include_directories('.')
libfdt_dep = declare_dependency(
include_directories: libfdt_inc,
link_with: libfdt,
)
install_headers(
files(
'fdt.h',
'libfdt.h',
'libfdt_env.h',
)
)
pkgconfig = import('pkgconfig')
pkgconfig.generate(
libraries: libfdt,
version: meson.project_version(),
filebase: 'libfdt',
name: 'libfdt',
description: 'Flat Device Tree manipulation',
)

View file

@ -77,6 +77,7 @@ LIBFDT_1.2 {
fdt_appendprop_addrrange;
fdt_setprop_inplace_namelen_partial;
fdt_create_with_flags;
fdt_overlay_target_offset;
local:
*;
};

View file

@ -438,7 +438,7 @@ cell_t propval_cell(struct property *prop)
return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
}
cell_t propval_cell_n(struct property *prop, int n)
cell_t propval_cell_n(struct property *prop, unsigned int n)
{
assert(prop->val.len / sizeof(cell_t) >= n);
return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
@ -526,7 +526,7 @@ struct node *get_node_by_path(struct node *tree, const char *path)
p = strchr(path, '/');
for_each_child(tree, child) {
if (p && strprefixeq(path, p - path, child->name))
if (p && strprefixeq(path, (size_t)(p - path), child->name))
return get_node_by_path(child, p+1);
else if (!p && streq(path, child->name))
return child;
@ -559,7 +559,7 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
{
struct node *child, *node;
if ((phandle == 0) || (phandle == -1)) {
if (!phandle_is_valid(phandle)) {
assert(generate_fixups);
return NULL;
}
@ -581,12 +581,39 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
struct node *get_node_by_ref(struct node *tree, const char *ref)
{
struct node *target = tree;
const char *label = NULL, *path = NULL;
if (streq(ref, "/"))
return tree;
else if (ref[0] == '/')
return get_node_by_path(tree, ref);
if (ref[0] == '/')
path = ref;
else
return get_node_by_label(tree, ref);
label = ref;
if (label) {
const char *slash = strchr(label, '/');
char *buf = NULL;
if (slash) {
buf = xstrndup(label, slash - label);
label = buf;
path = slash + 1;
}
target = get_node_by_label(tree, label);
free(buf);
if (!target)
return NULL;
}
if (path)
target = get_node_by_path(target, path);
return target;
}
cell_t get_node_phandle(struct node *root, struct node *node)
@ -594,7 +621,7 @@ cell_t get_node_phandle(struct node *root, struct node *node)
static cell_t phandle = 1; /* FIXME: ick, static local */
struct data d = empty_data;
if ((node->phandle != 0) && (node->phandle != -1))
if (phandle_is_valid(node->phandle))
return node->phandle;
while (get_node_by_phandle(root, phandle))

129
meson.build Normal file
View file

@ -0,0 +1,129 @@
project('dtc', 'c',
version: '1.6.0',
license: ['GPL2+', 'BSD-2'],
default_options: 'werror=true',
)
cc = meson.get_compiler('c')
add_project_arguments(
cc.get_supported_arguments([
'-Wpointer-arith',
'-Wcast-qual',
'-Wnested-externs',
'-Wstrict-prototypes',
'-Wmissing-prototypes',
'-Wredundant-decls',
'-Wshadow'
]),
language: 'c'
)
if host_machine.system() == 'windows'
add_project_arguments(
'-D__USE_MINGW_ANSI_STDIO=1',
language: 'c'
)
endif
add_project_arguments(
'-DFDT_ASSUME_MASK=' + get_option('assume-mask').to_string(),
language: 'c'
)
yamltree = 'yamltree.c'
yaml = dependency('yaml-0.1', required: get_option('yaml'))
if not yaml.found()
add_project_arguments('-DNO_YAML', language: 'c')
yamltree = []
endif
valgrind = dependency('valgrind', required: get_option('valgrind'))
if not valgrind.found()
add_project_arguments('-DNO_VALGRIND', language: 'c')
endif
py = import('python')
py = py.find_installation(required: get_option('python'))
swig = find_program('swig', required: get_option('python'))
version_gen_h = vcs_tag(
input: 'version_gen.h.in',
output: 'version_gen.h',
)
subdir('libfdt')
if get_option('tools')
flex = find_program('flex', required: true)
bison = find_program('bison', required: true)
util_dep = declare_dependency(
sources: ['util.c', version_gen_h],
include_directories: '.',
dependencies: libfdt_dep
)
lgen = generator(
flex,
output: '@PLAINNAME@.lex.c',
arguments: ['-o', '@OUTPUT@', '@INPUT@'],
)
pgen = generator(
bison,
output: ['@BASENAME@.tab.c', '@BASENAME@.tab.h'],
arguments: ['@INPUT@', '--defines=@OUTPUT1@', '--output=@OUTPUT0@'],
)
if cc.check_header('fnmatch.h')
executable(
'convert-dtsv0',
[
lgen.process('convert-dtsv0-lexer.l'),
'srcpos.c',
],
dependencies: util_dep,
install: true,
)
endif
executable(
'dtc',
[
lgen.process('dtc-lexer.l'),
pgen.process('dtc-parser.y'),
'checks.c',
'data.c',
'dtc.c',
'flattree.c',
'fstree.c',
'livetree.c',
'srcpos.c',
'treesource.c',
yamltree,
],
dependencies: [util_dep, yaml],
install: true,
)
foreach e: ['fdtdump', 'fdtget', 'fdtput', 'fdtoverlay']
executable(e, files(e + '.c'), dependencies: util_dep, install: true)
endforeach
install_data(
'dtdiff',
install_dir: get_option('prefix') / get_option('bindir'),
install_mode: 'rwxr-xr-x',
)
endif
if not meson.is_cross_build()
if py.found() and swig.found()
subdir('pylibfdt')
endif
if get_option('tools')
subdir('tests')
endif
endif

10
meson_options.txt Normal file
View file

@ -0,0 +1,10 @@
option('tools', type: 'boolean', value: true,
description: 'Build tools')
option('assume-mask', type: 'integer', value: 0,
description: 'Control the assumptions made (e.g. risking security issues) in the code.')
option('yaml', type: 'feature', value: 'auto',
description: 'YAML support')
option('valgrind', type: 'feature', value: 'auto',
description: 'Valgrind support')
option('python', type: 'feature', value: 'auto',
description: 'Build pylibfdt Python library')

View file

@ -9,16 +9,15 @@ PYLIBFDT_CLEANFILES = $(PYLIBFDT_CLEANFILES_L:%=$(PYLIBFDT_dir)/%)
PYLIBFDT_CLEANDIRS_L = build __pycache__
PYLIBFDT_CLEANDIRS = $(PYLIBFDT_CLEANDIRS_L:%=$(PYLIBFDT_dir)/%)
SETUP = $(PYLIBFDT_dir)/setup.py
SETUPFLAGS =
SETUP = ./setup.py
ifndef V
SETUPFLAGS += --quiet
endif
$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP) $(VERSION_FILE)
$(PYMODULE): $(PYLIBFDT_srcs) $(LIBFDT_archive) $(SETUP)
@$(VECHO) PYMOD $@
$(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=../$(PYLIBFDT_dir)
$(PYTHON) $(SETUP) $(SETUPFLAGS) build_ext --build-lib=$(PYLIBFDT_dir)
install_pylibfdt: $(PYMODULE)
@$(VECHO) INSTALL-PYLIB

View file

@ -443,6 +443,29 @@ class FdtRo(object):
"""
return fdt_get_alias(self._fdt, name)
def get_path(self, nodeoffset, quiet=()):
"""Get the full path of a node
Args:
nodeoffset: Node offset to check
Returns:
Full path to the node
Raises:
FdtException if an error occurs
"""
size = 1024
while True:
ret, path = fdt_get_path(self._fdt, nodeoffset, size)
if ret == -NOSPACE:
size = size * 2
continue
err = check_err(ret, quiet)
if err:
return err
return path
def parent_offset(self, nodeoffset, quiet=()):
"""Get the offset of a node's parent
@ -716,6 +739,21 @@ class Property(bytearray):
def as_int64(self):
return self.as_cell('q')
def as_list(self, fmt):
return list(map(lambda x: x[0], struct.iter_unpack('>' + fmt, self)))
def as_uint32_list(self):
return self.as_list('L')
def as_int32_list(self):
return self.as_list('l')
def as_uint64_list(self):
return self.as_list('Q')
def as_int64_list(self):
return self.as_list('q')
def as_str(self):
"""Unicode is supported by decoding from UTF-8"""
if self[-1] != 0:
@ -724,6 +762,13 @@ class Property(bytearray):
raise ValueError('Property contains embedded nul characters')
return self[:-1].decode('utf-8')
def as_stringlist(self):
"""Unicode is supported by decoding from UTF-8"""
if self[-1] != 0:
raise ValueError('Property lacks nul termination')
parts = self[:-1].split(b'\x00')
return list(map(lambda x: x.decode('utf-8'), parts))
class FdtSw(FdtRo):
"""Software interface to create a device tree from scratch
@ -1009,7 +1054,7 @@ typedef uint32_t fdt32_t;
}
$1 = (void *)PyByteArray_AsString($input);
fdt = $1;
fdt = fdt; /* avoid unused variable warning */
(void)fdt; /* avoid unused variable warning */
}
/* Some functions do change the device tree, so use void * */
@ -1020,7 +1065,7 @@ typedef uint32_t fdt32_t;
}
$1 = PyByteArray_AsString($input);
fdt = $1;
fdt = fdt; /* avoid unused variable warning */
(void)fdt; /* avoid unused variable warning */
}
/* typemap used for fdt_get_property_by_offset() */
@ -1040,14 +1085,16 @@ typedef uint32_t fdt32_t;
/* typemap used for fdt_getprop() */
%typemap(out) (const void *) {
if (!$1)
if (!$1) {
$result = Py_None;
else
Py_INCREF($result);
} else {
%#if PY_VERSION_HEX >= 0x03000000
$result = Py_BuildValue("y#", $1, *arg4);
$result = Py_BuildValue("y#", $1, (Py_ssize_t)*arg4);
%#else
$result = Py_BuildValue("s#", $1, *arg4);
$result = Py_BuildValue("s#", $1, (Py_ssize_t)*arg4);
%#endif
}
}
/* typemap used for fdt_setprop() */
@ -1091,6 +1138,11 @@ typedef uint32_t fdt32_t;
}
}
%include "cstring.i"
%cstring_output_maxsize(char *buf, int buflen);
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
/* We have both struct fdt_property and a function fdt_property() */
%warnfilter(302) fdt_property;

12
pylibfdt/meson.build Normal file
View file

@ -0,0 +1,12 @@
setup_py = find_program('../setup.py')
setup_py = [setup_py.path(), '--quiet', '--top-builddir', meson.project_build_root()]
custom_target(
'pylibfdt',
input: 'libfdt.i',
output: '_libfdt.so',
command: [setup_py, 'build_ext', '--build-lib=' + meson.current_build_dir()],
build_by_default: true,
)
meson.add_install_script(setup_py, 'install', '--prefix=' + get_option('prefix'), '--root=$DESTDIR')

View file

@ -1,48 +0,0 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
# While Python 3 is the default, it's also possible to invoke
# this setup.py script with Python 2.
"""
setup.py file for SWIG libfdt
Copyright (C) 2017 Google, Inc.
Written by Simon Glass <sjg@chromium.org>
"""
from distutils.core import setup, Extension
import os
import re
import sys
VERSION_PATTERN = '^#define DTC_VERSION "DTC ([^"]*)"$'
def get_version():
version_file = "../version_gen.h"
f = open(version_file, 'rt')
m = re.match(VERSION_PATTERN, f.readline())
return m.group(1)
setupdir = os.path.dirname(os.path.abspath(sys.argv[0]))
os.chdir(setupdir)
libfdt_module = Extension(
'_libfdt',
sources=['libfdt.i'],
include_dirs=['../libfdt'],
libraries=['fdt'],
library_dirs=['../libfdt'],
swig_opts=['-I../libfdt'],
)
setup(
name='libfdt',
version=get_version(),
author='Simon Glass <sjg@chromium.org>',
description='Python binding for libfdt',
ext_modules=[libfdt_module],
py_modules=['libfdt'],
)

77
setup.py Executable file
View file

@ -0,0 +1,77 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
# While Python 3 is the default, it's also possible to invoke
# this setup.py script with Python 2.
"""
setup.py file for SWIG libfdt
Copyright (C) 2017 Google, Inc.
Written by Simon Glass <sjg@chromium.org>
"""
from setuptools import setup, Extension
from setuptools.command.build_py import build_py as _build_py
import os
import re
import sys
srcdir = os.path.dirname(__file__)
with open(os.path.join(srcdir, "README"), "r") as fh:
long_description = fh.read()
def get_top_builddir():
if '--top-builddir' in sys.argv:
index = sys.argv.index('--top-builddir')
sys.argv.pop(index)
return sys.argv.pop(index)
else:
return srcdir
top_builddir = get_top_builddir()
libfdt_module = Extension(
'_libfdt',
sources=[os.path.join(srcdir, 'pylibfdt/libfdt.i')],
define_macros=[('PY_SSIZE_T_CLEAN', None)],
include_dirs=[os.path.join(srcdir, 'libfdt')],
libraries=['fdt'],
library_dirs=[os.path.join(top_builddir, 'libfdt')],
swig_opts=['-I' + os.path.join(srcdir, 'libfdt')],
)
class build_py(_build_py):
def run(self):
self.run_command("build_ext")
return super().run()
setup(
name='libfdt',
use_scm_version={
"root": srcdir,
},
cmdclass = {'build_py' : build_py},
setup_requires = ['setuptools_scm'],
author='Simon Glass',
author_email='sjg@chromium.org',
description='Python binding for libfdt',
ext_modules=[libfdt_module],
package_dir={'': os.path.join(srcdir, 'pylibfdt')},
py_modules=['libfdt'],
long_description=long_description,
long_description_content_type="text/plain",
url="https://git.kernel.org/pub/scm/utils/dtc/dtc.git",
license="BSD",
license_files=["GPL", "BSD-2-Clause"],
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: BSD License",
"License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)",
"Operating System :: OS Independent",
],
)

View file

@ -20,7 +20,7 @@ struct search_path {
static struct search_path *search_path_head, **search_path_tail;
/* Detect infinite include recursion. */
#define MAX_SRCFILE_DEPTH (100)
#define MAX_SRCFILE_DEPTH (200)
static int srcfile_depth; /* = 0 */
static char *get_dirname(const char *path)

1
tests/.gitignore vendored
View file

@ -54,6 +54,7 @@ tmp.*
/property_iterate
/propname_escapes
/references
/relref_merge
/root_node
/rw_tree1
/rw_oom

View file

@ -18,7 +18,7 @@ LIB_TESTS_L = get_mem_rsv \
open_pack rw_tree1 rw_oom set_name setprop del_property del_node \
appendprop1 appendprop2 propname_escapes \
string_escapes references path-references phandle_format \
boot-cpuid incbin \
boot-cpuid incbin relref_merge \
extra-terminating-null \
dtbs_equal_ordered \
dtb_reverse dtbs_equal_unordered \
@ -32,7 +32,9 @@ LIB_TESTS_L = get_mem_rsv \
fs_tree1
LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv
LIBTREE_TESTS_L = truncated_property truncated_string truncated_memrsv \
two_roots named_root
LIBTREE_TESTS = $(LIBTREE_TESTS_L:%=$(TESTS_PREFIX)%)
DL_LIB_TESTS_L = asm_tree_dump value-labels

View file

@ -0,0 +1,20 @@
/dts-v1/;
/ {
interrupt-parent = <&intc>;
intc: interrupt-controller {
#interrupt-cells = <3>;
interrupt-controller;
};
node {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-map = <1 &intc 1 2 3>;
interrupt-map-mask = <0 0>;
child {
interrupts = <1>;
};
};
};

View file

@ -0,0 +1,17 @@
/dts-v1/;
/ {
interrupt-parent = <&intc>;
intc: interrupt-controller {
};
node {
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-map = <1 &intc 1 2 3>;
child {
interrupts = <1>;
};
};
};

View file

@ -0,0 +1,19 @@
/dts-v1/;
/ {
interrupt-parent = <&intc>;
intc: interrupt-controller {
#interrupt-cells = <3>;
interrupt-controller;
};
node {
/* Missing #address-cells = <0>; */
#interrupt-cells = <1>;
interrupt-map = <1 &intc 1 2 3>;
child {
interrupts = <1>;
};
};
};

View file

@ -32,7 +32,7 @@ _dt_reserve_map:
dt_struct_start:
_dt_struct_start:
.long OF_DT_BEGIN_NODE
.string ""
.asciz ""
.balign 4
.long OF_DT_PROP
.long 0xa
@ -58,7 +58,7 @@ _dt_struct_start:
.long 0x2
.balign 4
.long OF_DT_BEGIN_NODE
.string "memory@0"
.asciz "memory@0"
.balign 4
.long OF_DT_PROP
.long 0x7
@ -77,7 +77,7 @@ _dt_struct_start:
.balign 4
.long OF_DT_END_NODE
.long OF_DT_BEGIN_NODE
.string "cpus"
.asciz "cpus"
.balign 4
.long OF_DT_PROP
.long 0x4
@ -151,22 +151,22 @@ _dt_struct_end:
.globl dt_strings_start
dt_strings_start:
_dt_strings_start:
.string "model"
.string "compatible"
.string "#address-cells"
.string "#size-cells"
.string "device_type"
.string "reg"
.string "d10"
.string "d23"
.string "b101"
.string "o17"
.string "hd00d"
.string "stuff"
.string "bad-d-1"
.string "bad-d-2"
.string "bad-o-1"
.string "bad-o-2"
.asciz "model"
.asciz "compatible"
.asciz "#address-cells"
.asciz "#size-cells"
.asciz "device_type"
.asciz "reg"
.asciz "d10"
.asciz "d23"
.asciz "b101"
.asciz "o17"
.asciz "hd00d"
.asciz "stuff"
.asciz "bad-d-1"
.asciz "bad-d-2"
.asciz "bad-o-1"
.asciz "bad-o-2"
.globl dt_strings_end
dt_strings_end:
_dt_strings_end:

View file

@ -24,13 +24,15 @@ static struct {
TREE(ovf_size_strings),
TREE(truncated_property), TREE(truncated_string),
TREE(truncated_memrsv),
TREE(two_roots),
TREE(named_root)
};
#define NUM_TREES (sizeof(trees) / sizeof(trees[0]))
int main(int argc, char *argv[])
{
int i;
unsigned int i;
if (argc != 2) {
fprintf(stderr, "Missing output directory argument\n");

View file

@ -54,7 +54,7 @@ static void mkfile(const char *name, void *data, size_t len)
rc = write(fd, data, len);
if (rc < 0)
FAIL("write(\"%s\"): %s", name, strerror(errno));
if (rc != len)
if ((unsigned)rc != len)
FAIL("write(\"%s\"): short write", name);
rc = close(fd);

View file

@ -34,12 +34,14 @@ static void check_name(void *fdt, const char *path)
offset, getname, len);
if (!getname)
FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len));
if (len < 0)
FAIL("negative name length (%d) for returned node name\n", len);
if (strcmp(getname, checkname) != 0)
FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
path, getname, checkname);
if (len != strlen(getname))
if ((unsigned)len != strlen(getname))
FAIL("fdt_get_name(%s) returned length %d instead of %zd",
path, len, strlen(getname));

12
tests/good-gpio.dts Normal file
View file

@ -0,0 +1,12 @@
/dts-v1/;
/ {
gpio: gpio-controller {
#gpio-cells = <3>;
};
node {
foo,nr-gpios = <1>;
foo-gpios = <&gpio 1 2 3>;
};
};

View file

@ -59,7 +59,7 @@ int main(int argc, char *argv[])
void *fdt;
const fdt32_t *res;
int reslen;
int i;
unsigned int i;
test_init(argc, argv);

131
tests/meson.build Normal file
View file

@ -0,0 +1,131 @@
trees = static_library('trees', files('trees.S'), c_args: '-D__ASSEMBLY__',
include_directories: libfdt_inc)
dumptrees = executable('dumptrees', files('dumptrees.c'),
link_with: trees, dependencies: libfdt_dep)
dumptrees_dtb = custom_target(
'dumptrees',
command: [dumptrees, meson.current_build_dir()],
output: [
'test_tree1.dtb',
'bad_node_char.dtb',
'bad_node_format.dtb',
'bad_prop_char.dtb',
'ovf_size_strings.dtb',
'truncated_property.dtb',
'truncated_string.dtb',
'truncated_memrsv.dtb',
]
)
testutil_dep = declare_dependency(sources: ['testutils.c'], link_with: trees)
tests = [
'add_subnode_with_nops',
'addr_size_cells',
'addr_size_cells2',
'appendprop1',
'appendprop2',
'appendprop_addrrange',
'boot-cpuid',
'char_literal',
'check_full',
'check_header',
'check_path',
'del_node',
'del_property',
'dtb_reverse',
'dtbs_equal_ordered',
'dtbs_equal_unordered',
'extra-terminating-null',
'find_property',
'fs_tree1',
'get_alias',
'get_mem_rsv',
'get_name',
'get_path',
'get_phandle',
'get_prop_offset',
'getprop',
'incbin',
'integer-expressions',
'mangle-layout',
'move_and_save',
'node_check_compatible',
'node_offset_by_compatible',
'node_offset_by_phandle',
'node_offset_by_prop_value',
'nop_node',
'nop_property',
'nopulate',
'notfound',
'open_pack',
'overlay',
'overlay_bad_fixup',
'parent_offset',
'path-references',
'path_offset',
'path_offset_aliases',
'phandle_format',
'property_iterate',
'propname_escapes',
'references',
'root_node',
'rw_oom',
'rw_tree1',
'set_name',
'setprop',
'setprop_inplace',
'sized_cells',
'string_escapes',
'stringlist',
'subnode_iterate',
'subnode_offset',
'supernode_atdepth_offset',
'sw_states',
'sw_tree1',
'utilfdt_test',
]
tests += [
'truncated_memrsv',
'truncated_property',
'truncated_string',
]
dl = cc.find_library('dl', required: false)
if dl.found()
tests += [
'asm_tree_dump',
'value-labels',
]
endif
foreach t: tests
executable(t, files(t + '.c'), dependencies: [testutil_dep, util_dep, libfdt_dep, dl])
endforeach
run_tests = find_program('run_tests.sh')
env = []
if not py.found()
env += 'NO_PYTHON=1'
else
env += [
'PYTHON=' + py.path(),
'PYTHONPATH=' + meson.source_root() / 'pylibfdt',
]
endif
if not yaml.found()
env += 'NO_YAML=1'
endif
test(
'run-test',
run_tests,
workdir: meson.current_build_dir(),
depends: dumptrees_dtb,
env: env,
timeout: 1800, # mostly for valgrind
)

View file

@ -43,7 +43,8 @@ static int nopulate_struct(char *buf, const char *fdt)
int main(int argc, char *argv[])
{
char *fdt, *fdt2, *buf;
int newsize, struct_start, struct_end_old, struct_end_new, delta;
int newsize, struct_end_old, struct_end_new, delta;
unsigned int struct_start;
const char *inname;
char outname[PATH_MAX];

View file

@ -35,7 +35,11 @@ static int fdt_getprop_u32_by_poffset(void *fdt, const char *path,
return node_off;
val = fdt_getprop(fdt, node_off, name, &len);
if (!val || (len < (sizeof(uint32_t) * (poffset + 1))))
if (val && len < 0)
FAIL("fdt_getprop() returns negative length");
if (!val && len < 0)
return len;
if (!val || ((unsigned)len < (sizeof(uint32_t) * (poffset + 1))))
return -FDT_ERR_NOTFOUND;
*out = fdt32_to_cpu(*(val + poffset));

View file

@ -48,7 +48,7 @@
};
};
fragment@5 {
fragment@4 {
target = <&test>;
__overlay__ {
@ -58,7 +58,7 @@
};
};
fragment@6 {
fragment@5 {
target = <&test>;
__overlay__ {
@ -66,7 +66,7 @@
};
};
fragment@7 {
fragment@6 {
target = <&test>;
__overlay__ {
@ -74,7 +74,7 @@
};
};
fragment@8 {
fragment@7 {
target = <&test>;
__overlay__ {

View file

@ -53,7 +53,7 @@ int main(int argc, char *argv[])
void *fdt;
const char *p;
int len, multilen;
int n1, n2, n3, n4;
int n1, n2, n3, n4, n5;
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
@ -89,6 +89,12 @@ int main(int argc, char *argv[])
check_ref(fdt, n3, "/foobar/baz");
check_ref(fdt, n4, "/foo/baz");
n5 = fdt_path_offset(fdt, "/bar/baz");
if (n5 < 0)
FAIL("fdt_path_offset(/bar/baz): %s", fdt_strerror(n5));
check_ref(fdt, n5, "/bar/baz");
check_rref(fdt);
PASS();

View file

@ -25,4 +25,13 @@
lref = &n3;
};
};
n5: bar {
baz {
};
};
};
n6: &{n5/baz} {
ref = &{n6/};
lref = &{n5/baz};
};

View file

@ -0,0 +1,18 @@
/dts-v1/;
/*
* https://github.com/dgibson/dtc/issues/64
*
* Certain dtc versions had a bug where this input caused an infinite
* loop in check_property_phandle_args().
*
*/
/ {
clocks = <&ref &ref>;
ref: poc {
phandle = <1>;
#clock-cells = <0xffffffff>;
};
};

View file

@ -45,7 +45,7 @@ int main(int argc, char *argv[])
FAIL("fdt_path_offset(/node4): %s", fdt_strerror(n4));
h4 = fdt_get_phandle(fdt, n4);
if ((h4 == 0) || (h4 == -1))
if ((h4 == 0) || (h4 == ~0U))
FAIL("/node4 has bad phandle 0x%x\n", h4);
if (phandle_format & PHANDLE_LEGACY)

View file

@ -23,7 +23,7 @@ static void test_node(void *fdt, int parent_offset)
uint32_t properties;
const fdt32_t *prop;
int offset, property;
int count;
unsigned int count;
int len;
/*

View file

@ -348,6 +348,19 @@ class PyLibfdtBasicTests(unittest.TestCase):
self.assertEqual("/subnode@1/subsubnode", self.fdt3.get_alias('ss1'))
self.assertEqual("/subnode@1/subsubnode/subsubsubnode", self.fdt3.get_alias('sss1'))
def testGetPath(self):
"""Test for the get_path() method"""
node = self.fdt.path_offset('/subnode@1')
node2 = self.fdt.path_offset('/subnode@1/subsubnode')
self.assertEqual("/subnode@1", self.fdt.get_path(node))
self.assertEqual("/subnode@1/subsubnode", self.fdt.get_path(node2))
with self.assertRaises(FdtException) as e:
self.fdt.get_path(-1)
self.assertEqual(e.exception.err, -libfdt.BADOFFSET)
self.assertEqual(-libfdt.BADOFFSET, self.fdt.get_path(-1, quiet=(libfdt.BADOFFSET,)))
def testParentOffset(self):
"""Test for the parent_offset() method"""
self.assertEqual(-libfdt.NOTFOUND,
@ -382,6 +395,25 @@ class PyLibfdtBasicTests(unittest.TestCase):
self.get_prop("prop-uint64").as_uint64())
self.assertEqual(-2, self.get_prop("prop-int64").as_int64())
def testGetIntListProperties(self):
"""Test that we can access properties as integer lists"""
self.assertEqual([128, -16, -2],
self.get_prop("prop-int32-array").as_int32_list())
self.assertEqual([0x1, 0x98765432, 0xdeadbeef],
self.get_prop("prop-uint32-array").as_uint32_list())
self.assertEqual([0x100000000, -2],
self.get_prop("prop-int64-array").as_int64_list())
self.assertEqual([0x100000000, 0x1],
self.get_prop("prop-uint64-array").as_uint64_list())
def testGetStringlistProperties(self):
"""Test that we can access properties as string list"""
node = self.fdt.path_offset('/subnode@1/subsubnode')
self.assertEqual(["subsubnode1", "subsubnode"],
self.fdt.getprop(node, "compatible").as_stringlist())
self.assertEqual(["this is a placeholder string", "string2"],
self.fdt.getprop(node, "placeholder").as_stringlist())
def testReserveMap(self):
"""Test that we can access the memory reserve map"""
self.assertEqual(2, self.fdt.num_mem_rsv())

View file

@ -106,7 +106,7 @@ int main(int argc, char *argv[])
if ((h4 == 0x2000) || (h4 == 0x1) || (h4 == 0))
FAIL("/node4 has bad phandle, 0x%x", h4);
if ((h5 == 0) || (h5 == -1))
if ((h5 == 0) || (h5 == ~0U))
FAIL("/node5 has bad phandle, 0x%x", h5);
if ((h5 == h4) || (h5 == h2) || (h5 == h1))
FAIL("/node5 has duplicate phandle, 0x%x", h5);

51
tests/relref_merge.c Normal file
View file

@ -0,0 +1,51 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* libfdt - Flat Device Tree manipulation
* Testcase for label relative child references in dtc
* Copyright (C) 2006 David Gibson, IBM Corporation.
* Copyright (C) 2020 Ahmad Fatoum, Pengutronix.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <libfdt.h>
#include "tests.h"
#include "testdata.h"
static void check_exist(void *fdt, const char *path)
{
int sn = fdt_path_offset(fdt, path);
if (sn < 0)
FAIL("%s expected but not found: %s", path, fdt_strerror(sn));
}
static void check_doesnt_exist(void *fdt, const char *path)
{
int sn = fdt_path_offset(fdt, path);
if (sn >= 0)
FAIL("%s found but not expected %d", path, sn);
}
int main(int argc, char *argv[])
{
void *fdt;
test_init(argc, argv);
fdt = load_blob_arg(argc, argv);
check_exist(fdt, "/node/subnode1");
check_exist(fdt, "/node/keep-me");
check_doesnt_exist(fdt, "/node/remove-me");
check_doesnt_exist(fdt, "/node2");
check_doesnt_exist(fdt, "/node/subnode3");
check_exist(fdt, "/node/subnode4");
check_exist(fdt, "/node/subnode1/add-me");
PASS();
}

40
tests/relref_merge.dts Normal file
View file

@ -0,0 +1,40 @@
/dts-v1/;
/ {
node_label: node {
keep-me {};
remove-me {};
subnode1 {
property-inline1;
property-inline2;
property-inline3;
};
subnode2 {
property-inline1;
};
subnode3 {
property-inline1;
};
};
node2_label: node2 {
property-inline1;
};
};
/omit-if-no-ref/ &{node_label/subnode1};
/omit-if-no-ref/ &node2_label;
/delete-node/ &{node_label/subnode3};
&{node_label/} {
/delete-node/ remove-me;
subnode4 { };
};
label: &{node_label/subnode1} {
selfref = &{node_label/subnode1};
add-me { };
};

View file

@ -288,7 +288,7 @@ dtc_overlay_tests () {
run_test check_path overlay_overlay.test.dtb exists "/__local_fixups__"
# Without syntactic sugar
run_dtc_test -I dts -O dtb -o overlay_overlay_nosugar.test.dtb "$SRCDIR/overlay_overlay.dts"
run_dtc_test -I dts -O dtb -o overlay_overlay_nosugar.test.dtb "$SRCDIR/overlay_overlay_nosugar.dts"
run_test check_path overlay_overlay_nosugar.test.dtb not-exists "/__symbols__"
run_test check_path overlay_overlay_nosugar.test.dtb exists "/__fixups__"
run_test check_path overlay_overlay_nosugar.test.dtb exists "/__local_fixups__"
@ -513,12 +513,15 @@ libfdt_tests () {
run_dtc_test -I fs -O dtb -o fs.test_tree1.test.dtb $FSBASE/test_tree1
run_test dtbs_equal_unordered -m fs.test_tree1.test.dtb test_tree1.dtb
## https://github.com/dgibson/dtc/issues/64
check_tests "$SRCDIR/phandle-args-overflow.dts" clocks_property
# check full tests
for good in test_tree1.dtb; do
run_test check_full $good
done
for bad in truncated_property.dtb truncated_string.dtb \
truncated_memrsv.dtb; do
truncated_memrsv.dtb two_roots.dtb named_root.dtb; do
run_test check_full -n $bad
done
}
@ -666,6 +669,9 @@ dtc_tests () {
tree1_tests dtc_tree1_merge_path.test.dtb test_tree1.dtb
run_wrap_error_test $DTC -I dts -O dtb -o /dev/null "$SRCDIR/test_label_ref.dts"
run_dtc_test -I dts -O dtb -o dtc_relref_merge.test.dtb "$SRCDIR/relref_merge.dts"
run_test relref_merge dtc_relref_merge.test.dtb
# Check prop/node delete functionality
run_dtc_test -I dts -O dtb -o dtc_tree1_delete.test.dtb "$SRCDIR/test_tree1_delete.dts"
tree1_tests dtc_tree1_delete.test.dtb
@ -691,7 +697,7 @@ dtc_tests () {
run_sh_test "$SRCDIR/dtc-fatal.sh" -I dts -O dtb "$SRCDIR/nonexist-node-ref2.dts"
check_tests "$SRCDIR/bad-name-property.dts" name_properties
check_tests "$SRCDIR/bad-ncells.dts" address_cells_is_cell size_cells_is_cell interrupt_cells_is_cell
check_tests "$SRCDIR/bad-ncells.dts" address_cells_is_cell size_cells_is_cell interrupts_extended_is_cell
check_tests "$SRCDIR/bad-string-props.dts" device_type_is_string model_is_string status_is_string label_is_string compatible_is_string_list names_is_string_list
check_tests "$SRCDIR/bad-chosen.dts" chosen_node_is_root
check_tests "$SRCDIR/bad-chosen.dts" chosen_node_bootargs
@ -709,12 +715,17 @@ dtc_tests () {
check_tests "$SRCDIR/unit-addr-unique.dts" unique_unit_address
check_tests "$SRCDIR/bad-phandle-cells.dts" interrupts_extended_property
check_tests "$SRCDIR/bad-gpio.dts" gpios_property
check_tests "$SRCDIR/good-gpio.dts" -n gpios_property
check_tests "$SRCDIR/bad-graph.dts" graph_child_address
check_tests "$SRCDIR/bad-graph.dts" graph_port
check_tests "$SRCDIR/bad-graph.dts" graph_endpoint
run_sh_test "$SRCDIR/dtc-checkfails.sh" deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/bad-gpio.dts"
run_sh_test "$SRCDIR/dtc-checkfails.sh" -n deprecated_gpio_property -- -Wdeprecated_gpio_property -I dts -O dtb "$SRCDIR/good-gpio.dts"
check_tests "$SRCDIR/bad-interrupt-cells.dts" interrupts_property
check_tests "$SRCDIR/bad-interrupt-controller.dts" interrupt_provider
check_tests "$SRCDIR/bad-interrupt-map.dts" interrupt_map
check_tests "$SRCDIR/bad-interrupt-map-parent.dts" interrupt_map
check_tests "$SRCDIR/bad-interrupt-map-mask.dts" interrupt_map
run_sh_test "$SRCDIR/dtc-checkfails.sh" node_name_chars -- -I dtb -O dtb bad_node_char.dtb
run_sh_test "$SRCDIR/dtc-checkfails.sh" node_name_format -- -I dtb -O dtb bad_node_format.dtb
run_sh_test "$SRCDIR/dtc-checkfails.sh" property_name_chars -- -I dtb -O dtb bad_prop_char.dtb
@ -738,7 +749,7 @@ dtc_tests () {
# Check warning options
run_sh_test "$SRCDIR/dtc-checkfails.sh" address_cells_is_cell interrupt_cells_is_cell -n size_cells_is_cell -- -Wno_size_cells_is_cell -I dts -O dtb "$SRCDIR/bad-ncells.dts"
run_sh_test "$SRCDIR/dtc-checkfails.sh" address_cells_is_cell interrupts_extended_is_cell -n size_cells_is_cell -- -Wno_size_cells_is_cell -I dts -O dtb "$SRCDIR/bad-ncells.dts"
run_sh_test "$SRCDIR/dtc-fails.sh" -n test-warn-output.test.dtb -I dts -O dtb "$SRCDIR/bad-ncells.dts"
run_sh_test "$SRCDIR/dtc-fails.sh" test-error-output.test.dtb -I dts -O dtb bad-ncells.dts -Esize_cells_is_cell
run_sh_test "$SRCDIR/dtc-checkfails.sh" always_fail -- -Walways_fail -I dts -O dtb "$SRCDIR/test_tree1.dts"
@ -850,6 +861,8 @@ fdtget_tests () {
run_fdtget_test 8000 -tx $dtb /cpus/PowerPC,970@1 d-cache-size
run_fdtget_test "61 62 63 0" -tbx $dtb /randomnode tricky1
run_fdtget_test "a b c d de ea ad be ef" -tbx $dtb /randomnode blob
run_fdtget_test "MyBoardName\0MyBoardFamilyName\0" -tr $dtb / compatible
run_fdtget_test "\x0a\x0b\x0c\x0d\xde\xea\xad\xbe\xef" -tr $dtb /randomnode blob
# Here the property size is not a multiple of 4 bytes, so it should fail
run_wrap_error_test $DTGET -tlx $dtb /randomnode mixed

View file

@ -39,7 +39,11 @@ static void check_set_name(void *fdt, const char *path, const char *newname)
FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
path, getname, oldname);
if (len != strlen(getname))
if (len < 0)
FAIL("fdt_get_name(%s) returned negative length: %d",
path, len);
if ((unsigned)len != strlen(getname))
FAIL("fdt_get_name(%s) returned length %d instead of %zd",
path, len, strlen(getname));
@ -51,12 +55,14 @@ static void check_set_name(void *fdt, const char *path, const char *newname)
getname = fdt_get_name(fdt, offset, &len);
if (!getname)
FAIL("fdt_get_name(%d): %s", offset, fdt_strerror(len));
if (len < 0)
FAIL("negative name length (%d) for returned node name\n", len);
if (strcmp(getname, newname) != 0)
FAIL("fdt_get_name(%s) returned \"%s\" instead of \"%s\"",
path, getname, newname);
if (len != strlen(getname))
if ((unsigned)len != strlen(getname))
FAIL("fdt_get_name(%s) returned length %d instead of %zd",
path, len, strlen(getname));
}

View file

@ -58,7 +58,7 @@ int main(int argc, char *argv[])
TEST_STRING_1);
verbose_printf("Old string value was \"%s\"\n", strp);
xstr = strdup(strp);
xstr = xstrdup(strp);
xlen = strlen(xstr);
for (i = 0; i < xlen; i++)
xstr[i] = toupper(xstr[i]);

View file

@ -23,7 +23,7 @@ static void test_node(void *fdt, int parent_offset)
uint32_t subnodes;
const fdt32_t *prop;
int offset;
int count;
unsigned int count;
int len;
/* This property indicates the number of subnodes to expect */

View file

@ -44,7 +44,7 @@ _dt_reserve_map:
dt_struct_start:
_dt_struct_start:
.long OF_DT_BEGIN_NODE
.string ""
.asciz ""
.balign 4
.long OF_DT_PROP
.long 0xc
@ -76,7 +76,7 @@ _dt_struct_start:
.long 0x2
.balign 4
.long OF_DT_BEGIN_NODE
.string "cpus"
.asciz "cpus"
.balign 4
.long OF_DT_PROP
.long 0x4
@ -94,7 +94,7 @@ _dt_struct_start:
.long 0x0
.balign 4
.long OF_DT_BEGIN_NODE
.string "PowerPC,970@0"
.asciz "PowerPC,970@0"
.balign 4
.long OF_DT_PROP
.long 0xc
@ -139,7 +139,7 @@ _dt_struct_start:
.balign 4
.long OF_DT_END_NODE
.long OF_DT_BEGIN_NODE
.string "PowerPC,970@1"
.asciz "PowerPC,970@1"
.balign 4
.long OF_DT_PROP
.long 0xc
@ -181,7 +181,7 @@ _dt_struct_start:
.long OF_DT_END_NODE
.long OF_DT_END_NODE
.long OF_DT_BEGIN_NODE
.string "randomnode"
.asciz "randomnode"
.balign 4
.long OF_DT_PROP
.long 0x13
@ -216,7 +216,7 @@ _dt_struct_start:
.balign 4
.long OF_DT_END_NODE
.long OF_DT_BEGIN_NODE
.string "memory@0"
.asciz "memory@0"
.balign 4
.long OF_DT_PROP
.long 0x7
@ -242,7 +242,7 @@ memreg:
.balign 4
.long OF_DT_END_NODE
.long OF_DT_BEGIN_NODE
.string "chosen"
.asciz "chosen"
.balign 4
.long OF_DT_PROP
.long 0xf
@ -267,25 +267,25 @@ _dt_struct_end:
.globl dt_strings_start
dt_strings_start:
_dt_strings_start:
.string "model"
.string "compatible"
.string "#address-cells"
.string "#size-cells"
.string "linux,phandle"
.string "name"
.string "device_type"
.string "reg"
.string "clock-frequency"
.string "timebase-frequency"
.string "linux,boot-cpu"
.string "i-cache-size"
.string "d-cache-size"
.string "string"
.string "blob"
.string "ref"
.string "mixed"
.string "bootargs"
.string "linux,platform"
.asciz "model"
.asciz "compatible"
.asciz "#address-cells"
.asciz "#size-cells"
.asciz "linux,phandle"
.asciz "name"
.asciz "device_type"
.asciz "reg"
.asciz "clock-frequency"
.asciz "timebase-frequency"
.asciz "linux,boot-cpu"
.asciz "i-cache-size"
.asciz "d-cache-size"
.asciz "string"
.asciz "blob"
.asciz "ref"
.asciz "mixed"
.asciz "bootargs"
.asciz "linux,platform"
.globl dt_strings_end
dt_strings_end:
_dt_strings_end:

View file

@ -8,4 +8,8 @@
prop-hex64 = /bits/ 64 <0xdeadbeef01abcdef>;
prop-uint64 = /bits/ 64 <9223372036854775807>;
prop-int64 = /bits/ 64 <0xfffffffffffffffe>;
prop-int32-array = <128>, <(-16)>, <0xfffffffe>;
prop-uint32-array = <0x1>, <0x98765432>, <0xdeadbeef>;
prop-int64-array = /bits/ 64 <0x100000000 0xfffffffffffffffe>;
prop-uint64-array = /bits/ 64 <0x100000000 0x1>;
};

View file

@ -55,4 +55,6 @@ extern struct fdt_header bad_prop_char;
extern struct fdt_header ovf_size_strings;
extern struct fdt_header truncated_string;
extern struct fdt_header truncated_memrsv;
extern struct fdt_header two_roots;
extern struct fdt_header named_root;
#endif /* ! __ASSEMBLY */

View file

@ -83,7 +83,7 @@ void cleanup(void);
void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size);
void check_property(void *fdt, int nodeoffset, const char *name,
int len, const void *val);
unsigned int len, const void *val);
#define check_property_cell(fdt, nodeoffset, name, val) \
({ \
fdt32_t x = cpu_to_fdt32(val); \

View file

@ -88,7 +88,7 @@ void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size)
}
void check_property(void *fdt, int nodeoffset, const char *name,
int len, const void *val)
unsigned int len, const void *val)
{
const struct fdt_property *prop;
int retlen, namelen;
@ -101,6 +101,9 @@ void check_property(void *fdt, int nodeoffset, const char *name,
if (! prop)
FAIL("Error retrieving \"%s\" pointer: %s", name,
fdt_strerror(retlen));
if (retlen < 0)
FAIL("negative name length (%d) for returned property\n",
retlen);
tag = fdt32_to_cpu(prop->tag);
nameoff = fdt32_to_cpu(prop->nameoff);
@ -112,13 +115,16 @@ void check_property(void *fdt, int nodeoffset, const char *name,
propname = fdt_get_string(fdt, nameoff, &namelen);
if (!propname)
FAIL("Couldn't get property name: %s", fdt_strerror(namelen));
if (namelen != strlen(propname))
if (namelen < 0)
FAIL("negative name length (%d) for returned string\n",
namelen);
if ((unsigned)namelen != strlen(propname))
FAIL("Incorrect prop name length: %d instead of %zd",
namelen, strlen(propname));
if (!streq(propname, name))
FAIL("Property name mismatch \"%s\" instead of \"%s\"",
propname, name);
if (proplen != retlen)
if (proplen != (unsigned)retlen)
FAIL("Length retrieved for \"%s\" by fdt_get_property()"
" differs from stored length (%d != %d)",
name, retlen, proplen);

View file

@ -1,174 +1,187 @@
#include <fdt.h>
#include "testdata.h"
#define FDTLONG(val) \
.byte ((val) >> 24) & 0xff ; \
.byte ((val) >> 16) & 0xff ; \
.byte ((val) >> 8) & 0xff ; \
.byte (val) & 0xff ;
.macro fdtlong val
.byte ((\val) >> 24) & 0xff
.byte ((\val) >> 16) & 0xff
.byte ((\val) >> 8) & 0xff
.byte (\val) & 0xff
.endm
#define TREE_HDR(tree) \
.balign 8 ; \
.globl tree ; \
tree: \
FDTLONG(FDT_MAGIC) ; \
FDTLONG(tree##_end - tree) ; \
FDTLONG(tree##_struct - tree) ; \
FDTLONG(tree##_strings - tree) ; \
FDTLONG(tree##_rsvmap - tree) ; \
FDTLONG(0x11) ; \
FDTLONG(0x10) ; \
FDTLONG(0) ; \
FDTLONG(tree##_strings_end - tree##_strings) ; \
FDTLONG(tree##_struct_end - tree##_struct) ;
.macro treehdr tree
.balign 8
.globl \tree
\tree :
fdtlong FDT_MAGIC
fdtlong (\tree\()_end - \tree)
fdtlong (\tree\()_struct - \tree)
fdtlong (\tree\()_strings - \tree)
fdtlong (\tree\()_rsvmap - \tree)
fdtlong 0x11
fdtlong 0x10
fdtlong 0
fdtlong (\tree\()_strings_end - \tree\()_strings)
fdtlong (\tree\()_struct_end - \tree\()_struct)
.endm
#define RSVMAP_ENTRY(addrh, addrl, lenh, lenl) \
FDTLONG(addrh) ; \
FDTLONG(addrl) ; \
FDTLONG(lenh) ; \
FDTLONG(lenl)
.macro rsvmape addrh, addrl, lenh, lenl
fdtlong \addrh
fdtlong \addrl
fdtlong \lenh
fdtlong \lenl
.endm
#define EMPTY_RSVMAP(tree) \
.balign 8 ; \
tree##_rsvmap: ; \
RSVMAP_ENTRY(0, 0, 0, 0) \
tree##_rsvmap_end: ;
.macro empty_rsvmap tree
.balign 8
\tree\()_rsvmap:
rsvmape 0, 0, 0, 0
\tree\()_rsvmap_end:
.endm
#define PROPHDR(tree, name, len) \
FDTLONG(FDT_PROP) ; \
FDTLONG(len) ; \
FDTLONG(tree##_##name - tree##_strings) ;
.macro prophdr tree, name, len
fdtlong FDT_PROP
fdtlong \len
fdtlong (\tree\()_\name - \tree\()_strings)
.endm
#define PROP_EMPTY(tree, name) \
PROPHDR(tree, name, 0) ;
.macro propnil tree, name
prophdr \tree, \name, 0
.endm
#define PROP_INT(tree, name, val) \
PROPHDR(tree, name, 4) \
FDTLONG(val) ;
.macro propu32 tree, name, val
prophdr \tree, \name, 4
fdtlong \val
.endm
#define PROP_INT64(tree, name, valh, vall) \
PROPHDR(tree, name, 8) \
FDTLONG(valh) ; \
FDTLONG(vall) ;
.macro propu64 tree, name, valh, vall
prophdr \tree, \name, 8
fdtlong \valh
fdtlong \vall
.endm
#define PROP_STR(tree, name, str) \
PROPHDR(tree, name, 55f - 54f) \
54: \
.string str ; \
55: \
.balign 4 ;
.macro propstr tree, name, str:vararg
prophdr \tree, \name, (55f - 54f)
54:
.asciz \str
55:
.balign 4
.endm
#define BEGIN_NODE(name) \
FDTLONG(FDT_BEGIN_NODE) ; \
.string name ; \
.balign 4 ;
.macro beginn name:vararg
fdtlong FDT_BEGIN_NODE
.asciz \name
.balign 4
.endm
#define END_NODE \
FDTLONG(FDT_END_NODE) ;
.macro endn
fdtlong FDT_END_NODE
.endm
.macro string tree, name, str:vararg
\tree\()_\name :
.asciz \str
.endm
#define STRING(tree, name, str) \
tree##_##name: ; \
.string str ;
.data
TREE_HDR(test_tree1)
treehdr test_tree1
.balign 8
test_tree1_rsvmap:
RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L)
RSVMAP_ENTRY(TEST_ADDR_2H, TEST_ADDR_2L, TEST_SIZE_2H, TEST_SIZE_2L)
RSVMAP_ENTRY(0, 0, 0, 0)
rsvmape TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L
rsvmape TEST_ADDR_2H, TEST_ADDR_2L, TEST_SIZE_2H, TEST_SIZE_2L
rsvmape 0, 0, 0, 0
test_tree1_rsvmap_end:
test_tree1_struct:
BEGIN_NODE("")
PROP_STR(test_tree1, compatible, "test_tree1")
PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1H, TEST_VALUE64_1L)
PROP_STR(test_tree1, prop_str, TEST_STRING_1)
PROP_INT(test_tree1, address_cells, 1)
PROP_INT(test_tree1, size_cells, 0)
beginn ""
propstr test_tree1, compatible, "test_tree1"
propu32 test_tree1, prop_int, TEST_VALUE_1
propu64 test_tree1, prop_int64, TEST_VALUE64_1H, TEST_VALUE64_1L
propstr test_tree1, prop_str, TEST_STRING_1
propu32 test_tree1, address_cells, 1
propu32 test_tree1, size_cells, 0
BEGIN_NODE("subnode@1")
PROP_STR(test_tree1, compatible, "subnode1")
PROP_INT(test_tree1, reg, 1)
PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
beginn "subnode@1"
propstr test_tree1, compatible, "subnode1"
propu32 test_tree1, reg, 1
propu32 test_tree1, prop_int, TEST_VALUE_1
BEGIN_NODE("subsubnode")
PROP_STR(test_tree1, compatible, "subsubnode1\0subsubnode")
PROP_STR(test_tree1, placeholder, "this is a placeholder string\0string2")
PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
END_NODE
beginn "subsubnode"
propstr test_tree1, compatible, "subsubnode1\0subsubnode"
propstr test_tree1, placeholder, "this is a placeholder string\0string2"
propu32 test_tree1, prop_int, TEST_VALUE_1
endn
BEGIN_NODE("ss1")
END_NODE
beginn "ss1"
endn
END_NODE
endn
BEGIN_NODE("subnode@2")
PROP_INT(test_tree1, reg, 2)
PROP_INT(test_tree1, linux_phandle, PHANDLE_1)
PROP_INT(test_tree1, prop_int, TEST_VALUE_2)
PROP_INT(test_tree1, address_cells, 1)
PROP_INT(test_tree1, size_cells, 0)
beginn "subnode@2"
propu32 test_tree1, reg, 2
propu32 test_tree1, linux_phandle, PHANDLE_1
propu32 test_tree1, prop_int, TEST_VALUE_2
propu32 test_tree1, address_cells, 1
propu32 test_tree1, size_cells, 0
BEGIN_NODE("subsubnode@0")
PROP_INT(test_tree1, reg, 0)
PROP_INT(test_tree1, phandle, PHANDLE_2)
PROP_STR(test_tree1, compatible, "subsubnode2\0subsubnode")
PROP_INT(test_tree1, prop_int, TEST_VALUE_2)
END_NODE
beginn "subsubnode@0"
propu32 test_tree1, reg, 0
propu32 test_tree1, phandle, PHANDLE_2
propstr test_tree1, compatible, "subsubnode2\0subsubnode"
propu32 test_tree1, prop_int, TEST_VALUE_2
endn
BEGIN_NODE("ss2")
END_NODE
beginn "ss2"
endn
END_NODE
endn
END_NODE
FDTLONG(FDT_END)
endn
fdtlong FDT_END
test_tree1_struct_end:
test_tree1_strings:
STRING(test_tree1, compatible, "compatible")
STRING(test_tree1, prop_int, "prop-int")
STRING(test_tree1, prop_int64, "prop-int64")
STRING(test_tree1, prop_str, "prop-str")
STRING(test_tree1, linux_phandle, "linux,phandle")
STRING(test_tree1, phandle, "phandle")
STRING(test_tree1, reg, "reg")
STRING(test_tree1, placeholder, "placeholder")
STRING(test_tree1, address_cells, "#address-cells")
STRING(test_tree1, size_cells, "#size-cells")
string test_tree1, compatible, "compatible"
string test_tree1, prop_int, "prop-int"
string test_tree1, prop_int64, "prop-int64"
string test_tree1, prop_str, "prop-str"
string test_tree1, linux_phandle, "linux,phandle"
string test_tree1, phandle, "phandle"
string test_tree1, reg, "reg"
string test_tree1, placeholder, "placeholder"
string test_tree1, address_cells, "#address-cells"
string test_tree1, size_cells, "#size-cells"
test_tree1_strings_end:
test_tree1_end:
TREE_HDR(truncated_property)
EMPTY_RSVMAP(truncated_property)
treehdr truncated_property
empty_rsvmap truncated_property
truncated_property_struct:
BEGIN_NODE("")
PROPHDR(truncated_property, prop_truncated, 4)
beginn ""
prophdr truncated_property, prop_truncated, 4
/* Oops, no actual property data here */
truncated_property_struct_end:
truncated_property_strings:
STRING(truncated_property, prop_truncated, "truncated")
string truncated_property, prop_truncated, "truncated"
truncated_property_strings_end:
truncated_property_end:
TREE_HDR(bad_node_char)
EMPTY_RSVMAP(bad_node_char)
treehdr bad_node_char
empty_rsvmap bad_node_char
bad_node_char_struct:
BEGIN_NODE("")
BEGIN_NODE("sub$node")
END_NODE
END_NODE
FDTLONG(FDT_END)
beginn ""
beginn "sub$node"
endn
endn
fdtlong FDT_END
bad_node_char_struct_end:
bad_node_char_strings:
@ -176,15 +189,15 @@ bad_node_char_strings_end:
bad_node_char_end:
TREE_HDR(bad_node_format)
EMPTY_RSVMAP(bad_node_format)
treehdr bad_node_format
empty_rsvmap bad_node_format
bad_node_format_struct:
BEGIN_NODE("")
BEGIN_NODE("subnode@1@2")
END_NODE
END_NODE
FDTLONG(FDT_END)
beginn ""
beginn "subnode@1@2"
endn
endn
fdtlong FDT_END
bad_node_format_struct_end:
bad_node_format_strings:
@ -192,18 +205,18 @@ bad_node_format_strings_end:
bad_node_format_end:
TREE_HDR(bad_prop_char)
EMPTY_RSVMAP(bad_prop_char)
treehdr bad_prop_char
empty_rsvmap bad_prop_char
bad_prop_char_struct:
BEGIN_NODE("")
PROP_INT(bad_prop_char, prop, TEST_VALUE_1)
END_NODE
FDTLONG(FDT_END)
beginn ""
propu32 bad_prop_char, prop, TEST_VALUE_1
endn
fdtlong FDT_END
bad_prop_char_struct_end:
bad_prop_char_strings:
STRING(bad_prop_char, prop, "prop$erty")
string bad_prop_char, prop, "prop$erty"
bad_prop_char_strings_end:
bad_prop_char_end:
@ -212,62 +225,60 @@ bad_prop_char_end:
.balign 8
.globl ovf_size_strings
ovf_size_strings:
FDTLONG(FDT_MAGIC)
FDTLONG(ovf_size_strings_end - ovf_size_strings)
FDTLONG(ovf_size_strings_struct - ovf_size_strings)
FDTLONG(ovf_size_strings_strings - ovf_size_strings)
FDTLONG(ovf_size_strings_rsvmap - ovf_size_strings)
FDTLONG(0x11)
FDTLONG(0x10)
FDTLONG(0)
FDTLONG(0xffffffff)
FDTLONG(ovf_size_strings_struct_end - ovf_size_strings_struct)
EMPTY_RSVMAP(ovf_size_strings)
fdtlong FDT_MAGIC
fdtlong (ovf_size_strings_end - ovf_size_strings)
fdtlong (ovf_size_strings_struct - ovf_size_strings)
fdtlong (ovf_size_strings_strings - ovf_size_strings)
fdtlong (ovf_size_strings_rsvmap - ovf_size_strings)
fdtlong 0x11
fdtlong 0x10
fdtlong 0
fdtlong 0xffffffff
fdtlong (ovf_size_strings_struct_end - ovf_size_strings_struct)
empty_rsvmap ovf_size_strings
ovf_size_strings_struct:
BEGIN_NODE("")
PROP_INT(ovf_size_strings, bad_string, 0)
END_NODE
FDTLONG(FDT_END)
beginn ""
propu32 ovf_size_strings, bad_string, 0
endn
fdtlong FDT_END
ovf_size_strings_struct_end:
ovf_size_strings_strings:
STRING(ovf_size_strings, x, "x")
string ovf_size_strings, x, "x"
ovf_size_strings_bad_string = ovf_size_strings_strings + 0x10000000
ovf_size_strings_strings_end:
ovf_size_strings_end:
/* truncated_string */
TREE_HDR(truncated_string)
EMPTY_RSVMAP(truncated_string)
treehdr truncated_string
empty_rsvmap truncated_string
truncated_string_struct:
BEGIN_NODE("")
PROP_EMPTY(truncated_string, good_string)
PROP_EMPTY(truncated_string, bad_string)
END_NODE
FDTLONG(FDT_END)
beginn ""
propnil truncated_string, good_string
propnil truncated_string, bad_string
endn
fdtlong FDT_END
truncated_string_struct_end:
truncated_string_strings:
STRING(truncated_string, good_string, "good")
string truncated_string, good_string, "good"
truncated_string_bad_string:
.byte 'b'
.byte 'a'
.byte 'd'
.ascii "bad"
/* NOTE: terminating \0 deliberately missing */
truncated_string_strings_end:
truncated_string_end:
/* truncated_memrsv */
TREE_HDR(truncated_memrsv)
treehdr truncated_memrsv
truncated_memrsv_struct:
BEGIN_NODE("")
END_NODE
FDTLONG(FDT_END)
beginn ""
endn
fdtlong FDT_END
truncated_memrsv_struct_end:
truncated_memrsv_strings:
@ -275,7 +286,41 @@ truncated_memrsv_strings_end:
.balign 8
truncated_memrsv_rsvmap:
RSVMAP_ENTRY(TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L)
rsvmape TEST_ADDR_1H, TEST_ADDR_1L, TEST_SIZE_1H, TEST_SIZE_1L
truncated_memrsv_rsvmap_end:
truncated_memrsv_end:
/* two root nodes */
treehdr two_roots
empty_rsvmap two_roots
two_roots_struct:
beginn ""
endn
beginn ""
endn
fdtlong FDT_END
two_roots_struct_end:
two_roots_strings:
two_roots_strings_end:
two_roots_end:
/* root node with a non-empty name */
treehdr named_root
empty_rsvmap named_root
named_root_struct:
beginn "fake"
endn
fdtlong FDT_END
named_root_struct_end:
named_root_strings:
named_root_strings_end:
named_root_end:

View file

@ -13,8 +13,11 @@
int64: [!u64 [0x200000000]]
int64-array: [!u64 [0x100000000, 0x0]]
a-string-with-nulls: ["foo\0bar", "baz"]
a-phandle: [[!phandle 0x1]]
a-phandle-with-args: [[!phandle 0x1, 0x0, 0x1], [!phandle 0x1, 0x2, 0x3]]
subsubnode:
compatible: ["subsubnode1", "subsubnode"]
phandle: [[0x1]]
subsubsubnode:
compatible: ["subsubsubnode1", [0x1234], "subsubsubnode"]
...

View file

@ -16,9 +16,12 @@
int64 = /bits/ 64 <0x200000000>;
int64-array = /bits/ 64 <0x100000000 0x00> int64_array_label_end:;
a-string-with-nulls = "foo\0bar", "baz";
a-phandle = <&subsub1>;
a-phandle-with-args = <&subsub1 0x00 0x01>, <&subsub1 0x02 0x03>;
subsub1: subsubnode {
compatible = "subsubnode1", "subsubnode";
phandle = <0x01>;
subsubsub1: subsubsubnode {
compatible = "subsubsubnode1", <0x1234>, valuea: valueb: "subsubsubnode";

View file

@ -73,6 +73,9 @@ static void check_sizes(char *modifier, int expected_size)
*ptr = 's';
check(fmt, 's', -1);
*ptr = 'r';
check(fmt, 'r', -1);
}
static void test_utilfdt_decode_type(void)
@ -90,7 +93,7 @@ static void test_utilfdt_decode_type(void)
/* try every other character */
checkfail("");
for (ch = ' '; ch < 127; ch++) {
if (!strchr("iuxs", ch)) {
if (!strchr("iuxsr", ch)) {
*fmt = ch;
fmt[1] = '\0';
checkfail(fmt);

View file

@ -124,27 +124,6 @@ static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
}
}
static bool has_data_type_information(struct marker *m)
{
return m->type >= TYPE_UINT8;
}
static struct marker *next_type_marker(struct marker *m)
{
while (m && !has_data_type_information(m))
m = m->next;
return m;
}
size_t type_marker_length(struct marker *m)
{
struct marker *next = next_type_marker(m->next);
if (next)
return next->offset - m->offset;
return 0;
}
static const char *delim_start[] = {
[TYPE_UINT8] = "[",
[TYPE_UINT16] = "/bits/ 16 <",
@ -229,26 +208,39 @@ static void write_propval(FILE *f, struct property *prop)
size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
size_t data_len = type_marker_length(m) ? : len - m->offset;
const char *p = &prop->val.val[m->offset];
struct marker *m_phandle;
if (has_data_type_information(m)) {
if (is_type_marker(m->type)) {
emit_type = m->type;
fprintf(f, " %s", delim_start[emit_type]);
} else if (m->type == LABEL)
fprintf(f, " %s:", m->ref);
else if (m->offset)
fputc(' ', f);
if (emit_type == TYPE_NONE) {
assert(chunk_len == 0);
if (emit_type == TYPE_NONE || chunk_len == 0)
continue;
}
switch(emit_type) {
case TYPE_UINT16:
write_propval_int(f, p, chunk_len, 2);
break;
case TYPE_UINT32:
write_propval_int(f, p, chunk_len, 4);
m_phandle = prop->val.markers;
for_each_marker_of_type(m_phandle, REF_PHANDLE)
if (m->offset == m_phandle->offset)
break;
if (m_phandle) {
if (m_phandle->ref[0] == '/')
fprintf(f, "&{%s}", m_phandle->ref);
else
fprintf(f, "&%s", m_phandle->ref);
if (chunk_len > 4) {
fputc(' ', f);
write_propval_int(f, p + 4, chunk_len - 4, 4);
}
} else {
write_propval_int(f, p, chunk_len, 4);
}
break;
case TYPE_UINT64:
write_propval_int(f, p, chunk_len, 8);

15
util.c
View file

@ -33,6 +33,17 @@ char *xstrdup(const char *s)
return d;
}
char *xstrndup(const char *s, size_t n)
{
size_t len = strnlen(s, n) + 1;
char *d = xmalloc(len);
memcpy(d, s, len - 1);
d[len - 1] = '\0';
return d;
}
int xavsprintf_append(char **strp, const char *fmt, va_list ap)
{
int n, size = 0; /* start with 128 bytes */
@ -353,11 +364,11 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
}
/* we should now have a type */
if ((*fmt == '\0') || !strchr("iuxs", *fmt))
if ((*fmt == '\0') || !strchr("iuxsr", *fmt))
return -1;
/* convert qualifier (bhL) to byte size */
if (*fmt != 's')
if (*fmt != 's' && *fmt != 'r')
*size = qualifier == 'b' ? 1 :
qualifier == 'h' ? 2 :
qualifier == 'l' ? 4 : -1;

11
util.h
View file

@ -2,6 +2,7 @@
#ifndef UTIL_H
#define UTIL_H
#include <stdlib.h>
#include <stdarg.h>
#include <stdbool.h>
#include <getopt.h>
@ -12,10 +13,10 @@
*/
#ifdef __GNUC__
#ifdef __clang__
#define PRINTF(i, j) __attribute__((format (printf, i, j)))
#else
#if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
#define PRINTF(i, j) __attribute__((format (gnu_printf, i, j)))
#else
#define PRINTF(i, j) __attribute__((format (printf, i, j)))
#endif
#define NORETURN __attribute__((noreturn))
#else
@ -60,6 +61,7 @@ static inline void *xrealloc(void *p, size_t len)
}
extern char *xstrdup(const char *s);
extern char *xstrndup(const char *s, size_t len);
extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...);
@ -142,6 +144,7 @@ int utilfdt_write_err(const char *filename, const void *blob);
* i signed integer
* u unsigned integer
* x hex
* r raw
*
* TODO: Implement ll modifier (8 bytes)
* TODO: Implement o type (octal)
@ -159,7 +162,7 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size);
*/
#define USAGE_TYPE_MSG \
"<type>\ts=string, i=int, u=unsigned, x=hex\n" \
"<type>\ts=string, i=int, u=unsigned, x=hex, r=raw\n" \
"\tOptional modifier prefix:\n" \
"\t\thh or b=byte, h=2 byte, l=4 byte (default)";

1
version_gen.h.in Normal file
View file

@ -0,0 +1 @@
#define DTC_VERSION "DTC @VCS_TAG@"

View file

@ -29,11 +29,12 @@ char *yaml_error_name[] = {
(emitter)->problem, __func__, __LINE__); \
})
static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width)
static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers,
char *data, unsigned int seq_offset, unsigned int len, int width)
{
yaml_event_t event;
void *tag;
int off, start_offset = markers->offset;
unsigned int off;
switch(width) {
case 1: tag = "!u8"; break;
@ -66,7 +67,7 @@ static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, ch
m = markers;
is_phandle = false;
for_each_marker_of_type(m, REF_PHANDLE) {
if (m->offset == (start_offset + off)) {
if (m->offset == (seq_offset + off)) {
is_phandle = true;
break;
}
@ -112,8 +113,9 @@ static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len)
static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
{
yaml_event_t event;
int len = prop->val.len;
unsigned int len = prop->val.len;
struct marker *m = prop->val.markers;
struct marker *markers = prop->val.markers;
/* Emit the property name */
yaml_scalar_event_initialize(&event, NULL,
@ -151,19 +153,19 @@ static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
switch(m->type) {
case TYPE_UINT16:
yaml_propval_int(emitter, m, data, chunk_len, 2);
yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 2);
break;
case TYPE_UINT32:
yaml_propval_int(emitter, m, data, chunk_len, 4);
yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 4);
break;
case TYPE_UINT64:
yaml_propval_int(emitter, m, data, chunk_len, 8);
yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 8);
break;
case TYPE_STRING:
yaml_propval_string(emitter, data, chunk_len);
break;
default:
yaml_propval_int(emitter, m, data, chunk_len, 1);
yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 1);
break;
}
}