1
0
Fork 0

scripts/dtc: Update to upstream version v1.4.4-8-g756ffc4f52f6

This adds the following commits from upstream:

756ffc4f52f6 Build pylibfdt as part of the normal build process
8cb3896358e9 Adjust libfdt.h to work with swig
b40aa8359aff Mention pylibfdt in the documentation
12cfb740cc76 Add tests for pylibfdt
50f250701631 Add an initial Python library for libfdt
cdbb2b6c7a3a checks: Warn on node name unit-addresses with '0x' or leading 0s
4c15d5da17cc checks: Add bus checks for simple-bus buses
33c3985226d3 checks: Add bus checks for PCI buses
558cd81bdd43 dtc: Bump version to v1.4.4
c17a811c62eb fdtput: Remove star from value_len documentation
194d5caaefcb fdtget: Use @return to document the return value
d922ecdd017b tests: Make realloc_fdt() really allocate *fdt
921cc17fec29 libfdt: overlay: Check the value of the right variable
9ffdf60bf463 dtc: Simplify asm_emit_string() implementation
881012e44386 libfdt: Change names of sparse helper macros
bad5b28049e5 Fix assorted sparse warnings
672ac09ea04d Clean up gcc attributes
49300f2ade6a dtc: Don't abuse struct fdt_reserve_entry
fa8bc7f928ac dtc: Bump version to v1.4.3
34a9886a177f Add printf format attributes
f72508e2b6ca Correct some broken printf() like format mismatches
397d5ef0203c libfdt: Add fdt_setprop_empty()
69a1bd6ad3f9 libfdt: Remove undefined behaviour setting empty properties
acd1b534a592 Print output filename as part of warning messages
120775eb1cf3 dtc: Use streq() in preference to strcmp()
852e9ecbe197 checks: Add Warning for stricter node name character checking
ef0e8f061534 checks: Add Warning for stricter property name character checking
00d7bb1f4b0e dtc: pos parameter to srcpos_string() can't be NULL
95d57726bca4 livetree.c: Fix memory leak
3b9c97093d6e dtc: Fix NULL pointer use in dtlabel + dtref case
43eb551426ea manual: Fix typo it -> in
4baf15f7f13f Makefile: Add tags rule

Signed-off-by: Rob Herring <robh@kernel.org>
zero-colors
Rob Herring 2017-03-21 09:01:08 -05:00
parent 86cef6144d
commit 89d123106a
19 changed files with 523 additions and 182 deletions

View File

