scripts/dtc: Update to upstream version 0931cea3ba20

Sync to upstream dtc commit 0931cea3ba20 ("dtc: fdtdump: check fdt if
not in scanning mode"). In particular, this pulls in dtc overlay
support.

This adds the following commits from upstream:

f88865469b65 dtc: Fix memory leak in character literal parsing
00fbb8696b66 Rename boot_info
1ef86ad2c24f dtc: Clean up /dts-v1/ and /plugin/ handling in grammar
e3c769aa9c16 dtc: Don't always generate __symbols__ for plugins
c96cb3c0169e tests: Don't use -@ on plugin de/recompile tests
66381538ce24 tests: Remove "suppression of fixups" tests
ba765b273f0f tests: Clarify dtc overlay tests
6ea8cd944fcd tests: More thorough tests of libfdt overlay application without dtc
7d8ef6e1db97 tests: Correct fdt handling of overlays without fixups and base trees without symbols
b4dc0ed8b127 tests: Fix double expansion bugs in test code
3ea879dc0c8f tests: Split overlay tests into those with do/don't exercise dtc plugin generation
47b4d66a2f11 tests: Test auto-alias generation on base tree, not overlay
72e1ad811523 tests: Make overlay/plugin tests unconditional
e7b3c3b5951b tests: Add overlay tests
9637e3f772a9 tests: Add check_path test
20f29d8d41f6 dtc: Plugin and fixup support
a2c92cac53f8 dtc: Document the dynamic plugin internals
8f70ac39801d checks: Pass boot_info instead of root node
ea10f953878f libfdt: add missing errors to fdt_strerror()
daa75e8fa594 libfdt: fix fdt_stringlist_search()
e28eff5b787a libfdt: fix fdt_stringlist_count()
ae97c7722840 tests: overlay: Rename the device tree blobs to be more explicit
96162d2bd9cb tests: overlay: Add test suffix to the compiled blobs
5ce8634733b7 libfdt: Add fdt_overlay_apply to the exported symbols
804a9db90ad2 fdt: strerr: Remove spurious BADOVERLAY
e8c3a1a493fa tests: overlay: Move back the bad fixup tests
7a72d89d3f81 libfdt: overlay: Fix symbols and fixups nodes condition
cabbaa972cdd libfdt: overlay: Report a bad overlay for mismatching local fixups
deb0a5c1aeaa libfdt: Add BADPHANDLE error string
7b7a6be9ba15 libfdt: Don't use 'index' as a local variable name
aea8860d831e tests: Add tests cases for the overlay code
0cdd06c5135b libfdt: Add overlay application function
39240cc865cf libfdt: Extend the reach of FDT_ERR_BADPHANDLE
4aa3a6f5e6d9 libfdt: Add new errors for the overlay code
6d1832c9e64b dtc: Remove "home page" link
45fd440a9561 Fix some typing errors in libfdt.h and livetree.c
a59be4939c13 Merge tag 'v1.4.2'
a34bb721caca dtc: Fix assorted problems in the testcases for the -a option
874f40588d3e Implement the -a option to pad dtb aligned
ec02b34c05be dtc: Makefile improvements for release uploading
1ed45d40a137 dtc: Bump version to 1.4.2
36fd7331fb11 libfdt: simplify fdt_del_mem_rsv()
d877364e4a0f libfdt: Add fdt_setprop_inplace_namelen_partial
3e9037aaad44 libfdt: Add fdt_getprop_namelen_w
84e0e1346c68 libfdt: Add max phandle retrieval function
d29126c90acb libfdt: Add iterator over properties
902d0f0953d0 libfdt: Add a subnodes iterator macro
c539075ba8ba fdtput.c: Fix memory leak.
f79ddb83e185 fdtget.c: Fix memory leak
1074ee54b63f convert-dtsv0-lexer.l: fix memory leak
e24d39a024e6 fdtdump.c: make sure size_t argument to memchr is always unsigned.
44a59713cf05 Remove unused srcpos_dump() function
cb9241ae3453 DTC: Fix memory leak on flatname.
1ee0ae24ea09 Simplify check field and macro names
9d97527a8621 Remove property check functions
2e709d158e11 Remove tree check functions
c4cb12e193e3 Alter grammar to allow multiple /dts-v1/ tags
d71d25d76012 Use xasprintf() in srcpos
9dc404958e9c util: Add xasprintf portable asprintf variant
beef80b8b55f Correct a missing space in a fdt_header cast
68d43cec1253 Correct line lengths in libfdt.h
b0dbceafd49a Correct space-after-tab in libfdt.h

Signed-off-by: Rob Herring <robh@kernel.org>
This commit is contained in:
Rob Herring 2017-01-04 10:45:20 -06:00
parent 0c744ea4f7
commit 6f05afcbb0
24 changed files with 1733 additions and 1091 deletions

View File

@ -40,16 +40,11 @@ enum checkstatus {
struct check; struct check;
typedef void (*tree_check_fn)(struct check *c, struct node *dt); typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node);
typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node);
typedef void (*prop_check_fn)(struct check *c, struct node *dt,
struct node *node, struct property *prop);
struct check { struct check {
const char *name; const char *name;
tree_check_fn tree_fn; check_fn fn;
node_check_fn node_fn;
prop_check_fn prop_fn;
void *data; void *data;
bool warn, error; bool warn, error;
enum checkstatus status; enum checkstatus status;
@ -58,45 +53,24 @@ struct check {
struct check **prereq; struct check **prereq;
}; };
#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...) \ #define CHECK_ENTRY(_nm, _fn, _d, _w, _e, ...) \
static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \ static struct check *_nm##_prereqs[] = { __VA_ARGS__ }; \
static struct check nm = { \ static struct check _nm = { \
.name = #nm, \ .name = #_nm, \
.tree_fn = (tfn), \ .fn = (_fn), \
.node_fn = (nfn), \ .data = (_d), \
.prop_fn = (pfn), \ .warn = (_w), \
.data = (d), \ .error = (_e), \
.warn = (w), \
.error = (e), \
.status = UNCHECKED, \ .status = UNCHECKED, \
.num_prereqs = ARRAY_SIZE(nm##_prereqs), \ .num_prereqs = ARRAY_SIZE(_nm##_prereqs), \
.prereq = nm##_prereqs, \ .prereq = _nm##_prereqs, \
}; };
#define WARNING(nm, tfn, nfn, pfn, d, ...) \ #define WARNING(_nm, _fn, _d, ...) \
CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__) CHECK_ENTRY(_nm, _fn, _d, true, false, __VA_ARGS__)
#define ERROR(nm, tfn, nfn, pfn, d, ...) \ #define ERROR(_nm, _fn, _d, ...) \
CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__) CHECK_ENTRY(_nm, _fn, _d, false, true, __VA_ARGS__)
#define CHECK(nm, tfn, nfn, pfn, d, ...) \ #define CHECK(_nm, _fn, _d, ...) \
CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__) CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__)
#define TREE_WARNING(nm, d, ...) \
WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
#define TREE_ERROR(nm, d, ...) \
ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
#define TREE_CHECK(nm, d, ...) \
CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
#define NODE_WARNING(nm, d, ...) \
WARNING(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
#define NODE_ERROR(nm, d, ...) \
ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
#define NODE_CHECK(nm, d, ...) \
CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
#define PROP_WARNING(nm, d, ...) \
WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
#define PROP_ERROR(nm, d, ...) \
ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
#define PROP_CHECK(nm, d, ...) \
CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
#ifdef __GNUC__ #ifdef __GNUC__
static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
@ -123,27 +97,21 @@ static inline void check_msg(struct check *c, const char *fmt, ...)
check_msg((c), __VA_ARGS__); \ check_msg((c), __VA_ARGS__); \
} while (0) } while (0)
static void check_nodes_props(struct check *c, struct node *dt, struct node *node) static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node)
{ {
struct node *child; struct node *child;
struct property *prop;
TRACE(c, "%s", node->fullpath); TRACE(c, "%s", node->fullpath);
if (c->node_fn) if (c->fn)
c->node_fn(c, dt, node); c->fn(c, dti, node);
if (c->prop_fn)
for_each_property(node, prop) {
TRACE(c, "%s\t'%s'", node->fullpath, prop->name);
c->prop_fn(c, dt, node, prop);
}
for_each_child(node, child) for_each_child(node, child)
check_nodes_props(c, dt, child); check_nodes_props(c, dti, child);
} }
static bool run_check(struct check *c, struct node *dt) static bool run_check(struct check *c, struct dt_info *dti)
{ {
struct node *dt = dti->dt;
bool error = false; bool error = false;
int i; int i;
@ -156,7 +124,7 @@ static bool run_check(struct check *c, struct node *dt)
for (i = 0; i < c->num_prereqs; i++) { for (i = 0; i < c->num_prereqs; i++) {
struct check *prq = c->prereq[i]; struct check *prq = c->prereq[i];
error = error || run_check(prq, dt); error = error || run_check(prq, dti);
if (prq->status != PASSED) { if (prq->status != PASSED) {
c->status = PREREQ; c->status = PREREQ;
check_msg(c, "Failed prerequisite '%s'", check_msg(c, "Failed prerequisite '%s'",
@ -167,11 +135,8 @@ static bool run_check(struct check *c, struct node *dt)
if (c->status != UNCHECKED) if (c->status != UNCHECKED)
goto out; goto out;
if (c->node_fn || c->prop_fn) check_nodes_props(c, dti, dt);
check_nodes_props(c, dt, dt);
if (c->tree_fn)
c->tree_fn(c, dt);
if (c->status == UNCHECKED) if (c->status == UNCHECKED)
c->status = PASSED; c->status = PASSED;
@ -189,13 +154,14 @@ out:
*/ */
/* A check which always fails, for testing purposes only */ /* A check which always fails, for testing purposes only */
static inline void check_always_fail(struct check *c, struct node *dt) static inline void check_always_fail(struct check *c, struct dt_info *dti,
struct node *node)
{ {
FAIL(c, "always_fail check"); FAIL(c, "always_fail check");
} }
TREE_CHECK(always_fail, NULL); CHECK(always_fail, check_always_fail, NULL);
static void check_is_string(struct check *c, struct node *root, static void check_is_string(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
struct property *prop; struct property *prop;
@ -210,11 +176,11 @@ static void check_is_string(struct check *c, struct node *root,
propname, node->fullpath); propname, node->fullpath);
} }
#define WARNING_IF_NOT_STRING(nm, propname) \ #define WARNING_IF_NOT_STRING(nm, propname) \
WARNING(nm, NULL, check_is_string, NULL, (propname)) WARNING(nm, check_is_string, (propname))
#define ERROR_IF_NOT_STRING(nm, propname) \ #define ERROR_IF_NOT_STRING(nm, propname) \
ERROR(nm, NULL, check_is_string, NULL, (propname)) ERROR(nm, check_is_string, (propname))
static void check_is_cell(struct check *c, struct node *root, static void check_is_cell(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
struct property *prop; struct property *prop;
@ -229,15 +195,15 @@ static void check_is_cell(struct check *c, struct node *root,
propname, node->fullpath); propname, node->fullpath);
} }
#define WARNING_IF_NOT_CELL(nm, propname) \ #define WARNING_IF_NOT_CELL(nm, propname) \
WARNING(nm, NULL, check_is_cell, NULL, (propname)) WARNING(nm, check_is_cell, (propname))
#define ERROR_IF_NOT_CELL(nm, propname) \ #define ERROR_IF_NOT_CELL(nm, propname) \
ERROR(nm, NULL, check_is_cell, NULL, (propname)) ERROR(nm, check_is_cell, (propname))
/* /*
* Structural check functions * Structural check functions
*/ */
static void check_duplicate_node_names(struct check *c, struct node *dt, static void check_duplicate_node_names(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
struct node *child, *child2; struct node *child, *child2;
@ -250,9 +216,9 @@ static void check_duplicate_node_names(struct check *c, struct node *dt,
FAIL(c, "Duplicate node name %s", FAIL(c, "Duplicate node name %s",
child->fullpath); child->fullpath);
} }
NODE_ERROR(duplicate_node_names, NULL); ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
static void check_duplicate_property_names(struct check *c, struct node *dt, static void check_duplicate_property_names(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
struct property *prop, *prop2; struct property *prop, *prop2;
@ -267,14 +233,14 @@ static void check_duplicate_property_names(struct check *c, struct node *dt,
} }
} }
} }
NODE_ERROR(duplicate_property_names, NULL); ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz" #define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define DIGITS "0123456789" #define DIGITS "0123456789"
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-" #define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
static void check_node_name_chars(struct check *c, struct node *dt, static void check_node_name_chars(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
int n = strspn(node->name, c->data); int n = strspn(node->name, c->data);
@ -283,19 +249,19 @@ static void check_node_name_chars(struct check *c, struct node *dt,
FAIL(c, "Bad character '%c' in node %s", FAIL(c, "Bad character '%c' in node %s",
node->name[n], node->fullpath); node->name[n], node->fullpath);
} }
NODE_ERROR(node_name_chars, PROPNODECHARS "@"); ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
static void check_node_name_format(struct check *c, struct node *dt, static void check_node_name_format(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
if (strchr(get_unitname(node), '@')) if (strchr(get_unitname(node), '@'))
FAIL(c, "Node %s has multiple '@' characters in name", FAIL(c, "Node %s has multiple '@' characters in name",
node->fullpath); node->fullpath);
} }
NODE_ERROR(node_name_format, NULL, &node_name_chars); ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
static void check_unit_address_vs_reg(struct check *c, struct node *dt, static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
const char *unitname = get_unitname(node); const char *unitname = get_unitname(node);
struct property *prop = get_property(node, "reg"); struct property *prop = get_property(node, "reg");
@ -316,18 +282,22 @@ static void check_unit_address_vs_reg(struct check *c, struct node *dt,
node->fullpath); node->fullpath);
} }
} }
NODE_WARNING(unit_address_vs_reg, NULL); WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
static void check_property_name_chars(struct check *c, struct node *dt, static void check_property_name_chars(struct check *c, struct dt_info *dti,
struct node *node, struct property *prop) struct node *node)
{ {
int n = strspn(prop->name, c->data); struct property *prop;
if (n < strlen(prop->name)) for_each_property(node, prop) {
FAIL(c, "Bad character '%c' in property name \"%s\", node %s", int n = strspn(prop->name, c->data);
prop->name[n], prop->name, node->fullpath);
if (n < strlen(prop->name))
FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
prop->name[n], prop->name, node->fullpath);
}
} }
PROP_ERROR(property_name_chars, PROPNODECHARS); ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
#define DESCLABEL_FMT "%s%s%s%s%s" #define DESCLABEL_FMT "%s%s%s%s%s"
#define DESCLABEL_ARGS(node,prop,mark) \ #define DESCLABEL_ARGS(node,prop,mark) \
@ -336,10 +306,11 @@ PROP_ERROR(property_name_chars, PROPNODECHARS);
((prop) ? (prop)->name : ""), \ ((prop) ? (prop)->name : ""), \
((prop) ? "' in " : ""), (node)->fullpath ((prop) ? "' in " : ""), (node)->fullpath
static void check_duplicate_label(struct check *c, struct node *dt, static void check_duplicate_label(struct check *c, struct dt_info *dti,
const char *label, struct node *node, const char *label, struct node *node,
struct property *prop, struct marker *mark) struct property *prop, struct marker *mark)
{ {
struct node *dt = dti->dt;
struct node *othernode = NULL; struct node *othernode = NULL;
struct property *otherprop = NULL; struct property *otherprop = NULL;
struct marker *othermark = NULL; struct marker *othermark = NULL;
@ -362,44 +333,43 @@ static void check_duplicate_label(struct check *c, struct node *dt,
DESCLABEL_ARGS(othernode, otherprop, othermark)); DESCLABEL_ARGS(othernode, otherprop, othermark));
} }
static void check_duplicate_label_node(struct check *c, struct node *dt, static void check_duplicate_label_node(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
struct label *l; struct label *l;
struct property *prop;
for_each_label(node->labels, l) for_each_label(node->labels, l)
check_duplicate_label(c, dt, l->label, node, NULL, NULL); check_duplicate_label(c, dti, l->label, node, NULL, NULL);
for_each_property(node, prop) {
struct marker *m = prop->val.markers;
for_each_label(prop->labels, l)
check_duplicate_label(c, dti, l->label, node, prop, NULL);
for_each_marker_of_type(m, LABEL)
check_duplicate_label(c, dti, m->ref, node, prop, m);
}
} }
static void check_duplicate_label_prop(struct check *c, struct node *dt, ERROR(duplicate_label, check_duplicate_label_node, NULL);
struct node *node, struct property *prop)
{ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
struct marker *m = prop->val.markers; struct node *node, const char *propname)
struct label *l;
for_each_label(prop->labels, l)
check_duplicate_label(c, dt, l->label, node, prop, NULL);
for_each_marker_of_type(m, LABEL)
check_duplicate_label(c, dt, m->ref, node, prop, m);
}
ERROR(duplicate_label, NULL, check_duplicate_label_node,
check_duplicate_label_prop, NULL);
static void check_explicit_phandles(struct check *c, struct node *root,
struct node *node, struct property *prop)
{ {
struct node *root = dti->dt;
struct property *prop;
struct marker *m; struct marker *m;
struct node *other;
cell_t phandle; cell_t phandle;
if (!streq(prop->name, "phandle") prop = get_property(node, propname);
&& !streq(prop->name, "linux,phandle")) if (!prop)
return; return 0;
if (prop->val.len != sizeof(cell_t)) { if (prop->val.len != sizeof(cell_t)) {
FAIL(c, "%s has bad length (%d) %s property", FAIL(c, "%s has bad length (%d) %s property",
node->fullpath, prop->val.len, prop->name); node->fullpath, prop->val.len, prop->name);
return; return 0;
} }
m = prop->val.markers; m = prop->val.markers;
@ -411,14 +381,13 @@ static void check_explicit_phandles(struct check *c, struct node *root,
* by construction. */ { * by construction. */ {
FAIL(c, "%s in %s is a reference to another node", FAIL(c, "%s in %s is a reference to another node",
prop->name, node->fullpath); prop->name, node->fullpath);
return;
} }
/* But setting this node's phandle equal to its own /* But setting this node's phandle equal to its own
* phandle is allowed - that means allocate a unique * phandle is allowed - that means allocate a unique
* phandle for this node, even if it's not otherwise * phandle for this node, even if it's not otherwise
* referenced. The value will be filled in later, so * referenced. The value will be filled in later, so
* no further checking for now. */ * we treat it as having no phandle data for now. */
return; return 0;
} }
phandle = propval_cell(prop); phandle = propval_cell(prop);
@ -426,12 +395,36 @@ static void check_explicit_phandles(struct check *c, struct node *root,
if ((phandle == 0) || (phandle == -1)) { if ((phandle == 0) || (phandle == -1)) {
FAIL(c, "%s has bad value (0x%x) in %s property", FAIL(c, "%s has bad value (0x%x) in %s property",
node->fullpath, phandle, prop->name); node->fullpath, phandle, prop->name);
return; return 0;
} }
if (node->phandle && (node->phandle != phandle)) return phandle;
FAIL(c, "%s has %s property which replaces existing phandle information", }
node->fullpath, prop->name);
static void check_explicit_phandles(struct check *c, struct dt_info *dti,
struct node *node)
{
struct node *root = dti->dt;
struct node *other;
cell_t phandle, linux_phandle;
/* Nothing should have assigned phandles yet */
assert(!node->phandle);
phandle = check_phandle_prop(c, dti, node, "phandle");
linux_phandle = check_phandle_prop(c, dti, node, "linux,phandle");
if (!phandle && !linux_phandle)
/* No valid phandles; nothing further to check */
return;
if (linux_phandle && phandle && (phandle != linux_phandle))
FAIL(c, "%s has mismatching 'phandle' and 'linux,phandle'"
" properties", node->fullpath);
if (linux_phandle && !phandle)
phandle = linux_phandle;
other = get_node_by_phandle(root, phandle); other = get_node_by_phandle(root, phandle);
if (other && (other != node)) { if (other && (other != node)) {
@ -442,9 +435,9 @@ static void check_explicit_phandles(struct check *c, struct node *root,
node->phandle = phandle; node->phandle = phandle;
} }
PROP_ERROR(explicit_phandles, NULL); ERROR(explicit_phandles, check_explicit_phandles, NULL);
static void check_name_properties(struct check *c, struct node *root, static void check_name_properties(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
struct property **pp, *prop = NULL; struct property **pp, *prop = NULL;
@ -472,60 +465,73 @@ static void check_name_properties(struct check *c, struct node *root,
} }
} }
ERROR_IF_NOT_STRING(name_is_string, "name"); ERROR_IF_NOT_STRING(name_is_string, "name");
NODE_ERROR(name_properties, NULL, &name_is_string); ERROR(name_properties, check_name_properties, NULL, &name_is_string);
/* /*
* Reference fixup functions * Reference fixup functions
*/ */
static void fixup_phandle_references(struct check *c, struct node *dt, static void fixup_phandle_references(struct check *c, struct dt_info *dti,
struct node *node, struct property *prop) struct node *node)
{ {
struct marker *m = prop->val.markers; struct node *dt = dti->dt;
struct node *refnode; struct property *prop;
cell_t phandle;
for_each_marker_of_type(m, REF_PHANDLE) { for_each_property(node, prop) {
assert(m->offset + sizeof(cell_t) <= prop->val.len); struct marker *m = prop->val.markers;
struct node *refnode;
cell_t phandle;
refnode = get_node_by_ref(dt, m->ref); for_each_marker_of_type(m, REF_PHANDLE) {
if (! refnode) { assert(m->offset + sizeof(cell_t) <= prop->val.len);
FAIL(c, "Reference to non-existent node or label \"%s\"\n",
m->ref); refnode = get_node_by_ref(dt, m->ref);
continue; if (! refnode) {
if (!(dti->dtsflags & DTSF_PLUGIN))
FAIL(c, "Reference to non-existent node or "
"label \"%s\"\n", m->ref);
else /* mark the entry as unresolved */
*((cell_t *)(prop->val.val + m->offset)) =
cpu_to_fdt32(0xffffffff);
continue;
}
phandle = get_node_phandle(dt, refnode);
*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
} }
phandle = get_node_phandle(dt, refnode);
*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
} }
} }
ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR(phandle_references, fixup_phandle_references, NULL,
&duplicate_node_names, &explicit_phandles); &duplicate_node_names, &explicit_phandles);
static void fixup_path_references(struct check *c, struct node *dt, static void fixup_path_references(struct check *c, struct dt_info *dti,
struct node *node, struct property *prop) struct node *node)
{ {
struct marker *m = prop->val.markers; struct node *dt = dti->dt;
struct node *refnode; struct property *prop;
char *path;
for_each_marker_of_type(m, REF_PATH) { for_each_property(node, prop) {
assert(m->offset <= prop->val.len); struct marker *m = prop->val.markers;
struct node *refnode;
char *path;
refnode = get_node_by_ref(dt, m->ref); for_each_marker_of_type(m, REF_PATH) {
if (!refnode) { assert(m->offset <= prop->val.len);
FAIL(c, "Reference to non-existent node or label \"%s\"\n",
m->ref); refnode = get_node_by_ref(dt, m->ref);
continue; if (!refnode) {
FAIL(c, "Reference to non-existent node or label \"%s\"\n",
m->ref);
continue;
}
path = refnode->fullpath;
prop->val = data_insert_at_marker(prop->val, m, path,
strlen(path) + 1);
} }
path = refnode->fullpath;
prop->val = data_insert_at_marker(prop->val, m, path,
strlen(path) + 1);
} }
} }
ERROR(path_references, NULL, NULL, fixup_path_references, NULL, ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names);
&duplicate_node_names);
/* /*
* Semantic checks * Semantic checks
@ -538,7 +544,7 @@ WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
WARNING_IF_NOT_STRING(model_is_string, "model"); WARNING_IF_NOT_STRING(model_is_string, "model");
WARNING_IF_NOT_STRING(status_is_string, "status"); WARNING_IF_NOT_STRING(status_is_string, "status");
static void fixup_addr_size_cells(struct check *c, struct node *dt, static void fixup_addr_size_cells(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
struct property *prop; struct property *prop;
@ -554,7 +560,7 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt,
if (prop) if (prop)
node->size_cells = propval_cell(prop); node->size_cells = propval_cell(prop);
} }
WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARNING(addr_size_cells, fixup_addr_size_cells, NULL,
&address_cells_is_cell, &size_cells_is_cell); &address_cells_is_cell, &size_cells_is_cell);
#define node_addr_cells(n) \ #define node_addr_cells(n) \
@ -562,7 +568,7 @@ WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL,
#define node_size_cells(n) \ #define node_size_cells(n) \
(((n)->size_cells == -1) ? 1 : (n)->size_cells) (((n)->size_cells == -1) ? 1 : (n)->size_cells)
static void check_reg_format(struct check *c, struct node *dt, static void check_reg_format(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
struct property *prop; struct property *prop;
@ -589,9 +595,9 @@ static void check_reg_format(struct check *c, struct node *dt,
"(#address-cells == %d, #size-cells == %d)", "(#address-cells == %d, #size-cells == %d)",
node->fullpath, prop->val.len, addr_cells, size_cells); node->fullpath, prop->val.len, addr_cells, size_cells);
} }
NODE_WARNING(reg_format, NULL, &addr_size_cells); WARNING(reg_format, check_reg_format, NULL, &addr_size_cells);
static void check_ranges_format(struct check *c, struct node *dt, static void check_ranges_format(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
struct property *prop; struct property *prop;
@ -630,12 +636,12 @@ static void check_ranges_format(struct check *c, struct node *dt,
p_addr_cells, c_addr_cells, c_size_cells); p_addr_cells, c_addr_cells, c_size_cells);
} }
} }
NODE_WARNING(ranges_format, NULL, &addr_size_cells); WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
/* /*
* Style checks * Style checks
*/ */
static void check_avoid_default_addr_size(struct check *c, struct node *dt, static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
struct property *reg, *ranges; struct property *reg, *ranges;
@ -657,14 +663,21 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt,
FAIL(c, "Relying on default #size-cells value for %s", FAIL(c, "Relying on default #size-cells value for %s",
node->fullpath); node->fullpath);
} }
NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells); WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
&addr_size_cells);
static void check_obsolete_chosen_interrupt_controller(struct check *c, static void check_obsolete_chosen_interrupt_controller(struct check *c,
struct node *dt) struct dt_info *dti,
struct node *node)
{ {
struct node *dt = dti->dt;
struct node *chosen; struct node *chosen;
struct property *prop; struct property *prop;
if (node != dt)
return;
chosen = get_node_by_path(dt, "/chosen"); chosen = get_node_by_path(dt, "/chosen");
if (!chosen) if (!chosen)
return; return;
@ -674,7 +687,8 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
FAIL(c, "/chosen has obsolete \"interrupt-controller\" " FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
"property"); "property");
} }
TREE_WARNING(obsolete_chosen_interrupt_controller, NULL); WARNING(obsolete_chosen_interrupt_controller,
check_obsolete_chosen_interrupt_controller, NULL);
static struct check *check_table[] = { static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names, &duplicate_node_names, &duplicate_property_names,
@ -760,9 +774,8 @@ void parse_checks_option(bool warn, bool error, const char *arg)
die("Unrecognized check name \"%s\"\n", name); die("Unrecognized check name \"%s\"\n", name);
} }
void process_checks(bool force, struct boot_info *bi) void process_checks(bool force, struct dt_info *dti)
{ {
struct node *dt = bi->dt;
int i; int i;
int error = 0; int error = 0;
@ -770,7 +783,7 @@ void process_checks(bool force, struct boot_info *bi)
struct check *c = check_table[i]; struct check *c = check_table[i];
if (c->warn || c->error) if (c->warn || c->error)
error = error || run_check(c, dt); error = error || run_check(c, dti);
} }
if (error) { if (error) {

View File

@ -121,6 +121,11 @@ static void lexical_error(const char *fmt, ...);
return DT_V1; return DT_V1;
} }
<*>"/plugin/" {
DPRINT("Keyword: /plugin/\n");
return DT_PLUGIN;
}
<*>"/memreserve/" { <*>"/memreserve/" {
DPRINT("Keyword: /memreserve/\n"); DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT(); BEGIN_DEFAULT();
@ -184,16 +189,16 @@ static void lexical_error(const char *fmt, ...);
if (d.len == 1) { if (d.len == 1) {
lexical_error("Empty character literal"); lexical_error("Empty character literal");
yylval.integer = 0; yylval.integer = 0;
return DT_CHAR_LITERAL; } else {
yylval.integer = (unsigned char)d.val[0];
if (d.len > 2)
lexical_error("Character literal has %d"
" characters instead of 1",
d.len - 1);
} }
yylval.integer = (unsigned char)d.val[0]; data_free(d);
if (d.len > 2)
lexical_error("Character literal has %d"
" characters instead of 1",
d.len - 1);
return DT_CHAR_LITERAL; return DT_CHAR_LITERAL;
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
/* A Bison parser, made by GNU Bison 3.0.2. */ /* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison interface for Yacc-like parsers in C /* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -46,35 +46,36 @@ extern int yydebug;
enum yytokentype enum yytokentype
{ {
DT_V1 = 258, DT_V1 = 258,
DT_MEMRESERVE = 259, DT_PLUGIN = 259,
DT_LSHIFT = 260, DT_MEMRESERVE = 260,
DT_RSHIFT = 261, DT_LSHIFT = 261,
DT_LE = 262, DT_RSHIFT = 262,
DT_GE = 263, DT_LE = 263,
DT_EQ = 264, DT_GE = 264,
DT_NE = 265, DT_EQ = 265,
DT_AND = 266, DT_NE = 266,
DT_OR = 267, DT_AND = 267,
DT_BITS = 268, DT_OR = 268,
DT_DEL_PROP = 269, DT_BITS = 269,
DT_DEL_NODE = 270, DT_DEL_PROP = 270,
DT_PROPNODENAME = 271, DT_DEL_NODE = 271,
DT_LITERAL = 272, DT_PROPNODENAME = 272,
DT_CHAR_LITERAL = 273, DT_LITERAL = 273,
DT_BYTE = 274, DT_CHAR_LITERAL = 274,
DT_STRING = 275, DT_BYTE = 275,
DT_LABEL = 276, DT_STRING = 276,
DT_REF = 277, DT_LABEL = 277,
DT_INCBIN = 278 DT_REF = 278,
DT_INCBIN = 279
}; };
#endif #endif
/* Value type. */ /* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE YYSTYPE;
union YYSTYPE union YYSTYPE
{ {
#line 38 "dtc-parser.y" /* yacc.c:1909 */ #line 39 "dtc-parser.y" /* yacc.c:1909 */
char *propnodename; char *propnodename;
char *labelref; char *labelref;
@ -92,9 +93,12 @@ union YYSTYPE
struct node *nodelist; struct node *nodelist;
struct reserve_info *re; struct reserve_info *re;
uint64_t integer; uint64_t integer;
unsigned int flags;
#line 97 "dtc-parser.tab.h" /* yacc.c:1909 */ #line 99 "dtc-parser.tab.h" /* yacc.c:1909 */
}; };
typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1 # define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_DECLARED 1
#endif #endif

