[PATCH 5/7] ARM: introduce jump_to_linux helper

Ahmad Fatoum a.fatoum at pengutronix.de
Wed Apr 9 07:01:33 PDT 2025


The upcoming FIP bootm handler should be usable on both ARM32 and ARM64
and thus we need an arch-independent way of booting a kernel with a
given device tree.

Introduce a jump_to_linux helper in <asm/boot.h> for this purpose.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/arm/include/asm/boot.h | 28 ++++++++++++++++++++++++++++
 arch/arm/lib32/armlinux.c   | 14 +++++++-------
 arch/arm/lib64/armlinux.c   | 12 ++++++------
 3 files changed, 41 insertions(+), 13 deletions(-)
 create mode 100644 arch/arm/include/asm/boot.h

diff --git a/arch/arm/include/asm/boot.h b/arch/arm/include/asm/boot.h
new file mode 100644
index 000000000000..a75d139ed8ea
--- /dev/null
+++ b/arch/arm/include/asm/boot.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef _ASM_BOOT_H_
+#define _ASM_BOOT_H_
+
+#include <linux/types.h>
+
+#ifdef CONFIG_ARM64
+static inline void jump_to_linux(const void *_kernel, phys_addr_t dtb)
+{
+	void (*kernel)(unsigned long dtb, unsigned long x1, unsigned long x2,
+		       unsigned long x3) = _kernel;
+	kernel(dtb, 0, 0, 0);
+}
+#else
+static inline void __jump_to_linux(const void *_kernel, unsigned arch,
+				   phys_addr_t params)
+{
+	void (*kernel)(int zero, unsigned arch, ulong params) = _kernel;
+	kernel(0, arch, params);
+}
+static inline void jump_to_linux(const void *_kernel, phys_addr_t dtb)
+{
+	__jump_to_linux(_kernel, ~0, dtb);
+}
+#endif
+
+#endif	/* _ASM_BOOT_H_ */
diff --git a/arch/arm/lib32/armlinux.c b/arch/arm/lib32/armlinux.c
index 0b332d23639d..56f278d3dbae 100644
--- a/arch/arm/lib32/armlinux.c
+++ b/arch/arm/lib32/armlinux.c
@@ -26,6 +26,7 @@
 #include <asm/armlinux.h>
 #include <asm/system.h>
 #include <asm/secure.h>
+#include <asm/boot.h>
 
 static struct tag *params;
 static void *armlinux_bootparams = NULL;
@@ -251,8 +252,7 @@ void start_linux(void *adr, int swap, unsigned long initrd_address,
 		 unsigned long initrd_size, void *oftree,
 		 enum arm_security_state state, void *optee)
 {
-	void (*kernel)(int zero, unsigned arch, void *params) = adr;
-	void *params = NULL;
+	phys_addr_t params = 0;
 	unsigned architecture;
 	int ret;
 
@@ -264,11 +264,11 @@ void start_linux(void *adr, int swap, unsigned long initrd_address,
 
 	if (oftree) {
 		pr_debug("booting kernel with devicetree\n");
-		params = oftree;
+		params = virt_to_phys(oftree);
 	} else {
-		params = armlinux_get_bootparams();
+		params = virt_to_phys(armlinux_get_bootparams());
 
-		if ((unsigned long)params < PAGE_SIZE)
+		if (params < PAGE_SIZE)
 			zero_page_access();
 
 		setup_tags(initrd_address, initrd_size, swap);
@@ -288,8 +288,8 @@ void start_linux(void *adr, int swap, unsigned long initrd_address,
 	}
 
 	if (optee && IS_ENABLED(CONFIG_BOOTM_OPTEE)) {
-		start_kernel_optee(optee, kernel, oftree);
+		start_kernel_optee(optee, adr, oftree);
 	} else {
-		kernel(0, architecture, params);
+		__jump_to_linux(adr, architecture, params);
 	}
 }
diff --git a/arch/arm/lib64/armlinux.c b/arch/arm/lib64/armlinux.c
index 5feee9c24f2a..13721a71236b 100644
--- a/arch/arm/lib64/armlinux.c
+++ b/arch/arm/lib64/armlinux.c
@@ -5,18 +5,18 @@
 #include <memory.h>
 #include <init.h>
 #include <bootm.h>
+#include <asm/boot.h>
 #include <efi/efi-mode.h>
 
 static int do_bootm_linux(struct image_data *data)
 {
-	void (*fn)(unsigned long dtb, unsigned long x1, unsigned long x2,
-		       unsigned long x3);
+	void *image;
 	phys_addr_t devicetree;
 	int ret;
 
-	fn = booti_load_image(data, &devicetree);
-	if (IS_ERR(fn))
-		return PTR_ERR(fn);
+	image = booti_load_image(data, &devicetree);
+	if (IS_ERR(image))
+		return PTR_ERR(image);
 
 	if (data->dryrun)
 		return 0;
@@ -27,7 +27,7 @@ static int do_bootm_linux(struct image_data *data)
 
 	shutdown_barebox();
 
-	fn(devicetree, 0, 0, 0);
+	jump_to_linux(image, devicetree);
 
 	return -EINVAL;
 }
-- 
2.39.5




More information about the barebox mailing list