@ -72,17 +72,16 @@ struct check {
#define CHECK(_nm, _fn, _d, ...) \ #define CHECK(_nm, _fn, _d, ...) \
CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__) CHECK_ENTRY(_nm, _fn, _d, false, false, __VA_ARGS__)
#ifdef __GNUC__ static inline void PRINTF(3, 4) check_msg(struct check *c, struct dt_info *dti,
static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3))); const char *fmt, ...)
#endif
static inline void check_msg(struct check *c, const char *fmt, ...)
{ {
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
if ((c->warn && (quiet < 1)) if ((c->warn && (quiet < 1))
|| (c->error && (quiet < 2))) { || (c->error && (quiet < 2))) {
fprintf(stderr, "%s (%s): ", fprintf(stderr, "%s: %s (%s): ",
strcmp(dti->outname, "-") ? dti->outname : "<stdout>",
(c->error) ? "ERROR" : "Warning", c->name); (c->error) ? "ERROR" : "Warning", c->name);
vfprintf(stderr, fmt, ap); vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
@ -90,11 +89,11 @@ static inline void check_msg(struct check *c, const char *fmt, ...)
va_end(ap); va_end(ap);
} }
#define FAIL(c, ...) \ #define FAIL(c, dti, ...) \
do { \ do { \
TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \ TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
(c)->status = FAILED; \ (c)->status = FAILED; \
check_msg((c), __VA_ARGS__); \ check_msg((c), dti, __VA_ARGS__); \
} while (0) } while (0)
static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node) static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node)
@ -127,7 +126,7 @@ static bool run_check(struct check *c, struct dt_info *dti)
error = error || run_check(prq, dti); 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, dti, "Failed prerequisite '%s'",
c->prereq[i]->name); c->prereq[i]->name);
} }
} }
@ -157,7 +156,7 @@ out:
static inline void check_always_fail(struct check *c, struct dt_info *dti, static inline void check_always_fail(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
{ {
FAIL(c, "always_fail check"); FAIL(c, dti, "always_fail check");
} }
CHECK(always_fail, check_always_fail, NULL); CHECK(always_fail, check_always_fail, NULL);
@ -172,7 +171,7 @@ static void check_is_string(struct check *c, struct dt_info *dti,
return; /* Not present, assumed ok */ return; /* Not present, assumed ok */
if (!data_is_one_string(prop->val)) if (!data_is_one_string(prop->val))
FAIL(c, "\"%s\" property in %s is not a string", FAIL(c, dti, "\"%s\" property in %s is not a string",
propname, node->fullpath); propname, node->fullpath);
} }
#define WARNING_IF_NOT_STRING(nm, propname) \ #define WARNING_IF_NOT_STRING(nm, propname) \
@ -191,7 +190,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti,
return; /* Not present, assumed ok */ return; /* Not present, assumed ok */
if (prop->val.len != sizeof(cell_t)) if (prop->val.len != sizeof(cell_t))
FAIL(c, "\"%s\" property in %s is not a single cell", FAIL(c, dti, "\"%s\" property in %s is not a single cell",
propname, node->fullpath); propname, node->fullpath);
} }
#define WARNING_IF_NOT_CELL(nm, propname) \ #define WARNING_IF_NOT_CELL(nm, propname) \
@ -213,7 +212,7 @@ static void check_duplicate_node_names(struct check *c, struct dt_info *dti,
child2; child2;
child2 = child2->next_sibling) child2 = child2->next_sibling)
if (streq(child->name, child2->name)) if (streq(child->name, child2->name))
FAIL(c, "Duplicate node name %s", FAIL(c, dti, "Duplicate node name %s",
child->fullpath); child->fullpath);
} }
ERROR(duplicate_node_names, check_duplicate_node_names, NULL); ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
@ -228,7 +227,7 @@ static void check_duplicate_property_names(struct check *c, struct dt_info *dti,
if (prop2->deleted) if (prop2->deleted)
continue; continue;
if (streq(prop->name, prop2->name)) if (streq(prop->name, prop2->name))
FAIL(c, "Duplicate property name %s in %s", FAIL(c, dti, "Duplicate property name %s in %s",
prop->name, node->fullpath); prop->name, node->fullpath);
} }
} }
@ -239,6 +238,7 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define DIGITS "0123456789" #define DIGITS "0123456789"
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-" #define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
#define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
static void check_node_name_chars(struct check *c, struct dt_info *dti, static void check_node_name_chars(struct check *c, struct dt_info *dti,
struct node *node) struct node *node)
@ -246,16 +246,27 @@ static void check_node_name_chars(struct check *c, struct dt_info *dti,
int n = strspn(node->name, c->data); int n = strspn(node->name, c->data);
if (n < strlen(node->name)) if (n < strlen(node->name))
FAIL(c, "Bad character '%c' in node %s", FAIL(c, dti, "Bad character '%c' in node %s",
node->name[n], node->fullpath); node->name[n], node->fullpath);
} }
ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@"); ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
struct node *node)
{
int n = strspn(node->name, c->data);
if (n < node->basenamelen)
FAIL(c, dti, "Character '%c' not recommended in node %s",
node->name[n], node->fullpath);
}
CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT);
static void check_node_name_format(struct check *c, struct dt_info *dti, 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, dti, "Node %s has multiple '@' characters in name",
node->fullpath); node->fullpath);
} }
ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars); ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
@ -274,11 +285,11 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
if (prop) { if (prop) {
if (!unitname[0]) if (!unitname[0])
FAIL(c, "Node %s has a reg or ranges property, but no unit name", FAIL(c, dti, "Node %s has a reg or ranges property, but no unit name",
node->fullpath); node->fullpath);
} else { } else {
if (unitname[0]) if (unitname[0])
FAIL(c, "Node %s has a unit name, but no reg property", FAIL(c, dti, "Node %s has a unit name, but no reg property",
node->fullpath); node->fullpath);
} }
} }
@ -293,12 +304,44 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
int n = strspn(prop->name, c->data); int n = strspn(prop->name, c->data);
if (n < strlen(prop->name)) if (n < strlen(prop->name))
FAIL(c, "Bad character '%c' in property name \"%s\", node %s", FAIL(c, dti, "Bad character '%c' in property name \"%s\", node %s",
prop->name[n], prop->name, node->fullpath); prop->name[n], prop->name, node->fullpath);
} }
} }
ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS); ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
static void check_property_name_chars_strict(struct check *c,
struct dt_info *dti,
struct node *node)
{
struct property *prop;
for_each_property(node, prop) {
const char *name = prop->name;
int n = strspn(name, c->data);
if (n == strlen(prop->name))
continue;
/* Certain names are whitelisted */
if (streq(name, "device_type"))
continue;
/*
* # is only allowed at the beginning of property names not counting
* the vendor prefix.
*/
if (name[n] == '#' && ((n == 0) || (name[n-1] == ','))) {
name += n + 1;
n = strspn(name, c->data);
}
if (n < strlen(name))
FAIL(c, dti, "Character '%c' not recommended in property name \"%s\", node %s",
name[n], prop->name, node->fullpath);
}
}
CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT);
#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) \
((mark) ? "value of " : ""), \ ((mark) ? "value of " : ""), \
@ -327,7 +370,7 @@ static void check_duplicate_label(struct check *c, struct dt_info *dti,
return; return;
if ((othernode != node) || (otherprop != prop) || (othermark != mark)) if ((othernode != node) || (otherprop != prop) || (othermark != mark))
FAIL(c, "Duplicate label '%s' on " DESCLABEL_FMT FAIL(c, dti, "Duplicate label '%s' on " DESCLABEL_FMT
" and " DESCLABEL_FMT, " and " DESCLABEL_FMT,
label, DESCLABEL_ARGS(node, prop, mark), label, DESCLABEL_ARGS(node, prop, mark),
DESCLABEL_ARGS(othernode, otherprop, othermark)); DESCLABEL_ARGS(othernode, otherprop, othermark));
@ -367,7 +410,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
return 0; 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, dti, "%s has bad length (%d) %s property",
node->fullpath, prop->val.len, prop->name); node->fullpath, prop->val.len, prop->name);
return 0; return 0;
} }
@ -379,7 +422,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
/* "Set this node's phandle equal to some /* "Set this node's phandle equal to some
* other node's phandle". That's nonsensical * other node's phandle". That's nonsensical
* by construction. */ { * by construction. */ {
FAIL(c, "%s in %s is a reference to another node", FAIL(c, dti, "%s in %s is a reference to another node",
prop->name, node->fullpath); prop->name, node->fullpath);
} }
/* But setting this node's phandle equal to its own /* But setting this node's phandle equal to its own
@ -393,7 +436,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
phandle = propval_cell(prop); phandle = propval_cell(prop);
if ((phandle == 0) || (phandle == -1)) { if ((phandle == 0) || (phandle == -1)) {
FAIL(c, "%s has bad value (0x%x) in %s property", FAIL(c, dti, "%s has bad value (0x%x) in %s property",
node->fullpath, phandle, prop->name); node->fullpath, phandle, prop->name);
return 0; return 0;
} }
@ -420,7 +463,7 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti,
return; return;
if (linux_phandle && phandle && (phandle != linux_phandle)) if (linux_phandle && phandle && (phandle != linux_phandle))
FAIL(c, "%s has mismatching 'phandle' and 'linux,phandle'" FAIL(c, dti, "%s has mismatching 'phandle' and 'linux,phandle'"
" properties", node->fullpath); " properties", node->fullpath);
if (linux_phandle && !phandle) if (linux_phandle && !phandle)
@ -428,7 +471,7 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti,
other = get_node_by_phandle(root, phandle); other = get_node_by_phandle(root, phandle);
if (other && (other != node)) { if (other && (other != node)) {
FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)", FAIL(c, dti, "%s has duplicated phandle 0x%x (seen before at %s)",
node->fullpath, phandle, other->fullpath); node->fullpath, phandle, other->fullpath);
return; return;
} }
@ -453,7 +496,7 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
if ((prop->val.len != node->basenamelen+1) if ((prop->val.len != node->basenamelen+1)
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) { || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead" FAIL(c, dti, "\"name\" property in %s is incorrect (\"%s\" instead"
" of base node name)", node->fullpath, prop->val.val); " of base node name)", node->fullpath, prop->val.val);
} else { } else {
/* The name property is correct, and therefore redundant. /* The name property is correct, and therefore redundant.
@ -488,16 +531,16 @@ static void fixup_phandle_references(struct check *c, struct dt_info *dti,
refnode = get_node_by_ref(dt, m->ref); refnode = get_node_by_ref(dt, m->ref);
if (! refnode) { if (! refnode) {
if (!(dti->dtsflags & DTSF_PLUGIN)) if (!(dti->dtsflags & DTSF_PLUGIN))
FAIL(c, "Reference to non-existent node or " FAIL(c, dti, "Reference to non-existent node or "
"label \"%s\"\n", m->ref); "label \"%s\"\n", m->ref);
else /* mark the entry as unresolved */ else /* mark the entry as unresolved */
*((cell_t *)(prop->val.val + m->offset)) = *((fdt32_t *)(prop->val.val + m->offset)) =
cpu_to_fdt32(0xffffffff); cpu_to_fdt32(0xffffffff);
continue; continue;
} }
phandle = get_node_phandle(dt, refnode); phandle = get_node_phandle(dt, refnode);
*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle); *((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
} }
} }
} }
@ -520,7 +563,7 @@ static void fixup_path_references(struct check *c, struct dt_info *dti,
refnode = get_node_by_ref(dt, m->ref); refnode = get_node_by_ref(dt, m->ref);
if (!refnode) { if (!refnode) {
FAIL(c, "Reference to non-existent node or label \"%s\"\n", FAIL(c, dti, "Reference to non-existent node or label \"%s\"\n",
m->ref); m->ref);
continue; continue;
} }
@ -579,19 +622,19 @@ static void check_reg_format(struct check *c, struct dt_info *dti,
return; /* No "reg", that's fine */ return; /* No "reg", that's fine */
if (!node->parent) { if (!node->parent) {
FAIL(c, "Root node has a \"reg\" property"); FAIL(c, dti, "Root node has a \"reg\" property");
return; return;
} }
if (prop->val.len == 0) if (prop->val.len == 0)
FAIL(c, "\"reg\" property in %s is empty", node->fullpath); FAIL(c, dti, "\"reg\" property in %s is empty", node->fullpath);
addr_cells = node_addr_cells(node->parent); addr_cells = node_addr_cells(node->parent);
size_cells = node_size_cells(node->parent); size_cells = node_size_cells(node->parent);
entrylen = (addr_cells + size_cells) * sizeof(cell_t); entrylen = (addr_cells + size_cells) * sizeof(cell_t);
if (!entrylen || (prop->val.len % entrylen) != 0) if (!entrylen || (prop->val.len % entrylen) != 0)
FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) " FAIL(c, dti, "\"reg\" property in %s has invalid length (%d bytes) "
"(#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);
} }
@ -608,7 +651,7 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
return; return;
if (!node->parent) { if (!node->parent) {
FAIL(c, "Root node has a \"ranges\" property"); FAIL(c, dti, "Root node has a \"ranges\" property");
return; return;
} }
@ -620,17 +663,17 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
if (prop->val.len == 0) { if (prop->val.len == 0) {
if (p_addr_cells != c_addr_cells) if (p_addr_cells != c_addr_cells)
FAIL(c, "%s has empty \"ranges\" property but its " FAIL(c, dti, "%s has empty \"ranges\" property but its "
"#address-cells (%d) differs from %s (%d)", "#address-cells (%d) differs from %s (%d)",
node->fullpath, c_addr_cells, node->parent->fullpath, node->fullpath, c_addr_cells, node->parent->fullpath,
p_addr_cells); p_addr_cells);
if (p_size_cells != c_size_cells) if (p_size_cells != c_size_cells)
FAIL(c, "%s has empty \"ranges\" property but its " FAIL(c, dti, "%s has empty \"ranges\" property but its "
"#size-cells (%d) differs from %s (%d)", "#size-cells (%d) differs from %s (%d)",
node->fullpath, c_size_cells, node->parent->fullpath, node->fullpath, c_size_cells, node->parent->fullpath,
p_size_cells); p_size_cells);
} else if ((prop->val.len % entrylen) != 0) { } else if ((prop->val.len % entrylen) != 0) {
FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) " FAIL(c, dti, "\"ranges\" property in %s has invalid length (%d bytes) "
"(parent #address-cells == %d, child #address-cells == %d, " "(parent #address-cells == %d, child #address-cells == %d, "
"#size-cells == %d)", node->fullpath, prop->val.len, "#size-cells == %d)", node->fullpath, prop->val.len,
p_addr_cells, c_addr_cells, c_size_cells); p_addr_cells, c_addr_cells, c_size_cells);
@ -638,6 +681,229 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
} }
WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells); WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
static const struct bus_type pci_bus = {
.name = "PCI",
};
static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *node)
{
struct property *prop;
cell_t *cells;
prop = get_property(node, "device_type");
if (!prop || !streq(prop->val.val, "pci"))
return;
node->bus = &pci_bus;
if (!strneq(node->name, "pci", node->basenamelen) &&
!strneq(node->name, "pcie", node->basenamelen))
FAIL(c, dti, "Node %s node name is not \"pci\" or \"pcie\"",
node->fullpath);
prop = get_property(node, "ranges");
if (!prop)
FAIL(c, dti, "Node %s missing ranges for PCI bridge (or not a bridge)",
node->fullpath);
if (node_addr_cells(node) != 3)
FAIL(c, dti, "Node %s incorrect #address-cells for PCI bridge",
node->fullpath);
if (node_size_cells(node) != 2)
FAIL(c, dti, "Node %s incorrect #size-cells for PCI bridge",
node->fullpath);
prop = get_property(node, "bus-range");
if (!prop) {
FAIL(c, dti, "Node %s missing bus-range for PCI bridge",
node->fullpath);
return;
}
if (prop->val.len != (sizeof(cell_t) * 2)) {
FAIL(c, dti, "Node %s bus-range must be 2 cells",
node->fullpath);
return;
}
cells = (cell_t *)prop->val.val;
if (fdt32_to_cpu(cells[0]) > fdt32_to_cpu(cells[1]))
FAIL(c, dti, "Node %s bus-range 1st cell must be less than or equal to 2nd cell",
node->fullpath);
if (fdt32_to_cpu(cells[1]) > 0xff)
FAIL(c, dti, "Node %s bus-range maximum bus number must be less than 256",
node->fullpath);
}
WARNING(pci_bridge, check_pci_bridge, NULL,
&device_type_is_string, &addr_size_cells);
static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struct node *node)
{
struct property *prop;
unsigned int bus_num, min_bus, max_bus;
cell_t *cells;
if (!node->parent || (node->parent->bus != &pci_bus))
return;
prop = get_property(node, "reg");
if (!prop)
return;
cells = (cell_t *)prop->val.val;
bus_num = (fdt32_to_cpu(cells[0]) & 0x00ff0000) >> 16;
prop = get_property(node->parent, "bus-range");
if (!prop) {
min_bus = max_bus = 0;
} else {
cells = (cell_t *)prop->val.val;
min_bus = fdt32_to_cpu(cells[0]);
max_bus = fdt32_to_cpu(cells[0]);
}
if ((bus_num < min_bus) || (bus_num > max_bus))
FAIL(c, dti, "Node %s PCI bus number %d out of range, expected (%d - %d)",
node->fullpath, bus_num, min_bus, max_bus);
}
WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, &reg_format, &pci_bridge);
static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct node *node)
{
struct property *prop;
const char *unitname = get_unitname(node);
char unit_addr[5];
unsigned int dev, func, reg;
cell_t *cells;
if (!node->parent || (node->parent->bus != &pci_bus))
return;
prop = get_property(node, "reg");
if (!prop) {
FAIL(c, dti, "Node %s missing PCI reg property", node->fullpath);
return;
}
cells = (cell_t *)prop->val.val;
if (cells[1] || cells[2])
FAIL(c, dti, "Node %s PCI reg config space address cells 2 and 3 must be 0",
node->fullpath);
reg = fdt32_to_cpu(cells[0]);
dev = (reg & 0xf800) >> 11;
func = (reg & 0x700) >> 8;
if (reg & 0xff000000)
FAIL(c, dti, "Node %s PCI reg address is not configuration space",
node->fullpath);
if (reg & 0x000000ff)
FAIL(c, dti, "Node %s PCI reg config space address register number must be 0",
node->fullpath);
if (func == 0) {
snprintf(unit_addr, sizeof(unit_addr), "%x", dev);
if (streq(unitname, unit_addr))
return;
}
snprintf(unit_addr, sizeof(unit_addr), "%x,%x", dev, func);
if (streq(unitname, unit_addr))
return;
FAIL(c, dti, "Node %s PCI unit address format error, expected \"%s\"",
node->fullpath, unit_addr);
}
WARNING(pci_device_reg, check_pci_device_reg, NULL, &reg_format, &pci_bridge);
static const struct bus_type simple_bus = {
.name = "simple-bus",
};
static bool node_is_compatible(struct node *node, const char *compat)
{
struct property *prop;
const char *str, *end;
prop = get_property(node, "compatible");
if (!prop)
return false;
for (str = prop->val.val, end = str + prop->val.len; str < end;
str += strnlen(str, end - str) + 1) {
if (strneq(str, compat, end - str))
return true;
}
return false;
}
static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
{
if (node_is_compatible(node, "simple-bus"))
node->bus = &simple_bus;
}
WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells);
static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
{
struct property *prop;
const char *unitname = get_unitname(node);
char unit_addr[17];
unsigned int size;
uint64_t reg = 0;
cell_t *cells = NULL;
if (!node->parent || (node->parent->bus != &simple_bus))
return;
prop = get_property(node, "reg");
if (prop)
cells = (cell_t *)prop->val.val;
else {
prop = get_property(node, "ranges");
if (prop && prop->val.len)
/* skip of child address */
cells = ((cell_t *)prop->val.val) + node_addr_cells(node);
}
if (!cells) {
if (node->parent->parent && !(node->bus == &simple_bus))
FAIL(c, dti, "Node %s missing or empty reg/ranges property", node->fullpath);
return;
}
size = node_addr_cells(node->parent);
while (size--)
reg = (reg << 32) | fdt32_to_cpu(*(cells++));
snprintf(unit_addr, sizeof(unit_addr), "%lx", reg);
if (!streq(unitname, unit_addr))
FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"",
node->fullpath, unit_addr);
}
WARNING(simple_bus_reg, check_simple_bus_reg, NULL, &reg_format, &simple_bus_bridge);
static void check_unit_address_format(struct check *c, struct dt_info *dti,
struct node *node)
{
const char *unitname = get_unitname(node);
if (node->parent && node->parent->bus)
return;
if (!unitname[0])
return;
if (!strncmp(unitname, "0x", 2)) {
FAIL(c, dti, "Node %s unit name should not have leading \"0x\"",
node->fullpath);
/* skip over 0x for next test */
unitname += 2;
}
if (unitname[0] == '0' && isxdigit(unitname[1]))
FAIL(c, dti, "Node %s unit name should not have leading 0s",
node->fullpath);
}
WARNING(unit_address_format, check_unit_address_format, NULL,
&node_name_format, &pci_bridge, &simple_bus_bridge);
/* /*
* Style checks * Style checks
*/ */
@ -656,11 +922,11 @@ static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti,
return; return;
if (node->parent->addr_cells == -1) if (node->parent->addr_cells == -1)
FAIL(c, "Relying on default #address-cells value for %s", FAIL(c, dti, "Relying on default #address-cells value for %s",
node->fullpath); node->fullpath);
if (node->parent->size_cells == -1) if (node->parent->size_cells == -1)
FAIL(c, "Relying on default #size-cells value for %s", FAIL(c, dti, "Relying on default #size-cells value for %s",
node->fullpath); node->fullpath);
} }
WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL, WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
@ -684,7 +950,7 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
prop = get_property(chosen, "interrupt-controller"); prop = get_property(chosen, "interrupt-controller");
if (prop) if (prop)
FAIL(c, "/chosen has obsolete \"interrupt-controller\" " FAIL(c, dti, "/chosen has obsolete \"interrupt-controller\" "
"property"); "property");
} }
WARNING(obsolete_chosen_interrupt_controller, WARNING(obsolete_chosen_interrupt_controller,
@ -703,9 +969,20 @@ static struct check *check_table[] = {
&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell, &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
&device_type_is_string, &model_is_string, &status_is_string, &device_type_is_string, &model_is_string, &status_is_string,
&property_name_chars_strict,
&node_name_chars_strict,
&addr_size_cells, &reg_format, &ranges_format, &addr_size_cells, &reg_format, &ranges_format,
&unit_address_vs_reg, &unit_address_vs_reg,
&unit_address_format,
&pci_bridge,
&pci_device_reg,
&pci_device_bus_num,
&simple_bus_bridge,
&simple_bus_reg,
&avoid_default_addr_size, &avoid_default_addr_size,
&obsolete_chosen_interrupt_controller, &obsolete_chosen_interrupt_controller,

View File

@ -171,9 +171,9 @@ struct data data_merge(struct data d1, struct data d2)
struct data data_append_integer(struct data d, uint64_t value, int bits) struct data data_append_integer(struct data d, uint64_t value, int bits)
{ {
uint8_t value_8; uint8_t value_8;
uint16_t value_16; fdt16_t value_16;
uint32_t value_32; fdt32_t value_32;
uint64_t value_64; fdt64_t value_64;
switch (bits) { switch (bits) {
case 8: case 8:
@ -197,14 +197,14 @@ struct data data_append_integer(struct data d, uint64_t value, int bits)
} }
} }
struct data data_append_re(struct data d, const struct fdt_reserve_entry *re) struct data data_append_re(struct data d, uint64_t address, uint64_t size)
{ {
struct fdt_reserve_entry bere; struct fdt_reserve_entry re;
bere.address = cpu_to_fdt64(re->address); re.address = cpu_to_fdt64(address);
bere.size = cpu_to_fdt64(re->size); re.size = cpu_to_fdt64(size);
return data_append_data(d, &bere, sizeof(bere)); return data_append_data(d, &re, sizeof(re));
} }
struct data data_append_cell(struct data d, cell_t word) struct data data_append_cell(struct data d, cell_t word)

View File

@ -62,7 +62,8 @@ static int dts_version = 1;
static void push_input_file(const char *filename); static void push_input_file(const char *filename);
static bool pop_input_file(void); static bool pop_input_file(void);
static void lexical_error(const char *fmt, ...); static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
%} %}
%% %%

View File

@ -655,8 +655,9 @@ static int dts_version = 1;
static void push_input_file(const char *filename); static void push_input_file(const char *filename);
static bool pop_input_file(void); static bool pop_input_file(void);
static void lexical_error(const char *fmt, ...); static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
#line 660 "dtc-lexer.lex.c"
#line 661 "dtc-lexer.lex.c"
#define INITIAL 0 #define INITIAL 0
#define BYTESTRING 1 #define BYTESTRING 1
@ -878,9 +879,9 @@ YY_DECL
} }
{ {
#line 68 "dtc-lexer.l" #line 69 "dtc-lexer.l"
#line 884 "dtc-lexer.lex.c" #line 885 "dtc-lexer.lex.c"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{ {
@ -937,7 +938,7 @@ do_action: /* This label is used only to access EOF actions. */
case 1: case 1:
/* rule 1 can match eol */ /* rule 1 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 69 "dtc-lexer.l" #line 70 "dtc-lexer.l"
{ {
char *name = strchr(yytext, '\"') + 1; char *name = strchr(yytext, '\"') + 1;
yytext[yyleng-1] = '\0'; yytext[yyleng-1] = '\0';
@ -947,7 +948,7 @@ YY_RULE_SETUP
case 2: case 2:
/* rule 2 can match eol */ /* rule 2 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 75 "dtc-lexer.l" #line 76 "dtc-lexer.l"
{ {
char *line, *fnstart, *fnend; char *line, *fnstart, *fnend;
struct data fn; struct data fn;
@ -981,7 +982,7 @@ case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(BYTESTRING): case YY_STATE_EOF(BYTESTRING):
case YY_STATE_EOF(PROPNODENAME): case YY_STATE_EOF(PROPNODENAME):
case YY_STATE_EOF(V1): case YY_STATE_EOF(V1):
#line 104 "dtc-lexer.l" #line 105 "dtc-lexer.l"
{ {
if (!pop_input_file()) { if (!pop_input_file()) {
yyterminate(); yyterminate();
@ -991,7 +992,7 @@ case YY_STATE_EOF(V1):
case 3: case 3:
/* rule 3 can match eol */ /* rule 3 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 110 "dtc-lexer.l" #line 111 "dtc-lexer.l"
{ {
DPRINT("String: %s\n", yytext); DPRINT("String: %s\n", yytext);
yylval.data = data_copy_escape_string(yytext+1, yylval.data = data_copy_escape_string(yytext+1,
@ -1001,7 +1002,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 4: case 4:
YY_RULE_SETUP YY_RULE_SETUP
#line 117 "dtc-lexer.l" #line 118 "dtc-lexer.l"
{ {
DPRINT("Keyword: /dts-v1/\n"); DPRINT("Keyword: /dts-v1/\n");
dts_version = 1; dts_version = 1;
@ -1011,7 +1012,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 5: case 5:
YY_RULE_SETUP YY_RULE_SETUP
#line 124 "dtc-lexer.l" #line 125 "dtc-lexer.l"
{ {
DPRINT("Keyword: /plugin/\n"); DPRINT("Keyword: /plugin/\n");
return DT_PLUGIN; return DT_PLUGIN;
@ -1019,7 +1020,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 6: case 6:
YY_RULE_SETUP YY_RULE_SETUP
#line 129 "dtc-lexer.l" #line 130 "dtc-lexer.l"
{ {
DPRINT("Keyword: /memreserve/\n"); DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT(); BEGIN_DEFAULT();
@ -1028,7 +1029,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 7: case 7:
YY_RULE_SETUP YY_RULE_SETUP
#line 135 "dtc-lexer.l" #line 136 "dtc-lexer.l"
{ {
DPRINT("Keyword: /bits/\n"); DPRINT("Keyword: /bits/\n");
BEGIN_DEFAULT(); BEGIN_DEFAULT();
@ -1037,7 +1038,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 8: case 8:
YY_RULE_SETUP YY_RULE_SETUP
#line 141 "dtc-lexer.l" #line 142 "dtc-lexer.l"
{ {
DPRINT("Keyword: /delete-property/\n"); DPRINT("Keyword: /delete-property/\n");
DPRINT("<PROPNODENAME>\n"); DPRINT("<PROPNODENAME>\n");
@ -1047,7 +1048,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 9: case 9:
YY_RULE_SETUP YY_RULE_SETUP
#line 148 "dtc-lexer.l" #line 149 "dtc-lexer.l"
{ {
DPRINT("Keyword: /delete-node/\n"); DPRINT("Keyword: /delete-node/\n");
DPRINT("<PROPNODENAME>\n"); DPRINT("<PROPNODENAME>\n");
@ -1057,7 +1058,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 10: case 10:
YY_RULE_SETUP YY_RULE_SETUP
#line 155 "dtc-lexer.l" #line 156 "dtc-lexer.l"
{ {
DPRINT("Label: %s\n", yytext); DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext); yylval.labelref = xstrdup(yytext);
@ -1067,7 +1068,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 11: case 11:
YY_RULE_SETUP YY_RULE_SETUP
#line 162 "dtc-lexer.l" #line 163 "dtc-lexer.l"
{ {
char *e; char *e;
DPRINT("Integer Literal: '%s'\n", yytext); DPRINT("Integer Literal: '%s'\n", yytext);
@ -1093,7 +1094,7 @@ YY_RULE_SETUP
case 12: case 12:
/* rule 12 can match eol */ /* rule 12 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 184 "dtc-lexer.l" #line 185 "dtc-lexer.l"
{ {
struct data d; struct data d;
DPRINT("Character literal: %s\n", yytext); DPRINT("Character literal: %s\n", yytext);
@ -1117,7 +1118,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 13: case 13:
YY_RULE_SETUP YY_RULE_SETUP
#line 205 "dtc-lexer.l" #line 206 "dtc-lexer.l"
{ /* label reference */ { /* label reference */
DPRINT("Ref: %s\n", yytext+1); DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1); yylval.labelref = xstrdup(yytext+1);
@ -1126,7 +1127,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 14: case 14:
YY_RULE_SETUP YY_RULE_SETUP
#line 211 "dtc-lexer.l" #line 212 "dtc-lexer.l"
{ /* new-style path reference */ { /* new-style path reference */
yytext[yyleng-1] = '\0'; yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2); DPRINT("Ref: %s\n", yytext+2);
@ -1136,7 +1137,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 15: case 15:
YY_RULE_SETUP YY_RULE_SETUP
#line 218 "dtc-lexer.l" #line 219 "dtc-lexer.l"
{ {
yylval.byte = strtol(yytext, NULL, 16); yylval.byte = strtol(yytext, NULL, 16);
DPRINT("Byte: %02x\n", (int)yylval.byte); DPRINT("Byte: %02x\n", (int)yylval.byte);
@ -1145,7 +1146,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 16: case 16:
YY_RULE_SETUP YY_RULE_SETUP
#line 224 "dtc-lexer.l" #line 225 "dtc-lexer.l"
{ {
DPRINT("/BYTESTRING\n"); DPRINT("/BYTESTRING\n");
BEGIN_DEFAULT(); BEGIN_DEFAULT();
@ -1154,7 +1155,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 17: case 17:
YY_RULE_SETUP YY_RULE_SETUP
#line 230 "dtc-lexer.l" #line 231 "dtc-lexer.l"
{ {
DPRINT("PropNodeName: %s\n", yytext); DPRINT("PropNodeName: %s\n", yytext);
yylval.propnodename = xstrdup((yytext[0] == '\\') ? yylval.propnodename = xstrdup((yytext[0] == '\\') ?
@ -1165,7 +1166,7 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 18: case 18:
YY_RULE_SETUP YY_RULE_SETUP
#line 238 "dtc-lexer.l" #line 239 "dtc-lexer.l"
{ {
DPRINT("Binary Include\n"); DPRINT("Binary Include\n");
return DT_INCBIN; return DT_INCBIN;
@ -1174,64 +1175,64 @@ YY_RULE_SETUP
case 19: case 19:
/* rule 19 can match eol */ /* rule 19 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 243 "dtc-lexer.l" #line 244 "dtc-lexer.l"
/* eat whitespace */ /* eat whitespace */
YY_BREAK YY_BREAK
case 20: case 20:
/* rule 20 can match eol */ /* rule 20 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 244 "dtc-lexer.l" #line 245 "dtc-lexer.l"
/* eat C-style comments */ /* eat C-style comments */
YY_BREAK YY_BREAK
case 21: case 21:
/* rule 21 can match eol */ /* rule 21 can match eol */
YY_RULE_SETUP YY_RULE_SETUP
#line 245 "dtc-lexer.l" #line 246 "dtc-lexer.l"
/* eat C++-style comments */ /* eat C++-style comments */
YY_BREAK YY_BREAK
case 22: case 22:
YY_RULE_SETUP YY_RULE_SETUP
#line 247 "dtc-lexer.l" #line 248 "dtc-lexer.l"
{ return DT_LSHIFT; }; { return DT_LSHIFT; };
YY_BREAK YY_BREAK
case 23: case 23:
YY_RULE_SETUP YY_RULE_SETUP
#line 248 "dtc-lexer.l" #line 249 "dtc-lexer.l"
{ return DT_RSHIFT; }; { return DT_RSHIFT; };
YY_BREAK YY_BREAK
case 24: case 24:
YY_RULE_SETUP YY_RULE_SETUP
#line 249 "dtc-lexer.l" #line 250 "dtc-lexer.l"
{ return DT_LE; }; { return DT_LE; };
YY_BREAK YY_BREAK
case 25: case 25:
YY_RULE_SETUP YY_RULE_SETUP
#line 250 "dtc-lexer.l" #line 251 "dtc-lexer.l"
{ return DT_GE; }; { return DT_GE; };
YY_BREAK YY_BREAK
case 26: case 26:
YY_RULE_SETUP YY_RULE_SETUP
#line 251 "dtc-lexer.l" #line 252 "dtc-lexer.l"
{ return DT_EQ; }; { return DT_EQ; };
YY_BREAK YY_BREAK
case 27: case 27:
YY_RULE_SETUP YY_RULE_SETUP
#line 252 "dtc-lexer.l" #line 253 "dtc-lexer.l"
{ return DT_NE; }; { return DT_NE; };
YY_BREAK YY_BREAK
case 28: case 28:
YY_RULE_SETUP YY_RULE_SETUP
#line 253 "dtc-lexer.l" #line 254 "dtc-lexer.l"
{ return DT_AND; }; { return DT_AND; };
YY_BREAK YY_BREAK
case 29: case 29:
YY_RULE_SETUP YY_RULE_SETUP
#line 254 "dtc-lexer.l" #line 255 "dtc-lexer.l"
{ return DT_OR; }; { return DT_OR; };
YY_BREAK YY_BREAK
case 30: case 30:
YY_RULE_SETUP YY_RULE_SETUP
#line 256 "dtc-lexer.l" #line 257 "dtc-lexer.l"
{ {
DPRINT("Char: %c (\\x%02x)\n", yytext[0], DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]); (unsigned)yytext[0]);
@ -1249,10 +1250,10 @@ YY_RULE_SETUP
YY_BREAK YY_BREAK
case 31: case 31:
YY_RULE_SETUP YY_RULE_SETUP
#line 271 "dtc-lexer.l" #line 272 "dtc-lexer.l"
ECHO; ECHO;
YY_BREAK YY_BREAK
#line 1256 "dtc-lexer.lex.c" #line 1257 "dtc-lexer.lex.c"
case YY_END_OF_BUFFER: case YY_END_OF_BUFFER:
{ {
@ -2218,7 +2219,7 @@ void yyfree (void * ptr )
#define YYTABLES_NAME "yytables" #define YYTABLES_NAME "yytables"
#line 271 "dtc-lexer.l" #line 272 "dtc-lexer.l"

View File

@ -1557,10 +1557,10 @@ yyreduce:
{ {
struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref)); struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref));
add_label(&target->labels, (yyvsp[-2].labelref)); if (target) {
if (target) add_label(&target->labels, (yyvsp[-2].labelref));
merge_nodes(target, (yyvsp[0].node)); merge_nodes(target, (yyvsp[0].node));
else } else
ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref)); ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref));
(yyval.node) = (yyvsp[-3].node); (yyval.node) = (yyvsp[-3].node);
} }

View File

@ -171,10 +171,10 @@ devicetree:
{ {
struct node *target = get_node_by_ref($1, $3); struct node *target = get_node_by_ref($1, $3);
add_label(&target->labels, $2); if (target) {
if (target) add_label(&target->labels, $2);
merge_nodes(target, $4); merge_nodes(target, $4);
else } else
ERROR(&@3, "Label or path %s not found", $3); ERROR(&@3, "Label or path %s not found", $3);
$$ = $1; $$ = $1;
} }

View File

@ -138,7 +138,7 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
static const char *guess_input_format(const char *fname, const char *fallback) static const char *guess_input_format(const char *fname, const char *fallback)
{ {
struct stat statbuf; struct stat statbuf;
uint32_t magic; fdt32_t magic;
FILE *f; FILE *f;
if (stat(fname, &statbuf) != 0) if (stat(fname, &statbuf) != 0)
@ -159,8 +159,7 @@ static const char *guess_input_format(const char *fname, const char *fallback)
} }
fclose(f); fclose(f);
magic = fdt32_to_cpu(magic); if (fdt32_to_cpu(magic) == FDT_MAGIC)
if (magic == FDT_MAGIC)
return "dtb"; return "dtb";
return guess_type_by_name(fname, fallback); return guess_type_by_name(fname, fallback);
@ -216,7 +215,7 @@ int main(int argc, char *argv[])
alignsize = strtol(optarg, NULL, 0); alignsize = strtol(optarg, NULL, 0);
if (!is_power_of_2(alignsize)) if (!is_power_of_2(alignsize))
die("Invalid argument \"%d\" to -a option\n", die("Invalid argument \"%d\" to -a option\n",
optarg); alignsize);
break; break;
case 'f': case 'f':
force = true; force = true;
@ -309,6 +308,8 @@ int main(int argc, char *argv[])
else else
die("Unknown input format \"%s\"\n", inform); die("Unknown input format \"%s\"\n", inform);
dti->outname = outname;
if (depfile) { if (depfile) {
fputc('\n', depfile); fputc('\n', depfile);
fclose(depfile); fclose(depfile);

View File

@ -43,7 +43,6 @@
#define debug(...) #define debug(...)
#endif #endif
#define DEFAULT_FDT_VERSION 17 #define DEFAULT_FDT_VERSION 17
/* /*
@ -114,7 +113,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m,
struct data data_merge(struct data d1, struct data d2); struct data data_merge(struct data d1, struct data d2);
struct data data_append_cell(struct data d, cell_t word); struct data data_append_cell(struct data d, cell_t word);
struct data data_append_integer(struct data d, uint64_t word, int bits); struct data data_append_integer(struct data d, uint64_t word, int bits);
struct data data_append_re(struct data d, const struct fdt_reserve_entry *re); struct data data_append_re(struct data d, uint64_t address, uint64_t size);
struct data data_append_addr(struct data d, uint64_t addr); struct data data_append_addr(struct data d, uint64_t addr);
struct data data_append_byte(struct data d, uint8_t byte); struct data data_append_byte(struct data d, uint8_t byte);
struct data data_append_zeroes(struct data d, int len); struct data data_append_zeroes(struct data d, int len);
@ -136,6 +135,10 @@ struct label {
struct label *next; struct label *next;
}; };
struct bus_type {
const char *name;
};
struct property { struct property {
bool deleted; bool deleted;
char *name; char *name;
@ -162,6 +165,7 @@ struct node {
int addr_cells, size_cells; int addr_cells, size_cells;
struct label *labels; struct label *labels;
const struct bus_type *bus;
}; };
#define for_each_label_withdel(l0, l) \ #define for_each_label_withdel(l0, l) \
@ -227,7 +231,7 @@ uint32_t guess_boot_cpuid(struct node *tree);
/* Boot info (tree plus memreserve information */ /* Boot info (tree plus memreserve information */
struct reserve_info { struct reserve_info {
struct fdt_reserve_entry re; uint64_t address, size;
struct reserve_info *next; struct reserve_info *next;
@ -246,6 +250,7 @@ struct dt_info {
struct reserve_info *reservelist; struct reserve_info *reservelist;
uint32_t boot_cpuid_phys; uint32_t boot_cpuid_phys;
struct node *dt; /* the device tree */ struct node *dt; /* the device tree */
const char *outname; /* filename being written to, "-" for stdout */
}; };
/* DTS version flags definitions */ /* DTS version flags definitions */

View File

@ -49,7 +49,7 @@ static struct version_info {
struct emitter { struct emitter {
void (*cell)(void *, cell_t); void (*cell)(void *, cell_t);
void (*string)(void *, char *, int); void (*string)(void *, const char *, int);
void (*align)(void *, int); void (*align)(void *, int);
void (*data)(void *, struct data); void (*data)(void *, struct data);
void (*beginnode)(void *, struct label *labels); void (*beginnode)(void *, struct label *labels);
@ -64,7 +64,7 @@ static void bin_emit_cell(void *e, cell_t val)
*dtbuf = data_append_cell(*dtbuf, val); *dtbuf = data_append_cell(*dtbuf, val);
} }
static void bin_emit_string(void *e, char *str, int len) static void bin_emit_string(void *e, const char *str, int len)
{ {
struct data *dtbuf = e; struct data *dtbuf = e;
@ -144,22 +144,14 @@ static void asm_emit_cell(void *e, cell_t val)
(val >> 8) & 0xff, val & 0xff); (val >> 8) & 0xff, val & 0xff);
} }
static void asm_emit_string(void *e, char *str, int len) static void asm_emit_string(void *e, const char *str, int len)
{ {
FILE *f = e; FILE *f = e;
char c = 0;
if (len != 0) { if (len != 0)
/* XXX: ewww */ fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
c = str[len]; else
str[len] = '\0'; fprintf(f, "\t.string\t\"%s\"\n", str);
}
fprintf(f, "\t.string\t\"%s\"\n", str);
if (len != 0) {
str[len] = c;
}
} }
static void asm_emit_align(void *e, int a) static void asm_emit_align(void *e, int a)
@ -179,7 +171,7 @@ static void asm_emit_data(void *e, struct data d)
emit_offset_label(f, m->ref, m->offset); emit_offset_label(f, m->ref, m->offset);
while ((d.len - off) >= sizeof(uint32_t)) { while ((d.len - off) >= sizeof(uint32_t)) {
asm_emit_cell(e, fdt32_to_cpu(*((uint32_t *)(d.val+off)))); asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off))));
off += sizeof(uint32_t); off += sizeof(uint32_t);
} }
@ -318,17 +310,16 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
{ {
struct reserve_info *re; struct reserve_info *re;
struct data d = empty_data; struct data d = empty_data;
static struct fdt_reserve_entry null_re = {0,0};
int j; int j;
for (re = reservelist; re; re = re->next) { for (re = reservelist; re; re = re->next) {
d = data_append_re(d, &re->re); d = data_append_re(d, re->address, re->size);
} }
/* /*
* Add additional reserved slots if the user asked for them. * Add additional reserved slots if the user asked for them.
*/ */
for (j = 0; j < reservenum; j++) { for (j = 0; j < reservenum; j++) {
d = data_append_re(d, &null_re); d = data_append_re(d, 0, 0);
} }
return d; return d;
@ -544,11 +535,11 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)
fprintf(f, "\t.globl\t%s\n", l->label); fprintf(f, "\t.globl\t%s\n", l->label);
fprintf(f, "%s:\n", l->label); fprintf(f, "%s:\n", l->label);
} }
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32)); ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->address >> 32));
ASM_EMIT_BELONG(f, "0x%08x", ASM_EMIT_BELONG(f, "0x%08x",
(unsigned int)(re->re.address & 0xffffffff)); (unsigned int)(re->address & 0xffffffff));
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32)); ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32));
ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff)); ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff));
} }
for (i = 0; i < reservenum; i++) { for (i = 0; i < reservenum; i++) {
fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n"); fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
@ -609,7 +600,7 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len)
static uint32_t flat_read_word(struct inbuf *inb) static uint32_t flat_read_word(struct inbuf *inb)
{ {
uint32_t val; fdt32_t val;
assert(((inb->ptr - inb->base) % sizeof(val)) == 0); assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
@ -718,13 +709,15 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
* First pass, count entries. * First pass, count entries.
*/ */
while (1) { while (1) {
uint64_t address, size;
flat_read_chunk(inb, &re, sizeof(re)); flat_read_chunk(inb, &re, sizeof(re));
re.address = fdt64_to_cpu(re.address); address = fdt64_to_cpu(re.address);
re.size = fdt64_to_cpu(re.size); size = fdt64_to_cpu(re.size);
if (re.size == 0) if (size == 0)
break; break;
new = build_reserve_entry(re.address, re.size); new = build_reserve_entry(address, size);
reservelist = add_reserve_entry(reservelist, new); reservelist = add_reserve_entry(reservelist, new);
} }
@ -817,6 +810,7 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
struct dt_info *dt_from_blob(const char *fname) struct dt_info *dt_from_blob(const char *fname)
{ {
FILE *f; FILE *f;
fdt32_t magic_buf, totalsize_buf;
uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys; uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
uint32_t off_dt, off_str, off_mem_rsvmap; uint32_t off_dt, off_str, off_mem_rsvmap;
int rc; int rc;
@ -833,7 +827,7 @@ struct dt_info *dt_from_blob(const char *fname)
f = srcfile_relative_open(fname, NULL); f = srcfile_relative_open(fname, NULL);
rc = fread(&magic, sizeof(magic), 1, f); rc = fread(&magic_buf, sizeof(magic_buf), 1, f);
if (ferror(f)) if (ferror(f))
die("Error reading DT blob magic number: %s\n", die("Error reading DT blob magic number: %s\n",
strerror(errno)); strerror(errno));
@ -844,11 +838,11 @@ struct dt_info *dt_from_blob(const char *fname)
die("Mysterious short read reading magic number\n"); die("Mysterious short read reading magic number\n");
} }
magic = fdt32_to_cpu(magic); magic = fdt32_to_cpu(magic_buf);
if (magic != FDT_MAGIC) if (magic != FDT_MAGIC)
die("Blob has incorrect magic number\n"); die("Blob has incorrect magic number\n");
rc = fread(&totalsize, sizeof(totalsize), 1, f); rc = fread(&totalsize_buf, sizeof(totalsize_buf), 1, f);
if (ferror(f)) if (ferror(f))
die("Error reading DT blob size: %s\n", strerror(errno)); die("Error reading DT blob size: %s\n", strerror(errno));
if (rc < 1) { if (rc < 1) {
@ -858,7 +852,7 @@ struct dt_info *dt_from_blob(const char *fname)
die("Mysterious short read reading blob size\n"); die("Mysterious short read reading blob size\n");
} }
totalsize = fdt32_to_cpu(totalsize); totalsize = fdt32_to_cpu(totalsize_buf);
if (totalsize < FDT_V1_SIZE) if (totalsize < FDT_V1_SIZE)
die("DT blob size (%d) is too small\n", totalsize); die("DT blob size (%d) is too small\n", totalsize);

View File

@ -283,7 +283,8 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
if (err) if (err)
return err; return err;
memcpy(prop->data, val, len); if (len)
memcpy(prop->data, val, len);
return 0; return 0;
} }

View File

@ -143,7 +143,9 @@
/* Low-level functions (you probably don't need these) */ /* Low-level functions (you probably don't need these) */
/**********************************************************************/ /**********************************************************************/
#ifndef SWIG /* This function is not useful in Python */
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
#endif
static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
{ {
return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
@ -210,7 +212,6 @@ int fdt_next_subnode(const void *fdt, int offset);
/**********************************************************************/ /**********************************************************************/
/* General functions */ /* General functions */
/**********************************************************************/ /**********************************************************************/
#define fdt_get_header(fdt, field) \ #define fdt_get_header(fdt, field) \
(fdt32_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))
@ -354,8 +355,10 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
* useful for finding subnodes based on a portion of a larger string, * useful for finding subnodes based on a portion of a larger string,
* such as a full path. * such as a full path.
*/ */
#ifndef SWIG /* Not available in Python */
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
const char *name, int namelen); const char *name, int namelen);
#endif
/** /**
* fdt_subnode_offset - find a subnode of a given node * fdt_subnode_offset - find a subnode of a given node
* @fdt: pointer to the device tree blob * @fdt: pointer to the device tree blob
@ -391,7 +394,9 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
* Identical to fdt_path_offset(), but only consider the first namelen * Identical to fdt_path_offset(), but only consider the first namelen
* characters of path as the path name. * characters of path as the path name.
*/ */
#ifndef SWIG /* Not available in Python */
int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
#endif
/** /**
* fdt_path_offset - find a tree node by its full path * fdt_path_offset - find a tree node by its full path
@ -550,10 +555,12 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
* Identical to fdt_get_property(), but only examine the first namelen * Identical to fdt_get_property(), but only examine the first namelen
* characters of name for matching the property name. * characters of name for matching the property name.
*/ */
#ifndef SWIG /* Not available in Python */
const struct fdt_property *fdt_get_property_namelen(const void *fdt, const struct fdt_property *fdt_get_property_namelen(const void *fdt,
int nodeoffset, int nodeoffset,
const char *name, const char *name,
int namelen, int *lenp); int namelen, int *lenp);
#endif
/** /**
* fdt_get_property - find a given property in a given node * fdt_get_property - find a given property in a given node
@ -624,8 +631,10 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
* -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_TRUNCATED, standard meanings * -FDT_ERR_TRUNCATED, standard meanings
*/ */
#ifndef SWIG /* This function is not useful in Python */
const void *fdt_getprop_by_offset(const void *fdt, int offset, const void *fdt_getprop_by_offset(const void *fdt, int offset,
const char **namep, int *lenp); const char **namep, int *lenp);
#endif
/** /**
* fdt_getprop_namelen - get property value based on substring * fdt_getprop_namelen - get property value based on substring
@ -638,6 +647,7 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
* Identical to fdt_getprop(), but only examine the first namelen * Identical to fdt_getprop(), but only examine the first namelen
* characters of name for matching the property name. * characters of name for matching the property name.
*/ */
#ifndef SWIG /* Not available in Python */
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, static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
@ -647,6 +657,7 @@ static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name, return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
namelen, lenp); namelen, lenp);
} }
#endif
/** /**
* fdt_getprop - retrieve the value of a given property * fdt_getprop - retrieve the value of a given property
@ -707,8 +718,10 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
* Identical to fdt_get_alias(), but only examine the first namelen * Identical to fdt_get_alias(), but only examine the first namelen
* characters of name for matching the alias name. * characters of name for matching the alias name.
*/ */
#ifndef SWIG /* Not available in Python */
const char *fdt_get_alias_namelen(const void *fdt, const char *fdt_get_alias_namelen(const void *fdt,
const char *name, int namelen); const char *name, int namelen);
#endif
/** /**
* fdt_get_alias - retrieve the path referenced by a given alias * fdt_get_alias - retrieve the path referenced by a given alias
@ -1106,10 +1119,12 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
* of the name. It is useful when you want to manipulate only one value of * 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. * an array and you have a string that doesn't end with \0.
*/ */
#ifndef SWIG /* Not available in Python */
int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
const char *name, int namelen, const char *name, int namelen,
uint32_t idx, const void *val, uint32_t idx, const void *val,
int len); int len);
#endif
/** /**
* fdt_setprop_inplace - change a property's value, but not its size * fdt_setprop_inplace - change a property's value, but not its size
@ -1139,8 +1154,10 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
* -FDT_ERR_BADSTRUCTURE, * -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_TRUNCATED, standard meanings * -FDT_ERR_TRUNCATED, standard meanings
*/ */
#ifndef SWIG /* Not available in Python */
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
const void *val, int len); const void *val, int len);
#endif
/** /**
* fdt_setprop_inplace_u32 - change the value of a 32-bit integer property * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
@ -1527,6 +1544,36 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
#define fdt_setprop_string(fdt, nodeoffset, name, str) \ #define fdt_setprop_string(fdt, nodeoffset, name, str) \
fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
/**
* fdt_setprop_empty - set a property to an empty value
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
*
* fdt_setprop_empty() sets the value of the named property in the
* given node to an empty (zero length) value, or creates a new empty
* property if it does not already exist.
*
* This function may insert or delete data from the blob, and will
* therefore change the offsets of some existing nodes.
*
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
* contain the new property value
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
#define fdt_setprop_empty(fdt, nodeoffset, name) \
fdt_setprop((fdt), (nodeoffset), (name), NULL, 0)
/** /**
* fdt_appendprop - append to or create a property * fdt_appendprop - append to or create a property
* @fdt: pointer to the device tree blob * @fdt: pointer to the device tree blob
@ -1704,8 +1751,10 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
* creating subnodes based on a portion of a larger string, such as a * creating subnodes based on a portion of a larger string, such as a
* full path. * full path.
*/ */
#ifndef SWIG /* Not available in Python */
int fdt_add_subnode_namelen(void *fdt, int parentoffset, int fdt_add_subnode_namelen(void *fdt, int parentoffset,
const char *name, int namelen); const char *name, int namelen);
#endif
/** /**
* fdt_add_subnode - creates a new node * fdt_add_subnode - creates a new node

View File

@ -58,16 +58,16 @@
#include <string.h> #include <string.h>
#ifdef __CHECKER__ #ifdef __CHECKER__
#define __force __attribute__((force)) #define FDT_FORCE __attribute__((force))
#define __bitwise __attribute__((bitwise)) #define FDT_BITWISE __attribute__((bitwise))
#else #else
#define __force #define FDT_FORCE
#define __bitwise #define FDT_BITWISE
#endif #endif
typedef uint16_t __bitwise fdt16_t; typedef uint16_t FDT_BITWISE fdt16_t;
typedef uint32_t __bitwise fdt32_t; typedef uint32_t FDT_BITWISE fdt32_t;
typedef uint64_t __bitwise fdt64_t; typedef uint64_t FDT_BITWISE fdt64_t;
#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n]) #define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n])
#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) #define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1))
@ -80,29 +80,29 @@ typedef uint64_t __bitwise fdt64_t;
static inline uint16_t fdt16_to_cpu(fdt16_t x) static inline uint16_t fdt16_to_cpu(fdt16_t x)
{ {
return (__force uint16_t)CPU_TO_FDT16(x); return (FDT_FORCE uint16_t)CPU_TO_FDT16(x);
} }
static inline fdt16_t cpu_to_fdt16(uint16_t x) static inline fdt16_t cpu_to_fdt16(uint16_t x)
{ {
return (__force fdt16_t)CPU_TO_FDT16(x); return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x);
} }
static inline uint32_t fdt32_to_cpu(fdt32_t x) static inline uint32_t fdt32_to_cpu(fdt32_t x)
{ {
return (__force uint32_t)CPU_TO_FDT32(x); return (FDT_FORCE uint32_t)CPU_TO_FDT32(x);
} }
static inline fdt32_t cpu_to_fdt32(uint32_t x) static inline fdt32_t cpu_to_fdt32(uint32_t x)
{ {
return (__force fdt32_t)CPU_TO_FDT32(x); return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x);
} }
static inline uint64_t fdt64_to_cpu(fdt64_t x) static inline uint64_t fdt64_to_cpu(fdt64_t x)
{ {
return (__force uint64_t)CPU_TO_FDT64(x); return (FDT_FORCE uint64_t)CPU_TO_FDT64(x);
} }
static inline fdt64_t cpu_to_fdt64(uint64_t x) static inline fdt64_t cpu_to_fdt64(uint64_t x)
{ {
return (__force fdt64_t)CPU_TO_FDT64(x); return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x);
} }
#undef CPU_TO_FDT64 #undef CPU_TO_FDT64
#undef CPU_TO_FDT32 #undef CPU_TO_FDT32

View File

@ -242,7 +242,7 @@ void delete_property_by_name(struct node *node, char *name)
struct property *prop = node->proplist; struct property *prop = node->proplist;
while (prop) { while (prop) {
if (!strcmp(prop->name, name)) { if (streq(prop->name, name)) {
delete_property(prop); delete_property(prop);
return; return;
} }
@ -275,7 +275,7 @@ void delete_node_by_name(struct node *parent, char *name)
struct node *node = parent->children; struct node *node = parent->children;
while (node) { while (node) {
if (!strcmp(node->name, name)) { if (streq(node->name, name)) {
delete_node(node); delete_node(node);
return; return;
} }
@ -319,8 +319,8 @@ struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
memset(new, 0, sizeof(*new)); memset(new, 0, sizeof(*new));
new->re.address = address; new->address = address;
new->re.size = size; new->size = size;
return new; return new;
} }
@ -393,7 +393,7 @@ struct property *get_property(struct node *node, const char *propname)
cell_t propval_cell(struct property *prop) cell_t propval_cell(struct property *prop)
{ {
assert(prop->val.len == sizeof(cell_t)); assert(prop->val.len == sizeof(cell_t));
return fdt32_to_cpu(*((cell_t *)prop->val.val)); return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
} }
struct property *get_property_by_label(struct node *tree, const char *label, struct property *get_property_by_label(struct node *tree, const char *label,
@ -599,13 +599,13 @@ static int cmp_reserve_info(const void *ax, const void *bx)
a = *((const struct reserve_info * const *)ax); a = *((const struct reserve_info * const *)ax);
b = *((const struct reserve_info * const *)bx); b = *((const struct reserve_info * const *)bx);
if (a->re.address < b->re.address) if (a->address < b->address)
return -1; return -1;
else if (a->re.address > b->re.address) else if (a->address > b->address)
return 1; return 1;
else if (a->re.size < b->re.size) else if (a->size < b->size)
return -1; return -1;
else if (a->re.size > b->re.size) else if (a->size > b->size)
return 1; return 1;
else else
return 0; return 0;
@ -847,6 +847,8 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn,
xasprintf(&entry, "%s:%s:%u", xasprintf(&entry, "%s:%s:%u",
node->fullpath, prop->name, m->offset); node->fullpath, prop->name, m->offset);
append_to_property(fn, m->ref, entry, strlen(entry) + 1); append_to_property(fn, m->ref, entry, strlen(entry) + 1);
free(entry);
} }
static void generate_fixups_tree_internal(struct dt_info *dti, static void generate_fixups_tree_internal(struct dt_info *dti,
@ -900,7 +902,7 @@ static void add_local_fixup_entry(struct dt_info *dti,
struct node *refnode) struct node *refnode)
{ {
struct node *wn, *nwn; /* local fixup node, walk node, new */ struct node *wn, *nwn; /* local fixup node, walk node, new */
uint32_t value_32; fdt32_t value_32;
char **compp; char **compp;
int i, depth; int i, depth;