View File

@ -19,6 +19,7 @@
*/ */
%{ %{
#include <stdio.h> #include <stdio.h>
#include <inttypes.h>
#include "dtc.h" #include "dtc.h"
#include "srcpos.h" #include "srcpos.h"
@ -31,7 +32,7 @@ extern void yyerror(char const *s);
treesource_error = true; \ treesource_error = true; \
} while (0) } while (0)
extern struct boot_info *the_boot_info; extern struct dt_info *parser_output;
extern bool treesource_error; extern bool treesource_error;
%} %}
@ -52,9 +53,11 @@ extern bool treesource_error;
struct node *nodelist; struct node *nodelist;
struct reserve_info *re; struct reserve_info *re;
uint64_t integer; uint64_t integer;
unsigned int flags;
} }
%token DT_V1 %token DT_V1
%token DT_PLUGIN
%token DT_MEMRESERVE %token DT_MEMRESERVE
%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
%token DT_BITS %token DT_BITS
@ -71,6 +74,8 @@ extern bool treesource_error;
%type <data> propdata %type <data> propdata
%type <data> propdataprefix %type <data> propdataprefix
%type <flags> header
%type <flags> headers
%type <re> memreserve %type <re> memreserve
%type <re> memreserves %type <re> memreserves
%type <array> arrayprefix %type <array> arrayprefix
@ -101,10 +106,31 @@ extern bool treesource_error;
%% %%
sourcefile: sourcefile:
DT_V1 ';' memreserves devicetree headers memreserves devicetree
{ {
the_boot_info = build_boot_info($3, $4, parser_output = build_dt_info($1, $2, $3,
guess_boot_cpuid($4)); guess_boot_cpuid($3));
}
;
header:
DT_V1 ';'
{
$$ = DTSF_V1;
}
| DT_V1 ';' DT_PLUGIN ';'
{
$$ = DTSF_V1 | DTSF_PLUGIN;
}
;
headers:
header
| header headers
{
if ($2 != $1)
ERROR(&@2, "Header flags don't match earlier ones");
$$ = $1;
} }
; ;

