10404 lines
320 KiB
Diff
10404 lines
320 KiB
Diff
From 33d62d2531ec28a54acd9392c38e621d2a72472b Mon Sep 17 00:00:00 2001
|
|
From: Pascal Vizeli <pvizeli@syshack.ch>
|
|
Date: Tue, 5 Jun 2018 22:35:03 +0000
|
|
Subject: [PATCH 1/2] scripts/dtc: Update to upstream version 1.4.6
|
|
|
|
Signed-off-by: Pascal Vizeli <pvizeli@syshack.ch>
|
|
---
|
|
scripts/dtc/.gitignore | 1 -
|
|
scripts/dtc/Makefile | 8 +-
|
|
scripts/dtc/checks.c | 1194 +++++++++++++++++++++-----
|
|
scripts/dtc/data.c | 16 +-
|
|
scripts/dtc/dtc-lexer.l | 63 +-
|
|
scripts/dtc/dtc-lexer.lex.c_shipped | 894 +++++++++----------
|
|
scripts/dtc/dtc-parser.tab.c_shipped | 813 ++++++++++--------
|
|
scripts/dtc/dtc-parser.tab.h_shipped | 54 +-
|
|
scripts/dtc/dtc-parser.y | 91 +-
|
|
scripts/dtc/dtc.c | 139 ++-
|
|
scripts/dtc/dtc.h | 62 +-
|
|
scripts/dtc/fdt.c | 24 +-
|
|
scripts/dtc/fdt.h | 6 +-
|
|
scripts/dtc/fdt_empty_tree.c | 1 -
|
|
scripts/dtc/fdt_overlay.c | 912 ++++++++++++++++++++
|
|
scripts/dtc/fdt_ro.c | 288 ++++++-
|
|
scripts/dtc/fdt_rw.c | 121 +--
|
|
scripts/dtc/fdt_strerror.c | 6 +
|
|
scripts/dtc/fdt_sw.c | 40 +-
|
|
scripts/dtc/fdt_wip.c | 43 +-
|
|
scripts/dtc/fdtdump.c | 136 +--
|
|
scripts/dtc/fdtget.c | 60 +-
|
|
scripts/dtc/fdtput.c | 142 ++-
|
|
scripts/dtc/flattree.c | 105 +--
|
|
scripts/dtc/fstree.c | 5 +-
|
|
scripts/dtc/libfdt.h | 429 +++++++--
|
|
scripts/dtc/libfdt_env.h | 60 +-
|
|
scripts/dtc/libfdt_internal.h | 32 +-
|
|
scripts/dtc/livetree.c | 356 +++++++-
|
|
scripts/dtc/srcpos.c | 42 +-
|
|
scripts/dtc/srcpos.h | 18 +-
|
|
scripts/dtc/treesource.c | 20 +-
|
|
scripts/dtc/update-dtc-source.sh | 46 +-
|
|
scripts/dtc/util.c | 44 +-
|
|
scripts/dtc/util.h | 33 +-
|
|
scripts/dtc/version_gen.h | 2 +-
|
|
36 files changed, 4578 insertions(+), 1728 deletions(-)
|
|
create mode 100644 scripts/dtc/fdt_overlay.c
|
|
|
|
diff --git a/scripts/dtc/.gitignore b/scripts/dtc/.gitignore
|
|
index 80f6b50fd..cdabdc95a 100644
|
|
--- a/scripts/dtc/.gitignore
|
|
+++ b/scripts/dtc/.gitignore
|
|
@@ -2,4 +2,3 @@ dtc
|
|
dtc-lexer.lex.c
|
|
dtc-parser.tab.c
|
|
dtc-parser.tab.h
|
|
-fdtget
|
|
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
|
|
index 05973b12a..06aaa8c55 100644
|
|
--- a/scripts/dtc/Makefile
|
|
+++ b/scripts/dtc/Makefile
|
|
@@ -1,17 +1,15 @@
|
|
# scripts/dtc makefile
|
|
|
|
-hostprogs-y := dtc fdtget
|
|
+hostprogs-y := dtc
|
|
always := $(hostprogs-y)
|
|
|
|
dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
|
|
srcpos.o checks.o util.o
|
|
dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
|
|
|
|
-libfdt-objs = fdt.o fdt_ro.o fdt_strerror.o fdt_wip.o
|
|
+libfdt-objs = fdt.o fdt_ro.o fdt_strerror.o fdt_wip.o fdt_overlay.o
|
|
libfdt-objs += fdt_empty_tree.o fdt_rw.o fdt_sw.o
|
|
|
|
-fdtget-objs += fdtget.o $(libfdt-objs) util.o
|
|
-
|
|
# Source files need to get at the userspace version of libfdt_env.h to compile
|
|
|
|
HOSTCFLAGS_DTC := -I$(src)
|
|
@@ -33,7 +31,7 @@ HOSTCFLAGS_fdt_wip.o := $(HOSTCFLAGS_DTC)
|
|
HOSTCFLAGS_fdt_empty_tree.o := $(HOSTCFLAGS_DTC)
|
|
HOSTCFLAGS_fdt_rw.o := $(HOSTCFLAGS_DTC)
|
|
HOSTCFLAGS_fdt_sw.o := $(HOSTCFLAGS_DTC)
|
|
-HOSTCFLAGS_fdtget.o := $(HOSTCFLAGS_DTC)
|
|
+HOSTCFLAGS_fdt_overlay.o := $(HOSTCFLAGS_DTC)
|
|
|
|
HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC)
|
|
HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)
|
|
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
|
|
index 3bf0fa4a4..815eaf140 100644
|
|
--- a/scripts/dtc/checks.c
|
|
+++ b/scripts/dtc/checks.c
|
|
@@ -40,16 +40,11 @@ enum checkstatus {
|
|
|
|
struct check;
|
|
|
|
-typedef void (*tree_check_fn)(struct check *c, struct node *dt);
|
|
-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);
|
|
+typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node);
|
|
|
|
struct check {
|
|
const char *name;
|
|
- tree_check_fn tree_fn;
|
|
- node_check_fn node_fn;
|
|
- prop_check_fn prop_fn;
|
|
+ check_fn fn;
|
|
void *data;
|
|
bool warn, error;
|
|
enum checkstatus status;
|
|
@@ -58,91 +53,80 @@ struct check {
|
|
struct check **prereq;
|
|
};
|
|
|
|
-#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...) \
|
|
- static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
|
|
- static struct check nm = { \
|
|
- .name = #nm, \
|
|
- .tree_fn = (tfn), \
|
|
- .node_fn = (nfn), \
|
|
- .prop_fn = (pfn), \
|
|
- .data = (d), \
|
|
- .warn = (w), \
|
|
- .error = (e), \
|
|
+#define CHECK_ENTRY(nm_, fn_, d_, w_, e_, ...) \
|
|
+ static struct check *nm_##_prereqs[] = { __VA_ARGS__ }; \
|
|
+ static struct check nm_ = { \
|
|
+ .name = #nm_, \
|
|
+ .fn = (fn_), \
|
|
+ .data = (d_), \
|
|
+ .warn = (w_), \
|
|
+ .error = (e_), \
|
|
.status = UNCHECKED, \
|
|
- .num_prereqs = ARRAY_SIZE(nm##_prereqs), \
|
|
- .prereq = nm##_prereqs, \
|
|
+ .num_prereqs = ARRAY_SIZE(nm_##_prereqs), \
|
|
+ .prereq = nm_##_prereqs, \
|
|
};
|
|
-#define WARNING(nm, tfn, nfn, pfn, d, ...) \
|
|
- CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
|
|
-#define ERROR(nm, tfn, nfn, pfn, d, ...) \
|
|
- CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__)
|
|
-#define CHECK(nm, tfn, nfn, pfn, d, ...) \
|
|
- CHECK_ENTRY(nm, tfn, nfn, pfn, 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__
|
|
-static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
|
|
-#endif
|
|
-static inline void check_msg(struct check *c, const char *fmt, ...)
|
|
+#define WARNING(nm_, fn_, d_, ...) \
|
|
+ CHECK_ENTRY(nm_, fn_, d_, true, false, __VA_ARGS__)
|
|
+#define ERROR(nm_, fn_, d_, ...) \
|
|
+ CHECK_ENTRY(nm_, fn_, d_, false, true, __VA_ARGS__)
|
|
+#define CHECK(nm_, fn_, d_, ...) \
|
|
+ CHECK_ENTRY(nm_, fn_, d_, false, false, __VA_ARGS__)
|
|
+
|
|
+static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti,
|
|
+ struct node *node,
|
|
+ struct property *prop,
|
|
+ const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
|
|
if ((c->warn && (quiet < 1))
|
|
|| (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);
|
|
+ if (node) {
|
|
+ fprintf(stderr, "%s", node->fullpath);
|
|
+ if (prop)
|
|
+ fprintf(stderr, ":%s", prop->name);
|
|
+ fputs(": ", stderr);
|
|
+ }
|
|
vfprintf(stderr, fmt, ap);
|
|
fprintf(stderr, "\n");
|
|
}
|
|
+ va_end(ap);
|
|
}
|
|
|
|
-#define FAIL(c, ...) \
|
|
- do { \
|
|
- TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
|
|
- (c)->status = FAILED; \
|
|
- check_msg((c), __VA_ARGS__); \
|
|
+#define FAIL(c, dti, node, ...) \
|
|
+ do { \
|
|
+ TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
|
|
+ (c)->status = FAILED; \
|
|
+ check_msg((c), dti, node, NULL, __VA_ARGS__); \
|
|
} while (0)
|
|
|
|
-static void check_nodes_props(struct check *c, struct node *dt, struct node *node)
|
|
+#define FAIL_PROP(c, dti, node, prop, ...) \
|
|
+ do { \
|
|
+ TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
|
|
+ (c)->status = FAILED; \
|
|
+ check_msg((c), dti, node, prop, __VA_ARGS__); \
|
|
+ } while (0)
|
|
+
|
|
+
|
|
+static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node)
|
|
{
|
|
struct node *child;
|
|
- struct property *prop;
|
|
|
|
TRACE(c, "%s", node->fullpath);
|
|
- if (c->node_fn)
|
|
- c->node_fn(c, dt, 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);
|
|
- }
|
|
+ if (c->fn)
|
|
+ c->fn(c, dti, node);
|
|
|
|
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;
|
|
int i;
|
|
|
|
@@ -155,10 +139,10 @@ static bool run_check(struct check *c, struct node *dt)
|
|
|
|
for (i = 0; i < c->num_prereqs; i++) {
|
|
struct check *prq = c->prereq[i];
|
|
- error = error || run_check(prq, dt);
|
|
+ error = error || run_check(prq, dti);
|
|
if (prq->status != PASSED) {
|
|
c->status = PREREQ;
|
|
- check_msg(c, "Failed prerequisite '%s'",
|
|
+ check_msg(c, dti, NULL, NULL, "Failed prerequisite '%s'",
|
|
c->prereq[i]->name);
|
|
}
|
|
}
|
|
@@ -166,11 +150,8 @@ static bool run_check(struct check *c, struct node *dt)
|
|
if (c->status != UNCHECKED)
|
|
goto out;
|
|
|
|
- if (c->node_fn || c->prop_fn)
|
|
- check_nodes_props(c, dt, dt);
|
|
+ check_nodes_props(c, dti, dt);
|
|
|
|
- if (c->tree_fn)
|
|
- c->tree_fn(c, dt);
|
|
if (c->status == UNCHECKED)
|
|
c->status = PASSED;
|
|
|
|
@@ -188,13 +169,14 @@ out:
|
|
*/
|
|
|
|
/* 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, dti, node, "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 property *prop;
|
|
@@ -205,15 +187,43 @@ static void check_is_string(struct check *c, struct node *root,
|
|
return; /* Not present, assumed ok */
|
|
|
|
if (!data_is_one_string(prop->val))
|
|
- FAIL(c, "\"%s\" property in %s is not a string",
|
|
- propname, node->fullpath);
|
|
+ FAIL_PROP(c, dti, node, prop, "property is not a string");
|
|
}
|
|
#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) \
|
|
- ERROR(nm, NULL, check_is_string, NULL, (propname))
|
|
+ ERROR(nm, check_is_string, (propname))
|
|
+
|
|
+static void check_is_string_list(struct check *c, struct dt_info *dti,
|
|
+ struct node *node)
|
|
+{
|
|
+ int rem, l;
|
|
+ struct property *prop;
|
|
+ char *propname = c->data;
|
|
+ char *str;
|
|
+
|
|
+ prop = get_property(node, propname);
|
|
+ if (!prop)
|
|
+ return; /* Not present, assumed ok */
|
|
+
|
|
+ str = prop->val.val;
|
|
+ rem = prop->val.len;
|
|
+ while (rem > 0) {
|
|
+ l = strnlen(str, rem);
|
|
+ if (l == rem) {
|
|
+ FAIL_PROP(c, dti, node, prop, "property is not a string list");
|
|
+ break;
|
|
+ }
|
|
+ rem -= l + 1;
|
|
+ str += l + 1;
|
|
+ }
|
|
+}
|
|
+#define WARNING_IF_NOT_STRING_LIST(nm, propname) \
|
|
+ WARNING(nm, check_is_string_list, (propname))
|
|
+#define ERROR_IF_NOT_STRING_LIST(nm, propname) \
|
|
+ ERROR(nm, check_is_string_list, (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 property *prop;
|
|
@@ -224,19 +234,18 @@ static void check_is_cell(struct check *c, struct node *root,
|
|
return; /* Not present, assumed ok */
|
|
|
|
if (prop->val.len != sizeof(cell_t))
|
|
- FAIL(c, "\"%s\" property in %s is not a single cell",
|
|
- propname, node->fullpath);
|
|
+ FAIL_PROP(c, dti, node, prop, "property is not a single cell");
|
|
}
|
|
#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) \
|
|
- ERROR(nm, NULL, check_is_cell, NULL, (propname))
|
|
+ ERROR(nm, check_is_cell, (propname))
|
|
|
|
/*
|
|
* 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 *child, *child2;
|
|
@@ -246,12 +255,11 @@ static void check_duplicate_node_names(struct check *c, struct node *dt,
|
|
child2;
|
|
child2 = child2->next_sibling)
|
|
if (streq(child->name, child2->name))
|
|
- FAIL(c, "Duplicate node name %s",
|
|
- child->fullpath);
|
|
+ FAIL(c, dti, node, "Duplicate node name");
|
|
}
|
|
-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 property *prop, *prop2;
|
|
@@ -261,48 +269,116 @@ static void check_duplicate_property_names(struct check *c, struct node *dt,
|
|
if (prop2->deleted)
|
|
continue;
|
|
if (streq(prop->name, prop2->name))
|
|
- FAIL(c, "Duplicate property name %s in %s",
|
|
- prop->name, node->fullpath);
|
|
+ FAIL_PROP(c, dti, node, prop, "Duplicate property name");
|
|
}
|
|
}
|
|
}
|
|
-NODE_ERROR(duplicate_property_names, NULL);
|
|
+ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
|
|
|
|
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
|
|
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
#define DIGITS "0123456789"
|
|
#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
|
|
+#define PROPNODECHARSSTRICT 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)
|
|
{
|
|
int n = strspn(node->name, c->data);
|
|
|
|
if (n < strlen(node->name))
|
|
- FAIL(c, "Bad character '%c' in node %s",
|
|
- node->name[n], node->fullpath);
|
|
+ FAIL(c, dti, node, "Bad character '%c' in node name",
|
|
+ node->name[n]);
|
|
}
|
|
-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_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, node, "Character '%c' not recommended in node name",
|
|
+ node->name[n]);
|
|
+}
|
|
+CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT);
|
|
+
|
|
+static void check_node_name_format(struct check *c, struct dt_info *dti,
|
|
struct node *node)
|
|
{
|
|
if (strchr(get_unitname(node), '@'))
|
|
- FAIL(c, "Node %s has multiple '@' characters in name",
|
|
- node->fullpath);
|
|
+ FAIL(c, dti, node, "multiple '@' characters in node name");
|
|
+}
|
|
+ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
|
|
+
|
|
+static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
|
|
+ struct node *node)
|
|
+{
|
|
+ const char *unitname = get_unitname(node);
|
|
+ struct property *prop = get_property(node, "reg");
|
|
+
|
|
+ if (!prop) {
|
|
+ prop = get_property(node, "ranges");
|
|
+ if (prop && !prop->val.len)
|
|
+ prop = NULL;
|
|
+ }
|
|
+
|
|
+ if (prop) {
|
|
+ if (!unitname[0])
|
|
+ FAIL(c, dti, node, "node has a reg or ranges property, but no unit name");
|
|
+ } else {
|
|
+ if (unitname[0])
|
|
+ FAIL(c, dti, node, "node has a unit name, but no reg property");
|
|
+ }
|
|
+}
|
|
+WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
|
|
+
|
|
+static void check_property_name_chars(struct check *c, struct dt_info *dti,
|
|
+ struct node *node)
|
|
+{
|
|
+ struct property *prop;
|
|
+
|
|
+ for_each_property(node, prop) {
|
|
+ int n = strspn(prop->name, c->data);
|
|
+
|
|
+ if (n < strlen(prop->name))
|
|
+ FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name",
|
|
+ prop->name[n]);
|
|
+ }
|
|
}
|
|
-NODE_ERROR(node_name_format, NULL, &node_name_chars);
|
|
+ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
|
|
|
|
-static void check_property_name_chars(struct check *c, struct node *dt,
|
|
- struct node *node, struct property *prop)
|
|
+static void check_property_name_chars_strict(struct check *c,
|
|
+ struct dt_info *dti,
|
|
+ struct node *node)
|
|
{
|
|
- int n = strspn(prop->name, c->data);
|
|
+ struct property *prop;
|
|
+
|
|
+ for_each_property(node, prop) {
|
|
+ const char *name = prop->name;
|
|
+ int n = strspn(name, c->data);
|
|
|
|
- if (n < strlen(prop->name))
|
|
- FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
|
|
- prop->name[n], prop->name, node->fullpath);
|
|
+ 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_PROP(c, dti, node, prop, "Character '%c' not recommended in property name",
|
|
+ name[n]);
|
|
+ }
|
|
}
|
|
-PROP_ERROR(property_name_chars, PROPNODECHARS);
|
|
+CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT);
|
|
|
|
#define DESCLABEL_FMT "%s%s%s%s%s"
|
|
#define DESCLABEL_ARGS(node,prop,mark) \
|
|
@@ -311,10 +387,11 @@ PROP_ERROR(property_name_chars, PROPNODECHARS);
|
|
((prop) ? (prop)->name : ""), \
|
|
((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,
|
|
struct property *prop, struct marker *mark)
|
|
{
|
|
+ struct node *dt = dti->dt;
|
|
struct node *othernode = NULL;
|
|
struct property *otherprop = NULL;
|
|
struct marker *othermark = NULL;
|
|
@@ -331,50 +408,49 @@ static void check_duplicate_label(struct check *c, struct node *dt,
|
|
return;
|
|
|
|
if ((othernode != node) || (otherprop != prop) || (othermark != mark))
|
|
- FAIL(c, "Duplicate label '%s' on " DESCLABEL_FMT
|
|
+ FAIL(c, dti, node, "Duplicate label '%s' on " DESCLABEL_FMT
|
|
" and " DESCLABEL_FMT,
|
|
label, DESCLABEL_ARGS(node, prop, mark),
|
|
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 label *l;
|
|
+ struct property *prop;
|
|
|
|
for_each_label(node->labels, l)
|
|
- check_duplicate_label(c, dt, l->label, node, NULL, NULL);
|
|
-}
|
|
-static void check_duplicate_label_prop(struct check *c, struct node *dt,
|
|
- struct node *node, struct property *prop)
|
|
-{
|
|
- struct marker *m = prop->val.markers;
|
|
- struct label *l;
|
|
+ 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, dt, l->label, node, prop, NULL);
|
|
+ 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, dt, m->ref, node, prop, m);
|
|
+ for_each_marker_of_type(m, LABEL)
|
|
+ check_duplicate_label(c, dti, m->ref, node, prop, m);
|
|
+ }
|
|
}
|
|
-ERROR(duplicate_label, NULL, check_duplicate_label_node,
|
|
- check_duplicate_label_prop, NULL);
|
|
+ERROR(duplicate_label, check_duplicate_label_node, NULL);
|
|
|
|
-static void check_explicit_phandles(struct check *c, struct node *root,
|
|
- struct node *node, struct property *prop)
|
|
+static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
|
|
+ struct node *node, const char *propname)
|
|
{
|
|
+ struct node *root = dti->dt;
|
|
+ struct property *prop;
|
|
struct marker *m;
|
|
- struct node *other;
|
|
cell_t phandle;
|
|
|
|
- if (!streq(prop->name, "phandle")
|
|
- && !streq(prop->name, "linux,phandle"))
|
|
- return;
|
|
+ prop = get_property(node, propname);
|
|
+ if (!prop)
|
|
+ return 0;
|
|
|
|
if (prop->val.len != sizeof(cell_t)) {
|
|
- FAIL(c, "%s has bad length (%d) %s property",
|
|
- node->fullpath, prop->val.len, prop->name);
|
|
- return;
|
|
+ FAIL_PROP(c, dti, node, prop, "bad length (%d) %s property",
|
|
+ prop->val.len, prop->name);
|
|
+ return 0;
|
|
}
|
|
|
|
m = prop->val.markers;
|
|
@@ -384,42 +460,65 @@ static void check_explicit_phandles(struct check *c, struct node *root,
|
|
/* "Set this node's phandle equal to some
|
|
* other node's phandle". That's nonsensical
|
|
* by construction. */ {
|
|
- FAIL(c, "%s in %s is a reference to another node",
|
|
- prop->name, node->fullpath);
|
|
- return;
|
|
+ FAIL(c, dti, node, "%s is a reference to another node",
|
|
+ prop->name);
|
|
}
|
|
/* But setting this node's phandle equal to its own
|
|
* phandle is allowed - that means allocate a unique
|
|
* phandle for this node, even if it's not otherwise
|
|
* referenced. The value will be filled in later, so
|
|
- * no further checking for now. */
|
|
- return;
|
|
+ * we treat it as having no phandle data for now. */
|
|
+ return 0;
|
|
}
|
|
|
|
phandle = propval_cell(prop);
|
|
|
|
if ((phandle == 0) || (phandle == -1)) {
|
|
- FAIL(c, "%s has bad value (0x%x) in %s property",
|
|
- node->fullpath, phandle, prop->name);
|
|
- return;
|
|
+ FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
|
|
+ phandle, prop->name);
|
|
+ return 0;
|
|
}
|
|
|
|
- if (node->phandle && (node->phandle != phandle))
|
|
- FAIL(c, "%s has %s property which replaces existing phandle information",
|
|
- node->fullpath, prop->name);
|
|
+ return phandle;
|
|
+}
|
|
+
|
|
+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, dti, node, "mismatching 'phandle' and 'linux,phandle'"
|
|
+ " properties");
|
|
+
|
|
+ if (linux_phandle && !phandle)
|
|
+ phandle = linux_phandle;
|
|
|
|
other = get_node_by_phandle(root, phandle);
|
|
if (other && (other != node)) {
|
|
- FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
|
|
- node->fullpath, phandle, other->fullpath);
|
|
+ FAIL(c, dti, node, "duplicated phandle 0x%x (seen before at %s)",
|
|
+ phandle, other->fullpath);
|
|
return;
|
|
}
|
|
|
|
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 property **pp, *prop = NULL;
|
|
@@ -435,8 +534,8 @@ static void check_name_properties(struct check *c, struct node *root,
|
|
|
|
if ((prop->val.len != node->basenamelen+1)
|
|
|| (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
|
|
- FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
|
|
- " of base node name)", node->fullpath, prop->val.val);
|
|
+ FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
|
|
+ " of base node name)", prop->val.val);
|
|
} else {
|
|
/* The name property is correct, and therefore redundant.
|
|
* Delete it */
|
|
@@ -447,60 +546,73 @@ static void check_name_properties(struct check *c, struct node *root,
|
|
}
|
|
}
|
|
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
|
|
*/
|
|
|
|
-static void fixup_phandle_references(struct check *c, struct node *dt,
|
|
- struct node *node, struct property *prop)
|
|
+static void fixup_phandle_references(struct check *c, struct dt_info *dti,
|
|
+ struct node *node)
|
|
{
|
|
- struct marker *m = prop->val.markers;
|
|
- struct node *refnode;
|
|
- cell_t phandle;
|
|
+ struct node *dt = dti->dt;
|
|
+ struct property *prop;
|
|
|
|
- for_each_marker_of_type(m, REF_PHANDLE) {
|
|
- assert(m->offset + sizeof(cell_t) <= prop->val.len);
|
|
+ for_each_property(node, prop) {
|
|
+ struct marker *m = prop->val.markers;
|
|
+ struct node *refnode;
|
|
+ cell_t phandle;
|
|
+
|
|
+ for_each_marker_of_type(m, REF_PHANDLE) {
|
|
+ assert(m->offset + sizeof(cell_t) <= prop->val.len);
|
|
+
|
|
+ refnode = get_node_by_ref(dt, m->ref);
|
|
+ if (! refnode) {
|
|
+ if (!(dti->dtsflags & DTSF_PLUGIN))
|
|
+ FAIL(c, dti, node, "Reference to non-existent node or "
|
|
+ "label \"%s\"\n", m->ref);
|
|
+ else /* mark the entry as unresolved */
|
|
+ *((fdt32_t *)(prop->val.val + m->offset)) =
|
|
+ cpu_to_fdt32(0xffffffff);
|
|
+ continue;
|
|
+ }
|
|
|
|
- refnode = get_node_by_ref(dt, m->ref);
|
|
- if (! refnode) {
|
|
- FAIL(c, "Reference to non-existent node or label \"%s\"\n",
|
|
- m->ref);
|
|
- continue;
|
|
+ phandle = get_node_phandle(dt, refnode);
|
|
+ *((fdt32_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);
|
|
|
|
-static void fixup_path_references(struct check *c, struct node *dt,
|
|
- struct node *node, struct property *prop)
|
|
+static void fixup_path_references(struct check *c, struct dt_info *dti,
|
|
+ struct node *node)
|
|
{
|
|
- struct marker *m = prop->val.markers;
|
|
- struct node *refnode;
|
|
- char *path;
|
|
+ struct node *dt = dti->dt;
|
|
+ struct property *prop;
|
|
|
|
- for_each_marker_of_type(m, REF_PATH) {
|
|
- assert(m->offset <= prop->val.len);
|
|
+ for_each_property(node, prop) {
|
|
+ struct marker *m = prop->val.markers;
|
|
+ struct node *refnode;
|
|
+ char *path;
|
|
|
|
- refnode = get_node_by_ref(dt, m->ref);
|
|
- if (!refnode) {
|
|
- FAIL(c, "Reference to non-existent node or label \"%s\"\n",
|
|
- m->ref);
|
|
- continue;
|
|
- }
|
|
+ for_each_marker_of_type(m, REF_PATH) {
|
|
+ assert(m->offset <= prop->val.len);
|
|
|
|
- path = refnode->fullpath;
|
|
- prop->val = data_insert_at_marker(prop->val, m, path,
|
|
- strlen(path) + 1);
|
|
+ refnode = get_node_by_ref(dt, m->ref);
|
|
+ if (!refnode) {
|
|
+ FAIL(c, dti, node, "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);
|
|
+ }
|
|
}
|
|
}
|
|
-ERROR(path_references, NULL, NULL, fixup_path_references, NULL,
|
|
- &duplicate_node_names);
|
|
+ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names);
|
|
|
|
/*
|
|
* Semantic checks
|
|
@@ -512,8 +624,47 @@ WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
|
|
WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
|
|
WARNING_IF_NOT_STRING(model_is_string, "model");
|
|
WARNING_IF_NOT_STRING(status_is_string, "status");
|
|
+WARNING_IF_NOT_STRING(label_is_string, "label");
|
|
+
|
|
+WARNING_IF_NOT_STRING_LIST(compatible_is_string_list, "compatible");
|
|
+
|
|
+static void check_names_is_string_list(struct check *c, struct dt_info *dti,
|
|
+ struct node *node)
|
|
+{
|
|
+ struct property *prop;
|
|
+
|
|
+ for_each_property(node, prop) {
|
|
+ const char *s = strrchr(prop->name, '-');
|
|
+ if (!s || !streq(s, "-names"))
|
|
+ continue;
|
|
+
|
|
+ c->data = prop->name;
|
|
+ check_is_string_list(c, dti, node);
|
|
+ }
|
|
+}
|
|
+WARNING(names_is_string_list, check_names_is_string_list, NULL);
|
|
+
|
|
+static void check_alias_paths(struct check *c, struct dt_info *dti,
|
|
+ struct node *node)
|
|
+{
|
|
+ struct property *prop;
|
|
|
|
-static void fixup_addr_size_cells(struct check *c, struct node *dt,
|
|
+ if (!streq(node->name, "aliases"))
|
|
+ return;
|
|
+
|
|
+ for_each_property(node, prop) {
|
|
+ if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) {
|
|
+ FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)",
|
|
+ prop->val.val);
|
|
+ continue;
|
|
+ }
|
|
+ if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name))
|
|
+ FAIL(c, dti, node, "aliases property name must include only lowercase and '-'");
|
|
+ }
|
|
+}
|
|
+WARNING(alias_paths, check_alias_paths, NULL);
|
|
+
|
|
+static void fixup_addr_size_cells(struct check *c, struct dt_info *dti,
|
|
struct node *node)
|
|
{
|
|
struct property *prop;
|
|
@@ -529,7 +680,7 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt,
|
|
if (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);
|
|
|
|
#define node_addr_cells(n) \
|
|
@@ -537,7 +688,7 @@ WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL,
|
|
#define node_size_cells(n) \
|
|
(((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 property *prop;
|
|
@@ -548,25 +699,25 @@ static void check_reg_format(struct check *c, struct node *dt,
|
|
return; /* No "reg", that's fine */
|
|
|
|
if (!node->parent) {
|
|
- FAIL(c, "Root node has a \"reg\" property");
|
|
+ FAIL(c, dti, node, "Root node has a \"reg\" property");
|
|
return;
|
|
}
|
|
|
|
if (prop->val.len == 0)
|
|
- FAIL(c, "\"reg\" property in %s is empty", node->fullpath);
|
|
+ FAIL_PROP(c, dti, node, prop, "property is empty");
|
|
|
|
addr_cells = node_addr_cells(node->parent);
|
|
size_cells = node_size_cells(node->parent);
|
|
entrylen = (addr_cells + size_cells) * sizeof(cell_t);
|
|
|
|
- if ((prop->val.len % entrylen) != 0)
|
|
- FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
|
|
- "(#address-cells == %d, #size-cells == %d)",
|
|
- node->fullpath, prop->val.len, addr_cells, size_cells);
|
|
+ if (!entrylen || (prop->val.len % entrylen) != 0)
|
|
+ FAIL_PROP(c, dti, node, prop, "property has invalid length (%d bytes) "
|
|
+ "(#address-cells == %d, #size-cells == %d)",
|
|
+ prop->val.len, addr_cells, size_cells);
|
|
}
|
|
-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 property *prop;
|
|
@@ -577,7 +728,7 @@ static void check_ranges_format(struct check *c, struct node *dt,
|
|
return;
|
|
|
|
if (!node->parent) {
|
|
- FAIL(c, "Root node has a \"ranges\" property");
|
|
+ FAIL_PROP(c, dti, node, prop, "Root node has a \"ranges\" property");
|
|
return;
|
|
}
|
|
|
|
@@ -589,28 +740,237 @@ static void check_ranges_format(struct check *c, struct node *dt,
|
|
|
|
if (prop->val.len == 0) {
|
|
if (p_addr_cells != c_addr_cells)
|
|
- FAIL(c, "%s has empty \"ranges\" property but its "
|
|
- "#address-cells (%d) differs from %s (%d)",
|
|
- node->fullpath, c_addr_cells, node->parent->fullpath,
|
|
- p_addr_cells);
|
|
+ FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its "
|
|
+ "#address-cells (%d) differs from %s (%d)",
|
|
+ c_addr_cells, node->parent->fullpath,
|
|
+ p_addr_cells);
|
|
if (p_size_cells != c_size_cells)
|
|
- FAIL(c, "%s has empty \"ranges\" property but its "
|
|
- "#size-cells (%d) differs from %s (%d)",
|
|
- node->fullpath, c_size_cells, node->parent->fullpath,
|
|
- p_size_cells);
|
|
+ FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its "
|
|
+ "#size-cells (%d) differs from %s (%d)",
|
|
+ c_size_cells, node->parent->fullpath,
|
|
+ p_size_cells);
|
|
} else if ((prop->val.len % entrylen) != 0) {
|
|
- FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) "
|
|
- "(parent #address-cells == %d, child #address-cells == %d, "
|
|
- "#size-cells == %d)", node->fullpath, prop->val.len,
|
|
- p_addr_cells, c_addr_cells, c_size_cells);
|
|
+ FAIL_PROP(c, dti, node, prop, "\"ranges\" property has invalid length (%d bytes) "
|
|
+ "(parent #address-cells == %d, child #address-cells == %d, "
|
|
+ "#size-cells == %d)", prop->val.len,
|
|
+ p_addr_cells, c_addr_cells, c_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 (!strprefixeq(node->name, node->basenamelen, "pci") &&
|
|
+ !strprefixeq(node->name, node->basenamelen, "pcie"))
|
|
+ FAIL(c, dti, node, "node name is not \"pci\" or \"pcie\"");
|
|
+
|
|
+ prop = get_property(node, "ranges");
|
|
+ if (!prop)
|
|
+ FAIL(c, dti, node, "missing ranges for PCI bridge (or not a bridge)");
|
|
+
|
|
+ if (node_addr_cells(node) != 3)
|
|
+ FAIL(c, dti, node, "incorrect #address-cells for PCI bridge");
|
|
+ if (node_size_cells(node) != 2)
|
|
+ FAIL(c, dti, node, "incorrect #size-cells for PCI bridge");
|
|
+
|
|
+ prop = get_property(node, "bus-range");
|
|
+ if (!prop)
|
|
+ return;
|
|
+
|
|
+ if (prop->val.len != (sizeof(cell_t) * 2)) {
|
|
+ FAIL_PROP(c, dti, node, prop, "value must be 2 cells");
|
|
+ return;
|
|
+ }
|
|
+ cells = (cell_t *)prop->val.val;
|
|
+ if (fdt32_to_cpu(cells[0]) > fdt32_to_cpu(cells[1]))
|
|
+ FAIL_PROP(c, dti, node, prop, "1st cell must be less than or equal to 2nd cell");
|
|
+ if (fdt32_to_cpu(cells[1]) > 0xff)
|
|
+ FAIL_PROP(c, dti, node, prop, "maximum bus number must be less than 256");
|
|
+}
|
|
+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_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)",
|
|
+ bus_num, min_bus, max_bus);
|
|
+}
|
|
+WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, ®_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, "missing PCI reg property");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ cells = (cell_t *)prop->val.val;
|
|
+ if (cells[1] || cells[2])
|
|
+ FAIL_PROP(c, dti, node, prop, "PCI reg config space address cells 2 and 3 must be 0");
|
|
+
|
|
+ reg = fdt32_to_cpu(cells[0]);
|
|
+ dev = (reg & 0xf800) >> 11;
|
|
+ func = (reg & 0x700) >> 8;
|
|
+
|
|
+ if (reg & 0xff000000)
|
|
+ FAIL_PROP(c, dti, node, prop, "PCI reg address is not configuration space");
|
|
+ if (reg & 0x000000ff)
|
|
+ FAIL_PROP(c, dti, node, prop, "PCI reg config space address register number must be 0");
|
|
+
|
|
+ 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, "PCI unit address format error, expected \"%s\"",
|
|
+ unit_addr);
|
|
+}
|
|
+WARNING(pci_device_reg, check_pci_device_reg, NULL, ®_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 (strprefixeq(str, end - str, compat))
|
|
+ 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;
|
|
}
|
|
-NODE_WARNING(ranges_format, NULL, &addr_size_cells);
|
|
+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, "missing or empty reg/ranges property");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ size = node_addr_cells(node->parent);
|
|
+ while (size--)
|
|
+ reg = (reg << 32) | fdt32_to_cpu(*(cells++));
|
|
+
|
|
+ snprintf(unit_addr, sizeof(unit_addr), "%"PRIx64, reg);
|
|
+ if (!streq(unitname, unit_addr))
|
|
+ FAIL(c, dti, node, "simple-bus unit address format error, expected \"%s\"",
|
|
+ unit_addr);
|
|
+}
|
|
+WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_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, "unit name should not have leading \"0x\"");
|
|
+ /* skip over 0x for next test */
|
|
+ unitname += 2;
|
|
+ }
|
|
+ if (unitname[0] == '0' && isxdigit(unitname[1]))
|
|
+ FAIL(c, dti, node, "unit name should not have leading 0s");
|
|
+}
|
|
+WARNING(unit_address_format, check_unit_address_format, NULL,
|
|
+ &node_name_format, &pci_bridge, &simple_bus_bridge);
|
|
|
|
/*
|
|
* 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 property *reg, *ranges;
|
|
@@ -625,31 +985,377 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt,
|
|
return;
|
|
|
|
if (node->parent->addr_cells == -1)
|
|
- FAIL(c, "Relying on default #address-cells value for %s",
|
|
- node->fullpath);
|
|
+ FAIL(c, dti, node, "Relying on default #address-cells value");
|
|
|
|
if (node->parent->size_cells == -1)
|
|
- FAIL(c, "Relying on default #size-cells value for %s",
|
|
- node->fullpath);
|
|
+ FAIL(c, dti, node, "Relying on default #size-cells value");
|
|
+}
|
|
+WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
|
|
+ &addr_size_cells);
|
|
+
|
|
+static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *dti,
|
|
+ struct node *node)
|
|
+{
|
|
+ struct property *prop;
|
|
+ struct node *child;
|
|
+ bool has_reg = false;
|
|
+
|
|
+ if (!node->parent || node->addr_cells < 0 || node->size_cells < 0)
|
|
+ return;
|
|
+
|
|
+ if (get_property(node, "ranges") || !node->children)
|
|
+ return;
|
|
+
|
|
+ for_each_child(node, child) {
|
|
+ prop = get_property(child, "reg");
|
|
+ if (prop)
|
|
+ has_reg = true;
|
|
+ }
|
|
+
|
|
+ if (!has_reg)
|
|
+ FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property");
|
|
}
|
|
-NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells);
|
|
+WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
|
|
|
|
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 property *prop;
|
|
|
|
+ if (node != dt)
|
|
+ return;
|
|
+
|
|
+
|
|
chosen = get_node_by_path(dt, "/chosen");
|
|
if (!chosen)
|
|
return;
|
|
|
|
prop = get_property(chosen, "interrupt-controller");
|
|
if (prop)
|
|
- FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
|
|
- "property");
|
|
+ FAIL_PROP(c, dti, node, prop,
|
|
+ "/chosen has obsolete \"interrupt-controller\" property");
|
|
+}
|
|
+WARNING(obsolete_chosen_interrupt_controller,
|
|
+ check_obsolete_chosen_interrupt_controller, NULL);
|
|
+
|
|
+static void check_chosen_node_is_root(struct check *c, struct dt_info *dti,
|
|
+ struct node *node)
|
|
+{
|
|
+ if (!streq(node->name, "chosen"))
|
|
+ return;
|
|
+
|
|
+ if (node->parent != dti->dt)
|
|
+ FAIL(c, dti, node, "chosen node must be at root node");
|
|
}
|
|
-TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
|
|
+WARNING(chosen_node_is_root, check_chosen_node_is_root, NULL);
|
|
+
|
|
+static void check_chosen_node_bootargs(struct check *c, struct dt_info *dti,
|
|
+ struct node *node)
|
|
+{
|
|
+ struct property *prop;
|
|
+
|
|
+ if (!streq(node->name, "chosen"))
|
|
+ return;
|
|
+
|
|
+ prop = get_property(node, "bootargs");
|
|
+ if (!prop)
|
|
+ return;
|
|
+
|
|
+ c->data = prop->name;
|
|
+ check_is_string(c, dti, node);
|
|
+}
|
|
+WARNING(chosen_node_bootargs, check_chosen_node_bootargs, NULL);
|
|
+
|
|
+static void check_chosen_node_stdout_path(struct check *c, struct dt_info *dti,
|
|
+ struct node *node)
|
|
+{
|
|
+ struct property *prop;
|
|
+
|
|
+ if (!streq(node->name, "chosen"))
|
|
+ return;
|
|
+
|
|
+ prop = get_property(node, "stdout-path");
|
|
+ if (!prop) {
|
|
+ prop = get_property(node, "linux,stdout-path");
|
|
+ if (!prop)
|
|
+ return;
|
|
+ FAIL_PROP(c, dti, node, prop, "Use 'stdout-path' instead");
|
|
+ }
|
|
+
|
|
+ c->data = prop->name;
|
|
+ check_is_string(c, dti, node);
|
|
+}
|
|
+WARNING(chosen_node_stdout_path, check_chosen_node_stdout_path, NULL);
|
|
+
|
|
+struct provider {
|
|
+ const char *prop_name;
|
|
+ const char *cell_name;
|
|
+ bool optional;
|
|
+};
|
|
+
|
|
+static void check_property_phandle_args(struct check *c,
|
|
+ struct dt_info *dti,
|
|
+ struct node *node,
|
|
+ struct property *prop,
|
|
+ const struct provider *provider)
|
|
+{
|
|
+ struct node *root = dti->dt;
|
|
+ int cell, cellsize = 0;
|
|
+
|
|
+ if (prop->val.len % sizeof(cell_t)) {
|
|
+ FAIL_PROP(c, dti, node, prop,
|
|
+ "property size (%d) is invalid, expected multiple of %zu",
|
|
+ prop->val.len, sizeof(cell_t));
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) {
|
|
+ struct node *provider_node;
|
|
+ struct property *cellprop;
|
|
+ int phandle;
|
|
+
|
|
+ phandle = propval_cell_n(prop, cell);
|
|
+ /*
|
|
+ * Some bindings use a cell value 0 or -1 to skip over optional
|
|
+ * entries when each index position has a specific definition.
|
|
+ */
|
|
+ if (phandle == 0 || phandle == -1) {
|
|
+ /* Give up if this is an overlay with external references */
|
|
+ if (dti->dtsflags & DTSF_PLUGIN)
|
|
+ break;
|
|
+
|
|
+ cellsize = 0;
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ /* If we have markers, verify the current cell is a phandle */
|
|
+ if (prop->val.markers) {
|
|
+ struct marker *m = prop->val.markers;
|
|
+ for_each_marker_of_type(m, REF_PHANDLE) {
|
|
+ if (m->offset == (cell * sizeof(cell_t)))
|
|
+ break;
|
|
+ }
|
|
+ if (!m)
|
|
+ FAIL_PROP(c, dti, node, prop,
|
|
+ "cell %d is not a phandle reference",
|
|
+ cell);
|
|
+ }
|
|
+
|
|
+ provider_node = get_node_by_phandle(root, phandle);
|
|
+ if (!provider_node) {
|
|
+ FAIL_PROP(c, dti, node, prop,
|
|
+ "Could not get phandle node for (cell %d)",
|
|
+ cell);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ cellprop = get_property(provider_node, provider->cell_name);
|
|
+ if (cellprop) {
|
|
+ cellsize = propval_cell(cellprop);
|
|
+ } else if (provider->optional) {
|
|
+ cellsize = 0;
|
|
+ } else {
|
|
+ FAIL(c, dti, node, "Missing property '%s' in node %s or bad phandle (referred from %s[%d])",
|
|
+ provider->cell_name,
|
|
+ provider_node->fullpath,
|
|
+ prop->name, cell);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
|
|
+ FAIL_PROP(c, dti, node, prop,
|
|
+ "property size (%d) too small for cell size %d",
|
|
+ prop->val.len, cellsize);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void check_provider_cells_property(struct check *c,
|
|
+ struct dt_info *dti,
|
|
+ struct node *node)
|
|
+{
|
|
+ struct provider *provider = c->data;
|
|
+ struct property *prop;
|
|
+
|
|
+ prop = get_property(node, provider->prop_name);
|
|
+ if (!prop)
|
|
+ return;
|
|
+
|
|
+ check_property_phandle_args(c, dti, node, prop, provider);
|
|
+}
|
|
+#define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \
|
|
+ static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \
|
|
+ WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references);
|
|
+
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(dmas, "dmas", "#dma-cells");
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(hwlocks, "hwlocks", "#hwlock-cells");
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(interrupts_extended, "interrupts-extended", "#interrupt-cells");
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(io_channels, "io-channels", "#io-channel-cells");
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(iommus, "iommus", "#iommu-cells");
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(mboxes, "mboxes", "#mbox-cells");
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(msi_parent, "msi-parent", "#msi-cells", true);
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(mux_controls, "mux-controls", "#mux-control-cells");
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(phys, "phys", "#phy-cells");
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(power_domains, "power-domains", "#power-domain-cells");
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(pwms, "pwms", "#pwm-cells");
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(resets, "resets", "#reset-cells");
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(sound_dai, "sound-dai", "#sound-dai-cells");
|
|
+WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sensor-cells");
|
|
+
|
|
+static bool prop_is_gpio(struct property *prop)
|
|
+{
|
|
+ char *str;
|
|
+
|
|
+ /*
|
|
+ * *-gpios and *-gpio can appear in property names,
|
|
+ * so skip over any false matches (only one known ATM)
|
|
+ */
|
|
+ if (strstr(prop->name, "nr-gpio"))
|
|
+ return false;
|
|
+
|
|
+ str = strrchr(prop->name, '-');
|
|
+ if (str)
|
|
+ str++;
|
|
+ else
|
|
+ str = prop->name;
|
|
+ if (!(streq(str, "gpios") || streq(str, "gpio")))
|
|
+ return false;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static void check_gpios_property(struct check *c,
|
|
+ struct dt_info *dti,
|
|
+ struct node *node)
|
|
+{
|
|
+ struct property *prop;
|
|
+
|
|
+ /* Skip GPIO hog nodes which have 'gpios' property */
|
|
+ if (get_property(node, "gpio-hog"))
|
|
+ return;
|
|
+
|
|
+ for_each_property(node, prop) {
|
|
+ struct provider provider;
|
|
+
|
|
+ if (!prop_is_gpio(prop))
|
|
+ continue;
|
|
+
|
|
+ provider.prop_name = prop->name;
|
|
+ provider.cell_name = "#gpio-cells";
|
|
+ provider.optional = false;
|
|
+ check_property_phandle_args(c, dti, node, prop, &provider);
|
|
+ }
|
|
+
|
|
+}
|
|
+WARNING(gpios_property, check_gpios_property, NULL, &phandle_references);
|
|
+
|
|
+static void check_deprecated_gpio_property(struct check *c,
|
|
+ struct dt_info *dti,
|
|
+ struct node *node)
|
|
+{
|
|
+ struct property *prop;
|
|
+
|
|
+ for_each_property(node, prop) {
|
|
+ char *str;
|
|
+
|
|
+ if (!prop_is_gpio(prop))
|
|
+ continue;
|
|
+
|
|
+ str = strstr(prop->name, "gpio");
|
|
+ if (!streq(str, "gpio"))
|
|
+ continue;
|
|
+
|
|
+ FAIL_PROP(c, dti, node, prop,
|
|
+ "'[*-]gpio' is deprecated, use '[*-]gpios' instead");
|
|
+ }
|
|
+
|
|
+}
|
|
+CHECK(deprecated_gpio_property, check_deprecated_gpio_property, NULL);
|
|
+
|
|
+static bool node_is_interrupt_provider(struct node *node)
|
|
+{
|
|
+ struct property *prop;
|
|
+
|
|
+ prop = get_property(node, "interrupt-controller");
|
|
+ if (prop)
|
|
+ return true;
|
|
+
|
|
+ prop = get_property(node, "interrupt-map");
|
|
+ if (prop)
|
|
+ return true;
|
|
+
|
|
+ return false;
|
|
+}
|
|
+static void check_interrupts_property(struct check *c,
|
|
+ struct dt_info *dti,
|
|
+ struct node *node)
|
|
+{
|
|
+ struct node *root = dti->dt;
|
|
+ struct node *irq_node = NULL, *parent = node;
|
|
+ struct property *irq_prop, *prop = NULL;
|
|
+ int irq_cells, phandle;
|
|
+
|
|
+ irq_prop = get_property(node, "interrupts");
|
|
+ if (!irq_prop)
|
|
+ return;
|
|
+
|
|
+ if (irq_prop->val.len % sizeof(cell_t))
|
|
+ FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu",
|
|
+ irq_prop->val.len, sizeof(cell_t));
|
|
+
|
|
+ while (parent && !prop) {
|
|
+ if (parent != node && node_is_interrupt_provider(parent)) {
|
|
+ irq_node = parent;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ prop = get_property(parent, "interrupt-parent");
|
|
+ if (prop) {
|
|
+ phandle = propval_cell(prop);
|
|
+ /* Give up if this is an overlay with external references */
|
|
+ if ((phandle == 0 || phandle == -1) &&
|
|
+ (dti->dtsflags & DTSF_PLUGIN))
|
|
+ return;
|
|
+
|
|
+ irq_node = get_node_by_phandle(root, phandle);
|
|
+ if (!irq_node) {
|
|
+ FAIL_PROP(c, dti, parent, prop, "Bad phandle");
|
|
+ return;
|
|
+ }
|
|
+ if (!node_is_interrupt_provider(irq_node))
|
|
+ FAIL(c, dti, irq_node,
|
|
+ "Missing interrupt-controller or interrupt-map property");
|
|
+
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ parent = parent->parent;
|
|
+ }
|
|
+
|
|
+ if (!irq_node) {
|
|
+ FAIL(c, dti, node, "Missing interrupt-parent");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ prop = get_property(irq_node, "#interrupt-cells");
|
|
+ if (!prop) {
|
|
+ FAIL(c, dti, irq_node, "Missing #interrupt-cells in interrupt-parent");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ irq_cells = propval_cell(prop);
|
|
+ if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) {
|
|
+ FAIL_PROP(c, dti, node, prop,
|
|
+ "size is (%d), expected multiple of %d",
|
|
+ irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)));
|
|
+ }
|
|
+}
|
|
+WARNING(interrupts_property, check_interrupts_property, &phandle_references);
|
|
|
|
static struct check *check_table[] = {
|
|
&duplicate_node_names, &duplicate_property_names,
|
|
@@ -663,11 +1369,52 @@ static struct check *check_table[] = {
|
|
|
|
&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
|
|
&device_type_is_string, &model_is_string, &status_is_string,
|
|
+ &label_is_string,
|
|
+
|
|
+ &compatible_is_string_list, &names_is_string_list,
|
|
+
|
|
+ &property_name_chars_strict,
|
|
+ &node_name_chars_strict,
|
|
|
|
&addr_size_cells, ®_format, &ranges_format,
|
|
|
|
+ &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_unnecessary_addr_size,
|
|
&obsolete_chosen_interrupt_controller,
|
|
+ &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
|
|
+
|
|
+ &clocks_property,
|
|
+ &cooling_device_property,
|
|
+ &dmas_property,
|
|
+ &hwlocks_property,
|
|
+ &interrupts_extended_property,
|
|
+ &io_channels_property,
|
|
+ &iommus_property,
|
|
+ &mboxes_property,
|
|
+ &msi_parent_property,
|
|
+ &mux_controls_property,
|
|
+ &phys_property,
|
|
+ &power_domains_property,
|
|
+ &pwms_property,
|
|
+ &resets_property,
|
|
+ &sound_dai_property,
|
|
+ &thermal_sensors_property,
|
|
+
|
|
+ &deprecated_gpio_property,
|
|
+ &gpios_property,
|
|
+ &interrupts_property,
|
|
+
|
|
+ &alias_paths,
|
|
|
|
&always_fail,
|
|
};
|
|
@@ -733,9 +1480,8 @@ void parse_checks_option(bool warn, bool error, const char *arg)
|
|
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 error = 0;
|
|
|
|
@@ -743,7 +1489,7 @@ void process_checks(bool force, struct boot_info *bi)
|
|
struct check *c = check_table[i];
|
|
|
|
if (c->warn || c->error)
|
|
- error = error || run_check(c, dt);
|
|
+ error = error || run_check(c, dti);
|
|
}
|
|
|
|
if (error) {
|
|
diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
|
|
index 8cae23746..aa37a16c8 100644
|
|
--- a/scripts/dtc/data.c
|
|
+++ b/scripts/dtc/data.c
|
|
@@ -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)
|
|
{
|
|
uint8_t value_8;
|
|
- uint16_t value_16;
|
|
- uint32_t value_32;
|
|
- uint64_t value_64;
|
|
+ fdt16_t value_16;
|
|
+ fdt32_t value_32;
|
|
+ fdt64_t value_64;
|
|
|
|
switch (bits) {
|
|
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);
|
|
- bere.size = cpu_to_fdt64(re->size);
|
|
+ re.address = cpu_to_fdt64(address);
|
|
+ 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)
|
|
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
|
|
index 0ee1caf03..fd825ebba 100644
|
|
--- a/scripts/dtc/dtc-lexer.l
|
|
+++ b/scripts/dtc/dtc-lexer.l
|
|
@@ -62,7 +62,8 @@ static int dts_version = 1;
|
|
|
|
static void push_input_file(const char *filename);
|
|
static bool pop_input_file(void);
|
|
-static void lexical_error(const char *fmt, ...);
|
|
+static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
|
|
+
|
|
%}
|
|
|
|
%%
|
|
@@ -73,24 +74,32 @@ static void lexical_error(const char *fmt, ...);
|
|
}
|
|
|
|
<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
|
|
- char *line, *tmp, *fn;
|
|
+ char *line, *fnstart, *fnend;
|
|
+ struct data fn;
|
|
/* skip text before line # */
|
|
line = yytext;
|
|
while (!isdigit((unsigned char)*line))
|
|
line++;
|
|
- /* skip digits in line # */
|
|
- tmp = line;
|
|
- while (!isspace((unsigned char)*tmp))
|
|
- tmp++;
|
|
- /* "NULL"-terminate line # */
|
|
- *tmp = '\0';
|
|
- /* start of filename */
|
|
- fn = strchr(tmp + 1, '"') + 1;
|
|
- /* strip trailing " from filename */
|
|
- tmp = strchr(fn, '"');
|
|
- *tmp = 0;
|
|
+
|
|
+ /* regexp ensures that first and list "
|
|
+ * in the whole yytext are those at
|
|
+ * beginning and end of the filename string */
|
|
+ fnstart = memchr(yytext, '"', yyleng);
|
|
+ for (fnend = yytext + yyleng - 1;
|
|
+ *fnend != '"'; fnend--)
|
|
+ ;
|
|
+ assert(fnstart && fnend && (fnend > fnstart));
|
|
+
|
|
+ fn = data_copy_escape_string(fnstart + 1,
|
|
+ fnend - fnstart - 1);
|
|
+
|
|
+ /* Don't allow nuls in filenames */
|
|
+ if (memchr(fn.val, '\0', fn.len - 1))
|
|
+ lexical_error("nul in line number directive");
|
|
+
|
|
/* -1 since #line is the number of the next line */
|
|
- srcpos_set_line(xstrdup(fn), atoi(line) - 1);
|
|
+ srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
|
|
+ data_free(fn);
|
|
}
|
|
|
|
<*><<EOF>> {
|
|
@@ -113,6 +122,11 @@ static void lexical_error(const char *fmt, ...);
|
|
return DT_V1;
|
|
}
|
|
|
|
+<*>"/plugin/" {
|
|
+ DPRINT("Keyword: /plugin/\n");
|
|
+ return DT_PLUGIN;
|
|
+ }
|
|
+
|
|
<*>"/memreserve/" {
|
|
DPRINT("Keyword: /memreserve/\n");
|
|
BEGIN_DEFAULT();
|
|
@@ -153,7 +167,10 @@ static void lexical_error(const char *fmt, ...);
|
|
errno = 0;
|
|
yylval.integer = strtoull(yytext, &e, 0);
|
|
|
|
- assert(!(*e) || !e[strspn(e, "UL")]);
|
|
+ if (*e && e[strspn(e, "UL")]) {
|
|
+ lexical_error("Bad integer literal '%s'",
|
|
+ yytext);
|
|
+ }
|
|
|
|
if (errno == ERANGE)
|
|
lexical_error("Integer literal '%s' out of range",
|
|
@@ -173,16 +190,16 @@ static void lexical_error(const char *fmt, ...);
|
|
if (d.len == 1) {
|
|
lexical_error("Empty character literal");
|
|
yylval.integer = 0;
|
|
- return DT_CHAR_LITERAL;
|
|
- }
|
|
-
|
|
- yylval.integer = (unsigned char)d.val[0];
|
|
+ } 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);
|
|
+ if (d.len > 2)
|
|
+ lexical_error("Character literal has %d"
|
|
+ " characters instead of 1",
|
|
+ d.len - 1);
|
|
+ }
|
|
|
|
+ data_free(d);
|
|
return DT_CHAR_LITERAL;
|
|
}
|
|
|
|
diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
|
|
index 11cd78e72..f032b24b2 100644
|
|
--- a/scripts/dtc/dtc-lexer.lex.c_shipped
|
|
+++ b/scripts/dtc/dtc-lexer.lex.c_shipped
|
|
@@ -1,6 +1,6 @@
|
|
-#line 2 "dtc-lexer.lex.c"
|
|
+#line 2 "dtc-lexer.l.c"
|
|
|
|
-#line 4 "dtc-lexer.lex.c"
|
|
+#line 4 "dtc-lexer.l.c"
|
|
|
|
#define YY_INT_ALIGNED short int
|
|
|
|
@@ -8,8 +8,8 @@
|
|
|
|
#define FLEX_SCANNER
|
|
#define YY_FLEX_MAJOR_VERSION 2
|
|
-#define YY_FLEX_MINOR_VERSION 5
|
|
-#define YY_FLEX_SUBMINOR_VERSION 39
|
|
+#define YY_FLEX_MINOR_VERSION 6
|
|
+#define YY_FLEX_SUBMINOR_VERSION 4
|
|
#if YY_FLEX_SUBMINOR_VERSION > 0
|
|
#define FLEX_BETA
|
|
#endif
|
|
@@ -84,60 +84,48 @@ typedef unsigned int flex_uint32_t;
|
|
#define UINT32_MAX (4294967295U)
|
|
#endif
|
|
|
|
+#ifndef SIZE_MAX
|
|
+#define SIZE_MAX (~(size_t)0)
|
|
+#endif
|
|
+
|
|
#endif /* ! C99 */
|
|
|
|
#endif /* ! FLEXINT_H */
|
|
|
|
-#ifdef __cplusplus
|
|
-
|
|
-/* The "const" storage-class-modifier is valid. */
|
|
-#define YY_USE_CONST
|
|
-
|
|
-#else /* ! __cplusplus */
|
|
-
|
|
-/* C99 requires __STDC__ to be defined as 1. */
|
|
-#if defined (__STDC__)
|
|
-
|
|
-#define YY_USE_CONST
|
|
+/* begin standard C++ headers. */
|
|
|
|
-#endif /* defined (__STDC__) */
|
|
-#endif /* ! __cplusplus */
|
|
-
|
|
-#ifdef YY_USE_CONST
|
|
+/* TODO: this is always defined, so inline it */
|
|
#define yyconst const
|
|
+
|
|
+#if defined(__GNUC__) && __GNUC__ >= 3
|
|
+#define yynoreturn __attribute__((__noreturn__))
|
|
#else
|
|
-#define yyconst
|
|
+#define yynoreturn
|
|
#endif
|
|
|
|
/* Returned upon end-of-file. */
|
|
#define YY_NULL 0
|
|
|
|
-/* Promotes a possibly negative, possibly signed char to an unsigned
|
|
- * integer for use as an array index. If the signed char is negative,
|
|
- * we want to instead treat it as an 8-bit unsigned char, hence the
|
|
- * double cast.
|
|
+/* Promotes a possibly negative, possibly signed char to an
|
|
+ * integer in range [0..255] for use as an array index.
|
|
*/
|
|
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
|
|
+#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
|
|
|
|
/* Enter a start condition. This macro really ought to take a parameter,
|
|
* but we do it the disgusting crufty way forced on us by the ()-less
|
|
* definition of BEGIN.
|
|
*/
|
|
#define BEGIN (yy_start) = 1 + 2 *
|
|
-
|
|
/* Translate the current start state into a value that can be later handed
|
|
* to BEGIN to return to the state. The YYSTATE alias is for lex
|
|
* compatibility.
|
|
*/
|
|
#define YY_START (((yy_start) - 1) / 2)
|
|
#define YYSTATE YY_START
|
|
-
|
|
/* Action number for EOF rule of a given start state. */
|
|
#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
|
|
-
|
|
/* Special action meaning "start processing a new file". */
|
|
-#define YY_NEW_FILE yyrestart(yyin )
|
|
-
|
|
+#define YY_NEW_FILE yyrestart( yyin )
|
|
#define YY_END_OF_BUFFER_CHAR 0
|
|
|
|
/* Size of default input buffer. */
|
|
@@ -167,14 +155,14 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
|
typedef size_t yy_size_t;
|
|
#endif
|
|
|
|
-extern yy_size_t yyleng;
|
|
+extern int yyleng;
|
|
|
|
extern FILE *yyin, *yyout;
|
|
|
|
#define EOB_ACT_CONTINUE_SCAN 0
|
|
#define EOB_ACT_END_OF_FILE 1
|
|
#define EOB_ACT_LAST_MATCH 2
|
|
-
|
|
+
|
|
#define YY_LESS_LINENO(n)
|
|
#define YY_LINENO_REWIND_TO(ptr)
|
|
|
|
@@ -191,7 +179,6 @@ extern FILE *yyin, *yyout;
|
|
YY_DO_BEFORE_ACTION; /* set up yytext again */ \
|
|
} \
|
|
while ( 0 )
|
|
-
|
|
#define unput(c) yyunput( c, (yytext_ptr) )
|
|
|
|
#ifndef YY_STRUCT_YY_BUFFER_STATE
|
|
@@ -206,12 +193,12 @@ struct yy_buffer_state
|
|
/* Size of input buffer in bytes, not including room for EOB
|
|
* characters.
|
|
*/
|
|
- yy_size_t yy_buf_size;
|
|
+ int yy_buf_size;
|
|
|
|
/* Number of characters read into yy_ch_buf, not including EOB
|
|
* characters.
|
|
*/
|
|
- yy_size_t yy_n_chars;
|
|
+ int yy_n_chars;
|
|
|
|
/* Whether we "own" the buffer - i.e., we know we created it,
|
|
* and can realloc() it to grow it, and should free() it to
|
|
@@ -234,7 +221,7 @@ struct yy_buffer_state
|
|
|
|
int yy_bs_lineno; /**< The line count. */
|
|
int yy_bs_column; /**< The column count. */
|
|
-
|
|
+
|
|
/* Whether to try to fill the input buffer when we reach the
|
|
* end of it.
|
|
*/
|
|
@@ -262,7 +249,7 @@ struct yy_buffer_state
|
|
/* Stack of input buffers. */
|
|
static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
|
|
static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
|
|
-static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
|
|
+static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */
|
|
|
|
/* We provide macros for accessing buffer states in case in the
|
|
* future we want to put the buffer states in a more general
|
|
@@ -273,7 +260,6 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
|
|
#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
|
|
? (yy_buffer_stack)[(yy_buffer_stack_top)] \
|
|
: NULL)
|
|
-
|
|
/* Same as previous macro, but useful when we know that the buffer stack is not
|
|
* NULL or when we need an lvalue. For internal use only.
|
|
*/
|
|
@@ -281,11 +267,11 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
|
|
|
|
/* yy_hold_char holds the character lost when yytext is formed. */
|
|
static char yy_hold_char;
|
|
-static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */
|
|
-yy_size_t yyleng;
|
|
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
|
|
+int yyleng;
|
|
|
|
/* Points to current character in buffer. */
|
|
-static char *yy_c_buf_p = (char *) 0;
|
|
+static char *yy_c_buf_p = NULL;
|
|
static int yy_init = 0; /* whether we need to initialize */
|
|
static int yy_start = 0; /* start state number */
|
|
|
|
@@ -294,87 +280,83 @@ static int yy_start = 0; /* start state number */
|
|
*/
|
|
static int yy_did_buffer_switch_on_eof;
|
|
|
|
-void yyrestart (FILE *input_file );
|
|
-void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer );
|
|
-YY_BUFFER_STATE yy_create_buffer (FILE *file,int size );
|
|
-void yy_delete_buffer (YY_BUFFER_STATE b );
|
|
-void yy_flush_buffer (YY_BUFFER_STATE b );
|
|
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer );
|
|
-void yypop_buffer_state (void );
|
|
-
|
|
-static void yyensure_buffer_stack (void );
|
|
-static void yy_load_buffer_state (void );
|
|
-static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
|
|
+void yyrestart ( FILE *input_file );
|
|
+void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer );
|
|
+YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size );
|
|
+void yy_delete_buffer ( YY_BUFFER_STATE b );
|
|
+void yy_flush_buffer ( YY_BUFFER_STATE b );
|
|
+void yypush_buffer_state ( YY_BUFFER_STATE new_buffer );
|
|
+void yypop_buffer_state ( void );
|
|
|
|
-#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
|
|
+static void yyensure_buffer_stack ( void );
|
|
+static void yy_load_buffer_state ( void );
|
|
+static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file );
|
|
+#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER )
|
|
|
|
-YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
|
|
-YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
|
|
-YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len );
|
|
+YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size );
|
|
+YY_BUFFER_STATE yy_scan_string ( const char *yy_str );
|
|
+YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len );
|
|
|
|
-void *yyalloc (yy_size_t );
|
|
-void *yyrealloc (void *,yy_size_t );
|
|
-void yyfree (void * );
|
|
+void *yyalloc ( yy_size_t );
|
|
+void *yyrealloc ( void *, yy_size_t );
|
|
+void yyfree ( void * );
|
|
|
|
#define yy_new_buffer yy_create_buffer
|
|
-
|
|
#define yy_set_interactive(is_interactive) \
|
|
{ \
|
|
if ( ! YY_CURRENT_BUFFER ){ \
|
|
yyensure_buffer_stack (); \
|
|
YY_CURRENT_BUFFER_LVALUE = \
|
|
- yy_create_buffer(yyin,YY_BUF_SIZE ); \
|
|
+ yy_create_buffer( yyin, YY_BUF_SIZE ); \
|
|
} \
|
|
YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
|
|
}
|
|
-
|
|
#define yy_set_bol(at_bol) \
|
|
{ \
|
|
if ( ! YY_CURRENT_BUFFER ){\
|
|
yyensure_buffer_stack (); \
|
|
YY_CURRENT_BUFFER_LVALUE = \
|
|
- yy_create_buffer(yyin,YY_BUF_SIZE ); \
|
|
+ yy_create_buffer( yyin, YY_BUF_SIZE ); \
|
|
} \
|
|
YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
|
|
}
|
|
-
|
|
#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
|
|
|
|
/* Begin user sect3 */
|
|
|
|
-#define yywrap() 1
|
|
+#define yywrap() (/*CONSTCOND*/1)
|
|
#define YY_SKIP_YYWRAP
|
|
+typedef flex_uint8_t YY_CHAR;
|
|
|
|
-typedef unsigned char YY_CHAR;
|
|
-
|
|
-FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
|
|
+FILE *yyin = NULL, *yyout = NULL;
|
|
|
|
typedef int yy_state_type;
|
|
|
|
extern int yylineno;
|
|
-
|
|
int yylineno = 1;
|
|
|
|
extern char *yytext;
|
|
+#ifdef yytext_ptr
|
|
+#undef yytext_ptr
|
|
+#endif
|
|
#define yytext_ptr yytext
|
|
|
|
-static yy_state_type yy_get_previous_state (void );
|
|
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
|
|
-static int yy_get_next_buffer (void );
|
|
-static void yy_fatal_error (yyconst char msg[] );
|
|
+static yy_state_type yy_get_previous_state ( void );
|
|
+static yy_state_type yy_try_NUL_trans ( yy_state_type current_state );
|
|
+static int yy_get_next_buffer ( void );
|
|
+static void yynoreturn yy_fatal_error ( const char* msg );
|
|
|
|
/* Done after the current pattern has been matched and before the
|
|
* corresponding action - sets up yytext.
|
|
*/
|
|
#define YY_DO_BEFORE_ACTION \
|
|
(yytext_ptr) = yy_bp; \
|
|
- yyleng = (size_t) (yy_cp - yy_bp); \
|
|
+ yyleng = (int) (yy_cp - yy_bp); \
|
|
(yy_hold_char) = *yy_cp; \
|
|
*yy_cp = '\0'; \
|
|
(yy_c_buf_p) = yy_cp;
|
|
-
|
|
-#define YY_NUM_RULES 30
|
|
-#define YY_END_OF_BUFFER 31
|
|
+#define YY_NUM_RULES 31
|
|
+#define YY_END_OF_BUFFER 32
|
|
/* This struct is not used in this scanner,
|
|
but its presence is necessary. */
|
|
struct yy_trans_info
|
|
@@ -382,28 +364,29 @@ struct yy_trans_info
|
|
flex_int32_t yy_verify;
|
|
flex_int32_t yy_nxt;
|
|
};
|
|
-static yyconst flex_int16_t yy_accept[159] =
|
|
+static const flex_int16_t yy_accept[166] =
|
|
{ 0,
|
|
- 0, 0, 0, 0, 0, 0, 0, 0, 31, 29,
|
|
- 18, 18, 29, 29, 29, 29, 29, 29, 29, 29,
|
|
- 29, 29, 29, 29, 29, 29, 15, 16, 16, 29,
|
|
- 16, 10, 10, 18, 26, 0, 3, 0, 27, 12,
|
|
- 0, 0, 11, 0, 0, 0, 0, 0, 0, 0,
|
|
- 21, 23, 25, 24, 22, 0, 9, 28, 0, 0,
|
|
- 0, 14, 14, 16, 16, 16, 10, 10, 10, 0,
|
|
- 12, 0, 11, 0, 0, 0, 20, 0, 0, 0,
|
|
- 0, 0, 0, 0, 0, 16, 10, 10, 10, 0,
|
|
- 13, 19, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
-
|
|
- 0, 16, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
- 0, 16, 6, 0, 0, 0, 0, 0, 0, 2,
|
|
- 0, 0, 0, 0, 0, 0, 0, 0, 4, 17,
|
|
- 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
|
|
- 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
|
|
- 5, 8, 0, 0, 0, 0, 7, 0
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 32, 30,
|
|
+ 19, 19, 30, 30, 30, 30, 30, 30, 30, 30,
|
|
+ 30, 30, 30, 30, 30, 30, 16, 17, 17, 30,
|
|
+ 17, 11, 11, 19, 27, 0, 3, 0, 28, 13,
|
|
+ 0, 0, 12, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 22, 24, 26, 25, 23, 0, 10, 29, 0,
|
|
+ 0, 0, 15, 15, 17, 17, 17, 11, 11, 11,
|
|
+ 0, 13, 0, 12, 0, 0, 0, 21, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 17, 11, 11,
|
|
+ 11, 0, 14, 20, 0, 0, 0, 0, 0, 0,
|
|
+
|
|
+ 0, 0, 0, 0, 17, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 17, 7, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 4, 18, 0, 0, 5, 2,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 1, 0, 0, 0, 0, 6, 9, 0,
|
|
+ 0, 0, 0, 8, 0
|
|
} ;
|
|
|
|
-static yyconst flex_int32_t yy_ec[256] =
|
|
+static const YY_CHAR yy_ec[256] =
|
|
{ 0,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
|
|
4, 4, 4, 1, 1, 1, 1, 1, 1, 1,
|
|
@@ -416,9 +399,9 @@ static yyconst flex_int32_t yy_ec[256] =
|
|
22, 22, 22, 22, 24, 22, 22, 25, 22, 22,
|
|
1, 26, 27, 1, 22, 1, 21, 28, 29, 30,
|
|
|
|
- 31, 21, 22, 22, 32, 22, 22, 33, 34, 35,
|
|
- 36, 37, 22, 38, 39, 40, 41, 42, 22, 25,
|
|
- 43, 22, 44, 45, 46, 1, 1, 1, 1, 1,
|
|
+ 31, 21, 32, 22, 33, 22, 22, 34, 35, 36,
|
|
+ 37, 38, 22, 39, 40, 41, 42, 43, 22, 25,
|
|
+ 44, 22, 45, 46, 47, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
@@ -435,163 +418,165 @@ static yyconst flex_int32_t yy_ec[256] =
|
|
1, 1, 1, 1, 1
|
|
} ;
|
|
|
|
-static yyconst flex_int32_t yy_meta[47] =
|
|
+static const YY_CHAR yy_meta[48] =
|
|
{ 0,
|
|
1, 1, 1, 1, 1, 1, 2, 3, 1, 2,
|
|
2, 2, 4, 5, 5, 5, 6, 1, 1, 1,
|
|
7, 8, 8, 8, 8, 1, 1, 7, 7, 7,
|
|
7, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
|
- 8, 8, 8, 3, 1, 4
|
|
+ 8, 8, 8, 8, 3, 1, 4
|
|
} ;
|
|
|
|
-static yyconst flex_int16_t yy_base[173] =
|
|
+static const flex_int16_t yy_base[180] =
|
|
{ 0,
|
|
- 0, 383, 34, 382, 65, 381, 37, 105, 387, 391,
|
|
- 54, 111, 367, 110, 109, 109, 112, 41, 366, 104,
|
|
- 367, 338, 124, 117, 0, 144, 391, 0, 121, 0,
|
|
- 135, 155, 140, 179, 391, 160, 391, 379, 391, 0,
|
|
- 368, 141, 391, 167, 370, 376, 346, 103, 342, 345,
|
|
- 391, 391, 391, 391, 391, 358, 391, 391, 175, 342,
|
|
- 338, 391, 355, 0, 185, 339, 184, 347, 346, 0,
|
|
- 0, 322, 175, 357, 175, 363, 352, 324, 330, 323,
|
|
- 332, 326, 201, 324, 329, 322, 391, 333, 181, 309,
|
|
- 391, 341, 340, 313, 320, 338, 178, 311, 146, 317,
|
|
-
|
|
- 314, 315, 335, 331, 303, 300, 309, 299, 308, 188,
|
|
- 336, 335, 391, 305, 320, 281, 283, 271, 203, 288,
|
|
- 281, 271, 266, 264, 245, 242, 208, 104, 391, 391,
|
|
- 244, 218, 204, 219, 206, 224, 201, 212, 204, 229,
|
|
- 215, 208, 207, 200, 219, 391, 233, 221, 200, 181,
|
|
- 391, 391, 149, 122, 86, 41, 391, 391, 245, 251,
|
|
- 259, 263, 267, 273, 280, 284, 292, 300, 304, 310,
|
|
- 318, 326
|
|
+ 0, 393, 35, 392, 66, 391, 38, 107, 397, 401,
|
|
+ 55, 113, 377, 112, 111, 111, 114, 42, 376, 106,
|
|
+ 377, 347, 126, 120, 0, 147, 401, 0, 124, 0,
|
|
+ 137, 158, 170, 163, 401, 153, 401, 389, 401, 0,
|
|
+ 378, 120, 401, 131, 380, 386, 355, 139, 351, 355,
|
|
+ 351, 401, 401, 401, 401, 401, 367, 401, 401, 185,
|
|
+ 350, 346, 401, 364, 0, 185, 347, 189, 356, 355,
|
|
+ 0, 0, 330, 180, 366, 141, 372, 361, 332, 338,
|
|
+ 331, 341, 334, 326, 205, 331, 337, 329, 401, 341,
|
|
+ 167, 316, 401, 349, 348, 320, 328, 346, 180, 318,
|
|
+
|
|
+ 324, 209, 324, 320, 322, 342, 338, 309, 306, 315,
|
|
+ 305, 315, 312, 192, 342, 341, 401, 293, 306, 282,
|
|
+ 268, 252, 255, 203, 285, 282, 272, 268, 252, 233,
|
|
+ 232, 239, 208, 107, 401, 401, 238, 211, 401, 211,
|
|
+ 212, 208, 228, 203, 215, 207, 233, 222, 212, 211,
|
|
+ 203, 227, 401, 237, 225, 204, 185, 401, 401, 149,
|
|
+ 128, 88, 42, 401, 401, 253, 259, 267, 271, 275,
|
|
+ 281, 288, 292, 300, 308, 312, 318, 326, 334
|
|
} ;
|
|
|
|
-static yyconst flex_int16_t yy_def[173] =
|
|
+static const flex_int16_t yy_def[180] =
|
|
{ 0,
|
|
- 158, 1, 1, 3, 158, 5, 1, 1, 158, 158,
|
|
- 158, 158, 158, 159, 160, 161, 158, 158, 158, 158,
|
|
- 162, 158, 158, 158, 163, 162, 158, 164, 165, 164,
|
|
- 164, 158, 158, 158, 158, 159, 158, 159, 158, 166,
|
|
- 158, 161, 158, 161, 167, 168, 158, 158, 158, 158,
|
|
- 158, 158, 158, 158, 158, 162, 158, 158, 158, 158,
|
|
- 158, 158, 162, 164, 165, 164, 158, 158, 158, 169,
|
|
- 166, 170, 161, 167, 167, 168, 158, 158, 158, 158,
|
|
- 158, 158, 158, 158, 158, 164, 158, 158, 169, 170,
|
|
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
|
|
-
|
|
- 158, 164, 158, 158, 158, 158, 158, 158, 158, 171,
|
|
- 158, 164, 158, 158, 158, 158, 158, 158, 171, 158,
|
|
- 171, 158, 158, 158, 158, 158, 158, 158, 158, 158,
|
|
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
|
|
- 172, 158, 158, 158, 172, 158, 172, 158, 158, 158,
|
|
- 158, 158, 158, 158, 158, 158, 158, 0, 158, 158,
|
|
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
|
|
- 158, 158
|
|
+ 165, 1, 1, 3, 165, 5, 1, 1, 165, 165,
|
|
+ 165, 165, 165, 166, 167, 168, 165, 165, 165, 165,
|
|
+ 169, 165, 165, 165, 170, 169, 165, 171, 172, 171,
|
|
+ 171, 165, 165, 165, 165, 166, 165, 166, 165, 173,
|
|
+ 165, 168, 165, 168, 174, 175, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 165, 165, 165, 169, 165, 165, 165,
|
|
+ 165, 165, 165, 169, 171, 172, 171, 165, 165, 165,
|
|
+ 176, 173, 177, 168, 174, 174, 175, 165, 165, 165,
|
|
+ 165, 165, 165, 165, 165, 165, 165, 171, 165, 165,
|
|
+ 176, 177, 165, 165, 165, 165, 165, 165, 165, 165,
|
|
+
|
|
+ 165, 165, 165, 165, 171, 165, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 178, 165, 171, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 178, 165, 178, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 165, 165, 165, 165, 179, 165, 165,
|
|
+ 165, 179, 165, 179, 165, 165, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 165, 0, 165, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 165, 165, 165, 165, 165, 165
|
|
} ;
|
|
|
|
-static yyconst flex_int16_t yy_nxt[438] =
|
|
+static const flex_int16_t yy_nxt[449] =
|
|
{ 0,
|
|
10, 11, 12, 11, 13, 14, 10, 15, 16, 10,
|
|
10, 10, 17, 10, 10, 10, 10, 18, 19, 20,
|
|
21, 21, 21, 21, 21, 10, 10, 21, 21, 21,
|
|
21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
|
|
- 21, 21, 21, 10, 22, 10, 24, 25, 25, 25,
|
|
- 32, 33, 33, 157, 26, 34, 34, 34, 51, 52,
|
|
- 27, 26, 26, 26, 26, 10, 11, 12, 11, 13,
|
|
- 14, 28, 15, 16, 28, 28, 28, 24, 28, 28,
|
|
- 28, 10, 18, 19, 20, 29, 29, 29, 29, 29,
|
|
- 30, 10, 29, 29, 29, 29, 29, 29, 29, 29,
|
|
-
|
|
- 29, 29, 29, 29, 29, 29, 29, 29, 10, 22,
|
|
- 10, 23, 34, 34, 34, 37, 39, 43, 32, 33,
|
|
- 33, 45, 54, 55, 46, 59, 45, 64, 156, 46,
|
|
- 64, 64, 64, 79, 44, 38, 59, 57, 134, 47,
|
|
- 135, 48, 80, 49, 47, 50, 48, 99, 61, 43,
|
|
- 50, 110, 41, 67, 67, 67, 60, 63, 63, 63,
|
|
- 57, 155, 68, 69, 63, 37, 44, 66, 67, 67,
|
|
- 67, 63, 63, 63, 63, 73, 59, 68, 69, 70,
|
|
- 34, 34, 34, 43, 75, 38, 154, 92, 83, 83,
|
|
- 83, 64, 44, 120, 64, 64, 64, 67, 67, 67,
|
|
-
|
|
- 44, 57, 99, 68, 69, 107, 68, 69, 120, 127,
|
|
- 108, 153, 152, 121, 83, 83, 83, 133, 133, 133,
|
|
- 146, 133, 133, 133, 146, 140, 140, 140, 121, 141,
|
|
- 140, 140, 140, 151, 141, 158, 150, 149, 148, 144,
|
|
- 147, 143, 142, 139, 147, 36, 36, 36, 36, 36,
|
|
- 36, 36, 36, 40, 138, 137, 136, 40, 40, 42,
|
|
- 42, 42, 42, 42, 42, 42, 42, 56, 56, 56,
|
|
- 56, 62, 132, 62, 64, 131, 130, 64, 129, 64,
|
|
- 64, 65, 128, 158, 65, 65, 65, 65, 71, 127,
|
|
- 71, 71, 74, 74, 74, 74, 74, 74, 74, 74,
|
|
-
|
|
- 76, 76, 76, 76, 76, 76, 76, 76, 89, 126,
|
|
- 89, 90, 125, 90, 90, 124, 90, 90, 119, 119,
|
|
- 119, 119, 119, 119, 119, 119, 145, 145, 145, 145,
|
|
- 145, 145, 145, 145, 123, 122, 59, 59, 118, 117,
|
|
- 116, 115, 114, 113, 45, 112, 108, 111, 109, 106,
|
|
- 105, 104, 46, 103, 91, 87, 102, 101, 100, 98,
|
|
- 97, 96, 95, 94, 93, 77, 75, 91, 88, 87,
|
|
- 86, 57, 85, 84, 57, 82, 81, 78, 77, 75,
|
|
- 72, 158, 58, 57, 53, 35, 158, 31, 23, 23,
|
|
- 9, 158, 158, 158, 158, 158, 158, 158, 158, 158,
|
|
-
|
|
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
|
|
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
|
|
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
|
|
- 158, 158, 158, 158, 158, 158, 158
|
|
+ 21, 21, 21, 21, 10, 22, 10, 24, 25, 25,
|
|
+ 25, 32, 33, 33, 164, 26, 34, 34, 34, 52,
|
|
+ 53, 27, 26, 26, 26, 26, 10, 11, 12, 11,
|
|
+ 13, 14, 28, 15, 16, 28, 28, 28, 24, 28,
|
|
+ 28, 28, 10, 18, 19, 20, 29, 29, 29, 29,
|
|
+ 29, 30, 10, 29, 29, 29, 29, 29, 29, 29,
|
|
+
|
|
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
|
|
+ 10, 22, 10, 23, 34, 34, 34, 37, 39, 43,
|
|
+ 32, 33, 33, 45, 55, 56, 46, 60, 43, 45,
|
|
+ 65, 163, 46, 65, 65, 65, 44, 38, 60, 74,
|
|
+ 58, 47, 141, 48, 142, 44, 49, 47, 50, 48,
|
|
+ 76, 51, 62, 94, 50, 41, 44, 51, 37, 61,
|
|
+ 64, 64, 64, 58, 34, 34, 34, 64, 162, 80,
|
|
+ 67, 68, 68, 68, 64, 64, 64, 64, 38, 81,
|
|
+ 69, 70, 71, 68, 68, 68, 60, 161, 43, 69,
|
|
+ 70, 65, 69, 70, 65, 65, 65, 125, 85, 85,
|
|
+
|
|
+ 85, 58, 68, 68, 68, 44, 102, 110, 125, 133,
|
|
+ 102, 69, 70, 111, 114, 160, 159, 126, 85, 85,
|
|
+ 85, 140, 140, 140, 140, 140, 140, 153, 126, 147,
|
|
+ 147, 147, 153, 148, 147, 147, 147, 158, 148, 165,
|
|
+ 157, 156, 155, 151, 150, 149, 146, 154, 145, 144,
|
|
+ 143, 139, 154, 36, 36, 36, 36, 36, 36, 36,
|
|
+ 36, 40, 138, 137, 136, 40, 40, 42, 42, 42,
|
|
+ 42, 42, 42, 42, 42, 57, 57, 57, 57, 63,
|
|
+ 135, 63, 65, 134, 165, 65, 133, 65, 65, 66,
|
|
+ 132, 131, 66, 66, 66, 66, 72, 130, 72, 72,
|
|
+
|
|
+ 75, 75, 75, 75, 75, 75, 75, 75, 77, 77,
|
|
+ 77, 77, 77, 77, 77, 77, 91, 129, 91, 92,
|
|
+ 128, 92, 92, 127, 92, 92, 124, 124, 124, 124,
|
|
+ 124, 124, 124, 124, 152, 152, 152, 152, 152, 152,
|
|
+ 152, 152, 60, 60, 123, 122, 121, 120, 119, 118,
|
|
+ 117, 45, 116, 111, 115, 113, 112, 109, 108, 107,
|
|
+ 46, 106, 93, 89, 105, 104, 103, 101, 100, 99,
|
|
+ 98, 97, 96, 95, 78, 76, 93, 90, 89, 88,
|
|
+ 58, 87, 86, 58, 84, 83, 82, 79, 78, 76,
|
|
+ 73, 165, 59, 58, 54, 35, 165, 31, 23, 23,
|
|
+
|
|
+ 9, 165, 165, 165, 165, 165, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 165, 165, 165, 165, 165
|
|
} ;
|
|
|
|
-static yyconst flex_int16_t yy_chk[438] =
|
|
+static const flex_int16_t yy_chk[449] =
|
|
{ 0,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
- 1, 1, 1, 1, 1, 1, 3, 3, 3, 3,
|
|
- 7, 7, 7, 156, 3, 11, 11, 11, 18, 18,
|
|
- 3, 3, 3, 3, 3, 5, 5, 5, 5, 5,
|
|
+ 1, 1, 1, 1, 1, 1, 1, 3, 3, 3,
|
|
+ 3, 7, 7, 7, 163, 3, 11, 11, 11, 18,
|
|
+ 18, 3, 3, 3, 3, 3, 5, 5, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
|
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
|
- 5, 8, 12, 12, 12, 14, 15, 16, 8, 8,
|
|
- 8, 17, 20, 20, 17, 23, 24, 29, 155, 24,
|
|
- 29, 29, 29, 48, 16, 14, 31, 29, 128, 17,
|
|
- 128, 17, 48, 17, 24, 17, 24, 99, 24, 42,
|
|
- 24, 99, 15, 33, 33, 33, 23, 26, 26, 26,
|
|
- 26, 154, 33, 33, 26, 36, 42, 31, 32, 32,
|
|
- 32, 26, 26, 26, 26, 44, 59, 32, 32, 32,
|
|
- 34, 34, 34, 73, 75, 36, 153, 75, 59, 59,
|
|
- 59, 65, 44, 110, 65, 65, 65, 67, 67, 67,
|
|
-
|
|
- 73, 65, 83, 89, 89, 97, 67, 67, 119, 127,
|
|
- 97, 150, 149, 110, 83, 83, 83, 133, 133, 133,
|
|
- 141, 127, 127, 127, 145, 136, 136, 136, 119, 136,
|
|
- 140, 140, 140, 148, 140, 147, 144, 143, 142, 139,
|
|
- 141, 138, 137, 135, 145, 159, 159, 159, 159, 159,
|
|
- 159, 159, 159, 160, 134, 132, 131, 160, 160, 161,
|
|
- 161, 161, 161, 161, 161, 161, 161, 162, 162, 162,
|
|
- 162, 163, 126, 163, 164, 125, 124, 164, 123, 164,
|
|
- 164, 165, 122, 121, 165, 165, 165, 165, 166, 120,
|
|
- 166, 166, 167, 167, 167, 167, 167, 167, 167, 167,
|
|
-
|
|
- 168, 168, 168, 168, 168, 168, 168, 168, 169, 118,
|
|
- 169, 170, 117, 170, 170, 116, 170, 170, 171, 171,
|
|
- 171, 171, 171, 171, 171, 171, 172, 172, 172, 172,
|
|
- 172, 172, 172, 172, 115, 114, 112, 111, 109, 108,
|
|
- 107, 106, 105, 104, 103, 102, 101, 100, 98, 96,
|
|
- 95, 94, 93, 92, 90, 88, 86, 85, 84, 82,
|
|
- 81, 80, 79, 78, 77, 76, 74, 72, 69, 68,
|
|
- 66, 63, 61, 60, 56, 50, 49, 47, 46, 45,
|
|
+ 5, 5, 5, 8, 12, 12, 12, 14, 15, 16,
|
|
+ 8, 8, 8, 17, 20, 20, 17, 23, 42, 24,
|
|
+ 29, 162, 24, 29, 29, 29, 16, 14, 31, 44,
|
|
+ 29, 17, 134, 17, 134, 42, 17, 24, 17, 24,
|
|
+ 76, 17, 24, 76, 24, 15, 44, 24, 36, 23,
|
|
+ 26, 26, 26, 26, 34, 34, 34, 26, 161, 48,
|
|
+ 31, 32, 32, 32, 26, 26, 26, 26, 36, 48,
|
|
+ 32, 32, 32, 33, 33, 33, 60, 160, 74, 91,
|
|
+ 91, 66, 33, 33, 66, 66, 66, 114, 60, 60,
|
|
+
|
|
+ 60, 66, 68, 68, 68, 74, 85, 99, 124, 133,
|
|
+ 102, 68, 68, 99, 102, 157, 156, 114, 85, 85,
|
|
+ 85, 133, 133, 133, 140, 140, 140, 148, 124, 143,
|
|
+ 143, 143, 152, 143, 147, 147, 147, 155, 147, 154,
|
|
+ 151, 150, 149, 146, 145, 144, 142, 148, 141, 138,
|
|
+ 137, 132, 152, 166, 166, 166, 166, 166, 166, 166,
|
|
+ 166, 167, 131, 130, 129, 167, 167, 168, 168, 168,
|
|
+ 168, 168, 168, 168, 168, 169, 169, 169, 169, 170,
|
|
+ 128, 170, 171, 127, 126, 171, 125, 171, 171, 172,
|
|
+ 123, 122, 172, 172, 172, 172, 173, 121, 173, 173,
|
|
+
|
|
+ 174, 174, 174, 174, 174, 174, 174, 174, 175, 175,
|
|
+ 175, 175, 175, 175, 175, 175, 176, 120, 176, 177,
|
|
+ 119, 177, 177, 118, 177, 177, 178, 178, 178, 178,
|
|
+ 178, 178, 178, 178, 179, 179, 179, 179, 179, 179,
|
|
+ 179, 179, 116, 115, 113, 112, 111, 110, 109, 108,
|
|
+ 107, 106, 105, 104, 103, 101, 100, 98, 97, 96,
|
|
+ 95, 94, 92, 90, 88, 87, 86, 84, 83, 82,
|
|
+ 81, 80, 79, 78, 77, 75, 73, 70, 69, 67,
|
|
+ 64, 62, 61, 57, 51, 50, 49, 47, 46, 45,
|
|
41, 38, 22, 21, 19, 13, 9, 6, 4, 2,
|
|
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
|
|
|
|
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
|
|
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
|
|
- 158, 158, 158, 158, 158, 158, 158, 158, 158, 158,
|
|
- 158, 158, 158, 158, 158, 158, 158
|
|
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 165, 165, 165, 165, 165, 165, 165,
|
|
+ 165, 165, 165, 165, 165, 165, 165, 165
|
|
} ;
|
|
|
|
static yy_state_type yy_last_accepting_state;
|
|
@@ -608,7 +593,7 @@ int yy_flex_debug = 0;
|
|
#define YY_MORE_ADJ 0
|
|
#define YY_RESTORE_YY_MORE_OFFSET
|
|
char *yytext;
|
|
-#line 1 "dtc-lexer.l"
|
|
+#line 1 "<stdin>"
|
|
/*
|
|
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
|
*
|
|
@@ -632,7 +617,7 @@ char *yytext;
|
|
|
|
|
|
|
|
-#line 37 "dtc-lexer.l"
|
|
+#line 37 "<stdin>"
|
|
#include "dtc.h"
|
|
#include "srcpos.h"
|
|
#include "dtc-parser.tab.h"
|
|
@@ -661,8 +646,10 @@ static int dts_version = 1;
|
|
|
|
static void push_input_file(const char *filename);
|
|
static bool pop_input_file(void);
|
|
-static void lexical_error(const char *fmt, ...);
|
|
-#line 666 "dtc-lexer.lex.c"
|
|
+static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
|
|
+
|
|
+#line 652 "dtc-lexer.l.c"
|
|
+#line 653 "dtc-lexer.l.c"
|
|
|
|
#define INITIAL 0
|
|
#define BYTESTRING 1
|
|
@@ -681,36 +668,36 @@ static void lexical_error(const char *fmt, ...);
|
|
#define YY_EXTRA_TYPE void *
|
|
#endif
|
|
|
|
-static int yy_init_globals (void );
|
|
+static int yy_init_globals ( void );
|
|
|
|
/* Accessor methods to globals.
|
|
These are made visible to non-reentrant scanners for convenience. */
|
|
|
|
-int yylex_destroy (void );
|
|
+int yylex_destroy ( void );
|
|
|
|
-int yyget_debug (void );
|
|
+int yyget_debug ( void );
|
|
|
|
-void yyset_debug (int debug_flag );
|
|
+void yyset_debug ( int debug_flag );
|
|
|
|
-YY_EXTRA_TYPE yyget_extra (void );
|
|
+YY_EXTRA_TYPE yyget_extra ( void );
|
|
|
|
-void yyset_extra (YY_EXTRA_TYPE user_defined );
|
|
+void yyset_extra ( YY_EXTRA_TYPE user_defined );
|
|
|
|
-FILE *yyget_in (void );
|
|
+FILE *yyget_in ( void );
|
|
|
|
-void yyset_in (FILE * in_str );
|
|
+void yyset_in ( FILE * _in_str );
|
|
|
|
-FILE *yyget_out (void );
|
|
+FILE *yyget_out ( void );
|
|
|
|
-void yyset_out (FILE * out_str );
|
|
+void yyset_out ( FILE * _out_str );
|
|
|
|
-yy_size_t yyget_leng (void );
|
|
+ int yyget_leng ( void );
|
|
|
|
-char *yyget_text (void );
|
|
+char *yyget_text ( void );
|
|
|
|
-int yyget_lineno (void );
|
|
+int yyget_lineno ( void );
|
|
|
|
-void yyset_lineno (int line_number );
|
|
+void yyset_lineno ( int _line_number );
|
|
|
|
/* Macros after this point can all be overridden by user definitions in
|
|
* section 1.
|
|
@@ -718,26 +705,29 @@ void yyset_lineno (int line_number );
|
|
|
|
#ifndef YY_SKIP_YYWRAP
|
|
#ifdef __cplusplus
|
|
-extern "C" int yywrap (void );
|
|
+extern "C" int yywrap ( void );
|
|
#else
|
|
-extern int yywrap (void );
|
|
+extern int yywrap ( void );
|
|
+#endif
|
|
#endif
|
|
+
|
|
+#ifndef YY_NO_UNPUT
|
|
+
|
|
#endif
|
|
|
|
#ifndef yytext_ptr
|
|
-static void yy_flex_strncpy (char *,yyconst char *,int );
|
|
+static void yy_flex_strncpy ( char *, const char *, int );
|
|
#endif
|
|
|
|
#ifdef YY_NEED_STRLEN
|
|
-static int yy_flex_strlen (yyconst char * );
|
|
+static int yy_flex_strlen ( const char * );
|
|
#endif
|
|
|
|
#ifndef YY_NO_INPUT
|
|
-
|
|
#ifdef __cplusplus
|
|
-static int yyinput (void );
|
|
+static int yyinput ( void );
|
|
#else
|
|
-static int input (void );
|
|
+static int input ( void );
|
|
#endif
|
|
|
|
#endif
|
|
@@ -757,7 +747,7 @@ static int input (void );
|
|
/* This used to be an fputs(), but since the string might contain NUL's,
|
|
* we now use fwrite().
|
|
*/
|
|
-#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
|
|
+#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
|
|
#endif
|
|
|
|
/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
|
|
@@ -768,7 +758,7 @@ static int input (void );
|
|
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
|
|
{ \
|
|
int c = '*'; \
|
|
- size_t n; \
|
|
+ int n; \
|
|
for ( n = 0; n < max_size && \
|
|
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
|
|
buf[n] = (char) c; \
|
|
@@ -781,7 +771,7 @@ static int input (void );
|
|
else \
|
|
{ \
|
|
errno=0; \
|
|
- while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
|
|
+ while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
|
|
{ \
|
|
if( errno != EINTR) \
|
|
{ \
|
|
@@ -836,7 +826,7 @@ extern int yylex (void);
|
|
|
|
/* Code executed at the end of each rule. */
|
|
#ifndef YY_BREAK
|
|
-#define YY_BREAK break;
|
|
+#define YY_BREAK /*LINTED*/break;
|
|
#endif
|
|
|
|
#define YY_RULE_SETUP \
|
|
@@ -849,9 +839,9 @@ extern int yylex (void);
|
|
*/
|
|
YY_DECL
|
|
{
|
|
- register yy_state_type yy_current_state;
|
|
- register char *yy_cp, *yy_bp;
|
|
- register int yy_act;
|
|
+ yy_state_type yy_current_state;
|
|
+ char *yy_cp, *yy_bp;
|
|
+ int yy_act;
|
|
|
|
if ( !(yy_init) )
|
|
{
|
|
@@ -873,18 +863,18 @@ YY_DECL
|
|
if ( ! YY_CURRENT_BUFFER ) {
|
|
yyensure_buffer_stack ();
|
|
YY_CURRENT_BUFFER_LVALUE =
|
|
- yy_create_buffer(yyin,YY_BUF_SIZE );
|
|
+ yy_create_buffer( yyin, YY_BUF_SIZE );
|
|
}
|
|
|
|
- yy_load_buffer_state( );
|
|
+ yy_load_buffer_state( );
|
|
}
|
|
|
|
{
|
|
-#line 68 "dtc-lexer.l"
|
|
+#line 69 "<stdin>"
|
|
|
|
-#line 886 "dtc-lexer.lex.c"
|
|
+#line 876 "dtc-lexer.l.c"
|
|
|
|
- while ( 1 ) /* loops until end-of-file is reached */
|
|
+ while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
|
|
{
|
|
yy_cp = (yy_c_buf_p);
|
|
|
|
@@ -901,7 +891,7 @@ YY_DECL
|
|
yy_match:
|
|
do
|
|
{
|
|
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
|
|
+ YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
|
|
if ( yy_accept[yy_current_state] )
|
|
{
|
|
(yy_last_accepting_state) = yy_current_state;
|
|
@@ -910,13 +900,13 @@ yy_match:
|
|
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
|
|
{
|
|
yy_current_state = (int) yy_def[yy_current_state];
|
|
- if ( yy_current_state >= 159 )
|
|
- yy_c = yy_meta[(unsigned int) yy_c];
|
|
+ if ( yy_current_state >= 166 )
|
|
+ yy_c = yy_meta[yy_c];
|
|
}
|
|
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
|
|
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
|
|
++yy_cp;
|
|
}
|
|
- while ( yy_current_state != 158 );
|
|
+ while ( yy_current_state != 165 );
|
|
yy_cp = (yy_last_accepting_cpos);
|
|
yy_current_state = (yy_last_accepting_state);
|
|
|
|
@@ -939,7 +929,7 @@ do_action: /* This label is used only to access EOF actions. */
|
|
case 1:
|
|
/* rule 1 can match eol */
|
|
YY_RULE_SETUP
|
|
-#line 69 "dtc-lexer.l"
|
|
+#line 70 "<stdin>"
|
|
{
|
|
char *name = strchr(yytext, '\"') + 1;
|
|
yytext[yyleng-1] = '\0';
|
|
@@ -949,33 +939,41 @@ YY_RULE_SETUP
|
|
case 2:
|
|
/* rule 2 can match eol */
|
|
YY_RULE_SETUP
|
|
-#line 75 "dtc-lexer.l"
|
|
+#line 76 "<stdin>"
|
|
{
|
|
- char *line, *tmp, *fn;
|
|
+ char *line, *fnstart, *fnend;
|
|
+ struct data fn;
|
|
/* skip text before line # */
|
|
line = yytext;
|
|
while (!isdigit((unsigned char)*line))
|
|
line++;
|
|
- /* skip digits in line # */
|
|
- tmp = line;
|
|
- while (!isspace((unsigned char)*tmp))
|
|
- tmp++;
|
|
- /* "NULL"-terminate line # */
|
|
- *tmp = '\0';
|
|
- /* start of filename */
|
|
- fn = strchr(tmp + 1, '"') + 1;
|
|
- /* strip trailing " from filename */
|
|
- tmp = strchr(fn, '"');
|
|
- *tmp = 0;
|
|
+
|
|
+ /* regexp ensures that first and list "
|
|
+ * in the whole yytext are those at
|
|
+ * beginning and end of the filename string */
|
|
+ fnstart = memchr(yytext, '"', yyleng);
|
|
+ for (fnend = yytext + yyleng - 1;
|
|
+ *fnend != '"'; fnend--)
|
|
+ ;
|
|
+ assert(fnstart && fnend && (fnend > fnstart));
|
|
+
|
|
+ fn = data_copy_escape_string(fnstart + 1,
|
|
+ fnend - fnstart - 1);
|
|
+
|
|
+ /* Don't allow nuls in filenames */
|
|
+ if (memchr(fn.val, '\0', fn.len - 1))
|
|
+ lexical_error("nul in line number directive");
|
|
+
|
|
/* -1 since #line is the number of the next line */
|
|
- srcpos_set_line(xstrdup(fn), atoi(line) - 1);
|
|
+ srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
|
|
+ data_free(fn);
|
|
}
|
|
YY_BREAK
|
|
case YY_STATE_EOF(INITIAL):
|
|
case YY_STATE_EOF(BYTESTRING):
|
|
case YY_STATE_EOF(PROPNODENAME):
|
|
case YY_STATE_EOF(V1):
|
|
-#line 96 "dtc-lexer.l"
|
|
+#line 105 "<stdin>"
|
|
{
|
|
if (!pop_input_file()) {
|
|
yyterminate();
|
|
@@ -985,7 +983,7 @@ case YY_STATE_EOF(V1):
|
|
case 3:
|
|
/* rule 3 can match eol */
|
|
YY_RULE_SETUP
|
|
-#line 102 "dtc-lexer.l"
|
|
+#line 111 "<stdin>"
|
|
{
|
|
DPRINT("String: %s\n", yytext);
|
|
yylval.data = data_copy_escape_string(yytext+1,
|
|
@@ -995,7 +993,7 @@ YY_RULE_SETUP
|
|
YY_BREAK
|
|
case 4:
|
|
YY_RULE_SETUP
|
|
-#line 109 "dtc-lexer.l"
|
|
+#line 118 "<stdin>"
|
|
{
|
|
DPRINT("Keyword: /dts-v1/\n");
|
|
dts_version = 1;
|
|
@@ -1005,25 +1003,33 @@ YY_RULE_SETUP
|
|
YY_BREAK
|
|
case 5:
|
|
YY_RULE_SETUP
|
|
-#line 116 "dtc-lexer.l"
|
|
+#line 125 "<stdin>"
|
|
+{
|
|
+ DPRINT("Keyword: /plugin/\n");
|
|
+ return DT_PLUGIN;
|
|
+ }
|
|
+ YY_BREAK
|
|
+case 6:
|
|
+YY_RULE_SETUP
|
|
+#line 130 "<stdin>"
|
|
{
|
|
DPRINT("Keyword: /memreserve/\n");
|
|
BEGIN_DEFAULT();
|
|
return DT_MEMRESERVE;
|
|
}
|
|
YY_BREAK
|
|
-case 6:
|
|
+case 7:
|
|
YY_RULE_SETUP
|
|
-#line 122 "dtc-lexer.l"
|
|
+#line 136 "<stdin>"
|
|
{
|
|
DPRINT("Keyword: /bits/\n");
|
|
BEGIN_DEFAULT();
|
|
return DT_BITS;
|
|
}
|
|
YY_BREAK
|
|
-case 7:
|
|
+case 8:
|
|
YY_RULE_SETUP
|
|
-#line 128 "dtc-lexer.l"
|
|
+#line 142 "<stdin>"
|
|
{
|
|
DPRINT("Keyword: /delete-property/\n");
|
|
DPRINT("<PROPNODENAME>\n");
|
|
@@ -1031,9 +1037,9 @@ YY_RULE_SETUP
|
|
return DT_DEL_PROP;
|
|
}
|
|
YY_BREAK
|
|
-case 8:
|
|
+case 9:
|
|
YY_RULE_SETUP
|
|
-#line 135 "dtc-lexer.l"
|
|
+#line 149 "<stdin>"
|
|
{
|
|
DPRINT("Keyword: /delete-node/\n");
|
|
DPRINT("<PROPNODENAME>\n");
|
|
@@ -1041,9 +1047,9 @@ YY_RULE_SETUP
|
|
return DT_DEL_NODE;
|
|
}
|
|
YY_BREAK
|
|
-case 9:
|
|
+case 10:
|
|
YY_RULE_SETUP
|
|
-#line 142 "dtc-lexer.l"
|
|
+#line 156 "<stdin>"
|
|
{
|
|
DPRINT("Label: %s\n", yytext);
|
|
yylval.labelref = xstrdup(yytext);
|
|
@@ -1051,9 +1057,9 @@ YY_RULE_SETUP
|
|
return DT_LABEL;
|
|
}
|
|
YY_BREAK
|
|
-case 10:
|
|
+case 11:
|
|
YY_RULE_SETUP
|
|
-#line 149 "dtc-lexer.l"
|
|
+#line 163 "<stdin>"
|
|
{
|
|
char *e;
|
|
DPRINT("Integer Literal: '%s'\n", yytext);
|
|
@@ -1061,7 +1067,10 @@ YY_RULE_SETUP
|
|
errno = 0;
|
|
yylval.integer = strtoull(yytext, &e, 0);
|
|
|
|
- assert(!(*e) || !e[strspn(e, "UL")]);
|
|
+ if (*e && e[strspn(e, "UL")]) {
|
|
+ lexical_error("Bad integer literal '%s'",
|
|
+ yytext);
|
|
+ }
|
|
|
|
if (errno == ERANGE)
|
|
lexical_error("Integer literal '%s' out of range",
|
|
@@ -1073,10 +1082,10 @@ YY_RULE_SETUP
|
|
return DT_LITERAL;
|
|
}
|
|
YY_BREAK
|
|
-case 11:
|
|
-/* rule 11 can match eol */
|
|
+case 12:
|
|
+/* rule 12 can match eol */
|
|
YY_RULE_SETUP
|
|
-#line 168 "dtc-lexer.l"
|
|
+#line 185 "<stdin>"
|
|
{
|
|
struct data d;
|
|
DPRINT("Character literal: %s\n", yytext);
|
|
@@ -1085,31 +1094,31 @@ YY_RULE_SETUP
|
|
if (d.len == 1) {
|
|
lexical_error("Empty character literal");
|
|
yylval.integer = 0;
|
|
- return DT_CHAR_LITERAL;
|
|
- }
|
|
+ } else {
|
|
+ yylval.integer = (unsigned char)d.val[0];
|
|
|
|
- yylval.integer = (unsigned char)d.val[0];
|
|
-
|
|
- if (d.len > 2)
|
|
- lexical_error("Character literal has %d"
|
|
- " characters instead of 1",
|
|
- d.len - 1);
|
|
+ if (d.len > 2)
|
|
+ lexical_error("Character literal has %d"
|
|
+ " characters instead of 1",
|
|
+ d.len - 1);
|
|
+ }
|
|
|
|
+ data_free(d);
|
|
return DT_CHAR_LITERAL;
|
|
}
|
|
YY_BREAK
|
|
-case 12:
|
|
+case 13:
|
|
YY_RULE_SETUP
|
|
-#line 189 "dtc-lexer.l"
|
|
+#line 206 "<stdin>"
|
|
{ /* label reference */
|
|
DPRINT("Ref: %s\n", yytext+1);
|
|
yylval.labelref = xstrdup(yytext+1);
|
|
return DT_REF;
|
|
}
|
|
YY_BREAK
|
|
-case 13:
|
|
+case 14:
|
|
YY_RULE_SETUP
|
|
-#line 195 "dtc-lexer.l"
|
|
+#line 212 "<stdin>"
|
|
{ /* new-style path reference */
|
|
yytext[yyleng-1] = '\0';
|
|
DPRINT("Ref: %s\n", yytext+2);
|
|
@@ -1117,27 +1126,27 @@ YY_RULE_SETUP
|
|
return DT_REF;
|
|
}
|
|
YY_BREAK
|
|
-case 14:
|
|
+case 15:
|
|
YY_RULE_SETUP
|
|
-#line 202 "dtc-lexer.l"
|
|
+#line 219 "<stdin>"
|
|
{
|
|
yylval.byte = strtol(yytext, NULL, 16);
|
|
DPRINT("Byte: %02x\n", (int)yylval.byte);
|
|
return DT_BYTE;
|
|
}
|
|
YY_BREAK
|
|
-case 15:
|
|
+case 16:
|
|
YY_RULE_SETUP
|
|
-#line 208 "dtc-lexer.l"
|
|
+#line 225 "<stdin>"
|
|
{
|
|
DPRINT("/BYTESTRING\n");
|
|
BEGIN_DEFAULT();
|
|
return ']';
|
|
}
|
|
YY_BREAK
|
|
-case 16:
|
|
+case 17:
|
|
YY_RULE_SETUP
|
|
-#line 214 "dtc-lexer.l"
|
|
+#line 231 "<stdin>"
|
|
{
|
|
DPRINT("PropNodeName: %s\n", yytext);
|
|
yylval.propnodename = xstrdup((yytext[0] == '\\') ?
|
|
@@ -1146,75 +1155,75 @@ YY_RULE_SETUP
|
|
return DT_PROPNODENAME;
|
|
}
|
|
YY_BREAK
|
|
-case 17:
|
|
+case 18:
|
|
YY_RULE_SETUP
|
|
-#line 222 "dtc-lexer.l"
|
|
+#line 239 "<stdin>"
|
|
{
|
|
DPRINT("Binary Include\n");
|
|
return DT_INCBIN;
|
|
}
|
|
YY_BREAK
|
|
-case 18:
|
|
-/* rule 18 can match eol */
|
|
-YY_RULE_SETUP
|
|
-#line 227 "dtc-lexer.l"
|
|
-/* eat whitespace */
|
|
- YY_BREAK
|
|
case 19:
|
|
/* rule 19 can match eol */
|
|
YY_RULE_SETUP
|
|
-#line 228 "dtc-lexer.l"
|
|
-/* eat C-style comments */
|
|
+#line 244 "<stdin>"
|
|
+/* eat whitespace */
|
|
YY_BREAK
|
|
case 20:
|
|
/* rule 20 can match eol */
|
|
YY_RULE_SETUP
|
|
-#line 229 "dtc-lexer.l"
|
|
-/* eat C++-style comments */
|
|
+#line 245 "<stdin>"
|
|
+/* eat C-style comments */
|
|
YY_BREAK
|
|
case 21:
|
|
+/* rule 21 can match eol */
|
|
YY_RULE_SETUP
|
|
-#line 231 "dtc-lexer.l"
|
|
-{ return DT_LSHIFT; };
|
|
+#line 246 "<stdin>"
|
|
+/* eat C++-style comments */
|
|
YY_BREAK
|
|
case 22:
|
|
YY_RULE_SETUP
|
|
-#line 232 "dtc-lexer.l"
|
|
-{ return DT_RSHIFT; };
|
|
+#line 248 "<stdin>"
|
|
+{ return DT_LSHIFT; };
|
|
YY_BREAK
|
|
case 23:
|
|
YY_RULE_SETUP
|
|
-#line 233 "dtc-lexer.l"
|
|
-{ return DT_LE; };
|
|
+#line 249 "<stdin>"
|
|
+{ return DT_RSHIFT; };
|
|
YY_BREAK
|
|
case 24:
|
|
YY_RULE_SETUP
|
|
-#line 234 "dtc-lexer.l"
|
|
-{ return DT_GE; };
|
|
+#line 250 "<stdin>"
|
|
+{ return DT_LE; };
|
|
YY_BREAK
|
|
case 25:
|
|
YY_RULE_SETUP
|
|
-#line 235 "dtc-lexer.l"
|
|
-{ return DT_EQ; };
|
|
+#line 251 "<stdin>"
|
|
+{ return DT_GE; };
|
|
YY_BREAK
|
|
case 26:
|
|
YY_RULE_SETUP
|
|
-#line 236 "dtc-lexer.l"
|
|
-{ return DT_NE; };
|
|
+#line 252 "<stdin>"
|
|
+{ return DT_EQ; };
|
|
YY_BREAK
|
|
case 27:
|
|
YY_RULE_SETUP
|
|
-#line 237 "dtc-lexer.l"
|
|
-{ return DT_AND; };
|
|
+#line 253 "<stdin>"
|
|
+{ return DT_NE; };
|
|
YY_BREAK
|
|
case 28:
|
|
YY_RULE_SETUP
|
|
-#line 238 "dtc-lexer.l"
|
|
-{ return DT_OR; };
|
|
+#line 254 "<stdin>"
|
|
+{ return DT_AND; };
|
|
YY_BREAK
|
|
case 29:
|
|
YY_RULE_SETUP
|
|
-#line 240 "dtc-lexer.l"
|
|
+#line 255 "<stdin>"
|
|
+{ return DT_OR; };
|
|
+ YY_BREAK
|
|
+case 30:
|
|
+YY_RULE_SETUP
|
|
+#line 257 "<stdin>"
|
|
{
|
|
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
|
|
(unsigned)yytext[0]);
|
|
@@ -1230,12 +1239,12 @@ YY_RULE_SETUP
|
|
return yytext[0];
|
|
}
|
|
YY_BREAK
|
|
-case 30:
|
|
+case 31:
|
|
YY_RULE_SETUP
|
|
-#line 255 "dtc-lexer.l"
|
|
+#line 272 "<stdin>"
|
|
ECHO;
|
|
YY_BREAK
|
|
-#line 1239 "dtc-lexer.lex.c"
|
|
+#line 1248 "dtc-lexer.l.c"
|
|
|
|
case YY_END_OF_BUFFER:
|
|
{
|
|
@@ -1312,7 +1321,7 @@ ECHO;
|
|
{
|
|
(yy_did_buffer_switch_on_eof) = 0;
|
|
|
|
- if ( yywrap( ) )
|
|
+ if ( yywrap( ) )
|
|
{
|
|
/* Note: because we've taken care in
|
|
* yy_get_next_buffer() to have set up
|
|
@@ -1377,9 +1386,9 @@ ECHO;
|
|
*/
|
|
static int yy_get_next_buffer (void)
|
|
{
|
|
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
|
|
- register char *source = (yytext_ptr);
|
|
- register int number_to_move, i;
|
|
+ char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
|
|
+ char *source = (yytext_ptr);
|
|
+ int number_to_move, i;
|
|
int ret_val;
|
|
|
|
if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
|
|
@@ -1408,7 +1417,7 @@ static int yy_get_next_buffer (void)
|
|
/* Try to read more data. */
|
|
|
|
/* First move last chars to start of buffer. */
|
|
- number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
|
|
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1);
|
|
|
|
for ( i = 0; i < number_to_move; ++i )
|
|
*(dest++) = *(source++);
|
|
@@ -1421,7 +1430,7 @@ static int yy_get_next_buffer (void)
|
|
|
|
else
|
|
{
|
|
- yy_size_t num_to_read =
|
|
+ int num_to_read =
|
|
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
|
|
|
|
while ( num_to_read <= 0 )
|
|
@@ -1435,7 +1444,7 @@ static int yy_get_next_buffer (void)
|
|
|
|
if ( b->yy_is_our_buffer )
|
|
{
|
|
- yy_size_t new_size = b->yy_buf_size * 2;
|
|
+ int new_size = b->yy_buf_size * 2;
|
|
|
|
if ( new_size <= 0 )
|
|
b->yy_buf_size += b->yy_buf_size / 8;
|
|
@@ -1444,11 +1453,12 @@ static int yy_get_next_buffer (void)
|
|
|
|
b->yy_ch_buf = (char *)
|
|
/* Include room in for 2 EOB chars. */
|
|
- yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
|
|
+ yyrealloc( (void *) b->yy_ch_buf,
|
|
+ (yy_size_t) (b->yy_buf_size + 2) );
|
|
}
|
|
else
|
|
/* Can't grow it, we don't own it. */
|
|
- b->yy_ch_buf = 0;
|
|
+ b->yy_ch_buf = NULL;
|
|
|
|
if ( ! b->yy_ch_buf )
|
|
YY_FATAL_ERROR(
|
|
@@ -1476,7 +1486,7 @@ static int yy_get_next_buffer (void)
|
|
if ( number_to_move == YY_MORE_ADJ )
|
|
{
|
|
ret_val = EOB_ACT_END_OF_FILE;
|
|
- yyrestart(yyin );
|
|
+ yyrestart( yyin );
|
|
}
|
|
|
|
else
|
|
@@ -1490,12 +1500,15 @@ static int yy_get_next_buffer (void)
|
|
else
|
|
ret_val = EOB_ACT_CONTINUE_SCAN;
|
|
|
|
- if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
|
|
+ if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
|
|
/* Extend the array by 50%, plus the number we really need. */
|
|
- yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
|
|
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
|
|
+ int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
|
|
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
|
|
+ (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size );
|
|
if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
|
|
YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
|
|
+ /* "- 2" to take care of EOB's */
|
|
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
|
|
}
|
|
|
|
(yy_n_chars) += number_to_move;
|
|
@@ -1511,15 +1524,15 @@ static int yy_get_next_buffer (void)
|
|
|
|
static yy_state_type yy_get_previous_state (void)
|
|
{
|
|
- register yy_state_type yy_current_state;
|
|
- register char *yy_cp;
|
|
+ yy_state_type yy_current_state;
|
|
+ char *yy_cp;
|
|
|
|
yy_current_state = (yy_start);
|
|
yy_current_state += YY_AT_BOL();
|
|
|
|
for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
|
|
{
|
|
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
|
|
+ YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
|
|
if ( yy_accept[yy_current_state] )
|
|
{
|
|
(yy_last_accepting_state) = yy_current_state;
|
|
@@ -1528,10 +1541,10 @@ static int yy_get_next_buffer (void)
|
|
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
|
|
{
|
|
yy_current_state = (int) yy_def[yy_current_state];
|
|
- if ( yy_current_state >= 159 )
|
|
- yy_c = yy_meta[(unsigned int) yy_c];
|
|
+ if ( yy_current_state >= 166 )
|
|
+ yy_c = yy_meta[yy_c];
|
|
}
|
|
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
|
|
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
|
|
}
|
|
|
|
return yy_current_state;
|
|
@@ -1544,10 +1557,10 @@ static int yy_get_next_buffer (void)
|
|
*/
|
|
static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
|
|
{
|
|
- register int yy_is_jam;
|
|
- register char *yy_cp = (yy_c_buf_p);
|
|
+ int yy_is_jam;
|
|
+ char *yy_cp = (yy_c_buf_p);
|
|
|
|
- register YY_CHAR yy_c = 1;
|
|
+ YY_CHAR yy_c = 1;
|
|
if ( yy_accept[yy_current_state] )
|
|
{
|
|
(yy_last_accepting_state) = yy_current_state;
|
|
@@ -1556,15 +1569,19 @@ static int yy_get_next_buffer (void)
|
|
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
|
|
{
|
|
yy_current_state = (int) yy_def[yy_current_state];
|
|
- if ( yy_current_state >= 159 )
|
|
- yy_c = yy_meta[(unsigned int) yy_c];
|
|
+ if ( yy_current_state >= 166 )
|
|
+ yy_c = yy_meta[yy_c];
|
|
}
|
|
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
|
|
- yy_is_jam = (yy_current_state == 158);
|
|
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
|
|
+ yy_is_jam = (yy_current_state == 165);
|
|
|
|
return yy_is_jam ? 0 : yy_current_state;
|
|
}
|
|
|
|
+#ifndef YY_NO_UNPUT
|
|
+
|
|
+#endif
|
|
+
|
|
#ifndef YY_NO_INPUT
|
|
#ifdef __cplusplus
|
|
static int yyinput (void)
|
|
@@ -1589,7 +1606,7 @@ static int yy_get_next_buffer (void)
|
|
|
|
else
|
|
{ /* need more input */
|
|
- yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
|
|
+ int offset = (int) ((yy_c_buf_p) - (yytext_ptr));
|
|
++(yy_c_buf_p);
|
|
|
|
switch ( yy_get_next_buffer( ) )
|
|
@@ -1606,14 +1623,14 @@ static int yy_get_next_buffer (void)
|
|
*/
|
|
|
|
/* Reset buffer status. */
|
|
- yyrestart(yyin );
|
|
+ yyrestart( yyin );
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case EOB_ACT_END_OF_FILE:
|
|
{
|
|
- if ( yywrap( ) )
|
|
- return EOF;
|
|
+ if ( yywrap( ) )
|
|
+ return 0;
|
|
|
|
if ( ! (yy_did_buffer_switch_on_eof) )
|
|
YY_NEW_FILE;
|
|
@@ -1652,11 +1669,11 @@ static int yy_get_next_buffer (void)
|
|
if ( ! YY_CURRENT_BUFFER ){
|
|
yyensure_buffer_stack ();
|
|
YY_CURRENT_BUFFER_LVALUE =
|
|
- yy_create_buffer(yyin,YY_BUF_SIZE );
|
|
+ yy_create_buffer( yyin, YY_BUF_SIZE );
|
|
}
|
|
|
|
- yy_init_buffer(YY_CURRENT_BUFFER,input_file );
|
|
- yy_load_buffer_state( );
|
|
+ yy_init_buffer( YY_CURRENT_BUFFER, input_file );
|
|
+ yy_load_buffer_state( );
|
|
}
|
|
|
|
/** Switch to a different input buffer.
|
|
@@ -1684,7 +1701,7 @@ static int yy_get_next_buffer (void)
|
|
}
|
|
|
|
YY_CURRENT_BUFFER_LVALUE = new_buffer;
|
|
- yy_load_buffer_state( );
|
|
+ yy_load_buffer_state( );
|
|
|
|
/* We don't actually know whether we did this switch during
|
|
* EOF (yywrap()) processing, but the only time this flag
|
|
@@ -1712,7 +1729,7 @@ static void yy_load_buffer_state (void)
|
|
{
|
|
YY_BUFFER_STATE b;
|
|
|
|
- b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
|
|
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) );
|
|
if ( ! b )
|
|
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
|
|
|
|
@@ -1721,13 +1738,13 @@ static void yy_load_buffer_state (void)
|
|
/* yy_ch_buf has to be 2 characters longer than the size given because
|
|
* we need to put in 2 end-of-buffer characters.
|
|
*/
|
|
- b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 );
|
|
+ b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) );
|
|
if ( ! b->yy_ch_buf )
|
|
YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
|
|
|
|
b->yy_is_our_buffer = 1;
|
|
|
|
- yy_init_buffer(b,file );
|
|
+ yy_init_buffer( b, file );
|
|
|
|
return b;
|
|
}
|
|
@@ -1746,9 +1763,9 @@ static void yy_load_buffer_state (void)
|
|
YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
|
|
|
|
if ( b->yy_is_our_buffer )
|
|
- yyfree((void *) b->yy_ch_buf );
|
|
+ yyfree( (void *) b->yy_ch_buf );
|
|
|
|
- yyfree((void *) b );
|
|
+ yyfree( (void *) b );
|
|
}
|
|
|
|
/* Initializes or reinitializes a buffer.
|
|
@@ -1760,7 +1777,7 @@ static void yy_load_buffer_state (void)
|
|
{
|
|
int oerrno = errno;
|
|
|
|
- yy_flush_buffer(b );
|
|
+ yy_flush_buffer( b );
|
|
|
|
b->yy_input_file = file;
|
|
b->yy_fill_buffer = 1;
|
|
@@ -1803,7 +1820,7 @@ static void yy_load_buffer_state (void)
|
|
b->yy_buffer_status = YY_BUFFER_NEW;
|
|
|
|
if ( b == YY_CURRENT_BUFFER )
|
|
- yy_load_buffer_state( );
|
|
+ yy_load_buffer_state( );
|
|
}
|
|
|
|
/** Pushes the new state onto the stack. The new state becomes
|
|
@@ -1834,7 +1851,7 @@ void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
|
|
YY_CURRENT_BUFFER_LVALUE = new_buffer;
|
|
|
|
/* copied from yy_switch_to_buffer. */
|
|
- yy_load_buffer_state( );
|
|
+ yy_load_buffer_state( );
|
|
(yy_did_buffer_switch_on_eof) = 1;
|
|
}
|
|
|
|
@@ -1853,7 +1870,7 @@ void yypop_buffer_state (void)
|
|
--(yy_buffer_stack_top);
|
|
|
|
if (YY_CURRENT_BUFFER) {
|
|
- yy_load_buffer_state( );
|
|
+ yy_load_buffer_state( );
|
|
(yy_did_buffer_switch_on_eof) = 1;
|
|
}
|
|
}
|
|
@@ -1871,15 +1888,15 @@ static void yyensure_buffer_stack (void)
|
|
* scanner will even need a stack. We use 2 instead of 1 to avoid an
|
|
* immediate realloc on the next call.
|
|
*/
|
|
- num_to_alloc = 1;
|
|
+ num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
|
|
(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
|
|
(num_to_alloc * sizeof(struct yy_buffer_state*)
|
|
);
|
|
if ( ! (yy_buffer_stack) )
|
|
YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
|
|
-
|
|
+
|
|
memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
|
|
-
|
|
+
|
|
(yy_buffer_stack_max) = num_to_alloc;
|
|
(yy_buffer_stack_top) = 0;
|
|
return;
|
|
@@ -1888,7 +1905,7 @@ static void yyensure_buffer_stack (void)
|
|
if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
|
|
|
|
/* Increase the buffer to prepare for a possible push. */
|
|
- int grow_size = 8 /* arbitrary grow size */;
|
|
+ yy_size_t grow_size = 8 /* arbitrary grow size */;
|
|
|
|
num_to_alloc = (yy_buffer_stack_max) + grow_size;
|
|
(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
|
|
@@ -1908,7 +1925,7 @@ static void yyensure_buffer_stack (void)
|
|
* @param base the character buffer
|
|
* @param size the size in bytes of the character buffer
|
|
*
|
|
- * @return the newly allocated buffer state object.
|
|
+ * @return the newly allocated buffer state object.
|
|
*/
|
|
YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
|
|
{
|
|
@@ -1918,23 +1935,23 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
|
|
base[size-2] != YY_END_OF_BUFFER_CHAR ||
|
|
base[size-1] != YY_END_OF_BUFFER_CHAR )
|
|
/* They forgot to leave room for the EOB's. */
|
|
- return 0;
|
|
+ return NULL;
|
|
|
|
- b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
|
|
+ b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) );
|
|
if ( ! b )
|
|
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
|
|
|
|
- b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
|
|
+ b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */
|
|
b->yy_buf_pos = b->yy_ch_buf = base;
|
|
b->yy_is_our_buffer = 0;
|
|
- b->yy_input_file = 0;
|
|
+ b->yy_input_file = NULL;
|
|
b->yy_n_chars = b->yy_buf_size;
|
|
b->yy_is_interactive = 0;
|
|
b->yy_at_bol = 1;
|
|
b->yy_fill_buffer = 0;
|
|
b->yy_buffer_status = YY_BUFFER_NEW;
|
|
|
|
- yy_switch_to_buffer(b );
|
|
+ yy_switch_to_buffer( b );
|
|
|
|
return b;
|
|
}
|
|
@@ -1947,10 +1964,10 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
|
|
* @note If you want to scan bytes that may contain NUL values, then use
|
|
* yy_scan_bytes() instead.
|
|
*/
|
|
-YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
|
|
+YY_BUFFER_STATE yy_scan_string (const char * yystr )
|
|
{
|
|
|
|
- return yy_scan_bytes(yystr,strlen(yystr) );
|
|
+ return yy_scan_bytes( yystr, (int) strlen(yystr) );
|
|
}
|
|
|
|
/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
|
|
@@ -1960,16 +1977,16 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
|
|
*
|
|
* @return the newly allocated buffer state object.
|
|
*/
|
|
-YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len )
|
|
+YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, int _yybytes_len )
|
|
{
|
|
YY_BUFFER_STATE b;
|
|
char *buf;
|
|
yy_size_t n;
|
|
- yy_size_t i;
|
|
+ int i;
|
|
|
|
/* Get memory for full buffer, including space for trailing EOB's. */
|
|
- n = _yybytes_len + 2;
|
|
- buf = (char *) yyalloc(n );
|
|
+ n = (yy_size_t) (_yybytes_len + 2);
|
|
+ buf = (char *) yyalloc( n );
|
|
if ( ! buf )
|
|
YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
|
|
|
|
@@ -1978,7 +1995,7 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len
|
|
|
|
buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
|
|
|
|
- b = yy_scan_buffer(buf,n );
|
|
+ b = yy_scan_buffer( buf, n );
|
|
if ( ! b )
|
|
YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
|
|
|
|
@@ -1994,9 +2011,9 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len
|
|
#define YY_EXIT_FAILURE 2
|
|
#endif
|
|
|
|
-static void yy_fatal_error (yyconst char* msg )
|
|
+static void yynoreturn yy_fatal_error (const char* msg )
|
|
{
|
|
- (void) fprintf( stderr, "%s\n", msg );
|
|
+ fprintf( stderr, "%s\n", msg );
|
|
exit( YY_EXIT_FAILURE );
|
|
}
|
|
|
|
@@ -2024,7 +2041,7 @@ static void yy_fatal_error (yyconst char* msg )
|
|
*/
|
|
int yyget_lineno (void)
|
|
{
|
|
-
|
|
+
|
|
return yylineno;
|
|
}
|
|
|
|
@@ -2047,7 +2064,7 @@ FILE *yyget_out (void)
|
|
/** Get the length of the current token.
|
|
*
|
|
*/
|
|
-yy_size_t yyget_leng (void)
|
|
+int yyget_leng (void)
|
|
{
|
|
return yyleng;
|
|
}
|
|
@@ -2062,29 +2079,29 @@ char *yyget_text (void)
|
|
}
|
|
|
|
/** Set the current line number.
|
|
- * @param line_number
|
|
+ * @param _line_number line number
|
|
*
|
|
*/
|
|
-void yyset_lineno (int line_number )
|
|
+void yyset_lineno (int _line_number )
|
|
{
|
|
|
|
- yylineno = line_number;
|
|
+ yylineno = _line_number;
|
|
}
|
|
|
|
/** Set the input stream. This does not discard the current
|
|
* input buffer.
|
|
- * @param in_str A readable stream.
|
|
+ * @param _in_str A readable stream.
|
|
*
|
|
* @see yy_switch_to_buffer
|
|
*/
|
|
-void yyset_in (FILE * in_str )
|
|
+void yyset_in (FILE * _in_str )
|
|
{
|
|
- yyin = in_str ;
|
|
+ yyin = _in_str ;
|
|
}
|
|
|
|
-void yyset_out (FILE * out_str )
|
|
+void yyset_out (FILE * _out_str )
|
|
{
|
|
- yyout = out_str ;
|
|
+ yyout = _out_str ;
|
|
}
|
|
|
|
int yyget_debug (void)
|
|
@@ -2092,9 +2109,9 @@ int yyget_debug (void)
|
|
return yy_flex_debug;
|
|
}
|
|
|
|
-void yyset_debug (int bdebug )
|
|
+void yyset_debug (int _bdebug )
|
|
{
|
|
- yy_flex_debug = bdebug ;
|
|
+ yy_flex_debug = _bdebug ;
|
|
}
|
|
|
|
static int yy_init_globals (void)
|
|
@@ -2103,10 +2120,10 @@ static int yy_init_globals (void)
|
|
* This function is called from yylex_destroy(), so don't allocate here.
|
|
*/
|
|
|
|
- (yy_buffer_stack) = 0;
|
|
+ (yy_buffer_stack) = NULL;
|
|
(yy_buffer_stack_top) = 0;
|
|
(yy_buffer_stack_max) = 0;
|
|
- (yy_c_buf_p) = (char *) 0;
|
|
+ (yy_c_buf_p) = NULL;
|
|
(yy_init) = 0;
|
|
(yy_start) = 0;
|
|
|
|
@@ -2115,8 +2132,8 @@ static int yy_init_globals (void)
|
|
yyin = stdin;
|
|
yyout = stdout;
|
|
#else
|
|
- yyin = (FILE *) 0;
|
|
- yyout = (FILE *) 0;
|
|
+ yyin = NULL;
|
|
+ yyout = NULL;
|
|
#endif
|
|
|
|
/* For future reference: Set errno on error, since we are called by
|
|
@@ -2131,7 +2148,7 @@ int yylex_destroy (void)
|
|
|
|
/* Pop the buffer stack, destroying each element. */
|
|
while(YY_CURRENT_BUFFER){
|
|
- yy_delete_buffer(YY_CURRENT_BUFFER );
|
|
+ yy_delete_buffer( YY_CURRENT_BUFFER );
|
|
YY_CURRENT_BUFFER_LVALUE = NULL;
|
|
yypop_buffer_state();
|
|
}
|
|
@@ -2152,18 +2169,19 @@ int yylex_destroy (void)
|
|
*/
|
|
|
|
#ifndef yytext_ptr
|
|
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
|
|
+static void yy_flex_strncpy (char* s1, const char * s2, int n )
|
|
{
|
|
- register int i;
|
|
+
|
|
+ int i;
|
|
for ( i = 0; i < n; ++i )
|
|
s1[i] = s2[i];
|
|
}
|
|
#endif
|
|
|
|
#ifdef YY_NEED_STRLEN
|
|
-static int yy_flex_strlen (yyconst char * s )
|
|
+static int yy_flex_strlen (const char * s )
|
|
{
|
|
- register int n;
|
|
+ int n;
|
|
for ( n = 0; s[n]; ++n )
|
|
;
|
|
|
|
@@ -2173,11 +2191,12 @@ static int yy_flex_strlen (yyconst char * s )
|
|
|
|
void *yyalloc (yy_size_t size )
|
|
{
|
|
- return (void *) malloc( size );
|
|
+ return malloc(size);
|
|
}
|
|
|
|
void *yyrealloc (void * ptr, yy_size_t size )
|
|
{
|
|
+
|
|
/* The cast to (char *) in the following accommodates both
|
|
* implementations that use char* generic pointers, and those
|
|
* that use void* generic pointers. It works with the latter
|
|
@@ -2185,18 +2204,17 @@ void *yyrealloc (void * ptr, yy_size_t size )
|
|
* any pointer type to void*, and deal with argument conversions
|
|
* as though doing an assignment.
|
|
*/
|
|
- return (void *) realloc( (char *) ptr, size );
|
|
+ return realloc(ptr, size);
|
|
}
|
|
|
|
void yyfree (void * ptr )
|
|
{
|
|
- free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
|
|
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
|
|
}
|
|
|
|
#define YYTABLES_NAME "yytables"
|
|
|
|
-#line 254 "dtc-lexer.l"
|
|
-
|
|
+#line 272 "<stdin>"
|
|
|
|
|
|
static void push_input_file(const char *filename)
|
|
@@ -2207,7 +2225,7 @@ static void push_input_file(const char *filename)
|
|
|
|
yyin = current_srcfile->f;
|
|
|
|
- yypush_buffer_state(yy_create_buffer(yyin,YY_BUF_SIZE));
|
|
+ yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
|
|
}
|
|
|
|
|
|
diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped
|
|
index 27fac4b9c..06a6e9414 100644
|
|
--- a/scripts/dtc/dtc-parser.tab.c_shipped
|
|
+++ b/scripts/dtc/dtc-parser.tab.c_shipped
|
|
@@ -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 implementation 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
|
|
it under the terms of the GNU General Public License as published by
|
|
@@ -44,7 +44,7 @@
|
|
#define YYBISON 1
|
|
|
|
/* Bison version. */
|
|
-#define YYBISON_VERSION "3.0.2"
|
|
+#define YYBISON_VERSION "3.0.4"
|
|
|
|
/* Skeleton name. */
|
|
#define YYSKELETON_NAME "yacc.c"
|
|
@@ -65,6 +65,7 @@
|
|
#line 20 "dtc-parser.y" /* yacc.c:339 */
|
|
|
|
#include <stdio.h>
|
|
+#include <inttypes.h>
|
|
|
|
#include "dtc.h"
|
|
#include "srcpos.h"
|
|
@@ -77,10 +78,10 @@ extern void yyerror(char const *s);
|
|
treesource_error = true; \
|
|
} while (0)
|
|
|
|
-extern struct boot_info *the_boot_info;
|
|
+extern struct dt_info *parser_output;
|
|
extern bool treesource_error;
|
|
|
|
-#line 84 "dtc-parser.tab.c" /* yacc.c:339 */
|
|
+#line 85 "dtc-parser.tab.c" /* yacc.c:339 */
|
|
|
|
# ifndef YY_NULLPTR
|
|
# if defined __cplusplus && 201103L <= __cplusplus
|
|
@@ -116,35 +117,36 @@ extern int yydebug;
|
|
enum yytokentype
|
|
{
|
|
DT_V1 = 258,
|
|
- DT_MEMRESERVE = 259,
|
|
- DT_LSHIFT = 260,
|
|
- DT_RSHIFT = 261,
|
|
- DT_LE = 262,
|
|
- DT_GE = 263,
|
|
- DT_EQ = 264,
|
|
- DT_NE = 265,
|
|
- DT_AND = 266,
|
|
- DT_OR = 267,
|
|
- DT_BITS = 268,
|
|
- DT_DEL_PROP = 269,
|
|
- DT_DEL_NODE = 270,
|
|
- DT_PROPNODENAME = 271,
|
|
- DT_LITERAL = 272,
|
|
- DT_CHAR_LITERAL = 273,
|
|
- DT_BYTE = 274,
|
|
- DT_STRING = 275,
|
|
- DT_LABEL = 276,
|
|
- DT_REF = 277,
|
|
- DT_INCBIN = 278
|
|
+ DT_PLUGIN = 259,
|
|
+ DT_MEMRESERVE = 260,
|
|
+ DT_LSHIFT = 261,
|
|
+ DT_RSHIFT = 262,
|
|
+ DT_LE = 263,
|
|
+ DT_GE = 264,
|
|
+ DT_EQ = 265,
|
|
+ DT_NE = 266,
|
|
+ DT_AND = 267,
|
|
+ DT_OR = 268,
|
|
+ DT_BITS = 269,
|
|
+ DT_DEL_PROP = 270,
|
|
+ DT_DEL_NODE = 271,
|
|
+ DT_PROPNODENAME = 272,
|
|
+ DT_LITERAL = 273,
|
|
+ DT_CHAR_LITERAL = 274,
|
|
+ DT_BYTE = 275,
|
|
+ DT_STRING = 276,
|
|
+ DT_LABEL = 277,
|
|
+ DT_REF = 278,
|
|
+ DT_INCBIN = 279
|
|
};
|
|
#endif
|
|
|
|
/* Value type. */
|
|
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
|
-typedef union YYSTYPE YYSTYPE;
|
|
+
|
|
union YYSTYPE
|
|
{
|
|
-#line 38 "dtc-parser.y" /* yacc.c:355 */
|
|
+#line 39 "dtc-parser.y" /* yacc.c:355 */
|
|
|
|
char *propnodename;
|
|
char *labelref;
|
|
@@ -162,9 +164,12 @@ union YYSTYPE
|
|
struct node *nodelist;
|
|
struct reserve_info *re;
|
|
uint64_t integer;
|
|
+ unsigned int flags;
|
|
|
|
-#line 167 "dtc-parser.tab.c" /* yacc.c:355 */
|
|
+#line 170 "dtc-parser.tab.c" /* yacc.c:355 */
|
|
};
|
|
+
|
|
+typedef union YYSTYPE YYSTYPE;
|
|
# define YYSTYPE_IS_TRIVIAL 1
|
|
# define YYSTYPE_IS_DECLARED 1
|
|
#endif
|
|
@@ -192,7 +197,7 @@ int yyparse (void);
|
|
|
|
/* Copy the second part of user declarations. */
|
|
|
|
-#line 196 "dtc-parser.tab.c" /* yacc.c:358 */
|
|
+#line 201 "dtc-parser.tab.c" /* yacc.c:358 */
|
|
|
|
#ifdef short
|
|
# undef short
|
|
@@ -434,23 +439,23 @@ union yyalloc
|
|
#endif /* !YYCOPY_NEEDED */
|
|
|
|
/* YYFINAL -- State number of the termination state. */
|
|
-#define YYFINAL 4
|
|
+#define YYFINAL 6
|
|
/* YYLAST -- Last index in YYTABLE. */
|
|
-#define YYLAST 133
|
|
+#define YYLAST 140
|
|
|
|
/* YYNTOKENS -- Number of terminals. */
|
|
-#define YYNTOKENS 47
|
|
+#define YYNTOKENS 48
|
|
/* YYNNTS -- Number of nonterminals. */
|
|
-#define YYNNTS 28
|
|
+#define YYNNTS 30
|
|
/* YYNRULES -- Number of rules. */
|
|
-#define YYNRULES 79
|
|
+#define YYNRULES 85
|
|
/* YYNSTATES -- Number of states. */
|
|
-#define YYNSTATES 141
|
|
+#define YYNSTATES 151
|
|
|
|
/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
|
|
by yylex, with out-of-bounds checking. */
|
|
#define YYUNDEFTOK 2
|
|
-#define YYMAXUTOK 278
|
|
+#define YYMAXUTOK 279
|
|
|
|
#define YYTRANSLATE(YYX) \
|
|
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
|
|
@@ -462,16 +467,16 @@ static const yytype_uint8 yytranslate[] =
|
|
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
- 2, 2, 2, 46, 2, 2, 2, 44, 40, 2,
|
|
- 32, 34, 43, 41, 33, 42, 2, 25, 2, 2,
|
|
- 2, 2, 2, 2, 2, 2, 2, 2, 37, 24,
|
|
- 35, 28, 29, 36, 2, 2, 2, 2, 2, 2,
|
|
+ 2, 2, 2, 47, 2, 2, 2, 45, 41, 2,
|
|
+ 33, 35, 44, 42, 34, 43, 2, 26, 2, 2,
|
|
+ 2, 2, 2, 2, 2, 2, 2, 2, 38, 25,
|
|
+ 36, 29, 30, 37, 2, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
- 2, 30, 2, 31, 39, 2, 2, 2, 2, 2,
|
|
+ 2, 31, 2, 32, 40, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
- 2, 2, 2, 26, 38, 27, 45, 2, 2, 2,
|
|
+ 2, 2, 2, 27, 39, 28, 46, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
@@ -486,21 +491,22 @@ static const yytype_uint8 yytranslate[] =
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
|
|
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
|
- 15, 16, 17, 18, 19, 20, 21, 22, 23
|
|
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
|
|
};
|
|
|
|
#if YYDEBUG
|
|
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
|
|
static const yytype_uint16 yyrline[] =
|
|
{
|
|
- 0, 104, 104, 113, 116, 123, 127, 135, 139, 143,
|
|
- 153, 168, 176, 179, 186, 190, 194, 198, 206, 210,
|
|
- 214, 218, 222, 238, 248, 256, 259, 263, 270, 286,
|
|
- 291, 310, 324, 331, 332, 333, 340, 344, 345, 349,
|
|
- 350, 354, 355, 359, 360, 364, 365, 369, 370, 374,
|
|
- 375, 376, 380, 381, 382, 383, 384, 388, 389, 390,
|
|
- 394, 395, 396, 400, 401, 402, 403, 407, 408, 409,
|
|
- 410, 415, 418, 422, 430, 433, 437, 445, 449, 453
|
|
+ 0, 109, 109, 117, 121, 128, 129, 139, 142, 149,
|
|
+ 153, 161, 165, 169, 180, 191, 210, 225, 233, 236,
|
|
+ 243, 247, 251, 255, 263, 267, 271, 275, 279, 295,
|
|
+ 305, 313, 316, 320, 327, 343, 348, 367, 381, 388,
|
|
+ 389, 390, 397, 401, 402, 406, 407, 411, 412, 416,
|
|
+ 417, 421, 422, 426, 427, 431, 432, 433, 437, 438,
|
|
+ 439, 440, 441, 445, 446, 447, 451, 452, 453, 457,
|
|
+ 458, 467, 476, 480, 481, 482, 483, 488, 491, 495,
|
|
+ 503, 506, 510, 518, 522, 526
|
|
};
|
|
#endif
|
|
|
|
@@ -509,19 +515,20 @@ static const yytype_uint16 yyrline[] =
|
|
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
|
|
static const char *const yytname[] =
|
|
{
|
|
- "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE", "DT_LSHIFT",
|
|
- "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND", "DT_OR",
|
|
- "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME", "DT_LITERAL",
|
|
- "DT_CHAR_LITERAL", "DT_BYTE", "DT_STRING", "DT_LABEL", "DT_REF",
|
|
- "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['", "']'",
|
|
- "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'", "'+'",
|
|
- "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile",
|
|
- "memreserves", "memreserve", "devicetree", "nodedef", "proplist",
|
|
- "propdef", "propdata", "propdataprefix", "arrayprefix", "integer_prim",
|
|
- "integer_expr", "integer_trinary", "integer_or", "integer_and",
|
|
- "integer_bitor", "integer_bitxor", "integer_bitand", "integer_eq",
|
|
- "integer_rela", "integer_shift", "integer_add", "integer_mul",
|
|
- "integer_unary", "bytestring", "subnodes", "subnode", YY_NULLPTR
|
|
+ "$end", "error", "$undefined", "DT_V1", "DT_PLUGIN", "DT_MEMRESERVE",
|
|
+ "DT_LSHIFT", "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND",
|
|
+ "DT_OR", "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME",
|
|
+ "DT_LITERAL", "DT_CHAR_LITERAL", "DT_BYTE", "DT_STRING", "DT_LABEL",
|
|
+ "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['",
|
|
+ "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'",
|
|
+ "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile",
|
|
+ "header", "headers", "memreserves", "memreserve", "devicetree",
|
|
+ "nodedef", "proplist", "propdef", "propdata", "propdataprefix",
|
|
+ "arrayprefix", "integer_prim", "integer_expr", "integer_trinary",
|
|
+ "integer_or", "integer_and", "integer_bitor", "integer_bitxor",
|
|
+ "integer_bitand", "integer_eq", "integer_rela", "integer_shift",
|
|
+ "integer_add", "integer_mul", "integer_unary", "bytestring", "subnodes",
|
|
+ "subnode", YY_NULLPTR
|
|
};
|
|
#endif
|
|
|
|
@@ -532,16 +539,16 @@ static const yytype_uint16 yytoknum[] =
|
|
{
|
|
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
|
|
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
|
|
- 275, 276, 277, 278, 59, 47, 123, 125, 61, 62,
|
|
- 91, 93, 40, 44, 41, 60, 63, 58, 124, 94,
|
|
- 38, 43, 45, 42, 37, 126, 33
|
|
+ 275, 276, 277, 278, 279, 59, 47, 123, 125, 61,
|
|
+ 62, 91, 93, 40, 44, 41, 60, 63, 58, 124,
|
|
+ 94, 38, 43, 45, 42, 37, 126, 33
|
|
};
|
|
# endif
|
|
|
|
-#define YYPACT_NINF -38
|
|
+#define YYPACT_NINF -81
|
|
|
|
#define yypact_value_is_default(Yystate) \
|
|
- (!!((Yystate) == (-38)))
|
|
+ (!!((Yystate) == (-81)))
|
|
|
|
#define YYTABLE_NINF -1
|
|
|
|
@@ -552,21 +559,22 @@ static const yytype_uint16 yytoknum[] =
|
|
STATE-NUM. */
|
|
static const yytype_int8 yypact[] =
|
|
{
|
|
- 21, 11, 45, 10, -38, 9, 10, 15, 10, -38,
|
|
- -38, -9, 9, -38, 56, 40, -38, -9, -9, -9,
|
|
- -38, 51, -38, -6, 75, 49, 52, 48, 50, 3,
|
|
- 66, 33, 0, -38, 65, -38, -38, 68, 56, 56,
|
|
- -38, -38, -38, -38, -9, -9, -9, -9, -9, -9,
|
|
- -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
|
|
- -9, -9, -9, -38, 42, 69, -38, -38, 75, 55,
|
|
- 49, 52, 48, 50, 3, 3, 66, 66, 66, 66,
|
|
- 33, 33, 0, 0, -38, -38, -38, 78, 79, -11,
|
|
- 42, -38, 70, 42, -38, -9, 72, 74, -38, -38,
|
|
- -38, -38, -38, 76, -38, -38, -38, -38, -38, 18,
|
|
- -1, -38, -38, -38, -38, 82, -38, -38, -38, 71,
|
|
- -38, -38, 32, 67, 81, -3, -38, -38, -38, -38,
|
|
- -38, 43, -38, -38, -38, 9, -38, 73, 9, 77,
|
|
- -38
|
|
+ 11, 17, 23, 11, 10, 56, -81, -81, 21, 10,
|
|
+ -5, 10, 39, -81, -81, -13, 21, -81, 44, 44,
|
|
+ 43, -81, -81, -13, -13, -13, -81, 38, -81, -2,
|
|
+ 67, 53, 55, 57, 41, 1, 75, 42, -19, -81,
|
|
+ 58, -81, -81, -81, 73, 74, 44, 44, -81, -81,
|
|
+ -81, -81, -13, -13, -13, -13, -13, -13, -13, -13,
|
|
+ -13, -13, -13, -13, -13, -13, -13, -13, -13, -13,
|
|
+ -13, -81, 46, 76, 44, -81, -81, 67, 61, 53,
|
|
+ 55, 57, 41, 1, 1, 75, 75, 75, 75, 42,
|
|
+ 42, -19, -19, -81, -81, -81, 83, 85, 45, 46,
|
|
+ -81, 77, 46, -81, -81, -13, 78, 79, -81, -81,
|
|
+ -81, -81, -81, 81, -81, -81, -81, -81, -81, 16,
|
|
+ 22, -81, -81, -81, -81, 89, -81, -81, -81, 80,
|
|
+ -81, -81, -6, 72, 88, 35, -81, -81, -81, -81,
|
|
+ -81, 52, -81, -81, -81, 21, -81, 82, 21, 84,
|
|
+ -81
|
|
};
|
|
|
|
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
|
|
@@ -574,37 +582,38 @@ static const yytype_int8 yypact[] =
|
|
means the default is an error. */
|
|
static const yytype_uint8 yydefact[] =
|
|
{
|
|
- 0, 0, 0, 3, 1, 0, 0, 0, 3, 33,
|
|
- 34, 0, 0, 6, 0, 2, 4, 0, 0, 0,
|
|
- 67, 0, 36, 37, 39, 41, 43, 45, 47, 49,
|
|
- 52, 59, 62, 66, 0, 12, 7, 0, 0, 0,
|
|
- 68, 69, 70, 35, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 5, 7, 3, 1, 6, 0, 0,
|
|
+ 0, 7, 0, 39, 40, 0, 0, 10, 0, 0,
|
|
+ 2, 8, 4, 0, 0, 0, 73, 0, 42, 43,
|
|
+ 45, 47, 49, 51, 53, 55, 58, 65, 68, 72,
|
|
+ 0, 18, 13, 11, 0, 0, 0, 0, 74, 75,
|
|
+ 76, 41, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
- 0, 0, 0, 5, 74, 0, 9, 8, 40, 0,
|
|
- 42, 44, 46, 48, 50, 51, 55, 56, 54, 53,
|
|
- 57, 58, 60, 61, 64, 63, 65, 0, 0, 0,
|
|
- 0, 13, 0, 74, 10, 0, 0, 0, 15, 25,
|
|
- 77, 17, 79, 0, 76, 75, 38, 16, 78, 0,
|
|
- 0, 11, 24, 14, 26, 0, 18, 27, 21, 0,
|
|
- 71, 29, 0, 0, 0, 0, 32, 31, 19, 30,
|
|
- 28, 0, 72, 73, 20, 0, 23, 0, 0, 0,
|
|
- 22
|
|
+ 0, 9, 80, 0, 0, 15, 12, 46, 0, 48,
|
|
+ 50, 52, 54, 56, 57, 61, 62, 60, 59, 63,
|
|
+ 64, 66, 67, 70, 69, 71, 0, 0, 0, 0,
|
|
+ 19, 0, 80, 16, 14, 0, 0, 0, 21, 31,
|
|
+ 83, 23, 85, 0, 82, 81, 44, 22, 84, 0,
|
|
+ 0, 17, 30, 20, 32, 0, 24, 33, 27, 0,
|
|
+ 77, 35, 0, 0, 0, 0, 38, 37, 25, 36,
|
|
+ 34, 0, 78, 79, 26, 0, 29, 0, 0, 0,
|
|
+ 28
|
|
};
|
|
|
|
/* YYPGOTO[NTERM-NUM]. */
|
|
static const yytype_int8 yypgoto[] =
|
|
{
|
|
- -38, -38, 96, 99, -38, -37, -38, -20, -38, -38,
|
|
- -38, -5, 62, 13, -38, 80, 63, 84, 64, 61,
|
|
- 28, 14, 24, 25, -14, -38, 20, 26
|
|
+ -81, -81, -81, 107, 100, 103, -81, -18, -81, -80,
|
|
+ -81, -81, -81, -8, 62, 9, -81, 65, 64, 66,
|
|
+ 69, 63, 30, 15, 26, 27, -21, -81, 20, 24
|
|
};
|
|
|
|
/* YYDEFGOTO[NTERM-NUM]. */
|
|
-static const yytype_int8 yydefgoto[] =
|
|
+static const yytype_int16 yydefgoto[] =
|
|
{
|
|
- -1, 2, 7, 8, 15, 36, 64, 91, 109, 110,
|
|
- 122, 20, 21, 22, 23, 24, 25, 26, 27, 28,
|
|
- 29, 30, 31, 32, 33, 125, 92, 93
|
|
+ -1, 2, 3, 4, 10, 11, 20, 42, 72, 100,
|
|
+ 119, 120, 132, 26, 27, 28, 29, 30, 31, 32,
|
|
+ 33, 34, 35, 36, 37, 38, 39, 135, 101, 102
|
|
};
|
|
|
|
/* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
|
|
@@ -612,85 +621,90 @@ static const yytype_int8 yydefgoto[] =
|
|
number is the opposite. If YYTABLE_NINF, syntax error. */
|
|
static const yytype_uint8 yytable[] =
|
|
{
|
|
- 12, 66, 67, 40, 41, 42, 44, 34, 9, 10,
|
|
- 52, 53, 115, 98, 5, 35, 132, 99, 133, 116,
|
|
- 117, 118, 119, 11, 1, 60, 9, 10, 134, 120,
|
|
- 45, 6, 54, 17, 121, 3, 18, 19, 55, 112,
|
|
- 14, 11, 113, 61, 62, 4, 84, 85, 86, 9,
|
|
- 10, 114, 100, 126, 127, 37, 87, 88, 89, 50,
|
|
- 51, 128, 38, 90, 11, 39, 76, 77, 78, 79,
|
|
- 101, 56, 57, 104, 58, 59, 135, 136, 74, 75,
|
|
- 80, 81, 35, 82, 83, 43, 46, 47, 49, 63,
|
|
- 65, 48, 95, 94, 96, 97, 107, 103, 108, 123,
|
|
- 111, 131, 130, 124, 16, 13, 138, 69, 106, 70,
|
|
- 73, 140, 72, 105, 0, 0, 102, 129, 0, 0,
|
|
- 0, 0, 0, 0, 68, 0, 0, 0, 0, 0,
|
|
- 137, 71, 0, 139
|
|
+ 16, 43, 48, 49, 50, 13, 14, 68, 40, 60,
|
|
+ 61, 52, 13, 14, 1, 8, 136, 137, 18, 111,
|
|
+ 15, 19, 114, 6, 138, 69, 70, 15, 75, 76,
|
|
+ 23, 62, 9, 24, 25, 53, 125, 63, 122, 13,
|
|
+ 14, 123, 5, 126, 127, 128, 129, 93, 94, 95,
|
|
+ 124, 58, 59, 130, 15, 142, 104, 143, 131, 44,
|
|
+ 12, 96, 97, 98, 22, 45, 46, 144, 99, 47,
|
|
+ 108, 41, 41, 51, 109, 85, 86, 87, 88, 54,
|
|
+ 110, 64, 65, 71, 66, 67, 145, 146, 83, 84,
|
|
+ 89, 90, 55, 91, 92, 56, 73, 74, 57, 105,
|
|
+ 106, 103, 107, 117, 118, 113, 121, 133, 140, 141,
|
|
+ 7, 21, 17, 134, 116, 78, 148, 77, 79, 150,
|
|
+ 82, 80, 115, 112, 139, 81, 0, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 147, 0, 0,
|
|
+ 149
|
|
};
|
|
|
|
static const yytype_int16 yycheck[] =
|
|
{
|
|
- 5, 38, 39, 17, 18, 19, 12, 12, 17, 18,
|
|
- 7, 8, 13, 24, 4, 26, 19, 28, 21, 20,
|
|
- 21, 22, 23, 32, 3, 25, 17, 18, 31, 30,
|
|
- 36, 21, 29, 42, 35, 24, 45, 46, 35, 21,
|
|
- 25, 32, 24, 43, 44, 0, 60, 61, 62, 17,
|
|
- 18, 33, 89, 21, 22, 15, 14, 15, 16, 9,
|
|
- 10, 29, 22, 21, 32, 25, 52, 53, 54, 55,
|
|
- 90, 5, 6, 93, 41, 42, 33, 34, 50, 51,
|
|
- 56, 57, 26, 58, 59, 34, 11, 38, 40, 24,
|
|
- 22, 39, 37, 24, 16, 16, 24, 27, 24, 17,
|
|
- 24, 20, 35, 32, 8, 6, 33, 45, 95, 46,
|
|
- 49, 34, 48, 93, -1, -1, 90, 122, -1, -1,
|
|
- -1, -1, -1, -1, 44, -1, -1, -1, -1, -1,
|
|
- 135, 47, -1, 138
|
|
+ 8, 19, 23, 24, 25, 18, 19, 26, 16, 8,
|
|
+ 9, 13, 18, 19, 3, 5, 22, 23, 23, 99,
|
|
+ 33, 26, 102, 0, 30, 44, 45, 33, 46, 47,
|
|
+ 43, 30, 22, 46, 47, 37, 14, 36, 22, 18,
|
|
+ 19, 25, 25, 21, 22, 23, 24, 68, 69, 70,
|
|
+ 34, 10, 11, 31, 33, 20, 74, 22, 36, 16,
|
|
+ 4, 15, 16, 17, 25, 22, 23, 32, 22, 26,
|
|
+ 25, 27, 27, 35, 29, 60, 61, 62, 63, 12,
|
|
+ 98, 6, 7, 25, 42, 43, 34, 35, 58, 59,
|
|
+ 64, 65, 39, 66, 67, 40, 23, 23, 41, 38,
|
|
+ 17, 25, 17, 25, 25, 28, 25, 18, 36, 21,
|
|
+ 3, 11, 9, 33, 105, 53, 34, 52, 54, 35,
|
|
+ 57, 55, 102, 99, 132, 56, -1, -1, -1, -1,
|
|
+ -1, -1, -1, -1, -1, -1, -1, 145, -1, -1,
|
|
+ 148
|
|
};
|
|
|
|
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
|
|
symbol of state STATE-NUM. */
|
|
static const yytype_uint8 yystos[] =
|
|
{
|
|
- 0, 3, 48, 24, 0, 4, 21, 49, 50, 17,
|
|
- 18, 32, 58, 50, 25, 51, 49, 42, 45, 46,
|
|
- 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
|
|
- 68, 69, 70, 71, 58, 26, 52, 15, 22, 25,
|
|
- 71, 71, 71, 34, 12, 36, 11, 38, 39, 40,
|
|
- 9, 10, 7, 8, 29, 35, 5, 6, 41, 42,
|
|
- 25, 43, 44, 24, 53, 22, 52, 52, 62, 59,
|
|
- 63, 64, 65, 66, 67, 67, 68, 68, 68, 68,
|
|
- 69, 69, 70, 70, 71, 71, 71, 14, 15, 16,
|
|
- 21, 54, 73, 74, 24, 37, 16, 16, 24, 28,
|
|
- 52, 54, 74, 27, 54, 73, 60, 24, 24, 55,
|
|
- 56, 24, 21, 24, 33, 13, 20, 21, 22, 23,
|
|
- 30, 35, 57, 17, 32, 72, 21, 22, 29, 58,
|
|
- 35, 20, 19, 21, 31, 33, 34, 58, 33, 58,
|
|
- 34
|
|
+ 0, 3, 49, 50, 51, 25, 0, 51, 5, 22,
|
|
+ 52, 53, 4, 18, 19, 33, 61, 53, 23, 26,
|
|
+ 54, 52, 25, 43, 46, 47, 61, 62, 63, 64,
|
|
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
|
|
+ 61, 27, 55, 55, 16, 22, 23, 26, 74, 74,
|
|
+ 74, 35, 13, 37, 12, 39, 40, 41, 10, 11,
|
|
+ 8, 9, 30, 36, 6, 7, 42, 43, 26, 44,
|
|
+ 45, 25, 56, 23, 23, 55, 55, 65, 62, 66,
|
|
+ 67, 68, 69, 70, 70, 71, 71, 71, 71, 72,
|
|
+ 72, 73, 73, 74, 74, 74, 15, 16, 17, 22,
|
|
+ 57, 76, 77, 25, 55, 38, 17, 17, 25, 29,
|
|
+ 55, 57, 77, 28, 57, 76, 63, 25, 25, 58,
|
|
+ 59, 25, 22, 25, 34, 14, 21, 22, 23, 24,
|
|
+ 31, 36, 60, 18, 33, 75, 22, 23, 30, 61,
|
|
+ 36, 21, 20, 22, 32, 34, 35, 61, 34, 61,
|
|
+ 35
|
|
};
|
|
|
|
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
|
|
static const yytype_uint8 yyr1[] =
|
|
{
|
|
- 0, 47, 48, 49, 49, 50, 50, 51, 51, 51,
|
|
- 51, 52, 53, 53, 54, 54, 54, 54, 55, 55,
|
|
- 55, 55, 55, 55, 55, 56, 56, 56, 57, 57,
|
|
- 57, 57, 57, 58, 58, 58, 59, 60, 60, 61,
|
|
- 61, 62, 62, 63, 63, 64, 64, 65, 65, 66,
|
|
- 66, 66, 67, 67, 67, 67, 67, 68, 68, 68,
|
|
- 69, 69, 69, 70, 70, 70, 70, 71, 71, 71,
|
|
- 71, 72, 72, 72, 73, 73, 73, 74, 74, 74
|
|
+ 0, 48, 49, 50, 50, 51, 51, 52, 52, 53,
|
|
+ 53, 54, 54, 54, 54, 54, 54, 55, 56, 56,
|
|
+ 57, 57, 57, 57, 58, 58, 58, 58, 58, 58,
|
|
+ 58, 59, 59, 59, 60, 60, 60, 60, 60, 61,
|
|
+ 61, 61, 62, 63, 63, 64, 64, 65, 65, 66,
|
|
+ 66, 67, 67, 68, 68, 69, 69, 69, 70, 70,
|
|
+ 70, 70, 70, 71, 71, 71, 72, 72, 72, 73,
|
|
+ 73, 73, 73, 74, 74, 74, 74, 75, 75, 75,
|
|
+ 76, 76, 76, 77, 77, 77
|
|
};
|
|
|
|
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
|
|
static const yytype_uint8 yyr2[] =
|
|
{
|
|
- 0, 2, 4, 0, 2, 4, 2, 2, 3, 3,
|
|
- 4, 5, 0, 2, 4, 2, 3, 2, 2, 3,
|
|
- 4, 2, 9, 5, 2, 0, 2, 2, 3, 1,
|
|
- 2, 2, 2, 1, 1, 3, 1, 1, 5, 1,
|
|
- 3, 1, 3, 1, 3, 1, 3, 1, 3, 1,
|
|
- 3, 3, 1, 3, 3, 3, 3, 3, 3, 1,
|
|
- 3, 3, 1, 3, 3, 3, 1, 1, 2, 2,
|
|
- 2, 0, 2, 2, 0, 2, 2, 2, 3, 2
|
|
+ 0, 2, 3, 2, 4, 1, 2, 0, 2, 4,
|
|
+ 2, 2, 3, 2, 4, 3, 4, 5, 0, 2,
|
|
+ 4, 2, 3, 2, 2, 3, 4, 2, 9, 5,
|
|
+ 2, 0, 2, 2, 3, 1, 2, 2, 2, 1,
|
|
+ 1, 3, 1, 1, 5, 1, 3, 1, 3, 1,
|
|
+ 3, 1, 3, 1, 3, 1, 3, 3, 1, 3,
|
|
+ 3, 3, 3, 3, 3, 1, 3, 3, 1, 3,
|
|
+ 3, 3, 1, 1, 2, 2, 2, 0, 2, 2,
|
|
+ 0, 2, 2, 2, 3, 2
|
|
};
|
|
|
|
|
|
@@ -1460,79 +1474,144 @@ yyreduce:
|
|
switch (yyn)
|
|
{
|
|
case 2:
|
|
-#line 105 "dtc-parser.y" /* yacc.c:1646 */
|
|
+#line 110 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
- the_boot_info = build_boot_info((yyvsp[-1].re), (yyvsp[0].node),
|
|
- guess_boot_cpuid((yyvsp[0].node)));
|
|
+ parser_output = build_dt_info((yyvsp[-2].flags), (yyvsp[-1].re), (yyvsp[0].node),
|
|
+ guess_boot_cpuid((yyvsp[0].node)));
|
|
}
|
|
-#line 1469 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1483 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
case 3:
|
|
-#line 113 "dtc-parser.y" /* yacc.c:1646 */
|
|
+#line 118 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
- (yyval.re) = NULL;
|
|
+ (yyval.flags) = DTSF_V1;
|
|
}
|
|
-#line 1477 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1491 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
case 4:
|
|
-#line 117 "dtc-parser.y" /* yacc.c:1646 */
|
|
+#line 122 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ {
|
|
+ (yyval.flags) = DTSF_V1 | DTSF_PLUGIN;
|
|
+ }
|
|
+#line 1499 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+ break;
|
|
+
|
|
+ case 6:
|
|
+#line 130 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ {
|
|
+ if ((yyvsp[0].flags) != (yyvsp[-1].flags))
|
|
+ ERROR(&(yylsp[0]), "Header flags don't match earlier ones");
|
|
+ (yyval.flags) = (yyvsp[-1].flags);
|
|
+ }
|
|
+#line 1509 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+ break;
|
|
+
|
|
+ case 7:
|
|
+#line 139 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ {
|
|
+ (yyval.re) = NULL;
|
|
+ }
|
|
+#line 1517 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+ break;
|
|
+
|
|
+ case 8:
|
|
+#line 143 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.re) = chain_reserve_entry((yyvsp[-1].re), (yyvsp[0].re));
|
|
}
|
|
-#line 1485 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1525 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 5:
|
|
-#line 124 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 9:
|
|
+#line 150 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.re) = build_reserve_entry((yyvsp[-2].integer), (yyvsp[-1].integer));
|
|
}
|
|
-#line 1493 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1533 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 6:
|
|
-#line 128 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 10:
|
|
+#line 154 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
add_label(&(yyvsp[0].re)->labels, (yyvsp[-1].labelref));
|
|
(yyval.re) = (yyvsp[0].re);
|
|
}
|
|
-#line 1502 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1542 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 7:
|
|
-#line 136 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 11:
|
|
+#line 162 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.node) = name_node((yyvsp[0].node), "");
|
|
}
|
|
-#line 1510 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1550 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 8:
|
|
-#line 140 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 12:
|
|
+#line 166 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.node) = merge_nodes((yyvsp[-2].node), (yyvsp[0].node));
|
|
}
|
|
-#line 1518 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1558 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 9:
|
|
-#line 144 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 13:
|
|
+#line 170 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
- struct node *target = get_node_by_ref((yyvsp[-2].node), (yyvsp[-1].labelref));
|
|
+ /*
|
|
+ * We rely on the rule being always:
|
|
+ * versioninfo plugindecl memreserves devicetree
|
|
+ * so $-1 is what we want (plugindecl)
|
|
+ */
|
|
+ if (!((yyvsp[(-1) - (2)].flags) & DTSF_PLUGIN))
|
|
+ ERROR(&(yylsp[0]), "Label or path %s not found", (yyvsp[-1].labelref));
|
|
+ (yyval.node) = add_orphan_node(name_node(build_node(NULL, NULL), ""), (yyvsp[0].node), (yyvsp[-1].labelref));
|
|
+ }
|
|
+#line 1573 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+ break;
|
|
|
|
- if (target)
|
|
+ case 14:
|
|
+#line 181 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ {
|
|
+ struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref));
|
|
+
|
|
+ if (target) {
|
|
+ add_label(&target->labels, (yyvsp[-2].labelref));
|
|
merge_nodes(target, (yyvsp[0].node));
|
|
- else
|
|
+ } else
|
|
ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref));
|
|
+ (yyval.node) = (yyvsp[-3].node);
|
|
+ }
|
|
+#line 1588 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+ break;
|
|
+
|
|
+ case 15:
|
|
+#line 192 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ {
|
|
+ struct node *target = get_node_by_ref((yyvsp[-2].node), (yyvsp[-1].labelref));
|
|
+
|
|
+ if (target) {
|
|
+ merge_nodes(target, (yyvsp[0].node));
|
|
+ } else {
|
|
+ /*
|
|
+ * We rely on the rule being always:
|
|
+ * versioninfo plugindecl memreserves devicetree
|
|
+ * so $-1 is what we want (plugindecl)
|
|
+ */
|
|
+ if ((yyvsp[(-1) - (3)].flags) & DTSF_PLUGIN)
|
|
+ add_orphan_node((yyvsp[-2].node), (yyvsp[0].node), (yyvsp[-1].labelref));
|
|
+ else
|
|
+ ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref));
|
|
+ }
|
|
(yyval.node) = (yyvsp[-2].node);
|
|
}
|
|
-#line 1532 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1611 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 10:
|
|
-#line 154 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 16:
|
|
+#line 211 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref));
|
|
|
|
@@ -1544,100 +1623,100 @@ yyreduce:
|
|
|
|
(yyval.node) = (yyvsp[-3].node);
|
|
}
|
|
-#line 1548 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1627 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 11:
|
|
-#line 169 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 17:
|
|
+#line 226 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.node) = build_node((yyvsp[-3].proplist), (yyvsp[-2].nodelist));
|
|
}
|
|
-#line 1556 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1635 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 12:
|
|
-#line 176 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 18:
|
|
+#line 233 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.proplist) = NULL;
|
|
}
|
|
-#line 1564 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1643 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 13:
|
|
-#line 180 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 19:
|
|
+#line 237 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.proplist) = chain_property((yyvsp[0].prop), (yyvsp[-1].proplist));
|
|
}
|
|
-#line 1572 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1651 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 14:
|
|
-#line 187 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 20:
|
|
+#line 244 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.prop) = build_property((yyvsp[-3].propnodename), (yyvsp[-1].data));
|
|
}
|
|
-#line 1580 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1659 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 15:
|
|
-#line 191 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 21:
|
|
+#line 248 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.prop) = build_property((yyvsp[-1].propnodename), empty_data);
|
|
}
|
|
-#line 1588 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1667 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 16:
|
|
-#line 195 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 22:
|
|
+#line 252 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.prop) = build_property_delete((yyvsp[-1].propnodename));
|
|
}
|
|
-#line 1596 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1675 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 17:
|
|
-#line 199 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 23:
|
|
+#line 256 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
add_label(&(yyvsp[0].prop)->labels, (yyvsp[-1].labelref));
|
|
(yyval.prop) = (yyvsp[0].prop);
|
|
}
|
|
-#line 1605 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1684 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 18:
|
|
-#line 207 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 24:
|
|
+#line 264 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.data) = data_merge((yyvsp[-1].data), (yyvsp[0].data));
|
|
}
|
|
-#line 1613 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1692 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 19:
|
|
-#line 211 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 25:
|
|
+#line 268 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.data) = data_merge((yyvsp[-2].data), (yyvsp[-1].array).data);
|
|
}
|
|
-#line 1621 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1700 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 20:
|
|
-#line 215 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 26:
|
|
+#line 272 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.data) = data_merge((yyvsp[-3].data), (yyvsp[-1].data));
|
|
}
|
|
-#line 1629 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1708 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 21:
|
|
-#line 219 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 27:
|
|
+#line 276 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.data) = data_add_marker((yyvsp[-1].data), REF_PATH, (yyvsp[0].labelref));
|
|
}
|
|
-#line 1637 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1716 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 22:
|
|
-#line 223 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 28:
|
|
+#line 280 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
FILE *f = srcfile_relative_open((yyvsp[-5].data).val, NULL);
|
|
struct data d;
|
|
@@ -1653,11 +1732,11 @@ yyreduce:
|
|
(yyval.data) = data_merge((yyvsp[-8].data), d);
|
|
fclose(f);
|
|
}
|
|
-#line 1657 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1736 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 23:
|
|
-#line 239 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 29:
|
|
+#line 296 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
FILE *f = srcfile_relative_open((yyvsp[-1].data).val, NULL);
|
|
struct data d = empty_data;
|
|
@@ -1667,43 +1746,43 @@ yyreduce:
|
|
(yyval.data) = data_merge((yyvsp[-4].data), d);
|
|
fclose(f);
|
|
}
|
|
-#line 1671 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1750 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 24:
|
|
-#line 249 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 30:
|
|
+#line 306 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref));
|
|
}
|
|
-#line 1679 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1758 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 25:
|
|
-#line 256 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 31:
|
|
+#line 313 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.data) = empty_data;
|
|
}
|
|
-#line 1687 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1766 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 26:
|
|
-#line 260 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 32:
|
|
+#line 317 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.data) = (yyvsp[-1].data);
|
|
}
|
|
-#line 1695 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1774 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 27:
|
|
-#line 264 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 33:
|
|
+#line 321 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref));
|
|
}
|
|
-#line 1703 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1782 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 28:
|
|
-#line 271 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 34:
|
|
+#line 328 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
unsigned long long bits;
|
|
|
|
@@ -1719,20 +1798,20 @@ yyreduce:
|
|
(yyval.array).data = empty_data;
|
|
(yyval.array).bits = bits;
|
|
}
|
|
-#line 1723 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1802 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 29:
|
|
-#line 287 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 35:
|
|
+#line 344 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.array).data = empty_data;
|
|
(yyval.array).bits = 32;
|
|
}
|
|
-#line 1732 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1811 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 30:
|
|
-#line 292 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 36:
|
|
+#line 349 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
if ((yyvsp[-1].array).bits < 64) {
|
|
uint64_t mask = (1ULL << (yyvsp[-1].array).bits) - 1;
|
|
@@ -1751,11 +1830,11 @@ yyreduce:
|
|
|
|
(yyval.array).data = data_append_integer((yyvsp[-1].array).data, (yyvsp[0].integer), (yyvsp[-1].array).bits);
|
|
}
|
|
-#line 1755 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1834 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 31:
|
|
-#line 311 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 37:
|
|
+#line 368 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
uint64_t val = ~0ULL >> (64 - (yyvsp[-1].array).bits);
|
|
|
|
@@ -1769,233 +1848,247 @@ yyreduce:
|
|
|
|
(yyval.array).data = data_append_integer((yyvsp[-1].array).data, val, (yyvsp[-1].array).bits);
|
|
}
|
|
-#line 1773 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1852 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 32:
|
|
-#line 325 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 38:
|
|
+#line 382 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.array).data = data_add_marker((yyvsp[-1].array).data, LABEL, (yyvsp[0].labelref));
|
|
}
|
|
-#line 1781 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1860 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 35:
|
|
-#line 334 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 41:
|
|
+#line 391 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.integer) = (yyvsp[-1].integer);
|
|
}
|
|
-#line 1789 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1868 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 38:
|
|
-#line 345 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 44:
|
|
+#line 402 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-4].integer) ? (yyvsp[-2].integer) : (yyvsp[0].integer); }
|
|
-#line 1795 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1874 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 40:
|
|
-#line 350 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 46:
|
|
+#line 407 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) || (yyvsp[0].integer); }
|
|
-#line 1801 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1880 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 42:
|
|
-#line 355 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 48:
|
|
+#line 412 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) && (yyvsp[0].integer); }
|
|
-#line 1807 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1886 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 44:
|
|
-#line 360 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 50:
|
|
+#line 417 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) | (yyvsp[0].integer); }
|
|
-#line 1813 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1892 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 46:
|
|
-#line 365 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 52:
|
|
+#line 422 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) ^ (yyvsp[0].integer); }
|
|
-#line 1819 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1898 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 48:
|
|
-#line 370 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 54:
|
|
+#line 427 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) & (yyvsp[0].integer); }
|
|
-#line 1825 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1904 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 50:
|
|
-#line 375 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 56:
|
|
+#line 432 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) == (yyvsp[0].integer); }
|
|
-#line 1831 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1910 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 51:
|
|
-#line 376 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 57:
|
|
+#line 433 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) != (yyvsp[0].integer); }
|
|
-#line 1837 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1916 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 53:
|
|
-#line 381 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 59:
|
|
+#line 438 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) < (yyvsp[0].integer); }
|
|
-#line 1843 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1922 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 54:
|
|
-#line 382 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 60:
|
|
+#line 439 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) > (yyvsp[0].integer); }
|
|
-#line 1849 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1928 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 55:
|
|
-#line 383 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 61:
|
|
+#line 440 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) <= (yyvsp[0].integer); }
|
|
-#line 1855 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1934 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 56:
|
|
-#line 384 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 62:
|
|
+#line 441 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) >= (yyvsp[0].integer); }
|
|
-#line 1861 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1940 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 57:
|
|
-#line 388 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 63:
|
|
+#line 445 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) << (yyvsp[0].integer); }
|
|
-#line 1867 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1946 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 58:
|
|
-#line 389 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 64:
|
|
+#line 446 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) >> (yyvsp[0].integer); }
|
|
-#line 1873 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1952 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 60:
|
|
-#line 394 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 66:
|
|
+#line 451 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) + (yyvsp[0].integer); }
|
|
-#line 1879 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1958 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 61:
|
|
-#line 395 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 67:
|
|
+#line 452 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) - (yyvsp[0].integer); }
|
|
-#line 1885 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1964 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 63:
|
|
-#line 400 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 69:
|
|
+#line 457 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = (yyvsp[-2].integer) * (yyvsp[0].integer); }
|
|
-#line 1891 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 1970 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 64:
|
|
-#line 401 "dtc-parser.y" /* yacc.c:1646 */
|
|
- { (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer); }
|
|
-#line 1897 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+ case 70:
|
|
+#line 459 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ {
|
|
+ if ((yyvsp[0].integer) != 0) {
|
|
+ (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer);
|
|
+ } else {
|
|
+ ERROR(&(yyloc), "Division by zero");
|
|
+ (yyval.integer) = 0;
|
|
+ }
|
|
+ }
|
|
+#line 1983 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 65:
|
|
-#line 402 "dtc-parser.y" /* yacc.c:1646 */
|
|
- { (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer); }
|
|
-#line 1903 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+ case 71:
|
|
+#line 468 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ {
|
|
+ if ((yyvsp[0].integer) != 0) {
|
|
+ (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer);
|
|
+ } else {
|
|
+ ERROR(&(yyloc), "Division by zero");
|
|
+ (yyval.integer) = 0;
|
|
+ }
|
|
+ }
|
|
+#line 1996 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 68:
|
|
-#line 408 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 74:
|
|
+#line 481 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = -(yyvsp[0].integer); }
|
|
-#line 1909 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 2002 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 69:
|
|
-#line 409 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 75:
|
|
+#line 482 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = ~(yyvsp[0].integer); }
|
|
-#line 1915 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 2008 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 70:
|
|
-#line 410 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 76:
|
|
+#line 483 "dtc-parser.y" /* yacc.c:1646 */
|
|
{ (yyval.integer) = !(yyvsp[0].integer); }
|
|
-#line 1921 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 2014 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 71:
|
|
-#line 415 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 77:
|
|
+#line 488 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.data) = empty_data;
|
|
}
|
|
-#line 1929 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 2022 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 72:
|
|
-#line 419 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 78:
|
|
+#line 492 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.data) = data_append_byte((yyvsp[-1].data), (yyvsp[0].byte));
|
|
}
|
|
-#line 1937 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 2030 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 73:
|
|
-#line 423 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 79:
|
|
+#line 496 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref));
|
|
}
|
|
-#line 1945 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 2038 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 74:
|
|
-#line 430 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 80:
|
|
+#line 503 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.nodelist) = NULL;
|
|
}
|
|
-#line 1953 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 2046 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 75:
|
|
-#line 434 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 81:
|
|
+#line 507 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.nodelist) = chain_node((yyvsp[-1].node), (yyvsp[0].nodelist));
|
|
}
|
|
-#line 1961 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 2054 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 76:
|
|
-#line 438 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 82:
|
|
+#line 511 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
ERROR(&(yylsp[0]), "Properties must precede subnodes");
|
|
YYERROR;
|
|
}
|
|
-#line 1970 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 2063 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 77:
|
|
-#line 446 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 83:
|
|
+#line 519 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.node) = name_node((yyvsp[0].node), (yyvsp[-1].propnodename));
|
|
}
|
|
-#line 1978 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 2071 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 78:
|
|
-#line 450 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 84:
|
|
+#line 523 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
(yyval.node) = name_node(build_node_delete(), (yyvsp[-1].propnodename));
|
|
}
|
|
-#line 1986 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 2079 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
- case 79:
|
|
-#line 454 "dtc-parser.y" /* yacc.c:1646 */
|
|
+ case 85:
|
|
+#line 527 "dtc-parser.y" /* yacc.c:1646 */
|
|
{
|
|
add_label(&(yyvsp[0].node)->labels, (yyvsp[-1].labelref));
|
|
(yyval.node) = (yyvsp[0].node);
|
|
}
|
|
-#line 1995 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 2088 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
break;
|
|
|
|
|
|
-#line 1999 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
+#line 2092 "dtc-parser.tab.c" /* yacc.c:1646 */
|
|
default: break;
|
|
}
|
|
/* User semantic actions sometimes alter yychar, and that requires
|
|
@@ -2230,7 +2323,7 @@ yyreturn:
|
|
#endif
|
|
return yyresult;
|
|
}
|
|
-#line 460 "dtc-parser.y" /* yacc.c:1906 */
|
|
+#line 533 "dtc-parser.y" /* yacc.c:1906 */
|
|
|
|
|
|
void yyerror(char const *s)
|
|
diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped
|
|
index 30867c688..6aa512c1b 100644
|
|
--- a/scripts/dtc/dtc-parser.tab.h_shipped
|
|
+++ b/scripts/dtc/dtc-parser.tab.h_shipped
|
|
@@ -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
|
|
|
|
- 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
|
|
it under the terms of the GNU General Public License as published by
|
|
@@ -46,35 +46,36 @@ extern int yydebug;
|
|
enum yytokentype
|
|
{
|
|
DT_V1 = 258,
|
|
- DT_MEMRESERVE = 259,
|
|
- DT_LSHIFT = 260,
|
|
- DT_RSHIFT = 261,
|
|
- DT_LE = 262,
|
|
- DT_GE = 263,
|
|
- DT_EQ = 264,
|
|
- DT_NE = 265,
|
|
- DT_AND = 266,
|
|
- DT_OR = 267,
|
|
- DT_BITS = 268,
|
|
- DT_DEL_PROP = 269,
|
|
- DT_DEL_NODE = 270,
|
|
- DT_PROPNODENAME = 271,
|
|
- DT_LITERAL = 272,
|
|
- DT_CHAR_LITERAL = 273,
|
|
- DT_BYTE = 274,
|
|
- DT_STRING = 275,
|
|
- DT_LABEL = 276,
|
|
- DT_REF = 277,
|
|
- DT_INCBIN = 278
|
|
+ DT_PLUGIN = 259,
|
|
+ DT_MEMRESERVE = 260,
|
|
+ DT_LSHIFT = 261,
|
|
+ DT_RSHIFT = 262,
|
|
+ DT_LE = 263,
|
|
+ DT_GE = 264,
|
|
+ DT_EQ = 265,
|
|
+ DT_NE = 266,
|
|
+ DT_AND = 267,
|
|
+ DT_OR = 268,
|
|
+ DT_BITS = 269,
|
|
+ DT_DEL_PROP = 270,
|
|
+ DT_DEL_NODE = 271,
|
|
+ DT_PROPNODENAME = 272,
|
|
+ DT_LITERAL = 273,
|
|
+ DT_CHAR_LITERAL = 274,
|
|
+ DT_BYTE = 275,
|
|
+ DT_STRING = 276,
|
|
+ DT_LABEL = 277,
|
|
+ DT_REF = 278,
|
|
+ DT_INCBIN = 279
|
|
};
|
|
#endif
|
|
|
|
/* Value type. */
|
|
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
|
-typedef union YYSTYPE YYSTYPE;
|
|
+
|
|
union YYSTYPE
|
|
{
|
|
-#line 38 "dtc-parser.y" /* yacc.c:1909 */
|
|
+#line 39 "dtc-parser.y" /* yacc.c:1909 */
|
|
|
|
char *propnodename;
|
|
char *labelref;
|
|
@@ -92,9 +93,12 @@ union YYSTYPE
|
|
struct node *nodelist;
|
|
struct reserve_info *re;
|
|
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_DECLARED 1
|
|
#endif
|
|
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
|
|
index ea57e0a05..44af170ab 100644
|
|
--- a/scripts/dtc/dtc-parser.y
|
|
+++ b/scripts/dtc/dtc-parser.y
|
|
@@ -19,6 +19,7 @@
|
|
*/
|
|
%{
|
|
#include <stdio.h>
|
|
+#include <inttypes.h>
|
|
|
|
#include "dtc.h"
|
|
#include "srcpos.h"
|
|
@@ -31,7 +32,7 @@ extern void yyerror(char const *s);
|
|
treesource_error = true; \
|
|
} while (0)
|
|
|
|
-extern struct boot_info *the_boot_info;
|
|
+extern struct dt_info *parser_output;
|
|
extern bool treesource_error;
|
|
%}
|
|
|
|
@@ -52,9 +53,11 @@ extern bool treesource_error;
|
|
struct node *nodelist;
|
|
struct reserve_info *re;
|
|
uint64_t integer;
|
|
+ unsigned int flags;
|
|
}
|
|
|
|
%token DT_V1
|
|
+%token DT_PLUGIN
|
|
%token DT_MEMRESERVE
|
|
%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
|
|
%token DT_BITS
|
|
@@ -71,6 +74,8 @@ extern bool treesource_error;
|
|
|
|
%type <data> propdata
|
|
%type <data> propdataprefix
|
|
+%type <flags> header
|
|
+%type <flags> headers
|
|
%type <re> memreserve
|
|
%type <re> memreserves
|
|
%type <array> arrayprefix
|
|
@@ -101,10 +106,31 @@ extern bool treesource_error;
|
|
%%
|
|
|
|
sourcefile:
|
|
- DT_V1 ';' memreserves devicetree
|
|
+ headers memreserves devicetree
|
|
{
|
|
- the_boot_info = build_boot_info($3, $4,
|
|
- guess_boot_cpuid($4));
|
|
+ parser_output = build_dt_info($1, $2, $3,
|
|
+ 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;
|
|
}
|
|
;
|
|
|
|
@@ -140,14 +166,45 @@ devicetree:
|
|
{
|
|
$$ = merge_nodes($1, $3);
|
|
}
|
|
+ | DT_REF nodedef
|
|
+ {
|
|
+ /*
|
|
+ * We rely on the rule being always:
|
|
+ * versioninfo plugindecl memreserves devicetree
|
|
+ * so $-1 is what we want (plugindecl)
|
|
+ */
|
|
+ if (!($<flags>-1 & DTSF_PLUGIN))
|
|
+ ERROR(&@2, "Label or path %s not found", $1);
|
|
+ $$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1);
|
|
+ }
|
|
+ | devicetree DT_LABEL DT_REF nodedef
|
|
+ {
|
|
+ struct node *target = get_node_by_ref($1, $3);
|
|
+
|
|
+ if (target) {
|
|
+ add_label(&target->labels, $2);
|
|
+ merge_nodes(target, $4);
|
|
+ } else
|
|
+ ERROR(&@3, "Label or path %s not found", $3);
|
|
+ $$ = $1;
|
|
+ }
|
|
| devicetree DT_REF nodedef
|
|
{
|
|
struct node *target = get_node_by_ref($1, $2);
|
|
|
|
- if (target)
|
|
+ if (target) {
|
|
merge_nodes(target, $3);
|
|
- else
|
|
- ERROR(&@2, "Label or path %s not found", $2);
|
|
+ } else {
|
|
+ /*
|
|
+ * We rely on the rule being always:
|
|
+ * versioninfo plugindecl memreserves devicetree
|
|
+ * so $-1 is what we want (plugindecl)
|
|
+ */
|
|
+ if ($<flags>-1 & DTSF_PLUGIN)
|
|
+ add_orphan_node($1, $3, $2);
|
|
+ else
|
|
+ ERROR(&@2, "Label or path %s not found", $2);
|
|
+ }
|
|
$$ = $1;
|
|
}
|
|
| devicetree DT_DEL_NODE DT_REF ';'
|
|
@@ -398,8 +455,24 @@ integer_add:
|
|
|
|
integer_mul:
|
|
integer_mul '*' integer_unary { $$ = $1 * $3; }
|
|
- | integer_mul '/' integer_unary { $$ = $1 / $3; }
|
|
- | integer_mul '%' integer_unary { $$ = $1 % $3; }
|
|
+ | integer_mul '/' integer_unary
|
|
+ {
|
|
+ if ($3 != 0) {
|
|
+ $$ = $1 / $3;
|
|
+ } else {
|
|
+ ERROR(&@$, "Division by zero");
|
|
+ $$ = 0;
|
|
+ }
|
|
+ }
|
|
+ | integer_mul '%' integer_unary
|
|
+ {
|
|
+ if ($3 != 0) {
|
|
+ $$ = $1 % $3;
|
|
+ } else {
|
|
+ ERROR(&@$, "Division by zero");
|
|
+ $$ = 0;
|
|
+ }
|
|
+ }
|
|
| integer_unary
|
|
;
|
|
|
|
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
|
|
index 8c4add69a..c36994e6e 100644
|
|
--- a/scripts/dtc/dtc.c
|
|
+++ b/scripts/dtc/dtc.c
|
|
@@ -18,6 +18,8 @@
|
|
* USA
|
|
*/
|
|
|
|
+#include <sys/stat.h>
|
|
+
|
|
#include "dtc.h"
|
|
#include "srcpos.h"
|
|
|
|
@@ -28,7 +30,16 @@ int quiet; /* Level of quietness */
|
|
int reservenum; /* Number of memory reservation slots */
|
|
int minsize; /* Minimum blob size */
|
|
int padsize; /* Additional padding to blob */
|
|
-int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
|
|
+int alignsize; /* Additional padding to blob accroding to the alignsize */
|
|
+int phandle_format = PHANDLE_EPAPR; /* 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)
|
|
{
|
|
@@ -48,10 +59,8 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
|
|
}
|
|
|
|
/* Usage related data. */
|
|
-#define FDT_VERSION(version) _FDT_VERSION(version)
|
|
-#define _FDT_VERSION(version) #version
|
|
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[] = {
|
|
{"quiet", no_argument, NULL, 'q'},
|
|
{"in-format", a_argument, NULL, 'I'},
|
|
@@ -62,6 +71,7 @@ static struct option const usage_long_opts[] = {
|
|
{"reserve", a_argument, NULL, 'R'},
|
|
{"space", a_argument, NULL, 'S'},
|
|
{"pad", a_argument, NULL, 'p'},
|
|
+ {"align", a_argument, NULL, 'a'},
|
|
{"boot-cpu", a_argument, NULL, 'b'},
|
|
{"force", no_argument, NULL, 'f'},
|
|
{"include", a_argument, NULL, 'i'},
|
|
@@ -69,6 +79,8 @@ static struct option const usage_long_opts[] = {
|
|
{"phandle", a_argument, NULL, 'H'},
|
|
{"warning", a_argument, NULL, 'W'},
|
|
{"error", a_argument, NULL, 'E'},
|
|
+ {"symbols", no_argument, NULL, '@'},
|
|
+ {"auto-alias", no_argument, NULL, 'A'},
|
|
{"help", no_argument, NULL, 'h'},
|
|
{"version", no_argument, NULL, 'v'},
|
|
{NULL, no_argument, NULL, 0x0},
|
|
@@ -84,11 +96,12 @@ static const char * const usage_opts_help[] = {
|
|
"\t\tdts - device tree source text\n"
|
|
"\t\tdtb - device tree blob\n"
|
|
"\t\tasm - assembler source",
|
|
- "\n\tBlob version to produce, defaults to "FDT_VERSION(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
|
|
+ "\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
|
|
"\n\tOutput dependency file",
|
|
"\n\tMake space for <number> reserve map entries (for dtb and asm output)",
|
|
"\n\tMake the blob at least <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\tTry to produce output even if the input tree has errors",
|
|
"\n\tAdd a path to search for include files",
|
|
@@ -99,16 +112,62 @@ static const char * const usage_opts_help[] = {
|
|
"\t\tboth - Both \"linux,phandle\" and \"phandle\" properties",
|
|
"\n\tEnable/disable warnings (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 version and exit",
|
|
NULL,
|
|
};
|
|
|
|
+static const char *guess_type_by_name(const char *fname, const char *fallback)
|
|
+{
|
|
+ const char *s;
|
|
+
|
|
+ s = strrchr(fname, '.');
|
|
+ if (s == NULL)
|
|
+ return fallback;
|
|
+ if (!strcasecmp(s, ".dts"))
|
|
+ return "dts";
|
|
+ if (!strcasecmp(s, ".dtb"))
|
|
+ return "dtb";
|
|
+ return fallback;
|
|
+}
|
|
+
|
|
+static const char *guess_input_format(const char *fname, const char *fallback)
|
|
+{
|
|
+ struct stat statbuf;
|
|
+ fdt32_t magic;
|
|
+ FILE *f;
|
|
+
|
|
+ if (stat(fname, &statbuf) != 0)
|
|
+ return fallback;
|
|
+
|
|
+ if (S_ISDIR(statbuf.st_mode))
|
|
+ return "fs";
|
|
+
|
|
+ if (!S_ISREG(statbuf.st_mode))
|
|
+ return fallback;
|
|
+
|
|
+ f = fopen(fname, "r");
|
|
+ if (f == NULL)
|
|
+ return fallback;
|
|
+ if (fread(&magic, 4, 1, f) != 1) {
|
|
+ fclose(f);
|
|
+ return fallback;
|
|
+ }
|
|
+ fclose(f);
|
|
+
|
|
+ if (fdt32_to_cpu(magic) == FDT_MAGIC)
|
|
+ return "dtb";
|
|
+
|
|
+ return guess_type_by_name(fname, fallback);
|
|
+}
|
|
+
|
|
int main(int argc, char *argv[])
|
|
{
|
|
- struct boot_info *bi;
|
|
- const char *inform = "dts";
|
|
- const char *outform = "dts";
|
|
+ struct dt_info *dti;
|
|
+ const char *inform = NULL;
|
|
+ const char *outform = NULL;
|
|
const char *outname = "-";
|
|
const char *depname = NULL;
|
|
bool force = false, sort = false;
|
|
@@ -122,6 +181,7 @@ int main(int argc, char *argv[])
|
|
reservenum = 0;
|
|
minsize = 0;
|
|
padsize = 0;
|
|
+ alignsize = 0;
|
|
|
|
while ((opt = util_getopt_long()) != EOF) {
|
|
switch (opt) {
|
|
@@ -149,6 +209,12 @@ int main(int argc, char *argv[])
|
|
case 'p':
|
|
padsize = strtol(optarg, NULL, 0);
|
|
break;
|
|
+ case 'a':
|
|
+ alignsize = strtol(optarg, NULL, 0);
|
|
+ if (!is_power_of_2(alignsize))
|
|
+ die("Invalid argument \"%d\" to -a option\n",
|
|
+ alignsize);
|
|
+ break;
|
|
case 'f':
|
|
force = true;
|
|
break;
|
|
@@ -187,6 +253,13 @@ int main(int argc, char *argv[])
|
|
parse_checks_option(false, true, optarg);
|
|
break;
|
|
|
|
+ case '@':
|
|
+ generate_symbols = 1;
|
|
+ break;
|
|
+ case 'A':
|
|
+ auto_label_aliases = 1;
|
|
+ break;
|
|
+
|
|
case 'h':
|
|
usage(NULL);
|
|
default:
|
|
@@ -213,28 +286,58 @@ int main(int argc, char *argv[])
|
|
fprintf(depfile, "%s:", outname);
|
|
}
|
|
|
|
+ if (inform == NULL)
|
|
+ inform = guess_input_format(arg, "dts");
|
|
+ if (outform == NULL) {
|
|
+ outform = guess_type_by_name(outname, NULL);
|
|
+ if (outform == NULL) {
|
|
+ if (streq(inform, "dts"))
|
|
+ outform = "dtb";
|
|
+ else
|
|
+ outform = "dts";
|
|
+ }
|
|
+ }
|
|
if (streq(inform, "dts"))
|
|
- bi = dt_from_source(arg);
|
|
+ dti = dt_from_source(arg);
|
|
else if (streq(inform, "fs"))
|
|
- bi = dt_from_fs(arg);
|
|
+ dti = dt_from_fs(arg);
|
|
else if(streq(inform, "dtb"))
|
|
- bi = dt_from_blob(arg);
|
|
+ dti = dt_from_blob(arg);
|
|
else
|
|
die("Unknown input format \"%s\"\n", inform);
|
|
|
|
+ dti->outname = outname;
|
|
+
|
|
if (depfile) {
|
|
fputc('\n', depfile);
|
|
fclose(depfile);
|
|
}
|
|
|
|
if (cmdline_boot_cpuid != -1)
|
|
- bi->boot_cpuid_phys = cmdline_boot_cpuid;
|
|
+ dti->boot_cpuid_phys = cmdline_boot_cpuid;
|
|
+
|
|
+ fill_fullpaths(dti->dt, "");
|
|
+
|
|
+ /* on a plugin, generate by default */
|
|
+ if (dti->dtsflags & DTSF_PLUGIN) {
|
|
+ generate_fixups = 1;
|
|
+ }
|
|
|
|
- fill_fullpaths(bi->dt, "");
|
|
- process_checks(force, bi);
|
|
+ process_checks(force, dti);
|
|
+
|
|
+ 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)
|
|
- sort_tree(bi);
|
|
+ sort_tree(dti);
|
|
|
|
if (streq(outname, "-")) {
|
|
outf = stdout;
|
|
@@ -246,11 +349,11 @@ int main(int argc, char *argv[])
|
|
}
|
|
|
|
if (streq(outform, "dts")) {
|
|
- dt_to_source(outf, bi);
|
|
+ dt_to_source(outf, dti);
|
|
} else if (streq(outform, "dtb")) {
|
|
- dt_to_blob(outf, bi, outversion);
|
|
+ dt_to_blob(outf, dti, outversion);
|
|
} else if (streq(outform, "asm")) {
|
|
- dt_to_asm(outf, bi, outversion);
|
|
+ dt_to_asm(outf, dti, outversion);
|
|
} else if (streq(outform, "null")) {
|
|
/* do nothing */
|
|
} else {
|
|
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
|
|
index 56212c8df..3b18a42b8 100644
|
|
--- a/scripts/dtc/dtc.h
|
|
+++ b/scripts/dtc/dtc.h
|
|
@@ -1,5 +1,5 @@
|
|
-#ifndef _DTC_H
|
|
-#define _DTC_H
|
|
+#ifndef DTC_H
|
|
+#define DTC_H
|
|
|
|
/*
|
|
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
|
|
@@ -31,6 +31,7 @@
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
+#include <inttypes.h>
|
|
|
|
#include <libfdt_env.h>
|
|
#include <fdt.h>
|
|
@@ -43,7 +44,6 @@
|
|
#define debug(...)
|
|
#endif
|
|
|
|
-
|
|
#define DEFAULT_FDT_VERSION 17
|
|
|
|
/*
|
|
@@ -53,7 +53,11 @@ extern int quiet; /* Level of quietness */
|
|
extern int reservenum; /* Number of memory reservation slots */
|
|
extern int minsize; /* Minimum blob size */
|
|
extern int padsize; /* Additional padding to blob */
|
|
+extern int alignsize; /* Additional padding to blob accroding to the alignsize */
|
|
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_EPAPR 0x2
|
|
@@ -63,7 +67,8 @@ typedef uint32_t cell_t;
|
|
|
|
|
|
#define streq(a, b) (strcmp((a), (b)) == 0)
|
|
-#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
|
|
+#define strstarts(s, prefix) (strncmp((s), (prefix), strlen(prefix)) == 0)
|
|
+#define strprefixeq(a, n, b) (strlen(b) == (n) && (memcmp(a, b, n) == 0))
|
|
|
|
#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
|
|
|
@@ -110,7 +115,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_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_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_byte(struct data d, uint8_t byte);
|
|
struct data data_append_zeroes(struct data d, int len);
|
|
@@ -132,6 +137,10 @@ struct label {
|
|
struct label *next;
|
|
};
|
|
|
|
+struct bus_type {
|
|
+ const char *name;
|
|
+};
|
|
+
|
|
struct property {
|
|
bool deleted;
|
|
char *name;
|
|
@@ -158,6 +167,7 @@ struct node {
|
|
int addr_cells, size_cells;
|
|
|
|
struct label *labels;
|
|
+ const struct bus_type *bus;
|
|
};
|
|
|
|
#define for_each_label_withdel(l0, l) \
|
|
@@ -194,6 +204,7 @@ struct node *build_node_delete(void);
|
|
struct node *name_node(struct node *node, char *name);
|
|
struct node *chain_node(struct node *first, struct node *list);
|
|
struct node *merge_nodes(struct node *old_node, struct node *new_node);
|
|
+struct node *add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
|
|
|
|
void add_property(struct node *node, struct property *prop);
|
|
void delete_property_by_name(struct node *node, char *name);
|
|
@@ -201,10 +212,13 @@ void delete_property(struct property *prop);
|
|
void add_child(struct node *parent, struct node *child);
|
|
void delete_node_by_name(struct node *parent, char *name);
|
|
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);
|
|
struct property *get_property(struct node *node, const char *propname);
|
|
cell_t propval_cell(struct property *prop);
|
|
+cell_t propval_cell_n(struct property *prop, int n);
|
|
struct property *get_property_by_label(struct node *tree, const char *label,
|
|
struct node **node);
|
|
struct marker *get_marker_label(struct node *tree, const char *label,
|
|
@@ -221,7 +235,7 @@ uint32_t guess_boot_cpuid(struct node *tree);
|
|
/* Boot info (tree plus memreserve information */
|
|
|
|
struct reserve_info {
|
|
- struct fdt_reserve_entry re;
|
|
+ uint64_t address, size;
|
|
|
|
struct reserve_info *next;
|
|
|
|
@@ -235,35 +249,45 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
|
|
struct reserve_info *new);
|
|
|
|
|
|
-struct boot_info {
|
|
+struct dt_info {
|
|
+ unsigned int dtsflags;
|
|
struct reserve_info *reservelist;
|
|
- struct node *dt; /* the device tree */
|
|
uint32_t boot_cpuid_phys;
|
|
+ struct node *dt; /* the device tree */
|
|
+ const char *outname; /* filename being written to, "-" for stdout */
|
|
};
|
|
|
|
-struct boot_info *build_boot_info(struct reserve_info *reservelist,
|
|
- struct node *tree, uint32_t boot_cpuid_phys);
|
|
-void sort_tree(struct boot_info *bi);
|
|
+/* DTS version flags definitions */
|
|
+#define DTSF_V1 0x0001 /* /dts-v1/ */
|
|
+#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 */
|
|
|
|
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 */
|
|
|
|
-void dt_to_blob(FILE *f, struct boot_info *bi, int version);
|
|
-void dt_to_asm(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 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 */
|
|
|
|
-void dt_to_source(FILE *f, struct boot_info *bi);
|
|
-struct boot_info *dt_from_source(const char *f);
|
|
+void dt_to_source(FILE *f, struct dt_info *dti);
|
|
+struct dt_info *dt_from_source(const char *f);
|
|
|
|
/* 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 */
|
|
diff --git a/scripts/dtc/fdt.c b/scripts/dtc/fdt.c
|
|
index 2ce6a4417..7855a1787 100644
|
|
--- a/scripts/dtc/fdt.c
|
|
+++ b/scripts/dtc/fdt.c
|
|
@@ -76,18 +76,19 @@ int fdt_check_header(const void *fdt)
|
|
|
|
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
|
|
{
|
|
- const char *p;
|
|
+ unsigned absoffset = offset + fdt_off_dt_struct(fdt);
|
|
+
|
|
+ if ((absoffset < offset)
|
|
+ || ((absoffset + len) < absoffset)
|
|
+ || (absoffset + len) > fdt_totalsize(fdt))
|
|
+ return NULL;
|
|
|
|
if (fdt_version(fdt) >= 0x11)
|
|
if (((offset + len) < offset)
|
|
|| ((offset + len) > fdt_size_dt_struct(fdt)))
|
|
return NULL;
|
|
|
|
- p = _fdt_offset_ptr(fdt, offset);
|
|
-
|
|
- if (p + len < p)
|
|
- return NULL;
|
|
- return p;
|
|
+ return fdt_offset_ptr_(fdt, offset);
|
|
}
|
|
|
|
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
|
@@ -122,6 +123,9 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
|
/* skip-name offset, length and value */
|
|
offset += sizeof(struct fdt_property) - FDT_TAGSIZE
|
|
+ fdt32_to_cpu(*lenp);
|
|
+ if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
|
|
+ ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
|
|
+ offset += 4;
|
|
break;
|
|
|
|
case FDT_END:
|
|
@@ -140,7 +144,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
|
|
return tag;
|
|
}
|
|
|
|
-int _fdt_check_node_offset(const void *fdt, int offset)
|
|
+int fdt_check_node_offset_(const void *fdt, int offset)
|
|
{
|
|
if ((offset < 0) || (offset % FDT_TAGSIZE)
|
|
|| (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
|
|
@@ -149,7 +153,7 @@ int _fdt_check_node_offset(const void *fdt, int offset)
|
|
return offset;
|
|
}
|
|
|
|
-int _fdt_check_prop_offset(const void *fdt, int offset)
|
|
+int fdt_check_prop_offset_(const void *fdt, int offset)
|
|
{
|
|
if ((offset < 0) || (offset % FDT_TAGSIZE)
|
|
|| (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
|
|
@@ -164,7 +168,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
|
|
uint32_t tag;
|
|
|
|
if (offset >= 0)
|
|
- if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
|
|
+ if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0)
|
|
return nextoffset;
|
|
|
|
do {
|
|
@@ -226,7 +230,7 @@ int fdt_next_subnode(const void *fdt, int offset)
|
|
return offset;
|
|
}
|
|
|
|
-const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
|
|
+const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)
|
|
{
|
|
int len = strlen(s) + 1;
|
|
const char *last = strtab + tabsize - len;
|
|
diff --git a/scripts/dtc/fdt.h b/scripts/dtc/fdt.h
|
|
index 526aedb51..74961f902 100644
|
|
--- a/scripts/dtc/fdt.h
|
|
+++ b/scripts/dtc/fdt.h
|
|
@@ -1,5 +1,5 @@
|
|
-#ifndef _FDT_H
|
|
-#define _FDT_H
|
|
+#ifndef FDT_H
|
|
+#define FDT_H
|
|
/*
|
|
* libfdt - Flat Device Tree manipulation
|
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
|
@@ -108,4 +108,4 @@ struct fdt_property {
|
|
#define FDT_V16_SIZE FDT_V3_SIZE
|
|
#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t))
|
|
|
|
-#endif /* _FDT_H */
|
|
+#endif /* FDT_H */
|
|
diff --git a/scripts/dtc/fdt_empty_tree.c b/scripts/dtc/fdt_empty_tree.c
|
|
index f72d13b1d..f2ae9b77c 100644
|
|
--- a/scripts/dtc/fdt_empty_tree.c
|
|
+++ b/scripts/dtc/fdt_empty_tree.c
|
|
@@ -81,4 +81,3 @@ int fdt_create_empty_tree(void *buf, int bufsize)
|
|
|
|
return fdt_open_into(buf, buf, bufsize);
|
|
}
|
|
-
|
|
diff --git a/scripts/dtc/fdt_overlay.c b/scripts/dtc/fdt_overlay.c
|
|
new file mode 100644
|
|
index 000000000..bf75388ec
|
|
--- /dev/null
|
|
+++ b/scripts/dtc/fdt_overlay.c
|
|
@@ -0,0 +1,912 @@
|
|
+/*
|
|
+ * libfdt - Flat Device Tree manipulation
|
|
+ * Copyright (C) 2016 Free Electrons
|
|
+ * Copyright (C) 2016 NextThing Co.
|
|
+ *
|
|
+ * libfdt is dual licensed: you can use it either under the terms of
|
|
+ * the GPL, or the BSD license, at your option.
|
|
+ *
|
|
+ * a) This library is free software; you can redistribute it and/or
|
|
+ * modify it under the terms of the GNU General Public License as
|
|
+ * published by the Free Software Foundation; either version 2 of the
|
|
+ * License, or (at your option) any later version.
|
|
+ *
|
|
+ * This library is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ * You should have received a copy of the GNU General Public
|
|
+ * License along with this library; if not, write to the Free
|
|
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
|
+ * MA 02110-1301 USA
|
|
+ *
|
|
+ * Alternatively,
|
|
+ *
|
|
+ * b) Redistribution and use in source and binary forms, with or
|
|
+ * without modification, are permitted provided that the following
|
|
+ * conditions are met:
|
|
+ *
|
|
+ * 1. Redistributions of source code must retain the above
|
|
+ * copyright notice, this list of conditions and the following
|
|
+ * disclaimer.
|
|
+ * 2. Redistributions in binary form must reproduce the above
|
|
+ * copyright notice, this list of conditions and the following
|
|
+ * disclaimer in the documentation and/or other materials
|
|
+ * provided with the distribution.
|
|
+ *
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
|
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
|
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
+ */
|
|
+#include "libfdt_env.h"
|
|
+
|
|
+#include <fdt.h>
|
|
+#include <libfdt.h>
|
|
+
|
|
+#include "libfdt_internal.h"
|
|
+
|
|
+/**
|
|
+ * overlay_get_target_phandle - retrieves the target phandle of a fragment
|
|
+ * @fdto: pointer to the device tree overlay blob
|
|
+ * @fragment: node offset of the fragment in the overlay
|
|
+ *
|
|
+ * overlay_get_target_phandle() retrieves the target phandle of an
|
|
+ * overlay fragment when that fragment uses a phandle (target
|
|
+ * property) instead of a path (target-path property).
|
|
+ *
|
|
+ * returns:
|
|
+ * the phandle pointed by the target property
|
|
+ * 0, if the phandle was not found
|
|
+ * -1, if the phandle was malformed
|
|
+ */
|
|
+static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
|
|
+{
|
|
+ const fdt32_t *val;
|
|
+ int len;
|
|
+
|
|
+ val = fdt_getprop(fdto, fragment, "target", &len);
|
|
+ if (!val)
|
|
+ return 0;
|
|
+
|
|
+ if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1))
|
|
+ return (uint32_t)-1;
|
|
+
|
|
+ return fdt32_to_cpu(*val);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * overlay_get_target - retrieves the offset of a fragment's target
|
|
+ * @fdt: Base device tree blob
|
|
+ * @fdto: Device tree overlay blob
|
|
+ * @fragment: node offset of the fragment in the overlay
|
|
+ * @pathp: pointer which receives the path of the target (or NULL)
|
|
+ *
|
|
+ * overlay_get_target() retrieves the target offset in the base
|
|
+ * device tree of a fragment, no matter how the actual targetting is
|
|
+ * done (through a phandle or a path)
|
|
+ *
|
|
+ * returns:
|
|
+ * the targetted node offset in the base device tree
|
|
+ * Negative error code on error
|
|
+ */
|
|
+static int overlay_get_target(const void *fdt, const void *fdto,
|
|
+ int fragment, char const **pathp)
|
|
+{
|
|
+ uint32_t phandle;
|
|
+ const char *path = NULL;
|
|
+ int path_len = 0, ret;
|
|
+
|
|
+ /* Try first to do a phandle based lookup */
|
|
+ phandle = overlay_get_target_phandle(fdto, fragment);
|
|
+ if (phandle == (uint32_t)-1)
|
|
+ return -FDT_ERR_BADPHANDLE;
|
|
+
|
|
+ /* no phandle, try path */
|
|
+ if (!phandle) {
|
|
+ /* And then a path based lookup */
|
|
+ path = fdt_getprop(fdto, fragment, "target-path", &path_len);
|
|
+ if (path)
|
|
+ ret = fdt_path_offset(fdt, path);
|
|
+ else
|
|
+ ret = path_len;
|
|
+ } else
|
|
+ ret = fdt_node_offset_by_phandle(fdt, phandle);
|
|
+
|
|
+ /*
|
|
+ * If we haven't found either a target or a
|
|
+ * target-path property in a node that contains a
|
|
+ * __overlay__ subnode (we wouldn't be called
|
|
+ * otherwise), consider it a improperly written
|
|
+ * overlay
|
|
+ */
|
|
+ if (ret < 0 && path_len == -FDT_ERR_NOTFOUND)
|
|
+ ret = -FDT_ERR_BADOVERLAY;
|
|
+
|
|
+ /* return on error */
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ /* return pointer to path (if available) */
|
|
+ if (pathp)
|
|
+ *pathp = path ? path : NULL;
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * overlay_phandle_add_offset - Increases a phandle by an offset
|
|
+ * @fdt: Base device tree blob
|
|
+ * @node: Device tree overlay blob
|
|
+ * @name: Name of the property to modify (phandle or linux,phandle)
|
|
+ * @delta: offset to apply
|
|
+ *
|
|
+ * overlay_phandle_add_offset() increments a node phandle by a given
|
|
+ * offset.
|
|
+ *
|
|
+ * returns:
|
|
+ * 0 on success.
|
|
+ * Negative error code on error
|
|
+ */
|
|
+static int overlay_phandle_add_offset(void *fdt, int node,
|
|
+ const char *name, uint32_t delta)
|
|
+{
|
|
+ const fdt32_t *val;
|
|
+ uint32_t adj_val;
|
|
+ int len;
|
|
+
|
|
+ val = fdt_getprop(fdt, node, name, &len);
|
|
+ if (!val)
|
|
+ return len;
|
|
+
|
|
+ if (len != sizeof(*val))
|
|
+ return -FDT_ERR_BADPHANDLE;
|
|
+
|
|
+ adj_val = fdt32_to_cpu(*val);
|
|
+ if ((adj_val + delta) < adj_val)
|
|
+ return -FDT_ERR_NOPHANDLES;
|
|
+
|
|
+ adj_val += delta;
|
|
+ if (adj_val == (uint32_t)-1)
|
|
+ return -FDT_ERR_NOPHANDLES;
|
|
+
|
|
+ return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * overlay_adjust_node_phandles - Offsets the phandles of a node
|
|
+ * @fdto: Device tree overlay blob
|
|
+ * @node: Offset of the node we want to adjust
|
|
+ * @delta: Offset to shift the phandles of
|
|
+ *
|
|
+ * overlay_adjust_node_phandles() adds a constant to all the phandles
|
|
+ * of a given node. This is mainly use as part of the overlay
|
|
+ * application process, when we want to update all the overlay
|
|
+ * phandles to not conflict with the overlays of the base device tree.
|
|
+ *
|
|
+ * returns:
|
|
+ * 0 on success
|
|
+ * Negative error code on failure
|
|
+ */
|
|
+static int overlay_adjust_node_phandles(void *fdto, int node,
|
|
+ uint32_t delta)
|
|
+{
|
|
+ int child;
|
|
+ int ret;
|
|
+
|
|
+ ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
|
|
+ if (ret && ret != -FDT_ERR_NOTFOUND)
|
|
+ return ret;
|
|
+
|
|
+ ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
|
|
+ if (ret && ret != -FDT_ERR_NOTFOUND)
|
|
+ return ret;
|
|
+
|
|
+ fdt_for_each_subnode(child, fdto, node) {
|
|
+ ret = overlay_adjust_node_phandles(fdto, child, delta);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay
|
|
+ * @fdto: Device tree overlay blob
|
|
+ * @delta: Offset to shift the phandles of
|
|
+ *
|
|
+ * overlay_adjust_local_phandles() adds a constant to all the
|
|
+ * phandles of an overlay. This is mainly use as part of the overlay
|
|
+ * application process, when we want to update all the overlay
|
|
+ * phandles to not conflict with the overlays of the base device tree.
|
|
+ *
|
|
+ * returns:
|
|
+ * 0 on success
|
|
+ * Negative error code on failure
|
|
+ */
|
|
+static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
|
|
+{
|
|
+ /*
|
|
+ * Start adjusting the phandles from the overlay root
|
|
+ */
|
|
+ return overlay_adjust_node_phandles(fdto, 0, delta);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * overlay_update_local_node_references - Adjust the overlay references
|
|
+ * @fdto: Device tree overlay blob
|
|
+ * @tree_node: Node offset of the node to operate on
|
|
+ * @fixup_node: Node offset of the matching local fixups node
|
|
+ * @delta: Offset to shift the phandles of
|
|
+ *
|
|
+ * overlay_update_local_nodes_references() update the phandles
|
|
+ * pointing to a node within the device tree overlay by adding a
|
|
+ * constant delta.
|
|
+ *
|
|
+ * This is mainly used as part of a device tree application process,
|
|
+ * where you want the device tree overlays phandles to not conflict
|
|
+ * with the ones from the base device tree before merging them.
|
|
+ *
|
|
+ * returns:
|
|
+ * 0 on success
|
|
+ * Negative error code on failure
|
|
+ */
|
|
+static int overlay_update_local_node_references(void *fdto,
|
|
+ int tree_node,
|
|
+ int fixup_node,
|
|
+ uint32_t delta)
|
|
+{
|
|
+ int fixup_prop;
|
|
+ int fixup_child;
|
|
+ int ret;
|
|
+
|
|
+ fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
|
|
+ const fdt32_t *fixup_val;
|
|
+ const char *tree_val;
|
|
+ const char *name;
|
|
+ int fixup_len;
|
|
+ int tree_len;
|
|
+ int i;
|
|
+
|
|
+ fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
|
|
+ &name, &fixup_len);
|
|
+ if (!fixup_val)
|
|
+ return fixup_len;
|
|
+
|
|
+ if (fixup_len % sizeof(uint32_t))
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+
|
|
+ tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
|
|
+ if (!tree_val) {
|
|
+ if (tree_len == -FDT_ERR_NOTFOUND)
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+
|
|
+ return tree_len;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) {
|
|
+ fdt32_t adj_val;
|
|
+ uint32_t poffset;
|
|
+
|
|
+ poffset = fdt32_to_cpu(fixup_val[i]);
|
|
+
|
|
+ /*
|
|
+ * phandles to fixup can be unaligned.
|
|
+ *
|
|
+ * Use a memcpy for the architectures that do
|
|
+ * not support unaligned accesses.
|
|
+ */
|
|
+ memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
|
|
+
|
|
+ adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);
|
|
+
|
|
+ ret = fdt_setprop_inplace_namelen_partial(fdto,
|
|
+ tree_node,
|
|
+ name,
|
|
+ strlen(name),
|
|
+ poffset,
|
|
+ &adj_val,
|
|
+ sizeof(adj_val));
|
|
+ if (ret == -FDT_ERR_NOSPACE)
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
|
|
+ const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
|
|
+ NULL);
|
|
+ int tree_child;
|
|
+
|
|
+ tree_child = fdt_subnode_offset(fdto, tree_node,
|
|
+ fixup_child_name);
|
|
+ if (tree_child == -FDT_ERR_NOTFOUND)
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+ if (tree_child < 0)
|
|
+ return tree_child;
|
|
+
|
|
+ ret = overlay_update_local_node_references(fdto,
|
|
+ tree_child,
|
|
+ fixup_child,
|
|
+ delta);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * overlay_update_local_references - Adjust the overlay references
|
|
+ * @fdto: Device tree overlay blob
|
|
+ * @delta: Offset to shift the phandles of
|
|
+ *
|
|
+ * overlay_update_local_references() update all the phandles pointing
|
|
+ * to a node within the device tree overlay by adding a constant
|
|
+ * delta to not conflict with the base overlay.
|
|
+ *
|
|
+ * This is mainly used as part of a device tree application process,
|
|
+ * where you want the device tree overlays phandles to not conflict
|
|
+ * with the ones from the base device tree before merging them.
|
|
+ *
|
|
+ * returns:
|
|
+ * 0 on success
|
|
+ * Negative error code on failure
|
|
+ */
|
|
+static int overlay_update_local_references(void *fdto, uint32_t delta)
|
|
+{
|
|
+ int fixups;
|
|
+
|
|
+ fixups = fdt_path_offset(fdto, "/__local_fixups__");
|
|
+ if (fixups < 0) {
|
|
+ /* There's no local phandles to adjust, bail out */
|
|
+ if (fixups == -FDT_ERR_NOTFOUND)
|
|
+ return 0;
|
|
+
|
|
+ return fixups;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Update our local references from the root of the tree
|
|
+ */
|
|
+ return overlay_update_local_node_references(fdto, 0, fixups,
|
|
+ delta);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * overlay_fixup_one_phandle - Set an overlay phandle to the base one
|
|
+ * @fdt: Base Device Tree blob
|
|
+ * @fdto: Device tree overlay blob
|
|
+ * @symbols_off: Node offset of the symbols node in the base device tree
|
|
+ * @path: Path to a node holding a phandle in the overlay
|
|
+ * @path_len: number of path characters to consider
|
|
+ * @name: Name of the property holding the phandle reference in the overlay
|
|
+ * @name_len: number of name characters to consider
|
|
+ * @poffset: Offset within the overlay property where the phandle is stored
|
|
+ * @label: Label of the node referenced by the phandle
|
|
+ *
|
|
+ * overlay_fixup_one_phandle() resolves an overlay phandle pointing to
|
|
+ * a node in the base device tree.
|
|
+ *
|
|
+ * This is part of the device tree overlay application process, when
|
|
+ * you want all the phandles in the overlay to point to the actual
|
|
+ * base dt nodes.
|
|
+ *
|
|
+ * returns:
|
|
+ * 0 on success
|
|
+ * Negative error code on failure
|
|
+ */
|
|
+static int overlay_fixup_one_phandle(void *fdt, void *fdto,
|
|
+ int symbols_off,
|
|
+ const char *path, uint32_t path_len,
|
|
+ const char *name, uint32_t name_len,
|
|
+ int poffset, const char *label)
|
|
+{
|
|
+ const char *symbol_path;
|
|
+ uint32_t phandle;
|
|
+ fdt32_t phandle_prop;
|
|
+ int symbol_off, fixup_off;
|
|
+ int prop_len;
|
|
+
|
|
+ if (symbols_off < 0)
|
|
+ return symbols_off;
|
|
+
|
|
+ symbol_path = fdt_getprop(fdt, symbols_off, label,
|
|
+ &prop_len);
|
|
+ if (!symbol_path)
|
|
+ return prop_len;
|
|
+
|
|
+ symbol_off = fdt_path_offset(fdt, symbol_path);
|
|
+ if (symbol_off < 0)
|
|
+ return symbol_off;
|
|
+
|
|
+ phandle = fdt_get_phandle(fdt, symbol_off);
|
|
+ if (!phandle)
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+
|
|
+ fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
|
|
+ if (fixup_off == -FDT_ERR_NOTFOUND)
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+ if (fixup_off < 0)
|
|
+ return fixup_off;
|
|
+
|
|
+ phandle_prop = cpu_to_fdt32(phandle);
|
|
+ return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
|
|
+ name, name_len, poffset,
|
|
+ &phandle_prop,
|
|
+ sizeof(phandle_prop));
|
|
+};
|
|
+
|
|
+/**
|
|
+ * overlay_fixup_phandle - Set an overlay phandle to the base one
|
|
+ * @fdt: Base Device Tree blob
|
|
+ * @fdto: Device tree overlay blob
|
|
+ * @symbols_off: Node offset of the symbols node in the base device tree
|
|
+ * @property: Property offset in the overlay holding the list of fixups
|
|
+ *
|
|
+ * overlay_fixup_phandle() resolves all the overlay phandles pointed
|
|
+ * to in a __fixups__ property, and updates them to match the phandles
|
|
+ * in use in the base device tree.
|
|
+ *
|
|
+ * This is part of the device tree overlay application process, when
|
|
+ * you want all the phandles in the overlay to point to the actual
|
|
+ * base dt nodes.
|
|
+ *
|
|
+ * returns:
|
|
+ * 0 on success
|
|
+ * Negative error code on failure
|
|
+ */
|
|
+static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
|
|
+ int property)
|
|
+{
|
|
+ const char *value;
|
|
+ const char *label;
|
|
+ int len;
|
|
+
|
|
+ value = fdt_getprop_by_offset(fdto, property,
|
|
+ &label, &len);
|
|
+ if (!value) {
|
|
+ if (len == -FDT_ERR_NOTFOUND)
|
|
+ return -FDT_ERR_INTERNAL;
|
|
+
|
|
+ return len;
|
|
+ }
|
|
+
|
|
+ do {
|
|
+ const char *path, *name, *fixup_end;
|
|
+ const char *fixup_str = value;
|
|
+ uint32_t path_len, name_len;
|
|
+ uint32_t fixup_len;
|
|
+ char *sep, *endptr;
|
|
+ int poffset, ret;
|
|
+
|
|
+ fixup_end = memchr(value, '\0', len);
|
|
+ if (!fixup_end)
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+ fixup_len = fixup_end - fixup_str;
|
|
+
|
|
+ len -= fixup_len + 1;
|
|
+ value += fixup_len + 1;
|
|
+
|
|
+ path = fixup_str;
|
|
+ sep = memchr(fixup_str, ':', fixup_len);
|
|
+ if (!sep || *sep != ':')
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+
|
|
+ path_len = sep - path;
|
|
+ if (path_len == (fixup_len - 1))
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+
|
|
+ fixup_len -= path_len + 1;
|
|
+ name = sep + 1;
|
|
+ sep = memchr(name, ':', fixup_len);
|
|
+ if (!sep || *sep != ':')
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+
|
|
+ name_len = sep - name;
|
|
+ if (!name_len)
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+
|
|
+ poffset = strtoul(sep + 1, &endptr, 10);
|
|
+ if ((*endptr != '\0') || (endptr <= (sep + 1)))
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+
|
|
+ ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
|
|
+ path, path_len, name, name_len,
|
|
+ poffset, label);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ } while (len > 0);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * overlay_fixup_phandles - Resolve the overlay phandles to the base
|
|
+ * device tree
|
|
+ * @fdt: Base Device Tree blob
|
|
+ * @fdto: Device tree overlay blob
|
|
+ *
|
|
+ * overlay_fixup_phandles() resolves all the overlay phandles pointing
|
|
+ * to nodes in the base device tree.
|
|
+ *
|
|
+ * This is one of the steps of the device tree overlay application
|
|
+ * process, when you want all the phandles in the overlay to point to
|
|
+ * the actual base dt nodes.
|
|
+ *
|
|
+ * returns:
|
|
+ * 0 on success
|
|
+ * Negative error code on failure
|
|
+ */
|
|
+static int overlay_fixup_phandles(void *fdt, void *fdto)
|
|
+{
|
|
+ int fixups_off, symbols_off;
|
|
+ int property;
|
|
+
|
|
+ /* We can have overlays without any fixups */
|
|
+ fixups_off = fdt_path_offset(fdto, "/__fixups__");
|
|
+ if (fixups_off == -FDT_ERR_NOTFOUND)
|
|
+ return 0; /* nothing to do */
|
|
+ if (fixups_off < 0)
|
|
+ return fixups_off;
|
|
+
|
|
+ /* And base DTs without symbols */
|
|
+ symbols_off = fdt_path_offset(fdt, "/__symbols__");
|
|
+ if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND)))
|
|
+ return symbols_off;
|
|
+
|
|
+ fdt_for_each_property_offset(property, fdto, fixups_off) {
|
|
+ int ret;
|
|
+
|
|
+ ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * overlay_apply_node - Merges a node into the base device tree
|
|
+ * @fdt: Base Device Tree blob
|
|
+ * @target: Node offset in the base device tree to apply the fragment to
|
|
+ * @fdto: Device tree overlay blob
|
|
+ * @node: Node offset in the overlay holding the changes to merge
|
|
+ *
|
|
+ * overlay_apply_node() merges a node into a target base device tree
|
|
+ * node pointed.
|
|
+ *
|
|
+ * This is part of the final step in the device tree overlay
|
|
+ * application process, when all the phandles have been adjusted and
|
|
+ * resolved and you just have to merge overlay into the base device
|
|
+ * tree.
|
|
+ *
|
|
+ * returns:
|
|
+ * 0 on success
|
|
+ * Negative error code on failure
|
|
+ */
|
|
+static int overlay_apply_node(void *fdt, int target,
|
|
+ void *fdto, int node)
|
|
+{
|
|
+ int property;
|
|
+ int subnode;
|
|
+
|
|
+ fdt_for_each_property_offset(property, fdto, node) {
|
|
+ const char *name;
|
|
+ const void *prop;
|
|
+ int prop_len;
|
|
+ int ret;
|
|
+
|
|
+ prop = fdt_getprop_by_offset(fdto, property, &name,
|
|
+ &prop_len);
|
|
+ if (prop_len == -FDT_ERR_NOTFOUND)
|
|
+ return -FDT_ERR_INTERNAL;
|
|
+ if (prop_len < 0)
|
|
+ return prop_len;
|
|
+
|
|
+ ret = fdt_setprop(fdt, target, name, prop, prop_len);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ fdt_for_each_subnode(subnode, fdto, node) {
|
|
+ const char *name = fdt_get_name(fdto, subnode, NULL);
|
|
+ int nnode;
|
|
+ int ret;
|
|
+
|
|
+ nnode = fdt_add_subnode(fdt, target, name);
|
|
+ if (nnode == -FDT_ERR_EXISTS) {
|
|
+ nnode = fdt_subnode_offset(fdt, target, name);
|
|
+ if (nnode == -FDT_ERR_NOTFOUND)
|
|
+ return -FDT_ERR_INTERNAL;
|
|
+ }
|
|
+
|
|
+ if (nnode < 0)
|
|
+ return nnode;
|
|
+
|
|
+ ret = overlay_apply_node(fdt, nnode, fdto, subnode);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * overlay_merge - Merge an overlay into its base device tree
|
|
+ * @fdt: Base Device Tree blob
|
|
+ * @fdto: Device tree overlay blob
|
|
+ *
|
|
+ * overlay_merge() merges an overlay into its base device tree.
|
|
+ *
|
|
+ * This is the next to last step in the device tree overlay application
|
|
+ * process, when all the phandles have been adjusted and resolved and
|
|
+ * you just have to merge overlay into the base device tree.
|
|
+ *
|
|
+ * returns:
|
|
+ * 0 on success
|
|
+ * Negative error code on failure
|
|
+ */
|
|
+static int overlay_merge(void *fdt, void *fdto)
|
|
+{
|
|
+ int fragment;
|
|
+
|
|
+ fdt_for_each_subnode(fragment, fdto, 0) {
|
|
+ int overlay;
|
|
+ int target;
|
|
+ int ret;
|
|
+
|
|
+ /*
|
|
+ * Each fragments will have an __overlay__ node. If
|
|
+ * they don't, it's not supposed to be merged
|
|
+ */
|
|
+ overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
|
|
+ if (overlay == -FDT_ERR_NOTFOUND)
|
|
+ continue;
|
|
+
|
|
+ if (overlay < 0)
|
|
+ return overlay;
|
|
+
|
|
+ target = overlay_get_target(fdt, fdto, fragment, NULL);
|
|
+ if (target < 0)
|
|
+ return target;
|
|
+
|
|
+ ret = overlay_apply_node(fdt, target, fdto, overlay);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int get_path_len(const void *fdt, int nodeoffset)
|
|
+{
|
|
+ int len = 0, namelen;
|
|
+ const char *name;
|
|
+
|
|
+ FDT_CHECK_HEADER(fdt);
|
|
+
|
|
+ for (;;) {
|
|
+ name = fdt_get_name(fdt, nodeoffset, &namelen);
|
|
+ if (!name)
|
|
+ return namelen;
|
|
+
|
|
+ /* root? we're done */
|
|
+ if (namelen == 0)
|
|
+ break;
|
|
+
|
|
+ nodeoffset = fdt_parent_offset(fdt, nodeoffset);
|
|
+ if (nodeoffset < 0)
|
|
+ return nodeoffset;
|
|
+ len += namelen + 1;
|
|
+ }
|
|
+
|
|
+ /* in case of root pretend it's "/" */
|
|
+ if (len == 0)
|
|
+ len++;
|
|
+ return len;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * overlay_symbol_update - Update the symbols of base tree after a merge
|
|
+ * @fdt: Base Device Tree blob
|
|
+ * @fdto: Device tree overlay blob
|
|
+ *
|
|
+ * overlay_symbol_update() updates the symbols of the base tree with the
|
|
+ * symbols of the applied overlay
|
|
+ *
|
|
+ * This is the last step in the device tree overlay application
|
|
+ * process, allowing the reference of overlay symbols by subsequent
|
|
+ * overlay operations.
|
|
+ *
|
|
+ * returns:
|
|
+ * 0 on success
|
|
+ * Negative error code on failure
|
|
+ */
|
|
+static int overlay_symbol_update(void *fdt, void *fdto)
|
|
+{
|
|
+ int root_sym, ov_sym, prop, path_len, fragment, target;
|
|
+ int len, frag_name_len, ret, rel_path_len;
|
|
+ const char *s, *e;
|
|
+ const char *path;
|
|
+ const char *name;
|
|
+ const char *frag_name;
|
|
+ const char *rel_path;
|
|
+ const char *target_path;
|
|
+ char *buf;
|
|
+ void *p;
|
|
+
|
|
+ ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__");
|
|
+
|
|
+ /* if no overlay symbols exist no problem */
|
|
+ if (ov_sym < 0)
|
|
+ return 0;
|
|
+
|
|
+ root_sym = fdt_subnode_offset(fdt, 0, "__symbols__");
|
|
+
|
|
+ /* it no root symbols exist we should create them */
|
|
+ if (root_sym == -FDT_ERR_NOTFOUND)
|
|
+ root_sym = fdt_add_subnode(fdt, 0, "__symbols__");
|
|
+
|
|
+ /* any error is fatal now */
|
|
+ if (root_sym < 0)
|
|
+ return root_sym;
|
|
+
|
|
+ /* iterate over each overlay symbol */
|
|
+ fdt_for_each_property_offset(prop, fdto, ov_sym) {
|
|
+ path = fdt_getprop_by_offset(fdto, prop, &name, &path_len);
|
|
+ if (!path)
|
|
+ return path_len;
|
|
+
|
|
+ /* verify it's a string property (terminated by a single \0) */
|
|
+ if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1])
|
|
+ return -FDT_ERR_BADVALUE;
|
|
+
|
|
+ /* keep end marker to avoid strlen() */
|
|
+ e = path + path_len;
|
|
+
|
|
+ /* format: /<fragment-name>/__overlay__/<relative-subnode-path> */
|
|
+
|
|
+ if (*path != '/')
|
|
+ return -FDT_ERR_BADVALUE;
|
|
+
|
|
+ /* get fragment name first */
|
|
+ s = strchr(path + 1, '/');
|
|
+ if (!s)
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+
|
|
+ frag_name = path + 1;
|
|
+ frag_name_len = s - path - 1;
|
|
+
|
|
+ /* verify format; safe since "s" lies in \0 terminated prop */
|
|
+ len = sizeof("/__overlay__/") - 1;
|
|
+ if ((e - s) < len || memcmp(s, "/__overlay__/", len))
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+
|
|
+ rel_path = s + len;
|
|
+ rel_path_len = e - rel_path;
|
|
+
|
|
+ /* find the fragment index in which the symbol lies */
|
|
+ ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
|
|
+ frag_name_len);
|
|
+ /* not found? */
|
|
+ if (ret < 0)
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+ fragment = ret;
|
|
+
|
|
+ /* an __overlay__ subnode must exist */
|
|
+ ret = fdt_subnode_offset(fdto, fragment, "__overlay__");
|
|
+ if (ret < 0)
|
|
+ return -FDT_ERR_BADOVERLAY;
|
|
+
|
|
+ /* get the target of the fragment */
|
|
+ ret = overlay_get_target(fdt, fdto, fragment, &target_path);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ target = ret;
|
|
+
|
|
+ /* if we have a target path use */
|
|
+ if (!target_path) {
|
|
+ ret = get_path_len(fdt, target);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ len = ret;
|
|
+ } else {
|
|
+ len = strlen(target_path);
|
|
+ }
|
|
+
|
|
+ ret = fdt_setprop_placeholder(fdt, root_sym, name,
|
|
+ len + (len > 1) + rel_path_len + 1, &p);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ if (!target_path) {
|
|
+ /* again in case setprop_placeholder changed it */
|
|
+ ret = overlay_get_target(fdt, fdto, fragment, &target_path);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ target = ret;
|
|
+ }
|
|
+
|
|
+ buf = p;
|
|
+ if (len > 1) { /* target is not root */
|
|
+ if (!target_path) {
|
|
+ ret = fdt_get_path(fdt, target, buf, len + 1);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+ } else
|
|
+ memcpy(buf, target_path, len + 1);
|
|
+
|
|
+ } else
|
|
+ len--;
|
|
+
|
|
+ buf[len] = '/';
|
|
+ memcpy(buf + len + 1, rel_path, rel_path_len);
|
|
+ buf[len + 1 + rel_path_len] = '\0';
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int fdt_overlay_apply(void *fdt, void *fdto)
|
|
+{
|
|
+ uint32_t delta = fdt_get_max_phandle(fdt);
|
|
+ int ret;
|
|
+
|
|
+ FDT_CHECK_HEADER(fdt);
|
|
+ FDT_CHECK_HEADER(fdto);
|
|
+
|
|
+ ret = overlay_adjust_local_phandles(fdto, delta);
|
|
+ if (ret)
|
|
+ goto err;
|
|
+
|
|
+ ret = overlay_update_local_references(fdto, delta);
|
|
+ if (ret)
|
|
+ goto err;
|
|
+
|
|
+ ret = overlay_fixup_phandles(fdt, fdto);
|
|
+ if (ret)
|
|
+ goto err;
|
|
+
|
|
+ ret = overlay_merge(fdt, fdto);
|
|
+ if (ret)
|
|
+ goto err;
|
|
+
|
|
+ ret = overlay_symbol_update(fdt, fdto);
|
|
+ if (ret)
|
|
+ goto err;
|
|
+
|
|
+ /*
|
|
+ * The overlay has been damaged, erase its magic.
|
|
+ */
|
|
+ fdt_set_magic(fdto, ~0);
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err:
|
|
+ /*
|
|
+ * The overlay might have been damaged, erase its magic.
|
|
+ */
|
|
+ fdt_set_magic(fdto, ~0);
|
|
+
|
|
+ /*
|
|
+ * The base device tree might have been damaged, erase its
|
|
+ * magic.
|
|
+ */
|
|
+ fdt_set_magic(fdt, ~0);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
diff --git a/scripts/dtc/fdt_ro.c b/scripts/dtc/fdt_ro.c
|
|
index 50007f61c..dfb3236da 100644
|
|
--- a/scripts/dtc/fdt_ro.c
|
|
+++ b/scripts/dtc/fdt_ro.c
|
|
@@ -55,12 +55,13 @@
|
|
|
|
#include "libfdt_internal.h"
|
|
|
|
-static int _fdt_nodename_eq(const void *fdt, int offset,
|
|
+static int fdt_nodename_eq_(const void *fdt, int offset,
|
|
const char *s, int len)
|
|
{
|
|
- const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
|
|
+ int olen;
|
|
+ const char *p = fdt_get_name(fdt, offset, &olen);
|
|
|
|
- if (! p)
|
|
+ if (!p || olen < len)
|
|
/* short match */
|
|
return 0;
|
|
|
|
@@ -80,7 +81,7 @@ const char *fdt_string(const void *fdt, int stroffset)
|
|
return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
|
|
}
|
|
|
|
-static int _fdt_string_eq(const void *fdt, int stroffset,
|
|
+static int fdt_string_eq_(const void *fdt, int stroffset,
|
|
const char *s, int len)
|
|
{
|
|
const char *p = fdt_string(fdt, stroffset);
|
|
@@ -88,11 +89,37 @@ static int _fdt_string_eq(const void *fdt, int stroffset,
|
|
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)
|
|
{
|
|
FDT_CHECK_HEADER(fdt);
|
|
- *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
|
|
- *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
|
|
+ *address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
|
|
+ *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
|
|
return 0;
|
|
}
|
|
|
|
@@ -100,12 +127,12 @@ int fdt_num_mem_rsv(const void *fdt)
|
|
{
|
|
int i = 0;
|
|
|
|
- while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
|
|
+ while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
|
|
i++;
|
|
return i;
|
|
}
|
|
|
|
-static int _nextprop(const void *fdt, int offset)
|
|
+static int nextprop_(const void *fdt, int offset)
|
|
{
|
|
uint32_t tag;
|
|
int nextoffset;
|
|
@@ -140,7 +167,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
|
|
(offset >= 0) && (depth >= 0);
|
|
offset = fdt_next_node(fdt, offset, &depth))
|
|
if ((depth == 1)
|
|
- && _fdt_nodename_eq(fdt, offset, name, namelen))
|
|
+ && fdt_nodename_eq_(fdt, offset, name, namelen))
|
|
return offset;
|
|
|
|
if (depth < 0)
|
|
@@ -154,9 +181,9 @@ int fdt_subnode_offset(const void *fdt, int parentoffset,
|
|
return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
|
|
}
|
|
|
|
-int fdt_path_offset(const void *fdt, const char *path)
|
|
+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
|
|
{
|
|
- const char *end = path + strlen(path);
|
|
+ const char *end = path + namelen;
|
|
const char *p = path;
|
|
int offset = 0;
|
|
|
|
@@ -164,7 +191,7 @@ int fdt_path_offset(const void *fdt, const char *path)
|
|
|
|
/* see if we have an alias */
|
|
if (*path != '/') {
|
|
- const char *q = strchr(path, '/');
|
|
+ const char *q = memchr(path, '/', end - p);
|
|
|
|
if (!q)
|
|
q = end;
|
|
@@ -177,14 +204,15 @@ int fdt_path_offset(const void *fdt, const char *path)
|
|
p = q;
|
|
}
|
|
|
|
- while (*p) {
|
|
+ while (p < end) {
|
|
const char *q;
|
|
|
|
- while (*p == '/')
|
|
+ while (*p == '/') {
|
|
p++;
|
|
- if (! *p)
|
|
- return offset;
|
|
- q = strchr(p, '/');
|
|
+ if (p == end)
|
|
+ return offset;
|
|
+ }
|
|
+ q = memchr(p, '/', end - p);
|
|
if (! q)
|
|
q = end;
|
|
|
|
@@ -198,19 +226,42 @@ int fdt_path_offset(const void *fdt, const char *path)
|
|
return offset;
|
|
}
|
|
|
|
+int fdt_path_offset(const void *fdt, const char *path)
|
|
+{
|
|
+ return fdt_path_offset_namelen(fdt, path, strlen(path));
|
|
+}
|
|
+
|
|
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
|
|
{
|
|
- const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
|
|
+ const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
|
|
+ const char *nameptr;
|
|
int err;
|
|
|
|
if (((err = fdt_check_header(fdt)) != 0)
|
|
- || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
|
|
+ || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
|
|
goto fail;
|
|
|
|
+ nameptr = nh->name;
|
|
+
|
|
+ if (fdt_version(fdt) < 0x10) {
|
|
+ /*
|
|
+ * For old FDT versions, match the naming conventions of V16:
|
|
+ * give only the leaf name (after all /). The actual tree
|
|
+ * contents are loosely checked.
|
|
+ */
|
|
+ const char *leaf;
|
|
+ leaf = strrchr(nameptr, '/');
|
|
+ if (leaf == NULL) {
|
|
+ err = -FDT_ERR_BADSTRUCTURE;
|
|
+ goto fail;
|
|
+ }
|
|
+ nameptr = leaf+1;
|
|
+ }
|
|
+
|
|
if (len)
|
|
- *len = strlen(nh->name);
|
|
+ *len = strlen(nameptr);
|
|
|
|
- return nh->name;
|
|
+ return nameptr;
|
|
|
|
fail:
|
|
if (len)
|
|
@@ -222,34 +273,34 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset)
|
|
{
|
|
int offset;
|
|
|
|
- if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
|
|
+ if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
|
|
return offset;
|
|
|
|
- return _nextprop(fdt, offset);
|
|
+ return nextprop_(fdt, offset);
|
|
}
|
|
|
|
int fdt_next_property_offset(const void *fdt, int offset)
|
|
{
|
|
- if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
|
|
+ if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0)
|
|
return offset;
|
|
|
|
- return _nextprop(fdt, offset);
|
|
+ return nextprop_(fdt, offset);
|
|
}
|
|
|
|
-const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
|
|
- int offset,
|
|
- int *lenp)
|
|
+static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
|
|
+ int offset,
|
|
+ int *lenp)
|
|
{
|
|
int err;
|
|
const struct fdt_property *prop;
|
|
|
|
- if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
|
|
+ if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
|
|
if (lenp)
|
|
*lenp = err;
|
|
return NULL;
|
|
}
|
|
|
|
- prop = _fdt_offset_ptr(fdt, offset);
|
|
+ prop = fdt_offset_ptr_(fdt, offset);
|
|
|
|
if (lenp)
|
|
*lenp = fdt32_to_cpu(prop->len);
|
|
@@ -257,23 +308,44 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
|
|
return prop;
|
|
}
|
|
|
|
-const struct fdt_property *fdt_get_property_namelen(const void *fdt,
|
|
- int offset,
|
|
- const char *name,
|
|
- int namelen, int *lenp)
|
|
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
|
|
+ int offset,
|
|
+ int *lenp)
|
|
+{
|
|
+ /* Prior to version 16, properties may need realignment
|
|
+ * and this API does not work. fdt_getprop_*() will, however. */
|
|
+
|
|
+ if (fdt_version(fdt) < 0x10) {
|
|
+ if (lenp)
|
|
+ *lenp = -FDT_ERR_BADVERSION;
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return fdt_get_property_by_offset_(fdt, offset, lenp);
|
|
+}
|
|
+
|
|
+static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
|
|
+ int offset,
|
|
+ const char *name,
|
|
+ int namelen,
|
|
+ int *lenp,
|
|
+ int *poffset)
|
|
{
|
|
for (offset = fdt_first_property_offset(fdt, offset);
|
|
(offset >= 0);
|
|
(offset = fdt_next_property_offset(fdt, offset))) {
|
|
const struct fdt_property *prop;
|
|
|
|
- if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
|
|
+ if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
|
|
offset = -FDT_ERR_INTERNAL;
|
|
break;
|
|
}
|
|
- if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
|
|
- name, namelen))
|
|
+ if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
|
|
+ name, namelen)) {
|
|
+ if (poffset)
|
|
+ *poffset = offset;
|
|
return prop;
|
|
+ }
|
|
}
|
|
|
|
if (lenp)
|
|
@@ -281,6 +353,25 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
|
|
return NULL;
|
|
}
|
|
|
|
+
|
|
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
|
|
+ int offset,
|
|
+ const char *name,
|
|
+ int namelen, int *lenp)
|
|
+{
|
|
+ /* Prior to version 16, properties may need realignment
|
|
+ * and this API does not work. fdt_getprop_*() will, however. */
|
|
+ if (fdt_version(fdt) < 0x10) {
|
|
+ if (lenp)
|
|
+ *lenp = -FDT_ERR_BADVERSION;
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
|
|
+ NULL);
|
|
+}
|
|
+
|
|
+
|
|
const struct fdt_property *fdt_get_property(const void *fdt,
|
|
int nodeoffset,
|
|
const char *name, int *lenp)
|
|
@@ -292,12 +383,18 @@ const struct fdt_property *fdt_get_property(const void *fdt,
|
|
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
|
const char *name, int namelen, int *lenp)
|
|
{
|
|
+ int poffset;
|
|
const struct fdt_property *prop;
|
|
|
|
- prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
|
|
- if (! prop)
|
|
+ prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
|
|
+ &poffset);
|
|
+ if (!prop)
|
|
return NULL;
|
|
|
|
+ /* Handle realignment */
|
|
+ if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
|
|
+ fdt32_to_cpu(prop->len) >= 8)
|
|
+ return prop->data + 4;
|
|
return prop->data;
|
|
}
|
|
|
|
@@ -306,11 +403,16 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
|
|
{
|
|
const struct fdt_property *prop;
|
|
|
|
- prop = fdt_get_property_by_offset(fdt, offset, lenp);
|
|
+ prop = fdt_get_property_by_offset_(fdt, offset, lenp);
|
|
if (!prop)
|
|
return NULL;
|
|
if (namep)
|
|
*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
|
|
+
|
|
+ /* Handle realignment */
|
|
+ if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
|
|
+ fdt32_to_cpu(prop->len) >= 8)
|
|
+ return prop->data + 4;
|
|
return prop->data;
|
|
}
|
|
|
|
@@ -532,6 +634,106 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
|
|
return 0;
|
|
}
|
|
|
|
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
|
|
+{
|
|
+ const char *list, *end;
|
|
+ int length, count = 0;
|
|
+
|
|
+ list = fdt_getprop(fdt, nodeoffset, property, &length);
|
|
+ if (!list)
|
|
+ return length;
|
|
+
|
|
+ end = list + length;
|
|
+
|
|
+ while (list < end) {
|
|
+ length = strnlen(list, end - list) + 1;
|
|
+
|
|
+ /* Abort if the last string isn't properly NUL-terminated. */
|
|
+ if (list + length > end)
|
|
+ return -FDT_ERR_BADVALUE;
|
|
+
|
|
+ list += length;
|
|
+ count++;
|
|
+ }
|
|
+
|
|
+ return count;
|
|
+}
|
|
+
|
|
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
|
|
+ const char *string)
|
|
+{
|
|
+ int length, len, idx = 0;
|
|
+ const char *list, *end;
|
|
+
|
|
+ list = fdt_getprop(fdt, nodeoffset, property, &length);
|
|
+ if (!list)
|
|
+ return length;
|
|
+
|
|
+ len = strlen(string) + 1;
|
|
+ end = list + length;
|
|
+
|
|
+ while (list < end) {
|
|
+ length = strnlen(list, end - list) + 1;
|
|
+
|
|
+ /* Abort if the last string isn't properly NUL-terminated. */
|
|
+ if (list + length > end)
|
|
+ return -FDT_ERR_BADVALUE;
|
|
+
|
|
+ if (length == len && memcmp(list, string, length) == 0)
|
|
+ return idx;
|
|
+
|
|
+ list += length;
|
|
+ idx++;
|
|
+ }
|
|
+
|
|
+ return -FDT_ERR_NOTFOUND;
|
|
+}
|
|
+
|
|
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
|
|
+ const char *property, int idx,
|
|
+ int *lenp)
|
|
+{
|
|
+ const char *list, *end;
|
|
+ int length;
|
|
+
|
|
+ list = fdt_getprop(fdt, nodeoffset, property, &length);
|
|
+ if (!list) {
|
|
+ if (lenp)
|
|
+ *lenp = length;
|
|
+
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ end = list + length;
|
|
+
|
|
+ while (list < end) {
|
|
+ length = strnlen(list, end - list) + 1;
|
|
+
|
|
+ /* Abort if the last string isn't properly NUL-terminated. */
|
|
+ if (list + length > end) {
|
|
+ if (lenp)
|
|
+ *lenp = -FDT_ERR_BADVALUE;
|
|
+
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (idx == 0) {
|
|
+ if (lenp)
|
|
+ *lenp = length - 1;
|
|
+
|
|
+ return list;
|
|
+ }
|
|
+
|
|
+ list += length;
|
|
+ idx--;
|
|
+ }
|
|
+
|
|
+ if (lenp)
|
|
+ *lenp = -FDT_ERR_NOTFOUND;
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
int fdt_node_check_compatible(const void *fdt, int nodeoffset,
|
|
const char *compatible)
|
|
{
|
|
@@ -541,10 +743,8 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
|
|
prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
|
|
if (!prop)
|
|
return len;
|
|
- if (fdt_stringlist_contains(prop, len, compatible))
|
|
- return 0;
|
|
- else
|
|
- return 1;
|
|
+
|
|
+ return !fdt_stringlist_contains(prop, len, compatible);
|
|
}
|
|
|
|
int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
|
|
diff --git a/scripts/dtc/fdt_rw.c b/scripts/dtc/fdt_rw.c
|
|
index 70adec6c3..9b829051e 100644
|
|
--- a/scripts/dtc/fdt_rw.c
|
|
+++ b/scripts/dtc/fdt_rw.c
|
|
@@ -55,8 +55,8 @@
|
|
|
|
#include "libfdt_internal.h"
|
|
|
|
-static int _fdt_blocks_misordered(const void *fdt,
|
|
- int mem_rsv_size, int struct_size)
|
|
+static int fdt_blocks_misordered_(const void *fdt,
|
|
+ int mem_rsv_size, int struct_size)
|
|
{
|
|
return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
|
|
|| (fdt_off_dt_struct(fdt) <
|
|
@@ -67,13 +67,13 @@ static int _fdt_blocks_misordered(const void *fdt,
|
|
(fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
|
|
}
|
|
|
|
-static int _fdt_rw_check_header(void *fdt)
|
|
+static int fdt_rw_check_header_(void *fdt)
|
|
{
|
|
FDT_CHECK_HEADER(fdt);
|
|
|
|
if (fdt_version(fdt) < 17)
|
|
return -FDT_ERR_BADVERSION;
|
|
- if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
|
|
+ if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
|
|
fdt_size_dt_struct(fdt)))
|
|
return -FDT_ERR_BADLAYOUT;
|
|
if (fdt_version(fdt) > 17)
|
|
@@ -84,35 +84,37 @@ static int _fdt_rw_check_header(void *fdt)
|
|
|
|
#define FDT_RW_CHECK_HEADER(fdt) \
|
|
{ \
|
|
- int __err; \
|
|
- if ((__err = _fdt_rw_check_header(fdt)) != 0) \
|
|
- return __err; \
|
|
+ int err_; \
|
|
+ if ((err_ = fdt_rw_check_header_(fdt)) != 0) \
|
|
+ return err_; \
|
|
}
|
|
|
|
-static inline int _fdt_data_size(void *fdt)
|
|
+static inline int fdt_data_size_(void *fdt)
|
|
{
|
|
return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
|
|
}
|
|
|
|
-static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
|
|
+static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
|
|
{
|
|
char *p = splicepoint;
|
|
- char *end = (char *)fdt + _fdt_data_size(fdt);
|
|
+ char *end = (char *)fdt + fdt_data_size_(fdt);
|
|
|
|
if (((p + oldlen) < p) || ((p + oldlen) > end))
|
|
return -FDT_ERR_BADOFFSET;
|
|
+ if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
|
|
+ return -FDT_ERR_BADOFFSET;
|
|
if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
|
|
return -FDT_ERR_NOSPACE;
|
|
memmove(p + newlen, p + oldlen, end - p - oldlen);
|
|
return 0;
|
|
}
|
|
|
|
-static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
|
|
+static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p,
|
|
int oldn, int newn)
|
|
{
|
|
int delta = (newn - oldn) * sizeof(*p);
|
|
int err;
|
|
- err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
|
|
+ err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
|
|
if (err)
|
|
return err;
|
|
fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
|
|
@@ -120,13 +122,13 @@ static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
|
|
return 0;
|
|
}
|
|
|
|
-static int _fdt_splice_struct(void *fdt, void *p,
|
|
+static int fdt_splice_struct_(void *fdt, void *p,
|
|
int oldlen, int newlen)
|
|
{
|
|
int delta = newlen - oldlen;
|
|
int err;
|
|
|
|
- if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
|
|
+ if ((err = fdt_splice_(fdt, p, oldlen, newlen)))
|
|
return err;
|
|
|
|
fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
|
|
@@ -134,20 +136,20 @@ static int _fdt_splice_struct(void *fdt, void *p,
|
|
return 0;
|
|
}
|
|
|
|
-static int _fdt_splice_string(void *fdt, int newlen)
|
|
+static int fdt_splice_string_(void *fdt, int newlen)
|
|
{
|
|
void *p = (char *)fdt
|
|
+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
|
|
int err;
|
|
|
|
- if ((err = _fdt_splice(fdt, p, 0, newlen)))
|
|
+ if ((err = fdt_splice_(fdt, p, 0, newlen)))
|
|
return err;
|
|
|
|
fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
|
|
return 0;
|
|
}
|
|
|
|
-static int _fdt_find_add_string(void *fdt, const char *s)
|
|
+static int fdt_find_add_string_(void *fdt, const char *s)
|
|
{
|
|
char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
|
|
const char *p;
|
|
@@ -155,13 +157,13 @@ static int _fdt_find_add_string(void *fdt, const char *s)
|
|
int len = strlen(s) + 1;
|
|
int err;
|
|
|
|
- p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
|
|
+ p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
|
|
if (p)
|
|
/* found it */
|
|
return (p - strtab);
|
|
|
|
new = strtab + fdt_size_dt_strings(fdt);
|
|
- err = _fdt_splice_string(fdt, len);
|
|
+ err = fdt_splice_string_(fdt, len);
|
|
if (err)
|
|
return err;
|
|
|
|
@@ -176,8 +178,8 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
|
|
|
|
FDT_RW_CHECK_HEADER(fdt);
|
|
|
|
- re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
|
|
- err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
|
|
+ re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
|
|
+ err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
|
|
if (err)
|
|
return err;
|
|
|
|
@@ -188,31 +190,27 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
|
|
|
|
int fdt_del_mem_rsv(void *fdt, int n)
|
|
{
|
|
- struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
|
|
- int err;
|
|
+ struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
|
|
|
|
FDT_RW_CHECK_HEADER(fdt);
|
|
|
|
if (n >= fdt_num_mem_rsv(fdt))
|
|
return -FDT_ERR_NOTFOUND;
|
|
|
|
- err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
|
|
- if (err)
|
|
- return err;
|
|
- return 0;
|
|
+ return fdt_splice_mem_rsv_(fdt, re, 1, 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,
|
|
int len, struct fdt_property **prop)
|
|
{
|
|
int oldlen;
|
|
int err;
|
|
|
|
*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
|
|
- if (! (*prop))
|
|
+ if (!*prop)
|
|
return oldlen;
|
|
|
|
- if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
|
|
+ if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
|
|
FDT_TAGALIGN(len))))
|
|
return err;
|
|
|
|
@@ -220,7 +218,7 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
|
|
return 0;
|
|
}
|
|
|
|
-static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
|
|
+static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
|
|
int len, struct fdt_property **prop)
|
|
{
|
|
int proplen;
|
|
@@ -228,17 +226,17 @@ static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
|
|
int namestroff;
|
|
int err;
|
|
|
|
- if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
|
|
+ if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
|
|
return nextoffset;
|
|
|
|
- namestroff = _fdt_find_add_string(fdt, name);
|
|
+ namestroff = fdt_find_add_string_(fdt, name);
|
|
if (namestroff < 0)
|
|
return namestroff;
|
|
|
|
- *prop = _fdt_offset_ptr_w(fdt, nextoffset);
|
|
+ *prop = fdt_offset_ptr_w_(fdt, nextoffset);
|
|
proplen = sizeof(**prop) + FDT_TAGALIGN(len);
|
|
|
|
- err = _fdt_splice_struct(fdt, *prop, 0, proplen);
|
|
+ err = fdt_splice_struct_(fdt, *prop, 0, proplen);
|
|
if (err)
|
|
return err;
|
|
|
|
@@ -262,7 +260,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
|
|
|
|
newlen = strlen(name);
|
|
|
|
- err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
|
|
+ err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1),
|
|
FDT_TAGALIGN(newlen+1));
|
|
if (err)
|
|
return err;
|
|
@@ -271,21 +269,36 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
|
|
return 0;
|
|
}
|
|
|
|
-int fdt_setprop(void *fdt, int nodeoffset, const char *name,
|
|
- const void *val, int len)
|
|
+int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
|
|
+ int len, void **prop_data)
|
|
{
|
|
struct fdt_property *prop;
|
|
int err;
|
|
|
|
FDT_RW_CHECK_HEADER(fdt);
|
|
|
|
- err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
|
|
+ err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
|
|
if (err == -FDT_ERR_NOTFOUND)
|
|
- err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
|
|
+ err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
|
|
+ if (err)
|
|
+ return err;
|
|
+
|
|
+ *prop_data = prop->data;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
|
|
+ const void *val, int len)
|
|
+{
|
|
+ void *prop_data;
|
|
+ int err;
|
|
+
|
|
+ err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data);
|
|
if (err)
|
|
return err;
|
|
|
|
- memcpy(prop->data, val, len);
|
|
+ if (len)
|
|
+ memcpy(prop_data, val, len);
|
|
return 0;
|
|
}
|
|
|
|
@@ -300,7 +313,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
|
|
prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
|
|
if (prop) {
|
|
newlen = len + oldlen;
|
|
- err = _fdt_splice_struct(fdt, prop->data,
|
|
+ err = fdt_splice_struct_(fdt, prop->data,
|
|
FDT_TAGALIGN(oldlen),
|
|
FDT_TAGALIGN(newlen));
|
|
if (err)
|
|
@@ -308,7 +321,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
|
|
prop->len = cpu_to_fdt32(newlen);
|
|
memcpy(prop->data + oldlen, val, len);
|
|
} else {
|
|
- err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
|
|
+ err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
|
|
if (err)
|
|
return err;
|
|
memcpy(prop->data, val, len);
|
|
@@ -324,11 +337,11 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
|
|
FDT_RW_CHECK_HEADER(fdt);
|
|
|
|
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
|
|
- if (! prop)
|
|
+ if (!prop)
|
|
return len;
|
|
|
|
proplen = sizeof(*prop) + FDT_TAGALIGN(len);
|
|
- return _fdt_splice_struct(fdt, prop, proplen, 0);
|
|
+ return fdt_splice_struct_(fdt, prop, proplen, 0);
|
|
}
|
|
|
|
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
|
@@ -356,10 +369,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
|
tag = fdt_next_tag(fdt, offset, &nextoffset);
|
|
} while ((tag == FDT_PROP) || (tag == FDT_NOP));
|
|
|
|
- nh = _fdt_offset_ptr_w(fdt, offset);
|
|
+ nh = fdt_offset_ptr_w_(fdt, offset);
|
|
nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
|
|
|
|
- err = _fdt_splice_struct(fdt, nh, 0, nodelen);
|
|
+ err = fdt_splice_struct_(fdt, nh, 0, nodelen);
|
|
if (err)
|
|
return err;
|
|
|
|
@@ -383,15 +396,15 @@ int fdt_del_node(void *fdt, int nodeoffset)
|
|
|
|
FDT_RW_CHECK_HEADER(fdt);
|
|
|
|
- endoffset = _fdt_node_end_offset(fdt, nodeoffset);
|
|
+ endoffset = fdt_node_end_offset_(fdt, nodeoffset);
|
|
if (endoffset < 0)
|
|
return endoffset;
|
|
|
|
- return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
|
|
+ return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset),
|
|
endoffset - nodeoffset, 0);
|
|
}
|
|
|
|
-static void _fdt_packblocks(const char *old, char *new,
|
|
+static void fdt_packblocks_(const char *old, char *new,
|
|
int mem_rsv_size, int struct_size)
|
|
{
|
|
int mem_rsv_off, struct_off, strings_off;
|
|
@@ -437,7 +450,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
|
|
return struct_size;
|
|
}
|
|
|
|
- if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
|
|
+ if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
|
|
/* no further work necessary */
|
|
err = fdt_move(fdt, buf, bufsize);
|
|
if (err)
|
|
@@ -465,7 +478,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
|
|
return -FDT_ERR_NOSPACE;
|
|
}
|
|
|
|
- _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
|
|
+ fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size);
|
|
memmove(buf, tmp, newsize);
|
|
|
|
fdt_set_magic(buf, FDT_MAGIC);
|
|
@@ -485,8 +498,8 @@ int fdt_pack(void *fdt)
|
|
|
|
mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
|
|
* sizeof(struct fdt_reserve_entry);
|
|
- _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
|
|
- fdt_set_totalsize(fdt, _fdt_data_size(fdt));
|
|
+ fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
|
|
+ fdt_set_totalsize(fdt, fdt_data_size_(fdt));
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/scripts/dtc/fdt_strerror.c b/scripts/dtc/fdt_strerror.c
|
|
index e6c3ceee8..9677a1887 100644
|
|
--- a/scripts/dtc/fdt_strerror.c
|
|
+++ b/scripts/dtc/fdt_strerror.c
|
|
@@ -69,6 +69,7 @@ static struct fdt_errtabent fdt_errtable[] = {
|
|
|
|
FDT_ERRTABENT(FDT_ERR_BADOFFSET),
|
|
FDT_ERRTABENT(FDT_ERR_BADPATH),
|
|
+ FDT_ERRTABENT(FDT_ERR_BADPHANDLE),
|
|
FDT_ERRTABENT(FDT_ERR_BADSTATE),
|
|
|
|
FDT_ERRTABENT(FDT_ERR_TRUNCATED),
|
|
@@ -76,6 +77,11 @@ static struct fdt_errtabent fdt_errtable[] = {
|
|
FDT_ERRTABENT(FDT_ERR_BADVERSION),
|
|
FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
|
|
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]))
|
|
|
|
diff --git a/scripts/dtc/fdt_sw.c b/scripts/dtc/fdt_sw.c
|
|
index 6a804859f..6d33cc29d 100644
|
|
--- a/scripts/dtc/fdt_sw.c
|
|
+++ b/scripts/dtc/fdt_sw.c
|
|
@@ -55,7 +55,7 @@
|
|
|
|
#include "libfdt_internal.h"
|
|
|
|
-static int _fdt_sw_check_header(void *fdt)
|
|
+static int fdt_sw_check_header_(void *fdt)
|
|
{
|
|
if (fdt_magic(fdt) != FDT_SW_MAGIC)
|
|
return -FDT_ERR_BADMAGIC;
|
|
@@ -66,11 +66,11 @@ static int _fdt_sw_check_header(void *fdt)
|
|
#define FDT_SW_CHECK_HEADER(fdt) \
|
|
{ \
|
|
int err; \
|
|
- if ((err = _fdt_sw_check_header(fdt)) != 0) \
|
|
+ if ((err = fdt_sw_check_header_(fdt)) != 0) \
|
|
return err; \
|
|
}
|
|
|
|
-static void *_fdt_grab_space(void *fdt, size_t len)
|
|
+static void *fdt_grab_space_(void *fdt, size_t len)
|
|
{
|
|
int offset = fdt_size_dt_struct(fdt);
|
|
int spaceleft;
|
|
@@ -82,7 +82,7 @@ static void *_fdt_grab_space(void *fdt, size_t len)
|
|
return NULL;
|
|
|
|
fdt_set_size_dt_struct(fdt, offset + len);
|
|
- return _fdt_offset_ptr_w(fdt, offset);
|
|
+ return fdt_offset_ptr_w_(fdt, offset);
|
|
}
|
|
|
|
int fdt_create(void *buf, int bufsize)
|
|
@@ -174,7 +174,7 @@ int fdt_begin_node(void *fdt, const char *name)
|
|
|
|
FDT_SW_CHECK_HEADER(fdt);
|
|
|
|
- nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
|
|
+ nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
|
|
if (! nh)
|
|
return -FDT_ERR_NOSPACE;
|
|
|
|
@@ -189,7 +189,7 @@ int fdt_end_node(void *fdt)
|
|
|
|
FDT_SW_CHECK_HEADER(fdt);
|
|
|
|
- en = _fdt_grab_space(fdt, FDT_TAGSIZE);
|
|
+ en = fdt_grab_space_(fdt, FDT_TAGSIZE);
|
|
if (! en)
|
|
return -FDT_ERR_NOSPACE;
|
|
|
|
@@ -197,7 +197,7 @@ int fdt_end_node(void *fdt)
|
|
return 0;
|
|
}
|
|
|
|
-static int _fdt_find_add_string(void *fdt, const char *s)
|
|
+static int fdt_find_add_string_(void *fdt, const char *s)
|
|
{
|
|
char *strtab = (char *)fdt + fdt_totalsize(fdt);
|
|
const char *p;
|
|
@@ -205,7 +205,7 @@ static int _fdt_find_add_string(void *fdt, const char *s)
|
|
int len = strlen(s) + 1;
|
|
int struct_top, offset;
|
|
|
|
- p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
|
|
+ p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
|
|
if (p)
|
|
return p - strtab;
|
|
|
|
@@ -220,25 +220,37 @@ static int _fdt_find_add_string(void *fdt, const char *s)
|
|
return offset;
|
|
}
|
|
|
|
-int fdt_property(void *fdt, const char *name, const void *val, int len)
|
|
+int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
|
|
{
|
|
struct fdt_property *prop;
|
|
int nameoff;
|
|
|
|
FDT_SW_CHECK_HEADER(fdt);
|
|
|
|
- nameoff = _fdt_find_add_string(fdt, name);
|
|
+ nameoff = fdt_find_add_string_(fdt, name);
|
|
if (nameoff == 0)
|
|
return -FDT_ERR_NOSPACE;
|
|
|
|
- prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
|
|
+ prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
|
|
if (! prop)
|
|
return -FDT_ERR_NOSPACE;
|
|
|
|
prop->tag = cpu_to_fdt32(FDT_PROP);
|
|
prop->nameoff = cpu_to_fdt32(nameoff);
|
|
prop->len = cpu_to_fdt32(len);
|
|
- memcpy(prop->data, val, len);
|
|
+ *valp = prop->data;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int fdt_property(void *fdt, const char *name, const void *val, int len)
|
|
+{
|
|
+ void *ptr;
|
|
+ int ret;
|
|
+
|
|
+ ret = fdt_property_placeholder(fdt, name, len, &ptr);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ memcpy(ptr, val, len);
|
|
return 0;
|
|
}
|
|
|
|
@@ -253,7 +265,7 @@ int fdt_finish(void *fdt)
|
|
FDT_SW_CHECK_HEADER(fdt);
|
|
|
|
/* Add terminator */
|
|
- end = _fdt_grab_space(fdt, sizeof(*end));
|
|
+ end = fdt_grab_space_(fdt, sizeof(*end));
|
|
if (! end)
|
|
return -FDT_ERR_NOSPACE;
|
|
*end = cpu_to_fdt32(FDT_END);
|
|
@@ -269,7 +281,7 @@ int fdt_finish(void *fdt)
|
|
while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
|
|
if (tag == FDT_PROP) {
|
|
struct fdt_property *prop =
|
|
- _fdt_offset_ptr_w(fdt, offset);
|
|
+ fdt_offset_ptr_w_(fdt, offset);
|
|
int nameoff;
|
|
|
|
nameoff = fdt32_to_cpu(prop->nameoff);
|
|
diff --git a/scripts/dtc/fdt_wip.c b/scripts/dtc/fdt_wip.c
|
|
index c5bbb68d3..534c1cbbb 100644
|
|
--- a/scripts/dtc/fdt_wip.c
|
|
+++ b/scripts/dtc/fdt_wip.c
|
|
@@ -55,24 +55,45 @@
|
|
|
|
#include "libfdt_internal.h"
|
|
|
|
+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
|
|
+ const char *name, int namelen,
|
|
+ uint32_t idx, const void *val,
|
|
+ int len)
|
|
+{
|
|
+ void *propval;
|
|
+ int 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)
|
|
{
|
|
- void *propval;
|
|
+ const void *propval;
|
|
int proplen;
|
|
|
|
- propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
|
|
- if (! propval)
|
|
+ propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
|
|
+ if (!propval)
|
|
return proplen;
|
|
|
|
if (proplen != len)
|
|
return -FDT_ERR_NOSPACE;
|
|
|
|
- memcpy(propval, val, len);
|
|
- return 0;
|
|
+ return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name,
|
|
+ strlen(name), 0,
|
|
+ val, len);
|
|
}
|
|
|
|
-static void _fdt_nop_region(void *start, int len)
|
|
+static void fdt_nop_region_(void *start, int len)
|
|
{
|
|
fdt32_t *p;
|
|
|
|
@@ -86,15 +107,15 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
|
|
int len;
|
|
|
|
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
|
|
- if (! prop)
|
|
+ if (!prop)
|
|
return len;
|
|
|
|
- _fdt_nop_region(prop, len + sizeof(*prop));
|
|
+ fdt_nop_region_(prop, len + sizeof(*prop));
|
|
|
|
return 0;
|
|
}
|
|
|
|
-int _fdt_node_end_offset(void *fdt, int offset)
|
|
+int fdt_node_end_offset_(void *fdt, int offset)
|
|
{
|
|
int depth = 0;
|
|
|
|
@@ -108,11 +129,11 @@ int fdt_nop_node(void *fdt, int nodeoffset)
|
|
{
|
|
int endoffset;
|
|
|
|
- endoffset = _fdt_node_end_offset(fdt, nodeoffset);
|
|
+ endoffset = fdt_node_end_offset_(fdt, nodeoffset);
|
|
if (endoffset < 0)
|
|
return endoffset;
|
|
|
|
- _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
|
|
+ fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0),
|
|
endoffset - nodeoffset);
|
|
return 0;
|
|
}
|
|
diff --git a/scripts/dtc/fdtdump.c b/scripts/dtc/fdtdump.c
|
|
index 95a6a2016..7d460a50b 100644
|
|
--- a/scripts/dtc/fdtdump.c
|
|
+++ b/scripts/dtc/fdtdump.c
|
|
@@ -1,17 +1,16 @@
|
|
+// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
|
|
*/
|
|
|
|
-#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
-#include <libfdt.h>
|
|
-#include <libfdt_env.h>
|
|
#include <fdt.h>
|
|
+#include <libfdt_env.h>
|
|
|
|
#include "util.h"
|
|
|
|
@@ -19,29 +18,33 @@
|
|
#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
|
|
#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4)))
|
|
|
|
-static const char *tagname(uint32_t tag)
|
|
+static void print_data(const char *data, int len)
|
|
{
|
|
- static const char * const names[] = {
|
|
-#define TN(t) [t] = #t
|
|
- TN(FDT_BEGIN_NODE),
|
|
- TN(FDT_END_NODE),
|
|
- TN(FDT_PROP),
|
|
- TN(FDT_NOP),
|
|
- TN(FDT_END),
|
|
-#undef TN
|
|
- };
|
|
- if (tag < ARRAY_SIZE(names))
|
|
- if (names[tag])
|
|
- return names[tag];
|
|
- return "FDT_???";
|
|
+ int i;
|
|
+ const char *p = data;
|
|
+
|
|
+ /* no data, don't print */
|
|
+ if (len == 0)
|
|
+ return;
|
|
+
|
|
+ if (util_is_printable_string(data, len)) {
|
|
+ printf(" = \"%s\"", (const char *)data);
|
|
+ } else if ((len % 4) == 0) {
|
|
+ printf(" = <");
|
|
+ for (i = 0; i < len; i += 4)
|
|
+ printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)),
|
|
+ i < (len - 4) ? " " : "");
|
|
+ printf(">");
|
|
+ } else {
|
|
+ printf(" = [");
|
|
+ for (i = 0; i < len; i++)
|
|
+ printf("%02x%s", *p++, i < len - 1 ? " " : "");
|
|
+ printf("]");
|
|
+ }
|
|
}
|
|
|
|
-#define dumpf(fmt, args...) \
|
|
- do { if (debug) printf("// " fmt, ## args); } while (0)
|
|
-
|
|
-static void dump_blob(void *blob, bool debug)
|
|
+static void dump_blob(void *blob)
|
|
{
|
|
- uintptr_t blob_off = (uintptr_t)blob;
|
|
struct fdt_header *bph = blob;
|
|
uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
|
|
uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
|
|
@@ -88,15 +91,14 @@ static void dump_blob(void *blob, bool debug)
|
|
if (addr == 0 && size == 0)
|
|
break;
|
|
|
|
- printf("/memreserve/ %#llx %#llx;\n",
|
|
+ printf("/memreserve/ %llx %llx;\n",
|
|
(unsigned long long)addr, (unsigned long long)size);
|
|
}
|
|
|
|
p = p_struct;
|
|
while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
|
|
|
|
- dumpf("%04zx: tag: 0x%08x (%s)\n",
|
|
- (uintptr_t)p - blob_off - 4, tag, tagname(tag));
|
|
+ /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
|
|
|
|
if (tag == FDT_BEGIN_NODE) {
|
|
s = p;
|
|
@@ -135,93 +137,27 @@ static void dump_blob(void *blob, bool debug)
|
|
|
|
p = PALIGN(p + sz, 4);
|
|
|
|
- dumpf("%04zx: string: %s\n", (uintptr_t)s - blob_off, s);
|
|
- dumpf("%04zx: value\n", (uintptr_t)t - blob_off);
|
|
printf("%*s%s", depth * shift, "", s);
|
|
- utilfdt_print_data(t, sz);
|
|
+ print_data(t, sz);
|
|
printf(";\n");
|
|
}
|
|
}
|
|
|
|
-/* Usage related data. */
|
|
-static const char usage_synopsis[] = "fdtdump [options] <file>";
|
|
-static const char usage_short_opts[] = "ds" USAGE_COMMON_SHORT_OPTS;
|
|
-static struct option const usage_long_opts[] = {
|
|
- {"debug", no_argument, NULL, 'd'},
|
|
- {"scan", no_argument, NULL, 's'},
|
|
- USAGE_COMMON_LONG_OPTS
|
|
-};
|
|
-static const char * const usage_opts_help[] = {
|
|
- "Dump debug information while decoding the file",
|
|
- "Scan for an embedded fdt in file",
|
|
- USAGE_COMMON_OPTS_HELP
|
|
-};
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
- int opt;
|
|
- const char *file;
|
|
char *buf;
|
|
- bool debug = false;
|
|
- bool scan = false;
|
|
- off_t len;
|
|
-
|
|
- while ((opt = util_getopt_long()) != EOF) {
|
|
- switch (opt) {
|
|
- case_USAGE_COMMON_FLAGS
|
|
|
|
- case 'd':
|
|
- debug = true;
|
|
- break;
|
|
- case 's':
|
|
- scan = true;
|
|
- break;
|
|
- }
|
|
- }
|
|
- if (optind != argc - 1)
|
|
- usage("missing input filename");
|
|
- file = argv[optind];
|
|
-
|
|
- buf = utilfdt_read_len(file, &len);
|
|
- if (!buf)
|
|
- die("could not read: %s\n", file);
|
|
-
|
|
- /* try and locate an embedded fdt in a bigger blob */
|
|
- if (scan) {
|
|
- unsigned char smagic[4];
|
|
- char *p = buf;
|
|
- char *endp = buf + len;
|
|
-
|
|
- fdt_set_magic(smagic, FDT_MAGIC);
|
|
-
|
|
- /* poor man's memmem */
|
|
- while (true) {
|
|
- p = memchr(p, smagic[0], endp - p - 4);
|
|
- if (!p)
|
|
- break;
|
|
- if (fdt_magic(p) == FDT_MAGIC) {
|
|
- /* try and validate the main struct */
|
|
- off_t this_len = endp - p;
|
|
- fdt32_t max_version = 17;
|
|
- if (fdt_version(p) <= max_version &&
|
|
- fdt_last_comp_version(p) < max_version &&
|
|
- fdt_totalsize(p) < this_len &&
|
|
- fdt_off_dt_struct(p) < this_len &&
|
|
- fdt_off_dt_strings(p) < this_len)
|
|
- break;
|
|
- if (debug)
|
|
- printf("%s: skipping fdt magic at offset %#zx\n",
|
|
- file, p - buf);
|
|
- }
|
|
- ++p;
|
|
- }
|
|
- if (!p)
|
|
- die("%s: could not locate fdt magic\n", file);
|
|
- printf("%s: found fdt at offset %#zx\n", file, p - buf);
|
|
- buf = p;
|
|
+ if (argc < 2) {
|
|
+ fprintf(stderr, "supply input filename\n");
|
|
+ return 5;
|
|
}
|
|
|
|
- dump_blob(buf, debug);
|
|
+ buf = utilfdt_read(argv[1]);
|
|
+ if (buf)
|
|
+ dump_blob(buf);
|
|
+ else
|
|
+ return 10;
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/scripts/dtc/fdtget.c b/scripts/dtc/fdtget.c
|
|
index 437741922..c2fbab2a5 100644
|
|
--- a/scripts/dtc/fdtget.c
|
|
+++ b/scripts/dtc/fdtget.c
|
|
@@ -277,33 +277,33 @@ static int do_fdtget(struct display_info *disp, const char *filename,
|
|
return 0;
|
|
}
|
|
|
|
-/* Usage related data. */
|
|
-static const char usage_synopsis[] =
|
|
- "read values from device tree\n"
|
|
+static const char *usage_msg =
|
|
+ "fdtget - read values from device tree\n"
|
|
+ "\n"
|
|
+ "Each value is printed on a new line.\n\n"
|
|
+ "Usage:\n"
|
|
" fdtget <options> <dt file> [<node> <property>]...\n"
|
|
" fdtget -p <options> <dt file> [<node> ]...\n"
|
|
- "\n"
|
|
- "Each value is printed on a new line.\n"
|
|
+ "Options:\n"
|
|
+ "\t-t <type>\tType of data\n"
|
|
+ "\t-p\t\tList properties for each node\n"
|
|
+ "\t-l\t\tList subnodes for each node\n"
|
|
+ "\t-d\t\tDefault value to display when the property is "
|
|
+ "missing\n"
|
|
+ "\t-h\t\tPrint this help\n\n"
|
|
USAGE_TYPE_MSG;
|
|
-static const char usage_short_opts[] = "t:pld:" USAGE_COMMON_SHORT_OPTS;
|
|
-static struct option const usage_long_opts[] = {
|
|
- {"type", a_argument, NULL, 't'},
|
|
- {"properties", no_argument, NULL, 'p'},
|
|
- {"list", no_argument, NULL, 'l'},
|
|
- {"default", a_argument, NULL, 'd'},
|
|
- USAGE_COMMON_LONG_OPTS,
|
|
-};
|
|
-static const char * const usage_opts_help[] = {
|
|
- "Type of data",
|
|
- "List properties for each node",
|
|
- "List subnodes for each node",
|
|
- "Default value to display when the property is missing",
|
|
- USAGE_COMMON_OPTS_HELP
|
|
-};
|
|
+
|
|
+static void usage(const char *msg)
|
|
+{
|
|
+ if (msg)
|
|
+ fprintf(stderr, "Error: %s\n\n", msg);
|
|
+
|
|
+ fprintf(stderr, "%s", usage_msg);
|
|
+ exit(2);
|
|
+}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
- int opt;
|
|
char *filename = NULL;
|
|
struct display_info disp;
|
|
int args_per_step = 2;
|
|
@@ -312,14 +312,20 @@ int main(int argc, char *argv[])
|
|
memset(&disp, '\0', sizeof(disp));
|
|
disp.size = -1;
|
|
disp.mode = MODE_SHOW_VALUE;
|
|
- while ((opt = util_getopt_long()) != EOF) {
|
|
- switch (opt) {
|
|
- case_USAGE_COMMON_FLAGS
|
|
+ for (;;) {
|
|
+ int c = getopt(argc, argv, "d:hlpt:");
|
|
+ if (c == -1)
|
|
+ break;
|
|
+
|
|
+ switch (c) {
|
|
+ case 'h':
|
|
+ case '?':
|
|
+ usage(NULL);
|
|
|
|
case 't':
|
|
if (utilfdt_decode_type(optarg, &disp.type,
|
|
&disp.size))
|
|
- usage("invalid type string");
|
|
+ usage("Invalid type string");
|
|
break;
|
|
|
|
case 'p':
|
|
@@ -341,7 +347,7 @@ int main(int argc, char *argv[])
|
|
if (optind < argc)
|
|
filename = argv[optind++];
|
|
if (!filename)
|
|
- usage("missing filename");
|
|
+ usage("Missing filename");
|
|
|
|
argv += optind;
|
|
argc -= optind;
|
|
@@ -352,7 +358,7 @@ int main(int argc, char *argv[])
|
|
|
|
/* Check for node, property arguments */
|
|
if (args_per_step == 2 && (argc % 2))
|
|
- usage("must have an even number of arguments");
|
|
+ usage("Must have an even number of arguments");
|
|
|
|
if (do_fdtget(&disp, filename, argv, argc, args_per_step))
|
|
return 1;
|
|
diff --git a/scripts/dtc/fdtput.c b/scripts/dtc/fdtput.c
|
|
index 2a8d67447..f2197f519 100644
|
|
--- a/scripts/dtc/fdtput.c
|
|
+++ b/scripts/dtc/fdtput.c
|
|
@@ -96,7 +96,12 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
|
|
/* enlarge our value buffer by a suitable margin if needed */
|
|
if (upto + len > value_size) {
|
|
value_size = (upto + len) + 500;
|
|
- value = xrealloc(value, value_size);
|
|
+ value = realloc(value, value_size);
|
|
+ if (!value) {
|
|
+ fprintf(stderr, "Out of mmory: cannot alloc "
|
|
+ "%d bytes\n", value_size);
|
|
+ return -1;
|
|
+ }
|
|
}
|
|
|
|
ptr = value + upto;
|
|
@@ -126,59 +131,19 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
|
|
return 0;
|
|
}
|
|
|
|
-#define ALIGN(x) (((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1))
|
|
-
|
|
-static char *_realloc_fdt(char *fdt, int delta)
|
|
-{
|
|
- int new_sz = fdt_totalsize(fdt) + delta;
|
|
- fdt = xrealloc(fdt, new_sz);
|
|
- fdt_open_into(fdt, fdt, new_sz);
|
|
- return fdt;
|
|
-}
|
|
-
|
|
-static char *realloc_node(char *fdt, const char *name)
|
|
-{
|
|
- int delta;
|
|
- /* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */
|
|
- delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1)
|
|
- + FDT_TAGSIZE;
|
|
- return _realloc_fdt(fdt, delta);
|
|
-}
|
|
-
|
|
-static char *realloc_property(char *fdt, int nodeoffset,
|
|
- const char *name, int newlen)
|
|
-{
|
|
- int delta = 0;
|
|
- int oldlen = 0;
|
|
-
|
|
- if (!fdt_get_property(fdt, nodeoffset, name, &oldlen))
|
|
- /* strings + property header */
|
|
- delta = sizeof(struct fdt_property) + strlen(name) + 1;
|
|
-
|
|
- if (newlen > oldlen)
|
|
- /* actual value in off_struct */
|
|
- delta += ALIGN(newlen) - ALIGN(oldlen);
|
|
-
|
|
- return _realloc_fdt(fdt, delta);
|
|
-}
|
|
-
|
|
-static int store_key_value(char **blob, const char *node_name,
|
|
+static int store_key_value(void *blob, const char *node_name,
|
|
const char *property, const char *buf, int len)
|
|
{
|
|
int node;
|
|
int err;
|
|
|
|
- node = fdt_path_offset(*blob, node_name);
|
|
+ node = fdt_path_offset(blob, node_name);
|
|
if (node < 0) {
|
|
report_error(node_name, -1, node);
|
|
return -1;
|
|
}
|
|
|
|
- err = fdt_setprop(*blob, node, property, buf, len);
|
|
- if (err == -FDT_ERR_NOSPACE) {
|
|
- *blob = realloc_property(*blob, node, property, len);
|
|
- err = fdt_setprop(*blob, node, property, buf, len);
|
|
- }
|
|
+ err = fdt_setprop(blob, node, property, buf, len);
|
|
if (err) {
|
|
report_error(property, -1, err);
|
|
return -1;
|
|
@@ -196,7 +161,7 @@ static int store_key_value(char **blob, const char *node_name,
|
|
* @param in_path Path to process
|
|
* @return 0 if ok, -1 on error
|
|
*/
|
|
-static int create_paths(char **blob, const char *in_path)
|
|
+static int create_paths(void *blob, const char *in_path)
|
|
{
|
|
const char *path = in_path;
|
|
const char *sep;
|
|
@@ -212,11 +177,10 @@ static int create_paths(char **blob, const char *in_path)
|
|
if (!sep)
|
|
sep = path + strlen(path);
|
|
|
|
- node = fdt_subnode_offset_namelen(*blob, offset, path,
|
|
+ node = fdt_subnode_offset_namelen(blob, offset, path,
|
|
sep - path);
|
|
if (node == -FDT_ERR_NOTFOUND) {
|
|
- *blob = realloc_node(*blob, path);
|
|
- node = fdt_add_subnode_namelen(*blob, offset, path,
|
|
+ node = fdt_add_subnode_namelen(blob, offset, path,
|
|
sep - path);
|
|
}
|
|
if (node < 0) {
|
|
@@ -239,7 +203,7 @@ static int create_paths(char **blob, const char *in_path)
|
|
* @param node_name Name of node to create
|
|
* @return new node offset if found, or -1 on failure
|
|
*/
|
|
-static int create_node(char **blob, const char *node_name)
|
|
+static int create_node(void *blob, const char *node_name)
|
|
{
|
|
int node = 0;
|
|
char *p;
|
|
@@ -251,17 +215,15 @@ static int create_node(char **blob, const char *node_name)
|
|
}
|
|
*p = '\0';
|
|
|
|
- *blob = realloc_node(*blob, p + 1);
|
|
-
|
|
if (p > node_name) {
|
|
- node = fdt_path_offset(*blob, node_name);
|
|
+ node = fdt_path_offset(blob, node_name);
|
|
if (node < 0) {
|
|
report_error(node_name, -1, node);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
- node = fdt_add_subnode(*blob, node, p + 1);
|
|
+ node = fdt_add_subnode(blob, node, p + 1);
|
|
if (node < 0) {
|
|
report_error(p + 1, -1, node);
|
|
return -1;
|
|
@@ -288,64 +250,66 @@ static int do_fdtput(struct display_info *disp, const char *filename,
|
|
* store them into the property.
|
|
*/
|
|
assert(arg_count >= 2);
|
|
- if (disp->auto_path && create_paths(&blob, *arg))
|
|
+ if (disp->auto_path && create_paths(blob, *arg))
|
|
return -1;
|
|
if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
|
|
- store_key_value(&blob, *arg, arg[1], value, len))
|
|
+ store_key_value(blob, *arg, arg[1], value, len))
|
|
ret = -1;
|
|
break;
|
|
case OPER_CREATE_NODE:
|
|
for (; ret >= 0 && arg_count--; arg++) {
|
|
if (disp->auto_path)
|
|
- ret = create_paths(&blob, *arg);
|
|
+ ret = create_paths(blob, *arg);
|
|
else
|
|
- ret = create_node(&blob, *arg);
|
|
+ ret = create_node(blob, *arg);
|
|
}
|
|
break;
|
|
}
|
|
- if (ret >= 0) {
|
|
- fdt_pack(blob);
|
|
+ if (ret >= 0)
|
|
ret = utilfdt_write(filename, blob);
|
|
- }
|
|
|
|
free(blob);
|
|
return ret;
|
|
}
|
|
|
|
-/* Usage related data. */
|
|
-static const char usage_synopsis[] =
|
|
- "write a property value to a device tree\n"
|
|
- " fdtput <options> <dt file> <node> <property> [<value>...]\n"
|
|
- " fdtput -c <options> <dt file> [<node>...]\n"
|
|
+static const char *usage_msg =
|
|
+ "fdtput - write a property value to a device tree\n"
|
|
"\n"
|
|
"The command line arguments are joined together into a single value.\n"
|
|
+ "\n"
|
|
+ "Usage:\n"
|
|
+ " fdtput <options> <dt file> <node> <property> [<value>...]\n"
|
|
+ " fdtput -c <options> <dt file> [<node>...]\n"
|
|
+ "Options:\n"
|
|
+ "\t-c\t\tCreate nodes if they don't already exist\n"
|
|
+ "\t-p\t\tAutomatically create nodes as needed for the node path\n"
|
|
+ "\t-t <type>\tType of data\n"
|
|
+ "\t-v\t\tVerbose: display each value decoded from command line\n"
|
|
+ "\t-h\t\tPrint this help\n\n"
|
|
USAGE_TYPE_MSG;
|
|
-static const char usage_short_opts[] = "cpt:v" USAGE_COMMON_SHORT_OPTS;
|
|
-static struct option const usage_long_opts[] = {
|
|
- {"create", no_argument, NULL, 'c'},
|
|
- {"auto-path", no_argument, NULL, 'p'},
|
|
- {"type", a_argument, NULL, 't'},
|
|
- {"verbose", no_argument, NULL, 'v'},
|
|
- USAGE_COMMON_LONG_OPTS,
|
|
-};
|
|
-static const char * const usage_opts_help[] = {
|
|
- "Create nodes if they don't already exist",
|
|
- "Automatically create nodes as needed for the node path",
|
|
- "Type of data",
|
|
- "Display each value decoded from command line",
|
|
- USAGE_COMMON_OPTS_HELP
|
|
-};
|
|
+
|
|
+static void usage(const char *msg)
|
|
+{
|
|
+ if (msg)
|
|
+ fprintf(stderr, "Error: %s\n\n", msg);
|
|
+
|
|
+ fprintf(stderr, "%s", usage_msg);
|
|
+ exit(2);
|
|
+}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
- int opt;
|
|
struct display_info disp;
|
|
char *filename = NULL;
|
|
|
|
memset(&disp, '\0', sizeof(disp));
|
|
disp.size = -1;
|
|
disp.oper = OPER_WRITE_PROP;
|
|
- while ((opt = util_getopt_long()) != EOF) {
|
|
+ for (;;) {
|
|
+ int c = getopt(argc, argv, "chpt:v");
|
|
+ if (c == -1)
|
|
+ break;
|
|
+
|
|
/*
|
|
* TODO: add options to:
|
|
* - delete property
|
|
@@ -353,13 +317,15 @@ int main(int argc, char *argv[])
|
|
* - rename node
|
|
* - pack fdt before writing
|
|
* - set amount of free space when writing
|
|
+ * - expand fdt if value doesn't fit
|
|
*/
|
|
- switch (opt) {
|
|
- case_USAGE_COMMON_FLAGS
|
|
-
|
|
+ switch (c) {
|
|
case 'c':
|
|
disp.oper = OPER_CREATE_NODE;
|
|
break;
|
|
+ case 'h':
|
|
+ case '?':
|
|
+ usage(NULL);
|
|
case 'p':
|
|
disp.auto_path = 1;
|
|
break;
|
|
@@ -378,16 +344,16 @@ int main(int argc, char *argv[])
|
|
if (optind < argc)
|
|
filename = argv[optind++];
|
|
if (!filename)
|
|
- usage("missing filename");
|
|
+ usage("Missing filename");
|
|
|
|
argv += optind;
|
|
argc -= optind;
|
|
|
|
if (disp.oper == OPER_WRITE_PROP) {
|
|
if (argc < 1)
|
|
- usage("missing node");
|
|
+ usage("Missing node");
|
|
if (argc < 2)
|
|
- usage("missing property");
|
|
+ usage("Missing property");
|
|
}
|
|
|
|
if (do_fdtput(&disp, filename, argv, argc))
|
|
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
|
|
index bd99fa2d3..8d268fb78 100644
|
|
--- a/scripts/dtc/flattree.c
|
|
+++ b/scripts/dtc/flattree.c
|
|
@@ -49,7 +49,7 @@ static struct version_info {
|
|
|
|
struct emitter {
|
|
void (*cell)(void *, cell_t);
|
|
- void (*string)(void *, char *, int);
|
|
+ void (*string)(void *, const char *, int);
|
|
void (*align)(void *, int);
|
|
void (*data)(void *, struct data);
|
|
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);
|
|
}
|
|
|
|
-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;
|
|
|
|
@@ -144,22 +144,14 @@ static void asm_emit_cell(void *e, cell_t val)
|
|
(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;
|
|
- char c = 0;
|
|
|
|
- if (len != 0) {
|
|
- /* XXX: ewww */
|
|
- c = str[len];
|
|
- str[len] = '\0';
|
|
- }
|
|
-
|
|
- fprintf(f, "\t.string\t\"%s\"\n", str);
|
|
-
|
|
- if (len != 0) {
|
|
- str[len] = c;
|
|
- }
|
|
+ if (len != 0)
|
|
+ fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
|
|
+ else
|
|
+ fprintf(f, "\t.string\t\"%s\"\n", str);
|
|
}
|
|
|
|
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);
|
|
|
|
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);
|
|
}
|
|
|
|
@@ -318,17 +310,16 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
|
|
{
|
|
struct reserve_info *re;
|
|
struct data d = empty_data;
|
|
- static struct fdt_reserve_entry null_re = {0,0};
|
|
int j;
|
|
|
|
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.
|
|
*/
|
|
for (j = 0; j < reservenum; j++) {
|
|
- d = data_append_re(d, &null_re);
|
|
+ d = data_append_re(d, 0, 0);
|
|
}
|
|
|
|
return d;
|
|
@@ -366,7 +357,7 @@ static void make_fdt_header(struct fdt_header *fdt,
|
|
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;
|
|
int i;
|
|
@@ -384,29 +375,36 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version)
|
|
if (!vi)
|
|
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);
|
|
|
|
- reservebuf = flatten_reserve_list(bi->reservelist, vi);
|
|
+ reservebuf = flatten_reserve_list(dti->reservelist, vi);
|
|
|
|
/* Make header */
|
|
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 (minsize > 0) {
|
|
padlen = minsize - fdt32_to_cpu(fdt.totalsize);
|
|
- if ((padlen < 0) && (quiet < 1))
|
|
- fprintf(stderr,
|
|
- "Warning: blob size %d >= minimum size %d\n",
|
|
- fdt32_to_cpu(fdt.totalsize), minsize);
|
|
+ if (padlen < 0) {
|
|
+ padlen = 0;
|
|
+ if (quiet < 1)
|
|
+ fprintf(stderr,
|
|
+ "Warning: blob size %d >= minimum size %d\n",
|
|
+ fdt32_to_cpu(fdt.totalsize), minsize);
|
|
+ }
|
|
}
|
|
|
|
if (padsize > 0)
|
|
padlen = padsize;
|
|
|
|
+ if (alignsize > 0)
|
|
+ padlen = ALIGN(fdt32_to_cpu(fdt.totalsize) + padlen, alignsize)
|
|
+ - fdt32_to_cpu(fdt.totalsize);
|
|
+
|
|
if (padlen > 0) {
|
|
int tsize = fdt32_to_cpu(fdt.totalsize);
|
|
tsize += padlen;
|
|
@@ -460,7 +458,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;
|
|
int i;
|
|
@@ -500,7 +498,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
|
|
|
|
if (vi->flags & FTF_BOOTCPUID) {
|
|
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) {
|
|
@@ -530,18 +528,18 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
|
|
* Use .long on high and low halfs of u64s to avoid .quad
|
|
* 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;
|
|
|
|
for_each_label(re->labels, l) {
|
|
fprintf(f, "\t.globl\t%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",
|
|
- (unsigned int)(re->re.address & 0xffffffff));
|
|
- ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32));
|
|
- ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff));
|
|
+ (unsigned int)(re->address & 0xffffffff));
|
|
+ ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32));
|
|
+ ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff));
|
|
}
|
|
for (i = 0; i < reservenum; i++) {
|
|
fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
|
|
@@ -550,7 +548,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");
|
|
|
|
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");
|
|
asm_emit_cell(f, FDT_END);
|
|
@@ -572,6 +570,8 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
|
|
if (padsize > 0) {
|
|
fprintf(f, "\t.space\t%d, 0\n", padsize);
|
|
}
|
|
+ if (alignsize > 0)
|
|
+ asm_emit_align(f, alignsize);
|
|
emit_label(f, symprefix, "blob_abs_end");
|
|
|
|
data_free(strbuf);
|
|
@@ -600,7 +600,7 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len)
|
|
|
|
static uint32_t flat_read_word(struct inbuf *inb)
|
|
{
|
|
- uint32_t val;
|
|
+ fdt32_t val;
|
|
|
|
assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
|
|
|
|
@@ -709,13 +709,15 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
|
|
* First pass, count entries.
|
|
*/
|
|
while (1) {
|
|
+ uint64_t address, size;
|
|
+
|
|
flat_read_chunk(inb, &re, sizeof(re));
|
|
- re.address = fdt64_to_cpu(re.address);
|
|
- re.size = fdt64_to_cpu(re.size);
|
|
- if (re.size == 0)
|
|
+ address = fdt64_to_cpu(re.address);
|
|
+ size = fdt64_to_cpu(re.size);
|
|
+ if (size == 0)
|
|
break;
|
|
|
|
- new = build_reserve_entry(re.address, re.size);
|
|
+ new = build_reserve_entry(address, size);
|
|
reservelist = add_reserve_entry(reservelist, new);
|
|
}
|
|
|
|
@@ -729,7 +731,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath)
|
|
|
|
plen = strlen(ppath);
|
|
|
|
- if (!strneq(ppath, cpath, plen))
|
|
+ if (!strstarts(cpath, ppath))
|
|
die("Path \"%s\" is not valid as a child of \"%s\"\n",
|
|
cpath, ppath);
|
|
|
|
@@ -797,13 +799,18 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
|
|
}
|
|
} while (val != FDT_END_NODE);
|
|
|
|
+ if (node->name != flatname) {
|
|
+ free(flatname);
|
|
+ }
|
|
+
|
|
return node;
|
|
}
|
|
|
|
|
|
-struct boot_info *dt_from_blob(const char *fname)
|
|
+struct dt_info *dt_from_blob(const char *fname)
|
|
{
|
|
FILE *f;
|
|
+ fdt32_t magic_buf, totalsize_buf;
|
|
uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
|
|
uint32_t off_dt, off_str, off_mem_rsvmap;
|
|
int rc;
|
|
@@ -820,7 +827,7 @@ struct boot_info *dt_from_blob(const char *fname)
|
|
|
|
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))
|
|
die("Error reading DT blob magic number: %s\n",
|
|
strerror(errno));
|
|
@@ -831,11 +838,11 @@ struct boot_info *dt_from_blob(const char *fname)
|
|
die("Mysterious short read reading magic number\n");
|
|
}
|
|
|
|
- magic = fdt32_to_cpu(magic);
|
|
+ magic = fdt32_to_cpu(magic_buf);
|
|
if (magic != FDT_MAGIC)
|
|
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))
|
|
die("Error reading DT blob size: %s\n", strerror(errno));
|
|
if (rc < 1) {
|
|
@@ -845,7 +852,7 @@ struct boot_info *dt_from_blob(const char *fname)
|
|
die("Mysterious short read reading blob size\n");
|
|
}
|
|
|
|
- totalsize = fdt32_to_cpu(totalsize);
|
|
+ totalsize = fdt32_to_cpu(totalsize_buf);
|
|
if (totalsize < FDT_V1_SIZE)
|
|
die("DT blob size (%d) is too small\n", totalsize);
|
|
|
|
@@ -889,7 +896,7 @@ struct boot_info *dt_from_blob(const char *fname)
|
|
|
|
if (version >= 3) {
|
|
uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings);
|
|
- if (off_str+size_str > totalsize)
|
|
+ if ((off_str+size_str < off_str) || (off_str+size_str > totalsize))
|
|
die("String table extends past total size\n");
|
|
inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
|
|
} else {
|
|
@@ -898,7 +905,7 @@ struct boot_info *dt_from_blob(const char *fname)
|
|
|
|
if (version >= 17) {
|
|
size_dt = fdt32_to_cpu(fdt->size_dt_struct);
|
|
- if (off_dt+size_dt > totalsize)
|
|
+ if ((off_dt+size_dt < off_dt) || (off_dt+size_dt > totalsize))
|
|
die("Structure block extends past total size\n");
|
|
}
|
|
|
|
@@ -929,5 +936,5 @@ struct boot_info *dt_from_blob(const char *fname)
|
|
|
|
fclose(f);
|
|
|
|
- return build_boot_info(reservelist, tree, boot_cpuid_phys);
|
|
+ return build_dt_info(DTSF_V1, reservelist, tree, boot_cpuid_phys);
|
|
}
|
|
diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c
|
|
index 6d1beec95..ae7d06c3c 100644
|
|
--- a/scripts/dtc/fstree.c
|
|
+++ b/scripts/dtc/fstree.c
|
|
@@ -79,13 +79,12 @@ static struct node *read_fstree(const char *dirname)
|
|
return tree;
|
|
}
|
|
|
|
-struct boot_info *dt_from_fs(const char *dirname)
|
|
+struct dt_info *dt_from_fs(const char *dirname)
|
|
{
|
|
struct node *tree;
|
|
|
|
tree = read_fstree(dirname);
|
|
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));
|
|
}
|
|
-
|
|
diff --git a/scripts/dtc/libfdt.h b/scripts/dtc/libfdt.h
|
|
index 32d52276d..1e27780e1 100644
|
|
--- a/scripts/dtc/libfdt.h
|
|
+++ b/scripts/dtc/libfdt.h
|
|
@@ -1,5 +1,5 @@
|
|
-#ifndef _LIBFDT_H
|
|
-#define _LIBFDT_H
|
|
+#ifndef LIBFDT_H
|
|
+#define LIBFDT_H
|
|
/*
|
|
* libfdt - Flat Device Tree manipulation
|
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
|
@@ -51,17 +51,17 @@
|
|
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
-#include <libfdt_env.h>
|
|
-#include <fdt.h>
|
|
+#include "libfdt_env.h"
|
|
+#include "fdt.h"
|
|
|
|
-#define FDT_FIRST_SUPPORTED_VERSION 0x10
|
|
+#define FDT_FIRST_SUPPORTED_VERSION 0x02
|
|
#define FDT_LAST_SUPPORTED_VERSION 0x11
|
|
|
|
/* Error codes: informative error codes */
|
|
#define FDT_ERR_NOTFOUND 1
|
|
/* FDT_ERR_NOTFOUND: The requested node or property does not exist */
|
|
#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 */
|
|
#define FDT_ERR_NOSPACE 3
|
|
/* FDT_ERR_NOSPACE: Operation needed to expand the device
|
|
@@ -79,8 +79,10 @@
|
|
* (e.g. missing a leading / for a function which requires an
|
|
* absolute path) */
|
|
#define FDT_ERR_BADPHANDLE 6
|
|
- /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
|
|
- * value. phandle values of 0 and -1 are not permitted. */
|
|
+ /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle.
|
|
+ * 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
|
|
/* FDT_ERR_BADSTATE: Function was passed an incomplete device
|
|
* tree created by the sequential-write functions, which is
|
|
@@ -121,13 +123,29 @@
|
|
/* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells
|
|
* or similar property with a bad format or value */
|
|
|
|
-#define FDT_ERR_MAX 14
|
|
+#define FDT_ERR_BADVALUE 15
|
|
+ /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected
|
|
+ * value. For example: a property expected to contain a string list
|
|
+ * is not NUL-terminated within the length of its value. */
|
|
+
|
|
+#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) */
|
|
/**********************************************************************/
|
|
|
|
+#ifndef SWIG /* This function is not useful in Python */
|
|
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)
|
|
{
|
|
return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
|
|
@@ -163,40 +181,67 @@ int fdt_first_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 */
|
|
/**********************************************************************/
|
|
-
|
|
#define fdt_get_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_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_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))
|
|
#define fdt_version(fdt) (fdt_get_header(fdt, 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_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
|
|
+#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_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_set_hdr(name) \
|
|
+#define fdt_set_hdr_(name) \
|
|
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); \
|
|
}
|
|
-__fdt_set_hdr(magic);
|
|
-__fdt_set_hdr(totalsize);
|
|
-__fdt_set_hdr(off_dt_struct);
|
|
-__fdt_set_hdr(off_dt_strings);
|
|
-__fdt_set_hdr(off_mem_rsvmap);
|
|
-__fdt_set_hdr(version);
|
|
-__fdt_set_hdr(last_comp_version);
|
|
-__fdt_set_hdr(boot_cpuid_phys);
|
|
-__fdt_set_hdr(size_dt_strings);
|
|
-__fdt_set_hdr(size_dt_struct);
|
|
-#undef __fdt_set_hdr
|
|
+fdt_set_hdr_(magic);
|
|
+fdt_set_hdr_(totalsize);
|
|
+fdt_set_hdr_(off_dt_struct);
|
|
+fdt_set_hdr_(off_dt_strings);
|
|
+fdt_set_hdr_(off_mem_rsvmap);
|
|
+fdt_set_hdr_(version);
|
|
+fdt_set_hdr_(last_comp_version);
|
|
+fdt_set_hdr_(boot_cpuid_phys);
|
|
+fdt_set_hdr_(size_dt_strings);
|
|
+fdt_set_hdr_(size_dt_struct);
|
|
+#undef fdt_set_hdr_
|
|
|
|
/**
|
|
* fdt_check_header - sanity check a device tree or possible device tree
|
|
@@ -253,6 +298,21 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
|
|
*/
|
|
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: pointer to the device tree blob
|
|
@@ -295,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,
|
|
* such as a full path.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
|
|
const char *name, int namelen);
|
|
+#endif
|
|
/**
|
|
* fdt_subnode_offset - find a subnode of a given node
|
|
* @fdt: pointer to the device tree blob
|
|
@@ -313,8 +375,9 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
|
|
* returns:
|
|
* structure block offset of the requested subnode (>=0), on success
|
|
* -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_BADMAGIC,
|
|
+ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
|
|
+ * tag
|
|
+ * -FDT_ERR_BADMAGIC,
|
|
* -FDT_ERR_BADVERSION,
|
|
* -FDT_ERR_BADSTATE,
|
|
* -FDT_ERR_BADSTRUCTURE,
|
|
@@ -322,6 +385,19 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
|
|
*/
|
|
int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
|
|
|
|
+/**
|
|
+ * fdt_path_offset_namelen - find a tree node by its full path
|
|
+ * @fdt: pointer to the device tree blob
|
|
+ * @path: full path of the node to locate
|
|
+ * @namelen: number of characters of path to consider
|
|
+ *
|
|
+ * Identical to fdt_path_offset(), but only consider the first namelen
|
|
+ * 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);
|
|
+#endif
|
|
+
|
|
/**
|
|
* fdt_path_offset - find a tree node by its full path
|
|
* @fdt: pointer to the device tree blob
|
|
@@ -335,7 +411,8 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
|
|
* address).
|
|
*
|
|
* 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_NOTFOUND, if the requested node does not exist
|
|
* -FDT_ERR_BADMAGIC,
|
|
@@ -359,10 +436,12 @@ int fdt_path_offset(const void *fdt, const char *path);
|
|
*
|
|
* returns:
|
|
* 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
|
|
* 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_BADVERSION,
|
|
* -FDT_ERR_BADSTATE, standard meanings
|
|
@@ -410,6 +489,33 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset);
|
|
*/
|
|
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: pointer to the device tree blob
|
|
@@ -421,6 +527,9 @@ int fdt_next_property_offset(const void *fdt, int offset);
|
|
* offset. If lenp is non-NULL, the length of the property value is
|
|
* also returned, in the integer pointed to by lenp.
|
|
*
|
|
+ * Note that this code only works on device tree versions >= 16. fdt_getprop()
|
|
+ * works on all versions.
|
|
+ *
|
|
* returns:
|
|
* pointer to the structure representing the property
|
|
* if lenp is non-NULL, *lenp contains the length of the property
|
|
@@ -446,13 +555,15 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
|
|
* @namelen: number of characters of name to consider
|
|
* @lenp: pointer to an integer variable (will be overwritten) or NULL
|
|
*
|
|
- * Identical to fdt_get_property_namelen(), but only examine the first
|
|
- * namelen characters of name for matching the property name.
|
|
+ * Identical to fdt_get_property(), but only examine the first namelen
|
|
+ * 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,
|
|
int nodeoffset,
|
|
const char *name,
|
|
int namelen, int *lenp);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_get_property - find a given property in a given node
|
|
@@ -474,7 +585,8 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
|
|
* NULL, on error
|
|
* if lenp is non-NULL, *lenp contains an error code (<0):
|
|
* -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_BADVERSION,
|
|
* -FDT_ERR_BADSTATE,
|
|
@@ -522,8 +634,10 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
|
|
* -FDT_ERR_BADSTRUCTURE,
|
|
* -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 char **namep, int *lenp);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_getprop_namelen - get property value based on substring
|
|
@@ -536,8 +650,17 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
|
|
* Identical to fdt_getprop(), but only examine the first namelen
|
|
* characters of name for matching the property name.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
|
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);
|
|
+}
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_getprop - retrieve the value of a given property
|
|
@@ -559,7 +682,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
|
|
* NULL, on error
|
|
* if lenp is non-NULL, *lenp contains an error code (<0):
|
|
* -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_BADVERSION,
|
|
* -FDT_ERR_BADSTATE,
|
|
@@ -597,11 +721,13 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
|
|
* Identical to fdt_get_alias(), but only examine the first namelen
|
|
* 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 *name, int namelen);
|
|
+#endif
|
|
|
|
/**
|
|
- * 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
|
|
* @name: name of the alias th look up
|
|
*
|
|
@@ -631,7 +757,7 @@ const char *fdt_get_alias(const void *fdt, const char *name);
|
|
* 0, on success
|
|
* buf contains the absolute path of the node at
|
|
* 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)
|
|
* characters and will not fit in the given buffer.
|
|
* -FDT_ERR_BADMAGIC,
|
|
@@ -661,11 +787,11 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
|
|
* structure from the start to nodeoffset.
|
|
*
|
|
* returns:
|
|
-
|
|
* structure block offset of the node at node offset's ancestor
|
|
* of depth supernodedepth (>=0), on success
|
|
- * -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_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
|
|
+ * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of
|
|
+ * nodeoffset
|
|
* -FDT_ERR_BADMAGIC,
|
|
* -FDT_ERR_BADVERSION,
|
|
* -FDT_ERR_BADSTATE,
|
|
@@ -687,7 +813,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
|
|
*
|
|
* returns:
|
|
* 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_BADVERSION,
|
|
* -FDT_ERR_BADSTATE,
|
|
@@ -710,7 +836,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset);
|
|
* returns:
|
|
* structure block offset of the parent 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_BADVERSION,
|
|
* -FDT_ERR_BADSTATE,
|
|
@@ -750,7 +876,7 @@ int fdt_parent_offset(const void *fdt, int nodeoffset);
|
|
* on success
|
|
* -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
|
|
* 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_BADVERSION,
|
|
* -FDT_ERR_BADSTATE,
|
|
@@ -797,7 +923,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
|
|
* the given string
|
|
* -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_BADVERSION,
|
|
* -FDT_ERR_BADSTATE,
|
|
@@ -834,7 +960,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
|
|
* on success
|
|
* -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
|
|
* 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_BADVERSION,
|
|
* -FDT_ERR_BADSTATE,
|
|
@@ -857,6 +983,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
|
|
*/
|
|
int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
|
|
|
|
+/**
|
|
+ * fdt_stringlist_count - count the number of strings in a string list
|
|
+ * @fdt: pointer to the device tree blob
|
|
+ * @nodeoffset: offset of a tree node
|
|
+ * @property: name of the property containing the string list
|
|
+ * @return:
|
|
+ * the number of strings in the given property
|
|
+ * -FDT_ERR_BADVALUE if the property value is not NUL-terminated
|
|
+ * -FDT_ERR_NOTFOUND if the property does not exist
|
|
+ */
|
|
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
|
|
+
|
|
+/**
|
|
+ * fdt_stringlist_search - find a string in a string list and return its index
|
|
+ * @fdt: pointer to the device tree blob
|
|
+ * @nodeoffset: offset of a tree node
|
|
+ * @property: name of the property containing the string list
|
|
+ * @string: string to look up in the string list
|
|
+ *
|
|
+ * Note that it is possible for this function to succeed on property values
|
|
+ * that are not NUL-terminated. That's because the function will stop after
|
|
+ * finding the first occurrence of @string. This can for example happen with
|
|
+ * small-valued cell properties, such as #address-cells, when searching for
|
|
+ * the empty string.
|
|
+ *
|
|
+ * @return:
|
|
+ * the index of the string in the list of strings
|
|
+ * -FDT_ERR_BADVALUE if the property value is not NUL-terminated
|
|
+ * -FDT_ERR_NOTFOUND if the property does not exist or does not contain
|
|
+ * the given string
|
|
+ */
|
|
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
|
|
+ const char *string);
|
|
+
|
|
+/**
|
|
+ * fdt_stringlist_get() - obtain the string at a given index in a string list
|
|
+ * @fdt: pointer to the device tree blob
|
|
+ * @nodeoffset: offset of a tree node
|
|
+ * @property: name of the property containing the string list
|
|
+ * @index: index of the string to return
|
|
+ * @lenp: return location for the string length or an error code on failure
|
|
+ *
|
|
+ * Note that this will successfully extract strings from properties with
|
|
+ * non-NUL-terminated values. For example on small-valued cell properties
|
|
+ * this function will return the empty string.
|
|
+ *
|
|
+ * If non-NULL, the length of the string (on success) or a negative error-code
|
|
+ * (on failure) will be stored in the integer pointer to by lenp.
|
|
+ *
|
|
+ * @return:
|
|
+ * A pointer to the string at the given index in the string list or NULL on
|
|
+ * failure. On success the length of the string will be stored in the memory
|
|
+ * location pointed to by the lenp parameter, if non-NULL. On failure one of
|
|
+ * the following negative error codes will be returned in the lenp parameter
|
|
+ * (if non-NULL):
|
|
+ * -FDT_ERR_BADVALUE if the property value is not NUL-terminated
|
|
+ * -FDT_ERR_NOTFOUND if the property does not exist
|
|
+ */
|
|
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
|
|
+ const char *property, int index,
|
|
+ int *lenp);
|
|
+
|
|
/**********************************************************************/
|
|
/* Read-only functions (addressing related) */
|
|
/**********************************************************************/
|
|
@@ -882,7 +1070,8 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
|
|
* returns:
|
|
* 0 <= n < FDT_MAX_NCELLS, on success
|
|
* 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_BADVERSION,
|
|
* -FDT_ERR_BADSTATE,
|
|
@@ -902,7 +1091,8 @@ int fdt_address_cells(const void *fdt, int nodeoffset);
|
|
* returns:
|
|
* 0 <= n < FDT_MAX_NCELLS, on success
|
|
* 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_BADVERSION,
|
|
* -FDT_ERR_BADSTATE,
|
|
@@ -916,6 +1106,29 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
|
|
/* 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.
|
|
+ */
|
|
+#ifndef SWIG /* Not available in Python */
|
|
+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
|
|
+ const char *name, int namelen,
|
|
+ uint32_t idx, const void *val,
|
|
+ int len);
|
|
+#endif
|
|
+
|
|
/**
|
|
* fdt_setprop_inplace - change a property's value, but not its size
|
|
* @fdt: pointer to the device tree blob
|
|
@@ -944,8 +1157,10 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
|
|
* -FDT_ERR_BADSTRUCTURE,
|
|
* -FDT_ERR_TRUNCATED, standard meanings
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
|
|
const void *val, int len);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
|
|
@@ -1102,6 +1317,22 @@ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
|
|
{
|
|
return fdt_property_u32(fdt, name, val);
|
|
}
|
|
+
|
|
+/**
|
|
+ * fdt_property_placeholder - add a new property and return a ptr to its value
|
|
+ *
|
|
+ * @fdt: pointer to the device tree blob
|
|
+ * @name: name of property to add
|
|
+ * @len: length of property value in bytes
|
|
+ * @valp: returns a pointer to where where the value should be placed
|
|
+ *
|
|
+ * returns:
|
|
+ * 0, on success
|
|
+ * -FDT_ERR_BADMAGIC,
|
|
+ * -FDT_ERR_NOSPACE, standard meanings
|
|
+ */
|
|
+int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp);
|
|
+
|
|
#define fdt_property_string(fdt, name, str) \
|
|
fdt_property(fdt, name, str, strlen(str)+1)
|
|
int fdt_end_node(void *fdt);
|
|
@@ -1220,6 +1451,37 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name);
|
|
int fdt_setprop(void *fdt, int nodeoffset, const char *name,
|
|
const void *val, int len);
|
|
|
|
+/**
|
|
+ * fdt_setprop_placeholder - allocate space for a property
|
|
+ * @fdt: pointer to the device tree blob
|
|
+ * @nodeoffset: offset of the node whose property to change
|
|
+ * @name: name of the property to change
|
|
+ * @len: length of the property value
|
|
+ * @prop_data: return pointer to property data
|
|
+ *
|
|
+ * fdt_setprop_placeholer() allocates the named property in the given node.
|
|
+ * If the property exists it is resized. In either case a pointer to the
|
|
+ * property data is returned.
|
|
+ *
|
|
+ * 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
|
|
+ */
|
|
+int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
|
|
+ int len, void **prop_data);
|
|
+
|
|
/**
|
|
* fdt_setprop_u32 - set a property to a 32-bit integer
|
|
* @fdt: pointer to the device tree blob
|
|
@@ -1332,6 +1594,36 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
|
|
#define fdt_setprop_string(fdt, nodeoffset, name, str) \
|
|
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: pointer to the device tree blob
|
|
@@ -1509,8 +1801,10 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
|
|
* creating subnodes based on a portion of a larger string, such as a
|
|
* full path.
|
|
*/
|
|
+#ifndef SWIG /* Not available in Python */
|
|
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
|
const char *name, int namelen);
|
|
+#endif
|
|
|
|
/**
|
|
* fdt_add_subnode - creates a new node
|
|
@@ -1526,9 +1820,11 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
|
|
* change the offsets of some existing nodes.
|
|
|
|
* 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_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
|
|
* the given name
|
|
* -FDT_ERR_NOSPACE, if there is insufficient free space in the
|
|
@@ -1566,10 +1862,41 @@ int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
|
|
*/
|
|
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 */
|
|
/**********************************************************************/
|
|
|
|
const char *fdt_strerror(int errval);
|
|
|
|
-#endif /* _LIBFDT_H */
|
|
+#endif /* LIBFDT_H */
|
|
diff --git a/scripts/dtc/libfdt_env.h b/scripts/dtc/libfdt_env.h
|
|
index 9dea97dff..bd2474628 100644
|
|
--- a/scripts/dtc/libfdt_env.h
|
|
+++ b/scripts/dtc/libfdt_env.h
|
|
@@ -1,5 +1,5 @@
|
|
-#ifndef _LIBFDT_ENV_H
|
|
-#define _LIBFDT_ENV_H
|
|
+#ifndef LIBFDT_ENV_H
|
|
+#define LIBFDT_ENV_H
|
|
/*
|
|
* libfdt - Flat Device Tree manipulation
|
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
|
@@ -54,19 +54,20 @@
|
|
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
+#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifdef __CHECKER__
|
|
-#define __force __attribute__((force))
|
|
-#define __bitwise __attribute__((bitwise))
|
|
+#define FDT_FORCE __attribute__((force))
|
|
+#define FDT_BITWISE __attribute__((bitwise))
|
|
#else
|
|
-#define __force
|
|
-#define __bitwise
|
|
+#define FDT_FORCE
|
|
+#define FDT_BITWISE
|
|
#endif
|
|
|
|
-typedef uint16_t __bitwise fdt16_t;
|
|
-typedef uint32_t __bitwise fdt32_t;
|
|
-typedef uint64_t __bitwise fdt64_t;
|
|
+typedef uint16_t FDT_BITWISE fdt16_t;
|
|
+typedef uint32_t FDT_BITWISE fdt32_t;
|
|
+typedef uint64_t FDT_BITWISE fdt64_t;
|
|
|
|
#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))
|
|
@@ -79,33 +80,60 @@ typedef uint64_t __bitwise fdt64_t;
|
|
|
|
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)
|
|
{
|
|
- 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)
|
|
{
|
|
- 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)
|
|
{
|
|
- 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)
|
|
{
|
|
- 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)
|
|
{
|
|
- return (__force fdt64_t)CPU_TO_FDT64(x);
|
|
+ return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x);
|
|
}
|
|
#undef CPU_TO_FDT64
|
|
#undef CPU_TO_FDT32
|
|
#undef CPU_TO_FDT16
|
|
#undef EXTRACT_BYTE
|
|
|
|
-#endif /* _LIBFDT_ENV_H */
|
|
+#ifdef __APPLE__
|
|
+#include <AvailabilityMacros.h>
|
|
+
|
|
+/* strnlen() is not available on Mac OS < 10.7 */
|
|
+# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \
|
|
+ MAC_OS_X_VERSION_10_7)
|
|
+
|
|
+#define strnlen fdt_strnlen
|
|
+
|
|
+/*
|
|
+ * fdt_strnlen: returns the length of a string or max_count - which ever is
|
|
+ * smallest.
|
|
+ * Input 1 string: the string whose size is to be determined
|
|
+ * Input 2 max_count: the maximum value returned by this function
|
|
+ * Output: length of the string or max_count (the smallest of the two)
|
|
+ */
|
|
+static inline size_t fdt_strnlen(const char *string, size_t max_count)
|
|
+{
|
|
+ const char *p = memchr(string, 0, max_count);
|
|
+ return p ? p - string : max_count;
|
|
+}
|
|
+
|
|
+#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED <
|
|
+ MAC_OS_X_VERSION_10_7) */
|
|
+
|
|
+#endif /* __APPLE__ */
|
|
+
|
|
+#endif /* LIBFDT_ENV_H */
|
|
diff --git a/scripts/dtc/libfdt_internal.h b/scripts/dtc/libfdt_internal.h
|
|
index 02cfa6fb6..7681e1922 100644
|
|
--- a/scripts/dtc/libfdt_internal.h
|
|
+++ b/scripts/dtc/libfdt_internal.h
|
|
@@ -1,5 +1,5 @@
|
|
-#ifndef _LIBFDT_INTERNAL_H
|
|
-#define _LIBFDT_INTERNAL_H
|
|
+#ifndef LIBFDT_INTERNAL_H
|
|
+#define LIBFDT_INTERNAL_H
|
|
/*
|
|
* libfdt - Flat Device Tree manipulation
|
|
* Copyright (C) 2006 David Gibson, IBM Corporation.
|
|
@@ -57,27 +57,27 @@
|
|
|
|
#define FDT_CHECK_HEADER(fdt) \
|
|
{ \
|
|
- int __err; \
|
|
- if ((__err = fdt_check_header(fdt)) != 0) \
|
|
- return __err; \
|
|
+ int err_; \
|
|
+ if ((err_ = fdt_check_header(fdt)) != 0) \
|
|
+ return err_; \
|
|
}
|
|
|
|
-int _fdt_check_node_offset(const void *fdt, int offset);
|
|
-int _fdt_check_prop_offset(const void *fdt, int offset);
|
|
-const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
|
|
-int _fdt_node_end_offset(void *fdt, int nodeoffset);
|
|
+int fdt_check_node_offset_(const void *fdt, int offset);
|
|
+int fdt_check_prop_offset_(const void *fdt, int offset);
|
|
+const char *fdt_find_string_(const char *strtab, int tabsize, const char *s);
|
|
+int fdt_node_end_offset_(void *fdt, int nodeoffset);
|
|
|
|
-static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
|
|
+static inline const void *fdt_offset_ptr_(const void *fdt, int offset)
|
|
{
|
|
return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
|
|
}
|
|
|
|
-static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
|
|
+static inline void *fdt_offset_ptr_w_(void *fdt, int offset)
|
|
{
|
|
- return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
|
|
+ return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset);
|
|
}
|
|
|
|
-static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
|
|
+static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n)
|
|
{
|
|
const struct fdt_reserve_entry *rsv_table =
|
|
(const struct fdt_reserve_entry *)
|
|
@@ -85,11 +85,11 @@ static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int
|
|
|
|
return rsv_table + n;
|
|
}
|
|
-static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
|
|
+static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
|
|
{
|
|
- return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
|
|
+ return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
|
|
}
|
|
|
|
#define FDT_SW_MAGIC (~FDT_MAGIC)
|
|
|
|
-#endif /* _LIBFDT_INTERNAL_H */
|
|
+#endif /* LIBFDT_INTERNAL_H */
|
|
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
|
|
index e229b8443..57b7db2ed 100644
|
|
--- a/scripts/dtc/livetree.c
|
|
+++ b/scripts/dtc/livetree.c
|
|
@@ -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)
|
|
add_child(old_node, new_child);
|
|
}
|
|
@@ -216,6 +216,29 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
|
|
return old_node;
|
|
}
|
|
|
|
+struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
|
|
+{
|
|
+ static unsigned int next_orphan_fragment = 0;
|
|
+ struct node *node;
|
|
+ struct property *p;
|
|
+ struct data d = empty_data;
|
|
+ char *name;
|
|
+
|
|
+ d = data_add_marker(d, REF_PHANDLE, ref);
|
|
+ d = data_append_integer(d, 0xffffffff, 32);
|
|
+
|
|
+ p = build_property("target", d);
|
|
+
|
|
+ xasprintf(&name, "fragment@%u",
|
|
+ next_orphan_fragment++);
|
|
+ name_node(new_node, "__overlay__");
|
|
+ node = build_node(p, new_node);
|
|
+ name_node(node, name);
|
|
+
|
|
+ add_child(dt, node);
|
|
+ return dt;
|
|
+}
|
|
+
|
|
struct node *chain_node(struct node *first, struct node *list)
|
|
{
|
|
assert(first->next_sibling == NULL);
|
|
@@ -242,7 +265,7 @@ void delete_property_by_name(struct node *node, char *name)
|
|
struct property *prop = node->proplist;
|
|
|
|
while (prop) {
|
|
- if (!strcmp(prop->name, name)) {
|
|
+ if (streq(prop->name, name)) {
|
|
delete_property(prop);
|
|
return;
|
|
}
|
|
@@ -275,7 +298,7 @@ void delete_node_by_name(struct node *parent, char *name)
|
|
struct node *node = parent->children;
|
|
|
|
while (node) {
|
|
- if (!strcmp(node->name, name)) {
|
|
+ if (streq(node->name, name)) {
|
|
delete_node(node);
|
|
return;
|
|
}
|
|
@@ -296,14 +319,31 @@ void delete_node(struct node *node)
|
|
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 *new = xmalloc(sizeof(*new));
|
|
|
|
memset(new, 0, sizeof(*new));
|
|
|
|
- new->re.address = address;
|
|
- new->re.size = size;
|
|
+ new->address = address;
|
|
+ new->size = size;
|
|
|
|
return new;
|
|
}
|
|
@@ -335,17 +375,19 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
|
|
return list;
|
|
}
|
|
|
|
-struct boot_info *build_boot_info(struct reserve_info *reservelist,
|
|
- struct node *tree, uint32_t boot_cpuid_phys)
|
|
+struct dt_info *build_dt_info(unsigned int dtsflags,
|
|
+ struct reserve_info *reservelist,
|
|
+ struct node *tree, uint32_t boot_cpuid_phys)
|
|
{
|
|
- struct boot_info *bi;
|
|
+ struct dt_info *dti;
|
|
|
|
- bi = xmalloc(sizeof(*bi));
|
|
- bi->reservelist = reservelist;
|
|
- bi->dt = tree;
|
|
- bi->boot_cpuid_phys = boot_cpuid_phys;
|
|
+ dti = xmalloc(sizeof(*dti));
|
|
+ dti->dtsflags = dtsflags;
|
|
+ dti->reservelist = reservelist;
|
|
+ dti->dt = tree;
|
|
+ dti->boot_cpuid_phys = boot_cpuid_phys;
|
|
|
|
- return bi;
|
|
+ return dti;
|
|
}
|
|
|
|
/*
|
|
@@ -374,7 +416,13 @@ struct property *get_property(struct node *node, const char *propname)
|
|
cell_t propval_cell(struct property *prop)
|
|
{
|
|
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));
|
|
+}
|
|
+
|
|
+cell_t propval_cell_n(struct property *prop, int n)
|
|
+{
|
|
+ assert(prop->val.len / sizeof(cell_t) >= n);
|
|
+ return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
|
|
}
|
|
|
|
struct property *get_property_by_label(struct node *tree, const char *label,
|
|
@@ -459,7 +507,8 @@ struct node *get_node_by_path(struct node *tree, const char *path)
|
|
p = strchr(path, '/');
|
|
|
|
for_each_child(tree, child) {
|
|
- if (p && strneq(path, child->name, p-path))
|
|
+ if (p && (strlen(child->name) == p-path) &&
|
|
+ strprefixeq(path, p - path, child->name))
|
|
return get_node_by_path(child, p+1);
|
|
else if (!p && streq(path, child->name))
|
|
return child;
|
|
@@ -492,7 +541,10 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
|
|
{
|
|
struct node *child, *node;
|
|
|
|
- assert((phandle != 0) && (phandle != -1));
|
|
+ if ((phandle == 0) || (phandle == -1)) {
|
|
+ assert(generate_fixups);
|
|
+ return NULL;
|
|
+ }
|
|
|
|
if (tree->phandle == phandle) {
|
|
if (tree->deleted)
|
|
@@ -580,24 +632,24 @@ static int cmp_reserve_info(const void *ax, const void *bx)
|
|
a = *((const struct reserve_info * const *)ax);
|
|
b = *((const struct reserve_info * const *)bx);
|
|
|
|
- if (a->re.address < b->re.address)
|
|
+ if (a->address < b->address)
|
|
return -1;
|
|
- else if (a->re.address > b->re.address)
|
|
+ else if (a->address > b->address)
|
|
return 1;
|
|
- else if (a->re.size < b->re.size)
|
|
+ else if (a->size < b->size)
|
|
return -1;
|
|
- else if (a->re.size > b->re.size)
|
|
+ else if (a->size > b->size)
|
|
return 1;
|
|
else
|
|
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;
|
|
int n = 0, i = 0;
|
|
|
|
- for (ri = bi->reservelist;
|
|
+ for (ri = dti->reservelist;
|
|
ri;
|
|
ri = ri->next)
|
|
n++;
|
|
@@ -607,14 +659,14 @@ static void sort_reserve_entries(struct boot_info *bi)
|
|
|
|
tbl = xmalloc(n * sizeof(*tbl));
|
|
|
|
- for (ri = bi->reservelist;
|
|
+ for (ri = dti->reservelist;
|
|
ri;
|
|
ri = ri->next)
|
|
tbl[i++] = ri;
|
|
|
|
qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
|
|
|
|
- bi->reservelist = tbl[0];
|
|
+ dti->reservelist = tbl[0];
|
|
for (i = 0; i < (n-1); i++)
|
|
tbl[i]->next = tbl[i+1];
|
|
tbl[n-1]->next = NULL;
|
|
@@ -704,8 +756,258 @@ static void sort_node(struct node *node)
|
|
sort_node(c);
|
|
}
|
|
|
|
-void sort_tree(struct boot_info *bi)
|
|
+void sort_tree(struct dt_info *dti)
|
|
+{
|
|
+ sort_reserve_entries(dti);
|
|
+ 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)
|
|
{
|
|
- sort_reserve_entries(bi);
|
|
- sort_node(bi->dt);
|
|
+ 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);
|
|
+
|
|
+ free(entry);
|
|
+}
|
|
+
|
|
+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 */
|
|
+ fdt32_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);
|
|
}
|
|
diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c
|
|
index f534c22a8..cb6ed0e3e 100644
|
|
--- a/scripts/dtc/srcpos.c
|
|
+++ b/scripts/dtc/srcpos.c
|
|
@@ -209,8 +209,6 @@ struct srcpos srcpos_empty = {
|
|
.file = NULL,
|
|
};
|
|
|
|
-#define TAB_SIZE 8
|
|
-
|
|
void srcpos_update(struct srcpos *pos, const char *text, int len)
|
|
{
|
|
int i;
|
|
@@ -224,9 +222,6 @@ void srcpos_update(struct srcpos *pos, const char *text, int len)
|
|
if (text[i] == '\n') {
|
|
current_srcfile->lineno++;
|
|
current_srcfile->colno = 1;
|
|
- } else if (text[i] == '\t') {
|
|
- current_srcfile->colno =
|
|
- ALIGN(current_srcfile->colno, TAB_SIZE);
|
|
} else {
|
|
current_srcfile->colno++;
|
|
}
|
|
@@ -246,46 +241,27 @@ srcpos_copy(struct srcpos *pos)
|
|
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 *
|
|
srcpos_string(struct srcpos *pos)
|
|
{
|
|
const char *fname = "<no-file>";
|
|
char *pos_str;
|
|
- int rc;
|
|
|
|
- if (pos)
|
|
+ if (pos->file && pos->file->name)
|
|
fname = pos->file->name;
|
|
|
|
|
|
if (pos->first_line != pos->last_line)
|
|
- rc = asprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
|
|
- pos->first_line, pos->first_column,
|
|
- pos->last_line, pos->last_column);
|
|
+ xasprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
|
|
+ pos->first_line, pos->first_column,
|
|
+ pos->last_line, pos->last_column);
|
|
else if (pos->first_column != pos->last_column)
|
|
- rc = asprintf(&pos_str, "%s:%d.%d-%d", fname,
|
|
- pos->first_line, pos->first_column,
|
|
- pos->last_column);
|
|
+ xasprintf(&pos_str, "%s:%d.%d-%d", fname,
|
|
+ pos->first_line, pos->first_column,
|
|
+ pos->last_column);
|
|
else
|
|
- rc = asprintf(&pos_str, "%s:%d.%d", fname,
|
|
- pos->first_line, pos->first_column);
|
|
-
|
|
- if (rc == -1)
|
|
- die("Couldn't allocate in srcpos string");
|
|
+ xasprintf(&pos_str, "%s:%d.%d", fname,
|
|
+ pos->first_line, pos->first_column);
|
|
|
|
return pos_str;
|
|
}
|
|
diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h
|
|
index f81827bd6..9ded12a38 100644
|
|
--- a/scripts/dtc/srcpos.h
|
|
+++ b/scripts/dtc/srcpos.h
|
|
@@ -17,11 +17,12 @@
|
|
* USA
|
|
*/
|
|
|
|
-#ifndef _SRCPOS_H_
|
|
-#define _SRCPOS_H_
|
|
+#ifndef SRCPOS_H
|
|
+#define SRCPOS_H
|
|
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
+#include "util.h"
|
|
|
|
struct srcfile_state {
|
|
FILE *f;
|
|
@@ -105,15 +106,12 @@ extern struct srcpos srcpos_empty;
|
|
extern void srcpos_update(struct srcpos *pos, const char *text, int len);
|
|
extern struct srcpos *srcpos_copy(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,
|
|
- const char *fmt, va_list va)
|
|
- __attribute__((format(printf, 3, 0)));
|
|
-extern void srcpos_error(struct srcpos *pos, const char *prefix,
|
|
- const char *fmt, ...)
|
|
- __attribute__((format(printf, 3, 4)));
|
|
+extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix,
|
|
+ const char *fmt, va_list va);
|
|
+extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix,
|
|
+ const char *fmt, ...);
|
|
|
|
extern void srcpos_set_line(char *f, int l);
|
|
|
|
-#endif /* _SRCPOS_H_ */
|
|
+#endif /* SRCPOS_H */
|
|
diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c
|
|
index a55d1d128..2461a3d06 100644
|
|
--- a/scripts/dtc/treesource.c
|
|
+++ b/scripts/dtc/treesource.c
|
|
@@ -25,12 +25,12 @@ extern FILE *yyin;
|
|
extern int yyparse(void);
|
|
extern YYLTYPE yylloc;
|
|
|
|
-struct boot_info *the_boot_info;
|
|
+struct dt_info *parser_output;
|
|
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;
|
|
|
|
srcfile_push(fname);
|
|
@@ -43,7 +43,7 @@ struct boot_info *dt_from_source(const char *fname)
|
|
if (treesource_error)
|
|
die("Syntax error parsing input tree\n");
|
|
|
|
- return the_boot_info;
|
|
+ return parser_output;
|
|
}
|
|
|
|
static void write_prefix(FILE *f, int level)
|
|
@@ -137,7 +137,7 @@ static void write_propval_string(FILE *f, struct data val)
|
|
static void write_propval_cells(FILE *f, struct data val)
|
|
{
|
|
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;
|
|
|
|
fprintf(f, "<");
|
|
@@ -263,22 +263,22 @@ 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;
|
|
|
|
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;
|
|
|
|
for_each_label(re->labels, l)
|
|
fprintf(f, "%s: ", l->label);
|
|
fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
|
|
- (unsigned long long)re->re.address,
|
|
- (unsigned long long)re->re.size);
|
|
+ (unsigned long long)re->address,
|
|
+ (unsigned long long)re->size);
|
|
}
|
|
|
|
- write_tree_source_node(f, bi->dt, 0);
|
|
+ write_tree_source_node(f, dti->dt, 0);
|
|
}
|
|
|
|
diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh
|
|
index 075d1d7af..1a009fd19 100755
|
|
--- a/scripts/dtc/update-dtc-source.sh
|
|
+++ b/scripts/dtc/update-dtc-source.sh
|
|
@@ -1,9 +1,10 @@
|
|
#!/bin/sh
|
|
+# SPDX-License-Identifier: GPL-2.0
|
|
# Simple script to update the version of DTC carried by the Linux kernel
|
|
#
|
|
# This script assumes that the dtc and the linux git trees are in the
|
|
# same directory. After building dtc in the dtc directory, it copies the
|
|
-# source files and generated source files into the scripts/dtc directory
|
|
+# source files and generated source file(s) into the scripts/dtc directory
|
|
# in the kernel and creates a git commit updating them to the new
|
|
# version.
|
|
#
|
|
@@ -32,16 +33,24 @@ DTC_LINUX_PATH=`pwd`/scripts/dtc
|
|
|
|
DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c \
|
|
srcpos.h treesource.c util.c util.h version_gen.h Makefile.dtc \
|
|
- dtc-lexer.l dtc-parser.y fdtdump.c fdtput.c fdtget.c"
|
|
-DTC_LIB="fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c fdt_ro.c fdt_rw.c \
|
|
- fdt_strerror.c fdt_sw.c fdt_wip.c libfdt.h libfdt_env.h \
|
|
- libfdt_internal.h"
|
|
-DTC_GENERATED="dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h"
|
|
+ dtc-lexer.l dtc-parser.y"
|
|
+LIBFDT_SOURCE="Makefile.libfdt fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c \
|
|
+ fdt_overlay.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c \
|
|
+ fdt_wip.c libfdt.h libfdt_env.h libfdt_internal.h"
|
|
+
|
|
+get_last_dtc_version() {
|
|
+ git log --oneline scripts/dtc/ | grep 'upstream' | head -1 | sed -e 's/^.* \(.*\)/\1/'
|
|
+}
|
|
+
|
|
+last_dtc_ver=$(get_last_dtc_version)
|
|
|
|
# Build DTC
|
|
cd $DTC_UPSTREAM_PATH
|
|
make clean
|
|
make check
|
|
+dtc_version=$(git describe HEAD)
|
|
+dtc_log=$(git log --oneline ${last_dtc_ver}..)
|
|
+
|
|
|
|
# Copy the files into the Linux tree
|
|
cd $DTC_LINUX_PATH
|
|
@@ -49,13 +58,22 @@ for f in $DTC_SOURCE; do
|
|
cp ${DTC_UPSTREAM_PATH}/${f} ${f}
|
|
git add ${f}
|
|
done
|
|
-for f in $DTC_LIB; do
|
|
- cp ${DTC_UPSTREAM_PATH}/libfdt/${f} ${f}
|
|
- git add ${f}
|
|
-done
|
|
-for f in $DTC_GENERATED; do
|
|
- cp ${DTC_UPSTREAM_PATH}/$f ${f}_shipped
|
|
- git add ${f}_shipped
|
|
+for f in $LIBFDT_SOURCE; do
|
|
+ cp ${DTC_UPSTREAM_PATH}/libfdt/${f} libfdt/${f}
|
|
+ git add libfdt/${f}
|
|
done
|
|
|
|
-git commit -e -v -m "scripts/dtc: Update to upstream version [CHANGEME]"
|
|
+sed -i -- 's/#include <libfdt_env.h>/#include "libfdt_env.h"/g' ./libfdt/libfdt.h
|
|
+sed -i -- 's/#include <fdt.h>/#include "fdt.h"/g' ./libfdt/libfdt.h
|
|
+git add ./libfdt/libfdt.h
|
|
+
|
|
+commit_msg=$(cat << EOF
|
|
+scripts/dtc: Update to upstream version ${dtc_version}
|
|
+
|
|
+This adds the following commits from upstream:
|
|
+
|
|
+${dtc_log}
|
|
+EOF
|
|
+)
|
|
+
|
|
+git commit -e -v -s -m "${commit_msg}"
|
|
diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
|
|
index 9d65226df..9953c32a0 100644
|
|
--- a/scripts/dtc/util.c
|
|
+++ b/scripts/dtc/util.c
|
|
@@ -46,6 +46,36 @@ char *xstrdup(const char *s)
|
|
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)
|
|
{
|
|
int lenp = strlen(path);
|
|
@@ -152,7 +182,6 @@ char get_escape_char(const char *s, int *i)
|
|
int j = *i + 1;
|
|
char val;
|
|
|
|
- assert(c);
|
|
switch (c) {
|
|
case 'a':
|
|
val = '\a';
|
|
@@ -349,7 +378,6 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
|
|
void utilfdt_print_data(const char *data, int len)
|
|
{
|
|
int i;
|
|
- const char *p = data;
|
|
const char *s;
|
|
|
|
/* no data, don't print */
|
|
@@ -368,7 +396,7 @@ void utilfdt_print_data(const char *data, int len)
|
|
} while (s < data + len);
|
|
|
|
} else if ((len % 4) == 0) {
|
|
- const uint32_t *cell = (const uint32_t *)data;
|
|
+ const fdt32_t *cell = (const fdt32_t *)data;
|
|
|
|
printf(" = <");
|
|
for (i = 0, len /= 4; i < len; i++)
|
|
@@ -376,6 +404,7 @@ void utilfdt_print_data(const char *data, int len)
|
|
i < (len - 1) ? " " : "");
|
|
printf(">");
|
|
} else {
|
|
+ const unsigned char *p = (const unsigned char *)data;
|
|
printf(" = [");
|
|
for (i = 0; i < len; i++)
|
|
printf("%02x%s", *p++, i < len - 1 ? " " : "");
|
|
@@ -383,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);
|
|
exit(0);
|
|
}
|
|
|
|
-void util_usage(const char *errmsg, const char *synopsis,
|
|
- const char *short_opts, struct option const long_opts[],
|
|
- const char * const opts_help[])
|
|
+void NORETURN util_usage(const char *errmsg, const char *synopsis,
|
|
+ const char *short_opts,
|
|
+ struct option const long_opts[],
|
|
+ const char * const opts_help[])
|
|
{
|
|
FILE *fp = errmsg ? stderr : stdout;
|
|
const char a_arg[] = "<arg>";
|
|
diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h
|
|
index ccfdf4b12..66fba8ea7 100644
|
|
--- a/scripts/dtc/util.h
|
|
+++ b/scripts/dtc/util.h
|
|
@@ -1,5 +1,5 @@
|
|
-#ifndef _UTIL_H
|
|
-#define _UTIL_H
|
|
+#ifndef UTIL_H
|
|
+#define UTIL_H
|
|
|
|
#include <stdarg.h>
|
|
#include <stdbool.h>
|
|
@@ -25,15 +25,27 @@
|
|
* 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]))
|
|
|
|
-static inline void __attribute__((noreturn)) die(const char *str, ...)
|
|
+#define stringify(s) stringify_(s)
|
|
+#define stringify_(s) #s
|
|
+
|
|
+static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, str);
|
|
fprintf(stderr, "FATAL ERROR: ");
|
|
vfprintf(stderr, str, ap);
|
|
+ va_end(ap);
|
|
exit(1);
|
|
}
|
|
|
|
@@ -52,12 +64,14 @@ static inline void *xrealloc(void *p, size_t len)
|
|
void *new = realloc(p, len);
|
|
|
|
if (!new)
|
|
- die("realloc() failed (len=%d)\n", len);
|
|
+ die("realloc() failed (len=%zd)\n", len);
|
|
|
|
return new;
|
|
}
|
|
|
|
extern char *xstrdup(const char *s);
|
|
+
|
|
+extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
|
|
extern char *join_path(const char *path, const char *name);
|
|
|
|
/**
|
|
@@ -186,7 +200,7 @@ void utilfdt_print_data(const char *data, int len);
|
|
/**
|
|
* Show source version and exit
|
|
*/
|
|
-void util_version(void) __attribute__((noreturn));
|
|
+void NORETURN util_version(void);
|
|
|
|
/**
|
|
* Show usage and exit
|
|
@@ -200,9 +214,10 @@ void util_version(void) __attribute__((noreturn));
|
|
* @param long_opts The structure of long options
|
|
* @param opts_help An array of help strings (should align with long_opts)
|
|
*/
|
|
-void util_usage(const char *errmsg, const char *synopsis,
|
|
- const char *short_opts, struct option const long_opts[],
|
|
- const char * const opts_help[]) __attribute__((noreturn));
|
|
+void NORETURN util_usage(const char *errmsg, const char *synopsis,
|
|
+ const char *short_opts,
|
|
+ struct option const long_opts[],
|
|
+ const char * const opts_help[]);
|
|
|
|
/**
|
|
* Show usage and exit
|
|
@@ -248,4 +263,4 @@ void util_usage(const char *errmsg, const char *synopsis,
|
|
case 'V': util_version(); \
|
|
case '?': usage("unknown option");
|
|
|
|
-#endif /* _UTIL_H */
|
|
+#endif /* UTIL_H */
|
|
diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h
|
|
index 607afac1c..89d4e0ad1 100644
|
|
--- a/scripts/dtc/version_gen.h
|
|
+++ b/scripts/dtc/version_gen.h
|
|
@@ -1 +1 @@
|
|
-#define DTC_VERSION "DTC 1.4.1"
|
|
+#define DTC_VERSION "DTC 1.4.6"
|
|
--
|
|
2.17.0
|
|
|