* [PATCH v2 01/13] FIT: implement fit_count_images
2026-02-09 18:10 [PATCH v2 00/13] bootm: prepare loadable abstraction rework Ahmad Fatoum
@ 2026-02-09 18:10 ` Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 02/13] FIT: add image index argument to fit_open_image Ahmad Fatoum
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2026-02-09 18:10 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
A FIT image can contain multiple images of the same type, e.g. a device
tree followed by overlays or multiple initrds.
To allow checking for that case, let's implement fit_count_images().
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/image-fit.c | 12 ++++--------
include/image-fit.h | 27 +++++++++++++++++++++++++--
2 files changed, 29 insertions(+), 10 deletions(-)
diff --git a/common/image-fit.c b/common/image-fit.c
index 26bd8e265b25..85096aff31e6 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -495,19 +495,15 @@ static int fit_image_verify_signature(struct fit_handle *handle,
return ret;
}
-bool fit_has_image(struct fit_handle *handle, void *configuration,
- const char *name)
+int fit_count_images(struct fit_handle *handle, void *configuration,
+ const char *name)
{
- const char *unit;
struct device_node *conf_node = configuration;
if (!conf_node)
- return false;
+ return -EINVAL;
- if (of_property_read_string(conf_node, name, &unit))
- return false;
-
- return true;
+ return of_property_count_strings(conf_node, name);
}
static int fit_get_address(struct device_node *image, const char *property,
diff --git a/include/image-fit.h b/include/image-fit.h
index c332f77bd374..31b8b54e272d 100644
--- a/include/image-fit.h
+++ b/include/image-fit.h
@@ -34,8 +34,31 @@ struct fit_handle *fit_open_buf(const void *buf, size_t len, bool verbose,
void *fit_open_configuration(struct fit_handle *handle, const char *name,
bool (*match_valid)(struct fit_handle *handle,
struct device_node *config));
-bool fit_has_image(struct fit_handle *handle, void *configuration,
- const char *name);
+/**
+ * fit_count_images() - count images of a given type in a FIT configuration
+ * @handle: FIT handle as returned by fit_open() or fit_open_buf()
+ * @configuration: configuration node as returned by fit_open_configuration()
+ * @name: image type property name (e.g., "kernel", "fdt", "ramdisk")
+ *
+ * Return: number of images on success, negative error code on failure
+ */
+int fit_count_images(struct fit_handle *handle, void *configuration,
+ const char *name);
+
+/**
+ * fit_has_image() - check if a FIT configuration contains an image type
+ * @handle: FIT handle as returned by fit_open() or fit_open_buf()
+ * @configuration: configuration node as returned by fit_open_configuration()
+ * @name: image type property name (e.g., "kernel", "fdt", "ramdisk")
+ *
+ * Return: true if at least one image of the given type exists, false otherwise
+ */
+static inline bool fit_has_image(struct fit_handle *handle, void *configuration,
+ const char *name)
+{
+ return fit_count_images(handle, configuration, name) > 0;
+}
+
int fit_open_image(struct fit_handle *handle, void *configuration,
const char *name, const void **outdata,
unsigned long *outsize);
--
2.47.3
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v2 02/13] FIT: add image index argument to fit_open_image
2026-02-09 18:10 [PATCH v2 00/13] bootm: prepare loadable abstraction rework Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 01/13] FIT: implement fit_count_images Ahmad Fatoum
@ 2026-02-09 18:10 ` Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 03/13] resource: implement gap-aware lookup_region Ahmad Fatoum
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2026-02-09 18:10 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
A FIT configuration can specify multiple images of the same type, e.g.
for device tree overlays. Add an index parameter to fit_open_image()
to allow callers to select which image to open. Existing callers pass
idx=0 to maintain current behavior of opening the first image.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/arm/lib32/bootm.c | 2 +-
common/bootm-fit.c | 6 ++---
common/image-fit.c | 50 ++++++++++++++++++++----------------------
drivers/of/overlay.c | 2 +-
efi/payload/bootm.c | 4 ++--
include/image-fit.h | 4 ++--
6 files changed, 33 insertions(+), 35 deletions(-)
diff --git a/arch/arm/lib32/bootm.c b/arch/arm/lib32/bootm.c
index 533c3ea946ff..e659d3c1a554 100644
--- a/arch/arm/lib32/bootm.c
+++ b/arch/arm/lib32/bootm.c
@@ -178,7 +178,7 @@ static int bootm_load_tee_from_fit(struct image_data *data)
const void *tee;
unsigned long tee_size;
- ret = fit_open_image(data->os_fit, data->fit_config, "tee",
+ ret = fit_open_image(data->os_fit, data->fit_config, "tee", 0,
&tee, &tee_size);
if (ret) {
pr_err("Error opening tee fit image: %pe\n", ERR_PTR(ret));
diff --git a/common/bootm-fit.c b/common/bootm-fit.c
index 3b2252ca8810..a0e808e31b40 100644
--- a/common/bootm-fit.c
+++ b/common/bootm-fit.c
@@ -61,7 +61,7 @@ struct resource *bootm_load_fit_initrd(struct image_data *data, unsigned long lo
if (!fitconfig_has_ramdisk(data))
return NULL;
- ret = fit_open_image(data->os_fit, data->fit_config, "ramdisk",
+ ret = fit_open_image(data->os_fit, data->fit_config, "ramdisk", 0,
&initrd, &initrd_size);
if (ret) {
pr_err("Cannot open ramdisk image in FIT image: %pe\n",
@@ -96,7 +96,7 @@ void *bootm_get_fit_devicetree(struct image_data *data)
const void *of_tree;
unsigned long of_size;
- ret = fit_open_image(data->os_fit, data->fit_config, "fdt",
+ ret = fit_open_image(data->os_fit, data->fit_config, "fdt", 0,
&of_tree, &of_size);
if (ret)
return ERR_PTR(ret);
@@ -144,7 +144,7 @@ int bootm_open_fit(struct image_data *data)
return PTR_ERR(data->fit_config);
}
- ret = fit_open_image(data->os_fit, data->fit_config, kernel_img,
+ ret = fit_open_image(data->os_fit, data->fit_config, kernel_img, 0,
&data->fit_kernel, &data->fit_kernel_size);
if (ret)
return ret;
diff --git a/common/image-fit.c b/common/image-fit.c
index 85096aff31e6..75592766941c 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -522,24 +522,20 @@ static int fit_get_address(struct device_node *image, const char *property,
return 0;
}
-static int
+static struct device_node *
fit_get_image(struct fit_handle *handle, void *configuration,
- const char **unit, struct device_node **image)
+ const char **unit, int idx)
{
struct device_node *conf_node = configuration;
if (conf_node) {
- if (of_property_read_string(conf_node, *unit, unit)) {
+ if (of_property_read_string_index(conf_node, *unit, idx, unit)) {
pr_err("No image named '%s'\n", *unit);
- return -ENOENT;
+ return NULL;
}
}
- *image = of_get_child_by_name(handle->images, *unit);
- if (!*image)
- return -ENOENT;
-
- return 0;
+ return of_get_child_by_name(handle->images, *unit);
}
/**
@@ -569,9 +565,9 @@ int fit_get_image_address(struct fit_handle *handle, void *configuration,
if (!address || !property || !name)
return -EINVAL;
- ret = fit_get_image(handle, configuration, &unit, &image);
- if (ret)
- return ret;
+ image = fit_get_image(handle, configuration, &unit, 0);
+ if (!image)
+ return -ENOENT;
/* Treat type = "kernel_noload" as if entry/load address is missing */
ret = of_property_read_string(image, "type", &type);
@@ -647,22 +643,22 @@ static int fit_handle_decompression(struct device_node *image,
/**
* fit_open_image - Open an image in a FIT image
* @handle: The FIT image handle
+ * @configuration: configuration cookie from fit_open_configuration(), or NULL
* @name: The name of the image to open
+ * @idx: The index of image to open (for multi-image properties like overlays)
* @outdata: The returned image
* @outsize: Size of the returned image
*
* Open an image in a FIT image. The returned image is freed during fit_close().
- * @configuration holds the cookie returned from fit_open_configuration() if
- * the image is opened as part of a configuration, or NULL if the image is
- * opened without a configuration. If @configuration is NULL then the RSA
- * signature of the image is checked if desired, if @configuration is non NULL,
- * then only the hash is checked (because opening the configuration already
- * checks the RSA signature of all involved nodes).
+ *
+ * If @configuration is NULL then the RSA signature of the image is checked
+ * if desired; otherwise only the hash is checked (because opening the
+ * configuration already checks the RSA signature of all involved nodes).
*
* Return: 0 for success, negative error code otherwise
*/
int fit_open_image(struct fit_handle *handle, void *configuration,
- const char *name, const void **outdata,
+ const char *name, int idx, const void **outdata,
unsigned long *outsize)
{
struct device_node *image;
@@ -671,9 +667,9 @@ int fit_open_image(struct fit_handle *handle, void *configuration,
int data_len;
int ret = 0;
- ret = fit_get_image(handle, configuration, &unit, &image);
- if (ret)
- return ret;
+ image = fit_get_image(handle, configuration, &unit, idx);
+ if (!image)
+ return -ENOENT;
of_property_read_string(image, "description", &desc);
if (handle->verbose)
@@ -765,9 +761,11 @@ static int fit_fdt_is_compatible(struct fit_handle *handle,
if (!of_property_present(child, "fdt"))
return 0;
- ret = fit_get_image(handle, child, &unit, &image);
- if (ret)
+ image = fit_get_image(handle, child, &unit, 0);
+ if (!image) {
+ ret = -ENOENT;
goto err;
+ }
data = of_get_property(image, "data", &data_len);
if (!data)
@@ -1134,14 +1132,14 @@ static int fuzz_fit(const u8 *data, size_t size)
goto out;
}
- ret = fit_open_image(&handle, config, imgname, &outdata, &outsize);
+ ret = fit_open_image(&handle, config, imgname, 0, &outdata, &outsize);
if (ret)
goto out;
fit_get_image_address(&handle, config, imgname, "load", &addr);
fit_get_image_address(&handle, config, imgname, "entry", &addr);
- ret = fit_open_image(&handle, NULL, imgname, &outdata, &outsize);
+ ret = fit_open_image(&handle, NULL, imgname, 0, &outdata, &outsize);
out:
__fit_close(&handle);
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index d2cf2fa3f371..b11edebd2080 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -487,7 +487,7 @@ static int of_overlay_apply_fit(struct device_node *root, struct fit_handle *fit
if (!of_overlay_matches_filter(name, NULL))
return 0;
- ret = fit_open_image(fit, config, "fdt", &ovl, &ovl_sz);
+ ret = fit_open_image(fit, config, "fdt", 0, &ovl, &ovl_sz);
if (ret)
return ret;
diff --git a/efi/payload/bootm.c b/efi/payload/bootm.c
index f4e6e6324bcd..617f5610e745 100644
--- a/efi/payload/bootm.c
+++ b/efi/payload/bootm.c
@@ -129,7 +129,7 @@ static int efi_load_ramdisk(struct image_data *data, void **initrd)
int ret;
if (ramdisk_is_fit(data)) {
- ret = fit_open_image(data->os_fit, data->fit_config, "ramdisk",
+ ret = fit_open_image(data->os_fit, data->fit_config, "ramdisk", 0,
(const void **)&initrd_mem, &initrd_size);
if (ret) {
pr_err("Cannot open ramdisk image in FIT image: %m\n");
@@ -175,7 +175,7 @@ static int efi_load_fdt(struct image_data *data, void **fdt)
int ret;
if (fdt_is_fit(data)) {
- ret = fit_open_image(data->os_fit, data->fit_config, "fdt",
+ ret = fit_open_image(data->os_fit, data->fit_config, "fdt", 0,
(const void **)&of_tree, &of_size);
if (ret) {
pr_err("Cannot open FDT image in FIT image: %m\n");
diff --git a/include/image-fit.h b/include/image-fit.h
index 31b8b54e272d..50f0482b65ad 100644
--- a/include/image-fit.h
+++ b/include/image-fit.h
@@ -60,8 +60,8 @@ static inline bool fit_has_image(struct fit_handle *handle, void *configuration,
}
int fit_open_image(struct fit_handle *handle, void *configuration,
- const char *name, const void **outdata,
- unsigned long *outsize);
+ const char *name, int idx,
+ const void **outdata, unsigned long *outsize);
int fit_get_image_address(struct fit_handle *handle, void *configuration,
const char *name, const char *property,
unsigned long *address);
--
2.47.3
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v2 03/13] resource: implement gap-aware lookup_region
2026-02-09 18:10 [PATCH v2 00/13] bootm: prepare loadable abstraction rework Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 01/13] FIT: implement fit_count_images Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 02/13] FIT: add image index argument to fit_open_image Ahmad Fatoum
@ 2026-02-09 18:10 ` Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 04/13] bootm: give bootm_load_ functions an end address Ahmad Fatoum
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2026-02-09 18:10 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The incoming bootm rework hinges on being able to determine how much
total space there is for boot artifacts. For that purpose, add
memory_bank_lookup_region(), which will return the gap or the resource a
specified address resides in.
While at it, give the local variable two leading __, so it's less likely
to mask local variables.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/memory.c | 25 +++++++++++++++++++++++++
common/resource.c | 33 +++++++++++++++++++++++++++++++++
include/linux/ioport.h | 11 +++++++----
include/memory.h | 2 ++
4 files changed, 67 insertions(+), 4 deletions(-)
diff --git a/common/memory.c b/common/memory.c
index 1c18c5b38710..b61df68e02dc 100644
--- a/common/memory.c
+++ b/common/memory.c
@@ -410,6 +410,31 @@ int memory_bank_first_find_space(resource_size_t *retstart,
return -ENOENT;
}
+/**
+ * memory_bank_lookup_region - find the memory region containing a given address
+ * @addr: physical address to look up
+ * @gap: if non-NULL and addr is in a gap, the gap info is copied here
+ *
+ * Searches all memory banks for the region containing @addr. If @addr falls
+ * within a gap between allocated regions and @gap is provided, the gap
+ * boundaries are returned via @gap.
+ *
+ * Return: pointer to the resource containing @addr, @gap if in a gap,
+ * or NULL if not found in any memory bank
+ */
+struct resource *memory_bank_lookup_region(resource_size_t addr, struct resource *gap)
+{
+ struct memory_bank *bank;
+
+ for_each_memory_bank(bank) {
+ if (addr < bank->res->start || bank->res->end < addr)
+ continue;
+ return lookup_region(bank->res, addr, gap);
+ }
+
+ return NULL;
+}
+
#ifdef CONFIG_OFTREE
static int of_memory_fixup(struct device_node *root, void *unused)
diff --git a/common/resource.c b/common/resource.c
index 33eb122f4668..e391d268e0bb 100644
--- a/common/resource.c
+++ b/common/resource.c
@@ -417,6 +417,39 @@ resource_iter_prev(struct resource *current,
return resource_iter_gap(parent, prev, gap, current);
}
+/**
+ * lookup_region - find the region containing a given address
+ * @parent: parent resource to search within
+ * @addr: address to look up
+ * @gap: if non-NULL and addr is in a gap, the gap info is copied here
+ *
+ * Searches the children of @parent (and gaps between them) for the region
+ * containing @addr.
+ *
+ * Return: pointer to the resource containing @addr, or @gap if @addr is in
+ * a gap and @gap is non-NULL, or NULL if @addr is not found or is
+ * in a gap and @gap is NULL
+ */
+struct resource *lookup_region(struct resource *parent,
+ resource_size_t addr, struct resource *gap)
+{
+ for_each_resource_region(parent, region) {
+ if (addr < region->start || region->end < addr)
+ continue;
+
+ if (!region_is_gap(region))
+ return region;
+ if (!gap)
+ return NULL;
+
+ *gap = *region;
+ INIT_LIST_HEAD(&gap->sibling);
+ return gap;
+ }
+
+ return NULL;
+}
+
struct resource_entry *resource_list_create_entry(struct resource *res,
size_t extra_size)
{
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 20c72e1b6cbb..5baae0dae10a 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -279,14 +279,17 @@ struct resource *resource_iter_last(struct resource *current, struct resource *g
struct resource *resource_iter_prev(struct resource *current, struct resource *gap);
struct resource *resource_iter_next(struct resource *current, struct resource *gap);
+struct resource *lookup_region(struct resource *parent,
+ resource_size_t addr, struct resource *gap);
+
/**
* for_each_resource_region - Iterate over child resources and gaps between them
* @parent: parent resource
* @region: pointer to child resource or gap
*/
#define for_each_resource_region(parent, region) \
- for (struct resource gap, *region = resource_iter_first((parent), &gap); \
- region; region = resource_iter_next(region, &gap))
+ for (struct resource __gap, *region = resource_iter_first((parent), &__gap); \
+ region; region = resource_iter_next(region, &__gap))
/**
* for_each_resource_region_reverse - Reverse iterate over child resources and gaps between them
@@ -294,8 +297,8 @@ struct resource *resource_iter_next(struct resource *current, struct resource *g
* @region: pointer to child resource or gap
*/
#define for_each_resource_region_reverse(parent, region) \
- for (struct resource gap, *region = resource_iter_last((parent), &gap); \
- region; region = resource_iter_prev(region, &gap))
+ for (struct resource __gap, *region = resource_iter_last((parent), &__gap); \
+ region; region = resource_iter_prev(region, &__gap))
#endif /* __ASSEMBLY__ */
#endif /* _LINUX_IOPORT_H */
diff --git a/include/memory.h b/include/memory.h
index 6b7ada641c9d..92483c39b0f4 100644
--- a/include/memory.h
+++ b/include/memory.h
@@ -97,6 +97,8 @@ void memory_bank_find_space(struct memory_bank *bank, resource_size_t *retstart,
int memory_bank_first_find_space(resource_size_t *retstart,
resource_size_t *retend);
+struct resource *memory_bank_lookup_region(resource_size_t addr, struct resource *gap);
+
static inline u64 memory_sdram_size(unsigned int cols,
unsigned int rows,
unsigned int banks,
--
2.47.3
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v2 04/13] bootm: give bootm_load_ functions an end address
2026-02-09 18:10 [PATCH v2 00/13] bootm: prepare loadable abstraction rework Ahmad Fatoum
` (2 preceding siblings ...)
2026-02-09 18:10 ` [PATCH v2 03/13] resource: implement gap-aware lookup_region Ahmad Fatoum
@ 2026-02-09 18:10 ` Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 05/13] bootm: store separate image_type and kernel_type Ahmad Fatoum
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2026-02-09 18:10 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
So far we expected that a load operation will not overflow, but there
was actually no way for the callee to check this.
As the architecture-specific bootm handlers are tasked with allocating
memory for boot artifacts have them pass along not only the start of the
load region, but also its end, so the callee can check that it didn't
overflow.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/arm/lib32/bootm.c | 24 +++++---
arch/arm/lib64/armlinux.c | 14 ++---
arch/arm/mach-at91/bootm-barebox.c | 7 ++-
arch/arm/mach-imx/imx-v3-image.c | 7 ++-
arch/arm/mach-layerscape/pblimage.c | 7 ++-
arch/arm/mach-rockchip/bootm.c | 13 ++--
arch/arm/mach-zynq/bootm-zynqimg.c | 7 ++-
arch/kvx/lib/bootm.c | 17 ++++--
arch/powerpc/lib/ppclinux.c | 13 +++-
common/booti.c | 30 +++++----
common/bootm.c | 95 ++++++++++++++++++-----------
efi/loader/bootm.c | 37 ++++++-----
include/bootm.h | 13 ++--
13 files changed, 171 insertions(+), 113 deletions(-)
diff --git a/arch/arm/lib32/bootm.c b/arch/arm/lib32/bootm.c
index e659d3c1a554..22364beadcd5 100644
--- a/arch/arm/lib32/bootm.c
+++ b/arch/arm/lib32/bootm.c
@@ -236,7 +236,8 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem,
{
unsigned long kernel;
unsigned long initrd_start = 0, initrd_size = 0, initrd_end = 0;
- const struct resource *initrd_res;
+ const struct resource *initrd_res, *sdram;
+ struct resource gap;
void *tee;
enum arm_security_state state = bootm_arm_security_state();
void *fdt_load_address = NULL;
@@ -255,7 +256,11 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem,
}
}
- initrd_res = bootm_load_initrd(data, initrd_start);
+ sdram = memory_bank_lookup_region(initrd_start, &gap);
+ if (sdram != &gap)
+ return sdram ? -EBUSY : -EINVAL;
+
+ initrd_res = bootm_load_initrd(data, initrd_start, gap.end);
if (IS_ERR(initrd_res)) {
return PTR_ERR(initrd_res);
} else if (initrd_res) {
@@ -277,13 +282,15 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem,
}
if (fdt) {
+ const struct resource *fdt_res;
+
fdt_load_address = (void *)free_mem;
- ret = bootm_load_devicetree(data, fdt, free_mem);
+ fdt_res = bootm_load_devicetree(data, fdt, free_mem, gap.end);
free(fdt);
- if (ret)
- return ret;
+ if (IS_ERR(fdt_res))
+ return PTR_ERR(fdt_res);
}
if (IS_ENABLED(CONFIG_BOOTM_OPTEE)) {
@@ -339,6 +346,7 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem,
static int do_bootm_linux(struct image_data *data)
{
+ const struct resource *os_res;
unsigned long load_address, mem_free;
int ret;
@@ -349,9 +357,9 @@ static int do_bootm_linux(struct image_data *data)
if (ret)
return ret;
- ret = bootm_load_os(data, load_address);
- if (ret)
- return ret;
+ os_res = bootm_load_os(data, load_address, mem_free - 1);
+ if (IS_ERR(os_res))
+ return PTR_ERR(os_res);
return __do_bootm_linux(data, mem_free, 0, NULL);
}
diff --git a/arch/arm/lib64/armlinux.c b/arch/arm/lib64/armlinux.c
index e40b61a26b07..4dbe0b03b420 100644
--- a/arch/arm/lib64/armlinux.c
+++ b/arch/arm/lib64/armlinux.c
@@ -43,19 +43,20 @@ static int do_bootm_barebox(struct image_data *data)
{
void (*fn)(unsigned long x0, unsigned long x1, unsigned long x2,
unsigned long x3);
+ const struct resource *os_res;
resource_size_t start, end;
unsigned long barebox;
int ret;
ret = memory_bank_first_find_space(&start, &end);
if (ret)
- goto out;
+ return ret;
barebox = PAGE_ALIGN(start);
- ret = bootm_load_os(data, barebox);
- if (ret)
- goto out;
+ os_res = bootm_load_os(data, barebox, end);
+ if (IS_ERR(os_res))
+ return PTR_ERR(os_res);
printf("Loaded barebox image to 0x%08lx\n", barebox);
@@ -65,10 +66,7 @@ static int do_bootm_barebox(struct image_data *data)
fn(0, 0, 0, 0);
- ret = -EINVAL;
-
-out:
- return ret;
+ return -EINVAL;
}
static struct image_handler aarch64_barebox_handler = {
diff --git a/arch/arm/mach-at91/bootm-barebox.c b/arch/arm/mach-at91/bootm-barebox.c
index 5540b8fad35e..f4894f247d11 100644
--- a/arch/arm/mach-at91/bootm-barebox.c
+++ b/arch/arm/mach-at91/bootm-barebox.c
@@ -13,6 +13,7 @@ EXPORT_SYMBOL(at91_bootsource);
static int do_bootm_at91_barebox_image(struct image_data *data)
{
+ const struct resource *os_res;
resource_size_t start, end;
int ret;
@@ -20,9 +21,9 @@ static int do_bootm_at91_barebox_image(struct image_data *data)
if (ret)
return ret;
- ret = bootm_load_os(data, start);
- if (ret)
- return ret;
+ os_res = bootm_load_os(data, start, end);
+ if (IS_ERR(os_res))
+ return PTR_ERR(os_res);
if (data->verbose)
printf("Loaded barebox image to 0x%08zx\n", start);
diff --git a/arch/arm/mach-imx/imx-v3-image.c b/arch/arm/mach-imx/imx-v3-image.c
index e5df5fdb81d9..5cce846f867f 100644
--- a/arch/arm/mach-imx/imx-v3-image.c
+++ b/arch/arm/mach-imx/imx-v3-image.c
@@ -8,6 +8,7 @@
static int do_bootm_imx_image_v3(struct image_data *data)
{
+ const struct resource *os_res;
void (*bb)(void);
resource_size_t start, end;
struct flash_header_v3 *hdr;
@@ -18,9 +19,9 @@ static int do_bootm_imx_image_v3(struct image_data *data)
if (ret)
return ret;
- ret = bootm_load_os(data, start);
- if (ret)
- return ret;
+ os_res = bootm_load_os(data, start, end);
+ if (IS_ERR(os_res))
+ return PTR_ERR(os_res);
hdr = (void *)start;
offset = hdr->img[0].offset;
diff --git a/arch/arm/mach-layerscape/pblimage.c b/arch/arm/mach-layerscape/pblimage.c
index 5a525f0933d5..31783f18c74d 100644
--- a/arch/arm/mach-layerscape/pblimage.c
+++ b/arch/arm/mach-layerscape/pblimage.c
@@ -15,6 +15,7 @@ static int do_bootm_layerscape_pblimage(struct image_data *data)
{
void (*barebox)(unsigned long x0, unsigned long x1, unsigned long x2,
unsigned long x3);
+ const struct resource *os_res;
resource_size_t start, end;
int ret;
@@ -22,9 +23,9 @@ static int do_bootm_layerscape_pblimage(struct image_data *data)
if (ret)
return ret;
- ret = bootm_load_os(data, start);
- if (ret)
- return ret;
+ os_res = bootm_load_os(data, start, end);
+ if (IS_ERR(os_res))
+ return PTR_ERR(os_res);
barebox = (void*)start + BAREBOX_STAGE2_OFFSET;
diff --git a/arch/arm/mach-rockchip/bootm.c b/arch/arm/mach-rockchip/bootm.c
index ff3d9a2db3a0..2e068b05cefd 100644
--- a/arch/arm/mach-rockchip/bootm.c
+++ b/arch/arm/mach-rockchip/bootm.c
@@ -40,6 +40,7 @@ static int do_bootm_rkns_barebox_image(struct image_data *data)
{
void (*barebox)(unsigned long x0, unsigned long x1, unsigned long x2,
unsigned long x3);
+ const struct resource *os_res;
resource_size_t start, end;
struct newidb *idb;
int ret, i, n_files;
@@ -50,14 +51,14 @@ static int do_bootm_rkns_barebox_image(struct image_data *data)
if (ret)
return ret;
- ret = bootm_load_os(data, start);
- if (ret)
- return ret;
+ os_res = bootm_load_os(data, start, end);
+ if (IS_ERR(os_res))
+ return PTR_ERR(os_res);
- idb = (void *)data->os_res->start;
- buf = (void *)data->os_res->start;
+ idb = (void *)os_res->start;
+ buf = (void *)os_res->start;
- image_size = resource_size(data->os_res);
+ image_size = resource_size(os_res);
if (image_size < SECTOR_SIZE)
return -EINVAL;
diff --git a/arch/arm/mach-zynq/bootm-zynqimg.c b/arch/arm/mach-zynq/bootm-zynqimg.c
index 77ed6880e4b6..ebd2d621520b 100644
--- a/arch/arm/mach-zynq/bootm-zynqimg.c
+++ b/arch/arm/mach-zynq/bootm-zynqimg.c
@@ -8,6 +8,7 @@
static int do_bootm_zynqimage(struct image_data *data)
{
resource_size_t start, end;
+ const struct resource *os_res;
void (*barebox)(void);
u32 *header;
int ret;
@@ -16,9 +17,9 @@ static int do_bootm_zynqimage(struct image_data *data)
if (ret)
return ret;
- ret = bootm_load_os(data, start);
- if (ret)
- return ret;
+ os_res = bootm_load_os(data, start, end);
+ if (IS_ERR(os_res))
+ return PTR_ERR(os_res);
header = (u32*)start;
barebox = (void*)start + header[12];
diff --git a/arch/kvx/lib/bootm.c b/arch/kvx/lib/bootm.c
index 6eba4054e500..c464b5006fa2 100644
--- a/arch/kvx/lib/bootm.c
+++ b/arch/kvx/lib/bootm.c
@@ -13,6 +13,7 @@
#include <bootm.h>
#include <binfmt.h>
#include <common.h>
+#include <memory.h>
#include <libfile.h>
#include <linux/kernel.h>
@@ -54,7 +55,8 @@ static int do_boot_entry(struct image_data *data, boot_func_entry entry,
static int do_boot_elf(struct image_data *data, struct elf_image *elf)
{
- const struct resource *initrd_res;
+ const struct resource *sdram, *initrd_res, *fdt_res;
+ struct resource gap;
int ret;
void *fdt;
boot_func_entry entry;
@@ -71,7 +73,11 @@ static int do_boot_elf(struct image_data *data, struct elf_image *elf)
else
initrd_address = load_addr;
- initrd_res = bootm_load_initrd(data, initrd_address);
+ sdram = memory_bank_lookup_region(initrd_address, &gap);
+ if (sdram != &gap)
+ return sdram ? -EBUSY : -EINVAL;
+
+ initrd_res = bootm_load_initrd(data, initrd_address, gap.end);
if (IS_ERR(initrd_res)) {
printf("Failed to load initrd\n");
return PTR_ERR(initrd_res);
@@ -93,9 +99,10 @@ static int do_boot_elf(struct image_data *data, struct elf_image *elf)
printf("Loading device tree at %lx\n", load_addr);
/* load device tree after the initrd if any */
- ret = bootm_load_devicetree(data, fdt, load_addr);
- if (ret) {
- printf("Failed to load device tree: %d\n", ret);
+ fdt_res = bootm_load_devicetree(data, fdt, load_addr, gap.end);
+ if (IS_ERR(fdt_res)) {
+ printf("Failed to load device tree: %pe\n", fdt_res);
+ ret = PTR_ERR(fdt_res);
goto err_free_fdt;
}
diff --git a/arch/powerpc/lib/ppclinux.c b/arch/powerpc/lib/ppclinux.c
index 564086482e5f..eda2539e6125 100644
--- a/arch/powerpc/lib/ppclinux.c
+++ b/arch/powerpc/lib/ppclinux.c
@@ -7,6 +7,7 @@
#include <image.h>
#include <init.h>
#include <malloc.h>
+#include <memory.h>
#include <environment.h>
#include <asm/bitops.h>
#include <asm/processor.h>
@@ -53,12 +54,18 @@ static int do_bootm_linux(struct image_data *data)
{
void (*kernel)(void *, void *, unsigned long,
unsigned long, unsigned long);
+ const struct resource *os_res, *sdram;
+ struct resource gap;
int ret;
struct fdt_header *fdt;
- ret = bootm_load_os(data, data->os_address);
- if (ret)
- return ret;
+ sdram = memory_bank_lookup_region(data->os_address, &gap);
+ if (sdram != &gap)
+ return sdram ? -EBUSY : -EINVAL;
+
+ os_res = bootm_load_os(data, data->os_address, gap.end);
+ if (IS_ERR(os_res))
+ return PTR_ERR(os_res);
fdt = of_get_fixed_tree_for_boot(data->of_root_node);
if (!fdt) {
diff --git a/common/booti.c b/common/booti.c
index 6a87b84c0308..67f31b793517 100644
--- a/common/booti.c
+++ b/common/booti.c
@@ -10,13 +10,14 @@
#include <linux/sizes.h>
static unsigned long get_kernel_address(unsigned long os_address,
- unsigned long text_offset)
+ unsigned long text_offset,
+ resource_size_t *end)
{
- resource_size_t start, end;
+ resource_size_t start;
int ret;
if (!UIMAGE_IS_ADDRESS_VALID(os_address)) {
- ret = memory_bank_first_find_space(&start, &end);
+ ret = memory_bank_first_find_space(&start, end);
if (ret)
return UIMAGE_INVALID_ADDRESS;
@@ -33,9 +34,10 @@ void *booti_load_image(struct image_data *data, phys_addr_t *oftree)
{
const void *kernel_header =
data->os_fit ? data->fit_kernel : data->os_header;
+ const struct resource *os_res;
unsigned long text_offset, image_size, kernel;
unsigned long image_end;
- int ret;
+ resource_size_t end;
void *fdt;
print_hex_dump_bytes("header ", DUMP_PREFIX_OFFSET, kernel_header, 80);
@@ -49,24 +51,26 @@ void *booti_load_image(struct image_data *data, phys_addr_t *oftree)
text_offset = le64_to_cpup(kernel_header + 8);
image_size = le64_to_cpup(kernel_header + 16);
- kernel = get_kernel_address(data->os_address, text_offset);
+ kernel = get_kernel_address(data->os_address, text_offset, &end);
pr_debug("Kernel to be loaded to %lx+%lx\n", kernel, image_size);
if (kernel == UIMAGE_INVALID_ADDRESS)
return ERR_PTR(-ENOENT);
+ if (kernel + image_size - 1 > end)
+ return ERR_PTR(-ENOSPC);
- ret = bootm_load_os(data, kernel);
- if (ret)
- return ERR_PTR(ret);
+ os_res = bootm_load_os(data, kernel, end);
+ if (IS_ERR(os_res))
+ return ERR_CAST(os_res);
image_end = PAGE_ALIGN(kernel + image_size);
if (oftree) {
unsigned long devicetree;
- const struct resource *initrd_res;
+ const struct resource *initrd_res, *dt_res;
- initrd_res = bootm_load_initrd(data, image_end);
+ initrd_res = bootm_load_initrd(data, image_end, end);
if (IS_ERR(initrd_res)) {
return ERR_CAST(initrd_res);
} else if (initrd_res) {
@@ -85,11 +89,11 @@ void *booti_load_image(struct image_data *data, phys_addr_t *oftree)
goto out;
}
- ret = bootm_load_devicetree(data, fdt, devicetree);
+ dt_res = bootm_load_devicetree(data, fdt, devicetree, end);
free(fdt);
- if (ret)
- return ERR_PTR(ret);
+ if (IS_ERR(dt_res))
+ return ERR_CAST(dt_res);
*oftree = devicetree;
}
diff --git a/common/bootm.c b/common/bootm.c
index b63c3ea4f547..505b670a4a5e 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -228,57 +228,69 @@ static bool bootm_get_override(char **oldpath, const char *newpath)
return true;
}
-/*
+/**
* bootm_load_os() - load OS to RAM
- *
* @data: image data context
* @load_address: The address where the OS should be loaded to
+ * @end_address: The end address of the load buffer (inclusive)
*
* This loads the OS to a RAM location. load_address must be a valid
- * address. If the image_data doesn't have a OS specified it's considered
+ * address. If the image_data doesn't have an OS specified it's considered
* an error.
*
- * Return: 0 on success, negative error code otherwise
+ * Return: the OS resource on success, or an error pointer on failure
*/
-int bootm_load_os(struct image_data *data, unsigned long load_address)
+const struct resource *bootm_load_os(struct image_data *data,
+ ulong load_address, ulong end_address)
{
+ int err;
+
if (data->os_res)
- return 0;
+ return data->os_res;
if (load_address == UIMAGE_INVALID_ADDRESS)
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
+ if (end_address <= load_address)
+ return ERR_PTR(-EINVAL);
- if (data->os_fit)
- return bootm_load_fit_os(data, load_address);
+ if (data->os_fit) {
+ err = bootm_load_fit_os(data, load_address);
+ } else if (image_is_uimage(data)) {
+ err = bootm_load_uimage_os(data, load_address);
+ } else if (data->os_file) {
+ data->os_res = file_to_sdram(data->os_file, load_address, MEMTYPE_LOADER_CODE);
+ err = data->os_res ? 0 : -EBUSY;
+ } else {
+ err = -EINVAL;
+ }
- if (image_is_uimage(data))
- return bootm_load_uimage_os(data, load_address);
+ if (err)
+ return ERR_PTR(err);
- if (!data->os_file)
- return -EINVAL;
+ /* FIXME: We need some more rework to be able to detect this overflow
+ * before it happens, but for now, let's at least detect it.
+ */
+ if (WARN_ON(data->os_res->end > end_address))
+ return ERR_PTR(-ENOSPC);
- data->os_res = file_to_sdram(data->os_file, load_address, MEMTYPE_LOADER_CODE);
- if (!data->os_res)
- return -ENOMEM;
-
- return 0;
+ return data->os_res;
}
-/*
+/**
* bootm_load_initrd() - load initrd to RAM
- *
* @data: image data context
* @load_address: The address where the initrd should be loaded to
+ * @end_address: The end address of the load buffer (inclusive)
*
* This loads the initrd to a RAM location. load_address must be a valid
- * address. If the image_data doesn't have a initrd specified this function
- * still returns successful as an initrd is optional. Check data->initrd_res
- * to see if an initrd has been loaded.
+ * address. If the image_data doesn't have an initrd specified this function
+ * still returns successful as an initrd is optional.
*
- * Return: 0 on success, negative error code otherwise
+ * Return: the initrd resource if one was loaded, NULL if no initrd was
+ * specified, or an error pointer on failure
*/
const struct resource *
-bootm_load_initrd(struct image_data *data, unsigned long load_address)
+bootm_load_initrd(struct image_data *data, ulong load_address, ulong end_address)
{
struct resource *res = NULL;
const char *initrd, *initrd_part = NULL;
@@ -293,6 +305,8 @@ bootm_load_initrd(struct image_data *data, unsigned long load_address)
*/
if (WARN_ON(data->initrd_res))
return data->initrd_res;
+ if (end_address <= load_address)
+ return ERR_PTR(-EINVAL);
bootm_get_override(&data->initrd_file, bootm_overrides.initrd_file);
@@ -313,7 +327,7 @@ bootm_load_initrd(struct image_data *data, unsigned long load_address)
} else if (initrd) {
res = file_to_sdram(initrd, load_address, MEMTYPE_LOADER_DATA)
- ?: ERR_PTR(-ENOMEM);
+ ?: ERR_PTR(-EBUSY);
} else if (data->os_fit) {
res = bootm_load_fit_initrd(data, load_address);
@@ -323,6 +337,12 @@ bootm_load_initrd(struct image_data *data, unsigned long load_address)
if (IS_ERR_OR_NULL(res))
return res;
+ /* FIXME: We need some more rework to be able to detect this overflow
+ * before it happens, but for now, let's at least detect it.
+ */
+ if (WARN_ON(res->end > end_address))
+ return ERR_PTR(-ENOSPC);
+
pr_info("Loaded initrd from %s %s%s%s to %pa-%pa\n",
file_type_to_string(type), initrd ?: "",
initrd_part ? "@" : "", initrd_part ?: "",
@@ -424,33 +444,38 @@ void *bootm_get_devicetree(struct image_data *data)
return oftree;
}
-/*
- * bootm_load_devicetree() - load devicetree
- *
+/**
+ * bootm_load_devicetree() - load devicetree into specified memory range
* @data: image data context
* @fdt: The flat device tree to load
* @load_address: The address where the devicetree should be loaded to
+ * @end_address: The end address of the load buffer (inclusive)
*
* This loads the devicetree to a RAM location. load_address must be a valid
* address which is requested with request_sdram_region. The associated region
* is released automatically in the bootm error path.
*
- * Return: 0 on success, negative error code otherwise
+ * Return: the devicetree resource on success, or an error pointer on failure
*/
-int bootm_load_devicetree(struct image_data *data, void *fdt,
- unsigned long load_address)
+const struct resource *
+bootm_load_devicetree(struct image_data *data, void *fdt,
+ ulong load_address, ulong end_address)
{
int fdt_size;
if (!IS_ENABLED(CONFIG_OFTREE))
- return -ENOSYS;
+ return ERR_PTR(-ENOSYS);
+ if (end_address <= load_address)
+ return ERR_PTR(-EINVAL);
fdt_size = be32_to_cpu(((struct fdt_header *)fdt)->totalsize);
+ if (load_address + fdt_size - 1 > end_address)
+ return ERR_PTR(-ENOSPC);
data->oftree_res = request_sdram_region("oftree", load_address,
fdt_size, MEMTYPE_LOADER_DATA, MEMATTRS_RW);
if (!data->oftree_res)
- return -ENOMEM;
+ return ERR_PTR(-EBUSY);
memcpy((void *)data->oftree_res->start, fdt, fdt_size);
@@ -460,7 +485,7 @@ int bootm_load_devicetree(struct image_data *data, void *fdt,
fdt_print_reserve_map(fdt);
}
- return 0;
+ return data->oftree_res;
}
int bootm_get_os_size(struct image_data *data)
diff --git a/efi/loader/bootm.c b/efi/loader/bootm.c
index da664847def8..498f4dce6b07 100644
--- a/efi/loader/bootm.c
+++ b/efi/loader/bootm.c
@@ -160,18 +160,15 @@ static efi_status_t efi_install_fdt(void *fdt)
/**
* efi_install_initrd() - install initrd
- *
- * Install the initrd located at @initrd using the EFI_LOAD_FILE2
- * protocol.
- *
- * @initrd: address of initrd or NULL if none is provided
- * @initrd_sz: size of initrd
+ * @data: image data
+ * @freemem: address of free memory usable for placing initrd
* Return: status code
*/
static efi_status_t efi_install_initrd(struct image_data *data,
- struct resource *source)
+ resource_size_t freemem)
{
- const struct resource *initrd_res;
+ const struct resource *initrd_res, *sdram;
+ struct resource gap;
unsigned long initrd_start;
if (!IS_ENABLED(CONFIG_BOOTM_INITRD))
@@ -180,9 +177,13 @@ static efi_status_t efi_install_initrd(struct image_data *data,
if (UIMAGE_IS_ADDRESS_VALID(data->initrd_address))
initrd_start = data->initrd_address;
else
- initrd_start = EFI_PAGE_ALIGN(source->end + 1);
+ initrd_start = EFI_PAGE_ALIGN(freemem);
- initrd_res = bootm_load_initrd(data, initrd_start);
+ sdram = memory_bank_lookup_region(initrd_start, &gap);
+ if (sdram != &gap)
+ return sdram ? EFI_OUT_OF_RESOURCES : EFI_INVALID_PARAMETER;
+
+ initrd_res = bootm_load_initrd(data, initrd_start, gap.end);
if (IS_ERR(initrd_res))
return PTR_ERR(initrd_res);
if (initrd_res)
@@ -194,12 +195,12 @@ static efi_status_t efi_install_initrd(struct image_data *data,
static int efi_loader_bootm(struct image_data *data)
{
+ const struct resource *os_res;
resource_size_t start, end;
void *load_option = NULL;
u32 load_option_size = 0;
efi_handle_t handle;
struct efi_device_path *file_path = NULL;
- struct resource *source;
struct efi_event *evt;
size_t exit_data_size = 0;
u16 *exit_data = NULL;
@@ -209,11 +210,10 @@ static int efi_loader_bootm(struct image_data *data)
int flags = 0;
memory_bank_first_find_space(&start, &end);
- data->os_address = start;
- source = file_to_sdram(data->os_file, data->os_address, MEMTYPE_LOADER_CODE);
- if (!source)
- return -EINVAL;
+ os_res = bootm_load_os(data, start, end);
+ if (IS_ERR(os_res))
+ return PTR_ERR(os_res);
if (filetype_is_linux_efi_image(data->os_type)) {
const char *options;
@@ -248,7 +248,7 @@ static int efi_loader_bootm(struct image_data *data)
return ret;
}
- efiret = efi_install_initrd(data, source);
+ efiret = efi_install_initrd(data, os_res->end + 1);
if(efiret != EFI_SUCCESS)
goto out;
@@ -258,8 +258,8 @@ static int efi_loader_bootm(struct image_data *data)
flags |= EFI_DRYRUN;
efiret = efiloader_load_image(false, efi_root, file_path,
- (void *)source->start,
- resource_size(source), &handle);
+ (void *)os_res->start,
+ resource_size(os_res), &handle);
if (efiret != EFI_SUCCESS) {
pr_err("Loading image failed\n");
goto out;
@@ -318,7 +318,6 @@ static int efi_loader_bootm(struct image_data *data)
efi_install_configuration_table(&efi_fdt_guid, NULL);
efi_free_pool(file_path);
free(load_option);
- release_sdram_region(source);
return ret ?: -efi_errno(efiret);
}
diff --git a/include/bootm.h b/include/bootm.h
index e56a999f0b11..1c3bb8899b38 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -150,14 +150,19 @@ static inline int bootm_verbose(struct image_data *data)
void bootm_data_init_defaults(struct bootm_data *data);
void bootm_data_restore_defaults(const struct bootm_data *data);
-int bootm_load_os(struct image_data *data, unsigned long load_address);
+const struct resource *
+bootm_load_os(struct image_data *data,
+ ulong load_address, ulong end_address);
const struct resource *
-bootm_load_initrd(struct image_data *data, unsigned long load_address);
+bootm_load_initrd(struct image_data *data,
+ ulong load_address, ulong end_address);
void *bootm_get_devicetree(struct image_data *data);
-int bootm_load_devicetree(struct image_data *data, void *fdt,
- unsigned long load_address);
+
+const struct resource *
+bootm_load_devicetree(struct image_data *data, void *fdt,
+ ulong load_address, ulong end_address);
int bootm_get_os_size(struct image_data *data);
enum bootm_verify bootm_get_verify_mode(void);
--
2.47.3
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v2 05/13] bootm: store separate image_type and kernel_type
2026-02-09 18:10 [PATCH v2 00/13] bootm: prepare loadable abstraction rework Ahmad Fatoum
` (3 preceding siblings ...)
2026-02-09 18:10 ` [PATCH v2 04/13] bootm: give bootm_load_ functions an end address Ahmad Fatoum
@ 2026-02-09 18:10 ` Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 06/13] bootm: fit: move length calculation into fit_open Ahmad Fatoum
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2026-02-09 18:10 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
For FIT images, image_data::os_type is either the container file type or
the kernel file type, depending on when we are looking.
This makes the code harder to refactor, so let's split it into two
separate image_type and kernel_type members.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/booti.c | 3 +--
common/bootm-fit.c | 15 +++++++++++++++
common/bootm.c | 29 +++++++++++++++--------------
efi/loader/bootm.c | 2 +-
include/bootm.h | 6 +++++-
5 files changed, 37 insertions(+), 18 deletions(-)
diff --git a/common/booti.c b/common/booti.c
index 67f31b793517..4f6ccf95f85c 100644
--- a/common/booti.c
+++ b/common/booti.c
@@ -32,8 +32,7 @@ static unsigned long get_kernel_address(unsigned long os_address,
void *booti_load_image(struct image_data *data, phys_addr_t *oftree)
{
- const void *kernel_header =
- data->os_fit ? data->fit_kernel : data->os_header;
+ const void *kernel_header = data->os_header;
const struct resource *os_res;
unsigned long text_offset, image_size, kernel;
unsigned long image_end;
diff --git a/common/bootm-fit.c b/common/bootm-fit.c
index a0e808e31b40..5bfd8ac61d3f 100644
--- a/common/bootm-fit.c
+++ b/common/bootm-fit.c
@@ -5,6 +5,7 @@
#include <bootm-fit.h>
#include <memory.h>
#include <zero_page.h>
+#include <filetype.h>
/*
* bootm_load_fit_os() - load OS from FIT to RAM
@@ -114,6 +115,17 @@ static bool bootm_fit_config_valid(struct fit_handle *fit,
return !!fit_has_image(fit, config, "kernel");
}
+static enum filetype bootm_fit_update_os_header(struct image_data *data)
+{
+ if (data->fit_kernel_size < PAGE_SIZE)
+ return filetype_unknown;
+
+ free(data->os_header);
+ data->os_header = xmemdup(data->fit_kernel, PAGE_SIZE);
+
+ return file_detect_type(data->os_header, PAGE_SIZE);
+}
+
int bootm_open_fit(struct image_data *data)
{
struct fit_handle *fit;
@@ -148,6 +160,9 @@ int bootm_open_fit(struct image_data *data)
&data->fit_kernel, &data->fit_kernel_size);
if (ret)
return ret;
+
+ data->kernel_type = bootm_fit_update_os_header(data);
+
if (data->os_address == UIMAGE_SOME_ADDRESS) {
ret = fit_get_image_address(data->os_fit,
data->fit_config,
diff --git a/common/bootm.c b/common/bootm.c
index 505b670a4a5e..efb2f401ed9b 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -550,9 +550,8 @@ int bootm_boot(struct bootm_data *bootm_data)
struct image_data *data;
struct image_handler *handler;
int ret;
- enum filetype os_type;
size_t size;
- const char *os_type_str;
+ const char *image_type_str;
if (!bootm_data->os_file) {
pr_err("no image given\n");
@@ -583,9 +582,9 @@ int bootm_boot(struct bootm_data *bootm_data)
if (size < PAGE_SIZE)
goto err_out;
- os_type = data->os_type = file_detect_boot_image_type(data->os_header, PAGE_SIZE);
+ data->image_type = file_detect_boot_image_type(data->os_header, PAGE_SIZE);
- if (!data->force && os_type == filetype_unknown) {
+ if (!data->force && data->image_type == filetype_unknown) {
pr_err("Unknown OS filetype (try -f)\n");
ret = -EINVAL;
goto err_out;
@@ -601,19 +600,21 @@ int bootm_boot(struct bootm_data *bootm_data)
data->oftree_file = NULL;
data->initrd_file = NULL;
data->tee_file = NULL;
- if (os_type != filetype_fit) {
+ if (data->image_type != filetype_fit) {
pr_err("Signed boot and image is no FIT image, aborting\n");
ret = -EINVAL;
goto err_out;
}
}
- os_type_str = file_type_to_short_string(os_type);
+ image_type_str = file_type_to_short_string(data->image_type);
- switch (os_type) {
+ /* May be updated by below container-specific handlers */
+ data->kernel_type = data->image_type;
+
+ switch (data->image_type) {
case filetype_fit:
ret = bootm_open_fit(data);
- os_type = file_detect_type(data->fit_kernel, data->fit_kernel_size);
break;
case filetype_uimage:
ret = bootm_open_uimage(data);
@@ -624,7 +625,7 @@ int bootm_boot(struct bootm_data *bootm_data)
}
if (ret) {
- pr_err("Loading %s image failed with: %pe\n", os_type_str, ERR_PTR(ret));
+ pr_err("Loading %s image failed with: %pe\n", image_type_str, ERR_PTR(ret));
goto err_out;
}
@@ -737,9 +738,9 @@ int bootm_boot(struct bootm_data *bootm_data)
free(hostname_bootarg);
}
- pr_info("\nLoading %s '%s'", file_type_to_string(os_type),
+ pr_info("\nLoading %s '%s'", file_type_to_string(data->kernel_type),
data->os_file);
- if (os_type == filetype_uimage &&
+ if (data->kernel_type == filetype_uimage &&
data->os->header.ih_type == IH_TYPE_MULTI)
pr_info(", multifile image %d", uimage_part_num(data->os_part));
pr_info("\n");
@@ -749,11 +750,11 @@ int bootm_boot(struct bootm_data *bootm_data)
if (data->os_entry == UIMAGE_SOME_ADDRESS)
data->os_entry = 0;
- handler = bootm_find_handler(os_type, data);
+ handler = bootm_find_handler(data->kernel_type, data);
if (!handler) {
pr_err("no image handler found for image type %s\n",
- file_type_to_string(os_type));
- if (os_type == filetype_uimage)
+ file_type_to_string(data->kernel_type));
+ if (data->kernel_type == filetype_uimage)
pr_err("and OS type: %d\n", data->os->header.ih_os);
ret = -ENODEV;
goto err_out;
diff --git a/efi/loader/bootm.c b/efi/loader/bootm.c
index 498f4dce6b07..97621d8a05e5 100644
--- a/efi/loader/bootm.c
+++ b/efi/loader/bootm.c
@@ -215,7 +215,7 @@ static int efi_loader_bootm(struct image_data *data)
if (IS_ERR(os_res))
return PTR_ERR(os_res);
- if (filetype_is_linux_efi_image(data->os_type)) {
+ if (filetype_is_linux_efi_image(data->kernel_type)) {
const char *options;
options = linux_bootargs_get();
diff --git a/include/bootm.h b/include/bootm.h
index 1c3bb8899b38..bdabba23f2b9 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -111,7 +111,11 @@ struct image_data {
char *tee_file;
struct resource *tee_res;
- enum filetype os_type;
+ /* Type of OS image, e.g. filetype_fit or the same as kernel_type */
+ enum filetype image_type;
+ /* Type of kernel image that's going to be booted */
+ enum filetype kernel_type;
+
enum bootm_verify verify;
int verbose;
int force;
--
2.47.3
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v2 06/13] bootm: fit: move length calculation into fit_open
2026-02-09 18:10 [PATCH v2 00/13] bootm: prepare loadable abstraction rework Ahmad Fatoum
` (4 preceding siblings ...)
2026-02-09 18:10 ` [PATCH v2 05/13] bootm: store separate image_type and kernel_type Ahmad Fatoum
@ 2026-02-09 18:10 ` Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 07/13] libfile: factor out zero-page resistant read_file as __read_full_anywhere Ahmad Fatoum
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2026-02-09 18:10 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
A FIT image is a device tree and its second big-endian 32-bit word
encodes the size and fit_open() takes an extra argument, so it need not
read a whole partition, but only as many bytes as the header describes.
We are going to add a new caller for fit_open(). Instead of repeating
the max_size determination at every call site, let's just move the size
calculation into the function.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/bootm-fit.c | 9 +-------
common/image-fit.c | 46 +++++++++++++++++++++++++++++++---------
drivers/of/overlay.c | 6 +++---
include/image-fit.h | 2 +-
include/libfile.h | 2 ++
lib/libfile.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 93 insertions(+), 22 deletions(-)
diff --git a/common/bootm-fit.c b/common/bootm-fit.c
index 5bfd8ac61d3f..70d6ba8edff2 100644
--- a/common/bootm-fit.c
+++ b/common/bootm-fit.c
@@ -129,17 +129,10 @@ static enum filetype bootm_fit_update_os_header(struct image_data *data)
int bootm_open_fit(struct image_data *data)
{
struct fit_handle *fit;
- struct fdt_header *header;
static const char *kernel_img = "kernel";
- size_t flen, hlen;
int ret;
- header = (struct fdt_header *)data->os_header;
- flen = bootm_get_os_size(data);
- hlen = fdt32_to_cpu(header->totalsize);
-
- fit = fit_open(data->os_file, data->verbose, data->verify,
- min(flen, hlen));
+ fit = fit_open(data->os_file, data->verbose, data->verify);
if (IS_ERR(fit)) {
pr_err("Loading FIT image %s failed with: %pe\n", data->os_file, fit);
return PTR_ERR(fit);
diff --git a/common/image-fit.c b/common/image-fit.c
index 75592766941c..50816452810c 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -992,7 +992,6 @@ struct fit_handle *fit_open_buf(const void *buf, size_t size, bool verbose,
* @filename: The filename of the FIT image
* @verbose: If true, be more verbose
* @verify: The verify mode
- * @max_size: maximum length to read from file
*
* This opens a FIT image found in @filename. The returned handle is used as
* context for the other FIT functions.
@@ -1000,11 +999,12 @@ struct fit_handle *fit_open_buf(const void *buf, size_t size, bool verbose,
* Return: A handle to a FIT image or a ERR_PTR
*/
struct fit_handle *fit_open(const char *_filename, bool verbose,
- enum bootm_verify verify, loff_t max_size)
+ enum bootm_verify verify)
{
struct fit_handle *handle;
+ ssize_t nbytes;
char *filename;
- int ret;
+ int fd, ret;
filename = canonicalize_path(AT_FDCWD, _filename);
if (!filename) {
@@ -1024,15 +1024,30 @@ struct fit_handle *fit_open(const char *_filename, bool verbose,
handle->verbose = verbose;
handle->verify = verify;
- ret = read_file_2(filename, &handle->size, &handle->fit_alloc,
- max_size);
- if (ret && ret != -EFBIG) {
- pr_err("unable to read %s: %pe\n", filename, ERR_PTR(ret));
- free(handle);
- free(filename);
- return ERR_PTR(ret);
+ fd = open_fdt(filename, &handle->size);
+ if (fd < 0) {
+ ret = fd;
+ goto free_handle;
}
+ handle->fit_alloc = malloc(handle->size);
+ if (!handle->fit_alloc) {
+ ret = -ENOMEM;
+ goto close_fd;
+ }
+
+ nbytes = read_full(fd, handle->fit_alloc, handle->size);
+ if (nbytes < 0) {
+ ret = nbytes;
+ goto free_fit_alloc;
+ }
+ if (handle->size != nbytes) {
+ ret = -ENODATA;
+ goto free_fit_alloc;
+ }
+
+ close(fd);
+
handle->fit = handle->fit_alloc;
handle->filename = filename;
@@ -1046,6 +1061,17 @@ struct fit_handle *fit_open(const char *_filename, bool verbose,
}
return handle;
+
+free_fit_alloc:
+ free(handle->fit_alloc);
+close_fd:
+ close(fd);
+free_handle:
+ pr_err("unable to read %s: %pe\n", filename, ERR_PTR(ret));
+ free(filename);
+ free(handle);
+ return ERR_PTR(ret);
+
}
static bool __fit_close(struct fit_handle *handle)
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index b11edebd2080..34543403e9ba 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -532,7 +532,7 @@ static bool of_overlay_valid_config(struct fit_handle *fit,
}
static int of_overlay_global_fixup_fit(struct device_node *root,
- const char *fit_path, loff_t fit_size)
+ const char *fit_path)
{
enum bootm_verify verify = bootm_get_verify_mode();
struct device_node *conf_node;
@@ -544,7 +544,7 @@ static int of_overlay_global_fixup_fit(struct device_node *root,
return -EINVAL;
}
- fit = fit_open(fit_path, 0, verify, fit_size);
+ fit = fit_open(fit_path, 0, verify);
if (IS_ERR(fit)) {
pr_err("Loading FIT image %s failed with: %pe\n", fit_path, fit);
return PTR_ERR(fit);
@@ -595,7 +595,7 @@ static int of_overlay_global_fixup(struct device_node *root, void *data)
}
/* Assume a FIT image if of_overlay_path points to a file */
- ret = of_overlay_global_fixup_fit(root, dir, s.st_size);
+ ret = of_overlay_global_fixup_fit(root, dir);
out:
free(dir);
diff --git a/include/image-fit.h b/include/image-fit.h
index 50f0482b65ad..ede43beab12e 100644
--- a/include/image-fit.h
+++ b/include/image-fit.h
@@ -28,7 +28,7 @@ struct fit_handle {
};
struct fit_handle *fit_open(const char *filename, bool verbose,
- enum bootm_verify verify, loff_t max_size);
+ enum bootm_verify verify);
struct fit_handle *fit_open_buf(const void *buf, size_t len, bool verbose,
enum bootm_verify verify);
void *fit_open_configuration(struct fit_handle *handle, const char *name,
diff --git a/include/libfile.h b/include/libfile.h
index 370f8b9725ab..f44046fb0f7b 100644
--- a/include/libfile.h
+++ b/include/libfile.h
@@ -59,4 +59,6 @@ struct resource *file_to_sdram(const char *filename, unsigned long adr,
int fixup_path_case(int dirfd, const char **path);
+int open_fdt(const char *filename, size_t *size);
+
#endif /* __LIBFILE_H */
diff --git a/lib/libfile.c b/lib/libfile.c
index 6924db587e8c..86b1bc3fa790 100644
--- a/lib/libfile.c
+++ b/lib/libfile.c
@@ -918,3 +918,53 @@ int fixup_path_case(int fd, const char **path)
free(resolved_path);
return -errno;
}
+
+/**
+ * open_fdt - open a flattened device tree file and determine its size
+ * @filename: path to the FDT file
+ * @size: returns the total size from the FDT header
+ *
+ * Opens the file, reads the FDT header to determine totalsize, validates
+ * it against the file size, then reopens the file for sequential reading.
+ *
+ * Return: file descriptor on success, negative error code on failure
+ */
+int open_fdt(const char *filename, size_t *size)
+{
+ __be32 fdt_hdr[2];
+ u32 fdt_size;
+ struct stat st;
+ int fd, ret;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return fd;
+
+ ret = fstat(fd, &st);
+ if (ret)
+ goto err;
+
+ ret = pread_full(fd, &fdt_hdr, sizeof(fdt_hdr), 0);
+ if (ret >= 0 && ret < sizeof(fdt_hdr))
+ ret = -EILSEQ;
+ if (ret < 0)
+ goto err;
+
+ fdt_size = be32_to_cpu(fdt_hdr[1]);
+ if (st.st_size < fdt_size) {
+ ret = -ENODATA;
+ goto err;
+ }
+
+ close(fd);
+
+ /* HACK: TFTP doesn't support backwards seeking, so reopen afresh */
+ fd = open(filename, O_RDONLY);
+ if (fd >= 0)
+ *size = fdt_size;
+
+ return fd;
+err:
+ close(fd);
+ return ret;
+}
--
2.47.3
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v2 07/13] libfile: factor out zero-page resistant read_file as __read_full_anywhere
2026-02-09 18:10 [PATCH v2 00/13] bootm: prepare loadable abstraction rework Ahmad Fatoum
` (5 preceding siblings ...)
2026-02-09 18:10 ` [PATCH v2 06/13] bootm: fit: move length calculation into fit_open Ahmad Fatoum
@ 2026-02-09 18:10 ` Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 08/13] resource: implement resize_region Ahmad Fatoum
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2026-02-09 18:10 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
This function will be useful for the incoming loadable support, so factor
it out of file_to_sdram().
While at it, make it a bit safer as well: Only the first page needs to
be copied with zero_page_memcpy if at all, so copy at most one page if
the zero page is overlapped and then copy the rest as usual.
file_to_sdram() is intentionally left as-is as it's going to be removed
in a later commit.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
include/libfile.h | 1 +
lib/libfile.c | 29 +++++++++++++++++++++++++++++
2 files changed, 30 insertions(+)
diff --git a/include/libfile.h b/include/libfile.h
index f44046fb0f7b..f61c45563c01 100644
--- a/include/libfile.h
+++ b/include/libfile.h
@@ -11,6 +11,7 @@ int pread_full(int fd, void *buf, size_t size, loff_t offset);
int pwrite_full(int fd, const void *buf, size_t size, loff_t offset);
int write_full(int fd, const void *buf, size_t size);
int read_full(int fd, void *buf, size_t size);
+int __read_full_anywhere(int fd, void *buf, size_t size);
int copy_fd(int in, int out, size_t size);
ssize_t read_file_into_buf(const char *filename, void *buf, size_t size);
diff --git a/lib/libfile.c b/lib/libfile.c
index 86b1bc3fa790..0ebb973e3680 100644
--- a/lib/libfile.c
+++ b/lib/libfile.c
@@ -798,6 +798,35 @@ int cache_file(const char *path, char **newpath)
return 0;
}
+/*
+ * __read_full_anywhere - read from filedescriptor, even into zero_page
+ *
+ * Like read_full, but this function will temporarily remap the zero
+ * page if data is to be placed there. You should not need to use this
+ * outside of boot code!
+ */
+int __read_full_anywhere(int fd, void *buf, size_t size)
+{
+ ssize_t now = 0;
+
+ if (unlikely(zero_page_contains((ulong)buf))) {
+ void *tmp = malloc(PAGE_SIZE);
+ if (!tmp)
+ return -ENOMEM;
+
+ now = read_full(fd, tmp, min_t(size_t, size, PAGE_SIZE));
+ if (now > 0)
+ zero_page_memcpy(buf, tmp, now);
+
+ free(tmp);
+
+ if (now <= 0)
+ return now;
+ }
+
+ return now + read_full(fd, buf + now, size - now);
+}
+
#define BUFSIZ (PAGE_SIZE * 32)
struct resource *file_to_sdram(const char *filename, unsigned long adr,
--
2.47.3
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v2 08/13] resource: implement resize_region
2026-02-09 18:10 [PATCH v2 00/13] bootm: prepare loadable abstraction rework Ahmad Fatoum
` (6 preceding siblings ...)
2026-02-09 18:10 ` [PATCH v2 07/13] libfile: factor out zero-page resistant read_file as __read_full_anywhere Ahmad Fatoum
@ 2026-02-09 18:10 ` Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 09/13] bootm: rename image_data::os/initrd with _uimage suffix Ahmad Fatoum
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2026-02-09 18:10 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
resize_region allows enlarging or reducing a region end while checking
for conflicts. This is less effort than removing a region and
reallocating it.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/resource.c | 62 ++++++++++++++++++++++++++++++++++++++++++
include/linux/ioport.h | 2 ++
2 files changed, 64 insertions(+)
diff --git a/common/resource.c b/common/resource.c
index e391d268e0bb..131f5e190c58 100644
--- a/common/resource.c
+++ b/common/resource.c
@@ -92,6 +92,68 @@ struct resource *__request_region(struct resource *parent,
return new;
}
+/**
+ * resize_region - change the size of an allocated resource region
+ * @res: resource to resize (may be NULL for no-op)
+ * @size: new desired size in bytes (must be non-zero)
+ *
+ * Shrinking checks that no child extends past the new end.
+ * Growing checks that the new end does not overflow, stays within
+ * the parent region and does not collide with the next sibling.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+int resize_region(struct resource *res, resource_size_t size)
+{
+ struct resource *parent;
+ struct resource *next;
+ resource_size_t newend;
+
+ if (!res)
+ return 0;
+ if (!size)
+ return -EINVAL;
+
+ if (size == resource_size(res))
+ return 0;
+
+ if (size < resource_size(res)) {
+ struct resource *last;
+
+ last = list_last_entry_or_null(&res->children,
+ struct resource, sibling);
+ if (last && last->end > res->start + size - 1)
+ return -EBUSY;
+ res->end = res->start + size - 1;
+ return 0;
+ }
+
+ parent = res->parent;
+ if (!parent)
+ return -EINVAL;
+
+ if (check_add_overflow(res->start, size - 1, &newend))
+ return -EINVAL;
+
+ if (newend > parent->end)
+ return -EINVAL;
+
+ /*
+ * parent->children is the list_head that anchors the ordered list of
+ * children. If res is not the last entry, the immediate next entry is
+ * the only sibling we must check.
+ */
+ if (res->sibling.next != &parent->children) {
+ next = list_next_entry(res, sibling);
+
+ if (newend >= next->start)
+ return -EBUSY;
+ }
+
+ res->end = newend;
+ return 0;
+}
+
/*
* release a region previously requested with request_*_region
*/
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 5baae0dae10a..8f9191d1c6be 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -272,6 +272,8 @@ static inline void resource_set_range(struct resource *res,
resource_set_size(res, size);
}
+int resize_region(struct resource *res, resource_size_t size);
+
#define region_is_gap(region) ((region)->flags & IORESOURCE_UNSET)
struct resource *resource_iter_first(struct resource *current, struct resource *gap);
--
2.47.3
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v2 09/13] bootm: rename image_data::os/initrd with _uimage suffix
2026-02-09 18:10 [PATCH v2 00/13] bootm: prepare loadable abstraction rework Ahmad Fatoum
` (7 preceding siblings ...)
2026-02-09 18:10 ` [PATCH v2 08/13] resource: implement resize_region Ahmad Fatoum
@ 2026-02-09 18:10 ` Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 10/13] uimage: record original file name in uimage_handle Ahmad Fatoum
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2026-02-09 18:10 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
We will use the generic unadorned for the incoming loadable support, so
add a _uimage suffix to the uimage-only members to make the association
clearer.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/powerpc/lib/ppclinux.c | 2 +-
common/bootm-uimage.c | 38 ++++++++++++++++++-------------------
common/bootm.c | 12 ++++++------
include/bootm.h | 4 ++--
4 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/arch/powerpc/lib/ppclinux.c b/arch/powerpc/lib/ppclinux.c
index eda2539e6125..4e9693cbad60 100644
--- a/arch/powerpc/lib/ppclinux.c
+++ b/arch/powerpc/lib/ppclinux.c
@@ -30,7 +30,7 @@ static struct fdt_header *bootm_relocate_fdt(struct image_data *data,
*/
if (os < (void *)fdt->totalsize) {
os = (void *)PAGE_ALIGN((phys_addr_t)os +
- data->os->header.ih_size);
+ data->os_uimage->header.ih_size);
os += fdt->totalsize;
if (os < LINUX_TLB1_MAX_ADDR)
os = LINUX_TLB1_MAX_ADDR;
diff --git a/common/bootm-uimage.c b/common/bootm-uimage.c
index 609b678e1d4a..b32ed5b0e95f 100644
--- a/common/bootm-uimage.c
+++ b/common/bootm-uimage.c
@@ -29,7 +29,7 @@ int bootm_load_uimage_os(struct image_data *data, unsigned long load_address)
num = uimage_part_num(data->os_part);
- data->os_res = uimage_load_to_sdram(data->os,
+ data->os_res = uimage_load_to_sdram(data->os_uimage,
num, load_address);
if (!data->os_res)
return -ENOMEM;
@@ -42,21 +42,21 @@ static int bootm_open_initrd_uimage(struct image_data *data)
int ret;
if (strcmp(data->os_file, data->initrd_file)) {
- data->initrd = uimage_open(data->initrd_file);
- if (!data->initrd)
+ data->initrd_uimage = uimage_open(data->initrd_file);
+ if (!data->initrd_uimage)
return -EINVAL;
if (bootm_get_verify_mode() > BOOTM_VERIFY_NONE) {
- ret = uimage_verify(data->initrd);
+ ret = uimage_verify(data->initrd_uimage);
if (ret) {
pr_err("Checking data crc failed with %pe\n",
ERR_PTR(ret));
return ret;
}
}
- uimage_print_contents(data->initrd);
+ uimage_print_contents(data->initrd_uimage);
} else {
- data->initrd = data->os;
+ data->initrd_uimage = data->os_uimage;
}
return 0;
@@ -90,7 +90,7 @@ bootm_load_uimage_initrd(struct image_data *data, unsigned long load_address)
num = uimage_part_num(data->initrd_part);
- res = uimage_load_to_sdram(data->initrd,
+ res = uimage_load_to_sdram(data->initrd_uimage,
num, load_address);
if (!res)
return ERR_PTR(-ENOMEM);
@@ -110,9 +110,9 @@ int bootm_open_oftree_uimage(struct image_data *data, size_t *size,
pr_info("Loading devicetree from '%s'@%d\n", oftree, num);
if (!strcmp(data->os_file, oftree)) {
- of_handle = data->os;
+ of_handle = data->os_uimage;
} else if (!strcmp(data->initrd_file, oftree)) {
- of_handle = data->initrd;
+ of_handle = data->initrd_uimage;
} else {
of_handle = uimage_open(oftree);
if (!of_handle)
@@ -141,12 +141,12 @@ int bootm_open_uimage(struct image_data *data)
{
int ret;
- data->os = uimage_open(data->os_file);
- if (!data->os)
+ data->os_uimage = uimage_open(data->os_file);
+ if (!data->os_uimage)
return -EINVAL;
if (bootm_get_verify_mode() > BOOTM_VERIFY_NONE) {
- ret = uimage_verify(data->os);
+ ret = uimage_verify(data->os_uimage);
if (ret) {
pr_err("Checking data crc failed with %pe\n",
ERR_PTR(ret));
@@ -154,23 +154,23 @@ int bootm_open_uimage(struct image_data *data)
}
}
- uimage_print_contents(data->os);
+ uimage_print_contents(data->os_uimage);
- if (IH_ARCH == IH_ARCH_INVALID || data->os->header.ih_arch != IH_ARCH) {
+ if (IH_ARCH == IH_ARCH_INVALID || data->os_uimage->header.ih_arch != IH_ARCH) {
pr_err("Unsupported Architecture 0x%x\n",
- data->os->header.ih_arch);
+ data->os_uimage->header.ih_arch);
return -EINVAL;
}
if (data->os_address == UIMAGE_SOME_ADDRESS)
- data->os_address = data->os->header.ih_load;
+ data->os_address = data->os_uimage->header.ih_load;
return 0;
}
void bootm_close_uimage(struct image_data *data)
{
- if (data->initrd && data->initrd != data->os)
- uimage_close(data->initrd);
- uimage_close(data->os);
+ if (data->initrd_uimage && data->initrd_uimage != data->os_uimage)
+ uimage_close(data->initrd_uimage);
+ uimage_close(data->os_uimage);
}
diff --git a/common/bootm.c b/common/bootm.c
index efb2f401ed9b..3c3523644b57 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -33,7 +33,7 @@ static bool uimage_check(struct image_handler *handler,
enum filetype detected_filetype)
{
return detected_filetype == filetype_uimage &&
- handler->ih_os == data->os->header.ih_os;
+ handler->ih_os == data->os_uimage->header.ih_os;
}
static bool filetype_check(struct image_handler *handler,
@@ -208,7 +208,7 @@ static int uimage_part_num(const char *partname)
static inline bool image_is_uimage(struct image_data *data)
{
- return IS_ENABLED(CONFIG_BOOTM_UIMAGE) && data->os;
+ return IS_ENABLED(CONFIG_BOOTM_UIMAGE) && data->os_uimage;
}
static bool bootm_get_override(char **oldpath, const char *newpath)
@@ -322,7 +322,7 @@ bootm_load_initrd(struct image_data *data, ulong load_address, ulong end_address
if (type == filetype_uimage) {
res = bootm_load_uimage_initrd(data, load_address);
- if (data->initrd->header.ih_type == IH_TYPE_MULTI)
+ if (data->initrd_uimage->header.ih_type == IH_TYPE_MULTI)
initrd_part = data->initrd_part;
} else if (initrd) {
@@ -495,7 +495,7 @@ int bootm_get_os_size(struct image_data *data)
int ret;
if (image_is_uimage(data))
- return uimage_get_size(data->os, uimage_part_num(data->os_part));
+ return uimage_get_size(data->os_uimage, uimage_part_num(data->os_part));
if (data->os_fit)
return data->fit_kernel_size;
if (!data->os_file)
@@ -741,7 +741,7 @@ int bootm_boot(struct bootm_data *bootm_data)
pr_info("\nLoading %s '%s'", file_type_to_string(data->kernel_type),
data->os_file);
if (data->kernel_type == filetype_uimage &&
- data->os->header.ih_type == IH_TYPE_MULTI)
+ data->os_uimage->header.ih_type == IH_TYPE_MULTI)
pr_info(", multifile image %d", uimage_part_num(data->os_part));
pr_info("\n");
@@ -755,7 +755,7 @@ int bootm_boot(struct bootm_data *bootm_data)
pr_err("no image handler found for image type %s\n",
file_type_to_string(data->kernel_type));
if (data->kernel_type == filetype_uimage)
- pr_err("and OS type: %d\n", data->os->header.ih_os);
+ pr_err("and OS type: %d\n", data->os_uimage->header.ih_os);
ret = -ENODEV;
goto err_out;
}
diff --git a/include/bootm.h b/include/bootm.h
index bdabba23f2b9..ef979807505d 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -59,7 +59,7 @@ struct image_data {
struct resource *os_res;
/* if os is an uImage this will be provided */
- struct uimage_handle *os;
+ struct uimage_handle *os_uimage;
/* if os is a FIT image this will be provided */
struct fit_handle *os_fit;
@@ -84,7 +84,7 @@ struct image_data {
struct resource *initrd_res;
/* if initrd is an uImage this will be provided */
- struct uimage_handle *initrd;
+ struct uimage_handle *initrd_uimage;
char *initrd_part;
/* otherwise only the filename will be provided */
--
2.47.3
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v2 10/13] uimage: record original file name in uimage_handle
2026-02-09 18:10 [PATCH v2 00/13] bootm: prepare loadable abstraction rework Ahmad Fatoum
` (8 preceding siblings ...)
2026-02-09 18:10 ` [PATCH v2 09/13] bootm: rename image_data::os/initrd with _uimage suffix Ahmad Fatoum
@ 2026-02-09 18:10 ` Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 11/13] bootm: factor out file detection into helper Ahmad Fatoum
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2026-02-09 18:10 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The struct uimage_handle only stores the file name if header->ih_name
if empty. To make it possible to always get a descriptive name for when
bootm-uimage is switched over to loadables, let's store the filename
in the uimage_handle.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/uimage.c | 2 ++
include/image.h | 1 +
2 files changed, 3 insertions(+)
diff --git a/common/uimage.c b/common/uimage.c
index 5f7087475709..d34205572510 100644
--- a/common/uimage.c
+++ b/common/uimage.c
@@ -183,6 +183,7 @@ struct uimage_handle *uimage_open(const char *filename)
* fd is now at the first data word
*/
handle->fd = fd;
+ handle->filename = xstrdup(filename);
return handle;
err_out:
@@ -212,6 +213,7 @@ void uimage_close(struct uimage_handle *handle)
}
free(handle->name);
+ free(handle->filename);
free(handle);
}
EXPORT_SYMBOL(uimage_close);
diff --git a/include/image.h b/include/image.h
index d9a1b8f3ee02..769523d6fcaf 100644
--- a/include/image.h
+++ b/include/image.h
@@ -312,6 +312,7 @@ void *uimage_load_to_buf(struct uimage_handle *handle, int image_no,
struct uimage_handle {
struct image_header header;
char *name;
+ char *filename;
char *copy;
struct uimage_handle_data ihd[MAX_MULTI_IMAGE_COUNT];
int nb_data_entries;
--
2.47.3
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v2 11/13] bootm: factor out file detection into helper
2026-02-09 18:10 [PATCH v2 00/13] bootm: prepare loadable abstraction rework Ahmad Fatoum
` (9 preceding siblings ...)
2026-02-09 18:10 ` [PATCH v2 10/13] uimage: record original file name in uimage_handle Ahmad Fatoum
@ 2026-02-09 18:10 ` Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 12/13] efi: payload: bootm: add dry run support Ahmad Fatoum
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2026-02-09 18:10 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Having this function callable on its own will come in handy once we add
boot.image override support as that would need to recompute the file
type.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/bootm.c | 39 ++++++++++++++++++++++++++++++---------
include/bootm.h | 2 ++
2 files changed, 32 insertions(+), 9 deletions(-)
diff --git a/common/bootm.c b/common/bootm.c
index 3c3523644b57..d43079bb81da 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -542,6 +542,33 @@ static int bootm_image_name_and_part(const char *name, char **filename, char **p
return 0;
}
+/**
+ * file_read_and_detect_boot_image_type - read file header and detect image type
+ * @os_file: path to the boot image file
+ * @os_header: returns a PAGE_SIZE buffer with the file header (caller frees)
+ *
+ * Return: detected filetype (enum filetype) on success, negative error code
+ * on failure. On error, *os_header is set to NULL.
+ */
+int file_read_and_detect_boot_image_type(const char *os_file, void **os_header)
+{
+ size_t size;
+ int ret;
+
+ ret = read_file_2(os_file, &size, os_header, PAGE_SIZE);
+ if (ret < 0 && ret != -EFBIG) {
+ pr_err("could not open %s: %pe\n", os_file, ERR_PTR(ret));
+ return ret;
+ }
+ if (size < PAGE_SIZE) {
+ free(*os_header);
+ *os_header = NULL;
+ return -ENODATA;
+ }
+
+ return file_detect_boot_image_type(*os_header, PAGE_SIZE);
+}
+
/*
* bootm_boot - Boot an application image described by bootm_data
*/
@@ -550,7 +577,6 @@ int bootm_boot(struct bootm_data *bootm_data)
struct image_data *data;
struct image_handler *handler;
int ret;
- size_t size;
const char *image_type_str;
if (!bootm_data->os_file) {
@@ -574,15 +600,10 @@ int bootm_boot(struct bootm_data *bootm_data)
data->os_entry = bootm_data->os_entry;
data->efi_boot = bootm_data->efi_boot;
- ret = read_file_2(data->os_file, &size, &data->os_header, PAGE_SIZE);
- if (ret < 0 && ret != -EFBIG) {
- pr_err("could not open %s: %pe\n", data->os_file, ERR_PTR(ret));
+ ret = file_read_and_detect_boot_image_type(data->os_file, &data->os_header);
+ if (ret < 0)
goto err_out;
- }
- if (size < PAGE_SIZE)
- goto err_out;
-
- data->image_type = file_detect_boot_image_type(data->os_header, PAGE_SIZE);
+ data->image_type = ret;
if (!data->force && data->image_type == filetype_unknown) {
pr_err("Unknown OS filetype (try -f)\n");
diff --git a/include/bootm.h b/include/bootm.h
index ef979807505d..21feb1ca98ae 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -186,4 +186,6 @@ bool bootm_efi_check_image(struct image_handler *handler,
struct image_data *data,
enum filetype detected_filetype);
+int file_read_and_detect_boot_image_type(const char *os_file, void **os_header);
+
#endif /* __BOOTM_H */
--
2.47.3
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v2 12/13] efi: payload: bootm: add dry run support
2026-02-09 18:10 [PATCH v2 00/13] bootm: prepare loadable abstraction rework Ahmad Fatoum
` (10 preceding siblings ...)
2026-02-09 18:10 ` [PATCH v2 11/13] bootm: factor out file detection into helper Ahmad Fatoum
@ 2026-02-09 18:10 ` Ahmad Fatoum
2026-02-09 18:10 ` [PATCH v2 13/13] efi: initrd: make efi_initrd_register initrd pointer param const Ahmad Fatoum
2026-02-13 14:07 ` [PATCH v2 00/13] bootm: prepare loadable abstraction rework Sascha Hauer
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2026-02-09 18:10 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
barebox bootm handlers are supposed to check the dry run flag.
While at it, also fix the code to free initrd in error paths.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/payload/bootm.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/efi/payload/bootm.c b/efi/payload/bootm.c
index 617f5610e745..f1f60e2eaa54 100644
--- a/efi/payload/bootm.c
+++ b/efi/payload/bootm.c
@@ -252,15 +252,16 @@ static int do_bootm_efi_stub(struct image_data *data)
goto unload_oftree;
type = file_detect_type(loaded_image->image_base, PAGE_SIZE);
- ret = efi_execute_image(handle, loaded_image, type);
- if (ret)
+
+ if (data->dryrun)
goto unload_ramdisk;
- return 0;
-
+ ret = efi_execute_image(handle, loaded_image, type);
unload_ramdisk:
- if (initrd)
+ if (initrd) {
efi_initrd_unregister();
+ free(initrd);
+ }
unload_oftree:
efi_unload_fdt(fdt);
unload_os:
--
2.47.3
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH v2 13/13] efi: initrd: make efi_initrd_register initrd pointer param const
2026-02-09 18:10 [PATCH v2 00/13] bootm: prepare loadable abstraction rework Ahmad Fatoum
` (11 preceding siblings ...)
2026-02-09 18:10 ` [PATCH v2 12/13] efi: payload: bootm: add dry run support Ahmad Fatoum
@ 2026-02-09 18:10 ` Ahmad Fatoum
2026-02-13 14:07 ` [PATCH v2 00/13] bootm: prepare loadable abstraction rework Sascha Hauer
13 siblings, 0 replies; 15+ messages in thread
From: Ahmad Fatoum @ 2026-02-09 18:10 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
The initrd buffer isn't actually used in a writable manner, so reflect
that in the types used to hold its base address.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
efi/initrd.c | 4 ++--
efi/loader/bootm.c | 2 +-
include/efi/initrd.h | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/efi/initrd.c b/efi/initrd.c
index 642422b38d2a..01361d0a3071 100644
--- a/efi/initrd.c
+++ b/efi/initrd.c
@@ -35,7 +35,7 @@ static const struct {
static struct linux_initrd {
struct efi_load_file_protocol base;
- void *start;
+ const void *start;
size_t size;
efi_handle_t lf2_handle;
} initrd;
@@ -70,7 +70,7 @@ static efi_status_t EFIAPI efi_initrd_load_file2(
return EFI_SUCCESS;
}
-int efi_initrd_register(void *initrd_base, size_t initrd_sz)
+int efi_initrd_register(const void *initrd_base, size_t initrd_sz)
{
struct efi_boot_services *bs;
efi_status_t efiret;
diff --git a/efi/loader/bootm.c b/efi/loader/bootm.c
index 97621d8a05e5..6b59fa0fad18 100644
--- a/efi/loader/bootm.c
+++ b/efi/loader/bootm.c
@@ -187,7 +187,7 @@ static efi_status_t efi_install_initrd(struct image_data *data,
if (IS_ERR(initrd_res))
return PTR_ERR(initrd_res);
if (initrd_res)
- efi_initrd_register((void *)initrd_res->start,
+ efi_initrd_register((const void *)initrd_res->start,
resource_size(initrd_res));
return EFI_SUCCESS;
diff --git a/include/efi/initrd.h b/include/efi/initrd.h
index 08af2d299ad6..b36875c7fe7c 100644
--- a/include/efi/initrd.h
+++ b/include/efi/initrd.h
@@ -5,7 +5,7 @@
#include <linux/types.h>
-int efi_initrd_register(void *initrd, size_t initrd_size);
+int efi_initrd_register(const void *initrd, size_t initrd_size);
void efi_initrd_unregister(void);
#endif
--
2.47.3
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH v2 00/13] bootm: prepare loadable abstraction rework
2026-02-09 18:10 [PATCH v2 00/13] bootm: prepare loadable abstraction rework Ahmad Fatoum
` (12 preceding siblings ...)
2026-02-09 18:10 ` [PATCH v2 13/13] efi: initrd: make efi_initrd_register initrd pointer param const Ahmad Fatoum
@ 2026-02-13 14:07 ` Sascha Hauer
13 siblings, 0 replies; 15+ messages in thread
From: Sascha Hauer @ 2026-02-13 14:07 UTC (permalink / raw)
To: barebox, Ahmad Fatoum
On Mon, 09 Feb 2026 19:10:39 +0100, Ahmad Fatoum wrote:
> v1 -> v2:
> - Dropped "efi: payload: bootm: fix memory corruption on initrd load error":
> Sent out separately
> - Dropped "bootm: cache os_file for appendroot purposes"
> Preparatory patch that has been superseded for the second part of
> this rework
> - Move memory_bank_lookup_region() closer to the bootm_load()
> functions, and make sure same argument are used for both.
> - Switch over efi_loader_bootm as well by using bootm_load_os
> - In fit_open, propagate error for short reads correctly
> - add kernel-doc for open_fdt, resize_region,
> file_read_and_detect_boot_image_type
> - export file_read_and_detect_boot_image_type for future use
> - fix intermittent regression for initrd loading
> - resize_region: return error on resizing to 0 size (Sascha)
> - resize_region: check that there is no conflict with child resources
> (Sascha)
>
> [...]
Applied, thanks!
[01/13] FIT: implement fit_count_images
https://git.pengutronix.de/cgit/barebox/commit/?id=78ab21a74771 (link may not be stable)
[02/13] FIT: add image index argument to fit_open_image
https://git.pengutronix.de/cgit/barebox/commit/?id=5b0796484a85 (link may not be stable)
[03/13] resource: implement gap-aware lookup_region
https://git.pengutronix.de/cgit/barebox/commit/?id=81bf39698226 (link may not be stable)
[04/13] bootm: give bootm_load_ functions an end address
https://git.pengutronix.de/cgit/barebox/commit/?id=f048eaf9323d (link may not be stable)
[05/13] bootm: store separate image_type and kernel_type
https://git.pengutronix.de/cgit/barebox/commit/?id=3b843b66e84d (link may not be stable)
[06/13] bootm: fit: move length calculation into fit_open
https://git.pengutronix.de/cgit/barebox/commit/?id=cc202f94db33 (link may not be stable)
[07/13] libfile: factor out zero-page resistant read_file as __read_full_anywhere
https://git.pengutronix.de/cgit/barebox/commit/?id=56832e6dbbab (link may not be stable)
[08/13] resource: implement resize_region
https://git.pengutronix.de/cgit/barebox/commit/?id=7cd4ea927438 (link may not be stable)
[09/13] bootm: rename image_data::os/initrd with _uimage suffix
https://git.pengutronix.de/cgit/barebox/commit/?id=fe3b12b27cd3 (link may not be stable)
[10/13] uimage: record original file name in uimage_handle
https://git.pengutronix.de/cgit/barebox/commit/?id=d540a886bd78 (link may not be stable)
[11/13] bootm: factor out file detection into helper
https://git.pengutronix.de/cgit/barebox/commit/?id=9be5e29c7262 (link may not be stable)
[12/13] efi: payload: bootm: add dry run support
https://git.pengutronix.de/cgit/barebox/commit/?id=12cfd35f6619 (link may not be stable)
[13/13] efi: initrd: make efi_initrd_register initrd pointer param const
https://git.pengutronix.de/cgit/barebox/commit/?id=f4d060f1b563 (link may not be stable)
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 15+ messages in thread