View File

@ -30,7 +30,16 @@ int quiet; /* Level of quietness */
int reservenum; /* Number of memory reservation slots */ int reservenum; /* Number of memory reservation slots */
int minsize; /* Minimum blob size */ int minsize; /* Minimum blob size */
int padsize; /* Additional padding to blob */ int padsize; /* Additional padding to blob */
int alignsize; /* Additional padding to blob accroding to the alignsize */
int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */ int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
int generate_symbols; /* enable symbols & fixup support */
int generate_fixups; /* suppress generation of fixups on symbol support */
int auto_label_aliases; /* auto generate labels -> aliases */
static int is_power_of_2(int x)
{
return (x > 0) && ((x & (x - 1)) == 0);
}
static void fill_fullpaths(struct node *tree, const char *prefix) static void fill_fullpaths(struct node *tree, const char *prefix)
{ {
@ -53,7 +62,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
#define FDT_VERSION(version) _FDT_VERSION(version) #define FDT_VERSION(version) _FDT_VERSION(version)
#define _FDT_VERSION(version) #version #define _FDT_VERSION(version) #version
static const char usage_synopsis[] = "dtc [options] <input file>"; static const char usage_synopsis[] = "dtc [options] <input file>";
static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv"; static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv";
static struct option const usage_long_opts[] = { static struct option const usage_long_opts[] = {
{"quiet", no_argument, NULL, 'q'}, {"quiet", no_argument, NULL, 'q'},
{"in-format", a_argument, NULL, 'I'}, {"in-format", a_argument, NULL, 'I'},
@ -64,6 +73,7 @@ static struct option const usage_long_opts[] = {
{"reserve", a_argument, NULL, 'R'}, {"reserve", a_argument, NULL, 'R'},
{"space", a_argument, NULL, 'S'}, {"space", a_argument, NULL, 'S'},
{"pad", a_argument, NULL, 'p'}, {"pad", a_argument, NULL, 'p'},
{"align", a_argument, NULL, 'a'},
{"boot-cpu", a_argument, NULL, 'b'}, {"boot-cpu", a_argument, NULL, 'b'},
{"force", no_argument, NULL, 'f'}, {"force", no_argument, NULL, 'f'},
{"include", a_argument, NULL, 'i'}, {"include", a_argument, NULL, 'i'},
@ -71,6 +81,8 @@ static struct option const usage_long_opts[] = {
{"phandle", a_argument, NULL, 'H'}, {"phandle", a_argument, NULL, 'H'},
{"warning", a_argument, NULL, 'W'}, {"warning", a_argument, NULL, 'W'},
{"error", a_argument, NULL, 'E'}, {"error", a_argument, NULL, 'E'},
{"symbols", no_argument, NULL, '@'},
{"auto-alias", no_argument, NULL, 'A'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'v'},
{NULL, no_argument, NULL, 0x0}, {NULL, no_argument, NULL, 0x0},
@ -91,6 +103,7 @@ static const char * const usage_opts_help[] = {
"\n\tMake space for <number> reserve map entries (for dtb and asm output)", "\n\tMake space for <number> reserve map entries (for dtb and asm output)",
"\n\tMake the blob at least <bytes> long (extra space)", "\n\tMake the blob at least <bytes> long (extra space)",
"\n\tAdd padding to the blob of <bytes> long (extra space)", "\n\tAdd padding to the blob of <bytes> long (extra space)",
"\n\tMake the blob align to the <bytes> (extra space)",
"\n\tSet the physical boot cpu", "\n\tSet the physical boot cpu",
"\n\tTry to produce output even if the input tree has errors", "\n\tTry to produce output even if the input tree has errors",
"\n\tAdd a path to search for include files", "\n\tAdd a path to search for include files",
@ -101,6 +114,8 @@ static const char * const usage_opts_help[] = {
"\t\tboth - Both \"linux,phandle\" and \"phandle\" properties", "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties",
"\n\tEnable/disable warnings (prefix with \"no-\")", "\n\tEnable/disable warnings (prefix with \"no-\")",
"\n\tEnable/disable errors (prefix with \"no-\")", "\n\tEnable/disable errors (prefix with \"no-\")",
"\n\tEnable generation of symbols",
"\n\tEnable auto-alias of labels",
"\n\tPrint this help and exit", "\n\tPrint this help and exit",
"\n\tPrint version and exit", "\n\tPrint version and exit",
NULL, NULL,
@ -153,7 +168,7 @@ static const char *guess_input_format(const char *fname, const char *fallback)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct boot_info *bi; struct dt_info *dti;
const char *inform = NULL; const char *inform = NULL;
const char *outform = NULL; const char *outform = NULL;
const char *outname = "-"; const char *outname = "-";
@ -169,6 +184,7 @@ int main(int argc, char *argv[])
reservenum = 0; reservenum = 0;
minsize = 0; minsize = 0;
padsize = 0; padsize = 0;
alignsize = 0;
while ((opt = util_getopt_long()) != EOF) { while ((opt = util_getopt_long()) != EOF) {
switch (opt) { switch (opt) {
@ -196,6 +212,12 @@ int main(int argc, char *argv[])
case 'p': case 'p':
padsize = strtol(optarg, NULL, 0); padsize = strtol(optarg, NULL, 0);
break; break;
case 'a':
alignsize = strtol(optarg, NULL, 0);
if (!is_power_of_2(alignsize))
die("Invalid argument \"%d\" to -a option\n",
optarg);
break;
case 'f': case 'f':
force = true; force = true;
break; break;
@ -234,6 +256,13 @@ int main(int argc, char *argv[])
parse_checks_option(false, true, optarg); parse_checks_option(false, true, optarg);
break; break;
case '@':
generate_symbols = 1;
break;
case 'A':
auto_label_aliases = 1;
break;
case 'h': case 'h':
usage(NULL); usage(NULL);
default: default:
@ -272,11 +301,11 @@ int main(int argc, char *argv[])
} }
} }
if (streq(inform, "dts")) if (streq(inform, "dts"))
bi = dt_from_source(arg); dti = dt_from_source(arg);
else if (streq(inform, "fs")) else if (streq(inform, "fs"))
bi = dt_from_fs(arg); dti = dt_from_fs(arg);
else if(streq(inform, "dtb")) else if(streq(inform, "dtb"))
bi = dt_from_blob(arg); dti = dt_from_blob(arg);
else else
die("Unknown input format \"%s\"\n", inform); die("Unknown input format \"%s\"\n", inform);
@ -286,13 +315,29 @@ int main(int argc, char *argv[])
} }
if (cmdline_boot_cpuid != -1) if (cmdline_boot_cpuid != -1)
bi->boot_cpuid_phys = cmdline_boot_cpuid; dti->boot_cpuid_phys = cmdline_boot_cpuid;
fill_fullpaths(bi->dt, ""); fill_fullpaths(dti->dt, "");
process_checks(force, bi); process_checks(force, dti);
/* on a plugin, generate by default */
if (dti->dtsflags & DTSF_PLUGIN) {
generate_fixups = 1;
}
if (auto_label_aliases)
generate_label_tree(dti, "aliases", false);
if (generate_symbols)
generate_label_tree(dti, "__symbols__", true);
if (generate_fixups) {
generate_fixups_tree(dti, "__fixups__");
generate_local_fixups_tree(dti, "__local_fixups__");
}
if (sort) if (sort)
sort_tree(bi); sort_tree(dti);
if (streq(outname, "-")) { if (streq(outname, "-")) {
outf = stdout; outf = stdout;
@ -304,11 +349,11 @@ int main(int argc, char *argv[])
} }
if (streq(outform, "dts")) { if (streq(outform, "dts")) {
dt_to_source(outf, bi); dt_to_source(outf, dti);
} else if (streq(outform, "dtb")) { } else if (streq(outform, "dtb")) {
dt_to_blob(outf, bi, outversion); dt_to_blob(outf, dti, outversion);
} else if (streq(outform, "asm")) { } else if (streq(outform, "asm")) {
dt_to_asm(outf, bi, outversion); dt_to_asm(outf, dti, outversion);
} else if (streq(outform, "null")) { } else if (streq(outform, "null")) {
/* do nothing */ /* do nothing */
} else { } else {

View File

@ -53,7 +53,11 @@ extern int quiet; /* Level of quietness */
extern int reservenum; /* Number of memory reservation slots */ extern int reservenum; /* Number of memory reservation slots */
extern int minsize; /* Minimum blob size */ extern int minsize; /* Minimum blob size */
extern int padsize; /* Additional padding to blob */ extern int padsize; /* Additional padding to blob */
extern int alignsize; /* Additional padding to blob accroding to the alignsize */
extern int phandle_format; /* Use linux,phandle or phandle properties */ extern int phandle_format; /* Use linux,phandle or phandle properties */
extern int generate_symbols; /* generate symbols for nodes with labels */
extern int generate_fixups; /* generate fixups */
extern int auto_label_aliases; /* auto generate labels -> aliases */
#define PHANDLE_LEGACY 0x1 #define PHANDLE_LEGACY 0x1
#define PHANDLE_EPAPR 0x2 #define PHANDLE_EPAPR 0x2
@ -201,6 +205,8 @@ void delete_property(struct property *prop);
void add_child(struct node *parent, struct node *child); void add_child(struct node *parent, struct node *child);
void delete_node_by_name(struct node *parent, char *name); void delete_node_by_name(struct node *parent, char *name);
void delete_node(struct node *node); void delete_node(struct node *node);
void append_to_property(struct node *node,
char *name, const void *data, int len);
const char *get_unitname(struct node *node); const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname); struct property *get_property(struct node *node, const char *propname);
@ -235,35 +241,44 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
struct reserve_info *new); struct reserve_info *new);
struct boot_info { struct dt_info {
unsigned int dtsflags;
struct reserve_info *reservelist; struct reserve_info *reservelist;
struct node *dt; /* the device tree */
uint32_t boot_cpuid_phys; uint32_t boot_cpuid_phys;
struct node *dt; /* the device tree */
}; };
struct boot_info *build_boot_info(struct reserve_info *reservelist, /* DTS version flags definitions */
struct node *tree, uint32_t boot_cpuid_phys); #define DTSF_V1 0x0001 /* /dts-v1/ */
void sort_tree(struct boot_info *bi); #define DTSF_PLUGIN 0x0002 /* /plugin/ */
struct dt_info *build_dt_info(unsigned int dtsflags,
struct reserve_info *reservelist,
struct node *tree, uint32_t boot_cpuid_phys);
void sort_tree(struct dt_info *dti);
void generate_label_tree(struct dt_info *dti, char *name, bool allocph);
void generate_fixups_tree(struct dt_info *dti, char *name);
void generate_local_fixups_tree(struct dt_info *dti, char *name);
/* Checks */ /* Checks */
void parse_checks_option(bool warn, bool error, const char *arg); void parse_checks_option(bool warn, bool error, const char *arg);
void process_checks(bool force, struct boot_info *bi); void process_checks(bool force, struct dt_info *dti);
/* Flattened trees */ /* Flattened trees */
void dt_to_blob(FILE *f, struct boot_info *bi, int version); void dt_to_blob(FILE *f, struct dt_info *dti, int version);
void dt_to_asm(FILE *f, struct boot_info *bi, int version); void dt_to_asm(FILE *f, struct dt_info *dti, int version);
struct boot_info *dt_from_blob(const char *fname); struct dt_info *dt_from_blob(const char *fname);
/* Tree source */ /* Tree source */
void dt_to_source(FILE *f, struct boot_info *bi); void dt_to_source(FILE *f, struct dt_info *dti);
struct boot_info *dt_from_source(const char *f); struct dt_info *dt_from_source(const char *f);
/* FS trees */ /* FS trees */
struct boot_info *dt_from_fs(const char *dirname); struct dt_info *dt_from_fs(const char *dirname);
#endif /* _DTC_H */ #endif /* _DTC_H */

View File

@ -366,7 +366,7 @@ static void make_fdt_header(struct fdt_header *fdt,
fdt->size_dt_struct = cpu_to_fdt32(dtsize); fdt->size_dt_struct = cpu_to_fdt32(dtsize);
} }
void dt_to_blob(FILE *f, struct boot_info *bi, int version) void dt_to_blob(FILE *f, struct dt_info *dti, int version)
{ {
struct version_info *vi = NULL; struct version_info *vi = NULL;
int i; int i;
@ -384,29 +384,36 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version)
if (!vi) if (!vi)
die("Unknown device tree blob version %d\n", version); die("Unknown device tree blob version %d\n", version);
flatten_tree(bi->dt, &bin_emitter, &dtbuf, &strbuf, vi); flatten_tree(dti->dt, &bin_emitter, &dtbuf, &strbuf, vi);
bin_emit_cell(&dtbuf, FDT_END); bin_emit_cell(&dtbuf, FDT_END);
reservebuf = flatten_reserve_list(bi->reservelist, vi); reservebuf = flatten_reserve_list(dti->reservelist, vi);
/* Make header */ /* Make header */
make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len, make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
bi->boot_cpuid_phys); dti->boot_cpuid_phys);
/* /*
* If the user asked for more space than is used, adjust the totalsize. * If the user asked for more space than is used, adjust the totalsize.
*/ */
if (minsize > 0) { if (minsize > 0) {
padlen = minsize - fdt32_to_cpu(fdt.totalsize); padlen = minsize - fdt32_to_cpu(fdt.totalsize);
if ((padlen < 0) && (quiet < 1)) if (padlen < 0) {
fprintf(stderr, padlen = 0;
"Warning: blob size %d >= minimum size %d\n", if (quiet < 1)
fdt32_to_cpu(fdt.totalsize), minsize); fprintf(stderr,
"Warning: blob size %d >= minimum size %d\n",
fdt32_to_cpu(fdt.totalsize), minsize);
}
} }
if (padsize > 0) if (padsize > 0)
padlen = padsize; padlen = padsize;
if (alignsize > 0)
padlen = ALIGN(fdt32_to_cpu(fdt.totalsize) + padlen, alignsize)
- fdt32_to_cpu(fdt.totalsize);
if (padlen > 0) { if (padlen > 0) {
int tsize = fdt32_to_cpu(fdt.totalsize); int tsize = fdt32_to_cpu(fdt.totalsize);
tsize += padlen; tsize += padlen;
@ -460,7 +467,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
} }
} }
void dt_to_asm(FILE *f, struct boot_info *bi, int version) void dt_to_asm(FILE *f, struct dt_info *dti, int version)
{ {
struct version_info *vi = NULL; struct version_info *vi = NULL;
int i; int i;
@ -500,7 +507,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
if (vi->flags & FTF_BOOTCPUID) { if (vi->flags & FTF_BOOTCPUID) {
fprintf(f, "\t/* boot_cpuid_phys */\n"); fprintf(f, "\t/* boot_cpuid_phys */\n");
asm_emit_cell(f, bi->boot_cpuid_phys); asm_emit_cell(f, dti->boot_cpuid_phys);
} }
if (vi->flags & FTF_STRTABSIZE) { if (vi->flags & FTF_STRTABSIZE) {
@ -530,7 +537,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
* Use .long on high and low halfs of u64s to avoid .quad * Use .long on high and low halfs of u64s to avoid .quad
* as it appears .quad isn't available in some assemblers. * as it appears .quad isn't available in some assemblers.
*/ */
for (re = bi->reservelist; re; re = re->next) { for (re = dti->reservelist; re; re = re->next) {
struct label *l; struct label *l;
for_each_label(re->labels, l) { for_each_label(re->labels, l) {
@ -550,7 +557,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
emit_label(f, symprefix, "struct_start"); emit_label(f, symprefix, "struct_start");
flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi); flatten_tree(dti->dt, &asm_emitter, f, &strbuf, vi);
fprintf(f, "\t/* FDT_END */\n"); fprintf(f, "\t/* FDT_END */\n");
asm_emit_cell(f, FDT_END); asm_emit_cell(f, FDT_END);
@ -572,6 +579,8 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
if (padsize > 0) { if (padsize > 0) {
fprintf(f, "\t.space\t%d, 0\n", padsize); fprintf(f, "\t.space\t%d, 0\n", padsize);
} }
if (alignsize > 0)
asm_emit_align(f, alignsize);
emit_label(f, symprefix, "blob_abs_end"); emit_label(f, symprefix, "blob_abs_end");
data_free(strbuf); data_free(strbuf);
@ -797,11 +806,15 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
} }
} while (val != FDT_END_NODE); } while (val != FDT_END_NODE);
if (node->name != flatname) {
free(flatname);
}
return node; return node;
} }
struct boot_info *dt_from_blob(const char *fname) struct dt_info *dt_from_blob(const char *fname)
{ {
FILE *f; FILE *f;
uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys; uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
@ -929,5 +942,5 @@ struct boot_info *dt_from_blob(const char *fname)
fclose(f); fclose(f);
return build_boot_info(reservelist, tree, boot_cpuid_phys); return build_dt_info(DTSF_V1, reservelist, tree, boot_cpuid_phys);
} }

View File

@ -79,13 +79,12 @@ static struct node *read_fstree(const char *dirname)
return tree; return tree;
} }
struct boot_info *dt_from_fs(const char *dirname) struct dt_info *dt_from_fs(const char *dirname)
{ {
struct node *tree; struct node *tree;
tree = read_fstree(dirname); tree = read_fstree(dirname);
tree = name_node(tree, ""); tree = name_node(tree, "");
return build_boot_info(NULL, tree, guess_boot_cpuid(tree)); return build_dt_info(DTSF_V1, NULL, tree, guess_boot_cpuid(tree));
} }