View File

@ -252,7 +252,7 @@ srcpos_string(struct srcpos *pos)
const char *fname = "<no-file>"; const char *fname = "<no-file>";
char *pos_str; char *pos_str;
if (pos) if (pos->file && pos->file->name)
fname = pos->file->name; fname = pos->file->name;

View File

@ -22,6 +22,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include "util.h"
struct srcfile_state { struct srcfile_state {
FILE *f; FILE *f;
@ -106,12 +107,10 @@ 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_verror(struct srcpos *pos, const char *prefix, extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix,
const char *fmt, va_list va) const char *fmt, va_list va);
__attribute__((format(printf, 3, 0))); extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix,
extern void srcpos_error(struct srcpos *pos, const char *prefix, const char *fmt, ...);
const char *fmt, ...)
__attribute__((format(printf, 3, 4)));
extern void srcpos_set_line(char *f, int l); extern void srcpos_set_line(char *f, int l);

View File

@ -137,7 +137,7 @@ static void write_propval_string(FILE *f, struct data val)
static void write_propval_cells(FILE *f, struct data val) static void write_propval_cells(FILE *f, struct data val)
{ {
void *propend = val.val + val.len; void *propend = val.val + val.len;
cell_t *cp = (cell_t *)val.val; fdt32_t *cp = (fdt32_t *)val.val;
struct marker *m = val.markers; struct marker *m = val.markers;
fprintf(f, "<"); fprintf(f, "<");
@ -275,8 +275,8 @@ void dt_to_source(FILE *f, struct dt_info *dti)
for_each_label(re->labels, l) for_each_label(re->labels, l)
fprintf(f, "%s: ", l->label); fprintf(f, "%s: ", l->label);
fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n", fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
(unsigned long long)re->re.address, (unsigned long long)re->address,
(unsigned long long)re->re.size); (unsigned long long)re->size);
} }
write_tree_source_node(f, dti->dt, 0); write_tree_source_node(f, dti->dt, 0);

