mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>,
	"Claude Opus 4.5" <noreply@anthropic.com>
Subject: [PATCH 11/16] bootm: implement plain and FIT bootm.image override
Date: Thu, 12 Mar 2026 15:44:54 +0100	[thread overview]
Message-ID: <20260312144505.2159816-11-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20260312144505.2159816-1-a.fatoum@pengutronix.de>

Add support for overriding the boot image via bootm.image when using
either plain files or FIT images. The override behavior depends on the
file types involved:

- If the override is not a FIT image, it replaces only the OS loadable,
  regardless of whether the original was a FIT image or not.

- If the override is a FIT image, it replaces the current OS, whether
  it's a FIT or not.

This allows developers to use devboot scripts to redirect FIT image
loading to alternate locations (e.g., network) while preserving the
configuration selection from the original boot entry.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
 commands/boot.c           |   2 +-
 common/bootm-fit.c        |  11 +++-
 common/bootm-overrides.c  | 119 +++++++++++++++++++++++++++++++++++++-
 common/bootm.c            |   4 +-
 include/bootm-fit.h       |   4 +-
 include/bootm-overrides.h |   3 +
 include/bootm.h           |   2 +
 7 files changed, 134 insertions(+), 11 deletions(-)

diff --git a/commands/boot.c b/commands/boot.c
index 555667ee098c..04bb9eb9186f 100644
--- a/commands/boot.c
+++ b/commands/boot.c
@@ -44,7 +44,7 @@ static int boot_add_override(struct bootm_overrides *overrides, char *var)
 	if (!strcmp(var, "bootm.image")) {
 		if (isempty(val))
 			return -EINVAL;
-		return -ENOSYS;
+		overrides->os_file = val;
 	} else if (!strcmp(var, "bootm.oftree")) {
 		overrides->oftree_file = val;
 	} else if (!strcmp(var, "bootm.initrd")) {
diff --git a/common/bootm-fit.c b/common/bootm-fit.c
index 5b110ad2f19e..995bd7181223 100644
--- a/common/bootm-fit.c
+++ b/common/bootm-fit.c
@@ -4,6 +4,7 @@
 #include <image-fit.h>
 #include <bootm-fit.h>
 #include <memory.h>
+#include <string.h>
 #include <zero_page.h>
 #include <filetype.h>
 #include <fs.h>
@@ -143,7 +144,7 @@ static enum filetype bootm_fit_update_os_header(struct image_data *data)
 	return os_type;
 }
 
-int bootm_open_fit(struct image_data *data)
+int bootm_open_fit(struct image_data *data, bool override)
 {
 	struct fit_handle *fit;
 	void *fit_config;
@@ -164,8 +165,12 @@ int bootm_open_fit(struct image_data *data)
 	}
 
 	loadable_from_fit_os(data, fit, fit_config);
-	loadable_from_fit_initrd(data, fit, fit_config);
-	loadable_from_fit_oftree(data, fit, fit_config);
+	if (override)
+		data->is_override.os = true;
+	if (loadable_from_fit_initrd(data, fit, fit_config) && override)
+		data->is_override.initrd = true;
+	if (loadable_from_fit_oftree(data, fit, fit_config) && override)
+		data->is_override.oftree = true;
 	loadable_from_fit_tee(data, fit, fit_config);
 
 	data->kernel_type = bootm_fit_update_os_header(data);
diff --git a/common/bootm-overrides.c b/common/bootm-overrides.c
index 59ca90a58684..8c71ceb5f80d 100644
--- a/common/bootm-overrides.c
+++ b/common/bootm-overrides.c
@@ -2,14 +2,118 @@
 
 #include <bootm.h>
 #include <bootm-overrides.h>