View File

@ -7,5 +7,5 @@ LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
LIBFDT_VERSION = version.lds LIBFDT_VERSION = version.lds
LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \ LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \
fdt_addresses.c fdt_addresses.c fdt_overlay.c
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)

View File

@ -88,6 +88,32 @@ static int _fdt_string_eq(const void *fdt, int stroffset,
return (strlen(p) == len) && (memcmp(p, s, len) == 0); return (strlen(p) == len) && (memcmp(p, s, len) == 0);
} }
uint32_t fdt_get_max_phandle(const void *fdt)
{
uint32_t max_phandle = 0;
int offset;
for (offset = fdt_next_node(fdt, -1, NULL);;
offset = fdt_next_node(fdt, offset, NULL)) {
uint32_t phandle;
if (offset == -FDT_ERR_NOTFOUND)
return max_phandle;
if (offset < 0)
return (uint32_t)-1;
phandle = fdt_get_phandle(fdt, offset);
if (phandle == (uint32_t)-1)
continue;
if (phandle > max_phandle)
max_phandle = phandle;
}
return 0;
}
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{ {
FDT_CHECK_HEADER(fdt); FDT_CHECK_HEADER(fdt);
@ -545,7 +571,7 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
list = fdt_getprop(fdt, nodeoffset, property, &length); list = fdt_getprop(fdt, nodeoffset, property, &length);
if (!list) if (!list)
return -length; return length;
end = list + length; end = list + length;
@ -571,7 +597,7 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
list = fdt_getprop(fdt, nodeoffset, property, &length); list = fdt_getprop(fdt, nodeoffset, property, &length);
if (!list) if (!list)
return -length; return length;
len = strlen(string) + 1; len = strlen(string) + 1;
end = list + length; end = list + length;

View File

@ -191,17 +191,13 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
int fdt_del_mem_rsv(void *fdt, int n) int fdt_del_mem_rsv(void *fdt, int n)
{ {
struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
int err;
FDT_RW_CHECK_HEADER(fdt); FDT_RW_CHECK_HEADER(fdt);
if (n >= fdt_num_mem_rsv(fdt)) if (n >= fdt_num_mem_rsv(fdt))
return -FDT_ERR_NOTFOUND; return -FDT_ERR_NOTFOUND;
err = _fdt_splice_mem_rsv(fdt, re, 1, 0); return _fdt_splice_mem_rsv(fdt, re, 1, 0);
if (err)
return err;
return 0;
} }
static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,

View File

@ -69,6 +69,7 @@ static struct fdt_errtabent fdt_errtable[] = {
FDT_ERRTABENT(FDT_ERR_BADOFFSET), FDT_ERRTABENT(FDT_ERR_BADOFFSET),
FDT_ERRTABENT(FDT_ERR_BADPATH), FDT_ERRTABENT(FDT_ERR_BADPATH),
FDT_ERRTABENT(FDT_ERR_BADPHANDLE),
FDT_ERRTABENT(FDT_ERR_BADSTATE), FDT_ERRTABENT(FDT_ERR_BADSTATE),
FDT_ERRTABENT(FDT_ERR_TRUNCATED), FDT_ERRTABENT(FDT_ERR_TRUNCATED),
@ -76,6 +77,11 @@ static struct fdt_errtabent fdt_errtable[] = {
FDT_ERRTABENT(FDT_ERR_BADVERSION), FDT_ERRTABENT(FDT_ERR_BADVERSION),
FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
FDT_ERRTABENT(FDT_ERR_BADLAYOUT), FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
FDT_ERRTABENT(FDT_ERR_INTERNAL),
FDT_ERRTABENT(FDT_ERR_BADNCELLS),
FDT_ERRTABENT(FDT_ERR_BADVALUE),
FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
}; };
#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) #define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))

View File

@ -55,21 +55,42 @@
#include "libfdt_internal.h" #include "libfdt_internal.h"
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
const void *val, int len) const char *name, int namelen,
uint32_t idx, const void *val,
int len)
{ {
void *propval; void *propval;
int proplen; int proplen;
propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen); propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen,
&proplen);
if (!propval)
return proplen;
if (proplen < (len + idx))
return -FDT_ERR_NOSPACE;
memcpy((char *)propval + idx, val, len);
return 0;
}
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
const void *val, int len)
{
const void *propval;
int proplen;
propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
if (! propval) if (! propval)
return proplen; return proplen;
if (proplen != len) if (proplen != len)
return -FDT_ERR_NOSPACE; return -FDT_ERR_NOSPACE;
memcpy(propval, val, len); return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name,
return 0; strlen(name), 0,
val, len);
} }
static void _fdt_nop_region(void *start, int len) static void _fdt_nop_region(void *start, int len)

