diff options
author | Tom Rini <trini@konsulko.com> | 2018-07-19 11:48:33 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2018-07-19 11:48:33 -0400 |
commit | f7e48c54b246c460503e90315d0cd50ccbd586c6 (patch) | |
tree | 836d7fd9f833b285645a33e457b74be6110a0e08 /board | |
parent | 1adbf2966adebe67de3dd17094749d387604194e (diff) | |
parent | 577012da71ea9dcf07272c7f458218aa8ab29984 (diff) |
Merge tag 'xilinx-for-v2018.09' of git://git.denx.de/u-boot-microblaze
Xilinx changes for v2018.09
clk:
- Fix zynqmp clock driver
common:
- Handle CMD_RET_USAGE in cmd_process_error
- Use return macros in cmd_process_error
- Fix duplication of CONFIG_SYS_PROMPT_HUSH_PS2
- Support watchdog in usb_kbd.c
- Fix name usage in usb_kbd.c
- Support systems with non zero memory start initialized from DT only
gpio:
- Add support for manual relocation in uclass
- zynq - use live tree
- zynq - fix match data reading
- zynq - setup bank name
- xilinx - convert driver to DM
microblaze:
- Use generic iounmap/ioremap implementations
- Redesign reset logic with sysreset features
- Use watchdog and gpio over DM
- Remove unused macros and fix some checkpatch issues
- Fix timer initialization not to be called twice
serial:
- zynq - Use platdata intead of priv data
sysreset:
- Add support for manual relocation in uclass
- Add gpio-restart driver
- Add microblaze soft reset driver
watchdog:
- Add support for aliases in uclass
- Add support for manual relocation in uclass
- Convert xilinx driver to DM
- cadence - update info in the driver and not stop wdt in probe
xilinx:
- Enable LED gpio for some targets with gpio-leds DT node
- Setup variables via Kconfig
zynq:
- Add support for watchdog aliases
- Add support for mini nand/nor configurations
- Wire FPGA initalization in SPL
zynqmp:
- Enable mass storage for zcu100
- Handle external pmufw files
- Add support for secure images
- Some Kconfig movements and alignments
- Add support for watchdog aliases
- Use subcommands style for platform command
- Add mmio_read/write platform commands
- DT updates
- Add support for mini qspi configuration
Diffstat (limited to 'board')
32 files changed, 926 insertions, 106 deletions
diff --git a/board/broadcom/bcmstb/bcmstb.c b/board/broadcom/bcmstb/bcmstb.c index 25cd354998..56328463ae 100644 --- a/board/broadcom/bcmstb/bcmstb.c +++ b/board/broadcom/bcmstb/bcmstb.c @@ -48,7 +48,7 @@ int print_cpuinfo(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/emulation/qemu-arm/qemu-arm.c b/board/emulation/qemu-arm/qemu-arm.c index 085cbbef99..1f5a33d520 100644 --- a/board/emulation/qemu-arm/qemu-arm.c +++ b/board/emulation/qemu-arm/qemu-arm.c @@ -47,7 +47,7 @@ int board_init(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/renesas/alt/alt.c b/board/renesas/alt/alt.c index 86e9d2446d..b18ab7ce88 100644 --- a/board/renesas/alt/alt.c +++ b/board/renesas/alt/alt.c @@ -78,7 +78,7 @@ int board_init(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/renesas/blanche/blanche.c b/board/renesas/blanche/blanche.c index 7d48d0faf9..f5ada6e288 100644 --- a/board/renesas/blanche/blanche.c +++ b/board/renesas/blanche/blanche.c @@ -339,7 +339,7 @@ int board_eth_init(bd_t *bis) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/renesas/draak/draak.c b/board/renesas/draak/draak.c index f804fae6ee..852fdda843 100644 --- a/board/renesas/draak/draak.c +++ b/board/renesas/draak/draak.c @@ -96,7 +96,7 @@ int board_init(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/renesas/eagle/eagle.c b/board/renesas/eagle/eagle.c index 7b89c10cc7..9317410071 100644 --- a/board/renesas/eagle/eagle.c +++ b/board/renesas/eagle/eagle.c @@ -74,7 +74,7 @@ int board_init(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/renesas/ebisu/ebisu.c b/board/renesas/ebisu/ebisu.c index fdff2a8286..248223b444 100644 --- a/board/renesas/ebisu/ebisu.c +++ b/board/renesas/ebisu/ebisu.c @@ -50,7 +50,7 @@ int board_init(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/renesas/gose/gose.c b/board/renesas/gose/gose.c index 96ac29d9ab..282381ede5 100644 --- a/board/renesas/gose/gose.c +++ b/board/renesas/gose/gose.c @@ -83,7 +83,7 @@ int board_init(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/renesas/koelsch/koelsch.c b/board/renesas/koelsch/koelsch.c index b6688a2cc0..52f37c970e 100644 --- a/board/renesas/koelsch/koelsch.c +++ b/board/renesas/koelsch/koelsch.c @@ -85,7 +85,7 @@ int board_init(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/renesas/lager/lager.c b/board/renesas/lager/lager.c index 6bfb0d1404..062e88c198 100644 --- a/board/renesas/lager/lager.c +++ b/board/renesas/lager/lager.c @@ -94,7 +94,7 @@ int board_init(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/renesas/porter/porter.c b/board/renesas/porter/porter.c index cadff2cd02..663b8001ef 100644 --- a/board/renesas/porter/porter.c +++ b/board/renesas/porter/porter.c @@ -83,7 +83,7 @@ int board_init(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/renesas/salvator-x/salvator-x.c b/board/renesas/salvator-x/salvator-x.c index 651877cac2..00256bc1a3 100644 --- a/board/renesas/salvator-x/salvator-x.c +++ b/board/renesas/salvator-x/salvator-x.c @@ -108,7 +108,7 @@ int board_init(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/renesas/silk/silk.c b/board/renesas/silk/silk.c index 5fa472ce81..966c0717b2 100644 --- a/board/renesas/silk/silk.c +++ b/board/renesas/silk/silk.c @@ -78,7 +78,7 @@ int board_init(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/renesas/stout/stout.c b/board/renesas/stout/stout.c index 778593b9ba..85e30db635 100644 --- a/board/renesas/stout/stout.c +++ b/board/renesas/stout/stout.c @@ -97,7 +97,7 @@ int board_init(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/renesas/ulcb/ulcb.c b/board/renesas/ulcb/ulcb.c index 9e15e45a30..213e869ebe 100644 --- a/board/renesas/ulcb/ulcb.c +++ b/board/renesas/ulcb/ulcb.c @@ -96,7 +96,7 @@ int board_init(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/st/stm32f429-discovery/stm32f429-discovery.c b/board/st/stm32f429-discovery/stm32f429-discovery.c index b7638c0f6a..e800d70f76 100644 --- a/board/st/stm32f429-discovery/stm32f429-discovery.c +++ b/board/st/stm32f429-discovery/stm32f429-discovery.c @@ -29,7 +29,7 @@ int dram_init(void) return rv; } - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) rv = -EINVAL; return rv; diff --git a/board/st/stm32f429-evaluation/stm32f429-evaluation.c b/board/st/stm32f429-evaluation/stm32f429-evaluation.c index 2e638c6059..fd2109b27c 100644 --- a/board/st/stm32f429-evaluation/stm32f429-evaluation.c +++ b/board/st/stm32f429-evaluation/stm32f429-evaluation.c @@ -23,7 +23,7 @@ int dram_init(void) return rv; } - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) rv = -EINVAL; return rv; diff --git a/board/st/stm32f469-discovery/stm32f469-discovery.c b/board/st/stm32f469-discovery/stm32f469-discovery.c index 90d7045e9a..a457f90952 100644 --- a/board/st/stm32f469-discovery/stm32f469-discovery.c +++ b/board/st/stm32f469-discovery/stm32f469-discovery.c @@ -23,7 +23,7 @@ int dram_init(void) return rv; } - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) rv = -EINVAL; return rv; diff --git a/board/st/stm32h743-disco/stm32h743-disco.c b/board/st/stm32h743-disco/stm32h743-disco.c index fa007c7986..3ab9518804 100644 --- a/board/st/stm32h743-disco/stm32h743-disco.c +++ b/board/st/stm32h743-disco/stm32h743-disco.c @@ -20,7 +20,7 @@ int dram_init(void) return ret; } - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) ret = -EINVAL; return ret; diff --git a/board/st/stm32h743-eval/stm32h743-eval.c b/board/st/stm32h743-eval/stm32h743-eval.c index fa007c7986..3ab9518804 100644 --- a/board/st/stm32h743-eval/stm32h743-eval.c +++ b/board/st/stm32h743-eval/stm32h743-eval.c @@ -20,7 +20,7 @@ int dram_init(void) return ret; } - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) ret = -EINVAL; return ret; diff --git a/board/xilinx/Kconfig b/board/xilinx/Kconfig new file mode 100644 index 0000000000..37bec5fae2 --- /dev/null +++ b/board/xilinx/Kconfig @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2018, Luca Ceresoli <luca@lucaceresoli.net> + +if ARCH_ZYNQ || ARCH_ZYNQMP + +config XILINX_PS_INIT_FILE + string "Zynq/ZynqMP PS init file(s) location" + help + On Zynq and ZynqMP U-Boot SPL (or U-Boot proper if + ZYNQMP_PSU_INIT_ENABLED is set) is responsible for some + basic initializations, such as enabling peripherals and + configuring pinmuxes. The PS init file (called + psu_init_gpl.c on ZynqMP, ps7_init_gpl.c for Zynq-7000) + contains the code for such initializations. + + U-Boot contains PS init files for some boards, but each of + them describes only one specific configuration. Users of a + different board, or needing a different configuration, can + generate custom files using the Xilinx development tools. + + There are three ways to give a PS init file to U-Boot: + + 1. Set this variable to the path, either relative to the + source tree or absolute, where the psu_init_gpl.c or + ps7_init_gpl.c file is located. U-Boot will build this + file. + + 2. If you leave an empty string here, U-Boot will use + board/xilinx/zynq/$(CONFIG_DEFAULT_DEVICE_TREE)/ps7_init_gpl.c + for Zynq-7000, or + board/xilinx/zynqmp/$(CONFIG_DEFAULT_DEVICE_TREE)/psu_init_gpl.c + for ZynqMP. + + 3. If the above file does not exist, U-Boot will use + board/xilinx/zynq/ps7_init_gpl.c for Zynq-7000, or + board/xilinx/zynqmp/psu_init_gpl.c for ZynqMP. This file + is not provided by U-Boot, you have to copy it there + before the build. + +endif diff --git a/board/xilinx/microblaze-generic/microblaze-generic.c b/board/xilinx/microblaze-generic/microblaze-generic.c index 58ca1d715d..44fb48b347 100644 --- a/board/xilinx/microblaze-generic/microblaze-generic.c +++ b/board/xilinx/microblaze-generic/microblaze-generic.c @@ -1,26 +1,32 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * (C) Copyright 2007 Michal Simek + * (C) Copyright 2007-2018 Michal Simek * - * Michal SIMEK <monstr@monstr.eu> + * Michal SIMEK <monstr@monstr.eu> */ -/* This is a board specific file. It's OK to include board specific - * header files */ +/* + * This is a board specific file. It's OK to include board specific + * header files + */ #include <common.h> #include <config.h> +#include <dm.h> +#include <dm/lists.h> #include <fdtdec.h> #include <asm/processor.h> #include <asm/microblaze_intc.h> #include <asm/asm.h> #include <asm/gpio.h> +#include <dm/uclass.h> +#include <wdt.h> DECLARE_GLOBAL_DATA_PTR; -#ifdef CONFIG_XILINX_GPIO -static int reset_pin = -1; -#endif +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) +static struct udevice *watchdog_dev; +#endif /* !CONFIG_SPL_BUILD && CONFIG_WDT */ ulong ram_base; @@ -58,38 +64,51 @@ int dram_init(void) return 0; }; -int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +#ifdef CONFIG_WDT +/* Called by macro WATCHDOG_RESET */ +void watchdog_reset(void) { -#ifndef CONFIG_SPL_BUILD -#ifdef CONFIG_XILINX_GPIO - if (reset_pin != -1) - gpio_direction_output(reset_pin, 1); -#endif +#if !defined(CONFIG_SPL_BUILD) + ulong now; + static ulong next_reset; -#ifdef CONFIG_XILINX_TB_WATCHDOG - hw_watchdog_disable(); -#endif -#endif - puts ("Reseting board\n"); - __asm__ __volatile__ (" mts rmsr, r0;" \ - "bra r0"); + if (!watchdog_dev) + return; - return 0; -} + now = timer_get_us(); -static int gpio_init(void) -{ -#ifdef CONFIG_XILINX_GPIO - reset_pin = gpio_alloc(CONFIG_SYS_GPIO_0_ADDR, "reset", 1); - if (reset_pin != -1) - gpio_request(reset_pin, "reset_pin"); -#endif - return 0; + /* Do not reset the watchdog too often */ + if (now > next_reset) { + wdt_reset(watchdog_dev); + next_reset = now + 1000; + } +#endif /* !CONFIG_SPL_BUILD */ } +#endif /* CONFIG_WDT */ int board_late_init(void) { - gpio_init(); +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) + watchdog_dev = NULL; + + if (uclass_get_device_by_seq(UCLASS_WDT, 0, &watchdog_dev)) { + debug("Watchdog: Not found by seq!\n"); + if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { + puts("Watchdog: Not found!\n"); + return 0; + } + } + + wdt_start(watchdog_dev, 0, 0); + puts("Watchdog: Started\n"); +#endif /* !CONFIG_SPL_BUILD && CONFIG_WDT */ +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_SYSRESET_MICROBLAZE) + int ret; + ret = device_bind_driver(gd->dm_root, "mb_soft_reset", + "reset_soft", NULL); + if (ret) + printf("Warning: No reset driver: ret=%d\n", ret); +#endif return 0; } diff --git a/board/xilinx/microblaze-generic/xparameters.h b/board/xilinx/microblaze-generic/xparameters.h index 51bca40e34..5e0911faf6 100644 --- a/board/xilinx/microblaze-generic/xparameters.h +++ b/board/xilinx/microblaze-generic/xparameters.h @@ -10,18 +10,9 @@ * the generated file from your Xilinx design flow. */ -#define XILINX_BOARD_NAME microblaze-generic - /* Microblaze is microblaze_0 */ #define XILINX_FSL_NUMBER 3 -/* GPIO is LEDs_4Bit*/ -#define XILINX_GPIO_BASEADDR 0x40000000 - /* Flash Memory is FLASH_2Mx32 */ #define XILINX_FLASH_START 0x2c000000 #define XILINX_FLASH_SIZE 0x00800000 - -/* Watchdog IP is wxi_timebase_wdt_0 */ -#define XILINX_WATCHDOG_BASEADDR 0x50000000 -#define XILINX_WATCHDOG_IRQ 1 diff --git a/board/xilinx/zynq/Kconfig b/board/xilinx/zynq/Kconfig new file mode 100644 index 0000000000..d6f40631cc --- /dev/null +++ b/board/xilinx/zynq/Kconfig @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2018, Xilinx, Inc. + +if ARCH_ZYNQ + +config CMD_ZYNQ + bool "Enable Zynq specific commands" + default y + help + Enables Zynq specific commands. + +config CMD_ZYNQ_AES + bool "Enable zynq aes command for decryption of encrypted images" + depends on CMD_ZYNQ + depends on FPGA_ZYNQPL + help + Decrypts the encrypted image present in source address + and places the decrypted image at destination address. + +config CMD_ZYNQ_RSA + bool "Enable zynq rsa command for loading secure images" + default y + depends on CMD_ZYNQ + depends on CMD_ZYNQ_AES + help + Enabling this will support zynq secure image verification. + The secure image is a xilinx specific BOOT.BIN with + either authentication or encryption or both encryption + and authentication feature enabled while generating + BOOT.BIN using Xilinx bootgen tool. + +endif diff --git a/board/xilinx/zynq/Makefile b/board/xilinx/zynq/Makefile index 5a76a26720..e7645be189 100644 --- a/board/xilinx/zynq/Makefile +++ b/board/xilinx/zynq/Makefile @@ -5,10 +5,18 @@ obj-y := board.o -hw-platform-y :=$(shell echo $(CONFIG_DEFAULT_DEVICE_TREE)) +ifneq ($(CONFIG_XILINX_PS_INIT_FILE),"") +PS_INIT_FILE := $(shell cd $(srctree); readlink -f $(CONFIG_XILINX_PS_INIT_FILE)) +init-objs := ps_init_gpl.o +spl/board/xilinx/zynq/ps_init_gpl.o board/xilinx/zynq/ps_init_gpl.o: $(PS_INIT_FILE) + $(CC) $(c_flags) -I $(srctree)/$(src) -c -o $@ $^ +endif +ifeq ($(init-objs),) +hw-platform-y :=$(shell echo $(CONFIG_DEFAULT_DEVICE_TREE)) init-objs := $(if $(wildcard $(srctree)/$(src)/$(hw-platform-y)/ps7_init_gpl.c),\ $(hw-platform-y)/ps7_init_gpl.o) +endif ifeq ($(init-objs),) ifneq ($(wildcard $(srctree)/$(src)/ps7_init_gpl.c),) @@ -18,6 +26,11 @@ $(warning Put custom ps7_init_gpl.c/h to board/xilinx/zynq/custom_hw_platform/)) endif endif +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_CMD_ZYNQ) += cmds.o +obj-$(CONFIG_CMD_ZYNQ_RSA) += bootimg.o +endif + obj-$(CONFIG_SPL_BUILD) += $(init-objs) # Suppress "warning: function declaration isn't a prototype" diff --git a/board/xilinx/zynq/board.c b/board/xilinx/zynq/board.c index 1106f5c2a8..614d93c082 100644 --- a/board/xilinx/zynq/board.c +++ b/board/xilinx/zynq/board.c @@ -36,12 +36,16 @@ int board_early_init_f(void) int board_init(void) { #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) - if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { - puts("Watchdog: Not found!\n"); - } else { - wdt_start(watchdog_dev, 0, 0); - puts("Watchdog: Started\n"); + if (uclass_get_device_by_seq(UCLASS_WDT, 0, &watchdog_dev)) { + debug("Watchdog: Not found by seq!\n"); + if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { + puts("Watchdog: Not found!\n"); + return 0; + } } + + wdt_start(watchdog_dev, 0, 0); + puts("Watchdog: Started\n"); # endif return 0; @@ -94,7 +98,7 @@ int dram_init_banksize(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; zynq_ddrc_init(); diff --git a/board/xilinx/zynq/bootimg.c b/board/xilinx/zynq/bootimg.c new file mode 100644 index 0000000000..56d69cddac --- /dev/null +++ b/board/xilinx/zynq/bootimg.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Xilinx, Inc. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> +#include <u-boot/md5.h> +#include <zynq_bootimg.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define ZYNQ_IMAGE_PHDR_OFFSET 0x09C +#define ZYNQ_IMAGE_FSBL_LEN_OFFSET 0x040 +#define ZYNQ_PART_HDR_CHKSUM_WORD_COUNT 0x0F +#define ZYNQ_PART_HDR_WORD_COUNT 0x10 +#define ZYNQ_MAXIMUM_IMAGE_WORD_LEN 0x40000000 +#define MD5_CHECKSUM_SIZE 16 + +struct headerarray { + u32 fields[16]; +}; + +/* + * Check whether the given partition is last partition or not + */ +static int zynq_islastpartition(struct headerarray *head) +{ + int index; + + debug("%s\n", __func__); + if (head->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT] != 0xFFFFFFFF) + return -1; + + for (index = 0; index < ZYNQ_PART_HDR_WORD_COUNT - 1; index++) { + if (head->fields[index] != 0x0) + return -1; + } + + return 0; +} + +/* + * Get the partition count from the partition header + */ +int zynq_get_part_count(struct partition_hdr *part_hdr_info) +{ + u32 count; + struct headerarray *hap; + + debug("%s\n", __func__); + + for (count = 0; count < ZYNQ_MAX_PARTITION_NUMBER; count++) { + hap = (struct headerarray *)&part_hdr_info[count]; + if (zynq_islastpartition(hap) != -1) + break; + } + + return count; +} + +/* + * Get the partition info of all the partitions available. + */ +int zynq_get_partition_info(u32 image_base_addr, u32 *fsbl_len, + struct partition_hdr *part_hdr) +{ + u32 parthdroffset; + + *fsbl_len = *((u32 *)(image_base_addr + ZYNQ_IMAGE_FSBL_LEN_OFFSET)); + + parthdroffset = *((u32 *)(image_base_addr + ZYNQ_IMAGE_PHDR_OFFSET)); + + parthdroffset += image_base_addr; + + memcpy(part_hdr, (u32 *)parthdroffset, + (sizeof(struct partition_hdr) * ZYNQ_MAX_PARTITION_NUMBER)); + + return 0; +} + +/* + * Check whether the partition header is valid or not + */ +int zynq_validate_hdr(struct partition_hdr *header) +{ + struct headerarray *hap; + u32 index; + u32 checksum; + + debug("%s\n", __func__); + + hap = (struct headerarray *)header; + + for (index = 0; index < ZYNQ_PART_HDR_WORD_COUNT; index++) { + if (hap->fields[index]) + break; + } + if (index == ZYNQ_PART_HDR_WORD_COUNT) + return -1; + + checksum = 0; + for (index = 0; index < ZYNQ_PART_HDR_CHKSUM_WORD_COUNT; index++) + checksum += hap->fields[index]; + + checksum ^= 0xFFFFFFFF; + + if (hap->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT] != checksum) { + printf("Error: Checksum 0x%8.8x != 0x%8.8x\n", + checksum, hap->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT]); + return -1; + } + + if (header->imagewordlen > ZYNQ_MAXIMUM_IMAGE_WORD_LEN) { + printf("INVALID_PARTITION_LENGTH\n"); + return -1; + } + + return 0; +} + +/* + * Validate the partition by calculationg the md5 checksum for the + * partition and compare with checksum present in checksum offset of + * partition + */ +int zynq_validate_partition(u32 start_addr, u32 len, u32 chksum_off) +{ + u8 checksum[MD5_CHECKSUM_SIZE]; + u8 calchecksum[MD5_CHECKSUM_SIZE]; + + memcpy(&checksum[0], (u32 *)chksum_off, MD5_CHECKSUM_SIZE); + + md5_wd((u8 *)start_addr, len, &calchecksum[0], 0x10000); + + if (!memcmp(checksum, calchecksum, MD5_CHECKSUM_SIZE)) + return 0; + + printf("Error: Partition DataChecksum\n"); + return -1; +} diff --git a/board/xilinx/zynq/cmds.c b/board/xilinx/zynq/cmds.c new file mode 100644 index 0000000000..0b2a8178d6 --- /dev/null +++ b/board/xilinx/zynq/cmds.c @@ -0,0 +1,513 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Xilinx, Inc. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/arch/sys_proto.h> +#include <malloc.h> +#include <u-boot/md5.h> +#include <u-boot/rsa.h> +#include <u-boot/rsa-mod-exp.h> +#include <u-boot/sha256.h> +#include <zynqpl.h> +#include <fpga.h> +#include <zynq_bootimg.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_CMD_ZYNQ_RSA + +#define ZYNQ_EFUSE_RSA_ENABLE_MASK 0x400 +#define ZYNQ_ATTRIBUTE_PL_IMAGE_MASK 0x20 +#define ZYNQ_ATTRIBUTE_CHECKSUM_TYPE_MASK 0x7000 +#define ZYNQ_ATTRIBUTE_RSA_PRESENT_MASK 0x8000 +#define ZYNQ_ATTRIBUTE_RSA_PART_OWNER_MASK 0x30000 + +#define ZYNQ_RSA_MODULAR_SIZE 256 +#define ZYNQ_RSA_MODULAR_EXT_SIZE 256 +#define ZYNQ_RSA_EXPO_SIZE 64 +#define ZYNQ_RSA_SPK_SIGNATURE_SIZE 256 +#define ZYNQ_RSA_PARTITION_SIGNATURE_SIZE 256 +#define ZYNQ_RSA_SIGNATURE_SIZE 0x6C0 +#define ZYNQ_RSA_HEADER_SIZE 4 +#define ZYNQ_RSA_MAGIC_WORD_SIZE 60 +#define ZYNQ_RSA_PART_OWNER_UBOOT 1 +#define ZYNQ_RSA_ALIGN_PPK_START 64 + +#define WORD_LENGTH_SHIFT 2 + +static u8 *ppkmodular; +static u8 *ppkmodularex; + +struct zynq_rsa_public_key { + uint len; /* Length of modulus[] in number of u32 */ + u32 n0inv; /* -1 / modulus[0] mod 2^32 */ + u32 *modulus; /* modulus as little endian array */ + u32 *rr; /* R^2 as little endian array */ +}; + +static struct zynq_rsa_public_key public_key; + +static struct partition_hdr part_hdr[ZYNQ_MAX_PARTITION_NUMBER]; + +/* + * Extract the primary public key components from already autheticated FSBL + */ +static void zynq_extract_ppk(u32 fsbl_len) +{ + u32 padsize; + u8 *ppkptr; + + debug("%s\n", __func__); + + /* + * Extract the authenticated PPK from OCM i.e at end of the FSBL + */ + ppkptr = (u8 *)(fsbl_len + ZYNQ_OCM_BASEADDR); + padsize = ((u32)ppkptr % ZYNQ_RSA_ALIGN_PPK_START); + if (padsize) + ppkptr += (ZYNQ_RSA_ALIGN_PPK_START - padsize); + + ppkptr += ZYNQ_RSA_HEADER_SIZE; + + ppkptr += ZYNQ_RSA_MAGIC_WORD_SIZE; + + ppkmodular = (u8 *)ppkptr; + ppkptr += ZYNQ_RSA_MODULAR_SIZE; + ppkmodularex = (u8 *)ppkptr; + ppkptr += ZYNQ_RSA_MODULAR_EXT_SIZE; +} + +/* + * Calculate the inverse(-1 / modulus[0] mod 2^32 ) for the PPK + */ +static u32 zynq_calc_inv(void) +{ + u32 modulus = public_key.modulus[0]; + u32 tmp = BIT(1); + u32 inverse; + + inverse = modulus & BIT(0); + + while (tmp) { + inverse *= 2 - modulus * inverse; + tmp *= tmp; + } + + return ~(inverse - 1); +} + +/* + * Recreate the signature by padding the bytes and verify with hash value + */ +static int zynq_pad_and_check(u8 *signature, u8 *hash) +{ + u8 padding[] = {0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, + 0x20}; + u8 *pad_ptr = signature + 256; + u32 pad = 202; + u32 ii; + + /* + * Re-Create PKCS#1v1.5 Padding + * MSB ----------------------------------------------------LSB + * 0x0 || 0x1 || 0xFF(for 202 bytes) || 0x0 || T_padding || SHA256 Hash + */ + if (*--pad_ptr != 0 || *--pad_ptr != 1) + return -1; + + for (ii = 0; ii < pad; ii++) { + if (*--pad_ptr != 0xFF) + return -1; + } + + if (*--pad_ptr != 0) + return -1; + + for (ii = 0; ii < sizeof(padding); ii++) { + if (*--pad_ptr != padding[ii]) + return -1; + } + + for (ii = 0; ii < 32; ii++) { + if (*--pad_ptr != hash[ii]) + return -1; + } + return 0; +} + +/* + * Verify and extract the hash value from signature using the public key + * and compare it with calculated hash value. + */ +static int zynq_rsa_verify_key(const struct zynq_rsa_public_key *key, + const u8 *sig, const u32 sig_len, const u8 *hash) +{ + int status; + void *buf; + + if (!key || !sig || !hash) + return -1; + + if (sig_len != (key->len * sizeof(u32))) { + printf("Signature is of incorrect length %d\n", sig_len); + return -1; + } + + /* Sanity check for stack size */ + if (sig_len > ZYNQ_RSA_SPK_SIGNATURE_SIZE) { + printf("Signature length %u exceeds maximum %d\n", sig_len, + ZYNQ_RSA_SPK_SIGNATURE_SIZE); + return -1; + } + + buf = malloc(sig_len); + if (!buf) + return -1; + + memcpy(buf, sig, sig_len); + + status = zynq_pow_mod((u32 *)key, (u32 *)buf); + if (status == -1) { + free(buf); + return status; + } + + status = zynq_pad_and_check((u8 *)buf, (u8 *)hash); + + free(buf); + return status; +} + +/* + * Authenticate the partition + */ +static int zynq_authenticate_part(u8 *buffer, u32 size) +{ + u8 hash_signature[32]; + u8 *spk_modular; + u8 *spk_modular_ex; + u8 *signature_ptr; + u32 status; + + debug("%s\n", __func__); + + signature_ptr = (u8 *)(buffer + size - ZYNQ_RSA_SIGNATURE_SIZE); + + signature_ptr += ZYNQ_RSA_HEADER_SIZE; + + signature_ptr += ZYNQ_RSA_MAGIC_WORD_SIZE; + + ppkmodular = (u8 *)signature_ptr; + signature_ptr += ZYNQ_RSA_MODULAR_SIZE; + ppkmodularex = signature_ptr; + signature_ptr += ZYNQ_RSA_MODULAR_EXT_SIZE; + signature_ptr += ZYNQ_RSA_EXPO_SIZE; + + sha256_csum_wd((const unsigned char *)signature_ptr, + (ZYNQ_RSA_MODULAR_EXT_SIZE + ZYNQ_RSA_EXPO_SIZE + + ZYNQ_RSA_MODULAR_SIZE), + (unsigned char *)hash_signature, 0x1000); + + spk_modular = (u8 *)signature_ptr; + signature_ptr += ZYNQ_RSA_MODULAR_SIZE; + spk_modular_ex = (u8 *)signature_ptr; + signature_ptr += ZYNQ_RSA_MODULAR_EXT_SIZE; + signature_ptr += ZYNQ_RSA_EXPO_SIZE; + + public_key.len = ZYNQ_RSA_MODULAR_SIZE / sizeof(u32); + public_key.modulus = (u32 *)ppkmodular; + public_key.rr = (u32 *)ppkmodularex; + public_key.n0inv = zynq_calc_inv(); + + status = zynq_rsa_verify_key(&public_key, signature_ptr, + ZYNQ_RSA_SPK_SIGNATURE_SIZE, + hash_signature); + if (status) + return status; + + signature_ptr += ZYNQ_RSA_SPK_SIGNATURE_SIZE; + + sha256_csum_wd((const unsigned char *)buffer, + (size - ZYNQ_RSA_PARTITION_SIGNATURE_SIZE), + (unsigned char *)hash_signature, 0x1000); + + public_key.len = ZYNQ_RSA_MODULAR_SIZE / sizeof(u32); + public_key.modulus = (u32 *)spk_modular; + public_key.rr = (u32 *)spk_modular_ex; + public_key.n0inv = zynq_calc_inv(); + + return zynq_rsa_verify_key(&public_key, (u8 *)signature_ptr, + ZYNQ_RSA_PARTITION_SIGNATURE_SIZE, + (u8 *)hash_signature); +} + +/* + * Parses the partition header and verfies the authenticated and + * encrypted image. + */ +static int zynq_verify_image(u32 src_ptr) +{ + u32 silicon_ver, image_base_addr, status; + u32 partition_num = 0; + u32 efuseval, srcaddr, size, fsbl_len; + struct partition_hdr *hdr_ptr; + u32 part_data_len, part_img_len, part_attr; + u32 part_load_addr, part_dst_addr, part_chksum_offset; + u32 part_start_addr, part_total_size, partitioncount; + bool encrypt_part_flag = false; + bool part_chksum_flag = false; + bool signed_part_flag = false; + + image_base_addr = src_ptr; + + silicon_ver = zynq_get_silicon_version(); + + /* RSA not supported in silicon versions 1.0 and 2.0 */ + if (silicon_ver == 0 || silicon_ver == 1) + return -1; + + zynq_get_partition_info(image_base_addr, &fsbl_len, + &part_hdr[0]); + + /* Extract ppk if efuse was blown Otherwise return error */ + efuseval = readl(&efuse_base->status); + if (!(efuseval & ZYNQ_EFUSE_RSA_ENABLE_MASK)) + return -1; + + zynq_extract_ppk(fsbl_len); + + partitioncount = zynq_get_part_count(&part_hdr[0]); + + /* + * As the first two partitions are related to fsbl, + * we can ignore those two in bootimage and the below + * code doesn't need to validate it as fsbl is already + * done by now + */ + if (partitioncount <= 2 || + partitioncount > ZYNQ_MAX_PARTITION_NUMBER) + return -1; + + while (partition_num < partitioncount) { + if (((part_hdr[partition_num].partitionattr & + ZYNQ_ATTRIBUTE_RSA_PART_OWNER_MASK) >> 16) != + ZYNQ_RSA_PART_OWNER_UBOOT) { + printf("UBOOT is not Owner for partition %d\n", + partition_num); + partition_num++; + continue; + } + hdr_ptr = &part_hdr[partition_num]; + status = zynq_validate_hdr(hdr_ptr); + if (status) + return status; + + part_data_len = hdr_ptr->datawordlen; + part_img_len = hdr_ptr->imagewordlen; + part_attr = hdr_ptr->partitionattr; + part_load_addr = hdr_ptr->loadaddr; + part_chksum_offset = hdr_ptr->checksumoffset; + part_start_addr = hdr_ptr->partitionstart; + part_total_size = hdr_ptr->partitionwordlen; + + if (part_data_len != part_img_len) { + debug("Encrypted\n"); + encrypt_part_flag = true; + } + + if (part_attr & ZYNQ_ATTRIBUTE_CHECKSUM_TYPE_MASK) + part_chksum_flag = true; + + if (part_attr & ZYNQ_ATTRIBUTE_RSA_PRESENT_MASK) { + debug("RSA Signed\n"); + signed_part_flag = true; + size = part_total_size << WORD_LENGTH_SHIFT; + } else { + size = part_img_len; + } + + if (!signed_part_flag && !part_chksum_flag) { + printf("Partition not signed & no chksum\n"); + partition_num++; + continue; + } + + srcaddr = image_base_addr + + (part_start_addr << WORD_LENGTH_SHIFT); + + /* + * This validation is just for PS DDR. + * TODO: Update this for PL DDR check as well. + */ + if (part_load_addr < gd->bd->bi_dram[0].start && + ((part_load_addr + part_data_len) > + (gd->bd->bi_dram[0].start + + gd->bd->bi_dram[0].size))) { + printf("INVALID_LOAD_ADDRESS_FAIL\n"); + return -1; + } + + if (part_attr & ZYNQ_ATTRIBUTE_PL_IMAGE_MASK) + part_load_addr = srcaddr; + else + memcpy((u32 *)part_load_addr, (u32 *)srcaddr, + size); + + if (part_chksum_flag) { + part_chksum_offset = image_base_addr + + (part_chksum_offset << + WORD_LENGTH_SHIFT); + status = zynq_validate_partition(part_load_addr, + (part_total_size << + WORD_LENGTH_SHIFT), + part_chksum_offset); + if (status != 0) { + printf("PART_CHKSUM_FAIL\n"); + return -1; + } + debug("Partition Validation Done\n"); + } + + if (signed_part_flag) { + status = zynq_authenticate_part((u8 *)part_load_addr, + size); + if (status != 0) { + printf("AUTHENTICATION_FAIL\n"); + return -1; + } + debug("Authentication Done\n"); + } + + if (encrypt_part_flag) { + debug("DECRYPTION\n"); + + part_dst_addr = part_load_addr; + + if (part_attr & ZYNQ_ATTRIBUTE_PL_IMAGE_MASK) { + partition_num++; + continue; + } + + status = zynq_decrypt_load(part_load_addr, + part_img_len, + part_dst_addr, + part_data_len); + if (status != 0) { + printf("DECRYPTION_FAIL\n"); + return -1; + } + } + partition_num++; + } + + return 0; +} + +static int do_zynq_rsa(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + u32 src_ptr; + char *endp; + + src_ptr = simple_strtoul(argv[2], &endp, 16); + if (*argv[2] == 0 || *endp != 0) + return CMD_RET_USAGE; + if (zynq_verify_image(src_ptr)) + return CMD_RET_FAILURE; + + return CMD_RET_SUCCESS; +} +#endif + +#ifdef CONFIG_CMD_ZYNQ_AES +static int zynq_decrypt_image(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + char *endp; + u32 srcaddr, srclen, dstaddr, dstlen; + int status; + + srcaddr = simple_strtoul(argv[2], &endp, 16); + if (*argv[2] == 0 || *endp != 0) + return CMD_RET_USAGE; + srclen = simple_strtoul(argv[3], &endp, 16); + if (*argv[3] == 0 || *endp != 0) + return CMD_RET_USAGE; + dstaddr = simple_strtoul(argv[4], &endp, 16); + if (*argv[4] == 0 || *endp != 0) + return CMD_RET_USAGE; + dstlen = simple_strtoul(argv[5], &endp, 16); + if (*argv[5] == 0 || *endp != 0) + return CMD_RET_USAGE; + + /* + * Roundup source and destination lengths to + * word size + */ + if (srclen % 4) + srclen = roundup(srclen, 4); + if (dstlen % 4) + dstlen = roundup(dstlen, 4); + + status = zynq_decrypt_load(srcaddr, srclen >> 2, dstaddr, dstlen >> 2); + if (status != 0) + return CMD_RET_FAILURE; + + return CMD_RET_SUCCESS; +} +#endif + +static cmd_tbl_t zynq_commands[] = { +#ifdef CONFIG_CMD_ZYNQ_RSA + U_BOOT_CMD_MKENT(rsa, 3, 1, do_zynq_rsa, "", ""), +#endif +#ifdef CONFIG_CMD_ZYNQ_AES + U_BOOT_CMD_MKENT(aes, 6, 1, zynq_decrypt_image, "", ""), +#endif +}; + +static int do_zynq(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + cmd_tbl_t *zynq_cmd; + int ret; + + if (!ARRAY_SIZE(zynq_commands)) { + puts("No zynq specific command enabled\n"); + return CMD_RET_USAGE; + } + + if (argc < 2) + return CMD_RET_USAGE; + zynq_cmd = find_cmd_tbl(argv[1], zynq_commands, + ARRAY_SIZE(zynq_commands)); + if (!zynq_cmd || argc != zynq_cmd->maxargs) + return CMD_RET_USAGE; + + ret = zynq_cmd->cmd(zynq_cmd, flag, argc, argv); + + return cmd_process_error(zynq_cmd, ret); +} + +static char zynq_help_text[] = + "" +#ifdef CONFIG_CMD_ZYNQ_RSA + "rsa <baseaddr> - Verifies the authenticated and encrypted\n" + " zynq images and loads them back to load\n" + " addresses as specified in BOOT image(BOOT.BIN)\n" +#endif +#ifdef CONFIG_CMD_ZYNQ_AES + "aes <srcaddr> <srclen> <dstaddr> <dstlen>\n" + " - Decrypts the encrypted image present in source\n" + " address and places the decrypted image at\n" + " destination address\n" +#endif + ; + +U_BOOT_CMD(zynq, 6, 0, do_zynq, + "Zynq specific commands", zynq_help_text +); diff --git a/board/xilinx/zynqmp/Makefile b/board/xilinx/zynqmp/Makefile index 05ccd25dce..960b81fc58 100644 --- a/board/xilinx/zynqmp/Makefile +++ b/board/xilinx/zynqmp/Makefile @@ -5,10 +5,18 @@ obj-y := zynqmp.o -hw-platform-y :=$(shell echo $(CONFIG_DEFAULT_DEVICE_TREE)) +ifneq ($(CONFIG_XILINX_PS_INIT_FILE),"") +PS_INIT_FILE := $(shell cd $(srctree); readlink -f $(CONFIG_XILINX_PS_INIT_FILE)) +init-objs := ps_init_gpl.o +spl/board/xilinx/zynqmp/ps_init_gpl.o board/xilinx/zynqmp/ps_init_gpl.o: $(PS_INIT_FILE) + $(CC) $(c_flags) -I $(srctree)/$(src) -c -o $@ $^ +endif +ifeq ($(init-objs),) +hw-platform-y :=$(shell echo $(CONFIG_DEFAULT_DEVICE_TREE)) init-objs := $(if $(wildcard $(srctree)/$(src)/$(hw-platform-y)/psu_init_gpl.c),\ $(hw-platform-y)/psu_init_gpl.o) +endif ifeq ($(init-objs),) ifneq ($(wildcard $(srctree)/$(src)/psu_init_gpl.c),) diff --git a/board/xilinx/zynqmp/cmds.c b/board/xilinx/zynqmp/cmds.c index d914653238..f8c8674f87 100644 --- a/board/xilinx/zynqmp/cmds.c +++ b/board/xilinx/zynqmp/cmds.c @@ -9,24 +9,37 @@ #include <asm/arch/sys_proto.h> #include <asm/io.h> -static int zynqmp_verify_secure(u8 *key_ptr, u8 *src_ptr, u32 len) +static int do_zynqmp_verify_secure(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) { + u64 src_addr, addr; + u32 len, src_lo, src_hi; + u8 *key_ptr = NULL; int ret; - u32 src_lo, src_hi; u32 key_lo = 0; u32 key_hi = 0; u32 ret_payload[PAYLOAD_ARG_CNT]; - u64 addr; - if ((ulong)src_ptr != ALIGN((ulong)src_ptr, - CONFIG_SYS_CACHELINE_SIZE)) { - printf("Failed: source address not aligned:%p\n", src_ptr); + if (argc < 4) + return CMD_RET_USAGE; + + src_addr = simple_strtoull(argv[2], NULL, 16); + len = simple_strtoul(argv[3], NULL, 16); + + if (argc == 5) + key_ptr = (uint8_t *)(uintptr_t)simple_strtoull(argv[4], + NULL, 16); + + if ((ulong)src_addr != ALIGN((ulong)src_addr, + CONFIG_SYS_CACHELINE_SIZE)) { + printf("Failed: source address not aligned:%lx\n", + (ulong)src_addr); return -EINVAL; } - src_lo = lower_32_bits((ulong)src_ptr); - src_hi = upper_32_bits((ulong)src_ptr); - flush_dcache_range((ulong)src_ptr, (ulong)(src_ptr + len)); + src_lo = lower_32_bits((ulong)src_addr); + src_hi = upper_32_bits((ulong)src_addr); + flush_dcache_range((ulong)src_addr, (ulong)(src_addr + len)); if (key_ptr) { key_lo = lower_32_bits((ulong)key_ptr); @@ -48,6 +61,53 @@ static int zynqmp_verify_secure(u8 *key_ptr, u8 *src_ptr, u32 len) return ret; } +static int do_zynqmp_mmio_read(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + u32 read_val, addr; + int ret; + + if (argc != cmdtp->maxargs) + return CMD_RET_USAGE; + + addr = simple_strtoul(argv[2], NULL, 16); + + ret = zynqmp_mmio_read(addr, &read_val); + if (!ret) + printf("mmio read value at 0x%x = 0x%x\n", + addr, read_val); + else + printf("Failed: mmio read\n"); + + return ret; +} + +static int do_zynqmp_mmio_write(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + u32 addr, mask, val; + int ret; + + if (argc != cmdtp->maxargs) + return CMD_RET_USAGE; + + addr = simple_strtoul(argv[2], NULL, 16); + mask = simple_strtoul(argv[3], NULL, 16); + val = simple_strtoul(argv[4], NULL, 16); + + ret = zynqmp_mmio_write(addr, mask, val); + if (ret != 0) + printf("Failed: mmio write\n"); + + return ret; +} + +static cmd_tbl_t cmd_zynqmp_sub[] = { + U_BOOT_CMD_MKENT(secure, 5, 0, do_zynqmp_verify_secure, "", ""), + U_BOOT_CMD_MKENT(mmio_read, 3, 0, do_zynqmp_mmio_read, "", ""), + U_BOOT_CMD_MKENT(mmio_write, 5, 0, do_zynqmp_mmio_write, "", ""), +}; + /** * do_zynqmp - Handle the "zynqmp" command-line command * @cmdtp: Command data struct pointer @@ -62,30 +122,18 @@ static int zynqmp_verify_secure(u8 *key_ptr, u8 *src_ptr, u32 len) static int do_zynqmp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { - u64 src_addr; - u32 len; - u8 *key_ptr = NULL; - u8 *src_ptr; - int ret; + cmd_tbl_t *c; - if (argc > 5 || argc < 4 || strncmp(argv[1], "secure", 6)) + if (argc < 2) return CMD_RET_USAGE; - src_addr = simple_strtoull(argv[2], NULL, 16); - - len = simple_strtoul(argv[3], NULL, 16); - - if (argc > 4) - key_ptr = (uint8_t *)(uintptr_t)simple_strtoull(argv[4], - NULL, 16); - - src_ptr = (uint8_t *)(uintptr_t)src_addr; + c = find_cmd_tbl(argv[1], &cmd_zynqmp_sub[0], + ARRAY_SIZE(cmd_zynqmp_sub)); - ret = zynqmp_verify_secure(key_ptr, src_ptr, len); - if (ret) - return CMD_RET_FAILURE; - - return CMD_RET_SUCCESS; + if (c) + return c->cmd(c, flag, argc, argv); + else + return CMD_RET_USAGE; } /***************************************************/ @@ -94,11 +142,14 @@ static char zynqmp_help_text[] = "secure src len [key_addr] - verifies secure images of $len bytes\n" " long at address $src. Optional key_addr\n" " can be specified if user key needs to\n" - " be used for decryption\n"; + " be used for decryption\n" + "zynqmp mmio_read address - read from address\n" + "zynqmp mmio_write address mask value - write value after masking to\n" + " address\n"; #endif U_BOOT_CMD( zynqmp, 5, 1, do_zynqmp, - "Verify and load secure images", + "ZynqMP sub-system", zynqmp_help_text ) diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index 81c10fcf8a..89fac6bb67 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -312,12 +312,16 @@ int board_init(void) #endif #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) - if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { - puts("Watchdog: Not found!\n"); - } else { - wdt_start(watchdog_dev, 0, 0); - puts("Watchdog: Started\n"); + if (uclass_get_device_by_seq(UCLASS_WDT, 0, &watchdog_dev)) { + debug("Watchdog: Not found by seq!\n"); + if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { + puts("Watchdog: Not found!\n"); + return 0; + } } + + wdt_start(watchdog_dev, 0, 0); + puts("Watchdog: Started\n"); #endif return 0; @@ -419,7 +423,7 @@ int dram_init_banksize(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; diff --git a/board/xilinx/zynqmp_r5/board.c b/board/xilinx/zynqmp_r5/board.c index 70fb202354..1c45ee7196 100644 --- a/board/xilinx/zynqmp_r5/board.c +++ b/board/xilinx/zynqmp_r5/board.c @@ -18,7 +18,7 @@ int dram_init_banksize(void) int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; |