meta-st-stm32mp/recipes-security/optee/optee-os/0002-3.9.0-stm32mp-r2.patch

4766 lines
159 KiB
Diff

From 755a68e59924e2437b9fb46c8ae1bfe690db1343 Mon Sep 17 00:00:00 2001
From: Christophe Priouzeau <christophe.priouzeau@st.com>
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 <drivers/stm32_etzpc.h>
#include <drivers/stm32_iwdg.h>
#include <drivers/stm32_uart.h>
-#include <drivers/stm32mp1_etzpc.h>
#include <drivers/stm32mp1_pmic.h>
#include <drivers/stm32mp1_rcc.h>
#include <drivers/stpmic1.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/soc/st,stm32-etzpc.h>
#include <io.h>
#include <kernel/dt.h>
#include <kernel/generic_boot.h>
@@ -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 <drivers/stm32mp1_rcc.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <inttypes.h>
-#include <kernel/panic.h>
#include <io.h>
#include <mm/core_memprot.h>
#include <platform_config.h>
@@ -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 <crypto/crypto.h>
+#include <drivers/stm32_etzpc.h>
+#include <drivers/stm32mp1_rcc.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/reset/stm32mp1-resets.h>
+#include <dt-bindings/soc/st,stm32-etzpc.h>
+#include <initcall.h>
+#include <kernel/pseudo_ta.h>
+#include <kernel/user_ta.h>
+#include <mm/core_memprot.h>
+#include <mm/core_mmu.h>
+#include <remoteproc_pta.h>
+#include <rproc_pub_key.h>
+#include <stm32_util.h>
+#include <string.h>
+
+#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, &params[3].value.b, &params[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(&params[2], &params[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 <types_ext.h>
+
+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 <drivers/stm32_etzpc.h>
#include <drivers/stm32_gpio.h>
-#include <drivers/stm32mp1_etzpc.h>
#include <drivers/stm32mp1_rcc.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <dt-bindings/reset/stm32mp1-resets.h>
+#include <dt-bindings/soc/st,stm32-etzpc.h>
#include <initcall.h>
#include <io.h>
#include <keep.h>
@@ -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 <kernel/pm.h>
#include <libfdt.h>
#include <mm/core_memprot.h>
+#include <stm32_util.h>
#include <util.h>
-/* 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 <util.h>
+
+/*
+ * 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:
# <name-of-ta>/<uuid>
# 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('<I', self._bufview_, self._offset,
+ ENUM_P_TYPE[seg.header.p_type])
+ self._offset += 4
+ struct.pack_into('<7I', self._bufview_, self._offset,
+ seg.header.p_offset, seg.header.p_vaddr,
+ seg.header.p_paddr, seg.header.p_filesz,
+ seg.header.p_memsz, seg.header.p_flags,
+ seg.header.p_align)
+ self._offset += 28
+ struct.pack_into('<32B', self._bufview_, self._offset, *seg.hash)
+ self._offset += 32
+ dump_buffer(self.buf, name='hash table', indent="\t")
+ return self.buf
+
+
+class ImageHeader(object):
+ '''
+ Image header
+ '''
+
+ magic = 'HELF' # SHDR_MAGIC
+ version = 1
+ sign_type = 1 # SHA256
+ img_type = 1 # ELF
+
+ MAGIC_OFFSET = 0
+ VERSION_OFFSET = 4
+ LENGTH_OFFSET = 8
+ SIGNATURE_LEN_OFFSET = 12
+ SIGNATURE_OFFSET_OFFSET = 16
+ SIGNATURE_TYPE_OFFSET = 20
+ HASH_LEN_OFFSET = 24
+ HASH_OFFSET_OFFSET = 28
+ HASH_TYPE_OFFSET = 32
+ PUBLIC_INFO_LEN_OFFSET = 36
+ PUBLIC_INFO_OFFSET_OFFSET = 40
+ IMG_LEN_OFFSET = 44
+ IMG_OFFSET_OFFSET = 48
+ IMG_TYPE_OFFSET = 52
+
+ def __init__(self):
+ self.size = 56
+
+ self.magic = 0x3543A468
+ self.version = 1
+ self.length = 0
+ self.sign_length = 0
+ self.sign_offset = 0
+ self.sign_type = 0
+ self.hash_length = 0
+ self.hash_offset = 0
+ self.hash_type = 0
+ self.key_length = 0
+ self.key_offset = 0
+ self.img_length = 0
+ self.img_offset = 0
+ self.img_type = 0
+
+ self.shdr = struct.pack('<IIIIIIIIIIIIII',
+ self.magic, self.version, self.length,
+ self.sign_length, self.sign_offset,
+ self.sign_type, self.hash_length,
+ self.hash_offset, self.hash_type,
+ self.key_length, self.key_offset,
+ self.img_length, self.img_offset,
+ self.img_type)
+
+ def dump(self):
+ logging.info("\tMAGIC\t\t= %08X" % (self.magic))
+ logging.info("\tHEADER_VERSION\t= %08X" % (self.version))
+ logging.info("\tHEADER_LENGTH\t= %08X" % (self.length))
+ logging.info("\tSIGN_LENGTH\t= %08X" % (self.sign_length))
+ logging.info("\tSIGN_OFFSET\t= %08X" % (self.sign_offset))
+ logging.info("\tSIGN_TYPE\t= %08X" % (self.sign_type))
+ logging.info("\tHASH_LENGTH\t= %08X" % (self.hash_length))
+ logging.info("\tHASH_OFFSET\t= %08X" % (self.hash_offset))
+ logging.info("\tHASH_TYPE\t= %08X" % (self.hash_type))
+ logging.info("\tPKEY_LENGTH\t= %08X" % (self.key_length))
+ logging.info("\tPKEY_OFFSET\t= %08X" % (self.key_offset))
+ logging.info("\tIMAGE_LENGTH\t= %08X" % (self.img_length))
+ logging.info("\tIMAGE_OFFSET\t= %08X" % (self.img_offset))
+ logging.info("\tIMAGE_TYPE\t= %08X" % (self.img_type))
+
+ def get_packed(self):
+ return struct.pack('<IIIIIIIIIIIIII',
+ self.magic, self.version, self.length,
+ self.sign_length, self.sign_offset, self.sign_type,
+ self.hash_length, self.hash_offset, self.hash_type,
+ self.key_length, self.key_offset, self.img_length,
+ self.img_offset, self.img_type)
+
+
+def get_args(logger):
+ from argparse import ArgumentParser, RawDescriptionHelpFormatter
+ import textwrap
+ command_base = ['sign']
+ command_choices = command_base
+
+ parser = ArgumentParser(
+ description='Sign a remote processor firmware loadable by OP-TEE.',
+ usage='\n %(prog)s command [ arguments ]\n\n'
+
+ ' command:\n' +
+ ' sign Generate signed loadable binary \n' +
+ ' Takes arguments --in, --out --key\n' +
+ ' %(prog)s --help show available commands and arguments\n\n',
+ formatter_class=RawDescriptionHelpFormatter,
+ )
+ parser.add_argument(
+ 'command', choices=command_choices, nargs='?',
+ default='sign',
+ help='Command, one of [' + ', '.join(command_base) + ']')
+ parser.add_argument('--key', required=True,
+ help='Name of signing key file',
+ dest='keyf')
+ parser.add_argument('--key_info', required=False,
+ help='Name file containing extra key information',
+ dest='key_infof')
+ parser.add_argument('--key_type', required=False,
+ help='Type of signing key: should be RSA or ECC',
+ default='RSA',
+ dest='key_type')
+ parser.add_argument(
+ '--in', required=True, dest='inf',
+ help='Name of firmware input file')
+ parser.add_argument(
+ '--out', required=False, dest='outf',
+ help='Name of the signed firmware output file,' +
+ ' default <in base name>.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 <assert.h>
+#include <elf_parser.h>
+#include <string.h>
+#include <trace.h>
+#include <types_ext.h>
+#include <util.h>
+
+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 <elf_common.h>
+#include <stdint.h>
+
+/*
+ * 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 <stdint.h>
+
+/*
+ * 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 <elf32.h>
+#include <stdint.h>
+#include <tee_api_types.h>
+
+/**
+ * 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 <ta_remoteproc.h>
+
+#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 <elf_parser.h>
+#include <remoteproc_pta.h>
+#include <string.h>
+#include <sys/queue.h>
+#include <ta_remoteproc.h>
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+#include <types_ext.h>
+#include <utee_defines.h>
+
+/* 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,
+ &params[1].value.b, &params[1].value.a);
+ reg_pair_from_64((uint64_t)ctx->rsc_size,
+ &params[2].value.b, &params[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