View File

@ -61,7 +61,7 @@
#define FDT_ERR_NOTFOUND 1 #define FDT_ERR_NOTFOUND 1
/* FDT_ERR_NOTFOUND: The requested node or property does not exist */ /* FDT_ERR_NOTFOUND: The requested node or property does not exist */
#define FDT_ERR_EXISTS 2 #define FDT_ERR_EXISTS 2
/* FDT_ERR_EXISTS: Attemped to create a node or property which /* FDT_ERR_EXISTS: Attempted to create a node or property which
* already exists */ * already exists */
#define FDT_ERR_NOSPACE 3 #define FDT_ERR_NOSPACE 3
/* FDT_ERR_NOSPACE: Operation needed to expand the device /* FDT_ERR_NOSPACE: Operation needed to expand the device
@ -79,8 +79,10 @@
* (e.g. missing a leading / for a function which requires an * (e.g. missing a leading / for a function which requires an
* absolute path) */ * absolute path) */
#define FDT_ERR_BADPHANDLE 6 #define FDT_ERR_BADPHANDLE 6
/* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle.
* value. phandle values of 0 and -1 are not permitted. */ * This can be caused either by an invalid phandle property
* length, or the phandle value was either 0 or -1, which are
* not permitted. */
#define FDT_ERR_BADSTATE 7 #define FDT_ERR_BADSTATE 7
/* FDT_ERR_BADSTATE: Function was passed an incomplete device /* FDT_ERR_BADSTATE: Function was passed an incomplete device
* tree created by the sequential-write functions, which is * tree created by the sequential-write functions, which is
@ -126,7 +128,16 @@
* value. For example: a property expected to contain a string list * value. For example: a property expected to contain a string list
* is not NUL-terminated within the length of its value. */ * is not NUL-terminated within the length of its value. */
#define FDT_ERR_MAX 15 #define FDT_ERR_BADOVERLAY 16
/* FDT_ERR_BADOVERLAY: The device tree overlay, while
* correctly structured, cannot be applied due to some
* unexpected or missing value, property or node. */
#define FDT_ERR_NOPHANDLES 17
/* FDT_ERR_NOPHANDLES: The device tree doesn't have any
* phandle available anymore without causing an overflow */
#define FDT_ERR_MAX 17
/**********************************************************************/ /**********************************************************************/
/* Low-level functions (you probably don't need these) */ /* Low-level functions (you probably don't need these) */
@ -168,27 +179,55 @@ int fdt_first_subnode(const void *fdt, int offset);
*/ */
int fdt_next_subnode(const void *fdt, int offset); int fdt_next_subnode(const void *fdt, int offset);
/**
* fdt_for_each_subnode - iterate over all subnodes of a parent
*
* @node: child node (int, lvalue)
* @fdt: FDT blob (const void *)
* @parent: parent node (int)
*
* This is actually a wrapper around a for loop and would be used like so:
*
* fdt_for_each_subnode(node, fdt, parent) {
* Use node
* ...
* }
*
* if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) {
* Error handling
* }
*
* 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); \
node >= 0; \
node = fdt_next_subnode(fdt, node))
/**********************************************************************/ /**********************************************************************/
/* General functions */ /* General functions */
/**********************************************************************/ /**********************************************************************/
#define fdt_get_header(fdt, field) \ #define fdt_get_header(fdt, field) \
(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) #define fdt_magic(fdt) (fdt_get_header(fdt, magic))
#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) #define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) #define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) #define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings))
#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) #define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))
#define fdt_version(fdt) (fdt_get_header(fdt, version)) #define fdt_version(fdt) (fdt_get_header(fdt, version))
#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) #define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))
#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) #define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) #define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) #define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
#define __fdt_set_hdr(name) \ #define __fdt_set_hdr(name) \
static inline void fdt_set_##name(void *fdt, uint32_t val) \ static inline void fdt_set_##name(void *fdt, uint32_t val) \
{ \ { \
struct fdt_header *fdth = (struct fdt_header*)fdt; \ struct fdt_header *fdth = (struct fdt_header *)fdt; \
fdth->name = cpu_to_fdt32(val); \ fdth->name = cpu_to_fdt32(val); \
} }
__fdt_set_hdr(magic); __fdt_set_hdr(magic);
@ -258,6 +297,21 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
*/ */
const char *fdt_string(const void *fdt, int stroffset); const char *fdt_string(const void *fdt, int stroffset);
/**
* fdt_get_max_phandle - retrieves the highest phandle in a tree
* @fdt: pointer to the device tree blob
*
* fdt_get_max_phandle retrieves the highest phandle in the given
* device tree. This will ignore badly formatted phandles, or phandles
* with a value of 0 or -1.
*
* returns:
* the highest phandle on success
* 0, if no phandle was found in the device tree
* -1, if an error occurred
*/
uint32_t fdt_get_max_phandle(const void *fdt);
/** /**
* fdt_num_mem_rsv - retrieve the number of memory reserve map entries * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
* @fdt: pointer to the device tree blob * @fdt: pointer to the device tree blob
@ -318,8 +372,9 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
* returns: * returns:
* structure block offset of the requested subnode (>=0), on success * structure block offset of the requested subnode (>=0), on success
* -FDT_ERR_NOTFOUND, if the requested subnode does not exist * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
* -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
* -FDT_ERR_BADMAGIC, * tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION, * -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADSTRUCTURE,
@ -351,7 +406,8 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
* address). * address).
* *
* returns: * returns:
* structure block offset of the node with the requested path (>=0), on success * structure block offset of the node with the requested path (>=0), on
* success
* -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
* -FDT_ERR_NOTFOUND, if the requested node does not exist * -FDT_ERR_NOTFOUND, if the requested node does not exist
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
@ -375,10 +431,12 @@ int fdt_path_offset(const void *fdt, const char *path);
* *
* returns: * returns:
* pointer to the node's name, on success * pointer to the node's name, on success
* If lenp is non-NULL, *lenp contains the length of that name (>=0) * If lenp is non-NULL, *lenp contains the length of that name
* (>=0)
* NULL, on error * NULL, on error
* if lenp is non-NULL *lenp contains an error code (<0): * if lenp is non-NULL *lenp contains an error code (<0):
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
* tag
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION, * -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, standard meanings * -FDT_ERR_BADSTATE, standard meanings
@ -426,6 +484,33 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset);
*/ */
int fdt_next_property_offset(const void *fdt, int offset); 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)
*
* This is actually a wrapper around a for loop and would be used like so:
*
* fdt_for_each_property_offset(property, fdt, node) {
* Use property
* ...
* }
*
* if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) {
* Error handling
* }
*
* Note that this is implemented as a macro and property is used as
* iterator in the loop. The node variable can be constant or even a
* literal.
*/
#define fdt_for_each_property_offset(property, fdt, node) \
for (property = fdt_first_property_offset(fdt, node); \
property >= 0; \
property = fdt_next_property_offset(fdt, property))
/** /**
* fdt_get_property_by_offset - retrieve the property at a given offset * fdt_get_property_by_offset - retrieve the property at a given offset
* @fdt: pointer to the device tree blob * @fdt: pointer to the device tree blob
@ -490,7 +575,8 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
* NULL, on error * NULL, on error
* if lenp is non-NULL, *lenp contains an error code (<0): * if lenp is non-NULL, *lenp contains an error code (<0):
* -FDT_ERR_NOTFOUND, node does not have named property * -FDT_ERR_NOTFOUND, node does not have named property
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
* tag
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION, * -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTATE,
@ -554,6 +640,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
*/ */
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
const char *name, int namelen, int *lenp); const char *name, int namelen, int *lenp);
static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
const char *name, int namelen,
int *lenp)
{
return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
namelen, lenp);
}
/** /**
* fdt_getprop - retrieve the value of a given property * fdt_getprop - retrieve the value of a given property
@ -575,7 +668,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
* NULL, on error * NULL, on error
* if lenp is non-NULL, *lenp contains an error code (<0): * if lenp is non-NULL, *lenp contains an error code (<0):
* -FDT_ERR_NOTFOUND, node does not have named property * -FDT_ERR_NOTFOUND, node does not have named property
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
* tag
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION, * -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTATE,
@ -617,7 +711,7 @@ const char *fdt_get_alias_namelen(const void *fdt,
const char *name, int namelen); const char *name, int namelen);
/** /**
* fdt_get_alias - retreive the path referenced by a given alias * fdt_get_alias - retrieve the path referenced by a given alias
* @fdt: pointer to the device tree blob * @fdt: pointer to the device tree blob
* @name: name of the alias th look up * @name: name of the alias th look up
* *
@ -647,7 +741,7 @@ const char *fdt_get_alias(const void *fdt, const char *name);
* 0, on success * 0, on success
* buf contains the absolute path of the node at * buf contains the absolute path of the node at
* nodeoffset, as a NUL-terminated string. * nodeoffset, as a NUL-terminated string.
* -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
* characters and will not fit in the given buffer. * characters and will not fit in the given buffer.
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
@ -677,11 +771,11 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
* structure from the start to nodeoffset. * structure from the start to nodeoffset.
* *
* returns: * returns:
* structure block offset of the node at node offset's ancestor * structure block offset of the node at node offset's ancestor
* of depth supernodedepth (>=0), on success * of depth supernodedepth (>=0), on success
* -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of
* nodeoffset
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION, * -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTATE,
@ -703,7 +797,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
* *
* returns: * returns:
* depth of the node at nodeoffset (>=0), on success * depth of the node at nodeoffset (>=0), on success
* -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION, * -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTATE,
@ -726,7 +820,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset);
* returns: * returns:
* structure block offset of the parent of the node at nodeoffset * structure block offset of the parent of the node at nodeoffset
* (>=0), on success * (>=0), on success
* -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION, * -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTATE,
@ -766,7 +860,7 @@ int fdt_parent_offset(const void *fdt, int nodeoffset);
* on success * on success
* -FDT_ERR_NOTFOUND, no node matching the criterion exists in the * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
* tree after startoffset * tree after startoffset
* -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION, * -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTATE,
@ -813,7 +907,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
* 1, if the node has a 'compatible' property, but it does not list * 1, if the node has a 'compatible' property, but it does not list
* the given string * the given string
* -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
* -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION, * -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTATE,
@ -850,7 +944,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
* on success * on success
* -FDT_ERR_NOTFOUND, no node matching the criterion exists in the * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
* tree after startoffset * tree after startoffset
* -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION, * -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTATE,
@ -960,7 +1054,8 @@ const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
* returns: * returns:
* 0 <= n < FDT_MAX_NCELLS, on success * 0 <= n < FDT_MAX_NCELLS, on success
* 2, if the node has no #address-cells property * 2, if the node has no #address-cells property
* -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid #address-cells property * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
* #address-cells property
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION, * -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTATE,
@ -980,7 +1075,8 @@ int fdt_address_cells(const void *fdt, int nodeoffset);
* returns: * returns:
* 0 <= n < FDT_MAX_NCELLS, on success * 0 <= n < FDT_MAX_NCELLS, on success
* 2, if the node has no #address-cells property * 2, if the node has no #address-cells property
* -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid #size-cells property * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
* #size-cells property
* -FDT_ERR_BADMAGIC, * -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION, * -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE, * -FDT_ERR_BADSTATE,
@ -994,6 +1090,27 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
/* Write-in-place functions */ /* Write-in-place functions */
/**********************************************************************/ /**********************************************************************/
/**
* fdt_setprop_inplace_namelen_partial - change a property's value,
* but not its size
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
* @namelen: number of characters of name to consider
* @idx: index of the property to change in the array
* @val: pointer to data to replace the property value with
* @len: length of the property value
*
* Identical to fdt_setprop_inplace(), but modifies the given property
* 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.
*/
int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
const char *name, int namelen,
uint32_t idx, const void *val,
int len);
/** /**
* fdt_setprop_inplace - change a property's value, but not its size * fdt_setprop_inplace - change a property's value, but not its size
* @fdt: pointer to the device tree blob * @fdt: pointer to the device tree blob
@ -1604,9 +1721,11 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
* change the offsets of some existing nodes. * change the offsets of some existing nodes.
* returns: * returns:
* structure block offset of the created nodeequested subnode (>=0), on success * structure block offset of the created nodeequested subnode (>=0), on
* success
* -FDT_ERR_NOTFOUND, if the requested subnode does not exist * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
* -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
* tag
* -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
* the given name * the given name
* -FDT_ERR_NOSPACE, if there is insufficient free space in the * -FDT_ERR_NOSPACE, if there is insufficient free space in the
@ -1644,6 +1763,37 @@ int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
*/ */
int fdt_del_node(void *fdt, int nodeoffset); int fdt_del_node(void *fdt, int nodeoffset);
/**
* fdt_overlay_apply - Applies a DT overlay on a base DT
* @fdt: pointer to the base device tree blob
* @fdto: pointer to the device tree overlay blob
*
* fdt_overlay_apply() will apply the given device tree overlay on the
* given base device tree.
*
* Expect the base device tree to be modified, even if the function
* returns an error.
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, there's not enough space in the base device tree
* -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
* properties in the base DT
* -FDT_ERR_BADPHANDLE,
* -FDT_ERR_BADOVERLAY,
* -FDT_ERR_NOPHANDLES,
* -FDT_ERR_INTERNAL,
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADOFFSET,
* -FDT_ERR_BADPATH,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_TRUNCATED, standard meanings
*/
int fdt_overlay_apply(void *fdt, void *fdto);
/**********************************************************************/ /**********************************************************************/
/* Debugging / informational functions */ /* Debugging / informational functions */
/**********************************************************************/ /**********************************************************************/