View File

@ -396,7 +396,7 @@ void utilfdt_print_data(const char *data, int len)
} while (s < data + len); } while (s < data + len);
} else if ((len % 4) == 0) { } else if ((len % 4) == 0) {
const uint32_t *cell = (const uint32_t *)data; const fdt32_t *cell = (const fdt32_t *)data;
printf(" = <"); printf(" = <");
for (i = 0, len /= 4; i < len; i++) for (i = 0, len /= 4; i < len; i++)
@ -412,15 +412,16 @@ void utilfdt_print_data(const char *data, int len)
} }
} }
void util_version(void) void NORETURN util_version(void)
{ {
printf("Version: %s\n", DTC_VERSION); printf("Version: %s\n", DTC_VERSION);
exit(0); exit(0);
} }
void util_usage(const char *errmsg, const char *synopsis, void NORETURN util_usage(const char *errmsg, const char *synopsis,
const char *short_opts, struct option const long_opts[], const char *short_opts,
const char * const opts_help[]) struct option const long_opts[],
const char * const opts_help[])
{ {
FILE *fp = errmsg ? stderr : stdout; FILE *fp = errmsg ? stderr : stdout;
const char a_arg[] = "<arg>"; const char a_arg[] = "<arg>";

View File

@ -25,9 +25,17 @@
* USA * USA
*/ */
#ifdef __GNUC__
#define PRINTF(i, j) __attribute__((format (printf, i, j)))
#define NORETURN __attribute__((noreturn))
#else
#define PRINTF(i, j)
#define NORETURN
#endif
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
static inline void __attribute__((noreturn)) die(const char *str, ...) static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
{ {
va_list ap; va_list ap;
@ -53,13 +61,14 @@ static inline void *xrealloc(void *p, size_t len)
void *new = realloc(p, len); void *new = realloc(p, len);
if (!new) if (!new)
die("realloc() failed (len=%d)\n", len); die("realloc() failed (len=%zd)\n", len);
return new; return new;
} }
extern char *xstrdup(const char *s); extern char *xstrdup(const char *s);
extern int xasprintf(char **strp, const char *fmt, ...);
extern int PRINTF(2, 3) 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);
/** /**
@ -188,7 +197,7 @@ void utilfdt_print_data(const char *data, int len);
/** /**
* Show source version and exit * Show source version and exit
*/ */
void util_version(void) __attribute__((noreturn)); void NORETURN util_version(void);
/** /**
* Show usage and exit * Show usage and exit
@ -202,9 +211,10 @@ void util_version(void) __attribute__((noreturn));
* @param long_opts The structure of long options * @param long_opts The structure of long options
* @param opts_help An array of help strings (should align with long_opts) * @param opts_help An array of help strings (should align with long_opts)
*/ */
void util_usage(const char *errmsg, const char *synopsis, void NORETURN util_usage(const char *errmsg, const char *synopsis,
const char *short_opts, struct option const long_opts[], const char *short_opts,
const char * const opts_help[]) __attribute__((noreturn)); struct option const long_opts[],
const char * const opts_help[]);
/** /**
* Show usage and exit * Show usage and exit

View File

@ -1 +1 @@
#define DTC_VERSION "DTC 1.4.2-g0931cea3" #define DTC_VERSION "DTC 1.4.4-g756ffc4f"