From: Aristo Chen Date: Sun, 14 Sep 2025 10:59:30 +0000 (+0000) Subject: tools: mkimage: detect overlapping load regions in FIT configurations X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=588094f2c8ec9a4f7d2dcda11ffae8db8462149c;p=pandora-u-boot.git tools: mkimage: detect overlapping load regions in FIT configurations This patch adds a validation step in mkimage to detect memory region overlaps between images specified in the same configuration of a FIT image. If any overlaps are found, the tool prints an error and aborts the build. This helps prevent runtime memory corruption caused by conflicting load addresses between images. Signed-off-by: Aristo Chen --- diff --git a/tools/fit_image.c b/tools/fit_image.c index 331be5ae71d..bd849110646 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -22,6 +22,20 @@ #include #include +struct fit_region { + ulong load; + ulong size; + const char *name; +}; + +static int regions_overlap(const struct fit_region *a, const struct fit_region *b) +{ + ulong a_end = a->load + a->size; + ulong b_end = b->load + b->size; + + return !(a_end <= b->load || b_end <= a->load); +} + static struct legacy_img_hdr header; static int fit_estimate_hash_sig_size(struct image_tool_params *params, const char *fname) @@ -775,9 +789,12 @@ static int fit_import_data(struct image_tool_params *params, const char *fname) } fdt_for_each_subnode(node, fdt, confs) { + struct fit_region *regions = NULL; + unsigned int img_count = 0; + unsigned int regions_allocated = 0; const char *conf_name = fdt_get_name(fdt, node, NULL); - for (int i = 0; i < ARRAY_SIZE(props); i++) { + for (unsigned int i = 0; i < ARRAY_SIZE(props); i++) { int count = fdt_stringlist_count(fdt, node, props[i]); if (count < 0) @@ -798,8 +815,79 @@ static int fit_import_data(struct image_tool_params *params, const char *fname) ret = FDT_ERR_NOTFOUND; goto err_munmap; } + + ulong img_load = 0; + int img_size = 0; + + if (fit_image_get_load(fdt, img, &img_load)) { + fprintf(stderr, + "Warning: not able to get `load` of node '%s'\n", + img_name); + // Skip checking the components that do not have a + // definition for `load` + continue; + } + const char *img_data = fdt_getprop(fdt, img, + FIT_DATA_PROP, + &img_size); + + if (!img_data || !img_size) + continue; + + // Check if we've already added this image to avoid duplicates + for (unsigned int k = 0; k < img_count; k++) { + if (!strcmp(regions[k].name, img_name)) + goto next_node; + } + + // Expand regions array if needed + if (img_count >= regions_allocated) { + unsigned int new_size = regions_allocated ? + regions_allocated * 2 : 8; + struct fit_region *new_regions = realloc(regions, + new_size * sizeof(struct fit_region)); + if (!new_regions) { + fprintf(stderr, + "Failed to allocate memory for regions in config %s\n", + fdt_get_name(fdt, node, NULL)); + free(regions); + ret = -ENOMEM; + goto err_munmap; + } + regions = new_regions; + regions_allocated = new_size; + } + + regions[img_count].load = img_load; + regions[img_count].size = img_size; + regions[img_count].name = img_name; + img_count++; +next_node:; + } + } + + // Check for overlap within this config only + for (unsigned int i = 0; i < img_count; i++) { + for (unsigned int j = i + 1; j < img_count; j++) { + if (regions_overlap(®ions[i], ®ions[j])) { + fprintf(stderr, + "[Config: %s] Error: Overlap detected:\n" + " - %s: [0x%lx - 0x%lx]\n" + " - %s: [0x%lx - 0x%lx]\n", + fdt_get_name(fdt, node, NULL), + regions[i].name, regions[i].load, + regions[i].load + regions[i].size, + regions[j].name, regions[j].load, + regions[j].load + regions[j].size); + ret = FDT_ERR_BADSTRUCTURE; + free(regions); + goto err_munmap; + } } } + + // Clean up allocated memory for this configuration + free(regions); } munmap(old_fdt, sbuf.st_size); diff --git a/tools/mkimage.c b/tools/mkimage.c index 361711c53b2..3f28918f5cf 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -520,7 +520,8 @@ int main(int argc, char **argv) retval = tparams->fflag_handle(¶ms); if (retval != EXIT_SUCCESS) { - if (retval == FDT_ERR_NOTFOUND) { + if (retval == FDT_ERR_NOTFOUND || + retval == FDT_ERR_BADSTRUCTURE) { // Already printed error, exit cleanly exit(EXIT_FAILURE); }