diff options
79 files changed, 2053 insertions, 621 deletions
@@ -114,6 +114,15 @@ if EXPERT Warning: When disabling this, please check if malloc calls, maybe should be replaced by calloc - if one expects zeroed memory. + +config TOOLS_DEBUG + bool "Enable debug information for tools" + help + Enable generation of debug information for tools such as mkimage. + This can be used for debugging purposes. With debug information + it is possible to set breakpoints on particular lines, single-step + debug through the source code, etc. + endif endmenu # General setup @@ -313,6 +322,20 @@ config SPL_LOAD_FIT particular it can handle selecting from multiple device tree and passing the correct one to U-Boot. +config SPL_FIT_IMAGE_POST_PROCESS + bool "Enable post-processing of FIT artifacts after loading by the SPL" + depends on SPL_LOAD_FIT && TI_SECURE_DEVICE + help + Allows doing any sort of manipulation to blobs after they got extracted + from the U-Boot FIT image like stripping off headers or modifying the + size of the blob, verification, authentication, decryption etc. in a + platform or board specific way. In order to use this feature a platform + or board-specific implementation of board_fit_image_post_process() must + be provided. Also, anything done during this post-processing step would + need to be comprehended in how the images were prepared before being + injected into the FIT creation (i.e. the blobs would have been pre- + processed before being added to the FIT image). + config SYS_CLK_FREQ depends on ARC || ARCH_SUNXI int "CPU clock frequency" @@ -256,7 +256,8 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ HOSTCC = cc HOSTCXX = c++ -HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer +HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer \ + $(if $(CONFIG_TOOLS_DEBUG),-g) HOSTCXXFLAGS = -O2 ifeq ($(HOSTOS),cygwin) diff --git a/arch/Kconfig b/arch/Kconfig index c43787c639..92d4b97701 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -1,6 +1,9 @@ config CREATE_ARCH_SYMLINK bool +config HAVE_ARCH_IOREMAP + bool + choice prompt "Architecture select" default SANDBOX @@ -33,6 +36,7 @@ config MICROBLAZE config MIPS bool "MIPS architecture" + select HAVE_ARCH_IOREMAP select HAVE_PRIVATE_LIBGCC select SUPPORT_OF_CONTROL diff --git a/arch/arm/cpu/arm11/cpu.c b/arch/arm/cpu/arm11/cpu.c index 1e4c2142b1..7244c2e7d7 100644 --- a/arch/arm/cpu/arm11/cpu.c +++ b/arch/arm/cpu/arm11/cpu.c @@ -69,23 +69,6 @@ void flush_dcache_all(void) asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0)); } -static int check_cache_range(unsigned long start, unsigned long stop) -{ - int ok = 1; - - if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) - ok = 0; - - if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) - ok = 0; - - if (!ok) - debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n", - start, stop); - - return ok; -} - void invalidate_dcache_range(unsigned long start, unsigned long stop) { if (!check_cache_range(start, stop)) diff --git a/arch/arm/cpu/arm926ejs/cache.c b/arch/arm/cpu/arm926ejs/cache.c index 2839c863e8..2119382ab2 100644 --- a/arch/arm/cpu/arm926ejs/cache.c +++ b/arch/arm/cpu/arm926ejs/cache.c @@ -29,23 +29,6 @@ void flush_dcache_all(void) ); } -static int check_cache_range(unsigned long start, unsigned long stop) -{ - int ok = 1; - - if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) - ok = 0; - - if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) - ok = 0; - - if (!ok) - debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n", - start, stop); - - return ok; -} - void invalidate_dcache_range(unsigned long start, unsigned long stop) { if (!check_cache_range(start, stop)) diff --git a/arch/arm/cpu/armv7/am33xx/config.mk b/arch/arm/cpu/armv7/am33xx/config.mk index 6d95d327b4..ab9470820d 100644 --- a/arch/arm/cpu/armv7/am33xx/config.mk +++ b/arch/arm/cpu/armv7/am33xx/config.mk @@ -26,6 +26,7 @@ endif else ifeq ($(CONFIG_TI_SECURE_DEVICE),y) ALL-$(CONFIG_QSPI_BOOT) += u-boot_HS_XIP_X-LOADER +ALL-y += u-boot_HS.img endif ALL-y += u-boot.img endif diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c index dc309dac90..52f18565db 100644 --- a/arch/arm/cpu/armv7/cache_v7.c +++ b/arch/arm/cpu/armv7/cache_v7.c @@ -19,23 +19,6 @@ void v7_flush_dcache_all(void); void v7_invalidate_dcache_all(void); -static int check_cache_range(unsigned long start, unsigned long stop) -{ - int ok = 1; - - if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) - ok = 0; - - if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) - ok = 0; - - if (!ok) - debug("CACHE: Misaligned operation at range [%08lx, %08lx]\n", - start, stop); - - return ok; -} - static u32 get_ccsidr(void) { u32 ccsidr; @@ -61,27 +44,8 @@ static void v7_dcache_inval_range(u32 start, u32 stop, u32 line_len) { u32 mva; - /* - * If start address is not aligned to cache-line do not - * invalidate the first cache-line - */ - if (start & (line_len - 1)) { - printf("ERROR: %s - start address is not aligned - 0x%08x\n", - __func__, start); - /* move to next cache line */ - start = (start + line_len - 1) & ~(line_len - 1); - } - - /* - * If stop address is not aligned to cache-line do not - * invalidate the last cache-line - */ - if (stop & (line_len - 1)) { - printf("ERROR: %s - stop address is not aligned - 0x%08x\n", - __func__, stop); - /* align to the beginning of this cache line */ - stop &= ~(line_len - 1); - } + if (!check_cache_range(start, stop)) + return; for (mva = start; mva < stop; mva = mva + line_len) { /* DCIMVAC - Invalidate data cache by MVA to PoC */ @@ -195,6 +159,14 @@ void flush_dcache_all(void) { } +void invalidate_dcache_range(unsigned long start, unsigned long stop) +{ +} + +void flush_dcache_range(unsigned long start, unsigned long stop) +{ +} + void arm_init_before_mmu(void) { } diff --git a/arch/arm/cpu/armv7/omap-common/Makefile b/arch/arm/cpu/armv7/omap-common/Makefile index 87a7ac03f9..3172bae105 100644 --- a/arch/arm/cpu/armv7/omap-common/Makefile +++ b/arch/arm/cpu/armv7/omap-common/Makefile @@ -36,3 +36,5 @@ obj-y += boot-common.o obj-y += lowlevel_init.o obj-y += mem-common.o + +obj-$(CONFIG_TI_SECURE_DEVICE) += sec-common.o diff --git a/arch/arm/cpu/armv7/omap-common/config_secure.mk b/arch/arm/cpu/armv7/omap-common/config_secure.mk index c7bb101be8..1122439e38 100644 --- a/arch/arm/cpu/armv7/omap-common/config_secure.mk +++ b/arch/arm/cpu/armv7/omap-common/config_secure.mk @@ -12,8 +12,8 @@ cmd_mkomapsecimg = $(TI_SECURE_DEV_PKG)/scripts/create-boot-image.sh \ $(if $(KBUILD_VERBOSE:1=), >/dev/null) else cmd_mkomapsecimg = $(TI_SECURE_DEV_PKG)/scripts/create-boot-image.sh \ - $(patsubst u-boot_HS_%,%,$(@F)) $< $@ $(CONFIG_ISW_ENTRY_ADDR) \ - $(if $(KBUILD_VERBOSE:1=), >/dev/null) + $(patsubst u-boot_HS_%,%,$(@F)) $< $@ $(CONFIG_ISW_ENTRY_ADDR) \ + $(if $(KBUILD_VERBOSE:1=), >/dev/null) endif else cmd_mkomapsecimg = echo "WARNING:" \ @@ -25,14 +25,33 @@ cmd_mkomapsecimg = echo "WARNING: TI_SECURE_DEV_PKG environment" \ "variable must be defined for TI secure devices. $@ was NOT created!" endif +ifdef CONFIG_SPL_LOAD_FIT +quiet_cmd_omapsecureimg = SECURE $@ +ifneq ($(TI_SECURE_DEV_PKG),) +ifneq ($(wildcard $(TI_SECURE_DEV_PKG)/scripts/secure-binary-image.sh),) +cmd_omapsecureimg = $(TI_SECURE_DEV_PKG)/scripts/secure-binary-image.sh \ + $< $@ \ + $(if $(KBUILD_VERBOSE:1=), >/dev/null) +else +cmd_omapsecureimg = echo "WARNING:" \ + "$(TI_SECURE_DEV_PKG)/scripts/secure-binary-image.sh not found." \ + "$@ was NOT created!"; cp $< $@ +endif +else +cmd_omapsecureimg = echo "WARNING: TI_SECURE_DEV_PKG environment" \ + "variable must be defined for TI secure devices." \ + "$@ was NOT created!"; cp $< $@ +endif +endif + + # Standard X-LOADER target (QPSI, NOR flash) u-boot-spl_HS_X-LOADER: $(obj)/u-boot-spl.bin $(call if_changed,mkomapsecimg) -# For MLO targets (SD card boot) the final file name -# that is copied to the SD card fAT partition must -# be MLO, so we make a copy of the output file to a -# new file with that name +# For MLO targets (SD card boot) the final file name that is copied to the SD +# card FAT partition must be MLO, so we make a copy of the output file to a new +# file with that name u-boot-spl_HS_MLO: $(obj)/u-boot-spl.bin $(call if_changed,mkomapsecimg) @if [ -f $@ ]; then \ @@ -51,16 +70,44 @@ u-boot-spl_HS_ULO: $(obj)/u-boot-spl.bin u-boot-spl_HS_ISSW: $(obj)/u-boot-spl.bin $(call if_changed,mkomapsecimg) -# For SPI flash on AM335x and AM43xx, these -# require special byte swap handling so we use -# the SPI_X-LOADER target instead of X-LOADER -# and let the create-boot-image.sh script handle -# that +# For SPI flash on AM335x and AM43xx, these require special byte swap handling +# so we use the SPI_X-LOADER target instead of X-LOADER and let the +# create-boot-image.sh script handle that u-boot-spl_HS_SPI_X-LOADER: $(obj)/u-boot-spl.bin $(call if_changed,mkomapsecimg) -# For supporting single stage XiP QSPI on AM43xx, the -# image is a full u-boot file, not an SPL. In this case -# the mkomapsecimg command looks for a u-boot-HS_* prefix +# For supporting single stage XiP QSPI on AM43xx, the image is a full u-boot +# file, not an SPL. In this case the mkomapsecimg command looks for a +# u-boot-HS_* prefix u-boot_HS_XIP_X-LOADER: $(obj)/u-boot.bin $(call if_changed,mkomapsecimg) + +# For supporting the SPL loading and interpreting of FIT images whose +# components are pre-processed before being integrated into the FIT image in +# order to secure them in some way +ifdef CONFIG_SPL_LOAD_FIT + +MKIMAGEFLAGS_u-boot_HS.img = -f auto -A $(ARCH) -T firmware -C none -O u-boot \ + -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \ + -n "U-Boot $(UBOOTRELEASE) for $(BOARD) board" -E \ + $(patsubst %,-b arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) + +OF_LIST_TARGETS = $(patsubst %,arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST))) +$(OF_LIST_TARGETS): dtbs + +%_HS.dtb: %.dtb + $(call if_changed,omapsecureimg) + $(Q)if [ -f $@ ]; then \ + cp -f $@ $<; \ + fi + +u-boot-nodtb_HS.bin: u-boot-nodtb.bin + $(call if_changed,omapsecureimg) + +u-boot_HS.img: u-boot-nodtb_HS.bin u-boot.img $(patsubst %.dtb,%_HS.dtb,$(OF_LIST_TARGETS)) + $(call if_changed,mkimage) + $(Q)if [ -f $@ ]; then \ + cp -f $@ u-boot.img; \ + fi + +endif diff --git a/arch/arm/cpu/armv7/omap-common/emif-common.c b/arch/arm/cpu/armv7/omap-common/emif-common.c index 9a9c764b4d..2b790105b0 100644 --- a/arch/arm/cpu/armv7/omap-common/emif-common.c +++ b/arch/arm/cpu/armv7/omap-common/emif-common.c @@ -37,7 +37,8 @@ void set_lpmode_selfrefresh(u32 base) void force_emif_self_refresh() { set_lpmode_selfrefresh(EMIF1_BASE); - set_lpmode_selfrefresh(EMIF2_BASE); + if (!is_dra72x()) + set_lpmode_selfrefresh(EMIF2_BASE); } inline u32 emif_num(u32 base) diff --git a/arch/arm/cpu/armv7/omap-common/hwinit-common.c b/arch/arm/cpu/armv7/omap-common/hwinit-common.c index 2f9693f28e..f317293988 100644 --- a/arch/arm/cpu/armv7/omap-common/hwinit-common.c +++ b/arch/arm/cpu/armv7/omap-common/hwinit-common.c @@ -147,8 +147,7 @@ void early_system_init(void) hw_data_init(); #ifdef CONFIG_SPL_BUILD - if (warm_reset() && - (is_omap44xx() || (omap_revision() == OMAP5430_ES1_0))) + if (warm_reset()) force_emif_self_refresh(); #endif watchdog_init(); diff --git a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S index 528313584f..66a3b3d26c 100644 --- a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S +++ b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S @@ -16,9 +16,10 @@ #include <asm/arch/spl.h> #include <linux/linkage.h> +.arch_extension sec + #ifdef CONFIG_SPL ENTRY(save_boot_params) - ldr r1, =OMAP_SRAM_SCRATCH_BOOT_PARAMS str r0, [r1] b save_boot_params_ret @@ -26,14 +27,40 @@ ENDPROC(save_boot_params) #endif ENTRY(omap_smc1) - PUSH {r4-r12, lr} @ save registers - ROM code may pollute + push {r4-r12, lr} @ save registers - ROM code may pollute @ our registers - MOV r12, r0 @ Service - MOV r0, r1 @ Argument - DSB - DMB - .word 0xe1600070 @ SMC #0 - hand assembled for GCC versions - @ call ROM Code API for the service requested + mov r12, r0 @ Service + mov r0, r1 @ Argument - POP {r4-r12, pc} + dsb + dmb + smc 0 @ SMC #0 to enter monitor mode + @ call ROM Code API for the service requested + pop {r4-r12, pc} ENDPROC(omap_smc1) + +ENTRY(omap_smc_sec) + push {r4-r12, lr} @ save registers - ROM code may pollute + @ our registers + mov r6, #0xFF @ Indicate new Task call + mov r12, #0x00 @ Secure Service ID in R12 + + dsb + dmb + smc 0 @ SMC #0 to enter monitor mode + + b omap_smc_sec_end @ exit at end of the service execution + nop + + @ In case of IRQ happening in Secure, then ARM will branch here. + @ At that moment, IRQ will be pending and ARM will jump to Non Secure + @ IRQ handler + mov r12, #0xFE + + dsb + dmb + smc 0 @ SMC #0 to enter monitor mode + +omap_smc_sec_end: + pop {r4-r12, pc} +ENDPROC(omap_smc_sec) diff --git a/arch/arm/cpu/armv7/omap-common/sec-common.c b/arch/arm/cpu/armv7/omap-common/sec-common.c new file mode 100644 index 0000000000..246a2393da --- /dev/null +++ b/arch/arm/cpu/armv7/omap-common/sec-common.c @@ -0,0 +1,139 @@ +/* + * + * Common security related functions for OMAP devices + * + * (C) Copyright 2016 + * Texas Instruments, <www.ti.com> + * + * Daniel Allred <d-allred@ti.com> + * Andreas Dannenberg <dannenberg@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <stdarg.h> + +#include <asm/arch/sys_proto.h> +#include <asm/omap_common.h> +#include <asm/omap_sec_common.h> +#include <asm/spl.h> +#include <spl.h> + +/* Index for signature verify ROM API */ +#define API_HAL_KM_VERIFYCERTIFICATESIGNATURE_INDEX (0x0000000E) + +static uint32_t secure_rom_call_args[5] __aligned(ARCH_DMA_MINALIGN); + +u32 secure_rom_call(u32 service, u32 proc_id, u32 flag, ...) +{ + int i; + u32 num_args; + va_list ap; + + va_start(ap, flag); + + num_args = va_arg(ap, u32); + + if (num_args > 4) + return 1; + + /* Copy args to aligned args structure */ + for (i = 0; i < num_args; i++) + secure_rom_call_args[i + 1] = va_arg(ap, u32); + + secure_rom_call_args[0] = num_args; + + va_end(ap); + + /* if data cache is enabled, flush the aligned args structure */ + flush_dcache_range( + (unsigned int)&secure_rom_call_args[0], + (unsigned int)&secure_rom_call_args[0] + + roundup(sizeof(secure_rom_call_args), ARCH_DMA_MINALIGN)); + + return omap_smc_sec(service, proc_id, flag, secure_rom_call_args); +} + +static u32 find_sig_start(char *image, size_t size) +{ + char *image_end = image + size; + char *sig_start_magic = "CERT_"; + int magic_str_len = strlen(sig_start_magic); + char *ch; + + while (--image_end > image) { + if (*image_end == '_') { + ch = image_end - magic_str_len + 1; + if (!strncmp(ch, sig_start_magic, magic_str_len)) + return (u32)ch; + } + } + return 0; +} + +int secure_boot_verify_image(void **image, size_t *size) +{ + int result = 1; + u32 cert_addr, sig_addr; + size_t cert_size; + + /* Perform cache writeback on input buffer */ + flush_dcache_range( + (u32)*image, + (u32)*image + roundup(*size, ARCH_DMA_MINALIGN)); + + cert_addr = (uint32_t)*image; + sig_addr = find_sig_start((char *)*image, *size); + + if (sig_addr == 0) { + printf("No signature found in image!\n"); + result = 1; + goto auth_exit; + } + + *size = sig_addr - cert_addr; /* Subtract out the signature size */ + cert_size = *size; + + /* Check if image load address is 32-bit aligned */ + if (!IS_ALIGNED(cert_addr, 4)) { + printf("Image is not 4-byte aligned!\n"); + result = 1; + goto auth_exit; + } + + /* Image size also should be multiple of 4 */ + if (!IS_ALIGNED(cert_size, 4)) { + printf("Image size is not 4-byte aligned!\n"); + result = 1; + goto auth_exit; + } + + /* Call ROM HAL API to verify certificate signature */ + debug("%s: load_addr = %x, size = %x, sig_addr = %x\n", __func__, + cert_addr, cert_size, sig_addr); + + result = secure_rom_call( + API_HAL_KM_VERIFYCERTIFICATESIGNATURE_INDEX, 0, 0, + 4, cert_addr, cert_size, sig_addr, 0xFFFFFFFF); +auth_exit: + if (result != 0) { + printf("Authentication failed!\n"); + printf("Return Value = %08X\n", result); + hang(); + } + + /* + * Output notification of successful authentication as well the name of + * the signing certificate used to re-assure the user that the secure + * code is being processed as expected. However suppress any such log + * output in case of building for SPL and booting via YMODEM. This is + * done to avoid disturbing the YMODEM serial protocol transactions. + */ + if (!(IS_ENABLED(CONFIG_SPL_BUILD) && + IS_ENABLED(CONFIG_SPL_YMODEM_SUPPORT) && + spl_boot_device() == BOOT_DEVICE_UART)) + printf("Authentication passed: %s\n", (char *)sig_addr); + + return result; +} diff --git a/arch/arm/cpu/armv7/omap5/config.mk b/arch/arm/cpu/armv7/omap5/config.mk index a7e55a5e24..d245572ef0 100644 --- a/arch/arm/cpu/armv7/omap5/config.mk +++ b/arch/arm/cpu/armv7/omap5/config.mk @@ -15,5 +15,8 @@ else ALL-y += MLO endif else +ifeq ($(CONFIG_TI_SECURE_DEVICE),y) +ALL-y += u-boot_HS.img +endif ALL-y += u-boot.img endif diff --git a/arch/arm/cpu/armv7m/config.mk b/arch/arm/cpu/armv7m/config.mk index 4a53006b6a..db4660e15d 100644 --- a/arch/arm/cpu/armv7m/config.mk +++ b/arch/arm/cpu/armv7m/config.mk @@ -5,4 +5,4 @@ # SPDX-License-Identifier: GPL-2.0+ # -PLATFORM_CPPFLAGS += -march=armv7-m -mthumb +PLATFORM_CPPFLAGS += -march=armv7-m -mthumb -mno-unaligned-access diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig index 3d19bbfbe2..acf2460ede 100644 --- a/arch/arm/cpu/armv8/Kconfig +++ b/arch/arm/cpu/armv8/Kconfig @@ -3,4 +3,22 @@ if ARM64 config ARMV8_MULTIENTRY boolean "Enable multiple CPUs to enter into U-Boot" +config ARMV8_SPIN_TABLE + bool "Support spin-table enable method" + depends on ARMV8_MULTIENTRY && OF_LIBFDT + help + Say Y here to support "spin-table" enable method for booting Linux. + + To use this feature, you must do: + - Specify enable-method = "spin-table" in each CPU node in the + Device Tree you are using to boot the kernel + - Let secondary CPUs in U-Boot (in a board specific manner) + before the master CPU jumps to the kernel + + U-Boot automatically does: + - Set "cpu-release-addr" property of each CPU node + (overwrites it if already exists). + - Reserve the code for the spin-table and the release address + via a /memreserve/ region in the Device Tree. + endif diff --git a/arch/arm/cpu/armv8/Makefile b/arch/arm/cpu/armv8/Makefile index bf8644ccd2..f6eb9f4a7f 100644 --- a/arch/arm/cpu/armv8/Makefile +++ b/arch/arm/cpu/armv8/Makefile @@ -15,6 +15,9 @@ obj-y += cache.o obj-y += tlb.o obj-y += transition.o obj-y += fwcall.o +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_ARMV8_SPIN_TABLE) += spin_table.o spin_table_v8.o +endif obj-$(CONFIG_FSL_LAYERSCAPE) += fsl-layerscape/ obj-$(CONFIG_S32V234) += s32v234/ diff --git a/arch/arm/cpu/armv8/spin_table.c b/arch/arm/cpu/armv8/spin_table.c new file mode 100644 index 0000000000..ec1c9b8ddb --- /dev/null +++ b/arch/arm/cpu/armv8/spin_table.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <libfdt.h> +#include <asm/spin_table.h> + +int spin_table_update_dt(void *fdt) +{ + int cpus_offset, offset; + const char *prop; + int ret; + unsigned long rsv_addr = (unsigned long)&spin_table_reserve_begin; + unsigned long rsv_size = &spin_table_reserve_end - + &spin_table_reserve_begin; + + cpus_offset = fdt_path_offset(fdt, "/cpus"); + if (cpus_offset < 0) + return -ENODEV; + + for (offset = fdt_first_subnode(fdt, cpus_offset); + offset >= 0; + offset = fdt_next_subnode(fdt, offset)) { + prop = fdt_getprop(fdt, offset, "device_type", NULL); + if (!prop || strcmp(prop, "cpu")) + continue; + + /* + * In the first loop, we check if every CPU node specifies + * spin-table. Otherwise, just return successfully to not + * disturb other methods, like psci. + */ + prop = fdt_getprop(fdt, offset, "enable-method", NULL); + if (!prop || strcmp(prop, "spin-table")) + return 0; + } + + for (offset = fdt_first_subnode(fdt, cpus_offset); + offset >= 0; + offset = fdt_next_subnode(fdt, offset)) { + prop = fdt_getprop(fdt, offset, "device_type", NULL); + if (!prop || strcmp(prop, "cpu")) + continue; + + ret = fdt_setprop_u64(fdt, offset, "cpu-release-addr", + (unsigned long)&spin_table_cpu_release_addr); + if (ret) + return -ENOSPC; + } + + ret = fdt_add_mem_rsv(fdt, rsv_addr, rsv_size); + if (ret) + return -ENOSPC; + + printf(" Reserved memory region for spin-table: addr=%lx size=%lx\n", + rsv_addr, rsv_size); + + return 0; +} diff --git a/arch/arm/cpu/armv8/spin_table_v8.S b/arch/arm/cpu/armv8/spin_table_v8.S new file mode 100644 index 0000000000..d7f78a6a67 --- /dev/null +++ b/arch/arm/cpu/armv8/spin_table_v8.S @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <linux/linkage.h> + +ENTRY(spin_table_secondary_jump) +.globl spin_table_reserve_begin +spin_table_reserve_begin: +0: wfe + ldr x0, spin_table_cpu_release_addr + cbz x0, 0b + br x0 +.globl spin_table_cpu_release_addr + .align 3 +spin_table_cpu_release_addr: + .quad 0 +.globl spin_table_reserve_end +spin_table_reserve_end: +ENDPROC(spin_table_secondary_jump) diff --git a/arch/arm/cpu/armv8/start.S b/arch/arm/cpu/armv8/start.S index 670e323b61..67edf94520 100644 --- a/arch/arm/cpu/armv8/start.S +++ b/arch/arm/cpu/armv8/start.S @@ -94,7 +94,11 @@ reset: /* Processor specific initialization */ bl lowlevel_init -#ifdef CONFIG_ARMV8_MULTIENTRY +#if CONFIG_IS_ENABLED(ARMV8_SPIN_TABLE) + branch_if_master x0, x1, master_cpu + b spin_table_secondary_jump + /* never return */ +#elif defined(CONFIG_ARMV8_MULTIENTRY) branch_if_master x0, x1, master_cpu /* @@ -106,10 +110,8 @@ slave_cpu: ldr x0, [x1] cbz x0, slave_cpu br x0 /* branch to the given address */ -master_cpu: - /* On the master CPU */ #endif /* CONFIG_ARMV8_MULTIENTRY */ - +master_cpu: bl _main #ifdef CONFIG_SYS_RESET_SCTRL diff --git a/arch/arm/include/asm/arch-stm32f7/fmc.h b/arch/arm/include/asm/arch-stm32f7/fmc.h new file mode 100644 index 0000000000..7dd5077d0c --- /dev/null +++ b/arch/arm/include/asm/arch-stm32f7/fmc.h @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2013 + * Pavel Boldin, Emcraft Systems, paboldin@emcraft.com + * + * (C) Copyright 2015 + * Kamil Lulko, <kamil.lulko@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _MACH_FMC_H_ +#define _MACH_FMC_H_ + +struct stm32_fmc_regs { + u32 sdcr1; /* Control register 1 */ + u32 sdcr2; /* Control register 2 */ + u32 sdtr1; /* Timing register 1 */ + u32 sdtr2; /* Timing register 2 */ + u32 sdcmr; /* Mode register */ + u32 sdrtr; /* Refresh timing register */ + u32 sdsr; /* Status register */ +}; + +/* + * FMC registers base + */ +#define STM32_SDRAM_FMC_BASE 0xA0000140 +#define STM32_SDRAM_FMC ((struct stm32_fmc_regs *)STM32_SDRAM_FMC_BASE) + +/* Control register SDCR */ +#define FMC_SDCR_RPIPE_SHIFT 13 /* RPIPE bit shift */ +#define FMC_SDCR_RBURST_SHIFT 12 /* RBURST bit shift */ +#define FMC_SDCR_SDCLK_SHIFT 10 /* SDRAM clock divisor shift */ +#define FMC_SDCR_WP_SHIFT 9 /* Write protection shift */ +#define FMC_SDCR_CAS_SHIFT 7 /* CAS latency shift */ +#define FMC_SDCR_NB_SHIFT 6 /* Number of banks shift */ +#define FMC_SDCR_MWID_SHIFT 4 /* Memory width shift */ +#define FMC_SDCR_NR_SHIFT 2 /* Number of row address bits shift */ +#define FMC_SDCR_NC_SHIFT 0 /* Number of col address bits shift */ + +/* Timings register SDTR */ +#define FMC_SDTR_TMRD_SHIFT 0 /* Load mode register to active */ +#define FMC_SDTR_TXSR_SHIFT 4 /* Exit self-refresh time */ +#define FMC_SDTR_TRAS_SHIFT 8 /* Self-refresh time */ +#define FMC_SDTR_TRC_SHIFT 12 /* Row cycle delay */ +#define FMC_SDTR_TWR_SHIFT 16 /* Recovery delay */ +#define FMC_SDTR_TRP_SHIFT 20 /* Row precharge delay */ +#define FMC_SDTR_TRCD_SHIFT 24 /* Row-to-column delay */ + + +#define FMC_SDCMR_NRFS_SHIFT 5 + +#define FMC_SDCMR_MODE_NORMAL 0 +#define FMC_SDCMR_MODE_START_CLOCK 1 +#define FMC_SDCMR_MODE_PRECHARGE 2 +#define FMC_SDCMR_MODE_AUTOREFRESH 3 +#define FMC_SDCMR_MODE_WRITE_MODE 4 +#define FMC_SDCMR_MODE_SELFREFRESH 5 +#define FMC_SDCMR_MODE_POWERDOWN 6 + +#define FMC_SDCMR_BANK_1 (1 << 4) +#define FMC_SDCMR_BANK_2 (1 << 3) + +#define FMC_SDCMR_MODE_REGISTER_SHIFT 9 + +#define FMC_SDSR_BUSY (1 << 5) + +#define FMC_BUSY_WAIT() do { \ + __asm__ __volatile__ ("dsb" : : : "memory"); \ + while (STM32_SDRAM_FMC->sdsr & FMC_SDSR_BUSY) \ + ; \ + } while (0) + + +#endif /* _MACH_FMC_H_ */ diff --git a/arch/arm/include/asm/arch-stm32f7/stm32.h b/arch/arm/include/asm/arch-stm32f7/stm32.h index 68bdab069d..de55ae5df1 100644 --- a/arch/arm/include/asm/arch-stm32f7/stm32.h +++ b/arch/arm/include/asm/arch-stm32f7/stm32.h @@ -64,6 +64,52 @@ enum clock { }; #define STM32_BUS_MASK 0xFFFF0000 +struct stm32_rcc_regs { + u32 cr; /* RCC clock control */ + u32 pllcfgr; /* RCC PLL configuration */ + u32 cfgr; /* RCC clock configuration */ + u32 cir; /* RCC clock interrupt */ + u32 ahb1rstr; /* RCC AHB1 peripheral reset */ + u32 ahb2rstr; /* RCC AHB2 peripheral reset */ + u32 ahb3rstr; /* RCC AHB3 peripheral reset */ + u32 rsv0; + u32 apb1rstr; /* RCC APB1 peripheral reset */ + u32 apb2rstr; /* RCC APB2 peripheral reset */ + u32 rsv1[2]; + u32 ahb1enr; /* RCC AHB1 peripheral clock enable */ + u32 ahb2enr; /* RCC AHB2 peripheral clock enable */ + u32 ahb3enr; /* RCC AHB3 peripheral clock enable */ + u32 rsv2; + u32 apb1enr; /* RCC APB1 peripheral clock enable */ + u32 apb2enr; /* RCC APB2 peripheral clock enable */ + u32 rsv3[2]; + u32 ahb1lpenr; /* RCC AHB1 periph clk enable in low pwr mode */ + u32 ahb2lpenr; /* RCC AHB2 periph clk enable in low pwr mode */ + u32 ahb3lpenr; /* RCC AHB3 periph clk enable in low pwr mode */ + u32 rsv4; + u32 apb1lpenr; /* RCC APB1 periph clk enable in low pwr mode */ + u32 apb2lpenr; /* RCC APB2 periph clk enable in low pwr mode */ + u32 rsv5[2]; + u32 bdcr; /* RCC Backup domain control */ + u32 csr; /* RCC clock control & status */ + u32 rsv6[2]; + u32 sscgr; /* RCC spread spectrum clock generation */ + u32 plli2scfgr; /* RCC PLLI2S configuration */ + u32 pllsaicfgr; + u32 dckcfgr; +}; +#define STM32_RCC ((struct stm32_rcc_regs *)RCC_BASE) + +struct stm32_pwr_regs { + u32 cr1; /* power control register 1 */ + u32 csr1; /* power control/status register 2 */ + u32 cr2; /* power control register 2 */ + u32 csr2; /* power control/status register 2 */ +}; +#define STM32_PWR ((struct stm32_pwr_regs *)PWR_BASE) + int configure_clocks(void); +unsigned long clock_get(enum clock clck); +void stm32_flash_latency_cfg(int latency); #endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/include/asm/arch-stm32f7/stm32_periph.h b/arch/arm/include/asm/arch-stm32f7/stm32_periph.h index 38adc4e0e2..0bd4695727 100644 --- a/arch/arm/include/asm/arch-stm32f7/stm32_periph.h +++ b/arch/arm/include/asm/arch-stm32f7/stm32_periph.h @@ -17,11 +17,13 @@ enum periph_id { UART1_GPIOA_9_10 = 0, UART2_GPIOD_5_6, + UART6_GPIOC_6_7, }; enum periph_clock { USART1_CLOCK_CFG = 0, USART2_CLOCK_CFG, + USART6_CLOCK_CFG, GPIO_A_CLOCK_CFG, GPIO_B_CLOCK_CFG, GPIO_C_CLOCK_CFG, diff --git a/arch/arm/include/asm/armv7m.h b/arch/arm/include/asm/armv7m.h index 200444dda1..54d8a2bdff 100644 --- a/arch/arm/include/asm/armv7m.h +++ b/arch/arm/include/asm/armv7m.h @@ -51,10 +51,21 @@ struct v7m_mpu { #define V7M_MPU_CTRL_ENABLE (1 << 0) #define V7M_MPU_CTRL_HFNMIENA (1 << 1) +#define V7M_MPU_CTRL_ENABLE (1 << 0) +#define V7M_MPU_CTRL_DISABLE (0 << 0) +#define V7M_MPU_CTRL_HFNMIENA (1 << 1) + #define V7M_MPU_RASR_EN (1 << 0) #define V7M_MPU_RASR_SIZE_BITS 1 #define V7M_MPU_RASR_SIZE_4GB (31 << V7M_MPU_RASR_SIZE_BITS) +#define V7M_MPU_RASR_SIZE_8MB (24 << V7M_MPU_RASR_SIZE_BITS) +#define V7M_MPU_RASR_TEX_SHIFT 19 +#define V7M_MPU_RASR_S_SHIFT 18 +#define V7M_MPU_RASR_C_SHIFT 17 +#define V7M_MPU_RASR_B_SHIFT 16 #define V7M_MPU_RASR_AP_RW_RW (3 << 24) +#define V7M_MPU_RASR_XN_ENABLE (0 << 28) +#define V7M_MPU_RASR_XN_DISABLE (1 << 28) #endif /* !defined(__ASSEMBLY__) */ #endif /* ARMV7M_H */ diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h index 1f63127bdc..16e65c36a9 100644 --- a/arch/arm/include/asm/cache.h +++ b/arch/arm/include/asm/cache.h @@ -29,6 +29,8 @@ static inline void invalidate_l2_cache(void) } #endif +int check_cache_range(unsigned long start, unsigned long stop); + void l2_cache_enable(void); void l2_cache_disable(void); void set_section_dcache(int section, enum dcache_option option); diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 9d185a6122..6121f1ddca 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -292,40 +292,6 @@ static inline void __raw_readsl(unsigned long addr, void *data, int longlen) #define readsb(a, d, s) __raw_readsb((unsigned long)a, d, s) /* - * ioremap and friends. - * - * ioremap takes a PCI memory address, as specified in - * linux/Documentation/IO-mapping.txt. If you want a - * physical address, use __ioremap instead. - */ -extern void * __ioremap(unsigned long offset, size_t size, unsigned long flags); -extern void __iounmap(void *addr); - -/* - * Generic ioremap support. - * - * Define: - * iomem_valid_addr(off,size) - * iomem_to_phys(off) - */ -#ifdef iomem_valid_addr -#define __arch_ioremap(off,sz,nocache) \ - ({ \ - unsigned long _off = (off), _size = (sz); \ - void *_ret = (void *)0; \ - if (iomem_valid_addr(_off, _size)) \ - _ret = __ioremap(iomem_to_phys(_off),_size,nocache); \ - _ret; \ - }) - -#define __arch_iounmap __iounmap -#endif - -#define ioremap(off,sz) __arch_ioremap((off),(sz),0) -#define ioremap_nocache(off,sz) __arch_ioremap((off),(sz),1) -#define iounmap(_addr) __arch_iounmap(_addr) - -/* * DMA-consistent mapping functions. These allocate/free a region of * uncached, unwrite-buffered mapped memory space for use with DMA * devices. This is the "generic" version. The PCI specific version diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h index 07f384867e..605c549f0a 100644 --- a/arch/arm/include/asm/omap_common.h +++ b/arch/arm/include/asm/omap_common.h @@ -627,6 +627,12 @@ void recalibrate_iodelay(void); void omap_smc1(u32 service, u32 val); +/* + * Low-level helper function used when performing secure ROM calls on high- + * security (HS) device variants by doing a specially-formed smc entry. + */ +u32 omap_smc_sec(u32 service, u32 proc_id, u32 flag, u32 *params); + void enable_edma3_clocks(void); void disable_edma3_clocks(void); diff --git a/arch/arm/include/asm/omap_sec_common.h b/arch/arm/include/asm/omap_sec_common.h new file mode 100644 index 0000000000..842f2af8d1 --- /dev/null +++ b/arch/arm/include/asm/omap_sec_common.h @@ -0,0 +1,30 @@ +/* + * (C) Copyright 2016 + * Texas Instruments, <www.ti.com> + * + * Andreas Dannenberg <dannenberg@ti.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef _OMAP_SEC_COMMON_H_ +#define _OMAP_SEC_COMMON_H_ + +#include <common.h> + +/* + * Invoke secure ROM API on high-security (HS) device variants. It formats + * the variable argument list into the format expected by the ROM code before + * triggering the actual low-level smc entry. + */ +u32 secure_rom_call(u32 service, u32 proc_id, u32 flag, ...); + +/* + * Invoke a secure ROM API on high-secure (HS) device variants that can be used + * to verify a secure blob by authenticating and optionally decrypting it. The + * exact operation performed depends on how the certificate that was embedded + * into the blob during the signing/encryption step when the secure blob was + * first created. + */ +int secure_boot_verify_image(void **p_image, size_t *p_size); + +#endif /* _OMAP_SEC_COMMON_H_ */ diff --git a/arch/arm/include/asm/spin_table.h b/arch/arm/include/asm/spin_table.h new file mode 100644 index 0000000000..8b57539f8d --- /dev/null +++ b/arch/arm/include/asm/spin_table.h @@ -0,0 +1,14 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __ASM_SPIN_TABLE_H__ +#define __ASM_SPIN_TABLE_H__ + +extern u64 spin_table_cpu_release_addr; +extern char spin_table_reserve_begin; +extern char spin_table_reserve_end; + +int spin_table_update_dt(void *fdt); + +#endif /* __ASM_SPIN_TABLE_H__ */ diff --git a/arch/arm/include/asm/types.h b/arch/arm/include/asm/types.h index d108915ff5..9af7353f08 100644 --- a/arch/arm/include/asm/types.h +++ b/arch/arm/include/asm/types.h @@ -71,5 +71,4 @@ typedef u32 dma_addr_t; #endif /* __KERNEL__ */ -typedef unsigned long resource_size_t; #endif diff --git a/arch/arm/lib/bootm-fdt.c b/arch/arm/lib/bootm-fdt.c index 76b75d8e46..2c0b56a8f3 100644 --- a/arch/arm/lib/bootm-fdt.c +++ b/arch/arm/lib/bootm-fdt.c @@ -21,6 +21,7 @@ #include <asm/armv7.h> #endif #include <asm/psci.h> +#include <asm/spin_table.h> DECLARE_GLOBAL_DATA_PTR; @@ -45,6 +46,12 @@ int arch_fixup_fdt(void *blob) if (ret) return ret; +#ifdef CONFIG_ARMV8_SPIN_TABLE + ret = spin_table_update_dt(blob); + if (ret) + return ret; +#endif + #ifdef CONFIG_ARMV7_NONSEC ret = psci_update_dt(blob); if (ret) diff --git a/arch/arm/lib/cache.c b/arch/arm/lib/cache.c index 3bd87105c5..d330b09434 100644 --- a/arch/arm/lib/cache.c +++ b/arch/arm/lib/cache.c @@ -10,6 +10,10 @@ #include <common.h> #include <malloc.h> +#ifndef CONFIG_SYS_CACHELINE_SIZE +#define CONFIG_SYS_CACHELINE_SIZE 32 +#endif + /* * Flush range from all levels of d-cache/unified-cache. * Affects the range [start, start + size - 1]. @@ -46,6 +50,24 @@ __weak void flush_dcache_range(unsigned long start, unsigned long stop) /* An empty stub, real implementation should be in platform code */ } +int check_cache_range(unsigned long start, unsigned long stop) +{ + int ok = 1; + + if (start & (CONFIG_SYS_CACHELINE_SIZE - 1)) + ok = 0; + + if (stop & (CONFIG_SYS_CACHELINE_SIZE - 1)) + ok = 0; + + if (!ok) { + warn_non_spl("CACHE: Misaligned operation at range [%08lx, %08lx]\n", + start, stop); + } + + return ok; +} + #ifdef CONFIG_SYS_NONCACHED_MEMORY /* * Reserve one MMU section worth of address space below the malloc() area that diff --git a/arch/arm/mach-stm32/stm32f7/Makefile b/arch/arm/mach-stm32/stm32f7/Makefile index 40f1ad35b7..643d4d919c 100644 --- a/arch/arm/mach-stm32/stm32f7/Makefile +++ b/arch/arm/mach-stm32/stm32f7/Makefile @@ -5,4 +5,4 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-y += timer.o clock.o +obj-y += timer.o clock.o soc.o diff --git a/arch/arm/mach-stm32/stm32f7/clock.c b/arch/arm/mach-stm32/stm32f7/clock.c index 17a715bac9..ac47850551 100644 --- a/arch/arm/mach-stm32/stm32f7/clock.c +++ b/arch/arm/mach-stm32/stm32f7/clock.c @@ -11,12 +11,243 @@ #include <asm/arch/stm32.h> #include <asm/arch/stm32_periph.h> +#define RCC_CR_HSION (1 << 0) +#define RCC_CR_HSEON (1 << 16) +#define RCC_CR_HSERDY (1 << 17) +#define RCC_CR_HSEBYP (1 << 18) +#define RCC_CR_CSSON (1 << 19) +#define RCC_CR_PLLON (1 << 24) +#define RCC_CR_PLLRDY (1 << 25) + +#define RCC_PLLCFGR_PLLM_MASK 0x3F +#define RCC_PLLCFGR_PLLN_MASK 0x7FC0 +#define RCC_PLLCFGR_PLLP_MASK 0x30000 +#define RCC_PLLCFGR_PLLQ_MASK 0xF000000 +#define RCC_PLLCFGR_PLLSRC (1 << 22) +#define RCC_PLLCFGR_PLLM_SHIFT 0 +#define RCC_PLLCFGR_PLLN_SHIFT 6 +#define RCC_PLLCFGR_PLLP_SHIFT 16 +#define RCC_PLLCFGR_PLLQ_SHIFT 24 + +#define RCC_CFGR_AHB_PSC_MASK 0xF0 +#define RCC_CFGR_APB1_PSC_MASK 0x1C00 +#define RCC_CFGR_APB2_PSC_MASK 0xE000 +#define RCC_CFGR_SW0 (1 << 0) +#define RCC_CFGR_SW1 (1 << 1) +#define RCC_CFGR_SW_MASK 0x3 +#define RCC_CFGR_SW_HSI 0 +#define RCC_CFGR_SW_HSE RCC_CFGR_SW0 +#define RCC_CFGR_SW_PLL RCC_CFGR_SW1 +#define RCC_CFGR_SWS0 (1 << 2) +#define RCC_CFGR_SWS1 (1 << 3) +#define RCC_CFGR_SWS_MASK 0xC +#define RCC_CFGR_SWS_HSI 0 +#define RCC_CFGR_SWS_HSE RCC_CFGR_SWS0 +#define RCC_CFGR_SWS_PLL RCC_CFGR_SWS1 +#define RCC_CFGR_HPRE_SHIFT 4 +#define RCC_CFGR_PPRE1_SHIFT 10 +#define RCC_CFGR_PPRE2_SHIFT 13 + +#define RCC_APB1ENR_PWREN (1 << 28) + +/* + * RCC USART specific definitions + */ +#define RCC_ENR_USART1EN (1 << 4) +#define RCC_ENR_USART2EN (1 << 17) +#define RCC_ENR_USART3EN (1 << 18) +#define RCC_ENR_USART6EN (1 << 5) + +/* + * Offsets of some PWR registers + */ +#define PWR_CR1_ODEN (1 << 16) +#define PWR_CR1_ODSWEN (1 << 17) +#define PWR_CSR1_ODRDY (1 << 16) +#define PWR_CSR1_ODSWRDY (1 << 17) + + +/* + * RCC GPIO specific definitions + */ +#define RCC_ENR_GPIO_A_EN (1 << 0) +#define RCC_ENR_GPIO_B_EN (1 << 1) +#define RCC_ENR_GPIO_C_EN (1 << 2) +#define RCC_ENR_GPIO_D_EN (1 << 3) +#define RCC_ENR_GPIO_E_EN (1 << 4) +#define RCC_ENR_GPIO_F_EN (1 << 5) +#define RCC_ENR_GPIO_G_EN (1 << 6) +#define RCC_ENR_GPIO_H_EN (1 << 7) +#define RCC_ENR_GPIO_I_EN (1 << 8) +#define RCC_ENR_GPIO_J_EN (1 << 9) +#define RCC_ENR_GPIO_K_EN (1 << 10) + +struct pll_psc { + u8 pll_m; + u16 pll_n; + u8 pll_p; + u8 pll_q; + u8 ahb_psc; + u8 apb1_psc; + u8 apb2_psc; +}; + +#define AHB_PSC_1 0 +#define AHB_PSC_2 0x8 +#define AHB_PSC_4 0x9 +#define AHB_PSC_8 0xA +#define AHB_PSC_16 0xB +#define AHB_PSC_64 0xC +#define AHB_PSC_128 0xD +#define AHB_PSC_256 0xE +#define AHB_PSC_512 0xF + +#define APB_PSC_1 0 +#define APB_PSC_2 0x4 +#define APB_PSC_4 0x5 +#define APB_PSC_8 0x6 +#define APB_PSC_16 0x7 + +#if !defined(CONFIG_STM32_HSE_HZ) +#error "CONFIG_STM32_HSE_HZ not defined!" +#else +#if (CONFIG_STM32_HSE_HZ == 25000000) +#if (CONFIG_SYS_CLK_FREQ == 200000000) +/* 200 MHz */ +struct pll_psc sys_pll_psc = { + .pll_m = 25, + .pll_n = 400, + .pll_p = 2, + .pll_q = 8, + .ahb_psc = AHB_PSC_1, + .apb1_psc = APB_PSC_4, + .apb2_psc = APB_PSC_2 +}; +#endif +#else +#error "No PLL/Prescaler configuration for given CONFIG_STM32_HSE_HZ exists" +#endif +#endif + +int configure_clocks(void) +{ + /* Reset RCC configuration */ + setbits_le32(&STM32_RCC->cr, RCC_CR_HSION); + writel(0, &STM32_RCC->cfgr); /* Reset CFGR */ + clrbits_le32(&STM32_RCC->cr, (RCC_CR_HSEON | RCC_CR_CSSON + | RCC_CR_PLLON)); + writel(0x24003010, &STM32_RCC->pllcfgr); /* Reset value from RM */ + clrbits_le32(&STM32_RCC->cr, RCC_CR_HSEBYP); + writel(0, &STM32_RCC->cir); /* Disable all interrupts */ + + /* Configure for HSE+PLL operation */ + setbits_le32(&STM32_RCC->cr, RCC_CR_HSEON); + while (!(readl(&STM32_RCC->cr) & RCC_CR_HSERDY)) + ; + + setbits_le32(&STM32_RCC->cfgr, (( + sys_pll_psc.ahb_psc << RCC_CFGR_HPRE_SHIFT) + | (sys_pll_psc.apb1_psc << RCC_CFGR_PPRE1_SHIFT) + | (sys_pll_psc.apb2_psc << RCC_CFGR_PPRE2_SHIFT))); + + /* Configure the main PLL */ + uint32_t pllcfgr = 0; + pllcfgr = RCC_PLLCFGR_PLLSRC; /* pll source HSE */ + pllcfgr |= sys_pll_psc.pll_m << RCC_PLLCFGR_PLLM_SHIFT; + pllcfgr |= sys_pll_psc.pll_n << RCC_PLLCFGR_PLLN_SHIFT; + pllcfgr |= ((sys_pll_psc.pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT; + pllcfgr |= sys_pll_psc.pll_q << RCC_PLLCFGR_PLLQ_SHIFT; + writel(pllcfgr, &STM32_RCC->pllcfgr); + + /* Enable the main PLL */ + setbits_le32(&STM32_RCC->cr, RCC_CR_PLLON); + while (!(readl(&STM32_RCC->cr) & RCC_CR_PLLRDY)) + ; + + /* Enable high performance mode, System frequency up to 200 MHz */ + setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_PWREN); + setbits_le32(&STM32_PWR->cr1, PWR_CR1_ODEN); + /* Infinite wait! */ + while (!(readl(&STM32_PWR->csr1) & PWR_CSR1_ODRDY)) + ; + /* Enable the Over-drive switch */ + setbits_le32(&STM32_PWR->cr1, PWR_CR1_ODSWEN); + /* Infinite wait! */ + while (!(readl(&STM32_PWR->csr1) & PWR_CSR1_ODSWRDY)) + ; + + stm32_flash_latency_cfg(5); + clrbits_le32(&STM32_RCC->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1)); + setbits_le32(&STM32_RCC->cfgr, RCC_CFGR_SW_PLL); + + while ((readl(&STM32_RCC->cfgr) & RCC_CFGR_SWS_MASK) != + RCC_CFGR_SWS_PLL) + ; + + return 0; +} + +unsigned long clock_get(enum clock clck) +{ + u32 sysclk = 0; + u32 shift = 0; + /* Prescaler table lookups for clock computation */ + u8 ahb_psc_table[16] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9 + }; + u8 apb_psc_table[8] = { + 0, 0, 0, 0, 1, 2, 3, 4 + }; + + if ((readl(&STM32_RCC->cfgr) & RCC_CFGR_SWS_MASK) == + RCC_CFGR_SWS_PLL) { + u16 pllm, plln, pllp; + pllm = (readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLM_MASK); + plln = ((readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLN_MASK) + >> RCC_PLLCFGR_PLLN_SHIFT); + pllp = ((((readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLP_MASK) + >> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1); + sysclk = ((CONFIG_STM32_HSE_HZ / pllm) * plln) / pllp; + } + + switch (clck) { + case CLOCK_CORE: + return sysclk; + break; + case CLOCK_AHB: + shift = ahb_psc_table[( + (readl(&STM32_RCC->cfgr) & RCC_CFGR_AHB_PSC_MASK) + >> RCC_CFGR_HPRE_SHIFT)]; + return sysclk >>= shift; + break; + case CLOCK_APB1: + shift = apb_psc_table[( + (readl(&STM32_RCC->cfgr) & RCC_CFGR_APB1_PSC_MASK) + >> RCC_CFGR_PPRE1_SHIFT)]; + return sysclk >>= shift; + break; + case CLOCK_APB2: + shift = apb_psc_table[( + (readl(&STM32_RCC->cfgr) & RCC_CFGR_APB2_PSC_MASK) + >> RCC_CFGR_PPRE2_SHIFT)]; + return sysclk >>= shift; + break; + default: + return 0; + break; + } +} + + void clock_setup(int peripheral) { switch (peripheral) { case USART1_CLOCK_CFG: setbits_le32(RCC_BASE + RCC_APB2ENR, RCC_ENR_USART1EN); break; + case USART6_CLOCK_CFG: + setbits_le32(RCC_BASE + RCC_APB2ENR, RCC_ENR_USART6EN); + break; case GPIO_A_CLOCK_CFG: setbits_le32(RCC_BASE + RCC_AHB1ENR, RCC_ENR_GPIO_A_EN); break; diff --git a/arch/arm/mach-stm32/stm32f7/soc.c b/arch/arm/mach-stm32/stm32f7/soc.c new file mode 100644 index 0000000000..8baee99a4f --- /dev/null +++ b/arch/arm/mach-stm32/stm32f7/soc.c @@ -0,0 +1,76 @@ +/* + * (C) Copyright 2015 + * Kamil Lulko, <kamil.lulko@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/armv7m.h> +#include <asm/arch/stm32.h> + +u32 get_cpu_rev(void) +{ + return 0; +} + +int arch_cpu_init(void) +{ + configure_clocks(); + + /* + * Configure the memory protection unit (MPU) + * 0x00000000 - 0xffffffff: Strong-order, Shareable + * 0xC0000000 - 0xC0800000: Normal, Outer and inner Non-cacheable + */ + + /* Disable MPU */ + writel(0, &V7M_MPU->ctrl); + + writel( + 0x00000000 /* address */ + | 1 << 4 /* VALID */ + | 0 << 0 /* REGION */ + , &V7M_MPU->rbar + ); + + /* Strong-order, Shareable */ + /* TEX=000, S=1, C=0, B=0*/ + writel( + (V7M_MPU_RASR_XN_ENABLE + | V7M_MPU_RASR_AP_RW_RW + | 0x01 << V7M_MPU_RASR_S_SHIFT + | 0x00 << V7M_MPU_RASR_TEX_SHIFT + | V7M_MPU_RASR_SIZE_4GB + | V7M_MPU_RASR_EN) + , &V7M_MPU->rasr + ); + + writel( + 0xC0000000 /* address */ + | 1 << 4 /* VALID */ + | 1 << 0 /* REGION */ + , &V7M_MPU->rbar + ); + + /* Normal, Outer and inner Non-cacheable */ + /* TEX=001, S=0, C=0, B=0*/ + writel( + (V7M_MPU_RASR_XN_ENABLE + | V7M_MPU_RASR_AP_RW_RW + | 0x01 << V7M_MPU_RASR_TEX_SHIFT + | V7M_MPU_RASR_SIZE_8MB + | V7M_MPU_RASR_EN) + , &V7M_MPU->rasr + ); + + /* Enable MPU */ + writel(V7M_MPU_CTRL_ENABLE | V7M_MPU_CTRL_HFNMIENA, &V7M_MPU->ctrl); + + return 0; +} + +void s_init(void) +{ +} diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h index 04708e9359..b2c4d0ef8c 100644 --- a/arch/nds32/include/asm/io.h +++ b/arch/nds32/include/asm/io.h @@ -344,40 +344,6 @@ static inline void writesl(unsigned int *addr, const void * data, int longlen) #define insl_p(port, to, len) insl(port, to, len) /* - * ioremap and friends. - * - * ioremap takes a PCI memory address, as specified in - * linux/Documentation/IO-mapping.txt. If you want a - * physical address, use __ioremap instead. - */ -extern void *__ioremap(unsigned long offset, size_t size, unsigned long flags); -extern void __iounmap(void *addr); - -/* - * Generic ioremap support. - * - * Define: - * iomem_valid_addr(off,size) - * iomem_to_phys(off) - */ -#ifdef iomem_valid_addr -#define __arch_ioremap(off, sz, nocache) \ -({ \ - unsigned long _off = (off), _size = (sz); \ - void *_ret = (void *)0; \ - if (iomem_valid_addr(_off, _size)) \ - _ret = __ioremap(iomem_to_phys(_off), _size, 0); \ - _ret; \ -}) - -#define __arch_iounmap __iounmap -#endif - -#define ioremap(off, sz) __arch_ioremap((off), (sz), 0) -#define ioremap_nocache(off, sz) __arch_ioremap((off), (sz), 1) -#define iounmap(_addr) __arch_iounmap(_addr) - -/* * DMA-consistent mapping functions. These allocate/free a region of * uncached, unwrite-buffered mapped memory space for use with DMA * devices. This is the "generic" version. The PCI specific version diff --git a/arch/sandbox/lib/bootm.c b/arch/sandbox/lib/bootm.c index d49c927b34..0c9a7979d2 100644 --- a/arch/sandbox/lib/bootm.c +++ b/arch/sandbox/lib/bootm.c @@ -56,7 +56,7 @@ int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images) bootstage_mark(BOOTSTAGE_ID_RUN_OS); printf("## Transferring control to Linux (at address %08lx)...\n", images->ep); - reset_cpu(0); + printf("sandbox: continuing, as we cannot run Linux\n"); } return 0; diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h index 0a00db3617..5dc27bebd5 100644 --- a/arch/sh/include/asm/io.h +++ b/arch/sh/include/asm/io.h @@ -128,39 +128,6 @@ extern void __raw_readsl(unsigned int addr, void *data, int longlen); #define in_8(port) inb(port) #define in_le16(port) inw(port) #define in_le32(port) inl(port) -/* - * ioremap and friends. - * - * ioremap takes a PCI memory address, as specified in - * linux/Documentation/IO-mapping.txt. If you want a - * physical address, use __ioremap instead. - */ -extern void *__ioremap(unsigned long offset, size_t size, unsigned long flags); -extern void __iounmap(void *addr); - -/* - * Generic ioremap support. - * - * Define: - * iomem_valid_addr(off,size) - * iomem_to_phys(off) - */ -#ifdef iomem_valid_addr -#define __arch_ioremap(off, sz, nocache) \ -({ \ - unsigned long _off = (off), _size = (sz); \ - void *_ret = (void *)0; \ - if (iomem_valid_addr(_off, _size)) \ - _ret = __ioremap(iomem_to_phys(_off), _size, 0); \ - _ret; \ -}) - -#define __arch_iounmap __iounmap -#endif - -#define ioremap(off, sz) __arch_ioremap((off), (sz), 0) -#define ioremap_nocache(off, sz) __arch_ioremap((off), (sz), 1) -#define iounmap(_addr) __arch_iounmap(_addr) /* * DMA-consistent mapping functions. These allocate/free a region of diff --git a/board/st/stm32f746-disco/stm32f746-disco.c b/board/st/stm32f746-disco/stm32f746-disco.c index 0e04d14148..47aa05897e 100644 --- a/board/st/stm32f746-disco/stm32f746-disco.c +++ b/board/st/stm32f746-disco/stm32f746-disco.c @@ -10,6 +10,8 @@ #include <asm/armv7m.h> #include <asm/arch/stm32.h> #include <asm/arch/gpio.h> +#include <asm/arch/rcc.h> +#include <asm/arch/fmc.h> #include <dm/platdata.h> #include <dm/platform_data/serial_stm32x7.h> #include <asm/arch/stm32_periph.h> @@ -30,12 +32,227 @@ const struct stm32_gpio_ctl gpio_ctl_usart = { .otype = STM32_GPIO_OTYPE_PP, .speed = STM32_GPIO_SPEED_50M, .pupd = STM32_GPIO_PUPD_UP, - .af = STM32_GPIO_AF7 + .af = STM32_GPIO_AF8 }; +const struct stm32_gpio_ctl gpio_ctl_fmc = { + .mode = STM32_GPIO_MODE_AF, + .otype = STM32_GPIO_OTYPE_PP, + .speed = STM32_GPIO_SPEED_100M, + .pupd = STM32_GPIO_PUPD_NO, + .af = STM32_GPIO_AF12 +}; + +static const struct stm32_gpio_dsc ext_ram_fmc_gpio[] = { + /* Chip is LQFP144, see DM00077036.pdf for details */ + {STM32_GPIO_PORT_D, STM32_GPIO_PIN_10}, /* 79, FMC_D15 */ + {STM32_GPIO_PORT_D, STM32_GPIO_PIN_9}, /* 78, FMC_D14 */ + {STM32_GPIO_PORT_D, STM32_GPIO_PIN_8}, /* 77, FMC_D13 */ + {STM32_GPIO_PORT_E, STM32_GPIO_PIN_15}, /* 68, FMC_D12 */ + {STM32_GPIO_PORT_E, STM32_GPIO_PIN_14}, /* 67, FMC_D11 */ + {STM32_GPIO_PORT_E, STM32_GPIO_PIN_13}, /* 66, FMC_D10 */ + {STM32_GPIO_PORT_E, STM32_GPIO_PIN_12}, /* 65, FMC_D9 */ + {STM32_GPIO_PORT_E, STM32_GPIO_PIN_11}, /* 64, FMC_D8 */ + {STM32_GPIO_PORT_E, STM32_GPIO_PIN_10}, /* 63, FMC_D7 */ + {STM32_GPIO_PORT_E, STM32_GPIO_PIN_9}, /* 60, FMC_D6 */ + {STM32_GPIO_PORT_E, STM32_GPIO_PIN_8}, /* 59, FMC_D5 */ + {STM32_GPIO_PORT_E, STM32_GPIO_PIN_7}, /* 58, FMC_D4 */ + {STM32_GPIO_PORT_D, STM32_GPIO_PIN_1}, /* 115, FMC_D3 */ + {STM32_GPIO_PORT_D, STM32_GPIO_PIN_0}, /* 114, FMC_D2 */ + {STM32_GPIO_PORT_D, STM32_GPIO_PIN_15}, /* 86, FMC_D1 */ + {STM32_GPIO_PORT_D, STM32_GPIO_PIN_14}, /* 85, FMC_D0 */ + + {STM32_GPIO_PORT_E, STM32_GPIO_PIN_1}, /* 142, FMC_NBL1 */ + {STM32_GPIO_PORT_E, STM32_GPIO_PIN_0}, /* 141, FMC_NBL0 */ + + {STM32_GPIO_PORT_G, STM32_GPIO_PIN_5}, /* 90, FMC_A15, BA1 */ + {STM32_GPIO_PORT_G, STM32_GPIO_PIN_4}, /* 89, FMC_A14, BA0 */ + + {STM32_GPIO_PORT_G, STM32_GPIO_PIN_1}, /* 57, FMC_A11 */ + {STM32_GPIO_PORT_G, STM32_GPIO_PIN_0}, /* 56, FMC_A10 */ + {STM32_GPIO_PORT_F, STM32_GPIO_PIN_15}, /* 55, FMC_A9 */ + {STM32_GPIO_PORT_F, STM32_GPIO_PIN_14}, /* 54, FMC_A8 */ + {STM32_GPIO_PORT_F, STM32_GPIO_PIN_13}, /* 53, FMC_A7 */ + {STM32_GPIO_PORT_F, STM32_GPIO_PIN_12}, /* 50, FMC_A6 */ + {STM32_GPIO_PORT_F, STM32_GPIO_PIN_5}, /* 15, FMC_A5 */ + {STM32_GPIO_PORT_F, STM32_GPIO_PIN_4}, /* 14, FMC_A4 */ + {STM32_GPIO_PORT_F, STM32_GPIO_PIN_3}, /* 13, FMC_A3 */ + {STM32_GPIO_PORT_F, STM32_GPIO_PIN_2}, /* 12, FMC_A2 */ + {STM32_GPIO_PORT_F, STM32_GPIO_PIN_1}, /* 11, FMC_A1 */ + {STM32_GPIO_PORT_F, STM32_GPIO_PIN_0}, /* 10, FMC_A0 */ + + {STM32_GPIO_PORT_H, STM32_GPIO_PIN_3}, /* 136, SDRAM_NE */ + {STM32_GPIO_PORT_F, STM32_GPIO_PIN_11}, /* 49, SDRAM_NRAS */ + {STM32_GPIO_PORT_G, STM32_GPIO_PIN_15}, /* 132, SDRAM_NCAS */ + {STM32_GPIO_PORT_H, STM32_GPIO_PIN_5}, /* 26, SDRAM_NWE */ + {STM32_GPIO_PORT_C, STM32_GPIO_PIN_3}, /* 135, SDRAM_CKE */ + + {STM32_GPIO_PORT_G, STM32_GPIO_PIN_8}, /* 93, SDRAM_CLK */ +}; + +static int fmc_setup_gpio(void) +{ + int rv = 0; + int i; + + clock_setup(GPIO_B_CLOCK_CFG); + clock_setup(GPIO_C_CLOCK_CFG); + clock_setup(GPIO_D_CLOCK_CFG); + clock_setup(GPIO_E_CLOCK_CFG); + clock_setup(GPIO_F_CLOCK_CFG); + clock_setup(GPIO_G_CLOCK_CFG); + clock_setup(GPIO_H_CLOCK_CFG); + + for (i = 0; i < ARRAY_SIZE(ext_ram_fmc_gpio); i++) { + rv = stm32_gpio_config(&ext_ram_fmc_gpio[i], + &gpio_ctl_fmc); + if (rv) + goto out; + } + +out: + return rv; +} + +/* + * STM32 RCC FMC specific definitions + */ +#define RCC_ENR_FMC (1 << 0) /* FMC module clock */ + +static inline u32 _ns2clk(u32 ns, u32 freq) +{ + u32 tmp = freq/1000000; + return (tmp * ns) / 1000; +} + +#define NS2CLK(ns) (_ns2clk(ns, freq)) + +/* + * Following are timings for IS42S16400J, from corresponding datasheet + */ +#define SDRAM_CAS 3 /* 3 cycles */ +#define SDRAM_NB 1 /* Number of banks */ +#define SDRAM_MWID 1 /* 16 bit memory */ + +#define SDRAM_NR 0x1 /* 12-bit row */ +#define SDRAM_NC 0x0 /* 8-bit col */ +#define SDRAM_RBURST 0x1 /* Single read requests always as bursts */ +#define SDRAM_RPIPE 0x0 /* No HCLK clock cycle delay */ + +#define SDRAM_TRRD NS2CLK(12) +#define SDRAM_TRCD NS2CLK(18) +#define SDRAM_TRP NS2CLK(18) +#define SDRAM_TRAS NS2CLK(42) +#define SDRAM_TRC NS2CLK(60) +#define SDRAM_TRFC NS2CLK(60) +#define SDRAM_TCDL (1 - 1) +#define SDRAM_TRDL NS2CLK(12) +#define SDRAM_TBDL (1 - 1) +#define SDRAM_TREF (NS2CLK(64000000 / 8192) - 20) +#define SDRAM_TCCD (1 - 1) + +#define SDRAM_TXSR SDRAM_TRFC /* Row cycle time after precharge */ +#define SDRAM_TMRD 1 /* Page 10, Mode Register Set */ + + +/* Last data in to row precharge, need also comply ineq on page 1648 */ +#define SDRAM_TWR max(\ + (int)max((int)SDRAM_TRDL, (int)(SDRAM_TRAS - SDRAM_TRCD)), \ + (int)(SDRAM_TRC - SDRAM_TRCD - SDRAM_TRP)\ +) + + +#define SDRAM_MODE_BL_SHIFT 0 +#define SDRAM_MODE_CAS_SHIFT 4 +#define SDRAM_MODE_BL 0 +#define SDRAM_MODE_CAS SDRAM_CAS + +int dram_init(void) +{ + u32 freq; + int rv; + + rv = fmc_setup_gpio(); + if (rv) + return rv; + + setbits_le32(RCC_BASE + RCC_AHB3ENR, RCC_ENR_FMC); + + /* + * Get frequency for NS2CLK calculation. + */ + freq = clock_get(CLOCK_AHB) / CONFIG_SYS_RAM_FREQ_DIV; + + writel( + CONFIG_SYS_RAM_FREQ_DIV << FMC_SDCR_SDCLK_SHIFT + | SDRAM_CAS << FMC_SDCR_CAS_SHIFT + | SDRAM_NB << FMC_SDCR_NB_SHIFT + | SDRAM_MWID << FMC_SDCR_MWID_SHIFT + | SDRAM_NR << FMC_SDCR_NR_SHIFT + | SDRAM_NC << FMC_SDCR_NC_SHIFT + | SDRAM_RPIPE << FMC_SDCR_RPIPE_SHIFT + | SDRAM_RBURST << FMC_SDCR_RBURST_SHIFT, + &STM32_SDRAM_FMC->sdcr1); + + writel( + SDRAM_TRCD << FMC_SDTR_TRCD_SHIFT + | SDRAM_TRP << FMC_SDTR_TRP_SHIFT + | SDRAM_TWR << FMC_SDTR_TWR_SHIFT + | SDRAM_TRC << FMC_SDTR_TRC_SHIFT + | SDRAM_TRAS << FMC_SDTR_TRAS_SHIFT + | SDRAM_TXSR << FMC_SDTR_TXSR_SHIFT + | SDRAM_TMRD << FMC_SDTR_TMRD_SHIFT, + &STM32_SDRAM_FMC->sdtr1); + + writel(FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_START_CLOCK, + &STM32_SDRAM_FMC->sdcmr); + + udelay(200); /* 200 us delay, page 10, "Power-Up" */ + FMC_BUSY_WAIT(); + + writel(FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_PRECHARGE, + &STM32_SDRAM_FMC->sdcmr); + + udelay(100); + FMC_BUSY_WAIT(); + + writel((FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_AUTOREFRESH + | 7 << FMC_SDCMR_NRFS_SHIFT), &STM32_SDRAM_FMC->sdcmr); + + udelay(100); + FMC_BUSY_WAIT(); + + writel(FMC_SDCMR_BANK_1 | (SDRAM_MODE_BL << SDRAM_MODE_BL_SHIFT + | SDRAM_MODE_CAS << SDRAM_MODE_CAS_SHIFT) + << FMC_SDCMR_MODE_REGISTER_SHIFT | FMC_SDCMR_MODE_WRITE_MODE, + &STM32_SDRAM_FMC->sdcmr); + + udelay(100); + + FMC_BUSY_WAIT(); + + writel(FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_NORMAL, + &STM32_SDRAM_FMC->sdcmr); + + FMC_BUSY_WAIT(); + + /* Refresh timer */ + writel(SDRAM_TREF, &STM32_SDRAM_FMC->sdrtr); + + /* + * Fill in global info with description of SRAM configuration + */ + gd->bd->bi_dram[0].start = CONFIG_SYS_RAM_BASE; + gd->bd->bi_dram[0].size = CONFIG_SYS_RAM_SIZE; + + gd->ram_size = CONFIG_SYS_RAM_SIZE; + + return rv; +} + static const struct stm32_gpio_dsc usart_gpio[] = { - {STM32_GPIO_PORT_A, STM32_GPIO_PIN_9}, /* TX */ - {STM32_GPIO_PORT_B, STM32_GPIO_PIN_7}, /* RX */ + {STM32_GPIO_PORT_C, STM32_GPIO_PIN_6}, /* TX */ + {STM32_GPIO_PORT_C, STM32_GPIO_PIN_7}, /* RX */ }; int uart_setup_gpio(void) @@ -43,8 +260,7 @@ int uart_setup_gpio(void) int i; int rv = 0; - clock_setup(GPIO_A_CLOCK_CFG); - clock_setup(GPIO_B_CLOCK_CFG); + clock_setup(GPIO_C_CLOCK_CFG); for (i = 0; i < ARRAY_SIZE(usart_gpio); i++) { rv = stm32_gpio_config(&usart_gpio[i], &gpio_ctl_usart); if (rv) @@ -56,7 +272,7 @@ out: } static const struct stm32x7_serial_platdata serial_platdata = { - .base = (struct stm32_usart *)USART1_BASE, + .base = (struct stm32_usart *)USART6_BASE, .clock = CONFIG_SYS_CLK_FREQ, }; @@ -75,7 +291,7 @@ int board_early_init_f(void) int res; res = uart_setup_gpio(); - clock_setup(USART1_CLOCK_CFG); + clock_setup(USART6_CLOCK_CFG); if (res) return res; @@ -88,12 +304,3 @@ int board_init(void) return 0; } - -int dram_init(void) -{ - gd->bd->bi_dram[0].start = CONFIG_SYS_RAM_BASE; - gd->bd->bi_dram[0].size = CONFIG_SYS_RAM_SIZE; - - gd->ram_size = CONFIG_SYS_RAM_SIZE; - return 0; -} diff --git a/board/ti/am43xx/board.c b/board/ti/am43xx/board.c index f005762eda..27c311ee9d 100644 --- a/board/ti/am43xx/board.c +++ b/board/ti/am43xx/board.c @@ -13,6 +13,7 @@ #include <asm/errno.h> #include <spl.h> #include <usb.h> +#include <asm/omap_sec_common.h> #include <asm/arch/clock.h> #include <asm/arch/sys_proto.h> #include <asm/arch/mux.h> @@ -862,3 +863,10 @@ int board_fit_config_name_match(const char *name) return -1; } #endif + +#ifdef CONFIG_TI_SECURE_DEVICE +void board_fit_image_post_process(void **p_image, size_t *p_size) +{ + secure_boot_verify_image(p_image, p_size); +} +#endif diff --git a/board/ti/am57xx/board.c b/board/ti/am57xx/board.c index 08cf14d5e7..927d1364fe 100644 --- a/board/ti/am57xx/board.c +++ b/board/ti/am57xx/board.c @@ -13,6 +13,7 @@ #include <sata.h> #include <usb.h> #include <asm/omap_common.h> +#include <asm/omap_sec_common.h> #include <asm/emif.h> #include <asm/gpio.h> #include <asm/arch/gpio.h> @@ -750,3 +751,10 @@ int board_fit_config_name_match(const char *name) return -1; } #endif + +#ifdef CONFIG_TI_SECURE_DEVICE +void board_fit_image_post_process(void **p_image, size_t *p_size) +{ + secure_boot_verify_image(p_image, p_size); +} +#endif diff --git a/board/ti/dra7xx/evm.c b/board/ti/dra7xx/evm.c index 6a4d02769e..99e82542f7 100644 --- a/board/ti/dra7xx/evm.c +++ b/board/ti/dra7xx/evm.c @@ -17,6 +17,8 @@ #include <asm/gpio.h> #include <usb.h> #include <linux/usb/gadget.h> +#include <asm/omap_common.h> +#include <asm/omap_sec_common.h> #include <asm/arch/gpio.h> #include <asm/arch/dra7xx_iodelay.h> #include <asm/emif.h> @@ -834,3 +836,10 @@ int board_fit_config_name_match(const char *name) return -1; } #endif + +#ifdef CONFIG_TI_SECURE_DEVICE +void board_fit_image_post_process(void **p_image, size_t *p_size) +{ + secure_boot_verify_image(p_image, p_size); +} +#endif diff --git a/common/board_f.c b/common/board_f.c index d405b5b407..8d936cc0b7 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -117,10 +117,11 @@ static int init_func_watchdog_init(void) # if defined(CONFIG_HW_WATCHDOG) && (defined(CONFIG_BLACKFIN) || \ defined(CONFIG_M68K) || defined(CONFIG_MICROBLAZE) || \ defined(CONFIG_SH) || defined(CONFIG_AT91SAM9_WATCHDOG) || \ + defined(CONFIG_DESIGNWARE_WATCHDOG) || \ defined(CONFIG_IMX_WATCHDOG)) hw_watchdog_init(); -# endif puts(" Watchdog enabled\n"); +# endif WATCHDOG_RESET(); return 0; diff --git a/common/bootm.c b/common/bootm.c index 2431019b3f..9ed6428281 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -635,10 +635,6 @@ int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], goto err; else if (ret == BOOTM_ERR_OVERLAP) ret = 0; -#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY) - if (images->os.os == IH_OS_LINUX) - fixup_silent_linux(); -#endif } /* Relocate the ramdisk */ @@ -678,13 +674,19 @@ int do_bootm_states(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[], return 1; } + /* Call various other states that are not generally used */ if (!ret && (states & BOOTM_STATE_OS_CMDLINE)) ret = boot_fn(BOOTM_STATE_OS_CMDLINE, argc, argv, images); if (!ret && (states & BOOTM_STATE_OS_BD_T)) ret = boot_fn(BOOTM_STATE_OS_BD_T, argc, argv, images); - if (!ret && (states & BOOTM_STATE_OS_PREP)) + if (!ret && (states & BOOTM_STATE_OS_PREP)) { +#if defined(CONFIG_SILENT_CONSOLE) && !defined(CONFIG_SILENT_U_BOOT_ONLY) + if (images->os.os == IH_OS_LINUX) + fixup_silent_linux(); +#endif ret = boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images); + } #ifdef CONFIG_TRACE /* Pretend to run the OS, then run a user command */ diff --git a/common/bootm_os.c b/common/bootm_os.c index 9ec84bd0db..e3f5a46412 100644 --- a/common/bootm_os.c +++ b/common/bootm_os.c @@ -481,6 +481,7 @@ int boot_selected_os(int argc, char * const argv[], int state, /* Stand-alone may return when 'autostart' is 'no' */ if (images->os.type == IH_TYPE_STANDALONE || + IS_ENABLED(CONFIG_SANDBOX) || state == BOOTM_STATE_OS_FAKE_GO) /* We expect to return */ return 0; bootstage_error(BOOTSTAGE_ID_BOOT_OS_RETURNED); diff --git a/common/image.c b/common/image.c index 0be09e5c63..af155b229b 100644 --- a/common/image.c +++ b/common/image.c @@ -69,7 +69,7 @@ static const image_header_t *image_get_ramdisk(ulong rd_addr, uint8_t arch, #endif static const table_entry_t uimage_arch[] = { - { IH_ARCH_INVALID, NULL, "Invalid ARCH", }, + { IH_ARCH_INVALID, "invalid", "Invalid ARCH", }, { IH_ARCH_ALPHA, "alpha", "Alpha", }, { IH_ARCH_ARM, "arm", "ARM", }, { IH_ARCH_I386, "x86", "Intel x86", }, @@ -97,7 +97,7 @@ static const table_entry_t uimage_arch[] = { }; static const table_entry_t uimage_os[] = { - { IH_OS_INVALID, NULL, "Invalid OS", }, + { IH_OS_INVALID, "invalid", "Invalid OS", }, { IH_OS_LINUX, "linux", "Linux", }, #if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC) { IH_OS_LYNXOS, "lynxos", "LynxOS", }, @@ -144,7 +144,7 @@ static const table_entry_t uimage_type[] = { { IH_TYPE_KERNEL_NOLOAD, "kernel_noload", "Kernel Image (no loading done)", }, { IH_TYPE_KWBIMAGE, "kwbimage", "Kirkwood Boot Image",}, { IH_TYPE_IMXIMAGE, "imximage", "Freescale i.MX Boot Image",}, - { IH_TYPE_INVALID, NULL, "Invalid Image", }, + { IH_TYPE_INVALID, "invalid", "Invalid Image", }, { IH_TYPE_MULTI, "multi", "Multi-File Image", }, { IH_TYPE_OMAPIMAGE, "omapimage", "TI OMAP SPL With GP CH",}, { IH_TYPE_PBLIMAGE, "pblimage", "Freescale PBL Boot Image",}, @@ -176,6 +176,19 @@ static const table_entry_t uimage_comp[] = { { -1, "", "", }, }; +struct table_info { + const char *desc; + int count; + const table_entry_t *table; +}; + +static const struct table_info table_info[IH_COUNT] = { + { "architecture", IH_ARCH_COUNT, uimage_arch }, + { "compression", IH_COMP_COUNT, uimage_comp }, + { "operating system", IH_OS_COUNT, uimage_os }, + { "image type", IH_TYPE_COUNT, uimage_type }, +}; + /*****************************************************************************/ /* Legacy format routines */ /*****************************************************************************/ @@ -570,6 +583,74 @@ const table_entry_t *get_table_entry(const table_entry_t *table, int id) return NULL; } +static const char *unknown_msg(enum ih_category category) +{ + static char msg[30]; + + strcpy(msg, "Unknown "); + strcat(msg, table_info[category].desc); + + return msg; +} + +/** + * get_cat_table_entry_name - translate entry id to long name + * @category: category to look up (enum ih_category) + * @id: entry id to be translated + * + * This will scan the translation table trying to find the entry that matches + * the given id. + * + * @retur long entry name if translation succeeds; error string on failure + */ +const char *genimg_get_cat_name(enum ih_category category, uint id) +{ + const table_entry_t *entry; + + entry = get_table_entry(table_info[category].table, id); + if (!entry) + return unknown_msg(category); +#if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC) + return entry->lname; +#else + return entry->lname + gd->reloc_off; +#endif +} + +/** + * get_cat_table_entry_short_name - translate entry id to short name + * @category: category to look up (enum ih_category) + * @id: entry id to be translated + * + * This will scan the translation table trying to find the entry that matches + * the given id. + * + * @retur short entry name if translation succeeds; error string on failure + */ +const char *genimg_get_cat_short_name(enum ih_category category, uint id) +{ + const table_entry_t *entry; + + entry = get_table_entry(table_info[category].table, id); + if (!entry) + return unknown_msg(category); +#if defined(USE_HOSTCC) || !defined(CONFIG_NEEDS_MANUAL_RELOC) + return entry->sname; +#else + return entry->sname + gd->reloc_off; +#endif +} + +int genimg_get_cat_count(enum ih_category category) +{ + return table_info[category].count; +} + +const char *genimg_get_cat_desc(enum ih_category category) +{ + return table_info[category].desc; +} + /** * get_table_entry_name - translate entry id to long name * @table: pointer to a translation table for entries of a specific type diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 987470896c..069e94d529 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -132,7 +132,7 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit) int data_offset, data_size; int base_offset, align_len = ARCH_DMA_MINALIGN - 1; int src_sector; - void *dst; + void *dst, *src; /* * Figure out where the external images start. This is the base for the @@ -206,8 +206,13 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit) return -EIO; debug("image: dst=%p, data_offset=%x, size=%x\n", dst, data_offset, data_size); - memcpy(dst, dst + get_aligned_image_overhead(info, data_offset), - data_size); + src = dst + get_aligned_image_overhead(info, data_offset); + +#ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS + board_fit_image_post_process((void **)&src, (size_t *)&data_size); +#endif + + memcpy(dst, src, data_size); /* Figure out which device tree the board wants to use */ fdt_len = spl_fit_select_fdt(fit, images, &fdt_offset); @@ -236,8 +241,14 @@ int spl_load_simple_fit(struct spl_load_info *info, ulong sector, void *fit) */ debug("fdt: dst=%p, data_offset=%x, size=%x\n", dst, fdt_offset, fdt_len); - memcpy(load_ptr + data_size, - dst + get_aligned_image_overhead(info, fdt_offset), fdt_len); + src = dst + get_aligned_image_overhead(info, fdt_offset); + dst = load_ptr + data_size; + +#ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS + board_fit_image_post_process((void **)&src, (size_t *)&fdt_len); +#endif + + memcpy(dst, src, fdt_len); return 0; } diff --git a/configs/am43xx_hs_evm_defconfig b/configs/am43xx_hs_evm_defconfig index 4856a19f0b..68dfb6c575 100644 --- a/configs/am43xx_hs_evm_defconfig +++ b/configs/am43xx_hs_evm_defconfig @@ -13,6 +13,7 @@ CONFIG_SPL_STACK_R=y CONFIG_FIT=y CONFIG_SYS_EXTRA_OPTIONS="CONS_INDEX=1, NAND" CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y CONFIG_HUSH_PARSER=y CONFIG_CMD_BOOTZ=y # CONFIG_CMD_IMLS is not set diff --git a/configs/am57xx_hs_evm_defconfig b/configs/am57xx_hs_evm_defconfig index e01e50482a..01a4701dab 100644 --- a/configs/am57xx_hs_evm_defconfig +++ b/configs/am57xx_hs_evm_defconfig @@ -40,4 +40,5 @@ CONFIG_USB_XHCI_DWC3=y CONFIG_FIT=y CONFIG_SPL_OF_LIBFDT=y CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y CONFIG_OF_LIST="am57xx-beagle-x15" diff --git a/configs/da850evm_defconfig b/configs/da850evm_defconfig index 0e281a5e67..40ab975f02 100644 --- a/configs/da850evm_defconfig +++ b/configs/da850evm_defconfig @@ -5,6 +5,7 @@ CONFIG_SPL=y CONFIG_SYS_EXTRA_OPTIONS="MAC_ADDR_IN_SPIFLASH" CONFIG_BOOTDELAY=3 CONFIG_HUSH_PARSER=y +CONFIG_CMD_BOOTZ=y CONFIG_SYS_PROMPT="U-Boot > " # CONFIG_CMD_IMLS is not set CONFIG_CMD_ASKENV=y diff --git a/configs/dra7xx_hs_evm_defconfig b/configs/dra7xx_hs_evm_defconfig index 6933ab5cc6..eb01f41d02 100644 --- a/configs/dra7xx_hs_evm_defconfig +++ b/configs/dra7xx_hs_evm_defconfig @@ -58,4 +58,5 @@ CONFIG_G_DNL_PRODUCT_NUM=0xd022 CONFIG_FIT=y CONFIG_SPL_OF_LIBFDT=y CONFIG_SPL_LOAD_FIT=y +CONFIG_SPL_FIT_IMAGE_POST_PROCESS=y CONFIG_OF_LIST="dra7-evm dra72-evm" diff --git a/doc/README.ti-secure b/doc/README.ti-secure index 7fc9b9bc30..54c996d8f6 100644 --- a/doc/README.ti-secure +++ b/doc/README.ti-secure @@ -19,69 +19,80 @@ control restrictions. Access must be requested and granted by TI before the package is viewable and downloadable. Contact TI, either online or by way of a local TI representative, to request access. -When CONFIG_TI_SECURE_DEVICE is set, the U-Boot SPL build process requires -the presence and use of these tools in order to create a viable boot image. -The build process will look for the environment variable TI_SECURE_DEV_PKG, -which should be the path of the installed SECDEV package. If the -TI_SECURE_DEV_PKG variable is not defined or if it is defined but doesn't -point to a valid SECDEV package, a warning is issued during the build to -indicate that a final secure bootable image was not created. - -Within the SECDEV package exists an image creation script: - -${TI_SECURE_DEV_PKG}/scripts/create-boot-image.sh - -This is called as part of the SPL/u-boot build process. As the secure boot -image formats and requirements differ between secure SOC from TI, the -purpose of this script is to abstract these details as much as possible. - -The script is basically the only required interface to the TI SECDEV package -for secure TI devices. - -Invoking the script for AM43xx Secure Devices -============================================= - -create-boot-image.sh <IMAGE_FLAG> <INPUT_FILE> <OUTPUT_FILE> <SPL_LOAD_ADDR> - -<IMAGE_FLAG> is a value that specifies the type of the image to generate OR -the action the image generation tool will take. Valid values are: - SPI_X-LOADER - Generates an image for SPI flash (byte swapped) - XIP_X-LOADER - Generates a single stage u-boot for NOR/QSPI XiP - ISSW - Generates an image for all other boot modes - -<INPUT_FILE> is the full path and filename of the public world boot loader -binary file (depending on the boot media, this is usually either -u-boot-spl.bin or u-boot.bin). - -<OUTPUT_FILE> is the full path and filename of the final secure image. The -output binary images should be used in place of the standard non-secure -binary images (see the platform-specific user's guides and releases notes -for how the non-secure images are typically used) +Booting of U-Boot SPL +===================== + + When CONFIG_TI_SECURE_DEVICE is set, the U-Boot SPL build process + requires the presence and use of these tools in order to create a + viable boot image. The build process will look for the environment + variable TI_SECURE_DEV_PKG, which should be the path of the installed + SECDEV package. If the TI_SECURE_DEV_PKG variable is not defined or + if it is defined but doesn't point to a valid SECDEV package, a + warning is issued during the build to indicate that a final secure + bootable image was not created. + + Within the SECDEV package exists an image creation script: + + ${TI_SECURE_DEV_PKG}/scripts/create-boot-image.sh + + This is called as part of the SPL/u-boot build process. As the secure + boot image formats and requirements differ between secure SOC from TI, + the purpose of this script is to abstract these details as much as + possible. + + The script is basically the only required interface to the TI SECDEV + package for creating a bootable SPL image for secure TI devices. + + Invoking the script for AM43xx Secure Devices + ============================================= + + create-boot-image.sh \ + <IMAGE_FLAG> <INPUT_FILE> <OUTPUT_FILE> <SPL_LOAD_ADDR> + + <IMAGE_FLAG> is a value that specifies the type of the image to + generate OR the action the image generation tool will take. Valid + values are: + SPI_X-LOADER - Generates an image for SPI flash (byte + swapped) + XIP_X-LOADER - Generates a single stage u-boot for + NOR/QSPI XiP + ISSW - Generates an image for all other boot modes + + <INPUT_FILE> is the full path and filename of the public world boot + loaderbinary file (depending on the boot media, this is usually + either u-boot-spl.bin or u-boot.bin). + + <OUTPUT_FILE> is the full path and filename of the final secure + image. The output binary images should be used in place of the standard + non-secure binary images (see the platform-specific user's guides and + releases notes for how the non-secure images are typically used) u-boot-spl_HS_SPI_X-LOADER - byte swapped boot image for SPI flash u-boot_HS_XIP_X-LOADER - boot image for NOR or QSPI flash u-boot-spl_HS_ISSW - boot image for all other boot media -<SPL_LOAD_ADDR> is the address at which SOC ROM should load the <INPUT_FILE> + <SPL_LOAD_ADDR> is the address at which SOC ROM should load the + <INPUT_FILE> -Invoking the script for DRA7xx/AM57xx Secure Devices -==================================================== + Invoking the script for DRA7xx/AM57xx Secure Devices + ==================================================== -create-boot-image.sh <IMAGE_TYPE> <INPUT_FILE> <OUTPUT_FILE> + create-boot-image.sh <IMAGE_TYPE> <INPUT_FILE> <OUTPUT_FILE> -<IMAGE_TYPE> is a value that specifies the type of the image to generate OR -the action the image generation tool will take. Valid values are: - X-LOADER - Generates an image for NOR or QSPI boot modes - MLO - Generates an image for SD/MMC/eMMC boot modes - ULO - Generates an image for USB/UART peripheral boot modes - Note: ULO is not yet used by the u-boot build process + <IMAGE_TYPE> is a value that specifies the type of the image to + generate OR the action the image generation tool will take. Valid + values are: + X-LOADER - Generates an image for NOR or QSPI boot modes + MLO - Generates an image for SD/MMC/eMMC boot modes + ULO - Generates an image for USB/UART peripheral boot modes + Note: ULO is not yet used by the u-boot build process -<INPUT_FILE> is the full path and filename of the public world boot loader -binary file (for this platform, this is always u-boot-spl.bin). + <INPUT_FILE> is the full path and filename of the public world boot + loader binary file (for this platform, this is always u-boot-spl.bin). -<OUTPUT_FILE> is the full path and filename of the final secure image. The -output binary images should be used in place of the standard non-secure -binary images (see the platform-specific user's guides and releases notes -for how the non-secure images are typically used) + <OUTPUT_FILE> is the full path and filename of the final secure image. + The output binary images should be used in place of the standard + non-secure binary images (see the platform-specific user's guides + and releases notes for how the non-secure images are typically used) u-boot-spl_HS_MLO - boot image for SD/MMC/eMMC. This image is copied to a file named MLO, which is the name that the device ROM bootloader requires for loading from @@ -89,3 +100,61 @@ for how the non-secure images are typically used) non-secure devices) u-boot-spl_HS_X-LOADER - boot image for all other flash memories including QSPI and NOR flash + +Booting of Primary U-Boot (u-boot.img) +====================================== + + The SPL image is responsible for loading the next stage boot loader, + which is the main u-boot image. For secure TI devices, the SPL will + be authenticated, as described above, as part of the particular + device's ROM boot process. In order to continue the secure boot + process, the authenticated SPL must authenticate the main u-boot + image that it loads. + + The configurations for secure TI platforms are written to make the boot + process use the FIT image format for the u-boot.img (CONFIG_SPL_FRAMEWORK + and CONFIG_SPL_LOAD_FIT). With these configurations the binary + components that the SPL loads include a specific DTB image and u-boot + image. These DTB image may be one of many available to the boot + process. In order to secure these components so that they can be + authenticated by the SPL as they are loaded from the FIT image, the + build procedure for secure TI devices will secure these images before + they are integrated into the FIT image. When those images are extracted + from the FIT image at boot time, they are post-processed to verify that + they are still secure. The outlined security-related SPL post-processing + is enabled through the CONFIG_SPL_FIT_IMAGE_POST_PROCESS option which + must be enabled for the secure boot scheme to work. In order to allow + verifying proper operation of the secure boot chain in case of successful + authentication messages like "Authentication passed: CERT_U-BOOT-NOD" are + output by the SPL to the console for each blob that got extracted from the + FIT image. Note that the last part of this log message is the (truncated) + name of the signing certificate embedded into the blob that got processed. + + The exact details of the how the images are secured is handled by the + SECDEV package. Within the SECDEV package exists a script to process + an input binary image: + + ${TI_SECURE_DEV_PKG}/scripts/secure-binary-image.sh + + This is called as part of the u-boot build process. As the secure + image formats and requirements can differ between the various secure + SOCs from TI, this script in the SECDEV package abstracts these + details. This script is essentially the only required interface to the + TI SECDEV package for creating a u-boot.img image for secure TI + devices. + + The SPL/u-boot code contains calls to dedicated secure ROM functions + to perform the validation on the secured images. The details of the + interface to those functions is shown in the code. The summary + is that they are accessed by invoking an ARM secure monitor call to + the device's secure ROM (fixed read-only-memory that is secure and + only accessible when the ARM core is operating in the secure mode). + + Invoking the secure-binary-image script for Secure Devices + ========================================================== + + secure-binary-image.sh <INPUT_FILE> <OUTPUT_FILE> + + <INPUT_FILE> is the full path and filename of the input binary image + + <OUTPUT_FILE> is the full path and filename of the output secure image. diff --git a/drivers/rtc/date.c b/drivers/rtc/date.c index 8c643a0b46..bfa2e1378e 100644 --- a/drivers/rtc/date.c +++ b/drivers/rtc/date.c @@ -5,10 +5,6 @@ * SPDX-License-Identifier: GPL-2.0+ */ -/* - * Date & Time support for Philips PCF8563 RTC - */ - #include <common.h> #include <command.h> #include <errno.h> @@ -28,53 +24,52 @@ static int month_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +static int month_offset[] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 +}; + /* * This only works for the Gregorian calendar - i.e. after 1752 (in the UK) */ int rtc_calc_weekday(struct rtc_time *tm) { - int leapsToDate; - int lastYear; + int leaps_to_date; + int last_year; int day; - int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 }; if (tm->tm_year < 1753) - return -EINVAL; - lastYear=tm->tm_year-1; + return -1; + last_year = tm->tm_year - 1; - /* - * Number of leap corrections to apply up to end of last year - */ - leapsToDate = lastYear/4 - lastYear/100 + lastYear/400; + /* Number of leap corrections to apply up to end of last year */ + leaps_to_date = last_year / 4 - last_year / 100 + last_year / 400; /* * This year is a leap year if it is divisible by 4 except when it is * divisible by 100 unless it is divisible by 400 * - * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be + * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 is. */ - if((tm->tm_year%4==0) && - ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) && - (tm->tm_mon>2)) { - /* - * We are past Feb. 29 in a leap year - */ - day=1; + if (tm->tm_year % 4 == 0 && + ((tm->tm_year % 100 != 0) || (tm->tm_year % 400 == 0)) && + tm->tm_mon > 2) { + /* We are past Feb. 29 in a leap year */ + day = 1; } else { - day=0; + day = 0; } - day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday; - - tm->tm_wday=day%7; + day += last_year * 365 + leaps_to_date + month_offset[tm->tm_mon - 1] + + tm->tm_mday; + tm->tm_wday = day % 7; return 0; } int rtc_to_tm(int tim, struct rtc_time *tm) { - register int i; - register long hms, day; + register int i; + register long hms, day; day = tim / SECDAY; hms = tim % SECDAY; @@ -85,22 +80,19 @@ int rtc_to_tm(int tim, struct rtc_time *tm) tm->tm_sec = (hms % 3600) % 60; /* Number of years in days */ - for (i = STARTOFTIME; day >= days_in_year(i); i++) { + for (i = STARTOFTIME; day >= days_in_year(i); i++) day -= days_in_year(i); - } tm->tm_year = i; /* Number of months in days left */ - if (leapyear(tm->tm_year)) { + if (leapyear(tm->tm_year)) days_in_month(FEBRUARY) = 29; - } - for (i = 1; day >= days_in_month(i); i++) { + for (i = 1; day >= days_in_month(i); i++) day -= days_in_month(i); - } days_in_month(FEBRUARY) = 28; tm->tm_mon = i; - /* Days are what is left over (+1) from all that. */ + /* Days are what is left over (+1) from all that */ tm->tm_mday = day + 1; /* Zero unused fields */ @@ -113,19 +105,20 @@ int rtc_to_tm(int tim, struct rtc_time *tm) return rtc_calc_weekday(tm); } -/* Converts Gregorian date to seconds since 1970-01-01 00:00:00. +/* + * Converts Gregorian date to seconds since 1970-01-01 00:00:00. * Assumes input in normal date format, i.e. 1980-12-31 23:59:59 * => year=1980, mon=12, day=31, hour=23, min=59, sec=59. * * [For the Julian calendar (which was used in Russia before 1917, * Britain & colonies before 1752, anywhere else before 1582, * and is still in use by some communities) leave out the - * -year/100+year/400 terms, and add 10.] + * -year / 100 + year / 400 terms, and add 10.] * * This algorithm was first published by Gauss (I think). * * WARNING: this function will overflow on 2106-02-07 06:28:16 on - * machines were long is 32-bit! (However, as time_t is signed, we + * machines where long is 32-bit! (However, as time_t is signed, we * will already get problems at other places on 2038-01-19 03:14:08) */ unsigned long rtc_mktime(const struct rtc_time *tm) @@ -135,8 +128,8 @@ unsigned long rtc_mktime(const struct rtc_time *tm) int days, hours; mon -= 2; - if (0 >= (int)mon) { /* 1..12 -> 11,12,1..10 */ - mon += 12; /* Puts Feb last since it has leap day */ + if (0 >= (int)mon) { /* 1..12 -> 11, 12, 1..10 */ + mon += 12; /* Puts Feb last since it has leap day */ year -= 1; } diff --git a/drivers/serial/serial_stm32x7.c b/drivers/serial/serial_stm32x7.c index cfbfab7e41..592c0bde36 100644 --- a/drivers/serial/serial_stm32x7.c +++ b/drivers/serial/serial_stm32x7.c @@ -9,6 +9,7 @@ #include <dm.h> #include <asm/io.h> #include <serial.h> +#include <asm/arch/stm32.h> #include <dm/platform_data/serial_stm32x7.h> #include "serial_stm32x7.h" @@ -18,7 +19,20 @@ static int stm32_serial_setbrg(struct udevice *dev, int baudrate) { struct stm32x7_serial_platdata *plat = dev->platdata; struct stm32_usart *const usart = plat->base; - writel(plat->clock/baudrate, &usart->brr); + u32 clock, int_div, frac_div, tmp; + + if (((u32)usart & STM32_BUS_MASK) == APB1_PERIPH_BASE) + clock = clock_get(CLOCK_APB1); + else if (((u32)usart & STM32_BUS_MASK) == APB2_PERIPH_BASE) + clock = clock_get(CLOCK_APB2); + else + return -EINVAL; + + int_div = (25 * clock) / (4 * baudrate); + tmp = ((int_div / 100) << USART_BRR_M_SHIFT) & USART_BRR_M_MASK; + frac_div = int_div - (100 * (tmp >> USART_BRR_M_SHIFT)); + tmp |= (((frac_div * 16) + 50) / 100) & USART_BRR_F_MASK; + writel(tmp, &usart->brr); return 0; } diff --git a/include/common.h b/include/common.h index 3feaae641c..e9f0dea308 100644 --- a/include/common.h +++ b/include/common.h @@ -101,6 +101,13 @@ typedef volatile unsigned char vu_char; #define _DEBUG 0 #endif +#ifdef CONFIG_SPL_BUILD +#define _SPL_BUILD 1 +#else +#define _SPL_BUILD 0 +#endif + +/* Define this at the top of a file to add a prefix to debug messages */ #ifndef pr_fmt #define pr_fmt(fmt) fmt #endif @@ -116,9 +123,14 @@ typedef volatile unsigned char vu_char; printf(pr_fmt(fmt), ##args); \ } while (0) +/* Show a message if DEBUG is defined in a file */ #define debug(fmt, args...) \ debug_cond(_DEBUG, fmt, ##args) +/* Show a message if not in SPL */ +#define warn_non_spl(fmt, args...) \ + debug_cond(!_SPL_BUILD, fmt, ##args) + /* * An assertion is run-time check done in debug mode only. If DEBUG is not * defined then it is skipped. If DEBUG is defined and the assertion fails, diff --git a/include/configs/dragonboard410c.h b/include/configs/dragonboard410c.h index 4b009223b2..1dbe2194f8 100644 --- a/include/configs/dragonboard410c.h +++ b/include/configs/dragonboard410c.h @@ -84,8 +84,8 @@ #define BOOT_TARGET_DEVICES(func) \ func(USB, usb, 0) \ - func(MMC, mmc, 0) \ func(MMC, mmc, 1) \ + func(MMC, mmc, 0) \ func(DHCP, dhcp, na) #include <config_distro_bootcmd.h> @@ -126,6 +126,8 @@ REFLASH(dragonboard/u-boot.img, 8)\ "fdtfile=apq8016-sbc.dtb\0" \ "fdt_addr_r=0x83000000\0"\ "ramdisk_addr_r=0x84000000\0"\ + "scriptaddr=0x90000000\0"\ + "pxefile_addr_r=0x90100000\0"\ BOOTENV #define CONFIG_ENV_IS_NOWHERE diff --git a/include/configs/stm32f746-disco.h b/include/configs/stm32f746-disco.h index e544a218dd..4391bff1cc 100644 --- a/include/configs/stm32f746-disco.h +++ b/include/configs/stm32f746-disco.h @@ -24,13 +24,13 @@ * Configuration of the external SDRAM memory */ #define CONFIG_NR_DRAM_BANKS 1 -#define CONFIG_SYS_RAM_SIZE ((64 + 192) << 10) +#define CONFIG_SYS_RAM_SIZE (8 * 1024 * 1024) #define CONFIG_SYS_RAM_CS 1 #define CONFIG_SYS_RAM_FREQ_DIV 2 -#define CONFIG_SYS_RAM_BASE 0x20000000 +#define CONFIG_SYS_RAM_BASE 0xC0000000 #define CONFIG_SYS_SDRAM_BASE CONFIG_SYS_RAM_BASE -#define CONFIG_SYS_LOAD_ADDR 0x20000000 -#define CONFIG_LOADADDR 0x20000000 +#define CONFIG_SYS_LOAD_ADDR 0xC0400000 +#define CONFIG_LOADADDR 0xC0400000 #define CONFIG_SYS_MAX_FLASH_SECT 8 #define CONFIG_SYS_MAX_FLASH_BANKS 1 @@ -42,7 +42,8 @@ #define CONFIG_STM32_FLASH #define CONFIG_STM32X7_SERIAL -#define CONFIG_SYS_CLK_FREQ 16*1000*1000 /* 180 MHz */ +#define CONFIG_STM32_HSE_HZ 25000000 +#define CONFIG_SYS_CLK_FREQ 200000000 /* 200 MHz */ #define CONFIG_SYS_HZ_CLOCK 1000000 /* Timer is clocked at 1MHz */ #define CONFIG_CMDLINE_TAG diff --git a/include/image.h b/include/image.h index d788c260e3..2a5b560575 100644 --- a/include/image.h +++ b/include/image.h @@ -123,62 +123,79 @@ struct lmb; # define IMAGE_OF_SYSTEM_SETUP 0 #endif +enum ih_category { + IH_ARCH, + IH_COMP, + IH_OS, + IH_TYPE, + + IH_COUNT, +}; + /* * Operating System Codes */ -#define IH_OS_INVALID 0 /* Invalid OS */ -#define IH_OS_OPENBSD 1 /* OpenBSD */ -#define IH_OS_NETBSD 2 /* NetBSD */ -#define IH_OS_FREEBSD 3 /* FreeBSD */ -#define IH_OS_4_4BSD 4 /* 4.4BSD */ -#define IH_OS_LINUX 5 /* Linux */ -#define IH_OS_SVR4 6 /* SVR4 */ -#define IH_OS_ESIX 7 /* Esix */ -#define IH_OS_SOLARIS 8 /* Solaris */ -#define IH_OS_IRIX 9 /* Irix */ -#define IH_OS_SCO 10 /* SCO */ -#define IH_OS_DELL 11 /* Dell */ -#define IH_OS_NCR 12 /* NCR */ -#define IH_OS_LYNXOS 13 /* LynxOS */ -#define IH_OS_VXWORKS 14 /* VxWorks */ -#define IH_OS_PSOS 15 /* pSOS */ -#define IH_OS_QNX 16 /* QNX */ -#define IH_OS_U_BOOT 17 /* Firmware */ -#define IH_OS_RTEMS 18 /* RTEMS */ -#define IH_OS_ARTOS 19 /* ARTOS */ -#define IH_OS_UNITY 20 /* Unity OS */ -#define IH_OS_INTEGRITY 21 /* INTEGRITY */ -#define IH_OS_OSE 22 /* OSE */ -#define IH_OS_PLAN9 23 /* Plan 9 */ -#define IH_OS_OPENRTOS 24 /* OpenRTOS */ +enum { + IH_OS_INVALID = 0, /* Invalid OS */ + IH_OS_OPENBSD, /* OpenBSD */ + IH_OS_NETBSD, /* NetBSD */ + IH_OS_FREEBSD, /* FreeBSD */ + IH_OS_4_4BSD, /* 4.4BSD */ + IH_OS_LINUX, /* Linux */ + IH_OS_SVR4, /* SVR4 */ + IH_OS_ESIX, /* Esix */ + IH_OS_SOLARIS, /* Solaris */ + IH_OS_IRIX, /* Irix */ + IH_OS_SCO, /* SCO */ + IH_OS_DELL, /* Dell */ + IH_OS_NCR, /* NCR */ + IH_OS_LYNXOS, /* LynxOS */ + IH_OS_VXWORKS, /* VxWorks */ + IH_OS_PSOS, /* pSOS */ + IH_OS_QNX, /* QNX */ + IH_OS_U_BOOT, /* Firmware */ + IH_OS_RTEMS, /* RTEMS */ + IH_OS_ARTOS, /* ARTOS */ + IH_OS_UNITY, /* Unity OS */ + IH_OS_INTEGRITY, /* INTEGRITY */ + IH_OS_OSE, /* OSE */ + IH_OS_PLAN9, /* Plan 9 */ + IH_OS_OPENRTOS, /* OpenRTOS */ + + IH_OS_COUNT, +}; /* * CPU Architecture Codes (supported by Linux) */ -#define IH_ARCH_INVALID 0 /* Invalid CPU */ -#define IH_ARCH_ALPHA 1 /* Alpha */ -#define IH_ARCH_ARM 2 /* ARM */ -#define IH_ARCH_I386 3 /* Intel x86 */ -#define IH_ARCH_IA64 4 /* IA64 */ -#define IH_ARCH_MIPS 5 /* MIPS */ -#define IH_ARCH_MIPS64 6 /* MIPS 64 Bit */ -#define IH_ARCH_PPC 7 /* PowerPC */ -#define IH_ARCH_S390 8 /* IBM S390 */ -#define IH_ARCH_SH 9 /* SuperH */ -#define IH_ARCH_SPARC 10 /* Sparc */ -#define IH_ARCH_SPARC64 11 /* Sparc 64 Bit */ -#define IH_ARCH_M68K 12 /* M68K */ -#define IH_ARCH_MICROBLAZE 14 /* MicroBlaze */ -#define IH_ARCH_NIOS2 15 /* Nios-II */ -#define IH_ARCH_BLACKFIN 16 /* Blackfin */ -#define IH_ARCH_AVR32 17 /* AVR32 */ -#define IH_ARCH_ST200 18 /* STMicroelectronics ST200 */ -#define IH_ARCH_SANDBOX 19 /* Sandbox architecture (test only) */ -#define IH_ARCH_NDS32 20 /* ANDES Technology - NDS32 */ -#define IH_ARCH_OPENRISC 21 /* OpenRISC 1000 */ -#define IH_ARCH_ARM64 22 /* ARM64 */ -#define IH_ARCH_ARC 23 /* Synopsys DesignWare ARC */ -#define IH_ARCH_X86_64 24 /* AMD x86_64, Intel and Via */ +enum { + IH_ARCH_INVALID = 0, /* Invalid CPU */ + IH_ARCH_ALPHA, /* Alpha */ + IH_ARCH_ARM, /* ARM */ + IH_ARCH_I386, /* Intel x86 */ + IH_ARCH_IA64, /* IA64 */ + IH_ARCH_MIPS, /* MIPS */ + IH_ARCH_MIPS64, /* MIPS 64 Bit */ + IH_ARCH_PPC, /* PowerPC */ + IH_ARCH_S390, /* IBM S390 */ + IH_ARCH_SH, /* SuperH */ + IH_ARCH_SPARC, /* Sparc */ + IH_ARCH_SPARC64, /* Sparc 64 Bit */ + IH_ARCH_M68K, /* M68K */ + IH_ARCH_MICROBLAZE, /* MicroBlaze */ + IH_ARCH_NIOS2, /* Nios-II */ + IH_ARCH_BLACKFIN, /* Blackfin */ + IH_ARCH_AVR32, /* AVR32 */ + IH_ARCH_ST200, /* STMicroelectronics ST200 */ + IH_ARCH_SANDBOX, /* Sandbox architecture (test only) */ + IH_ARCH_NDS32, /* ANDES Technology - NDS32 */ + IH_ARCH_OPENRISC, /* OpenRISC 1000 */ + IH_ARCH_ARM64, /* ARM64 */ + IH_ARCH_ARC, /* Synopsys DesignWare ARC */ + IH_ARCH_X86_64, /* AMD x86_64, Intel and Via */ + + IH_ARCH_COUNT, +}; /* * Image Types @@ -219,47 +236,54 @@ struct lmb; * as command interpreter (=> Shell Scripts). */ -#define IH_TYPE_INVALID 0 /* Invalid Image */ -#define IH_TYPE_STANDALONE 1 /* Standalone Program */ -#define IH_TYPE_KERNEL 2 /* OS Kernel Image */ -#define IH_TYPE_RAMDISK 3 /* RAMDisk Image */ -#define IH_TYPE_MULTI 4 /* Multi-File Image */ -#define IH_TYPE_FIRMWARE 5 /* Firmware Image */ -#define IH_TYPE_SCRIPT 6 /* Script file */ -#define IH_TYPE_FILESYSTEM 7 /* Filesystem Image (any type) */ -#define IH_TYPE_FLATDT 8 /* Binary Flat Device Tree Blob */ -#define IH_TYPE_KWBIMAGE 9 /* Kirkwood Boot Image */ -#define IH_TYPE_IMXIMAGE 10 /* Freescale IMXBoot Image */ -#define IH_TYPE_UBLIMAGE 11 /* Davinci UBL Image */ -#define IH_TYPE_OMAPIMAGE 12 /* TI OMAP Config Header Image */ -#define IH_TYPE_AISIMAGE 13 /* TI Davinci AIS Image */ -#define IH_TYPE_KERNEL_NOLOAD 14 /* OS Kernel Image, can run from any load address */ -#define IH_TYPE_PBLIMAGE 15 /* Freescale PBL Boot Image */ -#define IH_TYPE_MXSIMAGE 16 /* Freescale MXSBoot Image */ -#define IH_TYPE_GPIMAGE 17 /* TI Keystone GPHeader Image */ -#define IH_TYPE_ATMELIMAGE 18 /* ATMEL ROM bootable Image */ -#define IH_TYPE_SOCFPGAIMAGE 19 /* Altera SOCFPGA Preloader */ -#define IH_TYPE_X86_SETUP 20 /* x86 setup.bin Image */ -#define IH_TYPE_LPC32XXIMAGE 21 /* x86 setup.bin Image */ -#define IH_TYPE_LOADABLE 22 /* A list of typeless images */ -#define IH_TYPE_RKIMAGE 23 /* Rockchip Boot Image */ -#define IH_TYPE_RKSD 24 /* Rockchip SD card */ -#define IH_TYPE_RKSPI 25 /* Rockchip SPI image */ -#define IH_TYPE_ZYNQIMAGE 26 /* Xilinx Zynq Boot Image */ -#define IH_TYPE_ZYNQMPIMAGE 27 /* Xilinx ZynqMP Boot Image */ -#define IH_TYPE_FPGA 28 /* FPGA Image */ - -#define IH_TYPE_COUNT 29 /* Number of image types */ +enum { + IH_TYPE_INVALID = 0, /* Invalid Image */ + IH_TYPE_STANDALONE, /* Standalone Program */ + IH_TYPE_KERNEL, /* OS Kernel Image */ + IH_TYPE_RAMDISK, /* RAMDisk Image */ + IH_TYPE_MULTI, /* Multi-File Image */ + IH_TYPE_FIRMWARE, /* Firmware Image */ + IH_TYPE_SCRIPT, /* Script file */ + IH_TYPE_FILESYSTEM, /* Filesystem Image (any type) */ + IH_TYPE_FLATDT, /* Binary Flat Device Tree Blob */ + IH_TYPE_KWBIMAGE, /* Kirkwood Boot Image */ + IH_TYPE_IMXIMAGE, /* Freescale IMXBoot Image */ + IH_TYPE_UBLIMAGE, /* Davinci UBL Image */ + IH_TYPE_OMAPIMAGE, /* TI OMAP Config Header Image */ + IH_TYPE_AISIMAGE, /* TI Davinci AIS Image */ + /* OS Kernel Image, can run from any load address */ + IH_TYPE_KERNEL_NOLOAD, + IH_TYPE_PBLIMAGE, /* Freescale PBL Boot Image */ + IH_TYPE_MXSIMAGE, /* Freescale MXSBoot Image */ + IH_TYPE_GPIMAGE, /* TI Keystone GPHeader Image */ + IH_TYPE_ATMELIMAGE, /* ATMEL ROM bootable Image */ + IH_TYPE_SOCFPGAIMAGE, /* Altera SOCFPGA Preloader */ + IH_TYPE_X86_SETUP, /* x86 setup.bin Image */ + IH_TYPE_LPC32XXIMAGE, /* x86 setup.bin Image */ + IH_TYPE_LOADABLE, /* A list of typeless images */ + IH_TYPE_RKIMAGE, /* Rockchip Boot Image */ + IH_TYPE_RKSD, /* Rockchip SD card */ + IH_TYPE_RKSPI, /* Rockchip SPI image */ + IH_TYPE_ZYNQIMAGE, /* Xilinx Zynq Boot Image */ + IH_TYPE_ZYNQMPIMAGE, /* Xilinx ZynqMP Boot Image */ + IH_TYPE_FPGA, /* FPGA Image */ + + IH_TYPE_COUNT, /* Number of image types */ +}; /* * Compression Types */ -#define IH_COMP_NONE 0 /* No Compression Used */ -#define IH_COMP_GZIP 1 /* gzip Compression Used */ -#define IH_COMP_BZIP2 2 /* bzip2 Compression Used */ -#define IH_COMP_LZMA 3 /* lzma Compression Used */ -#define IH_COMP_LZO 4 /* lzo Compression Used */ -#define IH_COMP_LZ4 5 /* lz4 Compression Used */ +enum { + IH_COMP_NONE = 0, /* No Compression Used */ + IH_COMP_GZIP, /* gzip Compression Used */ + IH_COMP_BZIP2, /* bzip2 Compression Used */ + IH_COMP_LZMA, /* lzma Compression Used */ + IH_COMP_LZO, /* lzo Compression Used */ + IH_COMP_LZ4, /* lz4 Compression Used */ + + IH_COMP_COUNT, +}; #define IH_MAGIC 0x27051956 /* Image Magic Number */ #define IH_NMLEN 32 /* Image Name Length */ @@ -454,6 +478,40 @@ const char *genimg_get_comp_name(uint8_t comp); */ const char *genimg_get_comp_short_name(uint8_t comp); +/** + * genimg_get_cat_name() - Get the name of an item in a category + * + * @category: Category of item + * @id: Item ID + * @return name of item, or "Unknown ..." if unknown + */ +const char *genimg_get_cat_name(enum ih_category category, uint id); + +/** + * genimg_get_cat_short_name() - Get the short name of an item in a category + * + * @category: Category of item + * @id: Item ID + * @return short name of item, or "Unknown ..." if unknown + */ +const char *genimg_get_cat_short_name(enum ih_category category, uint id); + +/** + * genimg_get_cat_count() - Get the number of items in a category + * + * @category: Category to check + * @return the number of items in the category (IH_xxx_COUNT) + */ +int genimg_get_cat_count(enum ih_category category); + +/** + * genimg_get_cat_desc() - Get the description of a category + * + * @return the description of a category, e.g. "architecture". This + * effectively converts the enum to a string. + */ +const char *genimg_get_cat_desc(enum ih_category category); + int genimg_get_os_id(const char *name); int genimg_get_arch_id(const char *name); int genimg_get_type_id(const char *name); @@ -1173,4 +1231,21 @@ void android_print_contents(const struct andr_img_hdr *hdr); */ int board_fit_config_name_match(const char *name); +#ifdef CONFIG_SPL_FIT_IMAGE_POST_PROCESS +/** + * board_fit_image_post_process() - Do any post-process on FIT binary data + * + * This is used to do any sort of image manipulation, verification, decryption + * etc. in a platform or board specific way. Obviously, anything done here would + * need to be comprehended in how the images were prepared before being injected + * into the FIT creation (i.e. the binary blobs would have been pre-processed + * before being added to the FIT image). + * + * @image: pointer to the image start pointer + * @size: pointer to the image size + * @return no return value (failure should be handled internally) + */ +void board_fit_image_post_process(void **p_image, size_t *p_size); +#endif /* CONFIG_SPL_FIT_IMAGE_POST_PROCESS */ + #endif /* __IMAGE_H__ */ diff --git a/include/linux/io.h b/include/linux/io.h index 1b36a2299e..a104b7e69f 100644 --- a/include/linux/io.h +++ b/include/linux/io.h @@ -5,6 +5,22 @@ #ifndef _LINUX_IO_H #define _LINUX_IO_H +#include <linux/compiler.h> +#include <linux/types.h> #include <asm/io.h> +#ifndef CONFIG_HAVE_ARCH_IOREMAP +static inline void __iomem *ioremap(resource_size_t offset, + resource_size_t size) +{ + return (void __iomem *)(unsigned long)offset; +} + +static inline void iounmap(void __iomem *addr) +{ +} + +#define devm_ioremap(dev, offset, size) ioremap(offset, size) +#endif + #endif /* _LINUX_IO_H */ diff --git a/include/linux/types.h b/include/linux/types.h index 6f75be4253..416fa66284 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -124,6 +124,10 @@ typedef __UINT64_TYPE__ u_int64_t; typedef __INT64_TYPE__ int64_t; #endif +#ifdef __KERNEL__ +typedef phys_addr_t resource_size_t; +#endif + /* * Below are truly Linux-specific types that should never collide with * any application/library that wants linux/types.h. diff --git a/test/README b/test/README new file mode 100644 index 0000000000..ee559729b0 --- /dev/null +++ b/test/README @@ -0,0 +1,92 @@ +Testing in U-Boot +================= + +U-Boot has a large amount of code. This file describes how this code is +tested and what tests you should write when adding a new feature. + + +Running tests +------------- + +To run most tests on sandbox, type this: + + test/run + +in the U-Boot directory. Note that only the pytest suite is run using this +comment. + + +Sandbox +------- +U-Boot can be built as a user-space application (e.g. for Linux). This +allows test to be executed without needing target hardware. The 'sandbox' +target provides this feature and it is widely used in tests. + + +Pytest Suite +------------ + +Many tests are available using the pytest suite, in test/py. This can run +either on sandbox or on real hardware. It relies on the U-Boot console to +inject test commands and check the result. It is slower to run than C code, +but provides the ability to unify lots of test and summarise their results. + +You can run the tests on sandbox with: + + ./test/py/test.py --bd sandbox --build + +This will produce HTML output in build-sandbox/test-log.html + +See test/py/README.md for more information about the pytest suite. + + +tbot +---- + +Tbot provides a way to execute tests on target hardware. It is intended for +trying out both U-Boot and Linux (and potentially other software) on a +number of boards automatically. It can be used to create a continuous test +environment. See tools/tbot/README for more information. + + +Ad-hoc tests +------------ + +There are several ad-hoc tests which run outside the pytest environment: + + test/fs - File system test (shell script) + test/image - FIT and lagacy image tests (shell script and Python) + test/stdint - A test that stdint.h can be used in U-Boot (shell script) + trace - Test for the tracing feature (shell script) + +The above should be converted to run as part of the pytest suite. + + +When to write tests +------------------- + +If you add code to U-Boot without a test you are taking a risk. Even if you +perform thorough manual testing at the time of submission, it may break when +future changes are made to U-Boot. It may even break when applied to mainline, +if other changes interact with it. A good mindset is that untested code +probably doesn't work and should be deleted. + +You can assume that the Pytest suite will be run before patches are accepted +to mainline, so this provides protection against future breakage. + +On the other hand there is quite a bit of code that is not covered with tests, +or is covered sparingly. So here are some suggestions: + +- If you are adding a new uclass, add a sandbox driver and a test that uses it +- If you are modifying code covered by an existing test, add a new test case + to cover your changes +- If the code you are modifying has not tests, consider writing one. Even a + very basic test is useful, and may be picked up and enhanced by others. It + is much easier to add onto a test - writing a new large test can seem + daunting to most contributors. + + +Future work +----------- + +Converting existing shell scripts into pytest tests. diff --git a/test/py/conftest.py b/test/py/conftest.py index 050f6e409d..5b3a92316b 100644 --- a/test/py/conftest.py +++ b/test/py/conftest.py @@ -179,6 +179,7 @@ def pytest_configure(config): ubconfig.board_type = board_type ubconfig.board_identity = board_identity ubconfig.gdbserver = gdbserver + ubconfig.dtb = build_dir + '/arch/sandbox/dts/test.dtb' env_vars = ( 'board_type', diff --git a/test/py/multiplexed_log.py b/test/py/multiplexed_log.py index 68917eb0ea..35a32fb5c0 100644 --- a/test/py/multiplexed_log.py +++ b/test/py/multiplexed_log.py @@ -101,6 +101,7 @@ class RunAndLog(object): self.logfile = logfile self.name = name self.chained_file = chained_file + self.output = None def close(self): """Clean up any resources managed by this object.""" @@ -109,6 +110,9 @@ class RunAndLog(object): def run(self, cmd, cwd=None, ignore_errors=False): """Run a command as a sub-process, and log the results. + The output is available at self.output which can be useful if there is + an exception. + Args: cmd: The command to execute. cwd: The directory to run the command in. Can be None to use the @@ -119,7 +123,7 @@ class RunAndLog(object): raised if such problems occur. Returns: - Nothing. + The output as a string. """ msg = '+' + ' '.join(cmd) + '\n' @@ -159,8 +163,12 @@ class RunAndLog(object): self.logfile.write(self, output) if self.chained_file: self.chained_file.write(output) + + # Store the output so it can be accessed if we raise an exception. + self.output = output if exception: raise exception + return output class SectionCtxMgr(object): """A context manager for Python's "with" statement, which allows a certain diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py new file mode 100644 index 0000000000..c77989591c --- /dev/null +++ b/test/py/tests/test_vboot.py @@ -0,0 +1,185 @@ +# Copyright (c) 2013, Google Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# +# U-Boot Verified Boot Test + +""" +This tests verified boot in the following ways: + +For image verification: +- Create FIT (unsigned) with mkimage +- Check that verification shows that no keys are verified +- Sign image +- Check that verification shows that a key is now verified + +For configuration verification: +- Corrupt signature and check for failure +- Create FIT (with unsigned configuration) with mkimage +- Check that image veriication works +- Sign the FIT and mark the key as 'required' for verification +- Check that image verification works +- Corrupt the signature +- Check that image verification no-longer works + +Tests run with both SHA1 and SHA256 hashing. +""" + +import pytest +import sys +import u_boot_utils as util + +@pytest.mark.buildconfigspec('fit_signature') +def test_vboot(u_boot_console): + """Test verified boot signing with mkimage and verification with 'bootm'. + + This works using sandbox only as it needs to update the device tree used + by U-Boot to hold public keys from the signing process. + + The SHA1 and SHA256 tests are combined into a single test since the + key-generation process is quite slow and we want to avoid doing it twice. + """ + def dtc(dts): + """Run the device-tree compiler to compile a .dts file + + The output file will be the same as the input file but with a .dtb + extension. + + Args: + dts: Device tree file to compile. + """ + dtb = dts.replace('.dts', '.dtb') + util.cmd(cons, 'dtc %s %s%s -O dtb ' + '-o %s%s' % (dtc_args, datadir, dts, tmpdir, dtb)) + + def run_bootm(test_type, expect_string): + """Run a 'bootm' command U-Boot. + + This always starts a fresh U-Boot instance since the device tree may + contain a new public key. + + Args: + test_type: A string identifying the test type + expect_string: A string which is expected in the output + """ + cons.cleanup_spawn() + cons.ensure_spawned() + cons.log.action('%s: Test Verified Boot Run: %s' % (algo, test_type)) + output = cons.run_command_list( + ['sb load hostfs - 100 %stest.fit' % tmpdir, + 'fdt addr 100', + 'bootm 100']) + assert(expect_string in output) + + def make_fit(its): + """Make a new FIT from the .its source file + + This runs 'mkimage -f' to create a new FIT. + + Args: + its: Filename containing .its source + """ + util.run_and_log(cons, [mkimage, '-D', dtc_args, '-f', + '%s%s' % (datadir, its), fit]) + + def sign_fit(): + """Sign the FIT + + Signs the FIT and writes the signature into it. It also writes the + public key into the dtb. + """ + cons.log.action('%s: Sign images' % algo) + util.run_and_log(cons, [mkimage, '-F', '-k', tmpdir, '-K', dtb, + '-r', fit]) + + def test_with_algo(sha): + """Test verified boot with the given hash algorithm + + This is the main part of the test code. The same procedure is followed + for both hashing algorithms. + + Args: + sha: Either 'sha1' or 'sha256', to select the algorithm to use + """ + global algo + + algo = sha + + # Compile our device tree files for kernel and U-Boot + dtc('sandbox-kernel.dts') + dtc('sandbox-u-boot.dts') + + # Build the FIT, but don't sign anything yet + cons.log.action('%s: Test FIT with signed images' % algo) + make_fit('sign-images-%s.its' % algo) + run_bootm('unsigned images', 'dev-') + + # Sign images with our dev keys + sign_fit() + run_bootm('signed images', 'dev+') + + # Create a fresh .dtb without the public keys + dtc('sandbox-u-boot.dts') + + cons.log.action('%s: Test FIT with signed configuration' % algo) + make_fit('sign-configs-%s.its' % algo) + run_bootm('unsigned config', '%s+ OK' % algo) + + # Sign images with our dev keys + sign_fit() + run_bootm('signed config', 'dev+') + + cons.log.action('%s: Check signed config on the host' % algo) + + util.run_and_log(cons, [fit_check_sign, '-f', fit, '-k', tmpdir, + '-k', dtb]) + + # Increment the first byte of the signature, which should cause failure + sig = util.cmd(cons, 'fdtget -t bx %s %s value' % (fit, sig_node)) + byte_list = sig.split() + byte = int(byte_list[0], 16) + byte_list = ['%x' % (byte + 1)] + byte_list[1:] + sig = ' '.join(byte_list) + util.cmd(cons, 'fdtput -t bx %s %s value %s' % (fit, sig_node, sig)) + + run_bootm('Signed config with bad hash', 'Bad Data Hash') + + cons.log.action('%s: Check bad config on the host' % algo) + util.run_and_log_expect_exception(cons, [fit_check_sign, '-f', fit, + '-k', dtb], 1, 'Failed to verify required signature') + + cons = u_boot_console + tmpdir = cons.config.result_dir + '/' + tmp = tmpdir + 'vboot.tmp' + datadir = 'test/py/tests/vboot/' + fit = '%stest.fit' % tmpdir + mkimage = cons.config.build_dir + '/tools/mkimage' + fit_check_sign = cons.config.build_dir + '/tools/fit_check_sign' + dtc_args = '-I dts -O dtb -i %s' % tmpdir + dtb = '%ssandbox-u-boot.dtb' % tmpdir + sig_node = '/configurations/conf@1/signature@1' + + # Create an RSA key pair + public_exponent = 65537 + util.cmd(cons, 'openssl genpkey -algorithm RSA -out %sdev.key ' + '-pkeyopt rsa_keygen_bits:2048 ' + '-pkeyopt rsa_keygen_pubexp:%d ' + '2>/dev/null' % (tmpdir, public_exponent)) + + # Create a certificate containing the public key + util.cmd(cons, 'openssl req -batch -new -x509 -key %sdev.key -out ' + '%sdev.crt' % (tmpdir, tmpdir)) + + # Create a number kernel image with zeroes + with open('%stest-kernel.bin' % tmpdir, 'w') as fd: + fd.write(5000 * chr(0)) + + try: + # We need to use our own device tree file. Remember to restore it + # afterwards. + old_dtb = cons.config.dtb + cons.config.dtb = dtb + test_with_algo('sha1') + test_with_algo('sha256') + finally: + cons.config.dtb = old_dtb diff --git a/test/vboot/sandbox-kernel.dts b/test/py/tests/vboot/sandbox-kernel.dts index a1e853c9ca..a1e853c9ca 100644 --- a/test/vboot/sandbox-kernel.dts +++ b/test/py/tests/vboot/sandbox-kernel.dts diff --git a/test/vboot/sandbox-u-boot.dts b/test/py/tests/vboot/sandbox-u-boot.dts index 63f8f401de..63f8f401de 100644 --- a/test/vboot/sandbox-u-boot.dts +++ b/test/py/tests/vboot/sandbox-u-boot.dts diff --git a/test/vboot/sign-configs-sha1.its b/test/py/tests/vboot/sign-configs-sha1.its index db2ed79355..db2ed79355 100644 --- a/test/vboot/sign-configs-sha1.its +++ b/test/py/tests/vboot/sign-configs-sha1.its diff --git a/test/vboot/sign-configs-sha256.its b/test/py/tests/vboot/sign-configs-sha256.its index 1b3432ec14..1b3432ec14 100644 --- a/test/vboot/sign-configs-sha256.its +++ b/test/py/tests/vboot/sign-configs-sha256.its diff --git a/test/vboot/sign-images-sha1.its b/test/py/tests/vboot/sign-images-sha1.its index f69326a39b..f69326a39b 100644 --- a/test/vboot/sign-images-sha1.its +++ b/test/py/tests/vboot/sign-images-sha1.its diff --git a/test/vboot/sign-images-sha256.its b/test/py/tests/vboot/sign-images-sha256.its index e6aa9fc409..e6aa9fc409 100644 --- a/test/vboot/sign-images-sha256.its +++ b/test/py/tests/vboot/sign-images-sha256.its diff --git a/test/py/u_boot_console_base.py b/test/py/u_boot_console_base.py index 3d2ac44875..4606ad48bf 100644 --- a/test/py/u_boot_console_base.py +++ b/test/py/u_boot_console_base.py @@ -216,6 +216,22 @@ class ConsoleBase(object): self.cleanup_spawn() raise + def run_command_list(self, cmds): + """Run a list of commands. + + This is a helper function to call run_command() with default arguments + for each command in a list. + + Args: + cmd: List of commands (each a string) + Returns: + Combined output of all commands, as a string + """ + output = '' + for cmd in cmds: + output += self.run_command(cmd) + return output + def ctrlc(self): """Send a CTRL-C character to U-Boot. diff --git a/test/py/u_boot_console_sandbox.py b/test/py/u_boot_console_sandbox.py index 6bf4653083..647e1f879f 100644 --- a/test/py/u_boot_console_sandbox.py +++ b/test/py/u_boot_console_sandbox.py @@ -50,7 +50,7 @@ class ConsoleSandbox(ConsoleBase): self.config.build_dir + fname, '-v', '-d', - self.config.build_dir + '/arch/sandbox/dts/test.dtb' + self.config.dtb ] return Spawn(cmd, cwd=self.config.source_dir) diff --git a/test/py/u_boot_utils.py b/test/py/u_boot_utils.py index e4765e38c1..e358c585bf 100644 --- a/test/py/u_boot_utils.py +++ b/test/py/u_boot_utils.py @@ -165,12 +165,47 @@ def run_and_log(u_boot_console, cmd, ignore_errors=False): problems occur. Returns: - Nothing. + The output as a string. """ runner = u_boot_console.log.get_runner(cmd[0], sys.stdout) - runner.run(cmd, ignore_errors=ignore_errors) + output = runner.run(cmd, ignore_errors=ignore_errors) runner.close() + return output + +def cmd(u_boot_console, cmd_str): + """Run a single command string and log its output. + + Args: + u_boot_console: A console connection to U-Boot. + cmd: The command to run, as a string. + + Returns: + The output as a string. + """ + return run_and_log(u_boot_console, cmd_str.split()) + +def run_and_log_expect_exception(u_boot_console, cmd, retcode, msg): + """Run a command which is expected to fail. + + This runs a command and checks that it fails with the expected return code + and exception method. If not, an exception is raised. + + Args: + u_boot_console: A console connection to U-Boot. + cmd: The command to run, as an array of argv[]. + retcode: Expected non-zero return code from the command. + msg: String which should be contained within the command's output. + """ + try: + runner = u_boot_console.log.get_runner(cmd[0], sys.stdout) + runner.run(cmd) + except Exception as e: + assert(msg in runner.output) + else: + raise Exception('Expected exception, but not raised') + finally: + runner.close() ram_base = None def find_ram_base(u_boot_console): diff --git a/test/run b/test/run new file mode 100755 index 0000000000..a6dcf8f44f --- /dev/null +++ b/test/run @@ -0,0 +1,4 @@ +#!/bin/sh + +# Run all tests +./test/py/test.py --bd sandbox --build diff --git a/test/vboot/.gitignore b/test/vboot/.gitignore deleted file mode 100644 index 4631242709..0000000000 --- a/test/vboot/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/*.dtb -/test.fit -/dev-keys diff --git a/test/vboot/vboot_test.sh b/test/vboot/vboot_test.sh deleted file mode 100755 index 6d7abb82bd..0000000000 --- a/test/vboot/vboot_test.sh +++ /dev/null @@ -1,151 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2013, Google Inc. -# -# Simple Verified Boot Test Script -# -# SPDX-License-Identifier: GPL-2.0+ - -set -e - -# Run U-Boot and report the result -# Args: -# $1: Test message -run_uboot() { - echo -n "Test Verified Boot Run: $1: " - ${uboot} -d sandbox-u-boot.dtb >${tmp} -c ' -sb load hostfs - 100 test.fit; -fdt addr 100; -bootm 100; -reset' - if ! grep -q "$2" ${tmp}; then - echo - echo "Verified boot key check failed, output follows:" - cat ${tmp} - false - else - echo "OK" - fi -} - -echo "Simple Verified Boot Test" -echo "=========================" -echo -echo "Please see doc/uImage.FIT/verified-boot.txt for more information" -echo - -err=0 -tmp=/tmp/vboot_test.$$ - -dir=$(dirname $0) - -if [ -z ${O} ]; then - O=. -fi -O=$(readlink -f ${O}) - -dtc="-I dts -O dtb -p 2000" -uboot="${O}/u-boot" -mkimage="${O}/tools/mkimage" -fit_check_sign="${O}/tools/fit_check_sign" -keys="${dir}/dev-keys" -echo ${mkimage} -D "${dtc}" - -echo "Build keys" -mkdir -p ${keys} - -PUBLIC_EXPONENT=${1} - -if [ -z "${PUBLIC_EXPONENT}" ]; then - PUBLIC_EXPONENT=65537 -fi - -# Create an RSA key pair -openssl genpkey -algorithm RSA -out ${keys}/dev.key \ - -pkeyopt rsa_keygen_bits:2048 \ - -pkeyopt rsa_keygen_pubexp:${PUBLIC_EXPONENT} 2>/dev/null - -# Create a certificate containing the public key -openssl req -batch -new -x509 -key ${keys}/dev.key -out ${keys}/dev.crt - -pushd ${dir} >/dev/null - -function do_test { - echo do $sha test - # Compile our device tree files for kernel and U-Boot - dtc -p 0x1000 sandbox-kernel.dts -O dtb -o sandbox-kernel.dtb - dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb - - # Create a number kernel image with zeroes - head -c 5000 /dev/zero >test-kernel.bin - - # Build the FIT, but don't sign anything yet - echo Build FIT with signed images - ${mkimage} -D "${dtc}" -f sign-images-$sha.its test.fit >${tmp} - - run_uboot "unsigned signatures:" "dev-" - - # Sign images with our dev keys - echo Sign images - ${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb \ - -r test.fit >${tmp} - - run_uboot "signed images" "dev+" - - - # Create a fresh .dtb without the public keys - dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb - - echo Build FIT with signed configuration - ${mkimage} -D "${dtc}" -f sign-configs-$sha.its test.fit >${tmp} - - run_uboot "unsigned config" $sha"+ OK" - - # Sign images with our dev keys - echo Sign images - ${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb \ - -r test.fit >${tmp} - - run_uboot "signed config" "dev+" - - echo check signed config on the host - if ! ${fit_check_sign} -f test.fit -k sandbox-u-boot.dtb >${tmp}; then - echo - echo "Verified boot key check on host failed, output follows:" - cat ${tmp} - false - else - if ! grep -q "dev+" ${tmp}; then - echo - echo "Verified boot key check failed, output follows:" - cat ${tmp} - false - else - echo "OK" - fi - fi - - run_uboot "signed config" "dev+" - - # Increment the first byte of the signature, which should cause failure - sig=$(fdtget -t bx test.fit /configurations/conf@1/signature@1 value) - newbyte=$(printf %x $((0x${sig:0:2} + 1))) - sig="${newbyte} ${sig:2}" - fdtput -t bx test.fit /configurations/conf@1/signature@1 value ${sig} - - run_uboot "signed config with bad hash" "Bad Data Hash" -} - -sha=sha1 -do_test -sha=sha256 -do_test - -popd >/dev/null - -echo -if ${ok}; then - echo "Test passed" -else - echo "Test failed" -fi diff --git a/tools/fit_image.c b/tools/fit_image.c index 58aa8e27db..10fd6d4929 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -195,7 +195,8 @@ static int fit_write_images(struct image_tool_params *params, char *fdt) fdt_begin_node(fdt, str); fdt_property_string(fdt, "description", params->imagename); fdt_property_string(fdt, "type", typename); - fdt_property_string(fdt, "arch", genimg_get_arch_name(params->arch)); + fdt_property_string(fdt, "arch", + genimg_get_arch_short_name(params->arch)); fdt_property_string(fdt, "os", genimg_get_os_short_name(params->os)); fdt_property_string(fdt, "compression", genimg_get_comp_short_name(params->comp)); @@ -650,8 +651,8 @@ static int fit_handle_file(struct image_tool_params *params) } if (ret) { - fprintf(stderr, "%s Can't add hashes to FIT blob\n", - params->cmdname); + fprintf(stderr, "%s Can't add hashes to FIT blob: %d\n", + params->cmdname, ret); goto err_system; } diff --git a/tools/image-host.c b/tools/image-host.c index 7effb6cea5..3e14fdc1eb 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -38,7 +38,7 @@ static int fit_set_hash_value(void *fit, int noffset, uint8_t *value, printf("Can't set hash '%s' property for '%s' node(%s)\n", FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL), fdt_strerror(ret)); - return -1; + return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO; } return 0; @@ -64,25 +64,27 @@ static int fit_image_process_hash(void *fit, const char *image_name, const char *node_name; int value_len; char *algo; + int ret; node_name = fit_get_name(fit, noffset, NULL); if (fit_image_hash_get_algo(fit, noffset, &algo)) { printf("Can't get hash algo property for '%s' hash node in '%s' image node\n", node_name, image_name); - return -1; + return -ENOENT; } if (calculate_hash(data, size, algo, value, &value_len)) { printf("Unsupported hash algorithm (%s) for '%s' hash node in '%s' image node\n", algo, node_name, image_name); - return -1; + return -EPROTONOSUPPORT; } - if (fit_set_hash_value(fit, noffset, value, value_len)) { + ret = fit_set_hash_value(fit, noffset, value, value_len); + if (ret) { printf("Can't set hash value for '%s' hash node in '%s' image node\n", node_name, image_name); - return -1; + return ret; } return 0; @@ -322,7 +324,7 @@ int fit_image_add_verification_data(const char *keydir, void *keydest, comment, require_keys); } if (ret) - return -1; + return ret; } return 0; diff --git a/tools/mkimage.c b/tools/mkimage.c index ff3024a8f1..d9939583f5 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -25,45 +25,47 @@ static struct image_tool_params params = { .imagename2 = "", }; -static int h_compare_image_name(const void *vtype1, const void *vtype2) +static enum ih_category cur_category; + +static int h_compare_category_name(const void *vtype1, const void *vtype2) { const int *type1 = vtype1; const int *type2 = vtype2; - const char *name1 = genimg_get_type_short_name(*type1); - const char *name2 = genimg_get_type_short_name(*type2); + const char *name1 = genimg_get_cat_short_name(cur_category, *type1); + const char *name2 = genimg_get_cat_short_name(cur_category, *type2); return strcmp(name1, name2); } -/* Show all image types supported by mkimage */ -static void show_image_types(void) +static int show_valid_options(enum ih_category category) { - struct image_type_params *tparams; - int order[IH_TYPE_COUNT]; + int *order; int count; - int type; + int item; int i; + count = genimg_get_cat_count(category); + order = calloc(count, sizeof(*order)); + if (!order) + return -ENOMEM; + /* Sort the names in order of short name for easier reading */ - memset(order, '\0', sizeof(order)); - for (count = 0, type = 0; type < IH_TYPE_COUNT; type++) { - tparams = imagetool_get_type(type); - if (tparams) - order[count++] = type; - } - qsort(order, count, sizeof(int), h_compare_image_name); + for (item = 0; item < count; item++) + order[item] = item; + cur_category = category; + qsort(order, count, sizeof(int), h_compare_category_name); - fprintf(stderr, "\nInvalid image type. Supported image types:\n"); + fprintf(stderr, "\nInvalid %s, supported are:\n", + genimg_get_cat_desc(category)); for (i = 0; i < count; i++) { - type = order[i]; - tparams = imagetool_get_type(type); - if (tparams) { - fprintf(stderr, "\t%-15s %s\n", - genimg_get_type_short_name(type), - genimg_get_type_name(type)); - } + item = order[i]; + fprintf(stderr, "\t%-15s %s\n", + genimg_get_cat_short_name(category, item), + genimg_get_cat_name(category, item)); } fprintf(stderr, "\n"); + + return 0; } static void usage(const char *msg) @@ -150,8 +152,10 @@ static void process_args(int argc, char **argv) break; case 'A': params.arch = genimg_get_arch_id(optarg); - if (params.arch < 0) + if (params.arch < 0) { + show_valid_options(IH_ARCH); usage("Invalid architecture"); + } break; case 'b': if (add_content(IH_TYPE_FLATDT, optarg)) { @@ -166,8 +170,10 @@ static void process_args(int argc, char **argv) break; case 'C': params.comp = genimg_get_comp_id(optarg); - if (params.comp < 0) + if (params.comp < 0) { + show_valid_options(IH_COMP); usage("Invalid compression type"); + } break; case 'd': params.datafile = optarg; @@ -197,7 +203,6 @@ static void process_args(int argc, char **argv) * The flattened image tree (FIT) format * requires a flattened device tree image type */ - params.fit_image_type = params.type; params.type = IH_TYPE_FLATDT; params.fflag = 1; break; @@ -215,8 +220,10 @@ static void process_args(int argc, char **argv) break; case 'O': params.os = genimg_get_os_id(optarg); - if (params.os < 0) + if (params.os < 0) { + show_valid_options(IH_OS); usage("Invalid operating system"); + } break; case 'p': params.external_offset = strtoull(optarg, &ptr, 16); @@ -225,6 +232,7 @@ static void process_args(int argc, char **argv) params.cmdname, optarg); exit(EXIT_FAILURE); } + break; case 'q': params.quiet = 1; break; @@ -244,7 +252,7 @@ static void process_args(int argc, char **argv) case 'T': type = genimg_get_type_id(optarg); if (type < 0) { - show_image_types(); + show_valid_options(IH_TYPE); usage("Invalid image type"); } break; @@ -272,9 +280,12 @@ static void process_args(int argc, char **argv) * will always be IH_TYPE_FLATDT in this case). */ if (params.type == IH_TYPE_FLATDT) { - params.fit_image_type = type; + params.fit_image_type = type ? type : IH_TYPE_KERNEL; + /* For auto_its, datafile is always 'auto' */ if (!params.auto_its) params.datafile = datafile; + else if (!params.datafile) + usage("Missing data file for auto-FIT (use -d)"); } else if (type != IH_TYPE_INVALID) { params.type = type; } @@ -283,7 +294,6 @@ static void process_args(int argc, char **argv) usage("Missing output filename"); } - int main(int argc, char **argv) { int ifd = -1; |