View File

@ -54,6 +54,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#ifdef __CHECKER__ #ifdef __CHECKER__

View File

@ -204,7 +204,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
} }
} }
/* if no collision occured, add child to the old node. */ /* if no collision occurred, add child to the old node. */
if (new_child) if (new_child)
add_child(old_node, new_child); add_child(old_node, new_child);
} }
@ -296,6 +296,23 @@ void delete_node(struct node *node)
delete_labels(&node->labels); delete_labels(&node->labels);
} }
void append_to_property(struct node *node,
char *name, const void *data, int len)
{
struct data d;
struct property *p;
p = get_property(node, name);
if (p) {
d = data_append_data(p->val, data, len);
p->val = d;
} else {
d = data_append_data(empty_data, data, len);
p = build_property(name, d);
add_property(node, p);
}
}
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
{ {
struct reserve_info *new = xmalloc(sizeof(*new)); struct reserve_info *new = xmalloc(sizeof(*new));
@ -335,17 +352,19 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
return list; return list;
} }
struct boot_info *build_boot_info(struct reserve_info *reservelist, struct dt_info *build_dt_info(unsigned int dtsflags,
struct node *tree, uint32_t boot_cpuid_phys) struct reserve_info *reservelist,
struct node *tree, uint32_t boot_cpuid_phys)
{ {
struct boot_info *bi; struct dt_info *dti;
bi = xmalloc(sizeof(*bi)); dti = xmalloc(sizeof(*dti));
bi->reservelist = reservelist; dti->dtsflags = dtsflags;
bi->dt = tree; dti->reservelist = reservelist;
bi->boot_cpuid_phys = boot_cpuid_phys; dti->dt = tree;
dti->boot_cpuid_phys = boot_cpuid_phys;
return bi; return dti;
} }
/* /*
@ -592,12 +611,12 @@ static int cmp_reserve_info(const void *ax, const void *bx)
return 0; return 0;
} }
static void sort_reserve_entries(struct boot_info *bi) static void sort_reserve_entries(struct dt_info *dti)
{ {
struct reserve_info *ri, **tbl; struct reserve_info *ri, **tbl;
int n = 0, i = 0; int n = 0, i = 0;
for (ri = bi->reservelist; for (ri = dti->reservelist;
ri; ri;
ri = ri->next) ri = ri->next)
n++; n++;
@ -607,14 +626,14 @@ static void sort_reserve_entries(struct boot_info *bi)
tbl = xmalloc(n * sizeof(*tbl)); tbl = xmalloc(n * sizeof(*tbl));
for (ri = bi->reservelist; for (ri = dti->reservelist;
ri; ri;
ri = ri->next) ri = ri->next)
tbl[i++] = ri; tbl[i++] = ri;
qsort(tbl, n, sizeof(*tbl), cmp_reserve_info); qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
bi->reservelist = tbl[0]; dti->reservelist = tbl[0];
for (i = 0; i < (n-1); i++) for (i = 0; i < (n-1); i++)
tbl[i]->next = tbl[i+1]; tbl[i]->next = tbl[i+1];
tbl[n-1]->next = NULL; tbl[n-1]->next = NULL;
@ -704,8 +723,256 @@ static void sort_node(struct node *node)
sort_node(c); sort_node(c);
} }
void sort_tree(struct boot_info *bi) void sort_tree(struct dt_info *dti)
{ {
sort_reserve_entries(bi); sort_reserve_entries(dti);
sort_node(bi->dt); sort_node(dti->dt);
}
/* utility helper to avoid code duplication */
static struct node *build_and_name_child_node(struct node *parent, char *name)
{
struct node *node;
node = build_node(NULL, NULL);
name_node(node, xstrdup(name));
add_child(parent, node);
return node;
}
static struct node *build_root_node(struct node *dt, char *name)
{
struct node *an;
an = get_subnode(dt, name);
if (!an)
an = build_and_name_child_node(dt, name);
if (!an)
die("Could not build root node /%s\n", name);
return an;
}
static bool any_label_tree(struct dt_info *dti, struct node *node)
{
struct node *c;
if (node->labels)
return true;
for_each_child(node, c)
if (any_label_tree(dti, c))
return true;
return false;
}
static void generate_label_tree_internal(struct dt_info *dti,
struct node *an, struct node *node,
bool allocph)
{
struct node *dt = dti->dt;
struct node *c;
struct property *p;
struct label *l;
/* if there are labels */
if (node->labels) {
/* now add the label in the node */
for_each_label(node->labels, l) {
/* check whether the label already exists */
p = get_property(an, l->label);
if (p) {
fprintf(stderr, "WARNING: label %s already"
" exists in /%s", l->label,
an->name);
continue;
}
/* insert it */
p = build_property(l->label,
data_copy_mem(node->fullpath,
strlen(node->fullpath) + 1));
add_property(an, p);
}
/* force allocation of a phandle for this node */
if (allocph)
(void)get_node_phandle(dt, node);
}
for_each_child(node, c)
generate_label_tree_internal(dti, an, c, allocph);
}
static bool any_fixup_tree(struct dt_info *dti, struct node *node)
{
struct node *c;
struct property *prop;
struct marker *m;
for_each_property(node, prop) {
m = prop->val.markers;
for_each_marker_of_type(m, REF_PHANDLE) {
if (!get_node_by_ref(dti->dt, m->ref))
return true;
}
}
for_each_child(node, c) {
if (any_fixup_tree(dti, c))
return true;
}
return false;
}
static void add_fixup_entry(struct dt_info *dti, struct node *fn,
struct node *node, struct property *prop,
struct marker *m)
{
char *entry;
/* m->ref can only be a REF_PHANDLE, but check anyway */
assert(m->type == REF_PHANDLE);
/* there shouldn't be any ':' in the arguments */
if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
die("arguments should not contain ':'\n");
xasprintf(&entry, "%s:%s:%u",
node->fullpath, prop->name, m->offset);
append_to_property(fn, m->ref, entry, strlen(entry) + 1);
}
static void generate_fixups_tree_internal(struct dt_info *dti,
struct node *fn,
struct node *node)
{
struct node *dt = dti->dt;
struct node *c;
struct property *prop;
struct marker *m;
struct node *refnode;
for_each_property(node, prop) {
m = prop->val.markers;
for_each_marker_of_type(m, REF_PHANDLE) {
refnode = get_node_by_ref(dt, m->ref);
if (!refnode)
add_fixup_entry(dti, fn, node, prop, m);
}
}
for_each_child(node, c)
generate_fixups_tree_internal(dti, fn, c);
}
static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
{
struct node *c;
struct property *prop;
struct marker *m;
for_each_property(node, prop) {
m = prop->val.markers;
for_each_marker_of_type(m, REF_PHANDLE) {
if (get_node_by_ref(dti->dt, m->ref))
return true;
}
}
for_each_child(node, c) {
if (any_local_fixup_tree(dti, c))
return true;
}
return false;
}
static void add_local_fixup_entry(struct dt_info *dti,
struct node *lfn, struct node *node,
struct property *prop, struct marker *m,
struct node *refnode)
{
struct node *wn, *nwn; /* local fixup node, walk node, new */
uint32_t value_32;
char **compp;
int i, depth;
/* walk back retreiving depth */
depth = 0;
for (wn = node; wn; wn = wn->parent)
depth++;
/* allocate name array */
compp = xmalloc(sizeof(*compp) * depth);
/* store names in the array */
for (wn = node, i = depth - 1; wn; wn = wn->parent, i--)
compp[i] = wn->name;
/* walk the path components creating nodes if they don't exist */
for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
/* if no node exists, create it */
nwn = get_subnode(wn, compp[i]);
if (!nwn)
nwn = build_and_name_child_node(wn, compp[i]);
}
free(compp);
value_32 = cpu_to_fdt32(m->offset);
append_to_property(wn, prop->name, &value_32, sizeof(value_32));
}
static void generate_local_fixups_tree_internal(struct dt_info *dti,
struct node *lfn,
struct node *node)
{
struct node *dt = dti->dt;
struct node *c;
struct property *prop;
struct marker *m;
struct node *refnode;
for_each_property(node, prop) {
m = prop->val.markers;
for_each_marker_of_type(m, REF_PHANDLE) {
refnode = get_node_by_ref(dt, m->ref);
if (refnode)
add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
}
}
for_each_child(node, c)
generate_local_fixups_tree_internal(dti, lfn, c);
}
void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
{
if (!any_label_tree(dti, dti->dt))
return;
generate_label_tree_internal(dti, build_root_node(dti->dt, name),
dti->dt, allocph);
}
void generate_fixups_tree(struct dt_info *dti, char *name)
{
if (!any_fixup_tree(dti, dti->dt))
return;
generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
dti->dt);
}
void generate_local_fixups_tree(struct dt_info *dti, char *name)
{
if (!any_local_fixup_tree(dti, dti->dt))
return;
generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
dti->dt);
} }

