* [PATCH 0/7] commands: boot: add support for overriding boot artifacts
@ 2025-02-14 10:48 Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 1/7] bootm: add helper functions for checking if FIT image is used Ahmad Fatoum
` (7 more replies)
0 siblings, 8 replies; 11+ messages in thread
From: Ahmad Fatoum @ 2025-02-14 10:48 UTC (permalink / raw)
To: barebox
Replacing part of the boot artifacts is a common development use case,
e.g. to load the kernel from the network, but otherwise boot the
bootloader spec file as-is or to inject an initrd into an existing boot
flow (e.g. rsinit to enable usb9pfs boot).
This series adds a simple to use way to achieve that.
Ahmad Fatoum (7):
bootm: add helper functions for checking if FIT image is used
boot: move global.linux.bootargs.dyn. to common code
blspec: don't clobber bootm.image on boot attempt
fastboot: drop useless bootm.image clobber
bootm: don't clobber global.bootm. variables after script boot fails
bootm: retire bootm_has_initrd
commands: boot: add support for overriding boot artifacts
Documentation/user/booting-linux.rst | 8 ++
arch/arm/lib32/bootm.c | 18 ++-
arch/kvx/lib/bootm.c | 23 ++--
commands/boot.c | 53 +++++++-
common/Kconfig | 7 ++
common/blspec.c | 7 +-
common/boot.c | 14 ++-
common/booti.c | 10 +-
common/bootm.c | 173 +++++++++++++++++++--------
common/fastboot.c | 3 -
include/bootm.h | 23 +++-
11 files changed, 249 insertions(+), 90 deletions(-)
--
2.39.5
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/7] bootm: add helper functions for checking if FIT image is used
2025-02-14 10:48 [PATCH 0/7] commands: boot: add support for overriding boot artifacts Ahmad Fatoum
@ 2025-02-14 10:48 ` Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 2/7] boot: move global.linux.bootargs.dyn. to common code Ahmad Fatoum
` (6 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Ahmad Fatoum @ 2025-02-14 10:48 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
This introduces no functional change, but improves code readability.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/bootm.c | 31 +++++++++++++++++++------------
1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/common/bootm.c b/common/bootm.c
index 2c7d3691407b..d1dbf6890f6f 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -188,19 +188,20 @@ int bootm_load_os(struct image_data *data, unsigned long load_address)
return -EINVAL;
}
+static bool fitconfig_has_ramdisk(struct image_data *data)
+{
+ if (!IS_ENABLED(CONFIG_FITIMAGE) || !data->os_fit)
+ return false;
+
+ return fit_has_image(data->os_fit, data->fit_config, "ramdisk");
+}
+
bool bootm_has_initrd(struct image_data *data)
{
if (!IS_ENABLED(CONFIG_BOOTM_INITRD))
return false;
- if (IS_ENABLED(CONFIG_FITIMAGE) && data->os_fit &&
- fit_has_image(data->os_fit, data->fit_config, "ramdisk"))
- return true;
-
- if (data->initrd_file)
- return true;
-
- return false;
+ return fitconfig_has_ramdisk(data) || data->initrd_file;
}
static int bootm_open_initrd_uimage(struct image_data *data)
@@ -258,8 +259,7 @@ int bootm_load_initrd(struct image_data *data, unsigned long load_address)
if (data->initrd_res)
return 0;
- if (IS_ENABLED(CONFIG_FITIMAGE) && data->os_fit &&
- fit_has_image(data->os_fit, data->fit_config, "ramdisk")) {
+ if (fitconfig_has_ramdisk(data)) {
const void *initrd;
unsigned long initrd_size;
@@ -371,6 +371,14 @@ static int bootm_open_oftree_uimage(struct image_data *data, size_t *size,
return 0;
}
+static bool fitconfig_has_fdt(struct image_data *data)
+{
+ if (!IS_ENABLED(CONFIG_FITIMAGE) || !data->os_fit)
+ return false;
+
+ return fit_has_image(data->os_fit, data->fit_config, "fdt");
+}
+
/*
* bootm_get_devicetree() - get devicetree
*
@@ -391,8 +399,7 @@ void *bootm_get_devicetree(struct image_data *data)
if (!IS_ENABLED(CONFIG_OFTREE))
return ERR_PTR(-ENOSYS);
- if (IS_ENABLED(CONFIG_FITIMAGE) && data->os_fit &&
- fit_has_image(data->os_fit, data->fit_config, "fdt")) {
+ if (fitconfig_has_fdt(data)) {
const void *of_tree;
unsigned long of_size;
--
2.39.5
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/7] boot: move global.linux.bootargs.dyn. to common code
2025-02-14 10:48 [PATCH 0/7] commands: boot: add support for overriding boot artifacts Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 1/7] bootm: add helper functions for checking if FIT image is used Ahmad Fatoum
@ 2025-02-14 10:48 ` Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 3/7] blspec: don't clobber bootm.image on boot attempt Ahmad Fatoum
` (5 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Ahmad Fatoum @ 2025-02-14 10:48 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Instead of clearing these options by select boot targets prior to boot,
let's instead clear them directly after the boot aborting.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/blspec.c | 1 -
common/boot.c | 3 ++-
common/fastboot.c | 1 -
3 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/common/blspec.c b/common/blspec.c
index ea334e18718a..8a7f996e78d2 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -81,7 +81,6 @@ static int blspec_boot(struct bootentry *be, int verbose, int dryrun)
.dryrun = dryrun,
};
- globalvar_set_match("linux.bootargs.dyn.", "");
globalvar_set("bootm.image", "");
globalvar_set("bootm.oftree", "");
globalvar_set("bootm.initrd", "");
diff --git a/common/boot.c b/common/boot.c
index ced3b3a3477c..42818c6e2154 100644
--- a/common/boot.c
+++ b/common/boot.c
@@ -83,7 +83,6 @@ static int bootscript_boot(struct bootentry *entry, int verbose, int dryrun)
globalvar_add_simple("linux.bootargs.dyn.ip", NULL);
globalvar_add_simple("linux.bootargs.dyn.root", NULL);
- globalvar_set_match("linux.bootargs.dyn.", "");
ret = run_command(bs->scriptpath);
if (ret) {
@@ -162,6 +161,8 @@ int boot_entry(struct bootentry *be, int verbose, int dryrun)
if (ret && ret != -ENOMEDIUM)
pr_err("Booting entry '%s' failed: %pe\n", be->title, ERR_PTR(ret));
+ globalvar_set_match("linux.bootargs.dyn.", "");
+
return ret;
}
diff --git a/common/fastboot.c b/common/fastboot.c
index 66b59ab9b0d7..acc91490a553 100644
--- a/common/fastboot.c
+++ b/common/fastboot.c
@@ -419,7 +419,6 @@ static void __maybe_unused cb_boot(struct fastboot *fb, const char *opt)
fastboot_tx_print(fb, FASTBOOT_MSG_INFO, "Booting kernel..\n");
- globalvar_set_match("linux.bootargs.dyn.", "");
globalvar_set("bootm.image", "");
data.os_file = fb->tempname;
--
2.39.5
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/7] blspec: don't clobber bootm.image on boot attempt
2025-02-14 10:48 [PATCH 0/7] commands: boot: add support for overriding boot artifacts Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 1/7] bootm: add helper functions for checking if FIT image is used Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 2/7] boot: move global.linux.bootargs.dyn. to common code Ahmad Fatoum
@ 2025-02-14 10:48 ` Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 4/7] fastboot: drop useless bootm.image clobber Ahmad Fatoum
` (4 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Ahmad Fatoum @ 2025-02-14 10:48 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
bootm_data_init_defaults() initialized the defaults from global
variables and thus the blspec code cleared the global variables.
This roundabout way can be confusing to users as a failing bootloader
spec boot would clobber these variables.
Let's improve upon this by just ignoring the variables explicitly
instead of clobbering them.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/blspec.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/common/blspec.c b/common/blspec.c
index 8a7f996e78d2..1cbadf8963af 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -81,12 +81,8 @@ static int blspec_boot(struct bootentry *be, int verbose, int dryrun)
.dryrun = dryrun,
};
- globalvar_set("bootm.image", "");
- globalvar_set("bootm.oftree", "");
- globalvar_set("bootm.initrd", "");
-
bootm_data_init_defaults(&data);
-
+ data.os_file = data.oftree_file = data.initrd_file = NULL;
data.verbose = max(verbose, data.verbose);
devicetree = blspec_entry_var_get(entry, "devicetree");
--
2.39.5
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 4/7] fastboot: drop useless bootm.image clobber
2025-02-14 10:48 [PATCH 0/7] commands: boot: add support for overriding boot artifacts Ahmad Fatoum
` (2 preceding siblings ...)
2025-02-14 10:48 ` [PATCH 3/7] blspec: don't clobber bootm.image on boot attempt Ahmad Fatoum
@ 2025-02-14 10:48 ` Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 5/7] bootm: don't clobber global.bootm. variables after script boot fails Ahmad Fatoum
` (3 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Ahmad Fatoum @ 2025-02-14 10:48 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Clobbering bootm.image before a fastboot boot is not useful, because no
code would look at bootm.image anyway.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/fastboot.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/common/fastboot.c b/common/fastboot.c
index acc91490a553..60bef0ec776b 100644
--- a/common/fastboot.c
+++ b/common/fastboot.c
@@ -419,8 +419,6 @@ static void __maybe_unused cb_boot(struct fastboot *fb, const char *opt)
fastboot_tx_print(fb, FASTBOOT_MSG_INFO, "Booting kernel..\n");
- globalvar_set("bootm.image", "");
-
data.os_file = fb->tempname;
ret = bootm_boot(&data);
--
2.39.5
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 5/7] bootm: don't clobber global.bootm. variables after script boot fails
2025-02-14 10:48 [PATCH 0/7] commands: boot: add support for overriding boot artifacts Ahmad Fatoum
` (3 preceding siblings ...)
2025-02-14 10:48 ` [PATCH 4/7] fastboot: drop useless bootm.image clobber Ahmad Fatoum
@ 2025-02-14 10:48 ` Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 6/7] bootm: retire bootm_has_initrd Ahmad Fatoum
` (2 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Ahmad Fatoum @ 2025-02-14 10:48 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
While there is global.linux.bootargs.dyn to avoid boot script variables
contaminating later boot targets, there is no such thing for the
global.bootm. variables and as such it was up to the boot targets to
either ignore the variables or to override them.
The proper way would to expect the boot script boot callback to restore
the variables as they were before, so let's do that.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/boot.c | 11 ++++++++---
common/bootm.c | 17 +++++++++++++++++
include/bootm.h | 1 +
3 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/common/boot.c b/common/boot.c
index 42818c6e2154..2530a5bbeeac 100644
--- a/common/boot.c
+++ b/common/boot.c
@@ -74,20 +74,22 @@ static int bootscript_boot(struct bootentry *entry, int verbose, int dryrun)
struct bootentry_script *bs = container_of(entry, struct bootentry_script, entry);
int ret;
- struct bootm_data data = {};
+ struct bootm_data backup = {}, data = {};
if (dryrun == 1) {
printf("Would run %s\n", bs->scriptpath);
return 0;
}
+ bootm_data_init_defaults(&backup);
+
globalvar_add_simple("linux.bootargs.dyn.ip", NULL);
globalvar_add_simple("linux.bootargs.dyn.root", NULL);
ret = run_command(bs->scriptpath);
if (ret) {
pr_err("Running script '%s' failed: %s\n", bs->scriptpath, strerror(-ret));
- return ret;
+ goto out;
}
bootm_data_init_defaults(&data);
@@ -97,7 +99,10 @@ static int bootscript_boot(struct bootentry *entry, int verbose, int dryrun)
if (dryrun >= 2)
data.dryrun = dryrun - 1;
- return bootm_boot(&data);
+ ret = bootm_boot(&data);
+out:
+ bootm_data_restore_defaults(&backup);
+ return ret;
}
static unsigned int boot_watchdog_timeout;
diff --git a/common/bootm.c b/common/bootm.c
index d1dbf6890f6f..d24b18b41cb2 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -68,6 +68,23 @@ void bootm_data_init_defaults(struct bootm_data *data)
data->dryrun = bootm_dryrun;
}
+void bootm_data_restore_defaults(const struct bootm_data *data)
+{
+ globalvar_set("bootm.oftree", data->oftree_file);
+ globalvar_set("bootm.tee", data->tee_file);
+ globalvar_set("bootm.image", data->os_file);
+ pr_setenv("global.bootm.image.loadaddr", "0x%lx", data->os_address);
+ pr_setenv("global.bootm.initrd.loadaddr", "0x%lx", data->initrd_address);
+ globalvar_set("bootm.initrd", data->initrd_file);
+ globalvar_set("bootm.root_dev", data->root_dev);
+ bootm_set_verify_mode(data->verify);
+ bootm_appendroot = data->appendroot;
+ bootm_provide_machine_id = data->provide_machine_id;
+ bootm_provide_hostname = data->provide_hostname;
+ bootm_verbosity = data->verbose;
+ bootm_dryrun = data->dryrun;
+}
+
static enum bootm_verify bootm_verify_mode = BOOTM_VERIFY_HASH;
enum bootm_verify bootm_get_verify_mode(void)
diff --git a/include/bootm.h b/include/bootm.h
index 98ac5e5a9374..fdec137771f0 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -138,6 +138,7 @@ static inline int bootm_verbose(struct image_data *data)
#endif
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);
--
2.39.5
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 6/7] bootm: retire bootm_has_initrd
2025-02-14 10:48 [PATCH 0/7] commands: boot: add support for overriding boot artifacts Ahmad Fatoum
` (4 preceding siblings ...)
2025-02-14 10:48 ` [PATCH 5/7] bootm: don't clobber global.bootm. variables after script boot fails Ahmad Fatoum
@ 2025-02-14 10:48 ` Ahmad Fatoum
2025-02-14 20:02 ` [PATCH] fixup! " Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 7/7] commands: boot: add support for overriding boot artifacts Ahmad Fatoum
2025-02-17 9:27 ` [PATCH 0/7] " Sascha Hauer
7 siblings, 1 reply; 11+ messages in thread
From: Ahmad Fatoum @ 2025-02-14 10:48 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
All what's done by bootm_has_initrd can be folded into bootm_load_initrd
by having it return a special value (NULL) to indicate that no initrd
is available.
The advantage of doing it in one function is that it simplifies
overriding the initrd in a follow-up commit
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/arm/lib32/bootm.c | 18 ++++++++----------
arch/kvx/lib/bootm.c | 23 +++++++++++------------
common/booti.c | 10 +++++-----
common/bootm.c | 35 ++++++++++++++---------------------
include/bootm.h | 4 ++--
5 files changed, 40 insertions(+), 50 deletions(-)
diff --git a/arch/arm/lib32/bootm.c b/arch/arm/lib32/bootm.c
index aeb873a3a723..d3a4d99a5828 100644
--- a/arch/arm/lib32/bootm.c
+++ b/arch/arm/lib32/bootm.c
@@ -241,6 +241,7 @@ 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;
void *tee;
enum arm_security_state state = bootm_arm_security_state();
void *fdt_load_address = NULL;
@@ -259,16 +260,13 @@ static int __do_bootm_linux(struct image_data *data, unsigned long free_mem,
}
}
- if (bootm_has_initrd(data)) {
- ret = bootm_load_initrd(data, initrd_start);
- if (ret)
- return ret;
- }
-
- if (data->initrd_res) {
- initrd_start = data->initrd_res->start;
- initrd_end = data->initrd_res->end;
- initrd_size = resource_size(data->initrd_res);
+ initrd_res = bootm_load_initrd(data, initrd_start);
+ if (IS_ERR(initrd_res)) {
+ return PTR_ERR(initrd_res);
+ } else if (initrd_res) {
+ initrd_start = initrd_res->start;
+ initrd_end = initrd_res->end;
+ initrd_size = resource_size(initrd_res);
free_mem = PAGE_ALIGN(initrd_end + 1);
}
diff --git a/arch/kvx/lib/bootm.c b/arch/kvx/lib/bootm.c
index 4c77f676ec0b..6c35b68f3d5d 100644
--- a/arch/kvx/lib/bootm.c
+++ b/arch/kvx/lib/bootm.c
@@ -54,6 +54,7 @@ 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;
int ret;
void *fdt;
boot_func_entry entry;
@@ -61,21 +62,19 @@ static int do_boot_elf(struct image_data *data, struct elf_image *elf)
/* load initrd after the elf */
load_addr = PAGE_ALIGN((unsigned long) elf->high_addr);
- if (bootm_has_initrd(data)) {
- if (data->initrd_address != UIMAGE_INVALID_ADDRESS)
- initrd_address = data->initrd_address;
- else
- initrd_address = load_addr;
+ if (data->initrd_address != UIMAGE_INVALID_ADDRESS)
+ initrd_address = data->initrd_address;
+ else
+ initrd_address = load_addr;
+ initrd_res = bootm_load_initrd(data, initrd_address);
+ if (IS_ERR(initrd_res)) {
+ printf("Failed to load initrd\n");
+ return ret;
+ } else if (initrd_res) {
printf("Loading initrd at 0x%lx\n", initrd_address);
- ret = bootm_load_initrd(data, initrd_address);
- if (ret) {
- printf("Failed to load initrd\n");
- return ret;
- }
-
if (data->initrd_address == UIMAGE_INVALID_ADDRESS) {
- load_addr += resource_size(data->initrd_res);
+ load_addr += resource_size(initrd_res);
load_addr = PAGE_ALIGN(load_addr);
}
}
diff --git a/common/booti.c b/common/booti.c
index e745ff696376..5efd4f97bbc2 100644
--- a/common/booti.c
+++ b/common/booti.c
@@ -58,12 +58,12 @@ void *booti_load_image(struct image_data *data, phys_addr_t *oftree)
if (oftree) {
unsigned long devicetree;
+ const struct resource *initrd_res;
- if (bootm_has_initrd(data)) {
- ret = bootm_load_initrd(data, image_end);
- if (ret)
- return ERR_PTR(ret);
-
+ initrd_res = bootm_load_initrd(data, image_end);
+ if (IS_ERR(initrd_res)) {
+ return ERR_CAST(initrd_res);
+ } else if (initrd_res) {
image_end += resource_size(data->initrd_res);
image_end = PAGE_ALIGN(image_end);
}
diff --git a/common/bootm.c b/common/bootm.c
index d24b18b41cb2..d2373f321c19 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -213,14 +213,6 @@ static bool fitconfig_has_ramdisk(struct image_data *data)
return fit_has_image(data->os_fit, data->fit_config, "ramdisk");
}
-bool bootm_has_initrd(struct image_data *data)
-{
- if (!IS_ENABLED(CONFIG_BOOTM_INITRD))
- return false;
-
- return fitconfig_has_ramdisk(data) || data->initrd_file;
-}
-
static int bootm_open_initrd_uimage(struct image_data *data)
{
int ret;
@@ -262,19 +254,17 @@ static int bootm_open_initrd_uimage(struct image_data *data)
*
* Return: 0 on success, negative error code otherwise
*/
-int bootm_load_initrd(struct image_data *data, unsigned long load_address)
+const struct resource *
+bootm_load_initrd(struct image_data *data, unsigned long load_address)
{
enum filetype type;
int ret;
if (!IS_ENABLED(CONFIG_BOOTM_INITRD))
- return -ENOSYS;
-
- if (!bootm_has_initrd(data))
- return -EINVAL;
+ return NULL;
if (data->initrd_res)
- return 0;
+ return data->initrd_res;
if (fitconfig_has_ramdisk(data)) {
const void *initrd;
@@ -285,7 +275,7 @@ int bootm_load_initrd(struct image_data *data, unsigned long load_address)
if (ret) {
pr_err("Cannot open ramdisk image in FIT image: %s\n",
strerror(-ret));
- return ret;
+ return ERR_PTR(ret);
}
data->initrd_res = request_sdram_region("initrd",
load_address,
@@ -295,17 +285,20 @@ int bootm_load_initrd(struct image_data *data, unsigned long load_address)
" 0x%08llx-0x%08llx\n",
(unsigned long long)load_address,
(unsigned long long)load_address + initrd_size - 1);
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}
memcpy((void *)load_address, initrd, initrd_size);
pr_info("Loaded initrd from FIT image\n");
goto done1;
}
+ if (!data->initrd_file)
+ return NULL;
+
ret = file_name_detect_type(data->initrd_file, &type);
if (ret) {
pr_err("could not open initrd \"%s\": %s\n", data->initrd_file, strerror(-ret));
- return ret;
+ return ERR_PTR(ret);
}
if (type == filetype_uimage) {
@@ -314,7 +307,7 @@ int bootm_load_initrd(struct image_data *data, unsigned long load_address)
if (ret) {
pr_err("loading initrd failed with %s\n",
strerror(-ret));
- return ret;
+ return ERR_PTR(ret);
}
num = uimage_part_num(data->initrd_part);
@@ -322,14 +315,14 @@ int bootm_load_initrd(struct image_data *data, unsigned long load_address)
data->initrd_res = uimage_load_to_sdram(data->initrd,
num, load_address);
if (!data->initrd_res)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
goto done;
}
data->initrd_res = file_to_sdram(data->initrd_file, load_address);
if (!data->initrd_res)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
done:
@@ -343,7 +336,7 @@ int bootm_load_initrd(struct image_data *data, unsigned long load_address)
&data->initrd_res->start,
&data->initrd_res->end);
- return 0;
+ return data->initrd_res;
}
static int bootm_open_oftree_uimage(struct image_data *data, size_t *size,
diff --git a/include/bootm.h b/include/bootm.h
index fdec137771f0..b86d06b0f55d 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -142,8 +142,8 @@ void bootm_data_restore_defaults(const struct bootm_data *data);
int bootm_load_os(struct image_data *data, unsigned long load_address);
-bool bootm_has_initrd(struct image_data *data);
-int bootm_load_initrd(struct image_data *data, unsigned long load_address);
+const struct resource *
+bootm_load_initrd(struct image_data *data, unsigned long load_address);
void *bootm_get_devicetree(struct image_data *data);
int bootm_load_devicetree(struct image_data *data, void *fdt,
--
2.39.5
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 7/7] commands: boot: add support for overriding boot artifacts
2025-02-14 10:48 [PATCH 0/7] commands: boot: add support for overriding boot artifacts Ahmad Fatoum
` (5 preceding siblings ...)
2025-02-14 10:48 ` [PATCH 6/7] bootm: retire bootm_has_initrd Ahmad Fatoum
@ 2025-02-14 10:48 ` Ahmad Fatoum
2025-02-15 12:29 ` [PATCH] fixup! " Ahmad Fatoum
2025-02-17 9:27 ` [PATCH 0/7] " Sascha Hauer
7 siblings, 1 reply; 11+ messages in thread
From: Ahmad Fatoum @ 2025-02-14 10:48 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
Replacing part of the boot artifacts is a common development use case,
e.g. to load the kernel from the network, but otherwise boot the
bootloader spec file as-is or to inject an initrd into an existing boot
flow (e.g. rsinit to enable usb9pfs boot).
Add a simple to use way to achieve that.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
Documentation/user/booting-linux.rst | 8 ++
commands/boot.c | 53 +++++++++++++-
common/Kconfig | 7 ++
common/bootm.c | 106 +++++++++++++++++++++------
include/bootm.h | 18 +++++
5 files changed, 169 insertions(+), 23 deletions(-)
diff --git a/Documentation/user/booting-linux.rst b/Documentation/user/booting-linux.rst
index b26ada943a59..b49b2c93b1f3 100644
--- a/Documentation/user/booting-linux.rst
+++ b/Documentation/user/booting-linux.rst
@@ -161,6 +161,14 @@ This entry can be booted with ``boot mmc``. It can also be made the default by
setting the ``global.boot.default`` variable to ``mmc`` and then calling
``boot`` without arguments.
+Especially for development, it can be useful to override only parts of
+the images used in a boot. To do so, set ``CONFIG_BOOT_OVERRIDE=y``
+and configure the overrides as arguments to the ``boot`` command::
+
+.. code-block:: sh
+
+ boot -o bootm.image=/mnt/tftp/oftree mmc
+
.. _bootloader_spec:
Boot Loader Specification
diff --git a/commands/boot.c b/commands/boot.c
index e4699520e8f5..820708380191 100644
--- a/commands/boot.c
+++ b/commands/boot.c
@@ -6,6 +6,7 @@
#include <getopt.h>
#include <malloc.h>
#include <boot.h>
+#include <bootm.h>
#include <complete.h>
#include <linux/stat.h>
@@ -23,6 +24,42 @@ static char *next_word(void *context)
return strsep(context, " ");
}
+static int boot_add_override(struct bootm_overrides *overrides, char *var)
+{
+ const char *val;
+
+ if (!IS_ENABLED(CONFIG_BOOT_OVERRIDE))
+ return -ENOSYS;
+
+ var += str_has_prefix(var, "global.");
+
+ val = parse_assignment(var);
+ if (!val) {
+ val = globalvar_get(var);
+ if (isempty(val))
+ val = NULL;
+ }
+
+ if (!strcmp(var, "bootm.image")) {
+ if (isempty(val))
+ return -EINVAL;
+ overrides->os_file = val;
+ } else if (!strcmp(var, "bootm.oftree")) {
+ overrides->oftree_file = val;
+ } else if (!strcmp(var, "bootm.initrd")) {
+ overrides->initrd_file = val;
+ } else {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static inline bool boot_has_overrides(const struct bootm_overrides *overrides)
+{
+ return overrides->os_file || overrides->oftree_file || overrides->initrd_file;
+}
+
static int do_boot(int argc, char *argv[])
{
char *freep = NULL;
@@ -31,11 +68,12 @@ static int do_boot(int argc, char *argv[])
unsigned default_menu_entry = 0;
struct bootentries *entries;
struct bootentry *entry;
+ struct bootm_overrides overrides = {};
void *handle;
const char *name;
char *(*next)(void *);
- while ((opt = getopt(argc, argv, "vldmM:t:w:")) > 0) {
+ while ((opt = getopt(argc, argv, "vldmM:t:w:o:")) > 0) {
switch (opt) {
case 'v':
verbose++;
@@ -65,6 +103,11 @@ static int do_boot(int argc, char *argv[])
case 'w':
boot_set_watchdog_timeout(simple_strtoul(optarg, NULL, 0));
break;
+ case 'o':
+ ret = boot_add_override(&overrides, optarg);
+ if (ret)
+ return ret;
+ break;
default:
return COMMAND_ERROR_USAGE;
}
@@ -85,6 +128,8 @@ static int do_boot(int argc, char *argv[])
}
entries = bootentries_alloc();
+ if (boot_has_overrides(&overrides))
+ bootm_set_overrides(&overrides);
while ((name = next(&handle)) != NULL) {
if (!*name)
@@ -119,6 +164,8 @@ static int do_boot(int argc, char *argv[])
ret = 0;
out:
+ if (boot_has_overrides(&overrides))
+ bootm_unset_overrides();
bootentries_free(entries);
free(freep);
@@ -150,6 +197,10 @@ BAREBOX_CMD_HELP_OPT ("-l","List available boot sources")
BAREBOX_CMD_HELP_OPT ("-m","Show a menu with boot options")
BAREBOX_CMD_HELP_OPT ("-M INDEX","Show a menu with boot options with entry INDEX preselected")
BAREBOX_CMD_HELP_OPT ("-w SECS","Start watchdog with timeout SECS before booting")
+#ifdef CONFIG_BOOT_OVERRIDE
+BAREBOX_CMD_HELP_OPT ("-o VAR[=VAL]","override VAR (bootm.{image,oftree,initrd}) with VAL")
+BAREBOX_CMD_HELP_OPT (" ","if VAL is not specified, the value of VAR is taken")
+#endif
BAREBOX_CMD_HELP_OPT ("-t SECS","specify timeout in SECS")
BAREBOX_CMD_HELP_END
diff --git a/common/Kconfig b/common/Kconfig
index b5fba72390d8..0ce99e98286c 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -599,6 +599,13 @@ menuconfig BOOTM
default y if COMMAND_SUPPORT
bool "bootm support"
+config BOOT_OVERRIDE
+ bool "Support partial override of boot entries"
+ depends on BOOTM
+ help
+ Allow overriding of bootm image, oftree and initrd by passing
+ -o as an argument to the boot command.
+
config BOOTM_SHOW_TYPE
bool
depends on BOOTM && UIMAGE
diff --git a/common/bootm.c b/common/bootm.c
index d2373f321c19..80905d4cf1ce 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -17,6 +17,8 @@
static LIST_HEAD(handler_list);
+static __maybe_unused struct bootm_overrides bootm_overrides;
+
int register_image_handler(struct image_handler *handler)
{
list_add_tail(&handler->list, &handler_list);
@@ -141,6 +143,23 @@ static inline bool image_is_uimage(struct image_data *data)
return IS_ENABLED(CONFIG_BOOTM_UIMAGE) && data->os;
}
+static bool bootm_get_override(char **oldpath, const char *newpath)
+{
+ if (!IS_ENABLED(CONFIG_BOOT_OVERRIDE))
+ return false;
+ if (bootm_signed_images_are_forced())
+ return false;
+ if (!newpath)
+ return false;
+
+ if (oldpath && strcmp(*oldpath, newpath)) {
+ free(*oldpath);
+ *oldpath = *newpath ? xstrdup(newpath) : NULL;
+ }
+
+ return true;
+}
+
/*
* bootm_load_os() - load OS to RAM
*
@@ -155,6 +174,12 @@ static inline bool image_is_uimage(struct image_data *data)
*/
int bootm_load_os(struct image_data *data, unsigned long load_address)
{
+ if (bootm_get_override(&data->os_file, bootm_overrides.os_file)) {
+ if (load_address == UIMAGE_INVALID_ADDRESS)
+ return -EINVAL;
+ goto os_file;
+ }
+
if (data->os_res)
return 0;
@@ -194,15 +219,15 @@ int bootm_load_os(struct image_data *data, unsigned long load_address)
if (IS_ENABLED(CONFIG_ELF) && data->elf)
return elf_load(data->elf);
- if (data->os_file) {
- data->os_res = file_to_sdram(data->os_file, load_address);
- if (!data->os_res)
- return -ENOMEM;
+os_file:
+ if (!data->os_file)
+ return -EINVAL;
- return 0;
- }
+ data->os_res = file_to_sdram(data->os_file, load_address);
+ if (!data->os_res)
+ return -ENOMEM;
- return -EINVAL;
+ return 0;
}
static bool fitconfig_has_ramdisk(struct image_data *data)
@@ -263,6 +288,9 @@ bootm_load_initrd(struct image_data *data, unsigned long load_address)
if (!IS_ENABLED(CONFIG_BOOTM_INITRD))
return NULL;
+ if (bootm_get_override(&data->initrd_file, bootm_overrides.initrd_file))
+ goto initrd_file;
+
if (data->initrd_res)
return data->initrd_res;
@@ -292,6 +320,7 @@ bootm_load_initrd(struct image_data *data, unsigned long load_address)
goto done1;
}
+initrd_file:
if (!data->initrd_file)
return NULL;
@@ -404,12 +433,17 @@ void *bootm_get_devicetree(struct image_data *data)
{
enum filetype type;
struct fdt_header *oftree;
+ bool from_fit = false;
int ret;
if (!IS_ENABLED(CONFIG_OFTREE))
return ERR_PTR(-ENOSYS);
- if (fitconfig_has_fdt(data)) {
+ from_fit = fitconfig_has_fdt(data);
+ if (bootm_get_override(&data->oftree_file, bootm_overrides.oftree_file))
+ from_fit = false;
+
+ if (from_fit) {
const void *of_tree;
unsigned long of_size;
@@ -530,24 +564,29 @@ int bootm_load_devicetree(struct image_data *data, void *fdt,
int bootm_get_os_size(struct image_data *data)
{
+ const char *os_file;
+ struct stat s;
int ret;
- if (data->elf)
- return elf_get_mem_size(data->elf);
- if (image_is_uimage(data))
- return uimage_get_size(data->os, uimage_part_num(data->os_part));
- if (data->os_fit)
- return data->fit_kernel_size;
-
- if (data->os_file) {
- struct stat s;
- ret = stat(data->os_file, &s);
- if (ret)
- return ret;
- return s.st_size;
+ if (bootm_get_override(NULL, bootm_overrides.os_file)) {
+ os_file = bootm_overrides.os_file;
+ } else {
+ if (data->elf)
+ return elf_get_mem_size(data->elf);
+ if (image_is_uimage(data))
+ return uimage_get_size(data->os, uimage_part_num(data->os_part));
+ if (data->os_fit)
+ return data->fit_kernel_size;
+ if (!data->os_file)
+ return -EINVAL;
+ os_file = data->os_file;
}
- return -EINVAL;
+ ret = stat(os_file, &s);
+ if (ret)
+ return ret;
+
+ return s.st_size;
}
static int bootm_open_os_uimage(struct image_data *data)
@@ -909,6 +948,22 @@ int bootm_boot(struct bootm_data *bootm_data)
printf("Passing control to %s handler\n", handler->name);
}
+ if (bootm_get_override(&data->os_file, bootm_overrides.os_file)) {
+ if (data->os_res) {
+ release_sdram_region(data->os_res);
+ data->os_res = NULL;
+ }
+ }
+
+ bootm_get_override(&data->oftree_file, bootm_overrides.oftree_file);
+
+ if (bootm_get_override(&data->initrd_file, bootm_overrides.initrd_file)) {
+ if (data->initrd_res) {
+ release_sdram_region(data->initrd_res);
+ data->initrd_res = NULL;
+ }
+ }
+
ret = handler->bootm(data);
if (data->dryrun)
pr_info("Dryrun. Aborted\n");
@@ -946,6 +1001,13 @@ int bootm_boot(struct bootm_data *bootm_data)
return ret;
}
+#ifdef CONFIG_BOOT_OVERRIDE
+void bootm_set_overrides(const struct bootm_overrides *overrides)
+{
+ bootm_overrides = *overrides;
+}
+#endif
+
static int do_bootm_compressed(struct image_data *img_data)
{
struct bootm_data bootm_data = {
diff --git a/include/bootm.h b/include/bootm.h
index b86d06b0f55d..0e5e99773a26 100644
--- a/include/bootm.h
+++ b/include/bootm.h
@@ -160,4 +160,22 @@ void bootm_force_signed_images(void);
void *booti_load_image(struct image_data *data, phys_addr_t *oftree);
+struct bootm_overrides {
+ const char *os_file;
+ const char *oftree_file;
+ const char *initrd_file;
+};
+
+#ifdef CONFIG_BOOT_OVERRIDE
+void bootm_set_overrides(const struct bootm_overrides *overrides);
+#else
+static inline void bootm_set_overrides(const struct bootm_overrides *overrides) {}
+#endif
+
+static inline void bootm_unset_overrides(void)
+{
+ struct bootm_overrides overrides = {};
+ bootm_set_overrides(&overrides);
+}
+
#endif /* __BOOTM_H */
--
2.39.5
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] fixup! bootm: retire bootm_has_initrd
2025-02-14 10:48 ` [PATCH 6/7] bootm: retire bootm_has_initrd Ahmad Fatoum
@ 2025-02-14 20:02 ` Ahmad Fatoum
0 siblings, 0 replies; 11+ messages in thread
From: Ahmad Fatoum @ 2025-02-14 20:02 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
CI noticed correctly that ret is used uninitialized here.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
arch/kvx/lib/bootm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/kvx/lib/bootm.c b/arch/kvx/lib/bootm.c
index 6c35b68f3d5d..42c15ff27351 100644
--- a/arch/kvx/lib/bootm.c
+++ b/arch/kvx/lib/bootm.c
@@ -70,7 +70,7 @@ static int do_boot_elf(struct image_data *data, struct elf_image *elf)
initrd_res = bootm_load_initrd(data, initrd_address);
if (IS_ERR(initrd_res)) {
printf("Failed to load initrd\n");
- return ret;
+ return PTR_ERR(initrd_res);
} else if (initrd_res) {
printf("Loading initrd at 0x%lx\n", initrd_address);
if (data->initrd_address == UIMAGE_INVALID_ADDRESS) {
--
2.39.5
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] fixup! commands: boot: add support for overriding boot artifacts
2025-02-14 10:48 ` [PATCH 7/7] commands: boot: add support for overriding boot artifacts Ahmad Fatoum
@ 2025-02-15 12:29 ` Ahmad Fatoum
0 siblings, 0 replies; 11+ messages in thread
From: Ahmad Fatoum @ 2025-02-15 12:29 UTC (permalink / raw)
To: barebox; +Cc: Ahmad Fatoum
This allows e.g. adding an initrd, when none was specified before.
Otherwise, we would run into a NULL pointer exception.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
common/bootm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/bootm.c b/common/bootm.c
index dd9ba2eae3b2..fe4d51681d73 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -152,7 +152,7 @@ static bool bootm_get_override(char **oldpath, const char *newpath)
if (!newpath)
return false;
- if (oldpath && strcmp(*oldpath, newpath)) {
+ if (oldpath && !streq_ptr(*oldpath, newpath)) {
free(*oldpath);
*oldpath = *newpath ? xstrdup(newpath) : NULL;
}
--
2.39.5
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/7] commands: boot: add support for overriding boot artifacts
2025-02-14 10:48 [PATCH 0/7] commands: boot: add support for overriding boot artifacts Ahmad Fatoum
` (6 preceding siblings ...)
2025-02-14 10:48 ` [PATCH 7/7] commands: boot: add support for overriding boot artifacts Ahmad Fatoum
@ 2025-02-17 9:27 ` Sascha Hauer
7 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2025-02-17 9:27 UTC (permalink / raw)
To: barebox, Ahmad Fatoum
On Fri, 14 Feb 2025 11:48:10 +0100, Ahmad Fatoum wrote:
> Replacing part of the boot artifacts is a common development use case,
> e.g. to load the kernel from the network, but otherwise boot the
> bootloader spec file as-is or to inject an initrd into an existing boot
> flow (e.g. rsinit to enable usb9pfs boot).
>
> This series adds a simple to use way to achieve that.
>
> [...]
Applied, thanks!
[1/7] bootm: add helper functions for checking if FIT image is used
https://git.pengutronix.de/cgit/barebox/commit/?id=6244bcb9db80 (link may not be stable)
[2/7] boot: move global.linux.bootargs.dyn. to common code
https://git.pengutronix.de/cgit/barebox/commit/?id=1072e8421458 (link may not be stable)
[3/7] blspec: don't clobber bootm.image on boot attempt
https://git.pengutronix.de/cgit/barebox/commit/?id=f2c284fa14d6 (link may not be stable)
[4/7] fastboot: drop useless bootm.image clobber
https://git.pengutronix.de/cgit/barebox/commit/?id=3a07779b01e6 (link may not be stable)
[5/7] bootm: don't clobber global.bootm. variables after script boot fails
https://git.pengutronix.de/cgit/barebox/commit/?id=926985a74ee0 (link may not be stable)
[6/7] bootm: retire bootm_has_initrd
https://git.pengutronix.de/cgit/barebox/commit/?id=e86606dd2065 (link may not be stable)
[7/7] commands: boot: add support for overriding boot artifacts
https://git.pengutronix.de/cgit/barebox/commit/?id=a5e4c4340ef6 (link may not be stable)
Best regards,
--
Sascha Hauer <s.hauer@pengutronix.de>
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-02-17 9:42 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-02-14 10:48 [PATCH 0/7] commands: boot: add support for overriding boot artifacts Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 1/7] bootm: add helper functions for checking if FIT image is used Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 2/7] boot: move global.linux.bootargs.dyn. to common code Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 3/7] blspec: don't clobber bootm.image on boot attempt Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 4/7] fastboot: drop useless bootm.image clobber Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 5/7] bootm: don't clobber global.bootm. variables after script boot fails Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 6/7] bootm: retire bootm_has_initrd Ahmad Fatoum
2025-02-14 20:02 ` [PATCH] fixup! " Ahmad Fatoum
2025-02-14 10:48 ` [PATCH 7/7] commands: boot: add support for overriding boot artifacts Ahmad Fatoum
2025-02-15 12:29 ` [PATCH] fixup! " Ahmad Fatoum
2025-02-17 9:27 ` [PATCH 0/7] " Sascha Hauer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox