* [PATCH 1/2] bootm: fit: open FIT images only once per loadable
2026-10-01 7:11 [PATCH 0/2] FIT: Do not hash image data twice Sascha Hauer
@ 2026-10-01 7:11 ` Sascha Hauer
2026-10-01 7:11 ` [PATCH 2/2] FIT: do not cache uncompressed data Sascha Hauer
1 sibling, 0 replies; 3+ messages in thread
From: Sascha Hauer @ 2026-10-01 7:11 UTC (permalink / raw)
To: BAREBOX
Since commit c3d383e958f3 ("bootm: fit: switch to new loadable API")
the FIT loadable calls fit_open_image() on every access. bootm accesses
the kernel loadable twice: in bootm_open_fit() to detect the kernel type
from its header and in the image handler to copy it to its load address.
Each call hashes the image again, which takes about 40 ms for a 12 MB
kernel on an RK3588.
Cache data and size in the loadable, so the image is verified and
decompressed only on first use. The data is owned by the FIT handle,
which the loadable holds a reference to until it is released.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/bootm-fit.c | 40 +++++++++++++++++++++++++++-------------
1 file changed, 27 insertions(+), 13 deletions(-)
diff --git a/common/bootm-fit.c b/common/bootm-fit.c
index f7742b8717..68bede1300 100644
--- a/common/bootm-fit.c
+++ b/common/bootm-fit.c
@@ -194,23 +194,38 @@ struct fit_loadable_priv {
struct device_node *config;
const char *image_name;
int index;
+ const void *data;
+ unsigned long size;
};
+/*
+ * fit_loadable_open() - verify and decompress the image on first use
+ * @priv: FIT loadable private data
+ *
+ * The result is cached, so hashing and decompression happen only once.
+ * The data is owned by the FIT handle, which we hold a reference to.
+ */
+static int fit_loadable_open(struct fit_loadable_priv *priv)
+{
+ if (priv->data)
+ return 0;
+
+ return fit_open_image(priv->fit, priv->config, priv->image_name,
+ priv->index, &priv->data, &priv->size);
+}
+
static int fit_loadable_get_info(struct loadable *l, struct loadable_info *info)
{
struct fit_loadable_priv *priv = l->priv;
- const void *data;
- unsigned long size;
int ret;
/* Open image to get size */
- ret = fit_open_image(priv->fit, priv->config, priv->image_name,
- priv->index, &data, &size);
+ ret = fit_loadable_open(priv);
if (ret)
return ret;
/* TODO: This will trigger an uncompression currently.. */
- info->final_size = size;
+ info->final_size = priv->size;
return 0;
}
@@ -218,17 +233,14 @@ static int fit_loadable_get_info(struct loadable *l, struct loadable_info *info)
static const void *fit_loadable_mmap(struct loadable *l, size_t *size)
{
struct fit_loadable_priv *priv = l->priv;
- const void *data;
- unsigned long image_size;
int ret;
- ret = fit_open_image(priv->fit, priv->config, priv->image_name,
- priv->index, &data, &image_size);
+ ret = fit_loadable_open(priv);
if (ret)
return MAP_FAILED;
- *size = image_size;
- return data;
+ *size = priv->size;
+ return priv->data;
}
/**
@@ -264,11 +276,13 @@ static ssize_t fit_loadable_extract_into_buf(struct loadable *l, void *load_addr
/* TODO: optimize, so it decompresses directly to load address */
/* Open image to get data */
- ret = fit_open_image(priv->fit, priv->config, priv->image_name,
- priv->index, &data, &size);
+ ret = fit_loadable_open(priv);
if (ret)
return ret;
+ data = priv->data;
+ size = priv->size;
+
/* Check if buffer is large enough */
if (offset > size)
return 0;
--
2.47.3
^ permalink raw reply [flat|nested] 3+ messages in thread* [PATCH 2/2] FIT: do not cache uncompressed data
2026-10-01 7:11 [PATCH 0/2] FIT: Do not hash image data twice Sascha Hauer
2026-10-01 7:11 ` [PATCH 1/2] bootm: fit: open FIT images only once per loadable Sascha Hauer
@ 2026-10-01 7:11 ` Sascha Hauer
1 sibling, 0 replies; 3+ messages in thread
From: Sascha Hauer @ 2026-10-01 7:11 UTC (permalink / raw)
To: BAREBOX
This effectively reverts commit b1babdb15cf0 ("FIT: cache uncompressed
data").
That commit kept the decompressed data around, so that device trees
decompressed to match their compatible did not have to be decompressed
again later. Since commit 5d7d60c4961c ("FIT: do not decompress device
trees to find compatible") compressed device trees are no longer used
for compatible matching, and the FIT loadables now cache the opened
image themselves, so nothing benefits from the cache anymore.
The decompressed buffer is still attached to the image node, so that it
is freed together with the FIT.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
common/image-fit.c | 24 ++++++++++--------------
1 file changed, 10 insertions(+), 14 deletions(-)
diff --git a/common/image-fit.c b/common/image-fit.c
index d16d805d53..fdd4b271cc 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -754,7 +754,6 @@ static int fit_handle_decompression(struct device_node *image,
int *data_len)
{
const char *compression;
- struct property *pp;
void *uc_data;
int ret;
@@ -774,21 +773,18 @@ static int fit_handle_decompression(struct device_node *image,
return -ENOSYS;
}
- pp = of_find_property(image, "$uncompressed-data", NULL);
- if (!pp) {
- ret = uncompress_buf_to_buf(*data, *data_len, &uc_data,
- fit_uncompress_error_fn);
- if (ret < 0) {
- pr_err("%s data couldn't be decompressed\n", compression);
- return ret;
- }
-
- /* associate buffer with FIT, so it's not leaked */
- pp = __of_new_property(image, "$uncompressed-data", uc_data, ret);
+ ret = uncompress_buf_to_buf(*data, *data_len, &uc_data,
+ fit_uncompress_error_fn);
+ if (ret < 0) {
+ pr_err("%s data couldn't be decompressed\n", compression);
+ return ret;
}
- *data = of_property_get_value(pp);
- *data_len = pp->length;
+ *data = uc_data;
+ *data_len = ret;
+
+ /* associate buffer with FIT, so it's not leaked */
+ __of_new_property(image, "$uncompressed-data", uc_data, *data_len);
return 0;
}
--
2.47.3
^ permalink raw reply [flat|nested] 3+ messages in thread