View File

@ -246,46 +246,27 @@ srcpos_copy(struct srcpos *pos)
return pos_new; return pos_new;
} }
void
srcpos_dump(struct srcpos *pos)
{
printf("file : \"%s\"\n",
pos->file ? (char *) pos->file : "<no file>");
printf("first_line : %d\n", pos->first_line);
printf("first_column: %d\n", pos->first_column);
printf("last_line : %d\n", pos->last_line);
printf("last_column : %d\n", pos->last_column);
printf("file : %s\n", pos->file->name);
}
char * char *
srcpos_string(struct srcpos *pos) srcpos_string(struct srcpos *pos)
{ {
const char *fname = "<no-file>"; const char *fname = "<no-file>";
char *pos_str; char *pos_str;
int rc;
if (pos) if (pos)
fname = pos->file->name; fname = pos->file->name;
if (pos->first_line != pos->last_line) if (pos->first_line != pos->last_line)
rc = asprintf(&pos_str, "%s:%d.%d-%d.%d", fname, xasprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
pos->first_line, pos->first_column, pos->first_line, pos->first_column,
pos->last_line, pos->last_column); pos->last_line, pos->last_column);
else if (pos->first_column != pos->last_column) else if (pos->first_column != pos->last_column)
rc = asprintf(&pos_str, "%s:%d.%d-%d", fname, xasprintf(&pos_str, "%s:%d.%d-%d", fname,
pos->first_line, pos->first_column, pos->first_line, pos->first_column,
pos->last_column); pos->last_column);
else else
rc = asprintf(&pos_str, "%s:%d.%d", fname, xasprintf(&pos_str, "%s:%d.%d", fname,
pos->first_line, pos->first_column); pos->first_line, pos->first_column);
if (rc == -1)
die("Couldn't allocate in srcpos string");
return pos_str; return pos_str;
} }

