Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions dtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,9 +338,14 @@ int main(int argc, char *argv[])
if (auto_label_aliases)
generate_label_tree(dti, "aliases", false);

generate_labels_from_tree(dti, "__symbols__");

if (generate_symbols)
generate_label_tree(dti, "__symbols__", true);

fixup_phandles(dti, "__fixups__");
local_fixup_phandles(dti, "__local_fixups__");

if (generate_fixups) {
generate_fixups_tree(dti, "__fixups__");
generate_local_fixups_tree(dti, "__local_fixups__");
Expand Down
6 changes: 6 additions & 0 deletions dtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,9 +339,12 @@ 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_labels_from_tree(struct dt_info *dti, const char *name);
void generate_label_tree(struct dt_info *dti, const char *name, bool allocph);
void generate_fixups_tree(struct dt_info *dti, const char *name);
void fixup_phandles(struct dt_info *dti, const char *name);
void generate_local_fixups_tree(struct dt_info *dti, const char *name);
void local_fixup_phandles(struct dt_info *dti, const char *name);

/* Checks */

Expand All @@ -357,6 +360,9 @@ struct dt_info *dt_from_blob(const char *fname);

/* Tree source */

void property_add_marker(struct property *prop,
enum markertype type, unsigned int offset, char *ref);
void add_phandle_marker(struct dt_info *dti, struct property *prop, unsigned int offset);
void dt_to_source(FILE *f, struct dt_info *dti);
struct dt_info *dt_from_source(const char *f);

Expand Down
6 changes: 5 additions & 1 deletion flattree.c
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,7 @@ struct dt_info *dt_from_blob(const char *fname)
struct node *tree;
uint32_t val;
int flags = 0;
unsigned int dtsflags = DTSF_V1;

f = srcfile_relative_open(fname, NULL);

Expand Down Expand Up @@ -919,5 +920,8 @@ struct dt_info *dt_from_blob(const char *fname)

fclose(f);

return build_dt_info(DTSF_V1, reservelist, tree, boot_cpuid_phys);
if (get_subnode(tree, "__fixups__") || get_subnode(tree, "__local_fixups__"))
dtsflags |= DTSF_PLUGIN;

return build_dt_info(dtsflags, reservelist, tree, boot_cpuid_phys);
}
174 changes: 174 additions & 0 deletions livetree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1046,6 +1046,27 @@ static void generate_local_fixups_tree_internal(struct dt_info *dti,
generate_local_fixups_tree_internal(dti, lfn, c);
}

void generate_labels_from_tree(struct dt_info *dti, const char *name)
{
struct node *an;
struct property *p;

an = get_subnode(dti->dt, name);
if (!an)
return;

for_each_property(an, p) {
struct node *labeled_node;

labeled_node = get_node_by_path(dti->dt, p->val.val);
if (labeled_node)
add_label(&labeled_node->labels, p->name);
else if (quiet < 1)
fprintf(stderr, "Warning: Path %s referenced in property %s/%s missing",
p->val.val, name, p->name);
}
}

void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
{
if (!any_label_tree(dti, dti->dt))
Expand All @@ -1069,6 +1090,102 @@ void generate_fixups_tree(struct dt_info *dti, const char *name)
dti->dt);
}

