From c4aadcb58906f4a4c0bd120dbadb65df1f84b94c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 21 Oct 2024 09:23:56 +0200 Subject: [PATCH] Restore phandle references from __local_fixups__ node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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: 915daadbb62d ("Start with empty __local_fixups__ and __fixups__ nodes") Signed-off-by: Uwe Kleine-König --- dtc.c | 2 ++ dtc.h | 2 ++ livetree.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ treesource.c | 33 ++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) diff --git a/dtc.c b/dtc.c index 63a6c85..9f90b37 100644 --- a/dtc.c +++ b/dtc.c @@ -343,6 +343,8 @@ int main(int argc, char *argv[]) if (generate_symbols) generate_label_tree(dti, "__symbols__", true); + local_fixup_phandles(dti, "__local_fixups__"); + if (generate_fixups) { generate_fixups_tree(dti, "__fixups__"); generate_local_fixups_tree(dti, "__local_fixups__"); diff --git a/dtc.h b/dtc.h index f97f3c2..d07a583 100644 --- a/dtc.h +++ b/dtc.h @@ -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_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 */ @@ -358,6 +359,7 @@ struct dt_info *dt_from_blob(const char *fname); /* 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); struct dt_info *dt_from_source(const char *f); diff --git a/livetree.c b/livetree.c index cc54f97..10b767d 100644 --- a/livetree.c +++ b/livetree.c @@ -1103,3 +1103,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); +} diff --git a/treesource.c b/treesource.c index 5764959..5b8d7a6 100644 --- a/treesource.c +++ b/treesource.c @@ -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); } +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) { const char *p = prop->val.val + offset;