View File

@ -105,7 +105,6 @@ extern struct srcpos srcpos_empty;
extern void srcpos_update(struct srcpos *pos, const char *text, int len); extern void srcpos_update(struct srcpos *pos, const char *text, int len);
extern struct srcpos *srcpos_copy(struct srcpos *pos); extern struct srcpos *srcpos_copy(struct srcpos *pos);
extern char *srcpos_string(struct srcpos *pos); extern char *srcpos_string(struct srcpos *pos);
extern void srcpos_dump(struct srcpos *pos);
extern void srcpos_verror(struct srcpos *pos, const char *prefix, extern void srcpos_verror(struct srcpos *pos, const char *prefix,
const char *fmt, va_list va) const char *fmt, va_list va)

View File

@ -25,12 +25,12 @@ extern FILE *yyin;
extern int yyparse(void); extern int yyparse(void);
extern YYLTYPE yylloc; extern YYLTYPE yylloc;
struct boot_info *the_boot_info; struct dt_info *parser_output;
bool treesource_error; bool treesource_error;
struct boot_info *dt_from_source(const char *fname) struct dt_info *dt_from_source(const char *fname)
{ {
the_boot_info = NULL; parser_output = NULL;
treesource_error = false; treesource_error = false;
srcfile_push(fname); srcfile_push(fname);
@ -43,7 +43,7 @@ struct boot_info *dt_from_source(const char *fname)
if (treesource_error) if (treesource_error)
die("Syntax error parsing input tree\n"); die("Syntax error parsing input tree\n");
return the_boot_info; return parser_output;
} }
static void write_prefix(FILE *f, int level) static void write_prefix(FILE *f, int level)
@ -263,13 +263,13 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level)
} }
void dt_to_source(FILE *f, struct boot_info *bi) void dt_to_source(FILE *f, struct dt_info *dti)
{ {
struct reserve_info *re; struct reserve_info *re;
fprintf(f, "/dts-v1/;\n\n"); fprintf(f, "/dts-v1/;\n\n");
for (re = bi->reservelist; re; re = re->next) { for (re = dti->reservelist; re; re = re->next) {
struct label *l; struct label *l;
for_each_label(re->labels, l) for_each_label(re->labels, l)
@ -279,6 +279,6 @@ void dt_to_source(FILE *f, struct boot_info *bi)
(unsigned long long)re->re.size); (unsigned long long)re->re.size);
} }
write_tree_source_node(f, bi->dt, 0); write_tree_source_node(f, dti->dt, 0);
} }

View File

@ -46,6 +46,36 @@ char *xstrdup(const char *s)
return d; return d;
} }
/* based in part from (3) vsnprintf */
int xasprintf(char **strp, const char *fmt, ...)
{
int n, size = 128; /* start with 128 bytes */
char *p;
va_list ap;
/* initial pointer is NULL making the fist realloc to be malloc */
p = NULL;
while (1) {
p = xrealloc(p, size);
/* Try to print in the allocated space. */
va_start(ap, fmt);
n = vsnprintf(p, size, fmt, ap);
va_end(ap);
/* If that worked, return the string. */
if (n > -1 && n < size)
break;
/* Else try again with more space. */
if (n > -1) /* glibc 2.1 */
size = n + 1; /* precisely what is needed */
else /* glibc 2.0 */
size *= 2; /* twice the old size */
}
*strp = p;
return strlen(p);
}
char *join_path(const char *path, const char *name) char *join_path(const char *path, const char *name)
{ {
int lenp = strlen(path); int lenp = strlen(path);

View File

@ -59,6 +59,7 @@ static inline void *xrealloc(void *p, size_t len)
} }
extern char *xstrdup(const char *s); extern char *xstrdup(const char *s);
extern int xasprintf(char **strp, const char *fmt, ...);
extern char *join_path(const char *path, const char *name); extern char *join_path(const char *path, const char *name);
/** /**

View File

@ -1 +1 @@
#define DTC_VERSION "DTC 1.4.1-g53bf130b" #define DTC_VERSION "DTC 1.4.2-g0931cea3"