void fixup_phandles(struct dt_info *dti, const char *name)
{
struct node *an;
struct property *fp;

an = get_subnode(dti->dt, name);
if (!an)
return;

for_each_property(an, fp) {
char *fnext = fp->val.val;
char *fv;
unsigned int fl;

while ((fl = fp->val.len - (fnext - fp->val.val))) {
char *propname, *soffset;
struct node *n;
struct property *p;
long offset;

fv = fnext;
fnext = memchr(fv, 0, fl);

if (!fnext) {
if (quiet < 1)
fprintf(stderr, "Warning: Malformed fixup entry for label %s\n",
fp->name);
break;
}
fnext += 1;

propname = memchr(fv, ':', fnext - 1 - fv);
if (!propname) {
if (quiet < 1)
fprintf(stderr, "Warning: Malformed fixup entry for label %s\n",
fp->name);
continue;
}
propname++;

soffset = memchr(propname, ':', fnext - 1 - propname);
if (!soffset) {
if (quiet < 1)
fprintf(stderr, "Warning: Malformed fixup entry for label %s\n",
fp->name);
continue;
}
soffset++;

/*
* temporarily modify the property to not have to create
* a copy for the node path.
*/
*(propname - 1) = '\0';

n = get_node_by_path(dti->dt, fv);
if (!n && quiet < 1)
fprintf(stderr, "Warning: Label %s references non-existing node %s\n",
fp->name, fv);

*(propname - 1) = ':';

if (!n)
continue;

/*
* temporarily modify the property to not have to create
* a copy for the property name.
*/
*(soffset - 1) = '\0';

p = get_property(n, propname);

if (!p && quiet < 1)
fprintf(stderr, "Warning: Label %s references non-existing property %s in node %s\n",
fp->name, n->fullpath, propname);

*(soffset - 1) = ':';

if (!p)
continue;

offset = strtol(soffset, NULL, 0);
if (offset < 0 || offset + 4 > p->val.len) {
if (quiet < 1)
fprintf(stderr,
"Warning: Label %s contains invalid offset for property %s in node %s\n",
fp->name, p->name, n->fullpath);
continue;
}

property_add_marker(p, REF_PHANDLE, offset, fp->name);
}
}
}

void generate_local_fixups_tree(struct dt_info *dti, const char *name)
{
struct node *n = get_subnode(dti->dt, name);
Expand All @@ -1082,3 +1199,60 @@ void generate_local_fixups_tree(struct dt_info *dti, const char *name)
build_and_name_child_node(dti->dt, name),
dti->dt);
}

static void local_fixup_phandles_node(struct dt_info *dti, struct node *lf, struct node *n)
{
struct property *lfp;
struct node *lfsubnode;

for_each_property(lf, lfp) {
struct property *p = get_property(n, lfp->name);
fdt32_t *offsets = (fdt32_t *)lfp->val.val;
size_t i;

if (!p) {
if (quiet < 1)
fprintf(stderr, "Warning: Property %s in %s referenced in __local_fixups__ missing\n",
lfp->name, n->fullpath);
continue;
}

/*
* Each property in the __local_fixups__ tree is a concatenation
* of offsets, so it must be a multiple of sizeof(fdt32_t).
*/
if (lfp->val.len % sizeof(fdt32_t)) {
if (quiet < 1)
fprintf(stderr, "Warning: property %s in /__local_fixups__%s malformed\n",
lfp->name, n->fullpath);
continue;
}

for (i = 0; i < lfp->val.len / sizeof(fdt32_t); i++)
add_phandle_marker(dti, p, dtb_ld32(offsets + i));
}

for_each_child(lf, lfsubnode) {
struct node *subnode = get_subnode(n, lfsubnode->name);

if (!subnode) {
if (quiet < 1)
fprintf(stderr, "Warning: node %s/%s referenced in __local_fixups__ missing\n",
lfsubnode->name, n->fullpath);
continue;
}

local_fixup_phandles_node(dti, lfsubnode, subnode);
}
}

void local_fixup_phandles(struct dt_info *dti, const char *name)
{
struct node *an;

an = get_subnode(dti->dt, name);
if (!an)
return;

local_fixup_phandles_node(dti, an, dti->dt);
}
23 changes: 23 additions & 0 deletions tests/over-determined.dts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/dts-v1/;
/plugin/;

/ {
labelfornodea: nodea {
property = <&labelfornodea>;
};

nodeb {
property = <&nonexisting>;
};

__fixups__ {
nonexisting = "/nodeb:property:0";
};

__local_fixups__ {
nodea {
property = <0>;
};
};
};

4 changes: 4 additions & 0 deletions tests/run_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,10 @@ dtc_tests () {
run_dtc_test -I dts -O dtb -o dtc_sized_cells.test.dtb "$SRCDIR/sized_cells.dts"
run_test sized_cells dtc_sized_cells.test.dtb

run_dtc_test -I dts -O dts -o over-determined-once.test.dts "$SRCDIR/over-determined.dts"
run_dtc_test -I dts -O dts -o over-determined-twice.test.dts "over-determined-once.test.dts"
run_wrap_test cmp over-determined-once.test.dts over-determined-twice.test.dts

run_dtc_test -I dts -O dtb -o dtc_extra-terminating-null.test.dtb "$SRCDIR/extra-terminating-null.dts"
run_test extra-terminating-null dtc_extra-terminating-null.test.dtb

Expand Down
Loading