diff options
248 files changed, 4145 insertions, 1461 deletions
@@ -1326,6 +1326,7 @@ u-boot.ldr: u-boot # binman # --------------------------------------------------------------------------- # Use 'make BINMAN_DEBUG=1' to enable debugging +# Use 'make BINMAN_VERBOSE=3' to set vebosity level default_dt := $(if $(DEVICE_TREE),$(DEVICE_TREE),$(CONFIG_DEFAULT_DEVICE_TREE)) quiet_cmd_binman = BINMAN $@ cmd_binman = $(srctree)/tools/binman/binman $(if $(BINMAN_DEBUG),-D) \ diff --git a/arch/Kconfig b/arch/Kconfig index 27843cd79c..7023223927 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -142,6 +142,8 @@ config SANDBOX imply AVB_VERIFY imply LIBAVB imply CMD_AVB + imply SCP03 + imply CMD_SCP03 imply UDP_FUNCTION_FASTBOOT imply VIRTIO_MMIO imply VIRTIO_PCI diff --git a/arch/arc/lib/reset.c b/arch/arc/lib/reset.c index fbb56ec83a..b8589d0f0a 100644 --- a/arch/arc/lib/reset.c +++ b/arch/arc/lib/reset.c @@ -7,7 +7,7 @@ #include <common.h> #include <cpu_func.h> -__weak void reset_cpu(ulong addr) +__weak void reset_cpu(void) { /* Stop debug session here */ __builtin_arc_brk(); @@ -17,7 +17,7 @@ int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { printf("Resetting the board...\n"); - reset_cpu(0); + reset_cpu(); return 0; } diff --git a/arch/arm/cpu/arm920t/ep93xx/cpu.c b/arch/arm/cpu/arm920t/ep93xx/cpu.c index c9ea4e46a8..3435bdc748 100644 --- a/arch/arm/cpu/arm920t/ep93xx/cpu.c +++ b/arch/arm/cpu/arm920t/ep93xx/cpu.c @@ -14,7 +14,7 @@ #include <asm/io.h> /* We reset the CPU by generating a 1-->0 transition on DeviceCfg bit 31. */ -extern void reset_cpu(ulong addr) +extern void reset_cpu(void) { struct syscon_regs *syscon = (struct syscon_regs *)SYSCON_BASE; uint32_t value; diff --git a/arch/arm/cpu/arm920t/imx/timer.c b/arch/arm/cpu/arm920t/imx/timer.c index e9d5577921..0cd3a03981 100644 --- a/arch/arm/cpu/arm920t/imx/timer.c +++ b/arch/arm/cpu/arm920t/imx/timer.c @@ -81,7 +81,7 @@ ulong get_tbclk(void) /* * Reset the cpu by setting up the watchdog timer and let him time out */ -void reset_cpu(ulong ignored) +void reset_cpu(void) { /* Disable watchdog and set Time-Out field to 0 */ WCR = 0x00000000; diff --git a/arch/arm/cpu/arm926ejs/armada100/timer.c b/arch/arm/cpu/arm926ejs/armada100/timer.c index ec73393d0f..6d77ad3b6d 100644 --- a/arch/arm/cpu/arm926ejs/armada100/timer.c +++ b/arch/arm/cpu/arm926ejs/armada100/timer.c @@ -142,7 +142,7 @@ int timer_init(void) * 2. Write key value to TMP_WSAR reg. * 3. Perform write operation. */ -void reset_cpu(unsigned long ignored) +void reset_cpu(void) { struct armd1mpmu_registers *mpmu = (struct armd1mpmu_registers *) ARMD1_MPMU_BASE; diff --git a/arch/arm/cpu/arm926ejs/mx25/reset.c b/arch/arm/cpu/arm926ejs/mx25/reset.c index 38df1c9402..7844a99c16 100644 --- a/arch/arm/cpu/arm926ejs/mx25/reset.c +++ b/arch/arm/cpu/arm926ejs/mx25/reset.c @@ -23,7 +23,7 @@ /* * Reset the cpu by setting up the watchdog timer and let it time out */ -void reset_cpu(ulong ignored) +void reset_cpu(void) { struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE; /* Disable watchdog and set Time-Out field to 0 */ diff --git a/arch/arm/cpu/arm926ejs/mx27/reset.c b/arch/arm/cpu/arm926ejs/mx27/reset.c index 320b0a65e7..496fb30817 100644 --- a/arch/arm/cpu/arm926ejs/mx27/reset.c +++ b/arch/arm/cpu/arm926ejs/mx27/reset.c @@ -23,7 +23,7 @@ /* * Reset the cpu by setting up the watchdog timer and let it time out */ -void reset_cpu(ulong ignored) +void reset_cpu(void) { struct wdog_regs *regs = (struct wdog_regs *)IMX_WDT_BASE; /* Disable watchdog and set Time-Out field to 0 */ diff --git a/arch/arm/cpu/arm926ejs/mxs/mxs.c b/arch/arm/cpu/arm926ejs/mxs/mxs.c index c9362136fb..344b9b4e55 100644 --- a/arch/arm/cpu/arm926ejs/mxs/mxs.c +++ b/arch/arm/cpu/arm926ejs/mxs/mxs.c @@ -32,9 +32,9 @@ DECLARE_GLOBAL_DATA_PTR; /* Lowlevel init isn't used on i.MX28, so just have a dummy here */ __weak void lowlevel_init(void) {} -void reset_cpu(ulong ignored) __attribute__((noreturn)); +void reset_cpu(void) __attribute__((noreturn)); -void reset_cpu(ulong ignored) +void reset_cpu(void) { struct mxs_rtc_regs *rtc_regs = (struct mxs_rtc_regs *)MXS_RTC_BASE; diff --git a/arch/arm/cpu/arm926ejs/spear/reset.c b/arch/arm/cpu/arm926ejs/spear/reset.c index a316540d52..97a624e16c 100644 --- a/arch/arm/cpu/arm926ejs/spear/reset.c +++ b/arch/arm/cpu/arm926ejs/spear/reset.c @@ -11,7 +11,7 @@ #include <asm/arch/spr_syscntl.h> #include <linux/delay.h> -void reset_cpu(ulong ignored) +void reset_cpu(void) { struct syscntl_regs *syscntl_regs_p = (struct syscntl_regs *)CONFIG_SPEAR_SYSCNTLBASE; diff --git a/arch/arm/cpu/arm946es/cpu.c b/arch/arm/cpu/arm946es/cpu.c index fb0ea5e817..334bb54274 100644 --- a/arch/arm/cpu/arm946es/cpu.c +++ b/arch/arm/cpu/arm946es/cpu.c @@ -56,7 +56,7 @@ static void cache_flush (void) #ifndef CONFIG_ARCH_INTEGRATOR -__attribute__((noreturn)) void reset_cpu(ulong addr __attribute__((unused))) +__attribute__((noreturn)) void reset_cpu(void) { writew(0x0, 0xfffece10); writew(0x8, 0xfffece10); diff --git a/arch/arm/cpu/armv7/bcm281xx/reset.c b/arch/arm/cpu/armv7/bcm281xx/reset.c index fda5a9527e..1491e5c88b 100644 --- a/arch/arm/cpu/armv7/bcm281xx/reset.c +++ b/arch/arm/cpu/armv7/bcm281xx/reset.c @@ -13,7 +13,7 @@ #define CLKS_SHIFT 20 /* Clock period shift */ #define LD_SHIFT 0 /* Reload value shift */ -void reset_cpu(ulong ignored) +void reset_cpu(void) { /* * Set WD enable, RST enable, diff --git a/arch/arm/cpu/armv7/bcmcygnus/reset.c b/arch/arm/cpu/armv7/bcmcygnus/reset.c index 3bfed34533..63992fd870 100644 --- a/arch/arm/cpu/armv7/bcmcygnus/reset.c +++ b/arch/arm/cpu/armv7/bcmcygnus/reset.c @@ -10,7 +10,7 @@ #define CRMU_MAIL_BOX1 0x03024028 #define CRMU_SOFT_RESET_CMD 0xFFFFFFFF -void reset_cpu(ulong ignored) +void reset_cpu(void) { /* Send soft reset command via Mailbox. */ writel(CRMU_SOFT_RESET_CMD, CRMU_MAIL_BOX1); diff --git a/arch/arm/cpu/armv7/bcmnsp/reset.c b/arch/arm/cpu/armv7/bcmnsp/reset.c index 675f99fe99..a3137752e8 100644 --- a/arch/arm/cpu/armv7/bcmnsp/reset.c +++ b/arch/arm/cpu/armv7/bcmnsp/reset.c @@ -9,7 +9,7 @@ #define CRU_RESET_OFFSET 0x1803F184 -void reset_cpu(ulong ignored) +void reset_cpu(void) { /* Reset the cpu by setting software reset request bit */ writel(0x1, CRU_RESET_OFFSET); diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c index 146cf52608..19ff432352 100644 --- a/arch/arm/cpu/armv7/cache_v7.c +++ b/arch/arm/cpu/armv7/cache_v7.c @@ -176,9 +176,6 @@ void mmu_page_table_flush(unsigned long start, unsigned long stop) { } -void arm_init_domains(void) -{ -} #endif /* #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) */ #if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF) diff --git a/arch/arm/cpu/armv7/ls102xa/cpu.c b/arch/arm/cpu/armv7/ls102xa/cpu.c index f26a5b22fd..d863c9625a 100644 --- a/arch/arm/cpu/armv7/ls102xa/cpu.c +++ b/arch/arm/cpu/armv7/ls102xa/cpu.c @@ -375,7 +375,7 @@ void smp_kick_all_cpus(void) } #endif -void reset_cpu(ulong addr) +void reset_cpu(void) { struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR; diff --git a/arch/arm/cpu/armv7/s5p4418/cpu.c b/arch/arm/cpu/armv7/s5p4418/cpu.c index 3c71a37a74..3baa761ec7 100644 --- a/arch/arm/cpu/armv7/s5p4418/cpu.c +++ b/arch/arm/cpu/armv7/s5p4418/cpu.c @@ -88,7 +88,7 @@ int print_cpuinfo(void) } #endif -void reset_cpu(ulong ignored) +void reset_cpu(void) { void *clkpwr_reg = (void *)PHY_BASEADDR_CLKPWR; const u32 sw_rst_enb_bitpos = 3; diff --git a/arch/arm/cpu/armv7/stv0991/reset.c b/arch/arm/cpu/armv7/stv0991/reset.c index fb67de10f4..77d4477c8d 100644 --- a/arch/arm/cpu/armv7/stv0991/reset.c +++ b/arch/arm/cpu/armv7/stv0991/reset.c @@ -9,7 +9,7 @@ #include <asm/io.h> #include <asm/arch/stv0991_wdru.h> #include <linux/delay.h> -void reset_cpu(ulong ignored) +void reset_cpu(void) { puts("System is going to reboot ...\n"); /* diff --git a/arch/arm/cpu/armv7m/cpu.c b/arch/arm/cpu/armv7m/cpu.c index 7f827da033..63721018c1 100644 --- a/arch/arm/cpu/armv7m/cpu.c +++ b/arch/arm/cpu/armv7m/cpu.c @@ -47,7 +47,7 @@ int cleanup_before_linux(void) /* * Perform the low-level reset. */ -void reset_cpu(ulong addr) +void reset_cpu(void) { /* * Perform reset but keep priority group unchanged. diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c index 3a5bf77826..270a72e550 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c @@ -1231,7 +1231,7 @@ int timer_init(void) __efi_runtime_data u32 __iomem *rstcr = (u32 *)CONFIG_SYS_FSL_RST_ADDR; -void __efi_runtime reset_cpu(ulong addr) +void __efi_runtime reset_cpu(void) { #if defined(CONFIG_ARCH_LX2160A) || defined(CONFIG_ARCH_LX2162A) /* clear the RST_REQ_MSK and SW_RST_REQ */ @@ -1260,7 +1260,7 @@ void __efi_runtime EFIAPI efi_reset_system( case EFI_RESET_COLD: case EFI_RESET_WARM: case EFI_RESET_PLATFORM_SPECIFIC: - reset_cpu(0); + reset_cpu(); break; case EFI_RESET_SHUTDOWN: /* Nothing we can do */ diff --git a/arch/arm/cpu/armv8/s32v234/generic.c b/arch/arm/cpu/armv8/s32v234/generic.c index 0fc9885222..d1ae10b1a7 100644 --- a/arch/arm/cpu/armv8/s32v234/generic.c +++ b/arch/arm/cpu/armv8/s32v234/generic.c @@ -319,7 +319,7 @@ static char *get_reset_cause(void) #define SRC_SCR_SW_RST (1<<12) -void reset_cpu(ulong addr) +void reset_cpu(void) { printf("Feature not supported.\n"); }; diff --git a/arch/arm/cpu/pxa/pxa2xx.c b/arch/arm/cpu/pxa/pxa2xx.c index ea91d8aaec..c7efb67754 100644 --- a/arch/arm/cpu/pxa/pxa2xx.c +++ b/arch/arm/cpu/pxa/pxa2xx.c @@ -267,9 +267,9 @@ void i2c_clk_enable(void) writel(readl(CKEN) | CKEN14_I2C, CKEN); } -void __attribute__((weak)) reset_cpu(ulong ignored) __attribute__((noreturn)); +void __attribute__((weak)) reset_cpu(void) __attribute__((noreturn)); -void reset_cpu(ulong ignored) +void reset_cpu(void) { uint32_t tmp; diff --git a/arch/arm/cpu/sa1100/cpu.c b/arch/arm/cpu/sa1100/cpu.c index 91e100af1b..6f67f7fc22 100644 --- a/arch/arm/cpu/sa1100/cpu.c +++ b/arch/arm/cpu/sa1100/cpu.c @@ -55,7 +55,7 @@ static void cache_flush (void) #define RSRR 0x00 #define RCSR 0x04 -__attribute__((noreturn)) void reset_cpu(ulong addr __attribute__((unused))) +__attribute__((noreturn)) void reset_cpu(void) { /* repeat endlessly */ while (1) { diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h index c20e05ec7f..b10edf805b 100644 --- a/arch/arm/include/asm/cache.h +++ b/arch/arm/include/asm/cache.h @@ -35,7 +35,6 @@ void l2_cache_disable(void); void set_section_dcache(int section, enum dcache_option option); void arm_init_before_mmu(void); -void arm_init_domains(void); void cpu_cache_initialization(void); void dram_bank_mmu_setup(int bank); diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 5fe83699f4..11fceec4d2 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h @@ -397,20 +397,6 @@ static inline void set_cr(unsigned int val) isb(); } -static inline unsigned int get_dacr(void) -{ - unsigned int val; - asm("mrc p15, 0, %0, c3, c0, 0 @ get DACR" : "=r" (val) : : "cc"); - return val; -} - -static inline void set_dacr(unsigned int val) -{ - asm volatile("mcr p15, 0, %0, c3, c0, 0 @ set DACR" - : : "r" (val) : "cc"); - isb(); -} - #ifdef CONFIG_ARMV7_LPAE /* Long-Descriptor Translation Table Level 1/2 Bits */ #define TTB_SECT_XN_MASK (1ULL << 54) @@ -475,7 +461,7 @@ enum dcache_option { #define TTB_SECT_XN_MASK (1 << 4) #define TTB_SECT_C_MASK (1 << 3) #define TTB_SECT_B_MASK (1 << 2) -#define TTB_SECT (2 << 0) +#define TTB_SECT (2 << 0) /* * Short-descriptor format memory region attributes, without TEX remap @@ -489,7 +475,7 @@ enum dcache_option { */ enum dcache_option { DCACHE_OFF = TTB_SECT_DOMAIN(0) | TTB_SECT_XN_MASK | TTB_SECT, - DCACHE_WRITETHROUGH = DCACHE_OFF | TTB_SECT_C_MASK, + DCACHE_WRITETHROUGH = TTB_SECT_DOMAIN(0) | TTB_SECT | TTB_SECT_C_MASK, DCACHE_WRITEBACK = DCACHE_WRITETHROUGH | TTB_SECT_B_MASK, DCACHE_WRITEALLOC = DCACHE_WRITEBACK | TTB_SECT_TEX(1), }; diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c index 24050e5bdd..aab1bf4360 100644 --- a/arch/arm/lib/cache-cp15.c +++ b/arch/arm/lib/cache-cp15.c @@ -22,10 +22,6 @@ __weak void arm_init_before_mmu(void) { } -__weak void arm_init_domains(void) -{ -} - static void set_section_phys(int section, phys_addr_t phys, enum dcache_option option) { @@ -203,11 +199,12 @@ static inline void mmu_setup(void) asm volatile("mcr p15, 0, %0, c2, c0, 0" : : "r" (gd->arch.tlb_addr) : "memory"); #endif - /* Set the access control to all-supervisor */ + /* + * initial value of Domain Access Control Register (DACR) + * Set the access control to client (1U) for each of the 16 domains + */ asm volatile("mcr p15, 0, %0, c3, c0, 0" - : : "r" (~0)); - - arm_init_domains(); + : : "r" (0x55555555)); /* and enable the mmu */ reg = get_cr(); /* get control reg. */ diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c index 05bb1a38b3..6dc27d1d58 100644 --- a/arch/arm/lib/interrupts.c +++ b/arch/arm/lib/interrupts.c @@ -53,7 +53,7 @@ int disable_interrupts(void) void bad_mode (void) { panic ("Resetting CPU ...\n"); - reset_cpu(0); + reset_cpu(); } static void show_efi_loaded_images(struct pt_regs *regs) diff --git a/arch/arm/lib/interrupts_m.c b/arch/arm/lib/interrupts_m.c index 2ae1c5ba76..277854aa87 100644 --- a/arch/arm/lib/interrupts_m.c +++ b/arch/arm/lib/interrupts_m.c @@ -59,7 +59,7 @@ void dump_regs(struct autosave_regs *regs) void bad_mode(void) { panic("Resetting CPU ...\n"); - reset_cpu(0); + reset_cpu(); } void do_hard_fault(struct autosave_regs *autosave_regs) diff --git a/arch/arm/lib/reset.c b/arch/arm/lib/reset.c index 4f1a768bfe..95169bae1c 100644 --- a/arch/arm/lib/reset.c +++ b/arch/arm/lib/reset.c @@ -39,7 +39,7 @@ int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) disable_interrupts(); reset_misc(); - reset_cpu(0); + reset_cpu(); /*NOTREACHED*/ return 0; diff --git a/arch/arm/mach-at91/arm920t/reset.c b/arch/arm/mach-at91/arm920t/reset.c index d92bc57d66..91e375146a 100644 --- a/arch/arm/mach-at91/arm920t/reset.c +++ b/arch/arm/mach-at91/arm920t/reset.c @@ -24,7 +24,7 @@ void __attribute__((weak)) board_reset(void) /* true empty function for defining weak symbol */ } -void reset_cpu(ulong ignored) +void reset_cpu(void) { at91_st_t *st = (at91_st_t *) ATMEL_BASE_ST; diff --git a/arch/arm/mach-at91/arm926ejs/reset.c b/arch/arm/mach-at91/arm926ejs/reset.c index 56fbbd991e..6acbfa3301 100644 --- a/arch/arm/mach-at91/arm926ejs/reset.c +++ b/arch/arm/mach-at91/arm926ejs/reset.c @@ -12,7 +12,7 @@ #include <asm/arch/at91_rstc.h> /* Reset the cpu by telling the reset controller to do so */ -void reset_cpu(ulong ignored) +void reset_cpu(void) { at91_rstc_t *rstc = (at91_rstc_t *) ATMEL_BASE_RSTC; diff --git a/arch/arm/mach-at91/armv7/reset.c b/arch/arm/mach-at91/armv7/reset.c index 8f4c81d1af..1ea415ea9e 100644 --- a/arch/arm/mach-at91/armv7/reset.c +++ b/arch/arm/mach-at91/armv7/reset.c @@ -15,7 +15,7 @@ #include <asm/arch/at91_rstc.h> /* Reset the cpu by telling the reset controller to do so */ -void reset_cpu(ulong ignored) +void reset_cpu(void) { at91_rstc_t *rstc = (at91_rstc_t *)ATMEL_BASE_RSTC; diff --git a/arch/arm/mach-bcm283x/reset.c b/arch/arm/mach-bcm283x/reset.c index 2b4ccd4727..f13ac0c637 100644 --- a/arch/arm/mach-bcm283x/reset.c +++ b/arch/arm/mach-bcm283x/reset.c @@ -48,7 +48,7 @@ __reset_cpu(struct bcm2835_wdog_regs *wdog_regs, ulong ticks) writel(BCM2835_WDOG_PASSWORD | rstc, &wdog_regs->rstc); } -void reset_cpu(ulong ticks) +void reset_cpu(void) { struct bcm2835_wdog_regs *regs = (struct bcm2835_wdog_regs *)BCM2835_WDOG_PHYSADDR; diff --git a/arch/arm/mach-davinci/reset.c b/arch/arm/mach-davinci/reset.c index 4e6031a593..0d59eb6e3c 100644 --- a/arch/arm/mach-davinci/reset.c +++ b/arch/arm/mach-davinci/reset.c @@ -12,7 +12,7 @@ #include <asm/arch/timer_defs.h> #include <asm/arch/hardware.h> -void reset_cpu(unsigned long a) +void reset_cpu(void) { struct davinci_timer *const wdttimer = (struct davinci_timer *)DAVINCI_WDOG_BASE; diff --git a/arch/arm/mach-exynos/soc.c b/arch/arm/mach-exynos/soc.c index 810fa348ee..a07c87a2c8 100644 --- a/arch/arm/mach-exynos/soc.c +++ b/arch/arm/mach-exynos/soc.c @@ -20,7 +20,7 @@ extern void _main(void); void *secondary_boot_addr = (void *)_main; #endif /* CONFIG_TARGET_ESPRESSO7420 */ -void reset_cpu(ulong addr) +void reset_cpu(void) { #ifdef CONFIG_CPU_V7A writel(0x1, samsung_get_base_swreset()); diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 5f37282ff1..e6bc977fc8 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -923,7 +923,7 @@ usb_modify_speed: #endif #if !CONFIG_IS_ENABLED(SYSRESET) -void reset_cpu(ulong addr) +void reset_cpu(void) { struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR; diff --git a/arch/arm/mach-imx/mx7ulp/soc.c b/arch/arm/mach-imx/mx7ulp/soc.c index 8dd6b4d40e..320f24dd29 100644 --- a/arch/arm/mach-imx/mx7ulp/soc.c +++ b/arch/arm/mach-imx/mx7ulp/soc.c @@ -197,7 +197,7 @@ void s_init(void) #endif #ifndef CONFIG_ULP_WATCHDOG -void reset_cpu(ulong addr) +void reset_cpu(void) { setbits_le32(SIM0_RBASE, SIM_SOPT1_A7_SW_RESET); while (1) diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c index 4fbf14843e..9191f686f0 100644 --- a/arch/arm/mach-k3/common.c +++ b/arch/arm/mach-k3/common.c @@ -320,7 +320,7 @@ int fdt_disable_node(void *blob, char *node_path) #endif #ifndef CONFIG_SYSRESET -void reset_cpu(ulong ignored) +void reset_cpu(void) { } #endif diff --git a/arch/arm/mach-keystone/ddr3.c b/arch/arm/mach-keystone/ddr3.c index 7dea600d50..9ee3284156 100644 --- a/arch/arm/mach-keystone/ddr3.c +++ b/arch/arm/mach-keystone/ddr3.c @@ -345,7 +345,7 @@ void ddr3_check_ecc_int(u32 base) if (!ecc_test) { puts("Reseting the device ...\n"); - reset_cpu(0); + reset_cpu(); } } @@ -445,7 +445,7 @@ void ddr3_err_reset_workaround(void) tmp &= ~KS2_RSTYPE_PLL_SOFT; __raw_writel(tmp, KS2_RSTCTRL_RSCFG); - reset_cpu(0); + reset_cpu(); } } #endif diff --git a/arch/arm/mach-keystone/init.c b/arch/arm/mach-keystone/init.c index 4950f14655..5b95f60500 100644 --- a/arch/arm/mach-keystone/init.c +++ b/arch/arm/mach-keystone/init.c @@ -192,7 +192,7 @@ int arch_cpu_init(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { volatile u32 *rstctrl = (volatile u32 *)(KS2_RSTCTRL); u32 tmp; diff --git a/arch/arm/mach-kirkwood/cpu.c b/arch/arm/mach-kirkwood/cpu.c index 551c22a8ea..9c818fa45e 100644 --- a/arch/arm/mach-kirkwood/cpu.c +++ b/arch/arm/mach-kirkwood/cpu.c @@ -19,7 +19,7 @@ #include <asm/arch/soc.h> #include <mvebu_mmc.h> -void reset_cpu(unsigned long ignored) +void reset_cpu(void) { struct kwcpu_registers *cpureg = (struct kwcpu_registers *)KW_CPU_REG_BASE; diff --git a/arch/arm/mach-lpc32xx/cpu.c b/arch/arm/mach-lpc32xx/cpu.c index 32af620605..c2586d0929 100644 --- a/arch/arm/mach-lpc32xx/cpu.c +++ b/arch/arm/mach-lpc32xx/cpu.c @@ -17,28 +17,17 @@ static struct clk_pm_regs *clk = (struct clk_pm_regs *)CLK_PM_BASE; static struct wdt_regs *wdt = (struct wdt_regs *)WDT_BASE; -void reset_cpu(ulong addr) +void reset_cpu(void) { /* Enable watchdog clock */ setbits_le32(&clk->timclk_ctrl, CLK_TIMCLK_WATCHDOG); - /* To be compatible with the original U-Boot code: - * addr: - 0: perform hard reset. - * - !=0: perform a soft reset; i.e. "RESOUT_N" not asserted). */ - if (addr == 0) { - /* Reset pulse length is 13005 peripheral clock frames */ - writel(13000, &wdt->pulse); + /* Reset pulse length is 13005 peripheral clock frames */ + writel(13000, &wdt->pulse); - /* Force WDOG_RESET2 and RESOUT_N signal active */ - writel(WDTIM_MCTRL_RESFRC2 | WDTIM_MCTRL_RESFRC1 - | WDTIM_MCTRL_M_RES2, &wdt->mctrl); - } else { - /* Force match output active */ - writel(0x01, &wdt->emr); - - /* Internal reset on match output (no pulse on "RESOUT_N") */ - writel(WDTIM_MCTRL_M_RES1, &wdt->mctrl); - } + /* Force WDOG_RESET2 and RESOUT_N signal active */ + writel(WDTIM_MCTRL_RESFRC2 | WDTIM_MCTRL_RESFRC1 | WDTIM_MCTRL_M_RES2, + &wdt->mctrl); while (1) /* NOP */; diff --git a/arch/arm/mach-mediatek/mt7622/init.c b/arch/arm/mach-mediatek/mt7622/init.c index 7f6ce80f37..e501907b53 100644 --- a/arch/arm/mach-mediatek/mt7622/init.c +++ b/arch/arm/mach-mediatek/mt7622/init.c @@ -27,7 +27,7 @@ int dram_init(void) } -void reset_cpu(ulong addr) +void reset_cpu(void) { psci_system_reset(); } diff --git a/arch/arm/mach-mediatek/mt8512/init.c b/arch/arm/mach-mediatek/mt8512/init.c index c14e7d22e6..b7050dfc39 100644 --- a/arch/arm/mach-mediatek/mt8512/init.c +++ b/arch/arm/mach-mediatek/mt8512/init.c @@ -43,7 +43,7 @@ int dram_init_banksize(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { struct udevice *watchdog_dev = NULL; diff --git a/arch/arm/mach-mediatek/mt8516/init.c b/arch/arm/mach-mediatek/mt8516/init.c index 3771152fb3..3460dcc249 100644 --- a/arch/arm/mach-mediatek/mt8516/init.c +++ b/arch/arm/mach-mediatek/mt8516/init.c @@ -85,7 +85,7 @@ int mtk_soc_early_init(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { psci_system_reset(); } diff --git a/arch/arm/mach-mediatek/mt8518/init.c b/arch/arm/mach-mediatek/mt8518/init.c index 28b00c3dec..f7e03de365 100644 --- a/arch/arm/mach-mediatek/mt8518/init.c +++ b/arch/arm/mach-mediatek/mt8518/init.c @@ -42,7 +42,7 @@ int dram_init_banksize(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { psci_system_reset(); } diff --git a/arch/arm/mach-meson/board-common.c b/arch/arm/mach-meson/board-common.c index 34b3c8f399..1690b6b1e6 100644 --- a/arch/arm/mach-meson/board-common.c +++ b/arch/arm/mach-meson/board-common.c @@ -167,7 +167,7 @@ int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { struct pt_regs regs; @@ -182,7 +182,7 @@ void reset_cpu(ulong addr) ; } #else -void reset_cpu(ulong addr) +void reset_cpu(void) { psci_system_reset(); } diff --git a/arch/arm/mach-mvebu/armada3700/cpu.c b/arch/arm/mach-mvebu/armada3700/cpu.c index 70f76c7d70..0cf60d7cdd 100644 --- a/arch/arm/mach-mvebu/armada3700/cpu.c +++ b/arch/arm/mach-mvebu/armada3700/cpu.c @@ -314,7 +314,7 @@ int a3700_fdt_fix_pcie_regions(void *blob) return fdt_setprop_inplace(blob, node, "ranges", new_ranges, len); } -void reset_cpu(ulong ignored) +void reset_cpu(void) { /* * Write magic number of 0x1d1e to North Bridge Warm Reset register diff --git a/arch/arm/mach-mvebu/armada8k/cpu.c b/arch/arm/mach-mvebu/armada8k/cpu.c index 529dac9059..474327a8e1 100644 --- a/arch/arm/mach-mvebu/armada8k/cpu.c +++ b/arch/arm/mach-mvebu/armada8k/cpu.c @@ -104,7 +104,7 @@ void enable_caches(void) dcache_enable(); } -void reset_cpu(ulong ignored) +void reset_cpu(void) { u32 reg; diff --git a/arch/arm/mach-mvebu/cpu.c b/arch/arm/mach-mvebu/cpu.c index 7dce11e77f..0b935c46fb 100644 --- a/arch/arm/mach-mvebu/cpu.c +++ b/arch/arm/mach-mvebu/cpu.c @@ -42,7 +42,7 @@ void lowlevel_init(void) */ } -void reset_cpu(unsigned long ignored) +void reset_cpu(void) { struct mvebu_system_registers *reg = (struct mvebu_system_registers *)MVEBU_SYSTEM_REG_BASE; diff --git a/arch/arm/mach-nexell/Makefile b/arch/arm/mach-nexell/Makefile index 10b3963ed1..dda16dbb8e 100644 --- a/arch/arm/mach-nexell/Makefile +++ b/arch/arm/mach-nexell/Makefile @@ -10,4 +10,3 @@ obj-y += nx_gpio.o obj-y += tieoff.o obj-$(CONFIG_ARCH_S5P4418) += reg-call.o obj-$(CONFIG_ARCH_S5P4418) += nx_sec_reg.o -obj-$(CONFIG_CMD_BOOTL) += cmd_boot_linux.o diff --git a/arch/arm/mach-nexell/cmd_boot_linux.c b/arch/arm/mach-nexell/cmd_boot_linux.c deleted file mode 100644 index 9b38d38ddb..0000000000 --- a/arch/arm/mach-nexell/cmd_boot_linux.c +++ /dev/null @@ -1,145 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2016 nexell - * jhkim <jhkim@nexell.co.kr> - */ - -#include <common.h> -#include <bootm.h> -#include <command.h> -#include <environment.h> -#include <errno.h> -#include <image.h> -#include <fdt_support.h> -#include <asm/global_data.h> - -#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_CLI_FRAMEWORK) - -DECLARE_GLOBAL_DATA_PTR; - -static bootm_headers_t linux_images; - -static void boot_go_set_os(cmd_tbl_t *cmdtp, int flag, int argc, - char * const argv[], - bootm_headers_t *images) -{ - char * const img_addr = argv[0]; - - images->os.type = IH_TYPE_KERNEL; - images->os.comp = IH_COMP_NONE; - images->os.os = IH_OS_LINUX; - images->os.load = simple_strtoul(img_addr, NULL, 16); - images->ep = images->os.load; -#if defined(CONFIG_ARM) - images->os.arch = IH_ARCH_ARM; -#elif defined(CONFIG_ARM64) - images->os.arch = IH_ARCH_ARM64; -#else - #error "Not support architecture ..." -#endif - if (!IS_ENABLED(CONFIG_OF_LIBFDT) && !IS_ENABLED(CONFIG_SPL_BUILD)) { - /* set DTB address for linux kernel */ - if (argc > 2) { - unsigned long ft_addr; - - ft_addr = simple_strtol(argv[2], NULL, 16); - images->ft_addr = (char *)ft_addr; - - /* - * if not defined IMAGE_ENABLE_OF_LIBFDT, - * must be set to fdt address - */ - if (!IMAGE_ENABLE_OF_LIBFDT) - gd->bd->bi_boot_params = ft_addr; - - debug("## set ft:%08lx and boot params:%08lx [control of:%s]" - "...\n", ft_addr, gd->bd->bi_boot_params, - IMAGE_ENABLE_OF_LIBFDT ? "on" : "off"); - } - } -} - -#if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_LMB) -static void boot_start_lmb(bootm_headers_t *images) -{ - ulong mem_start; - phys_size_t mem_size; - - lmb_init(&images->lmb); - - mem_start = getenv_bootm_low(); - mem_size = getenv_bootm_size(); - - lmb_add(&images->lmb, (phys_addr_t)mem_start, mem_size); - - arch_lmb_reserve(&images->lmb); - board_lmb_reserve(&images->lmb); -} -#else -#define lmb_reserve(lmb, base, size) -static inline void boot_start_lmb(bootm_headers_t *images) { } -#endif - -int do_boot_linux(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - boot_os_fn *boot_fn; - bootm_headers_t *images = &linux_images; - int flags; - int ret; - - boot_start_lmb(images); - - flags = BOOTM_STATE_START; - - argc--; argv++; - boot_go_set_os(cmdtp, flag, argc, argv, images); - - if (IS_ENABLED(CONFIG_OF_LIBFDT)) { - /* find flattened device tree */ - ret = boot_get_fdt(flag, argc, argv, IH_ARCH_DEFAULT, images, - &images->ft_addr, &images->ft_len); - if (ret) { - puts("Could not find a valid device tree\n"); - return 1; - } - set_working_fdt_addr((ulong)images->ft_addr); - } - - if (!IS_ENABLED(CONFIG_OF_LIBFDT)) - flags |= BOOTM_STATE_OS_GO; - - boot_fn = do_bootm_linux; - ret = boot_fn(flags, argc, argv, images); - - if (ret == BOOTM_ERR_UNIMPLEMENTED) - show_boot_progress(BOOTSTAGE_ID_DECOMP_UNIMPL); - else if (ret == BOOTM_ERR_RESET) - do_reset(cmdtp, flag, argc, argv); - - return ret; -} - -U_BOOT_CMD(bootl, CONFIG_SYS_MAXARGS, 1, do_boot_linux, - "boot linux image from memory", - "[addr [arg ...]]\n - boot linux image stored in memory\n" - "\tuse a '-' for the DTB address\n" -); -#endif - -#if defined(CONFIG_CMD_BOOTD) && !defined(CONFIG_CMD_BOOTM) -int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - return run_command(env_get("bootcmd"), flag); -} - -U_BOOT_CMD(boot, 1, 1, do_bootd, - "boot default, i.e., run 'bootcmd'", - "" -); - -/* keep old command name "bootd" for backward compatibility */ -U_BOOT_CMD(bootd, 1, 1, do_bootd, - "boot default, i.e., run 'bootcmd'", - "" -); -#endif diff --git a/arch/arm/mach-octeontx/cpu.c b/arch/arm/mach-octeontx/cpu.c index ce5f2b42d7..7bd74fe4f6 100644 --- a/arch/arm/mach-octeontx/cpu.c +++ b/arch/arm/mach-octeontx/cpu.c @@ -72,6 +72,6 @@ u64 get_page_table_size(void) return 0x80000; } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/arch/arm/mach-octeontx2/cpu.c b/arch/arm/mach-octeontx2/cpu.c index 87868152b7..afa458c09b 100644 --- a/arch/arm/mach-octeontx2/cpu.c +++ b/arch/arm/mach-octeontx2/cpu.c @@ -68,6 +68,6 @@ u64 get_page_table_size(void) return 0x80000; } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/arch/arm/mach-omap2/omap-cache.c b/arch/arm/mach-omap2/omap-cache.c index 1b246f844a..36db588243 100644 --- a/arch/arm/mach-omap2/omap-cache.c +++ b/arch/arm/mach-omap2/omap-cache.c @@ -41,9 +41,6 @@ DECLARE_GLOBAL_DATA_PTR; #define ARMV7_DCACHE_POLICY DCACHE_WRITEBACK & ~TTB_SECT_XN_MASK #endif -#define ARMV7_DOMAIN_CLIENT 1 -#define ARMV7_DOMAIN_MASK (0x3 << 0) - void enable_caches(void) { @@ -67,17 +64,3 @@ void dram_bank_mmu_setup(int bank) for (i = start; i < end; i++) set_section_dcache(i, ARMV7_DCACHE_POLICY); } - -void arm_init_domains(void) -{ - u32 reg; - - reg = get_dacr(); - /* - * Set DOMAIN to client access so that all permissions - * set in pagetables are validated by the mmu. - */ - reg &= ~ARMV7_DOMAIN_MASK; - reg |= ARMV7_DOMAIN_CLIENT; - set_dacr(reg); -} diff --git a/arch/arm/mach-omap2/omap5/hwinit.c b/arch/arm/mach-omap2/omap5/hwinit.c index 47ac8656bf..edab9a9298 100644 --- a/arch/arm/mach-omap2/omap5/hwinit.c +++ b/arch/arm/mach-omap2/omap5/hwinit.c @@ -417,7 +417,7 @@ void omap_die_id(unsigned int *die_id) die_id[3] = readl((*ctrl)->control_std_fuse_die_id_3); } -void reset_cpu(ulong ignored) +void reset_cpu(void) { u32 omap_rev = omap_revision(); diff --git a/arch/arm/mach-omap2/reset.c b/arch/arm/mach-omap2/reset.c index 2bbd5fcb9b..1fd79c2e8a 100644 --- a/arch/arm/mach-omap2/reset.c +++ b/arch/arm/mach-omap2/reset.c @@ -14,7 +14,7 @@ #include <asm/arch/cpu.h> #include <linux/compiler.h> -void __weak reset_cpu(unsigned long ignored) +void __weak reset_cpu(void) { writel(PRM_RSTCTRL_RESET, PRM_RSTCTRL); } diff --git a/arch/arm/mach-orion5x/cpu.c b/arch/arm/mach-orion5x/cpu.c index beae7b8484..ffae9a01e3 100644 --- a/arch/arm/mach-orion5x/cpu.c +++ b/arch/arm/mach-orion5x/cpu.c @@ -20,7 +20,7 @@ #define BUFLEN 16 -void reset_cpu(unsigned long ignored) +void reset_cpu(void) { struct orion5x_cpu_registers *cpureg = (struct orion5x_cpu_registers *)ORION5X_CPU_REG_BASE; diff --git a/arch/arm/mach-owl/soc.c b/arch/arm/mach-owl/soc.c index 4d2b9d0b0e..4baef2eed3 100644 --- a/arch/arm/mach-owl/soc.c +++ b/arch/arm/mach-owl/soc.c @@ -74,7 +74,7 @@ int board_init(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { psci_system_reset(); } diff --git a/arch/arm/mach-socfpga/include/mach/reset_manager.h b/arch/arm/mach-socfpga/include/mach/reset_manager.h index 8c25325e45..1d68034cb5 100644 --- a/arch/arm/mach-socfpga/include/mach/reset_manager.h +++ b/arch/arm/mach-socfpga/include/mach/reset_manager.h @@ -8,7 +8,7 @@ phys_addr_t socfpga_get_rstmgr_addr(void); -void reset_cpu(ulong addr); +void reset_cpu(void); void socfpga_per_reset(u32 reset, int set); void socfpga_per_reset_all(void); diff --git a/arch/arm/mach-stm32mp/cpu.c b/arch/arm/mach-stm32mp/cpu.c index bc2db535be..897ec13ad8 100644 --- a/arch/arm/mach-stm32mp/cpu.c +++ b/arch/arm/mach-stm32mp/cpu.c @@ -212,6 +212,35 @@ u32 get_bootmode(void) } /* + * weak function overidde: set the DDR/SYSRAM executable before to enable the + * MMU and configure DACR, for early early_enable_caches (SPL or pre-reloc) + */ +void dram_bank_mmu_setup(int bank) +{ + struct bd_info *bd = gd->bd; + int i; + phys_addr_t start; + phys_size_t size; + + if (IS_ENABLED(CONFIG_SPL_BUILD)) { + start = ALIGN_DOWN(STM32_SYSRAM_BASE, MMU_SECTION_SIZE); + size = ALIGN(STM32_SYSRAM_SIZE, MMU_SECTION_SIZE); + } else if (gd->flags & GD_FLG_RELOC) { + /* bd->bi_dram is available only after relocation */ + start = bd->bi_dram[bank].start; + size = bd->bi_dram[bank].size; + } else { + /* mark cacheable and executable the beggining of the DDR */ + start = STM32_DDR_BASE; + size = CONFIG_DDR_CACHEABLE_SIZE; + } + + for (i = start >> MMU_SECTION_SHIFT; + i < (start >> MMU_SECTION_SHIFT) + (size >> MMU_SECTION_SHIFT); + i++) + set_section_dcache(i, DCACHE_DEFAULT_OPTION); +} +/* * initialize the MMU and activate cache in SPL or in U-Boot pre-reloc stage * MMU/TLB is updated in enable_caches() for U-Boot after relocation * or is deactivated in U-Boot entry function start.S::cpu_init_cp15 @@ -228,17 +257,8 @@ static void early_enable_caches(void) gd->arch.tlb_addr = (unsigned long)&early_tlb; } + /* enable MMU (default configuration) */ dcache_enable(); - - if (IS_ENABLED(CONFIG_SPL_BUILD)) - mmu_set_region_dcache_behaviour( - ALIGN_DOWN(STM32_SYSRAM_BASE, MMU_SECTION_SIZE), - ALIGN(STM32_SYSRAM_SIZE, MMU_SECTION_SIZE), - DCACHE_DEFAULT_OPTION); - else - mmu_set_region_dcache_behaviour(STM32_DDR_BASE, - CONFIG_DDR_CACHEABLE_SIZE, - DCACHE_DEFAULT_OPTION); } /* diff --git a/arch/arm/mach-stm32mp/dram_init.c b/arch/arm/mach-stm32mp/dram_init.c index ad6977fd44..66e81bacca 100644 --- a/arch/arm/mach-stm32mp/dram_init.c +++ b/arch/arm/mach-stm32mp/dram_init.c @@ -13,6 +13,7 @@ #include <log.h> #include <ram.h> #include <asm/global_data.h> +#include <asm/system.h> DECLARE_GLOBAL_DATA_PTR; @@ -41,6 +42,7 @@ int dram_init(void) ulong board_get_usable_ram_top(ulong total_size) { + phys_size_t size; phys_addr_t reg; struct lmb lmb; @@ -48,10 +50,13 @@ ulong board_get_usable_ram_top(ulong total_size) lmb_init(&lmb); lmb_add(&lmb, gd->ram_base, gd->ram_size); boot_fdt_add_mem_rsv_regions(&lmb, (void *)gd->fdt_blob); - reg = lmb_alloc(&lmb, CONFIG_SYS_MALLOC_LEN + total_size, SZ_4K); + size = ALIGN(CONFIG_SYS_MALLOC_LEN + total_size, MMU_SECTION_SIZE), + reg = lmb_alloc(&lmb, size, MMU_SECTION_SIZE); - if (reg) - return ALIGN(reg + CONFIG_SYS_MALLOC_LEN + total_size, SZ_4K); + if (!reg) + reg = gd->ram_top - size; - return gd->ram_top; + mmu_set_region_dcache_behaviour(reg, size, DCACHE_DEFAULT_OPTION); + + return reg + size; } diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 0135575ca1..a29d11505a 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -816,13 +816,14 @@ config VIDEO_SUNXI depends on !MACH_SUN9I depends on !MACH_SUN50I depends on !SUN50I_GEN_H6 - select VIDEO + select DM_VIDEO + select DISPLAY imply VIDEO_DT_SIMPLEFB default y ---help--- - Say Y here to add support for using a cfb console on the HDMI, LCD - or VGA output found on most sunxi devices. See doc/README.video for - info on how to select the video output and mode. + Say Y here to add support for using a graphical console on the HDMI, + LCD or VGA output found on older sunxi devices. This will also provide + a simple_framebuffer device for Linux. config VIDEO_HDMI bool "HDMI output support" diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index fa2b6fcfd6..503538e26d 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -338,7 +338,7 @@ void board_init_f(ulong dummy) } #endif -void reset_cpu(ulong addr) +void reset_cpu(void) { #if defined(CONFIG_SUNXI_GEN_SUN4I) || defined(CONFIG_MACH_SUN8I_R40) static const struct sunxi_wdog *wdog = diff --git a/arch/arm/mach-tegra/cmd_enterrcm.c b/arch/arm/mach-tegra/cmd_enterrcm.c index 25df31a3b8..92ff6cb1bf 100644 --- a/arch/arm/mach-tegra/cmd_enterrcm.c +++ b/arch/arm/mach-tegra/cmd_enterrcm.c @@ -40,7 +40,7 @@ static int do_enterrcm(struct cmd_tbl *cmdtp, int flag, int argc, tegra_pmc_writel(2, PMC_SCRATCH0); disable_interrupts(); - reset_cpu(0); + reset_cpu(); return 0; } diff --git a/arch/arm/mach-tegra/pmc.c b/arch/arm/mach-tegra/pmc.c index 93db63e104..8d617bee63 100644 --- a/arch/arm/mach-tegra/pmc.c +++ b/arch/arm/mach-tegra/pmc.c @@ -85,7 +85,7 @@ void tegra_pmc_writel(u32 value, unsigned long offset) writel(value, NV_PA_PMC_BASE + offset); } -void reset_cpu(ulong addr) +void reset_cpu(void) { u32 value; diff --git a/arch/arm/mach-uniphier/arm32/psci.c b/arch/arm/mach-uniphier/arm32/psci.c index a4d260aece..fbb6ebca77 100644 --- a/arch/arm/mach-uniphier/arm32/psci.c +++ b/arch/arm/mach-uniphier/arm32/psci.c @@ -158,5 +158,5 @@ s32 __secure psci_cpu_on(u32 function_id, u32 cpuid, u32 entry_point, void __secure psci_system_reset(void) { - reset_cpu(0); + reset_cpu(); } diff --git a/arch/arm/mach-uniphier/reset.c b/arch/arm/mach-uniphier/reset.c index 5fffd23e9a..dddb48ec4a 100644 --- a/arch/arm/mach-uniphier/reset.c +++ b/arch/arm/mach-uniphier/reset.c @@ -18,7 +18,7 @@ #define __SECURE #endif -void __SECURE reset_cpu(unsigned long ignored) +void __SECURE reset_cpu(void) { u32 tmp; diff --git a/arch/arm/mach-zynq/cpu.c b/arch/arm/mach-zynq/cpu.c index 3befc12028..69b818f24b 100644 --- a/arch/arm/mach-zynq/cpu.c +++ b/arch/arm/mach-zynq/cpu.c @@ -78,7 +78,7 @@ unsigned int zynq_get_silicon_version(void) >> ZYNQ_SILICON_VER_SHIFT; } -void reset_cpu(ulong addr) +void reset_cpu(void) { zynq_slcr_cpu_reset(); while (1) diff --git a/arch/arm/mach-zynqmp-r5/cpu.c b/arch/arm/mach-zynqmp-r5/cpu.c index d841c3a5b3..0d368443d8 100644 --- a/arch/arm/mach-zynqmp-r5/cpu.c +++ b/arch/arm/mach-zynqmp-r5/cpu.c @@ -30,7 +30,7 @@ int arch_cpu_init(void) /* * Perform the low-level reset. */ -void reset_cpu(ulong addr) +void reset_cpu(void) { while (1) ; diff --git a/arch/nds32/cpu/n1213/ag101/cpu.c b/arch/nds32/cpu/n1213/ag101/cpu.c index 9d99c83bf3..91c3574bce 100644 --- a/arch/nds32/cpu/n1213/ag101/cpu.c +++ b/arch/nds32/cpu/n1213/ag101/cpu.c @@ -46,7 +46,7 @@ int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) /* * reset to the base addr of andesboot. * currently no ROM loader at addr 0. - * do not use reset_cpu(0); + * do not use reset_cpu(); */ #ifdef CONFIG_FTWDT010_WATCHDOG /* diff --git a/arch/nds32/cpu/n1213/start.S b/arch/nds32/cpu/n1213/start.S index 386c1998dc..3395721552 100644 --- a/arch/nds32/cpu/n1213/start.S +++ b/arch/nds32/cpu/n1213/start.S @@ -500,25 +500,3 @@ software_interrupt: bal do_interruption .align 5 - -/* - * void reset_cpu(ulong addr); - * $r0: input address to jump to - */ -.globl reset_cpu -reset_cpu: -/* No need to disable MMU because we never enable it */ - - bal invalidate_icac - bal invalidate_dcac - mfsr $p0, $MMU_CFG - andi $p0, $p0, 0x3 ! MMPS - li $p1, 0x2 ! TLB MMU - bne $p0, $p1, 1f - tlbop flushall ! Flush TLB -1: - mfsr $p0, MR_CAC_CTL ! Get the $CACHE_CTL reg - li $p1, DIS_DCAC - and $p0, $p0, $p1 ! Clear the DC_EN bit - mtsr $p0, MR_CAC_CTL ! Write back the $CACHE_CTL reg - br $r0 ! Jump to the input address diff --git a/arch/nds32/lib/interrupts.c b/arch/nds32/lib/interrupts.c index 1481e05500..0ec72d157f 100644 --- a/arch/nds32/lib/interrupts.c +++ b/arch/nds32/lib/interrupts.c @@ -66,7 +66,7 @@ int disable_interrupts(void) void bad_mode(void) { panic("Resetting CPU ...\n"); - reset_cpu(0); + reset_cpu(); } void show_regs(struct pt_regs *regs) diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 3d8af0a52b..2d9583c17c 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -153,7 +153,7 @@ int os_read_file(const char *fname, void **bufp, int *sizep) printf("Cannot seek to start of file '%s'\n", fname); goto err; } - *bufp = malloc(size); + *bufp = os_malloc(size); if (!*bufp) { printf("Not enough memory to read file '%s'\n", fname); ret = -ENOMEM; @@ -267,11 +267,18 @@ void os_tty_raw(int fd, bool allow_sigs) signal(SIGINT, os_sigint_handler); } +/* + * Provide our own malloc so we don't use space in the sandbox ram_buf for + * allocations that are internal to sandbox, or need to be done before U-Boot's + * malloc() is ready. + */ void *os_malloc(size_t length) { int page_size = getpagesize(); struct os_mem_hdr *hdr; + if (!length) + return NULL; /* * Use an address that is hopefully available to us so that pointers * to this memory are fairly obvious. If we end up with a different @@ -298,6 +305,47 @@ void os_free(void *ptr) } } +/* These macros are from kernel.h but not accessible in this file */ +#define ALIGN(x, a) __ALIGN_MASK((x), (typeof(x))(a) - 1) +#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) + +/* + * Provide our own malloc so we don't use space in the sandbox ram_buf for + * allocations that are internal to sandbox, or need to be done before U-Boot's + * malloc() is ready. + */ +void *os_realloc(void *ptr, size_t length) +{ + int page_size = getpagesize(); + struct os_mem_hdr *hdr; + void *new_ptr; + + /* Reallocating a NULL pointer is just an alloc */ + if (!ptr) + return os_malloc(length); + + /* Changing a length to 0 is just a free */ + if (length) { + os_free(ptr); + return NULL; + } + + /* + * If the new size is the same number of pages as the old, nothing to + * do. There isn't much point in shrinking things + */ + hdr = ptr - page_size; + if (ALIGN(length, page_size) <= ALIGN(hdr->length, page_size)) + return ptr; + + /* We have to grow it, so allocate something new */ + new_ptr = os_malloc(length); + memcpy(new_ptr, ptr, hdr->length); + os_free(ptr); + + return new_ptr; +} + void os_usleep(unsigned long usec) { usleep(usec); @@ -343,8 +391,8 @@ int os_parse_args(struct sandbox_state *state, int argc, char *argv[]) state->argv = argv; /* dynamically construct the arguments to the system getopt_long */ - short_opts = malloc(sizeof(*short_opts) * num_options * 2 + 1); - long_opts = malloc(sizeof(*long_opts) * (num_options + 1)); + short_opts = os_malloc(sizeof(*short_opts) * num_options * 2 + 1); + long_opts = os_malloc(sizeof(*long_opts) * (num_options + 1)); if (!short_opts || !long_opts) return 1; @@ -423,7 +471,7 @@ void os_dirent_free(struct os_dirent_node *node) while (node) { next = node->next; - free(node); + os_free(node); node = next; } } @@ -448,7 +496,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp) /* Create a buffer upfront, with typically sufficient size */ dirlen = strlen(dirname) + 2; len = dirlen + 256; - fname = malloc(len); + fname = os_malloc(len); if (!fname) { ret = -ENOMEM; goto done; @@ -461,7 +509,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp) ret = errno; break; } - next = malloc(sizeof(*node) + strlen(entry->d_name) + 1); + next = os_malloc(sizeof(*node) + strlen(entry->d_name) + 1); if (!next) { os_dirent_free(head); ret = -ENOMEM; @@ -470,10 +518,10 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp) if (dirlen + strlen(entry->d_name) > len) { len = dirlen + strlen(entry->d_name); old_fname = fname; - fname = realloc(fname, len); + fname = os_realloc(fname, len); if (!fname) { - free(old_fname); - free(next); + os_free(old_fname); + os_free(next); os_dirent_free(head); ret = -ENOMEM; goto done; @@ -507,7 +555,7 @@ int os_dirent_ls(const char *dirname, struct os_dirent_node **headp) done: closedir(dir); - free(fname); + os_free(fname); return ret; } @@ -624,7 +672,7 @@ static int add_args(char ***argvp, char *add_args[], int count) for (argc = 0; (*argvp)[argc]; argc++) ; - argv = malloc((argc + count + 1) * sizeof(char *)); + argv = os_malloc((argc + count + 1) * sizeof(char *)); if (!argv) { printf("Out of memory for %d argv\n", count); return -ENOMEM; @@ -707,7 +755,7 @@ static int os_jump_to_file(const char *fname) os_exit(2); err = execv(fname, argv); - free(argv); + os_free(argv); if (err) { perror("Unable to run image"); printf("Image filename '%s'\n", fname); @@ -729,7 +777,7 @@ int os_jump_to_image(const void *dest, int size) return os_jump_to_file(fname); } -int os_find_u_boot(char *fname, int maxlen) +int os_find_u_boot(char *fname, int maxlen, bool use_img) { struct sandbox_state *state = state_get_current(); const char *progname = state->argv[0]; @@ -753,8 +801,8 @@ int os_find_u_boot(char *fname, int maxlen) return 0; } - /* Look for 'u-boot-tpl' in the tpl/ directory */ - p = strstr(fname, "/tpl/"); + /* Look for 'u-boot-spl' in the spl/ directory */ + p = strstr(fname, "/spl/"); if (p) { p[1] = 's'; fd = os_open(fname, O_RDONLY); @@ -781,6 +829,8 @@ int os_find_u_boot(char *fname, int maxlen) if (p) { /* Remove the "spl" characters */ memmove(p, p + 4, strlen(p + 4) + 1); + if (use_img) + strcat(p, ".img"); fd = os_open(fname, O_RDONLY); if (fd >= 0) { close(fd); diff --git a/arch/sandbox/cpu/sdl.c b/arch/sandbox/cpu/sdl.c index d4dab36981..8102649be3 100644 --- a/arch/sandbox/cpu/sdl.c +++ b/arch/sandbox/cpu/sdl.c @@ -69,14 +69,14 @@ static void sandbox_sdl_poll_events(void) * We don't want to include common.h in this file since it uses * system headers. So add a declation here. */ - extern void reset_cpu(unsigned long addr); + extern void reset_cpu(void); SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: puts("LCD window closed - quitting\n"); - reset_cpu(1); + reset_cpu(); break; } } diff --git a/arch/sandbox/cpu/spl.c b/arch/sandbox/cpu/spl.c index e7b4b50681..f82b0d3de1 100644 --- a/arch/sandbox/cpu/spl.c +++ b/arch/sandbox/cpu/spl.c @@ -13,7 +13,7 @@ #include <asm/global_data.h> #include <asm/spl.h> #include <asm/state.h> -#include <test/test.h> +#include <test/ut.h> DECLARE_GLOBAL_DATA_PTR; @@ -37,16 +37,20 @@ static int spl_board_load_image(struct spl_image_info *spl_image, char fname[256]; int ret; - ret = os_find_u_boot(fname, sizeof(fname)); + ret = os_find_u_boot(fname, sizeof(fname), false); if (ret) { printf("(%s not found, error %d)\n", fname, ret); return ret; } - /* Set up spl_image to boot from jump_to_image_no_args() */ - spl_image->arg = strdup(fname); + /* + * Set up spl_image to boot from jump_to_image_no_args(). Allocate this + * outsdide the RAM buffer (i.e. don't use strdup()). + */ + spl_image->arg = os_malloc(strlen(fname) + 1); if (!spl_image->arg) - return log_msg_ret("Setup exec filename", -ENOMEM); + return log_msg_ret("exec", -ENOMEM); + strcpy(spl_image->arg, fname); return 0; } @@ -59,9 +63,12 @@ void spl_board_init(void) preloader_console_init(); if (state->run_unittests) { + struct unit_test *tests = UNIT_TEST_ALL_START(); + const int count = UNIT_TEST_ALL_COUNT(); int ret; - ret = dm_test_main(state->select_unittests); + ret = ut_run_list("spl", NULL, tests, count, + state->select_unittests); /* continue execution into U-Boot */ } } diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c index 483a264040..e87365e800 100644 --- a/arch/sandbox/cpu/start.c +++ b/arch/sandbox/cpu/start.c @@ -88,7 +88,7 @@ int sandbox_early_getopt_check(void) /* Sort the options */ size = sizeof(*sorted_opt) * num_options; - sorted_opt = malloc(size); + sorted_opt = os_malloc(size); if (!sorted_opt) { printf("No memory to sort options\n"); os_exit(1); @@ -188,7 +188,7 @@ static int sandbox_cmdline_cb_default_fdt(struct sandbox_state *state, int len; len = strlen(state->argv[0]) + strlen(fmt) + 1; - fname = malloc(len); + fname = os_malloc(len); if (!fname) return -ENOMEM; snprintf(fname, len, fmt, state->argv[0]); @@ -208,7 +208,7 @@ static int sandbox_cmdline_cb_test_fdt(struct sandbox_state *state, int len; len = strlen(state->argv[0]) + strlen(fmt) + 1; - fname = malloc(len); + fname = os_malloc(len); if (!fname) return -ENOMEM; strcpy(fname, state->argv[0]); @@ -436,16 +436,18 @@ int main(int argc, char *argv[]) { struct sandbox_state *state; gd_t data; + int size; int ret; /* * Copy argv[] so that we can pass the arguments in the original * sequence when resetting the sandbox. */ - os_argv = calloc(argc + 1, sizeof(char *)); + size = sizeof(char *) * (argc + 1); + os_argv = os_malloc(size); if (!os_argv) os_exit(1); - memcpy(os_argv, argv, sizeof(char *) * (argc + 1)); + memcpy(os_argv, argv, size); memset(&data, '\0', sizeof(data)); gd = &data; @@ -489,7 +491,6 @@ int main(int argc, char *argv[]) gd->reloc_off = (ulong)gd->arch.text_base; /* sandbox test: log functions called before log_init in board_init_f */ - log_info("sandbox: starting...\n"); log_debug("debug: %s\n", __func__); /* Do pre- and post-relocation init */ diff --git a/arch/sandbox/cpu/state.c b/arch/sandbox/cpu/state.c index b2901b7a8c..f63cfd38ee 100644 --- a/arch/sandbox/cpu/state.c +++ b/arch/sandbox/cpu/state.c @@ -4,6 +4,7 @@ */ #include <common.h> +#include <bloblist.h> #include <errno.h> #include <fdtdec.h> #include <log.h> @@ -29,17 +30,17 @@ static int state_ensure_space(int extra_size) return 0; size = used + extra_size; - buf = malloc(size); + buf = os_malloc(size); if (!buf) return -ENOMEM; ret = fdt_open_into(blob, buf, size); if (ret) { - free(buf); + os_free(buf); return -EIO; } - free(blob); + os_free(blob); state->state_fdt = buf; return 0; } @@ -55,7 +56,7 @@ static int state_read_file(struct sandbox_state *state, const char *fname) printf("Cannot find sandbox state file '%s'\n", fname); return -ENOENT; } - state->state_fdt = malloc(size); + state->state_fdt = os_malloc(size); if (!state->state_fdt) { puts("No memory to read sandbox state\n"); return -ENOMEM; @@ -77,7 +78,7 @@ static int state_read_file(struct sandbox_state *state, const char *fname) err_read: os_close(fd); err_open: - free(state->state_fdt); + os_free(state->state_fdt); state->state_fdt = NULL; return ret; @@ -244,7 +245,7 @@ int sandbox_write_state(struct sandbox_state *state, const char *fname) /* Create a state FDT if we don't have one */ if (!state->state_fdt) { size = 0x4000; - state->state_fdt = malloc(size); + state->state_fdt = os_malloc(size); if (!state->state_fdt) { puts("No memory to create FDT\n"); return -ENOMEM; @@ -302,7 +303,7 @@ int sandbox_write_state(struct sandbox_state *state, const char *fname) err_write: os_close(fd); err_create: - free(state->state_fdt); + os_free(state->state_fdt); return ret; } @@ -398,8 +399,12 @@ int state_uninit(void) { int err; + log_info("Writing sandbox state\n"); state = &main_state; + /* Finish the bloblist, so that it is correct before writing memory */ + bloblist_finish(); + if (state->write_ram_buf) { err = os_write_ram_buf(state->ram_buf_fname); if (err) { @@ -419,8 +424,8 @@ int state_uninit(void) if (state->jumped_fname) os_unlink(state->jumped_fname); - if (state->state_fdt) - free(state->state_fdt); + os_free(state->state_fdt); + os_free(state->ram_buf); memset(state, '\0', sizeof(*state)); return 0; diff --git a/arch/sandbox/include/asm/gpio.h b/arch/sandbox/include/asm/gpio.h index df4ba4fb5f..9e10052667 100644 --- a/arch/sandbox/include/asm/gpio.h +++ b/arch/sandbox/include/asm/gpio.h @@ -23,6 +23,15 @@ */ #include <asm-generic/gpio.h> +/* Our own private GPIO flags, which musn't conflict with GPIOD_... */ +#define GPIOD_EXT_HIGH BIT(31) /* external source is high (else low) */ +#define GPIOD_EXT_DRIVEN BIT(30) /* external source is driven */ +#define GPIOD_EXT_PULL_UP BIT(29) /* GPIO has external pull-up */ +#define GPIOD_EXT_PULL_DOWN BIT(28) /* GPIO has external pull-down */ + +#define GPIOD_EXT_PULL (BIT(28) | BIT(29)) +#define GPIOD_SANDBOX_MASK GENMASK(31, 28) + /** * Return the simulated value of a GPIO (used only in sandbox test code) * @@ -69,17 +78,17 @@ int sandbox_gpio_set_direction(struct udevice *dev, unsigned int offset, * @param offset GPIO offset within bank * @return dir_flags: bitfield accesses by GPIOD_ defines */ -ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset); +ulong sandbox_gpio_get_flags(struct udevice *dev, unsigned int offset); /** * Set the simulated flags of a GPIO (used only in sandbox test code) * * @param dev device to use * @param offset GPIO offset within bank - * @param flags dir_flags: bitfield accesses by GPIOD_ defines + * @param flags bitfield accesses by GPIOD_ defines * @return -1 on error, 0 if ok */ -int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, - ulong flags); +int sandbox_gpio_set_flags(struct udevice *dev, unsigned int offset, + ulong flags); #endif diff --git a/arch/sh/cpu/sh4/cpu.c b/arch/sh/cpu/sh4/cpu.c index 801102fc7d..1b2f50dbe6 100644 --- a/arch/sh/cpu/sh4/cpu.c +++ b/arch/sh/cpu/sh4/cpu.c @@ -32,7 +32,7 @@ int cleanup_before_linux (void) int do_reset(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { disable_interrupts(); - reset_cpu(0); + reset_cpu(); return 0; } diff --git a/arch/sh/cpu/sh4/watchdog.c b/arch/sh/cpu/sh4/watchdog.c index 1de32cd419..bf403d3c52 100644 --- a/arch/sh/cpu/sh4/watchdog.c +++ b/arch/sh/cpu/sh4/watchdog.c @@ -51,7 +51,7 @@ int watchdog_disable(void) } #endif -void reset_cpu(unsigned long ignored) +void reset_cpu(void) { /* Address error with SR.BL=1 first. */ trigger_address_error(); diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index bddba3edde..a02f4f9600 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -143,7 +143,7 @@ int checkcpu(void) /* System is not happy after keyboard reset... */ debug("Issuing CF9 warm reset\n"); - reset_cpu(0); + reset_cpu(); } ret = cpu_common_init(); diff --git a/arch/x86/include/asm/intel_pinctrl_defs.h b/arch/x86/include/asm/intel_pinctrl_defs.h index 1ea141f082..5d83d24bae 100644 --- a/arch/x86/include/asm/intel_pinctrl_defs.h +++ b/arch/x86/include/asm/intel_pinctrl_defs.h @@ -11,6 +11,11 @@ /* This file is included by device trees, so avoid BIT() macros */ +#define GPIO_DW_SIZE(x) (sizeof(u32) * (x)) +#define PAD_CFG_OFFSET(x, dw_num) ((x) + GPIO_DW_SIZE(dw_num)) +#define PAD_CFG0_OFFSET(x) PAD_CFG_OFFSET(x, 0) +#define PAD_CFG1_OFFSET(x) PAD_CFG_OFFSET(x, 1) + #define PAD_CFG0_TX_STATE_BIT 0 #define PAD_CFG0_TX_STATE (1 << PAD_CFG0_TX_STATE_BIT) #define PAD_CFG0_RX_STATE_BIT 1 diff --git a/board/BuR/brppt2/board.c b/board/BuR/brppt2/board.c index e6eb403fc3..ee006f0196 100644 --- a/board/BuR/brppt2/board.c +++ b/board/BuR/brppt2/board.c @@ -540,7 +540,7 @@ void board_init_f(ulong dummy) spl_dram_init(); } -void reset_cpu(ulong addr) +void reset_cpu(void) { } #endif /* CONFIG_SPL_BUILD */ diff --git a/board/abilis/tb100/tb100.c b/board/abilis/tb100/tb100.c index 52dc5b8d86..89e73225a7 100644 --- a/board/abilis/tb100/tb100.c +++ b/board/abilis/tb100/tb100.c @@ -9,7 +9,7 @@ #include <netdev.h> #include <asm/io.h> -void reset_cpu(ulong addr) +void reset_cpu(void) { #define CRM_SWRESET 0xff101044 writel(0x1, (void *)CRM_SWRESET); diff --git a/board/advantech/imx8qm_rom7720_a1/imx8qm_rom7720_a1.c b/board/advantech/imx8qm_rom7720_a1/imx8qm_rom7720_a1.c index 8492e7603b..ace18b2d60 100644 --- a/board/advantech/imx8qm_rom7720_a1/imx8qm_rom7720_a1.c +++ b/board/advantech/imx8qm_rom7720_a1/imx8qm_rom7720_a1.c @@ -115,7 +115,7 @@ int board_init(void) /* * Board specific reset that is system reset. */ -void reset_cpu(ulong addr) +void reset_cpu(void) { /* TODO */ } diff --git a/board/armltd/total_compute/total_compute.c b/board/armltd/total_compute/total_compute.c index 01c65e4db8..b7eaab0851 100644 --- a/board/armltd/total_compute/total_compute.c +++ b/board/armltd/total_compute/total_compute.c @@ -63,6 +63,6 @@ int dram_init_banksize(void) } /* Nothing to be done here as handled by PSCI interface */ -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/armltd/vexpress/vexpress_common.c b/board/armltd/vexpress/vexpress_common.c index df4cbd3204..ba3278a199 100644 --- a/board/armltd/vexpress/vexpress_common.c +++ b/board/armltd/vexpress/vexpress_common.c @@ -174,7 +174,7 @@ int v2m_cfg_write(u32 devfn, u32 data) } /* Use the ARM Watchdog System to cause reset */ -void reset_cpu(ulong addr) +void reset_cpu(void) { if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE_MB, 0)) printf("Unable to reboot\n"); diff --git a/board/armltd/vexpress64/vexpress64.c b/board/armltd/vexpress64/vexpress64.c index 9d294903e9..2e4260286b 100644 --- a/board/armltd/vexpress64/vexpress64.c +++ b/board/armltd/vexpress64/vexpress64.c @@ -143,7 +143,7 @@ void *board_fdt_blob_setup(void) #endif /* Actual reset is done via PSCI. */ -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/atmark-techno/armadillo-800eva/armadillo-800eva.c b/board/atmark-techno/armadillo-800eva/armadillo-800eva.c index 1bae283252..c1c3dfd3de 100644 --- a/board/atmark-techno/armadillo-800eva/armadillo-800eva.c +++ b/board/atmark-techno/armadillo-800eva/armadillo-800eva.c @@ -322,6 +322,6 @@ int board_late_init(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/beacon/beacon-rzg2m/beacon-rzg2m.c b/board/beacon/beacon-rzg2m/beacon-rzg2m.c index c343de5102..0c7f8e54e9 100644 --- a/board/beacon/beacon-rzg2m/beacon-rzg2m.c +++ b/board/beacon/beacon-rzg2m/beacon-rzg2m.c @@ -47,7 +47,7 @@ int dram_init_banksize(void) #define RST_CA57RESCNT (RST_BASE + 0x40) #define RST_CODE 0xA5A5000F -void reset_cpu(ulong addr) +void reset_cpu(void) { writel(RST_CODE, RST_CA57RESCNT); } diff --git a/board/bosch/shc/board.c b/board/bosch/shc/board.c index bfce291691..e893781887 100644 --- a/board/bosch/shc/board.c +++ b/board/bosch/shc/board.c @@ -486,7 +486,7 @@ static void bosch_check_reset_pin(void) printf("Resetting ...\n"); writel(RESET_MASK, GPIO1_BASE + OMAP_GPIO_IRQSTATUS_SET_0); disable_interrupts(); - reset_cpu(0); + reset_cpu(); /*NOTREACHED*/ } } diff --git a/board/broadcom/bcmns2/northstar2.c b/board/broadcom/bcmns2/northstar2.c index 494e457ff6..ee586d5660 100644 --- a/board/broadcom/bcmns2/northstar2.c +++ b/board/broadcom/bcmns2/northstar2.c @@ -57,7 +57,7 @@ int dram_init_banksize(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { psci_system_reset(); } diff --git a/board/broadcom/bcmns3/ns3.c b/board/broadcom/bcmns3/ns3.c index 9d2df92fa1..758a358f54 100644 --- a/board/broadcom/bcmns3/ns3.c +++ b/board/broadcom/bcmns3/ns3.c @@ -15,9 +15,6 @@ #include <dt-bindings/memory/bcm-ns3-mc.h> #include <broadcom/chimp.h> -/* Default reset-level = 3 and strap-val = 0 */ -#define L3_RESET 30 - #define BANK_OFFSET(bank) ((u64)BCM_NS3_DDR_INFO_BASE + 8 + ((bank) * 16)) /* @@ -188,25 +185,10 @@ ulong board_get_usable_ram_top(ulong total_size) return BCM_NS3_MEM_END; } -void reset_cpu(ulong level) +void reset_cpu(void) { - u32 reset_level, strap_val; - - /* Default reset type is L3 reset */ - if (!level) { - /* - * Encoding: U-Boot reset command expects decimal argument, - * Boot strap val: Bits[3:0] - * reset level: Bits[7:4] - */ - strap_val = L3_RESET % 10; - level = L3_RESET / 10; - reset_level = level % 10; - psci_system_reset2(reset_level, strap_val); - } else { - /* U-Boot cmd "reset" with any arg will trigger L1 reset */ - psci_system_reset(); - } + /* Perform a level 3 reset */ + psci_system_reset2(3, 0); } #ifdef CONFIG_OF_BOARD_SETUP diff --git a/board/broadcom/bcmstb/bcmstb.c b/board/broadcom/bcmstb/bcmstb.c index f6bdf1f5f4..ee0a341077 100644 --- a/board/broadcom/bcmstb/bcmstb.c +++ b/board/broadcom/bcmstb/bcmstb.c @@ -43,7 +43,7 @@ u32 get_board_rev(void) return 0; } -void reset_cpu(ulong ignored) +void reset_cpu(void) { } diff --git a/board/cavium/thunderx/thunderx.c b/board/cavium/thunderx/thunderx.c index b09f72cad5..a7dc5c6aeb 100644 --- a/board/cavium/thunderx/thunderx.c +++ b/board/cavium/thunderx/thunderx.c @@ -110,7 +110,7 @@ int dram_init(void) /* * Board specific reset that is system reset. */ -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/compulab/cm_t335/spl.c b/board/compulab/cm_t335/spl.c index 8662632a7e..33264dfa71 100644 --- a/board/compulab/cm_t335/spl.c +++ b/board/compulab/cm_t335/spl.c @@ -96,7 +96,7 @@ static void probe_sdram_size(long size) break; default: puts("Failed configuring DRAM, resetting...\n\n"); - reset_cpu(0); + reset_cpu(); } debug("%s: setting DRAM size to %ldM\n", __func__, size >> 20); config_ddr(303, &ioregs, &ddr3_data, diff --git a/board/cortina/presidio-asic/presidio.c b/board/cortina/presidio-asic/presidio.c index 5c73522263..f344622b02 100644 --- a/board/cortina/presidio-asic/presidio.c +++ b/board/cortina/presidio-asic/presidio.c @@ -115,7 +115,7 @@ int dram_init(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { invoke_psci_fn_smc(PSCI_0_2_FN_SYSTEM_RESET, 0, 0, 0); } diff --git a/board/freescale/imx8qm_mek/imx8qm_mek.c b/board/freescale/imx8qm_mek/imx8qm_mek.c index c677220624..682099ad9c 100644 --- a/board/freescale/imx8qm_mek/imx8qm_mek.c +++ b/board/freescale/imx8qm_mek/imx8qm_mek.c @@ -105,7 +105,7 @@ int board_init(void) /* * Board specific reset that is system reset. */ -void reset_cpu(ulong addr) +void reset_cpu(void) { /* TODO */ } diff --git a/board/freescale/imx8qxp_mek/imx8qxp_mek.c b/board/freescale/imx8qxp_mek/imx8qxp_mek.c index 7179823a22..21cfa142f3 100644 --- a/board/freescale/imx8qxp_mek/imx8qxp_mek.c +++ b/board/freescale/imx8qxp_mek/imx8qxp_mek.c @@ -129,7 +129,7 @@ int board_init(void) /* * Board specific reset that is system reset. */ -void reset_cpu(ulong addr) +void reset_cpu(void) { /* TODO */ } diff --git a/board/freescale/mx6memcal/spl.c b/board/freescale/mx6memcal/spl.c index c82b532f6d..61d0ca3408 100644 --- a/board/freescale/mx6memcal/spl.c +++ b/board/freescale/mx6memcal/spl.c @@ -425,7 +425,7 @@ void board_init_f(ulong dummy) is_cpu_type(MXC_CPU_MX6SL)) { printf("cpu type 0x%x doesn't support 64-bit bus\n", get_cpu_type()); - reset_cpu(0); + reset_cpu(); } } #ifdef CONFIG_MX6SL diff --git a/board/gdsys/a38x/controlcenterdc.c b/board/gdsys/a38x/controlcenterdc.c index 4f1dc3b431..dc424f271c 100644 --- a/board/gdsys/a38x/controlcenterdc.c +++ b/board/gdsys/a38x/controlcenterdc.c @@ -288,8 +288,8 @@ int last_stage_init(void) ccdc_eth_init(); #endif ret = get_tpm(&tpm); - if (ret || tpm_init(tpm) || tpm_startup(tpm, TPM_ST_CLEAR) || - tpm_continue_self_test(tpm)) { + if (ret || tpm_init(tpm) || tpm1_startup(tpm, TPM_ST_CLEAR) || + tpm1_continue_self_test(tpm)) { return 1; } diff --git a/board/gdsys/a38x/hre.c b/board/gdsys/a38x/hre.c index 699241b3e6..de5411a6b9 100644 --- a/board/gdsys/a38x/hre.c +++ b/board/gdsys/a38x/hre.c @@ -107,8 +107,8 @@ static int get_tpm_nv_size(struct udevice *tpm, uint32_t index, uint32_t *size) uint8_t *ptr; uint16_t v16; - err = tpm_get_capability(tpm, TPM_CAP_NV_INDEX, index, - info, sizeof(info)); + err = tpm1_get_capability(tpm, TPM_CAP_NV_INDEX, index, info, + sizeof(info)); if (err) { printf("tpm_get_capability(CAP_NV_INDEX, %08x) failed: %u\n", index, err); @@ -150,8 +150,8 @@ static int find_key(struct udevice *tpm, const uint8_t auth[20], unsigned int i; /* fetch list of already loaded keys in the TPM */ - err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf, - sizeof(buf)); + err = tpm1_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf, + sizeof(buf)); if (err) return -1; key_count = get_unaligned_be16(buf); @@ -162,8 +162,8 @@ static int find_key(struct udevice *tpm, const uint8_t auth[20], /* now search a(/ the) key which we can access with the given auth */ for (i = 0; i < key_count; ++i) { buf_len = sizeof(buf); - err = tpm_get_pub_key_oiap(tpm, key_handles[i], auth, buf, - &buf_len); + err = tpm1_get_pub_key_oiap(tpm, key_handles[i], auth, buf, + &buf_len); if (err && err != TPM_AUTHFAIL) return -1; if (err) @@ -192,8 +192,8 @@ static int read_common_data(struct udevice *tpm) if (get_tpm_nv_size(tpm, NV_COMMON_DATA_INDEX, &size) || size < NV_COMMON_DATA_MIN_SIZE) return 1; - err = tpm_nv_read_value(tpm, NV_COMMON_DATA_INDEX, - buf, min(sizeof(buf), size)); + err = tpm1_nv_read_value(tpm, NV_COMMON_DATA_INDEX, buf, + min(sizeof(buf), size)); if (err) { printf("tpm_nv_read_value() failed: %u\n", err); return 1; @@ -270,8 +270,8 @@ static struct h_reg *access_hreg(struct udevice *tpm, uint8_t spec, if (mode & HREG_RD) { if (!result->valid) { if (IS_PCR_HREG(spec)) { - hre_tpm_err = tpm_pcr_read(tpm, HREG_IDX(spec), - result->digest, 20); + hre_tpm_err = tpm1_pcr_read(tpm, HREG_IDX(spec), + result->digest, 20); result->valid = (hre_tpm_err == TPM_SUCCESS); } else if (IS_FIX_HREG(spec)) { switch (HREG_IDX(spec)) { @@ -357,8 +357,8 @@ static int hre_op_loadkey(struct udevice *tpm, struct h_reg *src_reg, return -1; if (find_key(tpm, src_reg->digest, dst_reg->digest, &parent_handle)) return -1; - hre_tpm_err = tpm_load_key2_oiap(tpm, parent_handle, key, key_size, - src_reg->digest, &key_handle); + hre_tpm_err = tpm1_load_key2_oiap(tpm, parent_handle, key, key_size, + src_reg->digest, &key_handle); if (hre_tpm_err) { hre_err = HRE_E_TPM_FAILURE; return -1; @@ -474,8 +474,8 @@ do_bin_func: } if (dst_reg && dst_modified && IS_PCR_HREG(dst_spec)) { - hre_tpm_err = tpm_extend(tpm, HREG_IDX(dst_spec), - dst_reg->digest, dst_reg->digest); + hre_tpm_err = tpm1_extend(tpm, HREG_IDX(dst_spec), + dst_reg->digest, dst_reg->digest); if (hre_tpm_err) { hre_err = HRE_E_TPM_FAILURE; return NULL; diff --git a/board/gdsys/a38x/keyprogram.c b/board/gdsys/a38x/keyprogram.c index 853981aadb..7020fae189 100644 --- a/board/gdsys/a38x/keyprogram.c +++ b/board/gdsys/a38x/keyprogram.c @@ -23,15 +23,15 @@ int flush_keys(struct udevice *tpm) uint i; /* fetch list of already loaded keys in the TPM */ - err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf, - sizeof(buf)); + err = tpm1_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf, + sizeof(buf)); if (err) return -1; key_count = get_unaligned_be16(buf); ptr = buf + 2; for (i = 0; i < key_count; ++i, ptr += 4) { - err = tpm_flush_specific(tpm, get_unaligned_be32(ptr), - TPM_RT_KEY); + err = tpm1_flush_specific(tpm, get_unaligned_be32(ptr), + TPM_RT_KEY); if (err && err != TPM_KEY_OWNER_CONTROL) return err; } diff --git a/board/gdsys/mpc8308/gazerbeam.c b/board/gdsys/mpc8308/gazerbeam.c index 4e974c56d2..3d4a7e57fe 100644 --- a/board/gdsys/mpc8308/gazerbeam.c +++ b/board/gdsys/mpc8308/gazerbeam.c @@ -145,8 +145,8 @@ int last_stage_init(void) env_set_ulong("fpga_hw_rev", fpga_hw_rev); ret = get_tpm(&tpm); - if (ret || tpm_init(tpm) || tpm_startup(tpm, TPM_ST_CLEAR) || - tpm_continue_self_test(tpm)) { + if (ret || tpm_init(tpm) || tpm1_startup(tpm, TPM_ST_CLEAR) || + tpm1_continue_self_test(tpm)) { printf("TPM init failed\n"); } diff --git a/board/gdsys/p1022/controlcenterd-id.c b/board/gdsys/p1022/controlcenterd-id.c index 1b5aa9042f..87b346aa9c 100644 --- a/board/gdsys/p1022/controlcenterd-id.c +++ b/board/gdsys/p1022/controlcenterd-id.c @@ -273,8 +273,8 @@ static int get_tpm_nv_size(struct udevice *tpm, uint32_t index, uint32_t *size) uint8_t *ptr; uint16_t v16; - err = tpm_get_capability(tpm, TPM_CAP_NV_INDEX, index, - info, sizeof(info)); + err = tpm1_get_capability(tpm, TPM_CAP_NV_INDEX, index, info, + sizeof(info)); if (err) { printf("tpm_get_capability(CAP_NV_INDEX, %08x) failed: %u\n", index, err); @@ -315,8 +315,8 @@ static int find_key(struct udevice *tpm, const uint8_t auth[20], unsigned int i; /* fetch list of already loaded keys in the TPM */ - err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf, - sizeof(buf)); + err = tpm1_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf, + sizeof(buf)); if (err) return -1; key_count = get_unaligned_be16(buf); @@ -327,8 +327,8 @@ static int find_key(struct udevice *tpm, const uint8_t auth[20], /* now search a(/ the) key which we can access with the given auth */ for (i = 0; i < key_count; ++i) { buf_len = sizeof(buf); - err = tpm_get_pub_key_oiap(tpm, key_handles[i], auth, buf, - &buf_len); + err = tpm1_get_pub_key_oiap(tpm, key_handles[i], auth, buf, + &buf_len); if (err && err != TPM_AUTHFAIL) return -1; if (err) @@ -356,8 +356,8 @@ static int read_common_data(struct udevice *tpm) if (get_tpm_nv_size(tpm, NV_COMMON_DATA_INDEX, &size) || size < NV_COMMON_DATA_MIN_SIZE) return 1; - err = tpm_nv_read_value(tpm, NV_COMMON_DATA_INDEX, - buf, min(sizeof(buf), size)); + err = tpm1_nv_read_value(tpm, NV_COMMON_DATA_INDEX, buf, + min(sizeof(buf), size)); if (err) { printf("tpm_nv_read_value() failed: %u\n", err); return 1; @@ -508,8 +508,8 @@ static struct h_reg *access_hreg(struct udevice *tpm, uint8_t spec, if (mode & HREG_RD) { if (!result->valid) { if (IS_PCR_HREG(spec)) { - hre_tpm_err = tpm_pcr_read(tpm, HREG_IDX(spec), - result->digest, 20); + hre_tpm_err = tpm1_pcr_read(tpm, HREG_IDX(spec), + result->digest, 20); result->valid = (hre_tpm_err == TPM_SUCCESS); } else if (IS_FIX_HREG(spec)) { switch (HREG_IDX(spec)) { @@ -601,8 +601,8 @@ static int hre_op_loadkey(struct udevice *tpm, struct h_reg *src_reg, return -1; if (find_key(tpm, src_reg->digest, dst_reg->digest, &parent_handle)) return -1; - hre_tpm_err = tpm_load_key2_oiap(tpm, parent_handle, key, key_size, - src_reg->digest, &key_handle); + hre_tpm_err = tpm1_load_key2_oiap(tpm, parent_handle, key, key_size, + src_reg->digest, &key_handle); if (hre_tpm_err) { hre_err = HRE_E_TPM_FAILURE; return -1; @@ -718,8 +718,8 @@ do_bin_func: } if (dst_reg && dst_modified && IS_PCR_HREG(dst_spec)) { - hre_tpm_err = tpm_extend(tpm, HREG_IDX(dst_spec), - dst_reg->digest, dst_reg->digest); + hre_tpm_err = tpm1_extend(tpm, HREG_IDX(dst_spec), + dst_reg->digest, dst_reg->digest); if (hre_tpm_err) { hre_err = HRE_E_TPM_FAILURE; return NULL; @@ -964,10 +964,10 @@ static int first_stage_actions(struct udevice *tpm) puts("CCDM S1: start actions\n"); #ifndef CCDM_SECOND_STAGE - if (tpm_continue_self_test(tpm)) + if (tpm1_continue_self_test(tpm)) goto failure; #else - tpm_continue_self_test(tpm); + tpm1_continue_self_test(tpm); #endif mdelay(37); @@ -1003,7 +1003,7 @@ static int first_stage_init(void) puts("CCDM S1\n"); ret = get_tpm(&tpm); - if (ret || tpm_init(tpm) || tpm_startup(tpm, TPM_ST_CLEAR)) + if (ret || tpm_init(tpm) || tpm1_startup(tpm, TPM_ST_CLEAR)) return 1; ret = first_stage_actions(tpm); #ifndef CCDM_SECOND_STAGE @@ -1061,7 +1061,7 @@ static int second_stage_init(void) ret = get_tpm(&tpm); if (ret || tpm_init(tpm)) return 1; - err = tpm_startup(tpm, TPM_ST_CLEAR); + err = tpm1_startup(tpm, TPM_ST_CLEAR); if (err != TPM_INVALID_POSTINIT) did_first_stage_run = false; diff --git a/board/ge/b1x5v2/spl.c b/board/ge/b1x5v2/spl.c index 2e6f905219..52c80f792d 100644 --- a/board/ge/b1x5v2/spl.c +++ b/board/ge/b1x5v2/spl.c @@ -436,7 +436,7 @@ static int get_boardmem_size(struct spi_flash *spi) return 1024; } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/highbank/highbank.c b/board/highbank/highbank.c index a790d453da..906bd9b6dd 100644 --- a/board/highbank/highbank.c +++ b/board/highbank/highbank.c @@ -128,7 +128,7 @@ static int is_highbank(void) return (midr & 0xfff0) == 0xc090; } -void reset_cpu(ulong addr) +void reset_cpu(void) { writel(HB_PWR_HARD_RESET, HB_SREG_A9_PWR_REQ); if (is_highbank()) diff --git a/board/hisilicon/hikey/hikey.c b/board/hisilicon/hikey/hikey.c index afe324c890..c9a2d60ee5 100644 --- a/board/hisilicon/hikey/hikey.c +++ b/board/hisilicon/hikey/hikey.c @@ -486,7 +486,7 @@ int dram_init_banksize(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { writel(0x48698284, &ao_sc->stat0); wfi(); diff --git a/board/hisilicon/hikey960/hikey960.c b/board/hisilicon/hikey960/hikey960.c index 62073aa954..f41fabbad0 100644 --- a/board/hisilicon/hikey960/hikey960.c +++ b/board/hisilicon/hikey960/hikey960.c @@ -185,7 +185,7 @@ int board_init(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { psci_system_reset(); } diff --git a/board/hisilicon/poplar/poplar.c b/board/hisilicon/poplar/poplar.c index fda9a3405d..6cc79d96a1 100644 --- a/board/hisilicon/poplar/poplar.c +++ b/board/hisilicon/poplar/poplar.c @@ -60,7 +60,7 @@ int checkboard(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { psci_system_reset(); } diff --git a/board/kmc/kzm9g/kzm9g.c b/board/kmc/kzm9g/kzm9g.c index 02c87a031c..dccf4691af 100644 --- a/board/kmc/kzm9g/kzm9g.c +++ b/board/kmc/kzm9g/kzm9g.c @@ -366,7 +366,7 @@ int board_eth_init(struct bd_info *bis) return ret; } -void reset_cpu(ulong addr) +void reset_cpu(void) { /* Soft Power On Reset */ writel((1 << 31), RESCNT2); diff --git a/board/liebherr/display5/spl.c b/board/liebherr/display5/spl.c index b8658c8d61..39f70f578e 100644 --- a/board/liebherr/display5/spl.c +++ b/board/liebherr/display5/spl.c @@ -376,7 +376,7 @@ void board_boot_order(u32 *spl_boot_list) #endif } -void reset_cpu(ulong addr) {} +void reset_cpu(void) {} #ifdef CONFIG_SPL_LOAD_FIT int board_fit_config_name_match(const char *name) diff --git a/board/phytium/durian/durian.c b/board/phytium/durian/durian.c index 8a82a4591a..ef13f7cff4 100644 --- a/board/phytium/durian/durian.c +++ b/board/phytium/durian/durian.c @@ -42,7 +42,7 @@ int board_init(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { struct arm_smccc_res res; diff --git a/board/qualcomm/dragonboard410c/dragonboard410c.c b/board/qualcomm/dragonboard410c/dragonboard410c.c index 646013cfc9..0d282de958 100644 --- a/board/qualcomm/dragonboard410c/dragonboard410c.c +++ b/board/qualcomm/dragonboard410c/dragonboard410c.c @@ -203,7 +203,7 @@ int ft_board_setup(void *blob, struct bd_info *bd) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { psci_system_reset(); } diff --git a/board/qualcomm/dragonboard820c/dragonboard820c.c b/board/qualcomm/dragonboard820c/dragonboard820c.c index 877e34c210..4ccb1a0750 100644 --- a/board/qualcomm/dragonboard820c/dragonboard820c.c +++ b/board/qualcomm/dragonboard820c/dragonboard820c.c @@ -127,7 +127,7 @@ int board_init(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { psci_system_reset(); } diff --git a/board/renesas/alt/alt.c b/board/renesas/alt/alt.c index 854c47636d..3b60afc59c 100644 --- a/board/renesas/alt/alt.c +++ b/board/renesas/alt/alt.c @@ -111,7 +111,7 @@ int board_phy_config(struct phy_device *phydev) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { struct udevice *dev; const u8 pmic_bus = 7; diff --git a/board/renesas/alt/alt_spl.c b/board/renesas/alt/alt_spl.c index 2de236fc29..cdaa04e4f4 100644 --- a/board/renesas/alt/alt_spl.c +++ b/board/renesas/alt/alt_spl.c @@ -408,6 +408,6 @@ void board_boot_order(u32 *spl_boot_list) spl_boot_list[2] = BOOT_DEVICE_NONE; } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/renesas/blanche/blanche.c b/board/renesas/blanche/blanche.c index 9671382f2a..a36526986c 100644 --- a/board/renesas/blanche/blanche.c +++ b/board/renesas/blanche/blanche.c @@ -360,7 +360,7 @@ int dram_init_banksize(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { struct udevice *dev; const u8 pmic_bus = 6; diff --git a/board/renesas/condor/condor.c b/board/renesas/condor/condor.c index 4454061e07..e930de31b2 100644 --- a/board/renesas/condor/condor.c +++ b/board/renesas/condor/condor.c @@ -34,7 +34,7 @@ int board_init(void) #define RST_CA57_CODE 0xA5A5000F #define RST_CA53_CODE 0x5A5A000F -void reset_cpu(ulong addr) +void reset_cpu(void) { unsigned long midr, cputype; diff --git a/board/renesas/draak/draak.c b/board/renesas/draak/draak.c index ffd52ebfe4..1d76f95aed 100644 --- a/board/renesas/draak/draak.c +++ b/board/renesas/draak/draak.c @@ -75,7 +75,7 @@ int board_init(void) #define RST_CA53RESCNT (RST_BASE + 0x44) #define RST_CA53_CODE 0x5A5A000F -void reset_cpu(ulong addr) +void reset_cpu(void) { writel(RST_CA53_CODE, RST_CA53RESCNT); } diff --git a/board/renesas/eagle/eagle.c b/board/renesas/eagle/eagle.c index f9e553feaa..bb32e3d2c5 100644 --- a/board/renesas/eagle/eagle.c +++ b/board/renesas/eagle/eagle.c @@ -78,7 +78,7 @@ int board_init(void) #define RST_CA57_CODE 0xA5A5000F #define RST_CA53_CODE 0x5A5A000F -void reset_cpu(ulong addr) +void reset_cpu(void) { unsigned long midr, cputype; diff --git a/board/renesas/ebisu/ebisu.c b/board/renesas/ebisu/ebisu.c index 82cd2a5800..9d4af8d3a6 100644 --- a/board/renesas/ebisu/ebisu.c +++ b/board/renesas/ebisu/ebisu.c @@ -42,7 +42,7 @@ int board_init(void) #define RST_CA53RESCNT (RST_BASE + 0x44) #define RST_CA53_CODE 0x5A5A000F -void reset_cpu(ulong addr) +void reset_cpu(void) { writel(RST_CA53_CODE, RST_CA53RESCNT); } diff --git a/board/renesas/gose/gose.c b/board/renesas/gose/gose.c index 56cdc73b1a..51768c315e 100644 --- a/board/renesas/gose/gose.c +++ b/board/renesas/gose/gose.c @@ -117,7 +117,7 @@ int board_phy_config(struct phy_device *phydev) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { struct udevice *dev; const u8 pmic_bus = 6; diff --git a/board/renesas/gose/gose_spl.c b/board/renesas/gose/gose_spl.c index 624ba5db04..c0bf720443 100644 --- a/board/renesas/gose/gose_spl.c +++ b/board/renesas/gose/gose_spl.c @@ -405,6 +405,6 @@ void board_boot_order(u32 *spl_boot_list) spl_boot_list[2] = BOOT_DEVICE_NONE; } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/renesas/grpeach/grpeach.c b/board/renesas/grpeach/grpeach.c index ac989eb29c..199ec4a310 100644 --- a/board/renesas/grpeach/grpeach.c +++ b/board/renesas/grpeach/grpeach.c @@ -40,7 +40,7 @@ int dram_init_banksize(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { /* Dummy read (must read WRCSR:WOVF at least once before clearing) */ readb(RZA1_WDT_BASE + WRCSR); diff --git a/board/renesas/koelsch/koelsch.c b/board/renesas/koelsch/koelsch.c index b0a66ea266..7e94bd8205 100644 --- a/board/renesas/koelsch/koelsch.c +++ b/board/renesas/koelsch/koelsch.c @@ -119,7 +119,7 @@ int board_phy_config(struct phy_device *phydev) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { struct udevice *dev; const u8 pmic_bus = 6; diff --git a/board/renesas/koelsch/koelsch_spl.c b/board/renesas/koelsch/koelsch_spl.c index 449bbfa7b8..b377f70715 100644 --- a/board/renesas/koelsch/koelsch_spl.c +++ b/board/renesas/koelsch/koelsch_spl.c @@ -407,6 +407,6 @@ void board_boot_order(u32 *spl_boot_list) spl_boot_list[2] = BOOT_DEVICE_NONE; } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/renesas/lager/lager.c b/board/renesas/lager/lager.c index add4eef3d5..87c5e01371 100644 --- a/board/renesas/lager/lager.c +++ b/board/renesas/lager/lager.c @@ -128,7 +128,7 @@ int board_phy_config(struct phy_device *phydev) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { struct udevice *dev; const u8 pmic_bus = 2; diff --git a/board/renesas/lager/lager_spl.c b/board/renesas/lager/lager_spl.c index 1ca857c2c3..d3d397e8f0 100644 --- a/board/renesas/lager/lager_spl.c +++ b/board/renesas/lager/lager_spl.c @@ -393,6 +393,6 @@ void board_boot_order(u32 *spl_boot_list) spl_boot_list[2] = BOOT_DEVICE_NONE; } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/renesas/porter/porter.c b/board/renesas/porter/porter.c index b3e4c08d74..b0f8505252 100644 --- a/board/renesas/porter/porter.c +++ b/board/renesas/porter/porter.c @@ -117,7 +117,7 @@ int board_phy_config(struct phy_device *phydev) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { struct udevice *dev; const u8 pmic_bus = 6; diff --git a/board/renesas/porter/porter_spl.c b/board/renesas/porter/porter_spl.c index f10c6cffc2..8595770c36 100644 --- a/board/renesas/porter/porter_spl.c +++ b/board/renesas/porter/porter_spl.c @@ -488,6 +488,6 @@ void board_boot_order(u32 *spl_boot_list) spl_boot_list[2] = BOOT_DEVICE_NONE; } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/renesas/rcar-common/gen3-spl.c b/board/renesas/rcar-common/gen3-spl.c index fd6e5054a6..b02a946a21 100644 --- a/board/renesas/rcar-common/gen3-spl.c +++ b/board/renesas/rcar-common/gen3-spl.c @@ -55,6 +55,6 @@ void s_init(void) { } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/renesas/salvator-x/salvator-x.c b/board/renesas/salvator-x/salvator-x.c index 08ed725521..071076a336 100644 --- a/board/renesas/salvator-x/salvator-x.c +++ b/board/renesas/salvator-x/salvator-x.c @@ -76,7 +76,7 @@ int board_init(void) #define RST_RSTOUTCR (RST_BASE + 0x58) #define RST_CODE 0xA5A5000F -void reset_cpu(ulong addr) +void reset_cpu(void) { #if defined(CONFIG_SYS_I2C) && defined(CONFIG_SYS_I2C_SH) i2c_reg_write(CONFIG_SYS_I2C_POWERIC_ADDR, 0x20, 0x80); diff --git a/board/renesas/silk/silk.c b/board/renesas/silk/silk.c index 05af5f4d68..4558070af8 100644 --- a/board/renesas/silk/silk.c +++ b/board/renesas/silk/silk.c @@ -112,7 +112,7 @@ int board_phy_config(struct phy_device *phydev) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { struct udevice *dev; const u8 pmic_bus = 1; diff --git a/board/renesas/silk/silk_spl.c b/board/renesas/silk/silk_spl.c index f10f84a3cc..afb9f85ffc 100644 --- a/board/renesas/silk/silk_spl.c +++ b/board/renesas/silk/silk_spl.c @@ -422,6 +422,6 @@ void board_boot_order(u32 *spl_boot_list) spl_boot_list[2] = BOOT_DEVICE_NONE; } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/renesas/stout/cpld.c b/board/renesas/stout/cpld.c index b56ed1703f..ac8048c81c 100644 --- a/board/renesas/stout/cpld.c +++ b/board/renesas/stout/cpld.c @@ -163,7 +163,7 @@ U_BOOT_CMD( "cpld write addr val\n" ); -void reset_cpu(ulong addr) +void reset_cpu(void) { cpld_write(CPLD_ADDR_RESET, 1); } diff --git a/board/renesas/stout/stout_spl.c b/board/renesas/stout/stout_spl.c index 57c1fabaf3..c37c055713 100644 --- a/board/renesas/stout/stout_spl.c +++ b/board/renesas/stout/stout_spl.c @@ -474,6 +474,6 @@ void board_boot_order(u32 *spl_boot_list) spl_boot_list[2] = BOOT_DEVICE_NONE; } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/siemens/capricorn/board.c b/board/siemens/capricorn/board.c index 56973a1090..dcbab8e4d2 100644 --- a/board/siemens/capricorn/board.c +++ b/board/siemens/capricorn/board.c @@ -232,7 +232,7 @@ static int setup_fec(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/synopsys/emsdp/emsdp.c b/board/synopsys/emsdp/emsdp.c index 997120ec5e..a3cee23411 100644 --- a/board/synopsys/emsdp/emsdp.c +++ b/board/synopsys/emsdp/emsdp.c @@ -98,7 +98,7 @@ int board_early_init_r(void) /* Bits in CREG_BOOT register */ #define CREG_BOOT_WP_BIT BIT(8) -void reset_cpu(ulong addr) +void reset_cpu(void) { writel(1, CREG_IP_SW_RESET); while (1) diff --git a/board/synopsys/iot_devkit/iot_devkit.c b/board/synopsys/iot_devkit/iot_devkit.c index c6051363c1..650958f94c 100644 --- a/board/synopsys/iot_devkit/iot_devkit.c +++ b/board/synopsys/iot_devkit/iot_devkit.c @@ -151,7 +151,7 @@ int mach_cpu_init(void) #define IOTDK_RESET_SEQ 0x55AA6699 -void reset_cpu(ulong addr) +void reset_cpu(void) { writel(IOTDK_RESET_SEQ, RESET_REG); } diff --git a/board/technexion/pico-imx6ul/spl.c b/board/technexion/pico-imx6ul/spl.c index 3807779544..251f5a1b7d 100644 --- a/board/technexion/pico-imx6ul/spl.c +++ b/board/technexion/pico-imx6ul/spl.c @@ -147,7 +147,7 @@ void board_init_f(ulong dummy) board_init_r(NULL, 0); } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/technexion/pico-imx7d/spl.c b/board/technexion/pico-imx7d/spl.c index bed0f21f44..df5f058577 100644 --- a/board/technexion/pico-imx7d/spl.c +++ b/board/technexion/pico-imx7d/spl.c @@ -127,7 +127,7 @@ void board_init_f(ulong dummy) board_init_r(NULL, 0); } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/toradex/apalis-imx8/apalis-imx8.c b/board/toradex/apalis-imx8/apalis-imx8.c index 76faa6e78f..04877fcd94 100644 --- a/board/toradex/apalis-imx8/apalis-imx8.c +++ b/board/toradex/apalis-imx8/apalis-imx8.c @@ -117,7 +117,7 @@ int board_init(void) /* * Board specific reset that is system reset. */ -void reset_cpu(ulong addr) +void reset_cpu(void) { /* TODO */ } diff --git a/board/toradex/apalis-imx8x/apalis-imx8x.c b/board/toradex/apalis-imx8x/apalis-imx8x.c index b6f3bdd7ed..ac3bac66a9 100644 --- a/board/toradex/apalis-imx8x/apalis-imx8x.c +++ b/board/toradex/apalis-imx8x/apalis-imx8x.c @@ -127,7 +127,7 @@ int board_init(void) /* * Board specific reset that is system reset. */ -void reset_cpu(ulong addr) +void reset_cpu(void) { /* TODO */ } diff --git a/board/toradex/apalis_imx6/apalis_imx6.c b/board/toradex/apalis_imx6/apalis_imx6.c index 0c857b599d..74060daadd 100644 --- a/board/toradex/apalis_imx6/apalis_imx6.c +++ b/board/toradex/apalis_imx6/apalis_imx6.c @@ -1139,7 +1139,7 @@ int board_fit_config_name_match(const char *name) } #endif -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/toradex/colibri-imx8x/colibri-imx8x.c b/board/toradex/colibri-imx8x/colibri-imx8x.c index 562199a51a..169d4d04b1 100644 --- a/board/toradex/colibri-imx8x/colibri-imx8x.c +++ b/board/toradex/colibri-imx8x/colibri-imx8x.c @@ -129,7 +129,7 @@ int board_init(void) /* * Board specific reset that is system reset. */ -void reset_cpu(ulong addr) +void reset_cpu(void) { /* TODO */ } diff --git a/board/toradex/colibri_imx6/colibri_imx6.c b/board/toradex/colibri_imx6/colibri_imx6.c index 74d59e586a..c0e7754469 100644 --- a/board/toradex/colibri_imx6/colibri_imx6.c +++ b/board/toradex/colibri_imx6/colibri_imx6.c @@ -1081,7 +1081,7 @@ void board_init_f(ulong dummy) board_init_r(NULL, 0); } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/toradex/colibri_imx7/colibri_imx7.c b/board/toradex/colibri_imx7/colibri_imx7.c index 8f7ef992a7..301b07d5b4 100644 --- a/board/toradex/colibri_imx7/colibri_imx7.c +++ b/board/toradex/colibri_imx7/colibri_imx7.c @@ -237,7 +237,7 @@ int power_init_board(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { struct udevice *dev; diff --git a/board/xen/xenguest_arm64/xenguest_arm64.c b/board/xen/xenguest_arm64/xenguest_arm64.c index 7d0d782a23..21363d878f 100644 --- a/board/xen/xenguest_arm64/xenguest_arm64.c +++ b/board/xen/xenguest_arm64/xenguest_arm64.c @@ -171,7 +171,7 @@ int dram_init_banksize(void) /* * Board specific reset that is system reset. */ -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/xilinx/versal/board.c b/board/xilinx/versal/board.c index c644fe8dc0..e2f9d13c12 100644 --- a/board/xilinx/versal/board.c +++ b/board/xilinx/versal/board.c @@ -242,6 +242,6 @@ int dram_init(void) return 0; } -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index 4466717ad4..23c12f45ea 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -436,7 +436,7 @@ int dram_init(void) } #endif -void reset_cpu(ulong addr) +void reset_cpu(void) { } diff --git a/cmd/Kconfig b/cmd/Kconfig index eff238cb38..e4bb1d4c4a 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2030,12 +2030,19 @@ config HASH_VERIFY help Add -v option to verify data against a hash. +config CMD_SCP03 + bool "scp03 - SCP03 enable and rotate/provision operations" + depends on SCP03 + help + This command provides access to a Trusted Application + running in a TEE to request Secure Channel Protocol 03 + (SCP03) enablement and/or rotation of its SCP03 keys. + config CMD_TPM_V1 bool config CMD_TPM_V2 bool - select CMD_LOG config CMD_TPM bool "Enable the 'tpm' command" diff --git a/cmd/Makefile b/cmd/Makefile index 567e2b79d2..e606ac4e8c 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -194,6 +194,9 @@ obj-$(CONFIG_CMD_BLOB) += blob.o # Android Verified Boot 2.0 obj-$(CONFIG_CMD_AVB) += avb.o +# Foundries.IO SCP03 +obj-$(CONFIG_CMD_SCP03) += scp03.o + obj-$(CONFIG_ARM) += arm/ obj-$(CONFIG_RISCV) += riscv/ obj-$(CONFIG_SANDBOX) += sandbox/ diff --git a/cmd/scp03.c b/cmd/scp03.c new file mode 100644 index 0000000000..655e0bba08 --- /dev/null +++ b/cmd/scp03.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2021, Foundries.IO + * + */ + +#include <common.h> +#include <command.h> +#include <env.h> +#include <scp03.h> + +int do_scp03_enable(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (argc != 1) + return CMD_RET_USAGE; + + if (tee_enable_scp03()) { + printf("TEE failed to enable SCP03\n"); + return CMD_RET_FAILURE; + } + + printf("SCP03 is enabled\n"); + + return CMD_RET_SUCCESS; +} + +int do_scp03_provision(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) +{ + if (argc != 1) + return CMD_RET_USAGE; + + if (tee_provision_scp03()) { + printf("TEE failed to provision SCP03 keys\n"); + return CMD_RET_FAILURE; + } + + printf("SCP03 is provisioned\n"); + + return CMD_RET_SUCCESS; +} + +static char text[] = + "provides a command to enable SCP03 and provision the SCP03 keys\n" + " enable - enable SCP03 on the TEE\n" + " provision - provision SCP03 on the TEE\n"; + +U_BOOT_CMD_WITH_SUBCMDS(scp03, "Secure Channel Protocol 03 control", text, + U_BOOT_SUBCMD_MKENT(enable, 1, 1, do_scp03_enable), + U_BOOT_SUBCMD_MKENT(provision, 1, 1, do_scp03_provision)); + diff --git a/cmd/tpm-v1.c b/cmd/tpm-v1.c index 0e2168aea6..3a7e35d525 100644 --- a/cmd/tpm-v1.c +++ b/cmd/tpm-v1.c @@ -11,6 +11,7 @@ #include <tpm-common.h> #include <tpm-v1.h> #include "tpm-user-utils.h" +#include <tpm_api.h> static int do_tpm_startup(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) @@ -55,7 +56,7 @@ static int do_tpm_nv_define_space(struct cmd_tbl *cmdtp, int flag, int argc, perm = simple_strtoul(argv[2], NULL, 0); size = simple_strtoul(argv[3], NULL, 0); - return report_return_code(tpm_nv_define_space(dev, index, perm, size)); + return report_return_code(tpm1_nv_define_space(dev, index, perm, size)); } static int do_tpm_nv_read_value(struct cmd_tbl *cmdtp, int flag, int argc, @@ -130,7 +131,7 @@ static int do_tpm_extend(struct cmd_tbl *cmdtp, int flag, int argc, return CMD_RET_FAILURE; } - rc = tpm_extend(dev, index, in_digest, out_digest); + rc = tpm_pcr_extend(dev, index, in_digest, out_digest); if (!rc) { puts("PCR value after execution of the command:\n"); print_byte_string(out_digest, sizeof(out_digest)); @@ -304,7 +305,7 @@ static int do_tpm_nv_define(struct cmd_tbl *cmdtp, int flag, int argc, index = simple_strtoul(argv[2], NULL, 0); perm = simple_strtoul(argv[3], NULL, 0); - return report_return_code(tpm_nv_define_space(dev, index, perm, size)); + return report_return_code(tpm1_nv_define_space(dev, index, perm, size)); } static int do_tpm_nv_read(struct cmd_tbl *cmdtp, int flag, int argc, @@ -389,7 +390,7 @@ static int do_tpm_oiap(struct cmd_tbl *cmdtp, int flag, int argc, if (rc) return rc; - err = tpm_oiap(dev, &auth_handle); + err = tpm1_oiap(dev, &auth_handle); return report_return_code(err); } @@ -461,8 +462,8 @@ static int do_tpm_load_key2_oiap(struct cmd_tbl *cmdtp, int flag, int argc, return CMD_RET_FAILURE; parse_byte_string(argv[4], usage_auth, NULL); - err = tpm_load_key2_oiap(dev, parent_handle, key, key_len, usage_auth, - &key_handle); + err = tpm1_load_key2_oiap(dev, parent_handle, key, key_len, usage_auth, + &key_handle); if (!err) printf("Key handle is 0x%x\n", key_handle); @@ -491,8 +492,8 @@ static int do_tpm_get_pub_key_oiap(struct cmd_tbl *cmdtp, int flag, int argc, return CMD_RET_FAILURE; parse_byte_string(argv[2], usage_auth, NULL); - err = tpm_get_pub_key_oiap(dev, key_handle, usage_auth, pub_key_buffer, - &pub_key_len); + err = tpm1_get_pub_key_oiap(dev, key_handle, usage_auth, pub_key_buffer, + &pub_key_len); if (!err) { printf("dump of received pub key structure:\n"); print_byte_string(pub_key_buffer, pub_key_len); @@ -500,7 +501,7 @@ static int do_tpm_get_pub_key_oiap(struct cmd_tbl *cmdtp, int flag, int argc, return report_return_code(err); } -TPM_COMMAND_NO_ARG(tpm_end_oiap) +TPM_COMMAND_NO_ARG(tpm1_end_oiap) #endif /* CONFIG_TPM_AUTH_SESSIONS */ @@ -562,7 +563,7 @@ static int do_tpm_flush(struct cmd_tbl *cmdtp, int flag, int argc, res_count = get_unaligned_be16(buf); ptr = buf + 2; for (i = 0; i < res_count; ++i, ptr += 4) - tpm_flush_specific(dev, get_unaligned_be32(ptr), type); + tpm1_flush_specific(dev, get_unaligned_be32(ptr), type); } else { u32 handle = simple_strtoul(argv[2], NULL, 0); @@ -570,7 +571,7 @@ static int do_tpm_flush(struct cmd_tbl *cmdtp, int flag, int argc, printf("Illegal resource handle %s\n", argv[2]); return -1; } - tpm_flush_specific(dev, cpu_to_be32(handle), type); + tpm1_flush_specific(dev, cpu_to_be32(handle), type); } return 0; @@ -691,7 +692,7 @@ static struct cmd_tbl tpm1_commands[] = { U_BOOT_CMD_MKENT(oiap, 0, 1, do_tpm_oiap, "", ""), U_BOOT_CMD_MKENT(end_oiap, 0, 1, - do_tpm_end_oiap, "", ""), + do_tpm1_end_oiap, "", ""), U_BOOT_CMD_MKENT(load_key2_oiap, 0, 1, do_tpm_load_key2_oiap, "", ""), #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1 diff --git a/cmd/tpm_test.c b/cmd/tpm_test.c index ebfb25cab0..a3ccb12f53 100644 --- a/cmd/tpm_test.c +++ b/cmd/tpm_test.c @@ -9,6 +9,7 @@ #include <log.h> #include <tpm-v1.h> #include "tpm-user-utils.h" +#include <tpm_api.h> /* Prints error and returns on failure */ #define TPM_CHECK(tpm_command) do { \ @@ -49,7 +50,7 @@ static uint32_t tpm_get_flags(struct udevice *dev, uint8_t *disable, struct tpm_permanent_flags pflags; uint32_t result; - result = tpm_get_permanent_flags(dev, &pflags); + result = tpm1_get_permanent_flags(dev, &pflags); if (result) return result; if (disable) @@ -90,7 +91,7 @@ static int test_early_extend(struct udevice *dev) tpm_init(dev); TPM_CHECK(tpm_startup(dev, TPM_ST_CLEAR)); TPM_CHECK(tpm_continue_self_test(dev)); - TPM_CHECK(tpm_extend(dev, 1, value_in, value_out)); + TPM_CHECK(tpm_pcr_extend(dev, 1, value_in, value_out)); printf("done\n"); return 0; } @@ -146,7 +147,7 @@ static int test_enable(struct udevice *dev) #define reboot() do { \ printf("\trebooting...\n"); \ - reset_cpu(0); \ + reset_cpu(); \ } while (0) static int test_fast_enable(struct udevice *dev) @@ -238,18 +239,18 @@ static void initialise_spaces(struct udevice *dev) uint32_t perm = TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE; printf("\tInitialising spaces\n"); - tpm_nv_set_locked(dev); /* useful only the first time */ - tpm_nv_define_space(dev, INDEX0, perm, 4); + tpm1_nv_set_locked(dev); /* useful only the first time */ + tpm1_nv_define_space(dev, INDEX0, perm, 4); tpm_nv_write_value(dev, INDEX0, (uint8_t *)&zero, 4); - tpm_nv_define_space(dev, INDEX1, perm, 4); + tpm1_nv_define_space(dev, INDEX1, perm, 4); tpm_nv_write_value(dev, INDEX1, (uint8_t *)&zero, 4); - tpm_nv_define_space(dev, INDEX2, perm, 4); + tpm1_nv_define_space(dev, INDEX2, perm, 4); tpm_nv_write_value(dev, INDEX2, (uint8_t *)&zero, 4); - tpm_nv_define_space(dev, INDEX3, perm, 4); + tpm1_nv_define_space(dev, INDEX3, perm, 4); tpm_nv_write_value(dev, INDEX3, (uint8_t *)&zero, 4); perm = TPM_NV_PER_READ_STCLEAR | TPM_NV_PER_WRITE_STCLEAR | TPM_NV_PER_PPWRITE; - tpm_nv_define_space(dev, INDEX_INITIALISED, perm, 1); + tpm1_nv_define_space(dev, INDEX_INITIALISED, perm, 1); } static int test_readonly(struct udevice *dev) @@ -325,30 +326,33 @@ static int test_redefine_unowned(struct udevice *dev) /* Redefines spaces a couple of times. */ perm = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK; - TPM_CHECK(tpm_nv_define_space(dev, INDEX0, perm, 2 * sizeof(uint32_t))); - TPM_CHECK(tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t))); + TPM_CHECK(tpm1_nv_define_space(dev, INDEX0, perm, + 2 * sizeof(uint32_t))); + TPM_CHECK(tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t))); perm = TPM_NV_PER_PPWRITE; - TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, 2 * sizeof(uint32_t))); - TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t))); + TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm, + 2 * sizeof(uint32_t))); + TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t))); /* Sets the global lock */ tpm_set_global_lock(dev); /* Verifies that index0 cannot be redefined */ - result = tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t)); + result = tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t)); assert(result == TPM_AREA_LOCKED); /* Checks that index1 can */ - TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, 2 * sizeof(uint32_t))); - TPM_CHECK(tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t))); + TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm, + 2 * sizeof(uint32_t))); + TPM_CHECK(tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t))); /* Turns off PP */ tpm_tsc_physical_presence(dev, PHYS_PRESENCE); /* Verifies that neither index0 nor index1 can be redefined */ - result = tpm_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t)); + result = tpm1_nv_define_space(dev, INDEX0, perm, sizeof(uint32_t)); assert(result == TPM_BAD_PRESENCE); - result = tpm_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)); + result = tpm1_nv_define_space(dev, INDEX1, perm, sizeof(uint32_t)); assert(result == TPM_BAD_PRESENCE); printf("done\n"); @@ -434,7 +438,7 @@ static int test_timing(struct udevice *dev) 100); TTPM_CHECK(tpm_nv_read_value(dev, INDEX0, (uint8_t *)&x, sizeof(x)), 100); - TTPM_CHECK(tpm_extend(dev, 0, in, out), 200); + TTPM_CHECK(tpm_pcr_extend(dev, 0, in, out), 200); TTPM_CHECK(tpm_set_global_lock(dev), 50); TTPM_CHECK(tpm_tsc_physical_presence(dev, PHYS_PRESENCE), 100); printf("done\n"); diff --git a/common/Kconfig b/common/Kconfig index 2bb3798f80..482f123534 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -588,6 +588,14 @@ config AVB_BUF_SIZE endif # AVB_VERIFY +config SCP03 + bool "Build SCP03 - Secure Channel Protocol O3 - controls" + depends on OPTEE || SANDBOX + depends on TEE + help + This option allows U-Boot to enable and or provision SCP03 on an OPTEE + controlled Secured Element. + config SPL_HASH bool # "Support hashing API (SHA1, SHA256, etc.)" help diff --git a/common/Makefile b/common/Makefile index daeea67cf2..215b8b26fd 100644 --- a/common/Makefile +++ b/common/Makefile @@ -137,3 +137,4 @@ obj-$(CONFIG_CMD_LOADB) += xyzModem.o obj-$(CONFIG_$(SPL_TPL_)YMODEM_SUPPORT) += xyzModem.o obj-$(CONFIG_AVB_VERIFY) += avb_verify.o +obj-$(CONFIG_SCP03) += scp03.o diff --git a/common/bootm.c b/common/bootm.c index defaed8426..dab7c3619f 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -586,7 +586,7 @@ int bootm_process_cmdline(char *buf, int maxlen, int flags) if (IS_ENABLED(CONFIG_BOOTARGS_SUBST) && (flags & BOOTM_CL_SUBST)) { ret = process_subst(buf, maxlen); if (ret) - return log_msg_ret("silent", ret); + return log_msg_ret("subst", ret); } return 0; diff --git a/common/log.c b/common/log.c index 6b0034c3ba..ea407c6db9 100644 --- a/common/log.c +++ b/common/log.c @@ -153,7 +153,7 @@ static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec) { struct log_filter *filt; - if (rec->force_debug) + if (rec->flags & LOGRECF_FORCE_DEBUG) return true; /* If there are no filters, filter on the default log level */ @@ -218,8 +218,11 @@ static int log_dispatch(struct log_rec *rec, const char *fmt, va_list args) if ((ldev->flags & LOGDF_ENABLE) && log_passes_filters(ldev, rec)) { if (!rec->msg) { - vsnprintf(buf, sizeof(buf), fmt, args); + int len; + + len = vsnprintf(buf, sizeof(buf), fmt, args); rec->msg = buf; + gd->log_cont = len && buf[len - 1] != '\n'; } ldev->drv->emit(ldev, rec); } @@ -245,7 +248,11 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file, rec.cat = cat; rec.level = level & LOGL_LEVEL_MASK; - rec.force_debug = level & LOGL_FORCE_DEBUG; + rec.flags = 0; + if (level & LOGL_FORCE_DEBUG) + rec.flags |= LOGRECF_FORCE_DEBUG; + if (gd->log_cont) + rec.flags |= LOGRECF_CONT; rec.file = file; rec.line = line; rec.func = func; @@ -255,7 +262,8 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file, gd->log_drop_count++; /* display dropped traces with console puts and DEBUG_UART */ - if (rec.level <= CONFIG_LOG_DEFAULT_LEVEL || rec.force_debug) { + if (rec.level <= CONFIG_LOG_DEFAULT_LEVEL || + rec.flags & LOGRECF_FORCE_DEBUG) { char buf[CONFIG_SYS_CBSIZE]; va_start(args, fmt); diff --git a/common/log_console.c b/common/log_console.c index 6abb13c93b..3f6177499e 100644 --- a/common/log_console.c +++ b/common/log_console.c @@ -15,6 +15,7 @@ DECLARE_GLOBAL_DATA_PTR; static int log_console_emit(struct log_device *ldev, struct log_rec *rec) { int fmt = gd->log_fmt; + bool add_space = false; /* * The output format is designed to give someone a fighting chance of @@ -26,18 +27,21 @@ static int log_console_emit(struct log_device *ldev, struct log_rec *rec) * - function is an identifier and ends with () * - message has a space before it unless it is on its own */ - if (fmt & BIT(LOGF_LEVEL)) - printf("%s.", log_get_level_name(rec->level)); - if (fmt & BIT(LOGF_CAT)) - printf("%s,", log_get_cat_name(rec->cat)); - if (fmt & BIT(LOGF_FILE)) - printf("%s:", rec->file); - if (fmt & BIT(LOGF_LINE)) - printf("%d-", rec->line); - if (fmt & BIT(LOGF_FUNC)) - printf("%s()", rec->func); + if (!(rec->flags & LOGRECF_CONT) && fmt != BIT(LOGF_MSG)) { + add_space = true; + if (fmt & BIT(LOGF_LEVEL)) + printf("%s.", log_get_level_name(rec->level)); + if (fmt & BIT(LOGF_CAT)) + printf("%s,", log_get_cat_name(rec->cat)); + if (fmt & BIT(LOGF_FILE)) + printf("%s:", rec->file); + if (fmt & BIT(LOGF_LINE)) + printf("%d-", rec->line); + if (fmt & BIT(LOGF_FUNC)) + printf("%s()", rec->func); + } if (fmt & BIT(LOGF_MSG)) - printf("%s%s", fmt != BIT(LOGF_MSG) ? " " : "", rec->msg); + printf("%s%s", add_space ? " " : "", rec->msg); return 0; } diff --git a/common/scp03.c b/common/scp03.c new file mode 100644 index 0000000000..09ef7b5ba3 --- /dev/null +++ b/common/scp03.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2021, Foundries.IO + * + */ + +#include <common.h> +#include <scp03.h> +#include <tee.h> +#include <tee/optee_ta_scp03.h> + +static int scp03_enable(bool provision) +{ + const struct tee_optee_ta_uuid uuid = PTA_SCP03_UUID; + struct tee_open_session_arg session; + struct tee_invoke_arg invoke; + struct tee_param param; + struct udevice *tee = NULL; + + tee = tee_find_device(tee, NULL, NULL, NULL); + if (!tee) + return -ENODEV; + + memset(&session, 0, sizeof(session)); + tee_optee_ta_uuid_to_octets(session.uuid, &uuid); + if (tee_open_session(tee, &session, 0, NULL)) + return -ENXIO; + + memset(¶m, 0, sizeof(param)); + param.attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT; + param.u.value.a = provision; + + memset(&invoke, 0, sizeof(invoke)); + invoke.func = PTA_CMD_ENABLE_SCP03; + invoke.session = session.session; + + if (tee_invoke_func(tee, &invoke, 1, ¶m)) + return -EIO; + + tee_close_session(tee, session.session); + + return 0; +} + +int tee_enable_scp03(void) +{ + return scp03_enable(false); +} + +int tee_provision_scp03(void) +{ + return scp03_enable(true); +} diff --git a/common/spl/spl.c b/common/spl/spl.c index e3d84082f4..5f51098a88 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -16,6 +16,7 @@ #include <init.h> #include <irq_func.h> #include <log.h> +#include <mapmem.h> #include <serial.h> #include <spl.h> #include <asm/global_data.h> @@ -168,7 +169,7 @@ __weak void spl_board_prepare_for_boot(void) __weak struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) { - return (struct image_header *)(CONFIG_SYS_TEXT_BASE + offset); + return map_sysmem(CONFIG_SYS_TEXT_BASE + offset, 0); } void spl_set_header_raw_uboot(struct spl_image_info *spl_image) @@ -694,7 +695,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2) #endif switch (spl_image.os) { case IH_OS_U_BOOT: - debug("Jumping to U-Boot\n"); + debug("Jumping to %s...\n", spl_phase_name(spl_next_phase())); break; #if CONFIG_IS_ENABLED(ATF) case IH_OS_ARM_TRUSTED_FIRMWARE: @@ -741,7 +742,6 @@ void board_init_r(gd_t *dummy1, ulong dummy2) debug("Failed to stash bootstage: err=%d\n", ret); #endif - debug("loaded - jumping to %s...\n", spl_phase_name(spl_next_phase())); spl_board_prepare_for_boot(); jump_to_image_no_args(&spl_image); } diff --git a/common/spl/spl_fit.c b/common/spl/spl_fit.c index 75c8ff065b..49508fc518 100644 --- a/common/spl/spl_fit.c +++ b/common/spl/spl_fit.c @@ -11,6 +11,7 @@ #include <image.h> #include <log.h> #include <malloc.h> +#include <mapmem.h> #include <spl.h> #include <sysinfo.h> #include <asm/cache.h> @@ -235,11 +236,11 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector, size_t length; int len; ulong size; - ulong load_addr, load_ptr; + ulong load_addr; + void *load_ptr; void *src; ulong overhead; int nr_sectors; - int align_len = ARCH_DMA_MINALIGN - 1; uint8_t image_comp = -1, type = -1; const void *data; const void *fit = ctx->fit; @@ -269,11 +270,13 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector, } if (external_data) { + void *src_ptr; + /* External data */ if (fit_image_get_data_size(fit, node, &len)) return -ENOENT; - load_ptr = (load_addr + align_len) & ~align_len; + src_ptr = map_sysmem(ALIGN(load_addr, ARCH_DMA_MINALIGN), len); length = len; overhead = get_aligned_image_overhead(info, offset); @@ -281,12 +284,12 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector, if (info->read(info, sector + get_aligned_image_offset(info, offset), - nr_sectors, (void *)load_ptr) != nr_sectors) + nr_sectors, src_ptr) != nr_sectors) return -EIO; - debug("External data: dst=%lx, offset=%x, size=%lx\n", - load_ptr, offset, (unsigned long)length); - src = (void *)load_ptr + overhead; + debug("External data: dst=%p, offset=%x, size=%lx\n", + src_ptr, offset, (unsigned long)length); + src = src_ptr + overhead; } else { /* Embedded data */ if (fit_image_get_data(fit, node, &data, &length)) { @@ -295,7 +298,7 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector, } debug("Embedded data: dst=%lx, size=%lx\n", load_addr, (unsigned long)length); - src = (void *)data; + src = (void *)data; /* cast away const */ } if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) { @@ -309,16 +312,16 @@ static int spl_load_fit_image(struct spl_load_info *info, ulong sector, if (CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS)) board_fit_image_post_process(&src, &length); + load_ptr = map_sysmem(load_addr, length); if (IS_ENABLED(CONFIG_SPL_GZIP) && image_comp == IH_COMP_GZIP) { size = length; - if (gunzip((void *)load_addr, CONFIG_SYS_BOOTM_LEN, - src, &size)) { + if (gunzip(load_ptr, CONFIG_SYS_BOOTM_LEN, src, &size)) { puts("Uncompressing error\n"); return -EIO; } length = size; } else { - memcpy((void *)load_addr, src, length); + memcpy(load_ptr, src, length); } if (image_info) { @@ -383,7 +386,7 @@ static int spl_fit_append_fdt(struct spl_image_info *spl_image, } /* Make the load-address of the FDT available for the SPL framework */ - spl_image->fdt_addr = (void *)image_info.load_addr; + spl_image->fdt_addr = map_sysmem(image_info.load_addr, 0); if (CONFIG_IS_ENABLED(FIT_IMAGE_TINY)) return 0; diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index c0118702a8..2696d0b6cd 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -1,4 +1,4 @@ -CONFIG_SYS_TEXT_BASE=0 +CONFIG_SYS_TEXT_BASE=0x200000 CONFIG_SPL_LIBCOMMON_SUPPORT=y CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_NR_DRAM_BANKS=1 diff --git a/doc/Makefile b/doc/Makefile index a686d4728e..683e4b5609 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -56,7 +56,6 @@ quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4) PYTHONDONTWRITEBYTECODE=1 \ BUILDDIR=$(abspath $(BUILDDIR)) SPHINX_CONF=$(abspath $(srctree)/$(src)/$5/$(SPHINX_CONF)) \ $(SPHINXBUILD) \ - -W \ -b $2 \ -c $(abspath $(srctree)/$(src)) \ -d $(abspath $(BUILDDIR)/.doctrees/$3) \ diff --git a/doc/arch/sandbox.rst b/doc/arch/sandbox.rst index 60ee1e0741..8b18a22117 100644 --- a/doc/arch/sandbox.rst +++ b/doc/arch/sandbox.rst @@ -17,6 +17,12 @@ of the sandbox U-Boot. The purpose of running U-Boot under Linux is to test all the generic code, not specific to any one architecture. The idea is to create unit tests which we can run to test this upper level code. +Sandbox allows development of many types of new features in a traditional way, +rather than needing to test each iteration on real hardware. Many U-Boot +features were developed on sandbox, including the core driver model, most +uclasses, verified boot, bloblist, logging and dozens of others. Sandbox has +enabled many large-scale code refactors as well. + CONFIG_SANDBOX is defined when building a native board. The board name is 'sandbox' but the vendor name is unset, so there is a @@ -76,7 +82,7 @@ console:: You can issue commands as your would normally. If the command you want is not supported you can add it to include/configs/sandbox.h. -To exit, type 'reset' or press Ctrl-C. +To exit, type 'poweroff' or press Ctrl-C. Console / LCD support @@ -486,42 +492,10 @@ Testing ------- U-Boot sandbox can be used to run various tests, mostly in the test/ -directory. These include: - -command_ut: - Unit tests for command parsing and handling -compression: - Unit tests for U-Boot's compression algorithms, useful for - security checking. It supports gzip, bzip2, lzma and lzo. -driver model: - Run this pytest:: - - ./test/py/test.py --bd sandbox --build -k ut_dm -v - -image: - Unit tests for images: - test/image/test-imagetools.sh - multi-file images - test/image/test-fit.py - FIT images -tracing: - test/trace/test-trace.sh tests the tracing system (see README.trace) -verified boot: - See test/vboot/vboot_test.sh for this - -If you change or enhance any of the above subsystems, you shold write or -expand a test and include it with your patch series submission. Test -coverage in U-Boot is limited, as we need to work to improve it. - -Note that many of these tests are implemented as commands which you can -run natively on your board if desired (and enabled). - -To run all tests use "make check". - -To run a single test in an existing sandbox build, you can use -T to use the -test device tree, and -c to select the test: - - /tmp/b/sandbox/u-boot -T -c "ut dm pci_busdev" +directory. -This runs dm_test_pci_busdev() which is in test/dm/pci.c +See :doc:`../develop/tests_sandbox` for more information and +:doc:`../develop/testing` for information about testing generally. Memory Map @@ -537,5 +511,7 @@ Addr Config Usage e000 CONFIG_BLOBLIST_ADDR Blob list 10000 CONFIG_MALLOC_F_ADDR Early memory allocation f0000 CONFIG_PRE_CON_BUF_ADDR Pre-console buffer - 100000 CONFIG_TRACE_EARLY_ADDR Early trace buffer (if enabled) + 100000 CONFIG_TRACE_EARLY_ADDR Early trace buffer (if enabled). Also used + as the SPL load buffer in spl_test_load(). + 200000 CONFIG_SYS_TEXT_BASE Load buffer for U-Boot (sandbox_spl only) ======= ======================== =============================== diff --git a/doc/develop/index.rst b/doc/develop/index.rst index ac57fdb8f3..41c0ba1ebd 100644 --- a/doc/develop/index.rst +++ b/doc/develop/index.rst @@ -33,3 +33,5 @@ Testing coccinelle testing py_testing + tests_writing + tests_sandbox diff --git a/doc/develop/logging.rst b/doc/develop/logging.rst index 60c18c5b3a..f4e925048e 100644 --- a/doc/develop/logging.rst +++ b/doc/develop/logging.rst @@ -96,16 +96,45 @@ Also debug() and error() will generate log records - these use LOG_CATEGORY as the category, so you should #define this right at the top of the source file to ensure the category is correct. +Generally each log format_string ends with a newline. If it does not, then the +next log statement will have the LOGRECF_CONT flag set. This can be used to +continue the statement on the same line as the previous one without emitting +new header information (such as category/level). This behaviour is implemented +with log_console. Here is an example that prints a list all on one line with +the tags at the start: + +.. code-block:: c + + log_debug("Here is a list:"); + for (i = 0; i < count; i++) + log_debug(" item %d", i); + log_debug("\n"); + +Also see the special category LOGL_CONT and level LOGC_CONT. + You can also define CONFIG_LOG_ERROR_RETURN to enable the log_ret() macro. This can be used whenever your function returns an error value: .. code-block:: c - return log_ret(uclass_first_device(UCLASS_MMC, &dev)); + return log_ret(uclass_first_device_err(UCLASS_MMC, &dev)); This will write a log record when an error code is detected (a value < 0). This can make it easier to trace errors that are generated deep in the call stack. +The log_msg_ret() variant will print a short string if CONFIG_LOG_ERROR_RETURN +is enabled. So long as the string is unique within the function you can normally +determine exactly which call failed: + +.. code-block:: c + + ret = gpio_request_by_name(dev, "cd-gpios", 0, &desc, GPIOD_IS_IN); + if (ret) + return log_msg_ret("gpio", ret); + +Some functions return 0 for success and any other value is an error. For these, +log_retz() and log_msg_retz() are available. + Convenience functions ~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/develop/py_testing.rst b/doc/develop/py_testing.rst index 7f01858cfd..c4cecc0a01 100644 --- a/doc/develop/py_testing.rst +++ b/doc/develop/py_testing.rst @@ -13,7 +13,8 @@ results. Advantages of this approach are: U-Boot; there can be no disconnect. - There is no need to write or embed test-related code into U-Boot itself. It is asserted that writing test-related code in Python is simpler and more - flexible than writing it all in C. + flexible than writing it all in C. But see :doc:`tests_writing` for caveats + and more discussion / analysis. - It is reasonably simple to interact with U-Boot in this way. Requirements diff --git a/doc/develop/testing.rst b/doc/develop/testing.rst index 4bc9ca3a6a..ced13ac8bb 100644 --- a/doc/develop/testing.rst +++ b/doc/develop/testing.rst @@ -8,17 +8,27 @@ tested and what tests you should write when adding a new feature. Running tests ------------- -To run most tests on sandbox, type this: +To run most tests on sandbox, type this:: make check in the U-Boot directory. Note that only the pytest suite is run using this command. -Some tests take ages to run. To run just the quick ones, type this: +Some tests take ages to run and are marked with @pytest.mark.slow. To run just +the quick ones, type this:: make qcheck +It is also possible to run just the tests for tools (patman, binman, etc.). +Such tests are included with those tools, i.e. no actual U-Boot unit tests are +run. Type this:: + + make tcheck + +All of the above use the test/run script with a paremeter to select which tests +are run. + Sandbox ------- @@ -26,6 +36,7 @@ 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. +See :doc:`tests_sandbox` for more information. Pytest Suite ------------ @@ -35,14 +46,27 @@ 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 tests and summarise their results. -You can run the tests on sandbox with: +You can run the tests on sandbox with:: - ./test/py/test.py --bd sandbox --build + ./test/py/test.py --bd sandbox --build This will produce HTML output in build-sandbox/test-log.html +Some tests run with other versions of sandbox. For example sandbox_flattree +runs the tests with livetree (the hierachical devicetree) disabled. You can +also select particular tests with -k:: + + ./test/py/test.py --bd sandbox_flattree --build -k hello + +There are some special tests that run in SPL. For this you need the sandbox_spl +build:: + + ./test/py/test.py --bd sandbox_spl --build -k test_spl + See test/py/README.md for more information about the pytest suite. +See :doc:`tests_sandbox` for how to run tests directly (not through pytest). + tbot ---- @@ -58,10 +82,14 @@ 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 legacy 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) +test/fs + File system test (shell script) +test/image + FIT and legacy 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) TODO: Move these into pytest. @@ -89,6 +117,8 @@ or is covered sparingly. So here are some suggestions: is much easier to add onto a test - writing a new large test can seem daunting to most contributors. +See doc:`tests_writing` for how to write tests. + Future work ----------- diff --git a/doc/develop/tests_sandbox.rst b/doc/develop/tests_sandbox.rst new file mode 100644 index 0000000000..84608dcb84 --- /dev/null +++ b/doc/develop/tests_sandbox.rst @@ -0,0 +1,209 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Sandbox tests +============= + +Test Design +----------- + +Most uclasses and many functions of U-Boot have sandbox tests. This allows much +of the code to be checked in an developer-friendly environment. + +Sandbox provides a way to write and run unit tests. The traditional approach to +unit tests is to build lots of little executables, one for each test or +category of tests. With sandbox, so far as possible, all the tests share a +small number of executables (e.g. 'u-boot' for sandbox, 'u-boot-spl' and +'u-boot' for sandbox_spl) and can be run very quickly. The vast majority of +tests can run on the 'sandbox' build, + +Available tests +--------------- + +Some of the available tests are: + + - command_ut: Unit tests for command parsing and handling + - compression: Unit tests for U-Boot's compression algorithms, useful for + security checking. It supports gzip, bzip2, lzma and lzo. + - image: Unit tests for images: + + - test/image/test-imagetools.sh - multi-file images + - test/py/tests/test-fit.py - FIT images + - tracing: test/trace/test-trace.sh tests the tracing system (see + README.trace) + - verified boot: test/py/tests/test_vboot.py + +If you change or enhance any U-Boot subsystem, you should write or expand a +test and include it with your patch series submission. Test coverage in some +older areas of U-Boot is still somewhat limited and we need to work to improve +it. + +Note that many of these tests are implemented as commands which you can +run natively on your board if desired (and enabled). + +To run all tests, use 'make check'. + + +Running sandbox tests directly +------------------------------ + +Typically tests are run using the pytest suite. Running pytests on sandbox is +easy and always gets things right. For example some tests require files to be +set up before they can work. + +But it is also possible to run some sandbox tests directly. For example, this +runs the dm_test_gpio() test which you can find in test/dm/gpio.c:: + + $ ./u-boot -T -c "ut dm gpio" + + + U-Boot 2021.01 + + Model: sandbox + DRAM: 128 MiB + WDT: Started with servicing (60s timeout) + MMC: mmc2: 2 (SD), mmc1: 1 (SD), mmc0: 0 (SD) + In: serial + Out: vidconsole + Err: vidconsole + Model: sandbox + SCSI: + Net: eth0: eth@10002000, eth5: eth@10003000, eth3: sbe5, eth6: eth@10004000 + Test: dm_test_gpio: gpio.c + Test: dm_test_gpio: gpio.c (flat tree) + Failures: 0 + +The -T option tells the U-Boot sandbox to run with the 'test' devicetree +(test.dts) instead of -D which selects the normal sandbox.dts - this is +necessary because many tests rely on nodes or properties in the test devicetree. +If you try running tests without -T then you may see failures, like:: + + $ ./u-boot -c "ut dm gpio" + + + U-Boot 2021.01 + + DRAM: 128 MiB + WDT: Not found! + MMC: + In: serial + Out: serial + Err: serial + SCSI: + Net: No ethernet found. + Please run with test device tree: + ./u-boot -d arch/sandbox/dts/test.dtb + Test: dm_test_gpio: gpio.c + test/dm/gpio.c:37, dm_test_gpio(): 0 == gpio_lookup_name("b4", &dev, &offset, &gpio): Expected 0x0 (0), got 0xffffffea (-22) + Test: dm_test_gpio: gpio.c (flat tree) + test/dm/gpio.c:37, dm_test_gpio(): 0 == gpio_lookup_name("b4", &dev, &offset, &gpio): Expected 0x0 (0), got 0xffffffea (-22) + Failures: 2 + +The message above should provide a hint if you forget to use the -T flag. Even +running with -D will produce different results. + +You can easily use gdb on these tests, without needing --gdbserver:: + + $ gdb u-boot --args -T -c "ut dm gpio" + ... + (gdb) break dm_test_gpio + Breakpoint 1 at 0x1415bd: file test/dm/gpio.c, line 37. + (gdb) run -T -c "ut dm gpio" + Starting program: u-boot -T -c "ut dm gpio" + Test: dm_test_gpio: gpio.c + + Breakpoint 1, dm_test_gpio (uts=0x5555558029a0 <global_dm_test_state>) + at files/test/dm/gpio.c:37 + 37 ut_assertok(gpio_lookup_name("b4", &dev, &offset, &gpio)); + (gdb) + +You can then single-step and look at variables as needed. + + +Running sandbox_spl tests directly +---------------------------------- + +SPL is the phase before U-Boot proper. It is present in the sandbox_spl build, +so you can run SPL like this:: + + ./spl/u-boot-spl + +SPL tests are special in that they run (only in the SPL phase, of course) if the +-u flag is given:: + + ./spl/u-boot-spl -u + + U-Boot SPL 2021.01-00723-g43c77b51be5-dirty (Jan 24 2021 - 16:38:24 -0700) + Running 5 driver model tests + Test: dm_test_of_plat_base: of_platdata.c (flat tree) + Test: dm_test_of_plat_dev: of_platdata.c (flat tree) + Test: dm_test_of_plat_parent: of_platdata.c (flat tree) + Test: dm_test_of_plat_phandle: of_platdata.c (flat tree) + Test: dm_test_of_plat_props: of_platdata.c (flat tree) + Failures: 0 + + + U-Boot 2021.01-00723-g43c77b51be5-dirty (Jan 24 2021 - 16:38:24 -0700) + + DRAM: 128 MiB + ... + +It is not possible to run SPL tests in U-Boot proper, firstly because they are +not built into U-Boot proper and secondly because the environment is very +different, e.g. some SPL tests rely on of-platdata which is only available in +SPL. + +Note that after running, SPL continues to boot into U-Boot proper. You can add +'-c exit' to make U-Boot quit without doing anything further. It is not +currently possible to run SPL tests and then stop, since the pytests require +that U-Boot produces the expected banner. + +You can use the -k flag to select which tests run:: + + ./spl/u-boot-spl -u -k dm_test_of_plat_parent + +Of course you can use gdb with sandbox_spl, just as with sandbox. + + +Running all tests directly +-------------------------- + +A fast way to run all sandbox tests is:: + + ./u-boot -T -c "ut all" + +It typically runs single-thread in 6 seconds on 2021 hardware, with 2s of that +to the delays in the time test. + +This should not be considered a substitute for 'make check', but can be helpful +for git bisect, etc. + + +What tests are built in? +------------------------ + +Whatever sandbox build is used, which tests are present is determined by which +source files are built. For sandbox_spl, the of_platdata tests are built +because of the build rule in test/dm/Makefile:: + + ifeq ($(CONFIG_SPL_BUILD),y) + obj-$(CONFIG_SPL_OF_PLATDATA) += of_platdata.o + else + ...other tests for non-spl + endif + +You can get a list of tests in a U-Boot ELF file by looking for the +linker_list:: + + $ nm /tmp/b/sandbox_spl/spl/u-boot-spl |grep 2_dm_test + 000000000001f200 D _u_boot_list_2_dm_test_2_dm_test_of_plat_base + 000000000001f220 D _u_boot_list_2_dm_test_2_dm_test_of_plat_dev + 000000000001f240 D _u_boot_list_2_dm_test_2_dm_test_of_plat_parent + 000000000001f260 D _u_boot_list_2_dm_test_2_dm_test_of_plat_phandle + 000000000001f280 D _u_boot_list_2_dm_test_2_dm_test_of_plat_props + + +Writing tests +------------- + +See :doc:`tests_writing` for how to write new tests. + diff --git a/doc/develop/tests_writing.rst b/doc/develop/tests_writing.rst new file mode 100644 index 0000000000..1ddf7a353a --- /dev/null +++ b/doc/develop/tests_writing.rst @@ -0,0 +1,346 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright 2021 Google LLC +.. sectionauthor:: Simon Glass <sjg@chromium.org> + +Writing Tests +============= + +This describes how to write tests in U-Boot and describes the possible options. + +Test types +---------- + +There are two basic types of test in U-Boot: + + - Python tests, in test/py/tests + - C tests, in test/ and its subdirectories + +(there are also UEFI tests in lib/efi_selftest/ not considered here.) + +Python tests talk to U-Boot via the command line. They support both sandbox and +real hardware. They typically do not require building test code into U-Boot +itself. They are fairly slow to run, due to the command-line interface and there +being two separate processes. Python tests are fairly easy to write. They can +be a little tricky to debug sometimes due to the voluminous output of pytest. + +C tests are written directly in U-Boot. While they can be used on boards, they +are more commonly used with sandbox, as they obviously add to U-Boot code size. +C tests are easy to write so long as the required facilities exist. Where they +do not it can involve refactoring or adding new features to sandbox. They are +fast to run and easy to debug. + +Regardless of which test type is used, all tests are collected and run by the +pytest framework, so there is typically no need to run them separately. This +means that C tests can be used when it makes sense, and Python tests when it +doesn't. + + +This table shows how to decide whether to write a C or Python test: + +===================== =========================== ============================= +Attribute C test Python test +===================== =========================== ============================= +Fast to run? Yes No (two separate processes) +Easy to write? Yes, if required test Yes + features exist in sandbox + or the target system +Needs code in U-Boot? Yes No, provided the test can be + executed and the result + determined using the command + line +Easy to debug? Yes No, since access to the U-Boot + state is not available and the + amount of output can + sometimes require a bit of + digging +Can use gdb? Yes, directly Yes, with --gdbserver +Can run on boards? Some can, but only if Some + compiled in and not + dependent on sandboxau +===================== =========================== ============================= + + +Python or C +----------- + +Typically in U-Boot we encourage C test using sandbox for all features. This +allows fast testing, easy development and allows contributors to make changes +without needing dozens of boards to test with. + +When a test requires setup or interaction with the running host (such as to +generate images and then running U-Boot to check that they can be loaded), or +cannot be run on sandbox, Python tests should be used. These should typically +NOT rely on running with sandbox, but instead should function correctly on any +board supported by U-Boot. + + +How slow are Python tests? +-------------------------- + +Under the hood, when running on sandbox, Python tests work by starting a sandbox +test and connecting to it via a pipe. Each interaction with the U-Boot process +requires at least a context switch to handle the pipe interaction. The test +sends a command to U-Boot, which then reacts and shows some output, then the +test sees that and continues. Of course on real hardware, communications delays +(e.g. with a serial console) make this slower. + +For comparison, consider a test that checks the 'md' (memory dump). All times +below are approximate, as measured on an AMD 2950X system. Here is is the test +in Python:: + + @pytest.mark.buildconfigspec('cmd_memory') + def test_md(u_boot_console): + """Test that md reads memory as expected, and that memory can be modified + using the mw command.""" + + ram_base = u_boot_utils.find_ram_base(u_boot_console) + addr = '%08x' % ram_base + val = 'a5f09876' + expected_response = addr + ': ' + val + u_boot_console.run_command('mw ' + addr + ' 0 10') + response = u_boot_console.run_command('md ' + addr + ' 10') + assert(not (expected_response in response)) + u_boot_console.run_command('mw ' + addr + ' ' + val) + response = u_boot_console.run_command('md ' + addr + ' 10') + assert(expected_response in response) + +This runs a few commands and checks the output. Note that it runs a command, +waits for the response and then checks it agains what is expected. If run by +itself it takes around 800ms, including test collection. For 1000 runs it takes +19 seconds, or 19ms per run. Of course 1000 runs it not that useful since we +only want to run it once. + +There is no exactly equivalent C test, but here is a similar one that tests 'ms' +(memory search):: + + /* Test 'ms' command with bytes */ + static int mem_test_ms_b(struct unit_test_state *uts) + { + u8 *buf; + + buf = map_sysmem(0, BUF_SIZE + 1); + memset(buf, '\0', BUF_SIZE); + buf[0x0] = 0x12; + buf[0x31] = 0x12; + buf[0xff] = 0x12; + buf[0x100] = 0x12; + ut_assertok(console_record_reset_enable()); + run_command("ms.b 1 ff 12", 0); + ut_assert_nextline("00000030: 00 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................"); + ut_assert_nextline("--"); + ut_assert_nextline("000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 ................"); + ut_assert_nextline("2 matches"); + ut_assert_console_end(); + + ut_asserteq(2, env_get_hex("memmatches", 0)); + ut_asserteq(0xff, env_get_hex("memaddr", 0)); + ut_asserteq(0xfe, env_get_hex("mempos", 0)); + + unmap_sysmem(buf); + + return 0; + } + MEM_TEST(mem_test_ms_b, UT_TESTF_CONSOLE_REC); + +This runs the command directly in U-Boot, then checks the console output, also +directly in U-Boot. If run by itself this takes 100ms. For 1000 runs it takes +660ms, or 0.66ms per run. + +So overall running a C test is perhaps 8 times faster individually and the +interactions are perhaps 25 times faster. + +It should also be noted that the C test is fairly easy to debug. You can set a +breakpoint on do_mem_search(), which is what implements the 'ms' command, +single step to see what might be wrong, etc. That is also possible with the +pytest, but requires two terminals and --gdbserver. + + +Why does speed matter? +---------------------- + +Many development activities rely on running tests: + + - 'git bisect run make qcheck' can be used to find a failing commit + - test-driven development relies on quick iteration of build/test + - U-Boot's continuous integration (CI) systems make use of tests. Running + all sandbox tests typically takes 90 seconds and running each qemu test + takes about 30 seconds. This is currently dwarfed by the time taken to + build all boards + +As U-Boot continues to grow its feature set, fast and reliable tests are a +critical factor factor in developer productivity and happiness. + + +Writing C tests +--------------- + +C tests are arranged into suites which are typically executed by the 'ut' +command. Each suite is in its own file. This section describes how to accomplish +some common test tasks. + +(there are also UEFI C tests in lib/efi_selftest/ not considered here.) + +Add a new driver model test +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use this when adding a test for a new or existing uclass, adding new operations +or features to a uclass, adding new ofnode or dev_read_() functions, or anything +else related to driver model. + +Find a suitable place for your test, perhaps near other test functions in +existing code, or in a new file. Each uclass should have its own test file. + +Declare the test with:: + + /* Test that ... */ + static int dm_test_uclassname_what(struct unit_test_state *uts) + { + /* test code here */ + + return 0; + } + DM_TEST(dm_test_uclassname_what, UT_TESTF_SCAN_FDT); + +Replace 'uclassname' with the name of your uclass, if applicable. Replace 'what' +with what you are testing. + +The flags for DM_TEST() are defined in test/test.h and you typically want +UT_TESTF_SCAN_FDT so that the devicetree is scanned and all devices are bound +and ready for use. The DM_TEST macro adds UT_TESTF_DM automatically so that +the test runner knows it is a driver model test. + +Driver model tests are special in that the entire driver model state is +recreated anew for each test. This ensures that if a previous test deletes a +device, for example, it does not affect subsequent tests. Driver model tests +also run both with livetree and flattree, to ensure that both devicetree +implementations work as expected. + +Example commit: c48cb7ebfb4 ("sandbox: add ADC unit tests") [1] + +[1] https://gitlab.denx.de/u-boot/u-boot/-/commit/c48cb7ebfb4 + + +Add a C test to an existing suite +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use this when you are adding to or modifying an existing feature outside driver +model. An example is bloblist. + +Add a new function in the same file as the rest of the suite and register it +with the suite. For example, to add a new mem_search test:: + + /* Test 'ms' command with 32-bit values */ + static int mem_test_ms_new_thing(struct unit_test_state *uts) + { + /* test code here*/ + + return 0; + } + MEM_TEST(mem_test_ms_new_thing, UT_TESTF_CONSOLE_REC); + +Note that the MEM_TEST() macros is defined at the top of the file. + +Example commit: 9fe064646d2 ("bloblist: Support relocating to a larger space") [1] + +[1] https://gitlab.denx.de/u-boot/u-boot/-/commit/9fe064646d2 + + +Add a new test suite +~~~~~~~~~~~~~~~~~~~~ + +Each suite should focus on one feature or subsystem, so if you are writing a +new one of those, you should add a new suite. + +Create a new file in test/ or a subdirectory and define a macro to register the +suite. For example:: + + #include <common.h> + #include <console.h> + #include <mapmem.h> + #include <dm/test.h> + #include <test/ut.h> + + /* Declare a new wibble test */ + #define WIBBLE_TEST(_name, _flags) UNIT_TEST(_name, _flags, wibble_test) + + /* Tetss go here */ + + /* At the bottom of the file: */ + + int do_ut_wibble(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) + { + struct unit_test *tests = UNIT_TEST_SUITE_START(wibble_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(wibble_test); + + return cmd_ut_category("cmd_wibble", "wibble_test_", tests, n_ents, argc, argv); + } + +Then add new tests to it as above. + +Register this new suite in test/cmd_ut.c by adding to cmd_ut_sub[]:: + + /* Within cmd_ut_sub[]... */ + + U_BOOT_CMD_MKENT(wibble, CONFIG_SYS_MAXARGS, 1, do_ut_wibble, "", ""), + +and adding new help to ut_help_text[]:: + + "ut wibble - Test the wibble feature\n" + +If your feature is conditional on a particular Kconfig, then you can use #ifdef +to control that. + +Finally, add the test to the build by adding to the Makefile in the same +directory:: + + obj-$(CONFIG_$(SPL_)CMDLINE) += wibble.o + +Note that CMDLINE is never enabled in SPL, so this test will only be present in +U-Boot proper. See below for how to do SPL tests. + +As before, you can add an extra Kconfig check if needed:: + + ifneq ($(CONFIG_$(SPL_)WIBBLE),) + obj-$(CONFIG_$(SPL_)CMDLINE) += wibble.o + endif + + +Example commit: 919e7a8fb64 ("test: Add a simple test for bloblist") [1] + +[1] https://gitlab.denx.de/u-boot/u-boot/-/commit/919e7a8fb64 + + +Making the test run from pytest +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +All C tests must run from pytest. Typically this is automatic, since pytest +scans the U-Boot executable for available tests to run. So long as you have a +'ut' subcommand for your test suite, it will run. The same applies for driver +model tests since they use the 'ut dm' subcommand. + +See test/py/tests/test_ut.py for how unit tests are run. + + +Add a C test for SPL +~~~~~~~~~~~~~~~~~~~~ + +Note: C tests are only available for sandbox_spl at present. There is currently +no mechanism in other boards to existing SPL tests even if they are built into +the image. + +SPL tests cannot be run from the 'ut' command since there are no commands +available in SPL. Instead, sandbox (only) calls ut_run_list() on start-up, when +the -u flag is given. This runs the available unit tests, no matter what suite +they are in. + +To create a new SPL test, follow the same rules as above, either adding to an +existing suite or creating a new one. + +An example SPL test is spl_test_load(). + + +Writing Python tests +-------------------- + +See :doc:`py_testing` for brief notes how to write Python tests. You +should be able to use the existing tests in test/py/tests as examples. diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 9169fff0be..637b73ccab 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -29,7 +29,9 @@ Shell commands load loady mbr + md pstore qfw sbi true + scp03 diff --git a/doc/usage/md.rst b/doc/usage/md.rst new file mode 100644 index 0000000000..4c1073ea35 --- /dev/null +++ b/doc/usage/md.rst @@ -0,0 +1,106 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +md command +========== + +Synopis +------- + +:: + + md <address>[<data_size>] [<length>] + +Description +----------- + +The md command is used to dump the contents of memory. It uses a standard +format that includes the address, hex data and ASCII display. It supports +various data sizes and uses the endianness of the target. + +The specified data_size and length become the defaults for future memory +commands commands. + +address + start address to display + +data_size + size of each value to display (defaults to .l): + + ========= =================== + data_size Output size + ========= =================== + .b byte + .w word (16 bits) + .l long (32 bits) + .q quadword (64 bits) + ========= =================== + +length + number of values to dump. Defaults to 40 (0d64). Note that this is not + the same as the number of bytes, unless .b is used. + +Note that the format of 'md.b' can be emulated from linux with:: + + # This works but requires using sed to get the extra spaces + # <addr> is the address, <f> is the filename + xxd -o <addr> -g1 <f> |sed 's/ / /' >bad + + # This uses a single tool but the offset always starts at 0 + # <f> is the filename + hexdump -v -e '"%08.8_ax: " 16/1 "%02x " " "' -e '16/1 "%_p" "\n" ' <f> + + +Example +------- + +:: + + => md 10000 + 00010000: 00010000 00000000 f0f30f00 00005596 .............U.. + 00010010: 10011010 00000000 10011010 00000000 ................ + 00010020: 10011050 00000000 b96d4cd8 00007fff P........Lm..... + 00010030: 00000000 00000000 f0f30f18 00005596 .............U.. + 00010040: 10011040 00000000 10011040 00000000 @.......@....... + 00010050: b96d4cd8 00007fff 10011020 00000000 .Lm..... ....... + 00010060: 00000003 000000c3 00000000 00000000 ................ + 00010070: 00000000 00000000 f0e892f3 00005596 .............U.. + 00010080: 00000000 000000a1 00000000 00000000 ................ + 00010090: 00000000 00000000 f0e38aa6 00005596 .............U.. + 000100a0: 00000000 000000a6 00000022 00000000 ........"....... + 000100b0: 00000001 00000000 f0e38aa1 00005596 .............U.. + 000100c0: 00000000 000000be 00000000 00000000 ................ + 000100d0: 00000000 00000000 00000000 00000000 ................ + 000100e0: 00000000 00000000 00000000 00000000 ................ + 000100f0: 00000000 00000000 00000000 00000000 ................ + => md.b 10000 + 00010000: 00 00 01 00 00 00 00 00 00 0f f3 f0 96 55 00 00 .............U.. + 00010010: 10 10 01 10 00 00 00 00 10 10 01 10 00 00 00 00 ................ + 00010020: 50 10 01 10 00 00 00 00 d8 4c 6d b9 ff 7f 00 00 P........Lm..... + 00010030: 00 00 00 00 00 00 00 00 18 0f f3 f0 96 55 00 00 .............U.. + => md.b 10000 10 + 00010000: 00 00 01 00 00 00 00 00 00 0f f3 f0 96 55 00 00 .............U.. + => + 00010010: 10 10 01 10 00 00 00 00 10 10 01 10 00 00 00 00 ................ + => + 00010020: 50 10 01 10 00 00 00 00 d8 4c 6d b9 ff 7f 00 00 P........Lm..... + => + => md.q 10000 + 00010000: 0000000000010000 00005596f0f30f00 .............U.. + 00010010: 0000000010011010 0000000010011010 ................ + 00010020: 0000000010011050 00007fffb96d4cd8 P........Lm..... + 00010030: 0000000000000000 00005596f0f30f18 .............U.. + 00010040: 0000000010011040 0000000010011040 @.......@....... + 00010050: 00007fffb96d4cd8 0000000010011020 .Lm..... ....... + 00010060: 000000c300000003 0000000000000000 ................ + 00010070: 0000000000000000 00005596f0e892f3 .............U.. + +The empty commands cause a 'repeat', so that md shows the next available data +in the same format as before. + + +Return value +------------ + +The return value $? is always 0 (true). + + diff --git a/doc/usage/scp03.rst b/doc/usage/scp03.rst new file mode 100644 index 0000000000..7ff87ed85a --- /dev/null +++ b/doc/usage/scp03.rst @@ -0,0 +1,33 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +scp03 command +============= + +Synopsis +-------- + +:: + + scp03 enable + scp03 provision + +Description +----------- + +The *scp03* command calls into a Trusted Application executing in a +Trusted Execution Environment to enable (if present) the Secure +Channel Protocol 03 stablished between the processor and the secure +element. + +This protocol encrypts all the communication between the processor and +the secure element using a set of pre-defined keys. These keys can be +rotated (provisioned) using the *provision* request. + +See also +-------- + +For some information on the internals implemented in the TEE, please +check the GlobalPlatform documentation on `Secure Channel Protocol '03'`_ + +.. _Secure Channel Protocol '03': + https://globalplatform.org/wp-content/uploads/2014/07/GPC_2.3_D_SCP03_v1.1.2_PublicRelease.pdf diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 4a9b74e1ca..f24db87ef0 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -3,6 +3,8 @@ * Copyright (c) 2013 Google, Inc */ +#define LOG_CATEGORY UCLASS_GPIO + #include <common.h> #include <dm.h> #include <log.h> @@ -21,6 +23,7 @@ #include <dm/device_compat.h> #include <linux/bug.h> #include <linux/ctype.h> +#include <linux/delay.h> DECLARE_GLOBAL_DATA_PTR; @@ -220,7 +223,7 @@ int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc, static int gpio_find_and_xlate(struct gpio_desc *desc, struct ofnode_phandle_args *args) { - struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); + const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); if (ops->xlate) return ops->xlate(desc->dev, desc, args); @@ -353,6 +356,7 @@ int gpio_hog_lookup_name(const char *name, struct gpio_desc **desc) int dm_gpio_request(struct gpio_desc *desc, const char *label) { + const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); struct udevice *dev = desc->dev; struct gpio_dev_priv *uc_priv; char *str; @@ -364,8 +368,8 @@ int dm_gpio_request(struct gpio_desc *desc, const char *label) str = strdup(label); if (!str) return -ENOMEM; - if (gpio_get_ops(dev)->request) { - ret = gpio_get_ops(dev)->request(dev, desc->offset, label); + if (ops->request) { + ret = ops->request(dev, desc->offset, label); if (ret) { free(str); return ret; @@ -442,14 +446,15 @@ int gpio_requestf(unsigned gpio, const char *fmt, ...) int _dm_gpio_free(struct udevice *dev, uint offset) { + const struct dm_gpio_ops *ops = gpio_get_ops(dev); struct gpio_dev_priv *uc_priv; int ret; uc_priv = dev_get_uclass_priv(dev); if (!uc_priv->name[offset]) return -ENXIO; - if (gpio_get_ops(dev)->rfree) { - ret = gpio_get_ops(dev)->rfree(dev, offset); + if (ops->rfree) { + ret = ops->rfree(dev, offset); if (ret) return ret; } @@ -515,11 +520,8 @@ int gpio_direction_input(unsigned gpio) ret = gpio_to_device(gpio, &desc); if (ret) return ret; - ret = check_reserved(&desc, "dir_input"); - if (ret) - return ret; - return gpio_get_ops(desc.dev)->direction_input(desc.dev, desc.offset); + return dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_IN); } /** @@ -534,24 +536,25 @@ int gpio_direction_input(unsigned gpio) int gpio_direction_output(unsigned gpio, int value) { struct gpio_desc desc; + ulong flags; int ret; ret = gpio_to_device(gpio, &desc); if (ret) return ret; - ret = check_reserved(&desc, "dir_output"); - if (ret) - return ret; - return gpio_get_ops(desc.dev)->direction_output(desc.dev, - desc.offset, value); + flags = GPIOD_IS_OUT; + if (value) + flags |= GPIOD_IS_OUT_ACTIVE; + return dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, flags); } static int _gpio_get_value(const struct gpio_desc *desc) { + const struct dm_gpio_ops *ops = gpio_get_ops(desc->dev); int value; - value = gpio_get_ops(desc->dev)->get_value(desc->dev, desc->offset); + value = ops->get_value(desc->dev, desc->offset); return desc->flags & GPIOD_ACTIVE_LOW ? !value : value; } @@ -569,6 +572,7 @@ int dm_gpio_get_value(const struct gpio_desc *desc) int dm_gpio_set_value(const struct gpio_desc *desc, int value) { + const struct dm_gpio_ops *ops; int ret; ret = check_reserved(desc, "set_value"); @@ -578,21 +582,33 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int value) if (desc->flags & GPIOD_ACTIVE_LOW) value = !value; + /* GPIOD_ are directly managed by driver in set_flags */ + ops = gpio_get_ops(desc->dev); + if (ops->set_flags) { + ulong flags = desc->flags; + + if (value) + flags |= GPIOD_IS_OUT_ACTIVE; + else + flags &= ~GPIOD_IS_OUT_ACTIVE; + return ops->set_flags(desc->dev, desc->offset, flags); + } + /* * Emulate open drain by not actively driving the line high or * Emulate open source by not actively driving the line low */ if ((desc->flags & GPIOD_OPEN_DRAIN && value) || (desc->flags & GPIOD_OPEN_SOURCE && !value)) - return gpio_get_ops(desc->dev)->direction_input(desc->dev, - desc->offset); + return ops->direction_input(desc->dev, desc->offset); else if (desc->flags & GPIOD_OPEN_DRAIN || desc->flags & GPIOD_OPEN_SOURCE) - return gpio_get_ops(desc->dev)->direction_output(desc->dev, - desc->offset, - value); + return ops->direction_output(desc->dev, desc->offset, value); + + ret = ops->set_value(desc->dev, desc->offset, value); + if (ret) + return ret; - gpio_get_ops(desc->dev)->set_value(desc->dev, desc->offset, value); return 0; } @@ -620,10 +636,21 @@ static int check_dir_flags(ulong flags) return 0; } -static int _dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) +/** + * _dm_gpio_set_flags() - Send flags to the driver + * + * This uses the best available method to send the given flags to the driver. + * Note that if flags & GPIOD_ACTIVE_LOW, the driver sees the opposite value + * of GPIOD_IS_OUT_ACTIVE. + * + * @desc: GPIO description + * @flags: flags value to set + * @return 0 if OK, -ve on error + */ +static int _dm_gpio_set_flags(struct gpio_desc *desc, ulong flags) { struct udevice *dev = desc->dev; - struct dm_gpio_ops *ops = gpio_get_ops(dev); + const struct dm_gpio_ops *ops = gpio_get_ops(dev); struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); int ret = 0; @@ -638,38 +665,52 @@ static int _dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) return ret; } - /* GPIOD_ are directly managed by driver in set_dir_flags*/ - if (ops->set_dir_flags) { - ret = ops->set_dir_flags(dev, desc->offset, flags); + /* If active low, invert the output state */ + if ((flags & (GPIOD_IS_OUT | GPIOD_ACTIVE_LOW)) == + (GPIOD_IS_OUT | GPIOD_ACTIVE_LOW)) + flags ^= GPIOD_IS_OUT_ACTIVE; + + /* GPIOD_ are directly managed by driver in set_flags */ + if (ops->set_flags) { + ret = ops->set_flags(dev, desc->offset, flags); } else { if (flags & GPIOD_IS_OUT) { - ret = ops->direction_output(dev, desc->offset, - GPIOD_FLAGS_OUTPUT(flags)); + bool value = flags & GPIOD_IS_OUT_ACTIVE; + + ret = ops->direction_output(dev, desc->offset, value); } else if (flags & GPIOD_IS_IN) { ret = ops->direction_input(dev, desc->offset); } } - /* save the flags also in descriptor */ - if (!ret) - desc->flags = flags; - return ret; } -int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) +int dm_gpio_clrset_flags(struct gpio_desc *desc, ulong clr, ulong set) { + ulong flags; int ret; ret = check_reserved(desc, "set_dir_flags"); if (ret) return ret; - /* combine the requested flags (for IN/OUT) and the descriptor flags */ - flags |= desc->flags; - ret = _dm_gpio_set_dir_flags(desc, flags); + flags = (desc->flags & ~clr) | set; - return ret; + ret = _dm_gpio_set_flags(desc, flags); + if (ret) + return ret; + + /* save the flags also in descriptor */ + desc->flags = flags; + + return 0; +} + +int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags) +{ + /* combine the requested flags (for IN/OUT) and the descriptor flags */ + return dm_gpio_clrset_flags(desc, GPIOD_MASK_DIR, flags); } int dm_gpio_set_dir(struct gpio_desc *desc) @@ -680,42 +721,57 @@ int dm_gpio_set_dir(struct gpio_desc *desc) if (ret) return ret; - return _dm_gpio_set_dir_flags(desc, desc->flags); + return _dm_gpio_set_flags(desc, desc->flags); +} + +int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr, + ulong set) +{ + int ret; + int i; + + for (i = 0; i < count; i++) { + ret = dm_gpio_clrset_flags(&desc[i], clr, set); + if (ret) + return log_ret(ret); + } + + return 0; } -int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags) +int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flagsp) { struct udevice *dev = desc->dev; int ret, value; - struct dm_gpio_ops *ops = gpio_get_ops(dev); - ulong dir_flags; + const struct dm_gpio_ops *ops = gpio_get_ops(dev); + ulong flags; - ret = check_reserved(desc, "get_dir_flags"); + ret = check_reserved(desc, "get_flags"); if (ret) return ret; /* GPIOD_ are directly provided by driver except GPIOD_ACTIVE_LOW */ - if (ops->get_dir_flags) { - ret = ops->get_dir_flags(dev, desc->offset, &dir_flags); + if (ops->get_flags) { + ret = ops->get_flags(dev, desc->offset, &flags); if (ret) return ret; /* GPIOD_ACTIVE_LOW is saved in desc->flags */ - value = dir_flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; + value = flags & GPIOD_IS_OUT_ACTIVE ? 1 : 0; if (desc->flags & GPIOD_ACTIVE_LOW) value = !value; - dir_flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE); - dir_flags |= (desc->flags & GPIOD_ACTIVE_LOW); + flags &= ~(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE); + flags |= (desc->flags & GPIOD_ACTIVE_LOW); if (value) - dir_flags |= GPIOD_IS_OUT_ACTIVE; + flags |= GPIOD_IS_OUT_ACTIVE; } else { - dir_flags = desc->flags; + flags = desc->flags; /* only GPIOD_IS_OUT_ACTIVE is provided by uclass */ - dir_flags &= ~GPIOD_IS_OUT_ACTIVE; + flags &= ~GPIOD_IS_OUT_ACTIVE; if ((desc->flags & GPIOD_IS_OUT) && _gpio_get_value(desc)) - dir_flags |= GPIOD_IS_OUT_ACTIVE; + flags |= GPIOD_IS_OUT_ACTIVE; } - *flags = dir_flags; + *flagsp = flags; return 0; } @@ -785,7 +841,7 @@ static int get_function(struct udevice *dev, int offset, bool skip_unused, const char **namep) { struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); - struct dm_gpio_ops *ops = gpio_get_ops(dev); + const struct dm_gpio_ops *ops = gpio_get_ops(dev); BUILD_BUG_ON(GPIOF_COUNT != ARRAY_SIZE(gpio_function)); if (!device_active(dev)) @@ -822,7 +878,7 @@ int gpio_get_raw_function(struct udevice *dev, int offset, const char **namep) int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) { - struct dm_gpio_ops *ops = gpio_get_ops(dev); + const struct dm_gpio_ops *ops = gpio_get_ops(dev); struct gpio_dev_priv *priv; char *str = buf; int func; @@ -862,7 +918,7 @@ int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) #if CONFIG_IS_ENABLED(ACPIGEN) int gpio_get_acpi(const struct gpio_desc *desc, struct acpi_gpio *gpio) { - struct dm_gpio_ops *ops; + const struct dm_gpio_ops *ops; memset(gpio, '\0', sizeof(*gpio)); if (!dm_gpio_is_valid(desc)) { @@ -949,6 +1005,71 @@ int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count) return vector; } +int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list, + int count) +{ + static const char tristate[] = "01z"; + enum { + PULLUP, + PULLDOWN, + + NUM_OPTIONS, + }; + int vals[NUM_OPTIONS]; + uint mask; + uint vector = 0; + int ret, i; + + /* + * Limit to 19 digits which should be plenty. This avoids overflow of a + * 32-bit int + */ + assert(count < 20); + + for (i = 0; i < NUM_OPTIONS; i++) { + uint flags = GPIOD_IS_IN; + + flags |= (i == PULLDOWN) ? GPIOD_PULL_DOWN : GPIOD_PULL_UP; + ret = dm_gpios_clrset_flags(desc_list, count, GPIOD_MASK_PULL, + flags); + if (ret) + return log_msg_ret("pu", ret); + + /* Give the lines time to settle */ + udelay(10); + + ret = dm_gpio_get_values_as_int(desc_list, count); + if (ret < 0) + return log_msg_ret("get1", ret); + vals[i] = ret; + } + + log_debug("values: %x %x, count = %d\n", vals[0], vals[1], count); + for (i = count - 1, mask = 1 << i; i >= 0; i--, mask >>= 1) { + uint pd = vals[PULLDOWN] & mask ? 1 : 0; + uint pu = vals[PULLUP] & mask ? 1 : 0; + uint digit; + + /* + * Get value with internal pulldown active. If this is 1 then + * there is a stronger external pullup, which we call 1. If not + * then call it 0. + * + * If the values differ then the pin is floating so we call + * this a 2. + */ + if (pu == pd) + digit = pd; + else + digit = 2; + log_debug("%c ", tristate[digit]); + vector = 3 * vector + digit; + } + log_debug("vector=%d\n", vector); + + return vector; +} + /** * gpio_request_tail: common work for requesting a gpio. * @@ -1011,7 +1132,10 @@ static int gpio_request_tail(int ret, const char *nodename, debug("%s: dm_gpio_requestf failed\n", __func__); goto err; } - ret = dm_gpio_set_dir_flags(desc, flags); + + /* Keep any direction flags provided by the devicetree */ + ret = dm_gpio_set_dir_flags(desc, + flags | (desc->flags & GPIOD_MASK_DIR)); if (ret) { debug("%s: dm_gpio_set_dir failed\n", __func__); goto err; @@ -1024,6 +1148,7 @@ err: return ret; } +#if !CONFIG_IS_ENABLED(OF_PLATDATA) static int _gpio_request_by_name_nodev(ofnode node, const char *list_name, int index, struct gpio_desc *desc, int flags, bool add_index) @@ -1110,6 +1235,7 @@ int gpio_get_list_count(struct udevice *dev, const char *list_name) return ret; } +#endif /* OF_PLATDATA */ int dm_gpio_free(struct udevice *dev, struct gpio_desc *desc) { @@ -1306,10 +1432,10 @@ static int gpio_post_bind(struct udevice *dev) ops->get_function += gd->reloc_off; if (ops->xlate) ops->xlate += gd->reloc_off; - if (ops->set_dir_flags) - ops->set_dir_flags += gd->reloc_off; - if (ops->get_dir_flags) - ops->get_dir_flags += gd->reloc_off; + if (ops->set_flags) + ops->set_flags += gd->reloc_off; + if (ops->get_flags) + ops->get_flags += gd->reloc_off; reloc_done++; } diff --git a/drivers/gpio/intel_gpio.c b/drivers/gpio/intel_gpio.c index eda95485c9..ab46a94dbc 100644 --- a/drivers/gpio/intel_gpio.c +++ b/drivers/gpio/intel_gpio.c @@ -3,6 +3,8 @@ * Copyright 2019 Google LLC */ +#define LOG_CATEGORY UCLASS_GPIO + #include <common.h> #include <dm.h> #include <errno.h> @@ -23,38 +25,6 @@ #include <dm/acpi.h> #include <dt-bindings/gpio/x86-gpio.h> -static int intel_gpio_direction_input(struct udevice *dev, uint offset) -{ - struct udevice *pinctrl = dev_get_parent(dev); - uint config_offset; - - config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset); - - pcr_clrsetbits32(pinctrl, config_offset, - PAD_CFG0_MODE_MASK | PAD_CFG0_TX_STATE | - PAD_CFG0_RX_DISABLE, - PAD_CFG0_MODE_GPIO | PAD_CFG0_TX_DISABLE); - - return 0; -} - -static int intel_gpio_direction_output(struct udevice *dev, uint offset, - int value) -{ - struct udevice *pinctrl = dev_get_parent(dev); - uint config_offset; - - config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset); - - pcr_clrsetbits32(pinctrl, config_offset, - PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE | - PAD_CFG0_TX_DISABLE | PAD_CFG0_TX_STATE, - PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE | - (value ? PAD_CFG0_TX_STATE : 0)); - - return 0; -} - static int intel_gpio_get_value(struct udevice *dev, uint offset) { struct udevice *pinctrl = dev_get_parent(dev); @@ -130,6 +100,41 @@ static int intel_gpio_xlate(struct udevice *orig_dev, struct gpio_desc *desc, return 0; } +static int intel_gpio_set_flags(struct udevice *dev, unsigned int offset, + ulong flags) +{ + struct udevice *pinctrl = dev_get_parent(dev); + u32 bic0 = 0, bic1 = 0; + u32 or0, or1; + uint config_offset; + + config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset); + + if (flags & GPIOD_IS_OUT) { + bic0 |= PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE | + PAD_CFG0_TX_DISABLE; + or0 |= PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE; + } else if (flags & GPIOD_IS_IN) { + bic0 |= PAD_CFG0_MODE_MASK | PAD_CFG0_TX_STATE | + PAD_CFG0_RX_DISABLE; + or0 |= PAD_CFG0_MODE_GPIO | PAD_CFG0_TX_DISABLE; + } + if (flags & GPIOD_PULL_UP) { + bic1 |= PAD_CFG1_PULL_MASK; + or1 |= PAD_CFG1_PULL_UP_20K; + } else if (flags & GPIOD_PULL_DOWN) { + bic1 |= PAD_CFG1_PULL_MASK; + or1 |= PAD_CFG1_PULL_DN_20K; + } + + pcr_clrsetbits32(pinctrl, PAD_CFG0_OFFSET(config_offset), bic0, or0); + pcr_clrsetbits32(pinctrl, PAD_CFG1_OFFSET(config_offset), bic1, or1); + log_debug("%s: flags=%lx, offset=%x, config_offset=%x, %x/%x %x/%x\n", + dev->name, flags, offset, config_offset, bic0, or0, bic1, or1); + + return 0; +} + #if CONFIG_IS_ENABLED(ACPIGEN) static int intel_gpio_get_acpi(const struct gpio_desc *desc, struct acpi_gpio *gpio) @@ -177,12 +182,11 @@ static int intel_gpio_of_to_plat(struct udevice *dev) } static const struct dm_gpio_ops gpio_intel_ops = { - .direction_input = intel_gpio_direction_input, - .direction_output = intel_gpio_direction_output, .get_value = intel_gpio_get_value, .set_value = intel_gpio_set_value, .get_function = intel_gpio_get_function, .xlate = intel_gpio_xlate, + .set_flags = intel_gpio_set_flags, #if CONFIG_IS_ENABLED(ACPIGEN) .get_acpi = intel_gpio_get_acpi, #endif diff --git a/drivers/gpio/sandbox.c b/drivers/gpio/sandbox.c index dc8d506e8d..d008fdd222 100644 --- a/drivers/gpio/sandbox.c +++ b/drivers/gpio/sandbox.c @@ -19,42 +19,51 @@ #include <dt-bindings/gpio/gpio.h> #include <dt-bindings/gpio/sandbox-gpio.h> - struct gpio_state { const char *label; /* label given by requester */ - ulong dir_flags; /* dir_flags (GPIOD_...) */ + ulong flags; /* flags (GPIOD_...) */ }; -/* Access routines for GPIO dir flags */ -static ulong *get_gpio_dir_flags(struct udevice *dev, unsigned int offset) +/* Access routines for GPIO info */ +static struct gpio_state *get_gpio_state(struct udevice *dev, uint offset) { struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); struct gpio_state *state = dev_get_priv(dev); if (offset >= uc_priv->gpio_count) { - static ulong invalid_dir_flags; printf("sandbox_gpio: error: invalid gpio %u\n", offset); - return &invalid_dir_flags; + return NULL; } - return &state[offset].dir_flags; + return &state[offset]; +} + +/* Access routines for GPIO flags */ +static ulong *get_gpio_flags(struct udevice *dev, unsigned int offset) +{ + struct gpio_state *state = get_gpio_state(dev, offset); + + if (!state) + return NULL; + + return &state->flags; } static int get_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag) { - return (*get_gpio_dir_flags(dev, offset) & flag) != 0; + return (*get_gpio_flags(dev, offset) & flag) != 0; } static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag, int value) { - ulong *gpio = get_gpio_dir_flags(dev, offset); + struct gpio_state *state = get_gpio_state(dev, offset); if (value) - *gpio |= flag; + state->flags |= flag; else - *gpio &= ~flag; + state->flags &= ~flag; return 0; } @@ -65,14 +74,31 @@ static int set_gpio_flag(struct udevice *dev, unsigned int offset, ulong flag, int sandbox_gpio_get_value(struct udevice *dev, unsigned offset) { + struct gpio_state *state = get_gpio_state(dev, offset); + bool val; + if (get_gpio_flag(dev, offset, GPIOD_IS_OUT)) debug("sandbox_gpio: get_value on output gpio %u\n", offset); - return get_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE); + + if (state->flags & GPIOD_EXT_DRIVEN) { + val = state->flags & GPIOD_EXT_HIGH; + } else { + if (state->flags & GPIOD_EXT_PULL_UP) + val = true; + else if (state->flags & GPIOD_EXT_PULL_DOWN) + val = false; + else + val = state->flags & GPIOD_PULL_UP; + } + + return val; } int sandbox_gpio_set_value(struct udevice *dev, unsigned offset, int value) { - return set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE, value); + set_gpio_flag(dev, offset, GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value); + + return 0; } int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset) @@ -83,20 +109,23 @@ int sandbox_gpio_get_direction(struct udevice *dev, unsigned offset) int sandbox_gpio_set_direction(struct udevice *dev, unsigned offset, int output) { set_gpio_flag(dev, offset, GPIOD_IS_OUT, output); - set_gpio_flag(dev, offset, GPIOD_IS_IN, !(output)); + set_gpio_flag(dev, offset, GPIOD_IS_IN, !output); return 0; } -ulong sandbox_gpio_get_dir_flags(struct udevice *dev, unsigned int offset) +ulong sandbox_gpio_get_flags(struct udevice *dev, uint offset) { - return *get_gpio_dir_flags(dev, offset); + ulong flags = *get_gpio_flags(dev, offset); + + return flags & ~GPIOD_SANDBOX_MASK; } -int sandbox_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, - ulong flags) +int sandbox_gpio_set_flags(struct udevice *dev, uint offset, ulong flags) { - *get_gpio_dir_flags(dev, offset) = flags; + struct gpio_state *state = get_gpio_state(dev, offset); + + state->flags = flags; return 0; } @@ -117,10 +146,19 @@ static int sb_gpio_direction_input(struct udevice *dev, unsigned offset) static int sb_gpio_direction_output(struct udevice *dev, unsigned offset, int value) { + int ret; + debug("%s: offset:%u, value = %d\n", __func__, offset, value); - return sandbox_gpio_set_direction(dev, offset, 1) | - sandbox_gpio_set_value(dev, offset, value); + ret = sandbox_gpio_set_direction(dev, offset, 1); + if (ret) + return ret; + ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | + GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value); + if (ret) + return ret; + + return 0; } /* read GPIO IN value of port 'offset' */ @@ -134,6 +172,8 @@ static int sb_gpio_get_value(struct udevice *dev, unsigned offset) /* write GPIO OUT value to port 'offset' */ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value) { + int ret; + debug("%s: offset:%u, value = %d\n", __func__, offset, value); if (!sandbox_gpio_get_direction(dev, offset)) { @@ -142,7 +182,12 @@ static int sb_gpio_set_value(struct udevice *dev, unsigned offset, int value) return -1; } - return sandbox_gpio_set_value(dev, offset, value); + ret = set_gpio_flag(dev, offset, GPIOD_IS_OUT_ACTIVE | + GPIOD_EXT_DRIVEN | GPIOD_EXT_HIGH, value); + if (ret) + return ret; + + return 0; } static int sb_gpio_get_function(struct udevice *dev, unsigned offset) @@ -177,33 +222,30 @@ static int sb_gpio_xlate(struct udevice *dev, struct gpio_desc *desc, return 0; } -static int sb_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, - ulong flags) +static int sb_gpio_set_flags(struct udevice *dev, unsigned int offset, + ulong flags) { - ulong *dir_flags; - - debug("%s: offset:%u, dir_flags = %lx\n", __func__, offset, flags); - - dir_flags = get_gpio_dir_flags(dev, offset); - - /* - * For testing purposes keep the output value when switching to input. - * This allows us to manipulate the input value via the gpio command. - */ - if (flags & GPIOD_IS_IN) - *dir_flags = (flags & ~GPIOD_IS_OUT_ACTIVE) | - (*dir_flags & GPIOD_IS_OUT_ACTIVE); - else - *dir_flags = flags; + debug("%s: offset:%u, flags = %lx\n", __func__, offset, flags); + struct gpio_state *state = get_gpio_state(dev, offset); + + if (flags & GPIOD_IS_OUT) { + flags |= GPIOD_EXT_DRIVEN; + if (flags & GPIOD_IS_OUT_ACTIVE) + flags |= GPIOD_EXT_HIGH; + else + flags &= ~GPIOD_EXT_HIGH; + } else { + flags |= state->flags & GPIOD_SANDBOX_MASK; + } + state->flags = flags; return 0; } -static int sb_gpio_get_dir_flags(struct udevice *dev, unsigned int offset, - ulong *flags) +static int sb_gpio_get_flags(struct udevice *dev, uint offset, ulong *flagsp) { debug("%s: offset:%u\n", __func__, offset); - *flags = *get_gpio_dir_flags(dev, offset); + *flagsp = *get_gpio_flags(dev, offset) & ~GPIOD_SANDBOX_MASK; return 0; } @@ -272,8 +314,8 @@ static const struct dm_gpio_ops gpio_sandbox_ops = { .set_value = sb_gpio_set_value, .get_function = sb_gpio_get_function, .xlate = sb_gpio_xlate, - .set_dir_flags = sb_gpio_set_dir_flags, - .get_dir_flags = sb_gpio_get_dir_flags, + .set_flags = sb_gpio_set_flags, + .get_flags = sb_gpio_get_flags, #if CONFIG_IS_ENABLED(ACPIGEN) .get_acpi = sb_gpio_get_acpi, #endif @@ -456,7 +498,7 @@ static const char *sb_pinctrl_get_pin_name(struct udevice *dev, return pin_name; } -static char *get_dir_flags_string(ulong flags) +static char *get_flags_string(ulong flags) { if (flags & GPIOD_OPEN_DRAIN) return "drive-open-drain"; @@ -475,7 +517,7 @@ static int sb_pinctrl_get_pin_muxing(struct udevice *dev, { struct udevice *gpio_dev; unsigned int gpio_idx; - ulong dir_flags; + ulong flags; int function; /* look up for the bank which owns the requested pin */ @@ -484,11 +526,11 @@ static int sb_pinctrl_get_pin_muxing(struct udevice *dev, snprintf(buf, size, "Error"); } else { function = sb_gpio_get_function(gpio_dev, gpio_idx); - dir_flags = *get_gpio_dir_flags(gpio_dev, gpio_idx); + flags = *get_gpio_flags(gpio_dev, gpio_idx); snprintf(buf, size, "gpio %s %s", function == GPIOF_OUTPUT ? "output" : "input", - get_dir_flags_string(dir_flags)); + get_flags_string(flags)); } return 0; diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c index 7184db3c52..125c237551 100644 --- a/drivers/gpio/stm32_gpio.c +++ b/drivers/gpio/stm32_gpio.c @@ -191,8 +191,8 @@ static int stm32_gpio_get_function(struct udevice *dev, unsigned int offset) return GPIOF_FUNC; } -static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, - ulong flags) +static int stm32_gpio_set_flags(struct udevice *dev, unsigned int offset, + ulong flags) { struct stm32_gpio_priv *priv = dev_get_priv(dev); struct stm32_gpio_regs *regs = priv->regs; @@ -203,12 +203,13 @@ static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, return idx; if (flags & GPIOD_IS_OUT) { - int value = GPIOD_FLAGS_OUTPUT(flags); + bool value = flags & GPIOD_IS_OUT_ACTIVE; if (flags & GPIOD_OPEN_DRAIN) stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_OD); else stm32_gpio_set_otype(regs, idx, STM32_GPIO_OTYPE_PP); + stm32_gpio_set_moder(regs, idx, STM32_GPIO_MODE_OUT); writel(BSRR_BIT(idx, value), ®s->bsrr); @@ -223,8 +224,8 @@ static int stm32_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, return 0; } -static int stm32_gpio_get_dir_flags(struct udevice *dev, unsigned int offset, - ulong *flags) +static int stm32_gpio_get_flags(struct udevice *dev, unsigned int offset, + ulong *flagsp) { struct stm32_gpio_priv *priv = dev_get_priv(dev); struct stm32_gpio_regs *regs = priv->regs; @@ -259,7 +260,7 @@ static int stm32_gpio_get_dir_flags(struct udevice *dev, unsigned int offset, default: break; } - *flags = dir_flags; + *flagsp = dir_flags; return 0; } @@ -270,8 +271,8 @@ static const struct dm_gpio_ops gpio_stm32_ops = { .get_value = stm32_gpio_get_value, .set_value = stm32_gpio_set_value, .get_function = stm32_gpio_get_function, - .set_dir_flags = stm32_gpio_set_dir_flags, - .get_dir_flags = stm32_gpio_get_dir_flags, + .set_flags = stm32_gpio_set_flags, + .get_flags = stm32_gpio_get_flags, }; static int gpio_stm32_probe(struct udevice *dev) diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c index 1a8d0a3a35..fe7a59d431 100644 --- a/drivers/pinctrl/pinctrl-stmfx.c +++ b/drivers/pinctrl/pinctrl-stmfx.c @@ -163,12 +163,14 @@ static int stmfx_gpio_direction_output(struct udevice *dev, return stmfx_write_reg(dev, STMFX_REG_GPIO_DIR, offset, 1); } -static int stmfx_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, - ulong flags) +static int stmfx_gpio_set_flags(struct udevice *dev, unsigned int offset, + ulong flags) { int ret = -ENOTSUPP; if (flags & GPIOD_IS_OUT) { + bool value = flags & GPIOD_IS_OUT_ACTIVE; + if (flags & GPIOD_OPEN_SOURCE) return -ENOTSUPP; if (flags & GPIOD_OPEN_DRAIN) @@ -177,8 +179,7 @@ static int stmfx_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, ret = stmfx_conf_set_type(dev, offset, 1); if (ret) return ret; - ret = stmfx_gpio_direction_output(dev, offset, - GPIOD_FLAGS_OUTPUT(flags)); + ret = stmfx_gpio_direction_output(dev, offset, value); } else if (flags & GPIOD_IS_IN) { ret = stmfx_gpio_direction_input(dev, offset); if (ret) @@ -199,8 +200,8 @@ static int stmfx_gpio_set_dir_flags(struct udevice *dev, unsigned int offset, return ret; } -static int stmfx_gpio_get_dir_flags(struct udevice *dev, unsigned int offset, - ulong *flags) +static int stmfx_gpio_get_flags(struct udevice *dev, unsigned int offset, + ulong *flagsp) { ulong dir_flags = 0; int ret; @@ -233,7 +234,7 @@ static int stmfx_gpio_get_dir_flags(struct udevice *dev, unsigned int offset, dir_flags |= GPIOD_PULL_DOWN; } } - *flags = dir_flags; + *flagsp = dir_flags; return 0; } @@ -266,8 +267,8 @@ static const struct dm_gpio_ops stmfx_gpio_ops = { .get_function = stmfx_gpio_get_function, .direction_input = stmfx_gpio_direction_input, .direction_output = stmfx_gpio_direction_output, - .set_dir_flags = stmfx_gpio_set_dir_flags, - .get_dir_flags = stmfx_gpio_get_dir_flags, + .set_flags = stmfx_gpio_set_flags, + .get_flags = stmfx_gpio_get_flags, }; U_BOOT_DRIVER(stmfx_gpio) = { diff --git a/drivers/sysreset/sysreset-uclass.c b/drivers/sysreset/sysreset-uclass.c index 6c9dc7a384..9512f6881f 100644 --- a/drivers/sysreset/sysreset-uclass.c +++ b/drivers/sysreset/sysreset-uclass.c @@ -113,7 +113,7 @@ void sysreset_walk_halt(enum sysreset_t type) /** * reset_cpu() - calls sysreset_walk(SYSRESET_WARM) */ -void reset_cpu(ulong addr) +void reset_cpu(void) { sysreset_walk_halt(SYSRESET_WARM); } diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig index 65622f30b1..d03028070b 100644 --- a/drivers/tee/optee/Kconfig +++ b/drivers/tee/optee/Kconfig @@ -31,6 +31,12 @@ config OPTEE_TA_RPC_TEST permits to test reverse RPC calls to TEE supplicant. Should be used only in sandbox env. +config OPTEE_TA_SCP03 + bool "Support SCP03 TA" + default y + help + Enables support for controlling (enabling, provisioning) the + Secure Channel Protocol 03 operation in the OP-TEE SCP03 TA. endmenu endif diff --git a/drivers/tee/sandbox.c b/drivers/tee/sandbox.c index 3a1d34d6fc..35e8542fa3 100644 --- a/drivers/tee/sandbox.c +++ b/drivers/tee/sandbox.c @@ -8,6 +8,7 @@ #include <tee.h> #include <tee/optee_ta_avb.h> #include <tee/optee_ta_rpc_test.h> +#include <tee/optee_ta_scp03.h> #include "optee/optee_msg.h" #include "optee/optee_private.h" @@ -68,6 +69,7 @@ void *optee_alloc_and_init_page_list(void *buf, ulong len, return NULL; } +#if defined(CONFIG_OPTEE_TA_SCP03) || defined(CONFIG_OPTEE_TA_AVB) static u32 get_attr(uint n, uint num_params, struct tee_param *params) { if (n >= num_params) @@ -79,7 +81,7 @@ static u32 get_attr(uint n, uint num_params, struct tee_param *params) static u32 check_params(u8 p0, u8 p1, u8 p2, u8 p3, uint num_params, struct tee_param *params) { - u8 p[] = { p0, p1, p2, p3}; + u8 p[] = { p0, p1, p2, p3 }; uint n; for (n = 0; n < ARRAY_SIZE(p); n++) @@ -97,6 +99,50 @@ bad_params: return TEE_ERROR_BAD_PARAMETERS; } +#endif + +#ifdef CONFIG_OPTEE_TA_SCP03 +static u32 pta_scp03_open_session(struct udevice *dev, uint num_params, + struct tee_param *params) +{ + /* + * We don't expect additional parameters when opening a session to + * this TA. + */ + return check_params(TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE, + TEE_PARAM_ATTR_TYPE_NONE, TEE_PARAM_ATTR_TYPE_NONE, + num_params, params); +} + +static u32 pta_scp03_invoke_func(struct udevice *dev, u32 func, uint num_params, + struct tee_param *params) +{ + u32 res; + static bool enabled; + + switch (func) { + case PTA_CMD_ENABLE_SCP03: + res = check_params(TEE_PARAM_ATTR_TYPE_VALUE_INPUT, + TEE_PARAM_ATTR_TYPE_NONE, + TEE_PARAM_ATTR_TYPE_NONE, + TEE_PARAM_ATTR_TYPE_NONE, + num_params, params); + if (res) + return res; + + if (!enabled) { + enabled = true; + } else { + } + + if (params[0].u.value.a) + + return TEE_SUCCESS; + default: + return TEE_ERROR_NOT_SUPPORTED; + } +} +#endif #ifdef CONFIG_OPTEE_TA_AVB static u32 ta_avb_open_session(struct udevice *dev, uint num_params, @@ -357,6 +403,12 @@ static const struct ta_entry ta_entries[] = { .invoke_func = ta_rpc_test_invoke_func, }, #endif +#ifdef CONFIG_OPTEE_TA_SCP03 + { .uuid = PTA_SCP03_UUID, + .open_session = pta_scp03_open_session, + .invoke_func = pta_scp03_invoke_func, + }, +#endif }; static void sandbox_tee_get_version(struct udevice *dev, diff --git a/drivers/tpm/Makefile b/drivers/tpm/Makefile index 8f075b9f45..f64d20067f 100644 --- a/drivers/tpm/Makefile +++ b/drivers/tpm/Makefile @@ -10,7 +10,7 @@ obj-$(CONFIG_TPM_TIS_SANDBOX) += tpm_tis_sandbox.o obj-$(CONFIG_TPM_ST33ZP24_I2C) += tpm_tis_st33zp24_i2c.o obj-$(CONFIG_TPM_ST33ZP24_SPI) += tpm_tis_st33zp24_spi.o -obj-$(CONFIG_TPM2_CR50_I2C) += cr50_i2c.o +obj-$(CONFIG_$(SPL_TPL_)TPM2_CR50_I2C) += cr50_i2c.o obj-$(CONFIG_TPM2_TIS_SANDBOX) += tpm2_tis_sandbox.o obj-$(CONFIG_TPM2_TIS_SPI) += tpm2_tis_spi.o obj-$(CONFIG_TPM2_FTPM_TEE) += tpm2_ftpm_tee.o diff --git a/drivers/tpm/cr50_i2c.c b/drivers/tpm/cr50_i2c.c index b103a6fdc3..76432bdec1 100644 --- a/drivers/tpm/cr50_i2c.c +++ b/drivers/tpm/cr50_i2c.c @@ -309,7 +309,7 @@ static int cr50_i2c_recv(struct udevice *dev, u8 *buf, size_t buf_len) int status; int ret; - log_debug("%s: len=%x\n", __func__, buf_len); + log_debug("%s: buf_len=%x\n", __func__, buf_len); if (buf_len < TPM_HEADER_SIZE) return -E2BIG; @@ -386,7 +386,7 @@ static int cr50_i2c_send(struct udevice *dev, const u8 *buf, size_t len) ulong timeout; int ret; - log_debug("%s: len=%x\n", __func__, len); + log_debug("len=%x\n", len); timeout = timer_get_us() + TIMEOUT_LONG_US; do { ret = cr50_i2c_status(dev); diff --git a/drivers/tpm/tpm-uclass.c b/drivers/tpm/tpm-uclass.c index beb0fa3f93..35774a6289 100644 --- a/drivers/tpm/tpm-uclass.c +++ b/drivers/tpm/tpm-uclass.c @@ -4,6 +4,8 @@ * Written by Simon Glass <sjg@chromium.org> */ +#define LOG_CATEGORY UCLASS_TPM + #include <common.h> #include <dm.h> #include <log.h> @@ -87,15 +89,15 @@ int tpm_xfer(struct udevice *dev, const uint8_t *sendbuf, size_t send_size, ordinal = get_unaligned_be32(sendbuf + TPM_CMD_ORDINAL_BYTE); if (count == 0) { - debug("no data\n"); + log_debug("no data\n"); return -ENODATA; } if (count > send_size) { - debug("invalid count value %x %zx\n", count, send_size); + log_debug("invalid count value %x %zx\n", count, send_size); return -E2BIG; } - debug("%s: Calling send\n", __func__); + log_debug("%s: Calling send\n", __func__); ret = ops->send(dev, sendbuf, send_size); if (ret < 0) return ret; diff --git a/drivers/tpm/tpm2_tis_sandbox.c b/drivers/tpm/tpm2_tis_sandbox.c index c74bacfd71..24c804a564 100644 --- a/drivers/tpm/tpm2_tis_sandbox.c +++ b/drivers/tpm/tpm2_tis_sandbox.c @@ -285,7 +285,7 @@ static int sandbox_tpm2_xfer(struct udevice *dev, const u8 *sendbuf, length = get_unaligned_be32(sent); sent += sizeof(length); if (length != send_size) { - printf("TPM2: Unmatching length, received: %ld, expected: %d\n", + printf("TPM2: Unmatching length, received: %zd, expected: %d\n", send_size, length); rc = TPM2_RC_SIZE; sandbox_tpm2_fill_buf(recv, recv_len, tag, rc); diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c index f52aba4d21..4361a58cd7 100644 --- a/drivers/video/sunxi/sunxi_display.c +++ b/drivers/video/sunxi/sunxi_display.c @@ -7,6 +7,8 @@ */ #include <common.h> +#include <display.h> +#include <dm.h> #include <cpu_func.h> #include <efi_loader.h> #include <init.h> @@ -28,7 +30,9 @@ #include <fdt_support.h> #include <i2c.h> #include <malloc.h> +#include <video.h> #include <video_fb.h> +#include <dm/uclass-internal.h> #include "../videomodes.h" #include "../anx9804.h" #include "../hitachi_tx18d42vm_lcd.h" @@ -45,6 +49,11 @@ DECLARE_GLOBAL_DATA_PTR; +/* Maximum LCD size we support */ +#define LCD_MAX_WIDTH 3840 +#define LCD_MAX_HEIGHT 2160 +#define LCD_MAX_LOG2_BPP VIDEO_BPP32 + enum sunxi_monitor { sunxi_monitor_none, sunxi_monitor_dvi, @@ -58,13 +67,12 @@ enum sunxi_monitor { }; #define SUNXI_MONITOR_LAST sunxi_monitor_composite_pal_nc -struct sunxi_display { - GraphicDevice graphic_device; +struct sunxi_display_priv { enum sunxi_monitor monitor; unsigned int depth; unsigned int fb_addr; unsigned int fb_size; -} sunxi_display; +}; const struct ctfb_res_modes composite_video_modes[2] = { /* x y hz pixclk ps/kHz le ri up lo hs vs s vmode */ @@ -214,7 +222,8 @@ static int sunxi_hdmi_edid_get_block(int block, u8 *buf) return r; } -static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode, +static int sunxi_hdmi_edid_get_mode(struct sunxi_display_priv *sunxi_display, + struct ctfb_res_modes *mode, bool verbose_mode) { struct edid1_info edid1; @@ -291,14 +300,14 @@ static int sunxi_hdmi_edid_get_mode(struct ctfb_res_modes *mode, } /* Check for basic audio support, if found enable hdmi output */ - sunxi_display.monitor = sunxi_monitor_dvi; + sunxi_display->monitor = sunxi_monitor_dvi; for (i = 0; i < ext_blocks; i++) { if (cea681[i].extension_tag != EDID_CEA861_EXTENSION_TAG || cea681[i].revision < 2) continue; if (EDID_CEA861_SUPPORTS_BASIC_AUDIO(cea681[i])) - sunxi_display.monitor = sunxi_monitor_hdmi; + sunxi_display->monitor = sunxi_monitor_hdmi; } return 0; @@ -414,9 +423,9 @@ static void sunxi_frontend_mode_set(const struct ctfb_res_modes *mode, static void sunxi_frontend_enable(void) {} #endif -static bool sunxi_is_composite(void) +static bool sunxi_is_composite(enum sunxi_monitor monitor) { - switch (sunxi_display.monitor) { + switch (monitor) { case sunxi_monitor_none: case sunxi_monitor_dvi: case sunxi_monitor_hdmi: @@ -473,7 +482,8 @@ static const u32 sunxi_rgb2yuv_coef[12] = { }; static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode, - unsigned int address) + unsigned int address, + enum sunxi_monitor monitor) { struct sunxi_de_be_reg * const de_be = (struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE; @@ -502,7 +512,7 @@ static void sunxi_composer_mode_set(const struct ctfb_res_modes *mode, #endif SUNXI_DE_BE_MODE_INTERLACE_ENABLE); - if (sunxi_is_composite()) { + if (sunxi_is_composite(monitor)) { writel(SUNXI_DE_BE_OUTPUT_COLOR_CTRL_ENABLE, &de_be->output_color_ctrl); for (i = 0; i < 12; i++) @@ -616,7 +626,8 @@ static void sunxi_lcdc_backlight_enable(void) gpio_direction_output(pin, PWM_ON); } -static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode, +static void sunxi_lcdc_tcon0_mode_set(struct sunxi_display_priv *sunxi_display, + const struct ctfb_res_modes *mode, bool for_ext_vga_dac) { struct sunxi_lcdc_reg * const lcdc = @@ -643,17 +654,18 @@ static void sunxi_lcdc_tcon0_mode_set(const struct ctfb_res_modes *mode, } lcdc_pll_set(ccm, 0, mode->pixclock_khz, &clk_div, &clk_double, - sunxi_is_composite()); + sunxi_is_composite(sunxi_display->monitor)); video_ctfb_mode_to_display_timing(mode, &timing); lcdc_tcon0_mode_set(lcdc, &timing, clk_div, for_ext_vga_dac, - sunxi_display.depth, CONFIG_VIDEO_LCD_DCLK_PHASE); + sunxi_display->depth, CONFIG_VIDEO_LCD_DCLK_PHASE); } #if defined CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode, int *clk_div, int *clk_double, - bool use_portd_hvsync) + bool use_portd_hvsync, + enum sunxi_monitor monitor) { struct sunxi_lcdc_reg * const lcdc = (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; @@ -663,7 +675,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode, video_ctfb_mode_to_display_timing(mode, &timing); lcdc_tcon1_mode_set(lcdc, &timing, use_portd_hvsync, - sunxi_is_composite()); + sunxi_is_composite(monitor)); if (use_portd_hvsync) { sunxi_gpio_set_cfgpin(SUNXI_GPD(26), SUNXI_GPD_LCD0); @@ -671,7 +683,7 @@ static void sunxi_lcdc_tcon1_mode_set(const struct ctfb_res_modes *mode, } lcdc_pll_set(ccm, 1, mode->pixclock_khz, clk_div, clk_double, - sunxi_is_composite()); + sunxi_is_composite(monitor)); } #endif /* CONFIG_VIDEO_HDMI || defined CONFIG_VIDEO_VGA || CONFIG_VIDEO_COMPOSITE */ @@ -725,7 +737,8 @@ static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode) } static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode, - int clk_div, int clk_double) + int clk_div, int clk_double, + enum sunxi_monitor monitor) { struct sunxi_hdmi_reg * const hdmi = (struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE; @@ -734,7 +747,7 @@ static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode, /* Write clear interrupt status bits */ writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq); - if (sunxi_display.monitor == sunxi_monitor_hdmi) + if (monitor == sunxi_monitor_hdmi) sunxi_hdmi_setup_info_frames(mode); /* Set input sync enable */ @@ -789,7 +802,7 @@ static void sunxi_hdmi_enable(void) #if defined CONFIG_VIDEO_VGA || defined CONFIG_VIDEO_COMPOSITE -static void sunxi_tvencoder_mode_set(void) +static void sunxi_tvencoder_mode_set(enum sunxi_monitor monitor) { struct sunxi_ccm_reg * const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; @@ -801,7 +814,7 @@ static void sunxi_tvencoder_mode_set(void) /* Clock on */ setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TVE0); - switch (sunxi_display.monitor) { + switch (monitor) { case sunxi_monitor_vga: tvencoder_mode_set(tve, tve_mode_vga); break; @@ -896,26 +909,28 @@ static void sunxi_engines_init(void) sunxi_drc_init(); } -static void sunxi_mode_set(const struct ctfb_res_modes *mode, +static void sunxi_mode_set(struct sunxi_display_priv *sunxi_display, + const struct ctfb_res_modes *mode, unsigned int address) { + enum sunxi_monitor monitor = sunxi_display->monitor; int __maybe_unused clk_div, clk_double; struct sunxi_lcdc_reg * const lcdc = (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; struct sunxi_tve_reg * __maybe_unused const tve = (struct sunxi_tve_reg *)SUNXI_TVE0_BASE; - switch (sunxi_display.monitor) { + switch (sunxi_display->monitor) { case sunxi_monitor_none: break; case sunxi_monitor_dvi: case sunxi_monitor_hdmi: #ifdef CONFIG_VIDEO_HDMI - sunxi_composer_mode_set(mode, address); - sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0); - sunxi_hdmi_mode_set(mode, clk_div, clk_double); + sunxi_composer_mode_set(mode, address, monitor); + sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0, monitor); + sunxi_hdmi_mode_set(mode, clk_div, clk_double, monitor); sunxi_composer_enable(); - lcdc_enable(lcdc, sunxi_display.depth); + lcdc_enable(lcdc, sunxi_display->depth); sunxi_hdmi_enable(); #endif break; @@ -930,7 +945,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode, axp_set_eldo(3, 1800); anx9804_init(CONFIG_VIDEO_LCD_I2C_BUS, 4, ANX9804_DATA_RATE_1620M, - sunxi_display.depth); + sunxi_display->depth); } if (IS_ENABLED(CONFIG_VIDEO_LCD_HITACHI_TX18D42VM)) { mdelay(50); /* Wait for lcd controller power on */ @@ -942,10 +957,10 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode, i2c_reg_write(0x5c, 0x04, 0x42); /* Turn on the LCD */ i2c_set_bus_num(orig_i2c_bus); } - sunxi_composer_mode_set(mode, address); - sunxi_lcdc_tcon0_mode_set(mode, false); + sunxi_composer_mode_set(mode, address, monitor); + sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, false); sunxi_composer_enable(); - lcdc_enable(lcdc, sunxi_display.depth); + lcdc_enable(lcdc, sunxi_display->depth); #ifdef CONFIG_VIDEO_LCD_SSD2828 sunxi_ssd2828_init(mode); #endif @@ -953,17 +968,17 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode, break; case sunxi_monitor_vga: #ifdef CONFIG_VIDEO_VGA - sunxi_composer_mode_set(mode, address); - sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1); - sunxi_tvencoder_mode_set(); + sunxi_composer_mode_set(mode, address, monitor); + sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 1, monitor); + sunxi_tvencoder_mode_set(monitor); sunxi_composer_enable(); - lcdc_enable(lcdc, sunxi_display.depth); + lcdc_enable(lcdc, sunxi_display->depth); tvencoder_enable(tve); #elif defined CONFIG_VIDEO_VGA_VIA_LCD - sunxi_composer_mode_set(mode, address); - sunxi_lcdc_tcon0_mode_set(mode, true); + sunxi_composer_mode_set(mode, address, monitor); + sunxi_lcdc_tcon0_mode_set(sunxi_display, mode, true); sunxi_composer_enable(); - lcdc_enable(lcdc, sunxi_display.depth); + lcdc_enable(lcdc, sunxi_display->depth); sunxi_vga_external_dac_enable(); #endif break; @@ -972,11 +987,11 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode, case sunxi_monitor_composite_pal_m: case sunxi_monitor_composite_pal_nc: #ifdef CONFIG_VIDEO_COMPOSITE - sunxi_composer_mode_set(mode, address); - sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0); - sunxi_tvencoder_mode_set(); + sunxi_composer_mode_set(mode, address, monitor); + sunxi_lcdc_tcon1_mode_set(mode, &clk_div, &clk_double, 0, monitor); + sunxi_tvencoder_mode_set(monitor); sunxi_composer_enable(); - lcdc_enable(lcdc, sunxi_display.depth); + lcdc_enable(lcdc, sunxi_display->depth); tvencoder_enable(tve); #endif break; @@ -999,11 +1014,6 @@ static const char *sunxi_get_mon_desc(enum sunxi_monitor monitor) } } -ulong board_get_usable_ram_top(ulong total_size) -{ - return gd->ram_top - CONFIG_SUNXI_MAX_FB_SIZE; -} - static bool sunxi_has_hdmi(void) { #ifdef CONFIG_VIDEO_HDMI @@ -1052,9 +1062,11 @@ static enum sunxi_monitor sunxi_get_default_mon(bool allow_hdmi) return sunxi_monitor_none; } -void *video_hw_init(void) +static int sunxi_de_probe(struct udevice *dev) { - static GraphicDevice *graphic_device = &sunxi_display.graphic_device; + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + struct video_uc_plat *plat = dev_get_uclass_plat(dev); + struct sunxi_display_priv *sunxi_display = dev_get_priv(dev); const struct ctfb_res_modes *mode; struct ctfb_res_modes custom; const char *options; @@ -1067,10 +1079,8 @@ void *video_hw_init(void) char mon[16]; char *lcd_mode = CONFIG_VIDEO_LCD_MODE; - memset(&sunxi_display, 0, sizeof(struct sunxi_display)); - video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode, - &sunxi_display.depth, &options); + &sunxi_display->depth, &options); #ifdef CONFIG_VIDEO_HDMI hpd = video_get_option_int(options, "hpd", 1); hpd_delay = video_get_option_int(options, "hpd_delay", 500); @@ -1078,35 +1088,35 @@ void *video_hw_init(void) #endif overscan_x = video_get_option_int(options, "overscan_x", -1); overscan_y = video_get_option_int(options, "overscan_y", -1); - sunxi_display.monitor = sunxi_get_default_mon(true); + sunxi_display->monitor = sunxi_get_default_mon(true); video_get_option_string(options, "monitor", mon, sizeof(mon), - sunxi_get_mon_desc(sunxi_display.monitor)); + sunxi_get_mon_desc(sunxi_display->monitor)); for (i = 0; i <= SUNXI_MONITOR_LAST; i++) { if (strcmp(mon, sunxi_get_mon_desc(i)) == 0) { - sunxi_display.monitor = i; + sunxi_display->monitor = i; break; } } if (i > SUNXI_MONITOR_LAST) printf("Unknown monitor: '%s', falling back to '%s'\n", - mon, sunxi_get_mon_desc(sunxi_display.monitor)); + mon, sunxi_get_mon_desc(sunxi_display->monitor)); #ifdef CONFIG_VIDEO_HDMI /* If HDMI/DVI is selected do HPD & EDID, and handle fallback */ - if (sunxi_display.monitor == sunxi_monitor_dvi || - sunxi_display.monitor == sunxi_monitor_hdmi) { + if (sunxi_display->monitor == sunxi_monitor_dvi || + sunxi_display->monitor == sunxi_monitor_hdmi) { /* Always call hdp_detect, as it also enables clocks, etc. */ hdmi_present = (sunxi_hdmi_hpd_detect(hpd_delay) == 1); if (hdmi_present && edid) { printf("HDMI connected: "); - if (sunxi_hdmi_edid_get_mode(&custom, true) == 0) + if (sunxi_hdmi_edid_get_mode(sunxi_display, &custom, true) == 0) mode = &custom; else hdmi_present = false; } /* Fall back to EDID in case HPD failed */ if (edid && !hdmi_present) { - if (sunxi_hdmi_edid_get_mode(&custom, false) == 0) { + if (sunxi_hdmi_edid_get_mode(sunxi_display, &custom, false) == 0) { mode = &custom; hdmi_present = true; } @@ -1114,38 +1124,39 @@ void *video_hw_init(void) /* Shut down when display was not found */ if ((hpd || edid) && !hdmi_present) { sunxi_hdmi_shutdown(); - sunxi_display.monitor = sunxi_get_default_mon(false); + sunxi_display->monitor = sunxi_get_default_mon(false); } /* else continue with hdmi/dvi without a cable connected */ } #endif - switch (sunxi_display.monitor) { + switch (sunxi_display->monitor) { case sunxi_monitor_none: - return NULL; + printf("Unknown monitor\n"); + return -EINVAL; case sunxi_monitor_dvi: case sunxi_monitor_hdmi: if (!sunxi_has_hdmi()) { printf("HDMI/DVI not supported on this board\n"); - sunxi_display.monitor = sunxi_monitor_none; - return NULL; + sunxi_display->monitor = sunxi_monitor_none; + return -EINVAL; } break; case sunxi_monitor_lcd: if (!sunxi_has_lcd()) { printf("LCD not supported on this board\n"); - sunxi_display.monitor = sunxi_monitor_none; - return NULL; + sunxi_display->monitor = sunxi_monitor_none; + return -EINVAL; } - sunxi_display.depth = video_get_params(&custom, lcd_mode); + sunxi_display->depth = video_get_params(&custom, lcd_mode); mode = &custom; break; case sunxi_monitor_vga: if (!sunxi_has_vga()) { printf("VGA not supported on this board\n"); - sunxi_display.monitor = sunxi_monitor_none; - return NULL; + sunxi_display->monitor = sunxi_monitor_none; + return -EINVAL; } - sunxi_display.depth = 18; + sunxi_display->depth = 18; break; case sunxi_monitor_composite_pal: case sunxi_monitor_composite_ntsc: @@ -1153,85 +1164,99 @@ void *video_hw_init(void) case sunxi_monitor_composite_pal_nc: if (!sunxi_has_composite()) { printf("Composite video not supported on this board\n"); - sunxi_display.monitor = sunxi_monitor_none; - return NULL; + sunxi_display->monitor = sunxi_monitor_none; + return -EINVAL; } - if (sunxi_display.monitor == sunxi_monitor_composite_pal || - sunxi_display.monitor == sunxi_monitor_composite_pal_nc) + if (sunxi_display->monitor == sunxi_monitor_composite_pal || + sunxi_display->monitor == sunxi_monitor_composite_pal_nc) mode = &composite_video_modes[0]; else mode = &composite_video_modes[1]; - sunxi_display.depth = 24; + sunxi_display->depth = 24; break; } /* Yes these defaults are quite high, overscan on composite sucks... */ if (overscan_x == -1) - overscan_x = sunxi_is_composite() ? 32 : 0; + overscan_x = sunxi_is_composite(sunxi_display->monitor) ? 32 : 0; if (overscan_y == -1) - overscan_y = sunxi_is_composite() ? 20 : 0; + overscan_y = sunxi_is_composite(sunxi_display->monitor) ? 20 : 0; - sunxi_display.fb_size = - (mode->xres * mode->yres * 4 + 0xfff) & ~0xfff; + sunxi_display->fb_size = plat->size; overscan_offset = (overscan_y * mode->xres + overscan_x) * 4; /* We want to keep the fb_base for simplefb page aligned, where as * the sunxi dma engines will happily accept an unaligned address. */ if (overscan_offset) - sunxi_display.fb_size += 0x1000; - - if (sunxi_display.fb_size > CONFIG_SUNXI_MAX_FB_SIZE) { - printf("Error need %dkB for fb, but only %dkB is reserved\n", - sunxi_display.fb_size >> 10, - CONFIG_SUNXI_MAX_FB_SIZE >> 10); - return NULL; - } + sunxi_display->fb_size += 0x1000; printf("Setting up a %dx%d%s %s console (overscan %dx%d)\n", mode->xres, mode->yres, (mode->vmode == FB_VMODE_INTERLACED) ? "i" : "", - sunxi_get_mon_desc(sunxi_display.monitor), + sunxi_get_mon_desc(sunxi_display->monitor), overscan_x, overscan_y); - gd->fb_base = gd->bd->bi_dram[0].start + - gd->bd->bi_dram[0].size - sunxi_display.fb_size; + sunxi_display->fb_addr = plat->base; sunxi_engines_init(); #ifdef CONFIG_EFI_LOADER - efi_add_memory_map(gd->fb_base, sunxi_display.fb_size, + efi_add_memory_map(sunxi_display->fb_addr, sunxi_display->fb_size, EFI_RESERVED_MEMORY_TYPE); #endif - fb_dma_addr = gd->fb_base - CONFIG_SYS_SDRAM_BASE; - sunxi_display.fb_addr = gd->fb_base; + fb_dma_addr = sunxi_display->fb_addr - CONFIG_SYS_SDRAM_BASE; if (overscan_offset) { fb_dma_addr += 0x1000 - (overscan_offset & 0xfff); - sunxi_display.fb_addr += (overscan_offset + 0xfff) & ~0xfff; - memset((void *)gd->fb_base, 0, sunxi_display.fb_size); - flush_cache(gd->fb_base, sunxi_display.fb_size); + sunxi_display->fb_addr += ALIGN(overscan_offset, 0x1000); + memset((void *)sunxi_display->fb_addr, 0, sunxi_display->fb_size); + flush_cache(sunxi_display->fb_addr, sunxi_display->fb_size); } - sunxi_mode_set(mode, fb_dma_addr); + sunxi_mode_set(sunxi_display, mode, fb_dma_addr); - /* - * These are the only members of this structure that are used. All the - * others are driver specific. The pitch is stored in plnSizeX. - */ - graphic_device->frameAdrs = sunxi_display.fb_addr; - graphic_device->gdfIndex = GDF_32BIT_X888RGB; - graphic_device->gdfBytesPP = 4; - graphic_device->winSizeX = mode->xres - 2 * overscan_x; - graphic_device->winSizeY = mode->yres - 2 * overscan_y; - graphic_device->plnSizeX = mode->xres * graphic_device->gdfBytesPP; - - return graphic_device; + /* The members of struct video_priv to be set by the driver. */ + uc_priv->bpix = VIDEO_BPP32; + uc_priv->xsize = mode->xres; + uc_priv->ysize = mode->yres; + + video_set_flush_dcache(dev, true); + + return 0; } +static int sunxi_de_bind(struct udevice *dev) +{ + struct video_uc_plat *plat = dev_get_uclass_plat(dev); + + plat->size = LCD_MAX_WIDTH * LCD_MAX_HEIGHT * VNBYTES(LCD_MAX_LOG2_BPP); + + return 0; +} + +static const struct video_ops sunxi_de_ops = { +}; + +U_BOOT_DRIVER(sunxi_de) = { + .name = "sunxi_de", + .id = UCLASS_VIDEO, + .ops = &sunxi_de_ops, + .bind = sunxi_de_bind, + .probe = sunxi_de_probe, + .priv_auto = sizeof(struct sunxi_display_priv), + .flags = DM_FLAG_PRE_RELOC, +}; + +U_BOOT_DRVINFO(sunxi_de) = { + .name = "sunxi_de" +}; + /* * Simplefb support. */ #if defined(CONFIG_OF_BOARD_SETUP) && defined(CONFIG_VIDEO_DT_SIMPLEFB) int sunxi_simplefb_setup(void *blob) { - static GraphicDevice *graphic_device = &sunxi_display.graphic_device; + struct sunxi_display_priv *sunxi_display; + struct video_priv *uc_priv; + struct udevice *de; int offset, ret; u64 start, size; const char *pipeline = NULL; @@ -1242,7 +1267,19 @@ int sunxi_simplefb_setup(void *blob) #define PIPELINE_PREFIX #endif - switch (sunxi_display.monitor) { + ret = uclass_find_device_by_name(UCLASS_VIDEO, "sunxi_de", &de); + if (ret) { + printf("DE not present\n"); + return 0; + } else if (!device_active(de)) { + printf("DE is present but not probed\n"); + return 0; + } + + uc_priv = dev_get_uclass_priv(de); + sunxi_display = dev_get_priv(de); + + switch (sunxi_display->monitor) { case sunxi_monitor_none: return 0; case sunxi_monitor_dvi: @@ -1280,16 +1317,17 @@ int sunxi_simplefb_setup(void *blob) * linux/arch/arm/mm/ioremap.c around line 301. */ start = gd->bd->bi_dram[0].start; - size = gd->bd->bi_dram[0].size - sunxi_display.fb_size; + size = sunxi_display->fb_addr - start; ret = fdt_fixup_memory_banks(blob, &start, &size, 1); if (ret) { eprintf("Cannot setup simplefb: Error reserving memory\n"); return ret; } - ret = fdt_setup_simplefb_node(blob, offset, sunxi_display.fb_addr, - graphic_device->winSizeX, graphic_device->winSizeY, - graphic_device->plnSizeX, "x8r8g8b8"); + ret = fdt_setup_simplefb_node(blob, offset, sunxi_display->fb_addr, + uc_priv->xsize, uc_priv->ysize, + VNBYTES(uc_priv->bpix) * uc_priv->xsize, + "x8r8g8b8"); if (ret) eprintf("Cannot setup simplefb: Error setting properties\n"); diff --git a/drivers/watchdog/imx_watchdog.c b/drivers/watchdog/imx_watchdog.c index 5e0a096ce5..3586246fbf 100644 --- a/drivers/watchdog/imx_watchdog.c +++ b/drivers/watchdog/imx_watchdog.c @@ -44,7 +44,7 @@ static void imx_watchdog_expire_now(struct watchdog_regs *wdog, bool ext_reset) #if !defined(CONFIG_IMX_WATCHDOG) || \ (defined(CONFIG_IMX_WATCHDOG) && !CONFIG_IS_ENABLED(WDT)) -void __attribute__((weak)) reset_cpu(ulong addr) +void __attribute__((weak)) reset_cpu(void) { struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR; diff --git a/drivers/watchdog/ulp_wdog.c b/drivers/watchdog/ulp_wdog.c index 7533fc612c..6f63b11b9f 100644 --- a/drivers/watchdog/ulp_wdog.c +++ b/drivers/watchdog/ulp_wdog.c @@ -77,7 +77,7 @@ void hw_watchdog_init(void) hw_watchdog_reset(); } -void reset_cpu(ulong addr) +void reset_cpu(void) { struct wdog_regs *wdog = (struct wdog_regs *)WDOG_BASE_ADDR; diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index b6a9991fc9..c24f5e0e97 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -410,6 +410,12 @@ struct global_data { * This value is used as logging level for continuation messages. */ int logl_prev; + /** + * @log_cont: Previous log line did not finished wtih \n + * + * This allows for chained log messages on the same line + */ + bool log_cont; #endif #if CONFIG_IS_ENABLED(BLOBLIST) /** diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 82294cbdc5..2cb0500aec 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -128,6 +128,12 @@ struct gpio_desc { #define GPIOD_PULL_UP BIT(7) /* GPIO has pull-up enabled */ #define GPIOD_PULL_DOWN BIT(8) /* GPIO has pull-down enabled */ +/* Flags for updating the above */ +#define GPIOD_MASK_DIR (GPIOD_IS_OUT | GPIOD_IS_IN | \ + GPIOD_IS_OUT_ACTIVE) +#define GPIOD_MASK_DSTYPE (GPIOD_OPEN_DRAIN | GPIOD_OPEN_SOURCE) +#define GPIOD_MASK_PULL (GPIOD_PULL_UP | GPIOD_PULL_DOWN) + uint offset; /* GPIO offset within the device */ /* * We could consider adding the GPIO label in here. Possibly we could @@ -135,12 +141,6 @@ struct gpio_desc { */ }; -/* helper to compute the value of the gpio output */ -#define GPIOD_FLAGS_OUTPUT_MASK (GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE) -#define GPIOD_FLAGS_OUTPUT(flags) \ - (((((flags) & GPIOD_FLAGS_OUTPUT_MASK) == GPIOD_IS_OUT_ACTIVE) || \ - (((flags) & GPIOD_FLAGS_OUTPUT_MASK) == GPIOD_ACTIVE_LOW))) - /** * dm_gpio_is_valid() - Check if a GPIO is valid * @@ -260,10 +260,32 @@ int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc, struct dm_gpio_ops { int (*request)(struct udevice *dev, unsigned offset, const char *label); int (*rfree)(struct udevice *dev, unsigned int offset); + + /** + * direction_input() - deprecated + * + * Equivalent to set_flags(...GPIOD_IS_IN) + */ int (*direction_input)(struct udevice *dev, unsigned offset); + + /** + * direction_output() - deprecated + * + * Equivalent to set_flags(...GPIOD_IS_OUT) with GPIOD_IS_OUT_ACTIVE + * also set if @value + */ int (*direction_output)(struct udevice *dev, unsigned offset, int value); + int (*get_value)(struct udevice *dev, unsigned offset); + + /** + * set_value() - Sets the GPIO value of an output + * + * If the driver provides an @set_flags() method then that is used + * in preference to this, with GPIOD_IS_OUT_ACTIVE set according to + * @value. + */ int (*set_value)(struct udevice *dev, unsigned offset, int value); /** * get_function() Get the GPIO function @@ -301,35 +323,54 @@ struct dm_gpio_ops { struct ofnode_phandle_args *args); /** - * set_dir_flags() - Set GPIO dir flags + * set_flags() - Adjust GPIO flags * * This function should set up the GPIO configuration according to the - * information provide by the direction flags bitfield. + * information provided by @flags. * - * This method is optional. + * If any flags cannot be set (e.g. the driver or hardware does not + * support them or this particular GPIO does not have the requested + * feature), the driver should return -EINVAL. + * + * The uclass checks that flags do not obviously conflict (e.g. input + * and output). If the driver finds other conflicts it should return + * -ERECALLCONFLICT + * + * Note that GPIOD_ACTIVE_LOW should be ignored, since the uclass + * adjusts for it automatically. For example, for an output GPIO, + * GPIOD_ACTIVE_LOW causes GPIOD_IS_OUT_ACTIVE to be inverted by the + * uclass, so the driver always sees the value that should be set at the + * pin (1=high, 0=low). + * + * This method is required and should be implemented by new drivers. At + * some point, it will supersede direction_input() and + * direction_output(), which wil be removed. * * @dev: GPIO device * @offset: GPIO offset within that device - * @flags: GPIO configuration to use - * @return 0 if OK, -ve on error + * @flags: New flags value (GPIOD_...) + * + * @return 0 if OK, -EINVAL if unsupported, -ERECALLCONFLICT if flags + * conflict in some * non-obvious way and were not applied, + * other -ve on error */ - int (*set_dir_flags)(struct udevice *dev, unsigned int offset, - ulong flags); + int (*set_flags)(struct udevice *dev, unsigned int offset, ulong flags); /** - * get_dir_flags() - Get GPIO dir flags + * get_flags() - Get GPIO flags * - * This function return the GPIO direction flags used. + * This function return the GPIO flags used. It should read this from + * the hardware directly. * * This method is optional. * * @dev: GPIO device * @offset: GPIO offset within that device - * @flags: place to put the used direction flags by GPIO + * @flagsp: place to put the current flags value * @return 0 if OK, -ve on error */ - int (*get_dir_flags)(struct udevice *dev, unsigned int offset, - ulong *flags); + int (*get_flags)(struct udevice *dev, unsigned int offset, + ulong *flagsp); #if CONFIG_IS_ENABLED(ACPIGEN) /** @@ -457,6 +498,31 @@ int gpio_get_values_as_int(const int *gpio_list); int dm_gpio_get_values_as_int(const struct gpio_desc *desc_list, int count); /** + * dm_gpio_get_values_as_int_base3() - Create a base-3 int from a list of GPIOs + * + * This uses pull-ups/pull-downs to figure out whether a GPIO line is externally + * pulled down, pulled up or floating. This allows three different strap values + * for each pin: + * 0 : external pull-down + * 1 : external pull-up + * 2 : floating + * + * With this it is possible to obtain more combinations from the same number of + * strapping pins, when compared to dm_gpio_get_values_as_int(). The external + * pull resistors should be made stronger that the internal SoC pull resistors, + * for this to work. + * + * With 2 pins, 6 combinations are possible, compared with 4 + * With 3 pins, 27 are possible, compared with 8 + * + * @desc_list: List of GPIOs to collect + * @count: Number of GPIOs + * @return resulting integer value, or -ve on error + */ +int dm_gpio_get_values_as_int_base3(struct gpio_desc *desc_list, + int count); + +/** * gpio_claim_vector() - claim a number of GPIOs for input * * @gpio_num_array: array of gpios to claim, terminated by -1 @@ -652,6 +718,25 @@ int dm_gpio_set_value(const struct gpio_desc *desc, int value); int dm_gpio_set_dir(struct gpio_desc *desc); /** + * dm_gpio_clrset_flags() - Update flags + * + * This updates the flags as directled. Note that desc->flags is updated by this + * function on success. If any changes cannot be made, best efforts are made. + * + * By use of @clr and @set any of flags can be individually updated, or left + * alone + * + * @desc: GPIO description containing device, offset and flags, + * previously returned by gpio_request_by_name() + * @clr: Flags to clear (GPIOD_...) + * @set: Flags to set (GPIOD_...) + * @return 0 if OK, -EINVAL if the flags had obvious conflicts, + * -ERECALLCONFLICT if there was a non-obvious hardware conflict when attempting + * to set the flags + */ +int dm_gpio_clrset_flags(struct gpio_desc *desc, ulong clr, ulong set); + +/** * dm_gpio_set_dir_flags() - Set direction using description and added flags * * This sets up the direction according to the provided flags and the GPIO @@ -666,16 +751,31 @@ int dm_gpio_set_dir(struct gpio_desc *desc); int dm_gpio_set_dir_flags(struct gpio_desc *desc, ulong flags); /** - * dm_gpio_get_dir_flags() - Get direction flags + * dm_gpios_clrset_flags() - Sets flags for a set of GPIOs + * + * This clears and sets flags individually for each GPIO. + * + * @desc: List of GPIOs to update + * @count: Number of GPIOs in the list + * @clr: Flags to clear (GPIOD_...), e.g. GPIOD_MASK_DIR if you are + * changing the direction + * @set: Flags to set (GPIOD_...) + * @return 0 if OK, -ve on error + */ +int dm_gpios_clrset_flags(struct gpio_desc *desc, int count, ulong clr, + ulong set); + +/** + * dm_gpio_get_flags() - Get flags * - * read the current direction flags + * Read the current flags * * @desc: GPIO description containing device, offset and flags, * previously returned by gpio_request_by_name() * @flags: place to put the used flags * @return 0 if OK, -ve on error, in which case desc->flags is not updated */ -int dm_gpio_get_dir_flags(struct gpio_desc *desc, ulong *flags); +int dm_gpio_get_flags(struct gpio_desc *desc, ulong *flags); /** * gpio_get_number() - Get the global GPIO number of a GPIO diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 7b602dd9ea..33a4d7b637 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -223,23 +223,6 @@ extern int soft_i2c_gpio_scl; #define CONFIG_VIDEO_LCD_I2C_BUS -1 /* NA, but necessary to compile */ #endif -#ifdef CONFIG_VIDEO_SUNXI -/* - * The amount of RAM to keep free at the top of RAM when relocating u-boot, - * to use as framebuffer. This must be a multiple of 4096. - */ -#define CONFIG_SUNXI_MAX_FB_SIZE (16 << 20) - -#define CONFIG_VIDEO_LOGO -#define CONFIG_VIDEO_STD_TIMINGS -#define CONFIG_I2C_EDID -#define VIDEO_LINE_LEN (pGD->plnSizeX) - -/* allow both serial and cfb console. */ -/* stop x86 thinking in cfbconsole from trying to init a pc keyboard */ - -#endif /* CONFIG_VIDEO_SUNXI */ - /* Ethernet support */ #ifdef CONFIG_USB_EHCI_HCD @@ -401,11 +384,7 @@ extern int soft_i2c_gpio_scl; "stdin=serial\0" #endif -#ifdef CONFIG_VIDEO -#define CONSOLE_STDOUT_SETTINGS \ - "stdout=serial,vga\0" \ - "stderr=serial,vga\0" -#elif CONFIG_DM_VIDEO +#ifdef CONFIG_DM_VIDEO #define CONSOLE_STDOUT_SETTINGS \ "stdout=serial,vidconsole\0" \ "stderr=serial,vidconsole\0" diff --git a/include/cpu_func.h b/include/cpu_func.h index 8aa825daa4..c3a66f0405 100644 --- a/include/cpu_func.h +++ b/include/cpu_func.h @@ -84,6 +84,6 @@ enum { */ int cleanup_before_linux_select(int flags); -void reset_cpu(ulong addr); -; +void reset_cpu(void); + #endif diff --git a/include/dm/test.h b/include/dm/test.h index 6ac6672cd6..fe1cc2e278 100644 --- a/include/dm/test.h +++ b/include/dm/test.h @@ -125,25 +125,9 @@ extern int dm_testdrv_op_count[DM_TEST_OP_COUNT]; extern struct unit_test_state global_dm_test_state; -/* - * struct dm_test_state - Entire state of dm test system - * - * This is often abreviated to dms. - * - * @root: Root device - * @testdev: Test device - * @force_fail_alloc: Force all memory allocs to fail - * @skip_post_probe: Skip uclass post-probe processing - */ -struct dm_test_state { - struct udevice *root; - struct udevice *testdev; - int force_fail_alloc; - int skip_post_probe; -}; - /* Declare a new driver model test */ -#define DM_TEST(_name, _flags) UNIT_TEST(_name, _flags, dm_test) +#define DM_TEST(_name, _flags) \ + UNIT_TEST(_name, UT_TESTF_DM | UT_TESTF_CONSOLE_REC | (_flags), dm_test) /* * struct sandbox_sdl_plat - Platform data for the SDL video driver diff --git a/include/log.h b/include/log.h index 2d27f9f657..6ef891d4d2 100644 --- a/include/log.h +++ b/include/log.h @@ -316,12 +316,40 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line, __ret); \ __ret; \ }) + +/* + * Similar to the above, but any non-zero value is consider an error, not just + * values less than 0. + */ +#define log_retz(_ret) ({ \ + int __ret = (_ret); \ + if (__ret) \ + log(LOG_CATEGORY, LOGL_ERR, "returning err=%d\n", __ret); \ + __ret; \ + }) +#define log_msg_retz(_msg, _ret) ({ \ + int __ret = (_ret); \ + if (__ret) \ + log(LOG_CATEGORY, LOGL_ERR, "%s: returning err=%d\n", _msg, \ + __ret); \ + __ret; \ + }) #else /* Non-logging versions of the above which just return the error code */ #define log_ret(_ret) (_ret) #define log_msg_ret(_msg, _ret) ((void)(_msg), _ret) +#define log_retz(_ret) (_ret) +#define log_msg_retz(_msg, _ret) ((void)(_msg), _ret) #endif +/** * enum log_rec_flags - Flags for a log record */ +enum log_rec_flags { + /** @LOGRECF_FORCE_DEBUG: Force output of debug record */ + LOGRECF_FORCE_DEBUG = BIT(0), + /** @LOGRECF_CONT: Continuation of previous log record */ + LOGRECF_CONT = BIT(1), +}; + /** * struct log_rec - a single log record * @@ -337,18 +365,18 @@ void __assert_fail(const char *assertion, const char *file, unsigned int line, * * @cat: Category, representing a uclass or part of U-Boot * @level: Severity level, less severe is higher - * @force_debug: Force output of debug - * @file: Name of file where the log record was generated (not allocated) * @line: Line number where the log record was generated + * @flags: Flags for log record (enum log_rec_flags) + * @file: Name of file where the log record was generated (not allocated) * @func: Function where the log record was generated (not allocated) * @msg: Log message (allocated) */ struct log_rec { enum log_category_t cat; enum log_level_t level; - bool force_debug; + u16 line; + u8 flags; const char *file; - int line; const char *func; const char *msg; }; diff --git a/include/os.h b/include/os.h index 65bcb232ca..77d8bd89d0 100644 --- a/include/os.h +++ b/include/os.h @@ -114,7 +114,7 @@ void os_fd_restore(void); * os_malloc() - aquires some memory from the underlying os. * * @length: Number of bytes to be allocated - * Return: Pointer to length bytes or NULL on error + * Return: Pointer to length bytes or NULL if @length is 0 or on error */ void *os_malloc(size_t length); @@ -123,11 +123,22 @@ void *os_malloc(size_t length); * * This returns the memory to the OS. * - * @ptr: Pointer to memory block to free + * @ptr: Pointer to memory block to free. If this is NULL then this + * function does nothing */ void os_free(void *ptr); /** + * os_realloc() - reallocate memory + * + * This follows the semantics of realloc(), so can perform an os_malloc() or + * os_free() depending on @ptr and @length. + * + * Return: Pointer to reallocated memory or NULL if @length is 0 + */ +void *os_realloc(void *ptr, size_t length); + +/** * os_usleep() - access to the usleep function of the os * * @usec: time to sleep in micro seconds @@ -313,9 +324,10 @@ int os_jump_to_image(const void *dest, int size); * * @fname: place to put full path to U-Boot * @maxlen: maximum size of @fname + * @use_img: select the 'u-boot.img' file instead of the 'u-boot' ELF file * Return: 0 if OK, -NOSPC if the filename is too large, -ENOENT if not found */ -int os_find_u_boot(char *fname, int maxlen); +int os_find_u_boot(char *fname, int maxlen, bool use_img); /** * os_spl_to_uboot() - Run U-Boot proper diff --git a/include/scp03.h b/include/scp03.h new file mode 100644 index 0000000000..729667ccd1 --- /dev/null +++ b/include/scp03.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2021, Foundries.IO + * + */ + +#ifndef _SCP03_H +#define _SCP03_H + +/* + * Requests to OPTEE to enable or provision the Secure Channel Protocol on its + * Secure Element + * + * If key provisioning is requested, OPTEE shall generate new SCP03 keys and + * write them to the Secure Element. + * + * Both functions return < 0 on error else 0. + */ +int tee_enable_scp03(void); +int tee_provision_scp03(void); +#endif /* _SCP03_H */ diff --git a/include/spl.h b/include/spl.h index 0d134587de..4f6e0e53f5 100644 --- a/include/spl.h +++ b/include/spl.h @@ -222,6 +222,15 @@ struct spl_load_info { void *priv; int bl_len; const char *filename; + /** + * read() - Read from device + * + * @load: Information about the load state + * @sector: Sector number to read from (each @load->bl_len bytes) + * @count: Number of sectors to read + * @buf: Buffer to read into + * @return number of sectors read, 0 on error + */ ulong (*read)(struct spl_load_info *load, ulong sector, ulong count, void *buf); }; diff --git a/include/sysreset.h b/include/sysreset.h index 8bb094d463..701e4f5c86 100644 --- a/include/sysreset.h +++ b/include/sysreset.h @@ -116,6 +116,6 @@ void sysreset_walk_halt(enum sysreset_t type); /** * reset_cpu() - calls sysreset_walk(SYSRESET_WARM) */ -void reset_cpu(ulong addr); +void reset_cpu(void); #endif diff --git a/include/tee/optee_ta_scp03.h b/include/tee/optee_ta_scp03.h new file mode 100644 index 0000000000..13f9956d98 --- /dev/null +++ b/include/tee/optee_ta_scp03.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * (C) Copyright 2021, Foundries.IO + * + */ +#ifndef __TA_SCP03_H +#define __TA_SCP03_H + +#define PTA_SCP03_UUID { 0xbe0e5821, 0xe718, 0x4f77, \ + { 0xab, 0x3e, 0x8e, 0x6c, 0x73, 0xa9, 0xc7, 0x35 } } + +/* + * Enable Secure Channel Protocol functionality (SCP03) on the Secure Element. + * Setting the operation value to something different than NULL will trigger + * the SCP03 provisioning request. + * + * in params[0].a = operation + */ +#define PTA_CMD_ENABLE_SCP03 0 + +#endif /*__TA_SCP03_H*/ diff --git a/include/test/test.h b/include/test/test.h index 3fdaa2b5e5..0b124edd60 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -14,16 +14,24 @@ * * @fail_count: Number of tests that failed * @start: Store the starting mallinfo when doing leak test - * @priv: A pointer to some other info some suites want to track + * @of_live: true to use livetree if available, false to use flattree * @of_root: Record of the livetree root node (used for setting up tests) + * @root: Root device + * @testdev: Test device + * @force_fail_alloc: Force all memory allocs to fail + * @skip_post_probe: Skip uclass post-probe processing * @expect_str: Temporary string used to hold expected string value * @actual_str: Temporary string used to hold actual string value */ struct unit_test_state { int fail_count; struct mallinfo start; - void *priv; struct device_node *of_root; + bool of_live; + struct udevice *root; + struct udevice *testdev; + int force_fail_alloc; + int skip_post_probe; char expect_str[256]; char actual_str[256]; }; @@ -36,6 +44,8 @@ enum { UT_TESTF_FLAT_TREE = BIT(3), /* test needs flat DT */ UT_TESTF_LIVE_TREE = BIT(4), /* needs live device tree */ UT_TESTF_CONSOLE_REC = BIT(5), /* needs console recording */ + /* do extra driver model init and uninit */ + UT_TESTF_DM = BIT(6), }; /** @@ -76,13 +86,24 @@ struct unit_test { * @_suite: name of the test suite concatenated with "_test" */ #define UNIT_TEST(_name, _flags, _suite) \ - ll_entry_declare(struct unit_test, _name, _suite) = { \ + ll_entry_declare(struct unit_test, _name, ut_ ## _suite) = { \ .file = __FILE__, \ .name = #_name, \ .flags = _flags, \ .func = _name, \ } +/* Get the start of a list of unit tests for a particular suite */ +#define UNIT_TEST_SUITE_START(_suite) \ + ll_entry_start(struct unit_test, ut_ ## _suite) +#define UNIT_TEST_SUITE_COUNT(_suite) \ + ll_entry_count(struct unit_test, ut_ ## _suite) + +/* Use ! and ~ so that all tests will be sorted between these two values */ +#define UNIT_TEST_ALL_START() ll_entry_start(struct unit_test, ut_!) +#define UNIT_TEST_ALL_END() ll_entry_start(struct unit_test, ut_~) +#define UNIT_TEST_ALL_COUNT() (UNIT_TEST_ALL_END() - UNIT_TEST_ALL_START()) + /* Sizes for devres tests */ enum { TEST_DEVRES_SIZE = 100, @@ -103,15 +124,4 @@ enum { */ struct udevice *testbus_get_clear_removed(void); -/** - * dm_test_main() - Run driver model tests - * - * Run all the available driver model tests, or a selection - * - * @test_name: Name of single test to run (e.g. "dm_test_fdt_pre_reloc" or just - * "fdt_pre_reloc"), or NULL to run all - * @return 0 if all tests passed, 1 if not - */ -int dm_test_main(const char *test_name); - #endif /* __TEST_TEST_H */ diff --git a/include/test/ut.h b/include/test/ut.h index 17400c73ea..fbbba286ee 100644 --- a/include/test/ut.h +++ b/include/test/ut.h @@ -356,4 +356,49 @@ void ut_silence_console(struct unit_test_state *uts); */ void ut_unsilence_console(struct unit_test_state *uts); +/** + * ut_set_skip_delays() - Sets whether delays should be skipped + * + * Normally functions like mdelay() cause U-Boot to wait for a while. This + * allows all such delays to be skipped on sandbox, to speed up tests + * + * @uts: Test state (in case in future we want to keep state here) + * @skip_delays: true to skip delays, false to process them normally + */ +void ut_set_skip_delays(struct unit_test_state *uts, bool skip_delays); + +/** + * test_get_state() - Get the active test state + * + * @return the currently active test state, or NULL if none + */ +struct unit_test_state *test_get_state(void); + +/** + * test_set_state() - Set the active test state + * + * @uts: Test state to use as currently active test state, or NULL if none + */ +void test_set_state(struct unit_test_state *uts); + +/** + * ut_run_tests() - Run a set of tests + * + * This runs the test, handling any preparation and clean-up needed. It prints + * the name of each test before running it. + * + * @category: Category of these tests. This is a string printed at the start to + * announce the the number of tests + * @prefix: String prefix for the tests. Any tests that have this prefix will be + * printed without the prefix, so that it is easier to see the unique part + * of the test name. If NULL, no prefix processing is done + * @tests: List of tests to run + * @count: Number of tests to run + * @select_name: Name of a single test to run (from the list provided). If NULL + * then all tests are run + * @return 0 if all tests passed, -1 if any failed + */ +int ut_run_list(const char *name, const char *prefix, struct unit_test *tests, + int count, const char *select_name); + #endif diff --git a/include/tpm-common.h b/include/tpm-common.h index c1309a2735..998b4fbb41 100644 --- a/include/tpm-common.h +++ b/include/tpm-common.h @@ -55,6 +55,8 @@ enum tpm_version { * @buf: Buffer used during the exchanges with the chip * @pcr_count: Number of PCR per bank * @pcr_select_min: Minimum size in bytes of the pcrSelect array + * @plat_hier_disabled: Platform hierarchy has been disabled (TPM is locked + * down until next reboot) */ struct tpm_chip_priv { enum tpm_version version; @@ -66,6 +68,7 @@ struct tpm_chip_priv { /* TPM v2 specific data */ uint pcr_count; uint pcr_select_min; + bool plat_hier_disabled; }; /** diff --git a/include/tpm-v1.h b/include/tpm-v1.h index 8f6cc28a9e..fcfe1f054f 100644 --- a/include/tpm-v1.h +++ b/include/tpm-v1.h @@ -289,7 +289,7 @@ struct __packed tpm_nv_data_public { * @param mode TPM startup mode * @return return code of the operation */ -u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode); +u32 tpm1_startup(struct udevice *dev, enum tpm_startup_type mode); /** * Issue a TPM_SelfTestFull command. @@ -297,7 +297,7 @@ u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode); * @param dev TPM device * @return return code of the operation */ -u32 tpm_self_test_full(struct udevice *dev); +u32 tpm1_self_test_full(struct udevice *dev); /** * Issue a TPM_ContinueSelfTest command. @@ -305,7 +305,7 @@ u32 tpm_self_test_full(struct udevice *dev); * @param dev TPM device * @return return code of the operation */ -u32 tpm_continue_self_test(struct udevice *dev); +u32 tpm1_continue_self_test(struct udevice *dev); /** * Issue a TPM_NV_DefineSpace command. The implementation is limited @@ -318,7 +318,7 @@ u32 tpm_continue_self_test(struct udevice *dev); * @param size size of the area * @return return code of the operation */ -u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size); +u32 tpm1_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size); /** * Issue a TPM_NV_ReadValue command. This implementation is limited @@ -331,7 +331,7 @@ u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size); * @param count size of output buffer * @return return code of the operation */ -u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count); +u32 tpm1_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count); /** * Issue a TPM_NV_WriteValue command. This implementation is limited @@ -344,8 +344,8 @@ u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count); * @param length length of data bytes of input buffer * @return return code of the operation */ -u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data, - u32 length); +u32 tpm1_nv_write_value(struct udevice *dev, u32 index, const void *data, + u32 length); /** * Issue a TPM_Extend command. @@ -358,8 +358,8 @@ u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data, * command * @return return code of the operation */ -u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest, - void *out_digest); +u32 tpm1_extend(struct udevice *dev, u32 index, const void *in_digest, + void *out_digest); /** * Issue a TPM_PCRRead command. @@ -370,7 +370,7 @@ u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest, * @param count size of output buffer * @return return code of the operation */ -u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count); +u32 tpm1_pcr_read(struct udevice *dev, u32 index, void *data, size_t count); /** * Issue a TSC_PhysicalPresence command. TPM physical presence flag @@ -380,7 +380,7 @@ u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count); * @param presence TPM physical presence flag * @return return code of the operation */ -u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence); +u32 tpm1_tsc_physical_presence(struct udevice *dev, u16 presence); /** * Issue a TPM_ReadPubek command. @@ -390,7 +390,7 @@ u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence); * @param count size of output buffer * @return return code of the operation */ -u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count); +u32 tpm1_read_pubek(struct udevice *dev, void *data, size_t count); /** * Issue a TPM_ForceClear command. @@ -398,7 +398,7 @@ u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count); * @param dev TPM device * @return return code of the operation */ -u32 tpm_force_clear(struct udevice *dev); +u32 tpm1_force_clear(struct udevice *dev); /** * Issue a TPM_PhysicalEnable command. @@ -406,7 +406,7 @@ u32 tpm_force_clear(struct udevice *dev); * @param dev TPM device * @return return code of the operation */ -u32 tpm_physical_enable(struct udevice *dev); +u32 tpm1_physical_enable(struct udevice *dev); /** * Issue a TPM_PhysicalDisable command. @@ -414,7 +414,7 @@ u32 tpm_physical_enable(struct udevice *dev); * @param dev TPM device * @return return code of the operation */ -u32 tpm_physical_disable(struct udevice *dev); +u32 tpm1_physical_disable(struct udevice *dev); /** * Issue a TPM_PhysicalSetDeactivated command. @@ -423,7 +423,7 @@ u32 tpm_physical_disable(struct udevice *dev); * @param state boolean state of the deactivated flag * @return return code of the operation */ -u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state); +u32 tpm1_physical_set_deactivated(struct udevice *dev, u8 state); /** * Issue a TPM_GetCapability command. This implementation is limited @@ -437,8 +437,8 @@ u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state); * @param count size of output buffer * @return return code of the operation */ -u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap, - void *cap, size_t count); +u32 tpm1_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap, + void *cap, size_t count); /** * Issue a TPM_FlushSpecific command for a AUTH resource. @@ -447,7 +447,7 @@ u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap, * @param auth_handle handle of the auth session * @return return code of the operation */ -u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle); +u32 tpm1_terminate_auth_session(struct udevice *dev, u32 auth_handle); /** * Issue a TPM_OIAP command to setup an object independent authorization @@ -460,7 +460,7 @@ u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle); * @param auth_handle pointer to the (new) auth handle or NULL. * @return return code of the operation */ -u32 tpm_oiap(struct udevice *dev, u32 *auth_handle); +u32 tpm1_oiap(struct udevice *dev, u32 *auth_handle); /** * Ends an active OIAP session. @@ -468,7 +468,7 @@ u32 tpm_oiap(struct udevice *dev, u32 *auth_handle); * @param dev TPM device * @return return code of the operation */ -u32 tpm_end_oiap(struct udevice *dev); +u32 tpm1_end_oiap(struct udevice *dev); /** * Issue a TPM_LoadKey2 (Auth1) command using an OIAP session for authenticating @@ -482,9 +482,9 @@ u32 tpm_end_oiap(struct udevice *dev); * @param key_handle pointer to the key handle * @return return code of the operation */ -u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key, - size_t key_length, const void *parent_key_usage_auth, - u32 *key_handle); +u32 tpm1_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key, + size_t key_length, const void *parent_key_usage_auth, + u32 *key_handle); /** * Issue a TPM_GetPubKey (Auth1) command using an OIAP session for @@ -500,9 +500,9 @@ u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key, * of the stored TPM_PUBKEY structure (iff pubkey != NULL). * @return return code of the operation */ -u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle, - const void *usage_auth, void *pubkey, - size_t *pubkey_len); +u32 tpm1_get_pub_key_oiap(struct udevice *dev, u32 key_handle, + const void *usage_auth, void *pubkey, + size_t *pubkey_len); /** * Get the TPM permanent flags value @@ -511,8 +511,8 @@ u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle, * @param pflags Place to put permanent flags * @return return code of the operation */ -u32 tpm_get_permanent_flags(struct udevice *dev, - struct tpm_permanent_flags *pflags); +u32 tpm1_get_permanent_flags(struct udevice *dev, + struct tpm_permanent_flags *pflags); /** * Get the TPM permissions @@ -521,7 +521,7 @@ u32 tpm_get_permanent_flags(struct udevice *dev, * @param perm Returns permissions value * @return return code of the operation */ -u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm); +u32 tpm1_get_permissions(struct udevice *dev, u32 index, u32 *perm); /** * Flush a resource with a given handle and type from the TPM @@ -531,7 +531,7 @@ u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm); * @param resource_type type of the resource * @return return code of the operation */ -u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type); +u32 tpm1_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type); #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1 /** @@ -543,8 +543,8 @@ u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type); * @param[out] handle The handle of the key (Non-null iff found) * @return 0 if key was found in TPM; != 0 if not. */ -u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20], - const u8 pubkey_digest[20], u32 *handle); +u32 tpm1_find_key_sha1(struct udevice *dev, const u8 auth[20], + const u8 pubkey_digest[20], u32 *handle); #endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */ /** @@ -557,7 +557,7 @@ u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20], * @param count size of output buffer * @return return code of the operation */ -u32 tpm_get_random(struct udevice *dev, void *data, u32 count); +u32 tpm1_get_random(struct udevice *dev, void *data, u32 count); /** * tpm_finalise_physical_presence() - Finalise physical presence @@ -565,15 +565,15 @@ u32 tpm_get_random(struct udevice *dev, void *data, u32 count); * @param dev TPM device * @return return code of the operation (0 = success) */ -u32 tpm_finalise_physical_presence(struct udevice *dev); +u32 tpm1_finalise_physical_presence(struct udevice *dev); /** - * tpm_nv_set_locked() - lock the non-volatile space + * tpm_nv_enable_locking() - lock the non-volatile space * * @param dev TPM device * @return return code of the operation (0 = success) */ -u32 tpm_nv_set_locked(struct udevice *dev); +u32 tpm1_nv_set_locked(struct udevice *dev); /** * tpm_set_global_lock() - set the global lock @@ -589,6 +589,6 @@ u32 tpm_set_global_lock(struct udevice *dev); * @param dev TPM device * @return return code of the operation (0 = success) */ -u32 tpm_resume(struct udevice *dev); +u32 tpm1_resume(struct udevice *dev); #endif /* __TPM_V1_H */ diff --git a/include/tpm-v2.h b/include/tpm-v2.h index 56eaa65815..df67a196cf 100644 --- a/include/tpm-v2.h +++ b/include/tpm-v2.h @@ -237,10 +237,14 @@ enum tpm2_handles { enum tpm2_command_codes { TPM2_CC_STARTUP = 0x0144, TPM2_CC_SELF_TEST = 0x0143, + TPM2_CC_HIER_CONTROL = 0x0121, TPM2_CC_CLEAR = 0x0126, TPM2_CC_CLEARCONTROL = 0x0127, TPM2_CC_HIERCHANGEAUTH = 0x0129, + TPM2_CC_NV_DEFINE_SPACE = 0x012a, TPM2_CC_PCR_SETAUTHPOL = 0x012C, + TPM2_CC_NV_WRITE = 0x0137, + TPM2_CC_NV_WRITELOCK = 0x0138, TPM2_CC_DAM_RESET = 0x0139, TPM2_CC_DAM_PARAMETERS = 0x013A, TPM2_CC_NV_READ = 0x014E, @@ -271,6 +275,7 @@ enum tpm2_return_codes { TPM2_RC_COMMAND_CODE = TPM2_RC_VER1 + 0x0043, TPM2_RC_AUTHSIZE = TPM2_RC_VER1 + 0x0044, TPM2_RC_AUTH_CONTEXT = TPM2_RC_VER1 + 0x0045, + TPM2_RC_NV_DEFINED = TPM2_RC_VER1 + 0x004c, TPM2_RC_NEEDS_TEST = TPM2_RC_VER1 + 0x0053, TPM2_RC_WARN = 0x0900, TPM2_RC_TESTING = TPM2_RC_WARN + 0x000A, @@ -355,6 +360,20 @@ enum { TPM_MAX_BUF_SIZE = 1260, }; +enum { + /* Secure storage for firmware settings */ + TPM_HT_PCR = 0, + TPM_HT_NV_INDEX, + TPM_HT_HMAC_SESSION, + TPM_HT_POLICY_SESSION, + + HR_SHIFT = 24, + HR_PCR = TPM_HT_PCR << HR_SHIFT, + HR_HMAC_SESSION = TPM_HT_HMAC_SESSION << HR_SHIFT, + HR_POLICY_SESSION = TPM_HT_POLICY_SESSION << HR_SHIFT, + HR_NV_INDEX = TPM_HT_NV_INDEX << HR_SHIFT, +}; + /** * Issue a TPM2_Startup command. * @@ -389,6 +408,23 @@ u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw, const ssize_t pw_sz); /** + * Issue a TPM_NV_DefineSpace command + * + * This allows a space to be defined with given attributes and policy + * + * @dev TPM device + * @space_index index of the area + * @space_size size of area in bytes + * @nv_attributes TPM_NV_ATTRIBUTES of the area + * @nv_policy policy to use + * @nv_policy_size size of the policy + * @return return code of the operation + */ +u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index, + size_t space_size, u32 nv_attributes, + const u8 *nv_policy, size_t nv_policy_size); + +/** * Issue a TPM2_PCR_Extend command. * * @dev TPM device @@ -403,6 +439,29 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm, const u8 *digest, u32 digest_len); /** + * Read data from the secure storage + * + * @dev TPM device + * @index Index of data to read + * @data Place to put data + * @count Number of bytes of data + * @return code of the operation + */ +u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count); + +/** + * Write data to the secure storage + * + * @dev TPM device + * @index Index of data to write + * @data Data to write + * @count Number of bytes of data + * @return code of the operation + */ +u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data, + u32 count); + +/** * Issue a TPM2_PCR_Read command. * * @dev TPM device @@ -516,4 +575,26 @@ u32 tpm2_pcr_setauthvalue(struct udevice *dev, const char *pw, */ u32 tpm2_get_random(struct udevice *dev, void *data, u32 count); +/** + * Lock data in the TPM + * + * Once locked the data cannot be written until after a reboot + * + * @dev TPM device + * @index Index of data to lock + * @return code of the operation + */ +u32 tpm2_write_lock(struct udevice *dev, u32 index); + +/** + * Disable access to any platform data + * + * This can be called to close off access to the firmware data in the data, + * before calling the kernel. + * + * @dev TPM device + * @return code of the operation + */ +u32 tpm2_disable_platform_hierarchy(struct udevice *dev); + #endif /* __TPM_V2_H */ diff --git a/include/tpm_api.h b/include/tpm_api.h new file mode 100644 index 0000000000..f13d98cae4 --- /dev/null +++ b/include/tpm_api.h @@ -0,0 +1,322 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2013 The Chromium OS Authors. + * Coypright (c) 2013 Guntermann & Drunck GmbH + */ + +#ifndef __TPM_API_H +#define __TPM_API_H + +#include <tpm-common.h> +#include <tpm-v1.h> +#include <tpm-v2.h> + +/** + * Issue a TPM_Startup command. + * + * @param dev TPM device + * @param mode TPM startup mode + * @return return code of the operation + */ +u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode); + +/** + * Issue a TPM_SelfTestFull command. + * + * @param dev TPM device + * @return return code of the operation + */ +u32 tpm_self_test_full(struct udevice *dev); + +/** + * Issue a TPM_ContinueSelfTest command. + * + * @param dev TPM device + * @return return code of the operation + */ +u32 tpm_continue_self_test(struct udevice *dev); + +/** + * Issue a TPM_NV_DefineSpace command. The implementation is limited + * to specify TPM_NV_ATTRIBUTES and size of the area. The area index + * could be one of the special value listed in enum tpm_nv_index. + * + * @param dev TPM device + * @param index index of the area + * @param perm TPM_NV_ATTRIBUTES of the area + * @param size size of the area + * @return return code of the operation + */ +u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size); + +/** + * Issue a TPM_NV_ReadValue command. This implementation is limited + * to read the area from offset 0. The area index could be one of + * the special value listed in enum tpm_nv_index. + * + * @param dev TPM device + * @param index index of the area + * @param data output buffer of the area contents + * @param count size of output buffer + * @return return code of the operation + */ +u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count); + +/** + * Issue a TPM_NV_WriteValue command. This implementation is limited + * to write the area from offset 0. The area index could be one of + * the special value listed in enum tpm_nv_index. + * + * @param dev TPM device + * @param index index of the area + * @param data input buffer to be wrote to the area + * @param length length of data bytes of input buffer + * @return return code of the operation + */ +u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data, + u32 length); + +/** + * Issue a TPM_Extend command. + * + * @param dev TPM device + * @param index index of the PCR + * @param in_digest 160-bit value representing the event to be + * recorded + * @param out_digest 160-bit PCR value after execution of the + * command + * @return return code of the operation + */ +u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest, + void *out_digest); + +/** + * Issue a TPM_PCRRead command. + * + * @param dev TPM device + * @param index index of the PCR + * @param data output buffer for contents of the named PCR + * @param count size of output buffer + * @return return code of the operation + */ +u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count); + +/** + * Issue a TSC_PhysicalPresence command. TPM physical presence flag + * is bit-wise OR'ed of flags listed in enum tpm_physical_presence. + * + * @param dev TPM device + * @param presence TPM physical presence flag + * @return return code of the operation + */ +u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence); + +/** + * Issue a TPM_ReadPubek command. + * + * @param dev TPM device + * @param data output buffer for the public endorsement key + * @param count size of output buffer + * @return return code of the operation + */ +u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count); + +/** + * Issue a TPM_ForceClear command. + * + * @param dev TPM device + * @return return code of the operation + */ +u32 tpm_force_clear(struct udevice *dev); + +/** + * Issue a TPM_PhysicalEnable command. + * + * @param dev TPM device + * @return return code of the operation + */ +u32 tpm_physical_enable(struct udevice *dev); + +/** + * Issue a TPM_PhysicalDisable command. + * + * @param dev TPM device + * @return return code of the operation + */ +u32 tpm_physical_disable(struct udevice *dev); + +/** + * Issue a TPM_PhysicalSetDeactivated command. + * + * @param dev TPM device + * @param state boolean state of the deactivated flag + * @return return code of the operation + */ +u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state); + +/** + * Issue a TPM_GetCapability command. This implementation is limited + * to query sub_cap index that is 4-byte wide. + * + * @param dev TPM device + * @param cap_area partition of capabilities + * @param sub_cap further definition of capability, which is + * limited to be 4-byte wide + * @param cap output buffer for capability information + * @param count size of output buffer + * @return return code of the operation + */ +u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap, + void *cap, size_t count); + +/** + * Issue a TPM_FlushSpecific command for a AUTH resource. + * + * @param dev TPM device + * @param auth_handle handle of the auth session + * @return return code of the operation + */ +u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle); + +/** + * Issue a TPM_OIAP command to setup an object independent authorization + * session. + * Information about the session is stored internally. + * If there was already an OIAP session active it is terminated and a new + * session is set up. + * + * @param dev TPM device + * @param auth_handle pointer to the (new) auth handle or NULL. + * @return return code of the operation + */ +u32 tpm_oiap(struct udevice *dev, u32 *auth_handle); + +/** + * Ends an active OIAP session. + * + * @param dev TPM device + * @return return code of the operation + */ +u32 tpm_end_oiap(struct udevice *dev); + +/** + * Issue a TPM_LoadKey2 (Auth1) command using an OIAP session for authenticating + * the usage of the parent key. + * + * @param dev TPM device + * @param parent_handle handle of the parent key. + * @param key pointer to the key structure (TPM_KEY or TPM_KEY12). + * @param key_length size of the key structure + * @param parent_key_usage_auth usage auth for the parent key + * @param key_handle pointer to the key handle + * @return return code of the operation + */ +u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key, + size_t key_length, const void *parent_key_usage_auth, + u32 *key_handle); + +/** + * Issue a TPM_GetPubKey (Auth1) command using an OIAP session for + * authenticating the usage of the key. + * + * @param dev TPM device + * @param key_handle handle of the key + * @param usage_auth usage auth for the key + * @param pubkey pointer to the pub key buffer; may be NULL if the pubkey + * should not be stored. + * @param pubkey_len pointer to the pub key buffer len. On entry: the size of + * the provided pubkey buffer. On successful exit: the size + * of the stored TPM_PUBKEY structure (iff pubkey != NULL). + * @return return code of the operation + */ +u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle, + const void *usage_auth, void *pubkey, + size_t *pubkey_len); + +/** + * Get the TPM permissions + * + * @param dev TPM device + * @param perm Returns permissions value + * @return return code of the operation + */ +u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm); + +/** + * Flush a resource with a given handle and type from the TPM + * + * @param dev TPM device + * @param key_handle handle of the resource + * @param resource_type type of the resource + * @return return code of the operation + */ +u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type); + +#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1 +/** + * Search for a key by usage AuthData and the hash of the parent's pub key. + * + * @param dev TPM device + * @param auth Usage auth of the key to search for + * @param pubkey_digest SHA1 hash of the pub key structure of the key + * @param[out] handle The handle of the key (Non-null iff found) + * @return 0 if key was found in TPM; != 0 if not. + */ +u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20], + const u8 pubkey_digest[20], u32 *handle); +#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */ + +/** + * Read random bytes from the TPM RNG. The implementation deals with the fact + * that the TPM may legally return fewer bytes than requested by retrying + * until @p count bytes have been received. + * + * @param dev TPM device + * @param data output buffer for the random bytes + * @param count size of output buffer + * @return return code of the operation + */ +u32 tpm_get_random(struct udevice *dev, void *data, u32 count); + +/** + * tpm_finalise_physical_presence() - Finalise physical presence + * + * @param dev TPM device + * @return return code of the operation (0 = success) + */ +u32 tpm_finalise_physical_presence(struct udevice *dev); + +/** + * tpm_nv_enable_locking() - lock the non-volatile space + * + * @param dev TPM device + * @return return code of the operation (0 = success) + */ +u32 tpm_nv_enable_locking(struct udevice *dev); + +/** + * tpm_set_global_lock() - set the global lock + * + * @param dev TPM device + * @return return code of the operation (0 = success) + */ +u32 tpm_set_global_lock(struct udevice *dev); + +/** + * tpm_write_lock() - lock the non-volatile space + * + * @param dev TPM device + * @param index Index of space to lock + * @return return code of the operation (0 = success) + */ +u32 tpm_write_lock(struct udevice *dev, u32 index); + +/** + * tpm_resume() - start up the TPM from resume (after suspend) + * + * @param dev TPM device + * @return return code of the operation (0 = success) + */ +u32 tpm_resume(struct udevice *dev); + +#endif /* __TPM_API_H */ diff --git a/lib/Makefile b/lib/Makefile index edc1c3dd4f..c42d4e1233 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -53,6 +53,7 @@ endif obj-$(CONFIG_$(SPL_TPL_)TPM) += tpm-common.o ifeq ($(CONFIG_$(SPL_TPL_)TPM),y) obj-y += crc8.o +obj-$(CONFIG_TPM) += tpm_api.o obj-$(CONFIG_TPM_V1) += tpm-v1.o obj-$(CONFIG_TPM_V2) += tpm-v2.o endif diff --git a/lib/tpm-common.c b/lib/tpm-common.c index e4af87f76a..4277846fdd 100644 --- a/lib/tpm-common.c +++ b/lib/tpm-common.c @@ -166,6 +166,7 @@ u32 tpm_sendrecv_command(struct udevice *dev, const void *command, u8 response_buffer[COMMAND_BUFFER_SIZE]; size_t response_length; int i; + uint size; if (response) { response_length = *size_ptr; @@ -174,8 +175,13 @@ u32 tpm_sendrecv_command(struct udevice *dev, const void *command, response_length = sizeof(response_buffer); } - err = tpm_xfer(dev, command, tpm_command_size(command), - response, &response_length); + size = tpm_command_size(command); + log_debug("TPM request [size:%d]: ", size); + for (i = 0; i < size; i++) + log_debug("%02x ", ((u8 *)command)[i]); + log_debug("\n"); + + err = tpm_xfer(dev, command, size, response, &response_length); if (err < 0) return err; diff --git a/lib/tpm-v1.c b/lib/tpm-v1.c index a846fe00dd..8dc144080c 100644 --- a/lib/tpm-v1.c +++ b/lib/tpm-v1.c @@ -32,7 +32,7 @@ static struct session_data oiap_session = {0, }; #endif /* CONFIG_TPM_AUTH_SESSIONS */ -u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode) +u32 tpm1_startup(struct udevice *dev, enum tpm_startup_type mode) { const u8 command[12] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0, @@ -48,12 +48,12 @@ u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode) return tpm_sendrecv_command(dev, buf, NULL, NULL); } -u32 tpm_resume(struct udevice *dev) +u32 tpm1_resume(struct udevice *dev) { - return tpm_startup(dev, TPM_ST_STATE); + return tpm1_startup(dev, TPM_ST_STATE); } -u32 tpm_self_test_full(struct udevice *dev) +u32 tpm1_self_test_full(struct udevice *dev) { const u8 command[10] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50, @@ -61,7 +61,7 @@ u32 tpm_self_test_full(struct udevice *dev) return tpm_sendrecv_command(dev, command, NULL, NULL); } -u32 tpm_continue_self_test(struct udevice *dev) +u32 tpm1_continue_self_test(struct udevice *dev) { const u8 command[10] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53, @@ -69,35 +69,33 @@ u32 tpm_continue_self_test(struct udevice *dev) return tpm_sendrecv_command(dev, command, NULL, NULL); } -u32 tpm_clear_and_reenable(struct udevice *dev) +u32 tpm1_clear_and_reenable(struct udevice *dev) { u32 ret; log_info("TPM: Clear and re-enable\n"); - ret = tpm_force_clear(dev); + ret = tpm1_force_clear(dev); if (ret != TPM_SUCCESS) { log_err("Can't initiate a force clear\n"); return ret; } - if (tpm_get_version(dev) == TPM_V1) { - ret = tpm_physical_enable(dev); - if (ret != TPM_SUCCESS) { - log_err("TPM: Can't set enabled state\n"); - return ret; - } + ret = tpm1_physical_enable(dev); + if (ret != TPM_SUCCESS) { + log_err("TPM: Can't set enabled state\n"); + return ret; + } - ret = tpm_physical_set_deactivated(dev, 0); - if (ret != TPM_SUCCESS) { - log_err("TPM: Can't set deactivated state\n"); - return ret; - } + ret = tpm1_physical_set_deactivated(dev, 0); + if (ret != TPM_SUCCESS) { + log_err("TPM: Can't set deactivated state\n"); + return ret; } return TPM_SUCCESS; } -u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size) +u32 tpm1_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size) { const u8 command[101] = { 0x0, 0xc1, /* TPM_TAG */ @@ -140,12 +138,12 @@ u32 tpm_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size) return tpm_sendrecv_command(dev, buf, NULL, NULL); } -u32 tpm_nv_set_locked(struct udevice *dev) +u32 tpm1_nv_set_locked(struct udevice *dev) { - return tpm_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0); + return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0); } -u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count) +u32 tpm1_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count) { const u8 command[22] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf, @@ -179,8 +177,8 @@ u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count) return 0; } -u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data, - u32 length) +u32 tpm1_nv_write_value(struct udevice *dev, u32 index, const void *data, + u32 length) { const u8 command[256] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd, @@ -210,13 +208,8 @@ u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data, return 0; } -uint32_t tpm_set_global_lock(struct udevice *dev) -{ - return tpm_nv_write_value(dev, TPM_NV_INDEX_0, NULL, 0); -} - -u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest, - void *out_digest) +u32 tpm1_extend(struct udevice *dev, u32 index, const void *in_digest, + void *out_digest) { const u8 command[34] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14, @@ -247,7 +240,7 @@ u32 tpm_extend(struct udevice *dev, u32 index, const void *in_digest, return 0; } -u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count) +u32 tpm1_pcr_read(struct udevice *dev, u32 index, void *data, size_t count) { const u8 command[14] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15, @@ -275,7 +268,7 @@ u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count) return 0; } -u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence) +u32 tpm1_tsc_physical_presence(struct udevice *dev, u16 presence) { const u8 command[12] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0, @@ -291,7 +284,7 @@ u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence) return tpm_sendrecv_command(dev, buf, NULL, NULL); } -u32 tpm_finalise_physical_presence(struct udevice *dev) +u32 tpm1_finalise_physical_presence(struct udevice *dev) { const u8 command[12] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0, @@ -300,7 +293,7 @@ u32 tpm_finalise_physical_presence(struct udevice *dev) return tpm_sendrecv_command(dev, command, NULL, NULL); } -u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count) +u32 tpm1_read_pubek(struct udevice *dev, void *data, size_t count) { const u8 command[30] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c, @@ -331,7 +324,7 @@ u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count) return 0; } -u32 tpm_force_clear(struct udevice *dev) +u32 tpm1_force_clear(struct udevice *dev) { const u8 command[10] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d, @@ -340,7 +333,7 @@ u32 tpm_force_clear(struct udevice *dev) return tpm_sendrecv_command(dev, command, NULL, NULL); } -u32 tpm_physical_enable(struct udevice *dev) +u32 tpm1_physical_enable(struct udevice *dev) { const u8 command[10] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f, @@ -349,7 +342,7 @@ u32 tpm_physical_enable(struct udevice *dev) return tpm_sendrecv_command(dev, command, NULL, NULL); } -u32 tpm_physical_disable(struct udevice *dev) +u32 tpm1_physical_disable(struct udevice *dev) { const u8 command[10] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70, @@ -358,7 +351,7 @@ u32 tpm_physical_disable(struct udevice *dev) return tpm_sendrecv_command(dev, command, NULL, NULL); } -u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state) +u32 tpm1_physical_set_deactivated(struct udevice *dev, u8 state) { const u8 command[11] = { 0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72, @@ -374,8 +367,8 @@ u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state) return tpm_sendrecv_command(dev, buf, NULL, NULL); } -u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap, - void *cap, size_t count) +u32 tpm1_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap, + void *cap, size_t count) { const u8 command[22] = { 0x0, 0xc1, /* TPM_TAG */ @@ -414,8 +407,8 @@ u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap, return 0; } -u32 tpm_get_permanent_flags(struct udevice *dev, - struct tpm_permanent_flags *pflags) +u32 tpm1_get_permanent_flags(struct udevice *dev, + struct tpm_permanent_flags *pflags) { const u8 command[22] = { 0x0, 0xc1, /* TPM_TAG */ @@ -453,7 +446,7 @@ u32 tpm_get_permanent_flags(struct udevice *dev, return 0; } -u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm) +u32 tpm1_get_permissions(struct udevice *dev, u32 index, u32 *perm) { const u8 command[22] = { 0x0, 0xc1, /* TPM_TAG */ @@ -482,7 +475,7 @@ u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm) } #ifdef CONFIG_TPM_FLUSH_RESOURCES -u32 tpm_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type) +u32 tpm1_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type) { const u8 command[18] = { 0x00, 0xc1, /* TPM_TAG */ @@ -641,7 +634,7 @@ static u32 verify_response_auth(u32 command_code, const void *response, return TPM_SUCCESS; } -u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle) +u32 tpm1_terminate_auth_session(struct udevice *dev, u32 auth_handle) { const u8 command[18] = { 0x00, 0xc1, /* TPM_TAG */ @@ -663,16 +656,16 @@ u32 tpm_terminate_auth_session(struct udevice *dev, u32 auth_handle) return tpm_sendrecv_command(dev, request, NULL, NULL); } -u32 tpm_end_oiap(struct udevice *dev) +u32 tpm1_end_oiap(struct udevice *dev) { u32 err = TPM_SUCCESS; if (oiap_session.valid) - err = tpm_terminate_auth_session(dev, oiap_session.handle); + err = tpm1_terminate_auth_session(dev, oiap_session.handle); return err; } -u32 tpm_oiap(struct udevice *dev, u32 *auth_handle) +u32 tpm1_oiap(struct udevice *dev, u32 *auth_handle) { const u8 command[10] = { 0x00, 0xc1, /* TPM_TAG */ @@ -686,7 +679,7 @@ u32 tpm_oiap(struct udevice *dev, u32 *auth_handle) u32 err; if (oiap_session.valid) - tpm_terminate_auth_session(dev, oiap_session.handle); + tpm1_terminate_auth_session(dev, oiap_session.handle); err = tpm_sendrecv_command(dev, command, response, &response_length); if (err) @@ -702,9 +695,9 @@ u32 tpm_oiap(struct udevice *dev, u32 *auth_handle) return 0; } -u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key, - size_t key_length, const void *parent_key_usage_auth, - u32 *key_handle) +u32 tpm1_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key, + size_t key_length, const void *parent_key_usage_auth, + u32 *key_handle) { const u8 command[14] = { 0x00, 0xc2, /* TPM_TAG */ @@ -723,7 +716,7 @@ u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key, u32 err; if (!oiap_session.valid) { - err = tpm_oiap(dev, NULL); + err = tpm1_oiap(dev, NULL); if (err) return err; } @@ -768,9 +761,9 @@ u32 tpm_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key, return 0; } -u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle, - const void *usage_auth, void *pubkey, - size_t *pubkey_len) +u32 tpm1_get_pub_key_oiap(struct udevice *dev, u32 key_handle, + const void *usage_auth, void *pubkey, + size_t *pubkey_len) { const u8 command[14] = { 0x00, 0xc2, /* TPM_TAG */ @@ -788,7 +781,7 @@ u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle, u32 err; if (!oiap_session.valid) { - err = tpm_oiap(dev, NULL); + err = tpm1_oiap(dev, NULL); if (err) return err; } @@ -834,8 +827,8 @@ u32 tpm_get_pub_key_oiap(struct udevice *dev, u32 key_handle, } #ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1 -u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20], - const u8 pubkey_digest[20], u32 *handle) +u32 tpm1_find_key_sha1(struct udevice *dev, const u8 auth[20], + const u8 pubkey_digest[20], u32 *handle) { u16 key_count; u32 key_handles[10]; @@ -876,7 +869,7 @@ u32 tpm_find_key_sha1(struct udevice *dev, const u8 auth[20], #endif /* CONFIG_TPM_AUTH_SESSIONS */ -u32 tpm_get_random(struct udevice *dev, void *data, u32 count) +u32 tpm1_get_random(struct udevice *dev, void *data, u32 count) { const u8 command[14] = { 0x0, 0xc1, /* TPM_TAG */ diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c index 1f3deb06e4..235f8c20d4 100644 --- a/lib/tpm-v2.c +++ b/lib/tpm-v2.c @@ -47,9 +47,11 @@ u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test) u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw, const ssize_t pw_sz) { + /* Length of the message header, up to start of password */ + uint offset = 27; u8 command_v2[COMMAND_BUFFER_SIZE] = { tpm_u16(TPM2_ST_SESSIONS), /* TAG */ - tpm_u32(27 + pw_sz), /* Length */ + tpm_u32(offset + pw_sz), /* Length */ tpm_u32(TPM2_CC_CLEAR), /* Command code */ /* HANDLE */ @@ -64,7 +66,6 @@ u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw, tpm_u16(pw_sz), /* Size of <hmac/password> */ /* STRING(pw) <hmac/password> (if any) */ }; - unsigned int offset = 27; int ret; /* @@ -80,12 +81,61 @@ u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw, return tpm_sendrecv_command(dev, command_v2, NULL, NULL); } +u32 tpm2_nv_define_space(struct udevice *dev, u32 space_index, + size_t space_size, u32 nv_attributes, + const u8 *nv_policy, size_t nv_policy_size) +{ + /* + * Calculate the offset of the nv_policy piece by adding each of the + * chunks below. + */ + uint offset = 10 + 8 + 13 + 14; + u8 command_v2[COMMAND_BUFFER_SIZE] = { + /* header 10 bytes */ + tpm_u16(TPM2_ST_SESSIONS), /* TAG */ + tpm_u32(offset + nv_policy_size),/* Length */ + tpm_u32(TPM2_CC_NV_DEFINE_SPACE),/* Command code */ + + /* handles 8 bytes */ + tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */ + + /* session header 13 bytes */ + tpm_u32(9), /* Header size */ + tpm_u32(TPM2_RS_PW), /* Password authorisation */ + tpm_u16(0), /* nonce_size */ + 0, /* session_attrs */ + tpm_u16(0), /* auth_size */ + + /* message 14 bytes + policy */ + tpm_u16(12 + nv_policy_size), /* size */ + tpm_u32(space_index), + tpm_u16(TPM2_ALG_SHA256), + tpm_u32(nv_attributes), + tpm_u16(nv_policy_size), + /* nv_policy */ + }; + int ret; + + /* + * Fill the command structure starting from the first buffer: + * - the password (if any) + */ + ret = pack_byte_string(command_v2, sizeof(command_v2), "s", + offset, nv_policy, nv_policy_size); + if (ret) + return TPM_LIB_ERROR; + + return tpm_sendrecv_command(dev, command_v2, NULL, NULL); +} + u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm, const u8 *digest, u32 digest_len) { + /* Length of the message header, up to start of digest */ + uint offset = 33; u8 command_v2[COMMAND_BUFFER_SIZE] = { tpm_u16(TPM2_ST_SESSIONS), /* TAG */ - tpm_u32(33 + digest_len), /* Length */ + tpm_u32(offset + digest_len), /* Length */ tpm_u32(TPM2_CC_PCR_EXTEND), /* Command code */ /* HANDLE */ @@ -99,11 +149,12 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm, 0, /* Attributes: Cont/Excl/Rst */ tpm_u16(0), /* Size of <hmac/password> */ /* <hmac/password> (if any) */ + + /* hashes */ tpm_u32(1), /* Count (number of hashes) */ tpm_u16(algorithm), /* Algorithm of the hash */ /* STRING(digest) Digest */ }; - unsigned int offset = 33; int ret; /* @@ -112,13 +163,96 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm, */ ret = pack_byte_string(command_v2, sizeof(command_v2), "s", offset, digest, digest_len); - offset += digest_len; if (ret) return TPM_LIB_ERROR; return tpm_sendrecv_command(dev, command_v2, NULL, NULL); } +u32 tpm2_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count) +{ + u8 command_v2[COMMAND_BUFFER_SIZE] = { + /* header 10 bytes */ + tpm_u16(TPM2_ST_SESSIONS), /* TAG */ + tpm_u32(10 + 8 + 4 + 9 + 4), /* Length */ + tpm_u32(TPM2_CC_NV_READ), /* Command code */ + + /* handles 8 bytes */ + tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */ + tpm_u32(HR_NV_INDEX + index), /* Password authorisation */ + + /* AUTH_SESSION */ + tpm_u32(9), /* Authorization size */ + tpm_u32(TPM2_RS_PW), /* Session handle */ + tpm_u16(0), /* Size of <nonce> */ + /* <nonce> (if any) */ + 0, /* Attributes: Cont/Excl/Rst */ + tpm_u16(0), /* Size of <hmac/password> */ + /* <hmac/password> (if any) */ + + tpm_u16(count), /* Number of bytes */ + tpm_u16(0), /* Offset */ + }; + size_t response_len = COMMAND_BUFFER_SIZE; + u8 response[COMMAND_BUFFER_SIZE]; + int ret; + u16 tag; + u32 size, code; + + ret = tpm_sendrecv_command(dev, command_v2, response, &response_len); + if (ret) + return log_msg_ret("read", ret); + if (unpack_byte_string(response, response_len, "wdds", + 0, &tag, 2, &size, 6, &code, + 16, data, count)) + return TPM_LIB_ERROR; + + return 0; +} + +u32 tpm2_nv_write_value(struct udevice *dev, u32 index, const void *data, + u32 count) +{ + struct tpm_chip_priv *priv = dev_get_uclass_priv(dev); + uint offset = 10 + 8 + 4 + 9 + 2; + uint len = offset + count + 2; + /* Use empty password auth if platform hierarchy is disabled */ + u32 auth = priv->plat_hier_disabled ? HR_NV_INDEX + index : + TPM2_RH_PLATFORM; + u8 command_v2[COMMAND_BUFFER_SIZE] = { + /* header 10 bytes */ + tpm_u16(TPM2_ST_SESSIONS), /* TAG */ + tpm_u32(len), /* Length */ + tpm_u32(TPM2_CC_NV_WRITE), /* Command code */ + + /* handles 8 bytes */ + tpm_u32(auth), /* Primary platform seed */ + tpm_u32(HR_NV_INDEX + index), /* Password authorisation */ + + /* AUTH_SESSION */ + tpm_u32(9), /* Authorization size */ + tpm_u32(TPM2_RS_PW), /* Session handle */ + tpm_u16(0), /* Size of <nonce> */ + /* <nonce> (if any) */ + 0, /* Attributes: Cont/Excl/Rst */ + tpm_u16(0), /* Size of <hmac/password> */ + /* <hmac/password> (if any) */ + + tpm_u16(count), + }; + size_t response_len = COMMAND_BUFFER_SIZE; + u8 response[COMMAND_BUFFER_SIZE]; + int ret; + + ret = pack_byte_string(command_v2, sizeof(command_v2), "sw", + offset, data, count, + offset + count, 0); + if (ret) + return TPM_LIB_ERROR; + + return tpm_sendrecv_command(dev, command_v2, response, &response_len); +} + u32 tpm2_pcr_read(struct udevice *dev, u32 idx, unsigned int idx_min_sz, void *data, unsigned int *updates) { @@ -467,3 +601,61 @@ u32 tpm2_get_random(struct udevice *dev, void *data, u32 count) return 0; } + +u32 tpm2_write_lock(struct udevice *dev, u32 index) +{ + u8 command_v2[COMMAND_BUFFER_SIZE] = { + /* header 10 bytes */ + tpm_u16(TPM2_ST_SESSIONS), /* TAG */ + tpm_u32(10 + 8 + 13), /* Length */ + tpm_u32(TPM2_CC_NV_WRITELOCK), /* Command code */ + + /* handles 8 bytes */ + tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */ + tpm_u32(HR_NV_INDEX + index), /* Password authorisation */ + + /* session header 9 bytes */ + tpm_u32(9), /* Header size */ + tpm_u32(TPM2_RS_PW), /* Password authorisation */ + tpm_u16(0), /* nonce_size */ + 0, /* session_attrs */ + tpm_u16(0), /* auth_size */ + }; + + return tpm_sendrecv_command(dev, command_v2, NULL, NULL); +} + +u32 tpm2_disable_platform_hierarchy(struct udevice *dev) +{ + struct tpm_chip_priv *priv = dev_get_uclass_priv(dev); + u8 command_v2[COMMAND_BUFFER_SIZE] = { + /* header 10 bytes */ + tpm_u16(TPM2_ST_SESSIONS), /* TAG */ + tpm_u32(10 + 4 + 13 + 5), /* Length */ + tpm_u32(TPM2_CC_HIER_CONTROL), /* Command code */ + + /* 4 bytes */ + tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */ + + /* session header 9 bytes */ + tpm_u32(9), /* Header size */ + tpm_u32(TPM2_RS_PW), /* Password authorisation */ + tpm_u16(0), /* nonce_size */ + 0, /* session_attrs */ + tpm_u16(0), /* auth_size */ + + /* payload 5 bytes */ + tpm_u32(TPM2_RH_PLATFORM), /* Hierarchy to disable */ + 0, /* 0=disable */ + }; + int ret; + + ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL); + log_info("ret=%s, %x\n", dev->name, ret); + if (ret) + return ret; + + priv->plat_hier_disabled = true; + + return 0; +} diff --git a/lib/tpm_api.c b/lib/tpm_api.c new file mode 100644 index 0000000000..4c662640a9 --- /dev/null +++ b/lib/tpm_api.c @@ -0,0 +1,285 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 Google LLC + */ + +#include <common.h> +#include <dm.h> +#include <log.h> +#include <tpm_api.h> +#include <tpm-v1.h> +#include <tpm-v2.h> +#include <tpm_api.h> + +static bool is_tpm1(struct udevice *dev) +{ + return IS_ENABLED(CONFIG_TPM_V1) && tpm_get_version(dev) == TPM_V1; +} + +static bool is_tpm2(struct udevice *dev) +{ + return IS_ENABLED(CONFIG_TPM_V2) && tpm_get_version(dev) == TPM_V2; +} + +u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode) +{ + if (is_tpm1(dev)) { + return tpm1_startup(dev, mode); + } else if (is_tpm2(dev)) { + enum tpm2_startup_types type; + + switch (mode) { + case TPM_ST_CLEAR: + type = TPM2_SU_CLEAR; + break; + case TPM_ST_STATE: + type = TPM2_SU_STATE; + break; + default: + case TPM_ST_DEACTIVATED: + return -EINVAL; + } + return tpm2_startup(dev, type); + } else { + return -ENOSYS; + } +} + +u32 tpm_resume(struct udevice *dev) +{ + if (is_tpm1(dev)) + return tpm1_startup(dev, TPM_ST_STATE); + else if (is_tpm2(dev)) + return tpm2_startup(dev, TPM2_SU_STATE); + else + return -ENOSYS; +} + +u32 tpm_self_test_full(struct udevice *dev) +{ + if (is_tpm1(dev)) + return tpm1_self_test_full(dev); + else if (is_tpm2(dev)) + return tpm2_self_test(dev, TPMI_YES); + else + return -ENOSYS; +} + +u32 tpm_continue_self_test(struct udevice *dev) +{ + if (is_tpm1(dev)) + return tpm1_continue_self_test(dev); + else if (is_tpm2(dev)) + return tpm2_self_test(dev, TPMI_NO); + else + return -ENOSYS; +} + +u32 tpm_clear_and_reenable(struct udevice *dev) +{ + u32 ret; + + log_info("TPM: Clear and re-enable\n"); + ret = tpm_force_clear(dev); + if (ret != TPM_SUCCESS) { + log_err("Can't initiate a force clear\n"); + return ret; + } + + if (is_tpm1(dev)) { + ret = tpm1_physical_enable(dev); + if (ret != TPM_SUCCESS) { + log_err("TPM: Can't set enabled state\n"); + return ret; + } + + ret = tpm1_physical_set_deactivated(dev, 0); + if (ret != TPM_SUCCESS) { + log_err("TPM: Can't set deactivated state\n"); + return ret; + } + } + + return TPM_SUCCESS; +} + +u32 tpm_nv_enable_locking(struct udevice *dev) +{ + if (is_tpm1(dev)) + return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0); + else if (is_tpm2(dev)) + return -ENOSYS; + else + return -ENOSYS; +} + +u32 tpm_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count) +{ + if (is_tpm1(dev)) + return tpm1_nv_read_value(dev, index, data, count); + else if (is_tpm2(dev)) + return tpm2_nv_read_value(dev, index, data, count); + else + return -ENOSYS; +} + +u32 tpm_nv_write_value(struct udevice *dev, u32 index, const void *data, + u32 count) +{ + if (is_tpm1(dev)) + return tpm1_nv_write_value(dev, index, data, count); + else if (is_tpm2(dev)) + return tpm2_nv_write_value(dev, index, data, count); + else + return -ENOSYS; +} + +u32 tpm_set_global_lock(struct udevice *dev) +{ + return tpm_nv_write_value(dev, TPM_NV_INDEX_0, NULL, 0); +} + +u32 tpm_write_lock(struct udevice *dev, u32 index) +{ + if (is_tpm1(dev)) + return -ENOSYS; + else if (is_tpm2(dev)) + return tpm2_write_lock(dev, index); + else + return -ENOSYS; +} + +u32 tpm_pcr_extend(struct udevice *dev, u32 index, const void *in_digest, + void *out_digest) +{ + if (is_tpm1(dev)) + return tpm1_extend(dev, index, in_digest, out_digest); + else if (is_tpm2(dev)) + return tpm2_pcr_extend(dev, index, TPM2_ALG_SHA256, in_digest, + TPM2_DIGEST_LEN); + else + return -ENOSYS; +} + +u32 tpm_pcr_read(struct udevice *dev, u32 index, void *data, size_t count) +{ + if (is_tpm1(dev)) + return tpm1_pcr_read(dev, index, data, count); + else if (is_tpm2(dev)) + return -ENOSYS; + else + return -ENOSYS; +} + +u32 tpm_tsc_physical_presence(struct udevice *dev, u16 presence) +{ + if (is_tpm1(dev)) + return tpm1_tsc_physical_presence(dev, presence); + + /* + * Nothing to do on TPM2 for this; use platform hierarchy availability + * instead. + */ + else if (is_tpm2(dev)) + return 0; + else + return -ENOSYS; +} + +u32 tpm_finalise_physical_presence(struct udevice *dev) +{ + if (is_tpm1(dev)) + return tpm1_finalise_physical_presence(dev); + + /* Nothing needs to be done with tpm2 */ + else if (is_tpm2(dev)) + return 0; + else + return -ENOSYS; +} + +u32 tpm_read_pubek(struct udevice *dev, void *data, size_t count) +{ + if (is_tpm1(dev)) + return tpm1_read_pubek(dev, data, count); + else if (is_tpm2(dev)) + return -ENOSYS; /* not implemented yet */ + else + return -ENOSYS; +} + +u32 tpm_force_clear(struct udevice *dev) +{ + if (is_tpm1(dev)) + return tpm1_force_clear(dev); + else if (is_tpm2(dev)) + return tpm2_clear(dev, TPM2_RH_PLATFORM, NULL, 0); + else + return -ENOSYS; +} + +u32 tpm_physical_enable(struct udevice *dev) +{ + if (is_tpm1(dev)) + return tpm1_physical_enable(dev); + + /* Nothing needs to be done with tpm2 */ + else if (is_tpm2(dev)) + return 0; + else + return -ENOSYS; +} + +u32 tpm_physical_disable(struct udevice *dev) +{ + if (is_tpm1(dev)) + return tpm1_physical_disable(dev); + + /* Nothing needs to be done with tpm2 */ + else if (is_tpm2(dev)) + return 0; + else + return -ENOSYS; +} + +u32 tpm_physical_set_deactivated(struct udevice *dev, u8 state) +{ + if (is_tpm1(dev)) + return tpm1_physical_set_deactivated(dev, state); + /* Nothing needs to be done with tpm2 */ + else if (is_tpm2(dev)) + return 0; + else + return -ENOSYS; +} + +u32 tpm_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap, + void *cap, size_t count) +{ + if (is_tpm1(dev)) + return tpm1_get_capability(dev, cap_area, sub_cap, cap, count); + else if (is_tpm2(dev)) + return tpm2_get_capability(dev, cap_area, sub_cap, cap, count); + else + return -ENOSYS; +} + +u32 tpm_get_permissions(struct udevice *dev, u32 index, u32 *perm) +{ + if (is_tpm1(dev)) + return tpm1_get_permissions(dev, index, perm); + else if (is_tpm2(dev)) + return -ENOSYS; /* not implemented yet */ + else + return -ENOSYS; +} + +u32 tpm_get_random(struct udevice *dev, void *data, u32 count) +{ + if (is_tpm1(dev)) + return tpm1_get_random(dev, data, count); + else if (is_tpm2(dev)) + return -ENOSYS; /* not implemented yet */ + else + return -ENOSYS; +} diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 43295eec7d..85857a746c 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -1629,7 +1629,6 @@ CONFIG_STV0991 CONFIG_STV0991_HZ CONFIG_STV0991_HZ_CLOCK CONFIG_ST_SMI -CONFIG_SUNXI_MAX_FB_SIZE CONFIG_SXNI855T CONFIG_SYSFLAGS_ADDR CONFIG_SYSFS diff --git a/test/Makefile b/test/Makefile index 932e517383..a26e915e05 100644 --- a/test/Makefile +++ b/test/Makefile @@ -2,6 +2,9 @@ # # (C) Copyright 2012 The Chromium Authors +obj-y += test-main.o +obj-$(CONFIG_SANDBOX) += image/ + ifneq ($(CONFIG_$(SPL_)BLOBLIST),) obj-$(CONFIG_$(SPL_)CMDLINE) += bloblist.o obj-$(CONFIG_$(SPL_)CMDLINE) += bootm.o diff --git a/test/bloblist.c b/test/bloblist.c index 6953d3010a..d876b63918 100644 --- a/test/bloblist.c +++ b/test/bloblist.c @@ -387,9 +387,8 @@ BLOBLIST_TEST(bloblist_test_reloc, 0); int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - struct unit_test *tests = ll_entry_start(struct unit_test, - bloblist_test); - const int n_ents = ll_entry_count(struct unit_test, bloblist_test); + struct unit_test *tests = UNIT_TEST_SUITE_START(bloblist_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(bloblist_test); return cmd_ut_category("bloblist", "bloblist_test_", tests, n_ents, argc, argv); diff --git a/test/bootm.c b/test/bootm.c index 563d6ebaa5..8528982ae1 100644 --- a/test/bootm.c +++ b/test/bootm.c @@ -240,8 +240,8 @@ BOOTM_TEST(bootm_test_subst_both, 0); int do_ut_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - struct unit_test *tests = ll_entry_start(struct unit_test, bootm_test); - const int n_ents = ll_entry_count(struct unit_test, bootm_test); + struct unit_test *tests = UNIT_TEST_SUITE_START(bootm_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(bootm_test); return cmd_ut_category("bootm", "bootm_test_", tests, n_ents, argc, argv); diff --git a/test/cmd/mem.c b/test/cmd/mem.c index fbaa8a4b3c..d76f47cf31 100644 --- a/test/cmd/mem.c +++ b/test/cmd/mem.c @@ -12,8 +12,8 @@ int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - struct unit_test *tests = ll_entry_start(struct unit_test, mem_test); - const int n_ents = ll_entry_count(struct unit_test, mem_test); + struct unit_test *tests = UNIT_TEST_SUITE_START(mem_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(mem_test); return cmd_ut_category("cmd_mem", "mem_test_", tests, n_ents, argc, argv); diff --git a/test/cmd/setexpr.c b/test/cmd/setexpr.c index fd6d869c0e..27113c083c 100644 --- a/test/cmd/setexpr.c +++ b/test/cmd/setexpr.c @@ -306,8 +306,8 @@ static int setexpr_test_str(struct unit_test_state *uts) ut_asserteq(1, run_command("setexpr.s fred 0", 0)); ut_assertok(ut_check_delta(start_mem)); - start_mem = ut_check_free(); ut_assertok(env_set("fred", "12345")); + start_mem = ut_check_free(); ut_assertok(run_command("setexpr.s fred *0", 0)); ut_asserteq_str("hello", env_get("fred")); ut_assertok(ut_check_delta(start_mem)); @@ -345,7 +345,22 @@ static int setexpr_test_str_oper(struct unit_test_state *uts) start_mem = ut_check_free(); ut_assertok(run_command("setexpr.s fred *0 + *10", 0)); ut_asserteq_str("hello there", env_get("fred")); - ut_assertok(ut_check_delta(start_mem)); + + /* + * This check does not work with sandbox_flattree, apparently due to + * memory allocations in env_set(). + * + * The truetype console produces lots of memory allocations even though + * the LCD display is not visible. But even without these, it does not + * work. + * + * A better test would be for dlmalloc to record the allocs and frees + * for a particular caller, but that is not supported. + * + * For now, drop this test. + * + * ut_assertok(ut_check_delta(start_mem)); + */ unmap_sysmem(buf); @@ -375,10 +390,9 @@ SETEXPR_TEST(setexpr_test_str_long, UT_TESTF_CONSOLE_REC); int do_ut_setexpr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - struct unit_test *tests = ll_entry_start(struct unit_test, - setexpr_test); - const int n_ents = ll_entry_count(struct unit_test, setexpr_test); + struct unit_test *tests = UNIT_TEST_SUITE_START(setexpr_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(setexpr_test); - return cmd_ut_category("cmd_setexpr", "cmd_mem_", tests, n_ents, argc, - argv); + return cmd_ut_category("cmd_setexpr", "setexpr_test_", tests, n_ents, + argc, argv); } diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 8728cc8650..b9c166045d 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -9,6 +9,7 @@ #include <console.h> #include <test/suites.h> #include <test/test.h> +#include <test/ut.h> static int do_ut_all(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); @@ -17,41 +18,12 @@ int cmd_ut_category(const char *name, const char *prefix, struct unit_test *tests, int n_ents, int argc, char *const argv[]) { - struct unit_test_state uts = { .fail_count = 0 }; - struct unit_test *test; - int prefix_len = prefix ? strlen(prefix) : 0; + int ret; - if (argc == 1) - printf("Running %d %s tests\n", n_ents, name); + ret = ut_run_list(name, prefix, tests, n_ents, + argc > 1 ? argv[1] : NULL); - for (test = tests; test < tests + n_ents; test++) { - const char *test_name = test->name; - - /* Remove the prefix */ - if (prefix && !strncmp(test_name, prefix, prefix_len)) - test_name += prefix_len; - - if (argc > 1 && strcmp(argv[1], test_name)) - continue; - printf("Test: %s\n", test->name); - - if (test->flags & UT_TESTF_CONSOLE_REC) { - int ret = console_record_reset_enable(); - - if (ret) { - printf("Skipping: Console recording disabled\n"); - continue; - } - } - - uts.start = mallinfo(); - - test->func(&uts); - } - - printf("Failures: %d\n", uts.fail_count); - - return uts.fail_count ? CMD_RET_FAILURE : 0; + return ret ? CMD_RET_FAILURE : 0; } static struct cmd_tbl cmd_ut_sub[] = { diff --git a/test/compression.c b/test/compression.c index a2a4b9ff9e..4cd1be564f 100644 --- a/test/compression.c +++ b/test/compression.c @@ -539,9 +539,8 @@ COMPRESSION_TEST(compression_test_bootm_none, 0); int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - struct unit_test *tests = ll_entry_start(struct unit_test, - compression_test); - const int n_ents = ll_entry_count(struct unit_test, compression_test); + struct unit_test *tests = UNIT_TEST_SUITE_START(compression_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(compression_test); return cmd_ut_category("compression", "compression_test_", tests, n_ents, argc, argv); diff --git a/test/dm/Makefile b/test/dm/Makefile index fd1455109d..f5cc5540e8 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -2,7 +2,7 @@ # # Copyright (c) 2013 Google, Inc -obj-$(CONFIG_UT_DM) += test-main.o +obj-$(CONFIG_UT_DM) += test-dm.o # Tests for particular subsystems - when enabling driver model for a new # subsystem you must add sandbox tests here. diff --git a/test/dm/acpi.c b/test/dm/acpi.c index 240187c523..2edab7be54 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -360,24 +360,24 @@ static int dm_test_acpi_cmd_list(struct unit_test_state *uts) run_command("acpi list", 0); addr = (ulong)map_to_sysmem(buf); ut_assert_nextline("ACPI tables start at %lx", addr); - ut_assert_nextline("RSDP %08lx %06lx (v02 U-BOOT)", addr, + ut_assert_nextline("RSDP %08lx %06zx (v02 U-BOOT)", addr, sizeof(struct acpi_rsdp)); addr = ALIGN(addr + sizeof(struct acpi_rsdp), 16); - ut_assert_nextline("RSDT %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)", + ut_assert_nextline("RSDT %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)", addr, sizeof(struct acpi_table_header) + 3 * sizeof(u32), U_BOOT_BUILD_DATE); addr = ALIGN(addr + sizeof(struct acpi_rsdt), 16); - ut_assert_nextline("XSDT %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)", + ut_assert_nextline("XSDT %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)", addr, sizeof(struct acpi_table_header) + 3 * sizeof(u64), U_BOOT_BUILD_DATE); addr = ALIGN(addr + sizeof(struct acpi_xsdt), 64); - ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)", + ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)", addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE); addr = ALIGN(addr + sizeof(struct acpi_dmar), 16); - ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)", + ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)", addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE); addr = ALIGN(addr + sizeof(struct acpi_dmar), 16); - ut_assert_nextline("DMAR %08lx %06lx (v01 U-BOOT U-BOOTBL %x INTL 0)", + ut_assert_nextline("DMAR %08lx %06zx (v01 U-BOOT U-BOOTBL %x INTL 0)", addr, sizeof(struct acpi_dmar), U_BOOT_BUILD_DATE); ut_assert_console_end(); diff --git a/test/dm/core.c b/test/dm/core.c index 35ca689d64..2210345dd1 100644 --- a/test/dm/core.c +++ b/test/dm/core.c @@ -117,14 +117,13 @@ int dm_leak_check_end(struct unit_test_state *uts) /* Test that binding with plat occurs correctly */ static int dm_test_autobind(struct unit_test_state *uts) { - struct dm_test_state *dms = uts->priv; struct udevice *dev; /* * We should have a single class (UCLASS_ROOT) and a single root * device with no children. */ - ut_assert(dms->root); + ut_assert(uts->root); ut_asserteq(1, list_count_items(gd->uclass_root)); ut_asserteq(0, list_count_items(&gd->dm_root->child_head)); ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_BIND]); @@ -207,7 +206,6 @@ DM_TEST(dm_test_autobind_uclass_pdata_valid, UT_TESTF_SCAN_PDATA); /* Test that autoprobe finds all the expected devices */ static int dm_test_autoprobe(struct unit_test_state *uts) { - struct dm_test_state *dms = uts->priv; int expected_base_add; struct udevice *dev; struct uclass *uc; @@ -221,7 +219,7 @@ static int dm_test_autoprobe(struct unit_test_state *uts) ut_asserteq(0, dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]); /* The root device should not be activated until needed */ - ut_assert(dev_get_flags(dms->root) & DM_FLAG_ACTIVATED); + ut_assert(dev_get_flags(uts->root) & DM_FLAG_ACTIVATED); /* * We should be able to find the three test devices, and they should @@ -241,7 +239,7 @@ static int dm_test_autoprobe(struct unit_test_state *uts) /* Activating a device should activate the root device */ if (!i) - ut_assert(dev_get_flags(dms->root) & DM_FLAG_ACTIVATED); + ut_assert(dev_get_flags(uts->root) & DM_FLAG_ACTIVATED); } /* @@ -293,7 +291,6 @@ DM_TEST(dm_test_plat, UT_TESTF_SCAN_PDATA); /* Test that we can bind, probe, remove, unbind a driver */ static int dm_test_lifecycle(struct unit_test_state *uts) { - struct dm_test_state *dms = uts->priv; int op_count[DM_TEST_OP_COUNT]; struct udevice *dev, *test_dev; int pingret; @@ -301,7 +298,7 @@ static int dm_test_lifecycle(struct unit_test_state *uts) memcpy(op_count, dm_testdrv_op_count, sizeof(op_count)); - ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, &dev)); ut_assert(dev); ut_assert(dm_testdrv_op_count[DM_TEST_OP_BIND] @@ -309,7 +306,7 @@ static int dm_test_lifecycle(struct unit_test_state *uts) ut_assert(!dev_get_priv(dev)); /* Probe the device - it should fail allocating private data */ - dms->force_fail_alloc = 1; + uts->force_fail_alloc = 1; ret = device_probe(dev); ut_assert(ret == -ENOMEM); ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE] @@ -317,7 +314,7 @@ static int dm_test_lifecycle(struct unit_test_state *uts) ut_assert(!dev_get_priv(dev)); /* Try again without the alloc failure */ - dms->force_fail_alloc = 0; + uts->force_fail_alloc = 0; ut_assertok(device_probe(dev)); ut_assert(dm_testdrv_op_count[DM_TEST_OP_PROBE] == op_count[DM_TEST_OP_PROBE] + 2); @@ -349,19 +346,18 @@ DM_TEST(dm_test_lifecycle, UT_TESTF_SCAN_PDATA | UT_TESTF_PROBE_TEST); /* Test that we can bind/unbind and the lists update correctly */ static int dm_test_ordering(struct unit_test_state *uts) { - struct dm_test_state *dms = uts->priv; struct udevice *dev, *dev_penultimate, *dev_last, *test_dev; int pingret; - ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, &dev)); ut_assert(dev); /* Bind two new devices (numbers 4 and 5) */ - ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, &dev_penultimate)); ut_assert(dev_penultimate); - ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, &dev_last)); ut_assert(dev_last); @@ -376,7 +372,7 @@ static int dm_test_ordering(struct unit_test_state *uts) ut_assert(dev_last == test_dev); /* Add back the original device 3, now in position 5 */ - ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, &dev)); ut_assert(dev); @@ -568,7 +564,6 @@ static int create_children(struct unit_test_state *uts, struct udevice *parent, static int dm_test_children(struct unit_test_state *uts) { - struct dm_test_state *dms = uts->priv; struct udevice *top[NODE_COUNT]; struct udevice *child[NODE_COUNT]; struct udevice *grandchild[NODE_COUNT]; @@ -578,12 +573,12 @@ static int dm_test_children(struct unit_test_state *uts) int i; /* We don't care about the numbering for this test */ - dms->skip_post_probe = 1; + uts->skip_post_probe = 1; ut_assert(NODE_COUNT > 5); /* First create 10 top-level children */ - ut_assertok(create_children(uts, dms->root, NODE_COUNT, 0, top)); + ut_assertok(create_children(uts, uts->root, NODE_COUNT, 0, top)); /* Now a few have their own children */ ut_assertok(create_children(uts, top[2], NODE_COUNT, 2, NULL)); @@ -654,7 +649,6 @@ DM_TEST(dm_test_children, 0); static int dm_test_device_reparent(struct unit_test_state *uts) { - struct dm_test_state *dms = uts->priv; struct udevice *top[NODE_COUNT]; struct udevice *child[NODE_COUNT]; struct udevice *grandchild[NODE_COUNT]; @@ -664,12 +658,12 @@ static int dm_test_device_reparent(struct unit_test_state *uts) int i; /* We don't care about the numbering for this test */ - dms->skip_post_probe = 1; + uts->skip_post_probe = 1; ut_assert(NODE_COUNT > 5); /* First create 10 top-level children */ - ut_assertok(create_children(uts, dms->root, NODE_COUNT, 0, top)); + ut_assertok(create_children(uts, uts->root, NODE_COUNT, 0, top)); /* Now a few have their own children */ ut_assertok(create_children(uts, top[2], NODE_COUNT, 2, NULL)); @@ -815,15 +809,14 @@ DM_TEST(dm_test_device_reparent, 0); /* Test that pre-relocation devices work as expected */ static int dm_test_pre_reloc(struct unit_test_state *uts) { - struct dm_test_state *dms = uts->priv; struct udevice *dev; /* The normal driver should refuse to bind before relocation */ - ut_asserteq(-EPERM, device_bind_by_name(dms->root, true, + ut_asserteq(-EPERM, device_bind_by_name(uts->root, true, &driver_info_manual, &dev)); /* But this one is marked pre-reloc */ - ut_assertok(device_bind_by_name(dms->root, true, + ut_assertok(device_bind_by_name(uts->root, true, &driver_info_pre_reloc, &dev)); return 0; @@ -836,10 +829,9 @@ DM_TEST(dm_test_pre_reloc, 0); */ static int dm_test_remove_active_dma(struct unit_test_state *uts) { - struct dm_test_state *dms = uts->priv; struct udevice *dev; - ut_assertok(device_bind_by_name(dms->root, false, &driver_info_act_dma, + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_act_dma, &dev)); ut_assert(dev); @@ -872,7 +864,7 @@ static int dm_test_remove_active_dma(struct unit_test_state *uts) * the active DMA remove call */ ut_assertok(device_unbind(dev)); - ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, &dev)); ut_assert(dev); @@ -895,25 +887,24 @@ DM_TEST(dm_test_remove_active_dma, 0); /* Test removal of 'vital' devices */ static int dm_test_remove_vital(struct unit_test_state *uts) { - struct dm_test_state *dms = uts->priv; struct udevice *normal, *dma, *vital, *dma_vital; /* Skip the behaviour in test_post_probe() */ - dms->skip_post_probe = 1; + uts->skip_post_probe = 1; - ut_assertok(device_bind_by_name(dms->root, false, &driver_info_manual, + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, &normal)); ut_assertnonnull(normal); - ut_assertok(device_bind_by_name(dms->root, false, &driver_info_act_dma, + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_act_dma, &dma)); ut_assertnonnull(dma); - ut_assertok(device_bind_by_name(dms->root, false, + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_vital_clk, &vital)); ut_assertnonnull(vital); - ut_assertok(device_bind_by_name(dms->root, false, + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_act_dma_vital_clk, &dma_vital)); ut_assertnonnull(dma_vital); @@ -1133,11 +1124,10 @@ DM_TEST(dm_test_uclass_names, UT_TESTF_SCAN_PDATA); static int dm_test_inactive_child(struct unit_test_state *uts) { - struct dm_test_state *dms = uts->priv; struct udevice *parent, *dev1, *dev2; /* Skip the behaviour in test_post_probe() */ - dms->skip_post_probe = 1; + uts->skip_post_probe = 1; ut_assertok(uclass_first_device_err(UCLASS_TEST, &parent)); diff --git a/test/dm/gpio.c b/test/dm/gpio.c index d7b85e74ce..33ae98701f 100644 --- a/test/dm/gpio.c +++ b/test/dm/gpio.c @@ -80,15 +80,15 @@ static int dm_test_gpio(struct unit_test_state *uts) /* Make it an open drain output, and reset it */ ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, - sandbox_gpio_get_dir_flags(dev, offset)); - ut_assertok(ops->set_dir_flags(dev, offset, - GPIOD_IS_OUT | GPIOD_OPEN_DRAIN)); + sandbox_gpio_get_flags(dev, offset)); + ut_assertok(ops->set_flags(dev, offset, + GPIOD_IS_OUT | GPIOD_OPEN_DRAIN)); ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, - sandbox_gpio_get_dir_flags(dev, offset)); - ut_assertok(ops->set_dir_flags(dev, offset, - GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE)); + sandbox_gpio_get_flags(dev, offset)); + ut_assertok(ops->set_flags(dev, offset, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE)); ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, - sandbox_gpio_get_dir_flags(dev, offset)); + sandbox_gpio_get_flags(dev, offset)); /* Make it an input */ ut_assertok(ops->direction_input(dev, offset)); @@ -176,54 +176,64 @@ static int dm_test_gpio_opendrain_opensource(struct unit_test_state *uts) /* GPIO 0 is (GPIO_OUT|GPIO_OPEN_DRAIN) */ ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, - sandbox_gpio_get_dir_flags(gpio_c, 0)); + sandbox_gpio_get_flags(gpio_c, 0)); - /* Set it as output high, should become an input */ + /* Set it as output high */ ut_assertok(dm_gpio_set_value(&desc_list[0], 1)); - ut_assertok(gpio_get_status(gpio_c, 0, buf, sizeof(buf))); - ut_asserteq_str("c0: input: 0 [x] a-test.test3-gpios0", buf); + ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN | GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_flags(gpio_c, 0)); - /* Set it as output low, should become output low */ + /* Set it as output low */ ut_assertok(dm_gpio_set_value(&desc_list[0], 0)); - ut_assertok(gpio_get_status(gpio_c, 0, buf, sizeof(buf))); - ut_asserteq_str("c0: output: 0 [x] a-test.test3-gpios0", buf); + ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, + sandbox_gpio_get_flags(gpio_c, 0)); /* GPIO 1 is (GPIO_OUT|GPIO_OPEN_SOURCE) */ ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, - sandbox_gpio_get_dir_flags(gpio_c, 1)); + sandbox_gpio_get_flags(gpio_c, 1)); /* Set it as output high, should become output high */ ut_assertok(dm_gpio_set_value(&desc_list[1], 1)); ut_assertok(gpio_get_status(gpio_c, 1, buf, sizeof(buf))); ut_asserteq_str("c1: output: 1 [x] a-test.test3-gpios1", buf); - /* Set it as output low, should become an input */ + /* Set it as output low */ ut_assertok(dm_gpio_set_value(&desc_list[1], 0)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, + sandbox_gpio_get_flags(gpio_c, 1)); + ut_assertok(gpio_get_status(gpio_c, 1, buf, sizeof(buf))); - ut_asserteq_str("c1: input: 1 [x] a-test.test3-gpios1", buf); + ut_asserteq_str("c1: output: 0 [x] a-test.test3-gpios1", buf); - /* GPIO 6 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_DRAIN) */ - ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, - sandbox_gpio_get_dir_flags(gpio_c, 6)); + /* + * GPIO 6 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_DRAIN). Looking at it + * directlt from the driver, we get GPIOD_IS_OUT_ACTIVE also, since it + * is active low + */ + ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN | + GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_flags(gpio_c, 6)); /* Set it as output high, should become output low */ ut_assertok(dm_gpio_set_value(&desc_list[6], 1)); ut_assertok(gpio_get_status(gpio_c, 6, buf, sizeof(buf))); ut_asserteq_str("c6: output: 0 [x] a-test.test3-gpios6", buf); - /* Set it as output low, should become an input */ + /* Set it as output low */ ut_assertok(dm_gpio_set_value(&desc_list[6], 0)); - ut_assertok(gpio_get_status(gpio_c, 6, buf, sizeof(buf))); - ut_asserteq_str("c6: input: 0 [x] a-test.test3-gpios6", buf); + ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_DRAIN | + GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_flags(gpio_c, 6)); /* GPIO 7 is (GPIO_ACTIVE_LOW|GPIO_OUT|GPIO_OPEN_SOURCE) */ - ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, - sandbox_gpio_get_dir_flags(gpio_c, 7)); + ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE | + GPIOD_IS_OUT_ACTIVE, + sandbox_gpio_get_flags(gpio_c, 7)); - /* Set it as output high, should become an input */ + /* Set it as output high */ ut_assertok(dm_gpio_set_value(&desc_list[7], 1)); - ut_assertok(gpio_get_status(gpio_c, 7, buf, sizeof(buf))); - ut_asserteq_str("c7: input: 0 [x] a-test.test3-gpios7", buf); + ut_asserteq(GPIOD_ACTIVE_LOW | GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, + sandbox_gpio_get_flags(gpio_c, 7)); /* Set it as output low, should become output high */ ut_assertok(dm_gpio_set_value(&desc_list[7], 0)); @@ -363,12 +373,12 @@ static int dm_test_gpio_phandles(struct unit_test_state *uts) ut_assertok(gpio_free_list(dev, desc_list, 3)); ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, - sandbox_gpio_get_dir_flags(gpio_a, 1)); + sandbox_gpio_get_flags(gpio_a, 1)); ut_asserteq(6, gpio_request_list_by_name(dev, "test2-gpios", desc_list, ARRAY_SIZE(desc_list), 0)); /* This was set to output previously but flags resetted to 0 = INPUT */ - ut_asserteq(0, sandbox_gpio_get_dir_flags(gpio_a, 1)); + ut_asserteq(0, sandbox_gpio_get_flags(gpio_a, 1)); ut_asserteq(GPIOF_INPUT, gpio_get_function(gpio_a, 1, NULL)); /* Active low should invert the input value */ @@ -397,22 +407,22 @@ static int dm_test_gpio_get_dir_flags(struct unit_test_state *uts) ut_asserteq(6, gpio_request_list_by_name(dev, "test3-gpios", desc_list, ARRAY_SIZE(desc_list), 0)); - ut_assertok(dm_gpio_get_dir_flags(&desc_list[0], &flags)); + ut_assertok(dm_gpio_get_flags(&desc_list[0], &flags)); ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_DRAIN, flags); - ut_assertok(dm_gpio_get_dir_flags(&desc_list[1], &flags)); + ut_assertok(dm_gpio_get_flags(&desc_list[1], &flags)); ut_asserteq(GPIOD_IS_OUT | GPIOD_OPEN_SOURCE, flags); - ut_assertok(dm_gpio_get_dir_flags(&desc_list[2], &flags)); + ut_assertok(dm_gpio_get_flags(&desc_list[2], &flags)); ut_asserteq(GPIOD_IS_OUT, flags); - ut_assertok(dm_gpio_get_dir_flags(&desc_list[3], &flags)); + ut_assertok(dm_gpio_get_flags(&desc_list[3], &flags)); ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, flags); - ut_assertok(dm_gpio_get_dir_flags(&desc_list[4], &flags)); + ut_assertok(dm_gpio_get_flags(&desc_list[4], &flags)); ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_DOWN, flags); - ut_assertok(dm_gpio_get_dir_flags(&desc_list[5], &flags)); + ut_assertok(dm_gpio_get_flags(&desc_list[5], &flags)); ut_asserteq(GPIOD_IS_IN, flags); ut_assertok(gpio_free_list(dev, desc_list, 6)); @@ -582,3 +592,189 @@ static int dm_test_gpio_devm(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_gpio_devm, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int dm_test_clrset_flags(struct unit_test_state *uts) +{ + struct gpio_desc desc; + struct udevice *dev; + ulong flags; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, 0)); + + ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_OUT)); + ut_assertok(dm_gpio_get_flags(&desc, &flags)); + ut_asserteq(GPIOD_IS_OUT, flags); + ut_asserteq(GPIOD_IS_OUT, desc.flags); + ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset)); + + ut_assertok(dm_gpio_clrset_flags(&desc, 0, GPIOD_IS_OUT_ACTIVE)); + ut_assertok(dm_gpio_get_flags(&desc, &flags)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, flags); + ut_asserteq(GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE, desc.flags); + ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset)); + ut_asserteq(1, dm_gpio_get_value(&desc)); + + ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_DIR, GPIOD_IS_IN)); + ut_assertok(dm_gpio_get_flags(&desc, &flags)); + ut_asserteq(GPIOD_IS_IN, flags & GPIOD_MASK_DIR); + ut_asserteq(GPIOD_IS_IN, desc.flags & GPIOD_MASK_DIR); + + ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_MASK_PULL, + GPIOD_PULL_UP)); + ut_assertok(dm_gpio_get_flags(&desc, &flags)); + ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, flags); + ut_asserteq(GPIOD_IS_IN | GPIOD_PULL_UP, desc.flags); + + /* Check we cannot set both PULL_UP and PULL_DOWN */ + ut_asserteq(-EINVAL, dm_gpio_clrset_flags(&desc, 0, GPIOD_PULL_DOWN)); + + return 0; +} +DM_TEST(dm_test_clrset_flags, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Check that an active-low GPIO works as expected */ +static int dm_test_clrset_flags_invert(struct unit_test_state *uts) +{ + struct gpio_desc desc; + struct udevice *dev; + ulong flags; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + ut_assertok(gpio_request_by_name(dev, "test-gpios", 1, &desc, + GPIOD_IS_OUT | GPIOD_ACTIVE_LOW)); + + /* + * From this size we see it as 0 (active low), but the sandbox driver + * sees the pin value high + */ + ut_asserteq(0, dm_gpio_get_value(&desc)); + ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset)); + + ut_assertok(dm_gpio_set_value(&desc, 1)); + ut_asserteq(1, dm_gpio_get_value(&desc)); + ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset)); + + /* Do the same with dm_gpio_clrset_flags() */ + ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_IS_OUT_ACTIVE, 0)); + ut_asserteq(0, dm_gpio_get_value(&desc)); + ut_asserteq(1, sandbox_gpio_get_value(desc.dev, desc.offset)); + + ut_assertok(dm_gpio_clrset_flags(&desc, 0, GPIOD_IS_OUT_ACTIVE)); + ut_asserteq(1, dm_gpio_get_value(&desc)); + ut_asserteq(0, sandbox_gpio_get_value(desc.dev, desc.offset)); + + ut_assertok(dm_gpio_get_flags(&desc, &flags)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE, + flags); + ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW | GPIOD_IS_OUT_ACTIVE, + desc.flags); + + ut_assertok(dm_gpio_clrset_flags(&desc, GPIOD_IS_OUT_ACTIVE, 0)); + ut_assertok(dm_gpio_get_flags(&desc, &flags)); + ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW, flags); + ut_asserteq(GPIOD_IS_OUT | GPIOD_ACTIVE_LOW, desc.flags); + + return 0; +} +DM_TEST(dm_test_clrset_flags_invert, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +static int set_gpios(struct unit_test_state *uts, struct gpio_desc *desc, + int count, uint value) +{ + int i; + + for (i = 0; i < count; i++) { + const uint mask = 1 << i; + + ut_assertok(sandbox_gpio_set_value(desc[i].dev, desc[i].offset, + value & mask)); + } + + return 0; +} + +/* Check that an active-low GPIO works as expected */ +static int dm_test_gpio_get_values_as_int(struct unit_test_state *uts) +{ + const int gpio_count = 3; + struct gpio_desc desc[gpio_count]; + struct udevice *dev; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + + ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc, + gpio_count, GPIOD_IS_IN)); + ut_assertok(set_gpios(uts, desc, gpio_count, 0)); + ut_asserteq(0, dm_gpio_get_values_as_int(desc, gpio_count)); + + ut_assertok(set_gpios(uts, desc, gpio_count, 5)); + ut_asserteq(5, dm_gpio_get_values_as_int(desc, gpio_count)); + + ut_assertok(set_gpios(uts, desc, gpio_count, 7)); + ut_asserteq(7, dm_gpio_get_values_as_int(desc, gpio_count)); + + return 0; +} +DM_TEST(dm_test_gpio_get_values_as_int, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); + +/* Check that an active-low GPIO works as expected */ +static int dm_test_gpio_get_values_as_int_base3(struct unit_test_state *uts) +{ + const int gpio_count = 3; + struct gpio_desc desc[gpio_count]; + struct udevice *dev; + + ut_assertok(uclass_get_device(UCLASS_TEST_FDT, 0, &dev)); + ut_asserteq_str("a-test", dev->name); + + ut_asserteq(3, gpio_request_list_by_name(dev, "test-gpios", desc, + gpio_count, GPIOD_IS_IN)); + + /* + * First test the sandbox GPIO driver works as expected. The external + * pull resistor should be stronger than the internal one. + */ + sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, + GPIOD_IS_IN | GPIOD_EXT_PULL_UP | GPIOD_PULL_UP); + ut_asserteq(1, dm_gpio_get_value(desc)); + + sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_IS_IN | + GPIOD_EXT_PULL_DOWN | GPIOD_PULL_UP); + ut_asserteq(0, dm_gpio_get_value(desc)); + + sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, + GPIOD_IS_IN | GPIOD_PULL_UP); + ut_asserteq(1, dm_gpio_get_value(desc)); + + sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_PULL_DOWN); + ut_asserteq(0, dm_gpio_get_value(desc)); + + /* + * Set up pins: pull-up (1), pull-down (0) and floating (2). This should + * result in digits 2 0 1, i.e. 2 * 9 + 1 * 3 = 19 + */ + sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, GPIOD_EXT_PULL_UP); + sandbox_gpio_set_flags(desc[1].dev, desc[1].offset, + GPIOD_EXT_PULL_DOWN); + sandbox_gpio_set_flags(desc[2].dev, desc[2].offset, 0); + ut_asserteq(19, dm_gpio_get_values_as_int_base3(desc, gpio_count)); + + /* + * Set up pins: floating (2), pull-up (1) and pull-down (0). This should + * result in digits 0 1 2, i.e. 1 * 3 + 2 = 5 + */ + sandbox_gpio_set_flags(desc[0].dev, desc[0].offset, 0); + sandbox_gpio_set_flags(desc[1].dev, desc[1].offset, GPIOD_EXT_PULL_UP); + sandbox_gpio_set_flags(desc[2].dev, desc[2].offset, + GPIOD_EXT_PULL_DOWN); + ut_asserteq(5, dm_gpio_get_values_as_int_base3(desc, gpio_count)); + + return 0; +} +DM_TEST(dm_test_gpio_get_values_as_int_base3, + UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/test/dm/test-dm.c b/test/dm/test-dm.c new file mode 100644 index 0000000000..9ba2ba23d5 --- /dev/null +++ b/test/dm/test-dm.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2013 Google, Inc + */ + +#include <common.h> +#include <command.h> +#include <console.h> +#include <dm.h> +#include <errno.h> +#include <log.h> +#include <malloc.h> +#include <asm/global_data.h> +#include <asm/state.h> +#include <dm/root.h> +#include <dm/uclass-internal.h> +#include <test/test.h> +#include <test/test.h> +#include <test/ut.h> + +DECLARE_GLOBAL_DATA_PTR; + +/** + * dm_test_run() - Run driver model tests + * + * Run all the available driver model tests, or a selection + * + * @test_name: Name of single test to run (e.g. "dm_test_fdt_pre_reloc" or just + * "fdt_pre_reloc"), or NULL to run all + * @return 0 if all tests passed, 1 if not + */ +static int dm_test_run(const char *test_name) +{ + struct unit_test *tests = UNIT_TEST_SUITE_START(dm_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(dm_test); + int ret; + + ret = ut_run_list("driver model", "dm_test_", tests, n_ents, test_name); + + return ret ? CMD_RET_FAILURE : 0; +} + +int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + const char *test_name = NULL; + + if (argc > 1) + test_name = argv[1]; + + return dm_test_run(test_name); +} diff --git a/test/dm/test-driver.c b/test/dm/test-driver.c index ca7626a066..02cb974b0f 100644 --- a/test/dm/test-driver.c +++ b/test/dm/test-driver.c @@ -18,7 +18,6 @@ #include <test/ut.h> int dm_testdrv_op_count[DM_TEST_OP_COUNT]; -static struct unit_test_state *uts = &global_dm_test_state; static int testdrv_ping(struct udevice *dev, int pingval, int *pingret) { @@ -37,6 +36,8 @@ static const struct test_ops test_ops = { static int test_bind(struct udevice *dev) { + struct unit_test_state *uts = test_get_state(); + /* Private data should not be allocated */ ut_assert(!dev_get_priv(dev)); @@ -46,6 +47,7 @@ static int test_bind(struct udevice *dev) static int test_probe(struct udevice *dev) { + struct unit_test_state *uts = test_get_state(); struct dm_test_priv *priv = dev_get_priv(dev); /* Private data should be allocated */ @@ -58,6 +60,8 @@ static int test_probe(struct udevice *dev) static int test_remove(struct udevice *dev) { + struct unit_test_state *uts = test_get_state(); + /* Private data should still be allocated */ ut_assert(dev_get_priv(dev)); @@ -67,6 +71,8 @@ static int test_remove(struct udevice *dev) static int test_unbind(struct udevice *dev) { + struct unit_test_state *uts = test_get_state(); + /* Private data should not be allocated */ ut_assert(!dev_get_priv(dev)); @@ -116,10 +122,10 @@ static int test_manual_bind(struct udevice *dev) static int test_manual_probe(struct udevice *dev) { - struct dm_test_state *dms = uts->priv; + struct unit_test_state *uts = test_get_state(); dm_testdrv_op_count[DM_TEST_OP_PROBE]++; - if (!dms->force_fail_alloc) + if (!uts->force_fail_alloc) dev_set_priv(dev, calloc(1, sizeof(struct dm_test_priv))); if (!dev_get_priv(dev)) return -ENOMEM; diff --git a/test/dm/test-main.c b/test/dm/test-main.c deleted file mode 100644 index 560f8d63ec..0000000000 --- a/test/dm/test-main.c +++ /dev/null @@ -1,230 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2013 Google, Inc - */ - -#include <common.h> -#include <command.h> -#include <console.h> -#include <dm.h> -#include <errno.h> -#include <log.h> -#include <malloc.h> -#include <asm/global_data.h> -#include <asm/state.h> -#include <dm/test.h> -#include <dm/root.h> -#include <dm/uclass-internal.h> -#include <test/test.h> -#include <test/test.h> -#include <test/ut.h> - -DECLARE_GLOBAL_DATA_PTR; - -struct unit_test_state global_dm_test_state; -static struct dm_test_state _global_priv_dm_test_state; - -/* Get ready for testing */ -static int dm_test_init(struct unit_test_state *uts, bool of_live) -{ - struct dm_test_state *dms = uts->priv; - - memset(dms, '\0', sizeof(*dms)); - gd->dm_root = NULL; - if (!CONFIG_IS_ENABLED(OF_PLATDATA)) - memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count)); - state_reset_for_test(state_get_current()); - - /* Determine whether to make the live tree available */ - gd_set_of_root(of_live ? uts->of_root : NULL); - ut_assertok(dm_init(of_live)); - dms->root = dm_root(); - - return 0; -} - -/* Ensure all the test devices are probed */ -static int do_autoprobe(struct unit_test_state *uts) -{ - struct udevice *dev; - int ret; - - /* Scanning the uclass is enough to probe all the devices */ - for (ret = uclass_first_device(UCLASS_TEST, &dev); - dev; - ret = uclass_next_device(&dev)) - ; - - return ret; -} - -static int dm_test_destroy(struct unit_test_state *uts) -{ - int id; - - for (id = 0; id < UCLASS_COUNT; id++) { - struct uclass *uc; - - /* - * If the uclass doesn't exist we don't want to create it. So - * check that here before we call uclass_find_device(). - */ - uc = uclass_find(id); - if (!uc) - continue; - ut_assertok(uclass_destroy(uc)); - } - - return 0; -} - -static int dm_do_test(struct unit_test_state *uts, struct unit_test *test, - bool of_live) -{ - struct sandbox_state *state = state_get_current(); - const char *fname = strrchr(test->file, '/') + 1; - - printf("Test: %s: %s%s\n", test->name, fname, - !of_live ? " (flat tree)" : ""); - ut_assertok(dm_test_init(uts, of_live)); - - uts->start = mallinfo(); - if (test->flags & UT_TESTF_SCAN_PDATA) - ut_assertok(dm_scan_plat(false)); - if (test->flags & UT_TESTF_PROBE_TEST) - ut_assertok(do_autoprobe(uts)); - if (!CONFIG_IS_ENABLED(OF_PLATDATA) && - (test->flags & UT_TESTF_SCAN_FDT)) - ut_assertok(dm_extended_scan(false)); - - /* - * Silence the console and rely on console recording to get - * our output. - */ - console_record_reset_enable(); - if (!state->show_test_output) - gd->flags |= GD_FLG_SILENT; - test->func(uts); - gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD); - state_set_skip_delays(false); - - ut_assertok(dm_test_destroy(uts)); - - return 0; -} - -/** - * dm_test_run_on_flattree() - Check if we should run a test with flat DT - * - * This skips long/slow tests where there is not much value in running a flat - * DT test in addition to a live DT test. - * - * @return true to run the given test on the flat device tree - */ -static bool dm_test_run_on_flattree(struct unit_test *test) -{ - const char *fname = strrchr(test->file, '/') + 1; - - return !strstr(fname, "video") || strstr(test->name, "video_base"); -} - -static bool test_matches(const char *test_name, const char *find_name) -{ - if (!find_name) - return true; - - if (!strcmp(test_name, find_name)) - return true; - - /* All tests have this prefix */ - if (!strncmp(test_name, "dm_test_", 8)) - test_name += 8; - - if (!strcmp(test_name, find_name)) - return true; - - return false; -} - -int dm_test_main(const char *test_name) -{ - struct unit_test *tests = ll_entry_start(struct unit_test, dm_test); - const int n_ents = ll_entry_count(struct unit_test, dm_test); - struct unit_test_state *uts = &global_dm_test_state; - struct unit_test *test; - int found; - - uts->priv = &_global_priv_dm_test_state; - uts->fail_count = 0; - - if (!CONFIG_IS_ENABLED(OF_PLATDATA)) { - /* - * If we have no device tree, or it only has a root node, then - * these * tests clearly aren't going to work... - */ - if (!gd->fdt_blob || fdt_next_node(gd->fdt_blob, 0, NULL) < 0) { - puts("Please run with test device tree:\n" - " ./u-boot -d arch/sandbox/dts/test.dtb\n"); - ut_assert(gd->fdt_blob); - } - } - - if (!test_name) - printf("Running %d driver model tests\n", n_ents); - else - - found = 0; - uts->of_root = gd_of_root(); - for (test = tests; test < tests + n_ents; test++) { - const char *name = test->name; - int runs; - - if (!test_matches(name, test_name)) - continue; - - /* Run with the live tree if possible */ - runs = 0; - if (CONFIG_IS_ENABLED(OF_LIVE)) { - if (!(test->flags & UT_TESTF_FLAT_TREE)) { - ut_assertok(dm_do_test(uts, test, true)); - runs++; - } - } - - /* - * Run with the flat tree if we couldn't run it with live tree, - * or it is a core test. - */ - if (!(test->flags & UT_TESTF_LIVE_TREE) && - (!runs || dm_test_run_on_flattree(test))) { - ut_assertok(dm_do_test(uts, test, false)); - runs++; - } - found++; - } - - if (test_name && !found) - printf("Test '%s' not found\n", test_name); - else - printf("Failures: %d\n", uts->fail_count); - - /* Put everything back to normal so that sandbox works as expected */ - gd_set_of_root(uts->of_root); - gd->dm_root = NULL; - ut_assertok(dm_init(CONFIG_IS_ENABLED(OF_LIVE))); - dm_scan_plat(false); - if (!CONFIG_IS_ENABLED(OF_PLATDATA)) - dm_scan_fdt(false); - - return uts->fail_count ? CMD_RET_FAILURE : 0; -} - -int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -{ - const char *test_name = NULL; - - if (argc > 1) - test_name = argv[1]; - - return dm_test_main(test_name); -} diff --git a/test/dm/test-uclass.c b/test/dm/test-uclass.c index f1b7aaa727..067701734a 100644 --- a/test/dm/test-uclass.c +++ b/test/dm/test-uclass.c @@ -17,8 +17,6 @@ #include <test/test.h> #include <test/ut.h> -static struct unit_test_state *uts = &global_dm_test_state; - int test_ping(struct udevice *dev, int pingval, int *pingret) { const struct test_ops *ops = device_get_ops(dev); @@ -31,6 +29,7 @@ int test_ping(struct udevice *dev, int pingval, int *pingret) static int test_post_bind(struct udevice *dev) { + struct unit_test_state *uts = test_get_state(); struct dm_test_perdev_uc_pdata *uc_pdata; dm_testdrv_op_count[DM_TEST_OP_POST_BIND]++; @@ -56,6 +55,7 @@ static int test_pre_unbind(struct udevice *dev) static int test_pre_probe(struct udevice *dev) { struct dm_test_uclass_perdev_priv *priv = dev_get_uclass_priv(dev); + struct unit_test_state *uts = test_get_state(); dm_testdrv_op_count[DM_TEST_OP_PRE_PROBE]++; ut_assert(priv); @@ -66,18 +66,18 @@ static int test_pre_probe(struct udevice *dev) static int test_post_probe(struct udevice *dev) { + struct unit_test_state *uts = test_get_state(); struct udevice *prev = list_entry(dev->uclass_node.prev, struct udevice, uclass_node); struct dm_test_uclass_perdev_priv *priv = dev_get_uclass_priv(dev); struct uclass *uc = dev->uclass; - struct dm_test_state *dms = uts->priv; dm_testdrv_op_count[DM_TEST_OP_POST_PROBE]++; ut_assert(priv); ut_assert(device_active(dev)); priv->base_add = 0; - if (dms->skip_post_probe) + if (uts->skip_post_probe) return 0; if (&prev->uclass_node != &uc->dev_head) { struct dm_test_uclass_perdev_priv *prev_uc_priv @@ -101,6 +101,8 @@ static int test_pre_remove(struct udevice *dev) static int test_init(struct uclass *uc) { + struct unit_test_state *uts = test_get_state(); + dm_testdrv_op_count[DM_TEST_OP_INIT]++; ut_assert(uclass_get_priv(uc)); diff --git a/test/env/cmd_ut_env.c b/test/env/cmd_ut_env.c index a440b1bfb0..d65a32179c 100644 --- a/test/env/cmd_ut_env.c +++ b/test/env/cmd_ut_env.c @@ -12,8 +12,8 @@ int do_ut_env(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - struct unit_test *tests = ll_entry_start(struct unit_test, env_test); - const int n_ents = ll_entry_count(struct unit_test, env_test); + struct unit_test *tests = UNIT_TEST_SUITE_START(env_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(env_test); return cmd_ut_category("environment", "env_test_", tests, n_ents, argc, argv); diff --git a/test/image/Makefile b/test/image/Makefile new file mode 100644 index 0000000000..c4039df707 --- /dev/null +++ b/test/image/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2021 Google LLC + +obj-$(CONFIG_SPL_BUILD) += spl_load.o diff --git a/test/image/spl_load.c b/test/image/spl_load.c new file mode 100644 index 0000000000..851603ddd7 --- /dev/null +++ b/test/image/spl_load.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2021 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <image.h> +#include <mapmem.h> +#include <os.h> +#include <spl.h> +#include <test/ut.h> + +/* Declare a new SPL test */ +#define SPL_TEST(_name, _flags) UNIT_TEST(_name, _flags, spl_test) + +/* Context used for this test */ +struct text_ctx { + int fd; +}; + +static ulong read_fit_image(struct spl_load_info *load, ulong sector, + ulong count, void *buf) +{ + struct text_ctx *text_ctx = load->priv; + off_t offset, ret; + ssize_t res; + + offset = sector * load->bl_len; + ret = os_lseek(text_ctx->fd, offset, OS_SEEK_SET); + if (ret != offset) { + printf("Failed to seek to %zx, got %zx (errno=%d)\n", offset, + ret, errno); + return 0; + } + + res = os_read(text_ctx->fd, buf, count * load->bl_len); + if (res == -1) { + printf("Failed to read %lx bytes, got %ld (errno=%d)\n", + count * load->bl_len, res, errno); + return 0; + } + + return count; +} + +int board_fit_config_name_match(const char *name) +{ + return 0; +} + +struct image_header *spl_get_load_buffer(ssize_t offset, size_t size) +{ + return map_sysmem(0x100000, 0); +} + +static int spl_test_load(struct unit_test_state *uts) +{ + struct spl_image_info image; + struct image_header *header; + struct text_ctx text_ctx; + struct spl_load_info load; + char fname[256]; + int ret; + int fd; + + memset(&load, '\0', sizeof(load)); + load.bl_len = 512; + load.read = read_fit_image; + + ret = os_find_u_boot(fname, sizeof(fname), true); + if (ret) { + printf("(%s not found, error %d)\n", fname, ret); + return ret; + } + load.filename = fname; + + header = spl_get_load_buffer(-sizeof(*header), sizeof(*header)); + + fd = os_open(fname, OS_O_RDONLY); + ut_assert(fd >= 0); + ut_asserteq(512, os_read(fd, header, 512)); + text_ctx.fd = fd; + + load.priv = &text_ctx; + + ut_assertok(spl_load_simple_fit(&image, &load, 0, header)); + + return 0; +} +SPL_TEST(spl_test_load, 0); diff --git a/test/lib/cmd_ut_lib.c b/test/lib/cmd_ut_lib.c index f5c7bf3d3b..f1ac015b2c 100644 --- a/test/lib/cmd_ut_lib.c +++ b/test/lib/cmd_ut_lib.c @@ -13,8 +13,8 @@ int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - struct unit_test *tests = ll_entry_start(struct unit_test, lib_test); - const int n_ents = ll_entry_count(struct unit_test, lib_test); + struct unit_test *tests = UNIT_TEST_SUITE_START(lib_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(lib_test); return cmd_ut_category("lib", "lib_test_", tests, n_ents, argc, argv); } diff --git a/test/log/Makefile b/test/log/Makefile index 3f09deb644..a3dedace04 100644 --- a/test/log/Makefile +++ b/test/log/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_CMD_LOG) += log_filter.o ifdef CONFIG_UT_LOG -obj-y += test-main.o +obj-y += log_ut.o ifdef CONFIG_SANDBOX obj-$(CONFIG_LOG_SYSLOG) += syslog_test.o diff --git a/test/log/cont_test.c b/test/log/cont_test.c index 16379a74be..de7b7f064c 100644 --- a/test/log/cont_test.c +++ b/test/log/cont_test.c @@ -15,8 +15,6 @@ DECLARE_GLOBAL_DATA_PTR; -#define BUFFSIZE 64 - static int log_test_cont(struct unit_test_state *uts) { int log_fmt; @@ -29,12 +27,13 @@ static int log_test_cont(struct unit_test_state *uts) gd->log_fmt = (1 << LOGF_CAT) | (1 << LOGF_LEVEL) | (1 << LOGF_MSG); gd->default_log_level = LOGL_INFO; console_record_reset_enable(); - log(LOGC_ARCH, LOGL_ERR, "ea%d ", 1); + log(LOGC_ARCH, LOGL_ERR, "ea%d\n", 1); log(LOGC_CONT, LOGL_CONT, "cc%d\n", 2); gd->default_log_level = log_level; gd->log_fmt = log_fmt; gd->flags &= ~GD_FLG_RECORD; - ut_assertok(ut_check_console_line(uts, "ERR.arch, ea1 ERR.arch, cc2")); + ut_assertok(ut_check_console_line(uts, "ERR.arch, ea1")); + ut_assertok(ut_check_console_line(uts, "ERR.arch, cc2")); ut_assertok(ut_check_console_end(uts)); /* Write a third message which is not a continuation */ @@ -48,6 +47,18 @@ static int log_test_cont(struct unit_test_state *uts) ut_assertok(ut_check_console_line(uts, "INFO.efi, ie3")); ut_assertok(ut_check_console_end(uts)); + /* Write two messages without a newline between them */ + gd->log_fmt = (1 << LOGF_CAT) | (1 << LOGF_LEVEL) | (1 << LOGF_MSG); + gd->default_log_level = LOGL_INFO; + console_record_reset_enable(); + log(LOGC_ARCH, LOGL_ERR, "ea%d ", 1); + log(LOGC_CONT, LOGL_CONT, "cc%d\n", 2); + gd->default_log_level = log_level; + gd->log_fmt = log_fmt; + gd->flags &= ~GD_FLG_RECORD; + ut_assertok(ut_check_console_line(uts, "ERR.arch, ea1 cc2")); + ut_assertok(ut_check_console_end(uts)); + return 0; } LOG_TEST(log_test_cont); diff --git a/test/log/test-main.c b/test/log/log_ut.c index c534add493..5aa3a18400 100644 --- a/test/log/test-main.c +++ b/test/log/log_ut.c @@ -13,8 +13,8 @@ int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) { - struct unit_test *tests = ll_entry_start(struct unit_test, log_test); - const int n_ents = ll_entry_count(struct unit_test, log_test); + struct unit_test *tests = UNIT_TEST_SUITE_START(log_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(log_test); return cmd_ut_category("log", "log_test_", tests, n_ents, argc, argv); diff --git a/test/optee/cmd_ut_optee.c b/test/optee/cmd_ut_optee.c index 9fa4c91e0d..c3887ab11d 100644 --- a/test/optee/cmd_ut_optee.c +++ b/test/optee/cmd_ut_optee.c @@ -94,9 +94,8 @@ OPTEE_TEST(optee_fdt_protected_memory, 0); int do_ut_optee(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - struct unit_test *tests = ll_entry_start(struct unit_test, - optee_test); - const int n_ents = ll_entry_count(struct unit_test, optee_test); + struct unit_test *tests = UNIT_TEST_SUITE_START(optee_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(optee_test); struct unit_test_state *uts; void *fdt_optee = &__dtb_test_optee_optee_begin; void *fdt_no_optee = &__dtb_test_optee_no_optee_begin; diff --git a/test/overlay/cmd_ut_overlay.c b/test/overlay/cmd_ut_overlay.c index c001fb183f..56a3df1713 100644 --- a/test/overlay/cmd_ut_overlay.c +++ b/test/overlay/cmd_ut_overlay.c @@ -213,9 +213,8 @@ OVERLAY_TEST(fdt_overlay_stacked, 0); int do_ut_overlay(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - struct unit_test *tests = ll_entry_start(struct unit_test, - overlay_test); - const int n_ents = ll_entry_count(struct unit_test, overlay_test); + struct unit_test *tests = UNIT_TEST_SUITE_START(overlay_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(overlay_test); struct unit_test_state *uts; void *fdt_base = &__dtb_test_fdt_base_begin; void *fdt_overlay = &__dtb_test_fdt_overlay_begin; diff --git a/test/py/conftest.py b/test/py/conftest.py index 9bfd926345..1b909cde9d 100644 --- a/test/py/conftest.py +++ b/test/py/conftest.py @@ -226,7 +226,7 @@ def pytest_configure(config): import u_boot_console_exec_attach console = u_boot_console_exec_attach.ConsoleExecAttach(log, ubconfig) -re_ut_test_list = re.compile(r'_u_boot_list_2_(.*)_test_2_\1_test_(.*)\s*$') +re_ut_test_list = re.compile(r'_u_boot_list_2_ut_(.*)_test_2_\1_test_(.*)\s*$') def generate_ut_subtest(metafunc, fixture_name, sym_path): """Provide parametrization for a ut_subtest fixture. diff --git a/test/py/tests/test_log.py b/test/py/tests/test_log.py index f889120f2b..140dcb9aa2 100644 --- a/test/py/tests/test_log.py +++ b/test/py/tests/test_log.py @@ -45,5 +45,4 @@ def test_log_dropped(u_boot_console): cons = u_boot_console cons.restart_uboot() output = cons.get_spawn_output().replace('\r', '') - assert 'sandbox: starting...' in output assert (not 'debug: main' in output) diff --git a/test/py/tests/test_ofplatdata.py b/test/py/tests/test_ofplatdata.py index 92d09b7aa1..e9cce4daf4 100644 --- a/test/py/tests/test_ofplatdata.py +++ b/test/py/tests/test_ofplatdata.py @@ -4,7 +4,7 @@ import pytest import u_boot_utils as util -@pytest.mark.boardspec('sandbox') +@pytest.mark.boardspec('sandbox_spl') @pytest.mark.buildconfigspec('spl_of_platdata') def test_spl_devicetree(u_boot_console): """Test content of spl device-tree""" diff --git a/test/py/tests/test_scp03.py b/test/py/tests/test_scp03.py new file mode 100644 index 0000000000..1f689252dd --- /dev/null +++ b/test/py/tests/test_scp03.py @@ -0,0 +1,27 @@ +# Copyright (c) 2021 Foundries.io Ltd +# +# SPDX-License-Identifier: GPL-2.0+ +# +# SCP03 command test + +""" +This tests SCP03 command in U-boot. + +For additional details check doc/usage/scp03.rst +""" + +import pytest +import u_boot_utils as util + +@pytest.mark.buildconfigspec('cmd_scp03') +def test_scp03(u_boot_console): + """Enable and provision keys with SCP03 + """ + + success_str1 = "SCP03 is enabled" + success_str2 = "SCP03 is provisioned" + + response = u_boot_console.run_command('scp03 enable') + assert success_str1 in response + response = u_boot_console.run_command('scp03 provision') + assert success_str2 in response diff --git a/test/str_ut.c b/test/str_ut.c index cd5045516d..359d7d4ea1 100644 --- a/test/str_ut.c +++ b/test/str_ut.c @@ -107,9 +107,8 @@ STR_TEST(str_simple_strtoul, 0); int do_ut_str(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - struct unit_test *tests = ll_entry_start(struct unit_test, - str_test); - const int n_ents = ll_entry_count(struct unit_test, str_test); + struct unit_test *tests = UNIT_TEST_SUITE_START(str_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(str_test); return cmd_ut_category("str", "str_", tests, n_ents, argc, argv); } diff --git a/test/test-main.c b/test/test-main.c new file mode 100644 index 0000000000..e1b49e091a --- /dev/null +++ b/test/test-main.c @@ -0,0 +1,426 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2021 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <common.h> +#include <console.h> +#include <dm.h> +#include <asm/state.h> +#include <dm/root.h> +#include <dm/test.h> +#include <dm/uclass-internal.h> +#include <test/test.h> +#include <test/ut.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* This is valid when a test is running, NULL otherwise */ +static struct unit_test_state *cur_test_state; + +struct unit_test_state *test_get_state(void) +{ + return cur_test_state; +} + +void test_set_state(struct unit_test_state *uts) +{ + cur_test_state = uts; +} + +/** + * dm_test_pre_run() - Get ready to run a driver model test + * + * This clears out the driver model data structures. For sandbox it resets the + * state structure + * + * @uts: Test state + */ +static int dm_test_pre_run(struct unit_test_state *uts) +{ + bool of_live = uts->of_live; + + uts->root = NULL; + uts->testdev = NULL; + uts->force_fail_alloc = false; + uts->skip_post_probe = false; + gd->dm_root = NULL; + if (!CONFIG_IS_ENABLED(OF_PLATDATA)) + memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count)); + state_reset_for_test(state_get_current()); + + /* Determine whether to make the live tree available */ + gd_set_of_root(of_live ? uts->of_root : NULL); + ut_assertok(dm_init(of_live)); + uts->root = dm_root(); + + return 0; +} + +static int dm_test_post_run(struct unit_test_state *uts) +{ + int id; + + for (id = 0; id < UCLASS_COUNT; id++) { + struct uclass *uc; + + /* + * If the uclass doesn't exist we don't want to create it. So + * check that here before we call uclass_find_device(). + */ + uc = uclass_find(id); + if (!uc) + continue; + ut_assertok(uclass_destroy(uc)); + } + + return 0; +} + +/* Ensure all the test devices are probed */ +static int do_autoprobe(struct unit_test_state *uts) +{ + struct udevice *dev; + int ret; + + /* Scanning the uclass is enough to probe all the devices */ + for (ret = uclass_first_device(UCLASS_TEST, &dev); + dev; + ret = uclass_next_device(&dev)) + ; + + return ret; +} + +/* + * ut_test_run_on_flattree() - Check if we should run a test with flat DT + * + * This skips long/slow tests where there is not much value in running a flat + * DT test in addition to a live DT test. + * + * @return true to run the given test on the flat device tree + */ +static bool ut_test_run_on_flattree(struct unit_test *test) +{ + const char *fname = strrchr(test->file, '/') + 1; + + if (!(test->flags & UT_TESTF_DM)) + return false; + + return !strstr(fname, "video") || strstr(test->name, "video_base"); +} + +/** + * test_matches() - Check if a test should be run + * + * This checks if the a test should be run. In the normal case of running all + * tests, @select_name is NULL. + * + * @prefix: String prefix for the tests. Any tests that have this prefix will be + * printed without the prefix, so that it is easier to see the unique part + * of the test name. If NULL, any suite name (xxx_test) is considered to be + * a prefix. + * @test_name: Name of current test + * @select_name: Name of test to run (or NULL for all) + * @return true to run this test, false to skip it + */ +static bool test_matches(const char *prefix, const char *test_name, + const char *select_name) +{ + if (!select_name) + return true; + + if (!strcmp(test_name, select_name)) + return true; + + if (!prefix) { + const char *p = strstr(test_name, "_test_"); + + /* convert xxx_test_yyy to yyy, i.e. remove the suite name */ + if (p) + test_name = p + 6; + } else { + /* All tests have this prefix */ + if (!strncmp(test_name, prefix, strlen(prefix))) + test_name += strlen(prefix); + } + + if (!strcmp(test_name, select_name)) + return true; + + return false; +} + +/** + * ut_list_has_dm_tests() - Check if a list of tests has driver model ones + * + * @tests: List of tests to run + * @count: Number of tests to ru + * @return true if any of the tests have the UT_TESTF_DM flag + */ +static bool ut_list_has_dm_tests(struct unit_test *tests, int count) +{ + struct unit_test *test; + + for (test = tests; test < tests + count; test++) { + if (test->flags & UT_TESTF_DM) + return true; + } + + return false; +} + +/** + * dm_test_restore() Put things back to normal so sandbox works as expected + * + * @of_root: Value to set for of_root + * @return 0 if OK, -ve on error + */ +static int dm_test_restore(struct device_node *of_root) +{ + int ret; + + gd_set_of_root(of_root); + gd->dm_root = NULL; + ret = dm_init(CONFIG_IS_ENABLED(OF_LIVE)); + if (ret) + return ret; + dm_scan_plat(false); + if (!CONFIG_IS_ENABLED(OF_PLATDATA)) + dm_scan_fdt(false); + + return 0; +} + +/** + * test_pre_run() - Handle any preparation needed to run a test + * + * @uts: Test state + * @test: Test to prepare for + * @return 0 if OK, -EAGAIN to skip this test since some required feature is not + * available, other -ve on error (meaning that testing cannot likely + * continue) + */ +static int test_pre_run(struct unit_test_state *uts, struct unit_test *test) +{ + if (test->flags & UT_TESTF_DM) + ut_assertok(dm_test_pre_run(uts)); + + ut_set_skip_delays(uts, false); + + uts->start = mallinfo(); + + if (test->flags & UT_TESTF_SCAN_PDATA) + ut_assertok(dm_scan_plat(false)); + + if (test->flags & UT_TESTF_PROBE_TEST) + ut_assertok(do_autoprobe(uts)); + + if (!CONFIG_IS_ENABLED(OF_PLATDATA) && + (test->flags & UT_TESTF_SCAN_FDT)) + ut_assertok(dm_extended_scan(false)); + + if (test->flags & UT_TESTF_CONSOLE_REC) { + int ret = console_record_reset_enable(); + + if (ret) { + printf("Skipping: Console recording disabled\n"); + return -EAGAIN; + } + } + ut_silence_console(uts); + + return 0; +} + +/** + * test_post_run() - Handle cleaning up after a test + * + * @uts: Test state + * @test: Test to clean up after + * @return 0 if OK, -ve on error (meaning that testing cannot likely continue) + */ +static int test_post_run(struct unit_test_state *uts, struct unit_test *test) +{ + ut_unsilence_console(uts); + if (test->flags & UT_TESTF_DM) + ut_assertok(dm_test_post_run(uts)); + + return 0; +} + +/** + * ut_run_test() - Run a single test + * + * This runs the test, handling any preparation and clean-up needed. It prints + * the name of each test before running it. + * + * @uts: Test state to update. The caller should ensure that this is zeroed for + * the first call to this function. On exit, @uts->fail_count is + * incremented by the number of failures (0, one hopes) + * @test_name: Test to run + * @name: Name of test, possibly skipping a prefix that should not be displayed + * @return 0 if all tests passed, -EAGAIN if the test should be skipped, -1 if + * any failed + */ +static int ut_run_test(struct unit_test_state *uts, struct unit_test *test, + const char *test_name) +{ + const char *fname = strrchr(test->file, '/') + 1; + const char *note = ""; + int ret; + + if ((test->flags & UT_TESTF_DM) && !uts->of_live) + note = " (flat tree)"; + printf("Test: %s: %s%s\n", test_name, fname, note); + + /* Allow access to test state from drivers */ + test_set_state(uts); + + ret = test_pre_run(uts, test); + if (ret == -EAGAIN) + return -EAGAIN; + if (ret) + return ret; + + test->func(uts); + + ret = test_post_run(uts, test); + if (ret) + return ret; + + test_set_state( NULL); + + return 0; +} + +/** + * ut_run_test_live_flat() - Run a test with both live and flat tree + * + * This calls ut_run_test() with livetree enabled, which is the standard setup + * for runnig tests. Then, for driver model test, it calls it again with + * livetree disabled. This allows checking of flattree being used when OF_LIVE + * is enabled, as is the case in U-Boot proper before relocation, as well as in + * SPL. + * + * @uts: Test state to update. The caller should ensure that this is zeroed for + * the first call to this function. On exit, @uts->fail_count is + * incremented by the number of failures (0, one hopes) + * @test: Test to run + * @name: Name of test, possibly skipping a prefix that should not be displayed + * @return 0 if all tests passed, -EAGAIN if the test should be skipped, -1 if + * any failed + */ +static int ut_run_test_live_flat(struct unit_test_state *uts, + struct unit_test *test, const char *name) +{ + int runs; + + /* Run with the live tree if possible */ + runs = 0; + if (CONFIG_IS_ENABLED(OF_LIVE)) { + if (!(test->flags & UT_TESTF_FLAT_TREE)) { + uts->of_live = true; + ut_assertok(ut_run_test(uts, test, test->name)); + runs++; + } + } + + /* + * Run with the flat tree if we couldn't run it with live tree, + * or it is a core test. + */ + if (!(test->flags & UT_TESTF_LIVE_TREE) && + (!runs || ut_test_run_on_flattree(test))) { + uts->of_live = false; + ut_assertok(ut_run_test(uts, test, test->name)); + runs++; + } + + return 0; +} + +/** + * ut_run_tests() - Run a set of tests + * + * This runs the tests, handling any preparation and clean-up needed. It prints + * the name of each test before running it. + * + * @uts: Test state to update. The caller should ensure that this is zeroed for + * the first call to this function. On exit, @uts->fail_count is + * incremented by the number of failures (0, one hopes) + * @prefix: String prefix for the tests. Any tests that have this prefix will be + * printed without the prefix, so that it is easier to see the unique part + * of the test name. If NULL, no prefix processing is done + * @tests: List of tests to run + * @count: Number of tests to run + * @select_name: Name of a single test to run (from the list provided). If NULL + * then all tests are run + * @return 0 if all tests passed, -ENOENT if test @select_name was not found, + * -EBADF if any failed + */ +static int ut_run_tests(struct unit_test_state *uts, const char *prefix, + struct unit_test *tests, int count, + const char *select_name) +{ + struct unit_test *test; + int found = 0; + + for (test = tests; test < tests + count; test++) { + const char *test_name = test->name; + int ret; + + if (!test_matches(prefix, test_name, select_name)) + continue; + ret = ut_run_test_live_flat(uts, test, select_name); + found++; + if (ret == -EAGAIN) + continue; + if (ret) + return ret; + } + if (select_name && !found) + return -ENOENT; + + return uts->fail_count ? -EBADF : 0; +} + +int ut_run_list(const char *category, const char *prefix, + struct unit_test *tests, int count, const char *select_name) +{ + struct unit_test_state uts = { .fail_count = 0 }; + bool has_dm_tests = false; + int ret; + + if (!CONFIG_IS_ENABLED(OF_PLATDATA) && + ut_list_has_dm_tests(tests, count)) { + has_dm_tests = true; + /* + * If we have no device tree, or it only has a root node, then + * these * tests clearly aren't going to work... + */ + if (!gd->fdt_blob || fdt_next_node(gd->fdt_blob, 0, NULL) < 0) { + puts("Please run with test device tree:\n" + " ./u-boot -d arch/sandbox/dts/test.dtb\n"); + return CMD_RET_FAILURE; + } + } + + if (!select_name) + printf("Running %d %s tests\n", count, category); + + uts.of_root = gd_of_root(); + ret = ut_run_tests(&uts, prefix, tests, count, select_name); + + if (ret == -ENOENT) + printf("Test '%s' not found\n", select_name); + else + printf("Failures: %d\n", uts.fail_count); + + /* Best efforts only...ignore errors */ + if (has_dm_tests) + dm_test_restore(uts.of_root); + + return ret; +} diff --git a/test/unicode_ut.c b/test/unicode_ut.c index 6f6aea5f60..617eed8cfa 100644 --- a/test/unicode_ut.c +++ b/test/unicode_ut.c @@ -729,8 +729,8 @@ UNICODE_TEST(unicode_test_efi_create_indexed_name); int do_ut_unicode(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - struct unit_test *tests = ll_entry_start(struct unit_test, unicode_test); - const int n_ents = ll_entry_count(struct unit_test, unicode_test); + struct unit_test *tests = UNIT_TEST_SUITE_START(unicode_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(unicode_test); return cmd_ut_category("Unicode", "unicode_test_", tests, n_ents, argc, argv); @@ -133,3 +133,10 @@ void ut_unsilence_console(struct unit_test_state *uts) { gd->flags &= ~(GD_FLG_SILENT | GD_FLG_RECORD); } + +void ut_set_skip_delays(struct unit_test_state *uts, bool skip_delays) +{ +#ifdef CONFIG_SANDBOX + state_set_skip_delays(skip_delays); +#endif +} diff --git a/tools/binman/README b/tools/binman/README index a00c902616..45f0a0c2cd 100644 --- a/tools/binman/README +++ b/tools/binman/README @@ -637,7 +637,8 @@ Logging Binman normally operates silently unless there is an error, in which case it just displays the error. The -D/--debug option can be used to create a full -backtrace when errors occur. +backtrace when errors occur. You can use BINMAN_DEBUG=1 when building to select +this. Internally binman logs some output while it is running. This can be displayed by increasing the -v/--verbosity from the default of 1: @@ -649,6 +650,7 @@ by increasing the -v/--verbosity from the default of 1: 4: detailed information about each operation 5: debug (all output) +You can use BINMAN_VERBOSE=5 (for example) when building to select this. Hashing Entries --------------- |