summaryrefslogtreecommitdiff
path: root/scripts/dtc/livetree.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/dtc/livetree.c')
-rw-r--r--scripts/dtc/livetree.c166
1 files changed, 103 insertions, 63 deletions
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index 7a2e6446a17b..d51d05830b18 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -1,21 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * 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 the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program 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 program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
*/
#include "dtc.h"
@@ -51,27 +36,27 @@ void delete_labels(struct label **labels)
label->deleted = 1;
}
-struct property *build_property(char *name, struct data val,
+struct property *build_property(const char *name, struct data val,
struct srcpos *srcpos)
{
struct property *new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
- new->name = name;
+ new->name = xstrdup(name);
new->val = val;
new->srcpos = srcpos_copy(srcpos);
return new;
}
-struct property *build_property_delete(char *name)
+struct property *build_property_delete(const char *name)
{
struct property *new = xmalloc(sizeof(*new));
memset(new, 0, sizeof(*new));
- new->name = name;
+ new->name = xstrdup(name);
new->deleted = 1;
return new;
@@ -131,11 +116,11 @@ struct node *build_node_delete(struct srcpos *srcpos)
return new;
}
-struct node *name_node(struct node *node, char *name)
+struct node *name_node(struct node *node, const char *name)
{
assert(node->name == NULL);
- node->name = name;
+ node->name = xstrdup(name);
return node;
}
@@ -189,7 +174,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
old_prop->val = new_prop->val;
old_prop->deleted = 0;
- free(old_prop->srcpos);
+ srcpos_free(old_prop->srcpos);
old_prop->srcpos = new_prop->srcpos;
free(new_prop);
new_prop = NULL;
@@ -249,6 +234,7 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
char *name;
if (ref[0] == '/') {
+ d = data_add_marker(d, TYPE_STRING, ref);
d = data_append_data(d, ref, strlen(ref) + 1);
p = build_property("target-path", d, NULL);
@@ -264,6 +250,7 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
name_node(new_node, "__overlay__");
node = build_node(p, new_node, NULL);
name_node(node, name);
+ free(name);
add_child(dt, node);
return dt;
@@ -350,17 +337,20 @@ void delete_node(struct node *node)
}
void append_to_property(struct node *node,
- char *name, const void *data, int len)
+ char *name, const void *data, int len,
+ enum markertype type)
{
struct data d;
struct property *p;
p = get_property(node, name);
if (p) {
- d = data_append_data(p->val, data, len);
+ d = data_add_marker(p->val, type, name);
+ d = data_append_data(d, data, len);
p->val = d;
} else {
- d = data_append_data(empty_data, data, len);
+ d = data_add_marker(empty_data, type, name);
+ d = data_append_data(d, data, len);
p = build_property(name, d, NULL);
add_property(node, p);
}
@@ -449,9 +439,9 @@ cell_t propval_cell(struct property *prop)
return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
}
-cell_t propval_cell_n(struct property *prop, int n)
+cell_t propval_cell_n(struct property *prop, unsigned int n)
{
- assert(prop->val.len / sizeof(cell_t) >= n);
+ assert(prop->val.len / sizeof(cell_t) > n);
return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
}
@@ -514,7 +504,7 @@ struct node *get_subnode(struct node *node, const char *nodename)
struct node *child;
for_each_child(node, child)
- if (streq(child->name, nodename))
+ if (streq(child->name, nodename) && !child->deleted)
return child;
return NULL;
@@ -537,8 +527,7 @@ struct node *get_node_by_path(struct node *tree, const char *path)
p = strchr(path, '/');
for_each_child(tree, child) {
- if (p && (strlen(child->name) == p-path) &&
- strprefixeq(path, p - path, child->name))
+ if (p && strprefixeq(path, (size_t)(p - path), child->name))
return get_node_by_path(child, p+1);
else if (!p && streq(path, child->name))
return child;
@@ -571,7 +560,7 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
{
struct node *child, *node;
- if ((phandle == 0) || (phandle == -1)) {
+ if (!phandle_is_valid(phandle)) {
assert(generate_fixups);
return NULL;
}
@@ -593,20 +582,62 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
struct node *get_node_by_ref(struct node *tree, const char *ref)
{
+ struct node *target = tree;
+ const char *label = NULL, *path = NULL;
+
if (streq(ref, "/"))
return tree;
- else if (ref[0] == '/')
- return get_node_by_path(tree, ref);
+
+ if (ref[0] == '/')
+ path = ref;
else
- return get_node_by_label(tree, ref);
+ label = ref;
+
+ if (label) {
+ const char *slash = strchr(label, '/');
+ char *buf = NULL;
+
+ if (slash) {
+ buf = xstrndup(label, slash - label);
+ label = buf;
+ path = slash + 1;
+ }
+
+ target = get_node_by_label(tree, label);
+
+ free(buf);
+
+ if (!target)
+ return NULL;
+ }
+
+ if (path)
+ target = get_node_by_path(target, path);
+
+ return target;
+}
+
+static void add_phandle_property(struct node *node,
+ const char *name, int format)
+{
+ struct data d;
+
+ if (!(phandle_format & format))
+ return;
+ if (get_property(node, name))
+ return;
+
+ d = data_add_marker(empty_data, TYPE_UINT32, NULL);
+ d = data_append_cell(d, node->phandle);
+
+ add_property(node, build_property(name, d, NULL));
}
cell_t get_node_phandle(struct node *root, struct node *node)
{
static cell_t phandle = 1; /* FIXME: ick, static local */
- struct data d = empty_data;
- if ((node->phandle != 0) && (node->phandle != -1))
+ if (phandle_is_valid(node->phandle))
return node->phandle;
while (get_node_by_phandle(root, phandle))
@@ -614,16 +645,8 @@ cell_t get_node_phandle(struct node *root, struct node *node)
node->phandle = phandle;
- d = data_add_marker(d, TYPE_UINT32, NULL);
- d = data_append_cell(d, phandle);
-
- if (!get_property(node, "linux,phandle")
- && (phandle_format & PHANDLE_LEGACY))
- add_property(node, build_property("linux,phandle", d, NULL));
-
- if (!get_property(node, "phandle")
- && (phandle_format & PHANDLE_EPAPR))
- add_property(node, build_property("phandle", d, NULL));
+ add_phandle_property(node, "linux,phandle", PHANDLE_LEGACY);
+ add_phandle_property(node, "phandle", PHANDLE_EPAPR);
/* If the node *does* have a phandle property, we must
* be dealing with a self-referencing phandle, which will be
@@ -793,18 +816,18 @@ void sort_tree(struct dt_info *dti)
}
/* utility helper to avoid code duplication */
-static struct node *build_and_name_child_node(struct node *parent, char *name)
+static struct node *build_and_name_child_node(struct node *parent, const char *name)
{
struct node *node;
node = build_node(NULL, NULL, NULL);
- name_node(node, xstrdup(name));
+ name_node(node, name);
add_child(parent, node);
return node;
}
-static struct node *build_root_node(struct node *dt, char *name)
+static struct node *build_root_node(struct node *dt, const char *name)
{
struct node *an;
@@ -858,8 +881,8 @@ static void generate_label_tree_internal(struct dt_info *dti,
/* insert it */
p = build_property(l->label,
- data_copy_mem(node->fullpath,
- strlen(node->fullpath) + 1),
+ data_copy_escape_string(node->fullpath,
+ strlen(node->fullpath)),
NULL);
add_property(an, p);
}
@@ -904,13 +927,19 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn,
/* m->ref can only be a REF_PHANDLE, but check anyway */
assert(m->type == REF_PHANDLE);
+ /* The format only permits fixups for references to label, not
+ * references to path */
+ if (strchr(m->ref, '/'))
+ die("Can't generate fixup for reference to path &{%s}\n",
+ m->ref);
+
/* 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);
+ append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING);
free(entry);
}
@@ -970,7 +999,7 @@ static void add_local_fixup_entry(struct dt_info *dti,
char **compp;
int i, depth;
- /* walk back retreiving depth */
+ /* walk back retrieving depth */
depth = 0;
for (wn = node; wn; wn = wn->parent)
depth++;
@@ -985,15 +1014,13 @@ static void add_local_fixup_entry(struct dt_info *dti,
/* 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]);
+ nwn = build_root_node(wn, compp[i]);
}
free(compp);
value_32 = cpu_to_fdt32(m->offset);
- append_to_property(wn, prop->name, &value_32, sizeof(value_32));
+ append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32);
}
static void generate_local_fixups_tree_internal(struct dt_info *dti,
@@ -1019,7 +1046,7 @@ static void generate_local_fixups_tree_internal(struct dt_info *dti,
generate_local_fixups_tree_internal(dti, lfn, c);
}
-void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
+void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
{
if (!any_label_tree(dti, dti->dt))
return;
@@ -1027,18 +1054,31 @@ void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
dti->dt, allocph);
}
-void generate_fixups_tree(struct dt_info *dti, char *name)
+void generate_fixups_tree(struct dt_info *dti, const char *name)
{
+ struct node *n = get_subnode(dti->dt, name);
+
+ /* Start with an empty __fixups__ node to not get duplicates */
+ if (n)
+ n->deleted = true;
+
if (!any_fixup_tree(dti, dti->dt))
return;
- generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
+ generate_fixups_tree_internal(dti,
+ build_and_name_child_node(dti->dt, name),
dti->dt);
}
-void generate_local_fixups_tree(struct dt_info *dti, char *name)
+void generate_local_fixups_tree(struct dt_info *dti, const char *name)
{
+ struct node *n = get_subnode(dti->dt, name);
+
+ /* Start with an empty __local_fixups__ node to not get duplicates */
+ if (n)
+ n->deleted = true;
if (!any_local_fixup_tree(dti, dti->dt))
return;
- generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
+ generate_local_fixups_tree_internal(dti,
+ build_and_name_child_node(dti->dt, name),
dti->dt);
}