diff options
95 files changed, 2792 insertions, 215 deletions
diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 7985ff5523c..6f91553e861 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -299,6 +299,10 @@ stages: sandbox_noinst: TEST_PY_BD: "sandbox_noinst" TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl" + sandbox_noinst_load_fit_full: + TEST_PY_BD: "sandbox_noinst" + TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl" + OVERRIDE: "-a CONFIG_SPL_LOAD_FIT_FULL=y" sandbox_flattree: TEST_PY_BD: "sandbox_flattree" sandbox_trace: diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 129234ba3db..6decdfdee33 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -293,6 +293,13 @@ sandbox_noinst_test.py: TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl" <<: *buildman_and_testpy_dfn +sandbox_noinst with LOAD_FIT_FULL test.py: + variables: + TEST_PY_BD: "sandbox_noinst" + TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl" + OVERRIDE: "-a CONFIG_SPL_LOAD_FIT_FULL=y" + <<: *buildman_and_testpy_dfn + sandbox_vpl test.py: variables: TEST_PY_BD: "sandbox_vpl" diff --git a/MAINTAINERS b/MAINTAINERS index 16b17fdd96d..cde778bc4d3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -300,7 +300,9 @@ F: arch/arm/include/asm/arch-vf610/ F: arch/arm/include/asm/mach-imx/ F: board/freescale/*mx*/ F: board/freescale/common/ +F: common/spl/spl_imx_container.c F: drivers/serial/serial_mxc.c +F: include/imx_container.h ARM HISILICON M: Peter Griffin <peter.griffin@linaro.org> @@ -2165,7 +2165,7 @@ CLEAN_FILES += include/bmp_logo.h include/bmp_logo_data.h \ mkimage-out.spl.mkimage mkimage.spl.mkimage imx-boot.map \ itb.fit.fit itb.fit.itb itb.map spl.map mkimage-out.rom.mkimage \ mkimage.rom.mkimage rom.map simple-bin.map simple-bin-spi.map \ - idbloader-spi.img lib/efi_loader/helloworld_efi.S + idbloader-spi.img lib/efi_loader/helloworld_efi.S *.itb # Directories & files removed with 'make mrproper' MRPROPER_DIRS += include/config include/generated spl tpl vpl \ diff --git a/arch/arm/include/asm/mach-imx/ahab.h b/arch/arm/include/asm/mach-imx/ahab.h index 4222e3db278..4884f056251 100644 --- a/arch/arm/include/asm/mach-imx/ahab.h +++ b/arch/arm/include/asm/mach-imx/ahab.h @@ -6,7 +6,7 @@ #ifndef __IMX_AHAB_H__ #define __IMX_AHAB_H__ -#include <asm/mach-imx/image.h> +#include <imx_container.h> int ahab_auth_cntr_hdr(struct container_hdr *container, u16 length); int ahab_auth_release(void); diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 266bb20df9d..08ab7069187 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -194,19 +194,6 @@ config IMX_DCD_ADDR This information is shared with the user via mkimage -l just so the image can be signed. -config SPL_LOAD_IMX_CONTAINER - bool "Enable SPL loading U-Boot as a i.MX Container image" - depends on SPL - help - This is to let SPL could load i.MX Container image - -config IMX_CONTAINER_CFG - string "i.MX Container config file" - depends on SPL - help - This is to specific the cfg file for generating container - image which will be loaded by SPL. - config IOMUX_LPSR bool diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 6904cf38802..a3b44c93e3d 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -79,7 +79,7 @@ obj-$(CONFIG_CMD_NANDBCB) += cmd_nandbcb.o endif ifeq ($(CONFIG_SPL_BUILD),y) -obj-$(CONFIG_SPL_LOAD_IMX_CONTAINER) += image-container.o parse-container.o +obj-$(CONFIG_SPL_LOAD_IMX_CONTAINER) += image-container.o endif ifeq ($(SOC),$(filter $(SOC),imx8ulp imx9)) diff --git a/arch/arm/mach-imx/cmd_dek.c b/arch/arm/mach-imx/cmd_dek.c index 6fa5b41fcd3..2f389dbe8df 100644 --- a/arch/arm/mach-imx/cmd_dek.c +++ b/arch/arm/mach-imx/cmd_dek.c @@ -18,12 +18,12 @@ #include <mapmem.h> #include <tee.h> #ifdef CONFIG_IMX_SECO_DEK_ENCAP +#include <imx_container.h> #include <firmware/imx/sci/sci.h> -#include <asm/mach-imx/image.h> #endif #ifdef CONFIG_IMX_ELE_DEK_ENCAP +#include <imx_container.h> #include <asm/mach-imx/ele_api.h> -#include <asm/mach-imx/image.h> #endif #include <cpu_func.h> diff --git a/arch/arm/mach-imx/ele_ahab.c b/arch/arm/mach-imx/ele_ahab.c index 785b0d6ec3c..295c055ad0a 100644 --- a/arch/arm/mach-imx/ele_ahab.c +++ b/arch/arm/mach-imx/ele_ahab.c @@ -6,12 +6,12 @@ #include <common.h> #include <command.h> #include <errno.h> +#include <imx_container.h> #include <asm/io.h> #include <asm/mach-imx/ele_api.h> #include <asm/mach-imx/sys_proto.h> #include <asm/arch-imx/cpu.h> #include <asm/arch/sys_proto.h> -#include <asm/mach-imx/image.h> #include <console.h> #include <cpu_func.h> #include <asm/global_data.h> @@ -343,7 +343,7 @@ int authenticate_os_container(ulong addr) } phdr = (struct container_hdr *)addr; - if (phdr->tag != 0x87 || phdr->version != 0x0) { + if (!valid_container_hdr(phdr)) { printf("Error: Wrong container header\n"); return -EFAULT; } diff --git a/arch/arm/mach-imx/image-container.c b/arch/arm/mach-imx/image-container.c index 5f188ab32d1..ebc8021d7cc 100644 --- a/arch/arm/mach-imx/image-container.c +++ b/arch/arm/mach-imx/image-container.c @@ -5,6 +5,7 @@ #include <common.h> #include <errno.h> +#include <imx_container.h> #include <log.h> #include <malloc.h> #include <asm/io.h> @@ -12,7 +13,6 @@ #include <spi_flash.h> #include <spl.h> #include <nand.h> -#include <asm/mach-imx/image.h> #include <asm/arch/sys_proto.h> #include <asm/mach-imx/boot_mode.h> @@ -50,7 +50,7 @@ int get_container_size(ulong addr, u16 *header_length) u32 max_offset = 0, img_end; phdr = (struct container_hdr *)addr; - if (phdr->tag != 0x87 || phdr->version != 0x0) { + if (!valid_container_hdr(phdr)) { debug("Wrong container header\n"); return -EFAULT; } diff --git a/arch/arm/mach-imx/imx8/ahab.c b/arch/arm/mach-imx/imx8/ahab.c index b58b14ca9b4..994becccefd 100644 --- a/arch/arm/mach-imx/imx8/ahab.c +++ b/arch/arm/mach-imx/imx8/ahab.c @@ -6,6 +6,7 @@ #include <common.h> #include <command.h> #include <errno.h> +#include <imx_container.h> #include <log.h> #include <asm/global_data.h> #include <asm/io.h> @@ -13,7 +14,6 @@ #include <asm/mach-imx/sys_proto.h> #include <asm/arch-imx/cpu.h> #include <asm/arch/sys_proto.h> -#include <asm/mach-imx/image.h> #include <console.h> #include <cpu_func.h> #include "u-boot/sha256.h" @@ -146,7 +146,7 @@ int authenticate_os_container(ulong addr) } phdr = (struct container_hdr *)addr; - if (phdr->tag != 0x87 && phdr->version != 0x0) { + if (!valid_container_hdr(phdr)) { printf("Error: Wrong container header\n"); return -EFAULT; } diff --git a/arch/arm/mach-imx/spl_imx_romapi.c b/arch/arm/mach-imx/spl_imx_romapi.c index c4a4185eed1..93d48e56aca 100644 --- a/arch/arm/mach-imx/spl_imx_romapi.c +++ b/arch/arm/mach-imx/spl_imx_romapi.c @@ -6,11 +6,11 @@ #include <common.h> #include <errno.h> #include <image.h> +#include <imx_container.h> #include <log.h> #include <asm/global_data.h> #include <linux/libfdt.h> #include <spl.h> -#include <asm/mach-imx/image.h> #include <asm/arch/sys_proto.h> DECLARE_GLOBAL_DATA_PTR; @@ -111,7 +111,8 @@ static int spl_romapi_load_image_seekable(struct spl_image_info *spl_image, load.read = spl_romapi_read_seekable; load.priv = &pagesize; return spl_load_simple_fit(spl_image, &load, offset / pagesize, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load; memset(&load, 0, sizeof(load)); @@ -202,7 +203,8 @@ static u8 *search_container_header(u8 *p, int size) for (i = 0; i < size; i += 4) { hdr = p + i; - if (*(hdr + 3) == 0x87 && *hdr == 0 && (*(hdr + 1) != 0 || *(hdr + 2) != 0)) + if (valid_container_hdr((void *)hdr) && + (*(hdr + 1) != 0 || *(hdr + 2) != 0)) return p + i; } diff --git a/arch/arm/mach-rmobile/Kconfig b/arch/arm/mach-rmobile/Kconfig index 714eb4405bc..2bb96749fc0 100644 --- a/arch/arm/mach-rmobile/Kconfig +++ b/arch/arm/mach-rmobile/Kconfig @@ -77,6 +77,7 @@ config RZG2L imply PINCTRL_RZG2L imply RENESAS_SDHI imply RZG2L_GPIO + imply SCIF_CONSOLE imply SYS_MALLOC_F help Enable support for the Renesas RZ/G2L family of SoCs. Currently diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 183885ebe7d..e291456530b 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -187,6 +187,97 @@ config RISCV_ISA_D riscv32 ABI from ilp32 to ilp32d and the riscv64 ABI from lp64 to lp64d. +config RISCV_ISA_ZBB + bool "Zbb extension support for bit manipulation instructions" + help + Adds ZBB extension (basic bit manipulation) to the ISA subsets + that the toolchain is allowed to emit when building U-Boot. + The Zbb extension provides instructions to accelerate a number + of bit-specific operations (count bit population, sign extending, + bitrotation, etc) and enables optimized string routines. + +menu "Use assembly optimized implementation of string routines" + +config USE_ARCH_STRLEN + bool "Use an assembly optimized implementation of strlen" + default y + depends on RISCV_ISA_ZBB + help + Enable the generation of an optimized version of strlen using + Zbb extension. + +config SPL_USE_ARCH_STRLEN + bool "Use an assembly optimized implementation of strlen for SPL" + default y if USE_ARCH_STRLEN + depends on RISCV_ISA_ZBB + depends on SPL + help + Enable the generation of an optimized version of strlen using + Zbb extension. + +config TPL_USE_ARCH_STRLEN + bool "Use an assembly optimized implementation of strlen for TPL" + default y if USE_ARCH_STRLEN + depends on RISCV_ISA_ZBB + depends on TPL + help + Enable the generation of an optimized version of strlen using + Zbb extension. + +config USE_ARCH_STRCMP + bool "Use an assembly optimized implementation of strcmp" + default y + depends on RISCV_ISA_ZBB + help + Enable the generation of an optimized version of strcmp using + Zbb extension. + +config SPL_USE_ARCH_STRCMP + bool "Use an assembly optimized implementation of strcmp for SPL" + default y if USE_ARCH_STRCMP + depends on RISCV_ISA_ZBB + depends on SPL + help + Enable the generation of an optimized version of strcmp using + Zbb extension. + +config TPL_USE_ARCH_STRCMP + bool "Use an assembly optimized implementation of strcmp for TPL" + default y if USE_ARCH_STRCMP + depends on RISCV_ISA_ZBB + depends on TPL + help + Enable the generation of an optimized version of strcmp using + Zbb extension. + +config USE_ARCH_STRNCMP + bool "Use an assembly optimized implementation of strncmp" + default y + depends on RISCV_ISA_ZBB + help + Enable the generation of an optimized version of strncmp using + Zbb extension. + +config SPL_USE_ARCH_STRNCMP + bool "Use an assembly optimized implementation of strncmp for SPL" + default y if USE_ARCH_STRNCMP + depends on RISCV_ISA_ZBB + depends on SPL + help + Enable the generation of an optimized version of strncmp using + Zbb extension. + +config TPL_USE_ARCH_STRNCMP + bool "Use an assembly optimized implementation of strncmp for TPL" + default y if USE_ARCH_STRNCMP + depends on RISCV_ISA_ZBB + depends on TPL + help + Enable the generation of an optimized version of strncmp using + Zbb extension. + +endmenu + config RISCV_ISA_A def_bool y @@ -424,4 +515,12 @@ config TPL_USE_ARCH_MEMSET endmenu +config SPL_LOAD_FIT_OPENSBI_OS_BOOT + bool "Enable SPL (OpenSBI OS boot mode) applying linux from FIT" + depends on SPL_LOAD_FIT + help + Use fw_dynamic from the FIT image, and u-boot SPL will invoke it directly. + This is a shortcut boot flow, from u-boot SPL -> OpenSBI -> u-boot proper + -> linux to u-boot SPL -> OpenSBI -> linux. + endmenu diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index 4963b5109b2..b3ef87078b5 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -24,6 +24,9 @@ endif ifeq ($(CONFIG_RISCV_ISA_C),y) ARCH_C = c endif +ifeq ($(CONFIG_RISCV_ISA_ZBB),y) + ARCH_ZBB = _zbb +endif ifeq ($(CONFIG_CMODEL_MEDLOW),y) CMODEL = medlow endif @@ -32,7 +35,7 @@ ifeq ($(CONFIG_CMODEL_MEDANY),y) endif -RISCV_MARCH = $(ARCH_BASE)$(ARCH_A)$(ARCH_F)$(ARCH_D)$(ARCH_C) +RISCV_MARCH = $(ARCH_BASE)$(ARCH_A)$(ARCH_F)$(ARCH_D)$(ARCH_C)$(ARCH_ZBB) ABI = $(ABI_BASE)$(ABI_D) # Newer binutils versions default to ISA spec version 20191213 which moves some diff --git a/arch/riscv/cpu/generic/dram.c b/arch/riscv/cpu/generic/dram.c index 94d8018407e..1b51bae9b66 100644 --- a/arch/riscv/cpu/generic/dram.c +++ b/arch/riscv/cpu/generic/dram.c @@ -20,19 +20,3 @@ int dram_init_banksize(void) { return fdtdec_setup_memory_banksize(); } - -phys_addr_t board_get_usable_ram_top(phys_size_t total_size) -{ - /* - * Ensure that we run from first 4GB so that all - * addresses used by U-Boot are 32bit addresses. - * - * This in-turn ensures that 32bit DMA capable - * devices work fine because DMA mapping APIs will - * provide 32bit DMA addresses only. - */ - if (gd->ram_top >= SZ_4G) - return SZ_4G - 1; - - return gd->ram_top; -} diff --git a/arch/riscv/dts/binman.dtsi b/arch/riscv/dts/binman.dtsi index 156cb00971e..6b4eb8dc7b9 100644 --- a/arch/riscv/dts/binman.dtsi +++ b/arch/riscv/dts/binman.dtsi @@ -5,6 +5,9 @@ #include <config.h> +#define U64_TO_U32_H(addr) (((addr) >> 32) & 0xffffffff) +#define U64_TO_U32_L(addr) ((addr) & 0xffffffff) + / { binman: binman { multiple-images; @@ -13,26 +16,47 @@ &binman { itb { + +#ifndef CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT filename = "u-boot.itb"; +#else + filename = "linux.itb"; +#endif fit { description = "Configuration to load OpenSBI before U-Boot"; - #address-cells = <1>; + #address-cells = <2>; fit,fdt-list = "of-list"; images { +#ifndef CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT uboot { description = "U-Boot"; type = "standalone"; os = "U-Boot"; arch = "riscv"; compression = "none"; - load = <CONFIG_TEXT_BASE>; + load = <U64_TO_U32_H(CONFIG_TEXT_BASE) + U64_TO_U32_L(CONFIG_TEXT_BASE)>; uboot_blob: blob-ext { filename = "u-boot-nodtb.bin"; }; }; +#else + linux { + description = "Linux"; + type = "standalone"; + os = "Linux"; + arch = "riscv"; + compression = "none"; + load = <CONFIG_TEXT_BASE>; + + linux_blob: blob-ext { + filename = "Image"; + }; + }; +#endif opensbi { description = "OpenSBI fw_dynamic Firmware"; @@ -40,8 +64,10 @@ os = "opensbi"; arch = "riscv"; compression = "none"; - load = <CONFIG_SPL_OPENSBI_LOAD_ADDR>; - entry = <CONFIG_SPL_OPENSBI_LOAD_ADDR>; + load = <U64_TO_U32_H(CONFIG_SPL_OPENSBI_LOAD_ADDR) + U64_TO_U32_L(CONFIG_SPL_OPENSBI_LOAD_ADDR)>; + entry = <U64_TO_U32_H(CONFIG_SPL_OPENSBI_LOAD_ADDR) + U64_TO_U32_L(CONFIG_SPL_OPENSBI_LOAD_ADDR)>; opensbi_blob: opensbi { filename = "fw_dynamic.bin"; @@ -68,7 +94,11 @@ #endif description = "NAME"; firmware = "opensbi"; +#ifndef CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT loadables = "uboot"; +#else + loadables = "linux"; +#endif #ifndef CONFIG_OF_BOARD fdt = "fdt-SEQ"; #endif diff --git a/arch/riscv/include/asm/string.h b/arch/riscv/include/asm/string.h index 7dee3e4c9f6..38ad85fe3bb 100644 --- a/arch/riscv/include/asm/string.h +++ b/arch/riscv/include/asm/string.h @@ -40,4 +40,22 @@ extern void *memmove(void *, const void *, __kernel_size_t); #endif extern void *memset(void *, int, __kernel_size_t); +#undef __HAVE_ARCH_STRLEN +#if CONFIG_IS_ENABLED(USE_ARCH_STRLEN) +#define __HAVE_ARCH_STRLEN +#endif +extern __kernel_size_t strlen(const char *); + +#undef __HAVE_ARCH_STRCMP +#if CONFIG_IS_ENABLED(USE_ARCH_STRCMP) +#define __HAVE_ARCH_STRCMP +#endif +extern int strcmp(const char *, const char *); + +#undef __HAVE_ARCH_STRNCMP +#if CONFIG_IS_ENABLED(USE_ARCH_STRNCMP) +#define __HAVE_ARCH_STRNCMP +#endif +extern int strncmp(const char *, const char *, size_t __kernel_size_t); + #endif /* __ASM_RISCV_STRING_H */ diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile index 02c4d8fcc6c..9a05b662fd6 100644 --- a/arch/riscv/lib/Makefile +++ b/arch/riscv/lib/Makefile @@ -42,5 +42,8 @@ extra-$(CONFIG_EFI) += $(EFI_CRT0) $(EFI_RELOC) obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMSET) += memset.o obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMMOVE) += memmove.o obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_MEMCPY) += memcpy.o +obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_STRLEN) += strlen_zbb.o +obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_STRCMP) += strcmp_zbb.o +obj-$(CONFIG_$(SPL_TPL_)USE_ARCH_STRNCMP) += strncmp_zbb.o obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o diff --git a/arch/riscv/lib/andes_plicsw.c b/arch/riscv/lib/andes_plicsw.c index 75184080890..6fd49e873b1 100644 --- a/arch/riscv/lib/andes_plicsw.c +++ b/arch/riscv/lib/andes_plicsw.c @@ -22,7 +22,7 @@ #include <linux/err.h> /* pending register */ -#define PENDING_REG(base, hart) ((ulong)(base) + 0x1000 + ((hart) / 4) * 4) +#define PENDING_REG(base) ((ulong)(base) + 0x1000) /* enable register */ #define ENABLE_REG(base, hart) ((ulong)(base) + 0x2000 + (hart) * 0x80) /* claim register */ @@ -30,10 +30,11 @@ /* priority register */ #define PRIORITY_REG(base) ((ulong)(base) + PLICSW_PRIORITY_BASE) -#define ENABLE_HART_IPI (0x01010101) -#define SEND_IPI_TO_HART(hart) (0x1 << (hart)) +/* Bit 0 of PLIC-SW pending array is hardwired to zero, so we start from bit 1 */ +#define FIRST_AVAILABLE_BIT 0x2 +#define SEND_IPI_TO_HART(hart) (FIRST_AVAILABLE_BIT << (hart)) #define PLICSW_PRIORITY_BASE 0x4 -#define PLICSW_INTERRUPT_PER_HART 0x8 +#define PLICSW_INTERRUPT_PER_HART 0x1 DECLARE_GLOBAL_DATA_PTR; @@ -41,9 +42,8 @@ static int enable_ipi(int hart) { unsigned int en; - en = ENABLE_HART_IPI << hart; + en = FIRST_AVAILABLE_BIT << hart; writel(en, (void __iomem *)ENABLE_REG(gd->arch.plicsw, hart)); - writel(en, (void __iomem *)ENABLE_REG(gd->arch.plicsw + 0x4, hart)); return 0; } @@ -75,7 +75,7 @@ int riscv_init_ipi(void) ret = uclass_find_first_device(UCLASS_CPU, &dev); if (ret) return ret; - else if (!dev) + if (!dev) return -ENODEV; ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) { @@ -105,10 +105,9 @@ int riscv_init_ipi(void) int riscv_send_ipi(int hart) { - unsigned int ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart)); + unsigned int ipi = SEND_IPI_TO_HART(hart); - writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plicsw, - gd->arch.boot_hart)); + writel(ipi, (void __iomem *)PENDING_REG(gd->arch.plicsw)); return 0; } @@ -125,10 +124,9 @@ int riscv_clear_ipi(int hart) int riscv_get_ipi(int hart, int *pending) { - unsigned int ipi = (SEND_IPI_TO_HART(hart) << (8 * gd->arch.boot_hart)); + unsigned int ipi = SEND_IPI_TO_HART(hart); - *pending = readl((void __iomem *)PENDING_REG(gd->arch.plicsw, - gd->arch.boot_hart)); + *pending = readl((void __iomem *)PENDING_REG(gd->arch.plicsw)); *pending = !!(*pending & ipi); return 0; diff --git a/arch/riscv/lib/strcmp_zbb.S b/arch/riscv/lib/strcmp_zbb.S new file mode 100644 index 00000000000..e5a367c0e5c --- /dev/null +++ b/arch/riscv/lib/strcmp_zbb.S @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Taken from Linux arch/riscv/lib/strcmp.S + */ + +#include <linux/linkage.h> +#include <asm/asm.h> + +ENTRY(__strcmp) +WEAK(strcmp) +.option push +.option arch,+zbb + /* + * Returns + * a0 - comparison result, value like strcmp + * + * Parameters + * a0 - string1 + * a1 - string2 + * + * Clobbers + * t0, t1, t2, t3, t4 + */ + + or t2, a0, a1 + li t4, -1 + and t2, t2, SZREG-1 + bnez t2, 3f + + /* Main loop for aligned string. */ + .p2align 3 +1: + REG_L t0, 0(a0) + REG_L t1, 0(a1) + orc.b t3, t0 + bne t3, t4, 2f + addi a0, a0, SZREG + addi a1, a1, SZREG + beq t0, t1, 1b + + /* + * Words don't match, and no null byte in the first + * word. Get bytes in big-endian order and compare. + */ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + rev8 t0, t0 + rev8 t1, t1 +#endif + + /* Synthesize (t0 >= t1) ? 1 : -1 in a branchless sequence. */ + sltu a0, t0, t1 + neg a0, a0 + ori a0, a0, 1 + ret + +2: + /* + * Found a null byte. + * If words don't match, fall back to simple loop. + */ + bne t0, t1, 3f + + /* Otherwise, strings are equal. */ + li a0, 0 + ret + + /* Simple loop for misaligned strings. */ + .p2align 3 +3: + lbu t0, 0(a0) + lbu t1, 0(a1) + addi a0, a0, 1 + addi a1, a1, 1 + bne t0, t1, 4f + bnez t0, 3b + +4: + sub a0, t0, t1 + ret +.option pop +END(__strcmp) diff --git a/arch/riscv/lib/strlen_zbb.S b/arch/riscv/lib/strlen_zbb.S new file mode 100644 index 00000000000..bd8fa4c0bd0 --- /dev/null +++ b/arch/riscv/lib/strlen_zbb.S @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Taken from Linux arch/riscv/lib/strlen.S + */ + +#include <linux/linkage.h> +#include <asm/asm.h> + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define CZ ctz +# define SHIFT srl +#else +# define CZ clz +# define SHIFT sll +#endif + +ENTRY(__strlen) +WEAK(strlen) +.option push +.option arch,+zbb + /* + * Returns + * a0 - string length + * + * Parameters + * a0 - String to measure + * + * Clobbers + * t0, t1, t2, t3 + */ + + /* Number of irrelevant bytes in the first word. */ + andi t2, a0, SZREG-1 + + /* Align pointer. */ + andi t0, a0, -SZREG + + li t3, SZREG + sub t3, t3, t2 + slli t2, t2, 3 + + /* Get the first word. */ + REG_L t1, 0(t0) + + /* + * Shift away the partial data we loaded to remove the irrelevant bytes + * preceding the string with the effect of adding NUL bytes at the + * end of the string's first word. + */ + SHIFT t1, t1, t2 + + /* Convert non-NUL into 0xff and NUL into 0x00. */ + orc.b t1, t1 + + /* Convert non-NUL into 0x00 and NUL into 0xff. */ + not t1, t1 + + /* + * Search for the first set bit (corresponding to a NUL byte in the + * original chunk). + */ + CZ t1, t1 + + /* + * The first chunk is special: compare against the number + * of valid bytes in this chunk. + */ + srli a0, t1, 3 + bgtu t3, a0, 2f + + /* Prepare for the word comparison loop. */ + addi t2, t0, SZREG + li t3, -1 + + /* + * Our critical loop is 4 instructions and processes data in + * 4 byte or 8 byte chunks. + */ + .p2align 3 +1: + REG_L t1, SZREG(t0) + addi t0, t0, SZREG + orc.b t1, t1 + beq t1, t3, 1b + + not t1, t1 + CZ t1, t1 + srli t1, t1, 3 + + /* Get number of processed bytes. */ + sub t2, t0, t2 + + /* Add number of characters in the first word. */ + add a0, a0, t2 + + /* Add number of characters in the last word. */ + add a0, a0, t1 +2: + ret +.option pop +END(__strlen) diff --git a/arch/riscv/lib/strncmp_zbb.S b/arch/riscv/lib/strncmp_zbb.S new file mode 100644 index 00000000000..00e0fec3a66 --- /dev/null +++ b/arch/riscv/lib/strncmp_zbb.S @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Taken from Linux arch/riscv/lib/strncmp.S + */ + +#include <linux/linkage.h> +#include <asm/asm.h> + +ENTRY(__strncmp) +WEAK(strncmp) +.option push +.option arch,+zbb + /* + * Returns + * a0 - comparison result, like strncmp + * + * Parameters + * a0 - string1 + * a1 - string2 + * a2 - number of characters to compare + * + * Clobbers + * t0, t1, t2, t3, t4, t5, t6 + */ + + or t2, a0, a1 + li t5, -1 + and t2, t2, SZREG-1 + add t4, a0, a2 + bnez t2, 3f + + /* Adjust limit for fast-path. */ + andi t6, t4, -SZREG + + /* Main loop for aligned string. */ + .p2align 3 +1: + bge a0, t6, 3f + REG_L t0, 0(a0) + REG_L t1, 0(a1) + orc.b t3, t0 + bne t3, t5, 2f + orc.b t3, t1 + bne t3, t5, 2f + addi a0, a0, SZREG + addi a1, a1, SZREG + beq t0, t1, 1b + + /* + * Words don't match, and no null byte in the first + * word. Get bytes in big-endian order and compare. + */ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + rev8 t0, t0 + rev8 t1, t1 +#endif + + /* Synthesize (t0 >= t1) ? 1 : -1 in a branchless sequence. */ + sltu a0, t0, t1 + neg a0, a0 + ori a0, a0, 1 + ret + +2: + /* + * Found a null byte. + * If words don't match, fall back to simple loop. + */ + bne t0, t1, 3f + + /* Otherwise, strings are equal. */ + li a0, 0 + ret + + /* Simple loop for misaligned strings. */ + .p2align 3 +3: + bge a0, t4, 5f + lbu t0, 0(a0) + lbu t1, 0(a1) + addi a0, a0, 1 + addi a1, a1, 1 + bne t0, t1, 4f + bnez t0, 3b + +4: + sub a0, t0, t1 + ret + +5: + li a0, 0 + ret +.option pop +END(__strncmp) diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c index 7590f1b80a6..16b76627983 100644 --- a/arch/sandbox/cpu/spl.c +++ b/arch/sandbox/cpu/spl.c @@ -129,6 +129,10 @@ void spl_board_init(void) if (!CONFIG_IS_ENABLED(UNIT_TEST)) return; + /* These are necessary so TFTP can use LMBs to check its load address */ + gd->bd->bi_dram[0].start = gd->ram_base; + gd->bd->bi_dram[0].size = get_effective_memsize(); + if (state->run_unittests) { struct unit_test *tests = UNIT_TEST_ALL_START(); const int count = UNIT_TEST_ALL_COUNT(); diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 2c8a72590b5..2589c2eba73 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -13,6 +13,7 @@ #include <log.h> #include <os.h> #include <sort.h> +#include <spl.h> #include <asm/getopt.h> #include <asm/global_data.h> #include <asm/io.h> @@ -202,10 +203,14 @@ static int sandbox_cmdline_cb_test_fdt(struct sandbox_state *state, { char buf[256]; char *fname; + char *relname; int len; - len = state_get_rel_filename("arch/sandbox/dts/test.dtb", buf, - sizeof(buf)); + if (spl_phase() <= PHASE_SPL) + relname = "../arch/sandbox/dts/test.dtb"; + else + relname = "arch/sandbox/dts/test.dtb"; + len = state_get_rel_filename(relname, buf, sizeof(buf)); if (len < 0) return len; diff --git a/arch/sandbox/cpu/u-boot-spl.lds b/arch/sandbox/cpu/u-boot-spl.lds index ef885fd0cb0..a81d66a6f2e 100644 --- a/arch/sandbox/cpu/u-boot-spl.lds +++ b/arch/sandbox/cpu/u-boot-spl.lds @@ -26,6 +26,8 @@ SECTIONS KEEP(*(_u_boot_sandbox_getopt)) *(_u_boot_sandbox_getopt_end) } + + _image_binary_end = .; } INSERT AFTER .data; diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index e88c267620a..e4303473563 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -975,7 +975,7 @@ }; wdt-gpio-toggle { - gpios = <&gpio_a 7 0>; + gpios = <&gpio_a 8 0>; compatible = "linux,wdt-gpio"; hw_margin_ms = <100>; hw_algo = "toggle"; diff --git a/arch/sandbox/include/asm/spl.h b/arch/sandbox/include/asm/spl.h index 2f8b5fcfcfe..f349ea19971 100644 --- a/arch/sandbox/include/asm/spl.h +++ b/arch/sandbox/include/asm/spl.h @@ -12,6 +12,9 @@ enum { BOOT_DEVICE_MMC2_2, BOOT_DEVICE_BOARD, BOOT_DEVICE_VBE, + BOOT_DEVICE_CPGMAC, + BOOT_DEVICE_NOR, + BOOT_DEVICE_SPI, }; /** diff --git a/board/AndesTech/ae350/ae350.c b/board/AndesTech/ae350/ae350.c index 1c2288b6ce9..d78ee403e6c 100644 --- a/board/AndesTech/ae350/ae350.c +++ b/board/AndesTech/ae350/ae350.c @@ -19,6 +19,8 @@ #include <fdtdec.h> #include <dm.h> #include <spl.h> +#include <mapmem.h> +#include <hang.h> DECLARE_GLOBAL_DATA_PTR; @@ -26,6 +28,29 @@ DECLARE_GLOBAL_DATA_PTR; * Miscellaneous platform dependent initializations */ +#if CONFIG_IS_ENABLED(LOAD_FIT) || CONFIG_IS_ENABLED(LOAD_FIT_FULL) +#define ANDES_SPL_FDT_ADDR (CONFIG_TEXT_BASE - 0x100000) +void spl_perform_fixups(struct spl_image_info *spl_image) +{ + /* + * Originally, u-boot-spl will place DTB directly after the kernel, + * but the size of the kernel did not include the BSS section, which + * means u-boot-spl will place the DTB in the kernel BSS section + * causing the DTB to be cleared by kernel BSS initializtion. + * Moving DTB in front of the kernel can avoid the error. + */ + if (ANDES_SPL_FDT_ADDR < 0) { + printf("%s: CONFIG_TEXT_BASE needs to be larger than 0x100000\n", + __func__); + hang(); + } + + memcpy((void *)ANDES_SPL_FDT_ADDR, spl_image->fdt_addr, + fdt_totalsize(spl_image->fdt_addr)); + spl_image->fdt_addr = map_sysmem(ANDES_SPL_FDT_ADDR, 0); +} +#endif + int board_init(void) { gd->bd->bi_boot_params = PHYS_SDRAM_0 + 0x400; diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 46323597942..6bc4066fad7 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -330,6 +330,20 @@ config SPL_LEGACY_IMAGE_CRC_CHECK If disabled, Legacy images are booted if the image magic and size are correct, without further integrity checks. +config SPL_LOAD_IMX_CONTAINER + bool "Enable SPL loading and booting of i.MX8 Containers" + depends on SPL + help + Support booting U-Boot from an i.MX8 container image. If you are not + using i.MX8, say 'n'. + +config IMX_CONTAINER_CFG + string "i.MX8 Container config file" + depends on SPL && SPL_LOAD_IMX_CONTAINER + help + Specify the cfg file for generating the container image which will be + loaded by SPL. + config SPL_SYS_MALLOC_SIMPLE bool "Only use malloc_simple functions in the SPL" help @@ -643,6 +657,7 @@ config SPL_ETH config SPL_FS_EXT4 bool "Support EXT filesystems" + select SPL_CRC16 if EXT4_WRITE help Enable support for EXT2/3/4 filesystems with SPL. This permits U-Boot (or Linux in Falcon mode) to be loaded from an EXT diff --git a/common/spl/Makefile b/common/spl/Makefile index bad2bbf6cf1..4f8eb2ec0ca 100644 --- a/common/spl/Makefile +++ b/common/spl/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_$(SPL_TPL_)OPENSBI) += spl_opensbi.o obj-$(CONFIG_$(SPL_TPL_)USB_STORAGE) += spl_usb.o obj-$(CONFIG_$(SPL_TPL_)FS_FAT) += spl_fat.o obj-$(CONFIG_$(SPL_TPL_)FS_EXT4) += spl_ext.o +obj-$(CONFIG_$(SPL_TPL_)LOAD_IMX_CONTAINER) += spl_imx_container.o obj-$(CONFIG_$(SPL_TPL_)SATA) += spl_sata.o obj-$(CONFIG_$(SPL_TPL_)NVME) += spl_nvme.o obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += spl_semihosting.o diff --git a/common/spl/spl.c b/common/spl/spl.c index 66eeea41a34..732d90d39e6 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -653,7 +653,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2) spl_set_bd(); if (IS_ENABLED(CONFIG_SPL_SYS_MALLOC)) { - mem_malloc_init(SPL_SYS_MALLOC_START, SPL_SYS_MALLOC_SIZE); + mem_malloc_init((ulong)map_sysmem(SPL_SYS_MALLOC_START, + SPL_SYS_MALLOC_SIZE), + SPL_SYS_MALLOC_SIZE); gd->flags |= GD_FLG_FULL_MALLOC_INIT; } if (!(gd->flags & GD_FLG_SPL_INIT)) { diff --git a/common/spl/spl_blk_fs.c b/common/spl/spl_blk_fs.c index ea5d1a51d9f..63825d620d1 100644 --- a/common/spl/spl_blk_fs.c +++ b/common/spl/spl_blk_fs.c @@ -9,6 +9,7 @@ #include <spl.h> #include <image.h> #include <fs.h> +#include <asm/io.h> struct blk_dev { const char *ifname; @@ -29,7 +30,8 @@ static ulong spl_fit_read(struct spl_load_info *load, ulong file_offset, return ret; } - ret = fs_read(load->filename, (ulong)buf, file_offset, size, &actlen); + ret = fs_read(load->filename, virt_to_phys(buf), file_offset, size, + &actlen); if (ret < 0) { printf("spl: error reading image %s. Err - %d\n", load->filename, ret); @@ -69,7 +71,7 @@ int spl_blk_load_image(struct spl_image_info *spl_image, goto out; } - ret = fs_read(filename, (ulong)header, 0, + ret = fs_read(filename, virt_to_phys(header), 0, sizeof(struct legacy_img_hdr), &actlen); if (ret) { printf("spl: unable to read file %s. Err - %d\n", filename, diff --git a/common/spl/spl_ext.c b/common/spl/spl_ext.c index 902564a6077..af836ca15b8 100644 --- a/common/spl/spl_ext.c +++ b/common/spl/spl_ext.c @@ -2,6 +2,7 @@ #include <common.h> #include <env.h> +#include <mapmem.h> #include <part.h> #include <spl.h> #include <asm/u-boot.h> @@ -53,7 +54,8 @@ int spl_load_image_ext(struct spl_image_info *spl_image, goto end; } - err = ext4fs_read((char *)spl_image->load_addr, 0, filelen, &actlen); + err = ext4fs_read(map_sysmem(spl_image->load_addr, filelen), 0, filelen, + &actlen); end: #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT diff --git a/common/spl/spl_fat.c b/common/spl/spl_fat.c index c6e2526ade1..014074f85be 100644 --- a/common/spl/spl_fat.c +++ b/common/spl/spl_fat.c @@ -11,6 +11,7 @@ #include <common.h> #include <env.h> #include <log.h> +#include <mapmem.h> #include <spl.h> #include <asm/u-boot.h> #include <fat.h> @@ -20,6 +21,11 @@ static int fat_registered; +void spl_fat_force_reregister(void) +{ + fat_registered = 0; +} + static int spl_register_fat_device(struct blk_desc *block_dev, int partition) { int err = 0; @@ -74,11 +80,13 @@ int spl_load_image_fat(struct spl_image_info *spl_image, if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) && image_get_magic(header) == FDT_MAGIC) { - err = file_fat_read(filename, (void *)CONFIG_SYS_LOAD_ADDR, 0); + err = file_fat_read(filename, + map_sysmem(CONFIG_SYS_LOAD_ADDR, 0), 0); if (err <= 0) goto end; err = spl_parse_image_header(spl_image, bootdev, - (struct legacy_img_hdr *)CONFIG_SYS_LOAD_ADDR); + map_sysmem(CONFIG_SYS_LOAD_ADDR, + err)); if (err == -EAGAIN) return err; if (err == 0) @@ -99,8 +107,8 @@ int spl_load_image_fat(struct spl_image_info *spl_image, if (err) goto end; - err = file_fat_read(filename, - (u8 *)(uintptr_t)spl_image->load_addr, 0); + err = file_fat_read(filename, map_sysmem(spl_image->load_addr, + spl_image->size), 0); } end: diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 1409b926372..70d8d5942d9 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -16,6 +16,7 @@ #include <sysinfo.h> #include <asm/cache.h> #include <asm/global_data.h> +#include <asm/io.h> #include <linux/libfdt.h> #include <linux/printk.h> @@ -366,7 +367,8 @@ static bool os_takes_devicetree(uint8_t os) case IH_OS_U_BOOT: return true; case IH_OS_LINUX: - return IS_ENABLED(CONFIG_SPL_OS_BOOT); + return IS_ENABLED(CONFIG_SPL_OS_BOOT) || + IS_ENABLED(CONFIG_SPL_OPENSBI); default: return false; } @@ -393,25 +395,32 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, /* Figure out which device tree the board wants to use */ node = spl_fit_get_image_node(ctx, FIT_FDT_PROP, index++); if (node < 0) { + size_t size; + debug("%s: cannot find FDT node\n", __func__); /* * U-Boot did not find a device tree inside the FIT image. Use * the U-Boot device tree instead. */ - if (gd->fdt_blob) - memcpy((void *)image_info.load_addr, gd->fdt_blob, - fdt_totalsize(gd->fdt_blob)); - else + if (!gd->fdt_blob) return node; + + /* + * Make the load-address of the FDT available for the SPL + * framework + */ + size = fdt_totalsize(gd->fdt_blob); + spl_image->fdt_addr = map_sysmem(image_info.load_addr, size); + memcpy(spl_image->fdt_addr, gd->fdt_blob, size); } else { ret = load_simple_fit(info, sector, ctx, node, &image_info); if (ret < 0) return ret; + + spl_image->fdt_addr = phys_to_virt(image_info.load_addr); } - /* Make the load-address of the FDT available for the SPL framework */ - spl_image->fdt_addr = map_sysmem(image_info.load_addr, 0); if (CONFIG_IS_ENABLED(FIT_IMAGE_TINY)) return 0; @@ -876,7 +885,7 @@ int spl_load_fit_image(struct spl_image_info *spl_image, #ifdef CONFIG_SPL_FIT_SIGNATURE images.verify = 1; #endif - ret = fit_image_load(&images, (ulong)header, + ret = fit_image_load(&images, virt_to_phys((void *)header), NULL, &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_STANDALONE, -1, FIT_LOAD_OPTIONAL, &fw_data, &fw_len); @@ -884,15 +893,15 @@ int spl_load_fit_image(struct spl_image_info *spl_image, printf("DEPRECATED: 'standalone = ' property."); printf("Please use either 'firmware =' or 'kernel ='\n"); } else { - ret = fit_image_load(&images, (ulong)header, NULL, - &fit_uname_config, IH_ARCH_DEFAULT, + ret = fit_image_load(&images, virt_to_phys((void *)header), + NULL, &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_FIRMWARE, -1, FIT_LOAD_OPTIONAL, &fw_data, &fw_len); } if (ret < 0) { - ret = fit_image_load(&images, (ulong)header, NULL, - &fit_uname_config, IH_ARCH_DEFAULT, + ret = fit_image_load(&images, virt_to_phys((void *)header), + NULL, &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_KERNEL, -1, FIT_LOAD_OPTIONAL, &fw_data, &fw_len); } @@ -901,8 +910,9 @@ int spl_load_fit_image(struct spl_image_info *spl_image, return ret; spl_image->size = fw_len; - spl_image->entry_point = fw_data; spl_image->load_addr = fw_data; + if (fit_image_get_entry(header, ret, &spl_image->entry_point)) + spl_image->entry_point = fw_data; if (fit_image_get_os(header, ret, &spl_image->os)) spl_image->os = IH_OS_INVALID; spl_image->name = genimg_get_os_name(spl_image->os); @@ -913,9 +923,9 @@ int spl_load_fit_image(struct spl_image_info *spl_image, #ifdef CONFIG_SPL_FIT_SIGNATURE images.verify = 1; #endif - ret = fit_image_load(&images, (ulong)header, NULL, &fit_uname_config, - IH_ARCH_DEFAULT, IH_TYPE_FLATDT, -1, - FIT_LOAD_OPTIONAL, &dt_data, &dt_len); + ret = fit_image_load(&images, virt_to_phys((void *)header), NULL, + &fit_uname_config, IH_ARCH_DEFAULT, IH_TYPE_FLATDT, + -1, FIT_LOAD_OPTIONAL, &dt_data, &dt_len); if (ret >= 0) { spl_image->fdt_addr = (void *)dt_data; diff --git a/arch/arm/mach-imx/parse-container.c b/common/spl/spl_imx_container.c index e2a9e2b2732..127802f5cb7 100644 --- a/arch/arm/mach-imx/parse-container.c +++ b/common/spl/spl_imx_container.c @@ -3,12 +3,14 @@ * Copyright 2018-2021 NXP */ +#define LOG_CATEGORY LOGC_ARCH #include <common.h> #include <stdlib.h> #include <errno.h> +#include <imx_container.h> #include <log.h> +#include <mapmem.h> #include <spl.h> -#include <asm/mach-imx/image.h> #ifdef CONFIG_AHAB_BOOT #include <asm/mach-imx/ahab.h> #endif @@ -45,7 +47,8 @@ static struct boot_img_t *read_auth_image(struct spl_image_info *spl_image, debug("%s: container: %p sector: %lu sectors: %u\n", __func__, container, sector, sectors); if (info->read(info, sector, sectors, - (void *)images[image_index].entry) != sectors) { + map_sysmem(images[image_index].dst, + images[image_index].size)) != sectors) { printf("%s wrong\n", __func__); return NULL; } @@ -84,14 +87,14 @@ static int read_auth_container(struct spl_image_info *spl_image, goto end; } - if (container->tag != 0x87 && container->version != 0x0) { - printf("Wrong container header"); + if (!valid_container_hdr(container)) { + log_err("Wrong container header\n"); ret = -ENOENT; goto end; } if (!container->num_images) { - printf("Wrong container, no image found"); + log_err("Wrong container, no image found\n"); ret = -ENOENT; goto end; } diff --git a/common/spl/spl_legacy.c b/common/spl/spl_legacy.c index 095443c63d8..51656fb9617 100644 --- a/common/spl/spl_legacy.c +++ b/common/spl/spl_legacy.c @@ -7,6 +7,7 @@ #include <image.h> #include <log.h> #include <malloc.h> +#include <mapmem.h> #include <asm/sections.h> #include <spl.h> @@ -19,7 +20,7 @@ static void spl_parse_legacy_validate(uintptr_t start, uintptr_t size) { uintptr_t spl_start = (uintptr_t)_start; - uintptr_t spl_end = (uintptr_t)_image_binary_end; + uintptr_t spl_end = (uintptr_t)&_image_binary_end; uintptr_t end = start + size; if ((start >= spl_start && start < spl_end) || @@ -129,7 +130,7 @@ int spl_load_legacy_img(struct spl_image_info *spl_image, dataptr += sizeof(*hdr); load->read(load, dataptr, spl_image->size, - (void *)(unsigned long)spl_image->load_addr); + map_sysmem(spl_image->load_addr, spl_image->size)); break; case IH_COMP_LZMA: @@ -148,7 +149,8 @@ int spl_load_legacy_img(struct spl_image_info *spl_image, } load->read(load, dataptr, spl_image->size, src); - ret = lzmaBuffToBuffDecompress((void *)spl_image->load_addr, + ret = lzmaBuffToBuffDecompress(map_sysmem(spl_image->load_addr, + spl_image->size), &lzma_len, src, spl_image->size); if (ret) { printf("LZMA decompression error: %d\n", ret); diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c index 0ab85d2168c..0b01368d9de 100644 --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@ -8,6 +8,7 @@ #include <common.h> #include <dm.h> #include <log.h> +#include <mapmem.h> #include <part.h> #include <spl.h> #include <linux/compiler.h> @@ -16,6 +17,7 @@ #include <errno.h> #include <mmc.h> #include <image.h> +#include <imx_container.h> static int mmc_load_legacy(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, @@ -45,7 +47,8 @@ static int mmc_load_legacy(struct spl_image_info *spl_image, count = blk_dread(mmc_get_blk_desc(mmc), sector + image_offset_sectors, image_size_sectors, - (void *)(ulong)spl_image->load_addr); + map_sysmem(spl_image->load_addr, + image_size_sectors * mmc->read_bl_len)); debug("read %x sectors to %lx\n", image_size_sectors, spl_image->load_addr); if (count != image_size_sectors) @@ -108,7 +111,8 @@ int mmc_load_image_raw_sector(struct spl_image_info *spl_image, load.bl_len = mmc->read_bl_len; load.read = h_spl_load_read; ret = spl_load_simple_fit(spl_image, &load, sector, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load; load.dev = mmc; @@ -396,18 +400,24 @@ static int spl_mmc_get_mmc_devnum(struct mmc *mmc) #if !CONFIG_IS_ENABLED(BLK) block_dev = &mmc->block_dev; #else - block_dev = dev_get_uclass_plat(mmc->dev); + block_dev = mmc_get_blk_desc(mmc); #endif return block_dev->devnum; } +static struct mmc *mmc; + +void spl_mmc_clear_cache(void) +{ + mmc = NULL; +} + int spl_mmc_load(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, const char *filename, int raw_part, unsigned long raw_sect) { - static struct mmc *mmc; u32 boot_mode; int err = 0; __maybe_unused int part = 0; diff --git a/common/spl/spl_nand.c b/common/spl/spl_nand.c index 6cc34004f49..07916bedbb9 100644 --- a/common/spl/spl_nand.c +++ b/common/spl/spl_nand.c @@ -7,6 +7,7 @@ #include <config.h> #include <fdt_support.h> #include <image.h> +#include <imx_container.h> #include <log.h> #include <spl.h> #include <asm/io.h> @@ -99,7 +100,8 @@ static int spl_nand_load_element(struct spl_image_info *spl_image, load.bl_len = bl_len; load.read = spl_nand_fit_read; return spl_load_simple_fit(spl_image, &load, offset / bl_len, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load; load.dev = NULL; diff --git a/common/spl/spl_net.c b/common/spl/spl_net.c index b2c901b554b..f01d4df8bc6 100644 --- a/common/spl/spl_net.c +++ b/common/spl/spl_net.c @@ -11,6 +11,7 @@ #include <errno.h> #include <image.h> #include <log.h> +#include <mapmem.h> #include <spl.h> #include <net.h> #include <linux/libfdt.h> @@ -21,14 +22,15 @@ static ulong spl_net_load_read(struct spl_load_info *load, ulong sector, { debug("%s: sector %lx, count %lx, buf %lx\n", __func__, sector, count, (ulong)buf); - memcpy(buf, (void *)(image_load_addr + sector), count); + memcpy(buf, map_sysmem(image_load_addr + sector, count), count); return count; } static int spl_net_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { - struct legacy_img_hdr *header = (struct legacy_img_hdr *)image_load_addr; + struct legacy_img_hdr *header = map_sysmem(image_load_addr, + sizeof(*header)); int rv; env_init(); @@ -62,7 +64,9 @@ static int spl_net_load_image(struct spl_image_info *spl_image, if (rv) return rv; - memcpy((void *)spl_image->load_addr, header, spl_image->size); + memcpy(map_sysmem(spl_image->load_addr, spl_image->size), + map_sysmem(image_load_addr, spl_image->size), + spl_image->size); } return rv; diff --git a/common/spl/spl_nor.c b/common/spl/spl_nor.c index 79d4f1d7aa8..236b0718283 100644 --- a/common/spl/spl_nor.c +++ b/common/spl/spl_nor.c @@ -5,7 +5,9 @@ #include <common.h> #include <image.h> +#include <imx_container.h> #include <log.h> +#include <mapmem.h> #include <spl.h> static ulong spl_nor_load_read(struct spl_load_info *load, ulong sector, @@ -13,7 +15,7 @@ static ulong spl_nor_load_read(struct spl_load_info *load, ulong sector, { debug("%s: sector %lx, count %lx, buf %p\n", __func__, sector, count, buf); - memcpy(buf, (void *)sector, count); + memcpy(buf, map_sysmem(sector, count), count); return count; } @@ -26,7 +28,7 @@ unsigned long __weak spl_nor_get_uboot_base(void) static int spl_nor_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { - __maybe_unused const struct legacy_img_hdr *header; + struct legacy_img_hdr *header; __maybe_unused struct spl_load_info load; /* @@ -41,7 +43,7 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, * Load Linux from its location in NOR flash to its defined * location in SDRAM */ - header = (const struct legacy_img_hdr *)CONFIG_SYS_OS_BASE; + header = (void *)CONFIG_SYS_OS_BASE; #ifdef CONFIG_SPL_LOAD_FIT if (image_get_magic(header) == FDT_MAGIC) { int ret; @@ -91,8 +93,8 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, * Load real U-Boot from its location in NOR flash to its * defined location in SDRAM */ + header = map_sysmem(spl_nor_get_uboot_base(), sizeof(*header)); #ifdef CONFIG_SPL_LOAD_FIT - header = (const struct legacy_img_hdr *)spl_nor_get_uboot_base(); if (image_get_magic(header) == FDT_MAGIC) { debug("Found FIT format U-Boot\n"); load.bl_len = 1; @@ -102,7 +104,8 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, (void *)header); } #endif - if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { load.bl_len = 1; load.read = spl_nor_load_read; return spl_load_imx_container(spl_image, &load, @@ -111,14 +114,11 @@ static int spl_nor_load_image(struct spl_image_info *spl_image, /* Legacy image handling */ if (IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT)) { - struct legacy_img_hdr hdr; - load.bl_len = 1; load.read = spl_nor_load_read; - spl_nor_load_read(&load, spl_nor_get_uboot_base(), sizeof(hdr), &hdr); return spl_load_legacy_img(spl_image, bootdev, &load, spl_nor_get_uboot_base(), - &hdr); + header); } return -EINVAL; diff --git a/common/spl/spl_opensbi.c b/common/spl/spl_opensbi.c index 0df611623ae..9801d38c0b3 100644 --- a/common/spl/spl_opensbi.c +++ b/common/spl/spl_opensbi.c @@ -21,7 +21,7 @@ DECLARE_GLOBAL_DATA_PTR; struct fw_dynamic_info opensbi_info; -static int spl_opensbi_find_uboot_node(void *blob, int *uboot_node) +static int spl_opensbi_find_os_node(void *blob, int *uboot_node, int os_type) { int fit_images_node, node; const char *fit_os; @@ -35,7 +35,7 @@ static int spl_opensbi_find_uboot_node(void *blob, int *uboot_node) if (!fit_os) continue; - if (genimg_get_os_id(fit_os) == IH_OS_U_BOOT) { + if (genimg_get_os_id(fit_os) == os_type) { *uboot_node = node; return 0; } @@ -46,8 +46,9 @@ static int spl_opensbi_find_uboot_node(void *blob, int *uboot_node) void __noreturn spl_invoke_opensbi(struct spl_image_info *spl_image) { - int ret, uboot_node; - ulong uboot_entry; + int ret, os_node; + ulong os_entry; + int os_type; typedef void __noreturn (*opensbi_entry_t)(ulong hartid, ulong dtb, ulong info); opensbi_entry_t opensbi_entry; @@ -56,22 +57,32 @@ void __noreturn spl_invoke_opensbi(struct spl_image_info *spl_image) hang(); } - /* Find U-Boot image in /fit-images */ - ret = spl_opensbi_find_uboot_node(spl_image->fdt_addr, &uboot_node); + /* + * Find next os image in /fit-images + * The next os image default is u-boot proper, once enable + * OpenSBI OS boot mode, the OS image should be linux. + */ + if (CONFIG_IS_ENABLED(LOAD_FIT_OPENSBI_OS_BOOT)) + os_type = IH_OS_LINUX; + else + os_type = IH_OS_U_BOOT; + + ret = spl_opensbi_find_os_node(spl_image->fdt_addr, &os_node, os_type); if (ret) { - pr_err("Can't find U-Boot node, %d\n", ret); + pr_err("Can't find %s node for opensbi, %d\n", + genimg_get_os_name(os_type), ret); hang(); } /* Get U-Boot entry point */ - ret = fit_image_get_entry(spl_image->fdt_addr, uboot_node, &uboot_entry); + ret = fit_image_get_entry(spl_image->fdt_addr, os_node, &os_entry); if (ret) - ret = fit_image_get_load(spl_image->fdt_addr, uboot_node, &uboot_entry); + ret = fit_image_get_load(spl_image->fdt_addr, os_node, &os_entry); /* Prepare opensbi_info object */ opensbi_info.magic = FW_DYNAMIC_INFO_MAGIC_VALUE; opensbi_info.version = FW_DYNAMIC_INFO_VERSION; - opensbi_info.next_addr = uboot_entry; + opensbi_info.next_addr = os_entry; opensbi_info.next_mode = FW_DYNAMIC_INFO_NEXT_MODE_S; opensbi_info.options = CONFIG_SPL_OPENSBI_SCRATCH_OPTIONS; opensbi_info.boot_hart = gd->arch.boot_hart; diff --git a/common/spl/spl_spi.c b/common/spl/spl_spi.c index d69069a75bf..3ac4b1b5091 100644 --- a/common/spl/spl_spi.c +++ b/common/spl/spl_spi.c @@ -10,12 +10,15 @@ #include <common.h> #include <image.h> +#include <imx_container.h> #include <log.h> +#include <mapmem.h> #include <spi.h> #include <spi_flash.h> #include <errno.h> #include <spl.h> #include <asm/global_data.h> +#include <asm/io.h> #include <dm/ofnode.h> #if CONFIG_IS_ENABLED(OS_BOOT) @@ -133,13 +136,16 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, if (IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) && image_get_magic(header) == FDT_MAGIC) { + u32 size = roundup(fdt_totalsize(header), 4); + err = spi_flash_read(flash, payload_offs, - roundup(fdt_totalsize(header), 4), - (void *)CONFIG_SYS_LOAD_ADDR); + size, + map_sysmem(CONFIG_SYS_LOAD_ADDR, + size)); if (err) return err; err = spl_parse_image_header(spl_image, bootdev, - (struct legacy_img_hdr *)CONFIG_SYS_LOAD_ADDR); + phys_to_virt(CONFIG_SYS_LOAD_ADDR)); } else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && image_get_magic(header) == FDT_MAGIC) { struct spl_load_info load; @@ -153,7 +159,8 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, err = spl_load_simple_fit(spl_image, &load, payload_offs, header); - } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + } else if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load; load.dev = flash; @@ -170,7 +177,8 @@ static int spl_spi_load_image(struct spl_image_info *spl_image, return err; err = spi_flash_read(flash, payload_offs + spl_image->offset, spl_image->size, - (void *)spl_image->load_addr); + map_sysmem(spl_image->load_addr, + spl_image->size)); } if (IS_ENABLED(CONFIG_SPI_FLASH_SOFT_RESET)) { err = spi_nor_remove(flash); diff --git a/configs/ae350_rv32_falcon_defconfig b/configs/ae350_rv32_falcon_defconfig new file mode 100644 index 00000000000..8f796d88e36 --- /dev/null +++ b/configs/ae350_rv32_falcon_defconfig @@ -0,0 +1,60 @@ +CONFIG_RISCV=y +CONFIG_TEXT_BASE=0x01800000 +CONFIG_SYS_MALLOC_LEN=0x80000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x10000000 +CONFIG_ENV_SECT_SIZE=0x1000 +CONFIG_DEFAULT_DEVICE_TREE="ae350_32" +CONFIG_SYS_PROMPT="RISC-V # " +CONFIG_SYS_MONITOR_LEN=786432 +CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000000 +CONFIG_SPL=y +CONFIG_SYS_LOAD_ADDR=0x100000 +CONFIG_TARGET_ANDES_AE350=y +CONFIG_RISCV_SMODE=y +# CONFIG_AVAILABLE_HARTS is not set +CONFIG_FIT=y +CONFIG_SPL_LOAD_FIT_ADDRESS=0x10000000 +CONFIG_SYS_MONITOR_BASE=0x88000000 +CONFIG_DISTRO_DEFAULTS=y +CONFIG_BOOTDELAY=3 +CONFIG_DISPLAY_CPUINFO=y +CONFIG_DISPLAY_BOARDINFO=y +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_SPL_MAX_SIZE=0x100000 +CONFIG_SPL_BSS_START_ADDR=0x400000 +CONFIG_SPL_BOARD_INIT=y +CONFIG_SPL_CACHE=y +CONFIG_SPL_OPENSBI_SCRATCH_OPTIONS=0x0 +CONFIG_SYS_PBSIZE=1050 +CONFIG_SYS_BOOTM_LEN=0x4000000 +CONFIG_CMD_IMLS=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF_TEST=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_BOOTP_PREFER_SERVERIP=y +CONFIG_CMD_CACHE=y +CONFIG_ENV_OVERWRITE=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_NET_RETRY_COUNT=50 +CONFIG_BOOTP_SEND_HOSTNAME=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_MMC=y +CONFIG_FTSDC010=y +CONFIG_FTSDC010_SDIO=y +CONFIG_MTD_NOR_FLASH=y +CONFIG_FLASH_CFI_DRIVER=y +CONFIG_SYS_FLASH_CFI_WIDTH_16BIT=y +CONFIG_FLASH_SHOW_PROGRESS=0 +CONFIG_SYS_CFI_FLASH_STATUS_POLL=y +CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y +CONFIG_SYS_FLASH_CFI=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_FTMAC100=y +CONFIG_BAUDRATE=38400 +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_ATCSPI200_SPI=y +# CONFIG_BINMAN_FDT is not set +CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT=y
\ No newline at end of file diff --git a/configs/ae350_rv32_falcon_xip_defconfig b/configs/ae350_rv32_falcon_xip_defconfig new file mode 100644 index 00000000000..e01dd6fc513 --- /dev/null +++ b/configs/ae350_rv32_falcon_xip_defconfig @@ -0,0 +1,61 @@ +CONFIG_RISCV=y +CONFIG_TEXT_BASE=0x01800000 +CONFIG_SYS_MALLOC_LEN=0x80000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x10000000 +CONFIG_ENV_SECT_SIZE=0x1000 +CONFIG_DEFAULT_DEVICE_TREE="ae350_32" +CONFIG_SPL_TEXT_BASE=0x80000000 +CONFIG_SYS_PROMPT="RISC-V # " +CONFIG_SYS_MONITOR_LEN=786432 +CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000000 +CONFIG_SPL=y +CONFIG_SYS_LOAD_ADDR=0x100000 +CONFIG_TARGET_ANDES_AE350=y +CONFIG_RISCV_SMODE=y +CONFIG_SPL_XIP=y +CONFIG_FIT=y +CONFIG_SPL_LOAD_FIT_ADDRESS=0x80010000 +CONFIG_SYS_MONITOR_BASE=0x88000000 +CONFIG_DISTRO_DEFAULTS=y +CONFIG_BOOTDELAY=3 +CONFIG_DISPLAY_CPUINFO=y +CONFIG_DISPLAY_BOARDINFO=y +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_SPL_MAX_SIZE=0x100000 +CONFIG_SPL_BSS_START_ADDR=0x400000 +CONFIG_SPL_BOARD_INIT=y +CONFIG_SPL_CACHE=y +CONFIG_SPL_OPENSBI_SCRATCH_OPTIONS=0x0 +CONFIG_SYS_PBSIZE=1050 +CONFIG_SYS_BOOTM_LEN=0x4000000 +CONFIG_CMD_IMLS=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF_TEST=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_BOOTP_PREFER_SERVERIP=y +CONFIG_CMD_CACHE=y +CONFIG_ENV_OVERWRITE=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_NET_RETRY_COUNT=50 +CONFIG_BOOTP_SEND_HOSTNAME=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_MMC=y +CONFIG_FTSDC010=y +CONFIG_FTSDC010_SDIO=y +CONFIG_MTD_NOR_FLASH=y +CONFIG_FLASH_CFI_DRIVER=y +CONFIG_SYS_FLASH_CFI_WIDTH_16BIT=y +CONFIG_FLASH_SHOW_PROGRESS=0 +CONFIG_SYS_CFI_FLASH_STATUS_POLL=y +CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y +CONFIG_SYS_FLASH_CFI=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_FTMAC100=y +CONFIG_BAUDRATE=38400 +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_ATCSPI200_SPI=y +# CONFIG_BINMAN_FDT is not set +CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT=y
\ No newline at end of file diff --git a/configs/ae350_rv64_falcon_defconfig b/configs/ae350_rv64_falcon_defconfig new file mode 100644 index 00000000000..d11be976de3 --- /dev/null +++ b/configs/ae350_rv64_falcon_defconfig @@ -0,0 +1,60 @@ +CONFIG_RISCV=y +CONFIG_TEXT_BASE=0x01800000 +CONFIG_SYS_MALLOC_LEN=0x80000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x10000000 +CONFIG_ENV_SECT_SIZE=0x1000 +CONFIG_DEFAULT_DEVICE_TREE="ae350_64" +CONFIG_SYS_PROMPT="RISC-V # " +CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000000 +CONFIG_SPL=y +CONFIG_SYS_LOAD_ADDR=0x100000 +CONFIG_TARGET_ANDES_AE350=y +CONFIG_ARCH_RV64I=y +CONFIG_RISCV_SMODE=y +# CONFIG_AVAILABLE_HARTS is not set +CONFIG_FIT=y +CONFIG_SPL_LOAD_FIT_ADDRESS=0x10000000 +CONFIG_SYS_MONITOR_BASE=0x88000000 +CONFIG_DISTRO_DEFAULTS=y +CONFIG_BOOTDELAY=3 +CONFIG_DISPLAY_CPUINFO=y +CONFIG_DISPLAY_BOARDINFO=y +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_SPL_MAX_SIZE=0x100000 +CONFIG_SPL_BSS_START_ADDR=0x400000 +CONFIG_SPL_BOARD_INIT=y +CONFIG_SPL_CACHE=y +CONFIG_SPL_OPENSBI_SCRATCH_OPTIONS=0x0 +CONFIG_SYS_PBSIZE=1050 +CONFIG_SYS_BOOTM_LEN=0x4000000 +CONFIG_CMD_IMLS=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF_TEST=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_BOOTP_PREFER_SERVERIP=y +CONFIG_CMD_CACHE=y +CONFIG_ENV_OVERWRITE=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_NET_RETRY_COUNT=50 +CONFIG_BOOTP_SEND_HOSTNAME=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_MMC=y +CONFIG_FTSDC010=y +CONFIG_FTSDC010_SDIO=y +CONFIG_MTD_NOR_FLASH=y +CONFIG_FLASH_CFI_DRIVER=y +CONFIG_SYS_FLASH_CFI_WIDTH_16BIT=y +CONFIG_FLASH_SHOW_PROGRESS=0 +CONFIG_SYS_CFI_FLASH_STATUS_POLL=y +CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y +CONFIG_SYS_FLASH_CFI=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_FTMAC100=y +CONFIG_BAUDRATE=38400 +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_ATCSPI200_SPI=y +# CONFIG_BINMAN_FDT is not set +CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT=y
\ No newline at end of file diff --git a/configs/ae350_rv64_falcon_xip_defconfig b/configs/ae350_rv64_falcon_xip_defconfig new file mode 100644 index 00000000000..492451ecf13 --- /dev/null +++ b/configs/ae350_rv64_falcon_xip_defconfig @@ -0,0 +1,61 @@ +CONFIG_RISCV=y +CONFIG_TEXT_BASE=0x01800000 +CONFIG_SYS_MALLOC_LEN=0x80000 +CONFIG_NR_DRAM_BANKS=2 +CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y +CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x10000000 +CONFIG_ENV_SECT_SIZE=0x1000 +CONFIG_DEFAULT_DEVICE_TREE="ae350_64" +CONFIG_SPL_TEXT_BASE=0x80000000 +CONFIG_SYS_PROMPT="RISC-V # " +CONFIG_SPL_SYS_MALLOC_F_LEN=0x2000000 +CONFIG_SPL=y +CONFIG_SYS_LOAD_ADDR=0x100000 +CONFIG_TARGET_ANDES_AE350=y +CONFIG_ARCH_RV64I=y +CONFIG_RISCV_SMODE=y +CONFIG_SPL_XIP=y +CONFIG_FIT=y +CONFIG_SPL_LOAD_FIT_ADDRESS=0x80010000 +CONFIG_SYS_MONITOR_BASE=0x88000000 +CONFIG_DISTRO_DEFAULTS=y +CONFIG_BOOTDELAY=3 +CONFIG_DISPLAY_CPUINFO=y +CONFIG_DISPLAY_BOARDINFO=y +CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_SPL_MAX_SIZE=0x100000 +CONFIG_SPL_BSS_START_ADDR=0x400000 +CONFIG_SPL_BOARD_INIT=y +CONFIG_SPL_CACHE=y +CONFIG_SPL_OPENSBI_SCRATCH_OPTIONS=0x0 +CONFIG_SYS_PBSIZE=1050 +CONFIG_SYS_BOOTM_LEN=0x4000000 +CONFIG_CMD_IMLS=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF_TEST=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_BOOTP_PREFER_SERVERIP=y +CONFIG_CMD_CACHE=y +CONFIG_ENV_OVERWRITE=y +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_NET_RETRY_COUNT=50 +CONFIG_BOOTP_SEND_HOSTNAME=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_MMC=y +CONFIG_FTSDC010=y +CONFIG_FTSDC010_SDIO=y +CONFIG_MTD_NOR_FLASH=y +CONFIG_FLASH_CFI_DRIVER=y +CONFIG_SYS_FLASH_CFI_WIDTH_16BIT=y +CONFIG_FLASH_SHOW_PROGRESS=0 +CONFIG_SYS_CFI_FLASH_STATUS_POLL=y +CONFIG_SYS_FLASH_USE_BUFFER_WRITE=y +CONFIG_SYS_FLASH_CFI=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_FTMAC100=y +CONFIG_BAUDRATE=38400 +CONFIG_SYS_NS16550=y +CONFIG_SPI=y +CONFIG_ATCSPI200_SPI=y +# CONFIG_BINMAN_FDT is not set +CONFIG_SPL_LOAD_FIT_OPENSBI_OS_BOOT=y
\ No newline at end of file diff --git a/configs/deneb_defconfig b/configs/deneb_defconfig index 82869e4e0f9..ee2478aa0bb 100644 --- a/configs/deneb_defconfig +++ b/configs/deneb_defconfig @@ -44,6 +44,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/configs/giedi_defconfig b/configs/giedi_defconfig index b56b736c436..5e403c90c8c 100644 --- a/configs/giedi_defconfig +++ b/configs/giedi_defconfig @@ -44,6 +44,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/configs/imx8qm_mek_defconfig b/configs/imx8qm_mek_defconfig index b9083b0453f..4c5206306ee 100644 --- a/configs/imx8qm_mek_defconfig +++ b/configs/imx8qm_mek_defconfig @@ -38,6 +38,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/configs/imx8qxp_mek_defconfig b/configs/imx8qxp_mek_defconfig index f516b0b5557..f312d3945fb 100644 --- a/configs/imx8qxp_mek_defconfig +++ b/configs/imx8qxp_mek_defconfig @@ -38,6 +38,8 @@ CONFIG_SPL_HAS_BSS_LINKER_SECTION=y CONFIG_SPL_BSS_START_ADDR=0x128000 CONFIG_SPL_BSS_MAX_SIZE=0x1000 CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +# CONFIG_SPL_LEGACY_IMAGE_FORMAT is not set CONFIG_SPL_SYS_MALLOC_SIMPLE=y # CONFIG_SPL_SHARES_INIT_SP_ADDR is not set CONFIG_SPL_SYS_MALLOC=y diff --git a/configs/pogo_v4_defconfig b/configs/pogo_v4_defconfig index cbbade3c0ca..fd62146ed33 100644 --- a/configs/pogo_v4_defconfig +++ b/configs/pogo_v4_defconfig @@ -15,6 +15,7 @@ CONFIG_ENV_OFFSET=0xC0000 CONFIG_DEFAULT_DEVICE_TREE="kirkwood-pogoplug-series-4" CONFIG_IDENT_STRING="\nPogoplug V4" CONFIG_SYS_LOAD_ADDR=0x800000 +CONFIG_LTO=y CONFIG_PCI=y CONFIG_DISTRO_DEFAULTS=y CONFIG_BOOTSTAGE=y diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index d39e54f98d2..db05e630832 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -4,13 +4,18 @@ CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_NR_DRAM_BANKS=1 CONFIG_ENV_SIZE=0x2000 +CONFIG_SPL_DM_SPI=y CONFIG_DEFAULT_DEVICE_TREE="sandbox" CONFIG_DM_RESET=y +CONFIG_SPL_MMC=y CONFIG_SPL_SERIAL=y CONFIG_SPL_DRIVERS_MISC=y CONFIG_SPL_SYS_MALLOC_F_LEN=0x8000 CONFIG_SPL=y -CONFIG_SYS_LOAD_ADDR=0x0 +CONFIG_SPL_FS_FAT=y +CONFIG_SPL_SPI_FLASH_SUPPORT=y +CONFIG_SPL_SPI=y +CONFIG_SYS_LOAD_ADDR=0x1000000 CONFIG_PCI=y CONFIG_SANDBOX_SPL=y CONFIG_DEBUG_UART=y @@ -32,9 +37,26 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_SPL_NO_BSS_LIMIT=y CONFIG_HANDOFF=y CONFIG_SPL_BOARD_INIT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +CONFIG_SPL_LEGACY_IMAGE_FORMAT=y +CONFIG_SPL_LOAD_IMX_CONTAINER=y +CONFIG_SPL_SYS_MALLOC=y +CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y +CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0xa000000 +CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR=y +CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR=0x0 CONFIG_SPL_ENV_SUPPORT=y +CONFIG_SPL_ETH=y +CONFIG_SPL_FS_EXT4=y CONFIG_SPL_I2C=y +CONFIG_SPL_MMC_WRITE=y +CONFIG_SPL_DM_SPI_FLASH=y +CONFIG_SPL_NET=y +CONFIG_SPL_NOR_SUPPORT=y CONFIG_SPL_RTC=y +# CONFIG_SPL_SPI_FLASH_TINY is not set +CONFIG_SPL_SPI_LOAD=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y CONFIG_CMD_BOOTZ=y @@ -91,10 +113,13 @@ CONFIG_AMIGA_PARTITION=y CONFIG_OF_CONTROL=y CONFIG_SPL_OF_CONTROL=y CONFIG_SPL_OF_PLATDATA=y +CONFIG_SPL_OF_REAL=y CONFIG_ENV_IS_NOWHERE=y CONFIG_ENV_IS_IN_EXT4=y CONFIG_ENV_EXT4_INTERFACE="host" CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0" +CONFIG_USE_BOOTFILE=y +CONFIG_BOOTFILE="uImage" CONFIG_BOOTP_SEND_HOSTNAME=y CONFIG_NETCONSOLE=y CONFIG_IP_DEFRAG=y @@ -112,6 +137,7 @@ CONFIG_ADC=y CONFIG_ADC_SANDBOX=y CONFIG_AXI=y CONFIG_AXI_SANDBOX=y +CONFIG_SPL_BLK_FS=y CONFIG_SYS_IDE_MAXBUS=1 CONFIG_SYS_ATA_BASE_ADDR=0x100 CONFIG_SYS_ATA_STRIDE=4 @@ -153,6 +179,7 @@ CONFIG_CROS_EC_SPI=y CONFIG_P2SB=y CONFIG_PWRSEQ=y CONFIG_SPL_PWRSEQ=y +CONFIG_FS_LOADER=y CONFIG_MMC_SANDBOX=y CONFIG_SPI_FLASH_SANDBOX=y CONFIG_SPI_FLASH_ATMEL=y @@ -214,6 +241,7 @@ CONFIG_SYSRESET=y CONFIG_SPL_SYSRESET=y CONFIG_DM_THERMAL=y CONFIG_TIMER=y +CONFIG_SPL_TIMER=y CONFIG_TIMER_EARLY=y CONFIG_SANDBOX_TIMER=y CONFIG_USB=y @@ -236,6 +264,7 @@ CONFIG_RSA_VERIFY_WITH_PKEY=y CONFIG_TPM=y CONFIG_LZ4=y CONFIG_ZSTD=y +CONFIG_SPL_LZMA=y CONFIG_ERRNO_STR=y CONFIG_EFI_CAPSULE_ON_DISK=y CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index 4a67af2f088..56072b15ad2 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -32,9 +32,16 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_SPL_NO_BSS_LIMIT=y CONFIG_HANDOFF=y CONFIG_SPL_BOARD_INIT=y +CONFIG_SPL_LEGACY_IMAGE_FORMAT=y +CONFIG_SPL_LOAD_IMX_CONTAINER=y +CONFIG_SPL_SYS_MALLOC=y +CONFIG_SPL_HAS_CUSTOM_MALLOC_START=y +CONFIG_SPL_CUSTOM_SYS_MALLOC_ADDR=0xa000000 +CONFIG_SPL_SYS_MALLOC_SIZE=0x4000000 CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_FPGA=y CONFIG_SPL_I2C=y +CONFIG_SPL_NOR_SUPPORT=y CONFIG_SPL_RTC=y CONFIG_CMD_CPU=y CONFIG_CMD_LICENSE=y @@ -243,6 +250,7 @@ CONFIG_TPM=y CONFIG_SPL_CRC8=y CONFIG_LZ4=y CONFIG_ZSTD=y +CONFIG_SPL_LZMA=y CONFIG_ERRNO_STR=y CONFIG_SPL_HEXDUMP=y CONFIG_EFI_CAPSULE_ON_DISK=y diff --git a/configs/sandbox_vpl_defconfig b/configs/sandbox_vpl_defconfig index 8d76f19729b..5bd0281796d 100644 --- a/configs/sandbox_vpl_defconfig +++ b/configs/sandbox_vpl_defconfig @@ -262,3 +262,4 @@ CONFIG_UNIT_TEST=y CONFIG_SPL_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y +# CONFIG_SPL_UT_LOAD_OS is not set diff --git a/configs/starfive_visionfive2_defconfig b/configs/starfive_visionfive2_defconfig index 6590727fe75..b21754feafc 100644 --- a/configs/starfive_visionfive2_defconfig +++ b/configs/starfive_visionfive2_defconfig @@ -31,6 +31,7 @@ CONFIG_RISCV_SMODE=y # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set CONFIG_FIT=y CONFIG_DISTRO_DEFAULTS=y +CONFIG_BOOTSTAGE=y CONFIG_QSPI_BOOT=y CONFIG_SD_BOOT=y CONFIG_OF_BOARD_SETUP=y @@ -72,6 +73,7 @@ CONFIG_CMD_I2C=y CONFIG_CMD_PCI=y CONFIG_CMD_USB=y CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_BOOTSTAGE=y CONFIG_OF_BOARD=y CONFIG_ENV_OVERWRITE=y CONFIG_ENV_IS_NOWHERE=y diff --git a/drivers/core/Makefile b/drivers/core/Makefile index bce0a3f65cb..acbd2bf2cef 100644 --- a/drivers/core/Makefile +++ b/drivers/core/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_$(SPL_)OF_LIVE) += of_access.o of_addr.o ifndef CONFIG_DM_DEV_READ_INLINE obj-$(CONFIG_OF_CONTROL) += read.o endif +obj-$(CONFIG_$(SPL_)OF_PLATDATA) += read.o obj-$(CONFIG_OF_CONTROL) += of_extra.o ofnode.o read_extra.o ccflags-$(CONFIG_DM_DEBUG) += -DDEBUG diff --git a/drivers/core/root.c b/drivers/core/root.c index 126b3140666..d4ae652bcfb 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -426,7 +426,7 @@ void dm_get_mem(struct dm_stats *stats) stats->tag_size; } -#ifdef CONFIG_ACPIGEN +#if CONFIG_IS_ENABLED(ACPIGEN) static int root_acpi_get_name(const struct udevice *dev, char *out_name) { return acpi_copy_name(out_name, "\\_SB"); diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index d5b85f398db..a96a8c7e955 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -3,7 +3,7 @@ # (C) Copyright 2000-2007 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. obj-$(CONFIG_$(SPL_)DM_I2C) += i2c-uclass.o -ifdef CONFIG_ACPIGEN +ifdef CONFIG_$(SPL_)ACPIGEN obj-$(CONFIG_$(SPL_)DM_I2C) += acpi_i2c.o endif obj-$(CONFIG_$(SPL_)DM_I2C_GPIO) += i2c-gpio.o diff --git a/drivers/i2c/i2c-emul-uclass.c b/drivers/i2c/i2c-emul-uclass.c index 1107cf309fc..d421ddfcbe2 100644 --- a/drivers/i2c/i2c-emul-uclass.c +++ b/drivers/i2c/i2c-emul-uclass.c @@ -46,7 +46,7 @@ int i2c_emul_find(struct udevice *dev, struct udevice **emulp) struct udevice *emul; int ret; - if (!CONFIG_IS_ENABLED(OF_PLATDATA)) { + if (CONFIG_IS_ENABLED(OF_REAL)) { ret = uclass_find_device_by_phandle(UCLASS_I2C_EMUL, dev, "sandbox,emul", &emul); } else { diff --git a/drivers/serial/sandbox.c b/drivers/serial/sandbox.c index f4003811ee7..f6ac3d22852 100644 --- a/drivers/serial/sandbox.c +++ b/drivers/serial/sandbox.c @@ -280,7 +280,7 @@ U_BOOT_DRIVER(sandbox_serial) = { .flags = DM_FLAG_PRE_RELOC, }; -#if CONFIG_IS_ENABLED(OF_REAL) +#if CONFIG_IS_ENABLED(OF_REAL) && !CONFIG_IS_ENABLED(OF_PLATDATA) static const struct sandbox_serial_plat platdata_non_fdt = { .colour = -1, }; diff --git a/drivers/serial/serial_sh.c b/drivers/serial/serial_sh.c index 36263109e6b..c034ab54e15 100644 --- a/drivers/serial/serial_sh.c +++ b/drivers/serial/serial_sh.c @@ -12,10 +12,12 @@ #include <asm/processor.h> #include <clk.h> #include <dm.h> +#include <dm/device_compat.h> #include <dm/platform_data/serial_sh.h> #include <errno.h> #include <linux/compiler.h> #include <linux/delay.h> +#include <reset.h> #include <serial.h> #include "serial_sh.h" @@ -79,10 +81,22 @@ sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate) static void handle_error(struct uart_port *port) { - sci_in(port, SCxSR); - sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port)); + /* + * Most errors are cleared by resetting the relevant error bits to zero + * in the FSR & LSR registers. For each register, a read followed by a + * write is needed according to the relevant datasheets. + */ + unsigned short status = sci_in(port, SCxSR); + sci_out(port, SCxSR, status & ~SCxSR_ERRORS(port)); sci_in(port, SCLSR); sci_out(port, SCLSR, 0x00); + + /* + * To clear framing errors, we also need to read and discard a + * character. + */ + if ((port->type != PORT_SCI) && (status & SCIF_FER)) + sci_in(port, SCxRDR); } static int serial_raw_putc(struct uart_port *port, const char c) @@ -187,12 +201,24 @@ static int sh_serial_probe(struct udevice *dev) { struct sh_serial_plat *plat = dev_get_plat(dev); struct uart_port *priv = dev_get_priv(dev); + struct reset_ctl rst; + int ret; priv->membase = (unsigned char *)plat->base; priv->mapbase = plat->base; priv->type = plat->type; priv->clk_mode = plat->clk_mode; + /* De-assert the module reset if it is defined. */ + ret = reset_get_by_index(dev, 0, &rst); + if (!ret) { + ret = reset_deassert(&rst); + if (ret < 0) { + dev_err(dev, "failed to de-assert reset line\n"); + return ret; + } + } + sh_serial_init_generic(priv); return 0; @@ -209,6 +235,7 @@ static const struct dm_serial_ops sh_serial_ops = { static const struct udevice_id sh_serial_id[] ={ {.compatible = "renesas,sci", .data = PORT_SCI}, {.compatible = "renesas,scif", .data = PORT_SCIF}, + {.compatible = "renesas,scif-r9a07g044", .data = PORT_SCIFA}, {.compatible = "renesas,scifa", .data = PORT_SCIFA}, {.compatible = "renesas,hscif", .data = PORT_HSCIF}, {} diff --git a/drivers/serial/serial_sh.h b/drivers/serial/serial_sh.h index 149ec1fe739..58c2d22bc75 100644 --- a/drivers/serial/serial_sh.h +++ b/drivers/serial/serial_sh.h @@ -90,7 +90,7 @@ struct uart_port { # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ORER 0x0001 /* overrun error bit */ #elif defined(CONFIG_RCAR_GEN2) || defined(CONFIG_RCAR_64) || \ - defined(CONFIG_R7S72100) + defined(CONFIG_R7S72100) || defined(CONFIG_RZG2L) # if defined(CFG_SCIF_A) # define SCIF_ORER 0x0200 # else @@ -312,6 +312,9 @@ static inline void sci_##name##_out(struct uart_port *port,\ sh4_scif_offset, sh4_scif_size) #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \ CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) +#elif defined(CONFIG_RZG2L) +#define SCIF_FNS(reg_name, reg_offset, reg_size) \ + CPU_SCIF_FNS(reg_name, reg_offset, reg_size) #else #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size,\ sh4_sci_offset, sh4_sci_size, \ @@ -387,6 +390,20 @@ SCIF_FNS(SCLSR, 0, 0, 0x14, 16) #else SCIF_FNS(SCLSR, 0, 0, 0x24, 16) #endif +#elif defined(CONFIG_RZG2L) +SCIF_FNS(SCSMR, 0x00, 16) +SCIF_FNS(SCBRR, 0x02, 8) +SCIF_FNS(SCSCR, 0x04, 16) +SCIF_FNS(SCxTDR, 0x06, 8) +SCIF_FNS(SCxSR, 0x08, 16) +SCIF_FNS(SCxRDR, 0x0A, 8) +SCIF_FNS(SCFCR, 0x0C, 16) +SCIF_FNS(SCFDR, 0x0E, 16) +SCIF_FNS(SCSPTR, 0x10, 16) +SCIF_FNS(SCLSR, 0x12, 16) +SCIF_FNS(SCSEMR, 0x14, 8) +SCIF_FNS(SCxTCR, 0x16, 16) +SCIF_FNS(DL, 0x00, 0) #else /* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 SCI/H8*/ /* name off sz off sz off sz off sz off sz*/ diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c index 3750c60b9b9..f485a135299 100644 --- a/drivers/sysreset/sysreset_sandbox.c +++ b/drivers/sysreset/sysreset_sandbox.c @@ -132,7 +132,7 @@ U_BOOT_DRIVER(warm_sysreset_sandbox) = { .ops = &sandbox_warm_sysreset_ops, }; -#if CONFIG_IS_ENABLED(OF_REAL) +#if CONFIG_IS_ENABLED(OF_REAL) && !CONFIG_IS_ENABLED(OF_PLATDATA) /* This is here in case we don't have a device tree */ U_BOOT_DRVINFO(sysreset_sandbox_non_fdt) = { .name = "sysreset_sandbox", diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c index 2b3a9c5fd4c..ee9384fb37e 100644 --- a/drivers/usb/gadget/f_sdp.c +++ b/drivers/usb/gadget/f_sdp.c @@ -34,6 +34,7 @@ #include <spl.h> #include <image.h> #include <imximage.h> +#include <imx_container.h> #include <watchdog.h> #define HID_REPORT_ID_MASK 0x000000ff @@ -852,7 +853,8 @@ static int sdp_handle_in_ep(struct spl_image_info *spl_image, return SDP_EXIT; } #endif - if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER)) { + if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER) && + valid_container_hdr((void *)header)) { struct spl_load_info load; load.dev = header; diff --git a/drivers/watchdog/npcm_wdt.c b/drivers/watchdog/npcm_wdt.c index e56aa0ebe1d..57b61215a2a 100644 --- a/drivers/watchdog/npcm_wdt.c +++ b/drivers/watchdog/npcm_wdt.c @@ -69,15 +69,21 @@ static int npcm_wdt_stop(struct udevice *dev) static int npcm_wdt_reset(struct udevice *dev) { struct npcm_wdt_priv *priv = dev_get_priv(dev); + u32 val; - writel(NPCM_WTR | NPCM_WTRE | NPCM_WTE, priv->regs); + val = readl(priv->regs); + writel(val | NPCM_WTR, priv->regs); return 0; } static int npcm_wdt_expire_now(struct udevice *dev, ulong flags) { - return npcm_wdt_reset(dev); + struct npcm_wdt_priv *priv = dev_get_priv(dev); + + writel(NPCM_WTR | NPCM_WTRE | NPCM_WTE, priv->regs); + + return 0; } static int npcm_wdt_of_to_plat(struct udevice *dev) diff --git a/dts/Kconfig b/dts/Kconfig index 9152f5885e9..00c0aeff893 100644 --- a/dts/Kconfig +++ b/dts/Kconfig @@ -410,12 +410,14 @@ config SPL_OF_PLATDATA declarations for each node. See of-plat.txt for more information. config SPL_OF_REAL - bool + bool "Support a real devicetree in SPL" if SANDBOX + depends on SPL_OF_CONTROL + select SPL_OF_LIBFDT help Indicates that a real devicetree is available which can be accessed at runtime. This means that dev_read_...() functions can be used to - read data from the devicetree for each device. This is true if - SPL_OF_CONTROL is enabled and not SPL_OF_PLATDATA + read data from the devicetree for each device. You do not need to + enable this option if you have enabled SPL_OF_PLATDATA. if SPL_OF_PLATDATA diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index 9a9c520e22c..f50de7c089e 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -2373,10 +2373,6 @@ int ext4fs_mount(unsigned part_length) struct ext2_data *data; int status; struct ext_filesystem *fs = get_fs(); - - if (part_length < SUPERBLOCK_SIZE) - return 0; - data = zalloc(SUPERBLOCK_SIZE); if (!data) return 0; @@ -237,7 +237,7 @@ static struct fstype_info fstypes[] = { .mkdir = fs_mkdir_unsupported, }, #endif -#ifdef CONFIG_SANDBOX +#if IS_ENABLED(CONFIG_SANDBOX) && !IS_ENABLED(CONFIG_SPL_BUILD) { .fstype = FS_TYPE_SANDBOX, .name = "sandbox", diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 4e5653dc886..2372485c84e 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -18,4 +18,7 @@ #define CFG_SYS_BAUDRATE_TABLE {4800, 9600, 19200, 38400, 57600,\ 115200} +/* Unused but necessary to build */ +#define CFG_SYS_UBOOT_BASE CONFIG_TEXT_BASE + #endif diff --git a/include/ext4fs.h b/include/ext4fs.h index cb5d9cc0a5c..dd66d27f776 100644 --- a/include/ext4fs.h +++ b/include/ext4fs.h @@ -31,6 +31,7 @@ struct disk_partition; #define EXT4_INDEX_FL 0x00001000 /* Inode uses hash tree index */ +#define EXT4_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/ #define EXT4_EXTENTS_FL 0x00080000 /* Inode uses extents */ #define EXT4_EXT_MAGIC 0xf30a #define EXT4_FEATURE_RO_COMPAT_GDT_CSUM 0x0010 diff --git a/include/ext_common.h b/include/ext_common.h index 30a0c248414..b09bbde116a 100644 --- a/include/ext_common.h +++ b/include/ext_common.h @@ -35,6 +35,16 @@ struct cmd_tbl; #define EXT2_PATH_MAX 4096 /* Maximum nesting of symlinks, used to prevent a loop. */ #define EXT2_MAX_SYMLINKCNT 8 +/* Maximum file name length */ +#define EXT2_NAME_LEN 255 + +/* + * Revision levels + */ +#define EXT2_GOOD_OLD_REV 0 /* The good old (original) format */ +#define EXT2_DYNAMIC_REV 1 /* V2 format w/ dynamic inode sizes */ + +#define EXT2_GOOD_OLD_INODE_SIZE 128 /* Filetype used in directory entry. */ #define FILETYPE_UNKNOWN 0 @@ -48,6 +58,10 @@ struct cmd_tbl; #define FILETYPE_INO_DIRECTORY 0040000 #define FILETYPE_INO_SYMLINK 0120000 #define EXT2_ROOT_INO 2 /* Root inode */ +#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ + +/* First non-reserved inode for old ext2 filesystems */ +#define EXT2_GOOD_OLD_FIRST_INO 11 /* The size of an ext2 block in bytes. */ #define EXT2_BLOCK_SIZE(data) (1 << LOG2_BLOCK_SIZE(data)) diff --git a/arch/arm/include/asm/mach-imx/image.h b/include/imx_container.h index ee67ca96f4c..54cd684e35d 100644 --- a/arch/arm/include/asm/mach-imx/image.h +++ b/include/imx_container.h @@ -18,6 +18,9 @@ #define CONTAINER_HDR_QSPI_OFFSET SZ_4K #define CONTAINER_HDR_NAND_OFFSET SZ_128M +#define CONTAINER_HDR_TAG 0x87 +#define CONTAINER_HDR_VERSION 0 + struct container_hdr { u8 version; u8 length_lsb; @@ -66,4 +69,10 @@ struct generate_key_blob_hdr { } __packed; int get_container_size(ulong addr, u16 *header_length); + +static inline bool valid_container_hdr(struct container_hdr *container) +{ + return container->tag == CONTAINER_HDR_TAG && + container->version == CONTAINER_HDR_VERSION; +} #endif diff --git a/include/spl.h b/include/spl.h index 1d416b4c929..0d49e4a454c 100644 --- a/include/spl.h +++ b/include/spl.h @@ -416,6 +416,16 @@ int spl_load_imx_container(struct spl_image_info *spl_image, void preloader_console_init(void); u32 spl_boot_device(void); +struct spi_flash; + +/** + * spl_spi_get_uboot_offs() - Lookup function for the SPI boot offset + * @flash: The spi flash to boot from + * + * Return: The offset of U-Boot within the SPI flash + */ +unsigned int spl_spi_get_uboot_offs(struct spi_flash *flash); + /** * spl_spi_boot_bus() - Lookup function for the SPI boot bus source. * @@ -673,7 +683,23 @@ static inline const char *spl_loader_name(const struct spl_image_loader *loader) } #endif +#define SPL_LOAD_IMAGE_GET(_priority, _boot_device, _method) \ + ll_entry_get(struct spl_image_loader, \ + _boot_device ## _priority ## _method, spl_image_loader) + /* SPL FAT image functions */ + +/** + * spl_fat_force_reregister() - Force reregistration of FAT block devices + * + * To avoid repeatedly looking up block devices, spl_load_image_fat keeps track + * of whether it has already registered a block device. This is fine for most + * cases, but when running unit tests all devices are removed and recreated + * in-between tests. This function will force re-registration of any block + * devices, ensuring that we don't try to use an invalid block device. + */ +void spl_fat_force_reregister(void); + int spl_load_image_fat(struct spl_image_info *spl_image, struct spl_boot_device *bootdev, struct blk_desc *block_dev, int partition, @@ -753,6 +779,16 @@ bool spl_was_boot_source(void); */ int spl_dfu_cmd(int usbctrl, char *dfu_alt_info, char *interface, char *devstr); +/** + * spl_mmc_clear_cache() - Clear cached MMC devices + * + * To avoid reinitializing MMCs, spl_mmc_load caches the most-recently-used MMC + * device. This is fine for most cases, but when running unit tests all devices + * are removed and recreated in-between tests. This function will clear any + * cached state, ensuring that we don't try to use an invalid MMC. + */ +void spl_mmc_clear_cache(void); + int spl_mmc_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev); diff --git a/include/test/spl.h b/include/test/spl.h new file mode 100644 index 00000000000..c1f64658502 --- /dev/null +++ b/include/test/spl.h @@ -0,0 +1,155 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com> + */ + +#ifndef TEST_SPL_H +#define TEST_SPL_H + +struct unit_test_state; +struct spl_image_info; + +/* Declare a new SPL test */ +#define SPL_TEST(_name, _flags) UNIT_TEST(_name, _flags, spl_test) + +/** + * generate_data() - Generate some test payload data + * @data: The location to fill + * @size: The size of @data + * @test_name: The seed for the data + * + * Fill @data with data. The upper nibbles will be an incrementing counter + * (0x00, 0x10, 0x20...) to make the data identifiable in a hex dump. The lower + * nibbles are random bits seeded with @test_name. + */ +void generate_data(char *data, size_t size, const char *test_name); + +/** + * enum spl_test_image - Image types for testing + * @LEGACY: "Legacy" uImages + * @LEGACY_LZMA: "Legacy" uImages, LZMA compressed + * @IMX8: i.MX8 Container images + * @FIT_INTERNAL: FITs with internal data + * @FIT_EXTERNAL: FITs with external data + */ +enum spl_test_image { + LEGACY, + LEGACY_LZMA, + IMX8, + FIT_INTERNAL, + FIT_EXTERNAL, +}; + +/** + * create_image() - Create an image for testing + * @dst: The location to create the image at + * @type: The type of image to create + * @info: Image parameters + * @data_offset: Offset of payload data within the image + * + * Create a new image at @dst. @dst must be initialized to all zeros. @info + * should already have name and size filled in. All other parameters will be + * filled in by this function. @info can later be passed to check_image_info(). + * + * If @dst is %NULL, then no data is written. Otherwise, @dst must be + * initialized to zeros, except payload data which must already be present at + * @data_offset. @data_offset may be %NULL if unnecessary. + * + * Typically, this function will be called as follows: + * + * size = create_image(NULL, type, &info, &off); + * img = calloc(size, 1); + * generate_data(img + off, ...); + * create_image(img, type, &info, NULL); + * + * Return: The size of the image, or 0 on error + */ +size_t create_image(void *dst, enum spl_test_image type, + struct spl_image_info *info, size_t *data_offset); + +/** + * check_image_info() - Check image info after loading + * @uts: Current unit test state + * @info1: The base, known good info + * @info2: The info to check + * + * Check @info2 against @info1. This function is typically called after calling + * a function to load/parse an image. Image data is not checked. + * + * Return: 0 on success, or 1 on failure + */ +int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1, + struct spl_image_info *info2); + +/** + * typedef write_image_t - Callback for writing an image + * @uts: Current unit test state + * @img: Image to write + * @size: Size of @img + * + * Write @img to a location which will be read by a &struct spl_image_loader. + * + * Return: 0 on success or 1 on failure + */ +typedef int write_image_t(struct unit_test_state *its, void *img, size_t size); + +/** + * do_spl_test_load() - Test loading with an SPL image loader + * @uts: Current unit test state + * @test_name: Name of the current test + * @type: Type of image to try loading + * @loader: The loader to test + * @write_image: Callback to write the image to the backing storage + * + * Test @loader, performing the common tasks of setting up the image and + * checking it was loaded correctly. The caller must supply a @write_image + * callback to write the image to a location which will be read by @loader. + * + * Return: 0 on success or 1 on failure + */ +int do_spl_test_load(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type, struct spl_image_loader *loader, + write_image_t write_image); + +/** + * image_supported() - Determine whether an image type is supported + * @type: The image type to check + * + * Return: %true if supported and %false otherwise + */ +static inline bool image_supported(enum spl_test_image type) +{ + switch (type) { + case LEGACY_LZMA: + if (!IS_ENABLED(CONFIG_SPL_LZMA)) + return false; + case LEGACY: + return IS_ENABLED(CONFIG_SPL_LEGACY_IMAGE_FORMAT); + case IMX8: + return IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER); + case FIT_INTERNAL: + case FIT_EXTERNAL: + return IS_ENABLED(CONFIG_SPL_LOAD_FIT) || + IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL); + } + + return false; +} + +/* Declare an image test (skipped if the image type is unsupported) */ +#define SPL_IMG_TEST(func, type, flags) \ +static int func##_##type(struct unit_test_state *uts) \ +{ \ + if (!image_supported(type)) \ + return -EAGAIN; \ + return func(uts, __func__, type); \ +} \ +SPL_TEST(func##_##type, flags) + +/* More than a couple blocks, and will not be aligned to anything */ +#define SPL_TEST_DATA_SIZE 4099 + +/* Flags necessary for accessing DM devices */ +#define DM_FLAGS (UT_TESTF_DM | UT_TESTF_SCAN_FDT) + +#endif /* TEST_SPL_H */ diff --git a/lib/Kconfig b/lib/Kconfig index 79cf9ef0fa3..f6ca559897e 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -687,6 +687,12 @@ config SPL_CRC8 checksum with feedback to produce an 8-bit result. The code is small and it does not require a lookup table (unlike CRC32). +config SPL_CRC16 + bool "Support CRC16 in SPL" + depends on SPL + help + Enables CRC16 support in SPL. This is not normally required. + config CRC32 def_bool y help diff --git a/lib/Makefile b/lib/Makefile index 1c31ad9531e..2a76acf100d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_TPM_V2) += tpm-v2.o endif obj-$(CONFIG_$(SPL_TPL_)CRC8) += crc8.o +obj-$(CONFIG_$(SPL_TPL_)CRC16) += crc16.o obj-y += crypto/ diff --git a/net/Makefile b/net/Makefile index 3e2d061338d..64ab7ec740a 100644 --- a/net/Makefile +++ b/net/Makefile @@ -27,8 +27,8 @@ obj-$(CONFIG_CMD_PCAP) += pcap.o obj-$(CONFIG_CMD_RARP) += rarp.o obj-$(CONFIG_CMD_SNTP) += sntp.o obj-$(CONFIG_CMD_TFTPBOOT) += tftp.o -obj-$(CONFIG_UDP_FUNCTION_FASTBOOT) += fastboot_udp.o -obj-$(CONFIG_TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o +obj-$(CONFIG_$(SPL_TPL_)UDP_FUNCTION_FASTBOOT) += fastboot_udp.o +obj-$(CONFIG_$(SPL_TPL_)TCP_FUNCTION_FASTBOOT) += fastboot_tcp.o obj-$(CONFIG_CMD_WOL) += wol.o obj-$(CONFIG_PROT_UDP) += udp.o obj-$(CONFIG_PROT_TCP) += tcp.o diff --git a/net/bootp.c b/net/bootp.c index 8b1a4ae2ef8..7b0f45e18a9 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -41,9 +41,6 @@ */ #define TIMEOUT_MS ((3 + (CONFIG_NET_RETRY_COUNT * 5)) * 1000) -#define PORT_BOOTPS 67 /* BOOTP server UDP port */ -#define PORT_BOOTPC 68 /* BOOTP client UDP port */ - #ifndef CFG_DHCP_MIN_EXT_LEN /* minimal length of extension list */ #define CFG_DHCP_MIN_EXT_LEN 64 #endif @@ -1076,6 +1073,11 @@ static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip, CONFIG_SYS_BOOTFILE_PREFIX, strlen(CONFIG_SYS_BOOTFILE_PREFIX)) == 0) { #endif /* CONFIG_SYS_BOOTFILE_PREFIX */ + if (CONFIG_IS_ENABLED(UNIT_TEST) && + dhcp_message_type((u8 *)bp->bp_vend) == -1) { + debug("got BOOTP response; transitioning to BOUND\n"); + goto dhcp_got_bootp; + } dhcp_packet_process_options(bp); if (CONFIG_IS_ENABLED(EFI_LOADER) && IS_ENABLED(CONFIG_NETDEVICES)) @@ -1102,6 +1104,7 @@ static void dhcp_handler(uchar *pkt, unsigned dest, struct in_addr sip, debug("DHCP State: REQUESTING\n"); if (dhcp_message_type((u8 *)bp->bp_vend) == DHCP_ACK) { +dhcp_got_bootp: dhcp_packet_process_options(bp); /* Store net params from reply */ store_net_params(bp); diff --git a/net/bootp.h b/net/bootp.h index 567340ec5d4..4e32b19d424 100644 --- a/net/bootp.h +++ b/net/bootp.h @@ -15,6 +15,9 @@ /**********************************************************************/ +#define PORT_BOOTPS 67 /* BOOTP server UDP port */ +#define PORT_BOOTPC 68 /* BOOTP client UDP port */ + /* * BOOTP header. */ diff --git a/net/net.c b/net/net.c index e6f61f0f8f6..8357f084101 100644 --- a/net/net.c +++ b/net/net.c @@ -511,12 +511,12 @@ restart: tftp_start_server(); break; #endif -#if defined(CONFIG_UDP_FUNCTION_FASTBOOT) +#if CONFIG_IS_ENABLED(UDP_FUNCTION_FASTBOOT) case FASTBOOT_UDP: fastboot_udp_start_server(); break; #endif -#if defined(CONFIG_TCP_FUNCTION_FASTBOOT) +#if CONFIG_IS_ENABLED(TCP_FUNCTION_FASTBOOT) case FASTBOOT_TCP: fastboot_tcp_start_server(); break; diff --git a/test/Kconfig b/test/Kconfig index 830245b6f9a..ca648d23376 100644 --- a/test/Kconfig +++ b/test/Kconfig @@ -101,6 +101,7 @@ config UT_UNICODE source "test/dm/Kconfig" source "test/env/Kconfig" +source "test/image/Kconfig" source "test/lib/Kconfig" source "test/optee/Kconfig" source "test/overlay/Kconfig" diff --git a/test/Makefile b/test/Makefile index 178773647a8..8e1fed2c28b 100644 --- a/test/Makefile +++ b/test/Makefile @@ -3,9 +3,6 @@ # (C) Copyright 2012 The Chromium Authors obj-y += test-main.o -ifdef CONFIG_SPL_LOAD_FIT -obj-$(CONFIG_SANDBOX) += image/ -endif ifneq ($(CONFIG_$(SPL_)BLOBLIST),) obj-$(CONFIG_$(SPL_)CMDLINE) += bloblist.o @@ -30,4 +27,6 @@ obj-$(CONFIG_UNIT_TEST) += boot/ obj-$(CONFIG_UNIT_TEST) += common/ obj-y += log/ obj-$(CONFIG_$(SPL_)UT_UNICODE) += unicode_ut.o +else +obj-$(CONFIG_SPL_UT_LOAD) += image/ endif diff --git a/test/dm/wdt.c b/test/dm/wdt.c index 653d7b1c8b3..2bbebcdbf28 100644 --- a/test/dm/wdt.c +++ b/test/dm/wdt.c @@ -54,7 +54,7 @@ static int dm_test_wdt_gpio_toggle(struct unit_test_state *uts) */ struct udevice *wdt, *gpio; const u64 timeout = 42; - const int offset = 7; + const int offset = 8; int val; ut_assertok(uclass_get_device_by_name(UCLASS_WDT, @@ -115,7 +115,7 @@ static int dm_test_wdt_watchdog_reset(struct unit_test_state *uts) struct udevice *gpio_wdt, *sandbox_wdt; struct udevice *gpio; const u64 timeout = 42; - const int offset = 7; + const int offset = 8; uint reset_count; int val; diff --git a/test/image/Kconfig b/test/image/Kconfig new file mode 100644 index 00000000000..8f9e6ae036b --- /dev/null +++ b/test/image/Kconfig @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (C) 2023 Sean Anderson <seanga2@gmail.com> + +config SPL_UT_LOAD + bool "Unit tests for SPL load methods" + depends on SPL_UNIT_TEST + default y if SANDBOX + help + Test various SPL load methods. + +if SPL_UT_LOAD + +config SPL_UT_LOAD_FS + bool "Unit tests for filesystems" + depends on SANDBOX && SPL_OF_REAL + depends on FS_LOADER + depends on SPL_BLK_FS + depends on SPL_FS_FAT + depends on SPL_FS_EXT4 + depends on SPL_MMC_WRITE + depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR + default y + help + Test filesystems and the various load methods which use them. + +config SPL_UT_LOAD_NET + bool "Test loading over TFTP" + depends on SANDBOX && SPL_OF_REAL + depends on SPL_ETH + depends on USE_BOOTFILE + default y + help + Test loading images over TFTP using the NET image load method. + +config SPL_UT_LOAD_SPI + bool "Test loading from SPI Flash" + depends on SANDBOX && SPL_OF_REAL + depends on SPL_SPI_LOAD + default y + help + Test the SPI flash image load metod. + +config SPL_UT_LOAD_OS + bool "Test loading from the host OS" + depends on SANDBOX && SPL_LOAD_FIT + default y + help + Smoke test to ensure that loading U-boot works in sandbox. + +endif diff --git a/test/image/Makefile b/test/image/Makefile index c4039df707f..b30210106a4 100644 --- a/test/image/Makefile +++ b/test/image/Makefile @@ -2,4 +2,9 @@ # # Copyright 2021 Google LLC -obj-$(CONFIG_SPL_BUILD) += spl_load.o +obj-y += spl_load.o +obj-$(CONFIG_SPL_UT_LOAD_FS) += spl_load_fs.o +obj-$(CONFIG_SPL_UT_LOAD_NET) += spl_load_net.o +obj-$(CONFIG_SPL_NOR_SUPPORT) += spl_load_nor.o +obj-$(CONFIG_SPL_UT_LOAD_OS) += spl_load_os.o +obj-$(CONFIG_SPL_UT_LOAD_SPI) += spl_load_spi.o diff --git a/test/image/spl_load.c b/test/image/spl_load.c index 4e27ff460ab..ab4c14d6491 100644 --- a/test/image/spl_load.c +++ b/test/image/spl_load.c @@ -1,91 +1,661 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright 2021 Google LLC - * Written by Simon Glass <sjg@chromium.org> + * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com> */ #include <common.h> #include <image.h> +#include <imx_container.h> #include <mapmem.h> -#include <os.h> +#include <memalign.h> +#include <rand.h> +#include <spi_flash.h> #include <spl.h> +#include <test/spl.h> #include <test/ut.h> +#include <u-boot/crc.h> -/* Declare a new SPL test */ -#define SPL_TEST(_name, _flags) UNIT_TEST(_name, _flags, spl_test) +int board_fit_config_name_match(const char *name) +{ + return 0; +} -/* Context used for this test */ -struct text_ctx { - int fd; -}; +struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size) +{ + return map_sysmem(0x100000, 0); +} + +/* Try to reuse the load buffer to conserve memory */ +void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len) +{ + static void *buf; + static size_t size; + + if (size < sectors * bl_len) { + free(buf); + size = sectors * bl_len; + buf = malloc_cache_aligned(size); + } + return buf; +} + +/* Local flags for spl_image; start from the "top" to avoid conflicts */ +#define SPL_IMX_CONTAINER 0x80000000 +#define SPL_COMP_LZMA 0x40000000 -static ulong read_fit_image(struct spl_load_info *load, ulong sector, - ulong count, void *buf) +void generate_data(char *data, size_t size, const char *test_name) { - struct text_ctx *text_ctx = load->priv; - off_t offset, ret; - ssize_t res; + int i; + unsigned int seed = 1; + + while (*test_name) { + seed += *test_name++; + rand_r(&seed); + } + + for (i = 0; i < size; i++) + data[i] = (i & 0xf) << 4 | (rand_r(&seed) & 0xf); +} + +static size_t create_legacy(void *dst, struct spl_image_info *spl_image, + size_t *data_offset) +{ + struct legacy_img_hdr *hdr = dst; + void *data = dst + sizeof(*hdr); + + if (data_offset) + *data_offset = data - dst; + + if (!dst) + goto out; + + image_set_magic(hdr, IH_MAGIC); + image_set_time(hdr, 0); + image_set_size(hdr, spl_image->size); + image_set_load(hdr, spl_image->load_addr); + image_set_ep(hdr, spl_image->entry_point); + image_set_dcrc(hdr, crc32(0, data, spl_image->size)); + image_set_os(hdr, spl_image->os); + image_set_arch(hdr, IH_ARCH_DEFAULT); + image_set_type(hdr, IH_TYPE_FIRMWARE); + image_set_comp(hdr, spl_image->flags & SPL_COMP_LZMA ? IH_COMP_LZMA : + IH_COMP_NONE); + image_set_name(hdr, spl_image->name); + image_set_hcrc(hdr, crc32(0, (void *)hdr, sizeof(*hdr))); + +out: + return sizeof(*hdr) + spl_image->size; +} + +static size_t create_imx8(void *dst, struct spl_image_info *spl_image, + size_t *data_offset) +{ + struct container_hdr *hdr = dst; + struct boot_img_t *img = dst + sizeof(*hdr); + size_t length = sizeof(*hdr) + sizeof(*img); + /* Align to MMC block size for now */ + void *data = dst + 512; + + if (data_offset) + *data_offset = data - dst; - offset = sector * load->bl_len; - ret = os_lseek(text_ctx->fd, offset, OS_SEEK_SET); - if (ret != offset) { - printf("Failed to seek to %zx, got %zx (errno=%d)\n", offset, - ret, errno); + if (!dst) + goto out; + + hdr->version = CONTAINER_HDR_VERSION; + hdr->length_lsb = length & 0xff; + hdr->length_msb = length >> 8; + hdr->tag = CONTAINER_HDR_TAG; + hdr->num_images = 1; + + /* spl_load_imx_container doesn't handle endianness; whoops! */ + img->offset = data - dst; + img->size = spl_image->size; + img->dst = spl_image->load_addr; + img->entry = spl_image->entry_point; + +out: + return data - dst + spl_image->size; +} + +#define ADDRESS_CELLS (sizeof(uintptr_t) / sizeof(u32)) + +static inline int fdt_property_addr(void *fdt, const char *name, uintptr_t val) +{ + if (sizeof(uintptr_t) == sizeof(u32)) + return fdt_property_u32(fdt, name, val); + return fdt_property_u64(fdt, name, val); +} + +static size_t start_fit(void *dst, size_t fit_size, size_t data_size, + bool external) +{ + void *data; + + if (fdt_create(dst, fit_size)) + return 0; + if (fdt_finish_reservemap(dst)) + return 0; + if (fdt_begin_node(dst, "")) + return 0; + if (fdt_property_u32(dst, FIT_TIMESTAMP_PROP, 0)) return 0; + if (fdt_property_u32(dst, "#address-cells", ADDRESS_CELLS)) + return 0; + if (fdt_property_string(dst, FIT_DESC_PROP, "")) + return 0; + + if (fdt_begin_node(dst, "images")) + return 0; + if (fdt_begin_node(dst, "u-boot")) + return 0; + + if (external) { + if (fdt_property_u32(dst, FIT_DATA_OFFSET_PROP, 0)) + return 0; + return fit_size; } - res = os_read(text_ctx->fd, buf, count * load->bl_len); - if (res == -1) { - printf("Failed to read %lx bytes, got %ld (errno=%d)\n", - count * load->bl_len, res, errno); + if (fdt_property_placeholder(dst, FIT_DATA_PROP, data_size, &data)) return 0; + return data - dst; +} + +static size_t create_fit(void *dst, struct spl_image_info *spl_image, + size_t *data_offset, bool external) +{ + size_t prop_size = 596, total_size = prop_size + spl_image->size; + size_t off, size; + + if (external) { + size = prop_size; + off = size; + } else { + char tmp[256]; + + size = total_size; + off = start_fit(tmp, sizeof(tmp), 0, false); + if (!off) + return 0; } - return count; + if (data_offset) + *data_offset = off; + + if (!dst) + goto out; + + if (start_fit(dst, size, spl_image->size, external) != off) + return 0; + + if (fdt_property_string(dst, FIT_DESC_PROP, spl_image->name)) + return 0; + if (fdt_property_string(dst, FIT_TYPE_PROP, "firmware")) + return 0; + if (fdt_property_string(dst, FIT_COMP_PROP, "none")) + return 0; + if (fdt_property_u32(dst, FIT_DATA_SIZE_PROP, spl_image->size)) + return 0; + if (fdt_property_string(dst, FIT_OS_PROP, + genimg_get_os_short_name(spl_image->os))) + return 0; + if (fdt_property_string(dst, FIT_ARCH_PROP, + genimg_get_arch_short_name(IH_ARCH_DEFAULT))) + return 0; + if (fdt_property_addr(dst, FIT_ENTRY_PROP, spl_image->entry_point)) + return 0; + if (fdt_property_addr(dst, FIT_LOAD_PROP, spl_image->load_addr)) + return 0; + if (fdt_end_node(dst)) /* u-boot */ + return 0; + if (fdt_end_node(dst)) /* images */ + return 0; + + if (fdt_begin_node(dst, "configurations")) + return 0; + if (fdt_property_string(dst, FIT_DEFAULT_PROP, "config-1")) + return 0; + if (fdt_begin_node(dst, "config-1")) + return 0; + if (fdt_property_string(dst, FIT_DESC_PROP, spl_image->name)) + return 0; + if (fdt_property_string(dst, FIT_FIRMWARE_PROP, "u-boot")) + return 0; + if (fdt_end_node(dst)) /* configurations */ + return 0; + if (fdt_end_node(dst)) /* config-1 */ + return 0; + + if (fdt_end_node(dst)) /* root */ + return 0; + if (fdt_finish(dst)) + return 0; + + if (external) { + if (fdt_totalsize(dst) > size) + return 0; + fdt_set_totalsize(dst, size); + } + +out: + return total_size; } -int board_fit_config_name_match(const char *name) +size_t create_image(void *dst, enum spl_test_image type, + struct spl_image_info *info, size_t *data_offset) { + bool external = false; + + info->os = IH_OS_U_BOOT; + info->load_addr = CONFIG_TEXT_BASE; + info->entry_point = CONFIG_TEXT_BASE + 0x100; + info->flags = 0; + + switch (type) { + case LEGACY_LZMA: + info->flags = SPL_COMP_LZMA; + case LEGACY: + return create_legacy(dst, info, data_offset); + case IMX8: + info->flags = SPL_IMX_CONTAINER; + return create_imx8(dst, info, data_offset); + case FIT_EXTERNAL: + /* + * spl_fit_append_fdt will clobber external images with U-Boot's + * FDT if the image doesn't have one. Just set the OS to + * something which doesn't take a devicetree. + */ + if (!IS_ENABLED(CONFIG_LOAD_FIT_FULL)) + info->os = IH_OS_TEE; + external = true; + case FIT_INTERNAL: + info->flags = SPL_FIT_FOUND; + return create_fit(dst, info, data_offset, external); + } + return 0; } -struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size) +int check_image_info(struct unit_test_state *uts, struct spl_image_info *info1, + struct spl_image_info *info2) { - return map_sysmem(0x100000, 0); + if (info2->name) { + if (info1->flags & SPL_FIT_FOUND) + ut_asserteq_str(genimg_get_os_name(info1->os), + info2->name); + else + ut_asserteq_str(info1->name, info2->name); + } + + if (info1->flags & SPL_IMX_CONTAINER) + ut_asserteq(IH_OS_INVALID, info2->os); + else + ut_asserteq(info1->os, info2->os); + + ut_asserteq(info1->entry_point, info2->entry_point); + if (info1->flags & (SPL_FIT_FOUND | SPL_IMX_CONTAINER) || + info2->flags & SPL_COPY_PAYLOAD_ONLY) { + ut_asserteq(info1->load_addr, info2->load_addr); + if (info1->flags & SPL_IMX_CONTAINER) + ut_asserteq(0, info2->size); + else if (!(info1->flags & SPL_COMP_LZMA)) + ut_asserteq(info1->size, info2->size); + } else { + ut_asserteq(info1->load_addr - sizeof(struct legacy_img_hdr), + info2->load_addr); + ut_asserteq(info1->size + sizeof(struct legacy_img_hdr), + info2->size); + } + + return 0; +} + +static ulong spl_test_read(struct spl_load_info *load, ulong sector, + ulong count, void *buf) +{ + memcpy(buf, load->priv + sector, count); + return count; } -static int spl_test_load(struct unit_test_state *uts) +static int spl_test_image(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type) { - struct spl_image_info image; - struct legacy_img_hdr *header; - struct text_ctx text_ctx; - struct spl_load_info load; - char fname[256]; - int ret; - int fd; - - memset(&load, '\0', sizeof(load)); - load.bl_len = 512; - load.read = read_fit_image; - - ret = sandbox_find_next_phase(fname, sizeof(fname), true); - if (ret) { - printf("(%s not found, error %d)\n", fname, ret); - return ret; + size_t img_size, img_data, data_size = SPL_TEST_DATA_SIZE; + struct spl_image_info info_write = { + .name = test_name, + .size = data_size, + }, info_read = { }; + char *data; + void *img; + + img_size = create_image(NULL, type, &info_write, &img_data); + ut_assert(img_size); + img = calloc(img_size, 1); + ut_assertnonnull(img); + + data = img + img_data; + generate_data(data, data_size, test_name); + ut_asserteq(img_size, create_image(img, type, &info_write, NULL)); + + if (type == LEGACY) { + ut_assertok(spl_parse_image_header(&info_read, NULL, img)); + if (check_image_info(uts, &info_write, &info_read)) + return CMD_RET_FAILURE; + } else { + struct spl_load_info load = { + .bl_len = 1, + .priv = img, + .read = spl_test_read, + }; + + if (type == IMX8) + ut_assertok(spl_load_imx_container(&info_read, &load, + 0)); + else if (IS_ENABLED(CONFIG_SPL_FIT_FULL)) + ut_assertok(spl_parse_image_header(&info_read, NULL, + img)); + else + ut_assertok(spl_load_simple_fit(&info_read, &load, 0, + img)); + if (check_image_info(uts, &info_write, &info_read)) + return CMD_RET_FAILURE; + ut_asserteq_mem(data, phys_to_virt(info_write.load_addr), + data_size); } - load.filename = fname; - header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); + free(img); + return 0; +} +SPL_IMG_TEST(spl_test_image, LEGACY, 0); +SPL_IMG_TEST(spl_test_image, IMX8, 0); +SPL_IMG_TEST(spl_test_image, FIT_INTERNAL, 0); +SPL_IMG_TEST(spl_test_image, FIT_EXTERNAL, 0); + +/* + * LZMA is too complex to generate on the fly, so let's use some data I put in + * the oven^H^H^H^H compressed earlier + */ +static const char lzma_compressed[] = { + 0x5d, 0x00, 0x00, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x02, 0x05, 0x55, 0x4e, 0x82, 0xbc, 0xc2, 0x42, 0xf6, 0x88, + 0x6c, 0x99, 0xd6, 0x82, 0x48, 0xa6, 0x06, 0x67, 0xf8, 0x46, 0x7c, 0xe9, + 0x41, 0x79, 0xfe, 0x90, 0x0b, 0x31, 0x7b, 0x79, 0x91, 0xb8, 0x5f, 0x33, + 0x11, 0x04, 0xc3, 0x4f, 0xf5, 0x71, 0xd1, 0xfb, 0x94, 0x6b, 0x5f, 0x78, + 0xe2, 0xfa, 0x6a, 0x21, 0xb6, 0x1d, 0x11, 0x0e, 0x5b, 0x56, 0x6a, 0x5b, + 0xe9, 0x56, 0x5f, 0x8b, 0x87, 0x61, 0x96, 0x6d, 0xce, 0x66, 0xbb, 0xb6, + 0xe7, 0x13, 0x5a, 0xd8, 0x84, 0x29, 0x60, 0xa0, 0x80, 0x43, 0xdd, 0x0f, + 0x4b, 0x85, 0xb0, 0x04, 0x9d, 0x9f, 0x28, 0x97, 0x0a, 0x1e, 0x16, 0xb0, + 0x45, 0x33, 0x5e, 0x79, 0x4f, 0xaa, 0xee, 0x79, 0x6e, 0xc3, 0x4e, 0x3d, + 0xe8, 0x67, 0x7c, 0xe0, 0xd0, 0xcc, 0x05, 0x40, 0xae, 0x6b, 0x97, 0x82, + 0x97, 0x02, 0x01, 0xe2, 0xe3, 0xbc, 0xe4, 0x9b, 0xb3, 0x28, 0xed, 0x5e, + 0x0d, 0x68, 0x6e, 0xe5, 0x17, 0x0a, 0x86, 0x5a, 0xcd, 0x8d, 0x46, 0x2d, + 0x06, 0x10, 0xa6, 0x90, 0x44, 0xa1, 0xfc, 0x66, 0x6d, 0x7c, 0x57, 0x57, + 0x07, 0xbc, 0x95, 0xb2, 0x8d, 0xf0, 0x9f, 0x4d, 0x90, 0x04, 0xaf, 0x0c, + 0x23, 0x51, 0x1b, 0x34, 0xd5, 0x5c, 0x5d, 0x87, 0x5e, 0x10, 0x2b, 0x71, + 0xc2, 0xcf, 0xc5, 0x9d, 0x4b, 0x89, 0x01, 0xc4, 0x97, 0xf2, 0xea, 0x83, + 0x97, 0xfa, 0xe0, 0x51, 0x96, 0x78, 0x4f, 0x44, 0xb8, 0xa8, 0x9d, 0x03, + 0x1c, 0x6e, 0xb7, 0xc6, 0xd7, 0xc5, 0x3e, 0x32, 0x65, 0xa7, 0x06, 0xab, + 0x86, 0xfb, 0xd2, 0x9b, 0xd7, 0x86, 0xa8, 0xfe, 0x46, 0x41, 0x2e, 0xc2, + 0x4e, 0xed, 0xa2, 0x9b, 0x79, 0x36, 0x37, 0x49, 0x90, 0xfc, 0xa6, 0x14, + 0x93, 0x17, 0x82, 0x62, 0x3f, 0x79, 0x6b, 0x86, 0xc2, 0xeb, 0x82, 0xfe, + 0x87, 0x49, 0xa5, 0x7e, 0x41, 0xe3, 0x59, 0x60, 0x15, 0x61, 0x4e, 0x3b, + 0x16, 0xcf, 0xdb, 0x49, 0x2c, 0x84, 0x92, 0x26, 0x40, 0x04, 0x78, 0xd3, + 0xd6, 0xa6, 0xed, 0x6e, 0x63, 0x49, 0xcb, 0xea, 0xfe, 0x43, 0x85, 0x21, + 0x1a, 0x28, 0x36, 0x0a, 0x3e, 0x2a, 0xad, 0xba, 0xfc, 0x8a, 0x37, 0x18, + 0xb4, 0x80, 0xbe, 0x6a, 0x36, 0x14, 0x03, 0xdd, 0xa3, 0x37, 0xbd, 0xc1, + 0x8a, 0xbb, 0x2d, 0xd4, 0x08, 0xd7, 0x4b, 0xc4, 0xe9, 0xb8, 0xb4, 0x65, + 0xdd, 0xf6, 0xe8, 0x17, 0x2c, 0x2c, 0x9b, 0x1e, 0x92, 0x0b, 0xcb, 0x22, + 0x7c, 0x1b, 0x74, 0x8d, 0x65, 0x11, 0x5f, 0xfe, 0xf5, 0x2a, 0xc2, 0xbe, + 0xea, 0xa2, 0xf1, 0x7b, 0xe8, 0xaf, 0x32, 0x5a, 0x0a, 0x5b, 0xd2, 0x5a, + 0x11, 0x22, 0x79, 0xfa, 0xae, 0x2d, 0xe8, 0xc6, 0x17, 0xba, 0x17, 0x81, + 0x6a, 0x63, 0xb5, 0x26, 0xd7, 0x8d, 0xd0, 0x66, 0x0c, 0x4a, 0x0c, 0x22, + 0x1b, 0x20, 0x9f, 0x3d, 0x0b, 0x1b, 0x59, 0x53, 0x89, 0x9b, 0x5e, 0xbd, + 0x3d, 0xd1, 0xdd, 0xff, 0xca, 0xb2, 0xb7, 0x12, 0x8d, 0x03, 0xaa, 0xc3, + 0x1d, 0x56, 0x76, 0x14, 0xf8, 0xee, 0xb3, 0xeb, 0x80, 0x38, 0xc1, 0xc1, + 0x1a, 0xef, 0x4a, 0xd5, 0x16, 0x1f, 0x5e, 0x21, 0x5d, 0x46, 0x01, 0xb3, + 0xa4, 0xf7, 0x99, 0x94, 0x05, 0xc6, 0xc8, 0x06, 0xd8, 0x1c, 0xac, 0x47, + 0x13, 0x54, 0x13, 0x1b, 0x1f, 0xb6, 0x23, 0x9c, 0x73, 0x2b, 0x57, 0x32, + 0x94, 0x92, 0xf1, 0x71, 0x44, 0x40, 0x02, 0xc3, 0x21, 0x4a, 0x2f, 0x36, + 0x5e, 0x8a, 0xd0, 0x4b, 0x02, 0xc7, 0x6e, 0xcf, 0xed, 0xa2, 0xdb, 0xce, + 0x0a, 0x0f, 0x66, 0x4f, 0xb2, 0x3d, 0xb6, 0xcc, 0x75, 0x45, 0x80, 0x0a, + 0x49, 0x4a, 0xe7, 0xe7, 0x24, 0x62, 0x65, 0xc7, 0x02, 0x22, 0x13, 0xbe, + 0x6c, 0xa9, 0x9a, 0x8b, 0xa9, 0x1b, 0x2b, 0x3a, 0xde, 0x5e, 0x37, 0xbd, + 0x7f, 0x85, 0xd1, 0x32, 0x1d, 0xbf, 0x03, 0x8a, 0x3b, 0xe5, 0xb3, 0xfd, + 0x01, 0xca, 0xde, 0x0d, 0x7a, 0x5b, 0x01, 0x05, 0x1d, 0x3c, 0x23, 0x00, + 0x60, 0xb7, 0x50, 0xfd, 0x0d, 0xd7, 0x63, 0x92, 0xd6, 0xb0, 0x48, 0x3a, + 0x2d, 0xa3, 0xf8, 0xf6, 0x44, 0xe1, 0xda, 0x3b, 0xf4, 0x39, 0x47, 0xc4, + 0x4d, 0x8f, 0x54, 0x78, 0xec, 0x27, 0x7b, 0xc6, 0xe4, 0x81, 0x3a, 0x3f, + 0xa5, 0x61, 0x9d, 0xcb, 0x71, 0x0b, 0x0d, 0x55, 0xea, 0x5b, 0xeb, 0x58, + 0xa5, 0x49, 0xb5, 0x44, 0x1b, 0xb0, 0x0d, 0x1f, 0x58, 0xfb, 0x7a, 0xd4, + 0x09, 0x1e, 0x9a, 0x7e, 0x21, 0xba, 0xb3, 0x36, 0xa6, 0x04, 0x74, 0xe1, + 0xd0, 0xca, 0x02, 0x11, 0x84, 0x93, 0x8f, 0x86, 0x3d, 0x79, 0xbf, 0xa8, + 0xec, 0x0a, 0x23, 0x5e, 0xde, 0xc4, 0xc6, 0xda, 0x45, 0xbd, 0x95, 0x74, + 0x7b, 0xbf, 0xc1, 0x80, 0x48, 0x3f, 0x10, 0xb6, 0xb9, 0x5c, 0x31, 0x52, + 0x06, 0x5a, 0xac, 0xec, 0x94, 0x21, 0x80, 0x51, 0xba, 0x64, 0xed, 0x9d, + 0x27, 0x72, 0x8d, 0x17, 0x43, 0x5f, 0xf1, 0x60, 0xfa, 0xb5, 0x65, 0xd4, + 0xb9, 0xf8, 0xfc, 0x48, 0x7b, 0xe3, 0xfe, 0xae, 0xe4, 0x71, 0x4a, 0x3d, + 0x8c, 0xf5, 0x72, 0x8b, 0xbf, 0x60, 0xd8, 0x6a, 0x8f, 0x51, 0x82, 0xae, + 0x98, 0xd0, 0x56, 0xf9, 0xa8, 0x3a, 0xad, 0x86, 0x26, 0xa8, 0x5a, 0xf8, + 0x63, 0x87, 0x2c, 0x74, 0xbf, 0xf9, 0x7d, 0x00, 0xa0, 0x2f, 0x17, 0x23, + 0xb7, 0x62, 0x94, 0x19, 0x47, 0x57, 0xf9, 0xa8, 0xe7, 0x4b, 0xe9, 0x2b, + 0xe8, 0xb4, 0x03, 0xbf, 0x23, 0x75, 0xfe, 0xc3, 0x94, 0xc0, 0xa9, 0x5b, + 0x07, 0xb5, 0x75, 0x87, 0xcc, 0xa5, 0xb5, 0x9b, 0x35, 0x29, 0xe4, 0xb1, + 0xaa, 0x04, 0x57, 0xe9, 0xa3, 0xd0, 0xa3, 0xe4, 0x11, 0xe1, 0xaa, 0x3b, + 0x67, 0x09, 0x60, 0x83, 0x23, 0x72, 0xa6, 0x7b, 0x73, 0x22, 0x5b, 0x4a, + 0xe0, 0xf0, 0xa3, 0xeb, 0x9c, 0x91, 0xda, 0xba, 0x8b, 0xc1, 0x32, 0xa9, + 0x24, 0x13, 0x51, 0xe4, 0x67, 0x49, 0x4a, 0xd9, 0x3d, 0xae, 0x80, 0xfd, + 0x0a, 0x0d, 0x56, 0x98, 0x66, 0xa2, 0x6d, 0x92, 0x54, 0x7f, 0x82, 0xe5, + 0x17, 0x39, 0xd3, 0xaa, 0xc4, 0x4e, 0x6f, 0xe1, 0x2e, 0xfe, 0x03, 0x44, + 0x8a, 0xdd, 0xeb, 0xc0, 0x74, 0x79, 0x63, 0x33, 0x2b, 0x4b, 0xb5, 0x62, + 0xdd, 0x47, 0xba, 0x6e, 0xfc, 0x91, 0x08, 0xa9, 0x17, 0x8c, 0x47, 0x61, + 0xd9, 0x32, 0xe9, 0xa0, 0xb3, 0xa2, 0x82, 0xc9, 0xa6, 0x32, 0xa1, 0xca, + 0x7c, 0x41, 0xa6, 0x5a, 0xe2, 0x46, 0xb6, 0x45, 0x53, 0x72, 0x55, 0x9e, + 0xdf, 0xac, 0x96, 0x68, 0xe5, 0xdc, 0x4e, 0x2d, 0xa8, 0x1e, 0x7a, 0x8e, + 0xff, 0x54, 0xe4, 0x0a, 0x33, 0x5d, 0x97, 0xdf, 0x4e, 0x36, 0x96, 0xba, + 0x52, 0xd9, 0xa9, 0xec, 0x52, 0xe5, 0x1d, 0x94, 0xfe, 0x1c, 0x46, 0x54, + 0xa6, 0x8e, 0x85, 0x47, 0xba, 0xeb, 0x4b, 0x8d, 0x57, 0xe4, 0x34, 0x24, + 0x9e, 0x80, 0xb5, 0xc9, 0xa9, 0x94, 0x1d, 0xe4, 0x18, 0xb6, 0x07, 0x1e, + 0xfa, 0xe0, 0x1c, 0x88, 0x06, 0x84, 0xaa, 0xcb, 0x5e, 0xfa, 0x15, 0x5a, + 0xdd, 0x10, 0x43, 0x81, 0xf2, 0x50, 0x3e, 0x93, 0x26, 0x77, 0x1c, 0x77, + 0xe9, 0x0c, 0xfc, 0x5f, 0xdd, 0x67, 0x31, 0x02, 0xc6, 0xdd, 0xf4, 0x30, + 0x76, 0x51, 0xce, 0x56, 0xba, 0x7f, 0x44, 0xbd, 0x42, 0x9f, 0x10, 0x8c, + 0x56, 0x49, 0x48, 0xa2, 0xcb, 0xc4, 0xdd, 0x29, 0xae, 0xf0, 0x33, 0x35, + 0x46, 0x69, 0x1d, 0xae, 0xde, 0xde, 0x98, 0x82, 0x79, 0xa6, 0x50, 0x28, + 0xb3, 0x5f, 0x10, 0x24, 0x63, 0xee, 0x9a, 0x22, 0xbe, 0xf8, 0x3a, 0xf4, + 0xab, 0x98, 0xfe, 0xdf, 0x30, 0x03, 0xe8, 0x45, 0x8c, 0xf4, 0x85, 0xc6, + 0x98, 0x7b, 0x35, 0xb8, 0x30, 0x9c, 0x15, 0xa6, 0x45, 0xbd, 0x39, 0x84, + 0xe7, 0x43, 0x4b, 0x05, 0xa4, 0x8f, 0x52, 0x8e, 0x4a, 0xe4, 0x87, 0xc1, + 0xdc, 0xdf, 0x25, 0x9c, 0x5c, 0x37, 0xd0, 0x66, 0x12, 0x41, 0x66, 0x8c, + 0x28, 0xd0, 0x3f, 0x5c, 0x7f, 0x15, 0x9b, 0xcf, 0xa0, 0xae, 0x29, 0x33, + 0xb0, 0xe4, 0xb7, 0x36, 0x2a, 0x45, 0x83, 0xff, 0x86, 0x75, 0xcf, 0xa7, + 0x4d, 0x5c, 0xa8, 0xcf, 0x3f, 0xf2, 0xc8, 0xde, 0xdd, 0xad, 0x42, 0x8f, + 0x0e, 0xd0, 0x11, 0x24, 0x42, 0x86, 0x51, 0x52, 0x76, 0x21, 0x68, 0xf1, + 0xa7, 0x8f, 0xdb, 0x5b, 0x78, 0xfa, 0x44, 0x5f, 0xee, 0x31, 0xda, 0x62, + 0x5f, 0xfe, 0x69, 0xae, 0x97, 0xc9, 0xb5, 0x04, 0x76, 0x79, 0x2e, 0xb9, + 0xd9, 0x1b, 0xdd, 0xb7, 0xc4, 0x12, 0x78, 0xb2, 0x4d, 0xab, 0xd2, 0x29, + 0x25, 0x8c, 0xd5, 0x52, 0x4a, 0xd7, 0x2e, 0x18, 0x9d, 0xa2, 0xee, 0x7b, + 0xa5, 0xe5, 0x35, 0x3c, 0xb5, 0x54, 0x1c, 0x7f, 0x87, 0x4b, 0xc0, 0xbb, + 0x1a, 0x85, 0x19, 0xc0, 0xa9, 0x2b, 0x4d, 0xed, 0x71, 0xc0, 0x15, 0xb3, + 0x49, 0x2c, 0x46, 0xfc, 0x37, 0x40, 0xc0, 0x60, 0xd0, 0x00, 0x96, 0xfa, + 0x7f, 0xbb, 0x30, 0x94, 0x6b, 0x81, 0x61, 0xc5, 0x13, 0x93, 0x95, 0xaa, + 0xf3, 0x8d, 0x1d, 0xac, 0xdb, 0xbd, 0xc3, 0x90, 0xf3, 0xd2, 0x5f, 0x3a, + 0x08, 0xb1, 0xc9, 0x3a, 0xe8, 0x25, 0x4d, 0x20, 0x2a, 0xe9, 0x4c, 0xaf, + 0x9b, 0x54, 0x7b, 0xaf, 0x89, 0x44, 0x3a, 0x60, 0x23, 0xd3, 0x02, 0xb1, + 0xb3, 0x9a, 0x3a, 0xb0, 0xa0, 0xdb, 0x61, 0x0b, 0xac, 0x55, 0xa1, 0x36, + 0x55, 0x5b, 0xc4, 0xc5, 0xbd, 0x2a, 0x16, 0xe9, 0xe7, 0x86, 0x7f, 0xdb, + 0xee, 0x90, 0xfa, 0xfd, 0x08, 0x7f, 0x1a, 0x43, 0xe0, 0xb8, 0x21, 0xb3, + 0xe3, 0xdf, 0x27, 0x56, 0x61, 0xc4, 0xe8, 0xd5, 0x60, 0xe9, 0x6d, 0x49, + 0xd9, 0xa8, 0xf5, 0xd9, 0xfc, 0x66, 0x82, 0xe9, 0x80, 0x5b, 0x85, 0x16, + 0x55, 0x2b, 0xef, 0x50, 0x90, 0x6c, 0x5d, 0x81, 0x00, 0x00, 0x88, 0x9b, + 0xb4, 0x62, 0x49, 0x46, 0x2e, 0x5d, 0x71, 0x95, 0xff, 0x63, 0xfb, 0x93, + 0x23, 0xf8, 0x9f, 0xa2, 0x55, 0x56, 0xd4, 0xd5, 0xf7, 0xae, 0xaf, 0xd3, + 0xf6, 0x82, 0xc8, 0xdd, 0x89, 0x0f, 0x7e, 0x89, 0x0d, 0x0d, 0x7f, 0x4f, + 0x84, 0xa7, 0x16, 0xe8, 0xaf, 0xf2, 0x95, 0xd7, 0xc3, 0x66, 0xd6, 0x85, + 0x5b, 0xa1, 0xbb, 0xea, 0x31, 0x02, 0xac, 0xa2, 0x7b, 0x50, 0xf4, 0x78, + 0x29, 0x49, 0x59, 0xf6, 0x41, 0x42, 0x52, 0xa8, 0x19, 0xfb, 0x3d, 0xda, + 0xa9, 0x8d, 0xac, 0xe1, 0x25, 0xd4, 0x12, 0x1e, 0x2b, 0x48, 0x44, 0xb0, + 0xf6, 0x29, 0xd0, 0x55, 0x22, 0xb4, 0xe7, 0xbc, 0x22, 0x97, 0x1f, 0xe2, + 0xe1, 0x73, 0x16, 0x13, 0x7a, 0x00, 0x62, 0x14, 0xcb, 0x25, 0x9b, 0x21, + 0x98, 0x9d, 0xb8, 0xd8, 0xf4, 0x65, 0xf6, 0x8f, 0x39, 0xe4, 0x76, 0xf7, + 0x30, 0xaf, 0xbc, 0x3a, 0xfe, 0x0e, 0xf1, 0x81, 0xa7, 0xff, 0x4d, 0xa7, + 0xff, 0xbf, 0x15, 0x60, 0x0b, 0xcd, 0x69, 0xd5, 0x77, 0xba, 0xcb, 0x7b, + 0x5a, 0xfb, 0x34, 0xc7, 0x5d, 0x13, 0x33, 0xd7, 0x86, 0x02, 0x43, 0x57, + 0x52, 0x2c, 0x74, 0x61, 0x21, 0xa3, 0x34, 0xf5, 0x89, 0x51, 0x44, 0x89, + 0xfc, 0xbb, 0x57, 0x5c, 0x6d, 0xb0, 0x2e, 0x8c, 0xff, 0x73, 0xe5, 0x09, + 0x13, 0x3b, 0x45, 0x5b, 0x27, 0x88, 0xee, 0x9b, 0xab, 0x57, 0x7c, 0x9b, + 0xb9, 0x78, 0x73, 0xd2, 0x2d, 0x98, 0x6f, 0xd2, 0x78, 0xb3, 0xeb, 0xaa, + 0x18, 0x44, 0x87, 0x6d, 0x51, 0x1e, 0x9b, 0x73, 0xaa, 0x91, 0x1a, 0x4f, + 0x69, 0x78, 0xef, 0x3f, 0xb1, 0x2d, 0x39, 0x3e, 0xda, 0x31, 0xfc, 0x99, + 0xf6, 0xa2, 0x8c, 0xe5, 0xfd, 0x97, 0x95, 0x77, 0x37, 0xef, 0xf5, 0xd1, + 0xc8, 0x74, 0x2c, 0x9a, 0x1f, 0x23, 0x8f, 0x72, 0x96, 0x3d, 0xb5, 0xad, + 0x28, 0xa0, 0x6c, 0x66, 0xe8, 0xee, 0xaa, 0x9d, 0xc2, 0x8a, 0x56, 0x54, + 0x89, 0x74, 0x56, 0xdc, 0x57, 0x49, 0xc3, 0x8e, 0xb9, 0x3a, 0x91, 0x34, + 0xc4, 0x5e, 0x0b, 0x13, 0x63, 0x5e, 0xeb, 0xc5, 0xef, 0xc7, 0xe9, 0x7f, + 0x27, 0xe8, 0xe7, 0xe5, 0x0d, 0x83, 0x95, 0x5f, 0x8a, 0xf2, 0xb2, 0x22, + 0x03, 0x8d, 0x71, 0x4f, 0x62, 0xb7, 0xf1, 0x87, 0xf5, 0x3f, 0xc4, 0x23, + 0x21, 0x40, 0x35, 0xcf, 0x79, 0x7a, 0x5b, 0x9d, 0x76, 0xb2, 0xdc, 0x6a, + 0xb5, 0x1d, 0x8b, 0xb6, 0x9a, 0x19, 0xe4, 0x87, 0xf5, 0xce, 0x38, 0xf3, + 0x70, 0xbf, 0x9e, 0x86, 0xa6, 0x07, 0x53, 0xdd, 0x5d, 0xc7, 0x72, 0x84, + 0x47, 0x38, 0xd0, 0xe2, 0xeb, 0x64, 0x4c, 0x3a, 0x1e, 0xf6, 0x56, 0x79, + 0x75, 0x75, 0x14, 0x5d, 0xe4, 0x1d, 0x9d, 0xbb, 0xe1, 0x35, 0x03, 0x5e, + 0x4f, 0x8f, 0xea, 0x95, 0xde, 0x19, 0x57, 0x98, 0xe9, 0x2c, 0x42, 0x22, + 0xcb, 0x0f, 0x15, 0x7a, 0x6b, 0x53, 0xc3, 0xec, 0xdc, 0xa0, 0x66, 0x26, + 0x91, 0x04, 0x83, 0x75, 0x09, 0x0c, 0x22, 0x05, 0xec, 0x3a, 0x2d, 0x39, + 0xea, 0x19, 0xf2, 0x1d, 0xdb, 0xba, 0x5c, 0x46, 0x47, 0xd4, 0x94, 0x6d, + 0x51, 0xdb, 0x68, 0xde, 0x0c, 0xa0, 0x36, 0x8f, 0xbc, 0xfd, 0x9b, 0x8f, + 0xfe, 0x04, 0x1f, 0xde, 0x1e, 0x77, 0xb5, 0x80, 0xb9, 0x9c, 0x1b, 0x24, + 0x61, 0xfc, 0x2b, 0xc0, 0x42, 0x2b, 0xc5, 0x90, 0x58, 0xa2, 0xb1, 0x38, + 0x58, 0xf2, 0x8b, 0x65, 0xbf, 0xe8, 0xe6, 0x79, 0xcf, 0x65, 0x35, 0xa5, + 0xe1, 0xb7, 0x8b, 0x95, 0x54, 0xd7, 0x1d, 0xf0, 0x91, 0x18, 0xc0, 0x5d, + 0x2c, 0xb5, 0xca, 0x1a, 0x7f, 0x8d, 0xfb, 0x9e, 0x57, 0x1c, 0x5c, 0xf0, + 0x94, 0x36, 0x51, 0x95, 0x27, 0x62, 0xca, 0x92, 0x96, 0xe5, 0x00, 0x2e, + 0xa4, 0x41, 0x97, 0xbf, 0x28, 0x3c, 0x6d, 0xc1, 0xb7, 0xe9, 0x1c, 0x2e, + 0x3e, 0xe0, 0x5e, 0x89, 0x0c, 0x78, 0x88, 0x80, 0xb8, 0x30, 0xd2, 0x22, + 0xf9, 0x71, 0xb4, 0xc8, 0xee, 0xe6, 0x80, 0x04, 0x04, 0x9a, 0xfb, 0x0c, + 0x36, 0xcb, 0xea, 0x66, 0xf9, 0x52, 0x8c, 0x66, 0xbf, 0x4c, 0x0f, 0xf4, + 0xf8, 0x1e, 0x7e, 0x39, 0x80, 0xe8, 0x82, 0x4b, 0x0e, 0x66, 0x1d, 0x51, + 0x16, 0xa9, 0x8d, 0xd6, 0xea, 0x33, 0xb0, 0x2c, 0x36, 0x25, 0xf5, 0x01, + 0x30, 0x7e, 0x03, 0x7f, 0xae, 0x8e, 0xd6, 0x25, 0x62, 0x6d, 0x99, 0x8c, + 0x1f, 0xc1, 0x22, 0xf0, 0x94, 0x80, 0xbf, 0x82, 0x51, 0xea, 0xc2, 0x5a, + 0x3c, 0x85, 0x2a, 0x5d, 0xbe, 0xae, 0xe1, 0xe3, 0x07, 0x92, 0xd2, 0x40, + 0x47, 0xe8, 0x0f, 0x1a, 0xa5, 0x73, 0x64, 0x26, 0xc4, 0xac, 0xca, 0xc2, + 0x83, 0x5a, 0x56, 0xbc, 0x81, 0x21, 0xcb, 0x72, 0xf3, 0xe7, 0x82, 0x1e, + 0xc8, 0x54, 0x18, 0x42, 0xfe, 0xd6, 0xfc, 0x96, 0x0e, 0x03, 0x29, 0x98, + 0x4f, 0xd1, 0xd2, 0x98, 0x7c, 0x9e, 0x4e, 0x1a, 0x0f, 0xd6, 0x4e, 0xa4, + 0x52, 0x1b, 0xd1, 0xd8, 0x36, 0xf7, 0x47, 0x5f, 0xce, 0xcb, 0x87, 0x36, + 0xc8, 0x9b, 0x44, 0xc6, 0x7a, 0xf3, 0x45, 0x28, 0xae, 0x96, 0x5a, 0x85, + 0x62, 0x8b, 0x10, 0xc2, 0x7b, 0x39, 0x51, 0xdf, 0xf4, 0x21, 0xc2, 0x6b, + 0x6f, 0x93, 0x27, 0xed, 0xf6, 0xea, 0xff, 0x2a, 0x21, 0x70, 0x84, 0x4e, + 0x21, 0xac, 0xbc, 0x06, 0x41, 0xd3, 0x59, 0xa0, 0xa1, 0x50, 0xa6, 0x87, + 0xa2, 0x48, 0xad, 0x94, 0x44, 0x8d, 0x2f, 0xa8, 0xc6, 0x10, 0xb5, 0xeb, + 0x66, 0x82, 0x94, 0x5f, 0xae, 0x6a, 0x56, 0xb4, 0x8d, 0xf4, 0x62, 0x80, + 0xe4, 0x42, 0xc4, 0xbc, 0xe7, 0xee, 0xa6, 0x96, 0x3b, 0xfd, 0xc0, 0x92, + 0x7d, 0xcd, 0xe7, 0x0c, 0x99, 0x9a, 0xb6, 0x83, 0xcf, 0x45, 0xe5, 0x74, + 0xb3, 0xbc, 0xc0, 0x40, 0xad, 0x4d, 0xfc, 0xa7, 0x92, 0x35, 0x13, 0x81, + 0x5c, 0x9c, 0x21, 0x00, 0xa4, 0x37, 0x07, 0x1d, 0x19, 0xfc, 0x88, 0x4d, + 0x71, 0x43, 0x7d, 0x94, 0xf7, 0x32, 0xb8, 0x4b, 0x8a, 0x54, 0xd6, 0xe4, + 0x37, 0x4f, 0x27, 0x1f, 0xfd, 0x45, 0x83, 0xb9, 0x14, 0x5a, 0xf7, 0x36, + 0xdc, 0x98, 0xad, 0x99, 0xb9, 0x38, 0x69, 0xac, 0x18, 0x7e, 0x47, 0xd0, + 0x63, 0x27, 0xba, 0xe7, 0xd5, 0x1d, 0x7b, 0x6e, 0xde, 0x28, 0x7b, 0xf1, + 0x84, 0x4d, 0x2d, 0x7c, 0x16, 0x38, 0x4b, 0x16, 0xa9, 0x10, 0x83, 0xfb, + 0xe0, 0xe0, 0x6f, 0xdd, 0x03, 0x0a, 0xb8, 0x81, 0xf5, 0x8c, 0x98, 0xc3, + 0xf4, 0xc8, 0x31, 0x3a, 0xed, 0x14, 0x83, 0x89, 0xc3, 0x0e, 0xf7, 0xba, + 0x84, 0xb0, 0x49, 0xdf, 0xc6, 0x6b, 0xed, 0xbe, 0xd4, 0xa3, 0x83, 0x3a, + 0xe6, 0x6d, 0xa3, 0x83, 0x17, 0x43, 0x5e, 0x3a, 0x83, 0xda, 0x81, 0xe3, + 0x26, 0x95, 0x6b, 0xe5, 0x30, 0x28, 0x6d, 0xec, 0xd7, 0xd7, 0x35, 0xfa, + 0x1a, 0xad, 0x86, 0x04, 0x05, 0x2c, 0x76, 0x3f, 0xb2, 0x83, 0x92, 0x4e, + 0xef, 0x05, 0xde, 0x13, 0x26, 0x68, 0x80, 0x57, 0xee, 0x92, 0x80, 0xa3, + 0x99, 0xb4, 0xac, 0x98, 0x31, 0xd4, 0xf3, 0xe2, 0x60, 0xd9, 0xb9, 0x8d, + 0x20, 0xf7, 0x97, 0x70, 0x10, 0xd6, 0xba, 0x86, 0xb8, 0x9c, 0xb8, 0xf8, + 0x49, 0x71, 0x28, 0x9d, 0x05, 0x38, 0x1f, 0x63, 0xba, 0xf7, 0x15, 0x60, + 0x96, 0x61, 0x84, 0x68, 0xeb, 0x5d, 0x28, 0x51, 0xe3, 0x51, 0xdd, 0x69, + 0x8a, 0xdd, 0xba, 0xec, 0xbd, 0xd3, 0xa1, 0x42, 0x83, 0x59, 0x77, 0x11, + 0x12, 0x86, 0x5b, 0x8d, 0x30, 0xcf, 0xdf, 0x6f, 0xea, 0x9d, 0x31, 0xa2, + 0x65, 0xa5, 0x61, 0xc0, 0xde, 0x52, 0x6c, 0x72, 0x71, 0x0b, 0x4c, 0x7a, + 0x4c, 0x9f, 0x75, 0x74, 0x38, 0xc8, 0xdd, 0x12, 0xba, 0x21, 0x57, 0x1b, + 0x45, 0xb3, 0x02, 0x1d, 0x67, 0x22, 0x66, 0x53, 0x18, 0x48, 0xed, 0x60, + 0x40, 0x55, 0xd1, 0x25, 0x3b, 0xbc, 0x08, 0x7b, 0x19, 0x8a, 0x30, 0x5b, + 0x02, 0x4f, 0x65, 0x42, 0xff, 0xce, 0x87, 0xe8, 0x97, 0x2b, 0xbb, 0xfe, + 0x52, 0x52, 0x72, 0xe8, 0xb5, 0x77, 0xb7, 0x8e, 0x94, 0x34, 0xbc, 0x46, + 0xf1, 0xe1, 0x94, 0x98, 0x19, 0xbe, 0x7c, 0x3f, 0xf6, 0x0e, 0xe4, 0xbb, + 0x88, 0x32, 0x07, 0x83, 0x64, 0xad, 0xd7, 0xd1, 0xe8, 0x35, 0x8d, 0x5d, + 0x70, 0x16, 0xc8, 0x11, 0x94, 0x39, 0xc9, 0xac, 0xd6, 0xed, 0x6b, 0xdf, + 0xc8, 0xf3, 0x1d, 0x5e, 0x37, 0xd8, 0xb5, 0x86, 0x9b, 0xc2, 0xdc, 0x3c, + 0x5c, 0x04, 0x52, 0x5c, 0x11, 0x88, 0x0a, 0x2b, 0x78, 0x48, 0x9e, 0x5e, + 0x98, 0x57, 0x5a, 0xd1, 0x77, 0x1c, 0x7d, 0x5f, 0x60, 0xbb, 0x61, 0x7e, + 0x7e, 0x2a, 0xaf, 0x44, 0x14, 0x88, 0xfc, 0xa5, 0x31, 0xb7, 0xd4, 0x44, + 0x48, 0xda, 0xb5, 0x71, 0xa8, 0xd8, 0x4f, 0x79, 0xcd, 0xe4, 0xbe, 0xb6, + 0x1a, 0x61, 0x74, 0x4b, 0xd8, 0xec, 0xd7, 0xbf, 0xad, 0x57, 0x00, 0x42, + 0x04, 0xe8, 0xb3, 0xec, 0x47, 0x1d, 0x2a, 0x0a, 0xde, 0x7c, 0x6e, 0x5e, + 0xf8, 0xaa, 0x44, 0x05, 0x10, 0xab, 0xe9, 0x4e, 0xd7, 0x44, 0x0b, 0x97, + 0x6f, 0x1a, 0xc1, 0x59, 0x2b, 0xe4, 0xe1, 0x8a, 0x13, 0x82, 0x65, 0xd8, + 0xae, 0x5f, 0x2b, 0xbc, 0xa6, 0x14, 0x39, 0xaf, 0x38, 0x41, 0x26, 0x74, + 0xdb, 0x55, 0x6b, 0xe2, 0x21, 0x80, 0x5d, 0x20, 0xc3, 0xf5, 0x82, 0xee, + 0xcc, 0x3c, 0xc9, 0xb4, 0xeb, 0x52, 0xe9, 0x13, 0x8a, 0xea, 0xc6, 0x19, + 0x70, 0x37, 0x1b, 0xb8, 0x2e, 0x86, 0xa2, 0xe9, 0x9d, 0xb6, 0xd5, 0xd6, + 0xf3, 0xa8, 0x31, 0xf3, 0x02, 0xaa, 0x10, 0x33, 0x3f, 0xba, 0xf8, 0xf9, + 0x46, 0x5b, 0xe1, 0xd7, 0x34, 0x9f, 0x94, 0xcb, 0xfb, 0xb1, 0x3d, 0x60, + 0x77, 0x85, 0x14, 0xd4, 0xcf, 0x55, 0x60, 0x5d, 0x47, 0x6c, 0x07, 0xb4, + 0xc7, 0x73, 0xbd, 0x49, 0xbd, 0xa5, 0x31, 0xa1, 0xfa, 0x34, 0x3a, 0x8b, + 0x77, 0x1b, 0xaa, 0xaf, 0xa5, 0x87, 0x12, 0x4e, 0x36, 0x06, 0x14, 0xe7, + 0xb3, 0xb8, 0x87, 0x6c, 0x4b, 0x50, 0xc9, 0x52, 0x1b, 0x19, 0x48, 0x69, + 0x5b, 0x7f, 0xd8, 0xc9, 0x14, 0xb8, 0x11, 0xa0, 0x51, 0x09, 0xbd, 0x42, + 0x5a, 0x50, 0x32, 0x57, 0x69, 0x39, 0x30, 0xdb, 0xbf, 0x8b, 0x93, 0x54, + 0x43, 0x80, 0x4e, 0xd0, 0xc6, 0xf2, 0x81, 0x15, 0x6d, 0xef, 0x5a, 0xb6, + 0x4d, 0x70, 0x93, 0x88, 0x8d, 0xce, 0x0d, 0xb8, 0xe9, 0xac, 0xa2, 0xcd, + 0xc7, 0x18, 0xa5, 0x95, 0xb7, 0xf6, 0x0c, 0x6f, 0xe1, 0x10, 0x7b, 0x22, + 0xf8, 0x81, 0x18, 0x42, 0x6a, 0x09, 0x75, 0x20, 0xb4, 0x2f, 0x67, 0x7a, + 0xda, 0x55, 0x28, 0xc3, 0x81, 0xf7, 0xc1, 0xf0, 0xe6, 0x1b, 0x29, 0x9c, + 0x72, 0x87, 0xe5, 0x4c, 0xa9, 0x5b, 0x5b, 0x62, 0xb5, 0xb7, 0x1e, 0x82, + 0xc3, 0x7b, 0xaf, 0xe9, 0x6f, 0x37, 0x31, 0x9f, 0x79, 0xe7, 0x4f, 0x06, + 0x1e, 0xff, 0xff, 0x80, 0x8e, 0x00, 0x00 +}; - fd = os_open(fname, OS_O_RDONLY); - ut_assert(fd >= 0); - ut_asserteq(512, os_read(fd, header, 512)); - text_ctx.fd = fd; +int do_spl_test_load(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type, struct spl_image_loader *loader, + int (*write_image)(struct unit_test_state *, void *, size_t)) +{ + size_t img_size, img_data, plain_size = SPL_TEST_DATA_SIZE; + struct spl_image_info info_write = { + .name = test_name, + .size = type == LEGACY_LZMA ? sizeof(lzma_compressed) : + plain_size, + }, info_read = { }; + struct spl_boot_device bootdev = { + .boot_device = loader->boot_device, + }; + char *data, *plain; + void *img; + + img_size = create_image(NULL, type, &info_write, &img_data); + ut_assert(img_size); + img = calloc(img_size, 1); + ut_assertnonnull(img); + + data = img + img_data; + if (type == LEGACY_LZMA) { + plain = malloc(plain_size); + ut_assertnonnull(plain); + generate_data(plain, plain_size, "lzma"); + memcpy(data, lzma_compressed, sizeof(lzma_compressed)); + } else { + plain = data; + generate_data(plain, plain_size, test_name); + } + ut_asserteq(img_size, create_image(img, type, &info_write, NULL)); - load.priv = &text_ctx; + if (write_image(uts, img, img_size)) + return CMD_RET_FAILURE; - ut_assertok(spl_load_simple_fit(&image, &load, 0, header)); + ut_assertok(loader->load_image(&info_read, &bootdev)); + if (check_image_info(uts, &info_write, &info_read)) + return CMD_RET_FAILURE; + if (type == LEGACY_LZMA) + ut_asserteq(plain_size, info_read.size); + ut_asserteq_mem(plain, phys_to_virt(info_write.load_addr), plain_size); + if (type == LEGACY_LZMA) + free(plain); + free(img); return 0; } -SPL_TEST(spl_test_load, 0); diff --git a/test/image/spl_load_fs.c b/test/image/spl_load_fs.c new file mode 100644 index 00000000000..297ab08a820 --- /dev/null +++ b/test/image/spl_load_fs.c @@ -0,0 +1,428 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com> + */ + +#include <common.h> +#include <blk.h> +#include <ext_common.h> +#include <ext4fs.h> +#include <fat.h> +#include <fs.h> +#include <memalign.h> +#include <spl.h> +#include <asm/io.h> +#include <linux/stat.h> +#include <test/spl.h> +#include <test/ut.h> + +/** + * create_ext2() - Create an "ext2" filesystem with a single file + * @dst: The location of the new filesystem; MUST be zeroed + * @size: The size of the file + * @filename: The name of the file + * @data_offset: Filled with the offset of the file data from @dst + * + * Budget mke2fs. We use 1k blocks (to reduce overhead) with a single block + * group, which limits us to 8M of data. Almost every feature which increases + * complexity (checksums, hash tree directories, etc.) is disabled. We do cheat + * a little and use extents from ext4 to save having to deal with indirects, but + * U-Boot doesn't care. + * + * If @dst is %NULL, nothing is copied. + * + * Return: The size of the filesystem in bytes + */ +static size_t create_ext2(void *dst, size_t size, const char *filename, + size_t *data_offset) +{ + u32 super_block = 1; + u32 group_block = 2; + u32 block_bitmap_block = 3; + u32 inode_bitmap_block = 4; + u32 inode_table_block = 5; + u32 root_block = 6; + u32 file_block = 7; + + u32 root_ino = EXT2_ROOT_INO; + u32 file_ino = EXT2_BOOT_LOADER_INO; + + u32 block_size = EXT2_MIN_BLOCK_SIZE; + u32 inode_size = sizeof(struct ext2_inode); + + u32 file_blocks = (size + block_size - 1) / block_size; + u32 blocks = file_block + file_blocks; + u32 inodes = block_size / inode_size; + u32 filename_len = strlen(filename); + u32 dirent_len = ALIGN(filename_len, sizeof(struct ext2_dirent)) + + sizeof(struct ext2_dirent); + + struct ext2_sblock *sblock = dst + super_block * block_size; + struct ext2_block_group *bg = dst + group_block * block_size; + struct ext2_inode *inode_table = dst + inode_table_block * block_size; + struct ext2_inode *root_inode = &inode_table[root_ino - 1]; + struct ext2_inode *file_inode = &inode_table[file_ino - 1]; + struct ext4_extent_header *ext_block = (void *)&file_inode->b; + struct ext4_extent *extent = (void *)(ext_block + 1); + struct ext2_dirent *dot = dst + root_block * block_size; + struct ext2_dirent *dotdot = dot + 2; + struct ext2_dirent *dirent = dotdot + 2; + struct ext2_dirent *last = ((void *)dirent) + dirent_len; + + /* Make sure we fit in one block group */ + if (blocks > block_size * 8) + return 0; + + if (filename_len > EXT2_NAME_LEN) + return 0; + + if (data_offset) + *data_offset = file_block * block_size; + + if (!dst) + goto out; + + sblock->total_inodes = cpu_to_le32(inodes); + sblock->total_blocks = cpu_to_le32(blocks); + sblock->first_data_block = cpu_to_le32(super_block); + sblock->blocks_per_group = cpu_to_le32(blocks); + sblock->fragments_per_group = cpu_to_le32(blocks); + sblock->inodes_per_group = cpu_to_le32(inodes); + sblock->magic = cpu_to_le16(EXT2_MAGIC); + /* Done mostly so we can pretend to be (in)compatible */ + sblock->revision_level = cpu_to_le32(EXT2_DYNAMIC_REV); + /* Not really accurate but it doesn't matter */ + sblock->first_inode = cpu_to_le32(EXT2_GOOD_OLD_FIRST_INO); + sblock->inode_size = cpu_to_le32(inode_size); + sblock->feature_incompat = cpu_to_le32(EXT4_FEATURE_INCOMPAT_EXTENTS); + + bg->block_id = cpu_to_le32(block_bitmap_block); + bg->inode_id = cpu_to_le32(inode_bitmap_block); + bg->inode_table_id = cpu_to_le32(inode_table_block); + + /* + * All blocks/inodes are in-use. I don't want to have to deal with + * endianness, so just fill everything in. + */ + memset(dst + block_bitmap_block * block_size, 0xff, block_size * 2); + + root_inode->mode = cpu_to_le16(S_IFDIR | 0755); + root_inode->size = cpu_to_le32(block_size); + root_inode->nlinks = cpu_to_le16(3); + root_inode->blockcnt = cpu_to_le32(1); + root_inode->flags = cpu_to_le32(EXT4_TOPDIR_FL); + root_inode->b.blocks.dir_blocks[0] = root_block; + + file_inode->mode = cpu_to_le16(S_IFREG | 0644); + file_inode->size = cpu_to_le32(size); + file_inode->nlinks = cpu_to_le16(1); + file_inode->blockcnt = cpu_to_le32(file_blocks); + file_inode->flags = cpu_to_le32(EXT4_EXTENTS_FL); + ext_block->eh_magic = cpu_to_le16(EXT4_EXT_MAGIC); + ext_block->eh_entries = cpu_to_le16(1); + ext_block->eh_max = cpu_to_le16(sizeof(file_inode->b) / + sizeof(*ext_block) - 1); + extent->ee_len = cpu_to_le16(file_blocks); + extent->ee_start_lo = cpu_to_le16(file_block); + + /* I'm not sure we need these, but it can't hurt */ + dot->inode = cpu_to_le32(root_ino); + dot->direntlen = cpu_to_le16(2 * sizeof(*dot)); + dot->namelen = 1; + dot->filetype = FILETYPE_DIRECTORY; + memcpy(dot + 1, ".", dot->namelen); + + dotdot->inode = cpu_to_le32(root_ino); + dotdot->direntlen = cpu_to_le16(2 * sizeof(*dotdot)); + dotdot->namelen = 2; + dotdot->filetype = FILETYPE_DIRECTORY; + memcpy(dotdot + 1, "..", dotdot->namelen); + + dirent->inode = cpu_to_le32(file_ino); + dirent->direntlen = cpu_to_le16(dirent_len); + dirent->namelen = filename_len; + dirent->filetype = FILETYPE_REG; + memcpy(dirent + 1, filename, filename_len); + + last->direntlen = block_size - dirent_len; + +out: + return (size_t)blocks * block_size; +} + +/** + * create_fat() - Create a FAT32 filesystem with a single file + * @dst: The location of the new filesystem; MUST be zeroed + * @size: The size of the file + * @filename: The name of the file + * @data_offset: Filled with the offset of the file data from @dst + * + * Budget mkfs.fat. We use FAT32 (so I don't have to deal with FAT12) with no + * info sector, and a single one-sector FAT. This limits us to 64k of data + * (enough for anyone). The filename must fit in 8.3. + * + * If @dst is %NULL, nothing is copied. + * + * Return: The size of the filesystem in bytes + */ +static size_t create_fat(void *dst, size_t size, const char *filename, + size_t *data_offset) +{ + u16 boot_sector = 0; + u16 fat_sector = 1; + u32 root_sector = 2; + u32 file_sector = 3; + + u16 sector_size = 512; + u32 file_sectors = (size + sector_size - 1) / sector_size; + u32 sectors = file_sector + file_sectors; + + char *ext; + size_t filename_len, ext_len; + int i; + + struct boot_sector *bs = dst + boot_sector * sector_size; + struct volume_info *vi = (void *)(bs + 1); + __le32 *fat = dst + fat_sector * sector_size; + struct dir_entry *dirent = dst + root_sector * sector_size; + + /* Make sure we fit in the FAT */ + if (sectors > sector_size / sizeof(u32)) + return 0; + + ext = strchr(filename, '.'); + if (ext) { + filename_len = ext - filename; + ext++; + ext_len = strlen(ext); + } else { + filename_len = strlen(filename); + ext_len = 0; + } + + if (filename_len > 8 || ext_len > 3) + return 0; + + if (data_offset) + *data_offset = file_sector * sector_size; + + if (!dst) + goto out; + + bs->sector_size[0] = sector_size & 0xff; + bs->sector_size[1] = sector_size >> 8; + bs->cluster_size = 1; + bs->reserved = cpu_to_le16(fat_sector); + bs->fats = 1; + bs->media = 0xf8; + bs->total_sect = cpu_to_le32(sectors); + bs->fat32_length = cpu_to_le32(1); + bs->root_cluster = cpu_to_le32(root_sector); + + vi->ext_boot_sign = 0x29; + memcpy(vi->fs_type, FAT32_SIGN, sizeof(vi->fs_type)); + + memcpy(dst + 0x1fe, "\x55\xAA", 2); + + fat[0] = cpu_to_le32(0x0ffffff8); + fat[1] = cpu_to_le32(0x0fffffff); + fat[2] = cpu_to_le32(0x0ffffff8); + for (i = file_sector; file_sectors > 1; file_sectors--, i++) + fat[i] = cpu_to_le32(i + 1); + fat[i] = cpu_to_le32(0x0ffffff8); + + for (i = 0; i < sizeof(dirent->nameext.name); i++) { + if (i < filename_len) + dirent->nameext.name[i] = toupper(filename[i]); + else + dirent->nameext.name[i] = ' '; + } + + for (i = 0; i < sizeof(dirent->nameext.ext); i++) { + if (i < ext_len) + dirent->nameext.ext[i] = toupper(ext[i]); + else + dirent->nameext.ext[i] = ' '; + } + + dirent->start = cpu_to_le16(file_sector); + dirent->size = cpu_to_le32(size); + +out: + return sectors * sector_size; +} + +typedef size_t (*create_fs_t)(void *, size_t, const char *, size_t *); + +static int spl_test_fs(struct unit_test_state *uts, const char *test_name, + create_fs_t create) +{ + const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME; + struct blk_desc *dev_desc; + char *data_write, *data_read; + void *fs; + size_t fs_size, fs_data, fs_blocks, data_size = SPL_TEST_DATA_SIZE; + loff_t actread; + + fs_size = create(NULL, data_size, filename, &fs_data); + ut_assert(fs_size); + fs = calloc(fs_size, 1); + ut_assertnonnull(fs); + + data_write = fs + fs_data; + generate_data(data_write, data_size, test_name); + ut_asserteq(fs_size, create(fs, data_size, filename, NULL)); + + dev_desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0); + ut_assertnonnull(dev_desc); + ut_asserteq(512, dev_desc->blksz); + fs_blocks = fs_size / dev_desc->blksz; + ut_asserteq(fs_blocks, blk_dwrite(dev_desc, 0, fs_blocks, fs)); + + /* We have to use malloc so we can call virt_to_phys */ + data_read = malloc_cache_aligned(data_size); + ut_assertnonnull(data_read); + ut_assertok(fs_set_blk_dev_with_part(dev_desc, 0)); + ut_assertok(fs_read("/" CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, + virt_to_phys(data_read), 0, data_size, &actread)); + ut_asserteq(data_size, actread); + ut_asserteq_mem(data_write, data_read, data_size); + + free(data_read); + free(fs); + return 0; +} + +static int spl_test_ext(struct unit_test_state *uts) +{ + return spl_test_fs(uts, __func__, create_ext2); +} +SPL_TEST(spl_test_ext, DM_FLAGS); + +static int spl_test_fat(struct unit_test_state *uts) +{ + spl_fat_force_reregister(); + return spl_test_fs(uts, __func__, create_fat); +} +SPL_TEST(spl_test_fat, DM_FLAGS); + +static bool spl_mmc_raw; + +u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device) +{ + return spl_mmc_raw ? MMCSD_MODE_RAW : MMCSD_MODE_FS; +} + +static int spl_test_mmc_fs(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type, create_fs_t create_fs, + bool blk_mode) +{ + const char *filename = CONFIG_SPL_FS_LOAD_PAYLOAD_NAME; + struct blk_desc *dev_desc; + size_t fs_size, fs_data, img_size, img_data, + data_size = SPL_TEST_DATA_SIZE; + struct spl_image_info info_write = { + .name = test_name, + .size = data_size, + }, info_read = { }; + struct disk_partition part = { + .start = 1, + .sys_ind = 0x83, + }; + struct spl_image_loader *loader = + SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_MMC1, spl_mmc_load_image); + struct spl_boot_device bootdev = { + .boot_device = loader->boot_device, + }; + void *fs; + char *data; + + img_size = create_image(NULL, type, &info_write, &img_data); + ut_assert(img_size); + fs_size = create_fs(NULL, img_size, filename, &fs_data); + ut_assert(fs_size); + fs = calloc(fs_size, 1); + ut_assertnonnull(fs); + + data = fs + fs_data + img_data; + generate_data(data, data_size, test_name); + ut_asserteq(img_size, create_image(fs + fs_data, type, &info_write, + NULL)); + ut_asserteq(fs_size, create_fs(fs, img_size, filename, NULL)); + + dev_desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0); + ut_assertnonnull(dev_desc); + + ut_asserteq(512, dev_desc->blksz); + part.size = fs_size / dev_desc->blksz; + ut_assertok(write_mbr_partitions(dev_desc, &part, 1, 0)); + ut_asserteq(part.size, blk_dwrite(dev_desc, part.start, part.size, fs)); + + spl_mmc_raw = false; + if (blk_mode) + ut_assertok(spl_blk_load_image(&info_read, &bootdev, UCLASS_MMC, + 0, 1)); + else + ut_assertok(loader->load_image(&info_read, &bootdev)); + if (check_image_info(uts, &info_write, &info_read)) + return CMD_RET_FAILURE; + ut_asserteq_mem(data, phys_to_virt(info_write.load_addr), data_size); + + free(fs); + return 0; +} + +static int spl_test_blk(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type) +{ + spl_fat_force_reregister(); + if (spl_test_mmc_fs(uts, test_name, type, create_fat, true)) + return CMD_RET_FAILURE; + + return spl_test_mmc_fs(uts, test_name, type, create_ext2, true); +} +SPL_IMG_TEST(spl_test_blk, LEGACY, DM_FLAGS); +SPL_IMG_TEST(spl_test_blk, FIT_EXTERNAL, DM_FLAGS); +SPL_IMG_TEST(spl_test_blk, FIT_INTERNAL, DM_FLAGS); + +static int spl_test_mmc_write_image(struct unit_test_state *uts, void *img, + size_t img_size) +{ + struct blk_desc *dev_desc; + size_t img_blocks; + + dev_desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0); + ut_assertnonnull(dev_desc); + + img_blocks = DIV_ROUND_UP(img_size, dev_desc->blksz); + ut_asserteq(img_blocks, blk_dwrite(dev_desc, + CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, + img_blocks, img)); + + spl_mmc_raw = true; + return 0; +} + +static int spl_test_mmc(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type) +{ + spl_mmc_clear_cache(); + spl_fat_force_reregister(); + + if (type == LEGACY && + spl_test_mmc_fs(uts, test_name, type, create_ext2, false)) + return CMD_RET_FAILURE; + + if (type != IMX8 && + spl_test_mmc_fs(uts, test_name, type, create_fat, false)) + return CMD_RET_FAILURE; + + return do_spl_test_load(uts, test_name, type, + SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_MMC1, + spl_mmc_load_image), + spl_test_mmc_write_image); +} +SPL_IMG_TEST(spl_test_mmc, LEGACY, DM_FLAGS); +SPL_IMG_TEST(spl_test_mmc, IMX8, DM_FLAGS); +SPL_IMG_TEST(spl_test_mmc, FIT_EXTERNAL, DM_FLAGS); +SPL_IMG_TEST(spl_test_mmc, FIT_INTERNAL, DM_FLAGS); diff --git a/test/image/spl_load_net.c b/test/image/spl_load_net.c new file mode 100644 index 00000000000..f570cef163f --- /dev/null +++ b/test/image/spl_load_net.c @@ -0,0 +1,252 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com> + */ + +#include <common.h> +#include <dm.h> +#include <spl.h> +#include <test/spl.h> +#include <asm/eth.h> +#include <test/ut.h> +#include "../../net/bootp.h" + +/* + * sandbox_eth_bootp_req_to_reply() + * + * Check if a BOOTP request was sent. If so, inject a reply + * + * returns 0 if injected, -EAGAIN if not + */ +static int sandbox_eth_bootp_req_to_reply(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct ethernet_hdr *eth = packet; + struct ip_udp_hdr *ip; + struct bootp_hdr *bp; + struct ethernet_hdr *eth_recv; + struct ip_udp_hdr *ipr; + struct bootp_hdr *bpr; + + if (ntohs(eth->et_protlen) != PROT_IP) + return -EAGAIN; + + ip = packet + ETHER_HDR_SIZE; + if (ip->ip_p != IPPROTO_UDP) + return -EAGAIN; + + if (ntohs(ip->udp_dst) != PORT_BOOTPS) + return -EAGAIN; + + bp = (void *)ip + IP_UDP_HDR_SIZE; + if (bp->bp_op != OP_BOOTREQUEST) + return -EAGAIN; + + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return 0; + + /* reply to the request */ + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; + memcpy(eth_recv, packet, len); + ipr = (void *)eth_recv + ETHER_HDR_SIZE; + bpr = (void *)ipr + IP_UDP_HDR_SIZE; + memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + ipr->ip_sum = 0; + ipr->ip_off = 0; + net_write_ip(&ipr->ip_dst, net_ip); + net_write_ip(&ipr->ip_src, priv->fake_host_ipaddr); + ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE); + ipr->udp_src = ip->udp_dst; + ipr->udp_dst = ip->udp_src; + + bpr->bp_op = OP_BOOTREPLY; + net_write_ip(&bpr->bp_yiaddr, net_ip); + net_write_ip(&bpr->bp_siaddr, priv->fake_host_ipaddr); + copy_filename(bpr->bp_file, CONFIG_BOOTFILE, sizeof(CONFIG_BOOTFILE)); + memset(&bpr->bp_vend, 0, sizeof(bpr->bp_vend)); + + priv->recv_packet_length[priv->recv_packets] = len; + ++priv->recv_packets; + + return 0; +} + +struct spl_test_net_priv { + struct unit_test_state *uts; + void *img; + size_t img_size; + u16 port; +}; + +/* Well known TFTP port # */ +#define TFTP_PORT 69 +/* Transaction ID, chosen at random */ +#define TFTP_TID 21313 + +/* + * TFTP operations. + */ +#define TFTP_RRQ 1 +#define TFTP_DATA 3 +#define TFTP_ACK 4 + +/* default TFTP block size */ +#define TFTP_BLOCK_SIZE 512 + +struct tftp_hdr { + u16 opcode; + u16 block; +}; + +#define TFTP_HDR_SIZE sizeof(struct tftp_hdr) + +/* + * sandbox_eth_tftp_req_to_reply() + * + * Check if a TFTP request was sent. If so, inject a reply. We don't support + * options, and we don't check for rollover, so we are limited files of less + * than 32M. + * + * returns 0 if injected, -EAGAIN if not + */ +static int sandbox_eth_tftp_req_to_reply(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + struct spl_test_net_priv *test_priv = priv->priv; + struct ethernet_hdr *eth = packet; + struct ip_udp_hdr *ip; + struct tftp_hdr *tftp; + struct ethernet_hdr *eth_recv; + struct ip_udp_hdr *ipr; + struct tftp_hdr *tftpr; + size_t size; + u16 block; + + if (ntohs(eth->et_protlen) != PROT_IP) + return -EAGAIN; + + ip = packet + ETHER_HDR_SIZE; + if (ip->ip_p != IPPROTO_UDP) + return -EAGAIN; + + if (ntohs(ip->udp_dst) == TFTP_PORT) { + tftp = (void *)ip + IP_UDP_HDR_SIZE; + if (htons(tftp->opcode) != TFTP_RRQ) + return -EAGAIN; + + block = 0; + } else if (ntohs(ip->udp_dst) == TFTP_TID) { + tftp = (void *)ip + IP_UDP_HDR_SIZE; + if (htons(tftp->opcode) != TFTP_ACK) + return -EAGAIN; + + block = htons(tftp->block); + } else { + return -EAGAIN; + } + + if (block * TFTP_BLOCK_SIZE > test_priv->img_size) + return 0; + + size = min(test_priv->img_size - block * TFTP_BLOCK_SIZE, + (size_t)TFTP_BLOCK_SIZE); + + /* Don't allow the buffer to overrun */ + if (priv->recv_packets >= PKTBUFSRX) + return 0; + + /* reply to the request */ + eth_recv = (void *)priv->recv_packet_buffer[priv->recv_packets]; + memcpy(eth_recv->et_dest, eth->et_src, ARP_HLEN); + memcpy(eth_recv->et_src, priv->fake_host_hwaddr, ARP_HLEN); + eth_recv->et_protlen = htons(PROT_IP); + + ipr = (void *)eth_recv + ETHER_HDR_SIZE; + ipr->ip_hl_v = 0x45; + ipr->ip_len = htons(IP_UDP_HDR_SIZE + TFTP_HDR_SIZE + size); + ipr->ip_off = htons(IP_FLAGS_DFRAG); + ipr->ip_ttl = 255; + ipr->ip_p = IPPROTO_UDP; + ipr->ip_sum = 0; + net_copy_ip(&ipr->ip_dst, &ip->ip_src); + net_copy_ip(&ipr->ip_src, &ip->ip_dst); + ipr->ip_sum = compute_ip_checksum(ipr, IP_HDR_SIZE); + + ipr->udp_src = htons(TFTP_TID); + ipr->udp_dst = ip->udp_src; + ipr->udp_len = htons(UDP_HDR_SIZE + TFTP_HDR_SIZE + size); + ipr->udp_xsum = 0; + + tftpr = (void *)ipr + IP_UDP_HDR_SIZE; + tftpr->opcode = htons(TFTP_DATA); + tftpr->block = htons(block + 1); + memcpy((void *)tftpr + TFTP_HDR_SIZE, + test_priv->img + block * TFTP_BLOCK_SIZE, size); + + priv->recv_packet_length[priv->recv_packets] = + ETHER_HDR_SIZE + IP_UDP_HDR_SIZE + TFTP_HDR_SIZE + size; + ++priv->recv_packets; + + return 0; +} + +static int spl_net_handler(struct udevice *dev, void *packet, + unsigned int len) +{ + struct eth_sandbox_priv *priv = dev_get_priv(dev); + int old_packets = priv->recv_packets; + + priv->fake_host_ipaddr = string_to_ip("1.1.2.4"); + net_ip = string_to_ip("1.1.2.2"); + + sandbox_eth_arp_req_to_reply(dev, packet, len); + sandbox_eth_bootp_req_to_reply(dev, packet, len); + sandbox_eth_tftp_req_to_reply(dev, packet, len); + + if (old_packets == priv->recv_packets) + return 0; + + return 0; +} + +static int spl_test_net_write_image(struct unit_test_state *uts, void *img, + size_t img_size) +{ + struct spl_test_net_priv *test_priv = malloc(sizeof(*test_priv)); + + ut_assertnonnull(test_priv); + test_priv->uts = uts; + test_priv->img = img; + test_priv->img_size = img_size; + + sandbox_eth_set_tx_handler(0, spl_net_handler); + sandbox_eth_set_priv(0, test_priv); + return 0; +} + +static int spl_test_net(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type) +{ + struct eth_sandbox_priv *priv; + struct udevice *dev; + int ret; + + net_server_ip = string_to_ip("1.1.2.4"); + ret = do_spl_test_load(uts, test_name, type, + SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_CPGMAC, + spl_net_load_image_cpgmac), + spl_test_net_write_image); + + sandbox_eth_set_tx_handler(0, NULL); + ut_assertok(uclass_get_device(UCLASS_ETH, 0, &dev)); + priv = dev_get_priv(dev); + free(priv->priv); + return ret; +} +SPL_IMG_TEST(spl_test_net, LEGACY, DM_FLAGS); +SPL_IMG_TEST(spl_test_net, FIT_INTERNAL, DM_FLAGS); +SPL_IMG_TEST(spl_test_net, FIT_EXTERNAL, DM_FLAGS); diff --git a/test/image/spl_load_nor.c b/test/image/spl_load_nor.c new file mode 100644 index 00000000000..a62bb60d253 --- /dev/null +++ b/test/image/spl_load_nor.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com> + */ + +#include <common.h> +#include <dm.h> +#include <spl.h> +#include <asm/io.h> +#include <test/spl.h> +#include <test/ut.h> + +static void *spl_test_nor_base; + +unsigned long spl_nor_get_uboot_base(void) +{ + return virt_to_phys(spl_test_nor_base); +} + +static int spl_test_nor_write_image(struct unit_test_state *uts, void *img, + size_t img_size) +{ + spl_test_nor_base = img; + return 0; +} + +static int spl_test_nor(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type) +{ + return do_spl_test_load(uts, test_name, type, + SPL_LOAD_IMAGE_GET(0, BOOT_DEVICE_NOR, + spl_nor_load_image), + spl_test_nor_write_image); +} +SPL_IMG_TEST(spl_test_nor, LEGACY, 0); +SPL_IMG_TEST(spl_test_nor, LEGACY_LZMA, 0); +SPL_IMG_TEST(spl_test_nor, IMX8, 0); +SPL_IMG_TEST(spl_test_nor, FIT_INTERNAL, 0); +SPL_IMG_TEST(spl_test_nor, FIT_EXTERNAL, 0); diff --git a/test/image/spl_load_os.c b/test/image/spl_load_os.c new file mode 100644 index 00000000000..49edf152d78 --- /dev/null +++ b/test/image/spl_load_os.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2021 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <image.h> +#include <os.h> +#include <spl.h> +#include <test/spl.h> +#include <test/ut.h> + +/* Context used for this test */ +struct text_ctx { + int fd; +}; + +static ulong read_fit_image(struct spl_load_info *load, ulong sector, + ulong count, void *buf) +{ + struct text_ctx *text_ctx = load->priv; + off_t offset, ret; + ssize_t res; + + offset = sector * load->bl_len; + ret = os_lseek(text_ctx->fd, offset, OS_SEEK_SET); + if (ret != offset) { + printf("Failed to seek to %zx, got %zx (errno=%d)\n", offset, + ret, errno); + return 0; + } + + res = os_read(text_ctx->fd, buf, count * load->bl_len); + if (res == -1) { + printf("Failed to read %lx bytes, got %ld (errno=%d)\n", + count * load->bl_len, res, errno); + return 0; + } + + return count; +} + +static int spl_test_load(struct unit_test_state *uts) +{ + struct spl_image_info image; + struct legacy_img_hdr *header; + struct text_ctx text_ctx; + struct spl_load_info load; + char fname[256]; + int ret; + int fd; + + memset(&load, '\0', sizeof(load)); + load.bl_len = 512; + load.read = read_fit_image; + + ret = sandbox_find_next_phase(fname, sizeof(fname), true); + if (ret) + ut_assertf(0, "%s not found, error %d\n", fname, ret); + load.filename = fname; + + header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); + + fd = os_open(fname, OS_O_RDONLY); + ut_assert(fd >= 0); + ut_asserteq(512, os_read(fd, header, 512)); + text_ctx.fd = fd; + + load.priv = &text_ctx; + + ut_assertok(spl_load_simple_fit(&image, &load, 0, header)); + + return 0; +} +SPL_TEST(spl_test_load, 0); diff --git a/test/image/spl_load_spi.c b/test/image/spl_load_spi.c new file mode 100644 index 00000000000..8f9b6e0139b --- /dev/null +++ b/test/image/spl_load_spi.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Sean Anderson <seanga2@gmail.com> + */ + +#include <common.h> +#include <dm.h> +#include <spi_flash.h> +#include <spl.h> +#include <test/spl.h> +#include <test/ut.h> + +static int spl_test_spi_write_image(struct unit_test_state *uts, void *img, + size_t img_size) +{ + struct spi_flash *flash; + + flash = spi_flash_probe(spl_spi_boot_bus(), spl_spi_boot_cs(), + CONFIG_SF_DEFAULT_SPEED, + CONFIG_SF_DEFAULT_MODE); + ut_assertnonnull(flash); + ut_assertok(spi_flash_write(flash, spl_spi_get_uboot_offs(flash), + img_size, img)); + + return 0; +} + +static int spl_test_spi(struct unit_test_state *uts, const char *test_name, + enum spl_test_image type) +{ + return do_spl_test_load(uts, test_name, type, + SPL_LOAD_IMAGE_GET(1, BOOT_DEVICE_SPI, + spl_spi_load_image), + spl_test_spi_write_image); +} +SPL_IMG_TEST(spl_test_spi, LEGACY, DM_FLAGS); +SPL_IMG_TEST(spl_test_spi, IMX8, DM_FLAGS); +SPL_IMG_TEST(spl_test_spi, FIT_INTERNAL, DM_FLAGS); +#if !IS_ENABLED(CONFIG_SPL_LOAD_FIT_FULL) +SPL_IMG_TEST(spl_test_spi, FIT_EXTERNAL, DM_FLAGS); +#endif diff --git a/test/py/tests/test_spl.py b/test/py/tests/test_spl.py index bd273dad893..42e4c4342b2 100644 --- a/test/py/tests/test_spl.py +++ b/test/py/tests/test_spl.py @@ -5,6 +5,16 @@ import os.path import pytest +@pytest.mark.buildconfigspec('spl_unit_test') +def test_ut_spl_init(u_boot_console): + """Initialize data for ut spl tests.""" + + fn = u_boot_console.config.source_dir + '/spi.bin' + if not os.path.exists(fn): + data = b'\x00' * (2 * 1024 * 1024) + with open(fn, 'wb') as fh: + fh.write(data) + def test_spl(u_boot_console, ut_spl_subtest): """Execute a "ut" subtest. diff --git a/test/test-main.c b/test/test-main.c index edb20bc4b9c..b7015d9f38d 100644 --- a/test/test-main.c +++ b/test/test-main.c @@ -303,7 +303,7 @@ static int test_pre_run(struct unit_test_state *uts, struct unit_test *test) if (test->flags & UT_TESTF_PROBE_TEST) ut_assertok(do_autoprobe(uts)); - if (!CONFIG_IS_ENABLED(OF_PLATDATA) && + if (CONFIG_IS_ENABLED(OF_REAL) && (test->flags & UT_TESTF_SCAN_FDT)) { /* * only set this if we know the ethernet uclass will be created |