Restore phandle references from __fixups__ node

The __fixups__ node contains information about labels. Parse its
properties to create phandle markers which improve the resulting dts
when decompiling a device tree blob.

Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Message-ID: <20250919092912.663304-14-u.kleine-koenig@baylibre.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
main
Uwe Kleine-König 2025-09-19 11:29:19 +02:00 committed by David Gibson
parent 05c524db44
commit a26ef6400b
4 changed files with 106 additions and 0 deletions

1
dtc.c
View File

@ -343,6 +343,7 @@ int main(int argc, char *argv[])
if (generate_symbols)
generate_label_tree(dti, "__symbols__", true);

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

if (generate_fixups) {

3
dtc.h
View File

@ -342,6 +342,7 @@ 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);

@ -359,6 +360,8 @@ 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);

View File

@ -1151,6 +1151,102 @@ void generate_fixups_tree(struct dt_info *dti, const char *name)
name);
}

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)
{
if (!any_local_fixup_tree(dti, dti->dt))

View File

@ -173,6 +173,12 @@ static struct marker **add_marker(struct marker **mi,
return &nm->next;
}

void property_add_marker(struct property *prop,
enum markertype type, unsigned int offset, char *ref)
{
add_marker(&prop->val.markers, type, offset, ref);
}

static void add_string_markers(struct property *prop, unsigned int offset, int len)
{
int l;