
Hi York,
If you don't mind, I would like to ask you for some help and clarification regarding your work.
Add jump_to_image_linux() for arm64. Add "noreturn" flag to armv8_switch_to_el2(). Add hooks to fsl-layerscape to enable falcon boot.
I'm trying to do the same on imx6q board (armv7).
Signed-off-by: York Sun york.sun@nxp.com
Changes in v2: Relace getenv_f() with env_get_f() after rebasing to latet master.
.../arm/cpu/armv8/fsl-layerscape/doc/README.falcon | 140 +++++++++++++++++++++ arch/arm/cpu/armv8/fsl-layerscape/spl.c | 29 +++++ arch/arm/include/asm/system.h | 2 +- arch/arm/lib/spl.c | 11 ++ 4 files changed, 181 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/armv8/fsl-layerscape/doc/README.falcon
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/doc/README.falcon b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.falcon new file mode 100644 index 0000000..282b19f --- /dev/null +++ b/arch/arm/cpu/armv8/fsl-layerscape/doc/README.falcon @@ -0,0 +1,140 @@ +Falcon boot option +------------------ +Falcon boot is a short cut boot method for SD/eMMC targets. It skips loading the +RAM version U-Boot. Instead, it loads FIT image and boot directly to Linux. +CONFIG_SPL_OS_BOOT enables falcon boot. CONFIG_SPL_LOAD_FIT enables the FIT
^^^^^^ - this is a bit cumbersome, since it requires some stub for dtb creation (but this can be fixed for boards not yet supporting dts u-boot configuration).
+image support (also need CONFIG_SPL_OF_LIBFDT, CONFIG_SPL_FIT and optionally +CONFIG_SPL_GZIP).
+To enable falcon boot, a hook function spl_start_uboot() returns 0 to indicate +booting U-Boot is not the first choice. The kernel FIT image needs to be put +at CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR. SPL mmc driver reads the header to +determine if this is a FIT image. If true, FIT image components are parsed and +copied or decompressed (if applicable) to their desitinations. If FIT image is +not found, normal U-Boot flow will follow.
This part is similar to the one for old, venerable uImage.
+An important part of falcon boot is to prepare the device tree. A normal U-Boot +does FDT fixups when booting Linux. For falcon boot, Linux boots directly from +SPL, skipping the normal U-Boot. The device tree has to be prepared in advance. +A command "spl export" should be called under the normal RAM version U-Boot. +It is equivalent to go through "bootm" step-by-step until device tree fixup is +done. The device tree in memory is the one needed for falcon boot. Falcon boot +flow suggests to save this image to SD/eMMC at the location pointed by macro +CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR, with maximum size specified by macro +CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS. However, when FIT image is used for +Linux, the device tree stored in FIT image overwrites the memory loaded by spl +driver from these sectors. We could change this loading order to favor the +stored sectors. But when secure boot is enabled, these sectors are used for +signature header and needs to be loaded before the FIT image. So it is important +to understand the device tree in FIT image should be the one actually used, or +leave it abscent to favor the stored sectors. It is easier to deploy the FIT +image with embedded static device tree to multiple boards.
+Macro CONFIG_SYS_SPL_ARGS_ADDR serves two purposes. One is the pointer to load +the stored sectors to. Normally this is the static device tree. The second +purpose is the memory location of signature header for secure boot. After the +FIT image is loaded into memory, it is validated against the signature header +before individual components are extracted (and optionally decompressed) into +their final memory locations, respectivelly. After the validation, the header +is no longer used. The static device tree is copied into this location. So +this macro is passed as the location of device tree when booting Linux.
I've not yet go to this point -> Please look into below comments.
I'm just curious - how can I specify the DTBs precedence? I mean how to decide if one from FIT or from eMMC sector are used?
+components. Otherwise U-Boot cannot load them correctly.
+Generate FIT image with static device tree +------------------------------------------ +Example:
+/dts-v1/;
I'm trying to load fitImage (with kernel + 2 dtbs) from eMMC directly by SPL. The fitImage has been generated with OE-core recipe. The same results are with one generated with mkimage.
+/ {
- description = "Image file for the LS1043A Linux Kernel";
- #address-cells = <1>;
- images {
kernel@1 {
description = "ARM64 Linux kernel";
data = /incbin/("./arch/arm64/boot/Image.gz");
type = "kernel";
arch = "arm64";
os = "linux";
compression = "gzip";
load = <0x80080000>;
entry = <0x80080000>;
^^^^ common/spl/spl_fit.c - function spl_load_fit_image() requires "data-offset" and "data-size" properties to be defined - otherwise we exit with -ENOENT.
Even when creating my fitImage with u-boot's mkimage those properties haven't been added.
};
fdt@1 {
description = "Flattened Device Tree blob";
data = /incbin/("./fsl-ls1043ardb-static.dtb");
type = "flat_dt";
arch = "arm64";
compression = "none";
load = <0x90000000>;
};
ramdisk@1 {
description = "LS1043 Ramdisk";
data = /incbin/("./rootfs.cpio.gz");
type = "ramdisk";
arch = "arm64";
os = "linux";
compression = "gzip";
load = <0xa0000000>;
};
- };
- configurations {
default = "config@1";
config@1 {
description = "Boot Linux kernel";
kernel = "kernel@1";
fdt = "fdt@1";
ramdisk = "ramdisk@1";
loadables = "fdt", "ramdisk";
^^^ Isn't here loadables require "kernel", "fdt", "ramdisk" ?
Could you share how have you managed to load fitImage from SPL? Maybe I'm missing some patches? Is there any "reference" repo, so I could see the "complete" work?
};
- };
+};
+The "loadables" is not optional. It tells SPL which images to load into memory.
+Other things to consider +----------------------- +Falcon boot skips a lot of initialization in U-Boot. If Linux expects the +hardware to be initialized by U-Boot, the related code should be ported to SPL +build. For example, if Linux expect Ethernet PHY to be initialized in U-Boot +(which is not a common case), the PHY initialization has to be included in +falcon boot. This increases the SPL image size and should be handled carefully. +If Linux has PHY driver enabled, it still depends on the correct MDIO bus setup +in U-Boot. Normal U-Boot sets the MDC ratio to generate a proper clock signal. diff --git a/arch/arm/cpu/armv8/fsl-layerscape/spl.c b/arch/arm/cpu/armv8/fsl-layerscape/spl.c index 2776240..30b5432 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/spl.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/spl.c @@ -116,4 +116,33 @@ void board_init_f(ulong dummy) gd->arch.tlb_allocated = gd->arch.tlb_addr; #endif /* CONFIG_SPL_FSL_LS_PPA */ }
+#ifdef CONFIG_SPL_OS_BOOT +/*
- Return
- 0 if booting into OS is selected
- 1 if booting into U-Boot is selected
- */
+int spl_start_uboot(void) +{
- char s[8];
- env_init();
- env_get_f("boot_os", s, sizeof(s));
- if ((s != NULL) && (*s != '0' && *s != 'n' && *s != 'N' &&
*s != 'f' && *s != 'F'))
return 0;
- return 1;
+} +#endif /* CONFIG_SPL_OS_BOOT */ +#ifdef CONFIG_SPL_LOAD_FIT +int board_fit_config_name_match(const char *name) +{
- /* Just empty function now - can't decide what to choose */
- debug("%s: %s\n", __func__, name);
- return 0;
+} +#endif #endif /* CONFIG_SPL_BUILD */ diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 79bd19a..7d8dc44 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -215,7 +215,7 @@ void __asm_switch_ttbr(u64 new_ttbr);
- @entry_point: kernel entry point
- @es_flag: execution state flag, ES_TO_AARCH64 or ES_TO_AARCH32
*/ -void armv8_switch_to_el2(u64 args, u64 mach_nr, u64 fdt_addr, +void __noreturn armv8_switch_to_el2(u64 args, u64 mach_nr, u64 fdt_addr, u64 arg4, u64 entry_point, u64 es_flag); /*
- Switch from EL2 to EL1 for ARMv8
diff --git a/arch/arm/lib/spl.c b/arch/arm/lib/spl.c index 27d6682..ab5d227 100644 --- a/arch/arm/lib/spl.c +++ b/arch/arm/lib/spl.c @@ -7,6 +7,7 @@
- SPDX-License-Identifier: GPL-2.0+
*/
- #include <common.h> #include <config.h> #include <spl.h>
@@ -47,6 +48,15 @@ void __weak board_init_f(ulong dummy)
- image.
*/ #ifdef CONFIG_SPL_OS_BOOT +#ifdef CONFIG_ARM64 +void __noreturn jump_to_image_linux(struct spl_image_info *spl_image) +{
- debug("Entering kernel arg pointer: 0x%p\n", spl_image->arg);
- cleanup_before_linux();
- armv8_switch_to_el2((u64)spl_image->arg, 0, 0, 0,
spl_image->entry_point, ES_TO_AARCH64);
+} +#else void __noreturn jump_to_image_linux(struct spl_image_info *spl_image) { unsigned long machid = 0xffffffff; @@ -62,4 +72,5 @@ void __noreturn jump_to_image_linux(struct spl_image_info *spl_image) cleanup_before_linux(); image_entry(0, machid, spl_image->arg); } +#endif /* CONFIG_ARM64 */ #endif