[U-Boot] [PATCH v2 5/7] armv8: layerscape: Eanble falcon boot

Ɓukasz Majewski lukma at denx.de
Mon Sep 25 14:17:22 UTC 2017


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 at 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 at 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 at 1 {
> +			description = "Flattened Device Tree blob";
> +			data = /incbin/("./fsl-ls1043ardb-static.dtb");
> +			type = "flat_dt";
> +			arch = "arm64";
> +			compression = "none";
> +			load = <0x90000000>;
> +		};
> +		ramdisk at 1 {
> +			description = "LS1043 Ramdisk";
> +                        data = /incbin/("./rootfs.cpio.gz");
> +			type = "ramdisk";
> +			arch = "arm64";
> +			os = "linux";
> +			compression = "gzip";
> +			load = <0xa0000000>;
> +		};
> +	};
> +
> +	configurations {
> +		default = "config at 1";
> +		config at 1 {
> +			description = "Boot Linux kernel";
> +			kernel = "kernel at 1";
> +			fdt = "fdt at 1";
> +			ramdisk = "ramdisk at 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
> 


-- 
Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de


More information about the U-Boot mailing list