+#include <bootm-fit.h>
+#include <libfile.h>
+#include <linux/pagemap.h>
+
+/**
+ * bootm_apply_image_override - apply bootm.image override
+ * @data: image data context
+ * @override: override path (may include @config suffix for FIT)
+ *
+ * Applies a bootm.image override according to these rules:
+ * - If the override is not a FIT image, it replaces only data->os.
+ * - If the override is a FIT image, it is re-opened via bootm_open_fit()
+ *   using the default configuration or the @config suffix if given.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int bootm_apply_image_override(struct image_data *data,
+				      const char *override)
+{
+	char *override_file, *override_part;
+	void *override_header = NULL;
+	int ret;
+
+	ret = bootm_image_name_and_part(override, &override_file, &override_part);
+	if (ret)
+		return ret;
+
+	/* Read header to detect file type */
+	ret = file_read_and_detect_boot_image_type(override_file, &override_header);
+	if (ret < 0) {
+		free(override_file);
+		return ret;
+	}
+
+	data->image_type = ret;
+
+	/*
+	 * bootm_image_name_and_part() returns os_part pointing inside the
+	 * os_file allocation, so we must NULLify os_part before freeing
+	 * os_file to avoid a use-after-free.
+	 */
+	data->os_part = NULL;
+	free(data->os_file);
+	data->os_file = override_file;
+	if (override_part)
+		data->os_part = override_part;
+
+	/* Update the detected type for the handler */
+	free(data->os_header);
+	data->os_header = override_header;
+
+	switch (data->image_type) {
+	case filetype_fit:
+		/* Restore, so bootm_open_fit looks for them in the new FIT */
+		data->os_address = data->os_address_hint;
+		data->os_entry = data->os_entry_hint;
+
+		/* Re-open configuration and collect loadables */
+		return bootm_open_fit(data, true);
+	default:
+		loadable_release(&data->os);
+		data->os = loadable_from_file(override_file, LOADABLE_KERNEL);
+		if (IS_ERR(data->os))
+			return PTR_ERR(data->os);
+
+		data->kernel_type = data->image_type;
+		data->is_override.os = true;
+
+		if (file_is_compressed_file(data->kernel_type))
+			return bootm_open_os_compressed(data);
+
+		return 0;
+	}
+}
+
+static void report_active_override(const char *type_str, struct loadable *l)
+{
+	struct loadable *lc;
+	char *buf = NULL;
+
+	if (!l) {
+		pr_notice("[bootm override active] removed %s\n", type_str);
+		return;
+	}
+
+	buf = xrasprintf(buf, "[bootm override active] replacement %s: %s",
+		      type_str, l->name);
+
+	list_for_each_entry(lc, &l->chained_loadables, list)
+		buf = xrasprintf(buf, ", %s", lc->name);
+
+	pr_notice("%s\n", buf);
+	free(buf);
+}
+
+static void report_active_overrides(const struct image_data *data)
+{
+	if (data->is_override.os)
+		report_active_override("OS", data->os);
+	if (data->is_override.initrd)
+		report_active_override("initrd", data->initrd);
+	if (data->is_override.oftree)
+		report_active_override("FDT", data->oftree);
+}
 
 /**
  * bootm_apply_overrides - apply overrides
  * @data: image data context
  * @overrides: overrides to apply
  *
- * Applies bootm.initrd and bootm.oftree overrides by translating
- * them into file-based loadables.
+ * Applies bootm.image, bootm.initrd, and bootm.oftree overrides by translating
+ * them into file-based loadables or FIT image replacements.
  *
  * Context: Called during boot preparation
  * Return: 0 on success, negative error code otherwise
@@ -17,9 +121,17 @@
 int bootm_apply_overrides(struct image_data *data,
 			  const struct bootm_overrides *overrides)
 {
+	int ret;
+
 	if (bootm_signed_images_are_forced())
 		return 0;
 
+	if (nonempty(overrides->os_file)) {
+		ret = bootm_apply_image_override(data, overrides->os_file);
+		if (ret)
+			return ret;
+	}
+
 	if (IS_ENABLED(CONFIG_BOOTM_INITRD) && overrides->initrd_file) {
 		/* loadables_from_files() will set data->initrd on empty initrd_file */
 		int ret = loadables_from_files(&data->initrd, overrides->initrd_file, ":",
@@ -42,6 +154,7 @@ int bootm_apply_overrides(struct image_data *data,
 		data->is_override.oftree = true;
 	}
 
+	report_active_overrides(data);
+
 	return 0;
 }
-
diff --git a/common/bootm.c b/common/bootm.c
index ddc656fb34c8..ed79c20c0972 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -400,7 +400,7 @@ static void bootm_print_info(struct image_data *data)
 		printf("OS image not yet relocated\n");
 }
 
-static int bootm_image_name_and_part(const char *name, char **filename, char **part)
+int bootm_image_name_and_part(const char *name, char **filename, char **part)
 {
 	char *at, *ret;
 
@@ -570,7 +570,7 @@ struct image_data *bootm_boot_prep(const struct bootm_data *bootm_data)
 
 	switch (data->image_type) {
 	case filetype_fit:
-		ret = bootm_open_fit(data);
+		ret = bootm_open_fit(data, false);
 		break;
 	case filetype_uimage:
 		ret = bootm_open_uimage(data);
diff --git a/include/bootm-fit.h b/include/bootm-fit.h
index 05f4f5acfe9a..972d9e4fac8e 100644
--- a/include/bootm-fit.h
+++ b/include/bootm-fit.h
@@ -10,11 +10,11 @@ struct image_data;
 
 #ifdef CONFIG_BOOTM_FITIMAGE
 
-int bootm_open_fit(struct image_data *data);
+int bootm_open_fit(struct image_data *data, bool override);
 
 #else
 
-static inline int bootm_open_fit(struct image_data *data)
+static inline int bootm_open_fit(struct image_data *data, bool override)
 {
 	return -ENOSYS;
 }
diff --git a/include/bootm-overrides.h b/include/bootm-overrides.h
index a52a498b97a2..9b133928a923 100644
--- a/include/bootm-overrides.h
+++ b/include/bootm-overrides.h
@@ -3,6 +3,7 @@
 #define __BOOTM_OVERRIDES_H
 
 struct bootm_overrides {
+	const char *os_file;
 	const char *oftree_file;
 	const char *initrd_file;
 };
@@ -13,6 +14,8 @@ struct image_data;
 static inline void bootm_merge_overrides(struct bootm_overrides *dst,
 					 const struct bootm_overrides *src)
 {
+	if (src->os_file)
+		dst->os_file = src->os_file;
 	if (src->oftree_file)
 		dst->oftree_file = src->oftree_file;
 	if (src->initrd_file)
diff --git a/include/bootm.h b/include/bootm.h
index 570ac4d289f2..85199fc702b4 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -53,6 +53,8 @@ struct bootm_data {
 	unsigned long os_entry;
 };
 
+int bootm_image_name_and_part(const char *name, char **filename, char **part);
+
 int bootm_boot(const struct bootm_data *data);
 
 struct image_data *bootm_boot_prep(const struct bootm_data *bootm_data);
-- 
2.47.3




  parent reply	other threads:[~2026-03-12 15:03 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-12 14:44 [PATCH 01/16] lib: add lazy loadable infrastructure for deferred boot component loading Ahmad Fatoum
2026-03-12 14:44 ` [PATCH 02/16] bootm: split preparatory step from handler invocation Ahmad Fatoum
2026-03-12 14:44 ` [PATCH 03/16] boot: add bootm_boot wrapper that takes struct bootentry Ahmad Fatoum
2026-03-12 14:44 ` [PATCH 04/16] bootchooser: pass along " Ahmad Fatoum
2026-03-12 14:44 ` [PATCH 05/16] bootm: switch plain file names case to loadable API Ahmad Fatoum
2026-03-12 14:44 ` [PATCH 06/16] uimage: add offset parameter to uimage_load Ahmad Fatoum
2026-03-12 14:44 ` [PATCH 07/16] bootm: uimage: switch to loadable API Ahmad Fatoum
2026-03-12 14:44 ` [PATCH 08/16] bootm: fit: switch to new " Ahmad Fatoum
2026-03-12 14:44 ` [PATCH 09/16] bootm: stash initial OS address/entry in image_data Ahmad Fatoum
2026-03-12 14:44 ` [PATCH 10/16] bootm: support multiple entries for bootm.initrd Ahmad Fatoum
2026-03-12 14:44 ` Ahmad Fatoum [this message]
2026-03-18  9:01   ` [PATCH 11/16] bootm: implement plain and FIT bootm.image override Sascha Hauer
2026-03-18  9:17     ` Ahmad Fatoum
2026-03-12 14:44 ` [PATCH 12/16] bootm: overrides: add support for overlays Ahmad Fatoum
2026-03-12 14:44 ` [PATCH 13/16] test: py: add test for initrd concatenation Ahmad Fatoum
2026-03-12 14:44 ` [PATCH 14/16] defaultenv: base: add new devboot script Ahmad Fatoum
2026-03-18  9:50   ` Sascha Hauer
2026-03-18 10:50     ` Ahmad Fatoum
2026-03-18 14:49       ` Sascha Hauer
2026-03-12 14:44 ` [PATCH 15/16] Documentation: user: devboot: add section on forwarding build dirs Ahmad Fatoum
2026-03-12 14:44 ` [PATCH 16/16] libfile: remove file_to_sdram Ahmad Fatoum
2026-03-18 10:06 ` [PATCH 01/16] lib: add lazy loadable infrastructure for deferred boot component loading Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260312144505.2159816-11-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=barebox@lists.infradead.org \
    --cc=noreply@anthropic.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox