From 62f86c6a01690b473545fd6159c680a50b1bfeea Mon Sep 17 00:00:00 2001 From: Bharat Gooty Date: Tue, 24 Aug 2021 15:46:31 +0530 Subject: [PATCH 01/19] pinctrl: single: Parse gpio details from dt Parse different gpio properties from dt as part of probe function. This detail is required to enable pinctrl pad later when gpio lines are requested. Signed-off-by: Rayagonda Kokatanur Signed-off-by: Bharat Gooty Acked-by: Rayagonda Kokatanur --- drivers/pinctrl/pinctrl-single.c | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index cf9ad3670f..0f96cd5870 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -44,11 +45,27 @@ struct single_func { unsigned int *pins; }; +/** + * struct single_gpiofunc_range - pin ranges with same mux value of gpio fun + * @offset: offset base of pins + * @npins: number pins with the same mux value of gpio function + * @gpiofunc: mux value of gpio function + * @node: list node + */ +struct single_gpiofunc_range { + u32 offset; + u32 npins; + u32 gpiofunc; + struct list_head node; +}; + /** * struct single_priv - private data * @bits_per_pin: number of bits per pin * @npins: number of selectable pins * @pin_name: temporary buffer to store the pin name + * @functions: list pin functions + * @gpiofuncs: list gpio functions */ struct single_priv { #if (IS_ENABLED(CONFIG_SANDBOX)) @@ -58,6 +75,7 @@ struct single_priv { unsigned int npins; char pin_name[PINNAME_SIZE]; struct list_head functions; + struct list_head gpiofuncs; }; /** @@ -454,6 +472,36 @@ static int single_get_pins_count(struct udevice *dev) return priv->npins; } +static int single_add_gpio_func(struct udevice *dev) +{ + struct single_priv *priv = dev_get_priv(dev); + const char *propname = "pinctrl-single,gpio-range"; + const char *cellname = "#pinctrl-single,gpio-range-cells"; + struct single_gpiofunc_range *range; + struct ofnode_phandle_args gpiospec; + int ret, i; + + for (i = 0; ; i++) { + ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), propname, + cellname, 0, i, &gpiospec); + /* Do not treat it as error. Only treat it as end condition. */ + if (ret) { + ret = 0; + break; + } + range = devm_kzalloc(dev, sizeof(*range), GFP_KERNEL); + if (!range) { + ret = -ENOMEM; + break; + } + range->offset = gpiospec.args[0]; + range->npins = gpiospec.args[1]; + range->gpiofunc = gpiospec.args[2]; + list_add_tail(&range->node, &priv->gpiofuncs); + } + return ret; +} + static int single_probe(struct udevice *dev) { struct single_pdata *pdata = dev_get_plat(dev); @@ -461,6 +509,7 @@ static int single_probe(struct udevice *dev) u32 size; INIT_LIST_HEAD(&priv->functions); + INIT_LIST_HEAD(&priv->gpiofuncs); size = pdata->offset + pdata->width / BITS_PER_BYTE; #if (CONFIG_IS_ENABLED(SANDBOX)) @@ -483,6 +532,9 @@ static int single_probe(struct udevice *dev) priv->npins *= (pdata->width / priv->bits_per_pin); } + if (single_add_gpio_func(dev)) + dev_dbg(dev, "gpio functions are not added\n"); + dev_dbg(dev, "%d pins\n", priv->npins); return 0; } From fd921d20379b2c4544f62a94d642be6aeeb481f0 Mon Sep 17 00:00:00 2001 From: Bharat Gooty Date: Tue, 24 Aug 2021 15:46:32 +0530 Subject: [PATCH 02/19] pinctrl: single: Add request() api Add pinctrl_ops->request api to configure pctrl pad register in gpio mode. Signed-off-by: Rayagonda Kokatanur Signed-off-by: Bharat Gooty Acked-by: Rayagonda Kokatanur Reviewed-by: Simon Glass --- drivers/pinctrl/pinctrl-single.c | 34 ++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 0f96cd5870..8fc07e3498 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -250,6 +250,39 @@ static int single_get_pin_muxing(struct udevice *dev, unsigned int pin, return 0; } +static int single_request(struct udevice *dev, int pin, int flags) +{ + struct single_priv *priv = dev_get_priv(dev); + struct single_pdata *pdata = dev_get_plat(dev); + struct single_gpiofunc_range *frange = NULL; + struct list_head *pos, *tmp; + phys_addr_t reg; + int mux_bytes = 0; + u32 data; + + /* If function mask is null, needn't enable it. */ + if (!pdata->mask) + return -ENOTSUPP; + + list_for_each_safe(pos, tmp, &priv->gpiofuncs) { + frange = list_entry(pos, struct single_gpiofunc_range, node); + if ((pin >= frange->offset + frange->npins) || + pin < frange->offset) + continue; + + mux_bytes = pdata->width / BITS_PER_BYTE; + reg = pdata->base + pin * mux_bytes; + + data = single_read(dev, reg); + data &= ~pdata->mask; + data |= frange->gpiofunc; + single_write(dev, data, reg); + break; + } + + return 0; +} + static struct single_func *single_allocate_function(struct udevice *dev, unsigned int group_pins) { @@ -587,6 +620,7 @@ const struct pinctrl_ops single_pinctrl_ops = { .get_pin_name = single_get_pin_name, .set_state = single_set_state, .get_pin_muxing = single_get_pin_muxing, + .request = single_request, }; static const struct udevice_id single_pinctrl_match[] = { From 51827f9a8be3def01b837a2809094e2fd2703b6a Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 2 Sep 2021 11:56:16 +0200 Subject: [PATCH 03/19] lib: optee: remove the duplicate CONFIG_OPTEE The configuration CONFIG_OPTEE is defined 2 times: 1- in lib/optee/Kconfig for support of OPTEE images loaded by bootm command 2- in drivers/tee/optee/Kconfig for support of OP-TEE driver. It is abnormal to have the same CONFIG define for 2 purpose; and it is difficult to managed correctly their dependencies. Moreover CONFIG_SPL_OPTEE is defined in common/spl/Kconfig to manage OPTEE image load in SPL. This definition causes an issue with the macro CONFIG_IS_ENABLED(OPTEE) to test the availability of the OP-TEE driver. This patch cleans the configuration dependency with: - CONFIG_OPTEE_IMAGE (renamed) => support of OP-TEE image in U-Boot - CONFIG_SPL_OPTEE_IMAGE (renamed) => support of OP-TEE image in SPL - CONFIG_OPTEE (same) => support of OP-TEE driver in U-Boot - CONFIG_OPTEE_LIB (new) => support of OP-TEE library After this patch, the macro have the correct behavior: - CONFIG_IS_ENABLED(OPTEE_IMAGE) => Load of OP-TEE image is supported - CONFIG_IS_ENABLED(OPTEE) => OP-TEE driver is supported Signed-off-by: Patrick Delaunay --- arch/arm/mach-rockchip/sdram.c | 2 +- common/spl/Kconfig | 6 +++--- common/spl/Makefile | 2 +- common/spl/spl.c | 2 +- configs/evb-rk3229_defconfig | 2 +- configs/evb-rk3288_defconfig | 2 +- configs/odroid-go2_defconfig | 2 +- include/tee/optee.h | 6 +++--- lib/Makefile | 2 +- lib/optee/Kconfig | 24 ++++++++++++++---------- lib/optee/Makefile | 2 +- lib/optee/optee.c | 2 ++ 12 files changed, 30 insertions(+), 24 deletions(-) diff --git a/arch/arm/mach-rockchip/sdram.c b/arch/arm/mach-rockchip/sdram.c index 28c379ef07..705ec7ba64 100644 --- a/arch/arm/mach-rockchip/sdram.c +++ b/arch/arm/mach-rockchip/sdram.c @@ -45,7 +45,7 @@ int dram_init_banksize(void) gd->bd->bi_dram[0].start = 0x200000; gd->bd->bi_dram[0].size = top - gd->bd->bi_dram[0].start; #else -#ifdef CONFIG_SPL_OPTEE +#ifdef CONFIG_SPL_OPTEE_IMAGE struct tos_parameter_t *tos_parameter; tos_parameter = (struct tos_parameter_t *)(CONFIG_SYS_SDRAM_BASE + diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 34f6fc2cfa..8a8a971a91 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -1263,11 +1263,11 @@ config SPL_AM33XX_ENABLE_RTC32K_OSC Enable access to the AM33xx RTC and select the external 32kHz clock source. -config SPL_OPTEE - bool "Support OP-TEE Trusted OS" +config SPL_OPTEE_IMAGE + bool "Support OP-TEE Trusted OS image in SPL" depends on ARM help - OP-TEE is an open source Trusted OS which is loaded by SPL. + OP-TEE is an open source Trusted OS which is loaded by SPL. More detail at: https://github.com/OP-TEE/optee_os config SPL_OPENSBI diff --git a/common/spl/Makefile b/common/spl/Makefile index cb15c8e827..db8fd36a26 100644 --- a/common/spl/Makefile +++ b/common/spl/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_$(SPL_TPL_)UBI) += spl_ubi.o obj-$(CONFIG_$(SPL_TPL_)NET) += spl_net.o obj-$(CONFIG_$(SPL_TPL_)MMC) += spl_mmc.o obj-$(CONFIG_$(SPL_TPL_)ATF) += spl_atf.o -obj-$(CONFIG_$(SPL_TPL_)OPTEE) += spl_optee.o +obj-$(CONFIG_$(SPL_TPL_)OPTEE_IMAGE) += spl_optee.o obj-$(CONFIG_$(SPL_TPL_)OPENSBI) += spl_opensbi.o obj-$(CONFIG_$(SPL_TPL_)USB_STORAGE) += spl_usb.o obj-$(CONFIG_$(SPL_TPL_)FS_FAT) += spl_fat.o diff --git a/common/spl/spl.c b/common/spl/spl.c index ed94d5146c..a9304d4148 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -776,7 +776,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2) spl_invoke_atf(&spl_image); break; #endif -#if CONFIG_IS_ENABLED(OPTEE) +#if CONFIG_IS_ENABLED(OPTEE_IMAGE) case IH_OS_TEE: debug("Jumping to U-Boot via OP-TEE\n"); spl_board_prepare_for_optee(spl_image.fdt_addr); diff --git a/configs/evb-rk3229_defconfig b/configs/evb-rk3229_defconfig index 0bf91d61b4..a8b1c42ac6 100644 --- a/configs/evb-rk3229_defconfig +++ b/configs/evb-rk3229_defconfig @@ -28,7 +28,7 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set CONFIG_SPL_STACK_R=y CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000 -CONFIG_SPL_OPTEE=y +CONFIG_SPL_OPTEE_IMAGE=y CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_USB_MASS_STORAGE=y diff --git a/configs/evb-rk3288_defconfig b/configs/evb-rk3288_defconfig index efb2a3ede6..eca9f5c54d 100644 --- a/configs/evb-rk3288_defconfig +++ b/configs/evb-rk3288_defconfig @@ -25,7 +25,7 @@ CONFIG_SILENT_CONSOLE=y CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_SPL_STACK_R=y CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x10000 -CONFIG_SPL_OPTEE=y +CONFIG_SPL_OPTEE_IMAGE=y CONFIG_CMD_GPIO=y CONFIG_CMD_GPT=y CONFIG_CMD_I2C=y diff --git a/configs/odroid-go2_defconfig b/configs/odroid-go2_defconfig index c744c3a6ea..df64307f8e 100644 --- a/configs/odroid-go2_defconfig +++ b/configs/odroid-go2_defconfig @@ -98,7 +98,7 @@ CONFIG_DEBUG_UART_SHIFT=2 CONFIG_DEBUG_UART_SKIP_INIT=y CONFIG_SOUND=y CONFIG_SYSRESET=y -CONFIG_OPTEE=y +CONFIG_OPTEE_LIB=y CONFIG_DM_THERMAL=y CONFIG_USB=y CONFIG_USB_EHCI_HCD=y diff --git a/include/tee/optee.h b/include/tee/optee.h index ebdfe5e98d..2928597b61 100644 --- a/include/tee/optee.h +++ b/include/tee/optee.h @@ -43,7 +43,7 @@ optee_image_get_load_addr(const struct image_header *hdr) return optee_image_get_entry_point(hdr) - sizeof(struct optee_header); } -#if defined(CONFIG_OPTEE) +#if defined(CONFIG_OPTEE_IMAGE) int optee_verify_image(struct optee_header *hdr, unsigned long tzdram_start, unsigned long tzdram_len, unsigned long image_len); #else @@ -57,7 +57,7 @@ static inline int optee_verify_image(struct optee_header *hdr, #endif -#if defined(CONFIG_OPTEE) +#if defined(CONFIG_OPTEE_IMAGE) int optee_verify_bootm_image(unsigned long image_addr, unsigned long image_load_addr, unsigned long image_len); @@ -70,7 +70,7 @@ static inline int optee_verify_bootm_image(unsigned long image_addr, } #endif -#if defined(CONFIG_OPTEE) && defined(CONFIG_OF_LIBFDT) +#if defined(CONFIG_OPTEE_LIB) && defined(CONFIG_OF_LIBFDT) int optee_copy_fdt_nodes(void *new_blob); #else static inline int optee_copy_fdt_nodes(void *new_blob) diff --git a/lib/Makefile b/lib/Makefile index 09e380eb66..962470f496 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -16,7 +16,7 @@ obj-$(CONFIG_FIT) += libfdt/ obj-$(CONFIG_OF_LIVE) += of_live.o obj-$(CONFIG_CMD_DHRYSTONE) += dhry/ obj-$(CONFIG_ARCH_AT91) += at91/ -obj-$(CONFIG_OPTEE) += optee/ +obj-$(CONFIG_OPTEE_LIB) += optee/ obj-$(CONFIG_ASN1_DECODER) += asn1_decoder.o obj-y += crypto/ diff --git a/lib/optee/Kconfig b/lib/optee/Kconfig index 3290b6656d..3072c28912 100644 --- a/lib/optee/Kconfig +++ b/lib/optee/Kconfig @@ -1,23 +1,27 @@ -config OPTEE +config OPTEE_LIB + bool "Support OPTEE library" + default y if OPTEE || OPTEE_IMAGE + help + Selecting this option will enable the shared OPTEE library code. + +config OPTEE_IMAGE bool "Support OPTEE images" help - U-Boot can be configured to boot OPTEE images. - Selecting this option will enable shared OPTEE library code and - enable an OPTEE specific bootm command that will perform additional - OPTEE specific checks before booting an OPTEE image created with - mkimage. + Selecting this option to boot OPTEE images. + This option enable the OPTEE specific checks done before booting + an OPTEE image created with mkimage config OPTEE_LOAD_ADDR hex "OPTEE load address" default 0x00000000 - depends on OPTEE + depends on OPTEE_LIB help The load address of the bootable OPTEE binary. config OPTEE_TZDRAM_SIZE hex "Amount of Trust-Zone RAM for the OPTEE image" default 0x0000000 - depends on OPTEE + depends on OPTEE_LIB help The size of pre-allocated Trust Zone DRAM to allocate for the OPTEE runtime. @@ -25,7 +29,7 @@ config OPTEE_TZDRAM_SIZE config OPTEE_TZDRAM_BASE hex "Base address of Trust-Zone RAM for the OPTEE image" default 0x00000000 - depends on OPTEE + depends on OPTEE_LIB help The base address of pre-allocated Trust Zone DRAM for the OPTEE runtime. @@ -33,7 +37,7 @@ config OPTEE_TZDRAM_BASE config BOOTM_OPTEE bool "Support OPTEE bootm command" select BOOTM_LINUX - depends on OPTEE + select OPTEE_IMAGE help Select this command to enable chain-loading of a Linux kernel via an OPTEE firmware. diff --git a/lib/optee/Makefile b/lib/optee/Makefile index b692311864..9befe606d8 100644 --- a/lib/optee/Makefile +++ b/lib/optee/Makefile @@ -2,4 +2,4 @@ # # (C) Copyright 2017 Linaro -obj-$(CONFIG_OPTEE) += optee.o +obj-y += optee.o diff --git a/lib/optee/optee.c b/lib/optee/optee.c index 672690dc53..5676785cb5 100644 --- a/lib/optee/optee.c +++ b/lib/optee/optee.c @@ -20,6 +20,7 @@ "\n\theader lo=0x%08x hi=0x%08x size=0x%08lx arch=0x%08x" \ "\n\tuimage params 0x%08lx-0x%08lx\n" +#if defined(CONFIG_OPTEE_IMAGE) int optee_verify_image(struct optee_header *hdr, unsigned long tzdram_start, unsigned long tzdram_len, unsigned long image_len) { @@ -70,6 +71,7 @@ error: return ret; } +#endif #if defined(CONFIG_OF_LIBFDT) static int optee_copy_firmware_node(ofnode node, void *fdt_blob) From 4f53ac2adbc0f4d3bfebee1b414870e228469989 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Thu, 2 Sep 2021 11:56:17 +0200 Subject: [PATCH 04/19] tee: add a stub for tee_find_device Add stub for tee_find_device function when CONFIG_TEE is not activated to simplify the caller code. This patch allows to remove the CONFIG_IS_ENABLED(OPTEE) tests for stm32 platform. Signed-off-by: Patrick Delaunay Acked-by: Etienne Carriere Reviewed-by: Jens Wiklander --- arch/arm/mach-stm32mp/fdt.c | 1 - board/st/common/stm32mp_mtdparts.c | 3 +-- include/tee.h | 11 +++++++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-stm32mp/fdt.c b/arch/arm/mach-stm32mp/fdt.c index a19e954cf7..91330a68a4 100644 --- a/arch/arm/mach-stm32mp/fdt.c +++ b/arch/arm/mach-stm32mp/fdt.c @@ -341,7 +341,6 @@ int ft_system_setup(void *blob, struct bd_info *bd) * when FIP is not used by TF-A */ if (CONFIG_IS_ENABLED(STM32MP15x_STM32IMAGE) && - CONFIG_IS_ENABLED(OPTEE) && !tee_find_device(NULL, NULL, NULL, NULL)) stm32_fdt_disable_optee(blob); diff --git a/board/st/common/stm32mp_mtdparts.c b/board/st/common/stm32mp_mtdparts.c index 8b636d62fa..18878424c7 100644 --- a/board/st/common/stm32mp_mtdparts.c +++ b/board/st/common/stm32mp_mtdparts.c @@ -119,8 +119,7 @@ void board_mtdparts_default(const char **mtdids, const char **mtdparts) } #ifdef CONFIG_STM32MP15x_STM32IMAGE - if (!serial && CONFIG_IS_ENABLED(OPTEE) && - tee_find_device(NULL, NULL, NULL, NULL)) + if (!serial && tee_find_device(NULL, NULL, NULL, NULL)) tee = true; #endif diff --git a/include/tee.h b/include/tee.h index 2ef29bfc8f..44e9cd4321 100644 --- a/include/tee.h +++ b/include/tee.h @@ -307,11 +307,22 @@ bool tee_shm_is_registered(struct tee_shm *shm, struct udevice *dev); * Returns a probed TEE device of the first TEE device matched by the * match() callback or NULL. */ +#if CONFIG_IS_ENABLED(TEE) struct udevice *tee_find_device(struct udevice *start, int (*match)(struct tee_version_data *vers, const void *data), const void *data, struct tee_version_data *vers); +#else +static inline struct udevice *tee_find_device(struct udevice *start, + int (*match)(struct tee_version_data *vers, + const void *data), + const void *data, + struct tee_version_data *vers) +{ + return NULL; +} +#endif /** * tee_get_version() - Query capabilities of TEE device From 26fc66709c0de7732a12fd59dbce5a83eb454bae Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Tue, 7 Sep 2021 12:07:06 -0500 Subject: [PATCH 05/19] lib: optee: Avoid CONFIG_TZDRAM_* in optee_verify_bootm_image() The configs TZDRAM_BASE and TZDRAM_SIZE are expected to describe the memory allocated to the OPTEE region. according to according to commit c5a6e8bd00cc ("optee: Add optee_verify_bootm_image()"). The TZDRAM is with some limitations, described by "/reserved-memory" nodes in the devicetree. Consequently TZDRAM_BASE and TZDRAM_SIZE can point to imaginary regions which have nothing to do with actual DRAM. They are not used to configure the hardware or set up the Trust Zone Controller (TZC) for OP-TEE -- the devicetree values are used instead. When a valid OP-TEE image does not fall within the region described by these configs, u-boot will refuse to load it. In fact, it mostly serves to cause "bootm" to reject perfectly good OP-TEE images. Ironically, someone has to correctly configure the devicetree for TZDRAM, then go back and enter the same information in Kconfig for "bootm". To remedy this, do not use TZDRAM_BASE and TZDRAM_SIZE in the verification of OPTEE images. Signed-off-by: Alexandru Gagniuc --- include/tee/optee.h | 14 -------------- lib/optee/optee.c | 21 ++++++--------------- 2 files changed, 6 insertions(+), 29 deletions(-) diff --git a/include/tee/optee.h b/include/tee/optee.h index 2928597b61..5412bc7386 100644 --- a/include/tee/optee.h +++ b/include/tee/optee.h @@ -43,20 +43,6 @@ optee_image_get_load_addr(const struct image_header *hdr) return optee_image_get_entry_point(hdr) - sizeof(struct optee_header); } -#if defined(CONFIG_OPTEE_IMAGE) -int optee_verify_image(struct optee_header *hdr, unsigned long tzdram_start, - unsigned long tzdram_len, unsigned long image_len); -#else -static inline int optee_verify_image(struct optee_header *hdr, - unsigned long tzdram_start, - unsigned long tzdram_len, - unsigned long image_len) -{ - return -EPERM; -} - -#endif - #if defined(CONFIG_OPTEE_IMAGE) int optee_verify_bootm_image(unsigned long image_addr, unsigned long image_load_addr, diff --git a/lib/optee/optee.c b/lib/optee/optee.c index 5676785cb5..766d0d9e3f 100644 --- a/lib/optee/optee.c +++ b/lib/optee/optee.c @@ -16,15 +16,13 @@ #define optee_hdr_err_msg \ "OPTEE verification error:" \ - "\n\thdr=%p image=0x%08lx magic=0x%08x tzdram 0x%08lx-0x%08lx " \ + "\n\thdr=%p image=0x%08lx magic=0x%08x" \ "\n\theader lo=0x%08x hi=0x%08x size=0x%08lx arch=0x%08x" \ "\n\tuimage params 0x%08lx-0x%08lx\n" #if defined(CONFIG_OPTEE_IMAGE) -int optee_verify_image(struct optee_header *hdr, unsigned long tzdram_start, - unsigned long tzdram_len, unsigned long image_len) +static int optee_verify_image(struct optee_header *hdr, unsigned long image_len) { - unsigned long tzdram_end = tzdram_start + tzdram_len; uint32_t tee_file_size; tee_file_size = hdr->init_size + hdr->paged_size + @@ -32,11 +30,7 @@ int optee_verify_image(struct optee_header *hdr, unsigned long tzdram_start, if (hdr->magic != OPTEE_MAGIC || hdr->version != OPTEE_VERSION || - hdr->init_load_addr_hi > tzdram_end || - hdr->init_load_addr_lo < tzdram_start || - tee_file_size > tzdram_len || - tee_file_size != image_len || - (hdr->init_load_addr_lo + tee_file_size) > tzdram_end) { + tee_file_size != image_len) { return -EINVAL; } @@ -48,12 +42,9 @@ int optee_verify_bootm_image(unsigned long image_addr, unsigned long image_len) { struct optee_header *hdr = (struct optee_header *)image_addr; - unsigned long tzdram_start = CONFIG_OPTEE_TZDRAM_BASE; - unsigned long tzdram_len = CONFIG_OPTEE_TZDRAM_SIZE; - int ret; - ret = optee_verify_image(hdr, tzdram_start, tzdram_len, image_len); + ret = optee_verify_image(hdr, image_len); if (ret) goto error; @@ -64,8 +55,8 @@ int optee_verify_bootm_image(unsigned long image_addr, return ret; error: - printf(optee_hdr_err_msg, hdr, image_addr, hdr->magic, tzdram_start, - tzdram_start + tzdram_len, hdr->init_load_addr_lo, + printf(optee_hdr_err_msg, hdr, image_addr, hdr->magic, + hdr->init_load_addr_lo, hdr->init_load_addr_hi, image_len, hdr->arch, image_load_addr, image_load_addr + image_len); From 1ab968b2fb1d63c49943450bfff14d18c0f54705 Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Tue, 7 Sep 2021 12:07:07 -0500 Subject: [PATCH 06/19] lib: optee: Remove CONFIG_OPTEE_TZDRAM_BASE It is no longer used in u-boot. Information about the TZDRAM location is usually available in the devicetree as "/reserved-memory/" nodes. Because this isn't used, remove it. Signed-off-by: Alexandru Gagniuc --- configs/warp7_bl33_defconfig | 1 - configs/warp7_defconfig | 1 - lib/optee/Kconfig | 8 -------- 3 files changed, 10 deletions(-) diff --git a/configs/warp7_bl33_defconfig b/configs/warp7_bl33_defconfig index d127a4f8d3..246a1ec6fe 100644 --- a/configs/warp7_bl33_defconfig +++ b/configs/warp7_bl33_defconfig @@ -69,4 +69,3 @@ CONFIG_USB_ETH_CDC=y CONFIG_USBNET_HOST_ADDR="de:ad:be:af:00:00" CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_OPTEE_TZDRAM_SIZE=0x02000000 -CONFIG_OPTEE_TZDRAM_BASE=0x9e000000 diff --git a/configs/warp7_defconfig b/configs/warp7_defconfig index 4b339b47ca..27529dd991 100644 --- a/configs/warp7_defconfig +++ b/configs/warp7_defconfig @@ -75,5 +75,4 @@ CONFIG_USB_ETH_CDC=y CONFIG_USBNET_HOST_ADDR="de:ad:be:af:00:00" CONFIG_OPTEE_LOAD_ADDR=0x84000000 CONFIG_OPTEE_TZDRAM_SIZE=0x3000000 -CONFIG_OPTEE_TZDRAM_BASE=0x9d000000 CONFIG_BOOTM_OPTEE=y diff --git a/lib/optee/Kconfig b/lib/optee/Kconfig index 3072c28912..3f8ce49678 100644 --- a/lib/optee/Kconfig +++ b/lib/optee/Kconfig @@ -26,14 +26,6 @@ config OPTEE_TZDRAM_SIZE The size of pre-allocated Trust Zone DRAM to allocate for the OPTEE runtime. -config OPTEE_TZDRAM_BASE - hex "Base address of Trust-Zone RAM for the OPTEE image" - default 0x00000000 - depends on OPTEE_LIB - help - The base address of pre-allocated Trust Zone DRAM for - the OPTEE runtime. - config BOOTM_OPTEE bool "Support OPTEE bootm command" select BOOTM_LINUX From f6953047cb99d50cca0dc73740337b08fbdc1bf8 Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Tue, 7 Sep 2021 12:07:08 -0500 Subject: [PATCH 07/19] lib: optee: Remove CONFIG_OPTEE_LOAD_ADDR This value is not used by u-boot, and it should not. The load address of an OPTEE image is defined by said image. Either a uImage or a FIT will have a defined load address and entry point. Those values are the correct ones, not CONFIG_OPTEE_LOAD_ADDR. Commit f25006b96e9f ("optee: Add CONFIG_OPTEE_LOAD_ADDR") justifies this config by requiring its presence in u-boot's .config for other images as part of a larger build, claiming it is "the best way". This argument is not persuasive. U-boot's configuration is driven by platform requirements, not the other way around. It seems more likely that the argument is conflating tooling issues with Kconfig. Yocto and buildroot have excellent mechanisms for defining values across the board (pun intended). u-boot's Kconfig is the wrong place to do it. Furthermore, it is not "best" for u-boot because it hardcodes a value which is then not used. In fact the load address that u-boot uses is the one derived from the OPTEE image. Confused yet? I sure was. To prevent future confusion, remove CONFIG_OPTEE_LOAD_ADDR. Signed-off-by: Alexandru Gagniuc --- configs/warp7_defconfig | 1 - include/configs/warp7.h | 5 ----- lib/optee/Kconfig | 7 ------- 3 files changed, 13 deletions(-) diff --git a/configs/warp7_defconfig b/configs/warp7_defconfig index 27529dd991..db8d4f625a 100644 --- a/configs/warp7_defconfig +++ b/configs/warp7_defconfig @@ -73,6 +73,5 @@ CONFIG_USB_GADGET_DOWNLOAD=y CONFIG_USB_ETHER=y CONFIG_USB_ETH_CDC=y CONFIG_USBNET_HOST_ADDR="de:ad:be:af:00:00" -CONFIG_OPTEE_LOAD_ADDR=0x84000000 CONFIG_OPTEE_TZDRAM_SIZE=0x3000000 CONFIG_BOOTM_OPTEE=y diff --git a/include/configs/warp7.h b/include/configs/warp7.h index 0822eaf555..74fb988b76 100644 --- a/include/configs/warp7.h +++ b/include/configs/warp7.h @@ -28,10 +28,6 @@ #define BOOT_SCR_STRING "source ${bootscriptaddr}\0" #endif -#ifndef CONFIG_OPTEE_LOAD_ADDR -#define CONFIG_OPTEE_LOAD_ADDR 0 -#endif - #define CONFIG_EXTRA_ENV_SETTINGS \ CONFIG_DFU_ENV_SETTINGS \ "script=boot.scr\0" \ @@ -46,7 +42,6 @@ "fdt_file=imx7s-warp.dtb\0" \ "fdt_addr=" __stringify(CONFIG_SYS_FDT_ADDR)"\0" \ "fdtovaddr=0x83100000\0" \ - "optee_addr=" __stringify(CONFIG_OPTEE_LOAD_ADDR)"\0" \ "boot_fdt=try\0" \ "ip_dyn=yes\0" \ "mmcdev="__stringify(CONFIG_SYS_MMC_ENV_DEV)"\0" \ diff --git a/lib/optee/Kconfig b/lib/optee/Kconfig index 3f8ce49678..e6834d4d3e 100644 --- a/lib/optee/Kconfig +++ b/lib/optee/Kconfig @@ -11,13 +11,6 @@ config OPTEE_IMAGE This option enable the OPTEE specific checks done before booting an OPTEE image created with mkimage -config OPTEE_LOAD_ADDR - hex "OPTEE load address" - default 0x00000000 - depends on OPTEE_LIB - help - The load address of the bootable OPTEE binary. - config OPTEE_TZDRAM_SIZE hex "Amount of Trust-Zone RAM for the OPTEE image" default 0x0000000 From c5b68ef8af3c2f515c1f5b8d63a69359a85d753b Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Tue, 7 Sep 2021 12:07:09 -0500 Subject: [PATCH 08/19] arm: imx: mx7: Move CONFIG_OPTEE_TZDRAM_SIZE from lib/optee This config is only used by three boards with this SOC. Most other platforms derive this information from devicetree, and are unlikely to ever need this config. Moreover, it is confusing when Kconfig asks for this value under "Support OPTEE images", but does not do anything with the value. Move it to imx7 for those boards who still make use of it. Signed-off-by: Alexandru Gagniuc --- arch/arm/mach-imx/mx7/Kconfig | 8 ++++++++ lib/optee/Kconfig | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-imx/mx7/Kconfig b/arch/arm/mach-imx/mx7/Kconfig index 059e65879c..0cad825287 100644 --- a/arch/arm/mach-imx/mx7/Kconfig +++ b/arch/arm/mach-imx/mx7/Kconfig @@ -23,6 +23,14 @@ config SPL_TEXT_BASE depends on SPL default 0x00912000 +config OPTEE_TZDRAM_SIZE + hex "Amount of Trust-Zone RAM for the OPTEE image" + default 0x0000000 + depends on OPTEE_LIB + help + The size of pre-allocated Trust Zone DRAM to allocate for the OPTEE + runtime. + choice prompt "MX7 board select" optional diff --git a/lib/optee/Kconfig b/lib/optee/Kconfig index e6834d4d3e..517136a448 100644 --- a/lib/optee/Kconfig +++ b/lib/optee/Kconfig @@ -11,14 +11,6 @@ config OPTEE_IMAGE This option enable the OPTEE specific checks done before booting an OPTEE image created with mkimage -config OPTEE_TZDRAM_SIZE - hex "Amount of Trust-Zone RAM for the OPTEE image" - default 0x0000000 - depends on OPTEE_LIB - help - The size of pre-allocated Trust Zone DRAM to allocate for the OPTEE - runtime. - config BOOTM_OPTEE bool "Support OPTEE bootm command" select BOOTM_LINUX From 390ccffe07c45a3ad584ee6199cc1e63d07981ee Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 11 Sep 2021 17:05:51 -0500 Subject: [PATCH 09/19] gpio: Verify validity of pin offsets when looking up names Translation of a pin name to a device+offset should fail if the offset is larger than the number of pins in the GPIO bank. Signed-off-by: Samuel Holland Reviewed-by: Simon Glass --- drivers/gpio/gpio-uclass.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index bb2f23241e..45a7f8def4 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -141,7 +141,8 @@ int dm_gpio_lookup_name(const char *name, struct gpio_desc *desc) if (!strncasecmp(name, uc_priv->bank_name, len)) { if (!strict_strtoul(name + len, 10, &offset)) - break; + if (offset < uc_priv->gpio_count) + break; } /* From 37c10bf7ef22ccaa349581984340a616fb1c6ffb Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 11 Sep 2021 17:05:52 -0500 Subject: [PATCH 10/19] gpio: Verify validity of pin offsets from device trees Translation of an OF GPIO specifier should fail if the pin offset is larger than the number of pins in the GPIO bank. Signed-off-by: Samuel Holland Reviewed-by: Simon Glass --- drivers/gpio/gpio-uclass.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 45a7f8def4..fde046e8df 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -189,10 +189,14 @@ int gpio_lookup_name(const char *name, struct udevice **devp, int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc, struct ofnode_phandle_args *args) { + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + if (args->args_count < 1) return -EINVAL; desc->offset = args->args[0]; + if (desc->offset >= uc_priv->gpio_count) + return -EINVAL; if (args->args_count < 2) return 0; From 8a47982ed8d40595a83b82b2298753873e597708 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 11 Sep 2021 17:05:53 -0500 Subject: [PATCH 11/19] gpio: Factor out DT flag translation The generic GPIO flags binding is shared across many drivers, some of which need their own xlate function. Factor out the flag translation code from gpio_xlate_offs_flags so it does not need to be duplicated. Signed-off-by: Samuel Holland Reviewed-by: Simon Glass --- drivers/gpio/gpio-uclass.c | 50 ++++++++++++++++++++++---------------- include/asm-generic/gpio.h | 8 ++++++ 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index fde046e8df..1c5e2e7976 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -186,6 +186,34 @@ int gpio_lookup_name(const char *name, struct udevice **devp, return 0; } +unsigned long gpio_flags_xlate(uint32_t arg) +{ + unsigned long flags = 0; + + if (arg & GPIO_ACTIVE_LOW) + flags |= GPIOD_ACTIVE_LOW; + + /* + * need to test 2 bits for gpio output binding: + * OPEN_DRAIN (0x6) = SINGLE_ENDED (0x2) | LINE_OPEN_DRAIN (0x4) + * OPEN_SOURCE (0x2) = SINGLE_ENDED (0x2) | LINE_OPEN_SOURCE (0x0) + */ + if (arg & GPIO_SINGLE_ENDED) { + if (arg & GPIO_LINE_OPEN_DRAIN) + flags |= GPIOD_OPEN_DRAIN; + else + flags |= GPIOD_OPEN_SOURCE; + } + + if (arg & GPIO_PULL_UP) + flags |= GPIOD_PULL_UP; + + if (arg & GPIO_PULL_DOWN) + flags |= GPIOD_PULL_DOWN; + + return flags; +} + int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc, struct ofnode_phandle_args *args) { @@ -201,27 +229,7 @@ int gpio_xlate_offs_flags(struct udevice *dev, struct gpio_desc *desc, if (args->args_count < 2) return 0; - desc->flags = 0; - if (args->args[1] & GPIO_ACTIVE_LOW) - desc->flags |= GPIOD_ACTIVE_LOW; - - /* - * need to test 2 bits for gpio output binding: - * OPEN_DRAIN (0x6) = SINGLE_ENDED (0x2) | LINE_OPEN_DRAIN (0x4) - * OPEN_SOURCE (0x2) = SINGLE_ENDED (0x2) | LINE_OPEN_SOURCE (0x0) - */ - if (args->args[1] & GPIO_SINGLE_ENDED) { - if (args->args[1] & GPIO_LINE_OPEN_DRAIN) - desc->flags |= GPIOD_OPEN_DRAIN; - else - desc->flags |= GPIOD_OPEN_SOURCE; - } - - if (args->args[1] & GPIO_PULL_UP) - desc->flags |= GPIOD_PULL_UP; - - if (args->args[1] & GPIO_PULL_DOWN) - desc->flags |= GPIOD_PULL_DOWN; + desc->flags = gpio_flags_xlate(args->args[1]); return 0; } diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 6de13d925e..fa9b80722e 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -221,6 +221,14 @@ int gpio_requestf(unsigned gpio, const char *fmt, ...) struct fdtdec_phandle_args; +/** + * gpio_flags_xlate() - convert DT flags to internal flags + * + * This routine converts the GPIO_* flags from the generic DT binding to the + * GPIOD_* flags used internally. It can be called from driver xlate functions. + */ +unsigned long gpio_flags_xlate(uint32_t arg); + /** * gpio_xlate_offs_flags() - implementation for common use of dm_gpio_ops.xlate * From 01e1e2a966e282524f01ab14a5ceac793973cf28 Mon Sep 17 00:00:00 2001 From: Alexandru Gagniuc Date: Wed, 15 Sep 2021 14:33:01 -0500 Subject: [PATCH 12/19] test/py: Check hashes produced by mkimage against known values Target code and mkimage share the same hashing infrastructure. If one is wrong, it's very likely that both are wrong in the same way. Thus testing won't catch hash regressions. This already happened in commit 92055e138f28 ("image: Drop if/elseif hash selection in calculate_hash()"). None of the tests caught that CRC32 was broken. Instead of testing hash_calculate() against itself, create a FIT with containing a kernel with pre-calculated hashes. Then check the hashes produced against the known good hashes. Signed-off-by: Alexandru Gagniuc Reviewed-by: Simon Glass --- test/py/tests/test_fit_hashes.py | 111 ++++++++++++++++++++++++++++ test/py/tests/vboot/hash-images.its | 76 +++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 test/py/tests/test_fit_hashes.py create mode 100644 test/py/tests/vboot/hash-images.its diff --git a/test/py/tests/test_fit_hashes.py b/test/py/tests/test_fit_hashes.py new file mode 100644 index 0000000000..e228ea96d3 --- /dev/null +++ b/test/py/tests/test_fit_hashes.py @@ -0,0 +1,111 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2021 Alexandru Gagniuc + +""" +Check hashes produced by mkimage against known values + +This test checks the correctness of mkimage's hashes. by comparing the mkimage +output of a fixed data block with known good hashes. +This test doesn't run the sandbox. It only checks the host tool 'mkimage' +""" + +import pytest +import u_boot_utils as util + +kernel_hashes = { + "sha512" : "f18c1486a2c29f56360301576cdfce4dfd8e8e932d0ed8e239a1f314b8ae1d77b2a58cd7fe32e4075e69448e623ce53b0b6aa6ce5626d2c189a5beae29a68d93", + "sha384" : "16e28976740048485d08d793d8bf043ebc7826baf2bc15feac72825ad67530ceb3d09e0deb6932c62a5a0e9f3936baf4", + "sha256" : "2955c56bc1e5050c111ba6e089e0f5342bb47dedf77d87e3f429095feb98a7e5", + "sha1" : "652383e1a6d946953e1f65092c9435f6452c2ab7", + "md5" : "4879e5086e4c76128e525b5fe2af55f1", + "crc32" : "32eddfdf", + "crc16-ccitt" : "d4be" +} + +class ReadonlyFitImage(object): + """ Helper to manipulate a FIT image on disk """ + def __init__(self, cons, file_name): + self.fit = file_name + self.cons = cons + self.hashable_nodes = set() + + def __fdt_list(self, path): + return util.run_and_log(self.cons, f'fdtget -l {self.fit} {path}') + + def __fdt_get(self, node, prop): + val = util.run_and_log(self.cons, f'fdtget {self.fit} {node} {prop}') + return val.rstrip('\n') + + def __fdt_get_sexadecimal(self, node, prop): + numbers = util.run_and_log(self.cons, f'fdtget -tbx {self.fit} {node} {prop}') + + sexadecimal = '' + for num in numbers.rstrip('\n').split(' '): + sexadecimal += num.zfill(2) + return sexadecimal + + def find_hashable_image_nodes(self): + for node in self.__fdt_list('/images').split(): + # We only have known hashes for the kernel node + if 'kernel' not in node: + continue + self.hashable_nodes.add(f'/images/{node}') + + return self.hashable_nodes + + def verify_hashes(self): + for image in self.hashable_nodes: + algos = set() + for node in self.__fdt_list(image).split(): + if "hash-" not in node: + continue + + raw_hash = self.__fdt_get_sexadecimal(f'{image}/{node}', 'value') + algo = self.__fdt_get(f'{image}/{node}', 'algo') + algos.add(algo) + + good_hash = kernel_hashes[algo] + if good_hash != raw_hash: + raise ValueError(f'{image} Borked hash: {algo}'); + + # Did we test all the hashes we set out to test? + missing_algos = kernel_hashes.keys() - algos + if (missing_algos): + raise ValueError(f'Missing hashes from FIT: {missing_algos}') + + +@pytest.mark.buildconfigspec('hash') +@pytest.mark.requiredtool('dtc') +@pytest.mark.requiredtool('fdtget') +@pytest.mark.requiredtool('fdtput') +def test_mkimage_hashes(u_boot_console): + """ Test that hashes generated by mkimage are correct. """ + + def assemble_fit_image(dest_fit, its, destdir): + dtc_args = f'-I dts -O dtb -i {destdir}' + util.run_and_log(cons, [mkimage, '-D', dtc_args, '-f', its, dest_fit]) + + def dtc(dts): + dtb = dts.replace('.dts', '.dtb') + util.run_and_log(cons, f'dtc {datadir}/{dts} -O dtb -o {tempdir}/{dtb}') + + cons = u_boot_console + mkimage = cons.config.build_dir + '/tools/mkimage' + datadir = cons.config.source_dir + '/test/py/tests/vboot/' + tempdir = cons.config.result_dir + fit_file = f'{tempdir}/test.fit' + dtc('sandbox-kernel.dts') + + # Create a fake kernel image -- Avoid zeroes or crc16 will be zero + with open(f'{tempdir}/test-kernel.bin', 'w') as fd: + fd.write(500 * chr(0xa5)) + + assemble_fit_image(fit_file, f'{datadir}/hash-images.its', tempdir) + + fit = ReadonlyFitImage(cons, fit_file) + nodes = fit.find_hashable_image_nodes() + if len(nodes) == 0: + raise ValueError('FIT image has no "/image" nodes with "hash-..."') + + fit.verify_hashes() diff --git a/test/py/tests/vboot/hash-images.its b/test/py/tests/vboot/hash-images.its new file mode 100644 index 0000000000..3ff797288c --- /dev/null +++ b/test/py/tests/vboot/hash-images.its @@ -0,0 +1,76 @@ +/dts-v1/; + +/ { + description = "Chrome OS kernel image with one or more FDT blobs"; + #address-cells = <1>; + + images { + kernel { + data = /incbin/("test-kernel.bin"); + type = "kernel_noload"; + arch = "sandbox"; + os = "linux"; + compression = "none"; + load = <0x4>; + entry = <0x8>; + kernel-version = <1>; + hash-0 { + algo = "crc16-ccitt"; + }; + hash-1 { + algo = "crc32"; + }; + hash-2 { + algo = "md5"; + }; + hash-3 { + algo = "sha1"; + }; + hash-4 { + algo = "sha256"; + }; + hash-5 { + algo = "sha384"; + }; + hash-6 { + algo = "sha512"; + }; + }; + fdt-1 { + description = "snow"; + data = /incbin/("sandbox-kernel.dtb"); + type = "flat_dt"; + arch = "sandbox"; + compression = "none"; + fdt-version = <1>; + hash-0 { + algo = "crc16-ccitt"; + }; + hash-1 { + algo = "crc32"; + }; + hash-2 { + algo = "md5"; + }; + hash-3 { + algo = "sha1"; + }; + hash-4 { + algo = "sha256"; + }; + hash-5 { + algo = "sha384"; + }; + hash-6 { + algo = "sha512"; + }; + }; + }; + configurations { + default = "conf-1"; + conf-1 { + kernel = "kernel"; + fdt = "fdt-1"; + }; + }; +}; From cfb83f36666154d6eba51c03a5080a91be26f664 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 19 Sep 2021 15:14:48 -0600 Subject: [PATCH 13/19] test: Allow vboot tests to run in parallel Update the tests to use separate working directories, so we can run them in parallel. It also makes it possible to see the individual output files after the tests have completed. Signed-off-by: Simon Glass --- test/py/tests/test_vboot.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py index 6dff6779d1..095e00cce3 100644 --- a/test/py/tests/test_vboot.py +++ b/test/py/tests/test_vboot.py @@ -24,6 +24,7 @@ For configuration verification: Tests run with both SHA1 and SHA256 hashing. """ +import os import shutil import struct import pytest @@ -34,16 +35,16 @@ import vboot_evil # Only run the full suite on a few combinations, since it doesn't add any more # test coverage. TESTDATA = [ - ['sha1', '', None, False, True], - ['sha1', '', '-E -p 0x10000', False, False], - ['sha1', '-pss', None, False, False], - ['sha1', '-pss', '-E -p 0x10000', False, False], - ['sha256', '', None, False, False], - ['sha256', '', '-E -p 0x10000', False, False], - ['sha256', '-pss', None, False, False], - ['sha256', '-pss', '-E -p 0x10000', False, False], - ['sha256', '-pss', None, True, False], - ['sha256', '-pss', '-E -p 0x10000', True, True], + ['sha1-basic', 'sha1', '', None, False, True], + ['sha1-pad', 'sha1', '', '-E -p 0x10000', False, False], + ['sha1-pss', 'sha1', '-pss', None, False, False], + ['sha1-pss-pad', 'sha1', '-pss', '-E -p 0x10000', False, False], + ['sha256-basic', 'sha256', '', None, False, False], + ['sha256-pad', 'sha256', '', '-E -p 0x10000', False, False], + ['sha256-pss', 'sha256', '-pss', None, False, False], + ['sha256-pss-pad', 'sha256', '-pss', '-E -p 0x10000', False, False], + ['sha256-pss-required', 'sha256', '-pss', None, True, False], + ['sha256-pss-pad-required', 'sha256', '-pss', '-E -p 0x10000', True, True], ] @pytest.mark.boardspec('sandbox') @@ -52,9 +53,9 @@ TESTDATA = [ @pytest.mark.requiredtool('fdtget') @pytest.mark.requiredtool('fdtput') @pytest.mark.requiredtool('openssl') -@pytest.mark.parametrize("sha_algo,padding,sign_options,required,full_test", +@pytest.mark.parametrize("name,sha_algo,padding,sign_options,required,full_test", TESTDATA) -def test_vboot(u_boot_console, sha_algo, padding, sign_options, required, +def test_vboot(u_boot_console, name, sha_algo, padding, sign_options, required, full_test): """Test verified boot signing with mkimage and verification with 'bootm'. @@ -365,7 +366,9 @@ def test_vboot(u_boot_console, sha_algo, padding, sign_options, required, run_bootm(sha_algo, 'multi required key', '', False) cons = u_boot_console - tmpdir = cons.config.result_dir + '/' + tmpdir = os.path.join(cons.config.result_dir, name) + '/' + if not os.path.exists(tmpdir): + os.mkdir(tmpdir) datadir = cons.config.source_dir + '/test/py/tests/vboot/' fit = '%stest.fit' % tmpdir mkimage = cons.config.build_dir + '/tools/mkimage' From ea3164eeb040bdff65323f8717f5dc2296f548a4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 19 Sep 2021 15:14:49 -0600 Subject: [PATCH 14/19] test: Allow hush tests to run in parallel The -z tests don't really need to be part of the main set. Separate them out so we can drop the test setup/cleans functions and thus run all tests in parallel. Signed-off-by: Simon Glass --- test/py/tests/test_hush_if_test.py | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/test/py/tests/test_hush_if_test.py b/test/py/tests/test_hush_if_test.py index d117921a6a..37c1608bb2 100644 --- a/test/py/tests/test_hush_if_test.py +++ b/test/py/tests/test_hush_if_test.py @@ -119,11 +119,6 @@ subtests = ( ('test ! ! aaa != aaa -o ! ! bbb = bbb', True), ('test ! ! aaa = aaa -o ! ! bbb != bbb', True), ('test ! ! aaa = aaa -o ! ! bbb = bbb', True), - - # -z operator. - - ('test -z "$ut_var_nonexistent"', True), - ('test -z "$ut_var_exists"', False), ) def exec_hush_if(u_boot_console, expr, result): @@ -141,12 +136,6 @@ def exec_hush_if(u_boot_console, expr, result): response = u_boot_console.run_command(cmd) assert response.strip() == str(result).lower() -def test_hush_if_test_setup(u_boot_console): - """Set up environment variables used during the "if" tests.""" - - u_boot_console.run_command('setenv ut_var_nonexistent') - u_boot_console.run_command('setenv ut_var_exists 1') - @pytest.mark.buildconfigspec('cmd_echo') @pytest.mark.parametrize('expr,result', subtests) def test_hush_if_test(u_boot_console, expr, result): @@ -154,9 +143,12 @@ def test_hush_if_test(u_boot_console, expr, result): exec_hush_if(u_boot_console, expr, result) -def test_hush_if_test_teardown(u_boot_console): - """Clean up environment variables used during the "if" tests.""" - +def test_hush_z(u_boot_console): + """Test the -z operator""" + u_boot_console.run_command('setenv ut_var_nonexistent') + u_boot_console.run_command('setenv ut_var_exists 1') + exec_hush_if(u_boot_console, 'test -z "$ut_var_nonexistent"', True) + exec_hush_if(u_boot_console, 'test -z "$ut_var_exists"', False) u_boot_console.run_command('setenv ut_var_exists') # We might test this on real filesystems via UMS, DFU, 'save', etc. From 17d1fe1c4483d57edd3de5647973168713129374 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 19 Sep 2021 15:14:50 -0600 Subject: [PATCH 15/19] test: Allow tpm2 tests to run in parallel These tests currently run in a particular sequence, with some of them depending on the actions of earlier tests. Add a check for sandbox and reset to a known state at the start of each test, so that all tests can run in parallel. Signed-off-by: Simon Glass --- test/py/tests/test_tpm2.py | 52 +++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/test/py/tests/test_tpm2.py b/test/py/tests/test_tpm2.py index c7a9dc19bd..7c89f5f293 100644 --- a/test/py/tests/test_tpm2.py +++ b/test/py/tests/test_tpm2.py @@ -52,14 +52,17 @@ def force_init(u_boot_console, force=False): u_boot_console.run_command('tpm2 clear TPM2_RH_PLATFORM') u_boot_console.run_command('echo --- end of init ---') +def is_sandbox(cons): + # Array slice removes leading/trailing quotes. + sys_arch = cons.config.buildconfig.get('config_sys_arch', '"sandbox"')[1:-1] + return sys_arch == 'sandbox' + @pytest.mark.buildconfigspec('cmd_tpm_v2') def test_tpm2_init(u_boot_console): """Init the software stack to use TPMv2 commands.""" - skip_test = u_boot_console.config.env.get('env__tpm_device_test_skip', False) if skip_test: pytest.skip('skip TPM device test') - u_boot_console.run_command('tpm2 init') output = u_boot_console.run_command('echo $?') assert output.endswith('0') @@ -70,6 +73,19 @@ def test_tpm2_startup(u_boot_console): Initiate the TPM internal state machine. """ + u_boot_console.run_command('tpm2 startup TPM2_SU_CLEAR') + output = u_boot_console.run_command('echo $?') + assert output.endswith('0') + +def tpm2_sandbox_init(u_boot_console): + """Put sandbox back into a known state so we can run a test + + This allows all tests to run in parallel, since no test depends on another. + """ + u_boot_console.restart_uboot() + u_boot_console.run_command('tpm2 init') + output = u_boot_console.run_command('echo $?') + assert output.endswith('0') skip_test = u_boot_console.config.env.get('env__tpm_device_test_skip', False) if skip_test: @@ -78,12 +94,25 @@ def test_tpm2_startup(u_boot_console): output = u_boot_console.run_command('echo $?') assert output.endswith('0') + u_boot_console.run_command('tpm2 self_test full') + output = u_boot_console.run_command('echo $?') + assert output.endswith('0') + @pytest.mark.buildconfigspec('cmd_tpm_v2') -def test_tpm2_self_test_full(u_boot_console): +def test_tpm2_sandbox_self_test_full(u_boot_console): """Execute a TPM2_SelfTest (full) command. Ask the TPM to perform all self tests to also enable full capabilities. """ + if is_sandbox(u_boot_console): + u_boot_console.restart_uboot() + u_boot_console.run_command('tpm2 init') + output = u_boot_console.run_command('echo $?') + assert output.endswith('0') + + u_boot_console.run_command('tpm2 startup TPM2_SU_CLEAR') + output = u_boot_console.run_command('echo $?') + assert output.endswith('0') skip_test = u_boot_console.config.env.get('env__tpm_device_test_skip', False) if skip_test: @@ -103,6 +132,8 @@ def test_tpm2_continue_self_test(u_boot_console): skip_test = u_boot_console.config.env.get('env__tpm_device_test_skip', False) if skip_test: pytest.skip('skip TPM device test') + if is_sandbox(u_boot_console): + tpm2_sandbox_init(u_boot_console) u_boot_console.run_command('tpm2 self_test continue') output = u_boot_console.run_command('echo $?') assert output.endswith('0') @@ -119,6 +150,8 @@ def test_tpm2_clear(u_boot_console): not have a password set, otherwise this test will fail. ENDORSEMENT and PLATFORM hierarchies are also available. """ + if is_sandbox(u_boot_console): + tpm2_sandbox_init(u_boot_console) skip_test = u_boot_console.config.env.get('env__tpm_device_test_skip', False) if skip_test: @@ -140,7 +173,8 @@ def test_tpm2_change_auth(u_boot_console): Use the LOCKOUT hierarchy for this. ENDORSEMENT and PLATFORM hierarchies are also available. """ - + if is_sandbox(u_boot_console): + tpm2_sandbox_init(u_boot_console) force_init(u_boot_console) u_boot_console.run_command('tpm2 change_auth TPM2_RH_LOCKOUT unicorn') @@ -164,6 +198,8 @@ def test_tpm2_get_capability(u_boot_console): There is no expected default values because it would depend on the chip used. We can still save them in order to check they have changed later. """ + if is_sandbox(u_boot_console): + tpm2_sandbox_init(u_boot_console) force_init(u_boot_console) ram = u_boot_utils.find_ram_base(u_boot_console) @@ -186,7 +222,8 @@ def test_tpm2_dam_parameters(u_boot_console): the authentication, otherwise the lockout will be engaged after the first failed authentication attempt. """ - + if is_sandbox(u_boot_console): + tpm2_sandbox_init(u_boot_console) force_init(u_boot_console) ram = u_boot_utils.find_ram_base(u_boot_console) @@ -209,6 +246,8 @@ def test_tpm2_pcr_read(u_boot_console): Perform a PCR read of the 0th PCR. Must be zero. """ + if is_sandbox(u_boot_console): + tpm2_sandbox_init(u_boot_console) force_init(u_boot_console) ram = u_boot_utils.find_ram_base(u_boot_console) @@ -236,7 +275,8 @@ def test_tpm2_pcr_extend(u_boot_console): No authentication mechanism is used here, not protecting against packet replay, yet. """ - + if is_sandbox(u_boot_console): + tpm2_sandbox_init(u_boot_console) force_init(u_boot_console) ram = u_boot_utils.find_ram_base(u_boot_console) From 5f8cefb7b1f3c1ba3d3f698345bf173038da2b0c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 19 Sep 2021 15:14:51 -0600 Subject: [PATCH 16/19] doc: test: Explain how to run pytests in parallel Add documentation for this so people can try it out. At present it does not fully work. Signed-off-by: Simon Glass --- doc/develop/py_testing.rst | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/doc/develop/py_testing.rst b/doc/develop/py_testing.rst index c4cecc0a01..4f1e1f66e7 100644 --- a/doc/develop/py_testing.rst +++ b/doc/develop/py_testing.rst @@ -103,6 +103,36 @@ will be written to `${build_dir}/test-log.html`. This is best viewed in a web browser, but may be read directly as plain text, perhaps with the aid of the `html2text` utility. +Running tests in parallel +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Note: This does not fully work yet and is documented only so you can try to +fix the problems. + +First install support for parallel tests:: + + pip3 install pytest-xdist + +Then build sandbox in a suitable build directory. It is not possible to use +the --build flag with xdist. + +Finally, run the tests in parallel using the -n flag:: + + # build sandbox first, in a suitable build directory. It is not possible + # to use the --build flag with -n + test/py/test.py -B sandbox --build-dir /tmp/b/sandbox -q -k 'not slow' -n32 + +At least the following non-slow tests are known to fail: + +- test_fit_ecdsa +- test_bind_unbind_with_uclass +- ut_dm_spi_flash +- test_gpt_rename_partition +- test_gpt_swap_partitions +- test_pinmux_status +- test_sqfs_load + + Testing under a debugger ~~~~~~~~~~~~~~~~~~~~~~~~ From e2170c29eed7dc542836c7e770037d3d2fe545a0 Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 20 Sep 2021 17:56:06 +0200 Subject: [PATCH 17/19] remoteproc: migrate uclass to livetree Use dev_ function to read the name and boolean to support a live tree. Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass --- drivers/remoteproc/rproc-uclass.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/drivers/remoteproc/rproc-uclass.c b/drivers/remoteproc/rproc-uclass.c index 64c47c1e72..87e1ec7ad7 100644 --- a/drivers/remoteproc/rproc-uclass.c +++ b/drivers/remoteproc/rproc-uclass.c @@ -9,19 +9,15 @@ #define pr_fmt(fmt) "%s: " fmt, __func__ #include #include -#include #include #include #include -#include #include #include #include #include #include -DECLARE_GLOBAL_DATA_PTR; - /** * for_each_remoteproc_device() - iterate through the list of rproc devices * @fn: check function to call per match, if this function returns fail, @@ -121,21 +117,13 @@ static int rproc_pre_probe(struct udevice *dev) if (!dev_get_plat(dev)) { #if CONFIG_IS_ENABLED(OF_CONTROL) - int node = dev_of_offset(dev); - const void *blob = gd->fdt_blob; bool tmp; - if (!blob) { - debug("'%s' no dt?\n", dev->name); - return -EINVAL; - } debug("'%s': using fdt\n", dev->name); - uc_pdata->name = fdt_getprop(blob, node, - "remoteproc-name", NULL); + uc_pdata->name = dev_read_string(dev, "remoteproc-name"); /* Default is internal memory mapped */ uc_pdata->mem_type = RPROC_INTERNAL_MEMORY_MAPPED; - tmp = fdtdec_get_bool(blob, node, - "remoteproc-internal-memory-mapped"); + tmp = dev_read_bool(dev, "remoteproc-internal-memory-mapped"); if (tmp) uc_pdata->mem_type = RPROC_INTERNAL_MEMORY_MAPPED; #else From 455f2d15bfcf42a002d7d3a38c9c6b2dfe9f518c Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 20 Sep 2021 17:58:33 +0200 Subject: [PATCH 18/19] demo: migrate uclass to livetree Use dev_ function to read the sides and colour to support a live tree. Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass --- drivers/demo/demo-uclass.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/demo/demo-uclass.c b/drivers/demo/demo-uclass.c index 815f8de645..09f9a47d4d 100644 --- a/drivers/demo/demo-uclass.c +++ b/drivers/demo/demo-uclass.c @@ -10,15 +10,11 @@ #include #include #include -#include #include #include -#include #include #include -DECLARE_GLOBAL_DATA_PTR; - UCLASS_DRIVER(demo) = { .name = "demo", .id = UCLASS_DEMO, @@ -67,10 +63,9 @@ int demo_set_light(struct udevice *dev, int light) int demo_parse_dt(struct udevice *dev) { struct dm_demo_pdata *pdata = dev_get_plat(dev); - int dn = dev_of_offset(dev); - pdata->sides = fdtdec_get_int(gd->fdt_blob, dn, "sides", 0); - pdata->colour = fdt_getprop(gd->fdt_blob, dn, "colour", NULL); + pdata->sides = dev_read_s32_default(dev, "sides", 0); + pdata->colour = dev_read_string(dev, "colour"); if (!pdata->sides || !pdata->colour) { debug("%s: Invalid device tree data\n", __func__); return -EINVAL; From c3ef4550a2c439e9726205769d4381ed7e7fbc3d Mon Sep 17 00:00:00 2001 From: Patrick Delaunay Date: Mon, 20 Sep 2021 18:27:20 +0200 Subject: [PATCH 19/19] reboot-mode: migrate uclass to livetree Use dev_ function to support a live tree. Signed-off-by: Patrick Delaunay Reviewed-by: Simon Glass --- drivers/reboot-mode/reboot-mode-uclass.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/reboot-mode/reboot-mode-uclass.c b/drivers/reboot-mode/reboot-mode-uclass.c index bb7a355fbf..2b38aa26b8 100644 --- a/drivers/reboot-mode/reboot-mode-uclass.c +++ b/drivers/reboot-mode/reboot-mode-uclass.c @@ -10,8 +10,6 @@ #include #include -DECLARE_GLOBAL_DATA_PTR; - int dm_reboot_mode_update(struct udevice *dev) { struct reboot_mode_ops *ops = reboot_mode_get_ops(dev); @@ -66,25 +64,20 @@ int dm_reboot_mode_pre_probe(struct udevice *dev) return -EINVAL; #if CONFIG_IS_ENABLED(OF_CONTROL) - const int node = dev_of_offset(dev); const char *mode_prefix = "mode-"; const int mode_prefix_len = strlen(mode_prefix); - int property; + struct ofprop property; const u32 *propvalue; const char *propname; - plat_data->env_variable = fdt_getprop(gd->fdt_blob, - node, - "u-boot,env-variable", - NULL); + plat_data->env_variable = dev_read_string(dev, "u-boot,env-variable"); if (!plat_data->env_variable) plat_data->env_variable = "reboot-mode"; plat_data->count = 0; - fdt_for_each_property_offset(property, gd->fdt_blob, node) { - propvalue = fdt_getprop_by_offset(gd->fdt_blob, - property, &propname, NULL); + dev_for_each_property(property, dev) { + propvalue = dev_read_prop_by_prop(&property, &propname, NULL); if (!propvalue) { dev_err(dev, "Could not get the value for property %s\n", propname); @@ -100,9 +93,8 @@ int dm_reboot_mode_pre_probe(struct udevice *dev) struct reboot_mode_mode *next = plat_data->modes; - fdt_for_each_property_offset(property, gd->fdt_blob, node) { - propvalue = fdt_getprop_by_offset(gd->fdt_blob, - property, &propname, NULL); + dev_for_each_property(property, dev) { + propvalue = dev_read_prop_by_prop(&property, &propname, NULL); if (!propvalue) { dev_err(dev, "Could not get the value for property %s\n", propname);