[PATCH v3 10/11] boot: build the imagemap pointers only when enabled
Daniel Golle
daniel at makrotopia.org
Sat Oct 31 04:12:26 PDT 2026
struct bootm_headers and struct bootm_info carry an imagemap pointer
whatever the configuration, so every board pays for it with the feature
off, and each use site has to spell out an IS_ENABLED() test beside the
NULL check.
Compile the two fields under CONFIG_IMAGEMAP and reach them through
bootm_imagemap(), bootm_set_imagemap(), bootm_info_imagemap() and
bootm_info_set_imagemap(), which fold to NULL and to nothing when it
is off.
Reviewed-by: Simon Glass <sjg at chromium.org>
Signed-off-by: Daniel Golle <daniel at makrotopia.org>
---
v3: No changes since v1.
v2:
- Add bootm_info_set_imagemap() alongside the getter, so a future
caller does not have to spell the ifdef itself.
- The bootm_info_* accessors now carry the same !defined(USE_HOSTCC)
guard as bootm_imagemap(); tools/image-host.c pulls in bootm.h.
- fit_image_load_storage() keeps the device in a local instead of
calling bootm_imagemap() twice.
- The imagemap release in the OS-GO and error paths moves into the
shared bootm_imagemap_cleanup() helper.
boot/bootm.c | 44 ++++++++++++++++++++++++++++----------------
boot/image-fit.c | 13 +++++++------
include/bootm.h | 31 +++++++++++++++++++++++++++++++
include/image.h | 31 +++++++++++++++++++++++++++++++
4 files changed, 97 insertions(+), 22 deletions(-)
diff --git a/boot/bootm.c b/boot/bootm.c
index 67df647d176..a15296c8b8d 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -151,14 +151,14 @@ static int boot_get_kernel(const char *addr_fit, struct bootm_headers *images,
/* check image type, for FIT images get FIT kernel node */
*os_data = *os_len = 0;
- if (IS_ENABLED(CONFIG_IMAGEMAP) && images->imagemap) {
+ if (bootm_imagemap(images)) {
/*
* Storage path: read enough bytes to detect the image
* format. genimg_get_kernel_addr_fit() above still
* parsed any #config / :subimage suffix so the FIT
* selection variables are populated.
*/
- buf = imagemap_map(images->imagemap, 0,
+ buf = imagemap_map(bootm_imagemap(images), 0,
sizeof(struct legacy_img_hdr));
if (IS_ERR(buf)) {
puts("Cannot read image header from storage\n");
@@ -213,14 +213,14 @@ static int boot_get_kernel(const char *addr_fit, struct bootm_headers *images,
#endif
#if CONFIG_IS_ENABLED(FIT)
case IMAGE_FORMAT_FIT:
- if (IS_ENABLED(CONFIG_IMAGEMAP) && images->imagemap) {
+ if (bootm_imagemap(images)) {
/*
* Extend the mapping to cover the full FIT
* FDT structure so all metadata is accessible.
*/
size_t fdt_sz = fdt_totalsize(buf);
- buf = imagemap_map(images->imagemap, 0, fdt_sz);
+ buf = imagemap_map(bootm_imagemap(images), 0, fdt_sz);
if (IS_ERR(buf)) {
puts("Cannot read FIT header from storage\n");
return PTR_ERR(buf);
@@ -286,7 +286,7 @@ static int bootm_start(struct udevice *imagemap)
fit_verity_free(&images);
memset((void *)&images, 0, sizeof(images));
images.verify = env_get_yesno("verify");
- images.imagemap = imagemap;
+ bootm_set_imagemap(&images, imagemap);
bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start");
images.state = BOOTM_STATE_START;
@@ -1186,6 +1186,24 @@ unmap_image:
return ret;
}
+/**
+ * bootm_imagemap_cleanup() - release the on-demand storage loader
+ * @images: Boot images being used
+ *
+ * Tears down the imagemap device and clears the pointer, but only when one
+ * was in use. The two call sites (the OS-GO path and the error path) share
+ * this so the release logic lives in one place.
+ */
+static void bootm_imagemap_cleanup(struct bootm_headers *images)
+{
+ struct udevice *imagemap = bootm_imagemap(images);
+
+ if (imagemap) {
+ imagemap_cleanup(imagemap);
+ bootm_set_imagemap(images, NULL);
+ }
+}
+
int bootm_run_states(struct bootm_info *bmi, int states)
{
struct bootm_headers *images = bmi->images;
@@ -1200,11 +1218,11 @@ int bootm_run_states(struct bootm_info *bmi, int states)
* any error.
*/
if (states & BOOTM_STATE_START)
- ret = bootm_start(bmi->imagemap);
+ ret = bootm_start(bootm_info_imagemap(bmi));
if (!ret && (states & BOOTM_STATE_PRE_LOAD)) {
/* Pre-load verification is not applicable to storage boot */
- if (!IS_ENABLED(CONFIG_IMAGEMAP) || !images->imagemap)
+ if (!bootm_imagemap(images))
ret = bootm_pre_load(bmi->addr_img);
}
@@ -1214,7 +1232,7 @@ int bootm_run_states(struct bootm_info *bmi, int states)
if (!ret && (states & BOOTM_STATE_FINDOTHER)) {
ulong img_addr;
- if (IS_ENABLED(CONFIG_IMAGEMAP) && images->imagemap)
+ if (bootm_imagemap(images))
img_addr = images->os.start;
else
img_addr = bmi->addr_img ? hextoul(bmi->addr_img, NULL)
@@ -1318,10 +1336,7 @@ int bootm_run_states(struct bootm_info *bmi, int states)
/* Now run the OS! We hope this doesn't return */
if (!ret && (states & BOOTM_STATE_OS_GO)) {
/* Release storage backend before jumping - no return expected */
- if (IS_ENABLED(CONFIG_IMAGEMAP) && images->imagemap) {
- imagemap_cleanup(images->imagemap);
- images->imagemap = NULL;
- }
+ bootm_imagemap_cleanup(images);
ret = boot_selected_os(BOOTM_STATE_OS_GO, bmi, boot_fn);
}
@@ -1329,10 +1344,7 @@ int bootm_run_states(struct bootm_info *bmi, int states)
/* Deal with any fallout */
err:
/* Clean up imagemap on error (not reached on successful boot) */
- if (IS_ENABLED(CONFIG_IMAGEMAP) && images->imagemap) {
- imagemap_cleanup(images->imagemap);
- images->imagemap = NULL;
- }
+ bootm_imagemap_cleanup(images);
if (iflag)
enable_interrupts();
diff --git a/boot/image-fit.c b/boot/image-fit.c
index 0367331c25d..d104367f91b 100644
--- a/boot/image-fit.c
+++ b/boot/image-fit.c
@@ -1163,10 +1163,10 @@ int fit_image_get_data(const void *fit, int noffset, const void **data,
}
*data = fit + offset;
#if !defined(USE_HOSTCC) && CONFIG_IS_ENABLED(IMAGEMAP)
- if (images.imagemap) {
+ if (bootm_imagemap(&images)) {
void *mapped;
- mapped = imagemap_lookup(images.imagemap,
+ mapped = imagemap_lookup(bootm_imagemap(&images),
offset, len);
if (mapped)
*data = mapped;
@@ -2212,6 +2212,7 @@ static int fit_image_load_storage(struct bootm_headers *images, const void *fit,
u8 img_comp = IH_COMP_NONE;
void *mapped;
void *dst;
+ struct udevice *imagemap = bootm_imagemap(images);
int ret;
if (CONFIG_IS_ENABLED(FIT_VERITY)) {
@@ -2242,11 +2243,11 @@ static int fit_image_load_storage(struct bootm_headers *images, const void *fit,
!fit_image_get_load(fit, noffset, &img_load)) {
dst = map_sysmem(img_load, data_sz);
- mapped = imagemap_map_to(images->imagemap, data_off, data_sz,
+ mapped = imagemap_map_to(imagemap, data_off, data_sz,
dst);
unmap_sysmem(dst);
} else {
- mapped = imagemap_map(images->imagemap, data_off, data_sz);
+ mapped = imagemap_map(imagemap, data_off, data_sz);
}
return IS_ERR(mapped) ? PTR_ERR(mapped) : 0;
@@ -2361,7 +2362,7 @@ int fit_image_load(struct bootm_headers *images, ulong addr,
* On-demand storage: pre-load external-data payloads into RAM (or leave
* dm-verity filesystems on storage) before fit_image_select() verifies.
*/
- if (CONFIG_IS_ENABLED(IMAGEMAP) && !tools_build() && images->imagemap) {
+ if (!tools_build() && bootm_imagemap(images)) {
bool early = false;
ret = fit_image_load_storage(images, fit, noffset, load_op,
@@ -2486,7 +2487,7 @@ int fit_image_load(struct bootm_headers *images, ulong addr,
}
/* A storage-backed image was read straight to its load address */
- if (!images->imagemap || data != load)
+ if (!bootm_imagemap(images) || data != load)
printf(" Loading %s from 0x%08lx to 0x%08lx\n",
prop_name, data, load);
} else {
diff --git a/include/bootm.h b/include/bootm.h
index d1aac3d44df..272583c8471 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -52,12 +52,43 @@ struct bootm_info {
const char *conf_fdt;
bool boot_progress;
struct bootm_headers *images;
+#if CONFIG_IS_ENABLED(IMAGEMAP)
struct udevice *imagemap;
+#endif
const char *cmd_name;
int argc;
char *const *argv;
};
+/**
+ * bootm_info_imagemap() - Get the storage loader a boot was asked to use
+ *
+ * @bmi: Boot info
+ * Return: the imagemap device, or NULL to boot an image already in RAM
+ */
+static inline struct udevice *bootm_info_imagemap(struct bootm_info *bmi)
+{
+#if !defined(USE_HOSTCC) && CONFIG_IS_ENABLED(IMAGEMAP)
+ return bmi->imagemap;
+#else
+ return NULL;
+#endif
+}
+
+/**
+ * bootm_info_set_imagemap() - Record the storage loader a boot should use
+ *
+ * @bmi: Boot info
+ * @imagemap: The imagemap device, or NULL for an image already in RAM
+ */
+static inline void bootm_info_set_imagemap(struct bootm_info *bmi,
+ struct udevice *imagemap)
+{
+#if !defined(USE_HOSTCC) && CONFIG_IS_ENABLED(IMAGEMAP)
+ bmi->imagemap = imagemap;
+#endif
+}
+
/**
* bootm_init() - Set up a bootm_info struct with useful defaults
*
diff --git a/include/image.h b/include/image.h
index 5248ca98d41..14189581646 100644
--- a/include/image.h
+++ b/include/image.h
@@ -412,7 +412,9 @@ struct bootm_headers {
int verify; /* env_get("verify")[0] != 'n' */
+#if !defined(USE_HOSTCC) && CONFIG_IS_ENABLED(IMAGEMAP)
struct udevice *imagemap; /* on-demand storage loader, or NULL */
+#endif
#define BOOTM_STATE_START 0x00000001
#define BOOTM_STATE_FINDOS 0x00000002
@@ -432,6 +434,35 @@ struct bootm_headers {
extern struct bootm_headers images;
+/**
+ * bootm_imagemap() - Get the on-demand storage loader in use, if any
+ *
+ * @images: Images being booted
+ * Return: the imagemap device, or NULL when the image is already in RAM
+ */
+static inline struct udevice *bootm_imagemap(struct bootm_headers *images)
+{
+#if !defined(USE_HOSTCC) && CONFIG_IS_ENABLED(IMAGEMAP)
+ return images->imagemap;
+#else
+ return NULL;
+#endif
+}
+
+/**
+ * bootm_set_imagemap() - Record the on-demand storage loader to read through
+ *
+ * @images: Images being booted
+ * @imagemap: The imagemap device, or NULL for an image already in RAM
+ */
+static inline void bootm_set_imagemap(struct bootm_headers *images,
+ struct udevice *imagemap)
+{
+#if !defined(USE_HOSTCC) && CONFIG_IS_ENABLED(IMAGEMAP)
+ images->imagemap = imagemap;
+#endif
+}
+
/*
* Some systems (for example LWMON) have very short watchdog periods;
* we must make sure to split long operations like memmove() or
--
2.56.0
More information about the openwrt-devel
mailing list