From 755a68e59924e2437b9fb46c8ae1bfe690db1343 Mon Sep 17 00:00:00 2001 From: Christophe Priouzeau Date: Tue, 27 Oct 2020 12:01:30 +0100 Subject: [PATCH 2/2] 3.9.0-stm32mp-r2 --- core/arch/arm/dts/stm32mp157a-dk1.dts | 4 +- core/arch/arm/dts/stm32mp157a-ed1.dts | 4 +- core/arch/arm/dts/stm32mp157c-dk2.dts | 4 +- core/arch/arm/dts/stm32mp157c-ed1.dts | 4 +- core/arch/arm/dts/stm32mp157d-dk1.dts | 4 +- core/arch/arm/dts/stm32mp157d-ed1.dts | 4 +- core/arch/arm/dts/stm32mp157f-dk2.dts | 4 +- core/arch/arm/dts/stm32mp157f-ed1.dts | 4 +- core/arch/arm/dts/stm32mp15xx-dkx.dtsi | 2 +- core/arch/arm/dts/stm32mp15xx-edx.dtsi | 2 +- core/arch/arm/plat-stm32mp1/conf.mk | 9 +- .../plat-stm32mp1/drivers/stm32mp1_calib.c | 5 + .../plat-stm32mp1/drivers/stm32mp1_etzpc.h | 100 -- .../arm/plat-stm32mp1/drivers/stm32mp1_rcc.c | 17 + core/arch/arm/plat-stm32mp1/main.c | 26 +- .../arm/plat-stm32mp1/nsec-service/rcc_svc.c | 71 +- .../plat-stm32mp1/nsec-service/stm32mp1_smc.h | 4 +- core/arch/arm/plat-stm32mp1/platform_config.h | 8 + core/arch/arm/plat-stm32mp1/remoteproc_pta.c | 528 +++++++++ core/arch/arm/plat-stm32mp1/rproc_pub_key.h | 16 + core/arch/arm/plat-stm32mp1/scmi_server.c | 12 + .../arch/arm/plat-stm32mp1/shared_resources.c | 125 +- core/arch/arm/plat-stm32mp1/stm32_util.h | 12 + core/arch/arm/plat-stm32mp1/sub.mk | 9 + core/drivers/stm32_bsec.c | 2 +- core/drivers/stm32_etzpc.c | 55 +- core/drivers/stm32_gpio.c | 2 +- core/drivers/stm32_tim.c | 21 +- core/include/drivers/stm32_bsec.h | 8 - .../dt-bindings/reset/stm32mp1-resets.h | 2 + core/sub.mk | 7 +- keys/default_rproc.pem | 27 + lib/libutee/include/remoteproc_pta.h | 157 +++ mk/config.mk | 4 + scripts/sign_rproc_fw.py | 400 +++++++ ta/remoteproc/Makefile | 18 + ta/remoteproc/elf_parser.c | 181 +++ ta/remoteproc/include/elf32.h | 243 ++++ ta/remoteproc/include/elf_common.h | 1014 +++++++++++++++++ ta/remoteproc/include/elf_parser.h | 59 + ta/remoteproc/include/ta_remoteproc.h | 65 ++ .../include/user_ta_header_defines.h | 29 + ta/remoteproc/remoteproc_core.c | 781 +++++++++++++ ta/remoteproc/sub.mk | 3 + ta/remoteproc/user_ta.mk | 1 + 45 files changed, 3845 insertions(+), 212 deletions(-) delete mode 100644 core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h create mode 100644 core/arch/arm/plat-stm32mp1/remoteproc_pta.c create mode 100644 core/arch/arm/plat-stm32mp1/rproc_pub_key.h create mode 100644 keys/default_rproc.pem create mode 100644 lib/libutee/include/remoteproc_pta.h create mode 100755 scripts/sign_rproc_fw.py create mode 100644 ta/remoteproc/Makefile create mode 100644 ta/remoteproc/elf_parser.c create mode 100644 ta/remoteproc/include/elf32.h create mode 100644 ta/remoteproc/include/elf_common.h create mode 100644 ta/remoteproc/include/elf_parser.h create mode 100644 ta/remoteproc/include/ta_remoteproc.h create mode 100644 ta/remoteproc/include/user_ta_header_defines.h create mode 100644 ta/remoteproc/remoteproc_core.c create mode 100644 ta/remoteproc/sub.mk create mode 100644 ta/remoteproc/user_ta.mk diff --git a/core/arch/arm/dts/stm32mp157a-dk1.dts b/core/arch/arm/dts/stm32mp157a-dk1.dts index 4d506bce5..5d5c0a5f7 100644 --- a/core/arch/arm/dts/stm32mp157a-dk1.dts +++ b/core/arch/arm/dts/stm32mp157a-dk1.dts @@ -36,8 +36,8 @@ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) - DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) - DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) diff --git a/core/arch/arm/dts/stm32mp157a-ed1.dts b/core/arch/arm/dts/stm32mp157a-ed1.dts index 4f84ec623..9da3e307e 100644 --- a/core/arch/arm/dts/stm32mp157a-ed1.dts +++ b/core/arch/arm/dts/stm32mp157a-ed1.dts @@ -37,8 +37,8 @@ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) - DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) - DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) diff --git a/core/arch/arm/dts/stm32mp157c-dk2.dts b/core/arch/arm/dts/stm32mp157c-dk2.dts index 436a15970..ff5c4509f 100644 --- a/core/arch/arm/dts/stm32mp157c-dk2.dts +++ b/core/arch/arm/dts/stm32mp157c-dk2.dts @@ -42,8 +42,8 @@ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) - DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) - DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) diff --git a/core/arch/arm/dts/stm32mp157c-ed1.dts b/core/arch/arm/dts/stm32mp157c-ed1.dts index 5aadb1ff0..a1e72f816 100644 --- a/core/arch/arm/dts/stm32mp157c-ed1.dts +++ b/core/arch/arm/dts/stm32mp157c-ed1.dts @@ -42,8 +42,8 @@ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) - DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) - DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) diff --git a/core/arch/arm/dts/stm32mp157d-dk1.dts b/core/arch/arm/dts/stm32mp157d-dk1.dts index d320f993e..078bc717b 100644 --- a/core/arch/arm/dts/stm32mp157d-dk1.dts +++ b/core/arch/arm/dts/stm32mp157d-dk1.dts @@ -40,8 +40,8 @@ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) - DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) - DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) diff --git a/core/arch/arm/dts/stm32mp157d-ed1.dts b/core/arch/arm/dts/stm32mp157d-ed1.dts index 76f0614d6..961e43d6a 100644 --- a/core/arch/arm/dts/stm32mp157d-ed1.dts +++ b/core/arch/arm/dts/stm32mp157d-ed1.dts @@ -37,8 +37,8 @@ DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) - DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) - DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) diff --git a/core/arch/arm/dts/stm32mp157f-dk2.dts b/core/arch/arm/dts/stm32mp157f-dk2.dts index 9c79bfb43..a8ed842e4 100644 --- a/core/arch/arm/dts/stm32mp157f-dk2.dts +++ b/core/arch/arm/dts/stm32mp157f-dk2.dts @@ -46,8 +46,8 @@ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) - DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) - DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) diff --git a/core/arch/arm/dts/stm32mp157f-ed1.dts b/core/arch/arm/dts/stm32mp157f-ed1.dts index a659cf84d..729dae8af 100644 --- a/core/arch/arm/dts/stm32mp157f-ed1.dts +++ b/core/arch/arm/dts/stm32mp157f-ed1.dts @@ -42,8 +42,8 @@ DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK) - DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_S_RW, DECPROT_LOCK) - DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_S_RW, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) + DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK) DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK) diff --git a/core/arch/arm/dts/stm32mp15xx-dkx.dtsi b/core/arch/arm/dts/stm32mp15xx-dkx.dtsi index 7254f9a54..37a5525f3 100644 --- a/core/arch/arm/dts/stm32mp15xx-dkx.dtsi +++ b/core/arch/arm/dts/stm32mp15xx-dkx.dtsi @@ -209,7 +209,7 @@ regulator-max-microvolt = <3300000>; regulator-always-on; standby-ddr-sr { - regulator-on-in-suspend; + regulator-off-in-suspend; }; standby-ddr-off { regulator-off-in-suspend; diff --git a/core/arch/arm/dts/stm32mp15xx-edx.dtsi b/core/arch/arm/dts/stm32mp15xx-edx.dtsi index b7683a69a..4946f0cd0 100644 --- a/core/arch/arm/dts/stm32mp15xx-edx.dtsi +++ b/core/arch/arm/dts/stm32mp15xx-edx.dtsi @@ -214,7 +214,7 @@ regulator-max-microvolt = <3300000>; regulator-always-on; standby-ddr-sr { - regulator-on-in-suspend; + regulator-off-in-suspend; }; standby-ddr-off { regulator-off-in-suspend; diff --git a/core/arch/arm/plat-stm32mp1/conf.mk b/core/arch/arm/plat-stm32mp1/conf.mk index 8a449b521..6beef4635 100644 --- a/core/arch/arm/plat-stm32mp1/conf.mk +++ b/core/arch/arm/plat-stm32mp1/conf.mk @@ -89,9 +89,15 @@ CFG_TEE_CORE_NB_CORE ?= 2 CFG_WITH_PAGER ?= y CFG_WITH_LPAE ?= y CFG_WITH_STACK_CANARIES ?= y -CFG_MMAP_REGIONS ?= 25 +CFG_MMAP_REGIONS ?= 30 CFG_CORE_HEAP_SIZE ?= 49152 +# Disable early TA compression to limit HEAP size +CFG_EARLY_TA_COMPRESS ?= n + +# Embed public part of this key in OP-TEE OS +CFG_RPROC_SIGN_KEY ?= keys/default_rproc.pem + ifeq ($(CFG_EMBED_DTB_SOURCE_FILE),) # Some drivers mandate DT support $(call force,CFG_STM32_CLKCALIB,n) @@ -101,6 +107,7 @@ $(call force,CFG_STM32_TIM,n) $(call force,CFG_STPMIC1,n) endif +CFG_RPROC_PTA ?= n CFG_STM32_BSEC ?= y CFG_STM32_CLKCALIB ?= y CFG_STM32_CRYP ?= y diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c index b1b9f4366..15ea71519 100644 --- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c +++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_calib.c @@ -336,6 +336,11 @@ static void arm_timer_with_period(uint32_t period_sec) { timer_val = period_sec * read_cntfrq(); + if (timer_val > INT32_MAX) + timer_val = INT32_MAX; + + DMSG("Calibration timeout set to %"PRIu32, timer_val / read_cntfrq()); + arm_timer(); } diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h deleted file mode 100644 index 338a39283..000000000 --- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h +++ /dev/null @@ -1,100 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ -/* - * Copyright (C) 2018-2019, STMicroelectronics - */ - -#ifndef __STM32MP1_ETZPC_H -#define __STM32MP1_ETZPC_H - -/* Define DECPROT IDs for stm32mp1 familly */ -#define STM32MP1_ETZPC_STGENC_ID 0 -#define STM32MP1_ETZPC_BKPSRAM_ID 1 -#define STM32MP1_ETZPC_IWDG1_ID 2 -#define STM32MP1_ETZPC_USART1_ID 3 -#define STM32MP1_ETZPC_SPI6_ID 4 -#define STM32MP1_ETZPC_I2C4_ID 5 -#define STM32MP1_ETZPC_GPIOZ_ID 6 -#define STM32MP1_ETZPC_RNG1_ID 7 -#define STM32MP1_ETZPC_HASH1_ID 8 -#define STM32MP1_ETZPC_CRYP1_ID 9 -#define STM32MP1_ETZPC_DDRCTRL_ID 10 -#define STM32MP1_ETZPC_DDRPHYC_ID 11 -#define STM32MP1_ETZPC_I2C6_ID 12 -/* 13-15 Reserved */ -#define STM32MP1_ETZPC_TIM2_ID 16 -#define STM32MP1_ETZPC_TIM3_ID 17 -#define STM32MP1_ETZPC_TIM4_ID 18 -#define STM32MP1_ETZPC_TIM5_ID 19 -#define STM32MP1_ETZPC_TIM6_ID 20 -#define STM32MP1_ETZPC_TIM7_ID 21 -#define STM32MP1_ETZPC_TIM12_ID 22 -#define STM32MP1_ETZPC_TIM13_ID 23 -#define STM32MP1_ETZPC_TIM14_ID 24 -#define STM32MP1_ETZPC_LPTIM1_ID 25 -#define STM32MP1_ETZPC_WWDG1_ID 26 -#define STM32MP1_ETZPC_SPI2_ID 27 -#define STM32MP1_ETZPC_SPI3_ID 28 -#define STM32MP1_ETZPC_SPDIFRX_ID 29 -#define STM32MP1_ETZPC_USART2_ID 30 -#define STM32MP1_ETZPC_USART3_ID 31 -#define STM32MP1_ETZPC_UART4_ID 32 -#define STM32MP1_ETZPC_UART5_ID 33 -#define STM32MP1_ETZPC_I2C1_ID 34 -#define STM32MP1_ETZPC_I2C2_ID 35 -#define STM32MP1_ETZPC_I2C3_ID 36 -#define STM32MP1_ETZPC_I2C5_ID 37 -#define STM32MP1_ETZPC_CEC_ID 38 -#define STM32MP1_ETZPC_DAC_ID 39 -#define STM32MP1_ETZPC_UART7_ID 40 -#define STM32MP1_ETZPC_UART8_ID 41 -/* 42-43 Reserved */ -#define STM32MP1_ETZPC_MDIOS_ID 44 -/* 45-47 Reserved */ -#define STM32MP1_ETZPC_TIM1_ID 48 -#define STM32MP1_ETZPC_TIM8_ID 49 -/* 50 Reserved */ -#define STM32MP1_ETZPC_USART6_ID 51 -#define STM32MP1_ETZPC_SPI1_ID 52 -#define STM32MP1_ETZPC_SPI4_ID 53 -#define STM32MP1_ETZPC_TIM15_ID 54 -#define STM32MP1_ETZPC_TIM16_ID 55 -#define STM32MP1_ETZPC_TIM17_ID 56 -#define STM32MP1_ETZPC_SPI5_ID 57 -#define STM32MP1_ETZPC_SAI1_ID 58 -#define STM32MP1_ETZPC_SAI2_ID 59 -#define STM32MP1_ETZPC_SAI3_ID 60 -#define STM32MP1_ETZPC_DFSDM_ID 61 -#define STM32MP1_ETZPC_TT_FDCAN_ID 62 -/* 63 Reserved */ -#define STM32MP1_ETZPC_LPTIM2_ID 64 -#define STM32MP1_ETZPC_LPTIM3_ID 65 -#define STM32MP1_ETZPC_LPTIM4_ID 66 -#define STM32MP1_ETZPC_LPTIM5_ID 67 -#define STM32MP1_ETZPC_SAI4_ID 68 -#define STM32MP1_ETZPC_VREFBUF_ID 69 -#define STM32MP1_ETZPC_DCMI_ID 70 -#define STM32MP1_ETZPC_CRC2_ID 71 -#define STM32MP1_ETZPC_ADC_ID 72 -#define STM32MP1_ETZPC_HASH2_ID 73 -#define STM32MP1_ETZPC_RNG2_ID 74 -#define STM32MP1_ETZPC_CRYP2_ID 75 -/* 76-79 Reserved */ -#define STM32MP1_ETZPC_SRAM1_ID 80 -#define STM32MP1_ETZPC_SRAM2_ID 81 -#define STM32MP1_ETZPC_SRAM3_ID 82 -#define STM32MP1_ETZPC_SRAM4_ID 83 -#define STM32MP1_ETZPC_RETRAM_ID 84 -#define STM32MP1_ETZPC_OTG_ID 85 -#define STM32MP1_ETZPC_SDMMC3_ID 86 -#define STM32MP1_ETZPC_DLYBSD3_ID 87 -#define STM32MP1_ETZPC_DMA1_ID 88 -#define STM32MP1_ETZPC_DMA2_ID 89 -#define STM32MP1_ETZPC_DMAMUX_ID 90 -#define STM32MP1_ETZPC_FMC_ID 91 -#define STM32MP1_ETZPC_QSPI_ID 92 -#define STM32MP1_ETZPC_DLYBQ_ID 93 -#define STM32MP1_ETZPC_ETH_ID 94 -/* 95 Reserved */ -#define STM32MP1_ETZPC_MAX_ID 96 - -#endif /*__STM32MP1_ETZPC_H*/ diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.c index 3c3dd5e49..c07be0c53 100644 --- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.c +++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_rcc.c @@ -76,3 +76,20 @@ TEE_Result stm32_reset_deassert(unsigned int id, unsigned int to_us) return TEE_SUCCESS; } + +TEE_Result stm32_reset_assert_deassert_mcu(bool assert_not_deassert) +{ + vaddr_t rcc_base = stm32_rcc_base(); + + /* + * The RCC_MP_GCR is a read/write register. + * Assert the MCU HOLD_BOOT means clear the BOOT_MCU bit + * Deassert the MCU HOLD_BOOT means set the BOOT_MCU the bit + */ + if (assert_not_deassert) + io_clrbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU); + else + io_setbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU); + + return TEE_SUCCESS; +} diff --git a/core/arch/arm/plat-stm32mp1/main.c b/core/arch/arm/plat-stm32mp1/main.c index 40e426331..07af9fc1a 100644 --- a/core/arch/arm/plat-stm32mp1/main.c +++ b/core/arch/arm/plat-stm32mp1/main.c @@ -11,11 +11,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include @@ -102,6 +102,14 @@ register_dynamic_shm(TZDRAM_END, DRAM_END - TZDRAM_END); /* Map non-secure DDR bottom for the low power sequence */ register_phys_mem(MEM_AREA_RAM_NSEC, DDR_BASE, SMALL_PAGE_SIZE); +#ifdef CFG_RPROC_PTA +/* Map MCU RETRAM as read write for Cortex-M4 firmware management */ +register_phys_mem(MEM_AREA_IO_SEC, RETRAM_BASE, RETRAM_SIZE); + +/* Map MCU SRAM as read write for Cortex-M4 firmware management */ +register_phys_mem(MEM_AREA_IO_SEC, MCUSRAM_BASE, MCUSRAM_SIZE); +#endif + /* Map TEE physical RAM as read-only for content storage when suspending */ register_phys_mem(MEM_AREA_ROM_SEC, TEE_RAM_START, TEE_RAM_PH_SIZE); @@ -549,6 +557,22 @@ bool stm32mp_supports_cpu_opp(uint32_t opp_id) } } +enum etzpc_decprot_attributes stm32mp_etzpc_binding2decprot(uint32_t mode) +{ + switch (mode) { + case DECPROT_S_RW: + return ETZPC_DECPROT_S_RW; + case DECPROT_NS_R_S_W: + return ETZPC_DECPROT_NS_R_S_W; + case DECPROT_MCU_ISOLATION: + return ETZPC_DECPROT_MCU_ISOLATION; + case DECPROT_NS_RW: + return ETZPC_DECPROT_NS_RW; + default: + panic(); + } +} + unsigned int stm32mp_iwdg_irq2instance(size_t irq) { int id = irq - STM32MP1_IRQ_IWDG1; diff --git a/core/arch/arm/plat-stm32mp1/nsec-service/rcc_svc.c b/core/arch/arm/plat-stm32mp1/nsec-service/rcc_svc.c index 362e6d651..d2824c609 100644 --- a/core/arch/arm/plat-stm32mp1/nsec-service/rcc_svc.c +++ b/core/arch/arm/plat-stm32mp1/nsec-service/rcc_svc.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -16,29 +15,10 @@ #include "rcc_svc.h" #include "stm32mp1_smc.h" -#undef FULL_RCC_ACCESS - static bool offset_is_clear_register(uint32_t __maybe_unused offset) { -#ifdef FULL_RCC_ACCESS - switch (offset) { - case RCC_OCENCLRR: - case RCC_MP_SREQCLRR: - case RCC_APB5RSTCLRR: - case RCC_AHB5RSTCLRR: - case RCC_MP_APB5ENCLRR: - case RCC_MP_AHB5ENCLRR: - case RCC_MP_APB5LPENCLRR: - case RCC_MP_AHB5LPENCLRR: - case RCC_MP_IWDGFZCLRR: - return true; - default: - return false; - } -#else /* All allowed registers are non set/clear registers */ return false; -#endif } static void access_allowed_mask(uint32_t request, uint32_t offset, @@ -85,8 +65,8 @@ static void access_allowed_mask(uint32_t request, uint32_t offset, } } -static void raw_allowed_access_request(uint32_t request, - uint32_t offset, uint32_t value) +static uint32_t raw_allowed_access_request(uint32_t request, + uint32_t offset, uint32_t value) { uint32_t allowed_mask = 0; @@ -95,50 +75,13 @@ static void raw_allowed_access_request(uint32_t request, case RCC_MP_CIFR: allowed_mask = RCC_MP_CIFR_WKUPF; break; - case RCC_MP_GCR: - allowed_mask = RCC_MP_GCR_BOOT_MCU; - break; - -#ifdef FULL_RCC_ACCESS - case RCC_OCENSETR: - case RCC_OCENCLRR: - case RCC_HSICFGR: - case RCC_CSICFGR: - case RCC_MP_BOOTCR: /* Allowed MPU/MCU reboot cfg */ - case RCC_MP_GCR: /* Allowed MPU/MCU reboot cfg */ - case RCC_MP_GRSTCSETR: /* Allowed MCU and system reset */ - case RCC_BR_RSTSCLRR: /* Allowed system reset status */ - case RCC_MC_RSTSCLRR: /* Allowed system reset status */ - case RCC_MP_RSTSCLRR: /* Allowed system reset status */ - case RCC_BDCR: - case RCC_RDLSICR: - case RCC_APB5RSTSETR: - case RCC_APB5RSTCLRR: - case RCC_MP_APB5ENSETR: - case RCC_MP_APB5ENCLRR: - case RCC_MP_APB5LPENSETR: - case RCC_MP_APB5LPENCLRR: - case RCC_AHB5RSTSETR: - case RCC_AHB5RSTCLRR: - case RCC_MP_AHB5ENSETR: - case RCC_MP_AHB5ENCLRR: - case RCC_MP_AHB5LPENSETR: - case RCC_MP_AHB5LPENCLRR: - case RCC_RTCDIVR: - case RCC_I2C46CKSELR: - case RCC_SPI6CKSELR: - case RCC_UART1CKSELR: - case RCC_RNG1CKSELR: - case RCC_MP_IWDGFZSETR: - case RCC_MP_IWDGFZCLRR: - allowed_mask = UINT32_MAX; - break; -#endif default: - panic(); + return STM32_SIP_SVC_INVALID_PARAMS; } access_allowed_mask(request, offset, value, allowed_mask); + + return STM32_SIP_SVC_OK; } uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3) @@ -163,9 +106,7 @@ uint32_t rcc_scv_handler(uint32_t x1, uint32_t x2, uint32_t x3) request == STM32_SIP_SVC_REG_SET ? "set" : "clear", value, offset); - raw_allowed_access_request(request, offset, value); - - return STM32_SIP_SVC_OK; + return raw_allowed_access_request(request, offset, value); } uint32_t rcc_opp_scv_handler(uint32_t x1, uint32_t x2, uint32_t *res) diff --git a/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h b/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h index 86deb592b..a1f0e5859 100644 --- a/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h +++ b/core/arch/arm/plat-stm32mp1/nsec-service/stm32mp1_smc.h @@ -133,7 +133,9 @@ #define STM32_SIP_SVC_BSEC_PROG_OTP 0x2 #define STM32_SIP_SVC_BSEC_WRITE_SHADOW 0x3 #define STM32_SIP_SVC_BSEC_READ_OTP 0x4 -#define STM32_SIP_SVC_BSEC_WRLOCK_OTP 0x5 +/* reserved for STM32_SIP_SVC_SMC_READ_ALL 0x5 */ +/* reserved for STM32_SIP_SVC_SMC_WRITE_ALL 0x6 */ +#define STM32_SIP_SVC_BSEC_WRLOCK_OTP 0x7 /* * SIP functions STM32_SIP_FUNC_SR_MODE diff --git a/core/arch/arm/plat-stm32mp1/platform_config.h b/core/arch/arm/plat-stm32mp1/platform_config.h index 2b4bd95b5..0ea5efc32 100644 --- a/core/arch/arm/plat-stm32mp1/platform_config.h +++ b/core/arch/arm/plat-stm32mp1/platform_config.h @@ -39,6 +39,8 @@ #endif /*CFG_WITH_PAGER*/ /* SoC interface registers base address */ +#define MCUSRAM_BASE 0x30000000ul +#define RETRAM_BASE 0x38000000ul #define BKPSRAM_BASE 0x54000000 #define BSEC_BASE 0x5c005000 #define ETZPC_BASE 0x5c007000 @@ -238,6 +240,12 @@ #define SYSRAM_SEC_SIZE SYSRAM_SIZE #endif +/* RETRAM layout */ +#define RETRAM_SIZE 0x10000 + +/* MCUSRAM layout */ +#define MCUSRAM_SIZE 0x60000 + /* SoC part numbers and revisions */ #define STM32MP1_CHIP_ID 0x500 diff --git a/core/arch/arm/plat-stm32mp1/remoteproc_pta.c b/core/arch/arm/plat-stm32mp1/remoteproc_pta.c new file mode 100644 index 000000000..f8458336f --- /dev/null +++ b/core/arch/arm/plat-stm32mp1/remoteproc_pta.c @@ -0,0 +1,528 @@ + // SPDX-License-Identifier: BSD-2-Clause + /* + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PTA_NAME "remoteproc.pta" + +#define STM32_M4_FW_ID 0 + +/* Firmware states */ +enum rproc_load_state { + REMOTEPROC_OFF = 0, + REMOTEPROC_ON, +}; + +/* + * struct rproc_ta_etzpc_rams - memory protection strategy table + * @pa - Memory physical base address from current CPU space + * @size - Memory region byte size + * @etzpc_id - associated ETZPC identifier. + * @attr - memory access permission according to @etzpc_decprot_attributes + */ +struct rproc_ta_etzpc_rams { + paddr_t pa; + size_t size; + uint32_t etzpc_id; + enum etzpc_decprot_attributes attr; +}; + +/* + * struct rproc_ta_memory_region - Represent a remote processor memory mapping + * @pa - Memory physical base address from current CPU space + * @da - Memory physical base address from remote processor space + * @size - Memory region byte size + */ +struct rproc_ta_memory_region { + paddr_t pa; + paddr_t da; + size_t size; +}; + +static const struct rproc_ta_etzpc_rams rproc_ta_mp1_m4_rams[] = { + /* MCU SRAM 1*/ + { + .pa = MCUSRAM_BASE, + .size = 0x20000, + .etzpc_id = STM32MP1_ETZPC_SRAM1_ID, + .attr = ETZPC_DECPROT_MCU_ISOLATION, + }, + /* MCU SRAM 2*/ + { + .pa = MCUSRAM_BASE + 0x20000, + .size = 0x20000, + .etzpc_id = STM32MP1_ETZPC_SRAM2_ID, + .attr = ETZPC_DECPROT_MCU_ISOLATION, + }, + + /* MCU SRAM 3*/ + { + /* Used as shared memory between the NS and the coprocessor */ + .pa = MCUSRAM_BASE + 0x40000, + .size = 0x10000, + .etzpc_id = STM32MP1_ETZPC_SRAM3_ID, + .attr = ETZPC_DECPROT_NS_RW, + }, + /* MCU SRAM 4*/ + /* Not used reserved by NS for MDMA */ + { + .pa = MCUSRAM_BASE + 0x50000, + .size = 0x10000, + .etzpc_id = STM32MP1_ETZPC_SRAM4_ID, + .attr = ETZPC_DECPROT_NS_RW, + }, + + /* MCU RETRAM */ + { + .pa = RETRAM_BASE, + .size = RETRAM_SIZE, + .etzpc_id = STM32MP1_ETZPC_RETRAM_ID, + .attr = ETZPC_DECPROT_MCU_ISOLATION, + }, +}; + +static const struct rproc_ta_memory_region rproc_ta_mp1_m4_mems[] = { + /* MCU SRAM */ + { .pa = MCUSRAM_BASE, .da = 0x10000000, .size = MCUSRAM_SIZE }, + /* Alias of the MCU SRAM */ + { .pa = MCUSRAM_BASE, .da = 0x30000000, .size = MCUSRAM_SIZE }, + /* RETRAM */ + { .pa = RETRAM_BASE, .da = 0x00000000, .size = RETRAM_SIZE }, +}; + +static enum rproc_load_state rproc_ta_state; + +static TEE_Result rproc_pta_capabilities(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + /* Support only ELF format */ + params[1].value.a = PTA_REMOTEPROC_ELF_FMT; + + /* + * Due to stm32mp1 pager, secure memory is too expensive. Support hash + * protected image only, so that firmware image can be loaded from + * non-secure memory. + */ + params[2].value.a = PTA_REMOTEPROC_FW_WITH_HASH_TABLE; + + return TEE_SUCCESS; +} + +static TEE_Result da_to_pa(paddr_t da, size_t size, paddr_t *pa) +{ + const struct rproc_ta_memory_region *mems = rproc_ta_mp1_m4_mems; + size_t i = 0; + + DMSG("da addr: %#"PRIxPA" size: %zu", da, size); + + for (i = 0; i < ARRAY_SIZE(rproc_ta_mp1_m4_mems); i++) { + if (da >= mems[i].da && + (da + size) <= (mems[i].da + mems[i].size)) { + *pa = da - mems[i].da + mems[i].pa; + DMSG("da %#"PRIxPA" to pa %#"PRIxPA, da, *pa); + + return TEE_SUCCESS; + } + } + + return TEE_ERROR_ACCESS_DENIED; +} + +static TEE_Result rproc_pta_load_segment(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT); + TEE_Result res = TEE_ERROR_GENERIC; + paddr_t pa = 0; + uint8_t *dst = 0; + uint8_t *src = params[1].memref.buffer; + size_t size = params[1].memref.size; + uint8_t *hash = params[3].memref.buffer; + paddr_t da = (paddr_t)reg_pair_to_64(params[2].value.b, + params[2].value.a); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + if (!hash || params[3].memref.size != TEE_SHA256_HASH_SIZE) + return TEE_ERROR_BAD_PARAMETERS; + + /* Only STM32_M4_FW_ID supported */ + if (params[0].value.a != STM32_M4_FW_ID) { + EMSG("Unsupported firmware ID %#"PRIx32, params[0].value.a); + return TEE_ERROR_NOT_SUPPORTED; + } + + if (rproc_ta_state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + /* Get the physical address in A7 mapping */ + res = da_to_pa(da, size, &pa); + if (res) + return res; + + /* Get the associated va */ + dst = (void *)core_mmu_get_va(pa, MEM_AREA_IO_SEC); + + /* Copy the segment to the remote processor memory*/ + memcpy(dst, src, size); + + /* Verify that loaded segment is valid */ + res = hash_sha256_check(hash, dst, size); + if (res) + memset(dst, 0, size); + + return res; +} + +static TEE_Result rproc_pta_set_memory(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT); + TEE_Result res = TEE_ERROR_GENERIC; + paddr_t pa = 0; + vaddr_t dst = 0; + paddr_t da = params[1].value.a; + size_t size = params[2].value.a; + char value = (char)params[3].value.a; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + /* Only STM32_M4_FW_ID supported */ + if (params[0].value.a != STM32_M4_FW_ID) { + EMSG("Unsupported firmware ID %#"PRIx32, params[0].value.a); + return TEE_ERROR_NOT_SUPPORTED; + } + + if (rproc_ta_state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + /* Get the physical address in CPU mapping */ + res = da_to_pa(da, size, &pa); + if (res) + return res; + + dst = core_mmu_get_va(pa, MEM_AREA_IO_SEC); + + memset((void *)dst, value, size); + + return TEE_SUCCESS; +} + +static TEE_Result rproc_pta_da_to_pa(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT); + TEE_Result res = TEE_ERROR_GENERIC; + paddr_t da = params[1].value.a; + size_t size = params[2].value.a; + paddr_t pa = 0; + + DMSG("Conversion for address %#"PRIxPA" size %zu", da, size); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + /* Only STM32_M4_FW_ID supported */ + if (params[0].value.a != STM32_M4_FW_ID) { + EMSG("Unsupported firmware ID %#"PRIx32, params[0].value.a); + return TEE_ERROR_NOT_SUPPORTED; + } + + /* Target address is expected 32bit, ensure 32bit MSB are zero */ + if (params[1].value.b || params[2].value.b) + return TEE_ERROR_BAD_PARAMETERS; + + res = da_to_pa(da, size, &pa); + if (res) + return res; + + reg_pair_from_64((uint64_t)pa, ¶ms[3].value.b, ¶ms[3].value.a); + + return TEE_SUCCESS; +} + +static void rproc_pta_mem_protect(bool secure_access) +{ + unsigned int i = 0; + const struct rproc_ta_etzpc_rams *ram = NULL; + + /* + * MCU RAM banks access permissions for MCU memories depending on + * rproc_ta_mp1_m4_rams[]. + * If memory bank is declared as MCU isolated: + * if secure_access then set to secure world read/write permission + * else set to MCU isolated + * else apply memory permission as defined in rproc_ta_mp1_m4_rams[]. + */ + for (i = 0; i < ARRAY_SIZE(rproc_ta_mp1_m4_rams); i++) { + enum etzpc_decprot_attributes attr = ETZPC_DECPROT_MAX; + + ram = &rproc_ta_mp1_m4_rams[i]; + attr = ram->attr; + + if (secure_access && attr == ETZPC_DECPROT_MCU_ISOLATION) + attr = ETZPC_DECPROT_S_RW; + + etzpc_configure_decprot(ram->etzpc_id, attr); + } +} + +static TEE_Result rproc_pta_start(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + vaddr_t rcc_base = stm32_rcc_base(); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + /* Only STM32_M4_FW_ID supported */ + if (params[0].value.a != STM32_M4_FW_ID) { + EMSG("Unsupported firmware ID %#"PRIx32, params[0].value.a); + return TEE_ERROR_NOT_SUPPORTED; + } + + if (rproc_ta_state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + stm32_clock_enable(CK_MCU); + + /* Configure the Cortex-M4 RAMs as expected to run the firmware */ + rproc_pta_mem_protect(false); + + /* + * The firmware is started by deasserting the hold boot and + * asserting back to avoid auto restart on a crash. + * No need to release the MCU reset as it is automatically released by + * the hardware. + */ + io_setbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU); + io_clrbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU); + + rproc_ta_state = REMOTEPROC_ON; + + return TEE_SUCCESS; +} + +static TEE_Result rproc_pta_stop(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + const struct rproc_ta_etzpc_rams *ram = NULL; + vaddr_t rcc_base = stm32_rcc_base(); + unsigned int i = 0; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + /* Only STM32_M4_FW_ID supported */ + if (params[0].value.a != STM32_M4_FW_ID) { + EMSG("Unsupported firmware ID %#"PRIx32, params[0].value.a); + return TEE_ERROR_NOT_SUPPORTED; + } + + if (rproc_ta_state != REMOTEPROC_ON) + return TEE_ERROR_BAD_STATE; + + /* The firmware is stopped (reset with holdboot is active) */ + io_clrbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU); + + stm32_reset_set(MCU_R); + + stm32_clock_disable(CK_MCU); + + /* + * Cortex-M4 memories are cleaned and access rights restored for the + * secure context. + */ + rproc_pta_mem_protect(true); + for (i = 0; i < ARRAY_SIZE(rproc_ta_mp1_m4_rams); i++) { + ram = &rproc_ta_mp1_m4_rams[i]; + if (ram->attr == ETZPC_DECPROT_MCU_ISOLATION) { + memset((void *)core_mmu_get_va(ram->pa, + MEM_AREA_IO_SEC), + 0, ram->size); + } + } + rproc_ta_state = REMOTEPROC_OFF; + + return TEE_SUCCESS; +} + +static TEE_Result rproc_pta_verify_rsa_signature(TEE_Param *hash, + TEE_Param *sig, uint32_t algo) +{ + struct rsa_public_key key = { }; + TEE_Result res = TEE_ERROR_GENERIC; + uint32_t e = TEE_U32_TO_BIG_ENDIAN(rproc_pub_key_exponent); + size_t hash_size = (size_t)hash->memref.size; + size_t sig_size = (size_t)sig->memref.size; + + res = crypto_acipher_alloc_rsa_public_key(&key, sig_size); + if (res) + return TEE_ERROR_SECURITY; + + res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e); + if (res) + goto out; + + res = crypto_bignum_bin2bn(rproc_pub_key_modulus, + rproc_pub_key_modulus_size, key.n); + if (res) + goto out; + + res = crypto_acipher_rsassa_verify(algo, &key, hash_size, + hash->memref.buffer, hash_size, + sig->memref.buffer, sig_size); + +out: + crypto_acipher_free_rsa_public_key(&key); + + return res; +} + +static TEE_Result rproc_pta_verify_digest(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + struct rproc_pta_key_info *keyinfo = NULL; + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT); + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + /* Only STM32_M4_FW_ID supported */ + if (params[0].value.a != STM32_M4_FW_ID) { + EMSG("Unsupported firmware ID %#"PRIx32, params[0].value.a); + return TEE_ERROR_NOT_SUPPORTED; + } + + if (rproc_ta_state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + keyinfo = params[1].memref.buffer; + + if (!keyinfo || + RPROC_PTA_GET_KEYINFO_SIZE(keyinfo) != params[1].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + if (keyinfo->algo != TEE_ALG_RSASSA_PKCS1_V1_5_SHA256) + return TEE_ERROR_NOT_SUPPORTED; + + return rproc_pta_verify_rsa_signature(¶ms[2], ¶ms[3], + keyinfo->algo); +} + +static TEE_Result rproc_pta_invoke_command(void *pSessionContext __unused, + uint32_t cmd_id, + uint32_t param_types, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd_id) { + case PTA_REMOTEPROC_HW_CAPABILITIES: + return rproc_pta_capabilities(param_types, params); + case PTA_REMOTEPROC_LOAD_SEGMENT_SHA256: + return rproc_pta_load_segment(param_types, params); + case PTA_REMOTEPROC_SET_MEMORY: + return rproc_pta_set_memory(param_types, params); + case PTA_REMOTEPROC_FIRMWARE_START: + return rproc_pta_start(param_types, params); + case PTA_REMOTEPROC_FIRMWARE_STOP: + return rproc_pta_stop(param_types, params); + case PTA_REMOTEPROC_FIRMWARE_DA_TO_PA: + return rproc_pta_da_to_pa(param_types, params); + case PTA_REMOTEPROC_VERIFY_DIGEST: + return rproc_pta_verify_digest(param_types, params); + default: + break; + } + + return TEE_ERROR_NOT_IMPLEMENTED; +} + +/* + * Trusted Application entry points + */ +static TEE_Result + rproc_pta_open_session(uint32_t param_types __unused, + TEE_Param params[TEE_NUM_PARAMS] __unused, + void **sess_ctx __unused) +{ + struct tee_ta_session *s = tee_ta_get_calling_session(); + + /* Check that we're called from a user TA */ + if (!s) + return TEE_ERROR_ACCESS_DENIED; + + if (!is_user_ta_ctx(s->ctx)) + return TEE_ERROR_ACCESS_DENIED; + + return TEE_SUCCESS; +} + +static TEE_Result rproc_pta_init(void) +{ + TEE_Result ret = TEE_ERROR_GENERIC; + vaddr_t rcc_base = stm32_rcc_base(); + + /* Configure the Cortex-M4 rams access right for secure context only */ + rproc_pta_mem_protect(true); + + /* Initialise the context */ + rproc_ta_state = REMOTEPROC_OFF; + + /* Ensure that the MCU is HOLD */ + io_clrbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU); + stm32_reset_set(MCU_R); + + return TEE_SUCCESS; +} +service_init_late(rproc_pta_init); + +pseudo_ta_register(.uuid = PTA_REMOTEPROC_UUID, .name = PTA_NAME, + .flags = PTA_DEFAULT_FLAGS, + .invoke_command_entry_point = rproc_pta_invoke_command, + .open_session_entry_point = rproc_pta_open_session); diff --git a/core/arch/arm/plat-stm32mp1/rproc_pub_key.h b/core/arch/arm/plat-stm32mp1/rproc_pub_key.h new file mode 100644 index 000000000..9b1db4271 --- /dev/null +++ b/core/arch/arm/plat-stm32mp1/rproc_pub_key.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + */ + +#ifndef RPROC_PUB_KEY_H +#define RPROC_PUB_KEY_H + +#include + +extern const uint32_t rproc_pub_key_exponent; +extern const uint8_t rproc_pub_key_modulus[]; +extern const size_t rproc_pub_key_modulus_size; + +#endif /*RPROC_PUB_KEY_H*/ + diff --git a/core/arch/arm/plat-stm32mp1/scmi_server.c b/core/arch/arm/plat-stm32mp1/scmi_server.c index 5116b897a..2a0bdde4a 100644 --- a/core/arch/arm/plat-stm32mp1/scmi_server.c +++ b/core/arch/arm/plat-stm32mp1/scmi_server.c @@ -135,6 +135,7 @@ struct stm32_scmi_rd stm32_scmi0_reset_domain[] = { RESET_CELL(RST_SCMI0_RNG1, RNG1_R, "rng1"), RESET_CELL(RST_SCMI0_MDMA, MDMA_R, "mdma"), RESET_CELL(RST_SCMI0_MCU, MCU_R, "mcu"), + RESET_CELL(RST_SCMI0_MCU_HOLD_BOOT, MCU_HOLD_BOOT_R, "mcu_hold_boot"), }; struct scmi_agent_resources { @@ -329,6 +330,7 @@ int32_t plat_scmi_clock_set_rate(unsigned int agent_id, unsigned int scmi_id, if (!clock) return SCMI_NOT_FOUND; + if (!stm32mp_nsec_can_access_clock(clock->clock_id)) return SCMI_DENIED; @@ -445,6 +447,9 @@ int32_t plat_scmi_rd_autonomous(unsigned int agent_id, unsigned int scmi_id, if (!stm32mp_nsec_can_access_reset(rd->reset_id)) return SCMI_DENIED; + if (rd->reset_id == MCU_HOLD_BOOT_R) + return SCMI_NOT_SUPPORTED; + /* Supports only reset with context loss */ if (state) return SCMI_NOT_SUPPORTED; @@ -471,6 +476,13 @@ int32_t plat_scmi_rd_set_state(unsigned int agent_id, unsigned int scmi_id, if (!stm32mp_nsec_can_access_reset(rd->reset_id)) return SCMI_DENIED; + if (rd->reset_id == MCU_HOLD_BOOT_R) { + DMSG("SCMI MCU hold boot %s", + assert_not_deassert ? "set" : "release"); + stm32_reset_assert_deassert_mcu(assert_not_deassert); + return SCMI_SUCCESS; + } + if (assert_not_deassert) { DMSG("SCMI reset %u set", scmi_id); stm32_reset_set(rd->reset_id); diff --git a/core/arch/arm/plat-stm32mp1/shared_resources.c b/core/arch/arm/plat-stm32mp1/shared_resources.c index 08aa9a3f0..2726942ce 100644 --- a/core/arch/arm/plat-stm32mp1/shared_resources.c +++ b/core/arch/arm/plat-stm32mp1/shared_resources.c @@ -5,10 +5,10 @@ #include #include -#include #include #include #include +#include #include #include #include @@ -147,6 +147,9 @@ static const char __maybe_unused *shres2str_id_tbl[STM32MP1_SHRES_COUNT] = { static __maybe_unused const char *shres2str_id(enum stm32mp_shres id) { + if (id >= ARRAY_SIZE(shres2str_id_tbl)) + panic("Invalid shared resource ID"); + return shres2str_id_tbl[id]; } @@ -407,6 +410,91 @@ void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin) } } +#ifdef CFG_STM32_ETZPC +struct shres2decprot { + enum stm32mp_shres shres_id; + unsigned int decprot_id; +}; + +#define SHRES2DECPROT(shres, decprot) { \ + .shres_id = shres, \ + .decprot_id = decprot, \ + } + +static const struct shres2decprot shres2decprot_tbl[] = { + SHRES2DECPROT(STM32MP1_SHRES_IWDG1, STM32MP1_ETZPC_IWDG1_ID), + SHRES2DECPROT(STM32MP1_SHRES_USART1, STM32MP1_ETZPC_USART1_ID), + SHRES2DECPROT(STM32MP1_SHRES_SPI6, STM32MP1_ETZPC_SPI6_ID), + SHRES2DECPROT(STM32MP1_SHRES_I2C4, STM32MP1_ETZPC_I2C4_ID), + SHRES2DECPROT(STM32MP1_SHRES_RNG1, STM32MP1_ETZPC_RNG1_ID), + SHRES2DECPROT(STM32MP1_SHRES_HASH1, STM32MP1_ETZPC_HASH1_ID), + SHRES2DECPROT(STM32MP1_SHRES_CRYP1, STM32MP1_ETZPC_CRYP1_ID), + SHRES2DECPROT(STM32MP1_SHRES_I2C6, STM32MP1_ETZPC_I2C6_ID), +}; + +static enum stm32mp_shres decprot2shres(unsigned int decprot_id) +{ + size_t i = 0; + + for (i = 0; i < ARRAY_SIZE(shres2decprot_tbl); i++) + if (shres2decprot_tbl[i].decprot_id == decprot_id) + return shres2decprot_tbl[i].shres_id; + + DMSG("No shared resource for DECPROT ID %u", decprot_id); + return STM32MP1_SHRES_COUNT; +} + +void stm32mp_register_etzpc_decprot(unsigned int id, + enum etzpc_decprot_attributes attr) +{ + enum shres_state state = SHRES_SECURE; + bool write_secure = false; + unsigned int id_shres = STM32MP1_SHRES_COUNT; + + switch (attr) { + case ETZPC_DECPROT_S_RW: + state = SHRES_SECURE; + break; + case ETZPC_DECPROT_NS_R_S_W: + case ETZPC_DECPROT_MCU_ISOLATION: + case ETZPC_DECPROT_NS_RW: + state = SHRES_NON_SECURE; + break; + default: + panic(); + } + + write_secure = attr == ETZPC_DECPROT_NS_R_S_W || + attr == ETZPC_DECPROT_S_RW; + + switch (id) { + case STM32MP1_ETZPC_STGENC_ID: + case STM32MP1_ETZPC_BKPSRAM_ID: + if (state != SHRES_SECURE) + panic("ETZPC: STGEN & BKSRAM should be secure"); + break; + case STM32MP1_ETZPC_DDRCTRL_ID: + case STM32MP1_ETZPC_DDRPHYC_ID: + /* We assume these must always be write-only to secure world */ + if (!write_secure) + panic("ETZPC: DDRCTRL & DDRPHY should be write secure"); + break; + default: + id_shres = decprot2shres(id); + if (id_shres >= STM32MP1_SHRES_COUNT) { + if (write_secure) { + DMSG("ETZPC: cannot secure DECPROT %s", + shres2str_id(id_shres)); + panic(); + } + } else { + register_periph(id_shres, state); + } + break; + } +} +#endif /*CFG_STM32_ETZPC*/ + static void lock_registering(void) { registering_locked = true; @@ -571,6 +659,7 @@ bool stm32mp_nsec_can_access_reset(unsigned int reset_id) shres_id = STM32MP1_SHRES_MDMA; break; case MCU_R: + case MCU_HOLD_BOOT_R: shres_id = STM32MP1_SHRES_MCU; break; default: @@ -613,13 +702,39 @@ static void config_lock_decprot(uint32_t decprot_id, etzpc_lock_decprot(decprot_id); } +static bool decprot_is_write_secure(uint32_t decprot_id) +{ + enum etzpc_decprot_attributes attr = etzpc_get_decprot(decprot_id); + + return attr == ETZPC_DECPROT_S_RW || + attr == ETZPC_DECPROT_NS_R_S_W; +} + +static bool decprot_is_secure(uint32_t decprot_id) +{ + enum etzpc_decprot_attributes attr = etzpc_get_decprot(decprot_id); + + return attr == ETZPC_DECPROT_S_RW; +} + static void set_etzpc_secure_configuration(void) { /* Some peripherals shall be secure */ - config_lock_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW); - config_lock_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW); - config_lock_decprot(STM32MP1_ETZPC_DDRCTRL_ID, ETZPC_DECPROT_S_RW); - config_lock_decprot(STM32MP1_ETZPC_DDRPHYC_ID, ETZPC_DECPROT_S_RW); + if (!decprot_is_secure(STM32MP1_ETZPC_STGENC_ID)) + config_lock_decprot(STM32MP1_ETZPC_STGENC_ID, + ETZPC_DECPROT_S_RW); + + if (!decprot_is_secure(STM32MP1_ETZPC_BKPSRAM_ID)) + config_lock_decprot(STM32MP1_ETZPC_BKPSRAM_ID, + ETZPC_DECPROT_S_RW); + + if (!decprot_is_write_secure(STM32MP1_ETZPC_DDRCTRL_ID)) + config_lock_decprot(STM32MP1_ETZPC_DDRCTRL_ID, + ETZPC_DECPROT_NS_R_S_W); + + if (!decprot_is_write_secure(STM32MP1_ETZPC_DDRPHYC_ID)) + config_lock_decprot(STM32MP1_ETZPC_DDRPHYC_ID, + ETZPC_DECPROT_NS_R_S_W); /* Configure ETZPC with peripheral registering */ config_lock_decprot(STM32MP1_ETZPC_IWDG1_ID, diff --git a/core/arch/arm/plat-stm32mp1/stm32_util.h b/core/arch/arm/plat-stm32mp1/stm32_util.h index 9c86cd26c..3fd5c602e 100644 --- a/core/arch/arm/plat-stm32mp1/stm32_util.h +++ b/core/arch/arm/plat-stm32mp1/stm32_util.h @@ -120,6 +120,9 @@ int stm32mp1_round_opp_khz(uint32_t *freq_khz); TEE_Result stm32_reset_assert(unsigned int id, unsigned int timeout_us); TEE_Result stm32_reset_deassert(unsigned int id, unsigned int timeout_us); +/* Specific reset to manage the MCU hold boot */ +TEE_Result stm32_reset_assert_deassert_mcu(bool assert_not_deassert); + static inline void stm32_reset_set(unsigned int id) { (void)stm32_reset_assert(id, 0); @@ -164,6 +167,11 @@ static inline int stm32mp_start_clock_calib(unsigned int clock_id __unused) /* Platform util for the RTC driver */ bool stm32_rtc_get_read_twice(void); +/* Platform util for the ETZPC driver */ + +/* Convert a ETZPC mode from DT binding to ETZPC DECPROT configuration */ +enum etzpc_decprot_attributes stm32mp_etzpc_binding2decprot(uint32_t mode); + /* * Return true if platform is in closed_device mode */ @@ -335,4 +343,8 @@ bool stm32mp_gpio_bank_is_non_secure(unsigned int bank); /* Register parent clocks of @clock (ID used in clock DT bindings) as secure */ void stm32mp_register_clock_parents_secure(unsigned long clock_id); +/* Register a resource identified by a ETZPC DECPROT identifier */ +void stm32mp_register_etzpc_decprot(unsigned int id, + enum etzpc_decprot_attributes attr); + #endif /*__STM32_UTIL_H__*/ diff --git a/core/arch/arm/plat-stm32mp1/sub.mk b/core/arch/arm/plat-stm32mp1/sub.mk index 69df1ced5..ae2041741 100644 --- a/core/arch/arm/plat-stm32mp1/sub.mk +++ b/core/arch/arm/plat-stm32mp1/sub.mk @@ -6,6 +6,15 @@ srcs-$(CFG_STM32_RNG) += rng_seed.c srcs-y += scmi_server.c srcs-y += shared_resources.c srcs-$(CFG_TZC400) += plat_tzc400.c +srcs-$(CFG_RPROC_PTA) += remoteproc_pta.c + +ifeq ($(CFG_RPROC_PTA),y) +gensrcs-y += rproc_pub_key +produce-rproc_pub_key = rproc_pub_key.c +depends-rproc_pub_key = $(CFG_RPROC_SIGN_KEY) scripts/pem_to_pub_c.py +recipe-rproc_pub_key = $(PYTHON3) scripts/pem_to_pub_c.py --prefix rproc_pub_key \ + --key $(CFG_RPROC_SIGN_KEY) --out $(sub-dir-out)/rproc_pub_key.c +endif subdirs-y += drivers subdirs-y += nsec-service diff --git a/core/drivers/stm32_bsec.c b/core/drivers/stm32_bsec.c index a563f79f9..8df9730a4 100644 --- a/core/drivers/stm32_bsec.c +++ b/core/drivers/stm32_bsec.c @@ -287,7 +287,6 @@ TEE_Result stm32_bsec_shadow_read_otp(uint32_t *otp_value, uint32_t otp_id) return result; } -#ifdef CFG_STM32_BSEC_WRITE TEE_Result stm32_bsec_write_otp(uint32_t value, uint32_t otp_id) { TEE_Result result = 0; @@ -312,6 +311,7 @@ TEE_Result stm32_bsec_write_otp(uint32_t value, uint32_t otp_id) return TEE_SUCCESS; } +#ifdef CFG_STM32_BSEC_WRITE TEE_Result stm32_bsec_program_otp(uint32_t value, uint32_t otp_id) { TEE_Result result = 0; diff --git a/core/drivers/stm32_etzpc.c b/core/drivers/stm32_etzpc.c index 4a2cb251f..fc4daba87 100644 --- a/core/drivers/stm32_etzpc.c +++ b/core/drivers/stm32_etzpc.c @@ -26,10 +26,16 @@ #include #include #include +#include #include -/* Devicetree compatibulity */ +/* Devicetree compatibility */ #define ETZPC_COMPAT "st,stm32-etzpc" +#define ETZPC_LOCK_MASK BIT(0) +#define ETZPC_MODE_SHIFT 8 +#define ETZPC_MODE_MASK GENMASK_32(1, 0) +#define ETZPC_ID_SHIFT 16 +#define ETZPC_ID_MASK GENMASK_32(7, 0) /* ID Registers */ #define ETZPC_TZMA0_SIZE 0x000U @@ -288,7 +294,7 @@ static void get_hwcfg(struct etzpc_hwcfg *hwcfg) ETZPC_HWCFGR_CHUNCKS1N4_SHIFT; } -static void init_devive_from_hw_config(struct etzpc_instance *dev, +static void init_device_from_hw_config(struct etzpc_instance *dev, paddr_t pbase) { struct etzpc_hwcfg hwcfg = { }; @@ -312,10 +318,49 @@ static void init_devive_from_hw_config(struct etzpc_instance *dev, void stm32_etzpc_init(paddr_t base) { - init_devive_from_hw_config(&etzpc_dev, base); + init_device_from_hw_config(&etzpc_dev, base); } #ifdef CFG_DT +struct dt_id_attr { + /* The effective size of the array is meaningless here */ + fdt32_t id_attr[1]; +}; + +static void etzpc_dt_conf_decprot(void *fdt, int node) +{ + const struct dt_id_attr *conf_list = NULL; + size_t i = 0; + int len = 0; + + conf_list = (const struct dt_id_attr *)fdt_getprop(fdt, node, + "st,decprot", &len); + if (conf_list == NULL) { + DMSG("No ETZPC DECPROT configuration in DT"); + return; + } + + for (i = 0; i < len / sizeof(uint32_t); i++) { + uint32_t value = fdt32_to_cpu(conf_list->id_attr[i]); + uint32_t id = (value >> ETZPC_ID_SHIFT) & ETZPC_ID_MASK; + uint32_t mode = (value >> ETZPC_MODE_SHIFT) & ETZPC_MODE_MASK; + bool lock = value & ETZPC_LOCK_MASK; + enum etzpc_decprot_attributes attr = ETZPC_DECPROT_MAX; + + if (!valid_decprot_id(id)) { + DMSG("Invalid DECPROT %"PRIu32, id); + panic(); + } + + attr = stm32mp_etzpc_binding2decprot(mode); + stm32mp_register_etzpc_decprot(id, attr); + etzpc_configure_decprot(id, attr); + + if (lock) + etzpc_lock_decprot(id); + } +} + static TEE_Result init_etzpc_from_dt(void) { void *fdt = get_embedded_dt(); @@ -337,7 +382,9 @@ static TEE_Result init_etzpc_from_dt(void) if (pbase == (paddr_t)-1) panic(); - init_devive_from_hw_config(&etzpc_dev, pbase); + init_device_from_hw_config(&etzpc_dev, pbase); + + etzpc_dt_conf_decprot(fdt, node); return TEE_SUCCESS; } diff --git a/core/drivers/stm32_gpio.c b/core/drivers/stm32_gpio.c index 093407252..96a59dcd5 100644 --- a/core/drivers/stm32_gpio.c +++ b/core/drivers/stm32_gpio.c @@ -38,7 +38,7 @@ #define GPIO_MODE_MASK GENMASK_32(1, 0) #define GPIO_OSPEED_MASK GENMASK_32(1, 0) #define GPIO_PUPD_PULL_MASK GENMASK_32(1, 0) -#define GPIO_ALTERNATE_MASK GENMASK_32(15, 0) +#define GPIO_ALTERNATE_MASK GENMASK_32(3, 0) #define DT_GPIO_BANK_SHIFT 12 #define DT_GPIO_BANK_MASK GENMASK_32(16, 12) diff --git a/core/drivers/stm32_tim.c b/core/drivers/stm32_tim.c index 612fbbc44..3283f1115 100644 --- a/core/drivers/stm32_tim.c +++ b/core/drivers/stm32_tim.c @@ -63,6 +63,7 @@ #define TIM_PRESCAL_HSI 10 #define TIM_PRESCAL_CSI 7 #define TIM_MIN_FREQ_CALIB 50000000U +#define TIM_THRESHOLD 1U struct stm32_tim_instance { struct io_pa_va base; @@ -132,9 +133,9 @@ static int timer_config(struct stm32_tim_instance *timer) static uint32_t timer_start_capture(struct stm32_tim_instance *timer) { uint64_t timeout_ref = 0; + uint64_t timeout_conv = 0; uint32_t counter = 0; uint32_t old_counter = 0; - int twice = 0; vaddr_t base = timer_base(timer); if (timer_config(timer)) @@ -144,7 +145,7 @@ static uint32_t timer_start_capture(struct stm32_tim_instance *timer) io_write32(base + TIM_SR, 0); - timeout_ref = timeout_init_us(TIM_TIMEOUT_US); + timeout_ref = timeout_init_us(TIM_TIMEOUT_US / TIM_TIMEOUT_STEP_US); while (!timeout_elapsed(timeout_ref)) if (io_read32(base + TIM_SR) & TIM_SR_UIF) @@ -154,11 +155,20 @@ static uint32_t timer_start_capture(struct stm32_tim_instance *timer) io_write32(base + TIM_SR, 0); - for (twice = 0; (twice < 2) || (counter != old_counter); twice++) { - timeout_ref = timeout_init_us(TIM_TIMEOUT_US); + timeout_conv = timeout_init_us(TIM_TIMEOUT_US); + + do { + if (timeout_elapsed(timeout_conv)) { + counter = 0; + goto bail; + } + + timeout_ref = timeout_init_us(TIM_TIMEOUT_US / + TIM_TIMEOUT_STEP_US); while (!timeout_elapsed(timeout_ref)) if (io_read32(base + TIM_SR) & TIM_SR_CC1IF) break; + if (!(io_read32(base + TIM_SR) & TIM_SR_CC1IF)) { counter = 0; goto bail; @@ -166,7 +176,8 @@ static uint32_t timer_start_capture(struct stm32_tim_instance *timer) old_counter = counter; counter = io_read32(base + TIM_CCR1); - } + } while (MAX(counter, old_counter) - MIN(counter, old_counter) > + TIM_THRESHOLD); bail: stm32_clock_disable(timer->clk); diff --git a/core/include/drivers/stm32_bsec.h b/core/include/drivers/stm32_bsec.h index d284eea10..9fe85bc98 100644 --- a/core/include/drivers/stm32_bsec.h +++ b/core/include/drivers/stm32_bsec.h @@ -45,15 +45,7 @@ TEE_Result stm32_bsec_read_otp(uint32_t *value, uint32_t otp_id); * @otp_id: OTP number * Return a TEE_Result compliant return value */ -#ifdef CFG_STM32_BSEC_WRITE TEE_Result stm32_bsec_write_otp(uint32_t value, uint32_t otp_id); -#else -static inline TEE_Result stm32_bsec_write_otp(uint32_t value __unused, - uint32_t otp_id __unused) -{ - return TEE_ERROR_NOT_SUPPORTED; -} -#endif /* * Program a bit in SAFMEM without BSEC data refresh diff --git a/core/include/dt-bindings/reset/stm32mp1-resets.h b/core/include/dt-bindings/reset/stm32mp1-resets.h index bc71924fa..f3a0ed317 100644 --- a/core/include/dt-bindings/reset/stm32mp1-resets.h +++ b/core/include/dt-bindings/reset/stm32mp1-resets.h @@ -7,6 +7,7 @@ #ifndef _DT_BINDINGS_STM32MP1_RESET_H_ #define _DT_BINDINGS_STM32MP1_RESET_H_ +#define MCU_HOLD_BOOT_R 2144 #define LTDC_R 3072 #define DSI_R 3076 #define DDRPERFM_R 3080 @@ -117,5 +118,6 @@ #define RST_SCMI0_RNG1 8 #define RST_SCMI0_MDMA 9 #define RST_SCMI0_MCU 10 +#define RST_SCMI0_MCU_HOLD_BOOT 11 #endif /* _DT_BINDINGS_STM32MP1_RESET_H_ */ diff --git a/core/sub.mk b/core/sub.mk index 03cc6bc71..c034276b6 100644 --- a/core/sub.mk +++ b/core/sub.mk @@ -20,13 +20,16 @@ recipe-ldelf = scripts/gen_ldelf_hex.py --input $(out-dir)/ldelf/ldelf.elf \ endif ifeq ($(CFG_WITH_USER_TA)-$(CFG_EARLY_TA),y-y) +ifeq ($(CFG_EARLY_TA_COMPRESS),y) +early-ta-compress = --compress +endif define process_early_ta early-ta-$1-uuid := $(firstword $(subst ., ,$(notdir $1))) gensrcs-y += early-ta-$1 produce-early-ta-$1 = early_ta_$$(early-ta-$1-uuid).c depends-early-ta-$1 = $1 scripts/ta_bin_to_c.py -recipe-early-ta-$1 = scripts/ta_bin_to_c.py --compress --ta $1 \ - --out $(sub-dir-out)/early_ta_$$(early-ta-$1-uuid).c +recipe-early-ta-$1 = scripts/ta_bin_to_c.py $(early-ta-compress) \ + --ta $1 --out $(sub-dir-out)/early_ta_$$(early-ta-$1-uuid).c endef $(foreach f, $(EARLY_TA_PATHS), $(eval $(call process_early_ta,$(f)))) $(foreach f, $(CFG_IN_TREE_EARLY_TAS), $(eval $(call \ diff --git a/keys/default_rproc.pem b/keys/default_rproc.pem new file mode 100644 index 000000000..d54476f35 --- /dev/null +++ b/keys/default_rproc.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEA1TD3AMwyJhzsliOhEStPrCrgnG9Gy8z+OCtialVngW/rkqQB +cb/oOdiMPjfLoSio8zaUA86mTHo6DINZIopTZvs9pysnpvrOwbjCVRXTcIhgM/YZ +GyN9c+Qo5fCbOlCsxD0PG40hP4O0dktWyzmWQfjy0+9BDAyMoW59lPeYZcJAKSWT +M10V5h3JTabA4dqVroeztuTow3ftNImNuzMFYDqGDUcJy0EdluRsBfhOOKXE7ZaQ +RXnwY9CTCGqgsuNKwE1g8evkseaLcJk4/JpVFOgZp4fUgsxU6EBRD2i+C+Jq9KXg +qBcK0QwXNr2IwG3i76QmLzGGkpW7bKPn/QhGMQIDAQABAoIBAQCHBnAqzSmmAgPG +Q+KroSbhAHcqHUBVrAwHP1Mhzd20mVI2mjFf/g/zMzf/4A7Uj5ASGqs8jhG9tlw1 +uKsnuTyBqPavfiGrHIb/IynSAfTc/UMRJflYuu2mDQfqOq3WDWqfD50V8hjwxVXy +5lyecma8ehQyLwKfwwL+66AWTYr0Rx+OdXkGdGj1SXbJU39nv7UH8ZggpICFhUXO +r7NgJr2UOyhEje4stTGSb86SrvxHRm07JG1WSOJ2GV0EBhWNqbRtsnvH1NKNm03m +yM+zMbqvtdg1Wkfcfxtx6h7MGHhUUIHwotDoKgZ1lz1EdVWk8clmlKCLFEBxcwIp +sdbrodnBAoGBAPFQ1J7B+3eDBJjgrEFu9soygrjulhiA2+3qrra95RyuIE0wE8CO +DPjAGHOnxAoUt8H+TEGF2Wo2HVQauz2ElPOlIxQctr3w2Xpi1DibKEdooQLRlaSS +LHWAxTLZj9EI3NuYhdRvFHUW2ExEqCADOKY4+1xRSXuIbIkaLMaah8R9AoGBAOIq +BEiqoaQM/EA4z+m7RuOjc1PtA0qo9DJIEb4Mj92gEGzSHCdNN+eDCKbqyd8BGo/w +Pf6N8+dotjYvzlz3MqwfV1aczvQqbfkivzahO7GlK2KmwwLG3Vm8dZAZCZKEglOg +ex6h/L8gOgqSP+C4OmdEU4jdA24BSHr+1ZArHPrFAoGBAL27l/DbBCSLVun8fHNW +E6QW4sEUld7eMg12H7h+xc0u+ya1TlJvXbOXFaKZnYFvmKtmjf5WhwMDWTvvaJiN +za9jf5kommXtIJEhc0quc5TxpubYcpfadipM/L9mX7UzCrN90Hueeq81LwuIT8gb +wEaxNrD3GJeQRAXoFpxwk57hAoGAaeqLfwyKDq4WJG120VtnY4xUomVJOVnOow2l +YX+4kG45wvzTOoSrPbzb/G/QgqOdsPMt1VzdcO5VByN0XY1XKcyztlhRg3+raRWg +vxDbR+K2Ysj+YvqHB1N/KzDOjtOHxWpOvpXWLBwHkpPTXoZos5wIEvyOcqIfM5rM +oWvPcpECgYBCtncnPQQJfYcFebw3+rzm9OodF/s6G9afOrzqgEk/0Z6mi20x1c23 +dzcZUpLl9p7fCFg0iz9NwLUYR9tZ/4zy+J4ZET7PduxoLG3m1TVzxSJM+dU+GtQi +fBcdQuC6od9K9MJD2egwmes/I+aWhrIAatrG2iMtrOTG5N0mUMUc+w== +-----END RSA PRIVATE KEY----- diff --git a/lib/libutee/include/remoteproc_pta.h b/lib/libutee/include/remoteproc_pta.h new file mode 100644 index 000000000..cede192eb --- /dev/null +++ b/lib/libutee/include/remoteproc_pta.h @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + */ + +#ifndef __REMOTEPROC_PTA_H +#define __REMOTEPROC_PTA_H + +#include + +/* + * Interface to the pseudo TA which provides platform implementation + * of the remote processor management + */ + +#define PTA_REMOTEPROC_UUID { 0x54af4a68, 0x19be, 0x40d7, \ + { 0xbb, 0xe6, 0x89, 0x50, 0x35, 0x0a, 0x87, 0x44 } } + +/* Firmware format */ +#define PTA_REMOTEPROC_PROPRIETARY_FMT BIT32(0) +#define PTA_REMOTEPROC_ELF_FMT BIT32(1) + +/* Firmware image protection */ +/* The platorm supports copy of the input firmware image in secure memory */ +#define PTA_REMOTEPROC_FW_SECURE_COPY BIT32(0) +/* The platorm supports load of segment with hash protection */ +#define PTA_REMOTEPROC_FW_WITH_HASH_TABLE BIT32(1) +/* The platorm is able to change access to secure the firmware input image */ +#define PTA_REMOTEPROC_FW_MEMORY_PROTECTION BIT32(2) + +/** + * struct rproc_pta_key_info - public key information + * @algo: Algorithm, defined by public key algorithms TEE_ALG_* + * from TEE Internal API specification + * @info_size: Byte size of the @info + * @info: Append key information data + */ +struct rproc_pta_key_info { + uint32_t algo; + uint32_t info_size; + char info[]; +}; + +static inline size_t + rproc_pta_get_keyinfo_size(struct rproc_pta_key_info *keyinf) +{ + size_t s = 0; + + if (!keyinf || ADD_OVERFLOW(sizeof(*keyinf), keyinf->info_size, &s)) + return 0; + + return s; +} + +#define RPROC_PTA_GET_KEYINFO_SIZE(x) rproc_pta_get_keyinfo_size((x)) + +/* + * Platform capabilities. + * + * Get Platform firmware loader service capabilities. + * + * [in] params[0].value.a: Unique 32bit firmware identifier + * [out] params[1].value.a: Firmware format (PTA_REMOTEPROC_*_FMT) + * [out] params[2].value.a: Image protection method (PTA_REMOTEPROC_FW_*) + */ +#define PTA_REMOTEPROC_HW_CAPABILITIES 1 + +/* + * Firmware loading. + * + * Optional service to implement only in case of proprietary format. + * + * [in] params[0].value.a: Unique 32bit firmware identifier + * [in] params[1].memref: Loadable firmware image + */ +#define PTA_REMOTEPROC_FIRMWARE_LOAD 2 + +/* + * Load a segment with a SHA256 hash. + * + * This command is used when the platform secure memory is too expensive to + * save the whole firmware image in secure memory. Upon segment load, a + * successful completion ensures the loaded image complies with the provided + * hash. + * + * [in] params[0].value.a: Unique 32bit firmware identifier + * [in] params[1].memref: Section data to load + * [in] params[2].value.a: 32bit LSB load device segment address + * [in] params[2].value.b: 32bit MSB load device segment address + * [in] params[3].memref: Expected hash (SHA256) of the payload + */ +#define PTA_REMOTEPROC_LOAD_SEGMENT_SHA256 3 + +/* + * Memory set. + * + * Fill a remote device memory with requested value. this is use for instance + * to clear a memory on the remote firmware load. + * + * [in] params[0].value.a: Unique 32bit firmware identifier + * [in] params[1].value.a: 32bit LSB device memory address + * [in] params[1].value.b: 32bit MSB device memory address + * [in] params[2].value.a: 32bit LSB device memory size + * [in] params[2].value.b: 32bit MSB device memory size + * [in] params[3].value.a: Byte value to be set + */ +#define PTA_REMOTEPROC_SET_MEMORY 4 + +/* + * Firmware start. + * + * Start up a successfully remote processor firmware. + * + * [in] params[0].value.a: Unique 32bit firmware identifier + */ +#define PTA_REMOTEPROC_FIRMWARE_START 5 + +/* + * Firmware stop. + * + * Stop of the remote processor firmware and release/clean resources. + * After the command successful completion, remote processor firmware must be + * reloaded prior being started again. + * + * [in] params[0].value.a: Unique 32bit firmware identifier + */ +#define PTA_REMOTEPROC_FIRMWARE_STOP 6 + +/* + * Firmware device to physical address conversion. + * + * Return the physical address corresponding to an address got from the + * firmware address layout. + * + * [in] params[0].value.a: Unique 32bit firmware identifier + * [in] params[1].value.a: 32bit LSB Device memory address + * [in] params[1].value.b: 32bit MSB Device memory address + * [in] params[2].value.a: 32bit LSB Device memory size + * [in] params[2].value.b: 32bit MSB Device memory size + * [out] params[3].value.a: 32bit LSB converted physical address + * [out] params[3].value.b: 32bit MSB converted physical address + */ +#define PTA_REMOTEPROC_FIRMWARE_DA_TO_PA 7 + +/* + * Verify the firmware digest against a signature + * + * Return TEE_SUCCESS if the signature is verified, else an error + * + * [in] params[0].value.a: Unique 32bit firmware identifier + * [in] params[1].memref: Key information (refer to @rproc_pta_key_info) + * [in] params[2].memref: Digest of the firmware authenticated data + * [in] params[3].memref: Signature of the firmware authenticated data + */ +#define PTA_REMOTEPROC_VERIFY_DIGEST 8 + +#endif /* __REMOTEPROC_PTA_H */ diff --git a/mk/config.mk b/mk/config.mk index bc49f83d8..bc3e1dccf 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -296,6 +296,9 @@ $(eval $(call cfg-depends-all,CFG_REE_FS_TA_BUFFERED,CFG_REE_FS_TA)) # in-tree TAs. CFG_IN_TREE_EARLY_TAS is formatted as: # / # for instance avb/023f8f1a-292a-432b-8fc4-de8471358067 +# +# By default the early TAs are compressed in the TEE binary, it is possible to +# not compress them with CFG_EARLY_TA_COMPRESS=n ifneq ($(EARLY_TA_PATHS)$(CFG_IN_TREE_EARLY_TAS),) $(call force,CFG_EARLY_TA,y) else @@ -304,6 +307,7 @@ endif ifeq ($(CFG_EARLY_TA),y) $(call force,CFG_ZLIB,y) endif +CFG_EARLY_TA_COMPRESS ?= y # Enable paging, requires SRAM, can't be enabled by default CFG_WITH_PAGER ?= n diff --git a/scripts/sign_rproc_fw.py b/scripts/sign_rproc_fw.py new file mode 100755 index 000000000..0fd0a8755 --- /dev/null +++ b/scripts/sign_rproc_fw.py @@ -0,0 +1,400 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (C) 2020, STMicroelectronics - All Rights Reserved +# + +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import SymbolTableSection +from elftools.elf.enums import * +from Cryptodome.Hash import SHA256 +from Cryptodome.Signature import pkcs1_15 +from Cryptodome.PublicKey import RSA +from Cryptodome.Signature import DSS +from Cryptodome.PublicKey import ECC +import sys +import struct +import logging +import binascii + + +logging.basicConfig(stream=sys.stderr, level=logging.INFO) + +ENUM_HASH_TYPE = dict( + SHA256=1, +) + +ENUM_SIGNATURE_TYPE = dict( + RSA=1, + ECC=2, +) + +ENUM_BINARY_TYPE = dict( + ELF=1, +) + + +def dump_buffer(buf, step=16, name="", logger=logging.info, indent=""): + logger("%s%s:" % (indent, name)) + for i in range(0, len(buf), step): + logger("%s " % (indent) + " ". + join(["%02X" % c for c in buf[i:i+step]])) + logger("\n") + + +class RSA_Signature(object): + + def __init__(self, key): + self._hasher = SHA256.new() + self.signer = pkcs1_15.new(key) + + def hash_compute(self, segment): + self._hasher.update(segment) + + def sign(self): + return self.signer.sign(self._hasher) + + +class ECC_Signature(object): + + def __init__(self, key): + self._hasher = SHA256.new() + self.signer = DSS.new(key, 'fips-186-3') + + def hash_compute(self, segment): + self._hasher.update(segment) + + def sign(self): + return self.signer.sign(self._hasher) + + +Signature = { + 1: RSA_Signature, + 2: ECC_Signature, +} + + +class SegmentHashStruct: + pass + + +class SegmentHash(object): + ''' + Hash table based on Elf program segments + ''' + def __init__(self, img): + self._num_segments = img.num_segments() + self._pack_fmt = '<%dL' % 8 + self.img = img + self.hashProgTable = bytes() + self._offset = 0 + + def get_table(self): + ''' + Create a segment hash table containing for each segment: + - the segments header + - a hash of the segment + ''' + h = SHA256.new() + seg = SegmentHashStruct() + self.size = (h.digest_size + 32) * self._num_segments + logging.debug("hash section size %d" % self.size) + del h + self.buf = bytearray(self.size) + self._bufview_ = memoryview(self.buf) + + for i in range(self._num_segments): + h = SHA256.new() + segment = self.img.get_segment(i) + seg.header = self.img.get_segment(i).header + logging.debug("compute hash for segment offset %s" % seg.header) + h.update(segment.data()) + seg.hash = h.digest() + logging.debug("hash computed: %s" % seg.hash) + del h + struct.pack_into('.sig') + + parsed = parser.parse_args() + + # Set defaults for optional arguments. + + if parsed.outf is None: + parsed.outf = str(parsed.inf)+'.sig' + + return parsed + + +def rsa_key(keyf): + return RSA.importKey(open(keyf).read()) + + +def ecc_key(keyf): + return ECC.import_key(open(keyf).read()) + + +key_type = { + 1: rsa_key, + 2: ecc_key, +} + + +def rsa_sig_size(key): + return key.size_in_bytes() + + +def ecc_sig_size(key): + # to be improve... + # DSA size is N/4 so 64 for DSA (L,N) = (2048, 256) + return 64 + + +sig_size_type = { + 1: rsa_sig_size, + 2: ecc_sig_size, +} + + +def main(): + from Cryptodome.Signature import pss + from Cryptodome.Hash import SHA256 + from Cryptodome.PublicKey import RSA + import base64 + import logging + import os + import struct + + logging.basicConfig() + logger = logging.getLogger(os.path.basename(__file__)) + + args = get_args(logger) + + # Initialise the header */ + s_header = ImageHeader() + + get_key = key_type.get(ENUM_SIGNATURE_TYPE[args.key_type], + lambda: "Invalid sign type") + key = get_key(args.keyf) + + if not key.has_private(): + logger.error('Provided key cannot be used for signing, ' + + 'please use offline-signing mode.') + sys.exit(1) + + # Firmware image + input_file = open(args.inf, 'rb') + img = ELFFile(input_file) + + # need to reopen the file to get the raw data + with open(args.inf, 'rb') as f: + bin_img = f.read() + img_size = len(bin_img) + logging.debug("image size %d" % img_size) + s_header.img_length = img_size + s_header.img_type = ENUM_BINARY_TYPE['ELF'] + + # Hash table chunk + h = SHA256.new() + + # Compute the hash table + hash_table = SegmentHash(img) + hash = hash_table.get_table() + + s_header.hash_offset = s_header.size + s_header.hash_length = hash_table.size + s_header.hash_type = ENUM_HASH_TYPE['SHA256'] + # Get padding to align on 64 bytes + hash_align = s_header.hash_length % 8 + + # Key information chunk + if args.key_infof: + with open(args.key_infof, 'rb') as f: + key_info = f.read() + s_header.key_length = sys.getsizeof(key_info) + s_header.key_offset = s_header.hash_offset + s_header.hash_length + \ + hash_align + # Get padding to align on 64 bytes + key_info_align = s_header.key_length % 8 + else: + key_info_align = 0 + + # Signature chunk + s_header.sign_type = ENUM_SIGNATURE_TYPE[args.key_type] + + sign_size = sig_size_type.get(ENUM_SIGNATURE_TYPE[args.key_type], + lambda: "Invalid sign type")(key) + s_header.sign_length = sign_size + + if args.key_infof: + s_header.sign_offset = s_header.key_offset + s_header.key_length + \ + key_info_align + else: + s_header.sign_offset = s_header.hash_offset + s_header.hash_length + \ + hash_align + + s_header.img_offset = s_header.sign_offset + sign_size + + s_header.length = s_header.size + s_header.hash_length + hash_align + \ + s_header.key_length + key_info_align + s_header.sign_length + + header = s_header.get_packed() + + # Generate signature + signer = Signature.get(ENUM_SIGNATURE_TYPE[args.key_type])(key) + + signer.hash_compute(header) + signer.hash_compute(bytes(hash)) + if args.key_infof: + signer.hash_compute(key_info) + + signature = signer.sign() + if len(signature) != sign_size: + raise Exception(("Actual signature length is not equal to ", + "the computed one: {} != {}". + format(len(signature), sign_size))) + + s_header.dump() + + with open(args.outf, 'wb') as f: + f.write(header) + f.write(hash) + if hash_align: + f.write(bytearray(hash_align)) + if args.key_infof: + if key_info_align: + f.write(key_info) + f.write(bytearray(key_info_align)) + f.write(signature) + f.write(bytearray(sign_size - s_header.sign_length)) + f.write(bin_img) + + +if __name__ == "__main__": + main() diff --git a/ta/remoteproc/Makefile b/ta/remoteproc/Makefile new file mode 100644 index 000000000..0d1a5010c --- /dev/null +++ b/ta/remoteproc/Makefile @@ -0,0 +1,18 @@ +# The UUID for the Trusted Application +BINARY=80a4c275-0a47-4905-8285-1486a9771a08 + +ifdef TA_CROSS_COMPILE +CROSS_COMPILE ?= $(TA_CROSS_COMPILE) +endif +export CROSS_COMPILE + +CFG_TEE_TA_LOG_LEVEL ?= 2 +CPPFLAGS += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL) + +-include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk + +ifeq ($(wildcard $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk), ) +clean: + @echo 'Note: $$(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk not found, cannot clean TA' + @echo 'Note: TA_DEV_KIT_DIR=$(TA_DEV_KIT_DIR)' +endif diff --git a/ta/remoteproc/elf_parser.c b/ta/remoteproc/elf_parser.c new file mode 100644 index 000000000..59b7e0119 --- /dev/null +++ b/ta/remoteproc/elf_parser.c @@ -0,0 +1,181 @@ + // SPDX-License-Identifier: BSD-2-Clause + /* + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include + +static bool va_in_fwm_image_range(void *va, uint8_t *fw, size_t fw_size) +{ + uint8_t *vaddr = va; + + assert(fw + fw_size >= fw); + return vaddr >= fw && vaddr < fw + fw_size; +} + +/* + * e32_parse_ehdr() - Check and parse the ELF header + * + * fw: Firmware ELF file image + * size: Byte size of firmware ELF file image + */ +TEE_Result e32_parse_ehdr(uint8_t *fw, size_t size) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw; + + if (!fw || !ALIGNMENT_IS_OK(fw, uint32_t)) { + EMSG("Invalid fw address %p", fw); + return TEE_ERROR_BAD_PARAMETERS; + } + + if (size < sizeof(Elf32_Ehdr) || + size < (ehdr->e_shoff + sizeof(Elf32_Shdr))) + return TEE_ERROR_CORRUPT_OBJECT; + + if (!IS_ELF(*ehdr) || + ehdr->e_ident[EI_VERSION] != EV_CURRENT || + ehdr->e_ident[EI_CLASS] != ELFCLASS32 || + ehdr->e_phentsize != sizeof(Elf32_Phdr) || + ehdr->e_shentsize != sizeof(Elf32_Shdr)) { + EMSG("Invalid header"); + + return TEE_ERROR_BAD_FORMAT; + } + + if (ehdr->e_phnum == 0) { + EMSG("No loadable segment found"); + return TEE_ERROR_BAD_FORMAT; + } + + return TEE_SUCCESS; +} + +/* + * e32_parser_load_elf_image - simple ELF loader + * fw: Firmware ELF file image + * fw_size: Firmware ELF file image byte size + * load_seg: Callback for loading a firmware image segment into device memory + * priv_data: Private data passed to @load_seg callback. + */ +TEE_Result e32_parser_load_elf_image(uint8_t *fw, size_t fw_size, + TEE_Result (*load_seg)(uint8_t *src, + uint32_t size, + uint32_t da, + uint32_t mem_size, + void *priv), + void *priv_data) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw; + Elf32_Phdr *phdr = (void *)((int8_t *)ehdr + ehdr->e_phoff); + TEE_Result res = TEE_SUCCESS; + unsigned int i = 0; + + if (!load_seg) + return TEE_ERROR_BAD_PARAMETERS; + + if (!ALIGNMENT_IS_OK(phdr, uint32_t) || + !va_in_fwm_image_range(phdr, fw, fw_size)) + return TEE_ERROR_CORRUPT_OBJECT; + + for (i = 0; i < ehdr->e_phnum; i++, phdr++) { + uint32_t dst = phdr->p_paddr; + uint8_t *src = NULL; + + if (!va_in_fwm_image_range((void *)((vaddr_t)(phdr + 1) - 1), + fw, fw_size)) + return TEE_ERROR_CORRUPT_OBJECT; + + if (phdr->p_type != PT_LOAD) + continue; + + src = (uint8_t *)fw + phdr->p_offset; + + if (!va_in_fwm_image_range(src, fw, fw_size) || + !va_in_fwm_image_range(src + phdr->p_filesz, fw, fw_size)) + return TEE_ERROR_CORRUPT_OBJECT; + + res = load_seg(src, phdr->p_filesz, dst, phdr->p_memsz, + priv_data); + if (res) + return res; + } + + return TEE_SUCCESS; +} + +/* Helper to find resource table in an ELF image */ +int e32_parser_find_rsc_table(uint8_t *fw, size_t fw_size, + Elf32_Addr *rsc_addr, Elf32_Word *rsc_size) +{ + Elf32_Shdr *shdr = NULL; + int i = 0; + char *name_table = NULL; + struct resource_table *table = NULL; + Elf32_Ehdr *ehdr = (Elf32_Ehdr *)(void *)fw; + uint8_t *elf_data = fw; + + shdr = (void *)(fw + ehdr->e_shoff); + if (!ALIGNMENT_IS_OK(shdr, uint32_t) || + !va_in_fwm_image_range(shdr, fw, fw_size)) + return TEE_ERROR_CORRUPT_OBJECT; + + name_table = (char *)elf_data + shdr[ehdr->e_shstrndx].sh_offset; + if (!va_in_fwm_image_range(name_table, fw, fw_size)) + return TEE_ERROR_CORRUPT_OBJECT; + + for (i = 0; i < ehdr->e_shnum; i++, shdr++) { + size_t size = shdr->sh_size; + size_t offset = shdr->sh_offset; + + if (!va_in_fwm_image_range(shdr, fw, fw_size)) + return TEE_ERROR_CORRUPT_OBJECT; + + if (strcmp(name_table + shdr->sh_name, ".resource_table")) + continue; + + if (offset + size > fw_size || offset + size < size) { + EMSG("Resource table truncated"); + return TEE_ERROR_BAD_FORMAT; + } + + if (sizeof(struct resource_table) > size) { + EMSG("No header found in resource table"); + return TEE_ERROR_BAD_FORMAT; + } + + table = (struct resource_table *)(void *)(elf_data + offset); + if (!ALIGNMENT_IS_OK(table, uint32_t)) + return TEE_ERROR_CORRUPT_OBJECT; + + if (table->ver != 1) { + EMSG("Unsupported fw version %"PRId32, table->ver); + return TEE_ERROR_BAD_FORMAT; + } + + if (table->reserved[0] || table->reserved[1]) { + EMSG("Non zero reserved bytes"); + return TEE_ERROR_BAD_FORMAT; + } + + if (table->num * sizeof(*table->offset) + + sizeof(struct resource_table) > size) { + EMSG("Resource table incomplete"); + return TEE_ERROR_BAD_FORMAT; + } + + DMSG("Resource table address %#"PRIx32", size %"PRIu32, + shdr->sh_addr, shdr->sh_size); + + *rsc_addr = shdr->sh_addr; + *rsc_size = shdr->sh_size; + + return TEE_SUCCESS; + } + + return TEE_ERROR_NO_DATA; +} diff --git a/ta/remoteproc/include/elf32.h b/ta/remoteproc/include/elf32.h new file mode 100644 index 000000000..2806c615d --- /dev/null +++ b/ta/remoteproc/include/elf32.h @@ -0,0 +1,243 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF32_H_ +#define _SYS_ELF32_H_ 1 + +#include +#include + +/* + * ELF definitions common to all 32-bit architectures. + */ + +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; +typedef uint64_t Elf32_Lword; + +typedef Elf32_Word Elf32_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf32_Word Elf32_Size; +typedef Elf32_Sword Elf32_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf32_Half e_type; /* File type. */ + Elf32_Half e_machine; /* Machine architecture. */ + Elf32_Word e_version; /* ELF format version. */ + Elf32_Addr e_entry; /* Entry point. */ + Elf32_Off e_phoff; /* Program header file offset. */ + Elf32_Off e_shoff; /* Section header file offset. */ + Elf32_Word e_flags; /* Architecture-specific flags. */ + Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf32_Half e_phentsize; /* Size of program header entry. */ + Elf32_Half e_phnum; /* Number of program header entries. */ + Elf32_Half e_shentsize; /* Size of section header entry. */ + Elf32_Half e_shnum; /* Number of section header entries. */ + Elf32_Half e_shstrndx; /* Section name strings section. */ +} Elf32_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf32_Word sh_name; /* Section name (index into the + section header string table). */ + Elf32_Word sh_type; /* Section type. */ + Elf32_Word sh_flags; /* Section flags. */ + Elf32_Addr sh_addr; /* Address in memory image. */ + Elf32_Off sh_offset; /* Offset in file. */ + Elf32_Word sh_size; /* Size in bytes. */ + Elf32_Word sh_link; /* Index of a related section. */ + Elf32_Word sh_info; /* Depends on section type. */ + Elf32_Word sh_addralign; /* Alignment in bytes. */ + Elf32_Word sh_entsize; /* Size of each entry in section. */ +} Elf32_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf32_Word p_type; /* Entry type. */ + Elf32_Off p_offset; /* File offset of contents. */ + Elf32_Addr p_vaddr; /* Virtual address in memory image. */ + Elf32_Addr p_paddr; /* Physical address (not used). */ + Elf32_Word p_filesz; /* Size of contents in file. */ + Elf32_Word p_memsz; /* Size of contents in memory. */ + Elf32_Word p_flags; /* Access permission flags. */ + Elf32_Word p_align; /* Alignment in memory and file. */ +} Elf32_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf32_Sword d_tag; /* Entry type. */ + union { + Elf32_Word d_val; /* Integer value. */ + Elf32_Addr d_ptr; /* Address value. */ + } d_un; +} Elf32_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ +} Elf32_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ + Elf32_Sword r_addend; /* Addend. */ +} Elf32_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF32_R_SYM(info) ((info) >> 8) +#define ELF32_R_TYPE(info) ((unsigned char)(info)) + +/* Macro for constructing r_info from field values. */ +#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf32_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf32_Lword m_value; /* symbol value */ + Elf32_Word m_info; /* size + index */ + Elf32_Word m_poffset; /* symbol offset */ + Elf32_Half m_repeat; /* repeat count */ + Elf32_Half m_stride; /* stride info */ +} Elf32_Move; + +/* + * The macros compose and decompose values for Move.r_info + * + * sym = ELF32_M_SYM(M.m_info) + * size = ELF32_M_SIZE(M.m_info) + * M.m_info = ELF32_M_INFO(sym, size) + */ +#define ELF32_M_SYM(info) ((info)>>8) +#define ELF32_M_SIZE(info) ((unsigned char)(info)) +#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf32_Word c_tag; /* how to interpret value */ + union { + Elf32_Word c_val; + Elf32_Addr c_ptr; + } c_un; +} Elf32_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf32_Word st_name; /* String table index of name. */ + Elf32_Addr st_value; /* Symbol value. */ + Elf32_Word st_size; /* Size of associated object. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf32_Half st_shndx; /* Section index of symbol. */ +} Elf32_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF32_ST_BIND(info) ((info) >> 4) +#define ELF32_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU symbol versioning. */ +typedef struct { + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; +} Elf32_Verdef; + +typedef struct { + Elf32_Word vda_name; + Elf32_Word vda_next; +} Elf32_Verdaux; + +typedef struct { + Elf32_Half vn_version; + Elf32_Half vn_cnt; + Elf32_Word vn_file; + Elf32_Word vn_aux; + Elf32_Word vn_next; +} Elf32_Verneed; + +typedef struct { + Elf32_Word vna_hash; + Elf32_Half vna_flags; + Elf32_Half vna_other; + Elf32_Word vna_name; + Elf32_Word vna_next; +} Elf32_Vernaux; + +typedef Elf32_Half Elf32_Versym; + +typedef struct { + Elf32_Half si_boundto; /* direct bindings - symbol bound to */ + Elf32_Half si_flags; /* per symbol flags */ +} Elf32_Syminfo; + +#endif /* !_SYS_ELF32_H_ */ diff --git a/ta/remoteproc/include/elf_common.h b/ta/remoteproc/include/elf_common.h new file mode 100644 index 000000000..a1da0ef80 --- /dev/null +++ b/ta/remoteproc/include/elf_common.h @@ -0,0 +1,1014 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/*- + * Copyright (c) 2000, 2001, 2008, 2011, David E. O'Brien + * Copyright (c) 1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF_COMMON_H_ +#define _SYS_ELF_COMMON_H_ 1 + +#include + +/* + * ELF definitions that are independent of architecture or word size. + */ + +#ifndef __ASSEMBLER__ +/* + * Note header. The ".note" section contains an array of notes. Each + * begins with this header, aligned to a word boundary. Immediately + * following the note header is n_namesz bytes of name, padded to the + * next word boundary. Then comes n_descsz bytes of descriptor, again + * padded to a word boundary. The values of n_namesz and n_descsz do + * not include the padding. + */ + +typedef struct { + uint32_t n_namesz; /* Length of name. */ + uint32_t n_descsz; /* Length of descriptor. */ + uint32_t n_type; /* Type of this note. */ +} Elf_Note; + +/* + * The header for GNU-style hash sections. + */ + +typedef struct { + uint32_t gh_nbuckets; /* Number of hash buckets. */ + uint32_t gh_symndx; /* First visible symbol in .dynsym. */ + uint32_t gh_maskwords; /* #maskwords used in bloom filter. */ + uint32_t gh_shift2; /* Bloom filter shift count. */ +} Elf_GNU_Hash_Header; +#endif /*__ASSEMBLER__*/ + +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developers/gabi/latest/ch4.eheader.html */ +#define EI_MAG0 0 /* Magic number, byte 0. */ +#define EI_MAG1 1 /* Magic number, byte 1. */ +#define EI_MAG2 2 /* Magic number, byte 2. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#define EI_OSABI 7 /* Operating system / ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define OLD_EI_BRAND 8 /* Start of architecture identification. */ +#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for the magic number bytes. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" /* magic string */ +#define SELFMAG 4 /* magic string size */ + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_AROS 15 /* Amiga Research OS */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ +#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ +#define ET_LOOS 0xfe00 /* First operating system specific. */ +#define ET_HIOS 0xfeff /* Last operating system-specific. */ +#define ET_LOPROC 0xff00 /* First processor-specific. */ +#define ET_HIPROC 0xffff /* Last processor-specific. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M32 1 /* AT&T WE32100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ +#define EM_S370 9 /* IBM System/370. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ +#define EM_PARISC 15 /* HP PA-RISC. */ +#define EM_VPP500 17 /* Fujitsu VPP500. */ +#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ +#define EM_960 19 /* Intel 80960. */ +#define EM_PPC 20 /* PowerPC 32-bit. */ +#define EM_PPC64 21 /* PowerPC 64-bit. */ +#define EM_S390 22 /* IBM System/390. */ +#define EM_V800 36 /* NEC V800. */ +#define EM_FR20 37 /* Fujitsu FR20. */ +#define EM_RH32 38 /* TRW RH-32. */ +#define EM_RCE 39 /* Motorola RCE. */ +#define EM_ARM 40 /* ARM. */ +#define EM_SH 42 /* Hitachi SH. */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ +#define EM_ARC 45 /* Argonaut RISC Core. */ +#define EM_H8_300 46 /* Hitachi H8/300. */ +#define EM_H8_300H 47 /* Hitachi H8/300H. */ +#define EM_H8S 48 /* Hitachi H8S. */ +#define EM_H8_500 49 /* Hitachi H8/500. */ +#define EM_IA_64 50 /* Intel IA-64 Processor. */ +#define EM_MIPS_X 51 /* Stanford MIPS-X. */ +#define EM_COLDFIRE 52 /* Motorola ColdFire. */ +#define EM_68HC12 53 /* Motorola M68HC12. */ +#define EM_MMA 54 /* Fujitsu MMA. */ +#define EM_PCP 55 /* Siemens PCP. */ +#define EM_NCPU 56 /* Sony nCPU. */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ +#define EM_STARCORE 58 /* Motorola Star*Core processor. */ +#define EM_ME16 59 /* Toyota ME16 processor. */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ +#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ +#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ +#define EM_PDSP 63 /* Sony DSP Processor. */ +#define EM_FX66 66 /* Siemens FX66 microcontroller. */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 + microcontroller. */ +#define EM_ST7 68 /* STmicroelectronics ST7 8-bit + microcontroller. */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller. */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller. */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller. */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller. */ +#define EM_SVX 73 /* Silicon Graphics SVx. */ +#define EM_ST19 74 /* STMicroelectronics ST19 8-bit mc. */ +#define EM_VAX 75 /* Digital VAX. */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded + processor. */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded + processor. */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor. */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor. */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc. */ +#define EM_HUANY 81 /* Harvard University machine-independent + object files. */ +#define EM_PRISM 82 /* SiTera Prism. */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller. */ +#define EM_FR30 84 /* Fujitsu FR30. */ +#define EM_D10V 85 /* Mitsubishi D10V. */ +#define EM_D30V 86 /* Mitsubishi D30V. */ +#define EM_V850 87 /* NEC v850. */ +#define EM_M32R 88 /* Mitsubishi M32R. */ +#define EM_MN10300 89 /* Matsushita MN10300. */ +#define EM_MN10200 90 /* Matsushita MN10200. */ +#define EM_PJ 91 /* picoJava. */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor. */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5. */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture. */ +#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor. */ +#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose + Processor. */ +#define EM_NS32K 97 /* National Semiconductor 32000 series. */ +#define EM_TPC 98 /* Tenor Network TPC processor. */ +#define EM_SNP1K 99 /* Trebia SNP 1000 processor. */ +#define EM_ST200 100 /* STMicroelectronics ST200 microcontroller. */ +#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family. */ +#define EM_MAX 102 /* MAX Processor. */ +#define EM_CR 103 /* National Semiconductor CompactRISC + microprocessor. */ +#define EM_F2MC16 104 /* Fujitsu F2MC16. */ +#define EM_MSP430 105 /* Texas Instruments embedded microcontroller + msp430. */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor. */ +#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors. */ +#define EM_SEP 108 /* Sharp embedded microprocessor. */ +#define EM_ARCA 109 /* Arca RISC Microprocessor. */ +#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd. + and MPRC of Peking University */ +#define EM_AARCH64 183 /* AArch64 (64-bit ARM) */ + +/* Non-standard or deprecated. */ +#define EM_486 6 /* Intel i486. */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ +#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ + +/* e_flags for EM_ARM */ +#define EF_ARM_ABI_VERSION 0x05000000 /* ABI version 5 */ +#define EF_ARM_ABIMASK 0xFF000000 +#define EF_ARM_BE8 0x00800000 +#define EF_ARM_ABI_FLOAT_HARD 0x00000400 /* ABI version 5 and later */ +#define EF_ARM_ABI_FLOAT_SOFT 0x00000200 /* ABI version 5 and later */ + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_LOOS 0xff20 /* First operating system-specific. */ +#define SHN_HIOS 0xff3f /* Last operating system-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends */ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section - no addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ +#define SHT_GROUP 17 /* Section group. */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_LOSUNW 0x6ffffff4 +#define SHT_SUNW_dof 0x6ffffff4 +#define SHT_SUNW_cap 0x6ffffff5 +#define SHT_SUNW_SIGNATURE 0x6ffffff6 +#define SHT_GNU_HASH 0x6ffffff6 +#define SHT_GNU_LIBLIST 0x6ffffff7 +#define SHT_SUNW_ANNOTATE 0x6ffffff7 +#define SHT_SUNW_DEBUGSTR 0x6ffffff8 +#define SHT_SUNW_DEBUG 0x6ffffff9 +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_SUNW_verdef 0x6ffffffd +#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */ +#define SHT_SUNW_verneed 0x6ffffffe +#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */ +#define SHT_SUNW_versym 0x6fffffff +#define SHT_GNU_versym 0x6fffffff /* Symbol version table */ +#define SHT_HISUNW 0x6fffffff +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ +#define SHT_ARM_EXIDX 0x70000001 /* Exception index table. */ +#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking + pre-emption map. */ +#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility + attributes. */ +#define SHT_ARM_DEBUGOVERLAY 0x70000004 /* See DBGOVL for details. */ +#define SHT_ARM_OVERLAYSECTION 0x70000005 /* See DBGOVL for details. */ +#define SHT_MIPS_REGINFO 0x70000006 +#define SHT_MIPS_OPTIONS 0x7000000d +#define SHT_MIPS_DWARF 0x7000001e /* MIPS gcc uses MIPS_DWARF */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Flags for sh_flags. */ +#define SHF_WRITE 0x1 /* Section contains writable data. */ +#define SHF_ALLOC 0x2 /* Section occupies memory. */ +#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ +#define SHF_MERGE 0x10 /* Section may be merged. */ +#define SHF_STRINGS 0x20 /* Section contains strings. */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ +#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ +#define SHF_GROUP 0x200 /* Member of section group. */ +#define SHF_TLS 0x400 /* Section contains TLS data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* First OS-specific. */ +#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ +#define PT_GNU_EH_FRAME 0x6474e550 +#define PT_GNU_STACK 0x6474e551 +#define PT_GNU_RELRO 0x6474e552 +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ +#define PT_SUNWDTRACE 0x6ffffffc /* private */ +#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* Last OS-specific. */ +#define PT_LOPROC 0x70000000 /* First processor-specific type. */ +#define PT_ARM_EXIDX 0x70000001 /* .ARM.exidx segment */ +#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ +#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ + +/* Extended program header index. */ +#define PN_XNUM 0xffff + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +#define DT_NEEDED 1 /* String table offset of a needed shared + library. */ +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +#define DT_SONAME 14 /* String table offset of shared object + name. */ +#define DT_RPATH 15 /* String table offset of library path. [sup] */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ +#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ +#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +#define DT_TEXTREL 22 /* Indicates there may be relocations in + non-writable segments. [sup] */ +#define DT_JMPREL 23 /* Address of PLT relocations. */ +#define DT_BIND_NOW 24 /* [sup] */ +#define DT_INIT_ARRAY 25 /* Address of the array of pointers to + initialization functions */ +#define DT_FINI_ARRAY 26 /* Address of the array of pointers to + termination functions */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of + initialization functions. */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of + termination functions. */ +#define DT_RUNPATH 29 /* String table offset of a null-terminated + library search path string. */ +#define DT_FLAGS 30 /* Object specific flag values. */ +#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING + and less than DT_LOOS follow the rules for + the interpretation of the d_un union + as follows: even == 'd_ptr', odd == 'd_val' + or none */ +#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to + pre-initialization functions. */ +#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of + pre-initialization functions. */ +#define DT_MAXPOSTAGS 34 /* number of positive tags */ +#define DT_LOOS 0x6000000d /* First OS-specific */ +#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ +#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ +#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ +#define DT_SUNW_CAP 0x60000010 /* hardware/software */ +#define DT_HIOS 0x6ffff000 /* Last OS-specific */ + +/* + * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + * Dyn.d_un.d_val field of the Elf*_Dyn structure. + */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ +#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ +#define DT_MOVEENT 0x6ffffdfa /* move table entry size */ +#define DT_MOVESZ 0x6ffffdfb /* move table size */ +#define DT_FEATURE_1 0x6ffffdfc /* feature holder */ +#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ + /* the following DT_* entry. */ + /* See DF_P1_* definitions */ +#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */ +#define DT_VALRNGHI 0x6ffffdff + +/* + * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + * Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + * + * If any adjustment is made to the ELF object after it has been + * built, these entries will need to be adjusted. + */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table */ +#define DT_CONFIG 0x6ffffefa /* configuration information */ +#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ +#define DT_AUDIT 0x6ffffefc /* object auditing */ +#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */ +#define DT_MOVETAB 0x6ffffefe /* move table */ +#define DT_SYMINFO 0x6ffffeff /* syminfo table */ +#define DT_ADDRRNGHI 0x6ffffeff + +#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ +#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ +#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */ +#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */ +#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */ +#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ + +#define DT_LOPROC 0x70000000 /* First processor-specific type. */ +#define DT_DEPRECATED_SPARC_REGISTER 0x7000001 +#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ +#define DT_USED 0x7ffffffe /* ignored - same as needed */ +#define DT_FILTER 0x7fffffff /* shared library filter name */ +#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for DT_FLAGS */ +#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may + make reference to the $ORIGIN substitution + string */ +#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ +#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in + non-writable segments. */ +#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should + process all relocations for the object + containing this entry before transferring + control to the program. */ +#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or + executable contains code using a static + thread-local storage scheme. */ + +/* Values for DT_FLAGS_1 */ +#define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */ +#define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */ +#define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */ +#define DF_1_LOADFLTR 0x00000010 /* Immediate loading of filtees */ +#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ +#define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */ +#define DF_1_INTERPOSE 0x00000400 /* Interpose all objects but main */ +#define DF_1_NODEFLIB 0x00000800 /* Do not search default paths */ + +/* Values for n_type. Used in core files. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ +#define NT_THRMISC 7 /* Thread miscellaneous info. */ +#define NT_PROCSTAT_PROC 8 /* Procstat proc data. */ +#define NT_PROCSTAT_FILES 9 /* Procstat files data. */ +#define NT_PROCSTAT_VMMAP 10 /* Procstat vmmap data. */ +#define NT_PROCSTAT_GROUPS 11 /* Procstat groups data. */ +#define NT_PROCSTAT_UMASK 12 /* Procstat umask data. */ +#define NT_PROCSTAT_RLIMIT 13 /* Procstat rlimit data. */ +#define NT_PROCSTAT_OSREL 14 /* Procstat osreldate data. */ +#define NT_PROCSTAT_PSSTRINGS 15 /* Procstat ps_strings data. */ +#define NT_PROCSTAT_AUXV 16 /* Procstat auxv data. */ + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOOS 10 /* Reserved range for operating system */ +#define STB_HIOS 12 /* specific semantics. */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific semantics. */ + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_COMMON 5 /* Uninitialized common block. */ +#define STT_TLS 6 /* TLS object. */ +#define STT_NUM 7 +#define STT_LOOS 10 /* Reserved range for operating system */ +#define STT_GNU_IFUNC 10 +#define STT_HIOS 12 /* specific semantics. */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific semantics. */ + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ +#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ +#define STV_HIDDEN 0x2 /* Not visible. */ +#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ +#define STV_EXPORTED 0x4 +#define STV_SINGLETON 0x5 +#define STV_ELIMINATE 0x6 + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +/* Symbol versioning flags. */ +#define VER_DEF_CURRENT 1 +#define VER_DEF_IDX(x) VER_NDX(x) + +#define VER_FLG_BASE 0x01 +#define VER_FLG_WEAK 0x02 + +#define VER_NEED_CURRENT 1 +#define VER_NEED_WEAK (1u << 15) +#define VER_NEED_HIDDEN VER_NDX_HIDDEN +#define VER_NEED_IDX(x) VER_NDX(x) + +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 +#define VER_NDX_GIVEN 2 + +#define VER_NDX_HIDDEN (1u << 15) +#define VER_NDX(x) ((x) & ~(1u << 15)) + +#define CA_SUNW_NULL 0 +#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ +#define CA_SUNW_SF_1 2 /* first software capabilities entry */ + +/* + * Syminfo flag values + */ +#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */ + /* to object containing defn. */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ +#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */ + /* lazily-loaded */ +#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */ + /* object containing defn. */ +#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */ + /* directly bind to this symbol */ +#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ +#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ + +/* + * Syminfo.si_boundto values. + */ +#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ +#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ +#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ + +/* + * Syminfo version values. + */ +#define SYMINFO_NONE 0 /* Syminfo version */ +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* + * Relocation types. + * + * All machine architectures are defined here to allow tools on one to + * handle others. + */ + +#define R_386_NONE 0 /* No relocation. */ +#define R_386_32 1 /* Add symbol value. */ +#define R_386_PC32 2 /* Add PC-relative symbol value. */ +#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ +#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ +#define R_386_COPY 5 /* Copy data from shared object. */ +#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ +#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ +#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ +#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ +#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ +#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ +#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ +#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ +#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ +#define R_386_IRELATIVE 42 /* PLT entry resolved indirectly at runtime */ + +#define R_AARCH64_ABS64 257 +#define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address. */ +#define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address. */ +#define R_AARCH64_RELATIVE 1027 + +#define R_ARM_NONE 0 /* No relocation. */ +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +/* TLS relocations */ +#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ +#define R_ARM_COPY 20 /* Copy data from shared object. */ +#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ +#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ +#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ +#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ +#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ +#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ +#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + +/* Name Value Field Calculation */ +#define R_IA_64_NONE 0 /* None */ +#define R_IA_64_IMM14 0x21 /* immediate14 S + A */ +#define R_IA_64_IMM22 0x22 /* immediate22 S + A */ +#define R_IA_64_IMM64 0x23 /* immediate64 S + A */ +#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */ +#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */ +#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */ +#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ +#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ +#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ +#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */ +#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */ +#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ +#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ +#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ +#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ +#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ +#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ +#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ +#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ +#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ +#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ +#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ +#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */ +#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ +#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ +#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ +#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ +#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ +#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ +#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ +#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ +#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ +#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ +#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ +#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ +#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */ +#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */ +#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */ +#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ +#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */ +#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */ +#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */ +#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */ +#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */ +#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */ +#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */ +#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ +#define R_IA_64_SUB 0x85 /* immediate64 A - S */ +#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */ +#define R_IA_64_LDXMOV 0x87 /* immediate22 special */ +#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */ +#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */ +#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */ +#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */ +#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */ +#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */ +#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */ +#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */ +#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */ +#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */ +#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */ +#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */ +#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */ +#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ +#define R_MIPS_64 18 /* Direct 64 bit */ +#define R_MIPS_GOTHI16 21 /* GOT HI 16 bit */ +#define R_MIPS_GOTLO16 22 /* GOT LO 16 bit */ +#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */ +#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */ + +#define R_PPC_NONE 0 /* No relocation. */ +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* + * 64-bit relocations + */ +#define R_PPC64_ADDR64 38 +#define R_PPC64_ADDR16_HIGHER 39 +#define R_PPC64_ADDR16_HIGHERA 40 +#define R_PPC64_ADDR16_HIGHEST 41 +#define R_PPC64_ADDR16_HIGHESTA 42 +#define R_PPC64_UADDR64 43 +#define R_PPC64_REL64 44 +#define R_PPC64_PLT64 45 +#define R_PPC64_PLTREL64 46 +#define R_PPC64_TOC16 47 +#define R_PPC64_TOC16_LO 48 +#define R_PPC64_TOC16_HI 49 +#define R_PPC64_TOC16_HA 50 +#define R_PPC64_TOC 51 +#define R_PPC64_DTPMOD64 68 +#define R_PPC64_TPREL64 73 +#define R_PPC64_DTPREL64 78 + +/* + * TLS relocations + */ +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +/* + * The remaining relocs are from the Embedded ELF ABI, and are not in the + * SVR4 ELF ABI. + */ + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Add 64 bit symbol value. */ +#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ +#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ +#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ +#define R_X86_64_COPY 5 /* Copy data from shared object. */ +#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ +#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ +#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ +#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ +#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ +#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ +#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ +#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ +#define R_X86_64_IRELATIVE 37 + +#endif /* !_SYS_ELF_COMMON_H_ */ diff --git a/ta/remoteproc/include/elf_parser.h b/ta/remoteproc/include/elf_parser.h new file mode 100644 index 000000000..5950db971 --- /dev/null +++ b/ta/remoteproc/include/elf_parser.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + */ + +#ifndef ELF_PARSER +#define ELF_PARSER + +#include +#include +#include + +/** + * struct resource_table - firmware resource table header + * @ver: version number + * @num: number of resource entries + * @reserved: reserved (must be zero) + * @offset: array of offsets pointing at the various resource entries + * + * A resource table is essentially a list of system resources required + * by the remote processor. It may also include configuration entries. + * If needed, the remote processor firmware should contain this table + * as a dedicated ".resource_table" ELF section. + * + * This structure shall be consistent with the Linux kernel structure + * definition from include/linux/remoteproc.h. + */ +struct resource_table { + uint32_t ver; + uint32_t num; + uint32_t reserved[2]; + uint32_t offset[]; +} __packed; + +struct fw_elf32 { + uintptr_t e_entry; + uintptr_t e_phoff; + uintptr_t e_shoff; + uint32_t e_phnum; + uint32_t e_shnum; + uint32_t e_phentsize; + uint32_t e_shentsize; + + Elf32_Phdr *phdr; + Elf32_Shdr *shdr; +}; + +TEE_Result e32_parse_ehdr(uint8_t *fw, size_t size); +TEE_Result e32_parser_load_elf_image(uint8_t *fw, size_t fw_size, + TEE_Result (*load_seg)(uint8_t *src, + uint32_t size, + uint32_t da, + uint32_t mem_size, + void *priv), + void *priv_data); +int e32_parser_find_rsc_table(uint8_t *fw, size_t fw_size, Elf32_Addr *rsc_addr, + Elf32_Word *rsc_size); + +#endif /*ELF_PARSER*/ diff --git a/ta/remoteproc/include/ta_remoteproc.h b/ta/remoteproc/include/ta_remoteproc.h new file mode 100644 index 000000000..a51ba5f70 --- /dev/null +++ b/ta/remoteproc/include/ta_remoteproc.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + */ + +#ifndef TA_RPROC_FW_H +#define TA_RPROC_FW_H + +/* + * This UUID is generated with uuidgen + * the ITU-T UUID generator at http://www.itu.int/ITU-T/asn1/uuid.html + */ +#define TA_REMOTEPROC_UUID \ + { 0x80a4c275, 0x0a47, 0x4905, \ + { 0x82, 0x85, 0x14, 0x86, 0xa9, 0x77, 0x1a, 0x08} } + +/* The function IDs implemented in this TA */ + +/* + * Authentication of the firmware and load in the remote processor memory. + * + * [in] params[0].value.a: unique 32bit identifier of the firmware + * [in] params[1].memref: buffer containing the image of the firmware + */ +#define TA_RPROC_FW_CMD_LOAD_FW 1 + +/* + * Start the remote processor. + * + * [in] params[0].value.a: unique 32bit identifier of the firmware + */ +#define TA_RPROC_FW_CMD_START_FW 2 + +/* + * Stop the remote processor. + * + * [in] params[0].value.a: unique 32bit identifier of the firmware + */ +#define TA_RPROC_FW_CMD_STOP_FW 3 + +/* + * Return the physical address of the resource table, or 0 if not found + * No check is done to verify that the address returned is accessible by the + * non secure world. If the resource table is loaded in a protected memory, + * then accesses from non-secure world will likely fail. + * + * [in] params[0].value.a: unique 32bit identifier of the firmware + * [out] params[1].value.a: 32bit LSB resource table memory address + * [out] params[1].value.b: 32bit MSB resource table memory address + * [out] params[2].value.a: 32bit LSB resource table memory size + * [out] params[2].value.b: 32bit MSB resource table memory size + */ +#define TA_RPROC_FW_CMD_GET_RSC_TABLE 4 + +/* + * Get remote processor firmware core dump. If found, return either + * TEE_SUCCESS on successful completion or TEE_ERROR_SHORT_BUFFER if output + * buffer is too short to store the core dump. + * + * [in] params[0].value.a: unique 32bit identifier of the firmware + * [out] params[1].memref: Core dump, if found + */ +#define TA_RPROC_FW_CMD_GET_COREDUMP 5 + +#endif /*TA_RPROC_FW_H*/ diff --git a/ta/remoteproc/include/user_ta_header_defines.h b/ta/remoteproc/include/user_ta_header_defines.h new file mode 100644 index 000000000..c2ef1b21b --- /dev/null +++ b/ta/remoteproc/include/user_ta_header_defines.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + */ + +#ifndef USER_TA_HEADER_DEFINES_H +#define USER_TA_HEADER_DEFINES_H + +#include + +#define TA_UUID TA_REMOTEPROC_UUID + +#define TA_FLAGS (TA_FLAG_DEVICE_ENUM | \ + TA_FLAG_SINGLE_INSTANCE | \ + TA_FLAG_INSTANCE_KEEP_ALIVE) + +/* Provisioned stack size */ +#define TA_STACK_SIZE (4 * 1024) + +/* Provisioned heap size for TEE_Malloc() and friends */ +#define TA_DATA_SIZE (4 * 1024) + +/* The gpd.ta.version property */ +#define TA_VERSION "1.0" + +/* The gpd.ta.description property */ +#define TA_DESCRIPTION "remote processor firmware management" + +#endif /* USER_TA_HEADER_DEFINES_H */ diff --git a/ta/remoteproc/remoteproc_core.c b/ta/remoteproc/remoteproc_core.c new file mode 100644 index 000000000..341827b13 --- /dev/null +++ b/ta/remoteproc/remoteproc_core.c @@ -0,0 +1,781 @@ + // SPDX-License-Identifier: BSD-2-Clause + /* + * Copyright (C) 2020, STMicroelectronics - All Rights Reserved + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Firmware state */ +enum remoteproc_state { + REMOTEPROC_OFF, + REMOTEPROC_LOADED, + REMOTEPROC_STARTED, +}; + +#define RPROC_HDR_MAGIC 0x3543A468 /*random value */ +#define HEADER_VERSION 1 + +/* Supported signature algorithm */ +enum remoteproc_sign_type { + RPROC_RSASSA_PKCS1_v1_5_SHA256 = 1, + RPROC_ECDSA_SHA256 = 2, +}; + +/* + * struct remoteproc_segment - program header with hash structure + * @phdr: program header + * @hash: hash associated to the program segment. + */ +struct remoteproc_segment { + Elf32_Phdr phdr; + unsigned char hash[TEE_SHA256_HASH_SIZE]; +}; + +/* + * struct remoteproc_fw_hdr - firmware header + * @magic: Magic number, must be equal to RPROC_HDR_MAGIC + * @version: Version of the header (must be 1) + * @hdr_length: Total header byte length including chunks + * @sign_length: Signature chunk byte length + * @sign_offset: Signature chunk byte offset from header start + * @sign_type: Signature type + * @phhdr_length: Program header with hashes byte size, possibly 0 + * @phhdr_offset: Program header with hashes byte offset, 0 if not used + * @phhdr_type: Program header with hash type or 0 if not used + * @key_length: Authentication key info byte length, possibly 0 + * @key_offset: Authentication key info byte offset, 0 if not used + * @img_length: Firmware image chunk byte length + * @img_offset: Firmware image chunk byte offset + * @img_type: Firmware image type + */ +struct remoteproc_fw_hdr { + uint32_t magic; + uint32_t version; + uint32_t hdr_length; + uint32_t sign_length; + uint32_t sign_offset; + uint32_t sign_type; + uint32_t phhdr_length; + uint32_t phhdr_offset; + uint32_t phhdr_type; + uint32_t key_length; + uint32_t key_offset; + uint32_t img_length; + uint32_t img_offset; + uint32_t img_type; +}; + +/* + * struct remoteproc_sig_algo - signature algorithm information + * @sign_type: Header signature type + * @id: Signature algorigthm identifier TEE_ALG_* + * @hash_len: Signature hash length + */ +struct remoteproc_sig_algo { + enum remoteproc_sign_type sign_type; + uint32_t id; + size_t hash_len; +}; + +/* + * struct remoteproc_context - firmware context + * @fw_id: Unique Id of the firmware + * @hdr: Location of a secure copy of the firmware header + * @fw_img: Firmware image + * @fw_img_size: Byte size of the firmware image + * @rsc_pa: Physical address of the firmware resource table + * @rsc_size: Byte size of the firmware resource table + * @state: Remote-processor state + * @hw_fmt: Image format capabilities of the remoteproc PTA + * @hw_img_prot: Image protection capabilities of the remoteproc PTA + * @link: Linked list element + */ +struct remoteproc_context { + uint32_t fw_id; + struct remoteproc_fw_hdr *hdr; + uint8_t *fw_img; + size_t fw_img_size; + paddr_t rsc_pa; + size_t rsc_size; + enum remoteproc_state state; + uint32_t hw_fmt; + uint32_t hw_img_prot; + TAILQ_ENTRY(remoteproc_context) link; +}; + +TAILQ_HEAD(remoteproc_firmware_head, remoteproc_context); + +static struct remoteproc_firmware_head firmware_head = + TAILQ_HEAD_INITIALIZER(firmware_head); + +static const struct remoteproc_sig_algo rproc_ta_sign_algo[] = { + { + .sign_type = RPROC_RSASSA_PKCS1_v1_5_SHA256, + .id = TEE_ALG_RSASSA_PKCS1_V1_5_SHA256, + .hash_len = TEE_SHA256_HASH_SIZE, + }, + { + .sign_type = RPROC_ECDSA_SHA256, + .id = TEE_ALG_ECDSA_P256, + .hash_len = TEE_SHA256_HASH_SIZE, + }, +}; + +static size_t session_refcount; +static TEE_TASessionHandle pta_session; + +static void remoteproc_header_dump(struct remoteproc_fw_hdr __maybe_unused *hdr) +{ + DMSG("magic :\t%#"PRIx32, hdr->magic); + DMSG("version :\t%#"PRIx32, hdr->version); + DMSG("hdr_length :\t%#"PRIx32, hdr->hdr_length); + DMSG("sign_length :\t%#"PRIx32, hdr->sign_length); + DMSG("sign_offset :\t%#"PRIx32, hdr->sign_offset); + DMSG("sign_type :\t%#"PRIx32, hdr->sign_type); + DMSG("phhdr_length :\t%#"PRIx32, hdr->phhdr_length); + DMSG("phhdr_offset :\t%#"PRIx32, hdr->phhdr_offset); + DMSG("phhdr_type :\t%#"PRIx32, hdr->phhdr_type); + DMSG("key_length :\t%#"PRIx32, hdr->key_length); + DMSG("key_offset :\t%#"PRIx32, hdr->key_offset); + DMSG("img_length :\t%#"PRIx32, hdr->img_length); + DMSG("img_offset :\t%#"PRIx32, hdr->img_offset); + DMSG("img_type :\t%#"PRIx32, hdr->img_type); +} + +static struct remoteproc_context *remoteproc_find_firmware(uint32_t fw_id) +{ + struct remoteproc_context *ctx = NULL; + + TAILQ_FOREACH(ctx, &firmware_head, link) { + if (ctx->fw_id == fw_id) + return ctx; + } + + return NULL; +} + +static struct remoteproc_context *remoteproc_add_firmware(uint32_t fw_id) +{ + struct remoteproc_context *ctx = NULL; + + ctx = TEE_Malloc(sizeof(*ctx), TEE_MALLOC_FILL_ZERO); + if (!ctx) + return NULL; + + ctx->fw_id = fw_id; + + TAILQ_INSERT_TAIL(&firmware_head, ctx, link); + + return ctx; +} + +static const struct remoteproc_sig_algo *remoteproc_get_algo(uint32_t sign_type) +{ + unsigned int i = 0; + + for (i = 0; i < ARRAY_SIZE(rproc_ta_sign_algo); i++) + if (sign_type == rproc_ta_sign_algo[i].sign_type) + return &rproc_ta_sign_algo[i]; + + return NULL; +} + +static TEE_Result remoteproc_pta_verify(struct remoteproc_context *ctx, + const struct remoteproc_sig_algo *algo, + char *hash, size_t hash_len) +{ + TEE_Result res = TEE_ERROR_GENERIC; + struct remoteproc_fw_hdr *hdr = ctx->hdr; + struct rproc_pta_key_info *keyinfo = NULL; + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT); + TEE_Param params[TEE_NUM_PARAMS] = { }; + + keyinfo = TEE_Malloc(sizeof(*keyinfo) + hdr->key_length, 0); + if (!keyinfo) + return TEE_ERROR_OUT_OF_MEMORY; + + keyinfo->algo = algo->id; + keyinfo->info_size = hdr->key_length; + memcpy(keyinfo->info, (uint8_t *)hdr + hdr->key_offset, + hdr->key_length); + + params[0].value.a = ctx->fw_id; + params[1].memref.buffer = keyinfo; + params[1].memref.size = RPROC_PTA_GET_KEYINFO_SIZE(keyinfo); + params[2].memref.buffer = hash; + params[2].memref.size = hash_len; + params[3].memref.buffer = (uint8_t *)hdr + hdr->sign_offset; + params[3].memref.size = hdr->sign_length; + + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_REMOTEPROC_VERIFY_DIGEST, + param_types, params, NULL); + if (res != TEE_SUCCESS) + EMSG("Failed to verify signature, res = %#"PRIx32, res); + + TEE_Free(keyinfo); + + return res; +} + +static TEE_Result remoteproc_save_fw_header(struct remoteproc_context *ctx, + void *fw_orig, + uint32_t fw_orig_size) +{ + struct remoteproc_fw_hdr *hdr = fw_orig; + + remoteproc_header_dump(hdr); + + if (fw_orig_size <= sizeof(*hdr) || fw_orig_size <= hdr->hdr_length) + return TEE_ERROR_CORRUPT_OBJECT; + + ctx->hdr = TEE_Malloc(hdr->hdr_length, TEE_MALLOC_FILL_ZERO); + if (!ctx->hdr) + return TEE_ERROR_OUT_OF_MEMORY; + + memcpy(ctx->hdr, fw_orig, hdr->hdr_length); + + return TEE_SUCCESS; +} + +static TEE_Result remoteproc_verify_signature(struct remoteproc_context *ctx) +{ + TEE_OperationHandle op = TEE_HANDLE_NULL; + struct remoteproc_fw_hdr *hdr = ctx->hdr; + const struct remoteproc_sig_algo *algo = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + char *hash = NULL; + size_t hash_len = 0; + + algo = remoteproc_get_algo(hdr->sign_type); + if (!algo) { + EMSG("Unsupported signature type %d", hdr->sign_type); + return TEE_ERROR_NOT_SUPPORTED; + } + + /* Compute the header hash */ + hash_len = algo->hash_len; + hash = TEE_Malloc(hash_len, 0); + if (!hash) + return TEE_ERROR_OUT_OF_MEMORY; + + res = TEE_AllocateOperation(&op, TEE_ALG_SHA256, TEE_MODE_DIGEST, 0); + if (res != TEE_SUCCESS) + goto free_hash; + + res = TEE_DigestDoFinal(op, hdr, hdr->sign_offset, hash, &hash_len); + if (res != TEE_SUCCESS) + goto out; + + /* + * TODO: + * Provide alternative to verify the signature in the TA. This could + * be done for instance by getting the key object from secure storage. + */ + + /* By default ask the pta to verify the signature. */ + res = remoteproc_pta_verify(ctx, algo, hash, hash_len); + +out: + TEE_FreeOperation(op); +free_hash: + TEE_Free(hash); + + return res; +} + +static TEE_Result remoteproc_verify_header(struct remoteproc_context *ctx) +{ + struct remoteproc_fw_hdr *hdr = ctx->hdr; + uint32_t hdr_size = 0; + uint32_t chunk_size = 0; + uint32_t alignment = 0; + + if (hdr->magic != RPROC_HDR_MAGIC) + return TEE_ERROR_CORRUPT_OBJECT; + + if (hdr->version != HEADER_VERSION) + return TEE_ERROR_CORRUPT_OBJECT; + + /* + * The offsets are aligned to 64 bits format. The hdr_length takes into + * account these alignments while the length of each chunks are the + * effective length,excluding the alignment padding bytes. + */ + alignment = hdr->sign_length % sizeof(uint64_t) + + hdr->phhdr_length % sizeof(uint64_t) + + hdr->key_length % sizeof(uint64_t); + + if (ADD_OVERFLOW(sizeof(*hdr), hdr->sign_length, &hdr_size) || + ADD_OVERFLOW(hdr_size, hdr->phhdr_length, &hdr_size) || + ADD_OVERFLOW(hdr_size, hdr->key_length, &hdr_size) || + ADD_OVERFLOW(hdr_size, alignment, &hdr_size) || + hdr->hdr_length != hdr_size) + return TEE_ERROR_CORRUPT_OBJECT; + + if (ADD_OVERFLOW(hdr->sign_offset, hdr->sign_length, &chunk_size) || + chunk_size > hdr_size || + ADD_OVERFLOW(hdr->key_offset, hdr->key_length, &chunk_size) || + chunk_size > hdr_size || + ADD_OVERFLOW(hdr->phhdr_offset, hdr->phhdr_length, &chunk_size) || + chunk_size > hdr_size) + return TEE_ERROR_CORRUPT_OBJECT; + + if (hdr->phhdr_length % sizeof(struct remoteproc_segment)) + return TEE_ERROR_CORRUPT_OBJECT; + + return remoteproc_verify_signature(ctx); +} + +static TEE_Result get_rproc_pta_capabilities(struct remoteproc_context *ctx) +{ + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + TEE_Param params[TEE_NUM_PARAMS] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + + params[0].value.a = ctx->fw_id; + + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_REMOTEPROC_HW_CAPABILITIES, + param_types, params, NULL); + if (res) + return res; + + ctx->hw_fmt = params[1].value.a; + ctx->hw_img_prot = params[2].value.a; + + return TEE_SUCCESS; +} + +static TEE_Result remoteproc_verify_firmware(struct remoteproc_context *ctx, + uint8_t *fw_orig, + uint32_t fw_orig_size) +{ + struct remoteproc_fw_hdr *hdr = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + res = get_rproc_pta_capabilities(ctx); + if (res) + return res; + + /* Secure the firmware image depending on strategy */ + if (!(ctx->hw_img_prot & PTA_REMOTEPROC_FW_WITH_HASH_TABLE) || + ctx->hw_fmt != PTA_REMOTEPROC_ELF_FMT) { + /* + * Only hash table for ELF format support implemented + * in a first step. + */ + return TEE_ERROR_NOT_IMPLEMENTED; + } + + res = remoteproc_save_fw_header(ctx, fw_orig, fw_orig_size); + if (res) + return res; + + res = remoteproc_verify_header(ctx); + if (res) + goto free_hdr; + + /* Store location of the loadable binary in non-secure memory */ + hdr = ctx->hdr; + ctx->fw_img_size = hdr->img_length; + ctx->fw_img = fw_orig + hdr->img_offset; + + DMSG("Firmware image addr: %p size: %zu", ctx->fw_img, + ctx->fw_img_size); + +free_hdr: + TEE_Free(ctx->hdr); + + return res; +} + +static paddr_t remoteproc_da_to_pa(uint32_t da, int32_t size, void *priv) +{ + struct remoteproc_context *ctx = priv; + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT); + TEE_Param params[TEE_NUM_PARAMS] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + + params[0].value.a = ctx->fw_id; + params[1].value.a = da; + params[2].value.a = size; + + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_REMOTEPROC_FIRMWARE_DA_TO_PA, + param_types, params, NULL); + if (res != TEE_SUCCESS) { + EMSG("Failed to translate device address %#"PRIx32, da); + return 0; + } + + return (paddr_t)reg_pair_to_64(params[3].value.b, params[3].value.a); +} + +static TEE_Result remoteproc_parse_rsc_table(struct remoteproc_context *ctx) +{ + uint32_t da = 0; + TEE_Result res = TEE_ERROR_GENERIC; + + res = e32_parser_find_rsc_table(ctx->fw_img, ctx->fw_img_size, + &da, &ctx->rsc_size); + if (res == TEE_ERROR_NO_DATA) { + /* Firmware without resource table */ + ctx->rsc_size = 0; + ctx->rsc_pa = 0; + return TEE_SUCCESS; + } + if (res) + return res; + + if (da) { + DMSG("Resource table device address %#"PRIx32" size %zu", + da, ctx->rsc_size); + + ctx->rsc_pa = remoteproc_da_to_pa(da, ctx->rsc_size, ctx); + if (!ctx->rsc_pa) + return TEE_ERROR_ACCESS_DENIED; + } + + return TEE_SUCCESS; +} + +static TEE_Result get_segment_hash(struct remoteproc_context *ctx, uint8_t *src, + uint32_t size, uint32_t da, + uint32_t mem_size, unsigned char **hash) +{ + struct remoteproc_fw_hdr *hdr = ctx->hdr; + struct remoteproc_segment *peh = NULL; + unsigned int i = 0; + unsigned int nb_entry = hdr->phhdr_length / sizeof(*peh); + + peh = (void *)((uint8_t *)hdr + hdr->phhdr_offset); + + for (i = 0; i < nb_entry; peh++, i++) { + if (peh->phdr.p_paddr != da) + continue; + + /* + * Segment is read from a non secure memory. Crosscheck it using + * the hash table to verify that the segment has not been + * corrupted. + */ + if (peh->phdr.p_type != PT_LOAD) + return TEE_ERROR_CORRUPT_OBJECT; + + if (peh->phdr.p_filesz != size || peh->phdr.p_memsz != mem_size) + return TEE_ERROR_CORRUPT_OBJECT; + + if ((Elf32_Off)(src - ctx->fw_img) != peh->phdr.p_offset) + return TEE_ERROR_CORRUPT_OBJECT; + + *hash = peh->hash; + + return TEE_SUCCESS; + } + + return TEE_ERROR_NO_DATA; +} + +static TEE_Result remoteproc_load_segment(uint8_t *src, uint32_t size, + uint32_t da, uint32_t mem_size, + void *priv) +{ + struct remoteproc_context *ctx = priv; + uint32_t param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT); + TEE_Param params[TEE_NUM_PARAMS] = { }; + TEE_Result res = TEE_ERROR_GENERIC; + unsigned char *hash = NULL; + + /* + * Invoke platform remoteproc PTA to load the segment in remote + * processor memory which is not mapped in the TA space. + */ + + DMSG("Load segment %#"PRIx32" size %"PRIu32" (%"PRIu32")", da, size, + mem_size); + + res = get_segment_hash(ctx, src, size, da, mem_size, &hash); + if (res) + return res; + + params[0].value.a = ctx->fw_id; + params[1].memref.buffer = src; + params[1].memref.size = size; + params[2].value.a = da; + params[3].memref.buffer = hash; + params[3].memref.size = TEE_SHA256_HASH_SIZE; + + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_REMOTEPROC_LOAD_SEGMENT_SHA256, + param_types, params, NULL); + if (res != TEE_SUCCESS) { + EMSG("Fails to load segment, res = 0x%x", res); + return res; + } + + /* Fill the rest of the memory with 0 */ + if (size < mem_size) { + param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_INPUT); + params[1].value.a = da + size; + params[2].value.a = mem_size - size; + params[3].value.a = 0; + + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_REMOTEPROC_SET_MEMORY, + param_types, params, NULL); + if (res != TEE_SUCCESS) + EMSG("Fails to clear segment, res = 0x%x", res); + } + + return res; +} + +static TEE_Result remoteproc_load_elf(struct remoteproc_context *ctx) +{ + TEE_Result res = TEE_ERROR_GENERIC; + + res = e32_parse_ehdr(ctx->fw_img, ctx->fw_img_size); + if (res) { + EMSG("Failed to parse firmware, res = %#"PRIx32, res); + return res; + } + + return e32_parser_load_elf_image(ctx->fw_img, ctx->fw_img_size, + remoteproc_load_segment, ctx); +} + +static TEE_Result remoteproc_load_fw(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_MEMREF_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + struct remoteproc_context *ctx = NULL; + uint32_t fw_id = params[0].value.a; + TEE_Result res = TEE_ERROR_GENERIC; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ctx = remoteproc_find_firmware(fw_id); + if (!ctx) + ctx = remoteproc_add_firmware(fw_id); + if (!ctx) + return TEE_ERROR_OUT_OF_MEMORY; + + if (ctx->state != REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + if (!params[1].memref.buffer || !params[1].memref.size) + return TEE_ERROR_BAD_PARAMETERS; + + DMSG("Got base addr: %p size %zu", params[1].memref.buffer, + params[1].memref.size); + + res = remoteproc_verify_firmware(ctx, params[1].memref.buffer, + params[1].memref.size); + if (res) { + EMSG("Can't Authenticate the firmware, res = %#"PRIx32, res); + goto out; + } + + res = remoteproc_load_elf(ctx); + if (res) + goto out; + + /* Take opportunity to get the resource table address */ + res = remoteproc_parse_rsc_table(ctx); + if (res == TEE_SUCCESS) + ctx->state = REMOTEPROC_LOADED; + +out: + /* Clear reference to firmware image from shared memory */ + ctx->fw_img = NULL; + ctx->fw_img_size = 0; + + return res; +} + +static TEE_Result remoteproc_start_fw(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + struct remoteproc_context *ctx = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ctx = remoteproc_find_firmware(params[0].value.a); + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + switch (ctx->state) { + case REMOTEPROC_OFF: + res = TEE_ERROR_BAD_STATE; + break; + case REMOTEPROC_STARTED: + res = TEE_SUCCESS; + break; + case REMOTEPROC_LOADED: + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_REMOTEPROC_FIRMWARE_START, + pt, params, NULL); + if (res == TEE_SUCCESS) + ctx->state = REMOTEPROC_STARTED; + break; + default: + res = TEE_ERROR_BAD_STATE; + } + + return res; +} + +static TEE_Result remoteproc_stop_fw(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE, + TEE_PARAM_TYPE_NONE); + struct remoteproc_context *ctx = NULL; + TEE_Result res = TEE_ERROR_GENERIC; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ctx = remoteproc_find_firmware(params[0].value.a); + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + switch (ctx->state) { + case REMOTEPROC_LOADED: + res = TEE_ERROR_BAD_STATE; + break; + case REMOTEPROC_OFF: + res = TEE_SUCCESS; + break; + case REMOTEPROC_STARTED: + res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE, + PTA_REMOTEPROC_FIRMWARE_STOP, + pt, params, NULL); + if (res == TEE_SUCCESS) + ctx->state = REMOTEPROC_OFF; + break; + default: + res = TEE_ERROR_BAD_STATE; + } + + return res; +} + +static TEE_Result remoteproc_get_rsc_table(uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_VALUE_OUTPUT, + TEE_PARAM_TYPE_NONE); + struct remoteproc_context *ctx = NULL; + + if (pt != exp_pt) + return TEE_ERROR_BAD_PARAMETERS; + + ctx = remoteproc_find_firmware(params[0].value.a); + if (!ctx) + return TEE_ERROR_BAD_PARAMETERS; + + if (ctx->state == REMOTEPROC_OFF) + return TEE_ERROR_BAD_STATE; + + reg_pair_from_64((uint64_t)ctx->rsc_pa, + ¶ms[1].value.b, ¶ms[1].value.a); + reg_pair_from_64((uint64_t)ctx->rsc_size, + ¶ms[2].value.b, ¶ms[2].value.a); + + return TEE_SUCCESS; +} + +TEE_Result TA_CreateEntryPoint(void) +{ + return TEE_SUCCESS; +} + +void TA_DestroyEntryPoint(void) +{ +} + +TEE_Result TA_OpenSessionEntryPoint(uint32_t pt __unused, + TEE_Param params[TEE_NUM_PARAMS] __unused, + void **sess __unused) +{ + static const TEE_UUID uuid = PTA_REMOTEPROC_UUID; + TEE_Result res = TEE_ERROR_GENERIC; + + if (!session_refcount) { + res = TEE_OpenTASession(&uuid, TEE_TIMEOUT_INFINITE, 0, NULL, + &pta_session, NULL); + if (res) + return res; + } + + session_refcount++; + + return TEE_SUCCESS; +} + +void TA_CloseSessionEntryPoint(void *sess __unused) +{ + session_refcount--; + + if (!session_refcount) + TEE_CloseTASession(pta_session); +} + +TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd_id, + uint32_t pt, + TEE_Param params[TEE_NUM_PARAMS]) +{ + switch (cmd_id) { + case TA_RPROC_FW_CMD_LOAD_FW: + return remoteproc_load_fw(pt, params); + case TA_RPROC_FW_CMD_START_FW: + return remoteproc_start_fw(pt, params); + case TA_RPROC_FW_CMD_STOP_FW: + return remoteproc_stop_fw(pt, params); + case TA_RPROC_FW_CMD_GET_RSC_TABLE: + return remoteproc_get_rsc_table(pt, params); + case TA_RPROC_FW_CMD_GET_COREDUMP: + return TEE_ERROR_NOT_IMPLEMENTED; + default: + return TEE_ERROR_BAD_PARAMETERS; + } +} diff --git a/ta/remoteproc/sub.mk b/ta/remoteproc/sub.mk new file mode 100644 index 000000000..caca5901a --- /dev/null +++ b/ta/remoteproc/sub.mk @@ -0,0 +1,3 @@ +global-incdirs-y += include +srcs-y += remoteproc_core.c +srcs-y += elf_parser.c diff --git a/ta/remoteproc/user_ta.mk b/ta/remoteproc/user_ta.mk new file mode 100644 index 000000000..6db23f705 --- /dev/null +++ b/ta/remoteproc/user_ta.mk @@ -0,0 +1 @@ +user-ta-uuid := 80a4c275-0a47-4905-8285-1486a9771a08 \ No newline at end of file -- 2.17.1