Restore phandle references from __local_fixups__ node

The __local_fixups__ node contains information about phandles. Parse it
to improve the result when decompiling a device tree blob.

Note that this is essential to do before the __local_fixups__ node is
removed in generate_local_fixups_tree() because otherwise the
information contained in that node is lost.

Fixes: 915daadbb6 ("Start with empty __local_fixups__ and __fixups__ nodes")
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
This commit is contained in:
Uwe Kleine-König 2024-10-21 09:23:56 +02:00
parent 6a6f5aecd4
commit c4aadcb589
4 changed files with 94 additions and 0 deletions

2
dtc.c
View file

@ -343,6 +343,8 @@ int main(int argc, char *argv[])
if (generate_symbols) if (generate_symbols)
generate_label_tree(dti, "__symbols__", true); generate_label_tree(dti, "__symbols__", true);
local_fixup_phandles(dti, "__local_fixups__");
if (generate_fixups) { if (generate_fixups) {
generate_fixups_tree(dti, "__fixups__"); generate_fixups_tree(dti, "__fixups__");
generate_local_fixups_tree(dti, "__local_fixups__"); generate_local_fixups_tree(dti, "__local_fixups__");

2
dtc.h
View file

@ -343,6 +343,7 @@ 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_label_tree(struct dt_info *dti, const char *name, bool allocph);
void generate_fixups_tree(struct dt_info *dti, const char *name); void generate_fixups_tree(struct dt_info *dti, const char *name);
void generate_local_fixups_tree(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 */ /* Checks */
@ -358,6 +359,7 @@ struct dt_info *dt_from_blob(const char *fname);
/* Tree source */ /* Tree source */
void add_phandle_marker(struct dt_info *dti, struct property *prop, unsigned int offset);
void dt_to_source(FILE *f, struct dt_info *dti); void dt_to_source(FILE *f, struct dt_info *dti);
struct dt_info *dt_from_source(const char *f); struct dt_info *dt_from_source(const char *f);

View file

@ -1103,3 +1103,60 @@ void generate_local_fixups_tree(struct dt_info *dti, const char *name)
build_and_name_child_node(dti->dt, name), build_and_name_child_node(dti->dt, name),
dti->dt); 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);
}

View file

@ -183,6 +183,39 @@ static void add_string_markers(struct property *prop, unsigned int offset, int l
mi = add_marker(mi, TYPE_STRING, offset + l, NULL); mi = add_marker(mi, TYPE_STRING, offset + l, NULL);
} }
void add_phandle_marker(struct dt_info *dti, struct property *prop, unsigned int offset)
{
cell_t phandle;
struct node *refn;
char *ref;
if (prop->val.len < offset + 4) {
if (quiet < 1)
fprintf(stderr,
"Warning: property %s too short to contain a phandle at offset %u\n",
prop->name, offset);
}
phandle = dtb_ld32(prop->val.val + offset);
refn = get_node_by_phandle(dti->dt, phandle);
if (!refn) {
if (quiet < 1)
fprintf(stderr,
"Warning: node referenced by phandle 0x%x in property %s not found\n",
phandle, prop->name);
return;
}
if (refn->labels)
ref = refn->labels->label;
else
ref = refn->fullpath;
add_marker(&prop->val.markers, REF_PHANDLE, offset, ref);
}
static enum markertype guess_value_type(struct property *prop, unsigned int offset, int len) static enum markertype guess_value_type(struct property *prop, unsigned int offset, int len)
{ {
const char *p = prop->val.val + offset; const char *p = prop->val.val + offset;