Import 80d60e7 from yoctoproject.org meta-arm

To support ARMv8 SoCs.

meta-arm has several patch files.  Since they are maintained by the
upstream meta-arm community, add meta-arm to the ignore list in
run-repotest.

Change-Id: Ia87a2e947bbabd347d256eccc47a343e1c885479
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0001-tools-cmake-common-applying-lowercase-project-conven.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0001-tools-cmake-common-applying-lowercase-project-conven.patch
new file mode 100644
index 0000000..83c7b54
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0001-tools-cmake-common-applying-lowercase-project-conven.patch
@@ -0,0 +1,33 @@
+From 73c27b917e15eb04f39eedac9b79e5011e8a754f Mon Sep 17 00:00:00 2001
+From: Vishnu Banavath <vishnu.banavath@arm.com>
+Date: Sat, 13 Nov 2021 07:47:44 +0000
+Subject: [PATCH] tools/cmake/common: applying lowercase project convention
+
+Lowercase convention should only apply on the paths inside TS
+source-code.
+Host build paths should not be lowercased. Otherwise, builds
+with uppercase paths will break.
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+
+
+---
+ tools/cmake/common/AddPlatform.cmake | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/cmake/common/AddPlatform.cmake b/tools/cmake/common/AddPlatform.cmake
+index ae34c6e4..31bcd8ca 100644
+--- a/tools/cmake/common/AddPlatform.cmake
++++ b/tools/cmake/common/AddPlatform.cmake
+@@ -37,8 +37,8 @@ function(add_platform)
+ 	set(TGT ${MY_PARAMS_TARGET} CACHE STRING "")
+ 
+ 	# Ensure file path conforms to lowercase project convention
+-	string(TOLOWER "${TS_PLATFORM_ROOT}/${TS_PLATFORM}/platform.cmake" _platdef)
+-	include(${_platdef})
++	string(TOLOWER "${TS_PLATFORM}/platform.cmake" _platdef)
++	include(${TS_PLATFORM_ROOT}/${_platdef})
+ 	set(CMAKE_CONFIGURE_DEPENDS ${_platdef})
+ 
+ 	unset(TGT CACHE)
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0002-fix-EARLY_TA_PATHS-env-variable.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0002-fix-EARLY_TA_PATHS-env-variable.patch
new file mode 100644
index 0000000..f56b455
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0002-fix-EARLY_TA_PATHS-env-variable.patch
@@ -0,0 +1,32 @@
+From 146f4dfa73aa316d611188f63e3530cffe9200af Mon Sep 17 00:00:00 2001
+From: Vishnu Banavath <vishnu.banavath@arm.com>
+Date: Sat, 13 Nov 2021 07:51:53 +0000
+Subject: [PATCH] fix EARLY_TA_PATHS env variable
+
+Yocto cleans up environment varaibles at build time.
+EARLY_TA_PATHS should be set a separate rule for securepartitions
+to be included into optee-os image
+
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+
+
+---
+ environments/opteesp/sp.mk.in | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/environments/opteesp/sp.mk.in b/environments/opteesp/sp.mk.in
+index c44ad59e..d67e2dca 100644
+--- a/environments/opteesp/sp.mk.in
++++ b/environments/opteesp/sp.mk.in
+@@ -14,7 +14,8 @@ ifeq (,${@EXPORT_SP_UUID@-included})
+ endif
+ 
+ ifeq (embedded,${SP_PACKAGING_METHOD})
+-OPTEE_OS_COMMON_EXTRA_FLAGS+=EARLY_TA_PATHS+=${TS_INSTALL_PREFIX}/opteesp/bin/@EXPORT_SP_UUID@.stripped.elf
++EARLY_TA_PATHS+=${TS_INSTALL_PREFIX}/bin/@EXPORT_SP_UUID@.stripped.elf
++OPTEE_OS_COMMON_EXTRA_FLAGS+=${EARLY_TA_PATHS}
+ TS_SP_DTSI_LIST+="\\n\#include \"${TS_INSTALL_PREFIX}/opteesp/manifest/@EXPORT_SP_UUID@.dtsi\""
+ else ifeq (fip,${SP_PACKAGING_METHOD})
+ TS_SP_JSON_LIST+=${TS_INSTALL_PREFIX}/opteesp/json/@EXPORT_SP_NAME@.json
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0003-corstone1000-port-crypto-config.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0003-corstone1000-port-crypto-config.patch
new file mode 100644
index 0000000..3b26b77
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0003-corstone1000-port-crypto-config.patch
@@ -0,0 +1,234 @@
+From f86f5b42d853d2a65f6753362361bbb95aac1800 Mon Sep 17 00:00:00 2001
+From: Satish Kumar <satish.kumar01@arm.com>
+Date: Sat, 11 Dec 2021 11:06:57 +0000
+Subject: [PATCH] corstone1000: port crypto config
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
+
+%% original patch: 0003-corstone1000-port-crypto-config.patch
+---
+ .../nspe/pal_crypto_config.h                  | 83 +++++++++++++++----
+ 1 file changed, 66 insertions(+), 17 deletions(-)
+
+diff --git a/api-tests/platform/targets/tgt_dev_apis_linux/nspe/pal_crypto_config.h b/api-tests/platform/targets/tgt_dev_apis_linux/nspe/pal_crypto_config.h
+index 844cd2e..c936bdd 100755
+--- a/api-tests/platform/targets/tgt_dev_apis_linux/nspe/pal_crypto_config.h
++++ b/api-tests/platform/targets/tgt_dev_apis_linux/nspe/pal_crypto_config.h
+@@ -1,5 +1,5 @@
+ /** @file
+- * Copyright (c) 2021, Arm Limited or its affiliates. All rights reserved.
++ * Copyright (c) 2019-2020, Arm Limited or its affiliates. All rights reserved.
+  * SPDX-License-Identifier : Apache-2.0
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+@@ -34,10 +34,14 @@
+  *
+  * Comment macros to disable the types
+  */
++#ifndef TF_M_PROFILE_SMALL
++#ifndef TF_M_PROFILE_MEDIUM
+ #define ARCH_TEST_RSA
+ #define ARCH_TEST_RSA_1024
+ #define ARCH_TEST_RSA_2048
+ #define ARCH_TEST_RSA_3072
++#endif
++#endif
+ 
+ /**
+  * \def  ARCH_TEST_ECC
+@@ -50,11 +54,17 @@
+  * Requires: ARCH_TEST_ECC
+  * Comment macros to disable the curve
+  */
++#ifndef TF_M_PROFILE_SMALL
+ #define ARCH_TEST_ECC
+ #define ARCH_TEST_ECC_CURVE_SECP192R1
++#ifndef TF_M_PROFILE_MEDIUM
+ #define ARCH_TEST_ECC_CURVE_SECP224R1
++#endif
+ #define ARCH_TEST_ECC_CURVE_SECP256R1
++#ifndef TF_M_PROFILE_MEDIUM
+ #define ARCH_TEST_ECC_CURVE_SECP384R1
++#endif
++#endif
+ 
+ /**
+  * \def ARCH_TEST_AES
+@@ -78,10 +88,10 @@
+  *
+  * Comment macros to disable the types
+  */
+-#define ARCH_TEST_DES
+-#define ARCH_TEST_DES_1KEY
+-#define ARCH_TEST_DES_2KEY
+-#define ARCH_TEST_DES_3KEY
++//#define ARCH_TEST_DES
++//#define ARCH_TEST_DES_1KEY
++//#define ARCH_TEST_DES_2KEY
++//#define ARCH_TEST_DES_3KEY
+ 
+ /**
+  * \def  ARCH_TEST_RAW
+@@ -104,7 +114,7 @@
+  *
+  * Enable the ARC4 key type.
+  */
+-#define ARCH_TEST_ARC4
++//#define ARCH_TEST_ARC4
+ 
+ /**
+  * \def ARCH_TEST_CIPHER_MODE_CTR
+@@ -113,7 +123,11 @@
+  *
+  * Requires: ARCH_TEST_CIPHER
+  */
++#ifndef TF_M_PROFILE_SMALL
++#ifndef TF_M_PROFILE_MEDIUM
+ #define ARCH_TEST_CIPHER_MODE_CTR
++#endif
++#endif
+ 
+ /**
+  * \def ARCH_TEST_CIPHER_MODE_CFB
+@@ -138,7 +152,11 @@
+  *
+  * Requires: ARCH_TEST_CIPHER, ARCH_TEST_AES, ARCH_TEST_CIPHER_MODE_CTR
+  */
++#ifndef TF_M_PROFILE_SMALL
++#ifndef TF_M_PROFILE_MEDIUM
+ #define ARCH_TEST_CTR_AES
++#endif
++#endif
+ 
+ /**
+  * \def ARCH_TEST_CBC_AES
+@@ -157,7 +175,11 @@
+  *
+  * Comment macros to disable the types
+  */
++#ifndef TF_M_PROFILE_SMALL
++#ifndef TF_M_PROFILE_MEDIUM
+ #define ARCH_TEST_CBC_NO_PADDING
++#endif
++#endif
+ 
+ /**
+  * \def ARCH_TEST_CFB_AES
+@@ -177,11 +199,15 @@
+  *
+  * Comment macros to disable the types
+  */
++#ifndef TF_M_PROFILE_SMALL
++#ifndef TF_M_PROFILE_MEDIUM
+ #define ARCH_TEST_PKCS1V15
+ #define ARCH_TEST_RSA_PKCS1V15_SIGN
+ #define ARCH_TEST_RSA_PKCS1V15_SIGN_RAW
+ #define ARCH_TEST_RSA_PKCS1V15_CRYPT
+ #define ARCH_TEST_RSA_OAEP
++#endif
++#endif
+ 
+ /**
+  * \def ARCH_TEST_CBC_PKCS7
+@@ -190,7 +216,11 @@
+  *
+  * Comment macros to disable the types
+  */
++#ifndef TF_M_PROFILE_SMALL
++#ifndef TF_M_PROFILE_MEDIUM
+ #define ARCH_TEST_CBC_PKCS7
++#endif
++#endif
+ 
+ /**
+  * \def ARCH_TEST_ASYMMETRIC_ENCRYPTION
+@@ -227,21 +257,27 @@
+  *
+  * Comment macros to disable the types
+  */
+-// #define ARCH_TEST_MD2
+-// #define ARCH_TEST_MD4
+-#define ARCH_TEST_MD5
+-#define ARCH_TEST_RIPEMD160
+-#define ARCH_TEST_SHA1
++//#define ARCH_TEST_MD2
++//#define ARCH_TEST_MD4
++//#define ARCH_TEST_MD5
++//#define ARCH_TEST_RIPEMD160
++//#define ARCH_TEST_SHA1
++#ifndef TF_M_PROFILE_SMALL
+ #define ARCH_TEST_SHA224
++#endif
+ #define ARCH_TEST_SHA256
++#ifndef TF_M_PROFILE_SMALL
++#ifndef TF_M_PROFILE_MEDIUM
+ #define ARCH_TEST_SHA384
+ #define ARCH_TEST_SHA512
+-// #define ARCH_TEST_SHA512_224
+-// #define ARCH_TEST_SHA512_256
+-// #define ARCH_TEST_SHA3_224
+-// #define ARCH_TEST_SHA3_256
+-// #define ARCH_TEST_SHA3_384
+-// #define ARCH_TEST_SHA3_512
++#endif
++#endif
++//#define ARCH_TEST_SHA512_224
++//#define ARCH_TEST_SHA512_256
++//#define ARCH_TEST_SHA3_224
++//#define ARCH_TEST_SHA3_256
++//#define ARCH_TEST_SHA3_384
++//#define ARCH_TEST_SHA3_512
+ 
+ /**
+  * \def ARCH_TEST_HKDF
+@@ -261,7 +297,12 @@
+  *
+  * Comment macros to disable the types
+  */
++#ifndef TF_M_PROFILE_SMALL
++#ifndef TF_M_PROFILE_MEDIUM
+ #define ARCH_TEST_CMAC
++#endif
++#endif
++//#define ARCH_TEST_GMAC
+ #define ARCH_TEST_HMAC
+ 
+ /**
+@@ -281,7 +322,11 @@
+  * Requires: ARCH_TEST_AES
+  *
+  */
++#ifndef TF_M_PROFILE_SMALL
++#ifndef TF_M_PROFILE_MEDIUM
+ #define ARCH_TEST_GCM
++#endif
++#endif
+ 
+ /**
+  * \def ARCH_TEST_TRUNCATED_MAC
+@@ -300,7 +345,9 @@
+  *
+  * Requires: ARCH_TEST_ECC
+  */
++#ifndef TF_M_PROFILE_SMALL
+ #define ARCH_TEST_ECDH
++#endif
+ 
+ /**
+  * \def ARCH_TEST_ECDSA
+@@ -308,7 +355,9 @@
+  * Enable the elliptic curve DSA library.
+  * Requires: ARCH_TEST_ECC
+  */
++#ifndef TF_M_PROFILE_SMALL
+ #define ARCH_TEST_ECDSA
++#endif
+ 
+ /**
+  * \def ARCH_TEST_DETERMINISTIC_ECDSA
+-- 
+2.25.1
+
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0003-se-proxy-dts-add-se-proxy-as-child-node.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0003-se-proxy-dts-add-se-proxy-as-child-node.patch
new file mode 100644
index 0000000..bb4fc82
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0003-se-proxy-dts-add-se-proxy-as-child-node.patch
@@ -0,0 +1,46 @@
+From 0ec1b3d20d612325b9c55baa2539d080eb6a72a8 Mon Sep 17 00:00:00 2001
+From: Vishnu Banavath <vishnu.banavath@arm.com>
+Date: Sat, 13 Nov 2021 08:34:42 +0000
+Subject: [PATCH] se-proxy:dts: add se-proxy as child node
+
+se-proxy sp string should be added for se-proxy node to be
+read properly.
+
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com>
+
+
+---
+ .../se-proxy/opteesp/default_se-proxy.dts.in  | 20 ++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+diff --git a/deployments/se-proxy/opteesp/default_se-proxy.dts.in b/deployments/se-proxy/opteesp/default_se-proxy.dts.in
+index 961071ad..9f5cf712 100644
+--- a/deployments/se-proxy/opteesp/default_se-proxy.dts.in
++++ b/deployments/se-proxy/opteesp/default_se-proxy.dts.in
+@@ -7,13 +7,15 @@
+ @DTS_TAG@
+ 
+ @DTS_NODE@ {
+-	compatible = "arm,ffa-manifest-1.0";
+-	ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
+-	uuid = <@EXPORT_SP_UUID_DT@>;
+-	description = "SE Proxy";
+-	execution-ctx-count = <1>;
+-	exception-level = <1>; /* S-EL0 */
+-	execution-state = <0>; /* AArch64 */
+-	xlat-granule = <0>; /* 4KiB */
+-	messaging-method = <0>; /* Direct messaging only */
++	se-proxy {
++		compatible = "arm,ffa-manifest-1.0";
++		ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
++		uuid = <@EXPORT_SP_UUID_DT@>;
++		description = "SE Proxy";
++		execution-ctx-count = <1>;
++		exception-level = <1>; /* S-EL0 */
++		execution-state = <0>; /* AArch64 */
++		xlat-granule = <0>; /* 4KiB */
++		messaging-method = <0>; /* Direct messaging only */
++	};
+ };
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0004-Update-mm-comm-buffer-region-in-dts-file.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0004-Update-mm-comm-buffer-region-in-dts-file.patch
new file mode 100644
index 0000000..9ceb176
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0004-Update-mm-comm-buffer-region-in-dts-file.patch
@@ -0,0 +1,59 @@
+From 97b4f3cd0216c30c39f6ece4f68d8faf3901fded Mon Sep 17 00:00:00 2001
+From: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+Date: Wed, 17 Nov 2021 15:31:09 +0000
+Subject: [PATCH] Update mm-comm-buffer region in dts file
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+
+
+---
+ .../opteesp/default_smm-gateway.dts.in        | 35 ++++++++++---------
+ 1 file changed, 18 insertions(+), 17 deletions(-)
+
+diff --git a/deployments/smm-gateway/opteesp/default_smm-gateway.dts.in b/deployments/smm-gateway/opteesp/default_smm-gateway.dts.in
+index 0ad7878b..183c38a7 100644
+--- a/deployments/smm-gateway/opteesp/default_smm-gateway.dts.in
++++ b/deployments/smm-gateway/opteesp/default_smm-gateway.dts.in
+@@ -7,23 +7,24 @@
+ @DTS_TAG@
+ 
+ @DTS_NODE@ {
+-	compatible = "arm,ffa-manifest-1.0";
+-	ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
+-	uuid = <@EXPORT_SP_UUID_DT@>;
+-	description = "SMM Gateway";
+-	execution-ctx-count = <1>;
+-	exception-level = <1>; /* S-EL0 */
+-	execution-state = <0>; /* AArch64 */
+-	xlat-granule = <0>; /* 4KiB */
+-	messaging-method = <0>; /* Direct messaging only */
+-
+-	memory-regions {
+-		compatible = "arm,ffa-manifest-memory-regions";
+-
+-		mm-comm-buffer {
+-			base-address = <@MM_COMM_BUFFER_ADDRESS@>;
+-			pages-count = <@MM_COMM_BUFFER_PAGE_COUNT@>;
+-			attributes = <0xb>;  /* ns access-read-write */
++	smm-gateway{
++		compatible = "arm,ffa-manifest-1.0";
++		ffa-version = <0x00010000>; /* 31:16 - Major, 15:0 - Minor */
++		uuid = <@EXPORT_SP_UUID_DT@>;
++		description = "SMM Gateway";
++		execution-ctx-count = <1>;
++		exception-level = <1>; /* S-EL0 */
++		execution-state = <0>; /* AArch64 */
++		xlat-granule = <0>; /* 4KiB */
++		messaging-method = <0>; /* Direct messaging only */
++		device-regions {
++          compatible = "arm,ffa-manifest-device-regions";
++          mm-comm-buffer {
++              /* Armv8 A Foundation Platform values */
++              base-address = <0x00000000 0x02000000>;
++              pages-count = <1>;
++              attributes = <0x3>; /* read-write */
++              };
+ 		};
+ 	};
+ };
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0005-Configure-NV-storage-macro.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0005-Configure-NV-storage-macro.patch
new file mode 100644
index 0000000..8d2d62b
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0005-Configure-NV-storage-macro.patch
@@ -0,0 +1,26 @@
+From a11b23dd5f0c4124a5c6c2fcab0ea623bc76f4ba Mon Sep 17 00:00:00 2001
+From: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+Date: Wed, 17 Nov 2021 15:32:04 +0000
+Subject: [PATCH] Configure NV storage macro
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+
+
+---
+ deployments/smm-gateway/smm_gateway.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/deployments/smm-gateway/smm_gateway.c b/deployments/smm-gateway/smm_gateway.c
+index 4884a040..7828b3af 100644
+--- a/deployments/smm-gateway/smm_gateway.c
++++ b/deployments/smm-gateway/smm_gateway.c
+@@ -13,6 +13,8 @@
+ 
+ /* Build-time default configuration */
+ 
++#define SMM_GATEWAY_NV_STORE_SN "sn:ffa:46bb39d1-b4d9-45b5-88ff-040027dab249:1"
++
+ /* Default to using the Protected Storage SP */
+ #ifndef SMM_GATEWAY_NV_STORE_SN
+ #define SMM_GATEWAY_NV_STORE_SN		"sn:ffa:751bf801-3dde-4768-a514-0f10aeed1790:0"
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0006-Use-device-region.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0006-Use-device-region.patch
new file mode 100644
index 0000000..eba1338
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0006-Use-device-region.patch
@@ -0,0 +1,53 @@
+From ae22f5077d35e6acf3feb8a84a8ef7f599261b00 Mon Sep 17 00:00:00 2001
+From: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+Date: Wed, 17 Nov 2021 15:32:46 +0000
+Subject: [PATCH] Use device region
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+
+
+---
+ deployments/smm-gateway/opteesp/smm_gateway_sp.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/deployments/smm-gateway/opteesp/smm_gateway_sp.c b/deployments/smm-gateway/opteesp/smm_gateway_sp.c
+index 6f138850..0bc09023 100644
+--- a/deployments/smm-gateway/opteesp/smm_gateway_sp.c
++++ b/deployments/smm-gateway/opteesp/smm_gateway_sp.c
+@@ -10,7 +10,7 @@
+ #include <config/loader/sp/sp_config_loader.h>
+ #include "components/rpc/mm_communicate/endpoint/sp/mm_communicate_call_ep.h"
+ #include "components/service/smm_variable/frontend/mm_communicate/smm_variable_mm_service.h"
+-#include "platform/interface/memory_region.h"
++#include "platform/interface/device_region.h"
+ #include <ffa_api.h>
+ #include <sp_api.h>
+ #include <sp_messaging.h>
+@@ -25,7 +25,7 @@ static int sp_init(uint16_t *own_sp_id);
+ 
+ void __noreturn sp_main(struct ffa_init_info *init_info)
+ {
+-	struct memory_region mm_comm_buffer_region = { 0 };
++	struct device_region mm_comm_buffer_region = { 0 };
+ 	struct rpc_interface *gateway_iface = NULL;
+ 	struct smm_variable_mm_service smm_var_service = { 0 };
+ 	struct mm_service_interface *smm_var_service_interface = NULL;
+@@ -42,7 +42,7 @@ void __noreturn sp_main(struct ffa_init_info *init_info)
+ 	config_ramstore_init();
+ 	sp_config_load(init_info);
+ 
+-	if (!config_store_query(CONFIG_CLASSIFIER_MEMORY_REGION, CONFIG_NAME_MM_COMM_BUFFER_REGION,
++	if (!config_store_query(CONFIG_CLASSIFIER_DEVICE_REGION, CONFIG_NAME_MM_COMM_BUFFER_REGION,
+ 				0, &mm_comm_buffer_region, sizeof(mm_comm_buffer_region))) {
+ 		EMSG(CONFIG_NAME_MM_COMM_BUFFER_REGION " is not set in SP configuration");
+ 		goto fatal_error;
+@@ -57,7 +57,7 @@ void __noreturn sp_main(struct ffa_init_info *init_info)
+ 	/* Initialize MM communication layer */
+ 	if (!mm_communicate_call_ep_init(&mm_communicate_call_ep,
+ 					 (void *)mm_comm_buffer_region.base_addr,
+-					 mm_comm_buffer_region.region_size))
++					 mm_comm_buffer_region.io_region_size))
+ 		goto fatal_error;
+ 
+ 	/* Attach SMM variable service to MM communication layer */
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0007-Add-openamp-to-SE-proxy-deployment.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0007-Add-openamp-to-SE-proxy-deployment.patch
new file mode 100644
index 0000000..eb51ef7
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0007-Add-openamp-to-SE-proxy-deployment.patch
@@ -0,0 +1,259 @@
+From 90712f624c7b676e5b9a2d95cbe97d2b63fddcc9 Mon Sep 17 00:00:00 2001
+From: Vishnu Banavath <vishnu.banavath@arm.com>
+Date: Fri, 3 Dec 2021 16:36:51 +0000
+Subject: [PATCH] Add openamp to SE proxy deployment
+
+Openamp is required to communicate between secure partitions(running on
+Cortex-A) and trusted-firmware-m(running on Cortex-M).
+These changes are to fetch libmetal and openamp from github repo's
+and build it.
+
+Signed-off-by: Rui Miguel Silva <rui.silva@arm.com>
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+
+---
+ deployments/se-proxy/opteesp/CMakeLists.txt | 14 ++++
+ deployments/se-proxy/opteesp/lse.S          | 19 +++++
+ external/openamp/libmetal.cmake             | 81 ++++++++++++++++++++
+ external/openamp/openamp.cmake              | 82 +++++++++++++++++++++
+ 4 files changed, 196 insertions(+)
+ create mode 100644 deployments/se-proxy/opteesp/lse.S
+ create mode 100644 external/openamp/libmetal.cmake
+ create mode 100644 external/openamp/openamp.cmake
+
+diff --git a/deployments/se-proxy/opteesp/CMakeLists.txt b/deployments/se-proxy/opteesp/CMakeLists.txt
+index 4e2069a5..248bd7e3 100644
+--- a/deployments/se-proxy/opteesp/CMakeLists.txt
++++ b/deployments/se-proxy/opteesp/CMakeLists.txt
+@@ -89,6 +89,7 @@ add_components(TARGET "se-proxy"
+ target_sources(se-proxy PRIVATE
+ 	se_proxy_sp.c
+ 	service_proxy_factory.c
++	lse.S
+ )
+ 
+ #-------------------------------------------------------------------------------
+@@ -108,6 +109,19 @@ include(../../../external/nanopb/nanopb.cmake)
+ target_link_libraries(se-proxy PRIVATE nanopb::protobuf-nanopb-static)
+ protobuf_generate_all(TGT "se-proxy" NAMESPACE "protobuf" BASE_DIR "${TS_ROOT}/protocols")
+ 
++# libmetal
++list(APPEND LIBMETAL_EXTERNAL_INCLUDE_PATHS ${SP_DEV_KIT_INCLUDE_DIR})
++set(LIBMETAL_EXTRA_INCLUDE_PATHS ${LIBMETAL_EXTRA_INCLUDE_PATHS}
++	CACHE STRING "" FORCE)
++include(../../../external/openamp/libmetal.cmake)
++
++# OpenAMP
++list(APPEND OPENAMP_EXTERNAL_INCLUDE_PATHS ${SP_DEV_KIT_INCLUDE_DIR})
++set(OPENAMP_EXTRA_INCLUDE_PATHS ${OPENAMP_EXTRA_INCLUDE_PATHS}
++	CACHE STRING "" FORCE)
++include(../../../external/openamp/openamp.cmake)
++target_link_libraries(se-proxy PRIVATE openamp libmetal)
++
+ #################################################################
+ 
+ target_compile_definitions(se-proxy PRIVATE
+diff --git a/deployments/se-proxy/opteesp/lse.S b/deployments/se-proxy/opteesp/lse.S
+new file mode 100644
+index 00000000..840683a6
+--- /dev/null
++++ b/deployments/se-proxy/opteesp/lse.S
+@@ -0,0 +1,19 @@
++// SPDX-License-Identifier: BSD-3-Clause
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ */
++
++.text
++.globl __aarch64_cas4_acq_rel
++
++__aarch64_cas4_acq_rel:
++	mov	w16, w0
++	ldaxr	w0, [x2]
++	cmp	w0, w16
++0:	bne	1f
++
++	stlxr	w17, w1, [x2]
++	cbnz	w17, 0b
++1:	ret
++
++
+diff --git a/external/openamp/libmetal.cmake b/external/openamp/libmetal.cmake
+new file mode 100644
+index 00000000..3a647e69
+--- /dev/null
++++ b/external/openamp/libmetal.cmake
+@@ -0,0 +1,81 @@
++#-------------------------------------------------------------------------------
++# Copyright (c) 2021 Linaro Limited
++# Copyright (c) 2021, Arm Limited. All rights reserved.
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++#-------------------------------------------------------------------------------
++
++set (LIBMETAL_URL "https://github.com/OpenAMP/libmetal.git" CACHE STRING "libmetal repository URL")
++set (LIBMETAL_INSTALL_PATH "${CMAKE_CURRENT_BINARY_DIR}/libmetal_install" CACHE PATH "libmetal installation directory")
++set (LIBMETAL_PACKAGE_PATH "${LIBMETAL_INSTALL_PATH}/libmetal/cmake" CACHE PATH "libmetal CMake package directory")
++set (LIBMETAL_TARGET_NAME "libmetal")
++set (LIBMETAL_VERSION "f252f0e007fbfb8b3a52b1d5901250ddac96baad"  CACHE STRING "The version of libmetal to use")
++
++if(NOT LIBMETAL_DEBUG)
++	set(LIBMETAL_BUILD_TYPE "Release")
++else()
++	set(LIBMETAL_BUILD_TYPE "Debug")
++endif()
++
++include(FetchContent)
++
++# Checking git
++find_program(GIT_COMMAND "git")
++if (NOT GIT_COMMAND)
++	message(FATAL_ERROR "Please install git")
++endif()
++
++FetchContent_Declare(
++	libmetal
++	GIT_REPOSITORY ${LIBMETAL_URL}
++	GIT_TAG ${LIBMETAL_VERSION}
++)
++
++# FetchContent_GetProperties exports libmetal_SOURCE_DIR and libmetal_BINARY_DIR variables
++FetchContent_GetProperties(libmetal)
++if(NOT libmetal_POPULATED)
++	message(STATUS "Fetching libmetal")
++	FetchContent_Populate(libmetal)
++endif()
++
++# Ensure list of include paths is separated correctly
++string(REPLACE ";" "\\;" LIBMETAL_EXTERNAL_INCLUDE_PATHS "${LIBMETAL_EXTERNAL_INCLUDE_PATHS}")
++
++#Configure the library
++execute_process(COMMAND
++	${CMAKE_COMMAND}
++			-DCMAKE_BUILD_TYPE=${LIBMETAL_BUILD_TYPE}
++			-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
++			-DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
++			-DCMAKE_TOOLCHAIN_FILE=${TS_EXTERNAL_LIB_TOOLCHAIN_FILE}
++			-DCMAKE_INSTALL_PREFIX=${LIBMETAL_INSTALL_PATH}
++			-DCMAKE_C_FLAGS_DEBUG=${CMAKE_C_FLAGS_DEBUG}
++			-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
++			-DCMAKE_C_OUTPUT_EXTENSION=.o
++			-DCMAKE_C_COMPILER_WORKS=true
++			-DCMAKE_SYSTEM_PROCESSOR=arm
++			-DWITH_DOC=off
++			-DWITH_TESTS=off
++			-DWITH_EXAMPLES=off
++			-DWITH_DEFAULT_LOGGER=off
++			-DEXTERNAL_INCLUDE_PATHS=${LIBMETAL_EXTERNAL_INCLUDE_PATHS}
++			-DMACHINE=template
++			${libmetal_SOURCE_DIR}
++	WORKING_DIRECTORY
++			${libmetal_BINARY_DIR}
++)
++
++# Build the library
++execute_process(COMMAND
++    ${CMAKE_COMMAND} --build ${libmetal_BINARY_DIR} -- install
++		RESULT_VARIABLE _exec_error
++	)
++if (_exec_error)
++	message(FATAL_ERROR "Build step of libmetal failed with ${_exec_error}.")
++endif()
++
++#Create an imported target to have clean abstraction in the build-system.
++add_library(libmetal STATIC IMPORTED)
++set_property(TARGET libmetal PROPERTY IMPORTED_LOCATION "${LIBMETAL_INSTALL_PATH}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}metal${CMAKE_STATIC_LIBRARY_SUFFIX}")
++set_property(TARGET libmetal PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${LIBMETAL_INSTALL_PATH}/include")
+diff --git a/external/openamp/openamp.cmake b/external/openamp/openamp.cmake
+new file mode 100644
+index 00000000..aae13bad
+--- /dev/null
++++ b/external/openamp/openamp.cmake
+@@ -0,0 +1,82 @@
++#-------------------------------------------------------------------------------
++# Copyright (c) 2021 Linaro Limited
++# Copyright (c) 2021, Arm Limited. All rights reserved.
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++#-------------------------------------------------------------------------------
++
++set (OPENAMP_URL "https://github.com/OpenAMP/open-amp.git" CACHE STRING "OpenAMP repository URL")
++set (OPENAMP_INSTALL_PATH "${CMAKE_CURRENT_BINARY_DIR}/openamp_install" CACHE PATH "OpenAMP installation directory")
++set (OPENAMP_PACKAGE_PATH "${OPENAMP_INSTALL_PATH}/openamp/cmake" CACHE PATH "OpenAMP CMake package directory")
++set (OPENAMP_TARGET_NAME "openamp")
++set (OPENAMP_VERSION "347397decaa43372fc4d00f965640ebde042966d"  CACHE STRING "The version of openamp to use")
++
++
++if(NOT OPENAMP_DEBUG)
++	set(OPENAMP_BUILD_TYPE "Release")
++else()
++	set(OPENAMP_BUILD_TYPE "Debug")
++endif()
++
++include(FetchContent)
++
++# Checking git
++find_program(GIT_COMMAND "git")
++if (NOT GIT_COMMAND)
++	message(FATAL_ERROR "Please install git")
++endif()
++
++FetchContent_Declare(
++	openamp
++	GIT_REPOSITORY ${OPENAMP_URL}
++	GIT_TAG ${OPENAMP_VERSION}
++)
++
++# FetchContent_GetProperties exports openamp_SOURCE_DIR and openamp_BINARY_DIR variables
++FetchContent_GetProperties(openamp)
++if(NOT openamp_POPULATED)
++	message(STATUS "Fetching openamp")
++	FetchContent_Populate(openamp)
++endif()
++
++# Ensure list of include paths is separated correctly
++get_target_property(_libmetal_inc libmetal INTERFACE_INCLUDE_DIRECTORIES)
++set (_openam_external_include_paths ${_libmetal_inc} ${OPENAMP_EXTERNAL_INCLUDE_PATHS})
++string(REPLACE ";" "\\;" OPENAMP_EXTERNAL_INCLUDE_PATHS "${_openam_external_include_paths}")
++
++#Configure the library
++execute_process(COMMAND
++	${CMAKE_COMMAND}
++			-DCMAKE_BUILD_TYPE=${OPENAMP_BUILD_TYPE}
++			-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
++			-DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
++			-DCMAKE_TOOLCHAIN_FILE=${TS_EXTERNAL_LIB_TOOLCHAIN_FILE}
++			-DCMAKE_INSTALL_PREFIX=${OPENAMP_INSTALL_PATH}
++			-DCMAKE_C_FLAGS_DEBUG=${CMAKE_C_FLAGS_DEBUG}
++			-DLIBMETAL_INCLUDE_DIR=${CMAKE_CURRENT_BINARY_DIR}/libmetal/lib/include
++			-DLIBMETAL_LIB=${CMAKE_CURRENT_BINARY_DIR}/libmetal/lib
++			-DCMAKE_C_OUTPUT_EXTENSION=.o
++			-DCMAKE_C_COMPILER_WORKS=true
++			-DCMAKE_SYSTEM_PROCESSOR=arm
++			-DEXTERNAL_INCLUDE_PATHS=${OPENAMP_EXTERNAL_INCLUDE_PATHS}
++			-DMACHINE=template
++			-DRPMSG_BUFFER_SIZE=512
++			${openamp_SOURCE_DIR}
++	WORKING_DIRECTORY
++			${openamp_BINARY_DIR}
++)
++
++# Build the library
++execute_process(COMMAND
++    ${CMAKE_COMMAND} --build ${openamp_BINARY_DIR} -- install
++		RESULT_VARIABLE _exec_error
++	)
++if (_exec_error)
++	message(FATAL_ERROR "Build step of OpenAMP failed with ${_exec_error}.")
++endif()
++
++#Create an imported target to have clean abstraction in the build-system.
++add_library(openamp STATIC IMPORTED)
++set_property(TARGET openamp PROPERTY IMPORTED_LOCATION "${OPENAMP_INSTALL_PATH}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}open_amp${CMAKE_STATIC_LIBRARY_SUFFIX}")
++set_property(TARGET openamp PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${OPENAMP_INSTALL_PATH}/include")
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0008-Implement-mhu-driver-and-the-OpenAmp-conversion-laye.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0008-Implement-mhu-driver-and-the-OpenAmp-conversion-laye.patch
new file mode 100644
index 0000000..47ca59f
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0008-Implement-mhu-driver-and-the-OpenAmp-conversion-laye.patch
@@ -0,0 +1,1093 @@
+From 993a3c3cb08a723f5b5eb07cf38d70e9acf52e7f Mon Sep 17 00:00:00 2001
+From: Vishnu Banavath <vishnu.banavath@arm.com>
+Date: Fri, 3 Dec 2021 18:00:46 +0000
+Subject: [PATCH] Implement mhu driver and the OpenAmp conversion layer.
+
+This commit adds an mhu driver (v2.1 and v2) to the secure
+partition se_proxy and a conversion layer to communicate with
+the secure enclave using OpenAmp.
+
+Signed-off-by: Rui Miguel Silva <rui.silva@arm.com>
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+
+---
+ .../se-proxy/opteesp/default_se-proxy.dts.in  |  16 +
+ .../drivers/arm/mhu_driver/component.cmake    |  12 +
+ platform/drivers/arm/mhu_driver/mhu_v2.h      | 391 ++++++++++++
+ platform/drivers/arm/mhu_driver/mhu_v2_x.c    | 602 ++++++++++++++++++
+ .../providers/arm/corstone1000/platform.cmake |  10 +
+ 5 files changed, 1031 insertions(+)
+ create mode 100644 platform/drivers/arm/mhu_driver/component.cmake
+ create mode 100644 platform/drivers/arm/mhu_driver/mhu_v2.h
+ create mode 100644 platform/drivers/arm/mhu_driver/mhu_v2_x.c
+ create mode 100644 platform/providers/arm/corstone1000/platform.cmake
+
+diff --git a/deployments/se-proxy/opteesp/default_se-proxy.dts.in b/deployments/se-proxy/opteesp/default_se-proxy.dts.in
+index 9f5cf712..f351a592 100644
+--- a/deployments/se-proxy/opteesp/default_se-proxy.dts.in
++++ b/deployments/se-proxy/opteesp/default_se-proxy.dts.in
+@@ -17,5 +17,21 @@
+ 		execution-state = <0>; /* AArch64 */
+ 		xlat-granule = <0>; /* 4KiB */
+ 		messaging-method = <0>; /* Direct messaging only */
++
++		device-regions {
++			compatible = "arm,ffa-manifest-device-regions";
++			mhu-sender {
++				/* Armv8 A Foundation Platform values */
++				base-address = <0x00000000 0x1b820000>;
++				pages-count = <16>;
++				attributes = <0x3>; /* read-write */
++			};
++			mhu-receiver {
++				/* Armv8 A Foundation Platform values */
++				base-address = <0x00000000 0x1b830000>;
++				pages-count = <16>;
++				attributes = <0x3>; /* read-write */
++			};
++		};
+ 	};
+ };
+diff --git a/platform/drivers/arm/mhu_driver/component.cmake b/platform/drivers/arm/mhu_driver/component.cmake
+new file mode 100644
+index 00000000..77a5a50b
+--- /dev/null
++++ b/platform/drivers/arm/mhu_driver/component.cmake
+@@ -0,0 +1,12 @@
++#-------------------------------------------------------------------------------
++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++#-------------------------------------------------------------------------------
++
++# Add source files for using mhu driver
++target_sources(${TGT}
++	PRIVATE
++	"${CMAKE_CURRENT_LIST_DIR}/mhu_v2_x.c"
++)
+diff --git a/platform/drivers/arm/mhu_driver/mhu_v2.h b/platform/drivers/arm/mhu_driver/mhu_v2.h
+new file mode 100644
+index 00000000..2e4ba80f
+--- /dev/null
++++ b/platform/drivers/arm/mhu_driver/mhu_v2.h
+@@ -0,0 +1,391 @@
++/*
++ * Copyright (c) 2021 Arm Limited
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ *     http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++/**
++ * \file mhu_v2_x.h
++ * \brief Driver for Arm MHU v2.0 and v2.1
++ */
++
++#ifndef __MHU_V2_X_H__
++#define __MHU_V2_X_H__
++
++#include <stdint.h>
++#include <stdbool.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#define MHU_2_X_INTR_NR2R_OFF             (0x0u)
++#define MHU_2_X_INTR_R2NR_OFF             (0x1u)
++#define MHU_2_1_INTR_CHCOMB_OFF           (0x2u)
++
++#define MHU_2_X_INTR_NR2R_MASK            (0x1u << MHU_2_X_INTR_NR2R_OFF)
++#define MHU_2_X_INTR_R2NR_MASK            (0x1u << MHU_2_X_INTR_R2NR_OFF)
++#define MHU_2_1_INTR_CHCOMB_MASK          (0x1u << MHU_2_1_INTR_CHCOMB_OFF)
++
++enum mhu_v2_x_frame_t {
++    MHU_V2_X_SENDER_FRAME   = 0x0u,
++    MHU_V2_X_RECEIVER_FRAME = 0x1u,
++};
++
++enum mhu_v2_x_supported_revisions {
++     MHU_REV_READ_FROM_HW = 0,
++     MHU_REV_2_0,
++     MHU_REV_2_1,
++};
++
++struct mhu_v2_x_dev_t {
++    uint32_t base;
++    enum mhu_v2_x_frame_t frame;
++    uint32_t subversion;    /*!< Hardware subversion: v2.X */
++    bool is_initialized;    /*!< Indicates if the MHU driver
++                             *   is initialized and enabled
++                             */
++};
++
++/**
++ * \brief MHU v2 error enumeration types.
++ */
++enum mhu_v2_x_error_t {
++    MHU_V_2_X_ERR_NONE                =  0,
++    MHU_V_2_X_ERR_NOT_INIT            = -1,
++    MHU_V_2_X_ERR_ALREADY_INIT        = -2,
++    MHU_V_2_X_ERR_UNSUPPORTED_VERSION = -3,
++    MHU_V_2_X_ERR_INVALID_ARG         = -4,
++    MHU_V_2_X_ERR_GENERAL             = -5
++};
++
++/**
++ * \brief Initializes the driver
++ *
++ * \param[in] dev   MHU device struct \ref mhu_v2_x_dev_t
++ * \param[in] rev   MHU revision (if can't be identified from HW)
++ *
++ * Reads the MHU hardware version
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note MHU revision only has to be specified when versions can't be read
++ *       from HW (ARCH_MAJOR_REV reg reads as 0x0).
++ *
++ * \note This function doesn't check if dev is NULL.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_driver_init(struct mhu_v2_x_dev_t *dev,
++     enum mhu_v2_x_supported_revisions rev);
++
++/**
++ * \brief Returns the number of channels implemented.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ *
++ * Returns the number of channels implemented.
++ *
++ * \return Returns the number of channels implemented.
++ *
++ * \note This function doesn't check if dev is NULL.
++ */
++uint32_t mhu_v2_x_get_num_channel_implemented(
++         const struct mhu_v2_x_dev_t *dev);
++
++/**
++ * \brief Sends the value over a channel.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ * \param[in] channel     Channel to send the value over.
++ * \param[in] val         Value to send.
++ *
++ * Sends the value over a channel.
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ * \note This function doesn't check if channel is implemented.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_channel_send(const struct mhu_v2_x_dev_t *dev,
++     uint32_t channel, uint32_t val);
++
++/**
++ * \brief Clears the channel after the value is send over it.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ * \param[in] channel     Channel to clear.
++ *
++ * Clears the channel after the value is send over it.
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ * \note This function doesn't check if channel is implemented.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_channel_clear(const struct mhu_v2_x_dev_t *dev,
++     uint32_t channel);
++
++/**
++ * \brief Receives the value over a channel.
++ *
++ * \param[in]  dev         MHU device struct \ref mhu_v2_x_dev_t
++ * \param[in]  channel     Channel to receive the value from.
++ * \param[out] value       Pointer to variable that will store the value.
++ *
++ * Receives the value over a channel.
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ * \note This function doesn't check if channel is implemented.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_channel_receive(
++     const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t *value);
++
++/**
++ * \brief Sets bits in the Channel Mask.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ * \param[in] channel     Which channel's mask to set.
++ * \param[in] mask        Mask to be set over a receiver frame.
++ *
++ * Sets bits in the Channel Mask.
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ * \note This function doesn't check if channel is implemented.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_channel_mask_set(
++     const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask);
++
++/**
++ * \brief Clears bits in the Channel Mask.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ * \param[in] channel     Which channel's mask to clear.
++ * \param[in] mask        Mask to be clear over a receiver frame.
++ *
++ * Clears bits in the Channel Mask.
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ * \note This function doesn't check if channel is implemented.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_channel_mask_clear(
++     const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask);
++
++/**
++ * \brief Enables the Channel interrupt.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ * \param[in] channel     Which channel's interrupt to enable.
++ *
++ * Enables the Channel clear interrupt.
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ * \note This function doesn't check if channel is implemented.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_enable(
++     const struct mhu_v2_x_dev_t *dev, uint32_t channel);
++
++/**
++ * \brief Disables the Channel interrupt.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ * \param[in] channel     Which channel's interrupt to disable.
++ *
++ * Disables the Channel interrupt.
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ * \note This function doesn't check if channel is implemented.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_disable(
++     const struct mhu_v2_x_dev_t *dev, uint32_t channel);
++
++/**
++ * \brief Cleares the Channel interrupt.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ * \param[in] channel     Which channel's interrupt to clear.
++ *
++ * Cleares the Channel interrupt.
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ * \note This function doesn't check if channel is implemented.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_clear(
++     const struct mhu_v2_x_dev_t *dev, uint32_t channel);
++
++/**
++ * \brief Initiates a MHU transfer with the handshake signals.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ *
++ * Initiates a MHU transfer with the handshake signals in a blocking mode.
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_initiate_transfer(
++     const struct mhu_v2_x_dev_t *dev);
++
++/**
++ * \brief Closes a MHU transfer with the handshake signals.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ *
++ * Closes a MHU transfer with the handshake signals in a blocking mode.
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_close_transfer(
++     const struct mhu_v2_x_dev_t *dev);
++
++/**
++ * \brief Returns the value of access request signal.
++ *
++ * \param[in]  dev         MHU device struct \ref mhu_v2_x_dev_t
++ * \param[out] val         Pointer to variable that will store the value.
++ *
++ * For more information please read the MHU v2 user guide
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_get_access_request(
++     const struct mhu_v2_x_dev_t *dev, uint32_t *val);
++
++/**
++ * \brief Sets the value of access request signal to high.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ *
++ * For more information please read the MHU v2 user guide
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_set_access_request(
++     const struct mhu_v2_x_dev_t *dev);
++
++/**
++ * \brief Sets the value of access request signal to low.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ *
++ * For more information please read the MHU v2 user guide
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_reset_access_request(
++     const struct mhu_v2_x_dev_t *dev);
++
++/**
++ * \brief Returns the value of access ready signal.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ * \param[out] val        Pointer to variable that will store the value.
++ *
++ * For more information please read the MHU v2 user guide
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_get_access_ready(
++     const struct mhu_v2_x_dev_t *dev, uint32_t *val);
++
++/**
++ * \brief Returns the MHU interrupt status.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ *
++ * \return Interrupt status register value. Masking is needed for individual
++ *         interrupts.
++ *
++ * \note This function doesn't check if dev is NULL.
++ */
++uint32_t mhu_v2_x_get_interrupt_status(const struct mhu_v2_x_dev_t *dev);
++
++/**
++ * \brief Enables MHU interrupts.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ * \param[in] mask        Bit mask for enabling/disabling interrupts
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_interrupt_enable(
++     const struct mhu_v2_x_dev_t *dev, uint32_t mask);
++
++/**
++ * \brief Disables MHU interrupts.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ * \param[in] mask        Bit mask for enabling/disabling interrupts
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_interrupt_disable(
++     const struct mhu_v2_x_dev_t *dev, uint32_t mask);
++
++/**
++ * \brief Clears MHU interrupts.
++ *
++ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
++ * \param[in] mask        Bit mask for clearing interrupts
++ *
++ * \return Returns mhu_v2_x_error_t error code
++ *
++ * \note This function doesn't check if dev is NULL.
++ */
++enum mhu_v2_x_error_t mhu_v2_x_interrupt_clear(
++     const struct mhu_v2_x_dev_t *dev, uint32_t mask);
++
++/**
++ * \brief Returns the first channel number whose interrupt bit is high.
++ *
++ * \param[in]  dev         MHU device struct \ref mhu_v2_x_dev_t
++ * \param[out] channel     Pointer to variable that will have the channel value.
++ *
++ * \return Returns the first channel number whose interrupt bit is high.
++ * \return Returns mhu_v2_x_error_t error code.
++ *
++ * \note This function doesn't check if dev is NULL.
++ */
++enum mhu_v2_x_error_t mhu_v2_1_get_ch_interrupt_num(
++     const struct mhu_v2_x_dev_t *dev, uint32_t *channel);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* __MHU_V2_X_H__ */
+diff --git a/platform/drivers/arm/mhu_driver/mhu_v2_x.c b/platform/drivers/arm/mhu_driver/mhu_v2_x.c
+new file mode 100644
+index 00000000..01d8f659
+--- /dev/null
++++ b/platform/drivers/arm/mhu_driver/mhu_v2_x.c
+@@ -0,0 +1,602 @@
++/*
++ * Copyright (c) 2021 Arm Limited
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License");
++ * you may not use this file except in compliance with the License.
++ * You may obtain a copy of the License at
++ *
++ *     http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++#include <stdint.h>
++#include <stdbool.h>
++#include "mhu_v2.h"
++
++#define _MHU_V2_X_MAX_CHANNELS    124
++#define _MHU_V2_1_MAX_CHCOMB_INT  4
++#define ENABLE                    0x1
++#define DISABLE                   0x0
++#define CLEAR_INTR                0x1
++#define CH_PER_CH_COMB            0x20
++#define SEND_FRAME(p_mhu)       ((struct _mhu_v2_x_send_frame_t *)p_mhu)
++#define RECV_FRAME(p_mhu)       ((struct _mhu_v2_x_recv_frame_t *)p_mhu)
++
++#define MHU_MAJOR_REV_V2      0x1u
++#define MHU_MINOR_REV_2_0     0x0u
++#define MHU_MINOR_REV_2_1     0x1u
++
++struct _mhu_v2_x_send_ch_window_t {
++    /* Offset: 0x00 (R/ ) Channel Status */
++    volatile uint32_t ch_st;
++    /* Offset: 0x04 (R/ ) Reserved */
++    volatile uint32_t reserved_0;
++    /* Offset: 0x08 (R/ ) Reserved */
++    volatile uint32_t reserved_1;
++    /* Offset: 0x0C ( /W) Channel Set */
++    volatile uint32_t ch_set;
++    /* Offset: 0x10 (R/ ) Channel Interrupt Status (Reserved in 2.0) */
++    volatile uint32_t ch_int_st;
++    /* Offset: 0x14 ( /W) Channel Interrupt Clear  (Reserved in 2.0) */
++    volatile uint32_t ch_int_clr;
++    /* Offset: 0x18 (R/W) Channel Interrupt Enable (Reserved in 2.0) */
++    volatile uint32_t ch_int_en;
++    /* Offset: 0x1C (R/ ) Reserved */
++    volatile uint32_t reserved_2;
++};
++
++struct _mhu_v2_x_send_frame_t {
++    /* Offset: 0x000 ( / ) Sender Channel Window 0 -123 */
++    struct _mhu_v2_x_send_ch_window_t send_ch_window[_MHU_V2_X_MAX_CHANNELS];
++    /* Offset: 0xF80 (R/ ) Message Handling Unit Configuration */
++    volatile uint32_t mhu_cfg;
++    /* Offset: 0xF84 (R/W) Response Configuration */
++    volatile uint32_t resp_cfg;
++    /* Offset: 0xF88 (R/W) Access Request */
++    volatile uint32_t access_request;
++    /* Offset: 0xF8C (R/ ) Access Ready */
++    volatile uint32_t access_ready;
++    /* Offset: 0xF90 (R/ ) Interrupt Status */
++    volatile uint32_t int_st;
++    /* Offset: 0xF94 ( /W) Interrupt Clear */
++    volatile uint32_t int_clr;
++    /* Offset: 0xF98 (R/W) Interrupt Enable */
++    volatile uint32_t int_en;
++    /* Offset: 0xF9C (R/ ) Reserved */
++    volatile uint32_t reserved_0;
++    /* Offset: 0xFA0 (R/W) Channel Combined Interrupt Stat (Reserved in 2.0) */
++    volatile uint32_t ch_comb_int_st[_MHU_V2_1_MAX_CHCOMB_INT];
++    /* Offset: ‭0xFC4‬ (R/ ) Reserved */
++    volatile uint32_t reserved_1[6];
++    /* Offset: 0xFC8 (R/ ) Implementer Identification Register */
++    volatile uint32_t iidr;
++    /* Offset: 0xFCC (R/ ) Architecture Identification Register */
++    volatile uint32_t aidr;
++    /* Offset: 0xFD0 (R/ )  */
++    volatile uint32_t pid_1[4];
++    /* Offset: 0xFE0 (R/ )  */
++    volatile uint32_t pid_0[4];
++    /* Offset: 0xFF0 (R/ )  */
++    volatile uint32_t cid[4];
++};
++
++struct _mhu_v2_x_rec_ch_window_t {
++    /* Offset: 0x00 (R/ ) Channel Status */
++    volatile uint32_t ch_st;
++    /* Offset: 0x04 (R/ ) Channel Status Masked */
++    volatile uint32_t ch_st_msk;
++    /* Offset: 0x08 ( /W) Channel Clear */
++    volatile uint32_t ch_clr;
++    /* Offset: 0x0C (R/ ) Reserved */
++    volatile uint32_t reserved_0;
++    /* Offset: 0x10 (R/ ) Channel Mask Status */
++    volatile uint32_t ch_msk_st;
++    /* Offset: 0x14 ( /W) Channel Mask Set */
++    volatile uint32_t ch_msk_set;
++    /* Offset: 0x18 ( /W) Channel Mask Clear */
++    volatile uint32_t ch_msk_clr;
++    /* Offset: 0x1C (R/ ) Reserved */
++    volatile uint32_t reserved_1;
++};
++
++struct _mhu_v2_x_recv_frame_t {
++    /* Offset: 0x000 ( / ) Receiver Channel Window 0 -123 */
++    struct _mhu_v2_x_rec_ch_window_t rec_ch_window[_MHU_V2_X_MAX_CHANNELS];
++    /* Offset: 0xF80 (R/ ) Message Handling Unit Configuration */
++    volatile uint32_t mhu_cfg;
++    /* Offset: 0xF84 (R/ ) Reserved */
++    volatile uint32_t reserved_0[3];
++    /* Offset: 0xF90 (R/ ) Interrupt Status (Reserved in 2.0) */
++    volatile uint32_t int_st;
++    /* Offset: 0xF94 (R/ ) Interrupt Clear  (Reserved in 2.0) */
++    volatile uint32_t int_clr;
++    /* Offset: 0xF98 (R/W) Interrupt Enable (Reserved in 2.0) */
++    volatile uint32_t int_en;
++    /* Offset: 0xF9C (R/ ) Reserved  */
++    volatile uint32_t reserved_1;
++    /* Offset: 0xFA0 (R/ ) Channel Combined Interrupt Stat (Reserved in 2.0) */
++    volatile uint32_t ch_comb_int_st[_MHU_V2_1_MAX_CHCOMB_INT];
++    /* Offset: 0xFB0 (R/ ) Reserved */
++    volatile uint32_t reserved_2[6];
++    /* Offset: 0xFC8 (R/ ) Implementer Identification Register */
++    volatile uint32_t iidr;
++    /* Offset: 0xFCC (R/ ) Architecture Identification Register */
++    volatile uint32_t aidr;
++    /* Offset: 0xFD0 (R/ )  */
++    volatile uint32_t pid_1[4];
++    /* Offset: 0xFE0 (R/ )  */
++    volatile uint32_t pid_0[4];
++    /* Offset: 0xFF0 (R/ )  */
++    volatile uint32_t cid[4];
++};
++
++union _mhu_v2_x_frame_t {
++    struct _mhu_v2_x_send_frame_t send_frame;
++    struct _mhu_v2_x_recv_frame_t recv_frame;
++};
++
++enum mhu_v2_x_error_t mhu_v2_x_driver_init(struct mhu_v2_x_dev_t *dev,
++     enum mhu_v2_x_supported_revisions rev)
++{
++    uint32_t AIDR = 0;
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if (dev->is_initialized) {
++        return MHU_V_2_X_ERR_ALREADY_INIT;
++    }
++
++    if (rev == MHU_REV_READ_FROM_HW) {
++        /* Read revision from HW */
++        if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
++            AIDR = p_mhu->recv_frame.aidr;
++        } else {
++            AIDR = p_mhu->send_frame.aidr;
++        }
++
++        /* Get bits 7:4 to read major revision */
++        if ( ((AIDR >> 4) & 0b1111) != MHU_MAJOR_REV_V2) {
++            /* Unsupported MHU version */
++            return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
++        } /* No need to save major version, driver only supports MHUv2 */
++
++        /* Get bits 3:0 to read minor revision */
++        dev->subversion = AIDR & 0b1111;
++
++        if (dev->subversion != MHU_MINOR_REV_2_0 &&
++            dev->subversion != MHU_MINOR_REV_2_1) {
++            /* Unsupported subversion */
++            return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
++        }
++    } else {
++        /* Revisions were provided by caller */
++        if (rev == MHU_REV_2_0) {
++            dev->subversion = MHU_MINOR_REV_2_0;
++        } else if (rev == MHU_REV_2_1) {
++            dev->subversion = MHU_MINOR_REV_2_1;
++        } else {
++            /* Unsupported subversion */
++            return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
++        }/* No need to save major version, driver only supports MHUv2 */
++    }
++
++    dev->is_initialized = true;
++
++    return MHU_V_2_X_ERR_NONE;
++}
++
++uint32_t mhu_v2_x_get_num_channel_implemented(const struct mhu_v2_x_dev_t *dev)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
++        return (SEND_FRAME(p_mhu))->mhu_cfg;
++    } else {
++        return (RECV_FRAME(p_mhu))->mhu_cfg;
++    }
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_channel_send(const struct mhu_v2_x_dev_t *dev,
++     uint32_t channel, uint32_t val)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
++        (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_set = val;
++        return MHU_V_2_X_ERR_NONE;
++    } else {
++        return MHU_V_2_X_ERR_INVALID_ARG;
++    }
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_channel_clear(const struct mhu_v2_x_dev_t *dev,
++     uint32_t channel)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if(dev->frame == MHU_V2_X_RECEIVER_FRAME) {
++        (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_clr = UINT32_MAX;
++        return MHU_V_2_X_ERR_NONE;
++    } else {
++        return MHU_V_2_X_ERR_INVALID_ARG;
++    }
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_channel_receive(
++     const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t *value)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if(dev->frame == MHU_V2_X_RECEIVER_FRAME) {
++        *value = (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_st;
++        return MHU_V_2_X_ERR_NONE;
++    } else {
++        return MHU_V_2_X_ERR_INVALID_ARG;
++    }
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_channel_mask_set(
++     const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if(dev->frame == MHU_V2_X_RECEIVER_FRAME) {
++        (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_msk_set = mask;
++        return MHU_V_2_X_ERR_NONE;
++    } else {
++        return MHU_V_2_X_ERR_INVALID_ARG;
++    }
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_channel_mask_clear(
++     const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if(dev->frame == MHU_V2_X_RECEIVER_FRAME) {
++        (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_msk_clr = mask;
++        return MHU_V_2_X_ERR_NONE;
++    } else {
++        return MHU_V_2_X_ERR_INVALID_ARG;
++    }
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_enable(
++     const struct mhu_v2_x_dev_t *dev, uint32_t channel)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if (dev->subversion == MHU_MINOR_REV_2_1) {
++        return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
++    }
++
++    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
++        (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_int_en = ENABLE;
++        return MHU_V_2_X_ERR_NONE;
++    } else {
++        return MHU_V_2_X_ERR_INVALID_ARG;
++    }
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_disable(
++     const struct mhu_v2_x_dev_t *dev, uint32_t channel)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if (dev->subversion == MHU_MINOR_REV_2_1) {
++        return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
++    }
++
++    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
++        (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_int_en = DISABLE;
++        return MHU_V_2_X_ERR_NONE;
++    } else {
++        return MHU_V_2_X_ERR_INVALID_ARG;
++    }
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_clear(
++     const struct mhu_v2_x_dev_t *dev, uint32_t channel)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if (dev->subversion == MHU_MINOR_REV_2_1) {
++        return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
++    }
++
++    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
++        (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_int_clr = CLEAR_INTR;
++        return MHU_V_2_X_ERR_NONE;
++    } else {
++        return MHU_V_2_X_ERR_INVALID_ARG;
++    }
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_initiate_transfer(
++     const struct mhu_v2_x_dev_t *dev)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if(dev->frame != MHU_V2_X_SENDER_FRAME) {
++        return MHU_V_2_X_ERR_INVALID_ARG;
++    }
++
++    (SEND_FRAME(p_mhu))->access_request = ENABLE;
++
++    while ( !((SEND_FRAME(p_mhu))->access_ready) ) {
++        /* Wait in a loop for access ready signal to be high */
++        ;
++    }
++
++    return MHU_V_2_X_ERR_NONE;
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_close_transfer(const struct mhu_v2_x_dev_t *dev)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if(dev->frame != MHU_V2_X_SENDER_FRAME) {
++        return MHU_V_2_X_ERR_INVALID_ARG;
++    }
++
++    (SEND_FRAME(p_mhu))->access_request = DISABLE;
++
++    return MHU_V_2_X_ERR_NONE;
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_get_access_request(
++     const struct mhu_v2_x_dev_t *dev, uint32_t *val)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if(dev->frame != MHU_V2_X_SENDER_FRAME) {
++        return MHU_V_2_X_ERR_INVALID_ARG;
++    }
++
++    *val = (SEND_FRAME(p_mhu))->access_request;
++
++    return MHU_V_2_X_ERR_NONE;
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_set_access_request(
++     const struct mhu_v2_x_dev_t *dev)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if(dev->frame != MHU_V2_X_SENDER_FRAME) {
++        return MHU_V_2_X_ERR_INVALID_ARG;
++    }
++
++    (SEND_FRAME(p_mhu))->access_request = ENABLE;
++
++    return MHU_V_2_X_ERR_NONE;
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_reset_access_request(
++     const struct mhu_v2_x_dev_t *dev)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if(dev->frame != MHU_V2_X_SENDER_FRAME) {
++        return MHU_V_2_X_ERR_INVALID_ARG;
++    }
++
++    (SEND_FRAME(p_mhu))->access_request = DISABLE;
++
++    return MHU_V_2_X_ERR_NONE;
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_get_access_ready(
++     const struct mhu_v2_x_dev_t *dev, uint32_t *val)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if(dev->frame != MHU_V2_X_SENDER_FRAME) {
++        return MHU_V_2_X_ERR_INVALID_ARG;
++    }
++
++    *val = (SEND_FRAME(p_mhu))->access_ready;
++
++    return MHU_V_2_X_ERR_NONE;
++}
++
++uint32_t mhu_v2_x_get_interrupt_status(const struct mhu_v2_x_dev_t *dev)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
++        return (SEND_FRAME(p_mhu))->int_st;
++    } else {
++        return (RECV_FRAME(p_mhu))->int_st;
++    }
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_interrupt_enable(
++     const struct mhu_v2_x_dev_t *dev, uint32_t mask)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if (dev->subversion == MHU_MINOR_REV_2_0) {
++        if (mask & MHU_2_1_INTR_CHCOMB_MASK) {
++            /* Combined channel IRQ is not present in v2.0 */
++            return MHU_V_2_X_ERR_INVALID_ARG;
++        }
++
++        if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
++            /* Only sender frame has these registers */
++            return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
++        }
++    }
++
++    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
++        (SEND_FRAME(p_mhu))->int_en |= mask;
++    } else {
++        (RECV_FRAME(p_mhu))->int_en |= mask;
++    }
++
++    return MHU_V_2_X_ERR_NONE;
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_interrupt_disable(
++     const struct mhu_v2_x_dev_t *dev, uint32_t mask)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if (dev->subversion == MHU_MINOR_REV_2_0) {
++        if (mask & MHU_2_1_INTR_CHCOMB_MASK) {
++            /* Combined channel IRQ is not present in v2.0 */
++            return MHU_V_2_X_ERR_INVALID_ARG;
++        }
++
++        if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
++            /* Only sender frame has these registers */
++            return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
++        }
++    }
++
++    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
++        (SEND_FRAME(p_mhu))->int_en &= ~mask;
++    } else {
++        (RECV_FRAME(p_mhu))->int_en &= ~mask;
++    }
++
++    return MHU_V_2_X_ERR_NONE;
++}
++
++enum mhu_v2_x_error_t mhu_v2_x_interrupt_clear(
++     const struct mhu_v2_x_dev_t *dev, uint32_t mask)
++{
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if (dev->subversion == MHU_MINOR_REV_2_0) {
++        if (mask & MHU_2_1_INTR_CHCOMB_MASK) {
++            /* Combined channel IRQ is not present in v2.0 */
++            return MHU_V_2_X_ERR_INVALID_ARG;
++        }
++
++        if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
++            /* Only sender frame has these registers */
++            return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
++        }
++    }
++
++    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
++        (SEND_FRAME(p_mhu))->int_clr = mask;
++    } else {
++        (RECV_FRAME(p_mhu))->int_clr = mask;
++    }
++
++    return MHU_V_2_X_ERR_NONE;
++}
++
++enum mhu_v2_x_error_t mhu_v2_1_get_ch_interrupt_num(
++     const struct mhu_v2_x_dev_t *dev, uint32_t *channel)
++{
++    uint32_t i, j, status;
++    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
++
++    if ( !(dev->is_initialized) ) {
++        return MHU_V_2_X_ERR_NOT_INIT;
++    }
++
++    if (dev->subversion != MHU_MINOR_REV_2_1) {
++        /* Feature is only supported in MHU v2.1 */
++        return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
++    }
++
++    for(i = 0; i < _MHU_V2_1_MAX_CHCOMB_INT; i++) {
++        if(dev->frame == MHU_V2_X_SENDER_FRAME) {
++            status = (SEND_FRAME(p_mhu))->ch_comb_int_st[i];
++        } else {
++            status = (RECV_FRAME(p_mhu))->ch_comb_int_st[i];
++        }
++
++        for(j = 0; j < CH_PER_CH_COMB; j++) {
++            if ((status >> CH_PER_CH_COMB - j - 1) & (ENABLE)) {
++                *channel = (CH_PER_CH_COMB - j -1 + (i * CH_PER_CH_COMB));
++                return MHU_V_2_X_ERR_NONE;
++            }
++        }
++    }
++
++    return MHU_V_2_X_ERR_GENERAL;
++}
+diff --git a/platform/providers/arm/corstone1000/platform.cmake b/platform/providers/arm/corstone1000/platform.cmake
+new file mode 100644
+index 00000000..bb778bb9
+--- /dev/null
++++ b/platform/providers/arm/corstone1000/platform.cmake
+@@ -0,0 +1,10 @@
++#-------------------------------------------------------------------------------
++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++# Platform definition for the 'fvp_base_revc-2xaem8a' virtual platform.
++#-------------------------------------------------------------------------------
++
++# include MHU driver
++include(${TS_ROOT}/platform/drivers/arm/mhu_driver/component.cmake)
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0009-Add-openamp-rpc-caller.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0009-Add-openamp-rpc-caller.patch
new file mode 100644
index 0000000..0f3f2c6
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0009-Add-openamp-rpc-caller.patch
@@ -0,0 +1,1197 @@
+From a6721cc391397f5f999db84e4ebec4c20985996a Mon Sep 17 00:00:00 2001
+From: Vishnu Banavath <vishnu.banavath@arm.com>
+Date: Fri, 3 Dec 2021 19:00:54 +0000
+Subject: [PATCH] Add openamp rpc caller
+
+Signed-off-by: Rui Miguel Silva <rui.silva@arm.com>
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+
+---
+ components/rpc/common/caller/rpc_caller.c     |  10 +
+ components/rpc/common/interface/rpc_caller.h  |   8 +
+ .../rpc/openamp/caller/sp/component.cmake     |  15 +
+ .../rpc/openamp/caller/sp/openamp_caller.c    | 203 +++++++
+ .../rpc/openamp/caller/sp/openamp_caller.h    |  43 ++
+ .../rpc/openamp/caller/sp/openamp_mhu.c       | 191 ++++++
+ .../rpc/openamp/caller/sp/openamp_mhu.h       |  19 +
+ .../rpc/openamp/caller/sp/openamp_virtio.c    | 554 ++++++++++++++++++
+ .../rpc/openamp/caller/sp/openamp_virtio.h    |  24 +
+ deployments/se-proxy/opteesp/CMakeLists.txt   |   1 +
+ .../se-proxy/opteesp/default_se-proxy.dts.in  |   6 +
+ 11 files changed, 1074 insertions(+)
+ create mode 100644 components/rpc/openamp/caller/sp/component.cmake
+ create mode 100644 components/rpc/openamp/caller/sp/openamp_caller.c
+ create mode 100644 components/rpc/openamp/caller/sp/openamp_caller.h
+ create mode 100644 components/rpc/openamp/caller/sp/openamp_mhu.c
+ create mode 100644 components/rpc/openamp/caller/sp/openamp_mhu.h
+ create mode 100644 components/rpc/openamp/caller/sp/openamp_virtio.c
+ create mode 100644 components/rpc/openamp/caller/sp/openamp_virtio.h
+
+diff --git a/components/rpc/common/caller/rpc_caller.c b/components/rpc/common/caller/rpc_caller.c
+index 2dceabeb..20d889c1 100644
+--- a/components/rpc/common/caller/rpc_caller.c
++++ b/components/rpc/common/caller/rpc_caller.c
+@@ -37,3 +37,13 @@ void rpc_caller_end(struct rpc_caller *s, rpc_call_handle handle)
+ {
+ 	s->call_end(s->context, handle);
+ }
++
++void *rpc_caller_virt_to_phys(struct rpc_caller *s, void *va)
++{
++	return s->virt_to_phys(s->context, va);
++}
++
++void *rpc_caller_phys_to_virt(struct rpc_caller *s, void *pa)
++{
++	return s->phys_to_virt(s->context, pa);
++}
+diff --git a/components/rpc/common/interface/rpc_caller.h b/components/rpc/common/interface/rpc_caller.h
+index 387489cd..ef9bb649 100644
+--- a/components/rpc/common/interface/rpc_caller.h
++++ b/components/rpc/common/interface/rpc_caller.h
+@@ -45,6 +45,10 @@ struct rpc_caller
+ 		     	rpc_opstatus_t *opstatus, uint8_t **resp_buf, size_t *resp_len);
+ 
+ 	void (*call_end)(void *context, rpc_call_handle handle);
++
++	void *(*virt_to_phys)(void *context, void *va);
++
++	void *(*phys_to_virt)(void *context, void *pa);
+ };
+ 
+ /*
+@@ -87,6 +91,10 @@ RPC_CALLER_EXPORTED rpc_status_t rpc_caller_invoke(struct rpc_caller *s, rpc_cal
+  */
+ RPC_CALLER_EXPORTED void rpc_caller_end(struct rpc_caller *s, rpc_call_handle handle);
+ 
++RPC_CALLER_EXPORTED void *rpc_caller_virt_to_phys(struct rpc_caller *s, void *va);
++
++RPC_CALLER_EXPORTED void *rpc_caller_phys_to_virt(struct rpc_caller *s, void *pa);
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/components/rpc/openamp/caller/sp/component.cmake b/components/rpc/openamp/caller/sp/component.cmake
+new file mode 100644
+index 00000000..fc919529
+--- /dev/null
++++ b/components/rpc/openamp/caller/sp/component.cmake
+@@ -0,0 +1,15 @@
++#-------------------------------------------------------------------------------
++# Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++#-------------------------------------------------------------------------------
++if (NOT DEFINED TGT)
++	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
++endif()
++
++target_sources(${TGT} PRIVATE
++	"${CMAKE_CURRENT_LIST_DIR}/openamp_caller.c"
++	"${CMAKE_CURRENT_LIST_DIR}/openamp_virtio.c"
++	"${CMAKE_CURRENT_LIST_DIR}/openamp_mhu.c"
++	)
+diff --git a/components/rpc/openamp/caller/sp/openamp_caller.c b/components/rpc/openamp/caller/sp/openamp_caller.c
+new file mode 100644
+index 00000000..6cdfb756
+--- /dev/null
++++ b/components/rpc/openamp/caller/sp/openamp_caller.c
+@@ -0,0 +1,203 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021, Linaro Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#include <stddef.h>
++#include <trace.h>
++#include "openamp_caller.h"
++#include "openamp_mhu.h"
++#include "openamp_virtio.h"
++#include <protocols/rpc/common/packed-c/status.h>
++
++#define OPENAMP_TRANSACTION_IDLE	0x0
++#define OPENAMP_TRANSACTION_INPROGRESS	0x1
++#define OPENAMP_TRANSACTION_INVOKED	0x2
++
++static rpc_call_handle openamp_call_begin(void *context, uint8_t **req_buf,
++					  size_t req_len)
++{
++	struct openamp_caller *openamp = context;
++	const struct openamp_platform_ops *ops = openamp->platform_ops;
++	rpc_call_handle handle;
++	int ret;
++
++	if (!req_buf) {
++		EMSG("openamp: call_begin: not req_buf");
++		return NULL;
++	}
++
++	if (req_len > UINT32_MAX || req_len == 0) {
++		EMSG("openamp: call_begin: resp_len invalid: %lu", req_len);
++		return NULL;
++	}
++
++	if (openamp->status != OPENAMP_TRANSACTION_IDLE) {
++		EMSG("openamp: call_begin: transaction not idle");
++		return NULL;
++	}
++
++	ret = ops->platform_call_begin(openamp, req_buf, req_len);
++	if (ret < 0) {
++		EMSG("openamp: call_begin: platform begin failed: %d", ret);
++		return NULL;
++	}
++
++	openamp->status = OPENAMP_TRANSACTION_INPROGRESS;
++	handle = openamp;
++
++	return handle;
++}
++
++static rpc_status_t openamp_call_invoke(void *context, rpc_call_handle handle,
++					uint32_t opcode, int *opstatus,
++					uint8_t **resp_buf, size_t *resp_len)
++{
++	struct openamp_caller *openamp = context;
++	const struct openamp_platform_ops *ops = openamp->platform_ops;
++	rpc_status_t status;
++	int ret;
++
++	(void)opcode;
++
++	if ((handle != openamp) || !opstatus || !resp_buf || !resp_len) {
++		EMSG("openamp: call_invoke: invalid arguments");
++		return TS_RPC_ERROR_INVALID_PARAMETER;
++	}
++
++	if (openamp->status != OPENAMP_TRANSACTION_INPROGRESS) {
++		EMSG("openamp: call_invoke: transaction needed to be started");
++		return TS_RPC_ERROR_NOT_READY;
++	}
++
++	ret = ops->platform_call_invoke(openamp, opstatus, resp_buf, resp_len);
++	if (ret < 0)
++		return TS_RPC_ERROR_INTERNAL;
++
++	openamp->status = OPENAMP_TRANSACTION_INVOKED;
++	*opstatus = 0;
++
++	return TS_RPC_CALL_ACCEPTED;
++}
++
++static void openamp_call_end(void *context, rpc_call_handle handle)
++{
++	struct openamp_caller *openamp = context;
++	const struct openamp_platform_ops *ops = openamp->platform_ops;
++
++	if (handle != openamp) {
++		EMSG("openamp: call_end: invalid arguments");
++		return;
++	}
++
++	if (openamp->status == OPENAMP_TRANSACTION_IDLE) {
++		EMSG("openamp: call_end: transaction idle");
++		return;
++	}
++
++	ops->platform_call_end(openamp);
++
++	openamp->status = OPENAMP_TRANSACTION_IDLE;
++}
++
++static void *openamp_virt_to_phys(void *context, void *va)
++{
++	struct openamp_caller *openamp = context;
++	const struct openamp_platform_ops *ops = openamp->platform_ops;
++
++	return ops->platform_virt_to_phys(openamp, va);
++}
++
++static void *openamp_phys_to_virt(void *context, void *pa)
++{
++	struct openamp_caller *openamp = context;
++	const struct openamp_platform_ops *ops = openamp->platform_ops;
++
++	return ops->platform_phys_to_virt(openamp, pa);
++}
++
++static int openamp_init(struct openamp_caller *openamp)
++{
++	const struct openamp_platform_ops *ops = openamp->platform_ops;
++	int ret;
++
++	ret = ops->transport_init(openamp);
++	if (ret < 0)
++		return ret;
++
++	ret = ops->platform_init(openamp);
++	if (ret < 0)
++		goto denit_transport;
++
++	return 0;
++
++denit_transport:
++	ops->transport_deinit(openamp);
++
++	return ret;
++}
++
++static const struct openamp_platform_ops openamp_virtio_ops = {
++	.transport_init = openamp_mhu_init,
++	.transport_deinit = openamp_mhu_deinit,
++	.transport_notify = openamp_mhu_notify_peer,
++	.transport_receive = openamp_mhu_receive,
++	.platform_init = openamp_virtio_init,
++	.platform_call_begin = openamp_virtio_call_begin,
++	.platform_call_invoke = openamp_virtio_call_invoke,
++	.platform_call_end = openamp_virtio_call_end,
++	.platform_virt_to_phys = openamp_virtio_virt_to_phys,
++	.platform_phys_to_virt = openamp_virtio_phys_to_virt,
++};
++
++struct rpc_caller *openamp_caller_init(struct openamp_caller *openamp)
++{
++	struct rpc_caller *rpc = &openamp->rpc_caller;
++	int ret;
++
++	if (openamp->ref_count)
++		return rpc;
++
++	rpc_caller_init(rpc, openamp);
++
++	rpc->call_begin = openamp_call_begin;
++	rpc->call_invoke = openamp_call_invoke;
++	rpc->call_end = openamp_call_end;
++	rpc->virt_to_phys = openamp_virt_to_phys;
++	rpc->phys_to_virt = openamp_phys_to_virt;
++	openamp->platform_ops = &openamp_virtio_ops;
++
++	ret = openamp_init(openamp);
++	if (ret < 0) {
++		EMSG("openamp_init: failed to start: %d", ret);
++		return rpc;
++	}
++	openamp->ref_count++;
++
++	return rpc;
++}
++
++void openamp_caller_deinit(struct openamp_caller *openamp)
++{
++	struct rpc_caller *rpc = &openamp->rpc_caller;
++
++	if (--openamp->ref_count)
++		return;
++
++	rpc->context = NULL;
++	rpc->call_begin = NULL;
++	rpc->call_invoke = NULL;
++	rpc->call_end = NULL;
++}
++
++int openamp_caller_discover(struct openamp_caller *openamp)
++{
++	return openamp_init(openamp);
++}
++
++int openamp_caller_open(struct openamp_caller *openamp)
++{
++
++}
+diff --git a/components/rpc/openamp/caller/sp/openamp_caller.h b/components/rpc/openamp/caller/sp/openamp_caller.h
+new file mode 100644
+index 00000000..3fb67c56
+--- /dev/null
++++ b/components/rpc/openamp/caller/sp/openamp_caller.h
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021, Linaro Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++#ifndef OPENAMP_CALLER_H
++#define OPENAMP_CALLER_H
++
++#include <stddef.h>
++#include <rpc_caller.h>
++
++struct openamp_caller {
++	struct rpc_caller rpc_caller;
++	const struct openamp_platform_ops *platform_ops;
++	uint32_t ref_count;
++	uint8_t status;
++
++	void *transport;
++	void *platform;
++};
++
++struct openamp_platform_ops {
++	int (*transport_init)(struct openamp_caller *openamp);
++	int (*transport_deinit)(struct openamp_caller *openamp);
++	int (*transport_notify)(struct openamp_caller *openamp);
++	int (*transport_receive)(struct openamp_caller *openamp);
++	int (*platform_init)(struct openamp_caller *openamp);
++	int (*platform_deinit)(struct openamp_caller *openamp);
++	int (*platform_call_begin)(struct openamp_caller *openamp,
++				   uint8_t **req_buf, size_t req_len);
++	int (*platform_call_invoke)(struct openamp_caller *openamp,
++				    int *opstatus, uint8_t **resp_buf,
++				    size_t *resp_len);
++	int (*platform_call_end)(struct openamp_caller *openamp);
++	void *(*platform_virt_to_phys)(struct openamp_caller *openamp, void *va);
++	void *(*platform_phys_to_virt)(struct openamp_caller *openamp, void *pa);
++};
++
++struct rpc_caller *openamp_caller_init(struct openamp_caller *openamp);
++void openamp_caller_deinit(struct openamp_caller *openamp);
++
++#endif
+diff --git a/components/rpc/openamp/caller/sp/openamp_mhu.c b/components/rpc/openamp/caller/sp/openamp_mhu.c
+new file mode 100644
+index 00000000..ffdadaf8
+--- /dev/null
++++ b/components/rpc/openamp/caller/sp/openamp_mhu.c
+@@ -0,0 +1,191 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021, Linaro Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#include <config/interface/config_store.h>
++#include <config/interface/config_blob.h>
++#include <platform/interface/device_region.h>
++#include <platform/drivers/arm/mhu_driver/mhu_v2.h>
++#include <trace.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <stddef.h>
++#include <limits.h>
++
++#include "openamp_caller.h"
++
++#define MHU_V_2_NOTIFY_CHANNEL	0
++#define MHU_V_2_NOTIFY_VALUE	0xff
++
++struct openamp_mhu {
++	struct device_region rx_region;
++	struct device_region tx_region;
++	struct mhu_v2_x_dev_t rx_dev;
++	struct mhu_v2_x_dev_t tx_dev;
++};
++
++static int openamp_mhu_device_get(const char *dev,
++				  struct device_region *dev_region)
++{
++	bool found;
++
++	found = config_store_query(CONFIG_CLASSIFIER_DEVICE_REGION, dev, 0,
++				   dev_region, sizeof(*dev_region));
++	if (!found)
++		return -EINVAL;
++
++	if (!dev_region->base_addr)
++		return -EINVAL;
++
++	IMSG("mhu: device region found: %s addr: 0x%x size: %d", dev,
++	     dev_region->base_addr, dev_region->io_region_size);
++
++	return 0;
++}
++
++int openamp_mhu_receive(struct openamp_caller *openamp)
++{
++	struct mhu_v2_x_dev_t *rx_dev;
++	enum mhu_v2_x_error_t ret;
++	struct openamp_mhu *mhu;
++	uint32_t channel = 0;
++	uint32_t irq_status;
++
++	if (!openamp->transport) {
++		EMSG("openamp: mhu: receive transport not initialized");
++		return -EINVAL;
++	}
++
++	mhu = openamp->transport;
++	rx_dev = &mhu->rx_dev;
++
++	irq_status = 0;
++
++	do {
++		irq_status = mhu_v2_x_get_interrupt_status(rx_dev);
++	} while(!irq_status);
++
++	ret = mhu_v2_1_get_ch_interrupt_num(rx_dev, &channel);
++
++	ret = mhu_v2_x_channel_clear(rx_dev, channel);
++	if (ret != MHU_V_2_X_ERR_NONE) {
++		EMSG("openamp: mhu: failed to clear channel: %d", channel);
++		return -EPROTO;
++	}
++
++	return 0;
++}
++
++int openamp_mhu_notify_peer(struct openamp_caller *openamp)
++{
++	struct mhu_v2_x_dev_t *tx_dev;
++	enum mhu_v2_x_error_t ret;
++	struct openamp_mhu *mhu;
++	uint32_t access_ready;
++
++	if (!openamp->transport) {
++		EMSG("openamp: mhu: notify transport not initialized");
++		return -EINVAL;
++	}
++
++	mhu = openamp->transport;
++	tx_dev = &mhu->tx_dev;
++
++	ret = mhu_v2_x_set_access_request(tx_dev);
++	if (ret != MHU_V_2_X_ERR_NONE) {
++		EMSG("openamp: mhu: set access request failed");
++		return -EPROTO;
++	}
++
++	do {
++		ret = mhu_v2_x_get_access_ready(tx_dev, &access_ready);
++		if (ret != MHU_V_2_X_ERR_NONE) {
++			EMSG("openamp: mhu: failed to get access_ready");
++			return -EPROTO;
++		}
++	} while (!access_ready);
++
++	ret = mhu_v2_x_channel_send(tx_dev, MHU_V_2_NOTIFY_CHANNEL,
++				    MHU_V_2_NOTIFY_VALUE);
++	if (ret != MHU_V_2_X_ERR_NONE) {
++		EMSG("openamp: mhu: failed send over channel");
++		return -EPROTO;
++	}
++
++	ret = mhu_v2_x_reset_access_request(tx_dev);
++	if (ret != MHU_V_2_X_ERR_NONE) {
++		EMSG("openamp: mhu: failed reset access request");
++		return -EPROTO;
++	}
++
++	return 0;
++}
++
++int openamp_mhu_init(struct openamp_caller *openamp)
++{
++	struct mhu_v2_x_dev_t *rx_dev;
++	struct mhu_v2_x_dev_t *tx_dev;
++	struct openamp_mhu *mhu;
++	int ret;
++
++	/* if we already have initialized skip this */
++	if (openamp->transport)
++		return 0;
++
++	mhu = malloc(sizeof(*mhu));
++	if (!mhu)
++		return -1;
++
++	ret = openamp_mhu_device_get("mhu-sender", &mhu->tx_region);
++	if (ret < 0)
++		goto free_mhu;
++
++	ret = openamp_mhu_device_get("mhu-receiver", &mhu->rx_region);
++	if (ret < 0)
++		goto free_mhu;
++
++	rx_dev = &mhu->rx_dev;
++	tx_dev = &mhu->tx_dev;
++
++	rx_dev->base =  (unsigned int)mhu->rx_region.base_addr;
++	rx_dev->frame = MHU_V2_X_RECEIVER_FRAME;
++
++	tx_dev->base =  (unsigned int)mhu->tx_region.base_addr;
++	tx_dev->frame = MHU_V2_X_SENDER_FRAME;
++
++	ret = mhu_v2_x_driver_init(rx_dev, MHU_REV_READ_FROM_HW);
++	if (ret < 0)
++		goto free_mhu;
++
++	ret = mhu_v2_x_driver_init(tx_dev, MHU_REV_READ_FROM_HW);
++	if (ret < 0)
++		goto free_mhu;
++
++	openamp->transport = (void *)mhu;
++
++	return 0;
++
++free_mhu:
++	free(mhu);
++
++	return ret;
++}
++
++int openamp_mhu_deinit(struct openamp_caller *openamp)
++{
++	struct openamp_mhu *mhu;
++
++	if (!openamp->transport)
++		return 0;
++
++	mhu = openamp->transport;
++	free(mhu);
++
++	openamp->transport = NULL;
++
++	return 0;
++}
+diff --git a/components/rpc/openamp/caller/sp/openamp_mhu.h b/components/rpc/openamp/caller/sp/openamp_mhu.h
+new file mode 100644
+index 00000000..2ae5cb8e
+--- /dev/null
++++ b/components/rpc/openamp/caller/sp/openamp_mhu.h
+@@ -0,0 +1,19 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021, Linaro Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++#ifndef OPENAMP_MHU_H
++#define OPENAMP_MHU_H
++
++#include <stddef.h>
++#include "openamp_caller.h"
++
++int openamp_mhu_init(struct openamp_caller *openamp);
++int openamp_mhu_deinit(struct openamp_caller *openamp);
++
++int openamp_mhu_notify_peer(struct openamp_caller *openamp);
++int openamp_mhu_receive(struct openamp_caller *openamp);
++
++#endif
+diff --git a/components/rpc/openamp/caller/sp/openamp_virtio.c b/components/rpc/openamp/caller/sp/openamp_virtio.c
+new file mode 100644
+index 00000000..06e0735b
+--- /dev/null
++++ b/components/rpc/openamp/caller/sp/openamp_virtio.c
+@@ -0,0 +1,554 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021, Linaro Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#include <metal/device.h>
++#include <metal/spinlock.h>
++#include <openamp/open_amp.h>
++#include <platform/interface/device_region.h>
++#include <config/interface/config_store.h>
++
++#include <stddef.h>
++#include "openamp_caller.h"
++
++#define OPENAMP_SHEM_DEVICE_NAME "openamp-virtio"
++#define OPENAMP_RPMSG_ENDPOINT_NAME OPENAMP_SHEM_DEVICE_NAME
++#define OPENAMP_RPMSG_ENDPOINT_ADDR 1024
++
++#define OPENAMP_SHEM_PHYS 0x88000000
++#define OPENAMP_SHEM_PHYS_PAGES 1
++#define OPENAMP_SHEM_SE_PHYS 0xa8000000
++
++#define OPENAMP_SHEM_VDEV_SIZE (4 * 1024)
++#define OPENAMP_SHEM_VRING_SIZE (4 * 1024)
++
++#define OPENAMP_BUFFER_NO_WAIT  0
++#define OPENAMP_BUFFER_WAIT     1
++
++#define VIRTQUEUE_NR            2
++#define VQ_TX                   0
++#define VQ_RX                   1
++
++#define VRING_DESCRIPTORS       16
++#define VRING_ALIGN             4
++
++#define container_of(ptr, type, member) \
++	((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
++
++struct openamp_virtio_shm {
++	uintptr_t base_addr;
++	size_t size;
++	uintptr_t vdev_status;
++	size_t vdev_status_size;
++	uintptr_t payload_addr;
++	size_t payload_size;
++	uintptr_t vring_tx;
++	size_t vring_tx_size;
++	uintptr_t vring_rx;
++	size_t vring_rx_size;
++
++	metal_phys_addr_t shm_physmap[OPENAMP_SHEM_PHYS_PAGES];
++};
++
++struct openamp_virtio_metal {
++	struct metal_spinlock lock;
++	struct metal_device shm_dev;
++	struct metal_device *io_dev;
++
++	struct metal_io_region *io;
++	struct openamp_virtio_shm shm;
++};
++
++struct openamp_virtio_device {
++	struct virtio_device virtio_dev;
++	struct virtqueue *vq[VIRTQUEUE_NR];
++	struct virtio_vring_info rvrings[VIRTQUEUE_NR];
++};
++
++struct openamp_virtio_rpmsg {
++	struct rpmsg_virtio_device rpmsg_vdev;
++	struct rpmsg_endpoint ep;
++	uint8_t *req_buf;
++	uint32_t req_len;
++	uint8_t *resp_buf;
++	size_t resp_len;
++};
++
++struct openamp_virtio {
++	struct openamp_caller *openamp;
++	struct openamp_virtio_rpmsg rpmsg;
++	struct openamp_virtio_device vdev;
++	struct openamp_virtio_metal metal;
++};
++
++static struct openamp_virtio *openamp_virtio_from_dev(struct virtio_device *vdev)
++{
++	struct openamp_virtio_device *openamp_vdev;
++
++	openamp_vdev = container_of(vdev, struct openamp_virtio_device,
++			    virtio_dev);
++
++	return container_of(openamp_vdev, struct openamp_virtio, vdev);
++}
++
++static struct openamp_virtio_rpmsg *openamp_virtio_rpmsg_from_dev(struct rpmsg_device *rdev)
++{
++	struct rpmsg_virtio_device *rvdev;
++
++	rvdev = container_of(rdev, struct rpmsg_virtio_device, rdev);
++
++	return container_of(rvdev, struct openamp_virtio_rpmsg, rpmsg_vdev);
++
++}
++
++static void openamp_virtio_metal_device_setup(struct metal_device *shm_dev,
++					      struct openamp_virtio_shm *shm)
++{
++	struct metal_io_region *shm_region;
++
++	shm_region = &shm_dev->regions[0];
++
++	shm_dev->name = OPENAMP_SHEM_DEVICE_NAME;
++	shm_dev->num_regions = 1;
++
++	shm_region->virt = (void *)shm->payload_addr;
++	shm_region->size = shm->payload_size;
++
++	shm_region->physmap = &shm->shm_physmap;
++	shm_region->page_shift = (metal_phys_addr_t)(-1);
++	shm_region->page_mask = (metal_phys_addr_t)(-1);
++}
++
++static int openamp_virtio_metal_init(struct openamp_virtio_metal *metal)
++{
++	struct metal_init_params params = METAL_INIT_DEFAULTS;
++	struct metal_device *shm_dev = &metal->shm_dev;
++	int ret;
++
++	openamp_virtio_metal_device_setup(shm_dev, &metal->shm);
++
++	metal_spinlock_init(&metal->lock);
++
++	ret = metal_init(&params);
++	if (ret < 0)
++		return ret;
++
++	ret = metal_register_generic_device(shm_dev);
++	if (ret < 0)
++		goto metal_finish;
++
++	ret = metal_device_open("generic", OPENAMP_SHEM_DEVICE_NAME,
++				&metal->io_dev);
++	if (ret < 0)
++		goto metal_finish;
++
++	metal->io = metal_device_io_region(metal->io_dev, 0);
++	if (!metal->io) {
++		EMSG("openamp: virtio: failed to init metal io");
++		ret = -EPROTO;
++		goto metal_finish;
++	}
++
++	return 0;
++
++metal_finish:
++	metal_finish();
++	return ret;
++}
++
++static unsigned char openamp_virtio_status_get(struct virtio_device *vdev)
++{
++	struct openamp_virtio *virtio = openamp_virtio_from_dev(vdev);
++	struct openamp_virtio_shm *shm = &virtio->metal.shm;
++
++	uint32_t status = *(volatile uint32_t *)shm->vdev_status;
++
++	return status;
++}
++
++static void openamp_virtio_status_set(struct virtio_device *vdev,
++				      unsigned char status)
++{
++	struct openamp_virtio *virtio = openamp_virtio_from_dev(vdev);
++	struct openamp_virtio_shm *shm = &virtio->metal.shm;
++
++	*(volatile uint32_t *)shm->vdev_status = status;
++}
++
++static int count;
++
++static uint32_t openamp_virtio_features_get(struct virtio_device *vdev)
++{
++	return 1 << VIRTIO_RPMSG_F_NS;
++}
++
++static void openamp_virtio_notify(struct virtqueue *vq)
++{
++	struct openamp_virtio_device *openamp_vdev;
++	struct openamp_caller *openamp;
++	struct openamp_virtio *virtio;
++	int ret;
++
++	openamp_vdev = container_of(vq->vq_dev, struct openamp_virtio_device, virtio_dev);
++	virtio = container_of(openamp_vdev, struct openamp_virtio, vdev);
++	openamp = virtio->openamp;
++
++	ret = openamp->platform_ops->transport_notify(openamp);
++	if (ret < 0)
++		EMSG("openamp: virtio: erro in transport_notify: %d", ret);
++}
++
++const static struct virtio_dispatch openamp_virtio_dispatch = {
++	.get_status = openamp_virtio_status_get,
++	.set_status = openamp_virtio_status_set,
++	.get_features = openamp_virtio_features_get,
++	.notify = openamp_virtio_notify,
++};
++
++static int openamp_virtio_device_setup(struct openamp_virtio *virtio)
++{
++	struct openamp_virtio_metal *metal = &virtio->metal;
++	struct openamp_virtio_device *openamp_vdev = &virtio->vdev;
++	struct virtio_device *vdev = &openamp_vdev->virtio_dev;
++	struct openamp_virtio_shm *shm = &metal->shm;
++	struct virtio_vring_info *rvring;
++
++	rvring = &openamp_vdev->rvrings[0];
++
++	vdev->role = RPMSG_REMOTE;
++	vdev->vrings_num = VIRTQUEUE_NR;
++	vdev->func = &openamp_virtio_dispatch;
++
++	openamp_vdev->vq[VQ_TX] = virtqueue_allocate(VRING_DESCRIPTORS);
++	if (!openamp_vdev->vq[VQ_TX]) {
++		EMSG("openamp: virtio: failed to allocate virtqueue 0");
++		return -ENOMEM;
++	}
++	rvring->io = metal->io;
++	rvring->info.vaddr = (void *)shm->vring_tx;
++	rvring->info.num_descs = VRING_DESCRIPTORS;
++	rvring->info.align = VRING_ALIGN;
++	rvring->vq = openamp_vdev->vq[VQ_TX];
++
++	openamp_vdev->vq[VQ_RX] = virtqueue_allocate(VRING_DESCRIPTORS);
++	if (!openamp_vdev->vq[VQ_RX]) {
++		EMSG("openamp: virtio: failed to allocate virtqueue 1");
++		goto free_vq;
++	}
++	rvring = &openamp_vdev->rvrings[VQ_RX];
++	rvring->io = metal->io;
++	rvring->info.vaddr = (void *)shm->vring_rx;
++	rvring->info.num_descs = VRING_DESCRIPTORS;
++	rvring->info.align = VRING_ALIGN;
++	rvring->vq = openamp_vdev->vq[VQ_RX];
++
++	vdev->vrings_info = &openamp_vdev->rvrings[0];
++
++	return 0;
++
++free_vq:
++	virtqueue_free(openamp_vdev->vq[VQ_TX]);
++	virtqueue_free(openamp_vdev->vq[VQ_RX]);
++
++	return -ENOMEM;
++}
++
++static int openamp_virtio_rpmsg_endpoint_callback(struct rpmsg_endpoint *ep,
++						  void *data, size_t len,
++						  uint32_t src, void *priv)
++{
++	struct openamp_virtio_rpmsg *vrpmsg;
++	struct rpmsg_device *rdev;
++	struct openamp_virtio *virtio;
++
++	rdev = ep->rdev;
++	vrpmsg = openamp_virtio_rpmsg_from_dev(rdev);
++	virtio = container_of(vrpmsg, struct openamp_virtio, rpmsg);
++
++	rpmsg_hold_rx_buffer(ep, data);
++	vrpmsg->resp_buf = data;
++	vrpmsg->resp_len = len;
++
++	return 0;
++}
++
++static void openamp_virtio_rpmsg_service_unbind(struct rpmsg_endpoint *ep)
++{
++	struct openamp_virtio_rpmsg *vrpmsg;
++	struct rpmsg_device *rdev;
++
++	rdev = container_of(ep, struct rpmsg_device, ns_ept);
++	vrpmsg = openamp_virtio_rpmsg_from_dev(rdev);
++
++	rpmsg_destroy_ept(&vrpmsg->ep);
++}
++
++static void openamp_virtio_rpmsg_endpoint_bind(struct rpmsg_device *rdev,
++					       const char *name,
++					       unsigned int dest)
++{
++	struct openamp_virtio_rpmsg *vrpmsg;
++
++	vrpmsg = openamp_virtio_rpmsg_from_dev(rdev);
++
++	rpmsg_create_ept(&vrpmsg->ep, rdev, name, RPMSG_ADDR_ANY, dest,
++			 openamp_virtio_rpmsg_endpoint_callback,
++			 openamp_virtio_rpmsg_service_unbind);
++}
++
++static int openamp_virtio_rpmsg_device_setup(struct openamp_virtio *virtio,
++					     struct device_region *virtio_dev)
++{
++	struct openamp_virtio_rpmsg *vrpmsg = &virtio->rpmsg;
++	struct rpmsg_virtio_device *rpmsg_vdev = &vrpmsg->rpmsg_vdev;
++	struct openamp_virtio_device *openamp_vdev = &virtio->vdev;
++	struct virtio_device *vdev = &openamp_vdev->virtio_dev;
++	struct openamp_virtio_metal *metal = &virtio->metal;
++	int ret;
++
++	/*
++	 * we assume here that we are the client side and do not need to
++	 * initialize the share memory poll (this is done at server side).
++	 */
++	ret = rpmsg_init_vdev(rpmsg_vdev, vdev,
++			      openamp_virtio_rpmsg_endpoint_bind, metal->io,
++			      NULL);
++	if (ret < 0) {
++		EMSG("openamp: virtio: init vdev failed: %d", ret);
++		return ret;
++	}
++
++
++	ret = rpmsg_create_ept(&vrpmsg->ep, &rpmsg_vdev->rdev,
++			       OPENAMP_RPMSG_ENDPOINT_NAME, RPMSG_ADDR_ANY,
++			       RPMSG_ADDR_ANY,
++			       openamp_virtio_rpmsg_endpoint_callback,
++			       openamp_virtio_rpmsg_service_unbind);
++	if (ret < 0) {
++		EMSG("openamp: virtio: failed to create endpoint: %d", ret);
++		return ret;
++	}
++
++	/* set default remote addr */
++	vrpmsg->ep.dest_addr = OPENAMP_RPMSG_ENDPOINT_ADDR;
++
++	return 0;
++}
++
++static void openamp_virtio_shm_set(struct openamp_virtio *virtio,
++				   struct device_region *virtio_region)
++{
++	struct openamp_virtio_shm *shm = &virtio->metal.shm;
++
++	shm->base_addr = virtio_region->base_addr;
++	shm->size = virtio_region->io_region_size;
++
++	shm->vdev_status = shm->base_addr;
++	shm->vdev_status_size = OPENAMP_SHEM_VDEV_SIZE;
++
++	shm->vring_rx = shm->base_addr + shm->size -
++		(2 * OPENAMP_SHEM_VRING_SIZE);
++	shm->vring_rx_size = OPENAMP_SHEM_VRING_SIZE;
++
++	shm->vring_tx = shm->vring_rx + shm->vring_rx_size;
++	shm->vring_tx_size = OPENAMP_SHEM_VRING_SIZE;
++
++	shm->payload_addr = shm->vdev_status + shm->vdev_status_size;
++	shm->payload_size = shm->size - shm->vdev_status_size -
++		shm->vring_rx_size - shm->vring_tx_size;
++
++	shm->shm_physmap[0] = OPENAMP_SHEM_PHYS + shm->vdev_status_size;
++
++	IMSG("SHEM: base: 0x%0x size: 0x%0x size: %d",
++	     shm->base_addr, shm->size, shm->size);
++	IMSG("VDEV: base: 0x%0x size: 0x%0x size: %d",
++	     shm->vdev_status, shm->vdev_status_size, shm->vdev_status_size);
++	IMSG("PAYLOAD: base: 0x%0x size: 0x%0x size: %d",
++	     shm->payload_addr, shm->payload_size, shm->payload_size);
++	IMSG("VRING_TX: base: 0x%0x size: 0x%0x size: %d",
++	     shm->vring_tx, shm->vring_tx_size, shm->vring_tx_size);
++	IMSG("VRING_RX: base: 0x%0x size: 0x%0x size: %d",
++	     shm->vring_rx, shm->vring_rx_size, shm->vring_rx_size);
++	IMSG("PHYMAP: base: 0x%0x", shm->shm_physmap[0]);
++}
++
++static int openamp_virtio_device_get(const char *dev,
++				     struct device_region *dev_region)
++{
++	bool found;
++
++	found = config_store_query(CONFIG_CLASSIFIER_DEVICE_REGION, dev, 0,
++				   dev_region, sizeof(*dev_region));
++	if (!found) {
++		EMSG("openamp: virtio: device region not found: %s", dev);
++		return -EINVAL;
++	}
++
++	if (dev_region->base_addr == 0 || dev_region->io_region_size == 0) {
++		EMSG("openamp: virtio: device region not valid");
++		return -EINVAL;
++	}
++
++	IMSG("openamp: virtio: device region found: %s addr: 0x%x size: %d",
++	     dev, dev_region->base_addr, dev_region->io_region_size);
++
++	return  0;
++}
++
++int openamp_virtio_call_begin(struct openamp_caller *openamp, uint8_t **req_buf,
++			      size_t req_len)
++{
++	struct openamp_virtio *virtio = openamp->platform;
++	struct openamp_virtio_rpmsg *vrpmsg = &virtio->rpmsg;
++	struct rpmsg_endpoint *ep = &vrpmsg->ep;
++
++
++	*req_buf = rpmsg_get_tx_payload_buffer(ep, &vrpmsg->req_len,
++					       OPENAMP_BUFFER_WAIT);
++	if (*req_buf == NULL)
++		return -EINVAL;
++
++	if (vrpmsg->req_len < req_len)
++		return -E2BIG;
++
++	vrpmsg->req_buf = *req_buf;
++
++	return 0;
++}
++
++int openamp_virtio_call_invoke(struct openamp_caller *openamp, int *opstatus,
++			       uint8_t **resp_buf, size_t *resp_len)
++{
++	const struct openamp_platform_ops *ops = openamp->platform_ops;
++	struct openamp_virtio *virtio = openamp->platform;
++	struct openamp_virtio_device *openamp_vdev = &virtio->vdev;
++	struct openamp_virtio_rpmsg *vrpmsg = &virtio->rpmsg;
++	struct rpmsg_endpoint *ep = &vrpmsg->ep;
++	int ret;
++
++	ret = rpmsg_send_nocopy(ep, vrpmsg->req_buf, vrpmsg->req_len);
++	if (ret < 0) {
++		EMSG("openamp: virtio: send nocopy failed: %d", ret);
++		return -EIO;
++	}
++
++	if (ret != vrpmsg->req_len) {
++		EMSG("openamp: virtio: send less bytes %d than requested %d",
++		     ret, vrpmsg->req_len);
++		return -EIO;
++	}
++
++	if (!ops->transport_receive)
++		return 0;
++
++	ret = ops->transport_receive(openamp);
++	if (ret < 0) {
++		EMSG("openamp: virtio: failed transport_receive");
++		return -EIO;
++	}
++
++	virtqueue_notification(openamp_vdev->vq[VQ_RX]);
++
++	*resp_buf = vrpmsg->resp_buf;
++	*resp_len = vrpmsg->resp_len;
++
++	return  0;
++}
++
++void openamp_virtio_call_end(struct openamp_caller *openamp)
++{
++	struct openamp_virtio *virtio = openamp->platform;
++	struct openamp_virtio_rpmsg *vrpmsg = &virtio->rpmsg;
++
++	rpmsg_release_rx_buffer(&vrpmsg->ep, vrpmsg->resp_buf);
++
++	vrpmsg->req_buf = NULL;
++	vrpmsg->req_len = 0;
++	vrpmsg->resp_buf = NULL;
++	vrpmsg->resp_len = 0;
++}
++
++void *openamp_virtio_virt_to_phys(struct openamp_caller *openamp, void *va)
++{
++	struct openamp_virtio *virtio = openamp->platform;
++	struct openamp_virtio_metal *metal = &virtio->metal;
++
++	return metal_io_virt_to_phys(metal->io, va);
++}
++
++void *openamp_virtio_phys_to_virt(struct openamp_caller *openamp, void *pa)
++{
++	struct openamp_virtio *virtio = openamp->platform;
++	struct openamp_virtio_metal *metal = &virtio->metal;
++
++	return metal_io_phys_to_virt(metal->io, pa);
++}
++
++int openamp_virtio_init(struct openamp_caller *openamp)
++{
++	struct device_region virtio_dev;
++	struct openamp_virtio *virtio;
++	int ret;
++
++	if (openamp->platform)
++		return 0;
++
++
++	virtio = malloc(sizeof(*virtio));
++	if (!virtio)
++		return -ENOMEM;
++
++	virtio->openamp = openamp;
++
++	ret = openamp_virtio_device_get(OPENAMP_SHEM_DEVICE_NAME, &virtio_dev);
++	if (ret < 0)
++		goto free_virtio;
++
++	openamp_virtio_shm_set(virtio, &virtio_dev);
++
++	ret = openamp_virtio_metal_init(&virtio->metal);
++	if (ret < 0)
++		goto free_virtio;
++
++	ret = openamp_virtio_device_setup(virtio);
++	if (ret < 0)
++		goto finish_metal;
++
++	ret = openamp_virtio_rpmsg_device_setup(virtio, &virtio_dev);
++	if (ret < 0) {
++		EMSG("openamp: virtio: rpmsg device setup failed: %d", ret);
++		goto finish_metal;
++	}
++
++	openamp->platform = virtio;
++
++	return 0;
++
++finish_metal:
++	metal_finish();
++
++free_virtio:
++	free(virtio);
++
++	return ret;
++}
++
++int openamp_virtio_deinit(struct openamp_caller *openamp)
++{
++	struct openamp_virtio *virtio;
++
++	if (!openamp->platform)
++		return 0;
++
++	virtio = openamp->platform;
++
++	metal_finish();
++	free(virtio);
++
++	openamp->platform = NULL;
++
++	return 0;
++}
+diff --git a/components/rpc/openamp/caller/sp/openamp_virtio.h b/components/rpc/openamp/caller/sp/openamp_virtio.h
+new file mode 100644
+index 00000000..915128ff
+--- /dev/null
++++ b/components/rpc/openamp/caller/sp/openamp_virtio.h
+@@ -0,0 +1,24 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021, Linaro Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++#ifndef OPENAMP_VIRTIO_H
++#define OPENAMP_VIRTIO_H
++
++#include <stddef.h>
++#include "openamp_caller.h"
++
++int openamp_virtio_call_begin(struct openamp_caller *openamp, uint8_t **req_buf,
++			      size_t req_len);
++int openamp_virtio_call_invoke(struct openamp_caller *openamp, int *opstatus,
++			       uint8_t **resp_buf, size_t *resp_len);
++int openamp_virtio_call_end(struct openamp_caller *openamp);
++void *openamp_virtio_virt_to_phys(struct openamp_caller *openamp, void *va);
++void *openamp_virtio_phys_to_virt(struct openamp_caller *openamp, void *pa);
++
++int openamp_virtio_init(struct openamp_caller *openamp);
++int openamp_virtio_deinit(struct openamp_caller *openamp);
++
++#endif
+diff --git a/deployments/se-proxy/opteesp/CMakeLists.txt b/deployments/se-proxy/opteesp/CMakeLists.txt
+index 248bd7e3..1511bbad 100644
+--- a/deployments/se-proxy/opteesp/CMakeLists.txt
++++ b/deployments/se-proxy/opteesp/CMakeLists.txt
+@@ -75,6 +75,7 @@ add_components(TARGET "se-proxy"
+ 		"components/service/attestation/include"
+ 		"components/service/attestation/provider"
+ 		"components/service/attestation/provider/serializer/packed-c"
++		"components/rpc/openamp/caller/sp"
+ 
+ 		# Stub service provider backends
+ 		"components/rpc/dummy"
+diff --git a/deployments/se-proxy/opteesp/default_se-proxy.dts.in b/deployments/se-proxy/opteesp/default_se-proxy.dts.in
+index f351a592..55d49b31 100644
+--- a/deployments/se-proxy/opteesp/default_se-proxy.dts.in
++++ b/deployments/se-proxy/opteesp/default_se-proxy.dts.in
+@@ -32,6 +32,12 @@
+ 				pages-count = <16>;
+ 				attributes = <0x3>; /* read-write */
+ 			};
++			openamp-virtio {
++				/* Armv8 A Foundation Platform values */
++				base-address = <0x00000000 0x88000000>;
++				pages-count = <256>;
++				attributes = <0x3>; /* read-write */
++			};
+ 		};
+ 	};
+ };
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0010-add-psa-client-definitions-for-ff-m.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0010-add-psa-client-definitions-for-ff-m.patch
new file mode 100644
index 0000000..f41556a
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0010-add-psa-client-definitions-for-ff-m.patch
@@ -0,0 +1,299 @@
+From 791a1302d7b779f3aeee7d6f7c9fac00b4244c1b Mon Sep 17 00:00:00 2001
+From: Vishnu Banavath <vishnu.banavath@arm.com>
+Date: Fri, 3 Dec 2021 19:05:18 +0000
+Subject: [PATCH] add psa client definitions for ff-m
+
+Add PSA client definitions in common include to add future
+ff-m support.
+
+Signed-off-by: Rui Miguel Silva <rui.silva@arm.com>
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+
+---
+ .../service/common/include/psa/client.h       | 194 ++++++++++++++++++
+ components/service/common/include/psa/sid.h   |  71 +++++++
+ 2 files changed, 265 insertions(+)
+ create mode 100644 components/service/common/include/psa/client.h
+ create mode 100644 components/service/common/include/psa/sid.h
+
+diff --git a/components/service/common/include/psa/client.h b/components/service/common/include/psa/client.h
+new file mode 100644
+index 00000000..69ccf14f
+--- /dev/null
++++ b/components/service/common/include/psa/client.h
+@@ -0,0 +1,194 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef SERVICE_PSA_IPC_H
++#define SERVICE_PSA_IPC_H
++
++#include <stddef.h>
++#include <stdint.h>
++
++#include <rpc_caller.h>
++#include <psa/error.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++#ifndef IOVEC_LEN
++#define IOVEC_LEN(arr) ((uint32_t)(sizeof(arr)/sizeof(arr[0])))
++#endif
++
++/*********************** PSA Client Macros and Types *************************/
++
++typedef int32_t psa_handle_t;
++
++/**
++ * The version of the PSA Framework API that is being used to build the calling
++ * firmware. Only part of features of FF-M v1.1 have been implemented. FF-M v1.1
++ * is compatible with v1.0.
++ */
++#define PSA_FRAMEWORK_VERSION       (0x0101u)
++
++/**
++ * Return value from psa_version() if the requested RoT Service is not present
++ * in the system.
++ */
++#define PSA_VERSION_NONE            (0u)
++
++/**
++ * The zero-value null handle can be assigned to variables used in clients and
++ * RoT Services, indicating that there is no current connection or message.
++ */
++#define PSA_NULL_HANDLE             ((psa_handle_t)0)
++
++/**
++ * Tests whether a handle value returned by psa_connect() is valid.
++ */
++#define PSA_HANDLE_IS_VALID(handle) ((psa_handle_t)(handle) > 0)
++
++/**
++ * Converts the handle value returned from a failed call psa_connect() into
++ * an error code.
++ */
++#define PSA_HANDLE_TO_ERROR(handle) ((psa_status_t)(handle))
++
++/**
++ * Maximum number of input and output vectors for a request to psa_call().
++ */
++#define PSA_MAX_IOVEC               (4u)
++
++/**
++ * An IPC message type that indicates a generic client request.
++ */
++#define PSA_IPC_CALL                (0)
++
++/**
++ * A read-only input memory region provided to an RoT Service.
++ */
++struct __attribute__ ((__packed__)) psa_invec {
++    uint32_t base;           /*!< the start address of the memory buffer */
++    uint32_t len;                 /*!< the size in bytes                      */
++};
++
++/**
++ * A writable output memory region provided to an RoT Service.
++ */
++struct __attribute__ ((__packed__)) psa_outvec {
++    uint32_t base;                 /*!< the start address of the memory buffer */
++    uint32_t len;                 /*!< the size in bytes                      */
++};
++
++/*************************** PSA Client API **********************************/
++
++/**
++ * \brief Retrieve the version of the PSA Framework API that is implemented.
++ *
++ * \param[in] rpc_caller        RPC caller to use
++ * \return version              The version of the PSA Framework implementation
++ *                              that is providing the runtime services to the
++ *                              caller. The major and minor version are encoded
++ *                              as follows:
++ * \arg                           version[15:8] -- major version number.
++ * \arg                           version[7:0]  -- minor version number.
++ */
++uint32_t psa_framework_version(struct rpc_caller *caller);
++
++/**
++ * \brief Retrieve the version of an RoT Service or indicate that it is not
++ *        present on this system.
++ *
++ * \param[in] rpc_caller        RPC caller to use
++ * \param[in] sid               ID of the RoT Service to query.
++ *
++ * \retval PSA_VERSION_NONE     The RoT Service is not implemented, or the
++ *                              caller is not permitted to access the service.
++ * \retval > 0                  The version of the implemented RoT Service.
++ */
++uint32_t psa_version(struct rpc_caller *caller, uint32_t sid);
++
++/**
++ * \brief Connect to an RoT Service by its SID.
++ *
++ * \param[in] rpc_caller        RPC caller to use
++ * \param[in] sid               ID of the RoT Service to connect to.
++ * \param[in] version           Requested version of the RoT Service.
++ *
++ * \retval > 0                  A handle for the connection.
++ * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the
++ *                              connection.
++ * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the
++ *                              connection at the moment.
++ * \retval "PROGRAMMER ERROR"   The call is a PROGRAMMER ERROR if one or more
++ *                              of the following are true:
++ * \arg                           The RoT Service ID is not present.
++ * \arg                           The RoT Service version is not supported.
++ * \arg                           The caller is not allowed to access the RoT
++ *                                service.
++ */
++psa_handle_t psa_connect(struct rpc_caller *caller, uint32_t sid,
++			 uint32_t version);
++
++/**
++ * \brief Call an RoT Service on an established connection.
++ *
++ * \note  FF-M 1.0 proposes 6 parameters for psa_call but the secure gateway ABI
++ *        support at most 4 parameters. TF-M chooses to encode 'in_len',
++ *        'out_len', and 'type' into a 32-bit integer to improve efficiency.
++ *        Compared with struct-based encoding, this method saves extra memory
++ *        check and memory copy operation. The disadvantage is that the 'type'
++ *        range has to be reduced into a 16-bit integer. So with this encoding,
++ *        the valid range for 'type' is 0-32767.
++ *
++ * \param[in] rpc_caller        RPC caller to use
++ * \param[in] handle            A handle to an established connection.
++ * \param[in] type              The request type.
++ *                              Must be zero( \ref PSA_IPC_CALL) or positive.
++ * \param[in] in_vec            Array of input \ref psa_invec structures.
++ * \param[in] in_len            Number of input \ref psa_invec structures.
++ * \param[in,out] out_vec       Array of output \ref psa_outvec structures.
++ * \param[in] out_len           Number of output \ref psa_outvec structures.
++ *
++ * \retval >=0                  RoT Service-specific status value.
++ * \retval <0                   RoT Service-specific error code.
++ * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the
++ *                              RoT Service. The call is a PROGRAMMER ERROR if
++ *                              one or more of the following are true:
++ * \arg                           An invalid handle was passed.
++ * \arg                           The connection is already handling a request.
++ * \arg                           type < 0.
++ * \arg                           An invalid memory reference was provided.
++ * \arg                           in_len + out_len > PSA_MAX_IOVEC.
++ * \arg                           The message is unrecognized by the RoT
++ *                                Service or incorrectly formatted.
++ */
++psa_status_t psa_call(struct rpc_caller *caller, psa_handle_t handle,
++		      int32_t type, const struct psa_invec *in_vec,
++		      size_t in_len, struct psa_outvec *out_vec, size_t out_len);
++
++/**
++ * \brief Close a connection to an RoT Service.
++ *
++ * \param[in] rpc_caller        RPC caller to use
++ * \param[in] handle            A handle to an established connection, or the
++ *                              null handle.
++ *
++ * \retval void                 Success.
++ * \retval "PROGRAMMER ERROR"   The call is a PROGRAMMER ERROR if one or more
++ *                              of the following are true:
++ * \arg                           An invalid handle was provided that is not
++ *                                the null handle.
++ * \arg                           The connection is currently handling a
++ *                                request.
++ */
++void psa_close(struct rpc_caller *caller, psa_handle_t handle);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* SERVICE_PSA_IPC_H */
++
++
+diff --git a/components/service/common/include/psa/sid.h b/components/service/common/include/psa/sid.h
+new file mode 100644
+index 00000000..aaa973c6
+--- /dev/null
++++ b/components/service/common/include/psa/sid.h
+@@ -0,0 +1,71 @@
++/*
++ * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ *
++ */
++
++#ifndef __PSA_MANIFEST_SID_H__
++#define __PSA_MANIFEST_SID_H__
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/******** TFM_SP_PS ********/
++#define TFM_PROTECTED_STORAGE_SERVICE_SID                          (0x00000060U)
++#define TFM_PROTECTED_STORAGE_SERVICE_VERSION                      (1U)
++#define TFM_PROTECTED_STORAGE_SERVICE_HANDLE                       (0x40000101U)
++
++/* Invalid UID */
++#define TFM_PS_INVALID_UID 0
++
++/* PS message types that distinguish PS services. */
++#define TFM_PS_SET                1001
++#define TFM_PS_GET                1002
++#define TFM_PS_GET_INFO           1003
++#define TFM_PS_REMOVE             1004
++#define TFM_PS_GET_SUPPORT        1005
++
++/******** TFM_SP_ITS ********/
++#define TFM_INTERNAL_TRUSTED_STORAGE_SERVICE_SID                   (0x00000070U)
++#define TFM_INTERNAL_TRUSTED_STORAGE_SERVICE_VERSION               (1U)
++#define TFM_INTERNAL_TRUSTED_STORAGE_SERVICE_HANDLE                (0x40000102U)
++
++/******** TFM_SP_CRYPTO ********/
++#define TFM_CRYPTO_SID                                             (0x00000080U)
++#define TFM_CRYPTO_VERSION                                         (1U)
++#define TFM_CRYPTO_HANDLE                                          (0x40000100U)
++
++/******** TFM_SP_PLATFORM ********/
++#define TFM_SP_PLATFORM_SYSTEM_RESET_SID                           (0x00000040U)
++#define TFM_SP_PLATFORM_SYSTEM_RESET_VERSION                       (1U)
++#define TFM_SP_PLATFORM_IOCTL_SID                                  (0x00000041U)
++#define TFM_SP_PLATFORM_IOCTL_VERSION                              (1U)
++#define TFM_SP_PLATFORM_NV_COUNTER_SID                             (0x00000042U)
++#define TFM_SP_PLATFORM_NV_COUNTER_VERSION                         (1U)
++
++/******** TFM_SP_INITIAL_ATTESTATION ********/
++#define TFM_ATTESTATION_SERVICE_SID                                (0x00000020U)
++#define TFM_ATTESTATION_SERVICE_VERSION                            (1U)
++#define TFM_ATTESTATION_SERVICE_HANDLE                             (0x40000103U)
++
++/******** TFM_SP_FWU ********/
++#define TFM_FWU_WRITE_SID                                          (0x000000A0U)
++#define TFM_FWU_WRITE_VERSION                                      (1U)
++#define TFM_FWU_INSTALL_SID                                        (0x000000A1U)
++#define TFM_FWU_INSTALL_VERSION                                    (1U)
++#define TFM_FWU_ABORT_SID                                          (0x000000A2U)
++#define TFM_FWU_ABORT_VERSION                                      (1U)
++#define TFM_FWU_QUERY_SID                                          (0x000000A3U)
++#define TFM_FWU_QUERY_VERSION                                      (1U)
++#define TFM_FWU_REQUEST_REBOOT_SID                                 (0x000000A4U)
++#define TFM_FWU_REQUEST_REBOOT_VERSION                             (1U)
++#define TFM_FWU_ACCEPT_SID                                         (0x000000A5U)
++#define TFM_FWU_ACCEPT_VERSION                                     (1U)
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* __PSA_MANIFEST_SID_H__ */
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0011-Add-common-service-component-to-ipc-support.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0011-Add-common-service-component-to-ipc-support.patch
new file mode 100644
index 0000000..7ecb60f
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0011-Add-common-service-component-to-ipc-support.patch
@@ -0,0 +1,295 @@
+From b7e9e6fc59263f5daf4ae79eb758fa7647058338 Mon Sep 17 00:00:00 2001
+From: Vishnu Banavath <vishnu.banavath@arm.com>
+Date: Fri, 3 Dec 2021 19:13:03 +0000
+Subject: [PATCH] Add common service component to ipc support
+
+Add support for inter processor communication for PSA
+including, the openamp client side structures lib.
+
+Signed-off-by: Rui Miguel Silva <rui.silva@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+
+---
+ .../service/common/psa_ipc/component.cmake    |  13 ++
+ .../service/common/psa_ipc/service_psa_ipc.c  |  97 +++++++++++++
+ .../psa_ipc/service_psa_ipc_openamp_lib.h     | 131 ++++++++++++++++++
+ deployments/se-proxy/opteesp/CMakeLists.txt   |   1 +
+ 4 files changed, 242 insertions(+)
+ create mode 100644 components/service/common/psa_ipc/component.cmake
+ create mode 100644 components/service/common/psa_ipc/service_psa_ipc.c
+ create mode 100644 components/service/common/psa_ipc/service_psa_ipc_openamp_lib.h
+
+diff --git a/components/service/common/psa_ipc/component.cmake b/components/service/common/psa_ipc/component.cmake
+new file mode 100644
+index 00000000..5a1c9e62
+--- /dev/null
++++ b/components/service/common/psa_ipc/component.cmake
+@@ -0,0 +1,13 @@
++#-------------------------------------------------------------------------------
++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++#-------------------------------------------------------------------------------
++if (NOT DEFINED TGT)
++	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
++endif()
++
++target_sources(${TGT} PRIVATE
++	"${CMAKE_CURRENT_LIST_DIR}/service_psa_ipc.c"
++	)
+diff --git a/components/service/common/psa_ipc/service_psa_ipc.c b/components/service/common/psa_ipc/service_psa_ipc.c
+new file mode 100644
+index 00000000..e8093c20
+--- /dev/null
++++ b/components/service/common/psa_ipc/service_psa_ipc.c
+@@ -0,0 +1,97 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#include <stddef.h>
++#include <stdint.h>
++#include <string.h>
++#include <trace.h>
++
++#include <protocols/rpc/common/packed-c/status.h>
++#include <psa/error.h>
++#include <rpc_caller.h>
++
++#include <psa/client.h>
++#include "service_psa_ipc_openamp_lib.h"
++
++psa_handle_t psa_connect(struct rpc_caller *caller, uint32_t sid,
++			 uint32_t version)
++{
++	psa_status_t psa_status = PSA_SUCCESS;
++	struct s_openamp_msg *resp_msg = NULL;
++	struct ns_openamp_msg *req_msg;
++	rpc_call_handle rpc_handle;
++	size_t resp_len;
++	uint8_t *resp;
++	uint8_t *req;
++	int ret;
++
++	rpc_handle = rpc_caller_begin(caller, &req,
++				      sizeof(struct ns_openamp_msg));
++	if (!rpc_handle) {
++		EMSG("psa_connect: could not get handle");
++		return PSA_ERROR_GENERIC_ERROR;
++	}
++
++	req_msg = (struct ns_openamp_msg *)req;
++
++	req_msg->call_type = OPENAMP_PSA_CONNECT;
++	req_msg->params.psa_connect_params.sid = sid;
++	req_msg->params.psa_connect_params.version = version;
++
++	ret = rpc_caller_invoke(caller, rpc_handle, 0, &psa_status, &resp,
++				&resp_len);
++	if (ret != TS_RPC_CALL_ACCEPTED) {
++		EMSG("psa_connect: invoke failed: %d", ret);
++		return PSA_ERROR_GENERIC_ERROR;
++	}
++
++	if (psa_status == PSA_SUCCESS)
++		resp_msg = (struct s_openamp_msg *)resp;
++
++	rpc_caller_end(caller, rpc_handle);
++
++	return resp_msg ? (psa_handle_t)resp_msg->reply : PSA_NULL_HANDLE;
++}
++
++psa_status_t psa_call(struct rpc_caller *caller, psa_handle_t handle,
++		      int32_t type, const struct psa_invec *in_vec,
++		      size_t in_len, struct psa_outvec *out_vec, size_t out_len)
++{
++
++}
++
++void psa_close(struct rpc_caller *caller, psa_handle_t handle)
++{
++	psa_status_t psa_status = PSA_SUCCESS;
++	struct s_openamp_msg *resp_msg = NULL;
++	struct ns_openamp_msg *req_msg;
++	rpc_call_handle rpc_handle;
++	size_t resp_len;
++	uint8_t *resp;
++	uint8_t *req;
++	int ret;
++
++	rpc_handle = rpc_caller_begin(caller, &req,
++				      sizeof(struct ns_openamp_msg));
++	if (!rpc_handle) {
++		EMSG("psa_close: could not get handle");
++		return;
++	}
++
++	req_msg = (struct ns_openamp_msg *)req;
++
++	req_msg->call_type = OPENAMP_PSA_CLOSE;
++	req_msg->params.psa_close_params.handle = handle;
++
++	ret = rpc_caller_invoke(caller, rpc_handle, 0, &psa_status, &resp,
++				&resp_len);
++	if (ret != TS_RPC_CALL_ACCEPTED) {
++		EMSG("psa_close: invoke failed: %d", ret);
++		return;
++	}
++
++	rpc_caller_end(caller, rpc_handle);
++}
+diff --git a/components/service/common/psa_ipc/service_psa_ipc_openamp_lib.h b/components/service/common/psa_ipc/service_psa_ipc_openamp_lib.h
+new file mode 100644
+index 00000000..33ea9666
+--- /dev/null
++++ b/components/service/common/psa_ipc/service_psa_ipc_openamp_lib.h
+@@ -0,0 +1,131 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef SERVICE_PSA_IPC_OPENAMP_LIB_H
++#define SERVICE_PSA_IPC_OPENAMP_LIB_H
++
++#include <stddef.h>
++#include <stdint.h>
++
++#include <compiler.h>
++#include <psa/error.h>
++
++#include <stdint.h>
++#include <psa/client.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* PSA client call type value */
++#define OPENAMP_PSA_FRAMEWORK_VERSION       (0x1)
++#define OPENAMP_PSA_VERSION                 (0x2)
++#define OPENAMP_PSA_CONNECT                 (0x3)
++#define OPENAMP_PSA_CALL                    (0x4)
++#define OPENAMP_PSA_CLOSE                   (0x5)
++
++/* Return code of openamp APIs */
++#define OPENAMP_SUCCESS                     (0)
++#define OPENAMP_MAP_FULL                    (INT32_MIN + 1)
++#define OPENAMP_MAP_ERROR                   (INT32_MIN + 2)
++#define OPENAMP_INVAL_PARAMS                (INT32_MIN + 3)
++#define OPENAMP_NO_PERMS                    (INT32_MIN + 4)
++#define OPENAMP_NO_PEND_EVENT               (INT32_MIN + 5)
++#define OPENAMP_CHAN_BUSY                   (INT32_MIN + 6)
++#define OPENAMP_CALLBACK_REG_ERROR          (INT32_MIN + 7)
++#define OPENAMP_INIT_ERROR                  (INT32_MIN + 8)
++
++#define HOLD_INPUT_BUFFER (1) /* IF true, TF-M Library will hold the openamp
++			       * buffer so that openamp shared memory buffer
++			       * does not get freed.
++			       */
++
++/*
++ * This structure holds the parameters used in a PSA client call.
++ */
++typedef struct __packed psa_client_in_params {
++	union {
++		struct __packed {
++			uint32_t        sid;
++		} psa_version_params;
++
++		struct __packed {
++			uint32_t        sid;
++			uint32_t        version;
++		} psa_connect_params;
++
++		struct __packed {
++			psa_handle_t     handle;
++			int32_t          type;
++			uint32_t         in_vec;
++			uint32_t         in_len;
++			uint32_t         out_vec;
++			uint32_t         out_len;
++		} psa_call_params;
++
++		struct __packed {
++			psa_handle_t    handle;
++		} psa_close_params;
++	};
++} psa_client_in_params_t;
++
++/* Openamp message passed from NSPE to SPE to deliver a PSA client call */
++struct __packed ns_openamp_msg {
++	uint32_t                      call_type;   /* PSA client call type */
++	struct psa_client_in_params   params;      /* Contain parameters used in PSA
++						  * client call
++						  */
++
++	int32_t                     client_id;   /* Optional client ID of the
++						  * non-secure caller.
++						  * It is required to identify the
++						  * non-secure task when NSPE OS
++						  * enforces non-secure task
++						  * isolation
++						  */
++	int32_t                     request_id;  /* This is the unique ID for a
++						  * request send to TF-M by the
++						  * non-secure core. TF-M forward
++						  * the ID back to non-secure on the
++						  * reply to a given request. Using
++						  * this id, the non-secure library
++						  * can identify the request for
++						  * which the reply has received.
++						  */
++};
++
++/*
++ * This structure holds the location of the out data of the PSA client call.
++ */
++struct __packed psa_client_out_params {
++	uint32_t              out_vec;
++	uint32_t              out_len;
++};
++
++
++/* Openamp message from SPE to NSPE delivering the reply back for a PSA client
++ * call.
++ */
++struct __packed s_openamp_msg {
++	int32_t                     request_id;  /* Using this id, the non-secure
++						  * library identifies the request.
++						  * TF-M forwards the same
++						  * request-id received on the
++						  * initial request.
++						  */
++	int32_t                     reply;       /* Reply of the PSA client call */
++	struct psa_client_out_params     params;      /* Contain out data result of the
++						       * PSA client call.
++						       */
++};
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* SERVICE_PSA_IPC_OPENAMP_LIB_H */
++
++
+diff --git a/deployments/se-proxy/opteesp/CMakeLists.txt b/deployments/se-proxy/opteesp/CMakeLists.txt
+index 1511bbad..e0e0e12b 100644
+--- a/deployments/se-proxy/opteesp/CMakeLists.txt
++++ b/deployments/se-proxy/opteesp/CMakeLists.txt
+@@ -54,6 +54,7 @@ add_components(TARGET "se-proxy"
+ 		"components/service/common/include"
+ 		"components/service/common/serializer/protobuf"
+ 		"components/service/common/client"
++		"components/service/common/psa_ipc"
+ 		"components/service/common/provider"
+ 		"components/service/discovery/provider"
+ 		"components/service/discovery/provider/serializer/packed-c"
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0012-Add-secure-storage-ipc-backend.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0012-Add-secure-storage-ipc-backend.patch
new file mode 100644
index 0000000..068468b
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0012-Add-secure-storage-ipc-backend.patch
@@ -0,0 +1,523 @@
+From 962056a9c8115e9228719d46b09da983678ab024 Mon Sep 17 00:00:00 2001
+From: Vishnu Banavath <vishnu.banavath@arm.com>
+Date: Fri, 3 Dec 2021 19:19:24 +0000
+Subject: [PATCH] Add secure storage ipc backend
+
+Add secure storage ipc ff-m implementation which may use
+openamp as rpc to communicate with other processor.
+
+Signed-off-by: Rui Miguel Silva <rui.silva@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+
+---
+ .../service/common/psa_ipc/service_psa_ipc.c  | 143 +++++++++++-
+ .../secure_storage_ipc/component.cmake        |  14 ++
+ .../secure_storage_ipc/secure_storage_ipc.c   | 214 ++++++++++++++++++
+ .../secure_storage_ipc/secure_storage_ipc.h   |  52 +++++
+ deployments/se-proxy/opteesp/CMakeLists.txt   |   1 +
+ 5 files changed, 420 insertions(+), 4 deletions(-)
+ create mode 100644 components/service/secure_storage/backend/secure_storage_ipc/component.cmake
+ create mode 100644 components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
+ create mode 100644 components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.h
+
+diff --git a/components/service/common/psa_ipc/service_psa_ipc.c b/components/service/common/psa_ipc/service_psa_ipc.c
+index e8093c20..95a07c13 100644
+--- a/components/service/common/psa_ipc/service_psa_ipc.c
++++ b/components/service/common/psa_ipc/service_psa_ipc.c
+@@ -16,6 +16,52 @@
+ #include <psa/client.h>
+ #include "service_psa_ipc_openamp_lib.h"
+ 
++static struct psa_invec *psa_call_in_vec_param(uint8_t *req)
++{
++	return (struct psa_invec *)(req + sizeof(struct ns_openamp_msg));
++}
++
++static struct psa_outvec *psa_call_out_vec_param(uint8_t *req, size_t in_len)
++{
++	return (struct psa_outvec *)(req + sizeof(struct ns_openamp_msg) +
++				     (in_len * sizeof(struct psa_invec)));
++}
++
++static size_t psa_call_header_len(const struct psa_invec *in_vec, size_t in_len,
++				  struct psa_outvec *out_vec, size_t out_len)
++{
++	return sizeof(struct ns_openamp_msg) + (in_len * sizeof(*in_vec)) +
++		(out_len * sizeof(*out_vec));
++}
++
++static size_t psa_call_in_vec_len(const struct psa_invec *in_vec, size_t in_len)
++{
++	size_t req_len = 0;
++	int i;
++
++	if (!in_vec || !in_len)
++		return 0;
++
++	for (i = 0; i < in_len; i++)
++		req_len += in_vec[i].len;
++
++	return req_len;
++}
++
++static size_t psa_call_out_vec_len(const struct psa_outvec *out_vec, size_t out_len)
++{
++	size_t resp_len = 0;
++	int i;
++
++	if (!out_vec || !out_len)
++		return 0;
++
++	for (i = 0; i < out_len; i++)
++		resp_len += out_vec[i].len;
++
++	return resp_len;
++}
++
+ psa_handle_t psa_connect(struct rpc_caller *caller, uint32_t sid,
+ 			 uint32_t version)
+ {
+@@ -31,7 +77,7 @@ psa_handle_t psa_connect(struct rpc_caller *caller, uint32_t sid,
+ 	rpc_handle = rpc_caller_begin(caller, &req,
+ 				      sizeof(struct ns_openamp_msg));
+ 	if (!rpc_handle) {
+-		EMSG("psa_connect: could not get handle");
++		EMSG("psa_connect: could not get rpc handle");
+ 		return PSA_ERROR_GENERIC_ERROR;
+ 	}
+ 
+@@ -56,14 +102,100 @@ psa_handle_t psa_connect(struct rpc_caller *caller, uint32_t sid,
+ 	return resp_msg ? (psa_handle_t)resp_msg->reply : PSA_NULL_HANDLE;
+ }
+ 
+-psa_status_t psa_call(struct rpc_caller *caller, psa_handle_t handle,
++psa_status_t psa_call(struct rpc_caller *caller, psa_handle_t psa_handle,
+ 		      int32_t type, const struct psa_invec *in_vec,
+ 		      size_t in_len, struct psa_outvec *out_vec, size_t out_len)
+ {
++	psa_status_t psa_status = PSA_SUCCESS;
++	struct s_openamp_msg *resp_msg = NULL;
++	struct psa_outvec *out_vec_param;
++	struct psa_invec *in_vec_param;
++	struct ns_openamp_msg *req_msg;
++	rpc_call_handle rpc_handle;
++	size_t out_vec_len;
++	size_t in_vec_len;
++	size_t header_len;
++	uint8_t *payload;
++	size_t resp_len;
++	uint8_t *resp;
++	uint8_t *req;
++	int ret;
++	int i;
++
++	if ((psa_handle == PSA_NULL_HANDLE) || !caller)
++		return PSA_ERROR_INVALID_ARGUMENT;
++
++	header_len = psa_call_header_len(in_vec, in_len, out_vec, out_len);
++	in_vec_len = psa_call_in_vec_len(in_vec, in_len);
++	out_vec_len = psa_call_out_vec_len(out_vec, out_len);
+ 
++	rpc_handle = rpc_caller_begin(caller, &req, header_len + in_vec_len);
++	if (!rpc_handle) {
++		EMSG("psa_call: could not get handle");
++		return PSA_ERROR_GENERIC_ERROR;
++	}
++
++	payload = req + header_len;
++
++	out_vec_param = psa_call_out_vec_param(req, in_len);
++	in_vec_param = psa_call_in_vec_param(req);
++
++	req_msg = (struct ns_openamp_msg *)req;
++
++	req_msg->call_type = OPENAMP_PSA_CALL;
++	req_msg->request_id = 1234;
++	req_msg->params.psa_call_params.handle = psa_handle;
++	req_msg->params.psa_call_params.type = type;
++	req_msg->params.psa_call_params.in_len = in_len;
++	req_msg->params.psa_call_params.in_vec = rpc_caller_virt_to_phys(caller, in_vec_param);
++	req_msg->params.psa_call_params.out_len = out_len;
++	req_msg->params.psa_call_params.out_vec = rpc_caller_virt_to_phys(caller, out_vec_param);
++
++	for (i = 0; i < in_len; i++) {
++		in_vec_param[i].base = rpc_caller_virt_to_phys(caller, payload);
++		in_vec_param[i].len = in_vec[i].len;
++
++		memcpy(payload, in_vec[i].base, in_vec[i].len);
++		payload += in_vec[i].len;
++	}
++
++	for (i = 0; i < out_len; i++) {
++		out_vec_param[i].base = NULL;
++		out_vec_param[i].len = out_vec[i].len;
++	}
++
++	ret = rpc_caller_invoke(caller, rpc_handle, 0, &psa_status, &resp,
++				&resp_len);
++	if (ret != TS_RPC_CALL_ACCEPTED) {
++		EMSG("psa_call: invoke failed: %d", ret);
++		return PSA_ERROR_GENERIC_ERROR;
++	}
++
++	if (psa_status != PSA_SUCCESS) {
++		EMSG("psa_call: psa_status invoke failed: %d", psa_status);
++		return PSA_ERROR_GENERIC_ERROR;
++	}
++
++	resp_msg = (struct s_openamp_msg *)resp;
++
++	if (!resp_msg || !out_len || resp_msg->reply != PSA_SUCCESS)
++		goto caller_end;
++
++	out_vec_param = (struct psa_outvec *)rpc_caller_phys_to_virt(caller,
++						     resp_msg->params.out_vec);
++
++	for (i = 0; i < resp_msg->params.out_len; i++) {
++		memcpy(out_vec[i].base, rpc_caller_phys_to_virt(caller, out_vec_param[i].base),
++		       out_vec[i].len);
++	}
++
++caller_end:
++	rpc_caller_end(caller, rpc_handle);
++
++	return resp_msg ? resp_msg->reply : PSA_ERROR_COMMUNICATION_FAILURE;
+ }
+ 
+-void psa_close(struct rpc_caller *caller, psa_handle_t handle)
++void psa_close(struct rpc_caller *caller, psa_handle_t psa_handle)
+ {
+ 	psa_status_t psa_status = PSA_SUCCESS;
+ 	struct s_openamp_msg *resp_msg = NULL;
+@@ -74,6 +206,9 @@ void psa_close(struct rpc_caller *caller, psa_handle_t handle)
+ 	uint8_t *req;
+ 	int ret;
+ 
++	if ((psa_handle == PSA_NULL_HANDLE) || !caller)
++		return;
++
+ 	rpc_handle = rpc_caller_begin(caller, &req,
+ 				      sizeof(struct ns_openamp_msg));
+ 	if (!rpc_handle) {
+@@ -84,7 +219,7 @@ void psa_close(struct rpc_caller *caller, psa_handle_t handle)
+ 	req_msg = (struct ns_openamp_msg *)req;
+ 
+ 	req_msg->call_type = OPENAMP_PSA_CLOSE;
+-	req_msg->params.psa_close_params.handle = handle;
++	req_msg->params.psa_close_params.handle = psa_handle;
+ 
+ 	ret = rpc_caller_invoke(caller, rpc_handle, 0, &psa_status, &resp,
+ 				&resp_len);
+diff --git a/components/service/secure_storage/backend/secure_storage_ipc/component.cmake b/components/service/secure_storage/backend/secure_storage_ipc/component.cmake
+new file mode 100644
+index 00000000..5d8f6714
+--- /dev/null
++++ b/components/service/secure_storage/backend/secure_storage_ipc/component.cmake
+@@ -0,0 +1,14 @@
++#-------------------------------------------------------------------------------
++# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++#-------------------------------------------------------------------------------
++if (NOT DEFINED TGT)
++	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
++endif()
++
++target_sources(${TGT} PRIVATE
++	"${CMAKE_CURRENT_LIST_DIR}/secure_storage_ipc.c"
++	)
++
+diff --git a/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
+new file mode 100644
+index 00000000..9b55f77d
+--- /dev/null
++++ b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
+@@ -0,0 +1,214 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#include <protocols/rpc/common/packed-c/status.h>
++#include "secure_storage_ipc.h"
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <rpc_caller.h>
++#include <string.h>
++#include <trace.h>
++
++
++static psa_status_t secure_storage_ipc_set(void *context, uint32_t client_id,
++			 psa_storage_uid_t uid, size_t data_length,
++			 const void *p_data, psa_storage_create_flags_t create_flags)
++{
++	struct secure_storage_ipc *ipc = context;
++	struct rpc_caller *caller = ipc->client.caller;
++	psa_handle_t psa_handle;
++	psa_status_t psa_status;
++	struct psa_invec in_vec[] = {
++		{ .base = &uid, .len = sizeof(uid) },
++		{ .base = p_data, .len = data_length },
++		{ .base = &create_flags, .len = sizeof(create_flags) },
++	};
++
++	(void)client_id;
++
++	ipc->client.rpc_status = TS_RPC_CALL_ACCEPTED;
++
++	/* Validating input parameters */
++	if (p_data == NULL)
++		return PSA_ERROR_INVALID_ARGUMENT;
++
++	psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
++			      TFM_PS_SET, in_vec, IOVEC_LEN(in_vec), NULL, 0);
++	if (psa_status < 0)
++		EMSG("ipc_set: psa_call failed: %d", psa_status);
++
++	return psa_status;
++}
++
++static psa_status_t secure_storage_ipc_get(void *context,
++					   uint32_t client_id,
++					   psa_storage_uid_t uid,
++					   size_t data_offset,
++					   size_t data_size,
++					   void *p_data,
++					   size_t *p_data_length)
++{
++	struct secure_storage_ipc *ipc = context;
++	struct rpc_caller *caller = ipc->client.caller;
++	psa_handle_t psa_handle;
++	psa_status_t psa_status;
++	uint32_t offset = (uint32_t)data_offset;
++	struct psa_invec in_vec[] = {
++		{ .base = &uid, .len = sizeof(uid) },
++		{ .base = &offset, .len = sizeof(offset) },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = p_data, .len = data_size },
++	};
++
++	if (!p_data_length) {
++		EMSG("ipc_get: p_data_length not defined");
++		return PSA_ERROR_INVALID_ARGUMENT;
++	}
++
++	psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
++			      TFM_PS_GET, in_vec, IOVEC_LEN(in_vec),
++			      out_vec, IOVEC_LEN(out_vec));
++	if (psa_status == PSA_SUCCESS)
++		*p_data_length = out_vec[0].len;
++
++	return psa_status;
++}
++
++static psa_status_t secure_storage_ipc_get_info(void *context,
++						uint32_t client_id,
++						psa_storage_uid_t uid,
++						struct psa_storage_info_t *p_info)
++{
++	struct secure_storage_ipc *ipc = context;
++	struct rpc_caller *caller = ipc->client.caller;
++	psa_handle_t psa_handle;
++	psa_status_t psa_status;
++	struct psa_invec in_vec[] = {
++		{ .base = &uid, .len = sizeof(uid) },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = p_info, .len = sizeof(*p_info) },
++	};
++
++	(void)client_id;
++
++	/* Validating input parameters */
++	if (!p_info)
++		return PSA_ERROR_INVALID_ARGUMENT;
++
++	psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
++			      TFM_PS_GET_INFO, in_vec,
++			      IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++	if (psa_status != PSA_SUCCESS)
++		EMSG("ipc_get_info: failed to psa_call: %d", psa_status);
++
++	return psa_status;
++}
++
++static psa_status_t secure_storage_ipc_remove(void *context,
++						uint32_t client_id,
++						psa_storage_uid_t uid)
++{
++	struct secure_storage_ipc *ipc = context;
++	struct rpc_caller *caller = ipc->client.caller;
++	psa_handle_t psa_handle;
++	psa_status_t psa_status;
++	struct psa_invec in_vec[] = {
++		{ .base = &uid, .len = sizeof(uid) },
++	};
++
++	(void)client_id;
++
++	psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
++			      TFM_PS_REMOVE, in_vec,
++			      IOVEC_LEN(in_vec), NULL, 0);
++	if (psa_status != PSA_SUCCESS)
++		EMSG("ipc_remove: failed to psa_call: %d", psa_status);
++
++	return psa_status;
++}
++
++static psa_status_t secure_storage_ipc_create(void *context,
++					      uint32_t client_id,
++					      uint64_t uid,
++					      size_t capacity,
++					      uint32_t create_flags)
++{
++	(void)context;
++	(void)uid;
++	(void)client_id;
++	(void)capacity;
++	(void)create_flags;
++
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
++static psa_status_t secure_storage_set_extended(void *context,
++						uint32_t client_id,
++						uint64_t uid,
++						size_t data_offset,
++						size_t data_length,
++						const void *p_data)
++{
++	(void)context;
++	(void)uid;
++	(void)client_id;
++	(void)data_offset;
++	(void)data_length;
++	(void)p_data;
++
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
++static uint32_t secure_storage_get_support(void *context, uint32_t client_id)
++{
++	struct secure_storage_ipc *ipc = context;
++	struct rpc_caller *caller = ipc->client.caller;
++	psa_handle_t psa_handle;
++	psa_status_t psa_status;
++	uint32_t support_flags;
++	struct psa_outvec out_vec[] = {
++		{ .base = &support_flags, .len =  sizeof(support_flags) },
++	};
++
++	(void)client_id;
++
++	psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
++			      TFM_PS_GET_SUPPORT, NULL, 0,
++			      out_vec, IOVEC_LEN(out_vec));
++	if (psa_status != PSA_SUCCESS)
++		EMSG("ipc_get_support: failed to psa_call: %d", psa_status);
++
++	return psa_status;
++}
++
++struct storage_backend *secure_storage_ipc_init(struct secure_storage_ipc *context,
++						struct rpc_caller *caller)
++{
++	service_client_init(&context->client, caller);
++
++	static const struct storage_backend_interface interface =
++	{
++		.set = secure_storage_ipc_set,
++		.get = secure_storage_ipc_get,
++		.get_info = secure_storage_ipc_get_info,
++		.remove = secure_storage_ipc_remove,
++		.create = secure_storage_ipc_create,
++		.set_extended = secure_storage_set_extended,
++		.get_support = secure_storage_get_support,
++	};
++
++	context->backend.context = context;
++	context->backend.interface = &interface;
++
++	return &context->backend;
++}
++
++void secure_storage_ipc_deinit(struct secure_storage_ipc *context)
++{
++	service_client_deinit(&context->client);
++}
+diff --git a/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.h b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.h
+new file mode 100644
+index 00000000..e8c1e8fd
+--- /dev/null
++++ b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.h
+@@ -0,0 +1,52 @@
++/*
++ * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef SECURE_STORAGE_IPC_H
++#define SECURE_STORAGE_IPC_H
++
++#include <service/secure_storage/backend/storage_backend.h>
++#include <service/common/client/service_client.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * @brief      Secure storage ipc instance
++ */
++struct secure_storage_ipc
++{
++    struct storage_backend backend;
++    struct service_client client;
++};
++
++/**
++ * @brief      Initialize a secure storage ipc client
++ *
++ * A secure storage client is a storage backend that makes RPC calls
++ * to a remote secure storage provider.
++ *
++ * @param[in]  context    Instance data
++ * @param[in]  rpc_caller RPC caller instance
++ *
++ *
++ * @return     Pointer to inialized storage backend or NULL on failure
++ */
++struct storage_backend *secure_storage_ipc_init(struct secure_storage_ipc *context,
++						struct rpc_caller *caller);
++
++/**
++ * @brief      Deinitialize a secure storage ipc client
++ *
++ * @param[in]  context   Instance data
++ */
++void secure_storage_ipc_deinit(struct secure_storage_ipc *context);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* SECURE_STORAGE_IPC_H */
+diff --git a/deployments/se-proxy/opteesp/CMakeLists.txt b/deployments/se-proxy/opteesp/CMakeLists.txt
+index e0e0e12b..663177b7 100644
+--- a/deployments/se-proxy/opteesp/CMakeLists.txt
++++ b/deployments/se-proxy/opteesp/CMakeLists.txt
+@@ -73,6 +73,7 @@ add_components(TARGET "se-proxy"
+ 		"components/service/crypto/factory/full"
+ 		"components/service/secure_storage/include"
+ 		"components/service/secure_storage/frontend/secure_storage_provider"
++		"components/service/secure_storage/backend/secure_storage_ipc"
+ 		"components/service/attestation/include"
+ 		"components/service/attestation/provider"
+ 		"components/service/attestation/provider/serializer/packed-c"
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0013-Use-secure-storage-ipc-and-openamp-for-se_proxy.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0013-Use-secure-storage-ipc-and-openamp-for-se_proxy.patch
new file mode 100644
index 0000000..56964b5
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0013-Use-secure-storage-ipc-and-openamp-for-se_proxy.patch
@@ -0,0 +1,63 @@
+From 12b8b8bb28c96e6f121122939b7d23e6c7055f0f Mon Sep 17 00:00:00 2001
+From: Vishnu Banavath <vishnu.banavath@arm.com>
+Date: Fri, 3 Dec 2021 19:25:34 +0000
+Subject: [PATCH] Use secure storage ipc and openamp for se_proxy
+
+Remove mock up backend for secure storage in se proxy
+deployment and use instead the secure storage ipc backend with
+openamp as rpc to secure enclave side.
+
+Signed-off-by: Rui Miguel Silva <rui.silva@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+
+---
+ .../se-proxy/opteesp/service_proxy_factory.c     | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/deployments/se-proxy/opteesp/service_proxy_factory.c b/deployments/se-proxy/opteesp/service_proxy_factory.c
+index acfb6e88..57290056 100644
+--- a/deployments/se-proxy/opteesp/service_proxy_factory.c
++++ b/deployments/se-proxy/opteesp/service_proxy_factory.c
+@@ -6,15 +6,20 @@
+ 
+ #include <stddef.h>
+ #include <rpc/common/endpoint/rpc_interface.h>
++#include <rpc/openamp/caller/sp/openamp_caller.h>
+ #include <service/attestation/provider/attest_provider.h>
+ #include <service/attestation/provider/serializer/packed-c/packedc_attest_provider_serializer.h>
+ #include <service/crypto/factory/crypto_provider_factory.h>
+ #include <service/secure_storage/frontend/secure_storage_provider/secure_storage_provider.h>
++#include <trace.h>
+ 
+ /* Stub backends */
+ #include <service/crypto/backend/stub/stub_crypto_backend.h>
++#include <service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.h>
+ #include <service/secure_storage/backend/mock_store/mock_store.h>
+ 
++struct openamp_caller openamp;
++
+ struct rpc_interface *attest_proxy_create(void)
+ {
+ 	struct rpc_interface *attest_iface;
+@@ -47,10 +52,15 @@ struct rpc_interface *crypto_proxy_create(void)
+ 
+ struct rpc_interface *ps_proxy_create(void)
+ {
+-	static struct mock_store ps_backend;
+ 	static struct secure_storage_provider ps_provider;
+-
+-	struct storage_backend *backend = mock_store_init(&ps_backend);
++	static struct secure_storage_ipc ps_backend;
++	static struct rpc_caller *storage_caller;
++	struct storage_backend *backend;
++
++	storage_caller = openamp_caller_init(&openamp);
++	if (!storage_caller)
++		return NULL;
++	backend = secure_storage_ipc_init(&ps_backend, &openamp.rpc_caller);
+ 
+ 	return secure_storage_provider_init(&ps_provider, backend);
+ }
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0014-Add-uefi-variable-append-write-support.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0014-Add-uefi-variable-append-write-support.patch
new file mode 100644
index 0000000..cf7357e
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0014-Add-uefi-variable-append-write-support.patch
@@ -0,0 +1,1162 @@
+From 254f564c76320478e7b509faf279c0c493470657 Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Thu, 2 Dec 2021 10:15:54 +0000
+Subject: [PATCH] Add uefi variable append write support
+
+Adds support for extending UEFI variable data handled by the
+smm_variable service provider using the EFI_VARIABLE_APPEND_WRITE
+attribute.
+
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: I7a6562327bc0a5ce5cd0e85276325227b83e9f9e
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+
+---
+ .../backend/test/variable_index_tests.cpp     |  90 +++---
+ .../backend/test/variable_store_tests.cpp     |  40 ++-
+ .../backend/uefi_variable_store.c             | 263 +++++++++++-------
+ .../smm_variable/backend/variable_index.c     |  95 +++----
+ .../smm_variable/backend/variable_index.h     |  58 ++--
+ .../backend/variable_index_iterator.c         |   4 +-
+ .../backend/variable_index_iterator.h         |   2 +-
+ .../service/smm_variable_service_tests.cpp    |  48 ++++
+ protocols/service/smm_variable/parameters.h   |   3 +
+ 9 files changed, 364 insertions(+), 239 deletions(-)
+
+diff --git a/components/service/smm_variable/backend/test/variable_index_tests.cpp b/components/service/smm_variable/backend/test/variable_index_tests.cpp
+index c8bacf97..8edc0e70 100644
+--- a/components/service/smm_variable/backend/test/variable_index_tests.cpp
++++ b/components/service/smm_variable/backend/test/variable_index_tests.cpp
+@@ -69,34 +69,37 @@ TEST_GROUP(UefiVariableIndexTests)
+ 
+ 	void create_variables()
+ 	{
+-		const struct variable_info *info = NULL;
++		struct variable_info *info = NULL;
+ 
+-		info = variable_index_add_variable(
++		info = variable_index_add_entry(
+ 			&m_variable_index,
+ 			&guid_1,
+ 			name_1.size() * sizeof(int16_t),
+-			name_1.data(),
+-			EFI_VARIABLE_BOOTSERVICE_ACCESS);
+-
++			name_1.data());
+ 		CHECK_TRUE(info);
++		variable_index_set_variable(
++			info,
++			EFI_VARIABLE_BOOTSERVICE_ACCESS);
+ 
+-		info = variable_index_add_variable(
++		info = variable_index_add_entry(
+ 			&m_variable_index,
+ 			&guid_2,
+ 			name_2.size() * sizeof(int16_t),
+-			name_2.data(),
+-			EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS);
+-
++			name_2.data());
+ 		CHECK_TRUE(info);
++		variable_index_set_variable(
++			info,
++			EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS);
+ 
+-		info = variable_index_add_variable(
++		info = variable_index_add_entry(
+ 			&m_variable_index,
+ 			&guid_1,
+ 			name_3.size() * sizeof(int16_t),
+-			name_3.data(),
+-			EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS);
+-
++			name_3.data());
+ 		CHECK_TRUE(info);
++		variable_index_set_variable(
++			info,
++			EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS);
+ 	}
+ 
+ 	static const size_t MAX_VARIABLES = 10;
+@@ -111,7 +114,7 @@ TEST_GROUP(UefiVariableIndexTests)
+ 
+ TEST(UefiVariableIndexTests, emptyIndexOperations)
+ {
+-	const struct variable_info *info = NULL;
++	struct variable_info *info = NULL;
+ 
+ 	/* Expect not to find a variable */
+ 	info = variable_index_find(
+@@ -130,36 +133,34 @@ TEST(UefiVariableIndexTests, emptyIndexOperations)
+ 	POINTERS_EQUAL(NULL, info);
+ 
+ 	/* Remove should silently return */
+-	variable_index_remove_variable(
++	variable_index_clear_variable(
+ 		&m_variable_index,
+ 		info);
+ }
+ 
+ TEST(UefiVariableIndexTests, addWithOversizedName)
+ {
+-	const struct variable_info *info = NULL;
++	struct variable_info *info = NULL;
+ 	std::vector<int16_t> name;
+ 
+ 	name = to_variable_name(L"a long variable name that exceeds the length limit");
+ 
+-	info = variable_index_add_variable(
++	info = variable_index_add_entry(
+ 		&m_variable_index,
+ 		&guid_1,
+ 		name.size() * sizeof(int16_t),
+-		name.data(),
+-		EFI_VARIABLE_BOOTSERVICE_ACCESS);
++		name.data());
+ 
+ 	/* Expect the add to fail because of an oversized name */
+ 	POINTERS_EQUAL(NULL, info);
+ 
+ 	name = to_variable_name(L"a long variable name that fits!");
+ 
+-	info = variable_index_add_variable(
++	info = variable_index_add_entry(
+ 		&m_variable_index,
+ 		&guid_1,
+ 		name.size() * sizeof(int16_t),
+-		name.data(),
+-		EFI_VARIABLE_BOOTSERVICE_ACCESS);
++		name.data());
+ 
+ 	/* Expect the add succeed */
+ 	CHECK_TRUE(info);
+@@ -167,18 +168,17 @@ TEST(UefiVariableIndexTests, addWithOversizedName)
+ 
+ TEST(UefiVariableIndexTests, variableIndexFull)
+ {
+-	const struct variable_info *info = NULL;
++	struct variable_info *info = NULL;
+ 	EFI_GUID guid = guid_1;
+ 
+ 	/* Expect to be able to fill the index */
+ 	for (size_t i = 0; i < MAX_VARIABLES; ++i) {
+ 
+-		info = variable_index_add_variable(
++		info = variable_index_add_entry(
+ 			&m_variable_index,
+ 			&guid,
+ 			name_1.size() * sizeof(int16_t),
+-			name_1.data(),
+-			EFI_VARIABLE_BOOTSERVICE_ACCESS);
++			name_1.data());
+ 
+ 		CHECK_TRUE(info);
+ 
+@@ -187,12 +187,11 @@ TEST(UefiVariableIndexTests, variableIndexFull)
+ 	}
+ 
+ 	/* Variable index should now be full */
+-	info = variable_index_add_variable(
++	info = variable_index_add_entry(
+ 		&m_variable_index,
+ 		&guid,
+ 		name_1.size() * sizeof(int16_t),
+-		name_1.data(),
+-		EFI_VARIABLE_BOOTSERVICE_ACCESS);
++		name_1.data());
+ 
+ 	POINTERS_EQUAL(NULL, info);
+ }
+@@ -323,7 +322,7 @@ TEST(UefiVariableIndexTests, dumpBufferTooSmall)
+ TEST(UefiVariableIndexTests, removeVariable)
+ {
+ 	uint8_t buffer[MAX_VARIABLES * sizeof(struct variable_metadata)];
+-	const struct variable_info *info = NULL;
++	struct variable_info *info = NULL;
+ 
+ 	create_variables();
+ 
+@@ -334,7 +333,7 @@ TEST(UefiVariableIndexTests, removeVariable)
+ 		name_2.size() * sizeof(int16_t),
+ 		name_2.data());
+ 
+-	variable_index_remove_variable(
++	variable_index_clear_variable(
+ 		&m_variable_index,
+ 		info);
+ 
+@@ -352,7 +351,7 @@ TEST(UefiVariableIndexTests, removeVariable)
+ 		name_1.size() * sizeof(int16_t),
+ 		name_1.data());
+ 
+-	variable_index_remove_variable(
++	variable_index_clear_variable(
+ 		&m_variable_index,
+ 		info);
+ 
+@@ -370,7 +369,7 @@ TEST(UefiVariableIndexTests, removeVariable)
+ 		name_3.size() * sizeof(int16_t),
+ 		name_3.data());
+ 
+-	variable_index_remove_variable(
++	variable_index_clear_variable(
+ 		&m_variable_index,
+ 		info);
+ 
+@@ -395,7 +394,7 @@ TEST(UefiVariableIndexTests, removeVariable)
+ 
+ TEST(UefiVariableIndexTests, checkIterator)
+ {
+-	const struct variable_info *info = NULL;
++	struct variable_info *info = NULL;
+ 
+ 	create_variables();
+ 
+@@ -419,7 +418,7 @@ TEST(UefiVariableIndexTests, checkIterator)
+ 	UNSIGNED_LONGS_EQUAL(name_2.size() * sizeof(int16_t), info->metadata.name_size);
+ 	MEMCMP_EQUAL(name_2.data(), info->metadata.name, info->metadata.name_size);
+ 
+-	const struct variable_info *info_to_remove = info;
++	struct variable_info *info_to_remove = info;
+ 
+ 	variable_index_iterator_next(&iter);
+ 	CHECK_FALSE(variable_index_iterator_is_done(&iter));
+@@ -435,7 +434,8 @@ TEST(UefiVariableIndexTests, checkIterator)
+ 	CHECK_TRUE(variable_index_iterator_is_done(&iter));
+ 
+ 	/* Now remove the middle entry */
+-	variable_index_remove_variable(&m_variable_index, info_to_remove);
++	variable_index_clear_variable(&m_variable_index, info_to_remove);
++	variable_index_remove_unused_entry(&m_variable_index, info_to_remove);
+ 
+ 	/* Iterate again but this time there should only be two entries */
+ 	variable_index_iterator_first(&iter, &m_variable_index);
+@@ -478,7 +478,7 @@ TEST(UefiVariableIndexTests, setCheckConstraintsExistingVar)
+ 	constraints.max_size = 100;
+ 
+ 	/* Set check constraints on one of the variables */
+-	const struct variable_info *info = variable_index_find(
++	struct variable_info *info = variable_index_find(
+ 		&m_variable_index,
+ 		&guid_2,
+ 		name_2.size() * sizeof(int16_t),
+@@ -488,7 +488,7 @@ TEST(UefiVariableIndexTests, setCheckConstraintsExistingVar)
+ 	CHECK_TRUE(info->is_variable_set);
+ 	CHECK_FALSE(info->is_constraints_set);
+ 
+-	variable_index_update_constraints(info, &constraints);
++	variable_index_set_constraints(info, &constraints);
+ 
+ 	CHECK_TRUE(info->is_constraints_set);
+ 	CHECK_TRUE(info->is_variable_set);
+@@ -496,7 +496,7 @@ TEST(UefiVariableIndexTests, setCheckConstraintsExistingVar)
+ 	/* Remove the variable but still expect the variable to be indexed
+ 	 * because of the set constraints.
+ 	 */
+-	variable_index_remove_variable(
++	variable_index_clear_variable(
+ 		&m_variable_index,
+ 		info);
+ 
+@@ -588,7 +588,7 @@ TEST(UefiVariableIndexTests, setCheckConstraintsNonExistingVar)
+ 	constraints.max_size = 100;
+ 
+ 	/* Initially expect no variable_info */
+-	const struct variable_info *info = variable_index_find(
++	struct variable_info *info = variable_index_find(
+ 		&m_variable_index,
+ 		&guid_2,
+ 		name_2.size() * sizeof(int16_t),
+@@ -597,19 +597,19 @@ TEST(UefiVariableIndexTests, setCheckConstraintsNonExistingVar)
+ 	CHECK_FALSE(info);
+ 
+ 	/* Adding the check constraints should result in an entry being added */
+-	info = variable_index_add_constraints(
++	info = variable_index_add_entry(
+ 		&m_variable_index,
+ 		&guid_2,
+ 		name_2.size() * sizeof(int16_t),
+-		name_2.data(),
+-		&constraints);
+-
++		name_2.data());
+ 	CHECK_TRUE(info);
++
++	variable_index_set_constraints(info, &constraints);
+ 	CHECK_FALSE(info->is_variable_set);
+ 	CHECK_TRUE(info->is_constraints_set);
+ 
+ 	/* Updating the variable should cause the variable to be marked as set */
+-	variable_index_update_variable(info, EFI_VARIABLE_RUNTIME_ACCESS);
++	variable_index_set_variable(info, EFI_VARIABLE_RUNTIME_ACCESS);
+ 
+ 	CHECK_TRUE(info->is_variable_set);
+ 	CHECK_TRUE(info->is_constraints_set);
+diff --git a/components/service/smm_variable/backend/test/variable_store_tests.cpp b/components/service/smm_variable/backend/test/variable_store_tests.cpp
+index f6aba13a..578f118f 100644
+--- a/components/service/smm_variable/backend/test/variable_store_tests.cpp
++++ b/components/service/smm_variable/backend/test/variable_store_tests.cpp
+@@ -250,6 +250,21 @@ TEST(UefiVariableStoreTests, setGetRoundtrip)
+ 	/* Expect got variable data to be the same as the set value */
+ 	UNSIGNED_LONGLONGS_EQUAL(input_data.size(), output_data.size());
+ 	LONGS_EQUAL(0, input_data.compare(output_data));
++
++	/* Extend the variable using an append write */
++	std::string input_data2 = " jumps over the lazy dog";
++
++	status = set_variable(var_name, input_data2, EFI_VARIABLE_APPEND_WRITE);
++	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
++
++	status = get_variable(var_name, output_data);
++	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
++
++	std::string expected_output = input_data + input_data2;
++
++	/* Expect the append write operation to have extended the variable */
++	UNSIGNED_LONGLONGS_EQUAL(expected_output.size(), output_data.size());
++	LONGS_EQUAL(0, expected_output.compare(output_data));
+ }
+ 
+ TEST(UefiVariableStoreTests, persistentSetGet)
+@@ -259,7 +274,8 @@ TEST(UefiVariableStoreTests, persistentSetGet)
+ 	std::string input_data = "quick brown fox";
+ 	std::string output_data;
+ 
+-	status = set_variable(var_name, input_data, EFI_VARIABLE_NON_VOLATILE);
++	status = set_variable(var_name, input_data,
++		EFI_VARIABLE_NON_VOLATILE);
+ 	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+ 
+ 	status = get_variable(var_name, output_data);
+@@ -269,6 +285,22 @@ TEST(UefiVariableStoreTests, persistentSetGet)
+ 	UNSIGNED_LONGLONGS_EQUAL(input_data.size(), output_data.size());
+ 	LONGS_EQUAL(0, input_data.compare(output_data));
+ 
++	/* Extend the variable using an append write */
++	std::string input_data2 = " jumps over the lazy dog";
++
++	status = set_variable(var_name, input_data2,
++		EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_APPEND_WRITE);
++	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
++
++	status = get_variable(var_name, output_data);
++	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
++
++	std::string expected_output = input_data + input_data2;
++
++	/* Expect the append write operation to have extended the variable */
++	UNSIGNED_LONGLONGS_EQUAL(expected_output.size(), output_data.size());
++	LONGS_EQUAL(0, expected_output.compare(output_data));
++
+ 	/* Expect the variable to survive a power cycle */
+ 	power_cycle();
+ 
+@@ -277,8 +309,8 @@ TEST(UefiVariableStoreTests, persistentSetGet)
+ 	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+ 
+ 	/* Still expect got variable data to be the same as the set value */
+-	UNSIGNED_LONGLONGS_EQUAL(input_data.size(), output_data.size());
+-	LONGS_EQUAL(0, input_data.compare(output_data));
++	UNSIGNED_LONGLONGS_EQUAL(expected_output.size(), output_data.size());
++	LONGS_EQUAL(0, expected_output.compare(output_data));
+ }
+ 
+ TEST(UefiVariableStoreTests, removeVolatile)
+@@ -317,7 +349,7 @@ TEST(UefiVariableStoreTests, removePersistent)
+ 	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+ 
+ 	/* Remove by setting with zero data length */
+-	status = set_variable(var_name, std::string(), 0);
++	status = set_variable(var_name, std::string(), EFI_VARIABLE_NON_VOLATILE);
+ 	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+ 
+ 	/* Expect variable to no loger exist */
+diff --git a/components/service/smm_variable/backend/uefi_variable_store.c b/components/service/smm_variable/backend/uefi_variable_store.c
+index b7091d75..bcb85995 100644
+--- a/components/service/smm_variable/backend/uefi_variable_store.c
++++ b/components/service/smm_variable/backend/uefi_variable_store.c
+@@ -46,6 +46,13 @@ static efi_status_t load_variable_data(
+ 	SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var,
+ 	size_t max_data_len);
+ 
++static psa_status_t append_write(
++	struct storage_backend *storage_backend,
++	uint32_t client_id,
++	uint64_t uid,
++	size_t data_length,
++	const void *data);
++
+ static void purge_orphan_index_entries(
+ 	struct uefi_variable_store *context);
+ 
+@@ -113,40 +120,45 @@ efi_status_t uefi_variable_store_set_variable(
+ 	struct uefi_variable_store *context,
+ 	const SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var)
+ {
++	bool should_sync_index = false;
++
++	/* Validate incoming request */
+ 	efi_status_t status = check_name_terminator(var->Name, var->NameSize);
+ 	if (status != EFI_SUCCESS) return status;
+ 
+ 	status = check_capabilities(var);
+-	bool should_sync_index = false;
+-
+ 	if (status != EFI_SUCCESS) return status;
+ 
+-	/* Find in index */
+-	const struct variable_info *info = variable_index_find(
++	/* Find an existing entry in the variable index or add a new one */
++	struct variable_info *info = variable_index_find(
+ 		&context->variable_index,
+ 		&var->Guid,
+ 		var->NameSize,
+ 		var->Name);
+ 
+-	if (info) {
++	if (!info) {
+ 
+-		/* Variable info already exists */
+-		status = check_access_permitted_on_set(context, info, var);
++		info = variable_index_add_entry(
++			&context->variable_index,
++			&var->Guid,
++			var->NameSize,
++			var->Name);
+ 
+-		if (status == EFI_SUCCESS) {
++		if (!info) return EFI_OUT_OF_RESOURCES;
++	}
+ 
+-			should_sync_index =
+-				(var->Attributes & EFI_VARIABLE_NON_VOLATILE) ||
+-				(info->is_variable_set && (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE));
++	/* Control access */
++	status = check_access_permitted_on_set(context, info, var);
+ 
+-			if (var->DataSize) {
++	if (status == EFI_SUCCESS) {
+ 
+-				/* It's a set rather than a remove operation */
+-				variable_index_update_variable(
+-					info,
+-					var->Attributes);
+-			}
+-			else {
++		/* Access permitted */
++		if (info->is_variable_set) {
++
++			/* It's a request to update to an existing variable */
++			if (!(var->Attributes &
++				(EFI_VARIABLE_APPEND_WRITE | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS_MASK)) &&
++				!var->DataSize) {
+ 
+ 				/* It's a remove operation - for a remove, the variable
+ 				 * data must be removed from the storage backend before
+@@ -155,30 +167,29 @@ efi_status_t uefi_variable_store_set_variable(
+ 				 * the storage backend without a corresponding index entry.
+ 				 */
+ 				remove_variable_data(context, info);
+-				variable_index_remove_variable(&context->variable_index, info);
++				variable_index_clear_variable(&context->variable_index, info);
+ 
+-				/* Variable info no longer valid */
+-				info = NULL;
++				should_sync_index = (var->Attributes & EFI_VARIABLE_NON_VOLATILE);
++			}
++			else {
++
++				/* It's a set operation where variable data is potentially
++				 * being overwritten or extended.
++				 */
++				if ((var->Attributes & ~EFI_VARIABLE_APPEND_WRITE) != info->metadata.attributes) {
++
++					/* Modifying attributes is forbidden */
++					return EFI_INVALID_PARAMETER;
++				}
+ 			}
+ 		}
+ 		else {
+ 
+-			/* Access forbidden */
+-			info = NULL;
+-		}
+-	}
+-	else if (var->DataSize) {
++			/*  It's a request to create a new variable */
++			variable_index_set_variable(info, var->Attributes);
+ 
+-		/* It's a new variable */
+-		info = variable_index_add_variable(
+-			&context->variable_index,
+-			&var->Guid,
+-			var->NameSize,
+-			var->Name,
+-			var->Attributes);
+-
+-		if (!info) status = EFI_OUT_OF_RESOURCES;
+-		should_sync_index = info && (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE);
++			should_sync_index = (var->Attributes & EFI_VARIABLE_NON_VOLATILE);
++		}
+ 	}
+ 
+ 	/* The order of these operations is important. For an update
+@@ -195,11 +206,13 @@ efi_status_t uefi_variable_store_set_variable(
+ 	}
+ 
+ 	/* Store any variable data to the storage backend */
+-	if (info && (status == EFI_SUCCESS)) {
++	if (info->is_variable_set && (status == EFI_SUCCESS)) {
+ 
+ 		status = store_variable_data(context, info, var);
+ 	}
+ 
++	variable_index_remove_unused_entry(&context->variable_index, info);
++
+ 	return status;
+ }
+ 
+@@ -293,54 +306,42 @@ efi_status_t uefi_variable_store_set_var_check_property(
+ 	efi_status_t status = check_name_terminator(property->Name, property->NameSize);
+ 	if (status != EFI_SUCCESS) return status;
+ 
+-	/* Find in index */
+-	const struct variable_info *info = variable_index_find(
++	/* Find in index or create a new entry */
++	struct variable_info *info = variable_index_find(
+ 		&context->variable_index,
+ 		&property->Guid,
+ 		property->NameSize,
+ 		property->Name);
+ 
+-	if (info) {
++	if (!info) {
+ 
+-		/* Applying check constraints to an existing variable that may have
+-		 * constraints already set.  These could constrain the setting of
+-		 * the constraints.
+-		 */
+-		struct variable_constraints constraints = info->check_constraints;
+-
+-		status = variable_checker_set_constraints(
+-			&constraints,
+-			info->is_constraints_set,
+-			&property->VariableProperty);
+-
+-		if (status == EFI_SUCCESS) {
++		info = variable_index_add_entry(
++			&context->variable_index,
++			&property->Guid,
++			property->NameSize,
++			property->Name);
+ 
+-			variable_index_update_constraints(info, &constraints);
+-		}
++		if (!info) return EFI_OUT_OF_RESOURCES;
+ 	}
+-	else {
+-
+-		/* Applying check constraints for a new variable */
+-		struct variable_constraints constraints;
+ 
+-		status = variable_checker_set_constraints(
+-			&constraints,
+-			false,
+-			&property->VariableProperty);
++	/* Applying check constraints to an existing variable that may have
++	 * constraints already set.  These could constrain the setting of
++	 * the constraints.
++	 */
++	struct variable_constraints constraints = info->check_constraints;
+ 
+-		if (status == EFI_SUCCESS) {
++	status = variable_checker_set_constraints(
++		&constraints,
++		info->is_constraints_set,
++		&property->VariableProperty);
+ 
+-			info = variable_index_add_constraints(
+-				&context->variable_index,
+-				&property->Guid,
+-				property->NameSize,
+-				property->Name,
+-				&constraints);
++	if (status == EFI_SUCCESS) {
+ 
+-			if (!info) status = EFI_OUT_OF_RESOURCES;
+-		}
++		variable_index_set_constraints(info, &constraints);
+ 	}
+ 
++	variable_index_remove_unused_entry(&context->variable_index, info);
++
+ 	return status;
+ }
+ 
+@@ -440,7 +441,8 @@ static efi_status_t check_capabilities(
+ 	if (var->Attributes & ~(
+ 		EFI_VARIABLE_NON_VOLATILE |
+ 		EFI_VARIABLE_BOOTSERVICE_ACCESS |
+-		EFI_VARIABLE_RUNTIME_ACCESS)) {
++		EFI_VARIABLE_RUNTIME_ACCESS |
++		EFI_VARIABLE_APPEND_WRITE)) {
+ 
+ 		/* An unsupported attribute has been requested */
+ 		status = EFI_UNSUPPORTED;
+@@ -486,17 +488,6 @@ static efi_status_t check_access_permitted_on_set(
+ 			var->DataSize);
+ 	}
+ 
+-	if ((status == EFI_SUCCESS) && var->DataSize) {
+-
+-		/* Restrict which attributes can be modified for an existing variable */
+-		if ((var->Attributes & EFI_VARIABLE_NON_VOLATILE) !=
+-			(info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE)) {
+-
+-			/* Don't permit change of storage class */
+-			status = EFI_INVALID_PARAMETER;
+-		}
+-	}
+-
+ 	return status;
+ }
+ 
+@@ -518,20 +509,34 @@ static efi_status_t store_variable_data(
+ 
+ 	if (storage_backend) {
+ 
+-		psa_status = storage_backend->interface->set(
+-			storage_backend->context,
+-			context->owner_id,
+-			info->metadata.uid,
+-			data_len,
+-			data,
+-			PSA_STORAGE_FLAG_NONE);
++		if (!(var->Attributes & EFI_VARIABLE_APPEND_WRITE)) {
++
++			/* Create or overwrite variable data */
++			psa_status = storage_backend->interface->set(
++				storage_backend->context,
++				context->owner_id,
++				info->metadata.uid,
++				data_len,
++				data,
++				PSA_STORAGE_FLAG_NONE);
++		}
++		else {
++
++			/* Append new data to existing variable data */
++			psa_status = append_write(
++				storage_backend,
++				context->owner_id,
++				info->metadata.uid,
++				data_len,
++				data);
++		}
+ 	}
+ 
+ 	if ((psa_status != PSA_SUCCESS) && is_nv) {
+ 
+ 		/* A storage failure has occurred so attempt to fix any
+-		* mismatch between the variable index and stored NV variables.
+-		*/
++		 * mismatch between the variable index and stored NV variables.
++		 */
+ 		purge_orphan_index_entries(context);
+ 	}
+ 
+@@ -598,6 +603,76 @@ static efi_status_t load_variable_data(
+ 	return psa_to_efi_storage_status(psa_status);
+ }
+ 
++static psa_status_t append_write(
++	struct storage_backend *storage_backend,
++	uint32_t client_id,
++	uint64_t uid,
++	size_t data_length,
++	const void *data)
++{
++	struct psa_storage_info_t storage_info;
++
++	if (data_length == 0) return PSA_SUCCESS;
++
++	psa_status_t psa_status = storage_backend->interface->get_info(
++		storage_backend->context,
++		client_id,
++		uid,
++		&storage_info);
++
++	if (psa_status != PSA_SUCCESS) return psa_status;
++
++	/* Determine size of appended variable */
++	size_t new_size = storage_info.size + data_length;
++
++	/* Defend against integer overflow */
++	if (new_size < storage_info.size) return PSA_ERROR_INVALID_ARGUMENT;
++
++	/* Storage backend doesn't support an append operation so we need
++	 * need to read the current variable data, extend it and write it back.
++	 */
++	uint8_t *rw_buf = malloc(new_size);
++	if (!rw_buf) return PSA_ERROR_INSUFFICIENT_MEMORY;
++
++	size_t old_size = 0;
++	psa_status = storage_backend->interface->get(
++		storage_backend->context,
++		client_id,
++		uid,
++		0,
++		new_size,
++		rw_buf,
++		&old_size);
++
++	if (psa_status == PSA_SUCCESS) {
++
++		if ((old_size + data_length) <= new_size) {
++
++			/* Extend the variable data */
++			memcpy(&rw_buf[old_size], data, data_length);
++
++			psa_status = storage_backend->interface->set(
++				storage_backend->context,
++				client_id,
++				uid,
++				old_size + data_length,
++				rw_buf,
++				storage_info.flags);
++		}
++		else {
++
++			/* There's a mismatch between the length obtained from
++			 * get_info() and the subsequent length returned by get().
++			 */
++			psa_status = PSA_ERROR_STORAGE_FAILURE;
++		}
++	}
++
++	free(rw_buf);
++
++	return psa_status;
++}
++
+ static void purge_orphan_index_entries(
+ 	struct uefi_variable_store *context)
+ {
+@@ -612,7 +687,7 @@ static void purge_orphan_index_entries(
+ 	 */
+ 	while (!variable_index_iterator_is_done(&iter)) {
+ 
+-		const struct variable_info *info = variable_index_iterator_current(&iter);
++		struct variable_info *info = variable_index_iterator_current(&iter);
+ 
+ 		if (info->is_variable_set && (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE)) {
+ 
+@@ -628,7 +703,7 @@ static void purge_orphan_index_entries(
+ 			if (psa_status != PSA_SUCCESS) {
+ 
+ 				/* Detected a mismatch between the index and storage */
+-				variable_index_remove_variable(&context->variable_index, info);
++				variable_index_clear_variable(&context->variable_index, info);
+ 				any_orphans = true;
+ 			}
+ 		}
+diff --git a/components/service/smm_variable/backend/variable_index.c b/components/service/smm_variable/backend/variable_index.c
+index 99d7c97a..a8a55753 100644
+--- a/components/service/smm_variable/backend/variable_index.c
++++ b/components/service/smm_variable/backend/variable_index.c
+@@ -132,13 +132,13 @@ size_t variable_index_max_dump_size(
+ 	return sizeof(struct variable_metadata) * context->max_variables;
+ }
+ 
+-const struct variable_info *variable_index_find(
+-	const struct variable_index *context,
++struct variable_info *variable_index_find(
++	struct variable_index *context,
+ 	const EFI_GUID *guid,
+ 	size_t name_size,
+ 	const int16_t *name)
+ {
+-	const struct variable_info *result = NULL;
++	struct variable_info *result = NULL;
+ 	int pos = find_variable(context, guid, name_size, name);
+ 
+ 	if (pos >= 0) {
+@@ -149,13 +149,13 @@ const struct variable_info *variable_index_find(
+ 	return result;
+ }
+ 
+-const struct variable_info *variable_index_find_next(
++struct variable_info *variable_index_find_next(
+ 	const struct variable_index *context,
+ 	const EFI_GUID *guid,
+ 	size_t name_size,
+ 	const int16_t *name)
+ {
+-	const struct variable_info *result = NULL;
++	struct variable_info *result = NULL;
+ 
+ 	if (name_size >= sizeof(int16_t)) {
+ 
+@@ -263,12 +263,11 @@ static struct variable_entry *add_entry(
+ 	return entry;
+ }
+ 
+-const struct variable_info *variable_index_add_variable(
++struct variable_info *variable_index_add_entry(
+ 	struct variable_index *context,
+ 	const EFI_GUID *guid,
+ 	size_t name_size,
+-	const int16_t *name,
+-	uint32_t attributes)
++	const int16_t *name)
+ {
+ 	struct variable_info *info = NULL;
+ 	struct variable_entry *entry = add_entry(context, guid, name_size, name);
+@@ -276,40 +275,41 @@ const struct variable_info *variable_index_add_variable(
+ 	if (entry) {
+ 
+ 		info = &entry->info;
+-
+-		info->metadata.attributes = attributes;
+-		info->is_variable_set = true;
+-
+-		mark_dirty(entry);
+ 	}
+ 
+ 	return info;
+ }
+ 
+-const struct variable_info *variable_index_add_constraints(
++void variable_index_remove_unused_entry(
+ 	struct variable_index *context,
+-	const EFI_GUID *guid,
+-	size_t name_size,
+-	const int16_t *name,
+-	const struct variable_constraints *constraints)
++	struct variable_info *info)
+ {
+-	struct variable_info *info = NULL;
+-	struct variable_entry *entry = add_entry(context, guid, name_size, name);
+-
+-	if (entry) {
++	if (info &&
++		!info->is_constraints_set &&
++		!info->is_variable_set) {
+ 
+-		info = &entry->info;
++		struct variable_entry *entry = containing_entry(info);
++		entry->in_use = false;
+ 
+-		info->check_constraints = *constraints;
+-		info->is_constraints_set = true;
++		memset(info, 0, sizeof(struct variable_info));
+ 	}
++}
+ 
+-	return info;
++void variable_index_set_variable(
++	struct variable_info *info,
++	uint32_t attributes)
++{
++	struct variable_entry *entry = containing_entry(info);
++
++	info->metadata.attributes = attributes;
++	info->is_variable_set = true;
++
++	mark_dirty(entry);
+ }
+ 
+-void variable_index_remove_variable(
++void variable_index_clear_variable(
+ 	struct variable_index *context,
+-	const struct variable_info *info)
++	struct variable_info *info)
+ {
+ 	if (info) {
+ 
+@@ -318,48 +318,17 @@ void variable_index_remove_variable(
+ 
+ 		/* Mark variable as no longer set */
+ 		entry->info.is_variable_set = false;
+-
+-		/* Entry may still be needed if check constraints were set */
+-		entry->in_use = info->is_constraints_set;
+-
+-		if (!entry->in_use) {
+-
+-			/* Entry not needed so wipe */
+-			memset(&entry->info, 0, sizeof(struct variable_info));
+-		}
+ 	}
+ }
+ 
+-void variable_index_update_variable(
+-	const struct variable_info *info,
+-	uint32_t attributes)
+-{
+-	if (info) {
+-
+-		struct variable_info *modified_info = (struct variable_info*)info;
+-		struct variable_entry *entry = containing_entry(modified_info);
+-
+-		if (!modified_info->is_variable_set ||
+-			(attributes != modified_info->metadata.attributes)) {
+-
+-			/* The update changes the variable_info state */
+-			modified_info->is_variable_set = true;
+-			modified_info->metadata.attributes = attributes;
+-			mark_dirty(entry);
+-		}
+-	}
+-}
+-
+-void variable_index_update_constraints(
+-	const struct variable_info *info,
++void variable_index_set_constraints(
++	struct variable_info *info,
+ 	const struct variable_constraints *constraints)
+ {
+ 	if (info) {
+ 
+-		struct variable_info *modified_info = (struct variable_info*)info;
+-
+-		modified_info->check_constraints = *constraints;
+-		modified_info->is_constraints_set = true;
++		info->check_constraints = *constraints;
++		info->is_constraints_set = true;
+ 	}
+ }
+ 
+diff --git a/components/service/smm_variable/backend/variable_index.h b/components/service/smm_variable/backend/variable_index.h
+index e109d0d1..63f42ab6 100644
+--- a/components/service/smm_variable/backend/variable_index.h
++++ b/components/service/smm_variable/backend/variable_index.h
+@@ -119,8 +119,8 @@ size_t variable_index_max_dump_size(
+  *
+  * @return     Pointer to variable_info or NULL
+  */
+-const struct variable_info *variable_index_find(
+-	const struct variable_index *context,
++struct variable_info *variable_index_find(
++	struct variable_index *context,
+ 	const EFI_GUID *guid,
+ 	size_t name_size,
+ 	const int16_t *name);
+@@ -135,78 +135,76 @@ const struct variable_info *variable_index_find(
+  *
+  * @return     Pointer to variable_info or NULL
+  */
+-const struct variable_info *variable_index_find_next(
++struct variable_info *variable_index_find_next(
+ 	const struct variable_index *context,
+ 	const EFI_GUID *guid,
+ 	size_t name_size,
+ 	const int16_t *name);
+ 
+ /**
+- * @brief      Add a new variable to the index
++ * @brief      Add a new entry to the index
++ *
++ * An entry is needed either when a new variable is created or
++ * when variable constraints are set for a variable that doesn't
++ * yet exist.
+  *
+  * @param[in]  context variable_index
+  * @param[in]  guid The variable's guid
+  * @param[in]  name_size The name parameter's size
+  * @param[in]  name The variable's name
+- * @param[in]  attributes The variable's attributes
+  *
+  * @return     Pointer to variable_info or NULL
+  */
+-const struct variable_info *variable_index_add_variable(
++struct variable_info *variable_index_add_entry(
+ 	struct variable_index *context,
+ 	const EFI_GUID *guid,
+ 	size_t name_size,
+-	const int16_t *name,
+-	uint32_t attributes);
++	const int16_t *name);
+ 
+ /**
+- * @brief      Remove a variable from the index
++ * @brief      Remove an unused entry from the index
+  *
+- * Removes a variable from the index if it exists.
++ * Removes an entry if it is not in use.
+  *
+  * @param[in]  context variable_index
+  * @param[in]  info The variable info corresponding to the entry to remove
+  */
+-void variable_index_remove_variable(
++void variable_index_remove_unused_entry(
+ 	struct variable_index *context,
+-	const struct variable_info *info);
++	struct variable_info *info);
+ 
+ /**
+- * @brief      Update a variable that's already in the index
++ * @brief      Set a variable to the index
++ *
++ * An entry for the variable must already exist.
+  *
+  * @param[in]  info variable info
+  * @param[in]  attributes The variable's attributes
+  */
+-void variable_index_update_variable(
+-	const struct variable_info *info,
++void variable_index_set_variable(
++	struct variable_info *info,
+ 	uint32_t attributes);
+ 
+ /**
+- * @brief      Add a new check constraints object to the index
++ * @brief      Clear a variable from the index
+  *
+- * @param[in]  context variable_index
+- * @param[in]  guid The variable's guid
+- * @param[in]  name_size The name parameter's size
+- * @param[in]  name The variable's name
+- * @param[in]  constraints The check constraints
++ * Clears a variable from the index
+  *
+- * @return     Pointer to variable_info or NULL
++ * @param[in]  context variable_index
++ * @param[in]  info The variable info corresponding to the variable to clear
+  */
+-const struct variable_info *variable_index_add_constraints(
++void variable_index_clear_variable(
+ 	struct variable_index *context,
+-	const EFI_GUID *guid,
+-	size_t name_size,
+-	const int16_t *name,
+-	const struct variable_constraints *constraints);
++	struct variable_info *info);
+ 
+ /**
+- * @brief      Update variable constraints that are already in the index
++ * @brief      Set a check constraints object associated with a variavle
+  *
+  * @param[in]  info variable info
+  * @param[in]  constraints The check constraints
+  */
+-void variable_index_update_constraints(
+-	const struct variable_info *info,
++void variable_index_set_constraints(
++	struct variable_info *info,
+ 	const struct variable_constraints *constraints);
+ 
+ /**
+diff --git a/components/service/smm_variable/backend/variable_index_iterator.c b/components/service/smm_variable/backend/variable_index_iterator.c
+index 7cc6dc7a..8f8fc741 100644
+--- a/components/service/smm_variable/backend/variable_index_iterator.c
++++ b/components/service/smm_variable/backend/variable_index_iterator.c
+@@ -31,10 +31,10 @@ bool variable_index_iterator_is_done(
+ 	return iter->current_pos >= iter->variable_index->max_variables;
+ }
+ 
+-const struct variable_info *variable_index_iterator_current(
++struct variable_info *variable_index_iterator_current(
+ 	const struct variable_index_iterator *iter)
+ {
+-	const struct variable_info *current = NULL;
++	struct variable_info *current = NULL;
+ 
+ 	if (!variable_index_iterator_is_done(iter)) {
+ 
+diff --git a/components/service/smm_variable/backend/variable_index_iterator.h b/components/service/smm_variable/backend/variable_index_iterator.h
+index f64a2c49..7ff77c50 100644
+--- a/components/service/smm_variable/backend/variable_index_iterator.h
++++ b/components/service/smm_variable/backend/variable_index_iterator.h
+@@ -54,7 +54,7 @@ bool variable_index_iterator_is_done(
+  *
+  * @return     Pointer to variable_info or NULL
+  */
+-const struct variable_info *variable_index_iterator_current(
++struct variable_info *variable_index_iterator_current(
+ 	const struct variable_index_iterator *iter);
+ 
+ /**
+diff --git a/components/service/smm_variable/test/service/smm_variable_service_tests.cpp b/components/service/smm_variable/test/service/smm_variable_service_tests.cpp
+index d76d9cce..088940a8 100644
+--- a/components/service/smm_variable/test/service/smm_variable_service_tests.cpp
++++ b/components/service/smm_variable/test/service/smm_variable_service_tests.cpp
+@@ -249,6 +249,30 @@ TEST(SmmVariableServiceTests, setAndGet)
+ 	UNSIGNED_LONGS_EQUAL(set_data.size(), get_data.size());
+ 	LONGS_EQUAL(0, get_data.compare(set_data));
+ 
++	/* Extend the variable using an append write */
++	std::string append_data = " values added with append write";
++
++	efi_status = m_client->set_variable(
++		m_common_guid,
++		var_name,
++		append_data,
++		EFI_VARIABLE_APPEND_WRITE);
++
++	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
++
++	efi_status = m_client->get_variable(
++		m_common_guid,
++		var_name,
++		get_data);
++
++	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
++
++	std::string appended_data = set_data + append_data;
++
++	/* Expect the append write operation to have extended the variable */
++	UNSIGNED_LONGLONGS_EQUAL(appended_data.size(), get_data.size());
++	LONGS_EQUAL(0, appended_data.compare(get_data));
++
+ 	/* Expect remove to be permitted */
+ 	efi_status = m_client->remove_variable(m_common_guid, var_name);
+ 	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
+@@ -279,6 +303,30 @@ TEST(SmmVariableServiceTests, setAndGetNv)
+ 	UNSIGNED_LONGS_EQUAL(set_data.size(), get_data.size());
+ 	LONGS_EQUAL(0, get_data.compare(set_data));
+ 
++	/* Extend the variable using an append write */
++	std::string append_data = " values added with append write";
++
++	efi_status = m_client->set_variable(
++		m_common_guid,
++		var_name,
++		append_data,
++		EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_APPEND_WRITE);
++
++	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
++
++	efi_status = m_client->get_variable(
++		m_common_guid,
++		var_name,
++		get_data);
++
++	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
++
++	std::string appended_data = set_data + append_data;
++
++	/* Expect the append write operation to have extended the variable */
++	UNSIGNED_LONGLONGS_EQUAL(appended_data.size(), get_data.size());
++	LONGS_EQUAL(0, appended_data.compare(get_data));
++
+ 	/* Expect remove to be permitted */
+ 	efi_status = m_client->remove_variable(m_common_guid, var_name);
+ 	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
+diff --git a/protocols/service/smm_variable/parameters.h b/protocols/service/smm_variable/parameters.h
+index 1f795a9b..233f301b 100644
+--- a/protocols/service/smm_variable/parameters.h
++++ b/protocols/service/smm_variable/parameters.h
+@@ -47,6 +47,9 @@ typedef struct {
+ 	 EFI_VARIABLE_HARDWARE_ERROR_RECORD | \
+ 	 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
+ 	 EFI_VARIABLE_APPEND_WRITE)
++#define	EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS_MASK \
++	(EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
++	 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
+ 
+ /**
+  * Parameter structure for SetVariable and GetVariable.
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0015-Add-UEFI-variable-support-for-QueryVariableInfo.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0015-Add-UEFI-variable-support-for-QueryVariableInfo.patch
new file mode 100644
index 0000000..978600d
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0015-Add-UEFI-variable-support-for-QueryVariableInfo.patch
@@ -0,0 +1,830 @@
+From c4eaf83548eed4ed6194ff9e1368d6ae65f4ebf9 Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Thu, 2 Dec 2021 17:27:55 +0000
+Subject: [PATCH] Add UEFI variable support for QueryVariableInfo
+
+Adds support for the UEFI QueryVariableInfo operation. The total
+store size currently relies on pre-configured values, set for a
+particular deployment. Ideally, this information would be read
+from the storage backend. This facility is not however yet
+supported by the storage backend interface or by any PSA
+storage backend storage providers.
+
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: I971252831f7e478914d736c672d184a371e64502
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+
+---
+ .../backend/test/variable_store_tests.cpp     |  89 +++++++-
+ .../backend/uefi_variable_store.c             | 213 ++++++++++++++----
+ .../backend/uefi_variable_store.h             |  39 +++-
+ .../client/cpp/smm_variable_client.cpp        |  66 ++++++
+ .../client/cpp/smm_variable_client.h          |   7 +
+ .../provider/smm_variable_provider.c          |  31 ++-
+ .../service/smm_variable_service_tests.cpp    |  55 ++++-
+ 7 files changed, 445 insertions(+), 55 deletions(-)
+
+diff --git a/components/service/smm_variable/backend/test/variable_store_tests.cpp b/components/service/smm_variable/backend/test/variable_store_tests.cpp
+index 578f118f..e90c1067 100644
+--- a/components/service/smm_variable/backend/test/variable_store_tests.cpp
++++ b/components/service/smm_variable/backend/test/variable_store_tests.cpp
+@@ -27,6 +27,18 @@ TEST_GROUP(UefiVariableStoreTests)
+ 
+ 		UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+ 
++		uefi_variable_store_set_storage_limits(
++			&m_uefi_variable_store,
++			EFI_VARIABLE_NON_VOLATILE,
++			STORE_CAPACITY,
++			MAX_VARIABLE_SIZE);
++
++		uefi_variable_store_set_storage_limits(
++			&m_uefi_variable_store,
++			0,
++			STORE_CAPACITY,
++			MAX_VARIABLE_SIZE);
++
+ 		setup_common_guid();
+ 	}
+ 
+@@ -152,6 +164,33 @@ TEST_GROUP(UefiVariableStoreTests)
+ 		return status;
+ 	}
+ 
++	efi_status_t query_variable_info(
++		uint32_t attributes,
++		size_t *max_variable_storage_size,
++		size_t *remaining_variable_storage_size,
++		size_t *max_variable_size)
++	{
++		SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO query;
++
++		query.MaximumVariableStorageSize = 0;
++		query.RemainingVariableStorageSize = 0;
++		query.MaximumVariableSize = 0;
++		query.Attributes = attributes;
++
++		efi_status_t status = uefi_variable_store_query_variable_info(
++			&m_uefi_variable_store,
++			&query);
++
++		if (status == EFI_SUCCESS) {
++
++			*max_variable_storage_size = query.MaximumVariableStorageSize;
++			*remaining_variable_storage_size = query.RemainingVariableStorageSize;
++			*max_variable_size = query.MaximumVariableSize;
++		}
++
++		return status;
++	}
++
+ 	efi_status_t set_check_var_property(
+ 		const std::wstring &name,
+ 		const VAR_CHECK_VARIABLE_PROPERTY &check_property)
+@@ -195,7 +234,8 @@ TEST_GROUP(UefiVariableStoreTests)
+ 
+ 		if (info && (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE)) {
+ 
+-			struct storage_backend *storage_backend = m_uefi_variable_store.persistent_store;
++			struct storage_backend *storage_backend =
++				m_uefi_variable_store.persistent_store.storage_backend;
+ 
+ 			storage_backend->interface->remove(
+ 				storage_backend->context,
+@@ -220,9 +260,24 @@ TEST_GROUP(UefiVariableStoreTests)
+ 			m_volatile_backend);
+ 
+ 		UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
++
++		uefi_variable_store_set_storage_limits(
++			&m_uefi_variable_store,
++			EFI_VARIABLE_NON_VOLATILE,
++			STORE_CAPACITY,
++			MAX_VARIABLE_SIZE);
++
++		uefi_variable_store_set_storage_limits(
++			&m_uefi_variable_store,
++			0,
++			STORE_CAPACITY,
++			MAX_VARIABLE_SIZE);
+ 	}
+ 
+ 	static const size_t MAX_VARIABLES = 10;
++	static const size_t MAX_VARIABLE_SIZE = 100;
++	static const size_t STORE_CAPACITY = 1000;
++
+ 	static const uint32_t OWNER_ID = 100;
+ 	static const size_t VARIABLE_BUFFER_SIZE = 1024;
+ 
+@@ -265,6 +320,22 @@ TEST(UefiVariableStoreTests, setGetRoundtrip)
+ 	/* Expect the append write operation to have extended the variable */
+ 	UNSIGNED_LONGLONGS_EQUAL(expected_output.size(), output_data.size());
+ 	LONGS_EQUAL(0, expected_output.compare(output_data));
++
++	/* Expect query_variable_info to return consistent values */
++	size_t max_variable_storage_size = 0;
++	size_t remaining_variable_storage_size = 0;
++	size_t max_variable_size = 0;
++
++	status = query_variable_info(
++		0,
++		&max_variable_storage_size,
++		&remaining_variable_storage_size,
++		&max_variable_size);
++	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
++
++	UNSIGNED_LONGLONGS_EQUAL(STORE_CAPACITY, max_variable_storage_size);
++	UNSIGNED_LONGLONGS_EQUAL(MAX_VARIABLE_SIZE, max_variable_size);
++	UNSIGNED_LONGLONGS_EQUAL(STORE_CAPACITY - expected_output.size(), remaining_variable_storage_size);
+ }
+ 
+ TEST(UefiVariableStoreTests, persistentSetGet)
+@@ -311,6 +382,22 @@ TEST(UefiVariableStoreTests, persistentSetGet)
+ 	/* Still expect got variable data to be the same as the set value */
+ 	UNSIGNED_LONGLONGS_EQUAL(expected_output.size(), output_data.size());
+ 	LONGS_EQUAL(0, expected_output.compare(output_data));
++
++	/* Expect query_variable_info to return consistent values */
++	size_t max_variable_storage_size = 0;
++	size_t remaining_variable_storage_size = 0;
++	size_t max_variable_size = 0;
++
++	status = query_variable_info(
++		EFI_VARIABLE_NON_VOLATILE,
++		&max_variable_storage_size,
++		&remaining_variable_storage_size,
++		&max_variable_size);
++	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
++
++	UNSIGNED_LONGLONGS_EQUAL(STORE_CAPACITY, max_variable_storage_size);
++	UNSIGNED_LONGLONGS_EQUAL(MAX_VARIABLE_SIZE, max_variable_size);
++	UNSIGNED_LONGLONGS_EQUAL(STORE_CAPACITY - expected_output.size(), remaining_variable_storage_size);
+ }
+ 
+ TEST(UefiVariableStoreTests, removeVolatile)
+diff --git a/components/service/smm_variable/backend/uefi_variable_store.c b/components/service/smm_variable/backend/uefi_variable_store.c
+index bcb85995..ed50eaf9 100644
+--- a/components/service/smm_variable/backend/uefi_variable_store.c
++++ b/components/service/smm_variable/backend/uefi_variable_store.c
+@@ -46,8 +46,15 @@ static efi_status_t load_variable_data(
+ 	SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var,
+ 	size_t max_data_len);
+ 
+-static psa_status_t append_write(
+-	struct storage_backend *storage_backend,
++static psa_status_t store_overwrite(
++	struct delegate_variable_store *delegate_store,
++	uint32_t client_id,
++	uint64_t uid,
++	size_t data_length,
++	const void *data);
++
++static psa_status_t store_append_write(
++	struct delegate_variable_store *delegate_store,
+ 	uint32_t client_id,
+ 	uint64_t uid,
+ 	size_t data_length,
+@@ -56,6 +63,15 @@ static psa_status_t append_write(
+ static void purge_orphan_index_entries(
+ 	struct uefi_variable_store *context);
+ 
++static struct delegate_variable_store *select_delegate_store(
++	struct uefi_variable_store *context,
++	uint32_t attributes);
++
++static size_t space_used(
++	struct uefi_variable_store *context,
++	uint32_t attributes,
++	struct storage_backend *storage_backend);
++
+ static efi_status_t psa_to_efi_storage_status(
+ 	psa_status_t psa_status);
+ 
+@@ -66,6 +82,10 @@ static efi_status_t check_name_terminator(
+ /* Private UID for storing the variable index */
+ #define VARIABLE_INDEX_STORAGE_UID			(1)
+ 
++/* Default maximum variable size -
++ * may be overridden using uefi_variable_store_set_storage_limits()
++ */
++#define DEFAULT_MAX_VARIABLE_SIZE			(2048)
+ 
+ efi_status_t uefi_variable_store_init(
+ 	struct uefi_variable_store *context,
+@@ -76,8 +96,17 @@ efi_status_t uefi_variable_store_init(
+ {
+ 	efi_status_t status = EFI_SUCCESS;
+ 
+-	context->persistent_store = persistent_store;
+-	context->volatile_store = volatile_store;
++	/* Initialise persistent store defaults */
++	context->persistent_store.is_nv = true;
++	context->persistent_store.max_variable_size = DEFAULT_MAX_VARIABLE_SIZE;
++	context->persistent_store.total_capacity = DEFAULT_MAX_VARIABLE_SIZE * max_variables;
++	context->persistent_store.storage_backend = persistent_store;
++
++	/* Initialise volatile store defaults */
++	context->volatile_store.is_nv = false;
++	context->volatile_store.max_variable_size = DEFAULT_MAX_VARIABLE_SIZE;
++	context->volatile_store.total_capacity = DEFAULT_MAX_VARIABLE_SIZE * max_variables;
++	context->volatile_store.storage_backend = volatile_store;
+ 
+ 	context->owner_id = owner_id;
+ 	context->is_boot_service = true;
+@@ -116,6 +145,20 @@ void uefi_variable_store_deinit(
+ 	context->index_sync_buffer = NULL;
+ }
+ 
++void uefi_variable_store_set_storage_limits(
++	struct uefi_variable_store *context,
++	uint32_t attributes,
++	size_t total_capacity,
++	size_t max_variable_size)
++{
++	struct delegate_variable_store *delegate_store = select_delegate_store(
++		context,
++		attributes);
++
++	delegate_store->total_capacity = total_capacity;
++	delegate_store->max_variable_size = max_variable_size;
++}
++
+ efi_status_t uefi_variable_store_set_variable(
+ 	struct uefi_variable_store *context,
+ 	const SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var)
+@@ -284,12 +327,24 @@ efi_status_t uefi_variable_store_get_next_variable_name(
+ 
+ efi_status_t uefi_variable_store_query_variable_info(
+ 	struct uefi_variable_store *context,
+-	SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *cur)
++	SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *var_info)
+ {
+-	efi_status_t status = EFI_UNSUPPORTED;
++	struct delegate_variable_store *delegate_store = select_delegate_store(
++		context,
++		var_info->Attributes);
+ 
++	size_t total_used = space_used(
++		context,
++		var_info->Attributes,
++		delegate_store->storage_backend);
+ 
+-	return status;
++	var_info->MaximumVariableSize = delegate_store->max_variable_size;
++	var_info->MaximumVariableStorageSize = delegate_store->total_capacity;
++	var_info->RemainingVariableStorageSize = (total_used < delegate_store->total_capacity) ?
++		delegate_store->total_capacity - total_used :
++		0;
++
++	return EFI_SUCCESS;
+ }
+ 
+ efi_status_t uefi_variable_store_exit_boot_service(
+@@ -375,7 +430,7 @@ efi_status_t uefi_variable_store_get_var_check_property(
+ static void load_variable_index(
+ 	struct uefi_variable_store *context)
+ {
+-	struct storage_backend *persistent_store = context->persistent_store;
++	struct storage_backend *persistent_store = context->persistent_store.storage_backend;
+ 
+ 	if (persistent_store) {
+ 
+@@ -413,7 +468,7 @@ static efi_status_t sync_variable_index(
+ 
+ 	if (is_dirty) {
+ 
+-		struct storage_backend *persistent_store = context->persistent_store;
++		struct storage_backend *persistent_store = context->persistent_store.storage_backend;
+ 
+ 		if (persistent_store) {
+ 
+@@ -501,30 +556,27 @@ static efi_status_t store_variable_data(
+ 	const uint8_t *data = (const uint8_t*)var +
+ 		SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE_DATA_OFFSET(var);
+ 
+-	bool is_nv = (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE);
+-
+-	struct storage_backend *storage_backend = (is_nv) ?
+-		context->persistent_store :
+-		context->volatile_store;
++	struct delegate_variable_store *delegate_store = select_delegate_store(
++		context,
++		info->metadata.attributes);
+ 
+-	if (storage_backend) {
++	if (delegate_store->storage_backend) {
+ 
+ 		if (!(var->Attributes & EFI_VARIABLE_APPEND_WRITE)) {
+ 
+ 			/* Create or overwrite variable data */
+-			psa_status = storage_backend->interface->set(
+-				storage_backend->context,
++			psa_status = store_overwrite(
++				delegate_store,
+ 				context->owner_id,
+ 				info->metadata.uid,
+ 				data_len,
+-				data,
+-				PSA_STORAGE_FLAG_NONE);
++				data);
+ 		}
+ 		else {
+ 
+ 			/* Append new data to existing variable data */
+-			psa_status = append_write(
+-				storage_backend,
++			psa_status = store_append_write(
++				delegate_store,
+ 				context->owner_id,
+ 				info->metadata.uid,
+ 				data_len,
+@@ -532,7 +584,7 @@ static efi_status_t store_variable_data(
+ 		}
+ 	}
+ 
+-	if ((psa_status != PSA_SUCCESS) && is_nv) {
++	if ((psa_status != PSA_SUCCESS) && delegate_store->is_nv) {
+ 
+ 		/* A storage failure has occurred so attempt to fix any
+ 		 * mismatch between the variable index and stored NV variables.
+@@ -551,16 +603,14 @@ static efi_status_t remove_variable_data(
+ 
+ 	if (info->is_variable_set) {
+ 
+-		bool is_nv = (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE);
++		struct delegate_variable_store *delegate_store = select_delegate_store(
++			context,
++			info->metadata.attributes);
+ 
+-		struct storage_backend *storage_backend = (is_nv) ?
+-			context->persistent_store :
+-			context->volatile_store;
++		if (delegate_store->storage_backend) {
+ 
+-		if (storage_backend) {
+-
+-			psa_status = storage_backend->interface->remove(
+-				storage_backend->context,
++			psa_status = delegate_store->storage_backend->interface->remove(
++				delegate_store->storage_backend->context,
+ 				context->owner_id,
+ 				info->metadata.uid);
+ 		}
+@@ -580,16 +630,14 @@ static efi_status_t load_variable_data(
+ 	uint8_t *data = (uint8_t*)var +
+ 		SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE_DATA_OFFSET(var);
+ 
+-	bool is_nv = (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE);
++	struct delegate_variable_store *delegate_store = select_delegate_store(
++		context,
++		info->metadata.attributes);
+ 
+-	struct storage_backend *storage_backend = (is_nv) ?
+-		context->persistent_store :
+-		context->volatile_store;
++	if (delegate_store->storage_backend) {
+ 
+-	if (storage_backend) {
+-
+-		psa_status = storage_backend->interface->get(
+-			storage_backend->context,
++		psa_status = delegate_store->storage_backend->interface->get(
++			delegate_store->storage_backend->context,
+ 			context->owner_id,
+ 			info->metadata.uid,
+ 			0,
+@@ -603,8 +651,29 @@ static efi_status_t load_variable_data(
+ 	return psa_to_efi_storage_status(psa_status);
+ }
+ 
+-static psa_status_t append_write(
+-	struct storage_backend *storage_backend,
++static psa_status_t store_overwrite(
++	struct delegate_variable_store *delegate_store,
++	uint32_t client_id,
++	uint64_t uid,
++	size_t data_length,
++	const void *data)
++{
++	/* Police maximum variable size limit */
++	if (data_length > delegate_store->max_variable_size) return PSA_ERROR_INVALID_ARGUMENT;
++
++	psa_status_t psa_status = delegate_store->storage_backend->interface->set(
++		delegate_store->storage_backend->context,
++		client_id,
++		uid,
++		data_length,
++		data,
++		PSA_STORAGE_FLAG_NONE);
++
++	return psa_status;
++}
++
++static psa_status_t store_append_write(
++	struct delegate_variable_store *delegate_store,
+ 	uint32_t client_id,
+ 	uint64_t uid,
+ 	size_t data_length,
+@@ -614,8 +683,8 @@ static psa_status_t append_write(
+ 
+ 	if (data_length == 0) return PSA_SUCCESS;
+ 
+-	psa_status_t psa_status = storage_backend->interface->get_info(
+-		storage_backend->context,
++	psa_status_t psa_status = delegate_store->storage_backend->interface->get_info(
++		delegate_store->storage_backend->context,
+ 		client_id,
+ 		uid,
+ 		&storage_info);
+@@ -628,6 +697,9 @@ static psa_status_t append_write(
+ 	/* Defend against integer overflow */
+ 	if (new_size < storage_info.size) return PSA_ERROR_INVALID_ARGUMENT;
+ 
++		/* Police maximum variable size limit */
++	if (new_size > delegate_store->max_variable_size) return PSA_ERROR_INVALID_ARGUMENT;
++
+ 	/* Storage backend doesn't support an append operation so we need
+ 	 * need to read the current variable data, extend it and write it back.
+ 	 */
+@@ -635,8 +707,8 @@ static psa_status_t append_write(
+ 	if (!rw_buf) return PSA_ERROR_INSUFFICIENT_MEMORY;
+ 
+ 	size_t old_size = 0;
+-	psa_status = storage_backend->interface->get(
+-		storage_backend->context,
++	psa_status = delegate_store->storage_backend->interface->get(
++		delegate_store->storage_backend->context,
+ 		client_id,
+ 		uid,
+ 		0,
+@@ -651,8 +723,8 @@ static psa_status_t append_write(
+ 			/* Extend the variable data */
+ 			memcpy(&rw_buf[old_size], data, data_length);
+ 
+-			psa_status = storage_backend->interface->set(
+-				storage_backend->context,
++			psa_status = delegate_store->storage_backend->interface->set(
++				delegate_store->storage_backend->context,
+ 				client_id,
+ 				uid,
+ 				old_size + data_length,
+@@ -692,7 +764,7 @@ static void purge_orphan_index_entries(
+ 		if (info->is_variable_set && (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE)) {
+ 
+ 			struct psa_storage_info_t storage_info;
+-			struct storage_backend *storage_backend = context->persistent_store;
++			struct storage_backend *storage_backend = context->persistent_store.storage_backend;
+ 
+ 			psa_status_t psa_status = storage_backend->interface->get_info(
+ 				storage_backend->context,
+@@ -714,6 +786,53 @@ static void purge_orphan_index_entries(
+ 	if (any_orphans) sync_variable_index(context);
+ }
+ 
++static struct delegate_variable_store *select_delegate_store(
++	struct uefi_variable_store *context,
++	uint32_t attributes)
++{
++	bool is_nv = (attributes & EFI_VARIABLE_NON_VOLATILE);
++
++	return (is_nv) ?
++		&context->persistent_store :
++		&context->volatile_store;
++}
++
++static size_t space_used(
++	struct uefi_variable_store *context,
++	uint32_t attributes,
++	struct storage_backend *storage_backend)
++{
++	if (!storage_backend) return 0;
++
++	size_t total_used = 0;
++	struct variable_index_iterator iter;
++	variable_index_iterator_first(&iter, &context->variable_index);
++
++	while (!variable_index_iterator_is_done(&iter)) {
++
++		struct variable_info *info = variable_index_iterator_current(&iter);
++
++		if (info->is_variable_set &&
++		    ((info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE) ==
++			 (attributes & EFI_VARIABLE_NON_VOLATILE))) {
++
++			struct psa_storage_info_t storage_info;
++
++			psa_status_t psa_status = storage_backend->interface->get_info(
++				storage_backend->context,
++				context->owner_id,
++				info->metadata.uid,
++				&storage_info);
++
++			if (psa_status == PSA_SUCCESS) total_used += storage_info.size;
++		}
++
++		variable_index_iterator_next(&iter);
++	}
++
++	return total_used;
++}
++
+ static efi_status_t psa_to_efi_storage_status(
+ 	psa_status_t psa_status)
+ {
+diff --git a/components/service/smm_variable/backend/uefi_variable_store.h b/components/service/smm_variable/backend/uefi_variable_store.h
+index fe0f24af..cc992067 100644
+--- a/components/service/smm_variable/backend/uefi_variable_store.h
++++ b/components/service/smm_variable/backend/uefi_variable_store.h
+@@ -20,6 +20,20 @@
+ extern "C" {
+ #endif
+ 
++/**
++ * \brief delegate_variable_store structure definition
++ *
++ * A delegate_variable_store combines an association with a concrete
++ * storage backend and a set of limits parameters.
++ */
++struct delegate_variable_store
++{
++	bool is_nv;
++	size_t total_capacity;
++	size_t max_variable_size;
++	struct storage_backend *storage_backend;
++};
++
+ /**
+  * \brief uefi_variable_store structure definition
+  *
+@@ -35,8 +49,8 @@ struct uefi_variable_store
+ 	uint8_t *index_sync_buffer;
+ 	size_t index_sync_buffer_size;
+ 	struct variable_index variable_index;
+-	struct storage_backend *persistent_store;
+-	struct storage_backend *volatile_store;
++	struct delegate_variable_store persistent_store;
++	struct delegate_variable_store volatile_store;
+ };
+ 
+ /**
+@@ -69,6 +83,23 @@ efi_status_t uefi_variable_store_init(
+ void uefi_variable_store_deinit(
+ 	struct uefi_variable_store *context);
+ 
++/**
++ * @brief      Set storage limits
++ *
++ * Overrides the default limits for the specified storage space. These
++ * values are reflected in the values returned by QueryVariableInfo.
++ *
++ * @param[in]  context uefi_variable_store instance
++ * @param[in]  attributes EFI_VARIABLE_NON_VOLATILE or 0
++ * @param[in]  total_capacity The total storage capacity in bytes
++ * @param[in]  max_variable_size Variable size limit
++ */
++void uefi_variable_store_set_storage_limits(
++	struct uefi_variable_store *context,
++	uint32_t attributes,
++	size_t total_capacity,
++	size_t max_variable_size);
++
+ /**
+  * @brief      Set variable
+  *
+@@ -123,13 +154,13 @@ efi_status_t uefi_variable_store_get_next_variable_name(
+  * @brief      Query for variable info
+  *
+  * @param[in]  context uefi_variable_store instance
+- * @param[out] info Returns info
++ * @param[inout] var_info Returns info
+  *
+  * @return     EFI_SUCCESS if succesful
+  */
+ efi_status_t uefi_variable_store_query_variable_info(
+ 	struct uefi_variable_store *context,
+-	SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *cur);
++	SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *var_info);
+ 
+ /**
+  * @brief      Exit boot service
+diff --git a/components/service/smm_variable/client/cpp/smm_variable_client.cpp b/components/service/smm_variable/client/cpp/smm_variable_client.cpp
+index a68b7ace..8438285b 100644
+--- a/components/service/smm_variable/client/cpp/smm_variable_client.cpp
++++ b/components/service/smm_variable/client/cpp/smm_variable_client.cpp
+@@ -219,6 +219,72 @@ efi_status_t smm_variable_client::get_next_variable_name(
+ 		0);
+ }
+ 
++efi_status_t smm_variable_client::query_variable_info(
++	uint32_t attributes,
++	size_t *max_variable_storage_size,
++	size_t *remaining_variable_storage_size,
++	size_t *max_variable_size)
++{
++	efi_status_t efi_status = EFI_NOT_READY;
++
++	size_t req_len = sizeof(SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO);
++	rpc_call_handle call_handle;
++	uint8_t *req_buf;
++
++	call_handle = rpc_caller_begin(m_caller, &req_buf, req_len);
++
++	if (call_handle) {
++
++		uint8_t *resp_buf;
++        size_t resp_len;
++		rpc_opstatus_t opstatus;
++
++		SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *query =
++			(SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO*)req_buf;
++
++		query->Attributes = attributes;
++		query->MaximumVariableSize = 0;
++		query->MaximumVariableStorageSize = 0;
++		query->RemainingVariableStorageSize = 0;
++
++		m_err_rpc_status = rpc_caller_invoke(m_caller, call_handle,
++			SMM_VARIABLE_FUNCTION_QUERY_VARIABLE_INFO, &opstatus, &resp_buf, &resp_len);
++
++		if (m_err_rpc_status == TS_RPC_CALL_ACCEPTED) {
++
++			efi_status = opstatus;
++
++			if (efi_status == EFI_SUCCESS) {
++
++				if (resp_len >= sizeof(SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO)) {
++
++					query = (SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO*)resp_buf;
++
++					*max_variable_storage_size = query->MaximumVariableStorageSize;
++					*remaining_variable_storage_size = query->RemainingVariableStorageSize;
++					*max_variable_size = query->MaximumVariableSize;
++				}
++				else {
++
++					efi_status = EFI_PROTOCOL_ERROR;
++				}
++			}
++			else {
++
++				efi_status = EFI_PROTOCOL_ERROR;
++			}
++		}
++		else {
++
++			efi_status = rpc_to_efi_status();
++		}
++
++		rpc_caller_end(m_caller, call_handle);
++	}
++
++	return efi_status;
++}
++
+ efi_status_t smm_variable_client::get_next_variable_name(
+ 	EFI_GUID &guid,
+ 	std::wstring &name,
+diff --git a/components/service/smm_variable/client/cpp/smm_variable_client.h b/components/service/smm_variable/client/cpp/smm_variable_client.h
+index 9c36c4eb..c7973916 100644
+--- a/components/service/smm_variable/client/cpp/smm_variable_client.h
++++ b/components/service/smm_variable/client/cpp/smm_variable_client.h
+@@ -63,6 +63,13 @@ public:
+ 		const EFI_GUID &guid,
+ 		const std::wstring &name);
+ 
++	/* Query variable info */
++	efi_status_t query_variable_info(
++		uint32_t attributes,
++		size_t *max_variable_storage_size,
++		size_t *remaining_variable_storage_size,
++		size_t *max_variable_size);
++
+ 	/* Get the next variable name - for enumerating store contents */
+ 	efi_status_t get_next_variable_name(
+ 		EFI_GUID &guid,
+diff --git a/components/service/smm_variable/provider/smm_variable_provider.c b/components/service/smm_variable/provider/smm_variable_provider.c
+index d239a428..52e68d09 100644
+--- a/components/service/smm_variable/provider/smm_variable_provider.c
++++ b/components/service/smm_variable/provider/smm_variable_provider.c
+@@ -252,11 +252,38 @@ static rpc_status_t set_variable_handler(void *context, struct call_req* req)
+ 
+ static rpc_status_t query_variable_info_handler(void *context, struct call_req* req)
+ {
++	efi_status_t efi_status = EFI_INVALID_PARAMETER;
+ 	struct smm_variable_provider *this_instance = (struct smm_variable_provider*)context;
+ 
+-	/* todo */
++	const struct call_param_buf *req_buf = call_req_get_req_buf(req);
++
++	if (req_buf->data_len >= sizeof(SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO)) {
++
++		struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
++
++		if (resp_buf->size >= req_buf->data_len) {
+ 
+-	return TS_RPC_ERROR_NOT_READY;
++			memmove(resp_buf->data, req_buf->data, req_buf->data_len);
++
++			efi_status = uefi_variable_store_query_variable_info(
++				&this_instance->variable_store,
++				(SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO*)resp_buf->data);
++
++			if (efi_status == EFI_SUCCESS) {
++
++				resp_buf->data_len = sizeof(SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO);
++			}
++		}
++		else {
++
++			/* Reponse buffer not big enough */
++			efi_status = EFI_BAD_BUFFER_SIZE;
++		}
++	}
++
++	call_req_set_opstatus(req, efi_status);
++
++	return TS_RPC_CALL_ACCEPTED;
+ }
+ 
+ static rpc_status_t exit_boot_service_handler(void *context, struct call_req* req)
+diff --git a/components/service/smm_variable/test/service/smm_variable_service_tests.cpp b/components/service/smm_variable/test/service/smm_variable_service_tests.cpp
+index 088940a8..15556e9d 100644
+--- a/components/service/smm_variable/test/service/smm_variable_service_tests.cpp
++++ b/components/service/smm_variable/test/service/smm_variable_service_tests.cpp
+@@ -335,12 +335,38 @@ TEST(SmmVariableServiceTests, setAndGetNv)
+ TEST(SmmVariableServiceTests, enumerateStoreContents)
+ {
+ 	efi_status_t efi_status = EFI_SUCCESS;
++
++	/* Query information about the empty variable store */
++	size_t nv_max_variable_storage_size = 0;
++	size_t nv_max_variable_size = 0;
++	size_t nv_remaining_variable_storage_size = 0;
++
++	efi_status = m_client->query_variable_info(
++		EFI_VARIABLE_NON_VOLATILE,
++		&nv_max_variable_storage_size,
++		&nv_remaining_variable_storage_size,
++		&nv_max_variable_size);
++	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
++	UNSIGNED_LONGLONGS_EQUAL(nv_max_variable_storage_size, nv_remaining_variable_storage_size);
++
++	size_t v_max_variable_storage_size = 0;
++	size_t v_max_variable_size = 0;
++	size_t v_remaining_variable_storage_size = 0;
++
++	efi_status = m_client->query_variable_info(
++		0,
++		&v_max_variable_storage_size,
++		&v_remaining_variable_storage_size,
++		&v_max_variable_size);
++	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
++	UNSIGNED_LONGLONGS_EQUAL(v_max_variable_storage_size, v_remaining_variable_storage_size);
++
++	/* Add some variables to the store */
+ 	std::wstring var_name_1 = L"varibale_1";
+ 	std::wstring var_name_2 = L"varibale_2";
+ 	std::wstring var_name_3 = L"varibale_3";
+ 	std::string set_data = "Some variable data";
+ 
+-	/* Add some variables to the store */
+ 	efi_status = m_client->set_variable(
+ 		m_common_guid,
+ 		var_name_1,
+@@ -365,6 +391,33 @@ TEST(SmmVariableServiceTests, enumerateStoreContents)
+ 
+ 	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
+ 
++	/* Query variable info again and check it's as expected */
++	size_t max_variable_storage_size = 0;
++	size_t max_variable_size = 0;
++	size_t remaining_variable_storage_size = 0;
++
++	/* Check non-volatile - two variables have been added */
++	efi_status = m_client->query_variable_info(
++		EFI_VARIABLE_NON_VOLATILE,
++		&max_variable_storage_size,
++		&remaining_variable_storage_size,
++		&max_variable_size);
++	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
++	UNSIGNED_LONGLONGS_EQUAL(
++		(nv_remaining_variable_storage_size - set_data.size() * 2),
++		remaining_variable_storage_size);
++
++	/* Check volatile - one variables have been added */
++	efi_status = m_client->query_variable_info(
++		0,
++		&max_variable_storage_size,
++		&remaining_variable_storage_size,
++		&max_variable_size);
++	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
++	UNSIGNED_LONGLONGS_EQUAL(
++		(v_remaining_variable_storage_size - set_data.size() * 1),
++		remaining_variable_storage_size);
++
+ 	/* Enumerate store contents - expect the values we added */
+ 	std::wstring var_name;
+ 	EFI_GUID guid = {0};
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0016-Add-uefi-test-deployment.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0016-Add-uefi-test-deployment.patch
new file mode 100644
index 0000000..66a4499
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0016-Add-uefi-test-deployment.patch
@@ -0,0 +1,248 @@
+From 22120b4bd64da232e5a4e04a9a15376f34a933a3 Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Mon, 6 Dec 2021 15:20:12 +0000
+Subject: [PATCH] Add uefi-test deployment
+
+Adds a new deployment for building and running service level tests
+for UEFI SMM services. Tests may be run against StMM, smm-gateway
+or any other similar secure-world uefi service provider.
+
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: Ic0e16dff51ef76ddd1f4dea37a4a55b029edd696
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+
+---
+ .../ts-service-test/arm-linux/CMakeLists.txt  |  3 -
+ .../uefi-test/arm-linux/CMakeLists.txt        | 43 +++++++++++
+ deployments/uefi-test/linux-pc/CMakeLists.txt | 76 +++++++++++++++++++
+ deployments/uefi-test/uefi-test.cmake         | 52 +++++++++++++
+ tools/b-test/test_data.yaml                   | 10 +++
+ 5 files changed, 181 insertions(+), 3 deletions(-)
+ create mode 100644 deployments/uefi-test/arm-linux/CMakeLists.txt
+ create mode 100644 deployments/uefi-test/linux-pc/CMakeLists.txt
+ create mode 100644 deployments/uefi-test/uefi-test.cmake
+
+diff --git a/deployments/ts-service-test/arm-linux/CMakeLists.txt b/deployments/ts-service-test/arm-linux/CMakeLists.txt
+index 6a01d38a..e902cd2f 100644
+--- a/deployments/ts-service-test/arm-linux/CMakeLists.txt
++++ b/deployments/ts-service-test/arm-linux/CMakeLists.txt
+@@ -23,9 +23,6 @@ add_components(
+ 	BASE_DIR ${TS_ROOT}
+ 	COMPONENTS
+ 		"components/app/test-runner"
+-# Running smm_variable tests currently requires kernel built with CONFIG_STRICT_DEVMEM=n
+-#		"components/service/smm_variable/client/cpp"
+-#		"components/service/smm_variable/test/service"
+  )
+ 
+ include(${TS_ROOT}/external/CppUTest/CppUTest.cmake)
+diff --git a/deployments/uefi-test/arm-linux/CMakeLists.txt b/deployments/uefi-test/arm-linux/CMakeLists.txt
+new file mode 100644
+index 00000000..053041ad
+--- /dev/null
++++ b/deployments/uefi-test/arm-linux/CMakeLists.txt
+@@ -0,0 +1,43 @@
++#-------------------------------------------------------------------------------
++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++#-------------------------------------------------------------------------------
++cmake_minimum_required(VERSION 3.16)
++include(../../deployment.cmake REQUIRED)
++
++#-------------------------------------------------------------------------------
++#  The CMakeLists.txt for building the uefi-test deployment for arm-linux
++#
++#  Used for building and running service level tests from Linux user-space
++#  on an Arm platform with real deployments of UEFI SMM services
++#-------------------------------------------------------------------------------
++include(${TS_ROOT}/environments/arm-linux/env.cmake)
++project(trusted-services LANGUAGES CXX C)
++add_executable(uefi-test)
++target_include_directories(uefi-test PRIVATE "${TOP_LEVEL_INCLUDE_DIRS}")
++
++add_components(
++	TARGET "uefi-test"
++	BASE_DIR ${TS_ROOT}
++	COMPONENTS
++		"components/app/test-runner"
++ )
++
++include(${TS_ROOT}/external/CppUTest/CppUTest.cmake)
++target_link_libraries(uefi-test PRIVATE CppUTest)
++
++#-------------------------------------------------------------------------------
++#  Extend with components that are common across all deployments of
++#  uefi-test
++#
++#-------------------------------------------------------------------------------
++include(../uefi-test.cmake REQUIRED)
++
++#-------------------------------------------------------------------------------
++#  Define library options and dependencies.
++#
++#-------------------------------------------------------------------------------
++env_set_link_options(TGT uefi-test)
++target_link_libraries(uefi-test PRIVATE stdc++ gcc m)
+diff --git a/deployments/uefi-test/linux-pc/CMakeLists.txt b/deployments/uefi-test/linux-pc/CMakeLists.txt
+new file mode 100644
+index 00000000..be6e9840
+--- /dev/null
++++ b/deployments/uefi-test/linux-pc/CMakeLists.txt
+@@ -0,0 +1,76 @@
++#-------------------------------------------------------------------------------
++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++#-------------------------------------------------------------------------------
++cmake_minimum_required(VERSION 3.16)
++include(../../deployment.cmake REQUIRED)
++
++#-------------------------------------------------------------------------------
++#  The CMakeLists.txt for building the uefi-test deployment for linux-pc
++#
++#  Used for building and running service level tests in a native PC enviroment.
++#  Tests can be run by running the built executable called "uefi-test"
++#-------------------------------------------------------------------------------
++include(${TS_ROOT}/environments/linux-pc/env.cmake)
++project(trusted-services LANGUAGES CXX C)
++
++# Prevents symbols in the uefi-test executable overriding symbols with
++# with same name in libts during dynamic linking performed by the program
++# loader.
++set(CMAKE_C_VISIBILITY_PRESET hidden)
++
++# Preparing firmware-test-build by including it
++include(${TS_ROOT}/external/firmware_test_builder/FirmwareTestBuilder.cmake)
++
++include(CTest)
++include(UnitTest)
++
++set(COVERAGE FALSE CACHE BOOL "Enable code coverage measurement")
++set(UNIT_TEST_PROJECT_PATH ${TS_ROOT} CACHE PATH "Path of the project directory")
++set(CMAKE_CXX_STANDARD 11)
++
++unit_test_init_cpputest()
++
++if (COVERAGE)
++	include(Coverage)
++
++	set(COVERAGE_FILE "coverage.info")
++	set(TS_SERVICE_TEST_COVERAGE_FILE "uefi-test-coverage.info" CACHE PATH "Path of coverage info file")
++	set(TS_SERVICE_TEST_COVERAGE_REPORT_DIR "${CMAKE_CURRENT_BINARY_DIR}/ts-service-coverage-report" CACHE PATH "Directory of coverage report")
++
++	# Collecting coverage
++	coverage_generate(
++		NAME "ts-service test"
++		SOURCE_DIR ${TS_ROOT}
++		BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}
++		OUTPUT_FILE ${COVERAGE_FILE}
++	)
++
++	# Filtering project file coverage
++	coverage_filter(
++		INPUT_FILE ${COVERAGE_FILE}
++		OUTPUT_FILE ${TS_SERVICE_TEST_COVERAGE_FILE}
++		INCLUDE_DIRECTORY ${UNIT_TEST_PROJECT_PATH}/components
++	)
++
++	# Coverage report
++	coverage_generate_report(
++		INPUT_FILE ${TS_SERVICE_TEST_COVERAGE_FILE}
++		OUTPUT_DIRECTORY ${TS_SERVICE_TEST_COVERAGE_REPORT_DIR}
++	)
++endif()
++
++unit_test_add_suite(
++	NAME uefi-test
++)
++
++target_include_directories(uefi-test PRIVATE "${TOP_LEVEL_INCLUDE_DIRS}")
++
++#-------------------------------------------------------------------------------
++#  Extend with components that are common across all deployments of
++#  uefi-test
++#
++#-------------------------------------------------------------------------------
++include(../uefi-test.cmake REQUIRED)
+diff --git a/deployments/uefi-test/uefi-test.cmake b/deployments/uefi-test/uefi-test.cmake
+new file mode 100644
+index 00000000..ea678d0e
+--- /dev/null
++++ b/deployments/uefi-test/uefi-test.cmake
+@@ -0,0 +1,52 @@
++#-------------------------------------------------------------------------------
++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++#-------------------------------------------------------------------------------
++
++#-------------------------------------------------------------------------------
++#  The base build file shared between deployments of 'uefi-test' for
++#  different environments.  Used for running end-to-end service-level tests
++#  against SMM service providers that implement UEFI services such as smm
++#  variable.
++#-------------------------------------------------------------------------------
++
++#-------------------------------------------------------------------------------
++#  Use libts for locating and accessing services. An appropriate version of
++#  libts will be imported for the enviroment in which service tests are
++#  deployed.
++#-------------------------------------------------------------------------------
++include(${TS_ROOT}/deployments/libts/libts-import.cmake)
++target_link_libraries(uefi-test PRIVATE libts)
++
++#-------------------------------------------------------------------------------
++#  Components that are common accross all deployments
++#
++#-------------------------------------------------------------------------------
++add_components(
++	TARGET "uefi-test"
++	BASE_DIR ${TS_ROOT}
++	COMPONENTS
++		"components/service/smm_variable/client/cpp"
++		"components/service/smm_variable/test/service"
++)
++
++#-------------------------------------------------------------------------------
++#  Components used from external projects
++#
++#-------------------------------------------------------------------------------
++
++# Nanopb
++include(${TS_ROOT}/external/nanopb/nanopb.cmake)
++target_link_libraries(uefi-test PRIVATE nanopb::protobuf-nanopb-static)
++protobuf_generate_all(TGT "uefi-test" NAMESPACE "protobuf" BASE_DIR "${TS_ROOT}/protocols")
++
++#-------------------------------------------------------------------------------
++#  Define install content.
++#
++#-------------------------------------------------------------------------------
++if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
++	set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install CACHE PATH "location to install build output to." FORCE)
++endif()
++install(TARGETS uefi-test RUNTIME DESTINATION ${TS_ENV}/bin)
+diff --git a/tools/b-test/test_data.yaml b/tools/b-test/test_data.yaml
+index 11f8f633..33a85b12 100644
+--- a/tools/b-test/test_data.yaml
++++ b/tools/b-test/test_data.yaml
+@@ -163,3 +163,13 @@ data:
+       os_id : "GNU/Linux"
+       params:
+           - "-GUnix Makefiles"
++    - name: "uefi-test-pc-linux"
++      src: "$TS_ROOT/deployments/uefi-test/linux-pc"
++      os_id : "GNU/Linux"
++      params:
++          - "-GUnix Makefiles"
++    - name: "uefi-test-arm-linux"
++      src: "$TS_ROOT/deployments/uefi-test/arm-linux"
++      os_id : "GNU/Linux"
++      params:
++          - "-GUnix Makefiles"
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0017-Fix-interface-ID-parameter-setting-in-sp-ffarpc_call.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0017-Fix-interface-ID-parameter-setting-in-sp-ffarpc_call.patch
new file mode 100644
index 0000000..9ad506b
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0017-Fix-interface-ID-parameter-setting-in-sp-ffarpc_call.patch
@@ -0,0 +1,33 @@
+From 289bec4cacac80cb43c19e4ca7b2c50fc932712e Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Wed, 8 Dec 2021 11:48:28 +0000
+Subject: [PATCH] Fix interface ID parameter setting in sp/ffarpc_caller
+
+When making FFA based RPC calls from one SP to another, the
+destination interface ID parameter was not being set correctly.
+This change fixes this issue.
+
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: Iab520e4c7dc63ee1f5d3bf1bd1de702e4cc6f093
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+
+---
+ components/rpc/ffarpc/caller/sp/ffarpc_caller.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/components/rpc/ffarpc/caller/sp/ffarpc_caller.c b/components/rpc/ffarpc/caller/sp/ffarpc_caller.c
+index 250b1781..dabcd90c 100644
+--- a/components/rpc/ffarpc/caller/sp/ffarpc_caller.c
++++ b/components/rpc/ffarpc/caller/sp/ffarpc_caller.c
+@@ -81,7 +81,7 @@ static rpc_status_t call_invoke(void *context, rpc_call_handle handle, uint32_t
+ 	req.destination_id = this_context->dest_partition_id;
+ 	req.source_id = own_id;
+ 	req.args[SP_CALL_ARGS_IFACE_ID_OPCODE] =
+-		FFA_CALL_ARGS_COMBINE_IFACE_ID_OPCODE(this_context->dest_partition_id, opcode);
++		FFA_CALL_ARGS_COMBINE_IFACE_ID_OPCODE(this_context->dest_iface_id, opcode);
+ 	//TODO: downcast problem?
+ 	req.args[SP_CALL_ARGS_REQ_DATA_LEN] = (uint32_t)this_context->req_len;
+ 	req.args[SP_CALL_ARGS_ENCODING] = this_context->rpc_caller.encoding;
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0018-Support-FFARPC-call-requests-with-no-shared-buffer.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0018-Support-FFARPC-call-requests-with-no-shared-buffer.patch
new file mode 100644
index 0000000..6ea473b
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0018-Support-FFARPC-call-requests-with-no-shared-buffer.patch
@@ -0,0 +1,109 @@
+From 18b20dea7cf7e8afc26c5d49d5368d3180bd54d7 Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Wed, 8 Dec 2021 16:05:22 +0000
+Subject: [PATCH] Support FFARPC call requests with no shared buffer
+
+To allow simple clients to make RPC calls for service operations
+that take no request parameters and return no response parameters,
+the ffarpc_call_ep.c has been modified to accept call requests
+when no shared buffer exists, as long as there is no request data.
+
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: I83b1bfb719a005922d6394887492d2d272b74907
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+
+---
+ .../rpc/ffarpc/endpoint/ffarpc_call_ep.c      | 52 ++++++++++---------
+ 1 file changed, 27 insertions(+), 25 deletions(-)
+
+diff --git a/components/rpc/ffarpc/endpoint/ffarpc_call_ep.c b/components/rpc/ffarpc/endpoint/ffarpc_call_ep.c
+index 17f957c2..a08a250c 100644
+--- a/components/rpc/ffarpc/endpoint/ffarpc_call_ep.c
++++ b/components/rpc/ffarpc/endpoint/ffarpc_call_ep.c
+@@ -150,29 +150,43 @@ out:
+ static void handle_service_msg(struct ffa_call_ep *call_ep, uint16_t source_id,
+ 			       const uint32_t *req_args, uint32_t *resp_args)
+ {
+-	rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
++	rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_PARAMETER;
+ 	struct call_req call_req;
+ 
+ 	uint32_t ifaceid_opcode = req_args[SP_CALL_ARGS_IFACE_ID_OPCODE];
+ 	int idx = find_shm(call_ep, source_id);
+ 
+-	if (idx < 0) {
+-		EMSG("handle service msg error");
+-		goto out;
+-	}
+-
+ 	call_req.caller_id = source_id;
+ 	call_req.interface_id = FFA_CALL_ARGS_EXTRACT_IFACE(ifaceid_opcode);
+ 	call_req.opcode = FFA_CALL_ARGS_EXTRACT_OPCODE(ifaceid_opcode);
+ 	call_req.encoding = req_args[SP_CALL_ARGS_ENCODING];
+ 
+-	call_req.req_buf.data = call_ep->shmem_buf[idx];
+ 	call_req.req_buf.data_len = req_args[SP_CALL_ARGS_REQ_DATA_LEN];
+-	call_req.req_buf.size = call_ep->shmem_buf_size[idx];
+-
+-	call_req.resp_buf.data = call_ep->shmem_buf[idx];
+ 	call_req.resp_buf.data_len = 0;
+-	call_req.resp_buf.size = call_ep->shmem_buf_size[idx];
++
++	if (idx >= 0 && call_ep->shmem_buf[idx]) {
++		/* A shared buffer is available for call parameters */
++		call_req.req_buf.data = call_ep->shmem_buf[idx];
++		call_req.req_buf.size = call_ep->shmem_buf_size[idx];
++
++		call_req.resp_buf.data = call_ep->shmem_buf[idx];
++		call_req.resp_buf.size = call_ep->shmem_buf_size[idx];
++	}
++	else if (call_req.req_buf.data_len == 0) {
++		/* No shared buffer so only allow calls with no request data */
++		call_req.req_buf.data = NULL;
++		call_req.req_buf.size = 0;
++
++		call_req.resp_buf.data = NULL;
++		call_req.resp_buf.size = 0;
++	}
++	else {
++		/*
++		 * Caller has specified non-zero length request data but there is
++		 * no shared buffer to carry the request data.
++		 */
++		goto out;
++	}
+ 
+ 	rpc_status = rpc_interface_receive(call_ep->iface, &call_req);
+ 
+@@ -223,7 +237,6 @@ void ffa_call_ep_receive(struct ffa_call_ep *call_ep,
+ {
+ 	const uint32_t *req_args = req_msg->args;
+ 	uint32_t *resp_args = resp_msg->args;
+-	int idx;
+ 
+ 	uint16_t source_id = req_msg->source_id;
+ 	uint32_t ifaceid_opcode = req_args[SP_CALL_ARGS_IFACE_ID_OPCODE];
+@@ -232,18 +245,7 @@ void ffa_call_ep_receive(struct ffa_call_ep *call_ep,
+ 		/* It's an RPC layer management request */
+ 		handle_mgmt_msg(call_ep, source_id, req_args, resp_args);
+ 	} else {
+-		/*
+-		 * Assume anything else is a service request. Service requests
+-		 * rely on a buffer being shared from the requesting client.
+-		 * If it hasn't been set-up, fail the request.
+-		 */
+-		idx = find_shm(call_ep, source_id);
+-
+-		if (idx >= 0 && call_ep->shmem_buf[idx]) {
+-			handle_service_msg(call_ep, source_id, req_args, resp_args);
+-		} else {
+-			EMSG("shared buffer not found or NULL");
+-			set_mgmt_resp_args(resp_args, ifaceid_opcode, TS_RPC_ERROR_NOT_READY);
+-		}
++		/* Assume anything else is a service request */
++		handle_service_msg(call_ep, source_id, req_args, resp_args);
+ 	}
+ }
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0019-Run-psa-arch-test.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0019-Run-psa-arch-test.patch
new file mode 100644
index 0000000..4f54215
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0019-Run-psa-arch-test.patch
@@ -0,0 +1,86 @@
+From a496978dcf82494c69e600f65adf061f15e565f4 Mon Sep 17 00:00:00 2001
+From: Satish Kumar <satish.kumar01@arm.com>
+Date: Sun, 12 Dec 2021 10:43:48 +0000
+Subject: [PATCH] Run psa-arch-test
+
+Fixes needed to run psa-arch-test
+
+Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
+
+
+---
+ components/service/common/psa_ipc/service_psa_ipc.c       | 1 +
+ .../backend/secure_storage_ipc/secure_storage_ipc.c       | 8 --------
+ .../service/secure_storage/include/psa/storage_common.h   | 4 ++--
+ external/openamp/openamp.cmake                            | 2 +-
+ 4 files changed, 4 insertions(+), 11 deletions(-)
+
+diff --git a/components/service/common/psa_ipc/service_psa_ipc.c b/components/service/common/psa_ipc/service_psa_ipc.c
+index 95a07c13..5e5815db 100644
+--- a/components/service/common/psa_ipc/service_psa_ipc.c
++++ b/components/service/common/psa_ipc/service_psa_ipc.c
+@@ -185,6 +185,7 @@ psa_status_t psa_call(struct rpc_caller *caller, psa_handle_t psa_handle,
+ 						     resp_msg->params.out_vec);
+ 
+ 	for (i = 0; i < resp_msg->params.out_len; i++) {
++                out_vec[i].len = out_vec_param[i].len;
+ 		memcpy(out_vec[i].base, rpc_caller_phys_to_virt(caller, out_vec_param[i].base),
+ 		       out_vec[i].len);
+ 	}
+diff --git a/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
+index 9b55f77d..a1f369db 100644
+--- a/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
++++ b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
+@@ -31,10 +31,6 @@ static psa_status_t secure_storage_ipc_set(void *context, uint32_t client_id,
+ 
+ 	ipc->client.rpc_status = TS_RPC_CALL_ACCEPTED;
+ 
+-	/* Validating input parameters */
+-	if (p_data == NULL)
+-		return PSA_ERROR_INVALID_ARGUMENT;
+-
+ 	psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
+ 			      TFM_PS_SET, in_vec, IOVEC_LEN(in_vec), NULL, 0);
+ 	if (psa_status < 0)
+@@ -96,10 +92,6 @@ static psa_status_t secure_storage_ipc_get_info(void *context,
+ 
+ 	(void)client_id;
+ 
+-	/* Validating input parameters */
+-	if (!p_info)
+-		return PSA_ERROR_INVALID_ARGUMENT;
+-
+ 	psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
+ 			      TFM_PS_GET_INFO, in_vec,
+ 			      IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
+diff --git a/components/service/secure_storage/include/psa/storage_common.h b/components/service/secure_storage/include/psa/storage_common.h
+index 4f6ba2a7..1fd6b40d 100644
+--- a/components/service/secure_storage/include/psa/storage_common.h
++++ b/components/service/secure_storage/include/psa/storage_common.h
+@@ -20,8 +20,8 @@ typedef uint64_t psa_storage_uid_t;
+ typedef uint32_t psa_storage_create_flags_t;
+ 
+ struct psa_storage_info_t {
+-	size_t capacity;
+-	size_t size;
++	uint32_t capacity;
++	uint32_t size;
+ 	psa_storage_create_flags_t flags;
+ };
+ 
+diff --git a/external/openamp/openamp.cmake b/external/openamp/openamp.cmake
+index aae13bad..75ab2290 100644
+--- a/external/openamp/openamp.cmake
++++ b/external/openamp/openamp.cmake
+@@ -61,7 +61,7 @@ execute_process(COMMAND
+ 			-DCMAKE_SYSTEM_PROCESSOR=arm
+ 			-DEXTERNAL_INCLUDE_PATHS=${OPENAMP_EXTERNAL_INCLUDE_PATHS}
+ 			-DMACHINE=template
+-			-DRPMSG_BUFFER_SIZE=512
++			-DRPMSG_BUFFER_SIZE=8192
+ 			${openamp_SOURCE_DIR}
+ 	WORKING_DIRECTORY
+ 			${openamp_BINARY_DIR}
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0020-Use-address-instead-of-pointers.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0020-Use-address-instead-of-pointers.patch
new file mode 100644
index 0000000..844bca3
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0020-Use-address-instead-of-pointers.patch
@@ -0,0 +1,169 @@
+From b417c1124af9d4569ba8871dfd1e43e626dddf12 Mon Sep 17 00:00:00 2001
+From: Satish Kumar <satish.kumar01@arm.com>
+Date: Sun, 12 Dec 2021 10:57:17 +0000
+Subject: [PATCH] Use address instead of pointers
+
+Since secure enclave is 32bit and we 64bit there is an issue
+in the protocol communication design that force us to handle
+on our side the manipulation of address and pointers to make
+this work.
+
+Signed-off-by: Rui Miguel Silva <rui.silva@arm.com>
+Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
+
+
+---
+ .../service/common/include/psa/client.h       | 15 ++++++++++++++
+ .../service/common/psa_ipc/service_psa_ipc.c  | 20 ++++++++++++-------
+ .../secure_storage_ipc/secure_storage_ipc.c   | 20 +++++++++----------
+ 3 files changed, 38 insertions(+), 17 deletions(-)
+
+diff --git a/components/service/common/include/psa/client.h b/components/service/common/include/psa/client.h
+index 69ccf14f..12dcd68f 100644
+--- a/components/service/common/include/psa/client.h
++++ b/components/service/common/include/psa/client.h
+@@ -81,6 +81,21 @@ struct __attribute__ ((__packed__)) psa_outvec {
+     uint32_t len;                 /*!< the size in bytes                      */
+ };
+ 
++static void *psa_u32_to_ptr(uint32_t addr)
++{
++	return (void *)(uintptr_t)addr;
++}
++
++static uint32_t psa_ptr_to_u32(void *ptr)
++{
++	return (uintptr_t)ptr;
++}
++
++static uint32_t psa_ptr_const_to_u32(const void *ptr)
++{
++	return (uintptr_t)ptr;
++}
++
+ /*************************** PSA Client API **********************************/
+ 
+ /**
+diff --git a/components/service/common/psa_ipc/service_psa_ipc.c b/components/service/common/psa_ipc/service_psa_ipc.c
+index 5e5815db..435c6c0a 100644
+--- a/components/service/common/psa_ipc/service_psa_ipc.c
++++ b/components/service/common/psa_ipc/service_psa_ipc.c
+@@ -62,6 +62,11 @@ static size_t psa_call_out_vec_len(const struct psa_outvec *out_vec, size_t out_
+ 	return resp_len;
+ }
+ 
++static uint32_t psa_virt_to_phys_u32(struct rpc_caller *caller, void *va)
++{
++	return (uintptr_t)rpc_caller_virt_to_phys(caller, va);
++}
++
+ psa_handle_t psa_connect(struct rpc_caller *caller, uint32_t sid,
+ 			 uint32_t version)
+ {
+@@ -147,20 +152,20 @@ psa_status_t psa_call(struct rpc_caller *caller, psa_handle_t psa_handle,
+ 	req_msg->params.psa_call_params.handle = psa_handle;
+ 	req_msg->params.psa_call_params.type = type;
+ 	req_msg->params.psa_call_params.in_len = in_len;
+-	req_msg->params.psa_call_params.in_vec = rpc_caller_virt_to_phys(caller, in_vec_param);
++	req_msg->params.psa_call_params.in_vec = psa_virt_to_phys_u32(caller, in_vec_param);
+ 	req_msg->params.psa_call_params.out_len = out_len;
+-	req_msg->params.psa_call_params.out_vec = rpc_caller_virt_to_phys(caller, out_vec_param);
++	req_msg->params.psa_call_params.out_vec = psa_virt_to_phys_u32(caller, out_vec_param);
+ 
+ 	for (i = 0; i < in_len; i++) {
+-		in_vec_param[i].base = rpc_caller_virt_to_phys(caller, payload);
++		in_vec_param[i].base = psa_virt_to_phys_u32(caller, payload);
+ 		in_vec_param[i].len = in_vec[i].len;
+ 
+-		memcpy(payload, in_vec[i].base, in_vec[i].len);
++		memcpy(payload, psa_u32_to_ptr(in_vec[i].base), in_vec[i].len);
+ 		payload += in_vec[i].len;
+ 	}
+ 
+ 	for (i = 0; i < out_len; i++) {
+-		out_vec_param[i].base = NULL;
++		out_vec_param[i].base = 0;
+ 		out_vec_param[i].len = out_vec[i].len;
+ 	}
+ 
+@@ -182,11 +187,12 @@ psa_status_t psa_call(struct rpc_caller *caller, psa_handle_t psa_handle,
+ 		goto caller_end;
+ 
+ 	out_vec_param = (struct psa_outvec *)rpc_caller_phys_to_virt(caller,
+-						     resp_msg->params.out_vec);
++				psa_u32_to_ptr(resp_msg->params.out_vec));
+ 
+ 	for (i = 0; i < resp_msg->params.out_len; i++) {
+                 out_vec[i].len = out_vec_param[i].len;
+-		memcpy(out_vec[i].base, rpc_caller_phys_to_virt(caller, out_vec_param[i].base),
++		memcpy(psa_u32_to_ptr(out_vec[i].base),
++		       rpc_caller_phys_to_virt(caller,	psa_u32_to_ptr(out_vec_param[i].base)),
+ 		       out_vec[i].len);
+ 	}
+ 
+diff --git a/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
+index a1f369db..bda442a6 100644
+--- a/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
++++ b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
+@@ -22,9 +22,9 @@ static psa_status_t secure_storage_ipc_set(void *context, uint32_t client_id,
+ 	psa_handle_t psa_handle;
+ 	psa_status_t psa_status;
+ 	struct psa_invec in_vec[] = {
+-		{ .base = &uid, .len = sizeof(uid) },
+-		{ .base = p_data, .len = data_length },
+-		{ .base = &create_flags, .len = sizeof(create_flags) },
++		{ .base = psa_ptr_to_u32(&uid), .len = sizeof(uid) },
++		{ .base = psa_ptr_const_to_u32(p_data), .len = data_length },
++		{ .base = psa_ptr_to_u32(&create_flags), .len = sizeof(create_flags) },
+ 	};
+ 
+ 	(void)client_id;
+@@ -53,11 +53,11 @@ static psa_status_t secure_storage_ipc_get(void *context,
+ 	psa_status_t psa_status;
+ 	uint32_t offset = (uint32_t)data_offset;
+ 	struct psa_invec in_vec[] = {
+-		{ .base = &uid, .len = sizeof(uid) },
+-		{ .base = &offset, .len = sizeof(offset) },
++		{ .base = psa_ptr_to_u32(&uid), .len = sizeof(uid) },
++		{ .base = psa_ptr_to_u32(&offset), .len = sizeof(offset) },
+ 	};
+ 	struct psa_outvec out_vec[] = {
+-		{ .base = p_data, .len = data_size },
++		{ .base = psa_ptr_to_u32(p_data), .len = data_size },
+ 	};
+ 
+ 	if (!p_data_length) {
+@@ -84,10 +84,10 @@ static psa_status_t secure_storage_ipc_get_info(void *context,
+ 	psa_handle_t psa_handle;
+ 	psa_status_t psa_status;
+ 	struct psa_invec in_vec[] = {
+-		{ .base = &uid, .len = sizeof(uid) },
++		{ .base = psa_ptr_to_u32(&uid), .len = sizeof(uid) },
+ 	};
+ 	struct psa_outvec out_vec[] = {
+-		{ .base = p_info, .len = sizeof(*p_info) },
++		{ .base = psa_ptr_to_u32(p_info), .len = sizeof(*p_info) },
+ 	};
+ 
+ 	(void)client_id;
+@@ -110,7 +110,7 @@ static psa_status_t secure_storage_ipc_remove(void *context,
+ 	psa_handle_t psa_handle;
+ 	psa_status_t psa_status;
+ 	struct psa_invec in_vec[] = {
+-		{ .base = &uid, .len = sizeof(uid) },
++		{ .base = psa_ptr_to_u32(&uid), .len = sizeof(uid) },
+ 	};
+ 
+ 	(void)client_id;
+@@ -164,7 +164,7 @@ static uint32_t secure_storage_get_support(void *context, uint32_t client_id)
+ 	psa_status_t psa_status;
+ 	uint32_t support_flags;
+ 	struct psa_outvec out_vec[] = {
+-		{ .base = &support_flags, .len =  sizeof(support_flags) },
++		{ .base = psa_ptr_to_u32(&support_flags), .len =  sizeof(support_flags) },
+ 	};
+ 
+ 	(void)client_id;
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0021-Add-psa-ipc-attestation-to-se-proxy.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0021-Add-psa-ipc-attestation-to-se-proxy.patch
new file mode 100644
index 0000000..5376bb2
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0021-Add-psa-ipc-attestation-to-se-proxy.patch
@@ -0,0 +1,267 @@
+From 259300dc81b95ff65cd2e95e0fecd140d76e4b5e Mon Sep 17 00:00:00 2001
+From: Rui Miguel Silva <rui.silva@linaro.org>
+Date: Tue, 7 Dec 2021 11:50:00 +0000
+Subject: [PATCH] Add psa ipc attestation to se proxy
+
+Implement attestation client API as psa ipc and include it to
+se proxy deployment.
+
+Signed-off-by: Rui Miguel Silva <rui.silva@arm.com>
+Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+
+
+---
+ .../client/psa_ipc/component.cmake            | 13 +++
+ .../client/psa_ipc/iat_ipc_client.c           | 86 +++++++++++++++++++
+ .../reporter/psa_ipc/component.cmake          | 13 +++
+ .../reporter/psa_ipc/psa_ipc_attest_report.c  | 45 ++++++++++
+ components/service/common/include/psa/sid.h   |  4 +
+ deployments/se-proxy/opteesp/CMakeLists.txt   |  3 +-
+ .../se-proxy/opteesp/service_proxy_factory.c  |  6 ++
+ 7 files changed, 169 insertions(+), 1 deletion(-)
+ create mode 100644 components/service/attestation/client/psa_ipc/component.cmake
+ create mode 100644 components/service/attestation/client/psa_ipc/iat_ipc_client.c
+ create mode 100644 components/service/attestation/reporter/psa_ipc/component.cmake
+ create mode 100644 components/service/attestation/reporter/psa_ipc/psa_ipc_attest_report.c
+
+diff --git a/components/service/attestation/client/psa_ipc/component.cmake b/components/service/attestation/client/psa_ipc/component.cmake
+new file mode 100644
+index 00000000..a5bc6b4a
+--- /dev/null
++++ b/components/service/attestation/client/psa_ipc/component.cmake
+@@ -0,0 +1,13 @@
++#-------------------------------------------------------------------------------
++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++#-------------------------------------------------------------------------------
++if (NOT DEFINED TGT)
++	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
++endif()
++
++target_sources(${TGT} PRIVATE
++	"${CMAKE_CURRENT_LIST_DIR}/iat_ipc_client.c"
++	)
+diff --git a/components/service/attestation/client/psa_ipc/iat_ipc_client.c b/components/service/attestation/client/psa_ipc/iat_ipc_client.c
+new file mode 100644
+index 00000000..30bd0a13
+--- /dev/null
++++ b/components/service/attestation/client/psa_ipc/iat_ipc_client.c
+@@ -0,0 +1,86 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#include <stddef.h>
++#include <string.h>
++
++#include "../psa/iat_client.h"
++#include <protocols/rpc/common/packed-c/status.h>
++#include <psa/initial_attestation.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++
++/**
++ * @brief      The singleton psa_iat_client instance
++ *
++ * The psa attestation C API assumes a single backend service provider.
++ */
++static struct service_client instance;
++
++
++psa_status_t psa_iat_client_init(struct rpc_caller *caller)
++{
++	return service_client_init(&instance, caller);
++}
++
++void psa_iat_client_deinit(void)
++{
++	service_client_deinit(&instance);
++}
++
++int psa_iat_client_rpc_status(void)
++{
++	return instance.rpc_status;
++}
++
++psa_status_t psa_initial_attest_get_token(const uint8_t *auth_challenge,
++					  size_t challenge_size,
++					  uint8_t *token_buf,
++					  size_t token_buf_size,
++					  size_t *token_size)
++{
++	psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
++	struct rpc_caller *caller = instance.caller;
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_const_to_u32(auth_challenge), .len = challenge_size},
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(token_buf), .len = token_buf_size},
++	};
++
++	if (!token_buf || !token_buf_size)
++		return PSA_ERROR_INVALID_ARGUMENT;
++
++	status = psa_call(caller, TFM_ATTESTATION_SERVICE_HANDLE,
++			  TFM_ATTEST_GET_TOKEN, in_vec, IOVEC_LEN(in_vec),
++			  out_vec, IOVEC_LEN(out_vec));
++	if (status == PSA_SUCCESS) {
++		*token_size = out_vec[0].len;
++	}
++
++	return status;
++}
++
++psa_status_t psa_initial_attest_get_token_size(size_t challenge_size,
++						size_t *token_size)
++{
++	struct rpc_caller *caller = instance.caller;
++	psa_status_t status;
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&challenge_size), .len = sizeof(uint32_t)}
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(token_size), .len = sizeof(uint32_t)}
++	};
++
++	status = psa_call(caller, TFM_ATTESTATION_SERVICE_HANDLE,
++			  TFM_ATTEST_GET_TOKEN_SIZE,
++			  in_vec, IOVEC_LEN(in_vec),
++			  out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
+diff --git a/components/service/attestation/reporter/psa_ipc/component.cmake b/components/service/attestation/reporter/psa_ipc/component.cmake
+new file mode 100644
+index 00000000..b37830c6
+--- /dev/null
++++ b/components/service/attestation/reporter/psa_ipc/component.cmake
+@@ -0,0 +1,13 @@
++#-------------------------------------------------------------------------------
++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++#-------------------------------------------------------------------------------
++if (NOT DEFINED TGT)
++	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
++endif()
++
++target_sources(${TGT} PRIVATE
++	"${CMAKE_CURRENT_LIST_DIR}/psa_ipc_attest_report.c"
++	)
+diff --git a/components/service/attestation/reporter/psa_ipc/psa_ipc_attest_report.c b/components/service/attestation/reporter/psa_ipc/psa_ipc_attest_report.c
+new file mode 100644
+index 00000000..15805e8e
+--- /dev/null
++++ b/components/service/attestation/reporter/psa_ipc/psa_ipc_attest_report.c
+@@ -0,0 +1,45 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++/**
++ * A attestation reporter for psa ipc
++ */
++
++#include <stddef.h>
++#include <psa/error.h>
++#include <service/attestation/reporter/attest_report.h>
++#include <psa/initial_attestation.h>
++
++#define TOKEN_BUF_SIZE	1024
++
++static uint8_t token_buf[TOKEN_BUF_SIZE];
++
++int attest_report_create(int32_t client_id, const uint8_t *auth_challenge_data,
++			 size_t auth_challenge_len, const uint8_t **report,
++			 size_t *report_len)
++{
++	*report = token_buf;
++	psa_status_t ret;
++	size_t token_size = 0;
++
++	ret = psa_initial_attest_get_token(auth_challenge_data,
++					   auth_challenge_len, token_buf,
++					   TOKEN_BUF_SIZE, &token_size);
++	if (ret != PSA_SUCCESS) {
++		*report = NULL;
++		*report_len = 0;
++		return ret;
++	}
++
++	*report_len = token_size;
++
++	return PSA_SUCCESS;
++}
++
++void attest_report_destroy(const uint8_t *report)
++{
++	(void)report;
++}
+diff --git a/components/service/common/include/psa/sid.h b/components/service/common/include/psa/sid.h
+index aaa973c6..833f5039 100644
+--- a/components/service/common/include/psa/sid.h
++++ b/components/service/common/include/psa/sid.h
+@@ -50,6 +50,10 @@ extern "C" {
+ #define TFM_ATTESTATION_SERVICE_VERSION                            (1U)
+ #define TFM_ATTESTATION_SERVICE_HANDLE                             (0x40000103U)
+ 
++/* Initial Attestation message types that distinguish Attest services. */
++#define TFM_ATTEST_GET_TOKEN       1001
++#define TFM_ATTEST_GET_TOKEN_SIZE  1002
++
+ /******** TFM_SP_FWU ********/
+ #define TFM_FWU_WRITE_SID                                          (0x000000A0U)
+ #define TFM_FWU_WRITE_VERSION                                      (1U)
+diff --git a/deployments/se-proxy/opteesp/CMakeLists.txt b/deployments/se-proxy/opteesp/CMakeLists.txt
+index 663177b7..af2225e7 100644
+--- a/deployments/se-proxy/opteesp/CMakeLists.txt
++++ b/deployments/se-proxy/opteesp/CMakeLists.txt
+@@ -77,12 +77,13 @@ add_components(TARGET "se-proxy"
+ 		"components/service/attestation/include"
+ 		"components/service/attestation/provider"
+ 		"components/service/attestation/provider/serializer/packed-c"
++		"components/service/attestation/reporter/psa_ipc"
++		"components/service/attestation/client/psa_ipc"
+ 		"components/rpc/openamp/caller/sp"
+ 
+ 		# Stub service provider backends
+ 		"components/rpc/dummy"
+ 		"components/rpc/common/caller"
+-		"components/service/attestation/reporter/stub"
+ 		"components/service/attestation/key_mngr/stub"
+ 		"components/service/crypto/backend/stub"
+ 		"components/service/crypto/client/psa"
+diff --git a/deployments/se-proxy/opteesp/service_proxy_factory.c b/deployments/se-proxy/opteesp/service_proxy_factory.c
+index 57290056..4b8ccecc 100644
+--- a/deployments/se-proxy/opteesp/service_proxy_factory.c
++++ b/deployments/se-proxy/opteesp/service_proxy_factory.c
+@@ -23,12 +23,18 @@ struct openamp_caller openamp;
+ struct rpc_interface *attest_proxy_create(void)
+ {
+ 	struct rpc_interface *attest_iface;
++	struct rpc_caller *attest_caller;
+ 
+ 	/* Static objects for proxy instance */
+ 	static struct attest_provider attest_provider;
+ 
++	attest_caller = openamp_caller_init(&openamp);
++	if (!attest_caller)
++		return NULL;
++
+ 	/* Initialize the service provider */
+ 	attest_iface = attest_provider_init(&attest_provider);
++	psa_iat_client_init(&openamp.rpc_caller);
+ 
+ 	attest_provider_register_serializer(&attest_provider,
+ 		TS_RPC_ENCODING_PACKED_C, packedc_attest_provider_serializer_instance());
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0022-Setup-its-backend-as-openamp-rpc-using-secure-storag.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0022-Setup-its-backend-as-openamp-rpc-using-secure-storag.patch
new file mode 100644
index 0000000..aa389d8
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0022-Setup-its-backend-as-openamp-rpc-using-secure-storag.patch
@@ -0,0 +1,164 @@
+From 90006cecbbba58afee5f51e6bd72f7027a257b5e Mon Sep 17 00:00:00 2001
+From: Satish Kumar <satish.kumar01@arm.com>
+Date: Thu, 9 Dec 2021 14:11:06 +0000
+Subject: [PATCH] Setup its backend as openamp rpc using secure storage ipc
+ implementation.
+
+Signed-off-by: Rui Miguel Silva <rui.silva@arm.com>
+Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
+
+
+---
+ components/service/common/include/psa/sid.h   | 12 +++++-----
+ .../secure_storage_ipc/secure_storage_ipc.c   | 20 ++++++++---------
+ .../secure_storage_ipc/secure_storage_ipc.h   |  1 +
+ .../se-proxy/opteesp/service_proxy_factory.c  | 22 +++++++++++++------
+ 4 files changed, 32 insertions(+), 23 deletions(-)
+
+diff --git a/components/service/common/include/psa/sid.h b/components/service/common/include/psa/sid.h
+index 833f5039..4a951d4a 100644
+--- a/components/service/common/include/psa/sid.h
++++ b/components/service/common/include/psa/sid.h
+@@ -20,12 +20,12 @@ extern "C" {
+ /* Invalid UID */
+ #define TFM_PS_INVALID_UID 0
+ 
+-/* PS message types that distinguish PS services. */
+-#define TFM_PS_SET                1001
+-#define TFM_PS_GET                1002
+-#define TFM_PS_GET_INFO           1003
+-#define TFM_PS_REMOVE             1004
+-#define TFM_PS_GET_SUPPORT        1005
++/* PS / ITS message types that distinguish PS services. */
++#define TFM_PS_ITS_SET                1001
++#define TFM_PS_ITS_GET                1002
++#define TFM_PS_ITS_GET_INFO           1003
++#define TFM_PS_ITS_REMOVE             1004
++#define TFM_PS_ITS_GET_SUPPORT        1005
+ 
+ /******** TFM_SP_ITS ********/
+ #define TFM_INTERNAL_TRUSTED_STORAGE_SERVICE_SID                   (0x00000070U)
+diff --git a/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
+index bda442a6..0e1b48c0 100644
+--- a/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
++++ b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.c
+@@ -31,8 +31,8 @@ static psa_status_t secure_storage_ipc_set(void *context, uint32_t client_id,
+ 
+ 	ipc->client.rpc_status = TS_RPC_CALL_ACCEPTED;
+ 
+-	psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
+-			      TFM_PS_SET, in_vec, IOVEC_LEN(in_vec), NULL, 0);
++	psa_status = psa_call(caller, ipc->service_handle, TFM_PS_ITS_SET,
++			      in_vec, IOVEC_LEN(in_vec), NULL, 0);
+ 	if (psa_status < 0)
+ 		EMSG("ipc_set: psa_call failed: %d", psa_status);
+ 
+@@ -65,8 +65,8 @@ static psa_status_t secure_storage_ipc_get(void *context,
+ 		return PSA_ERROR_INVALID_ARGUMENT;
+ 	}
+ 
+-	psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
+-			      TFM_PS_GET, in_vec, IOVEC_LEN(in_vec),
++	psa_status = psa_call(caller, ipc->service_handle,
++			      TFM_PS_ITS_GET, in_vec, IOVEC_LEN(in_vec),
+ 			      out_vec, IOVEC_LEN(out_vec));
+ 	if (psa_status == PSA_SUCCESS)
+ 		*p_data_length = out_vec[0].len;
+@@ -92,8 +92,8 @@ static psa_status_t secure_storage_ipc_get_info(void *context,
+ 
+ 	(void)client_id;
+ 
+-	psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
+-			      TFM_PS_GET_INFO, in_vec,
++	psa_status = psa_call(caller, ipc->service_handle,
++			      TFM_PS_ITS_GET_INFO, in_vec,
+ 			      IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
+ 	if (psa_status != PSA_SUCCESS)
+ 		EMSG("ipc_get_info: failed to psa_call: %d", psa_status);
+@@ -115,8 +115,8 @@ static psa_status_t secure_storage_ipc_remove(void *context,
+ 
+ 	(void)client_id;
+ 
+-	psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
+-			      TFM_PS_REMOVE, in_vec,
++	psa_status = psa_call(caller, ipc->service_handle,
++			      TFM_PS_ITS_REMOVE, in_vec,
+ 			      IOVEC_LEN(in_vec), NULL, 0);
+ 	if (psa_status != PSA_SUCCESS)
+ 		EMSG("ipc_remove: failed to psa_call: %d", psa_status);
+@@ -169,8 +169,8 @@ static uint32_t secure_storage_get_support(void *context, uint32_t client_id)
+ 
+ 	(void)client_id;
+ 
+-	psa_status = psa_call(caller, TFM_PROTECTED_STORAGE_SERVICE_HANDLE,
+-			      TFM_PS_GET_SUPPORT, NULL, 0,
++	psa_status = psa_call(caller, ipc->service_handle,
++			      TFM_PS_ITS_GET_SUPPORT, NULL, 0,
+ 			      out_vec, IOVEC_LEN(out_vec));
+ 	if (psa_status != PSA_SUCCESS)
+ 		EMSG("ipc_get_support: failed to psa_call: %d", psa_status);
+diff --git a/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.h b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.h
+index e8c1e8fd..d9949f6a 100644
+--- a/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.h
++++ b/components/service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.h
+@@ -21,6 +21,7 @@ struct secure_storage_ipc
+ {
+     struct storage_backend backend;
+     struct service_client client;
++    int32_t service_handle;
+ };
+ 
+ /**
+diff --git a/deployments/se-proxy/opteesp/service_proxy_factory.c b/deployments/se-proxy/opteesp/service_proxy_factory.c
+index 4b8ccecc..1110ac46 100644
+--- a/deployments/se-proxy/opteesp/service_proxy_factory.c
++++ b/deployments/se-proxy/opteesp/service_proxy_factory.c
+@@ -5,6 +5,7 @@
+  */
+ 
+ #include <stddef.h>
++#include <psa/sid.h>
+ #include <rpc/common/endpoint/rpc_interface.h>
+ #include <rpc/openamp/caller/sp/openamp_caller.h>
+ #include <service/attestation/provider/attest_provider.h>
+@@ -60,23 +61,30 @@ struct rpc_interface *ps_proxy_create(void)
+ {
+ 	static struct secure_storage_provider ps_provider;
+ 	static struct secure_storage_ipc ps_backend;
+-	static struct rpc_caller *storage_caller;
++	struct rpc_caller *storage_caller;
+ 	struct storage_backend *backend;
+ 
+ 	storage_caller = openamp_caller_init(&openamp);
+ 	if (!storage_caller)
+ 		return NULL;
+ 	backend = secure_storage_ipc_init(&ps_backend, &openamp.rpc_caller);
++	ps_backend.service_handle = TFM_PROTECTED_STORAGE_SERVICE_HANDLE;
+ 
+ 	return secure_storage_provider_init(&ps_provider, backend);
+ }
+ 
+ struct rpc_interface *its_proxy_create(void)
+ {
+-	static struct mock_store its_backend;
+-	static struct secure_storage_provider its_provider;
+-
+-	struct storage_backend *backend = mock_store_init(&its_backend);
+-
+-	return secure_storage_provider_init(&its_provider, backend);
++        static struct secure_storage_provider its_provider;
++        static struct secure_storage_ipc its_backend;
++        struct rpc_caller *storage_caller;
++        struct storage_backend *backend;
++ 
++        storage_caller = openamp_caller_init(&openamp);
++        if (!storage_caller)
++        	return NULL;
++        backend = secure_storage_ipc_init(&its_backend, &openamp.rpc_caller);
++        its_backend.service_handle = TFM_INTERNAL_TRUSTED_STORAGE_SERVICE_HANDLE;
++ 
++        return secure_storage_provider_init(&its_provider, backend);
+ }
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0023-add-psa-ipc-crypto-backend.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0023-add-psa-ipc-crypto-backend.patch
new file mode 100644
index 0000000..a20a6a4
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0023-add-psa-ipc-crypto-backend.patch
@@ -0,0 +1,2586 @@
+From 5af98a77887c2aa60bc93dbdddb174e03501b733 Mon Sep 17 00:00:00 2001
+From: Rui Miguel Silva <rui.silva@linaro.org>
+Date: Thu, 9 Dec 2021 14:17:39 +0000
+Subject: [PATCH] add psa ipc crypto backend
+
+Add psa ipc crypto backend and attach it to se proxy
+deployment.
+
+Signed-off-by: Rui Miguel Silva <rui.silva@arm.com>
+Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
+
+
+---
+ components/service/common/include/psa/sid.h   |  73 +++++
+ .../crypto/backend/psa_ipc/component.cmake    |  21 ++
+ .../backend/psa_ipc/crypto_ipc_backend.c      |  26 ++
+ .../backend/psa_ipc/crypto_ipc_backend.h      |  70 ++++
+ .../client/caller/psa_ipc/crypto_caller.h     |  34 ++
+ .../caller/psa_ipc/crypto_caller_aead.h       | 252 +++++++++++++++
+ .../crypto_caller_asymmetric_decrypt.h        |  76 +++++
+ .../crypto_caller_asymmetric_encrypt.h        |  76 +++++
+ .../caller/psa_ipc/crypto_caller_cipher.h     | 246 +++++++++++++++
+ .../caller/psa_ipc/crypto_caller_copy_key.h   |  57 ++++
+ .../psa_ipc/crypto_caller_destroy_key.h       |  51 +++
+ .../caller/psa_ipc/crypto_caller_export_key.h |  59 ++++
+ .../psa_ipc/crypto_caller_export_public_key.h |  59 ++++
+ .../psa_ipc/crypto_caller_generate_key.h      |  55 ++++
+ .../psa_ipc/crypto_caller_generate_random.h   |  57 ++++
+ .../crypto_caller_get_key_attributes.h        |  56 ++++
+ .../caller/psa_ipc/crypto_caller_hash.h       | 220 +++++++++++++
+ .../caller/psa_ipc/crypto_caller_import_key.h |  57 ++++
+ .../psa_ipc/crypto_caller_key_attributes.h    |  51 +++
+ .../psa_ipc/crypto_caller_key_derivation.h    | 298 ++++++++++++++++++
+ .../client/caller/psa_ipc/crypto_caller_mac.h | 207 ++++++++++++
+ .../caller/psa_ipc/crypto_caller_purge_key.h  |  51 +++
+ .../caller/psa_ipc/crypto_caller_sign_hash.h  |  64 ++++
+ .../psa_ipc/crypto_caller_verify_hash.h       |  59 ++++
+ .../crypto/include/psa/crypto_client_struct.h |   8 +-
+ .../service/crypto/include/psa/crypto_sizes.h |   2 +-
+ deployments/se-proxy/opteesp/CMakeLists.txt   |   2 +-
+ .../se-proxy/opteesp/service_proxy_factory.c  |  15 +-
+ .../providers/arm/corstone1000/platform.cmake |   2 +
+ 29 files changed, 2293 insertions(+), 11 deletions(-)
+ create mode 100644 components/service/crypto/backend/psa_ipc/component.cmake
+ create mode 100644 components/service/crypto/backend/psa_ipc/crypto_ipc_backend.c
+ create mode 100644 components/service/crypto/backend/psa_ipc/crypto_ipc_backend.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_aead.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_asymmetric_decrypt.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_asymmetric_encrypt.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_cipher.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_copy_key.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_destroy_key.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_export_key.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_export_public_key.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_generate_key.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_generate_random.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_get_key_attributes.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_hash.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_import_key.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_key_attributes.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_key_derivation.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_mac.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_purge_key.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_sign_hash.h
+ create mode 100644 components/service/crypto/client/caller/psa_ipc/crypto_caller_verify_hash.h
+
+diff --git a/components/service/common/include/psa/sid.h b/components/service/common/include/psa/sid.h
+index 4a951d4a..7a29cc25 100644
+--- a/components/service/common/include/psa/sid.h
++++ b/components/service/common/include/psa/sid.h
+@@ -37,6 +37,79 @@ extern "C" {
+ #define TFM_CRYPTO_VERSION                                         (1U)
+ #define TFM_CRYPTO_HANDLE                                          (0x40000100U)
+ 
++/**
++ * \brief Define a progressive numerical value for each SID which can be used
++ *        when dispatching the requests to the service
++ */
++enum {
++    TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID = (0u),
++    TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID,
++    TFM_CRYPTO_OPEN_KEY_SID,
++    TFM_CRYPTO_CLOSE_KEY_SID,
++    TFM_CRYPTO_IMPORT_KEY_SID,
++    TFM_CRYPTO_DESTROY_KEY_SID,
++    TFM_CRYPTO_EXPORT_KEY_SID,
++    TFM_CRYPTO_EXPORT_PUBLIC_KEY_SID,
++    TFM_CRYPTO_PURGE_KEY_SID,
++    TFM_CRYPTO_COPY_KEY_SID,
++    TFM_CRYPTO_HASH_COMPUTE_SID,
++    TFM_CRYPTO_HASH_COMPARE_SID,
++    TFM_CRYPTO_HASH_SETUP_SID,
++    TFM_CRYPTO_HASH_UPDATE_SID,
++    TFM_CRYPTO_HASH_FINISH_SID,
++    TFM_CRYPTO_HASH_VERIFY_SID,
++    TFM_CRYPTO_HASH_ABORT_SID,
++    TFM_CRYPTO_HASH_CLONE_SID,
++    TFM_CRYPTO_MAC_COMPUTE_SID,
++    TFM_CRYPTO_MAC_VERIFY_SID,
++    TFM_CRYPTO_MAC_SIGN_SETUP_SID,
++    TFM_CRYPTO_MAC_VERIFY_SETUP_SID,
++    TFM_CRYPTO_MAC_UPDATE_SID,
++    TFM_CRYPTO_MAC_SIGN_FINISH_SID,
++    TFM_CRYPTO_MAC_VERIFY_FINISH_SID,
++    TFM_CRYPTO_MAC_ABORT_SID,
++    TFM_CRYPTO_CIPHER_ENCRYPT_SID,
++    TFM_CRYPTO_CIPHER_DECRYPT_SID,
++    TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID,
++    TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID,
++    TFM_CRYPTO_CIPHER_GENERATE_IV_SID,
++    TFM_CRYPTO_CIPHER_SET_IV_SID,
++    TFM_CRYPTO_CIPHER_UPDATE_SID,
++    TFM_CRYPTO_CIPHER_FINISH_SID,
++    TFM_CRYPTO_CIPHER_ABORT_SID,
++    TFM_CRYPTO_AEAD_ENCRYPT_SID,
++    TFM_CRYPTO_AEAD_DECRYPT_SID,
++    TFM_CRYPTO_AEAD_ENCRYPT_SETUP_SID,
++    TFM_CRYPTO_AEAD_DECRYPT_SETUP_SID,
++    TFM_CRYPTO_AEAD_GENERATE_NONCE_SID,
++    TFM_CRYPTO_AEAD_SET_NONCE_SID,
++    TFM_CRYPTO_AEAD_SET_LENGTHS_SID,
++    TFM_CRYPTO_AEAD_UPDATE_AD_SID,
++    TFM_CRYPTO_AEAD_UPDATE_SID,
++    TFM_CRYPTO_AEAD_FINISH_SID,
++    TFM_CRYPTO_AEAD_VERIFY_SID,
++    TFM_CRYPTO_AEAD_ABORT_SID,
++    TFM_CRYPTO_SIGN_MESSAGE_SID,
++    TFM_CRYPTO_VERIFY_MESSAGE_SID,
++    TFM_CRYPTO_SIGN_HASH_SID,
++    TFM_CRYPTO_VERIFY_HASH_SID,
++    TFM_CRYPTO_ASYMMETRIC_ENCRYPT_SID,
++    TFM_CRYPTO_ASYMMETRIC_DECRYPT_SID,
++    TFM_CRYPTO_KEY_DERIVATION_SETUP_SID,
++    TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID,
++    TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID,
++    TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID,
++    TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID,
++    TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID,
++    TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID,
++    TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID,
++    TFM_CRYPTO_KEY_DERIVATION_ABORT_SID,
++    TFM_CRYPTO_RAW_KEY_AGREEMENT_SID,
++    TFM_CRYPTO_GENERATE_RANDOM_SID,
++    TFM_CRYPTO_GENERATE_KEY_SID,
++    TFM_CRYPTO_SID_MAX,
++};
++
+ /******** TFM_SP_PLATFORM ********/
+ #define TFM_SP_PLATFORM_SYSTEM_RESET_SID                           (0x00000040U)
+ #define TFM_SP_PLATFORM_SYSTEM_RESET_VERSION                       (1U)
+diff --git a/components/service/crypto/backend/psa_ipc/component.cmake b/components/service/crypto/backend/psa_ipc/component.cmake
+new file mode 100644
+index 00000000..93c297a8
+--- /dev/null
++++ b/components/service/crypto/backend/psa_ipc/component.cmake
+@@ -0,0 +1,21 @@
++#-------------------------------------------------------------------------------
++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++#-------------------------------------------------------------------------------
++if (NOT DEFINED TGT)
++	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
++endif()
++
++target_sources(${TGT} PRIVATE
++	"${CMAKE_CURRENT_LIST_DIR}/crypto_ipc_backend.c"
++	)
++
++# The ipc crypto backend uses the psa crypto client to realize the
++# psa crypto API that the crypto provider depends on.  This define
++# configures the psa crypto client to be built with the ipc crypto
++# caller.
++target_compile_definitions(${TGT} PRIVATE
++	PSA_CRYPTO_CLIENT_CALLER_SELECTION_H="service/crypto/client/caller/psa_ipc/crypto_caller.h"
++)
+diff --git a/components/service/crypto/backend/psa_ipc/crypto_ipc_backend.c b/components/service/crypto/backend/psa_ipc/crypto_ipc_backend.c
+new file mode 100644
+index 00000000..e47cd4ff
+--- /dev/null
++++ b/components/service/crypto/backend/psa_ipc/crypto_ipc_backend.c
+@@ -0,0 +1,26 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#include <stddef.h>
++#include <psa/crypto.h>
++#include <service/crypto/client/psa/psa_crypto_client.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include "crypto_ipc_backend.h"
++
++psa_status_t crypto_ipc_backend_init(struct rpc_caller *caller)
++{
++	psa_status_t status = psa_crypto_client_init(caller);
++
++	if (status == PSA_SUCCESS)
++		status = psa_crypto_init();
++
++	return status;
++}
++
++void crypto_ipc_backend_deinit(void)
++{
++	psa_crypto_client_deinit();
++}
+diff --git a/components/service/crypto/backend/psa_ipc/crypto_ipc_backend.h b/components/service/crypto/backend/psa_ipc/crypto_ipc_backend.h
+new file mode 100644
+index 00000000..c13c20e8
+--- /dev/null
++++ b/components/service/crypto/backend/psa_ipc/crypto_ipc_backend.h
+@@ -0,0 +1,70 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef CRYPTO_IPC_BACKEND_H
++#define CRYPTO_IPC_BACKEND_H
++
++#include <service/crypto/client/psa/psa_crypto_client.h>
++#include <psa/error.h>
++#include <rpc_caller.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * \brief This type is used to overcome a limitation in the number of maximum
++ *        IOVECs that can be used especially in psa_aead_encrypt and
++ *        psa_aead_decrypt. To be removed in case the AEAD APIs number of
++ *        parameters passed gets restructured
++ */
++#define TFM_CRYPTO_MAX_NONCE_LENGTH (16u)
++struct psa_ipc_crypto_aead_pack_input {
++	uint8_t nonce[TFM_CRYPTO_MAX_NONCE_LENGTH];
++	uint32_t nonce_length;
++};
++
++struct psa_ipc_crypto_pack_iovec {
++	uint32_t sfn_id;             /*!< Secure function ID used to dispatch the
++				      *   request
++				      */
++	uint16_t step;               /*!< Key derivation step */
++	psa_key_id_t key_id;         /*!< Key id */
++	psa_algorithm_t alg;         /*!< Algorithm */
++	uint32_t op_handle;          /*!< Frontend context handle associated to a
++				      *   multipart operation
++				      */
++	uint32_t capacity;             /*!< Key derivation capacity */
++
++	struct psa_ipc_crypto_aead_pack_input aead_in; /*!< FixMe: Temporarily used for
++							    *   AEAD until the API is
++							    *   restructured
++							    */
++};
++
++#define iov_size sizeof(struct psa_ipc_crypto_pack_iovec)
++
++/**
++ * \brief Initialize the psa ipc crypto backend
++ *
++ * Initializes a crypto backend that uses the psa API client with a
++ * psa_ipc_backend caller to realize the PSA crypto API used by the crypto
++ * service proviser.
++ *
++ * \return PSA_SUCCESS if backend initialized successfully
++ */
++psa_status_t crypto_ipc_backend_init(struct rpc_caller *caller);
++
++/**
++ * \brief Clean-up to free any resource used by the crypto backend
++ */
++void crypto_ipc_backend_deinit(void);
++
++#ifdef __cplusplus
++} /* extern "C" */
++#endif
++
++#endif /* CRYPTO_IPC_BACKEND_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller.h
+new file mode 100644
+index 00000000..0a972187
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller.h
+@@ -0,0 +1,34 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_H
++#define PSA_IPC_CRYPTO_CALLER_H
++
++/**
++ * Includes all header files that form the psa ipc crypto caller
++ * interface.  May be used by a client that needs to call operations
++ * provided by a crypto service instance using the psa ipc interface.
++ */
++#include "crypto_caller_aead.h"
++#include "crypto_caller_asymmetric_decrypt.h"
++#include "crypto_caller_asymmetric_encrypt.h"
++#include "crypto_caller_cipher.h"
++#include "crypto_caller_copy_key.h"
++#include "crypto_caller_destroy_key.h"
++#include "crypto_caller_export_key.h"
++#include "crypto_caller_export_public_key.h"
++#include "crypto_caller_generate_key.h"
++#include "crypto_caller_generate_random.h"
++#include "crypto_caller_get_key_attributes.h"
++#include "crypto_caller_hash.h"
++#include "crypto_caller_import_key.h"
++#include "crypto_caller_key_derivation.h"
++#include "crypto_caller_mac.h"
++#include "crypto_caller_purge_key.h"
++#include "crypto_caller_sign_hash.h"
++#include "crypto_caller_verify_hash.h"
++
++#endif /* PSA_IPC_CRYPTO_CALLER_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_aead.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_aead.h
+new file mode 100644
+index 00000000..78517fe3
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_aead.h
+@@ -0,0 +1,252 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_AEAD_H
++#define PSA_IPC_CRYPTO_CALLER_AEAD_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_aead_encrypt(
++					      struct service_client *context,
++					      psa_key_id_t key,
++					      psa_algorithm_t alg,
++					      const uint8_t *nonce,
++					      size_t nonce_length,
++					      const uint8_t *additional_data,
++					      size_t additional_data_length,
++					      const uint8_t *plaintext,
++					      size_t plaintext_length,
++					      uint8_t *aeadtext,
++					      size_t aeadtext_size,
++					      size_t *aeadtext_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	size_t in_len;
++	int i;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_AEAD_ENCRYPT_SID,
++		.key_id = key,
++		.alg = alg,
++		.aead_in = { .nonce = {0}, .nonce_length = nonce_length },
++	};
++
++	if (!additional_data && additional_data_length)
++		return PSA_ERROR_INVALID_ARGUMENT;
++
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(plaintext),
++			.len = plaintext_length },
++		{ .base = psa_ptr_const_to_u32(additional_data),
++			.len = additional_data_length},
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(aeadtext), .len = aeadtext_size },
++	};
++
++	if (nonce_length > TFM_CRYPTO_MAX_NONCE_LENGTH)
++		return PSA_ERROR_INVALID_ARGUMENT;
++
++	if (nonce) {
++		for (i = 0; i < nonce_length; i++)
++			iov.aead_in.nonce[i] = nonce[i];
++	}
++
++	in_len = IOVEC_LEN(in_vec);
++
++	if (!additional_data)
++		in_len--;
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  in_len, out_vec, IOVEC_LEN(out_vec));
++
++	*aeadtext_length = out_vec[0].len;
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_aead_decrypt(
++					      struct service_client *context,
++					      psa_key_id_t key,
++					      psa_algorithm_t alg,
++					      const uint8_t *nonce,
++					      size_t nonce_length,
++					      const uint8_t *additional_data,
++					      size_t additional_data_length,
++					      const uint8_t *aeadtext,
++					      size_t aeadtext_length,
++					      uint8_t *plaintext,
++					      size_t plaintext_size,
++					      size_t *plaintext_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	size_t in_len;
++	int i;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_AEAD_DECRYPT_SID,
++		.key_id = key,
++		.alg = alg,
++		.aead_in = { .nonce = {0}, .nonce_length = nonce_length },
++	};
++
++	if (!additional_data && additional_data_length)
++		return PSA_ERROR_INVALID_ARGUMENT;
++
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(aeadtext),
++			.len = aeadtext_length },
++		{ .base = psa_ptr_const_to_u32(additional_data),
++			.len = additional_data_length},
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(plaintext), .len = plaintext_size },
++	};
++
++	if (nonce_length > TFM_CRYPTO_MAX_NONCE_LENGTH)
++		return PSA_ERROR_INVALID_ARGUMENT;
++
++	if (nonce) {
++		for (i = 0; i < nonce_length; i++)
++			iov.aead_in.nonce[i] = nonce[i];
++	}
++
++	in_len = IOVEC_LEN(in_vec);
++
++	if (!additional_data)
++		in_len--;
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  in_len, out_vec, IOVEC_LEN(out_vec));
++
++	*plaintext_length = out_vec[0].len;
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_aead_encrypt_setup(
++					    struct service_client *context,
++					    uint32_t *op_handle,
++					    psa_key_id_t key,
++					    psa_algorithm_t alg)
++{
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
++static inline psa_status_t crypto_caller_aead_decrypt_setup(
++					    struct service_client *context,
++					    uint32_t *op_handle,
++					    psa_key_id_t key,
++					    psa_algorithm_t alg)
++{
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
++static inline psa_status_t crypto_caller_aead_generate_nonce(
++					     struct service_client *context,
++					     uint32_t op_handle,
++					     uint8_t *nonce,
++					     size_t nonce_size,
++					     size_t *nonce_length)
++{
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
++static inline psa_status_t crypto_caller_aead_set_nonce(
++						struct service_client *context,
++						uint32_t op_handle,
++						const uint8_t *nonce,
++						size_t nonce_length)
++{
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
++static inline psa_status_t crypto_caller_aead_set_lengths(
++					  struct service_client *context,
++					  uint32_t op_handle,
++					  size_t ad_length,
++					  size_t plaintext_length)
++{
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
++static inline psa_status_t crypto_caller_aead_update_ad(
++						struct service_client *context,
++						uint32_t op_handle,
++						const uint8_t *input,
++						size_t input_length)
++{
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
++static inline psa_status_t crypto_caller_aead_update(
++					     struct service_client *context,
++					     uint32_t op_handle,
++					     const uint8_t *input,
++					     size_t input_length,
++					     uint8_t *output,
++					     size_t output_size,
++					     size_t *output_length)
++{
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
++static inline psa_status_t crypto_caller_aead_finish(
++					     struct service_client *context,
++					     uint32_t op_handle,
++					     uint8_t *aeadtext,
++					     size_t aeadtext_size,
++					     size_t *aeadtext_length,
++					     uint8_t *tag,
++					     size_t tag_size,
++					     size_t *tag_length)
++{
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
++static inline psa_status_t crypto_caller_aead_verify(
++					     struct service_client *context,
++					     uint32_t op_handle,
++					     uint8_t *plaintext,
++					     size_t plaintext_size,
++					     size_t *plaintext_length,
++					     const uint8_t *tag,
++					     size_t tag_length)
++{
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
++static inline psa_status_t crypto_caller_aead_abort(
++					    struct service_client *context,
++					    uint32_t op_handle)
++{
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_AEAD_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_asymmetric_decrypt.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_asymmetric_decrypt.h
+new file mode 100644
+index 00000000..ff01815c
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_asymmetric_decrypt.h
+@@ -0,0 +1,76 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_ASYMMETRIC_DECRYPT_H
++#define PSA_IPC_CRYPTO_CALLER_ASYMMETRIC_DECRYPT_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_asymmetric_decrypt(
++				    struct service_client *context,
++				    psa_key_id_t id,
++				    psa_algorithm_t alg,
++				    const uint8_t *input, size_t input_length,
++				    const uint8_t *salt, size_t salt_length,
++				    uint8_t *output, size_t output_size,
++				    size_t *output_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	size_t in_len;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_ASYMMETRIC_DECRYPT_SID,
++		.key_id = id,
++		.alg = alg,
++	};
++
++	/* Sanitize optional input */
++	if (!salt && salt_length)
++		return PSA_ERROR_INVALID_ARGUMENT;
++
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(input), .len = input_length },
++		{ .base = psa_ptr_const_to_u32(salt), .len = salt_length },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(output), .len = output_size },
++	};
++
++
++	in_len = IOVEC_LEN(in_vec);
++	if (!salt)
++		in_len--;
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  in_len, out_vec, IOVEC_LEN(out_vec));
++
++	*output_length = out_vec[0].len;
++
++	return status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_ASYMMETRIC_DECRYPT_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_asymmetric_encrypt.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_asymmetric_encrypt.h
+new file mode 100644
+index 00000000..1daf1689
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_asymmetric_encrypt.h
+@@ -0,0 +1,76 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_ASYMMETRIC_ENCRYPT_H
++#define PSA_IPC_CRYPTO_CALLER_ASYMMETRIC_ENCRYPT_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_asymmetric_encrypt(
++				    struct service_client *context,
++				    psa_key_id_t id,
++				    psa_algorithm_t alg,
++				    const uint8_t *input, size_t input_length,
++				    const uint8_t *salt, size_t salt_length,
++				    uint8_t *output, size_t output_size,
++				    size_t *output_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	size_t in_len;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_ASYMMETRIC_ENCRYPT_SID,
++		.key_id = id,
++		.alg = alg,
++	};
++
++	/* Sanitize optional input */
++	if (!salt && salt_length)
++		return PSA_ERROR_INVALID_ARGUMENT;
++
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(input), .len = input_length },
++		{ .base = psa_ptr_const_to_u32(salt), .len = salt_length },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(output), .len = output_size },
++	};
++
++
++	in_len = IOVEC_LEN(in_vec);
++	if (!salt)
++		in_len--;
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  in_len, out_vec, IOVEC_LEN(out_vec));
++
++	*output_length = out_vec[0].len;
++
++	return status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_ASYMMETRIC_ENCRYPT_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_cipher.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_cipher.h
+new file mode 100644
+index 00000000..fbefb28d
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_cipher.h
+@@ -0,0 +1,246 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_CIPHER_H
++#define PSA_IPC_CRYPTO_CALLER_CIPHER_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_cipher_encrypt_setup(
++					      struct service_client *context,
++					      uint32_t *op_handle,
++					      psa_key_id_t key,
++					      psa_algorithm_t alg)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID,
++		.key_id = key,
++		.alg = alg,
++		.op_handle = *op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(op_handle), .len = sizeof(uint32_t) }
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_cipher_decrypt_setup(
++					      struct service_client *context,
++					      uint32_t *op_handle,
++					      psa_key_id_t key,
++					      psa_algorithm_t alg)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID,
++		.key_id = key,
++		.alg = alg,
++		.op_handle = *op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(op_handle), .len = sizeof(uint32_t) }
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_cipher_generate_iv(
++					    struct service_client *context,
++					    uint32_t op_handle,
++					    uint8_t *iv,
++					    size_t iv_size,
++					    size_t *iv_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_CIPHER_GENERATE_IV_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t) },
++		{ .base = psa_ptr_to_u32(iv), .len = iv_size },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	*iv_length = out_vec[1].len;
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_cipher_set_iv(
++					       struct service_client *context,
++					       uint32_t op_handle,
++					       const uint8_t *iv,
++					       size_t iv_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_CIPHER_SET_IV_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(iv), .len = iv_length },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t) },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_cipher_update(
++					       struct service_client *context,
++					       uint32_t op_handle,
++					       const uint8_t *input,
++					       size_t input_length,
++					       uint8_t *output,
++					       size_t output_size,
++					       size_t *output_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_CIPHER_UPDATE_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(input), .len = input_length },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t) },
++		{ .base = psa_ptr_to_u32(output), .len = output_size },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	*output_length = out_vec[1].len;
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_cipher_finish(
++					       struct service_client *context,
++					       uint32_t op_handle,
++					       uint8_t *output,
++					       size_t output_size,
++					       size_t *output_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_CIPHER_FINISH_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t) },
++		{ .base = psa_ptr_to_u32(output), .len = output_size },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	*output_length = out_vec[1].len;
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_cipher_abort(
++					      struct service_client *context,
++					      uint32_t op_handle)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_CIPHER_ABORT_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t) },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline size_t crypto_caller_cipher_max_update_size(const struct service_client *context)
++{
++	/* Returns the maximum number of bytes that may be
++	 * carried as a parameter of the cipher_update operation
++	 * using the ipc encoding.
++	 */
++	size_t payload_space = context->service_info.max_payload;
++	size_t overhead = iov_size;
++
++	/* Allow for output to be a whole number of blocks */
++	overhead += PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE;
++
++	return (payload_space > overhead) ? payload_space - overhead : 0;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_CIPHER_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_copy_key.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_copy_key.h
+new file mode 100644
+index 00000000..9a988171
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_copy_key.h
+@@ -0,0 +1,57 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_COPY_KEY_H
++#define PSA_IPC_CRYPTO_CALLER_COPY_KEY_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_copy_key(struct service_client *context,
++						  psa_key_id_t source_key,
++						  const psa_key_attributes_t *attributes,
++						  psa_key_id_t *target_key)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_COPY_KEY_SID,
++		.key_id = source_key,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec) },
++		{ .base = psa_ptr_const_to_u32(attributes), .len = sizeof(psa_key_attributes_t) },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(target_key), .len = sizeof(psa_key_id_t) }
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_COPY_KEY_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_destroy_key.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_destroy_key.h
+new file mode 100644
+index 00000000..d00f4faa
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_destroy_key.h
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_DESTROY_KEY_H
++#define PSA_IPC_CRYPTO_CALLER_DESTROY_KEY_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_destroy_key(struct service_client *context,
++						     psa_key_id_t id)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_DESTROY_KEY_SID,
++		.key_id = id,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec) },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), NULL, 0);
++
++	return status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_DESTROY_KEY_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_export_key.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_export_key.h
+new file mode 100644
+index 00000000..8ac5477f
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_export_key.h
+@@ -0,0 +1,59 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_EXPORT_KEY_H
++#define PSA_IPC_CRYPTO_CALLER_EXPORT_KEY_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_export_key(struct service_client *context,
++						    psa_key_id_t id,
++						    uint8_t *data,
++						    size_t data_size,
++						    size_t *data_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_EXPORT_KEY_SID,
++		.key_id = id,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec) },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(data), .len = data_size }
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	*data_length = out_vec[0].len;
++
++	return status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_EXPORT_KEY_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_export_public_key.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_export_public_key.h
+new file mode 100644
+index 00000000..b24c47f1
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_export_public_key.h
+@@ -0,0 +1,59 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_EXPORT_PUBLIC_KEY_H
++#define PSA_IPC_CRYPTO_CALLER_EXPORT_PUBLIC_KEY_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_export_public_key(struct service_client *context,
++							   psa_key_id_t id,
++							   uint8_t *data,
++							   size_t data_size,
++							   size_t *data_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_EXPORT_PUBLIC_KEY_SID,
++		.key_id = id,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec) },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(data), .len = data_size }
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	*data_length = out_vec[0].len;
++
++	return status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_EXPORT_PUBLIC_KEY_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_generate_key.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_generate_key.h
+new file mode 100644
+index 00000000..1b66ed40
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_generate_key.h
+@@ -0,0 +1,55 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_GENERATE_KEY_H
++#define PSA_IPC_CRYPTO_CALLER_GENERATE_KEY_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_generate_key(struct service_client *context,
++						      const psa_key_attributes_t *attributes,
++						      psa_key_id_t *id)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_GENERATE_KEY_SID,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec) },
++		{ .base = psa_ptr_const_to_u32(attributes), .len = sizeof(psa_key_attributes_t) },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(id), .len = sizeof(psa_key_id_t) }
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_GENERATE_KEY_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_generate_random.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_generate_random.h
+new file mode 100644
+index 00000000..7c538237
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_generate_random.h
+@@ -0,0 +1,57 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_GENERATE_RANDOM_H
++#define PSA_IPC_CRYPTO_CALLER_GENERATE_RANDOM_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_generate_random(struct service_client *context,
++							 uint8_t *output,
++							 size_t output_size)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_GENERATE_RANDOM_SID,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec) },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(output), .len = output_size }
++	};
++
++	if (!output_size)
++		return PSA_SUCCESS;
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_GENERATE_RANDOM_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_get_key_attributes.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_get_key_attributes.h
+new file mode 100644
+index 00000000..22f1d18f
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_get_key_attributes.h
+@@ -0,0 +1,56 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_GET_KEY_ATTRIBUTES_H
++#define PSA_IPC_CRYPTO_CALLER_GET_KEY_ATTRIBUTES_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_get_key_attributes(
++					    struct service_client *context,
++					    psa_key_id_t key,
++					    psa_key_attributes_t *attributes)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID,
++		.key_id = key,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec) },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(attributes), .len = sizeof(psa_key_attributes_t) }
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_GET_KEY_ATTRIBUTES_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_hash.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_hash.h
+new file mode 100644
+index 00000000..9f37908a
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_hash.h
+@@ -0,0 +1,220 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_HASH_H
++#define PSA_IPC_CRYPTO_CALLER_HASH_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_hash_setup(
++					    struct service_client *context,
++					    uint32_t *op_handle,
++					    psa_algorithm_t alg)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_HASH_SETUP_SID,
++		.alg = alg,
++		.op_handle = *op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(op_handle), .len = sizeof(uint32_t) }
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_hash_update(
++					     struct service_client *context,
++					     uint32_t op_handle,
++					     const uint8_t *input,
++					     size_t input_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_HASH_UPDATE_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(input), .len = input_length },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t) },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_hash_finish(
++					     struct service_client *context,
++					     uint32_t op_handle,
++					     uint8_t *hash,
++					     size_t hash_size,
++					     size_t *hash_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_HASH_FINISH_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t) },
++		{ .base = psa_ptr_to_u32(hash), .len = hash_size},
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	*hash_length = out_vec[1].len;
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_hash_abort(
++					    struct service_client *context,
++					    uint32_t op_handle)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_HASH_ABORT_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t) },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_hash_verify(
++					     struct service_client *context,
++					     uint32_t op_handle,
++					     const uint8_t *hash,
++					     size_t hash_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_HASH_VERIFY_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(hash), .len = hash_length},
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t) },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_hash_clone(
++					    struct service_client *context,
++					    uint32_t source_op_handle,
++					    uint32_t *target_op_handle)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_HASH_CLONE_SID,
++		.op_handle = source_op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(target_op_handle),
++			.len = sizeof(uint32_t) },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_hash_suspend(struct service_client *context,
++	uint32_t op_handle,
++	uint8_t *hash_state,
++	size_t hash_state_size,
++	size_t *hash_state_length)
++{
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
++static inline psa_status_t crypto_caller_hash_resume(struct service_client *context,
++	uint32_t op_handle,
++	const uint8_t *hash_state,
++	size_t hash_state_length)
++{
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
++static inline size_t crypto_caller_hash_max_update_size(const struct service_client *context)
++{
++	/* Returns the maximum number of bytes that may be
++	 * carried as a parameter of the hash_update operation
++	 * using the packed-c encoding.
++	 */
++	size_t payload_space = context->service_info.max_payload;
++	size_t overhead = iov_size;
++
++	return (payload_space > overhead) ? payload_space - overhead : 0;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_HASH_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_import_key.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_import_key.h
+new file mode 100644
+index 00000000..d4703366
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_import_key.h
+@@ -0,0 +1,57 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_IMPORT_KEY_H
++#define PSA_IPC_CRYPTO_CALLER_IMPORT_KEY_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_import_key(struct service_client *context,
++				    const psa_key_attributes_t *attributes,
++				    const uint8_t *data, size_t data_length,
++				    psa_key_id_t *id)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_IMPORT_KEY_SID,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec) },
++		{ .base = psa_ptr_const_to_u32(attributes), .len = sizeof(psa_key_attributes_t) },
++		{ .base = psa_ptr_const_to_u32(data), .len = data_length }
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(id), .len = sizeof(psa_key_id_t) }
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PACKEDC_CRYPTO_CALLER_IMPORT_KEY_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_key_attributes.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_key_attributes.h
+new file mode 100644
+index 00000000..2fad2f0a
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_key_attributes.h
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PACKEDC_CRYPTO_CALLER_KEY_ATTRIBUTES_H
++#define PACKEDC_CRYPTO_CALLER_KEY_ATTRIBUTES_H
++
++#include <psa/crypto.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline void packedc_crypto_caller_translate_key_attributes_to_proto(
++	struct ts_crypto_key_attributes *proto_attributes,
++	const psa_key_attributes_t *psa_attributes)
++{
++	proto_attributes->type = psa_get_key_type(psa_attributes);
++	proto_attributes->key_bits = psa_get_key_bits(psa_attributes);
++	proto_attributes->lifetime = psa_get_key_lifetime(psa_attributes);
++	proto_attributes->id = psa_get_key_id(psa_attributes);
++
++	proto_attributes->policy.usage = psa_get_key_usage_flags(psa_attributes);
++	proto_attributes->policy.alg = psa_get_key_algorithm(psa_attributes);
++ }
++
++static inline void packedc_crypto_caller_translate_key_attributes_from_proto(
++	psa_key_attributes_t *psa_attributes,
++	const struct ts_crypto_key_attributes *proto_attributes)
++{
++	psa_set_key_type(psa_attributes, proto_attributes->type);
++	psa_set_key_bits(psa_attributes, proto_attributes->key_bits);
++	psa_set_key_lifetime(psa_attributes, proto_attributes->lifetime);
++
++	if (proto_attributes->lifetime == PSA_KEY_LIFETIME_PERSISTENT) {
++
++		psa_set_key_id(psa_attributes, proto_attributes->id);
++	}
++
++	psa_set_key_usage_flags(psa_attributes, proto_attributes->policy.usage);
++	psa_set_key_algorithm(psa_attributes, proto_attributes->policy.alg);
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PACKEDC_CRYPTO_CALLER_KEY_ATTRIBUTES_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_key_derivation.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_key_derivation.h
+new file mode 100644
+index 00000000..5ce4fb6c
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_key_derivation.h
+@@ -0,0 +1,298 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_KEY_DERIVATION_H
++#define PSA_IPC_CRYPTO_CALLER_KEY_DERIVATION_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_key_derivation_setup(
++					      struct service_client *context,
++					      uint32_t *op_handle,
++					      psa_algorithm_t alg)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_KEY_DERIVATION_SETUP_SID,
++		.alg = alg,
++		.op_handle = *op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(op_handle), .len = sizeof(uint32_t) }
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_key_derivation_get_capacity(
++					     struct service_client *context,
++					     const uint32_t op_handle,
++					     size_t *capacity)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(capacity), .len = sizeof(uint32_t) }
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_key_derivation_set_capacity(
++					     struct service_client *context,
++					     uint32_t op_handle,
++					     size_t capacity)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID,
++		.capacity = capacity,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), NULL, 0);
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_key_derivation_input_bytes(
++					    struct service_client *context,
++					    uint32_t op_handle,
++					    psa_key_derivation_step_t step,
++					    const uint8_t *data,
++					    size_t data_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID,
++		.step = step,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(data), .len = data_length },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), NULL, 0);
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_key_derivation_input_key(
++					  struct service_client *context,
++					  uint32_t op_handle,
++					  psa_key_derivation_step_t step,
++					  psa_key_id_t key)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID,
++		.key_id = key,
++		.step = step,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), NULL, 0);
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_key_derivation_output_bytes(
++					     struct service_client *context,
++					     uint32_t op_handle,
++					     uint8_t *output,
++					     size_t output_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(output), .len = output_length },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_key_derivation_output_key(
++				   struct service_client *context,
++				   const psa_key_attributes_t *attributes,
++				   uint32_t op_handle,
++				   psa_key_id_t *key)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(attributes),
++			.len = sizeof(psa_key_attributes_t) },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(key), .len = sizeof(psa_key_id_t)},
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_key_derivation_abort(
++					      struct service_client *context,
++					      uint32_t op_handle)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_KEY_DERIVATION_ABORT_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t) },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_key_derivation_key_agreement(
++				      struct service_client *context,
++				      uint32_t op_handle,
++				      psa_key_derivation_step_t step,
++				      psa_key_id_t private_key,
++				      const uint8_t *peer_key,
++				      size_t peer_key_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID,
++		.key_id = private_key,
++		.step = step,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(peer_key),
++			.len = peer_key_length},
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), NULL, 0);
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_raw_key_agreement(
++					   struct service_client *context,
++					   psa_algorithm_t alg,
++					   psa_key_id_t private_key,
++					   const uint8_t *peer_key,
++					   size_t peer_key_length,
++					   uint8_t *output,
++					   size_t output_size,
++					   size_t *output_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_RAW_KEY_AGREEMENT_SID,
++		.alg = alg,
++		.key_id = private_key,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(peer_key),
++			.len = peer_key_length},
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(output), .len = output_size },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	*output_length = out_vec[0].len;
++
++	return status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_KEY_DERIVATION_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_mac.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_mac.h
+new file mode 100644
+index 00000000..3a820192
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_mac.h
+@@ -0,0 +1,207 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_MAC_H
++#define PSA_IPC_CRYPTO_CALLER_MAC_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_mac_sign_setup(
++						struct service_client *context,
++						uint32_t *op_handle,
++						psa_key_id_t key,
++						psa_algorithm_t alg)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_MAC_SIGN_SETUP_SID,
++		.key_id = key,
++		.alg = alg,
++		.op_handle = *op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(op_handle), .len = sizeof(uint32_t) },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_mac_verify_setup(
++					  struct service_client *context,
++					  uint32_t *op_handle,
++					  psa_key_id_t key,
++					  psa_algorithm_t alg)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_MAC_VERIFY_SETUP_SID,
++		.key_id = key,
++		.alg = alg,
++		.op_handle = *op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(op_handle), .len = sizeof(uint32_t) },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_mac_update(
++					    struct service_client *context,
++					    uint32_t op_handle,
++					    const uint8_t *input,
++					    size_t input_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_MAC_UPDATE_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(input), .len = input_length },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t) },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_mac_sign_finish(
++						 struct service_client *context,
++						 uint32_t op_handle,
++						 uint8_t *mac,
++						 size_t mac_size,
++						 size_t *mac_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_MAC_SIGN_FINISH_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t) },
++		{ .base = psa_ptr_to_u32(mac), .len = mac_size },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	*mac_length = out_vec[1].len;
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_mac_verify_finish(
++					   struct service_client *context,
++					   uint32_t op_handle,
++					   const uint8_t *mac,
++					   size_t mac_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_MAC_VERIFY_FINISH_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(mac), .len = mac_length },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t) },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline psa_status_t crypto_caller_mac_abort(
++					   struct service_client *context,
++					   uint32_t op_handle)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_MAC_ABORT_SID,
++		.op_handle = op_handle,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t) },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
++}
++
++static inline size_t crypto_caller_mac_max_update_size(const struct service_client *context)
++{
++	/* Returns the maximum number of bytes that may be
++	 * carried as a parameter of the mac_update operation
++	 * using the packed-c encoding.
++	 */
++	size_t payload_space = context->service_info.max_payload;
++	size_t overhead = iov_size;
++
++	return (payload_space > overhead) ? payload_space - overhead : 0;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_MAC_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_purge_key.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_purge_key.h
+new file mode 100644
+index 00000000..a3a796e2
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_purge_key.h
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PACKEDC_CRYPTO_CALLER_PURGE_KEY_H
++#define PACKEDC_CRYPTO_CALLER_PURGE_KEY_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_purge_key(struct service_client *context,
++						   psa_key_id_t id)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_PURGE_KEY_SID,
++		.key_id = id,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec) },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), NULL, 0);
++
++	return status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PACKEDC_CRYPTO_CALLER_PURGE_KEY_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_sign_hash.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_sign_hash.h
+new file mode 100644
+index 00000000..71d88ced
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_sign_hash.h
+@@ -0,0 +1,64 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_SIGN_HASH_H
++#define PSA_IPC_CRYPTO_CALLER_SIGN_HASH_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_sign_hash(struct service_client *context,
++						   psa_key_id_t id,
++						   psa_algorithm_t alg,
++						   const uint8_t *hash,
++						   size_t hash_length,
++						   uint8_t *signature,
++						   size_t signature_size,
++						   size_t *signature_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_SIGN_HASH_SID,
++		.key_id = id,
++		.alg = alg,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(hash), .len = hash_length },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(signature), .len = signature_size },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	*signature_length = out_vec[0].len;
++
++	return status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_SIGN_HASH_H */
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_verify_hash.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_verify_hash.h
+new file mode 100644
+index 00000000..e16f6e54
+--- /dev/null
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_verify_hash.h
+@@ -0,0 +1,59 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef PSA_IPC_CRYPTO_CALLER_VERIFY_HASH_H
++#define PSA_IPC_CRYPTO_CALLER_VERIFY_HASH_H
++
++#include <string.h>
++#include <stdlib.h>
++#include <psa/crypto.h>
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <service/common/client/service_client.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include <protocols/service/crypto/packed-c/opcodes.h>
++#include <protocols/service/crypto/packed-c/key_attributes.h>
++#include <protocols/service/crypto/packed-c/import_key.h>
++#include "crypto_caller_key_attributes.h"
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++static inline psa_status_t crypto_caller_verify_hash(struct service_client *context,
++						     psa_key_id_t id,
++						     psa_algorithm_t alg,
++						     const uint8_t *hash,
++						     size_t hash_length,
++						     const uint8_t *signature,
++						     size_t signature_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_VERIFY_HASH_SID,
++		.key_id = id,
++		.alg = alg,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec) },
++		{ .base = psa_ptr_const_to_u32(hash), .len = hash_length },
++		{ .base = psa_ptr_const_to_u32(signature), .len = signature_length},
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), NULL, 0);
++
++	return status;
++}
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* PSA_IPC_CRYPTO_CALLER_VERIFY_HASH_H */
+diff --git a/components/service/crypto/include/psa/crypto_client_struct.h b/components/service/crypto/include/psa/crypto_client_struct.h
+index abd420c8..bf95c982 100644
+--- a/components/service/crypto/include/psa/crypto_client_struct.h
++++ b/components/service/crypto/include/psa/crypto_client_struct.h
+@@ -31,12 +31,12 @@ extern "C" {
+  * data structure internally. */
+ struct psa_client_key_attributes_s
+ {
++    uint16_t type;
++    uint16_t bits;
+     uint32_t lifetime;
+-    uint32_t id;
+-    uint32_t alg;
++    psa_key_id_t id;
+     uint32_t usage;
+-    size_t bits;
+-    uint16_t type;
++    uint32_t alg;
+ };
+ 
+ #define PSA_CLIENT_KEY_ATTRIBUTES_INIT {0, 0, 0, 0, 0, 0}
+diff --git a/components/service/crypto/include/psa/crypto_sizes.h b/components/service/crypto/include/psa/crypto_sizes.h
+index 7a0149bb..4d7bf6e9 100644
+--- a/components/service/crypto/include/psa/crypto_sizes.h
++++ b/components/service/crypto/include/psa/crypto_sizes.h
+@@ -81,7 +81,7 @@
+ #define PSA_HASH_MAX_SIZE 64
+ #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128
+ #else
+-#define PSA_HASH_MAX_SIZE 32
++#define PSA_HASH_MAX_SIZE 64
+ #define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64
+ #endif
+ 
+diff --git a/deployments/se-proxy/opteesp/CMakeLists.txt b/deployments/se-proxy/opteesp/CMakeLists.txt
+index af2225e7..21904283 100644
+--- a/deployments/se-proxy/opteesp/CMakeLists.txt
++++ b/deployments/se-proxy/opteesp/CMakeLists.txt
+@@ -85,7 +85,7 @@ add_components(TARGET "se-proxy"
+ 		"components/rpc/dummy"
+ 		"components/rpc/common/caller"
+ 		"components/service/attestation/key_mngr/stub"
+-		"components/service/crypto/backend/stub"
++		"components/service/crypto/backend/psa_ipc"
+ 		"components/service/crypto/client/psa"
+ 		"components/service/secure_storage/backend/mock_store"
+ )
+diff --git a/deployments/se-proxy/opteesp/service_proxy_factory.c b/deployments/se-proxy/opteesp/service_proxy_factory.c
+index 1110ac46..7edeef8b 100644
+--- a/deployments/se-proxy/opteesp/service_proxy_factory.c
++++ b/deployments/se-proxy/opteesp/service_proxy_factory.c
+@@ -15,7 +15,7 @@
+ #include <trace.h>
+ 
+ /* Stub backends */
+-#include <service/crypto/backend/stub/stub_crypto_backend.h>
++#include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
+ #include <service/secure_storage/backend/secure_storage_ipc/secure_storage_ipc.h>
+ #include <service/secure_storage/backend/mock_store/mock_store.h>
+ 
+@@ -47,12 +47,17 @@ struct rpc_interface *crypto_proxy_create(void)
+ {
+ 	struct rpc_interface *crypto_iface = NULL;
+ 	struct crypto_provider *crypto_provider;
++	struct rpc_caller *crypto_caller;
+ 
+-	if (stub_crypto_backend_init() == PSA_SUCCESS) {
++	crypto_caller = openamp_caller_init(&openamp);
++	if (!crypto_caller)
++		return NULL;
++
++	if (crypto_ipc_backend_init(&openamp.rpc_caller) != PSA_SUCCESS)
++		return NULL;
+ 
+-		crypto_provider = crypto_provider_factory_create();
+-		crypto_iface = service_provider_get_rpc_interface(&crypto_provider->base_provider);
+-	}
++	crypto_provider = crypto_provider_factory_create();
++	crypto_iface = service_provider_get_rpc_interface(&crypto_provider->base_provider);
+ 
+ 	return crypto_iface;
+ }
+diff --git a/platform/providers/arm/corstone1000/platform.cmake b/platform/providers/arm/corstone1000/platform.cmake
+index bb778bb9..51e5faa3 100644
+--- a/platform/providers/arm/corstone1000/platform.cmake
++++ b/platform/providers/arm/corstone1000/platform.cmake
+@@ -8,3 +8,5 @@
+ 
+ # include MHU driver
+ include(${TS_ROOT}/platform/drivers/arm/mhu_driver/component.cmake)
++
++add_compile_definitions(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0024-Increase-SMM-gateway-UEFI-variable-macro-value.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0024-Increase-SMM-gateway-UEFI-variable-macro-value.patch
new file mode 100644
index 0000000..91207bd
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0024-Increase-SMM-gateway-UEFI-variable-macro-value.patch
@@ -0,0 +1,34 @@
+From 8fca2a8eed6ebc1cbf9f7972c6a9bb137ebafe1a Mon Sep 17 00:00:00 2001
+From: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+Date: Sun, 12 Dec 2021 17:07:03 +0000
+Subject: [PATCH] Increase SMM gateway UEFI variable macro value
+
+The maximum number of UEFI variables that be supported by SMM
+gateway is currently 40. When more than 40 variables are written,
+or read SMM gateway returns error code. Currently this value is
+increased to 100 to support more UEFI variables.
+
+Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+
+
+---
+ deployments/smm-gateway/smm_gateway.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/deployments/smm-gateway/smm_gateway.c b/deployments/smm-gateway/smm_gateway.c
+index 7828b3af..7e6729ee 100644
+--- a/deployments/smm-gateway/smm_gateway.c
++++ b/deployments/smm-gateway/smm_gateway.c
+@@ -20,6 +20,9 @@
+ #define SMM_GATEWAY_NV_STORE_SN		"sn:ffa:751bf801-3dde-4768-a514-0f10aeed1790:0"
+ #endif
+ 
++/* Maximum number of UEFI variables set to 100 */
++#define SMM_GATEWAY_MAX_UEFI_VARIABLES		(100)
++
+ /* Default maximum number of UEFI variables */
+ #ifndef SMM_GATEWAY_MAX_UEFI_VARIABLES
+ #define SMM_GATEWAY_MAX_UEFI_VARIABLES		(40)
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0025-Add-stub-capsule-update-service-components.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0025-Add-stub-capsule-update-service-components.patch
new file mode 100644
index 0000000..943568c
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0025-Add-stub-capsule-update-service-components.patch
@@ -0,0 +1,436 @@
+From eb1beb0f4f3a0d97a1ee941b068fb1f3b7ba7d7b Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Tue, 12 Oct 2021 15:45:41 +0100
+Subject: [PATCH] Add stub capsule update service components
+
+To facilitate development of a capsule update service provider,
+stub components are added to provide a starting point for an
+implementation. The capsule update service provider is integrated
+into the se-proxy/opteesp deployment.
+
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: I0d4049bb4de5af7ca80806403301692507085d28
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+
+---
+ .../backend/capsule_update_backend.h          |  24 ++++
+ .../provider/capsule_update_provider.c        | 133 ++++++++++++++++++
+ .../provider/capsule_update_provider.h        |  51 +++++++
+ .../capsule_update/provider/component.cmake   |  13 ++
+ deployments/se-proxy/opteesp/CMakeLists.txt   |   1 +
+ deployments/se-proxy/opteesp/se_proxy_sp.c    |   3 +
+ .../se-proxy/opteesp/service_proxy_factory.c  |  16 +++
+ .../se-proxy/opteesp/service_proxy_factory.h  |   1 +
+ deployments/se-proxy/se_proxy_interfaces.h    |   9 +-
+ .../capsule_update/capsule_update_proto.h     |  13 ++
+ protocols/service/capsule_update/opcodes.h    |  17 +++
+ protocols/service/capsule_update/parameters.h |  15 ++
+ 12 files changed, 292 insertions(+), 4 deletions(-)
+ create mode 100644 components/service/capsule_update/backend/capsule_update_backend.h
+ create mode 100644 components/service/capsule_update/provider/capsule_update_provider.c
+ create mode 100644 components/service/capsule_update/provider/capsule_update_provider.h
+ create mode 100644 components/service/capsule_update/provider/component.cmake
+ create mode 100644 protocols/service/capsule_update/capsule_update_proto.h
+ create mode 100644 protocols/service/capsule_update/opcodes.h
+ create mode 100644 protocols/service/capsule_update/parameters.h
+
+diff --git a/components/service/capsule_update/backend/capsule_update_backend.h b/components/service/capsule_update/backend/capsule_update_backend.h
+new file mode 100644
+index 00000000..f3144ff1
+--- /dev/null
++++ b/components/service/capsule_update/backend/capsule_update_backend.h
+@@ -0,0 +1,24 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef CAPSULE_UPDATE_BACKEND_H
++#define CAPSULE_UPDATE_BACKEND_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * Defines the common capsule update backend interface.  Concrete backends
++ * implement this interface for different types of platform.
++ */
++
++
++#ifdef __cplusplus
++} /* extern "C" */
++#endif
++
++#endif /* CAPSULE_UPDATE_BACKEND_H */
+diff --git a/components/service/capsule_update/provider/capsule_update_provider.c b/components/service/capsule_update/provider/capsule_update_provider.c
+new file mode 100644
+index 00000000..9bbd7abc
+--- /dev/null
++++ b/components/service/capsule_update/provider/capsule_update_provider.c
+@@ -0,0 +1,133 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#include <psa/client.h>
++#include <psa/sid.h>
++#include <trace.h>
++
++#include <protocols/service/capsule_update/capsule_update_proto.h>
++#include <protocols/rpc/common/packed-c/status.h>
++#include "capsule_update_provider.h"
++
++
++#define CAPSULE_UPDATE_REQUEST (0x1)
++#define KERNEL_STARTED_EVENT   (0x2)
++
++enum corstone1000_ioctl_id_t {
++	IOCTL_CORSTONE1000_FWU_FLASH_IMAGES = 0,
++	IOCTL_CORSTONE1000_FWU_HOST_ACK,
++};
++
++/* Service request handlers */
++static rpc_status_t update_capsule_handler(void *context, struct call_req *req);
++static rpc_status_t boot_confirmed_handler(void *context, struct call_req *req);
++
++/* Handler mapping table for service */
++static const struct service_handler handler_table[] = {
++	{CAPSULE_UPDATE_OPCODE_UPDATE_CAPSULE,			update_capsule_handler},
++	{CAPSULE_UPDATE_OPCODE_BOOT_CONFIRMED,			boot_confirmed_handler}
++};
++
++struct rpc_interface *capsule_update_provider_init(
++	struct capsule_update_provider *context)
++{
++	struct rpc_interface *rpc_interface = NULL;
++
++	if (context) {
++
++		service_provider_init(
++			&context->base_provider,
++			context,
++			handler_table,
++			sizeof(handler_table)/sizeof(struct service_handler));
++
++		rpc_interface = service_provider_get_rpc_interface(&context->base_provider);
++	}
++
++	return rpc_interface;
++}
++
++void capsule_update_provider_deinit(struct capsule_update_provider *context)
++{
++	(void)context;
++}
++
++static rpc_status_t event_handler(uint32_t opcode, struct rpc_caller *caller)
++{
++	uint32_t ioctl_id;
++	psa_handle_t handle;
++	rpc_status_t rpc_status = TS_RPC_CALL_ACCEPTED;
++
++	struct psa_invec in_vec[] = {
++			{ .base = &ioctl_id, .len = sizeof(ioctl_id) }
++	};
++
++	if(!caller) {
++		EMSG("event_handler rpc_caller is NULL");
++		rpc_status = TS_RPC_ERROR_RESOURCE_FAILURE;
++		return rpc_status;
++	}
++
++	MSG("event handler opcode %x", opcode);
++	switch(opcode) {
++		case CAPSULE_UPDATE_REQUEST:
++		/* Openamp call with IOCTL for firmware update*/
++		ioctl_id = IOCTL_CORSTONE1000_FWU_FLASH_IMAGES;
++		handle = psa_connect(caller, TFM_SP_PLATFORM_IOCTL_SID,
++				TFM_SP_PLATFORM_IOCTL_VERSION);
++		if (handle <= 0) {
++			EMSG("%s Invalid handle", __func__);
++			rpc_status = TS_RPC_ERROR_INVALID_PARAMETER;
++			return rpc_status;
++		}
++		psa_call(caller,handle, PSA_IPC_CALL,
++			in_vec,IOVEC_LEN(in_vec), NULL, 0);
++		break;
++
++		case KERNEL_STARTED_EVENT:
++		ioctl_id = IOCTL_CORSTONE1000_FWU_HOST_ACK;
++		/*openamp call with IOCTL for kernel start*/
++		handle = psa_connect(caller, TFM_SP_PLATFORM_IOCTL_SID,
++				TFM_SP_PLATFORM_IOCTL_VERSION);
++		if (handle <= 0) {
++			EMSG("%s Invalid handle", __func__);
++			rpc_status = TS_RPC_ERROR_INVALID_PARAMETER;
++			return rpc_status;
++		}
++		psa_call(caller,handle, PSA_IPC_CALL,
++			in_vec,IOVEC_LEN(in_vec), NULL, 0);
++		break;
++		default:
++			EMSG("%s unsupported opcode", __func__);
++			rpc_status = TS_RPC_ERROR_INVALID_PARAMETER;
++			return rpc_status;
++	}
++	return rpc_status;
++
++}
++
++static rpc_status_t update_capsule_handler(void *context, struct call_req *req)
++{
++	struct capsule_update_provider *this_instance = (struct capsule_update_provider*)context;
++	struct rpc_caller *caller = this_instance->client.caller;
++	uint32_t opcode = req->opcode;
++	rpc_status_t rpc_status = TS_RPC_ERROR_NOT_READY;
++
++	rpc_status = event_handler(opcode, caller);
++	return rpc_status;
++}
++
++static rpc_status_t boot_confirmed_handler(void *context, struct call_req *req)
++{
++	struct capsule_update_provider *this_instance = (struct capsule_update_provider*)context;
++	struct rpc_caller *caller = this_instance->client.caller;
++	uint32_t opcode = req->opcode;
++	rpc_status_t rpc_status = TS_RPC_ERROR_NOT_READY;
++
++	rpc_status = event_handler(opcode, caller);
++
++	return rpc_status;
++}
+diff --git a/components/service/capsule_update/provider/capsule_update_provider.h b/components/service/capsule_update/provider/capsule_update_provider.h
+new file mode 100644
+index 00000000..3de49854
+--- /dev/null
++++ b/components/service/capsule_update/provider/capsule_update_provider.h
+@@ -0,0 +1,51 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef CAPSULE_UPDATE_PROVIDER_H
++#define CAPSULE_UPDATE_PROVIDER_H
++
++#include <rpc/common/endpoint/rpc_interface.h>
++#include <service/common/provider/service_provider.h>
++#include <service/common/client/service_client.h>
++#include <service/capsule_update/backend/capsule_update_backend.h>
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/**
++ * The capsule_update_provider is a service provider that accepts update capsule
++ * requests and delegates them to a suitable backend that applies the update.
++ */
++struct capsule_update_provider
++{
++	struct service_provider base_provider;
++	struct service_client client;
++};
++
++/**
++ * \brief Initialize an instance of the capsule update service provider
++ *
++ * @param[in] context The instance to initialize
++ *
++ * \return An rpc_interface or NULL on failure
++ */
++struct rpc_interface *capsule_update_provider_init(
++	struct capsule_update_provider *context);
++
++/**
++ * \brief Cleans up when the instance is no longer needed
++ *
++ * \param[in] context   The instance to de-initialize
++ */
++void capsule_update_provider_deinit(
++	struct capsule_update_provider *context);
++
++#ifdef __cplusplus
++} /* extern "C" */
++#endif
++
++#endif /* CAPSULE_UPDATE_PROVIDER_H */
+diff --git a/components/service/capsule_update/provider/component.cmake b/components/service/capsule_update/provider/component.cmake
+new file mode 100644
+index 00000000..1d412eb2
+--- /dev/null
++++ b/components/service/capsule_update/provider/component.cmake
+@@ -0,0 +1,13 @@
++#-------------------------------------------------------------------------------
++# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++#
++# SPDX-License-Identifier: BSD-3-Clause
++#
++#-------------------------------------------------------------------------------
++if (NOT DEFINED TGT)
++	message(FATAL_ERROR "mandatory parameter TGT is not defined.")
++endif()
++
++target_sources(${TGT} PRIVATE
++	"${CMAKE_CURRENT_LIST_DIR}/capsule_update_provider.c"
++	)
+diff --git a/deployments/se-proxy/opteesp/CMakeLists.txt b/deployments/se-proxy/opteesp/CMakeLists.txt
+index 21904283..953bb716 100644
+--- a/deployments/se-proxy/opteesp/CMakeLists.txt
++++ b/deployments/se-proxy/opteesp/CMakeLists.txt
+@@ -80,6 +80,7 @@ add_components(TARGET "se-proxy"
+ 		"components/service/attestation/reporter/psa_ipc"
+ 		"components/service/attestation/client/psa_ipc"
+ 		"components/rpc/openamp/caller/sp"
++		"components/service/capsule_update/provider"
+ 
+ 		# Stub service provider backends
+ 		"components/rpc/dummy"
+diff --git a/deployments/se-proxy/opteesp/se_proxy_sp.c b/deployments/se-proxy/opteesp/se_proxy_sp.c
+index ef90d9ee..11b014b2 100644
+--- a/deployments/se-proxy/opteesp/se_proxy_sp.c
++++ b/deployments/se-proxy/opteesp/se_proxy_sp.c
+@@ -48,6 +48,9 @@ void __noreturn sp_main(struct ffa_init_info *init_info)
+ 	rpc_iface = attest_proxy_create();
+ 	rpc_demux_attach(&rpc_demux, SE_PROXY_INTERFACE_ID_ATTEST, rpc_iface);
+ 
++	rpc_iface = capsule_update_proxy_create();
++	rpc_demux_attach(&rpc_demux, SE_PROXY_INTERFACE_ID_CAPSULE_UPDATE, rpc_iface);
++
+ 	/* End of boot phase */
+ 	sp_msg_wait(&req_msg);
+ 
+diff --git a/deployments/se-proxy/opteesp/service_proxy_factory.c b/deployments/se-proxy/opteesp/service_proxy_factory.c
+index 7edeef8b..591cc9ee 100644
+--- a/deployments/se-proxy/opteesp/service_proxy_factory.c
++++ b/deployments/se-proxy/opteesp/service_proxy_factory.c
+@@ -13,6 +13,7 @@
+ #include <service/crypto/factory/crypto_provider_factory.h>
+ #include <service/secure_storage/frontend/secure_storage_provider/secure_storage_provider.h>
+ #include <trace.h>
++#include <service/capsule_update/provider/capsule_update_provider.h>
+ 
+ /* Stub backends */
+ #include <service/crypto/backend/psa_ipc/crypto_ipc_backend.h>
+@@ -93,3 +94,18 @@ struct rpc_interface *its_proxy_create(void)
+  
+         return secure_storage_provider_init(&its_provider, backend);
+ }
++
++struct rpc_interface *capsule_update_proxy_create(void)
++{
++	static struct capsule_update_provider capsule_update_provider;
++	static struct rpc_caller *capsule_update_caller;
++
++	capsule_update_caller = openamp_caller_init(&openamp);
++
++	if (!capsule_update_caller)
++	return NULL;
++
++	capsule_update_provider.client.caller = capsule_update_caller;
++
++	return capsule_update_provider_init(&capsule_update_provider);
++}
+diff --git a/deployments/se-proxy/opteesp/service_proxy_factory.h b/deployments/se-proxy/opteesp/service_proxy_factory.h
+index 298d407a..02aa7fe2 100644
+--- a/deployments/se-proxy/opteesp/service_proxy_factory.h
++++ b/deployments/se-proxy/opteesp/service_proxy_factory.h
+@@ -17,6 +17,7 @@ struct rpc_interface *attest_proxy_create(void);
+ struct rpc_interface *crypto_proxy_create(void);
+ struct rpc_interface *ps_proxy_create(void);
+ struct rpc_interface *its_proxy_create(void);
++struct rpc_interface *capsule_update_proxy_create(void);
+ 
+ #ifdef __cplusplus
+ }
+diff --git a/deployments/se-proxy/se_proxy_interfaces.h b/deployments/se-proxy/se_proxy_interfaces.h
+index 48908f84..3d4a7c20 100644
+--- a/deployments/se-proxy/se_proxy_interfaces.h
++++ b/deployments/se-proxy/se_proxy_interfaces.h
+@@ -8,9 +8,10 @@
+ #define SE_PROXY_INTERFACES_H
+ 
+ /* Interface IDs from service endpoints available from an se-proxy deployment */
+-#define SE_PROXY_INTERFACE_ID_ITS			(0)
+-#define SE_PROXY_INTERFACE_ID_PS			(1)
+-#define SE_PROXY_INTERFACE_ID_CRYPTO		(2)
+-#define SE_PROXY_INTERFACE_ID_ATTEST		(3)
++#define SE_PROXY_INTERFACE_ID_ITS			    (0)
++#define SE_PROXY_INTERFACE_ID_PS			    (1)
++#define SE_PROXY_INTERFACE_ID_CRYPTO		    (2)
++#define SE_PROXY_INTERFACE_ID_ATTEST		    (3)
++#define SE_PROXY_INTERFACE_ID_CAPSULE_UPDATE    (4)
+ 
+ #endif /* SE_PROXY_INTERFACES_H */
+diff --git a/protocols/service/capsule_update/capsule_update_proto.h b/protocols/service/capsule_update/capsule_update_proto.h
+new file mode 100644
+index 00000000..8f326cd3
+--- /dev/null
++++ b/protocols/service/capsule_update/capsule_update_proto.h
+@@ -0,0 +1,13 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef CAPSULE_UPDATE_PROTO_H
++#define CAPSULE_UPDATE_PROTO_H
++
++#include <protocols/service/capsule_update/opcodes.h>
++#include <protocols/service/capsule_update/parameters.h>
++
++#endif /* CAPSULE_UPDATE_PROTO_H */
+diff --git a/protocols/service/capsule_update/opcodes.h b/protocols/service/capsule_update/opcodes.h
+new file mode 100644
+index 00000000..8185a090
+--- /dev/null
++++ b/protocols/service/capsule_update/opcodes.h
+@@ -0,0 +1,17 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef CAPSULE_UPDATE_OPCODES_H
++#define CAPSULE_UPDATE_OPCODES_H
++
++/**
++ * Opcode definitions for the capsule update service
++ */
++
++#define CAPSULE_UPDATE_OPCODE_UPDATE_CAPSULE		1
++#define CAPSULE_UPDATE_OPCODE_BOOT_CONFIRMED		2
++
++#endif /* CAPSULE_UPDATE_OPCODES_H */
+diff --git a/protocols/service/capsule_update/parameters.h b/protocols/service/capsule_update/parameters.h
+new file mode 100644
+index 00000000..285d9241
+--- /dev/null
++++ b/protocols/service/capsule_update/parameters.h
+@@ -0,0 +1,15 @@
++/*
++ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ *
++ * SPDX-License-Identifier: BSD-3-Clause
++ */
++
++#ifndef CAPSULE_UPDATE_PARAMETERS_H
++#define CAPSULE_UPDATE_PARAMETERS_H
++
++/**
++ * Operation parameter definitions for the capsule update service access protocol.
++ */
++
++
++#endif /* CAPSULE_UPDATE_PARAMETERS_H */
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0026-Add-logs-to-functions-in-SMM-gateway-SP.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0026-Add-logs-to-functions-in-SMM-gateway-SP.patch
new file mode 100644
index 0000000..38ce243
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0026-Add-logs-to-functions-in-SMM-gateway-SP.patch
@@ -0,0 +1,248 @@
+From c9188e59fd27d208a975187da285a9b5938bb00d Mon Sep 17 00:00:00 2001
+From: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+Date: Thu, 16 Dec 2021 13:29:58 +0000
+Subject: [PATCH] Add logs to functions in SMM gateway SP
+
+Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+
+
+---
+ .../backend/uefi_variable_store.c             | 29 +++++++++++++++++--
+ .../provider/smm_variable_provider.c          |  7 +++--
+ 2 files changed, 32 insertions(+), 4 deletions(-)
+
+diff --git a/components/service/smm_variable/backend/uefi_variable_store.c b/components/service/smm_variable/backend/uefi_variable_store.c
+index ed50eaf9..0c371e94 100644
+--- a/components/service/smm_variable/backend/uefi_variable_store.c
++++ b/components/service/smm_variable/backend/uefi_variable_store.c
+@@ -11,6 +11,7 @@
+ #include "uefi_variable_store.h"
+ #include "variable_index_iterator.h"
+ #include "variable_checker.h"
++#include <trace.h>
+ 
+ /* Private functions */
+ static void load_variable_index(
+@@ -151,12 +152,15 @@ void uefi_variable_store_set_storage_limits(
+ 	size_t total_capacity,
+ 	size_t max_variable_size)
+ {
++	EMSG("In func %s\n", __func__);
+ 	struct delegate_variable_store *delegate_store = select_delegate_store(
+ 		context,
+ 		attributes);
+ 
+ 	delegate_store->total_capacity = total_capacity;
+ 	delegate_store->max_variable_size = max_variable_size;
++	EMSG("In func %s total_capacity is %d\n", __func__, total_capacity);
++	EMSG("In func %s max_variable_size is %d\n", __func__, max_variable_size);
+ }
+ 
+ efi_status_t uefi_variable_store_set_variable(
+@@ -265,6 +269,7 @@ efi_status_t uefi_variable_store_get_variable(
+ 	size_t max_data_len,
+ 	size_t *total_length)
+ {
++	EMSG("In func %s\n", __func__);
+ 	efi_status_t status = check_name_terminator(var->Name, var->NameSize);
+ 	if (status != EFI_SUCCESS) return status;
+ 
+@@ -299,6 +304,7 @@ efi_status_t uefi_variable_store_get_next_variable_name(
+ 	size_t max_name_len,
+ 	size_t *total_length)
+ {
++	EMSG("In func %s\n", __func__);
+ 	efi_status_t status = check_name_terminator(cur->Name, cur->NameSize);
+ 	if (status != EFI_SUCCESS) return status;
+ 
+@@ -329,6 +335,8 @@ efi_status_t uefi_variable_store_query_variable_info(
+ 	struct uefi_variable_store *context,
+ 	SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO *var_info)
+ {
++
++	EMSG("In func %s\n", __func__);
+ 	struct delegate_variable_store *delegate_store = select_delegate_store(
+ 		context,
+ 		var_info->Attributes);
+@@ -337,13 +345,15 @@ efi_status_t uefi_variable_store_query_variable_info(
+ 		context,
+ 		var_info->Attributes,
+ 		delegate_store->storage_backend);
+-
++	EMSG("In func %s total_used is %d\n", __func__, total_used);
+ 	var_info->MaximumVariableSize = delegate_store->max_variable_size;
+ 	var_info->MaximumVariableStorageSize = delegate_store->total_capacity;
+ 	var_info->RemainingVariableStorageSize = (total_used < delegate_store->total_capacity) ?
+ 		delegate_store->total_capacity - total_used :
+ 		0;
+-
++	EMSG("In func %s var_info->MaximumVariableSize is %d\n", __func__, var_info->MaximumVariableSize);
++	EMSG("In func %s var_info->MaximumVariableStorageSize is %d\n", __func__, var_info->MaximumVariableStorageSize);
++	EMSG("In func %s var_info->RemainingVariableStorageSize is %d\n", __func__, var_info->RemainingVariableStorageSize);
+ 	return EFI_SUCCESS;
+ }
+ 
+@@ -358,6 +368,7 @@ efi_status_t uefi_variable_store_set_var_check_property(
+ 	struct uefi_variable_store *context,
+ 	const SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *property)
+ {
++	EMSG("In func %s\n", __func__);
+ 	efi_status_t status = check_name_terminator(property->Name, property->NameSize);
+ 	if (status != EFI_SUCCESS) return status;
+ 
+@@ -404,6 +415,7 @@ efi_status_t uefi_variable_store_get_var_check_property(
+ 	struct uefi_variable_store *context,
+ 	SMM_VARIABLE_COMMUNICATE_VAR_CHECK_VARIABLE_PROPERTY *property)
+ {
++	EMSG("In func %s\n", __func__);
+ 	efi_status_t status = check_name_terminator(property->Name, property->NameSize);
+ 	if (status != EFI_SUCCESS) return status;
+ 
+@@ -430,6 +442,7 @@ efi_status_t uefi_variable_store_get_var_check_property(
+ static void load_variable_index(
+ 	struct uefi_variable_store *context)
+ {
++	EMSG("In func %s\n", __func__);
+ 	struct storage_backend *persistent_store = context->persistent_store.storage_backend;
+ 
+ 	if (persistent_store) {
+@@ -444,6 +457,7 @@ static void load_variable_index(
+ 			context->index_sync_buffer_size,
+ 			context->index_sync_buffer,
+ 			&data_len);
++		EMSG("In func %s get status is %d\n", __func__, psa_status);
+ 
+ 		if (psa_status == PSA_SUCCESS) {
+ 
+@@ -455,6 +469,7 @@ static void load_variable_index(
+ static efi_status_t sync_variable_index(
+ 	struct uefi_variable_store *context)
+ {
++	EMSG("In func %s\n", __func__);
+ 	efi_status_t status = EFI_SUCCESS;
+ 
+ 	/* Sync the varibale index to storage if anything is dirty */
+@@ -479,6 +494,7 @@ static efi_status_t sync_variable_index(
+ 				data_len,
+ 				context->index_sync_buffer,
+ 				PSA_STORAGE_FLAG_NONE);
++			EMSG("In func %s set status is %d\n", __func__, psa_status);
+ 
+ 			status = psa_to_efi_storage_status(psa_status);
+ 		}
+@@ -490,6 +506,7 @@ static efi_status_t sync_variable_index(
+ static efi_status_t check_capabilities(
+ 	const SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var)
+ {
++	EMSG("In func %s\n", __func__);
+ 	efi_status_t status = EFI_SUCCESS;
+ 
+ 	/* Check if any unsupported variable attributes have been requested */
+@@ -551,6 +568,7 @@ static efi_status_t store_variable_data(
+ 	const struct variable_info *info,
+ 	const SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var)
+ {
++	EMSG("In func %s\n", __func__);
+ 	psa_status_t psa_status = PSA_SUCCESS;
+ 	size_t data_len = var->DataSize;
+ 	const uint8_t *data = (const uint8_t*)var +
+@@ -599,6 +617,7 @@ static efi_status_t remove_variable_data(
+ 	struct uefi_variable_store *context,
+ 	const struct variable_info *info)
+ {
++	EMSG("In func %s\n", __func__);
+ 	psa_status_t psa_status = PSA_SUCCESS;
+ 
+ 	if (info->is_variable_set) {
+@@ -613,6 +632,7 @@ static efi_status_t remove_variable_data(
+ 				delegate_store->storage_backend->context,
+ 				context->owner_id,
+ 				info->metadata.uid);
++			EMSG("In func %s status is %d\n", __func__, psa_status);
+ 		}
+ 	}
+ 
+@@ -625,6 +645,7 @@ static efi_status_t load_variable_data(
+ 	SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var,
+ 	size_t max_data_len)
+ {
++	EMSG("In func %s\n", __func__);
+ 	psa_status_t psa_status = PSA_SUCCESS;
+ 	size_t data_len = 0;
+ 	uint8_t *data = (uint8_t*)var +
+@@ -644,6 +665,7 @@ static efi_status_t load_variable_data(
+ 			max_data_len,
+ 			data,
+ 			&data_len);
++		EMSG("In func %s get status is %d\n", __func__, psa_status);
+ 
+ 		var->DataSize = data_len;
+ 	}
+@@ -771,6 +793,7 @@ static void purge_orphan_index_entries(
+ 				context->owner_id,
+ 				info->metadata.uid,
+ 				&storage_info);
++			EMSG("In func %s get status is %d\n", __func__, psa_status);
+ 
+ 			if (psa_status != PSA_SUCCESS) {
+ 
+@@ -802,6 +825,7 @@ static size_t space_used(
+ 	uint32_t attributes,
+ 	struct storage_backend *storage_backend)
+ {
++	EMSG("In func %s\n", __func__);
+ 	if (!storage_backend) return 0;
+ 
+ 	size_t total_used = 0;
+@@ -823,6 +847,7 @@ static size_t space_used(
+ 				context->owner_id,
+ 				info->metadata.uid,
+ 				&storage_info);
++			EMSG("In func %s get status is %d\n", __func__, psa_status);
+ 
+ 			if (psa_status == PSA_SUCCESS) total_used += storage_info.size;
+ 		}
+diff --git a/components/service/smm_variable/provider/smm_variable_provider.c b/components/service/smm_variable/provider/smm_variable_provider.c
+index 52e68d09..1f362c17 100644
+--- a/components/service/smm_variable/provider/smm_variable_provider.c
++++ b/components/service/smm_variable/provider/smm_variable_provider.c
+@@ -9,6 +9,7 @@
+ #include <protocols/service/smm_variable/smm_variable_proto.h>
+ #include <protocols/rpc/common/packed-c/status.h>
+ #include "smm_variable_provider.h"
++#include <trace.h>
+ 
+ /* Service request handlers */
+ static rpc_status_t get_variable_handler(void *context, struct call_req *req);
+@@ -252,17 +253,18 @@ static rpc_status_t set_variable_handler(void *context, struct call_req* req)
+ 
+ static rpc_status_t query_variable_info_handler(void *context, struct call_req* req)
+ {
++	EMSG("In func %s \n", __func__);
+ 	efi_status_t efi_status = EFI_INVALID_PARAMETER;
+ 	struct smm_variable_provider *this_instance = (struct smm_variable_provider*)context;
+ 
+ 	const struct call_param_buf *req_buf = call_req_get_req_buf(req);
+-
++	EMSG("In func %s sizeof(SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO) is %d\n", __func__, sizeof(SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO));
+ 	if (req_buf->data_len >= sizeof(SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO)) {
+ 
+ 		struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ 
+ 		if (resp_buf->size >= req_buf->data_len) {
+-
++			
+ 			memmove(resp_buf->data, req_buf->data, req_buf->data_len);
+ 
+ 			efi_status = uefi_variable_store_query_variable_info(
+@@ -272,6 +274,7 @@ static rpc_status_t query_variable_info_handler(void *context, struct call_req*
+ 			if (efi_status == EFI_SUCCESS) {
+ 
+ 				resp_buf->data_len = sizeof(SMM_VARIABLE_COMMUNICATE_QUERY_VARIABLE_INFO);
++				EMSG("In func %s resp_buf->data_len is %d\n", __func__, resp_buf->data_len);
+ 			}
+ 		}
+ 		else {
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0027-Configure-storage-size.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0027-Configure-storage-size.patch
new file mode 100644
index 0000000..ddf9503
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0027-Configure-storage-size.patch
@@ -0,0 +1,41 @@
+From 3e472452bca64ed90071b61416460f1a69382293 Mon Sep 17 00:00:00 2001
+From: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+Date: Thu, 16 Dec 2021 21:31:40 +0000
+Subject: [PATCH] Configure storage size
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+
+
+---
+ .../service/smm_variable/backend/uefi_variable_store.c       | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/components/service/smm_variable/backend/uefi_variable_store.c b/components/service/smm_variable/backend/uefi_variable_store.c
+index 0c371e94..b7cfff40 100644
+--- a/components/service/smm_variable/backend/uefi_variable_store.c
++++ b/components/service/smm_variable/backend/uefi_variable_store.c
+@@ -87,6 +87,7 @@ static efi_status_t check_name_terminator(
+  * may be overridden using uefi_variable_store_set_storage_limits()
+  */
+ #define DEFAULT_MAX_VARIABLE_SIZE			(2048)
++#define CONFIGURE_STORAGE_SIZE			    (50)
+ 
+ efi_status_t uefi_variable_store_init(
+ 	struct uefi_variable_store *context,
+@@ -100,13 +101,13 @@ efi_status_t uefi_variable_store_init(
+ 	/* Initialise persistent store defaults */
+ 	context->persistent_store.is_nv = true;
+ 	context->persistent_store.max_variable_size = DEFAULT_MAX_VARIABLE_SIZE;
+-	context->persistent_store.total_capacity = DEFAULT_MAX_VARIABLE_SIZE * max_variables;
++	context->persistent_store.total_capacity = CONFIGURE_STORAGE_SIZE * max_variables;
+ 	context->persistent_store.storage_backend = persistent_store;
+ 
+ 	/* Initialise volatile store defaults */
+ 	context->volatile_store.is_nv = false;
+ 	context->volatile_store.max_variable_size = DEFAULT_MAX_VARIABLE_SIZE;
+-	context->volatile_store.total_capacity = DEFAULT_MAX_VARIABLE_SIZE * max_variables;
++	context->volatile_store.total_capacity = CONFIGURE_STORAGE_SIZE * max_variables;
+ 	context->volatile_store.storage_backend = volatile_store;
+ 
+ 	context->owner_id = owner_id;
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0028-Revert-Add-uefi-variable-append-write-support.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0028-Revert-Add-uefi-variable-append-write-support.patch
new file mode 100644
index 0000000..9bb3f91
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0028-Revert-Add-uefi-variable-append-write-support.patch
@@ -0,0 +1,1219 @@
+From da3bd0721f2403562b6ae6d1939f5f331fd141bb Mon Sep 17 00:00:00 2001
+From: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+Date: Wed, 15 Dec 2021 17:23:25 +0000
+Subject: [PATCH] Revert "Add uefi variable append write support"
+
+This reverts commit e8758d9aff0eddae81a74b0191cd027bcdc92c04.
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+
+
+---
+ .../backend/test/variable_index_tests.cpp     |  90 +++---
+ .../backend/test/variable_store_tests.cpp     |  72 +----
+ .../backend/uefi_variable_store.c             | 293 ++++++------------
+ .../smm_variable/backend/variable_index.c     |  95 ++++--
+ .../smm_variable/backend/variable_index.h     |  58 ++--
+ .../backend/variable_index_iterator.c         |   4 +-
+ .../backend/variable_index_iterator.h         |   2 +-
+ .../service/smm_variable_service_tests.cpp    |  48 ---
+ protocols/service/smm_variable/parameters.h   |   3 -
+ 9 files changed, 239 insertions(+), 426 deletions(-)
+
+diff --git a/components/service/smm_variable/backend/test/variable_index_tests.cpp b/components/service/smm_variable/backend/test/variable_index_tests.cpp
+index 8edc0e70..c8bacf97 100644
+--- a/components/service/smm_variable/backend/test/variable_index_tests.cpp
++++ b/components/service/smm_variable/backend/test/variable_index_tests.cpp
+@@ -69,37 +69,34 @@ TEST_GROUP(UefiVariableIndexTests)
+ 
+ 	void create_variables()
+ 	{
+-		struct variable_info *info = NULL;
++		const struct variable_info *info = NULL;
+ 
+-		info = variable_index_add_entry(
++		info = variable_index_add_variable(
+ 			&m_variable_index,
+ 			&guid_1,
+ 			name_1.size() * sizeof(int16_t),
+-			name_1.data());
+-		CHECK_TRUE(info);
+-		variable_index_set_variable(
+-			info,
++			name_1.data(),
+ 			EFI_VARIABLE_BOOTSERVICE_ACCESS);
+ 
+-		info = variable_index_add_entry(
++		CHECK_TRUE(info);
++
++		info = variable_index_add_variable(
+ 			&m_variable_index,
+ 			&guid_2,
+ 			name_2.size() * sizeof(int16_t),
+-			name_2.data());
+-		CHECK_TRUE(info);
+-		variable_index_set_variable(
+-			info,
++			name_2.data(),
+ 			EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS);
+ 
+-		info = variable_index_add_entry(
++		CHECK_TRUE(info);
++
++		info = variable_index_add_variable(
+ 			&m_variable_index,
+ 			&guid_1,
+ 			name_3.size() * sizeof(int16_t),
+-			name_3.data());
+-		CHECK_TRUE(info);
+-		variable_index_set_variable(
+-			info,
++			name_3.data(),
+ 			EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS);
++
++		CHECK_TRUE(info);
+ 	}
+ 
+ 	static const size_t MAX_VARIABLES = 10;
+@@ -114,7 +111,7 @@ TEST_GROUP(UefiVariableIndexTests)
+ 
+ TEST(UefiVariableIndexTests, emptyIndexOperations)
+ {
+-	struct variable_info *info = NULL;
++	const struct variable_info *info = NULL;
+ 
+ 	/* Expect not to find a variable */
+ 	info = variable_index_find(
+@@ -133,34 +130,36 @@ TEST(UefiVariableIndexTests, emptyIndexOperations)
+ 	POINTERS_EQUAL(NULL, info);
+ 
+ 	/* Remove should silently return */
+-	variable_index_clear_variable(
++	variable_index_remove_variable(
+ 		&m_variable_index,
+ 		info);
+ }
+ 
+ TEST(UefiVariableIndexTests, addWithOversizedName)
+ {
+-	struct variable_info *info = NULL;
++	const struct variable_info *info = NULL;
+ 	std::vector<int16_t> name;
+ 
+ 	name = to_variable_name(L"a long variable name that exceeds the length limit");
+ 
+-	info = variable_index_add_entry(
++	info = variable_index_add_variable(
+ 		&m_variable_index,
+ 		&guid_1,
+ 		name.size() * sizeof(int16_t),
+-		name.data());
++		name.data(),
++		EFI_VARIABLE_BOOTSERVICE_ACCESS);
+ 
+ 	/* Expect the add to fail because of an oversized name */
+ 	POINTERS_EQUAL(NULL, info);
+ 
+ 	name = to_variable_name(L"a long variable name that fits!");
+ 
+-	info = variable_index_add_entry(
++	info = variable_index_add_variable(
+ 		&m_variable_index,
+ 		&guid_1,
+ 		name.size() * sizeof(int16_t),
+-		name.data());
++		name.data(),
++		EFI_VARIABLE_BOOTSERVICE_ACCESS);
+ 
+ 	/* Expect the add succeed */
+ 	CHECK_TRUE(info);
+@@ -168,17 +167,18 @@ TEST(UefiVariableIndexTests, addWithOversizedName)
+ 
+ TEST(UefiVariableIndexTests, variableIndexFull)
+ {
+-	struct variable_info *info = NULL;
++	const struct variable_info *info = NULL;
+ 	EFI_GUID guid = guid_1;
+ 
+ 	/* Expect to be able to fill the index */
+ 	for (size_t i = 0; i < MAX_VARIABLES; ++i) {
+ 
+-		info = variable_index_add_entry(
++		info = variable_index_add_variable(
+ 			&m_variable_index,
+ 			&guid,
+ 			name_1.size() * sizeof(int16_t),
+-			name_1.data());
++			name_1.data(),
++			EFI_VARIABLE_BOOTSERVICE_ACCESS);
+ 
+ 		CHECK_TRUE(info);
+ 
+@@ -187,11 +187,12 @@ TEST(UefiVariableIndexTests, variableIndexFull)
+ 	}
+ 
+ 	/* Variable index should now be full */
+-	info = variable_index_add_entry(
++	info = variable_index_add_variable(
+ 		&m_variable_index,
+ 		&guid,
+ 		name_1.size() * sizeof(int16_t),
+-		name_1.data());
++		name_1.data(),
++		EFI_VARIABLE_BOOTSERVICE_ACCESS);
+ 
+ 	POINTERS_EQUAL(NULL, info);
+ }
+@@ -322,7 +323,7 @@ TEST(UefiVariableIndexTests, dumpBufferTooSmall)
+ TEST(UefiVariableIndexTests, removeVariable)
+ {
+ 	uint8_t buffer[MAX_VARIABLES * sizeof(struct variable_metadata)];
+-	struct variable_info *info = NULL;
++	const struct variable_info *info = NULL;
+ 
+ 	create_variables();
+ 
+@@ -333,7 +334,7 @@ TEST(UefiVariableIndexTests, removeVariable)
+ 		name_2.size() * sizeof(int16_t),
+ 		name_2.data());
+ 
+-	variable_index_clear_variable(
++	variable_index_remove_variable(
+ 		&m_variable_index,
+ 		info);
+ 
+@@ -351,7 +352,7 @@ TEST(UefiVariableIndexTests, removeVariable)
+ 		name_1.size() * sizeof(int16_t),
+ 		name_1.data());
+ 
+-	variable_index_clear_variable(
++	variable_index_remove_variable(
+ 		&m_variable_index,
+ 		info);
+ 
+@@ -369,7 +370,7 @@ TEST(UefiVariableIndexTests, removeVariable)
+ 		name_3.size() * sizeof(int16_t),
+ 		name_3.data());
+ 
+-	variable_index_clear_variable(
++	variable_index_remove_variable(
+ 		&m_variable_index,
+ 		info);
+ 
+@@ -394,7 +395,7 @@ TEST(UefiVariableIndexTests, removeVariable)
+ 
+ TEST(UefiVariableIndexTests, checkIterator)
+ {
+-	struct variable_info *info = NULL;
++	const struct variable_info *info = NULL;
+ 
+ 	create_variables();
+ 
+@@ -418,7 +419,7 @@ TEST(UefiVariableIndexTests, checkIterator)
+ 	UNSIGNED_LONGS_EQUAL(name_2.size() * sizeof(int16_t), info->metadata.name_size);
+ 	MEMCMP_EQUAL(name_2.data(), info->metadata.name, info->metadata.name_size);
+ 
+-	struct variable_info *info_to_remove = info;
++	const struct variable_info *info_to_remove = info;
+ 
+ 	variable_index_iterator_next(&iter);
+ 	CHECK_FALSE(variable_index_iterator_is_done(&iter));
+@@ -434,8 +435,7 @@ TEST(UefiVariableIndexTests, checkIterator)
+ 	CHECK_TRUE(variable_index_iterator_is_done(&iter));
+ 
+ 	/* Now remove the middle entry */
+-	variable_index_clear_variable(&m_variable_index, info_to_remove);
+-	variable_index_remove_unused_entry(&m_variable_index, info_to_remove);
++	variable_index_remove_variable(&m_variable_index, info_to_remove);
+ 
+ 	/* Iterate again but this time there should only be two entries */
+ 	variable_index_iterator_first(&iter, &m_variable_index);
+@@ -478,7 +478,7 @@ TEST(UefiVariableIndexTests, setCheckConstraintsExistingVar)
+ 	constraints.max_size = 100;
+ 
+ 	/* Set check constraints on one of the variables */
+-	struct variable_info *info = variable_index_find(
++	const struct variable_info *info = variable_index_find(
+ 		&m_variable_index,
+ 		&guid_2,
+ 		name_2.size() * sizeof(int16_t),
+@@ -488,7 +488,7 @@ TEST(UefiVariableIndexTests, setCheckConstraintsExistingVar)
+ 	CHECK_TRUE(info->is_variable_set);
+ 	CHECK_FALSE(info->is_constraints_set);
+ 
+-	variable_index_set_constraints(info, &constraints);
++	variable_index_update_constraints(info, &constraints);
+ 
+ 	CHECK_TRUE(info->is_constraints_set);
+ 	CHECK_TRUE(info->is_variable_set);
+@@ -496,7 +496,7 @@ TEST(UefiVariableIndexTests, setCheckConstraintsExistingVar)
+ 	/* Remove the variable but still expect the variable to be indexed
+ 	 * because of the set constraints.
+ 	 */
+-	variable_index_clear_variable(
++	variable_index_remove_variable(
+ 		&m_variable_index,
+ 		info);
+ 
+@@ -588,7 +588,7 @@ TEST(UefiVariableIndexTests, setCheckConstraintsNonExistingVar)
+ 	constraints.max_size = 100;
+ 
+ 	/* Initially expect no variable_info */
+-	struct variable_info *info = variable_index_find(
++	const struct variable_info *info = variable_index_find(
+ 		&m_variable_index,
+ 		&guid_2,
+ 		name_2.size() * sizeof(int16_t),
+@@ -597,19 +597,19 @@ TEST(UefiVariableIndexTests, setCheckConstraintsNonExistingVar)
+ 	CHECK_FALSE(info);
+ 
+ 	/* Adding the check constraints should result in an entry being added */
+-	info = variable_index_add_entry(
++	info = variable_index_add_constraints(
+ 		&m_variable_index,
+ 		&guid_2,
+ 		name_2.size() * sizeof(int16_t),
+-		name_2.data());
+-	CHECK_TRUE(info);
++		name_2.data(),
++		&constraints);
+ 
+-	variable_index_set_constraints(info, &constraints);
++	CHECK_TRUE(info);
+ 	CHECK_FALSE(info->is_variable_set);
+ 	CHECK_TRUE(info->is_constraints_set);
+ 
+ 	/* Updating the variable should cause the variable to be marked as set */
+-	variable_index_set_variable(info, EFI_VARIABLE_RUNTIME_ACCESS);
++	variable_index_update_variable(info, EFI_VARIABLE_RUNTIME_ACCESS);
+ 
+ 	CHECK_TRUE(info->is_variable_set);
+ 	CHECK_TRUE(info->is_constraints_set);
+diff --git a/components/service/smm_variable/backend/test/variable_store_tests.cpp b/components/service/smm_variable/backend/test/variable_store_tests.cpp
+index e90c1067..235642e6 100644
+--- a/components/service/smm_variable/backend/test/variable_store_tests.cpp
++++ b/components/service/smm_variable/backend/test/variable_store_tests.cpp
+@@ -305,37 +305,6 @@ TEST(UefiVariableStoreTests, setGetRoundtrip)
+ 	/* Expect got variable data to be the same as the set value */
+ 	UNSIGNED_LONGLONGS_EQUAL(input_data.size(), output_data.size());
+ 	LONGS_EQUAL(0, input_data.compare(output_data));
+-
+-	/* Extend the variable using an append write */
+-	std::string input_data2 = " jumps over the lazy dog";
+-
+-	status = set_variable(var_name, input_data2, EFI_VARIABLE_APPEND_WRITE);
+-	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+-
+-	status = get_variable(var_name, output_data);
+-	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+-
+-	std::string expected_output = input_data + input_data2;
+-
+-	/* Expect the append write operation to have extended the variable */
+-	UNSIGNED_LONGLONGS_EQUAL(expected_output.size(), output_data.size());
+-	LONGS_EQUAL(0, expected_output.compare(output_data));
+-
+-	/* Expect query_variable_info to return consistent values */
+-	size_t max_variable_storage_size = 0;
+-	size_t remaining_variable_storage_size = 0;
+-	size_t max_variable_size = 0;
+-
+-	status = query_variable_info(
+-		0,
+-		&max_variable_storage_size,
+-		&remaining_variable_storage_size,
+-		&max_variable_size);
+-	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+-
+-	UNSIGNED_LONGLONGS_EQUAL(STORE_CAPACITY, max_variable_storage_size);
+-	UNSIGNED_LONGLONGS_EQUAL(MAX_VARIABLE_SIZE, max_variable_size);
+-	UNSIGNED_LONGLONGS_EQUAL(STORE_CAPACITY - expected_output.size(), remaining_variable_storage_size);
+ }
+ 
+ TEST(UefiVariableStoreTests, persistentSetGet)
+@@ -345,8 +314,7 @@ TEST(UefiVariableStoreTests, persistentSetGet)
+ 	std::string input_data = "quick brown fox";
+ 	std::string output_data;
+ 
+-	status = set_variable(var_name, input_data,
+-		EFI_VARIABLE_NON_VOLATILE);
++	status = set_variable(var_name, input_data, EFI_VARIABLE_NON_VOLATILE);
+ 	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+ 
+ 	status = get_variable(var_name, output_data);
+@@ -356,22 +324,6 @@ TEST(UefiVariableStoreTests, persistentSetGet)
+ 	UNSIGNED_LONGLONGS_EQUAL(input_data.size(), output_data.size());
+ 	LONGS_EQUAL(0, input_data.compare(output_data));
+ 
+-	/* Extend the variable using an append write */
+-	std::string input_data2 = " jumps over the lazy dog";
+-
+-	status = set_variable(var_name, input_data2,
+-		EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_APPEND_WRITE);
+-	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+-
+-	status = get_variable(var_name, output_data);
+-	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+-
+-	std::string expected_output = input_data + input_data2;
+-
+-	/* Expect the append write operation to have extended the variable */
+-	UNSIGNED_LONGLONGS_EQUAL(expected_output.size(), output_data.size());
+-	LONGS_EQUAL(0, expected_output.compare(output_data));
+-
+ 	/* Expect the variable to survive a power cycle */
+ 	power_cycle();
+ 
+@@ -380,24 +332,8 @@ TEST(UefiVariableStoreTests, persistentSetGet)
+ 	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+ 
+ 	/* Still expect got variable data to be the same as the set value */
+-	UNSIGNED_LONGLONGS_EQUAL(expected_output.size(), output_data.size());
+-	LONGS_EQUAL(0, expected_output.compare(output_data));
+-
+-	/* Expect query_variable_info to return consistent values */
+-	size_t max_variable_storage_size = 0;
+-	size_t remaining_variable_storage_size = 0;
+-	size_t max_variable_size = 0;
+-
+-	status = query_variable_info(
+-		EFI_VARIABLE_NON_VOLATILE,
+-		&max_variable_storage_size,
+-		&remaining_variable_storage_size,
+-		&max_variable_size);
+-	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+-
+-	UNSIGNED_LONGLONGS_EQUAL(STORE_CAPACITY, max_variable_storage_size);
+-	UNSIGNED_LONGLONGS_EQUAL(MAX_VARIABLE_SIZE, max_variable_size);
+-	UNSIGNED_LONGLONGS_EQUAL(STORE_CAPACITY - expected_output.size(), remaining_variable_storage_size);
++	UNSIGNED_LONGLONGS_EQUAL(input_data.size(), output_data.size());
++	LONGS_EQUAL(0, input_data.compare(output_data));
+ }
+ 
+ TEST(UefiVariableStoreTests, removeVolatile)
+@@ -436,7 +372,7 @@ TEST(UefiVariableStoreTests, removePersistent)
+ 	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+ 
+ 	/* Remove by setting with zero data length */
+-	status = set_variable(var_name, std::string(), EFI_VARIABLE_NON_VOLATILE);
++	status = set_variable(var_name, std::string(), 0);
+ 	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, status);
+ 
+ 	/* Expect variable to no loger exist */
+diff --git a/components/service/smm_variable/backend/uefi_variable_store.c b/components/service/smm_variable/backend/uefi_variable_store.c
+index b7cfff40..6a90f46a 100644
+--- a/components/service/smm_variable/backend/uefi_variable_store.c
++++ b/components/service/smm_variable/backend/uefi_variable_store.c
+@@ -47,20 +47,6 @@ static efi_status_t load_variable_data(
+ 	SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var,
+ 	size_t max_data_len);
+ 
+-static psa_status_t store_overwrite(
+-	struct delegate_variable_store *delegate_store,
+-	uint32_t client_id,
+-	uint64_t uid,
+-	size_t data_length,
+-	const void *data);
+-
+-static psa_status_t store_append_write(
+-	struct delegate_variable_store *delegate_store,
+-	uint32_t client_id,
+-	uint64_t uid,
+-	size_t data_length,
+-	const void *data);
+-
+ static void purge_orphan_index_entries(
+ 	struct uefi_variable_store *context);
+ 
+@@ -168,45 +154,40 @@ efi_status_t uefi_variable_store_set_variable(
+ 	struct uefi_variable_store *context,
+ 	const SMM_VARIABLE_COMMUNICATE_ACCESS_VARIABLE *var)
+ {
+-	bool should_sync_index = false;
+-
+-	/* Validate incoming request */
+ 	efi_status_t status = check_name_terminator(var->Name, var->NameSize);
+ 	if (status != EFI_SUCCESS) return status;
+ 
+ 	status = check_capabilities(var);
++	bool should_sync_index = false;
++
+ 	if (status != EFI_SUCCESS) return status;
+ 
+-	/* Find an existing entry in the variable index or add a new one */
+-	struct variable_info *info = variable_index_find(
++	/* Find in index */
++	const struct variable_info *info = variable_index_find(
+ 		&context->variable_index,
+ 		&var->Guid,
+ 		var->NameSize,
+ 		var->Name);
+ 
+-	if (!info) {
++	if (info) {
+ 
+-		info = variable_index_add_entry(
+-			&context->variable_index,
+-			&var->Guid,
+-			var->NameSize,
+-			var->Name);
++		/* Variable info already exists */
++		status = check_access_permitted_on_set(context, info, var);
+ 
+-		if (!info) return EFI_OUT_OF_RESOURCES;
+-	}
++		if (status == EFI_SUCCESS) {
+ 
+-	/* Control access */
+-	status = check_access_permitted_on_set(context, info, var);
++			should_sync_index =
++				(var->Attributes & EFI_VARIABLE_NON_VOLATILE) ||
++				(info->is_variable_set && (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE));
+ 
+-	if (status == EFI_SUCCESS) {
++			if (var->DataSize) {
+ 
+-		/* Access permitted */
+-		if (info->is_variable_set) {
+-
+-			/* It's a request to update to an existing variable */
+-			if (!(var->Attributes &
+-				(EFI_VARIABLE_APPEND_WRITE | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS_MASK)) &&
+-				!var->DataSize) {
++				/* It's a set rather than a remove operation */
++				variable_index_update_variable(
++					info,
++					var->Attributes);
++			}
++			else {
+ 
+ 				/* It's a remove operation - for a remove, the variable
+ 				 * data must be removed from the storage backend before
+@@ -215,30 +196,31 @@ efi_status_t uefi_variable_store_set_variable(
+ 				 * the storage backend without a corresponding index entry.
+ 				 */
+ 				remove_variable_data(context, info);
+-				variable_index_clear_variable(&context->variable_index, info);
++				variable_index_remove_variable(&context->variable_index, info);
+ 
+-				should_sync_index = (var->Attributes & EFI_VARIABLE_NON_VOLATILE);
+-			}
+-			else {
+-
+-				/* It's a set operation where variable data is potentially
+-				 * being overwritten or extended.
+-				 */
+-				if ((var->Attributes & ~EFI_VARIABLE_APPEND_WRITE) != info->metadata.attributes) {
+-
+-					/* Modifying attributes is forbidden */
+-					return EFI_INVALID_PARAMETER;
+-				}
++				/* Variable info no longer valid */
++				info = NULL;
+ 			}
+ 		}
+ 		else {
+ 
+-			/*  It's a request to create a new variable */
+-			variable_index_set_variable(info, var->Attributes);
+-
+-			should_sync_index = (var->Attributes & EFI_VARIABLE_NON_VOLATILE);
++			/* Access forbidden */
++			info = NULL;
+ 		}
+ 	}
++	else if (var->DataSize) {
++
++		/* It's a new variable */
++		info = variable_index_add_variable(
++			&context->variable_index,
++			&var->Guid,
++			var->NameSize,
++			var->Name,
++			var->Attributes);
++
++		if (!info) status = EFI_OUT_OF_RESOURCES;
++		should_sync_index = info && (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE);
++	}
+ 
+ 	/* The order of these operations is important. For an update
+ 	 * or create operation, The variable index is always synchronized
+@@ -254,13 +236,11 @@ efi_status_t uefi_variable_store_set_variable(
+ 	}
+ 
+ 	/* Store any variable data to the storage backend */
+-	if (info->is_variable_set && (status == EFI_SUCCESS)) {
++	if (info && (status == EFI_SUCCESS)) {
+ 
+ 		status = store_variable_data(context, info, var);
+ 	}
+ 
+-	variable_index_remove_unused_entry(&context->variable_index, info);
+-
+ 	return status;
+ }
+ 
+@@ -373,41 +353,53 @@ efi_status_t uefi_variable_store_set_var_check_property(
+ 	efi_status_t status = check_name_terminator(property->Name, property->NameSize);
+ 	if (status != EFI_SUCCESS) return status;
+ 
+-	/* Find in index or create a new entry */
+-	struct variable_info *info = variable_index_find(
++	/* Find in index */
++	const struct variable_info *info = variable_index_find(
+ 		&context->variable_index,
+ 		&property->Guid,
+ 		property->NameSize,
+ 		property->Name);
+ 
+-	if (!info) {
++	if (info) {
+ 
+-		info = variable_index_add_entry(
+-			&context->variable_index,
+-			&property->Guid,
+-			property->NameSize,
+-			property->Name);
++		/* Applying check constraints to an existing variable that may have
++		 * constraints already set.  These could constrain the setting of
++		 * the constraints.
++		 */
++		struct variable_constraints constraints = info->check_constraints;
++
++		status = variable_checker_set_constraints(
++			&constraints,
++			info->is_constraints_set,
++			&property->VariableProperty);
++
++		if (status == EFI_SUCCESS) {
+ 
+-		if (!info) return EFI_OUT_OF_RESOURCES;
++			variable_index_update_constraints(info, &constraints);
++		}
+ 	}
++	else {
+ 
+-	/* Applying check constraints to an existing variable that may have
+-	 * constraints already set.  These could constrain the setting of
+-	 * the constraints.
+-	 */
+-	struct variable_constraints constraints = info->check_constraints;
++		/* Applying check constraints for a new variable */
++		struct variable_constraints constraints;
+ 
+-	status = variable_checker_set_constraints(
+-		&constraints,
+-		info->is_constraints_set,
+-		&property->VariableProperty);
++		status = variable_checker_set_constraints(
++			&constraints,
++			false,
++			&property->VariableProperty);
+ 
+-	if (status == EFI_SUCCESS) {
++		if (status == EFI_SUCCESS) {
+ 
+-		variable_index_set_constraints(info, &constraints);
+-	}
++			info = variable_index_add_constraints(
++				&context->variable_index,
++				&property->Guid,
++				property->NameSize,
++				property->Name,
++				&constraints);
+ 
+-	variable_index_remove_unused_entry(&context->variable_index, info);
++			if (!info) status = EFI_OUT_OF_RESOURCES;
++		}
++	}
+ 
+ 	return status;
+ }
+@@ -514,8 +506,7 @@ static efi_status_t check_capabilities(
+ 	if (var->Attributes & ~(
+ 		EFI_VARIABLE_NON_VOLATILE |
+ 		EFI_VARIABLE_BOOTSERVICE_ACCESS |
+-		EFI_VARIABLE_RUNTIME_ACCESS |
+-		EFI_VARIABLE_APPEND_WRITE)) {
++		EFI_VARIABLE_RUNTIME_ACCESS)) {
+ 
+ 		/* An unsupported attribute has been requested */
+ 		status = EFI_UNSUPPORTED;
+@@ -561,6 +552,17 @@ static efi_status_t check_access_permitted_on_set(
+ 			var->DataSize);
+ 	}
+ 
++	if ((status == EFI_SUCCESS) && var->DataSize) {
++
++		/* Restrict which attributes can be modified for an existing variable */
++		if ((var->Attributes & EFI_VARIABLE_NON_VOLATILE) !=
++			(info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE)) {
++
++			/* Don't permit change of storage class */
++			status = EFI_INVALID_PARAMETER;
++		}
++	}
++
+ 	return status;
+ }
+ 
+@@ -581,33 +583,20 @@ static efi_status_t store_variable_data(
+ 
+ 	if (delegate_store->storage_backend) {
+ 
+-		if (!(var->Attributes & EFI_VARIABLE_APPEND_WRITE)) {
+-
+-			/* Create or overwrite variable data */
+-			psa_status = store_overwrite(
+-				delegate_store,
+-				context->owner_id,
+-				info->metadata.uid,
+-				data_len,
+-				data);
+-		}
+-		else {
+-
+-			/* Append new data to existing variable data */
+-			psa_status = store_append_write(
+-				delegate_store,
+-				context->owner_id,
+-				info->metadata.uid,
+-				data_len,
+-				data);
+-		}
++		psa_status = delegate_store->storage_backend->interface->set(
++			delegate_store->storage_backend->context,
++			context->owner_id,
++			info->metadata.uid,
++			data_len,
++			data,
++			PSA_STORAGE_FLAG_NONE);
+ 	}
+ 
+ 	if ((psa_status != PSA_SUCCESS) && delegate_store->is_nv) {
+ 
+ 		/* A storage failure has occurred so attempt to fix any
+-		 * mismatch between the variable index and stored NV variables.
+-		 */
++		* mismatch between the variable index and stored NV variables.
++		*/
+ 		purge_orphan_index_entries(context);
+ 	}
+ 
+@@ -674,100 +663,6 @@ static efi_status_t load_variable_data(
+ 	return psa_to_efi_storage_status(psa_status);
+ }
+ 
+-static psa_status_t store_overwrite(
+-	struct delegate_variable_store *delegate_store,
+-	uint32_t client_id,
+-	uint64_t uid,
+-	size_t data_length,
+-	const void *data)
+-{
+-	/* Police maximum variable size limit */
+-	if (data_length > delegate_store->max_variable_size) return PSA_ERROR_INVALID_ARGUMENT;
+-
+-	psa_status_t psa_status = delegate_store->storage_backend->interface->set(
+-		delegate_store->storage_backend->context,
+-		client_id,
+-		uid,
+-		data_length,
+-		data,
+-		PSA_STORAGE_FLAG_NONE);
+-
+-	return psa_status;
+-}
+-
+-static psa_status_t store_append_write(
+-	struct delegate_variable_store *delegate_store,
+-	uint32_t client_id,
+-	uint64_t uid,
+-	size_t data_length,
+-	const void *data)
+-{
+-	struct psa_storage_info_t storage_info;
+-
+-	if (data_length == 0) return PSA_SUCCESS;
+-
+-	psa_status_t psa_status = delegate_store->storage_backend->interface->get_info(
+-		delegate_store->storage_backend->context,
+-		client_id,
+-		uid,
+-		&storage_info);
+-
+-	if (psa_status != PSA_SUCCESS) return psa_status;
+-
+-	/* Determine size of appended variable */
+-	size_t new_size = storage_info.size + data_length;
+-
+-	/* Defend against integer overflow */
+-	if (new_size < storage_info.size) return PSA_ERROR_INVALID_ARGUMENT;
+-
+-		/* Police maximum variable size limit */
+-	if (new_size > delegate_store->max_variable_size) return PSA_ERROR_INVALID_ARGUMENT;
+-
+-	/* Storage backend doesn't support an append operation so we need
+-	 * need to read the current variable data, extend it and write it back.
+-	 */
+-	uint8_t *rw_buf = malloc(new_size);
+-	if (!rw_buf) return PSA_ERROR_INSUFFICIENT_MEMORY;
+-
+-	size_t old_size = 0;
+-	psa_status = delegate_store->storage_backend->interface->get(
+-		delegate_store->storage_backend->context,
+-		client_id,
+-		uid,
+-		0,
+-		new_size,
+-		rw_buf,
+-		&old_size);
+-
+-	if (psa_status == PSA_SUCCESS) {
+-
+-		if ((old_size + data_length) <= new_size) {
+-
+-			/* Extend the variable data */
+-			memcpy(&rw_buf[old_size], data, data_length);
+-
+-			psa_status = delegate_store->storage_backend->interface->set(
+-				delegate_store->storage_backend->context,
+-				client_id,
+-				uid,
+-				old_size + data_length,
+-				rw_buf,
+-				storage_info.flags);
+-		}
+-		else {
+-
+-			/* There's a mismatch between the length obtained from
+-			 * get_info() and the subsequent length returned by get().
+-			 */
+-			psa_status = PSA_ERROR_STORAGE_FAILURE;
+-		}
+-	}
+-
+-	free(rw_buf);
+-
+-	return psa_status;
+-}
+-
+ static void purge_orphan_index_entries(
+ 	struct uefi_variable_store *context)
+ {
+@@ -782,7 +677,7 @@ static void purge_orphan_index_entries(
+ 	 */
+ 	while (!variable_index_iterator_is_done(&iter)) {
+ 
+-		struct variable_info *info = variable_index_iterator_current(&iter);
++		const struct variable_info *info = variable_index_iterator_current(&iter);
+ 
+ 		if (info->is_variable_set && (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE)) {
+ 
+@@ -799,7 +694,7 @@ static void purge_orphan_index_entries(
+ 			if (psa_status != PSA_SUCCESS) {
+ 
+ 				/* Detected a mismatch between the index and storage */
+-				variable_index_clear_variable(&context->variable_index, info);
++				variable_index_remove_variable(&context->variable_index, info);
+ 				any_orphans = true;
+ 			}
+ 		}
+diff --git a/components/service/smm_variable/backend/variable_index.c b/components/service/smm_variable/backend/variable_index.c
+index a8a55753..99d7c97a 100644
+--- a/components/service/smm_variable/backend/variable_index.c
++++ b/components/service/smm_variable/backend/variable_index.c
+@@ -132,13 +132,13 @@ size_t variable_index_max_dump_size(
+ 	return sizeof(struct variable_metadata) * context->max_variables;
+ }
+ 
+-struct variable_info *variable_index_find(
+-	struct variable_index *context,
++const struct variable_info *variable_index_find(
++	const struct variable_index *context,
+ 	const EFI_GUID *guid,
+ 	size_t name_size,
+ 	const int16_t *name)
+ {
+-	struct variable_info *result = NULL;
++	const struct variable_info *result = NULL;
+ 	int pos = find_variable(context, guid, name_size, name);
+ 
+ 	if (pos >= 0) {
+@@ -149,13 +149,13 @@ struct variable_info *variable_index_find(
+ 	return result;
+ }
+ 
+-struct variable_info *variable_index_find_next(
++const struct variable_info *variable_index_find_next(
+ 	const struct variable_index *context,
+ 	const EFI_GUID *guid,
+ 	size_t name_size,
+ 	const int16_t *name)
+ {
+-	struct variable_info *result = NULL;
++	const struct variable_info *result = NULL;
+ 
+ 	if (name_size >= sizeof(int16_t)) {
+ 
+@@ -263,11 +263,12 @@ static struct variable_entry *add_entry(
+ 	return entry;
+ }
+ 
+-struct variable_info *variable_index_add_entry(
++const struct variable_info *variable_index_add_variable(
+ 	struct variable_index *context,
+ 	const EFI_GUID *guid,
+ 	size_t name_size,
+-	const int16_t *name)
++	const int16_t *name,
++	uint32_t attributes)
+ {
+ 	struct variable_info *info = NULL;
+ 	struct variable_entry *entry = add_entry(context, guid, name_size, name);
+@@ -275,41 +276,40 @@ struct variable_info *variable_index_add_entry(
+ 	if (entry) {
+ 
+ 		info = &entry->info;
++
++		info->metadata.attributes = attributes;
++		info->is_variable_set = true;
++
++		mark_dirty(entry);
+ 	}
+ 
+ 	return info;
+ }
+ 
+-void variable_index_remove_unused_entry(
++const struct variable_info *variable_index_add_constraints(
+ 	struct variable_index *context,
+-	struct variable_info *info)
++	const EFI_GUID *guid,
++	size_t name_size,
++	const int16_t *name,
++	const struct variable_constraints *constraints)
+ {
+-	if (info &&
+-		!info->is_constraints_set &&
+-		!info->is_variable_set) {
+-
+-		struct variable_entry *entry = containing_entry(info);
+-		entry->in_use = false;
++	struct variable_info *info = NULL;
++	struct variable_entry *entry = add_entry(context, guid, name_size, name);
+ 
+-		memset(info, 0, sizeof(struct variable_info));
+-	}
+-}
++	if (entry) {
+ 
+-void variable_index_set_variable(
+-	struct variable_info *info,
+-	uint32_t attributes)
+-{
+-	struct variable_entry *entry = containing_entry(info);
++		info = &entry->info;
+ 
+-	info->metadata.attributes = attributes;
+-	info->is_variable_set = true;
++		info->check_constraints = *constraints;
++		info->is_constraints_set = true;
++	}
+ 
+-	mark_dirty(entry);
++	return info;
+ }
+ 
+-void variable_index_clear_variable(
++void variable_index_remove_variable(
+ 	struct variable_index *context,
+-	struct variable_info *info)
++	const struct variable_info *info)
+ {
+ 	if (info) {
+ 
+@@ -318,17 +318,48 @@ void variable_index_clear_variable(
+ 
+ 		/* Mark variable as no longer set */
+ 		entry->info.is_variable_set = false;
++
++		/* Entry may still be needed if check constraints were set */
++		entry->in_use = info->is_constraints_set;
++
++		if (!entry->in_use) {
++
++			/* Entry not needed so wipe */
++			memset(&entry->info, 0, sizeof(struct variable_info));
++		}
+ 	}
+ }
+ 
+-void variable_index_set_constraints(
+-	struct variable_info *info,
++void variable_index_update_variable(
++	const struct variable_info *info,
++	uint32_t attributes)
++{
++	if (info) {
++
++		struct variable_info *modified_info = (struct variable_info*)info;
++		struct variable_entry *entry = containing_entry(modified_info);
++
++		if (!modified_info->is_variable_set ||
++			(attributes != modified_info->metadata.attributes)) {
++
++			/* The update changes the variable_info state */
++			modified_info->is_variable_set = true;
++			modified_info->metadata.attributes = attributes;
++			mark_dirty(entry);
++		}
++	}
++}
++
++void variable_index_update_constraints(
++	const struct variable_info *info,
+ 	const struct variable_constraints *constraints)
+ {
+ 	if (info) {
+ 
+-		info->check_constraints = *constraints;
+-		info->is_constraints_set = true;
++		struct variable_info *modified_info = (struct variable_info*)info;
++
++		modified_info->check_constraints = *constraints;
++		modified_info->is_constraints_set = true;
+ 	}
+ }
+ 
+diff --git a/components/service/smm_variable/backend/variable_index.h b/components/service/smm_variable/backend/variable_index.h
+index 63f42ab6..e109d0d1 100644
+--- a/components/service/smm_variable/backend/variable_index.h
++++ b/components/service/smm_variable/backend/variable_index.h
+@@ -119,8 +119,8 @@ size_t variable_index_max_dump_size(
+  *
+  * @return     Pointer to variable_info or NULL
+  */
+-struct variable_info *variable_index_find(
+-	struct variable_index *context,
++const struct variable_info *variable_index_find(
++	const struct variable_index *context,
+ 	const EFI_GUID *guid,
+ 	size_t name_size,
+ 	const int16_t *name);
+@@ -135,76 +135,78 @@ struct variable_info *variable_index_find(
+  *
+  * @return     Pointer to variable_info or NULL
+  */
+-struct variable_info *variable_index_find_next(
++const struct variable_info *variable_index_find_next(
+ 	const struct variable_index *context,
+ 	const EFI_GUID *guid,
+ 	size_t name_size,
+ 	const int16_t *name);
+ 
+ /**
+- * @brief      Add a new entry to the index
+- *
+- * An entry is needed either when a new variable is created or
+- * when variable constraints are set for a variable that doesn't
+- * yet exist.
++ * @brief      Add a new variable to the index
+  *
+  * @param[in]  context variable_index
+  * @param[in]  guid The variable's guid
+  * @param[in]  name_size The name parameter's size
+  * @param[in]  name The variable's name
++ * @param[in]  attributes The variable's attributes
+  *
+  * @return     Pointer to variable_info or NULL
+  */
+-struct variable_info *variable_index_add_entry(
++const struct variable_info *variable_index_add_variable(
+ 	struct variable_index *context,
+ 	const EFI_GUID *guid,
+ 	size_t name_size,
+-	const int16_t *name);
++	const int16_t *name,
++	uint32_t attributes);
+ 
+ /**
+- * @brief      Remove an unused entry from the index
++ * @brief      Remove a variable from the index
+  *
+- * Removes an entry if it is not in use.
++ * Removes a variable from the index if it exists.
+  *
+  * @param[in]  context variable_index
+  * @param[in]  info The variable info corresponding to the entry to remove
+  */
+-void variable_index_remove_unused_entry(
++void variable_index_remove_variable(
+ 	struct variable_index *context,
+-	struct variable_info *info);
++	const struct variable_info *info);
+ 
+ /**
+- * @brief      Set a variable to the index
+- *
+- * An entry for the variable must already exist.
++ * @brief      Update a variable that's already in the index
+  *
+  * @param[in]  info variable info
+  * @param[in]  attributes The variable's attributes
+  */
+-void variable_index_set_variable(
+-	struct variable_info *info,
++void variable_index_update_variable(
++	const struct variable_info *info,
+ 	uint32_t attributes);
+ 
+ /**
+- * @brief      Clear a variable from the index
+- *
+- * Clears a variable from the index
++ * @brief      Add a new check constraints object to the index
+  *
+  * @param[in]  context variable_index
+- * @param[in]  info The variable info corresponding to the variable to clear
++ * @param[in]  guid The variable's guid
++ * @param[in]  name_size The name parameter's size
++ * @param[in]  name The variable's name
++ * @param[in]  constraints The check constraints
++ *
++ * @return     Pointer to variable_info or NULL
+  */
+-void variable_index_clear_variable(
++const struct variable_info *variable_index_add_constraints(
+ 	struct variable_index *context,
+-	struct variable_info *info);
++	const EFI_GUID *guid,
++	size_t name_size,
++	const int16_t *name,
++	const struct variable_constraints *constraints);
+ 
+ /**
+- * @brief      Set a check constraints object associated with a variavle
++ * @brief      Update variable constraints that are already in the index
+  *
+  * @param[in]  info variable info
+  * @param[in]  constraints The check constraints
+  */
+-void variable_index_set_constraints(
+-	struct variable_info *info,
++void variable_index_update_constraints(
++	const struct variable_info *info,
+ 	const struct variable_constraints *constraints);
+ 
+ /**
+diff --git a/components/service/smm_variable/backend/variable_index_iterator.c b/components/service/smm_variable/backend/variable_index_iterator.c
+index 8f8fc741..7cc6dc7a 100644
+--- a/components/service/smm_variable/backend/variable_index_iterator.c
++++ b/components/service/smm_variable/backend/variable_index_iterator.c
+@@ -31,10 +31,10 @@ bool variable_index_iterator_is_done(
+ 	return iter->current_pos >= iter->variable_index->max_variables;
+ }
+ 
+-struct variable_info *variable_index_iterator_current(
++const struct variable_info *variable_index_iterator_current(
+ 	const struct variable_index_iterator *iter)
+ {
+-	struct variable_info *current = NULL;
++	const struct variable_info *current = NULL;
+ 
+ 	if (!variable_index_iterator_is_done(iter)) {
+ 
+diff --git a/components/service/smm_variable/backend/variable_index_iterator.h b/components/service/smm_variable/backend/variable_index_iterator.h
+index 7ff77c50..f64a2c49 100644
+--- a/components/service/smm_variable/backend/variable_index_iterator.h
++++ b/components/service/smm_variable/backend/variable_index_iterator.h
+@@ -54,7 +54,7 @@ bool variable_index_iterator_is_done(
+  *
+  * @return     Pointer to variable_info or NULL
+  */
+-struct variable_info *variable_index_iterator_current(
++const struct variable_info *variable_index_iterator_current(
+ 	const struct variable_index_iterator *iter);
+ 
+ /**
+diff --git a/components/service/smm_variable/test/service/smm_variable_service_tests.cpp b/components/service/smm_variable/test/service/smm_variable_service_tests.cpp
+index 15556e9d..38c08ebe 100644
+--- a/components/service/smm_variable/test/service/smm_variable_service_tests.cpp
++++ b/components/service/smm_variable/test/service/smm_variable_service_tests.cpp
+@@ -249,30 +249,6 @@ TEST(SmmVariableServiceTests, setAndGet)
+ 	UNSIGNED_LONGS_EQUAL(set_data.size(), get_data.size());
+ 	LONGS_EQUAL(0, get_data.compare(set_data));
+ 
+-	/* Extend the variable using an append write */
+-	std::string append_data = " values added with append write";
+-
+-	efi_status = m_client->set_variable(
+-		m_common_guid,
+-		var_name,
+-		append_data,
+-		EFI_VARIABLE_APPEND_WRITE);
+-
+-	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
+-
+-	efi_status = m_client->get_variable(
+-		m_common_guid,
+-		var_name,
+-		get_data);
+-
+-	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
+-
+-	std::string appended_data = set_data + append_data;
+-
+-	/* Expect the append write operation to have extended the variable */
+-	UNSIGNED_LONGLONGS_EQUAL(appended_data.size(), get_data.size());
+-	LONGS_EQUAL(0, appended_data.compare(get_data));
+-
+ 	/* Expect remove to be permitted */
+ 	efi_status = m_client->remove_variable(m_common_guid, var_name);
+ 	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
+@@ -303,30 +279,6 @@ TEST(SmmVariableServiceTests, setAndGetNv)
+ 	UNSIGNED_LONGS_EQUAL(set_data.size(), get_data.size());
+ 	LONGS_EQUAL(0, get_data.compare(set_data));
+ 
+-	/* Extend the variable using an append write */
+-	std::string append_data = " values added with append write";
+-
+-	efi_status = m_client->set_variable(
+-		m_common_guid,
+-		var_name,
+-		append_data,
+-		EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_APPEND_WRITE);
+-
+-	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
+-
+-	efi_status = m_client->get_variable(
+-		m_common_guid,
+-		var_name,
+-		get_data);
+-
+-	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
+-
+-	std::string appended_data = set_data + append_data;
+-
+-	/* Expect the append write operation to have extended the variable */
+-	UNSIGNED_LONGLONGS_EQUAL(appended_data.size(), get_data.size());
+-	LONGS_EQUAL(0, appended_data.compare(get_data));
+-
+ 	/* Expect remove to be permitted */
+ 	efi_status = m_client->remove_variable(m_common_guid, var_name);
+ 	UNSIGNED_LONGLONGS_EQUAL(EFI_SUCCESS, efi_status);
+diff --git a/protocols/service/smm_variable/parameters.h b/protocols/service/smm_variable/parameters.h
+index 233f301b..1f795a9b 100644
+--- a/protocols/service/smm_variable/parameters.h
++++ b/protocols/service/smm_variable/parameters.h
+@@ -47,9 +47,6 @@ typedef struct {
+ 	 EFI_VARIABLE_HARDWARE_ERROR_RECORD | \
+ 	 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
+ 	 EFI_VARIABLE_APPEND_WRITE)
+-#define	EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS_MASK \
+-	(EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
+-	 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
+ 
+ /**
+  * Parameter structure for SetVariable and GetVariable.
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0029-Change-UID-of-variable-index-in-SMM.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0029-Change-UID-of-variable-index-in-SMM.patch
new file mode 100644
index 0000000..caa1d9a
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0029-Change-UID-of-variable-index-in-SMM.patch
@@ -0,0 +1,31 @@
+From 12e9b977e4c7515ce90fecc62630be394fd7da62 Mon Sep 17 00:00:00 2001
+From: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+Date: Mon, 20 Dec 2021 19:54:39 +0000
+Subject: [PATCH] Change UID of variable index in SMM
+
+This patch fixes the os_indications setVariable() failure. The variable
+index UID in SMM gateway which was 1 is changed in this patch. TFM has a
+special usage for variable with UID 1, which makes it write once only.
+This is not required for SMM variable index.
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+
+
+---
+ components/service/smm_variable/backend/uefi_variable_store.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/components/service/smm_variable/backend/uefi_variable_store.c b/components/service/smm_variable/backend/uefi_variable_store.c
+index 6a90f46a..1bb869ae 100644
+--- a/components/service/smm_variable/backend/uefi_variable_store.c
++++ b/components/service/smm_variable/backend/uefi_variable_store.c
+@@ -67,7 +67,7 @@ static efi_status_t check_name_terminator(
+ 	size_t name_size);
+ 
+ /* Private UID for storing the variable index */
+-#define VARIABLE_INDEX_STORAGE_UID			(1)
++#define VARIABLE_INDEX_STORAGE_UID			(0x787)
+ 
+ /* Default maximum variable size -
+  * may be overridden using uefi_variable_store_set_storage_limits()
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0030-Add-missing-features-to-setVariable.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0030-Add-missing-features-to-setVariable.patch
new file mode 100644
index 0000000..244146a
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0030-Add-missing-features-to-setVariable.patch
@@ -0,0 +1,73 @@
+From 55fc3dbfb0ec21b1239808d0dddae14fbb8bb5f3 Mon Sep 17 00:00:00 2001
+From: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+Date: Mon, 20 Dec 2021 19:56:30 +0000
+Subject: [PATCH] Add missing features to setVariable()
+
+This patch resolves the failing tests in SCT related to
+setVariable() function. The existing implementation is
+missing few cases where error codes are returned when called
+with certain paramters. These conditions are implemented in
+this patch based on the explanation provided in uefi spec.
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+
+
+---
+ .../backend/uefi_variable_store.c             | 29 ++++++++++++++++---
+ 1 file changed, 25 insertions(+), 4 deletions(-)
+
+diff --git a/components/service/smm_variable/backend/uefi_variable_store.c b/components/service/smm_variable/backend/uefi_variable_store.c
+index 1bb869ae..a1671074 100644
+--- a/components/service/smm_variable/backend/uefi_variable_store.c
++++ b/components/service/smm_variable/backend/uefi_variable_store.c
+@@ -161,6 +161,17 @@ efi_status_t uefi_variable_store_set_variable(
+ 	bool should_sync_index = false;
+ 
+ 	if (status != EFI_SUCCESS) return status;
++	
++	/*
++	* Runtime access to a data variable implies boot service access. Attributes that have
++	* EFI_VARIABLE_RUNTIME_ACCESS set must also have EFI_VARIABLE_BOOTSERVICE_ACCESS set.
++	* The caller is responsible for following this rule.
++	*/
++	if((var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))
++	{
++			if((var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) != EFI_VARIABLE_BOOTSERVICE_ACCESS )
++			return EFI_INVALID_PARAMETER;
++	}
+ 
+ 	/* Find in index */
+ 	const struct variable_info *info = variable_index_find(
+@@ -221,6 +232,13 @@ efi_status_t uefi_variable_store_set_variable(
+ 		if (!info) status = EFI_OUT_OF_RESOURCES;
+ 		should_sync_index = info && (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE);
+ 	}
++	else 
++    {
++		/* Return EFI_NOT_FOUND when a remove operation is performed
++		 * on variable that is not existing.
++		*/
++        status = EFI_NOT_FOUND;
++    }
+ 
+ 	/* The order of these operations is important. For an update
+ 	 * or create operation, The variable index is always synchronized
+@@ -555,10 +573,13 @@ static efi_status_t check_access_permitted_on_set(
+ 	if ((status == EFI_SUCCESS) && var->DataSize) {
+ 
+ 		/* Restrict which attributes can be modified for an existing variable */
+-		if ((var->Attributes & EFI_VARIABLE_NON_VOLATILE) !=
+-			(info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE)) {
+-
+-			/* Don't permit change of storage class */
++        if (((var->Attributes & EFI_VARIABLE_NON_VOLATILE) !=
++            (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE)) ||
++            ((var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) !=
++            (info->metadata.attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)) ||
++            ((var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) !=
++            (info->metadata.attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {
++			/* Don't permit change of attributes */
+ 			status = EFI_INVALID_PARAMETER;
+ 		}
+ 	}
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0031-Add-invalid-parameter-check-in-getNextVariableName.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0031-Add-invalid-parameter-check-in-getNextVariableName.patch
new file mode 100644
index 0000000..3990d82
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0031-Add-invalid-parameter-check-in-getNextVariableName.patch
@@ -0,0 +1,55 @@
+From dc3f134436ad6852f1bad9542232e84166843a7e Mon Sep 17 00:00:00 2001
+From: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+Date: Mon, 20 Dec 2021 20:01:10 +0000
+Subject: [PATCH] Add invalid parameter check in getNextVariableName()
+
+This patch resolves the failing tests in SCT related to
+getNextVariableName() function. The existing implementation is
+missing few cases where error codes are returned when called
+with certain paramters. These conditions are implemented in
+this patch based on the explanation provided in uefi spec.
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Gowtham Suresh Kumar <gowtham.sureshkumar@arm.com>
+
+
+---
+ .../smm_variable/backend/uefi_variable_store.c | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/components/service/smm_variable/backend/uefi_variable_store.c b/components/service/smm_variable/backend/uefi_variable_store.c
+index a1671074..a57b3346 100644
+--- a/components/service/smm_variable/backend/uefi_variable_store.c
++++ b/components/service/smm_variable/backend/uefi_variable_store.c
+@@ -161,7 +161,7 @@ efi_status_t uefi_variable_store_set_variable(
+ 	bool should_sync_index = false;
+ 
+ 	if (status != EFI_SUCCESS) return status;
+-	
++
+ 	/*
+ 	* Runtime access to a data variable implies boot service access. Attributes that have
+ 	* EFI_VARIABLE_RUNTIME_ACCESS set must also have EFI_VARIABLE_BOOTSERVICE_ACCESS set.
+@@ -310,6 +310,22 @@ efi_status_t uefi_variable_store_get_next_variable_name(
+ 	status = EFI_NOT_FOUND;
+ 	*total_length = 0;
+ 
++	/*
++	 *	If input values of VariableName and VendorGuid are not a name and GUID of an 
++	 *	existing variable, EFI_INVALID_PARAMETER is returned.	
++	 */
++	if (cur->NameSize >= sizeof(int16_t)) {
++		/*
++		* Name must be at least one character long to accommodate
++		* the mandatory null terminator.
++		*/
++		if (cur->Name[0] != 0) {
++			const struct variable_info *var_info = variable_index_find(&context->variable_index,&cur->Guid,cur->NameSize,cur->Name);
++			if(var_info == NULL)
++					return EFI_INVALID_PARAMETER;
++		}
++	}
++
+ 	const struct variable_info *info = variable_index_find_next(
+ 		&context->variable_index,
+ 		&cur->Guid,
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0032-smm_gateway-add-checks-for-null-attributes.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0032-smm_gateway-add-checks-for-null-attributes.patch
new file mode 100644
index 0000000..da3ddaf
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0032-smm_gateway-add-checks-for-null-attributes.patch
@@ -0,0 +1,81 @@
+From 571ddac16048dfba4b25b04fe5cbd706c392b5ba Mon Sep 17 00:00:00 2001
+From: Vishnu Banavath <vishnu.banavath@arm.com>
+Date: Fri, 24 Dec 2021 19:17:17 +0000
+Subject: [PATCH] smm_gateway: add checks for null attributes
+
+As par EDK-2 and EDK-2 test code, when a user issue's
+setVariable() with 0 in attributes field, it means a variable
+delete request. Currently, smm gatway doesn't handle this scenario.
+This change is to add that support
+
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Vishnu Banavath <vishnu.banavath@arm.com>
+
+
+---
+ .../backend/uefi_variable_store.c             | 28 ++++++++++++-------
+ 1 file changed, 18 insertions(+), 10 deletions(-)
+
+diff --git a/components/service/smm_variable/backend/uefi_variable_store.c b/components/service/smm_variable/backend/uefi_variable_store.c
+index a57b3346..e8771c21 100644
+--- a/components/service/smm_variable/backend/uefi_variable_store.c
++++ b/components/service/smm_variable/backend/uefi_variable_store.c
+@@ -167,7 +167,9 @@ efi_status_t uefi_variable_store_set_variable(
+ 	* EFI_VARIABLE_RUNTIME_ACCESS set must also have EFI_VARIABLE_BOOTSERVICE_ACCESS set.
+ 	* The caller is responsible for following this rule.
+ 	*/
+-	if((var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))
++	if (!var->Attributes)
++		EMSG("It might be a delete variable request\n");
++	else if((var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))
+ 	{
+ 			if((var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) != EFI_VARIABLE_BOOTSERVICE_ACCESS )
+ 			return EFI_INVALID_PARAMETER;
+@@ -191,7 +193,7 @@ efi_status_t uefi_variable_store_set_variable(
+ 				(var->Attributes & EFI_VARIABLE_NON_VOLATILE) ||
+ 				(info->is_variable_set && (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE));
+ 
+-			if (var->DataSize) {
++			if (var->DataSize && var->Attributes) {
+ 
+ 				/* It's a set rather than a remove operation */
+ 				variable_index_update_variable(
+@@ -206,7 +208,9 @@ efi_status_t uefi_variable_store_set_variable(
+ 				 * that it's never possible for an object to exist within
+ 				 * the storage backend without a corresponding index entry.
+ 				 */
+-				remove_variable_data(context, info);
++				EMSG("  deleting variable %s \n",var->Name);
++				if (remove_variable_data(context, info) != PSA_SUCCESS)
++					EMSG("  deleting variable %s FAILED\n",var->Name);
+ 				variable_index_remove_variable(&context->variable_index, info);
+ 
+ 				/* Variable info no longer valid */
+@@ -587,14 +591,18 @@ static efi_status_t check_access_permitted_on_set(
+ 	}
+ 
+ 	if ((status == EFI_SUCCESS) && var->DataSize) {
+-
++		/* Delete the variable with Attributes is 0 */
++		if (!var->Attributes) {
++			EMSG("Null attributes, may be a delete variable request\n");
++			status = EFI_SUCCESS;
++		}
+ 		/* Restrict which attributes can be modified for an existing variable */
+-        if (((var->Attributes & EFI_VARIABLE_NON_VOLATILE) !=
+-            (info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE)) ||
+-            ((var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) !=
+-            (info->metadata.attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)) ||
+-            ((var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) !=
+-            (info->metadata.attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {
++		else if (((var->Attributes & EFI_VARIABLE_NON_VOLATILE) !=
++			(info->metadata.attributes & EFI_VARIABLE_NON_VOLATILE)) ||
++			((var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) !=
++			(info->metadata.attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)) ||
++			((var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) !=
++			(info->metadata.attributes & EFI_VARIABLE_RUNTIME_ACCESS))) {
+ 			/* Don't permit change of attributes */
+ 			status = EFI_INVALID_PARAMETER;
+ 		}
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0033-Enhance-mbedtls-fetch-process.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0033-Enhance-mbedtls-fetch-process.patch
new file mode 100644
index 0000000..02130b5
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0033-Enhance-mbedtls-fetch-process.patch
@@ -0,0 +1,258 @@
+From 47db072e9ec749c6be7c0a27d64d7fbd75748d60 Mon Sep 17 00:00:00 2001
+From: Gyorgy Szing <Gyorgy.Szing@arm.com>
+Date: Wed, 8 Dec 2021 04:20:34 +0100
+Subject: [PATCH] Enhance mbedtls fetch process
+
+Update management of MbedTLS external component to be optimized
+for download speed insted of availability.
+The updated process is:
+  - check if binary is available. If yes configure build to use it
+    and stop.
+  - if not, check is source is available. If yes, build it and use
+    the resulting binary.
+  - if not, then download the source using git, compile it and use
+    the resulting binary
+
+The following variables can be set on the command line to alter the
+behavior of the module:
+  - MBEDTLS_URL git repo URL to fetch from.
+  - MBEDTLS_REFSPEC revision to fetch
+  - MBEDTLS_SOURCE_DIR to specify location of source code in
+    local file syetem.
+  - MBEDTLS_INSTALL_DIR to specify location of binary.
+
+I.e. cmake -S <...> -B <...> -DMBEDTLS_INSTALL_DIR=~/mbedtls
+will make the resulting binary installed to ~/mbedtls. This can be
+used later to speed up a clean build an use the prebuilt binary.
+
+Change-Id: I8a9ad8b3303e6dfa0a7c9c3d7e4b4787b94d925a
+Signed-off-by: Gyorgy Szing <Gyorgy.Szing@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ external/MbedTLS/MbedTLS.cmake | 192 ++++++++++++++++++++-------------
+ 1 file changed, 119 insertions(+), 73 deletions(-)
+
+diff --git a/external/MbedTLS/MbedTLS.cmake b/external/MbedTLS/MbedTLS.cmake
+index 3cbaed15..935be765 100644
+--- a/external/MbedTLS/MbedTLS.cmake
++++ b/external/MbedTLS/MbedTLS.cmake
+@@ -1,96 +1,142 @@
+ #-------------------------------------------------------------------------------
+-# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++# Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+ #
+ # SPDX-License-Identifier: BSD-3-Clause
+ #
+ #-------------------------------------------------------------------------------
+ 
+-# Determine the number of processes to run while running parallel builds.
+-# Pass -DPROCESSOR_COUNT=<n> to cmake to override.
+-if(NOT DEFINED PROCESSOR_COUNT)
+-	include(ProcessorCount)
+-	ProcessorCount(PROCESSOR_COUNT)
+-	set(PROCESSOR_COUNT ${PROCESSOR_COUNT} CACHE STRING "Number of cores to use for parallel builds.")
+-endif()
++set(MBEDTLS_URL "https://github.com/ARMmbed/mbedtls.git"
++		CACHE STRING "Mbed TLS repository URL")
++set(MBEDTLS_REFSPEC "mbedtls-3.0.0"
++		CACHE STRING "Mbed TLS git refspec")
++set(MBEDTLS_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_deps/mbedtls-src"
++		CACHE PATH "MbedTLS source directory")
++set(MBEDTLS_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/mbedtls_install"
++		CACHE PATH "Mbed TLS installation directory")
+ 
+-set(MBEDTLS_URL "https://github.com/ARMmbed/mbedtls.git" CACHE STRING "Mbed TLS repository URL")
+-set(MBEDTLS_REFSPEC "mbedtls-3.0.0" CACHE STRING "Mbed TLS git refspec")
+-set(MBEDTLS_INSTALL_PATH "${CMAKE_CURRENT_BINARY_DIR}/mbedtls_install" CACHE PATH "Mbed TLS installation directory")
+-set(MBEDTLS_PACKAGE_PATH "${MBEDTLS_INSTALL_PATH}/lib/mbedtls/cmake" CACHE PATH "Mbed TLS CMake package directory")
++find_library(MBEDCRYPTO_LIB_FILE
++				NAMES libmbedcrypto.a mbedcrypto.a libmbedcrypto.lib mbedcrypto.lib
++				PATHS ${MBEDTLS_INSTALL_DIR}
++				PATH_SUFFIXES "lib"
++				DOC "Location of mberdrypto library."
++				NO_DEFAULT_PATH
++)
+ 
+-include(FetchContent)
++set(MBEDCRYPTO_LIB_FILE ${MBEDCRYPTO_LIB_FILE})
++unset(MBEDCRYPTO_LIB_FILE CACHE)
+ 
+-# Checking git
+-find_program(GIT_COMMAND "git")
+-if (NOT GIT_COMMAND)
+-	message(FATAL_ERROR "Please install git")
+-endif()
++set(MBEDTLS_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/_deps/mbedtls-build")
+ 
+-# Fetching Mbed TLS
+-FetchContent_Declare(
+-	mbedtls
+-	GIT_REPOSITORY ${MBEDTLS_URL}
+-	GIT_TAG ${MBEDTLS_REFSPEC}
+-	GIT_SHALLOW TRUE
+-)
++# Binary not found and it needs to be built.
++if (NOT MBEDCRYPTO_LIB_FILE)
++	# Determine the number of processes to run while running parallel builds.
++	# Pass -DPROCESSOR_COUNT=<n> to cmake to override.
++	if(NOT DEFINED PROCESSOR_COUNT)
++		include(ProcessorCount)
++		ProcessorCount(PROCESSOR_COUNT)
++		set(PROCESSOR_COUNT ${PROCESSOR_COUNT}
++				CACHE STRING "Number of cores to use for parallel builds.")
++	endif()
+ 
+-# FetchContent_GetProperties exports mbedtls_SOURCE_DIR and mbedtls_BINARY_DIR variables
+-FetchContent_GetProperties(mbedtls)
+-if(NOT mbedtls_POPULATED)
+-	message(STATUS "Fetching Mbed TLS")
+-	FetchContent_Populate(mbedtls)
+-endif()
++	# See if the source is available locally
++	find_file(MBEDCRYPTO_HEADER_FILE
++		NAMES crypto.h
++		PATHS ${MBEDTLS_SOURCE_DIR}
++		PATH_SUFFIXES "include/psa"
++		NO_DEFAULT_PATH
++	)
++	set(MBEDCRYPTO_HEADER_FILE ${MBEDCRYPTO_HEADER_FILE})
++	unset(MBEDCRYPTO_HEADER_FILE CACHE)
+ 
+-# Convert the include path list to a string. Needed to make parameter passing to
+-# Mbed TLS build work fine.
+-string(REPLACE ";" "\\;" MBEDTLS_EXTRA_INCLUDES "${MBEDTLS_EXTRA_INCLUDES}")
++	# Source not found, fetch it.
++	if (NOT MBEDCRYPTO_HEADER_FILE)
++		include(FetchContent)
+ 
+-find_package(Python3 COMPONENTS Interpreter)
+-if (NOT Python3_Interpreter_FOUND)
+-	message(FATAL_ERROR "Python 3 interpreter not found.")
+-endif()
++		# Checking git
++		find_program(GIT_COMMAND "git")
++		if (NOT GIT_COMMAND)
++			message(FATAL_ERROR "Please install git")
++		endif()
+ 
+-#Configure Mbed TLS to build only mbedcrypto lib
+-execute_process(COMMAND ${Python3_EXECUTABLE} scripts/config.py crypto WORKING_DIRECTORY ${mbedtls_SOURCE_DIR})
+-
+-# Advertise Mbed TLS as the provider of the psa crypto API
+-set(PSA_CRYPTO_API_INCLUDE "${MBEDTLS_INSTALL_PATH}/include" CACHE STRING "PSA Crypto API include path")
+-
+-#Configure the library
+-execute_process(COMMAND
+-	${CMAKE_COMMAND}
+-		-DENABLE_PROGRAMS=OFF
+-		-DENABLE_TESTING=OFF
+-		-DUNSAFE_BUILD=ON
+-		-DCMAKE_INSTALL_PREFIX=${MBEDTLS_INSTALL_PATH}
+-		-DCMAKE_TOOLCHAIN_FILE=${TS_EXTERNAL_LIB_TOOLCHAIN_FILE}
+-		-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY
+-		-DEXTERNAL_DEFINITIONS=-DMBEDTLS_USER_CONFIG_FILE="${MBEDTLS_USER_CONFIG_FILE}"
+-		-DEXTERNAL_INCLUDE_PATHS=${MBEDTLS_EXTRA_INCLUDES}
+-		-GUnix\ Makefiles
+-		${mbedtls_SOURCE_DIR}
+-	WORKING_DIRECTORY
+-		${mbedtls_BINARY_DIR}
+-	RESULT_VARIABLE _exec_error
+-)
++		# Fetching Mbed TLS
++		FetchContent_Declare(
++			mbedtls
++			SOURCE_DIR ${MBEDTLS_SOURCE_DIR}
++			BINARY_DIR ${MBEDTLS_BINARY_DIR}
++			GIT_REPOSITORY ${MBEDTLS_URL}
++			GIT_TAG ${MBEDTLS_REFSPEC}
++			GIT_SHALLOW TRUE
++		)
+ 
+-if (_exec_error)
+-	message(FATAL_ERROR "Configuration step of Mbed TLS failed with ${_exec_error}.")
+-endif()
++		# FetchContent_GetProperties exports mbedtls_SOURCE_DIR and mbedtls_BINARY_DIR variables
++		FetchContent_GetProperties(mbedtls)
++		# FetchContent_Populate will fail if the source directory is removed since it will try to
++		# do an "update" and not a "populate" action. As a workaround, remove the subbuild directory.
++		# Note: this fix assumes, the default subbuild location is used.
++		file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/_deps/mbedtls-subbuild")
++
++		# If the source directory has been moved, the binary dir must be regenerated from scratch.
++		file(REMOVE_RECURSE "${MBEDTLS_BINARY_DIR}")
+ 
+-#TODO: add dependency to generated project on this file!
+-#TODO: add custom target to rebuild Mbed TLS
++		if (NOT mbedtls_POPULATED)
++			message(STATUS "Fetching Mbed TLS")
++			FetchContent_Populate(mbedtls)
++		endif()
++		set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${MBEDTLS_SOURCE_DIR})
++	endif()
+ 
+-#Build the library
+-execute_process(COMMAND
+-		${CMAKE_COMMAND} --build ${mbedtls_BINARY_DIR} --parallel ${PROCESSOR_COUNT} --target install
++	# Build mbedcrypto library
++
++	# Convert the include path list to a string. Needed to make parameter passing to
++	# Mbed TLS build work fine.
++	string(REPLACE ";" "\\;" MBEDTLS_EXTRA_INCLUDES "${MBEDTLS_EXTRA_INCLUDES}")
++
++	find_package(Python3 REQUIRED COMPONENTS Interpreter)
++
++	#Configure Mbed TLS to build only mbedcrypto lib
++	execute_process(COMMAND ${Python3_EXECUTABLE} scripts/config.py crypto WORKING_DIRECTORY ${MBEDTLS_SOURCE_DIR})
++
++	# Advertise Mbed TLS as the provider of the psa crypto API
++	set(PSA_CRYPTO_API_INCLUDE "${MBEDTLS_INSTALL_DIR}/include" CACHE STRING "PSA Crypto API include path")
++
++	#Configure the library
++	execute_process(COMMAND
++		${CMAKE_COMMAND} -E env CROSS_COMPILE=${CROSS_COMPILE}
++			${CMAKE_COMMAND}
++				-DENABLE_PROGRAMS=OFF
++				-DENABLE_TESTING=OFF
++				-DUNSAFE_BUILD=ON
++				-DCMAKE_INSTALL_PREFIX=${MBEDTLS_INSTALL_DIR}
++				-DCMAKE_TOOLCHAIN_FILE=${TS_EXTERNAL_LIB_TOOLCHAIN_FILE}
++				-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY
++				-DEXTERNAL_DEFINITIONS=-DMBEDTLS_USER_CONFIG_FILE="${MBEDTLS_USER_CONFIG_FILE}"
++				-DEXTERNAL_INCLUDE_PATHS=${MBEDTLS_EXTRA_INCLUDES}
++				-GUnix\ Makefiles
++				${MBEDTLS_SOURCE_DIR}
++		WORKING_DIRECTORY
++			${MBEDTLS_BINARY_DIR}
+ 		RESULT_VARIABLE _exec_error
+ 	)
+-if (_exec_error)
+-	message(FATAL_ERROR "Build step of Mbed TLS failed with ${_exec_error}.")
++
++	if (_exec_error)
++		message(FATAL_ERROR "Configuration step of Mbed TLS failed with ${_exec_error}.")
++	endif()
++
++	#Build the library
++	execute_process(COMMAND
++			${CMAKE_COMMAND} --build ${MBEDTLS_BINARY_DIR} --parallel ${PROCESSOR_COUNT} --target install
++			RESULT_VARIABLE _exec_error
++		)
++
++	if (_exec_error)
++		message(FATAL_ERROR "Build step of Mbed TLS failed with ${_exec_error}.")
++	endif()
++
++	set(MBEDCRYPTO_LIB_FILE "${MBEDTLS_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}mbedcrypto${CMAKE_STATIC_LIBRARY_SUFFIX}")
+ endif()
+ 
+ #Create an imported target to have clean abstraction in the build-system.
+ add_library(mbedcrypto STATIC IMPORTED)
+-set_property(TARGET mbedcrypto PROPERTY IMPORTED_LOCATION "${MBEDTLS_INSTALL_PATH}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}mbedcrypto${CMAKE_STATIC_LIBRARY_SUFFIX}")
+-set_property(TARGET mbedcrypto PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_INSTALL_PATH}/include")
++set_property(DIRECTORY ${CMAKE_SOURCE_DIR} APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${MBEDCRYPTO_LIB_FILE})
++set_property(TARGET mbedcrypto PROPERTY IMPORTED_LOCATION ${MBEDCRYPTO_LIB_FILE})
++set_property(TARGET mbedcrypto PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${MBEDTLS_INSTALL_DIR}/include")
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0034-Fix-format-specifier-in-logging_caller.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0034-Fix-format-specifier-in-logging_caller.patch
new file mode 100644
index 0000000..75fa7c2
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0034-Fix-format-specifier-in-logging_caller.patch
@@ -0,0 +1,41 @@
+From 131bb3c577fff93ff9ba6f5e7d450f727fec0e62 Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Fri, 11 Feb 2022 12:30:45 +0000
+Subject: [PATCH] Fix format specifier in logging_caller
+
+A previous change increased the width of the opstatus value
+returned by an rpc endpoint from 32 to 64 bits. This change
+corrects the printf format specifier in the rpc logging_caller
+that corresponds to logging the opstatus value.
+
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: Ie695a6bf8cf8014317b85196d7b933d344782b2c
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ components/rpc/common/logging/logging_caller.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/components/rpc/common/logging/logging_caller.c b/components/rpc/common/logging/logging_caller.c
+index 07c33de5..cac03f2f 100644
+--- a/components/rpc/common/logging/logging_caller.c
++++ b/components/rpc/common/logging/logging_caller.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -87,7 +87,7 @@ static rpc_status_t call_invoke(void *context, rpc_call_handle handle, uint32_t
+ 
+ 	if (status == TS_RPC_CALL_ACCEPTED) {
+ 
+-		fprintf(this_instance->log_file, "op_status: %d\n", *opstatus);
++		fprintf(this_instance->log_file, "op_status: %ld\n", *opstatus);
+ 		fprintf(this_instance->log_file, "resp_len: %ld\n", *resp_len);
+ 	}
+ 
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0035-Update-refspecs-for-mbedtls-and-psa-arch-tests-for-v.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0035-Update-refspecs-for-mbedtls-and-psa-arch-tests-for-v.patch
new file mode 100644
index 0000000..01b99d3
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0035-Update-refspecs-for-mbedtls-and-psa-arch-tests-for-v.patch
@@ -0,0 +1,64 @@
+From 7aa9796020487ce32746c25934ce20829acc462c Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Fri, 11 Feb 2022 13:42:59 +0000
+Subject: [PATCH] Update refspecs for mbedtls and psa-arch-tests for v3.1.0
+
+Updates external component refspecs to use mbedtls 3.1.0 and
+compatible API tests from psa-arch-test.
+
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: I1b5cebd7de3c1885f5f8a8ea21ba5e4c52aefaf4
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ external/MbedTLS/MbedTLS.cmake               |  2 +-
+ external/psa_arch_tests/psa_arch_tests.cmake | 17 ++++++-----------
+ 2 files changed, 7 insertions(+), 12 deletions(-)
+
+diff --git a/external/MbedTLS/MbedTLS.cmake b/external/MbedTLS/MbedTLS.cmake
+index 935be765..3350d8a0 100644
+--- a/external/MbedTLS/MbedTLS.cmake
++++ b/external/MbedTLS/MbedTLS.cmake
+@@ -7,7 +7,7 @@
+ 
+ set(MBEDTLS_URL "https://github.com/ARMmbed/mbedtls.git"
+ 		CACHE STRING "Mbed TLS repository URL")
+-set(MBEDTLS_REFSPEC "mbedtls-3.0.0"
++set(MBEDTLS_REFSPEC "mbedtls-3.1.0"
+ 		CACHE STRING "Mbed TLS git refspec")
+ set(MBEDTLS_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_deps/mbedtls-src"
+ 		CACHE PATH "MbedTLS source directory")
+diff --git a/external/psa_arch_tests/psa_arch_tests.cmake b/external/psa_arch_tests/psa_arch_tests.cmake
+index e6ab73f7..f6d2fb9f 100644
+--- a/external/psa_arch_tests/psa_arch_tests.cmake
++++ b/external/psa_arch_tests/psa_arch_tests.cmake
+@@ -5,20 +5,15 @@
+ #
+ #-------------------------------------------------------------------------------
+ 
+-# Determine the number of processes to run while running parallel builds.
+-# Pass -DPROCESSOR_COUNT=<n> to cmake to override.
+-if(NOT DEFINED PROCESSOR_COUNT)
+-	include(ProcessorCount)
+-	ProcessorCount(PROCESSOR_COUNT)
+-	set(PROCESSOR_COUNT ${PROCESSOR_COUNT} CACHE STRING "Number of cores to use for parallel builds.")
+-endif()
++# Temporarily using modified tests used for tf-m verification
++set(PSA_ARCH_TESTS_URL "https://github.com/bensze01/psa-arch-tests.git" CACHE STRING "psa-arch-tests repository URL")
++set(PSA_ARCH_TESTS_REFSPEC "fix-multipart-aead" CACHE STRING "psa-arch-tests git refspec")
+ 
+-set(PSA_ARCH_TESTS_URL "https://github.com/ARM-software/psa-arch-tests.git" CACHE STRING "psa-arch-tests repository URL")
+-set(PSA_ARCH_TESTS_REFSPEC "master" CACHE STRING "psa-arch-tests git refspec")
++#set(PSA_ARCH_TESTS_URL "https://github.com/ARM-software/psa-arch-tests.git" CACHE STRING "psa-arch-tests repository URL")
++#set(PSA_ARCH_TESTS_REFSPEC "2a1852252a9b9af655cbe02d5d3c930952d0d798" CACHE STRING "psa-arch-tests v22.01_API1.4_ADAC_BETA")
+ set(PSA_ARCH_TESTS_INSTALL_PATH "${CMAKE_CURRENT_BINARY_DIR}/psa-arch-tests_install" CACHE PATH "psa-arch-tests installation directory")
+ set(PSA_ARCH_TESTS_PACKAGE_PATH "${PSA_ARCH_TESTS_INSTALL_PATH}/libpsa-arch-tests/cmake" CACHE PATH "psa-arch-tests CMake package directory")
+-
+-include(FetchContent)
++set(PSA_ARCH_TESTS_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_deps/psa_arch_tests-src" CACHE PATH "psa-arch-tests source.")
+ 
+ # Checking git
+ find_program(GIT_COMMAND "git")
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0036-Separate-sign-verify-message-and-hash-operations.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0036-Separate-sign-verify-message-and-hash-operations.patch
new file mode 100644
index 0000000..ae78f41
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0036-Separate-sign-verify-message-and-hash-operations.patch
@@ -0,0 +1,1080 @@
+From b160f734006f4959d92377dc3aa8eabc3ac7c1da Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Fri, 11 Feb 2022 14:08:13 +0000
+Subject: [PATCH] Separate sign/verify message and hash operations
+
+Previous versions of mbedtls didn't distinguish between
+asymmetric sign and verify operations on a hash or message.
+They are now treated as separate operations from a usage
+control perspective. This change makes the corresponding
+hash/message sepration in client and service provider
+components.
+
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: Ic0041c694c026522c9b00c974d22261e9e2feadd
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ .../caller/packed-c/crypto_caller_sign_hash.h | 29 +++++++-
+ .../packed-c/crypto_caller_verify_hash.h      | 33 ++++++++-
+ .../caller/stub/crypto_caller_sign_hash.h     | 11 ++-
+ .../caller/stub/crypto_caller_verify_hash.h   | 11 ++-
+ .../service/crypto/client/cpp/crypto_client.h | 17 ++++-
+ .../packed-c/packedc_crypto_client.cpp        | 22 +++++-
+ .../protocol/packed-c/packedc_crypto_client.h | 17 ++++-
+ .../protobuf/protobuf_crypto_client.cpp       | 43 ++++++++++-
+ .../protobuf/protobuf_crypto_client.h         | 27 ++++++-
+ .../crypto/client/psa/psa_sign_message.c      | 24 +++---
+ .../crypto/client/psa/psa_verify_message.c    | 24 +++---
+ .../service/crypto/provider/crypto_provider.c | 40 ++++++----
+ .../serializer/crypto_provider_serializer.h   |  6 +-
+ .../packedc_crypto_provider_serializer.c      | 12 +--
+ .../protobuf/pb_crypto_provider_serializer.c  | 74 +++++++++----------
+ .../check_crypto_opcode_alignment.cpp         | 25 ++++---
+ .../test/service/crypto_service_scenarios.cpp | 56 +++++++++++++-
+ .../test/service/crypto_service_scenarios.h   |  3 +-
+ .../packed-c/crypto_service_packedc_tests.cpp |  7 +-
+ .../crypto_service_protobuf_tests.cpp         |  7 +-
+ protocols/service/crypto/packed-c/opcodes.h   |  4 +-
+ .../service/crypto/protobuf/opcodes.proto     |  4 +-
+ 22 files changed, 366 insertions(+), 130 deletions(-)
+
+diff --git a/components/service/crypto/client/caller/packed-c/crypto_caller_sign_hash.h b/components/service/crypto/client/caller/packed-c/crypto_caller_sign_hash.h
+index e807773e..4a9ed20d 100644
+--- a/components/service/crypto/client/caller/packed-c/crypto_caller_sign_hash.h
++++ b/components/service/crypto/client/caller/packed-c/crypto_caller_sign_hash.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -20,7 +20,8 @@
+ extern "C" {
+ #endif
+ 
+-static inline psa_status_t crypto_caller_sign_hash(struct service_client *context,
++static inline psa_status_t crypto_caller_asym_sign_commom(struct service_client *context,
++	uint32_t opcode,
+ 	psa_key_id_t id,
+ 	psa_algorithm_t alg,
+ 	const uint8_t *hash, size_t hash_length,
+@@ -60,7 +61,7 @@ static inline psa_status_t crypto_caller_sign_hash(struct service_client *contex
+ 
+ 		context->rpc_status =
+ 			rpc_caller_invoke(context->caller, call_handle,
+-						TS_CRYPTO_OPCODE_SIGN_HASH, &opstatus, &resp_buf, &resp_len);
++						opcode, &opstatus, &resp_buf, &resp_len);
+ 
+ 		if (context->rpc_status == TS_RPC_CALL_ACCEPTED) {
+ 
+@@ -98,6 +99,28 @@ static inline psa_status_t crypto_caller_sign_hash(struct service_client *contex
+ 	return psa_status;
+ }
+ 
++static inline psa_status_t crypto_caller_sign_hash(struct service_client *context,
++	psa_key_id_t id,
++	psa_algorithm_t alg,
++	const uint8_t *hash, size_t hash_length,
++	uint8_t *signature, size_t signature_size, size_t *signature_length)
++{
++	return crypto_caller_asym_sign_commom(context, TS_CRYPTO_OPCODE_SIGN_HASH,
++		id, alg, hash, hash_length,
++		signature, signature_size, signature_length);
++}
++
++static inline psa_status_t crypto_caller_sign_message(struct service_client *context,
++	psa_key_id_t id,
++	psa_algorithm_t alg,
++	const uint8_t *hash, size_t hash_length,
++	uint8_t *signature, size_t signature_size, size_t *signature_length)
++{
++	return crypto_caller_asym_sign_commom(context, TS_CRYPTO_OPCODE_SIGN_MESSAGE,
++		id, alg, hash, hash_length,
++		signature, signature_size, signature_length);
++}
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/components/service/crypto/client/caller/packed-c/crypto_caller_verify_hash.h b/components/service/crypto/client/caller/packed-c/crypto_caller_verify_hash.h
+index 47152946..daa11330 100644
+--- a/components/service/crypto/client/caller/packed-c/crypto_caller_verify_hash.h
++++ b/components/service/crypto/client/caller/packed-c/crypto_caller_verify_hash.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -20,7 +20,8 @@
+ extern "C" {
+ #endif
+ 
+-static inline psa_status_t crypto_caller_verify_hash(struct service_client *context,
++static inline psa_status_t crypto_caller_asym_verify_common(struct service_client *context,
++	uint32_t opcode,
+ 	psa_key_id_t id,
+ 	psa_algorithm_t alg,
+ 	const uint8_t *hash, size_t hash_length,
+@@ -65,7 +66,7 @@ static inline psa_status_t crypto_caller_verify_hash(struct service_client *cont
+ 
+ 		context->rpc_status =
+ 			rpc_caller_invoke(context->caller, call_handle,
+-					TS_CRYPTO_OPCODE_VERIFY_HASH, &opstatus, &resp_buf, &resp_len);
++					opcode, &opstatus, &resp_buf, &resp_len);
+ 
+ 		if (context->rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus;
+ 
+@@ -75,6 +76,32 @@ static inline psa_status_t crypto_caller_verify_hash(struct service_client *cont
+ 	return psa_status;
+ }
+ 
++static inline psa_status_t crypto_caller_verify_hash(struct service_client *context,
++	psa_key_id_t id,
++	psa_algorithm_t alg,
++	const uint8_t *hash, size_t hash_length,
++	const uint8_t *signature, size_t signature_length)
++{
++	return crypto_caller_asym_verify_common(context,
++		TS_CRYPTO_OPCODE_VERIFY_HASH,
++		id, alg,
++		hash, hash_length,
++		signature, signature_length);
++}
++
++static inline psa_status_t crypto_caller_verify_message(struct service_client *context,
++	psa_key_id_t id,
++	psa_algorithm_t alg,
++	const uint8_t *input, size_t input_length,
++	const uint8_t *signature, size_t signature_length)
++{
++	return crypto_caller_asym_verify_common(context,
++		TS_CRYPTO_OPCODE_VERIFY_MESSAGE,
++		id, alg,
++		input, input_length,
++		signature, signature_length);
++}
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/components/service/crypto/client/caller/stub/crypto_caller_sign_hash.h b/components/service/crypto/client/caller/stub/crypto_caller_sign_hash.h
+index d09369a2..09049f5c 100644
+--- a/components/service/crypto/client/caller/stub/crypto_caller_sign_hash.h
++++ b/components/service/crypto/client/caller/stub/crypto_caller_sign_hash.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -23,6 +23,15 @@ static inline psa_status_t crypto_caller_sign_hash(struct service_client *contex
+ 	return PSA_ERROR_NOT_SUPPORTED;
+ }
+ 
++static inline psa_status_t crypto_caller_sign_message(struct service_client *context,
++	psa_key_id_t id,
++	psa_algorithm_t alg,
++	const uint8_t *hash, size_t hash_length,
++	uint8_t *signature, size_t signature_size, size_t *signature_length)
++{
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/components/service/crypto/client/caller/stub/crypto_caller_verify_hash.h b/components/service/crypto/client/caller/stub/crypto_caller_verify_hash.h
+index 20d11dcf..3f3eb878 100644
+--- a/components/service/crypto/client/caller/stub/crypto_caller_verify_hash.h
++++ b/components/service/crypto/client/caller/stub/crypto_caller_verify_hash.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -23,6 +23,15 @@ static inline psa_status_t crypto_caller_verify_hash(struct service_client *cont
+ 	return PSA_ERROR_NOT_SUPPORTED;
+ }
+ 
++static inline psa_status_t crypto_caller_verify_message(struct service_client *context,
++	psa_key_id_t id,
++	psa_algorithm_t alg,
++	const uint8_t *input, size_t input_length,
++	const uint8_t *signature, size_t signature_length)
++{
++	return PSA_ERROR_NOT_SUPPORTED;
++}
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/components/service/crypto/client/cpp/crypto_client.h b/components/service/crypto/client/cpp/crypto_client.h
+index 2a5e5b99..ccb0714a 100644
+--- a/components/service/crypto/client/cpp/crypto_client.h
++++ b/components/service/crypto/client/cpp/crypto_client.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -57,7 +57,7 @@ public:
+ 		psa_key_id_t id,
+ 		uint8_t *data, size_t data_size, size_t *data_length) = 0;
+ 
+-	/* Sign/verify methods */
++	/* Sign/verify hash methods */
+ 	virtual psa_status_t sign_hash(
+ 		psa_key_id_t id,
+ 		psa_algorithm_t alg,
+@@ -70,6 +70,19 @@ public:
+ 		const uint8_t *hash, size_t hash_length,
+ 		const uint8_t *signature, size_t signature_length) = 0;
+ 
++	/* Sign/verify message methods */
++	virtual psa_status_t sign_message(
++		psa_key_id_t id,
++		psa_algorithm_t alg,
++		const uint8_t *message, size_t message_length,
++		uint8_t *signature, size_t signature_size, size_t *signature_length) = 0;
++
++	virtual psa_status_t verify_message(
++		psa_key_id_t id,
++		psa_algorithm_t alg,
++		const uint8_t *message, size_t message_length,
++		const uint8_t *signature, size_t signature_length) = 0;
++
+ 	/* Asymmetric encrypt/decrypt */
+ 	virtual psa_status_t asymmetric_encrypt(
+ 		psa_key_id_t id,
+diff --git a/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp
+index 4d9d8f41..4e10f9be 100644
+--- a/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp
++++ b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.cpp
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -107,6 +107,26 @@ psa_status_t packedc_crypto_client::verify_hash(
+ 		signature, signature_length);
+ }
+ 
++psa_status_t packedc_crypto_client::sign_message(
++	psa_key_id_t id, psa_algorithm_t alg,
++	const uint8_t *message, size_t message_length,
++	uint8_t *signature, size_t signature_size, size_t *signature_length)
++{
++	return crypto_caller_sign_message(&m_client, id, alg,
++		message, message_length,
++		signature, signature_size, signature_length);
++}
++
++psa_status_t packedc_crypto_client::verify_message(
++	psa_key_id_t id, psa_algorithm_t alg,
++	const uint8_t *message, size_t message_length,
++	const uint8_t *signature, size_t signature_length)
++{
++	return crypto_caller_verify_message(&m_client, id, alg,
++		message, message_length,
++		signature, signature_length);
++}
++
+ psa_status_t packedc_crypto_client::asymmetric_encrypt(
+ 	psa_key_id_t id, psa_algorithm_t alg,
+ 	const uint8_t *input, size_t input_length,
+diff --git a/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h
+index 377b51d1..d74ba609 100644
+--- a/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h
++++ b/components/service/crypto/client/cpp/protocol/packed-c/packedc_crypto_client.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -54,7 +54,7 @@ public:
+ 		psa_key_id_t id,
+ 		uint8_t *data, size_t data_size, size_t *data_length);
+ 
+-	/* Sign/verify methods */
++	/* Sign/verify hash methods */
+ 	psa_status_t sign_hash(
+ 		psa_key_id_t id,
+ 		psa_algorithm_t alg,
+@@ -67,6 +67,19 @@ public:
+ 		const uint8_t *hash, size_t hash_length,
+ 		const uint8_t *signature, size_t signature_length);
+ 
++	/* Sign/verify message methods */
++	psa_status_t sign_message(
++		psa_key_id_t id,
++		psa_algorithm_t alg,
++		const uint8_t *message, size_t message_length,
++		uint8_t *signature, size_t signature_size, size_t *signature_length);
++
++	psa_status_t verify_message(
++		psa_key_id_t id,
++		psa_algorithm_t alg,
++		const uint8_t *message, size_t message_length,
++		const uint8_t *signature, size_t signature_length);
++
+ 	/* Asymmetric encrypt/decrypt */
+ 	psa_status_t asymmetric_encrypt(
+ 		psa_key_id_t id,
+diff --git a/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.cpp b/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.cpp
+index 17780351..28c8f6fb 100644
+--- a/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.cpp
++++ b/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.cpp
+@@ -386,6 +386,25 @@ psa_status_t protobuf_crypto_client::export_public_key(psa_key_id_t id,
+ psa_status_t protobuf_crypto_client::sign_hash(psa_key_id_t id, psa_algorithm_t alg,
+ 							const uint8_t *hash, size_t hash_length,
+ 							uint8_t *signature, size_t signature_size, size_t *signature_length)
++{
++	return asym_sign(ts_crypto_Opcode_SIGN_HASH, id, alg,
++				hash, hash_length,
++				signature, signature_size, signature_length);
++}
++
++psa_status_t protobuf_crypto_client::sign_message(psa_key_id_t id, psa_algorithm_t alg,
++							const uint8_t *message, size_t message_length,
++							uint8_t *signature, size_t signature_size, size_t *signature_length)
++{
++	return asym_sign(ts_crypto_Opcode_SIGN_MESSAGE, id, alg,
++				message, message_length,
++				signature, signature_size, signature_length);
++}
++
++psa_status_t protobuf_crypto_client::asym_sign(uint32_t opcode,
++							psa_key_id_t id, psa_algorithm_t alg,
++							const uint8_t *hash, size_t hash_length,
++							uint8_t *signature, size_t signature_size, size_t *signature_length)
+ {
+ 	size_t req_len;
+ 	pb_bytes_array_t *hash_byte_array =
+@@ -416,7 +435,7 @@ psa_status_t protobuf_crypto_client::sign_hash(psa_key_id_t id, psa_algorithm_t
+ 			pb_encode(&ostream, ts_crypto_SignHashIn_fields, &req_msg);
+ 
+ 			m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
+-						ts_crypto_Opcode_SIGN_HASH, &opstatus, &resp_buf, &resp_len);
++						opcode, &opstatus, &resp_buf, &resp_len);
+ 
+ 			if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) {
+ 
+@@ -462,10 +481,28 @@ psa_status_t protobuf_crypto_client::sign_hash(psa_key_id_t id, psa_algorithm_t
+ 	return psa_status;
+ }
+ 
+-
+ psa_status_t protobuf_crypto_client::verify_hash(psa_key_id_t id, psa_algorithm_t alg,
+ 						const uint8_t *hash, size_t hash_length,
+ 						const uint8_t *signature, size_t signature_length)
++{
++	return asym_verify(ts_crypto_Opcode_VERIFY_HASH, id, alg,
++				hash, hash_length,
++				signature, signature_length);
++}
++
++psa_status_t protobuf_crypto_client::verify_message(psa_key_id_t id, psa_algorithm_t alg,
++						const uint8_t *message, size_t message_length,
++						const uint8_t *signature, size_t signature_length)
++{
++	return asym_verify(ts_crypto_Opcode_VERIFY_MESSAGE, id, alg,
++				message, message_length,
++				signature, signature_length);
++}
++
++psa_status_t protobuf_crypto_client::asym_verify(uint32_t opcode,
++						psa_key_id_t id, psa_algorithm_t alg,
++						const uint8_t *hash, size_t hash_length,
++						const uint8_t *signature, size_t signature_length)
+ {
+ 	size_t req_len;
+ 	pb_bytes_array_t *hash_byte_array =
+@@ -497,7 +534,7 @@ psa_status_t protobuf_crypto_client::verify_hash(psa_key_id_t id, psa_algorithm_
+ 			pb_encode(&ostream, ts_crypto_VerifyHashIn_fields, &req_msg);
+ 
+ 			m_client.rpc_status = rpc_caller_invoke(m_client.caller, call_handle,
+-						ts_crypto_Opcode_VERIFY_HASH, &opstatus, &resp_buf, &resp_len);
++						opcode, &opstatus, &resp_buf, &resp_len);
+ 
+ 			if (m_client.rpc_status == TS_RPC_CALL_ACCEPTED) psa_status = opstatus;
+ 
+diff --git a/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.h b/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.h
+index 085d9cfa..abe4439e 100644
+--- a/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.h
++++ b/components/service/crypto/client/cpp/protocol/protobuf/protobuf_crypto_client.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -54,7 +54,7 @@ public:
+ 		psa_key_id_t id,
+ 		uint8_t *data, size_t data_size, size_t *data_length);
+ 
+-	/* Sign/verify methods */
++	/* Sign/verify hash methods */
+ 	psa_status_t sign_hash(
+ 		psa_key_id_t id,
+ 		psa_algorithm_t alg,
+@@ -67,6 +67,19 @@ public:
+ 		const uint8_t *hash, size_t hash_length,
+ 		const uint8_t *signature, size_t signature_length);
+ 
++	/* Sign/verify message methods */
++	psa_status_t sign_message(
++		psa_key_id_t id,
++		psa_algorithm_t alg,
++		const uint8_t *message, size_t message_length,
++		uint8_t *signature, size_t signature_size, size_t *signature_length);
++
++	psa_status_t verify_message(
++		psa_key_id_t id,
++		psa_algorithm_t alg,
++		const uint8_t *message, size_t message_length,
++		const uint8_t *signature, size_t signature_length);
++
+ 	/* Asymmetric encrypt/decrypt */
+ 	psa_status_t asymmetric_encrypt(
+ 		psa_key_id_t id,
+@@ -221,6 +234,16 @@ public:
+ 
+ private:
+ 
++	psa_status_t asym_sign(uint32_t opcode,
++		psa_key_id_t id, psa_algorithm_t alg,
++		const uint8_t *hash, size_t hash_length,
++		uint8_t *signature, size_t signature_size, size_t *signature_length);
++
++	psa_status_t asym_verify(uint32_t opcode,
++		psa_key_id_t id, psa_algorithm_t alg,
++		const uint8_t *hash, size_t hash_length,
++		const uint8_t *signature, size_t signature_length);
++
+ 	void translate_key_attributes(
+ 		ts_crypto_KeyAttributes &proto_attributes,
+ 		const psa_key_attributes_t &psa_attributes);
+diff --git a/components/service/crypto/client/psa/psa_sign_message.c b/components/service/crypto/client/psa/psa_sign_message.c
+index dc2f7e80..b6446253 100644
+--- a/components/service/crypto/client/psa/psa_sign_message.c
++++ b/components/service/crypto/client/psa/psa_sign_message.c
+@@ -1,13 +1,15 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+ 
+ #include <psa/crypto.h>
++#include "psa_crypto_client.h"
++#include "crypto_caller_selector.h"
+ 
+ psa_status_t psa_sign_message(
+-	psa_key_id_t key,
++	psa_key_id_t id,
+ 	psa_algorithm_t alg,
+ 	const uint8_t *input,
+ 	size_t input_length,
+@@ -15,19 +17,11 @@ psa_status_t psa_sign_message(
+ 	size_t signature_size,
+ 	size_t *signature_length)
+ {
+-	size_t hash_len;
+-	uint8_t hash[PSA_HASH_MAX_SIZE];
++	if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
++		return psa_crypto_client_instance.init_status;
+ 
+-	psa_status_t psa_status = psa_hash_compute(PSA_ALG_SIGN_GET_HASH(alg),
++	return crypto_caller_sign_message(&psa_crypto_client_instance.base,
++		id, alg,
+ 		input, input_length,
+-		hash, sizeof(hash), &hash_len);
+-
+-	if (psa_status == PSA_SUCCESS) {
+-
+-		psa_status = psa_sign_hash(key, alg,
+-			hash, hash_len,
+-			signature, signature_size, signature_length);
+-	}
+-
+-	return psa_status;
++		signature, signature_size, signature_length);
+ }
+diff --git a/components/service/crypto/client/psa/psa_verify_message.c b/components/service/crypto/client/psa/psa_verify_message.c
+index d0fbc7c8..57c2c5e8 100644
+--- a/components/service/crypto/client/psa/psa_verify_message.c
++++ b/components/service/crypto/client/psa/psa_verify_message.c
+@@ -1,32 +1,26 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+ 
+ #include <psa/crypto.h>
++#include "psa_crypto_client.h"
++#include "crypto_caller_selector.h"
+ 
+ psa_status_t psa_verify_message(
+-	psa_key_id_t key,
++	psa_key_id_t id,
+ 	psa_algorithm_t alg,
+ 	const uint8_t *input,
+ 	size_t input_length,
+ 	const uint8_t * signature,
+ 	size_t signature_length)
+ {
+-	size_t hash_len;
+-	uint8_t hash[PSA_HASH_MAX_SIZE];
++	if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
++		return psa_crypto_client_instance.init_status;
+ 
+-	psa_status_t psa_status = psa_hash_compute(PSA_ALG_SIGN_GET_HASH(alg),
++	return crypto_caller_verify_message(&psa_crypto_client_instance.base,
++		id, alg,
+ 		input, input_length,
+-		hash, sizeof(hash), &hash_len);
+-
+-	if (psa_status == PSA_SUCCESS) {
+-
+-		psa_status = psa_verify_hash(key, alg,
+-			hash, hash_len,
+-			signature, signature_length);
+-	}
+-
+-	return psa_status;
++		signature, signature_length);
+ }
+diff --git a/components/service/crypto/provider/crypto_provider.c b/components/service/crypto/provider/crypto_provider.c
+index d0fc7cac..67a5b340 100644
+--- a/components/service/crypto/provider/crypto_provider.c
++++ b/components/service/crypto/provider/crypto_provider.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -16,8 +16,8 @@ static rpc_status_t destroy_key_handler(void *context, struct call_req* req);
+ static rpc_status_t export_key_handler(void *context, struct call_req* req);
+ static rpc_status_t export_public_key_handler(void *context, struct call_req* req);
+ static rpc_status_t import_key_handler(void *context, struct call_req* req);
+-static rpc_status_t sign_hash_handler(void *context, struct call_req* req);
+-static rpc_status_t verify_hash_handler(void *context, struct call_req* req);
++static rpc_status_t asymmetric_sign_handler(void *context, struct call_req* req);
++static rpc_status_t asymmetric_verify_handler(void *context, struct call_req* req);
+ static rpc_status_t asymmetric_decrypt_handler(void *context, struct call_req* req);
+ static rpc_status_t asymmetric_encrypt_handler(void *context, struct call_req* req);
+ static rpc_status_t generate_random_handler(void *context, struct call_req* req);
+@@ -32,14 +32,16 @@ static const struct service_handler handler_table[] = {
+ 	{TS_CRYPTO_OPCODE_EXPORT_KEY,           export_key_handler},
+ 	{TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY,    export_public_key_handler},
+ 	{TS_CRYPTO_OPCODE_IMPORT_KEY,           import_key_handler},
+-	{TS_CRYPTO_OPCODE_SIGN_HASH,            sign_hash_handler},
+-	{TS_CRYPTO_OPCODE_VERIFY_HASH,          verify_hash_handler},
++	{TS_CRYPTO_OPCODE_SIGN_HASH,            asymmetric_sign_handler},
++	{TS_CRYPTO_OPCODE_VERIFY_HASH,          asymmetric_verify_handler},
+ 	{TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT,   asymmetric_decrypt_handler},
+ 	{TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT,   asymmetric_encrypt_handler},
+ 	{TS_CRYPTO_OPCODE_GENERATE_RANDOM,      generate_random_handler},
+ 	{TS_CRYPTO_OPCODE_COPY_KEY,          	copy_key_handler},
+ 	{TS_CRYPTO_OPCODE_PURGE_KEY,          	purge_key_handler},
+ 	{TS_CRYPTO_OPCODE_GET_KEY_ATTRIBUTES, 	get_key_attributes_handler},
++	{TS_CRYPTO_OPCODE_SIGN_MESSAGE,         asymmetric_sign_handler},
++	{TS_CRYPTO_OPCODE_VERIFY_MESSAGE,       asymmetric_verify_handler},
+ };
+ 
+ struct rpc_interface *crypto_provider_init(struct crypto_provider *context)
+@@ -272,7 +274,7 @@ static rpc_status_t import_key_handler(void *context, struct call_req* req)
+ 	return rpc_status;
+ }
+ 
+-static rpc_status_t sign_hash_handler(void *context, struct call_req* req)
++static rpc_status_t asymmetric_sign_handler(void *context, struct call_req* req)
+ {
+ 	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+ 	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+@@ -284,7 +286,7 @@ static rpc_status_t sign_hash_handler(void *context, struct call_req* req)
+ 	uint8_t hash_buffer[PSA_HASH_MAX_SIZE];
+ 
+ 	if (serializer)
+-		rpc_status = serializer->deserialize_sign_hash_req(req_buf, &id, &alg, hash_buffer, &hash_len);
++		rpc_status = serializer->deserialize_asymmetric_sign_req(req_buf, &id, &alg, hash_buffer, &hash_len);
+ 
+ 	if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+ 
+@@ -292,14 +294,16 @@ static rpc_status_t sign_hash_handler(void *context, struct call_req* req)
+ 		size_t sig_len;
+ 		uint8_t sig_buffer[PSA_SIGNATURE_MAX_SIZE];
+ 
+-		psa_status = psa_sign_hash(id, alg,
+-					hash_buffer, hash_len,
+-					sig_buffer, sizeof(sig_buffer), &sig_len);
++		psa_status = (call_req_get_opcode(req) == TS_CRYPTO_OPCODE_SIGN_HASH) ?
++			psa_sign_hash(id, alg, hash_buffer, hash_len,
++				sig_buffer, sizeof(sig_buffer), &sig_len) :
++			psa_sign_message(id, alg, hash_buffer, hash_len,
++				sig_buffer, sizeof(sig_buffer), &sig_len);
+ 
+ 		if (psa_status == PSA_SUCCESS) {
+ 
+ 			struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+-			rpc_status = serializer->serialize_sign_hash_resp(resp_buf, sig_buffer, sig_len);
++			rpc_status = serializer->serialize_asymmetric_sign_resp(resp_buf, sig_buffer, sig_len);
+ 		}
+ 
+ 		call_req_set_opstatus(req, psa_status);
+@@ -308,7 +312,7 @@ static rpc_status_t sign_hash_handler(void *context, struct call_req* req)
+ 	return rpc_status;
+ }
+ 
+-static rpc_status_t verify_hash_handler(void *context, struct call_req* req)
++static rpc_status_t asymmetric_verify_handler(void *context, struct call_req* req)
+ {
+ 	rpc_status_t rpc_status = TS_RPC_ERROR_SERIALIZATION_NOT_SUPPORTED;
+ 	struct call_param_buf *req_buf = call_req_get_req_buf(req);
+@@ -322,7 +326,7 @@ static rpc_status_t verify_hash_handler(void *context, struct call_req* req)
+ 	uint8_t sig_buffer[PSA_SIGNATURE_MAX_SIZE];
+ 
+ 	if (serializer)
+-		rpc_status = serializer->deserialize_verify_hash_req(req_buf, &id, &alg,
++		rpc_status = serializer->deserialize_asymmetric_verify_req(req_buf, &id, &alg,
+ 											hash_buffer, &hash_len,
+ 											sig_buffer, &sig_len);
+ 
+@@ -330,9 +334,13 @@ static rpc_status_t verify_hash_handler(void *context, struct call_req* req)
+ 
+ 		psa_status_t psa_status;
+ 
+-		psa_status = psa_verify_hash(id, alg,
+-					hash_buffer, hash_len,
+-					sig_buffer, sig_len);
++		psa_status = (call_req_get_opcode(req) == TS_CRYPTO_OPCODE_VERIFY_HASH) ?
++			psa_verify_hash(id, alg,
++				hash_buffer, hash_len,
++				sig_buffer, sig_len) :
++			psa_verify_message(id, alg,
++				hash_buffer, hash_len,
++				sig_buffer, sig_len);
+ 
+ 		call_req_set_opstatus(req, psa_status);
+ 	}
+diff --git a/components/service/crypto/provider/serializer/crypto_provider_serializer.h b/components/service/crypto/provider/serializer/crypto_provider_serializer.h
+index 68940cae..57364f24 100644
+--- a/components/service/crypto/provider/serializer/crypto_provider_serializer.h
++++ b/components/service/crypto/provider/serializer/crypto_provider_serializer.h
+@@ -79,15 +79,15 @@ struct crypto_provider_serializer {
+                                         const psa_key_attributes_t *attributes);
+ 
+     /* Operation: sign_hash */
+-    rpc_status_t (*deserialize_sign_hash_req)(const struct call_param_buf *req_buf,
++    rpc_status_t (*deserialize_asymmetric_sign_req)(const struct call_param_buf *req_buf,
+                                         psa_key_id_t *id, psa_algorithm_t *alg,
+                                         uint8_t *hash, size_t *hash_len);
+ 
+-    rpc_status_t (*serialize_sign_hash_resp)(struct call_param_buf *resp_buf,
++    rpc_status_t (*serialize_asymmetric_sign_resp)(struct call_param_buf *resp_buf,
+                                         const uint8_t *sig, size_t sig_len);
+ 
+     /* Operation: verify_hash */
+-    rpc_status_t (*deserialize_verify_hash_req)(const struct call_param_buf *req_buf,
++    rpc_status_t (*deserialize_asymmetric_verify_req)(const struct call_param_buf *req_buf,
+                                         psa_key_id_t *id, psa_algorithm_t *alg,
+                                         uint8_t *hash, size_t *hash_len,
+                                         uint8_t *sig, size_t *sig_len);
+diff --git a/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.c b/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.c
+index c70db865..4a7e59f0 100644
+--- a/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.c
++++ b/components/service/crypto/provider/serializer/packed-c/packedc_crypto_provider_serializer.c
+@@ -333,7 +333,7 @@ static rpc_status_t serialize_get_key_attributes_resp(struct call_param_buf *res
+ }
+ 
+ /* Operation: sign_hash */
+-static rpc_status_t deserialize_sign_hash_req(const struct call_param_buf *req_buf,
++static rpc_status_t deserialize_asymmetric_sign_req(const struct call_param_buf *req_buf,
+                             psa_key_id_t *id, psa_algorithm_t *alg,
+                             uint8_t *hash, size_t *hash_len)
+ {
+@@ -378,7 +378,7 @@ static rpc_status_t deserialize_sign_hash_req(const struct call_param_buf *req_b
+     return rpc_status;
+ }
+ 
+-static rpc_status_t serialize_sign_hash_resp(struct call_param_buf *resp_buf,
++static rpc_status_t serialize_asymmetric_sign_resp(struct call_param_buf *resp_buf,
+                             const uint8_t *sig, size_t sig_len)
+ {
+     rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+@@ -401,7 +401,7 @@ static rpc_status_t serialize_sign_hash_resp(struct call_param_buf *resp_buf,
+ }
+ 
+ /* Operation: verify_hash */
+-static rpc_status_t deserialize_verify_hash_req(const struct call_param_buf *req_buf,
++static rpc_status_t deserialize_asymmetric_verify_req(const struct call_param_buf *req_buf,
+                                 psa_key_id_t *id, psa_algorithm_t *alg,
+                                 uint8_t *hash, size_t *hash_len,
+                                 uint8_t *sig, size_t *sig_len)
+@@ -695,9 +695,9 @@ const struct crypto_provider_serializer *packedc_crypto_provider_serializer_inst
+         deserialize_purge_key_req,
+         deserialize_get_key_attributes_req,
+         serialize_get_key_attributes_resp,
+-        deserialize_sign_hash_req,
+-        serialize_sign_hash_resp,
+-        deserialize_verify_hash_req,
++        deserialize_asymmetric_sign_req,
++        serialize_asymmetric_sign_resp,
++        deserialize_asymmetric_verify_req,
+         deserialize_asymmetric_decrypt_req,
+         serialize_asymmetric_decrypt_resp,
+         deserialize_asymmetric_encrypt_req,
+diff --git a/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.c b/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.c
+index 7767d20a..083a581a 100644
+--- a/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.c
++++ b/components/service/crypto/provider/serializer/protobuf/pb_crypto_provider_serializer.c
+@@ -267,9 +267,9 @@ static rpc_status_t serialize_get_key_attributes_resp(struct call_param_buf *res
+ }
+ 
+ /* Operation: sign_hash */
+-static rpc_status_t deserialize_sign_hash_req(const struct call_param_buf *req_buf,
+-                            psa_key_id_t *id, psa_algorithm_t *alg,
+-                            uint8_t *hash, size_t *hash_len)
++static rpc_status_t deserialize_asymmetric_sign_req(const struct call_param_buf *req_buf,
++							psa_key_id_t *id, psa_algorithm_t *alg,
++							uint8_t *hash, size_t *hash_len)
+ {
+     rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+     ts_crypto_SignHashIn recv_msg = ts_crypto_SignHashIn_init_default;
+@@ -295,8 +295,8 @@ static rpc_status_t deserialize_sign_hash_req(const struct call_param_buf *req_b
+     return rpc_status;
+ }
+ 
+-static rpc_status_t serialize_sign_hash_resp(struct call_param_buf *resp_buf,
+-                            const uint8_t *sig, size_t sig_len)
++static rpc_status_t serialize_asymmetric_sign_resp(struct call_param_buf *resp_buf,
++							const uint8_t *sig, size_t sig_len)
+ {
+     size_t packed_resp_size;
+     rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
+@@ -323,10 +323,10 @@ static rpc_status_t serialize_sign_hash_resp(struct call_param_buf *resp_buf,
+ }
+ 
+ /* Operation: verify_hash */
+-static rpc_status_t deserialize_verify_hash_req(const struct call_param_buf *req_buf,
+-                                psa_key_id_t *id, psa_algorithm_t *alg,
+-                                uint8_t *hash, size_t *hash_len,
+-                                uint8_t *sig, size_t *sig_len)
++static rpc_status_t deserialize_asymmetric_verify_req(const struct call_param_buf *req_buf,
++								psa_key_id_t *id, psa_algorithm_t *alg,
++								uint8_t *hash, size_t *hash_len,
++								uint8_t *sig, size_t *sig_len)
+ {
+     rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+     ts_crypto_VerifyHashIn recv_msg = ts_crypto_VerifyHashIn_init_default;
+@@ -538,32 +538,32 @@ static rpc_status_t serialize_generate_random_resp(struct call_param_buf *resp_b
+ /* Singleton method to provide access to the serializer instance */
+ const struct crypto_provider_serializer *pb_crypto_provider_serializer_instance(void)
+ {
+-    static const struct crypto_provider_serializer instance = {
+-        max_deserialised_parameter_size,
+-        deserialize_generate_key_req,
+-        serialize_generate_key_resp,
+-        deserialize_destroy_key_req,
+-        deserialize_export_key_req,
+-        serialize_export_key_resp,
+-        deserialize_export_public_key_req,
+-        serialize_export_public_key_resp,
+-        deserialize_import_key_req,
+-        serialize_import_key_resp,
+-        deserialize_copy_key_req,
+-        serialize_copy_key_resp,
+-        deserialize_purge_key_req,
+-        deserialize_get_key_attributes_req,
+-        serialize_get_key_attributes_resp,
+-        deserialize_sign_hash_req,
+-        serialize_sign_hash_resp,
+-        deserialize_verify_hash_req,
+-        deserialize_asymmetric_decrypt_req,
+-        serialize_asymmetric_decrypt_resp,
+-        deserialize_asymmetric_encrypt_req,
+-        serialize_asymmetric_encrypt_resp,
+-        deserialize_generate_random_req,
+-        serialize_generate_random_resp
+-    };
+-
+-    return &instance;
++	static const struct crypto_provider_serializer instance = {
++		max_deserialised_parameter_size,
++		deserialize_generate_key_req,
++		serialize_generate_key_resp,
++		deserialize_destroy_key_req,
++		deserialize_export_key_req,
++		serialize_export_key_resp,
++		deserialize_export_public_key_req,
++		serialize_export_public_key_resp,
++		deserialize_import_key_req,
++		serialize_import_key_resp,
++		deserialize_copy_key_req,
++		serialize_copy_key_resp,
++		deserialize_purge_key_req,
++		deserialize_get_key_attributes_req,
++		serialize_get_key_attributes_resp,
++		deserialize_asymmetric_sign_req,
++		serialize_asymmetric_sign_resp,
++		deserialize_asymmetric_verify_req,
++		deserialize_asymmetric_decrypt_req,
++		serialize_asymmetric_decrypt_resp,
++		deserialize_asymmetric_encrypt_req,
++		serialize_asymmetric_encrypt_resp,
++		deserialize_generate_random_req,
++		serialize_generate_random_resp
++	};
++
++	return &instance;
+ }
+diff --git a/components/service/crypto/test/protocol/check_crypto_opcode_alignment.cpp b/components/service/crypto/test/protocol/check_crypto_opcode_alignment.cpp
+index bd6c66ee..da01abf4 100644
+--- a/components/service/crypto/test/protocol/check_crypto_opcode_alignment.cpp
++++ b/components/service/crypto/test/protocol/check_crypto_opcode_alignment.cpp
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -18,15 +18,16 @@ TEST_GROUP(CryptoProtocolOpcodeChecks)
+ 
+ TEST(CryptoProtocolOpcodeChecks, checkPackedcToProtobuf)
+ {
+-    CHECK_EQUAL(TS_CRYPTO_OPCODE_GENERATE_KEY, ts_crypto_Opcode_GENERATE_KEY);
+-    CHECK_EQUAL(TS_CRYPTO_OPCODE_DESTROY_KEY, ts_crypto_Opcode_DESTROY_KEY);
+-    CHECK_EQUAL(TS_CRYPTO_OPCODE_EXPORT_KEY, ts_crypto_Opcode_EXPORT_KEY);
+-    CHECK_EQUAL(TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY, ts_crypto_Opcode_EXPORT_PUBLIC_KEY);
+-    CHECK_EQUAL(TS_CRYPTO_OPCODE_IMPORT_KEY, ts_crypto_Opcode_IMPORT_KEY);
+-    CHECK_EQUAL(TS_CRYPTO_OPCODE_SIGN_HASH, ts_crypto_Opcode_SIGN_HASH);
+-    CHECK_EQUAL(TS_CRYPTO_OPCODE_VERIFY_HASH, ts_crypto_Opcode_VERIFY_HASH);
+-    CHECK_EQUAL(TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT, ts_crypto_Opcode_ASYMMETRIC_DECRYPT);
+-    CHECK_EQUAL(TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT, ts_crypto_Opcode_ASYMMETRIC_ENCRYPT);
+-    CHECK_EQUAL(TS_CRYPTO_OPCODE_GENERATE_RANDOM, ts_crypto_Opcode_GENERATE_RANDOM);
++	CHECK_EQUAL(TS_CRYPTO_OPCODE_GENERATE_KEY, ts_crypto_Opcode_GENERATE_KEY);
++	CHECK_EQUAL(TS_CRYPTO_OPCODE_DESTROY_KEY, ts_crypto_Opcode_DESTROY_KEY);
++	CHECK_EQUAL(TS_CRYPTO_OPCODE_EXPORT_KEY, ts_crypto_Opcode_EXPORT_KEY);
++	CHECK_EQUAL(TS_CRYPTO_OPCODE_EXPORT_PUBLIC_KEY, ts_crypto_Opcode_EXPORT_PUBLIC_KEY);
++	CHECK_EQUAL(TS_CRYPTO_OPCODE_IMPORT_KEY, ts_crypto_Opcode_IMPORT_KEY);
++	CHECK_EQUAL(TS_CRYPTO_OPCODE_SIGN_HASH, ts_crypto_Opcode_SIGN_HASH);
++	CHECK_EQUAL(TS_CRYPTO_OPCODE_VERIFY_HASH, ts_crypto_Opcode_VERIFY_HASH);
++	CHECK_EQUAL(TS_CRYPTO_OPCODE_ASYMMETRIC_DECRYPT, ts_crypto_Opcode_ASYMMETRIC_DECRYPT);
++	CHECK_EQUAL(TS_CRYPTO_OPCODE_ASYMMETRIC_ENCRYPT, ts_crypto_Opcode_ASYMMETRIC_ENCRYPT);
++	CHECK_EQUAL(TS_CRYPTO_OPCODE_GENERATE_RANDOM, ts_crypto_Opcode_GENERATE_RANDOM);
++	CHECK_EQUAL(TS_CRYPTO_OPCODE_SIGN_MESSAGE, ts_crypto_Opcode_SIGN_MESSAGE);
++	CHECK_EQUAL(TS_CRYPTO_OPCODE_VERIFY_MESSAGE, ts_crypto_Opcode_VERIFY_MESSAGE);
+ }
+-
+diff --git a/components/service/crypto/test/service/crypto_service_scenarios.cpp b/components/service/crypto/test/service/crypto_service_scenarios.cpp
+index ec2c6736..b3345551 100644
+--- a/components/service/crypto/test/service/crypto_service_scenarios.cpp
++++ b/components/service/crypto/test/service/crypto_service_scenarios.cpp
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -290,6 +290,56 @@ void crypto_service_scenarios::signAndVerifyHash()
+ 	CHECK_EQUAL(PSA_SUCCESS, status);
+ }
+ 
++void crypto_service_scenarios::signAndVerifyMessage()
++{
++	psa_status_t status;
++	psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
++	psa_key_id_t key_id;
++
++	psa_set_key_id(&attributes, 14);
++	psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
++	psa_set_key_algorithm(&attributes, PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256));
++	psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
++	psa_set_key_bits(&attributes, 256);
++
++	/* Generate a key */
++	status = m_crypto_client->generate_key(&attributes, &key_id);
++	CHECK_EQUAL(PSA_SUCCESS, status);
++
++	psa_reset_key_attributes(&attributes);
++
++	/* Sign a message */
++	uint8_t message[21];
++	uint8_t signature[PSA_SIGNATURE_MAX_SIZE];
++	size_t signature_length;
++
++	memset(message, 0x99, sizeof(message));
++
++	status = m_crypto_client->sign_message(key_id,
++		PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), message, sizeof(message),
++		signature, sizeof(signature), &signature_length);
++
++	CHECK_EQUAL(PSA_SUCCESS, status);
++	CHECK(signature_length > 0);
++
++	/* Verify the signature */
++	status = m_crypto_client->verify_message(key_id,
++		PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), message, sizeof(message),
++		signature, signature_length);
++	CHECK_EQUAL(PSA_SUCCESS, status);
++
++	/* Change the message and expect verify to fail */
++	message[0] = 0x72;
++	status = m_crypto_client->verify_message(key_id,
++		PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_SHA_256), message, sizeof(message),
++		signature, signature_length);
++	CHECK_EQUAL(PSA_ERROR_INVALID_SIGNATURE, status);
++
++	/* Remove the key */
++	status = m_crypto_client->destroy_key(key_id);
++	CHECK_EQUAL(PSA_SUCCESS, status);
++}
++
+ void crypto_service_scenarios::signAndVerifyEat()
+ {
+ 	/* Sign and verify a hash using EAT key type and algorithm */
+@@ -348,7 +398,7 @@ void crypto_service_scenarios::asymEncryptDecrypt()
+ 	psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ 	psa_key_id_t key_id;
+ 
+-	psa_set_key_id(&attributes, 14);
++	psa_set_key_id(&attributes, 15);
+ 	psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+ 	psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+ 	psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
+@@ -394,7 +444,7 @@ void crypto_service_scenarios::asymEncryptDecryptWithSalt()
+ 	psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ 	psa_key_id_t key_id;
+ 
+-	psa_set_key_id(&attributes, 15);
++	psa_set_key_id(&attributes, 16);
+ 	psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
+ 	psa_set_key_algorithm(&attributes,  PSA_ALG_RSA_OAEP(PSA_ALG_SHA_256));
+ 	psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
+diff --git a/components/service/crypto/test/service/crypto_service_scenarios.h b/components/service/crypto/test/service/crypto_service_scenarios.h
+index c65eba26..23671644 100644
+--- a/components/service/crypto/test/service/crypto_service_scenarios.h
++++ b/components/service/crypto/test/service/crypto_service_scenarios.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -24,6 +24,7 @@ public:
+ 	void asymEncryptDecrypt();
+ 	void asymEncryptDecryptWithSalt();
+ 	void signAndVerifyHash();
++	void signAndVerifyMessage();
+ 	void signAndVerifyEat();
+ 	void exportAndImportKeyPair();
+ 	void exportPublicKey();
+diff --git a/components/service/crypto/test/service/packed-c/crypto_service_packedc_tests.cpp b/components/service/crypto/test/service/packed-c/crypto_service_packedc_tests.cpp
+index 79eddfbb..ea238432 100644
+--- a/components/service/crypto/test/service/packed-c/crypto_service_packedc_tests.cpp
++++ b/components/service/crypto/test/service/packed-c/crypto_service_packedc_tests.cpp
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -87,6 +87,11 @@ TEST(CryptoServicePackedcTests, signAndVerifyHash)
+ 	m_scenarios->signAndVerifyHash();
+ }
+ 
++TEST(CryptoServicePackedcTests, signAndVerifyMessage)
++{
++	m_scenarios->signAndVerifyMessage();
++}
++
+ TEST(CryptoServicePackedcTests, signAndVerifyEat)
+ {
+ 	m_scenarios->signAndVerifyEat();
+diff --git a/components/service/crypto/test/service/protobuf/crypto_service_protobuf_tests.cpp b/components/service/crypto/test/service/protobuf/crypto_service_protobuf_tests.cpp
+index 1230752c..c172ad4a 100644
+--- a/components/service/crypto/test/service/protobuf/crypto_service_protobuf_tests.cpp
++++ b/components/service/crypto/test/service/protobuf/crypto_service_protobuf_tests.cpp
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -77,6 +77,11 @@ TEST(CryptoServiceProtobufTests, signAndVerifyHash)
+     m_scenarios->signAndVerifyHash();
+ }
+ 
++TEST(CryptoServiceProtobufTests, signAndVerifyMessage)
++{
++    m_scenarios->signAndVerifyMessage();
++}
++
+ TEST(CryptoServiceProtobufTests, asymEncryptDecrypt)
+ {
+     m_scenarios->asymEncryptDecrypt();
+diff --git a/protocols/service/crypto/packed-c/opcodes.h b/protocols/service/crypto/packed-c/opcodes.h
+index a07bd57e..5aebf2fa 100644
+--- a/protocols/service/crypto/packed-c/opcodes.h
++++ b/protocols/service/crypto/packed-c/opcodes.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -25,6 +25,8 @@
+ #define TS_CRYPTO_OPCODE_COPY_KEY               (TS_CRYPTO_OPCODE_BASE + 13)
+ #define TS_CRYPTO_OPCODE_PURGE_KEY              (TS_CRYPTO_OPCODE_BASE + 14)
+ #define TS_CRYPTO_OPCODE_GET_KEY_ATTRIBUTES     (TS_CRYPTO_OPCODE_BASE + 15)
++#define TS_CRYPTO_OPCODE_SIGN_MESSAGE           (TS_CRYPTO_OPCODE_BASE + 16)
++#define TS_CRYPTO_OPCODE_VERIFY_MESSAGE         (TS_CRYPTO_OPCODE_BASE + 17)
+ 
+ /* Hash operations */
+ #define TS_CRYPTO_OPCODE_HASH_BASE              (0x0200)
+diff --git a/protocols/service/crypto/protobuf/opcodes.proto b/protocols/service/crypto/protobuf/opcodes.proto
+index 094d3a02..ef64d044 100644
+--- a/protocols/service/crypto/protobuf/opcodes.proto
++++ b/protocols/service/crypto/protobuf/opcodes.proto
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+ syntax = "proto3";
+@@ -18,4 +18,6 @@ enum Opcode {
+   ASYMMETRIC_DECRYPT  = 0x010a;
+   ASYMMETRIC_ENCRYPT  = 0x010b;
+   GENERATE_RANDOM     = 0x010c;
++  SIGN_MESSAGE        = 0x0110;
++  VERIFY_MESSAGE      = 0x0111;
+ }
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0037-Add-defence-against-uninitialised-multi-part-transac.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0037-Add-defence-against-uninitialised-multi-part-transac.patch
new file mode 100644
index 0000000..a56e0f8
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0037-Add-defence-against-uninitialised-multi-part-transac.patch
@@ -0,0 +1,123 @@
+From 9a83c32964ee2b1ecb7b36b4c08466202efd3bf2 Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Fri, 11 Feb 2022 14:19:26 +0000
+Subject: [PATCH] Add defence against uninitialised multi-part transaction
+
+Adds checks for the condition where there is an attempt to
+setup a multi-part transaction without first initialising
+transaction state.
+
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: I754479260fed0490d8f32b41a077d26028dc9903
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ components/service/crypto/client/psa/psa_cipher.c | 14 +++++++++++++-
+ components/service/crypto/client/psa/psa_hash.c   |  8 +++++++-
+ components/service/crypto/client/psa/psa_mac.c    | 10 ++++++++--
+ 3 files changed, 28 insertions(+), 4 deletions(-)
+
+diff --git a/components/service/crypto/client/psa/psa_cipher.c b/components/service/crypto/client/psa/psa_cipher.c
+index 70836ea6..3ab8ea21 100644
+--- a/components/service/crypto/client/psa/psa_cipher.c
++++ b/components/service/crypto/client/psa/psa_cipher.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -13,6 +13,12 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
+ 	psa_key_id_t key,
+ 	psa_algorithm_t alg)
+ {
++	if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
++		return psa_crypto_client_instance.init_status;
++
++	if (operation->handle)
++		return PSA_ERROR_BAD_STATE;
++
+ 	return crypto_caller_cipher_encrypt_setup(&psa_crypto_client_instance.base,
+ 		&operation->handle,
+ 		key, alg);
+@@ -22,6 +28,12 @@ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation,
+ 	psa_key_id_t key,
+ 	psa_algorithm_t alg)
+ {
++	if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
++		return psa_crypto_client_instance.init_status;
++
++	if (operation->handle)
++		return PSA_ERROR_BAD_STATE;
++
+ 	return crypto_caller_cipher_decrypt_setup(&psa_crypto_client_instance.base,
+ 		&operation->handle,
+ 		key, alg);
+diff --git a/components/service/crypto/client/psa/psa_hash.c b/components/service/crypto/client/psa/psa_hash.c
+index 7005c390..83278de6 100644
+--- a/components/service/crypto/client/psa/psa_hash.c
++++ b/components/service/crypto/client/psa/psa_hash.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -14,6 +14,9 @@ psa_status_t psa_hash_setup(psa_hash_operation_t *operation,
+ 	if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
+ 		return psa_crypto_client_instance.init_status;
+ 
++	if (operation->handle)
++		return PSA_ERROR_BAD_STATE;
++
+ 	return crypto_caller_hash_setup(&psa_crypto_client_instance.base,
+ 		&operation->handle, alg);
+ }
+@@ -55,6 +58,9 @@ psa_status_t psa_hash_verify(psa_hash_operation_t *operation,
+ psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation,
+ 	psa_hash_operation_t *target_operation)
+ {
++	if (target_operation->handle)
++		return PSA_ERROR_BAD_STATE;
++
+ 	return crypto_caller_hash_clone(&psa_crypto_client_instance.base,
+ 		source_operation->handle,
+ 		&target_operation->handle);
+diff --git a/components/service/crypto/client/psa/psa_mac.c b/components/service/crypto/client/psa/psa_mac.c
+index 5efa1c4d..5c5eb32a 100644
+--- a/components/service/crypto/client/psa/psa_mac.c
++++ b/components/service/crypto/client/psa/psa_mac.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -16,6 +16,9 @@ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation,
+ 	if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
+ 		return psa_crypto_client_instance.init_status;
+ 
++	if (operation->handle)
++		return PSA_ERROR_BAD_STATE;
++
+ 	return crypto_caller_mac_sign_setup(&psa_crypto_client_instance.base,
+ 		&operation->handle,
+ 		key, alg);
+@@ -28,7 +31,10 @@ psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation,
+ 	if (psa_crypto_client_instance.init_status != PSA_SUCCESS)
+ 		return psa_crypto_client_instance.init_status;
+ 
+-	return crypto_caller_mac_sign_setup(&psa_crypto_client_instance.base,
++	if (operation->handle)
++		return PSA_ERROR_BAD_STATE;
++
++	return crypto_caller_mac_verify_setup(&psa_crypto_client_instance.base,
+ 		&operation->handle,
+ 		key, alg);
+ }
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0038-Integrate-AEAD-operation-support.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0038-Integrate-AEAD-operation-support.patch
new file mode 100644
index 0000000..2ad1efb
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0038-Integrate-AEAD-operation-support.patch
@@ -0,0 +1,521 @@
+From 00b4f777b377c69f948f5a9d68cbfc8fa8c38a86 Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Fri, 11 Feb 2022 14:24:53 +0000
+Subject: [PATCH] Integrate AEAD operation support
+
+Resolves issues and integrates AEAD support into the crypto service
+provider and clients.
+
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: I5fbe78a2dd825f592e26fd665f60c18b576f9de9
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ .../caller/packed-c/crypto_caller_aead.h      |  70 +++---
+ .../client/caller/stub/crypto_caller_aead.h   |  12 +-
+ .../service/crypto/client/psa/psa_aead.c      | 221 +++++++++++++++---
+ .../factory/full/crypto_provider_factory.c    |  16 +-
+ .../component-test/component-test.cmake       |   4 +-
+ deployments/crypto/opteesp/CMakeLists.txt     |   4 +-
+ deployments/libts/linux-pc/CMakeLists.txt     |   4 +-
+ deployments/se-proxy/opteesp/CMakeLists.txt   |   4 +-
+ 8 files changed, 263 insertions(+), 72 deletions(-)
+
+diff --git a/components/service/crypto/client/caller/packed-c/crypto_caller_aead.h b/components/service/crypto/client/caller/packed-c/crypto_caller_aead.h
+index 3d9947d5..c4ffb20c 100644
+--- a/components/service/crypto/client/caller/packed-c/crypto_caller_aead.h
++++ b/components/service/crypto/client/caller/packed-c/crypto_caller_aead.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -20,38 +20,6 @@
+ extern "C" {
+ #endif
+ 
+-static inline psa_status_t crypto_caller_aead_encrypt(struct service_client *context,
+-	psa_key_id_t key,
+-	psa_algorithm_t alg,
+-	const uint8_t *nonce,
+-	size_t nonce_length,
+-	const uint8_t *additional_data,
+-	size_t additional_data_length,
+-	const uint8_t *plaintext,
+-	size_t plaintext_length,
+-	uint8_t *aeadtext,
+-	size_t aeadtext_size,
+-	size_t *aeadtext_length)
+-{
+-	return PSA_ERROR_NOT_SUPPORTED;
+-}
+-
+-static inline psa_status_t crypto_caller_aead_decrypt(struct service_client *context,
+-	psa_key_id_t key,
+-	psa_algorithm_t alg,
+-	const uint8_t *nonce,
+-	size_t nonce_length,
+-	const uint8_t *additional_data,
+-	size_t additional_data_length,
+-	const uint8_t *aeadtext,
+-	size_t aeadtext_length,
+-	uint8_t *plaintext,
+-	size_t plaintext_size,
+-	size_t *plaintext_length)
+-{
+-	return PSA_ERROR_NOT_SUPPORTED;
+-}
+-
+ static inline psa_status_t common_aead_setup(struct service_client *context,
+ 	uint32_t *op_handle,
+ 	psa_key_id_t key,
+@@ -247,7 +215,7 @@ static inline psa_status_t crypto_caller_aead_set_lengths(struct service_client
+ {
+ 	psa_status_t psa_status = PSA_ERROR_GENERIC_ERROR;
+ 	struct ts_crypto_aead_set_lengths_in req_msg;
+-	size_t req_fixed_len = sizeof(struct ts_crypto_aead_abort_in);
++	size_t req_fixed_len = sizeof(struct ts_crypto_aead_set_lengths_in);
+ 	size_t req_len = req_fixed_len;
+ 
+ 	req_msg.op_handle = op_handle;
+@@ -611,6 +579,40 @@ static inline psa_status_t crypto_caller_aead_abort(struct service_client *conte
+ 	return psa_status;
+ }
+ 
++/**
++ * The maximum data length that may be carried in an update operation will be
++ * constrained by the maximum call payload capacity imposed by the end-to-end
++ * RPC call path. These functions return the maximum update size when serialization
++ * overheads are considered. This allows large paylaods to be processed in
++ * maximum size chunks.
++ */
++static inline size_t crypto_caller_aead_max_update_ad_size(const struct service_client *context)
++{
++	/* Returns the maximum number of bytes of additional data that may be
++	 * carried as a parameter of the aead_update_ad operation
++	 * using the packed-c encoding.
++	 */
++	size_t payload_space = context->service_info.max_payload;
++	size_t overhead = sizeof(struct ts_crypto_aead_update_ad_in) + TLV_HDR_LEN;
++
++	return (payload_space > overhead) ? payload_space - overhead : 0;
++}
++
++static inline size_t crypto_caller_aead_max_update_size(const struct service_client *context)
++{
++	/* Returns the maximum number of bytes that may be
++	 * carried as a parameter of the aead_update operation
++	 * using the packed-c encoding.
++	 */
++	size_t payload_space = context->service_info.max_payload;
++	size_t overhead = sizeof(struct ts_crypto_aead_update_in) + TLV_HDR_LEN;
++
++	/* Allow for output to be a whole number of blocks */
++	overhead += PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE;
++
++	return (payload_space > overhead) ? payload_space - overhead : 0;
++}
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/components/service/crypto/client/caller/stub/crypto_caller_aead.h b/components/service/crypto/client/caller/stub/crypto_caller_aead.h
+index 18aa8cec..455e7ac1 100644
+--- a/components/service/crypto/client/caller/stub/crypto_caller_aead.h
++++ b/components/service/crypto/client/caller/stub/crypto_caller_aead.h
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -135,6 +135,16 @@ static inline psa_status_t crypto_caller_aead_abort(struct service_client *conte
+ 	return PSA_ERROR_NOT_SUPPORTED;
+ }
+ 
++static inline size_t crypto_caller_aead_max_update_ad_size(const struct service_client *context)
++{
++	return 0;
++}
++
++static inline size_t crypto_caller_aead_max_update_size(const struct service_client *context)
++{
++	return 0;
++}
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/components/service/crypto/client/psa/psa_aead.c b/components/service/crypto/client/psa/psa_aead.c
+index 22fd3da1..e4579e63 100644
+--- a/components/service/crypto/client/psa/psa_aead.c
++++ b/components/service/crypto/client/psa/psa_aead.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -8,37 +8,6 @@
+ #include "psa_crypto_client.h"
+ #include "crypto_caller_selector.h"
+ 
+-
+-psa_status_t psa_aead_encrypt(psa_key_id_t key,
+-	psa_algorithm_t alg,
+-	const uint8_t *nonce,
+-	size_t nonce_length,
+-	const uint8_t *additional_data,
+-	size_t additional_data_length,
+-	const uint8_t *plaintext,
+-	size_t plaintext_length,
+-	uint8_t *aeadtext,
+-	size_t aeadtext_size,
+-	size_t *aeadtext_length)
+-{
+-	return PSA_ERROR_NOT_SUPPORTED;
+-}
+-
+-psa_status_t psa_aead_decrypt(psa_key_id_t key,
+-	psa_algorithm_t alg,
+-	const uint8_t *nonce,
+-	size_t nonce_length,
+-	const uint8_t *additional_data,
+-	size_t additional_data_length,
+-	const uint8_t *aeadtext,
+-	size_t aeadtext_length,
+-	uint8_t *plaintext,
+-	size_t plaintext_size,
+-	size_t *plaintext_length)
+-{
+-	return PSA_ERROR_NOT_SUPPORTED;
+-}
+-
+ psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation,
+ 	psa_key_id_t key,
+ 	psa_algorithm_t alg)
+@@ -143,3 +112,191 @@ psa_status_t psa_aead_abort(psa_aead_operation_t *operation)
+ 	return crypto_caller_aead_abort(&psa_crypto_client_instance.base,
+ 		operation->handle);
+ }
++
++static psa_status_t multi_aead_update_ad(psa_aead_operation_t *operation,
++	const uint8_t *input,
++	size_t input_length)
++{
++	psa_status_t psa_status = PSA_SUCCESS;
++	size_t max_update_size =
++		crypto_caller_aead_max_update_ad_size(&psa_crypto_client_instance.base);
++	size_t bytes_input = 0;
++
++	if (!max_update_size) {
++
++		/* Don't know the max update size so assume that the entire
++		 * input and output can be handled in a single update.  If
++		 * this isn't true, the first aead update operation will fail
++		 * safely.
++		 */
++		max_update_size = input_length;
++	}
++
++	while (bytes_input < input_length) {
++
++		size_t bytes_remaining = input_length - bytes_input;
++		size_t update_len = (bytes_remaining < max_update_size) ?
++			bytes_remaining :
++			max_update_size;
++
++		psa_status = psa_aead_update_ad(operation,
++			&input[bytes_input], update_len);
++
++		if (psa_status != PSA_SUCCESS) break;
++
++		bytes_input += update_len;
++	}
++
++	return psa_status;
++}
++
++static psa_status_t multi_aead_update(psa_aead_operation_t *operation,
++	const uint8_t *input,
++	size_t input_length,
++	uint8_t *output,
++	size_t output_size,
++	size_t *output_length)
++{
++	psa_status_t psa_status = PSA_SUCCESS;
++	size_t max_update_size =
++		crypto_caller_aead_max_update_size(&psa_crypto_client_instance.base);
++	size_t bytes_input = 0;
++	size_t bytes_output = 0;
++
++	*output_length = 0;
++
++	if (!max_update_size) {
++
++		/* Don't know the max update size so assume that the entire
++		 * input and output can be handled in a single update.  If
++		 * this isn't true, the first aead update operation will fail
++		 * safely.
++		 */
++		max_update_size = input_length;
++	}
++
++	while ((bytes_input < input_length) && (bytes_output < output_size)) {
++
++		size_t update_output_len = 0;
++		size_t bytes_remaining = input_length - bytes_input;
++		size_t update_len = (bytes_remaining < max_update_size) ?
++			bytes_remaining :
++			max_update_size;
++
++		psa_status = psa_aead_update(operation,
++			&input[bytes_input], update_len,
++			&output[bytes_output], output_size - bytes_output, &update_output_len);
++
++		if (psa_status != PSA_SUCCESS) break;
++
++		bytes_input += update_len;
++		bytes_output += update_output_len;
++	}
++
++	if (psa_status == PSA_SUCCESS) {
++
++		*output_length = bytes_output;
++	}
++
++	return psa_status;
++}
++
++psa_status_t psa_aead_encrypt(psa_key_id_t key,
++	psa_algorithm_t alg,
++	const uint8_t *nonce,
++	size_t nonce_length,
++	const uint8_t *additional_data,
++	size_t additional_data_length,
++	const uint8_t *plaintext,
++	size_t plaintext_length,
++	uint8_t *aeadtext,
++	size_t aeadtext_size,
++	size_t *aeadtext_length)
++{
++	psa_aead_operation_t operation = psa_aead_operation_init();
++	size_t bytes_output = 0;
++	*aeadtext_length = 0;
++
++	psa_status_t psa_status = psa_aead_encrypt_setup(&operation, key, alg);
++	if (psa_status != PSA_SUCCESS) return psa_status;
++
++	if ((psa_status = psa_aead_set_lengths(&operation, additional_data_length, plaintext_length),
++			psa_status == PSA_SUCCESS) &&
++		(psa_status = psa_aead_set_nonce(&operation, nonce, nonce_length),
++			psa_status == PSA_SUCCESS) &&
++		(psa_status = multi_aead_update_ad(&operation, additional_data, additional_data_length),
++			psa_status == PSA_SUCCESS) &&
++		(psa_status = multi_aead_update(&operation, plaintext, plaintext_length,
++			aeadtext, aeadtext_size, &bytes_output),
++			psa_status == PSA_SUCCESS))
++	{
++		size_t remaining_aead_len = 0;
++		size_t tag_len = 0;
++
++		psa_status = psa_aead_finish(&operation,
++			NULL, 0, &remaining_aead_len,
++			&aeadtext[bytes_output], aeadtext_size - bytes_output, &tag_len);
++
++		if (psa_status == PSA_SUCCESS) {
++
++			*aeadtext_length = bytes_output + remaining_aead_len + tag_len;
++		}
++	}
++	else {
++
++		psa_aead_abort(&operation);
++	}
++
++	return psa_status;
++}
++
++psa_status_t psa_aead_decrypt(psa_key_id_t key,
++	psa_algorithm_t alg,
++	const uint8_t *nonce,
++	size_t nonce_length,
++	const uint8_t *additional_data,
++	size_t additional_data_length,
++	const uint8_t *aeadtext,
++	size_t aeadtext_length,
++	uint8_t *plaintext,
++	size_t plaintext_size,
++	size_t *plaintext_length)
++{
++	psa_aead_operation_t operation = psa_aead_operation_init();
++	size_t bytes_output = 0;
++	*plaintext_length = 0;
++
++	psa_status_t psa_status = psa_aead_decrypt_setup(&operation, key, alg);
++	if (psa_status != PSA_SUCCESS) return psa_status;
++
++	size_t tag_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
++	size_t ciphertext_len = (aeadtext_length > tag_len) ? aeadtext_length - tag_len : 0;
++
++	if ((psa_status = psa_aead_set_lengths(&operation, additional_data_length, ciphertext_len),
++			psa_status == PSA_SUCCESS) &&
++		(psa_status = psa_aead_set_nonce(&operation, nonce, nonce_length),
++			psa_status == PSA_SUCCESS) &&
++		(psa_status = multi_aead_update_ad(&operation, additional_data, additional_data_length),
++			psa_status == PSA_SUCCESS) &&
++		(psa_status = multi_aead_update(&operation, aeadtext, ciphertext_len,
++			plaintext, plaintext_size, &bytes_output),
++			psa_status == PSA_SUCCESS))
++	{
++		size_t remaining_plaintext_len = 0;
++
++		psa_status = psa_aead_verify(&operation,
++			NULL, 0, &remaining_plaintext_len,
++			&aeadtext[bytes_output], aeadtext_length - bytes_output);
++
++		if (psa_status == PSA_SUCCESS) {
++
++			*plaintext_length = bytes_output + remaining_plaintext_len;
++		}
++	}
++	else {
++
++		psa_aead_abort(&operation);
++	}
++
++	return psa_status;
++}
+diff --git a/components/service/crypto/factory/full/crypto_provider_factory.c b/components/service/crypto/factory/full/crypto_provider_factory.c
+index 2d926eb6..ee2b4473 100644
+--- a/components/service/crypto/factory/full/crypto_provider_factory.c
++++ b/components/service/crypto/factory/full/crypto_provider_factory.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  *
+@@ -17,6 +17,8 @@
+ #include <service/crypto/provider/extension/key_derivation/serializer/packed-c/packedc_key_derivation_provider_serializer.h>
+ #include <service/crypto/provider/extension/mac/mac_provider.h>
+ #include <service/crypto/provider/extension/mac/serializer/packed-c/packedc_mac_provider_serializer.h>
++#include <service/crypto/provider/extension/aead/aead_provider.h>
++#include <service/crypto/provider/extension/aead/serializer/packed-c/packedc_aead_provider_serializer.h>
+ #include <service/discovery/provider/discovery_provider.h>
+ #include <service/discovery/provider/serializer/packed-c/packedc_discovery_provider_serializer.h>
+ 
+@@ -34,6 +36,7 @@ static struct full_crypto_provider
+ 	struct cipher_provider cipher_provider;
+ 	struct key_derivation_provider key_derivation_provider;
+ 	struct mac_provider mac_provider;
++	struct aead_provider aead_provider;
+ 
+ } instance;
+ 
+@@ -98,6 +101,17 @@ struct crypto_provider *crypto_provider_factory_create(void)
+ 	crypto_provider_extend(&instance.crypto_provider,
+ 		&instance.mac_provider.base_provider);
+ 
++	/**
++	 * Extend with aead operations
++	 */
++	aead_provider_init(&instance.aead_provider);
++
++	aead_provider_register_serializer(&instance.aead_provider,
++		TS_RPC_ENCODING_PACKED_C, packedc_aead_provider_serializer_instance());
++
++	crypto_provider_extend(&instance.crypto_provider,
++		&instance.aead_provider.base_provider);
++
+ 	return &instance.crypto_provider;
+ }
+ 
+diff --git a/deployments/component-test/component-test.cmake b/deployments/component-test/component-test.cmake
+index a0233c34..c3b015ab 100644
+--- a/deployments/component-test/component-test.cmake
++++ b/deployments/component-test/component-test.cmake
+@@ -1,5 +1,5 @@
+ #-------------------------------------------------------------------------------
+-# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++# Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+ #
+ # SPDX-License-Identifier: BSD-3-Clause
+ #
+@@ -85,6 +85,8 @@ add_components(
+ 		"components/service/crypto/provider/extension/key_derivation/serializer/packed-c"
+ 		"components/service/crypto/provider/extension/mac"
+ 		"components/service/crypto/provider/extension/mac/serializer/packed-c"
++		"components/service/crypto/provider/extension/aead"
++		"components/service/crypto/provider/extension/aead/serializer/packed-c"
+ 		"components/service/crypto/provider/test"
+ 		"components/service/crypto/backend/mbedcrypto"
+ 		"components/service/crypto/factory/full"
+diff --git a/deployments/crypto/opteesp/CMakeLists.txt b/deployments/crypto/opteesp/CMakeLists.txt
+index 8ada74e9..eb5d0847 100644
+--- a/deployments/crypto/opteesp/CMakeLists.txt
++++ b/deployments/crypto/opteesp/CMakeLists.txt
+@@ -1,5 +1,5 @@
+ #-------------------------------------------------------------------------------
+-# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++# Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+ #
+ # SPDX-License-Identifier: BSD-3-Clause
+ #
+@@ -62,6 +62,8 @@ add_components(TARGET "crypto-sp"
+ 		"components/service/crypto/provider/extension/key_derivation/serializer/packed-c"
+ 		"components/service/crypto/provider/extension/mac"
+ 		"components/service/crypto/provider/extension/mac/serializer/packed-c"
++		"components/service/crypto/provider/extension/aead"
++		"components/service/crypto/provider/extension/aead/serializer/packed-c"
+ 		"components/service/crypto/factory/full"
+ 		"components/service/crypto/backend/mbedcrypto"
+ 		"components/service/crypto/backend/mbedcrypto/trng_adapter/platform"
+diff --git a/deployments/libts/linux-pc/CMakeLists.txt b/deployments/libts/linux-pc/CMakeLists.txt
+index fc98407c..97eaaa73 100644
+--- a/deployments/libts/linux-pc/CMakeLists.txt
++++ b/deployments/libts/linux-pc/CMakeLists.txt
+@@ -1,5 +1,5 @@
+ #-------------------------------------------------------------------------------
+-# Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
++# Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
+ #
+ # SPDX-License-Identifier: BSD-3-Clause
+ #
+@@ -71,6 +71,8 @@ add_components(
+ 		"components/service/crypto/provider/extension/key_derivation/serializer/packed-c"
+ 		"components/service/crypto/provider/extension/mac"
+ 		"components/service/crypto/provider/extension/mac/serializer/packed-c"
++		"components/service/crypto/provider/extension/aead"
++		"components/service/crypto/provider/extension/aead/serializer/packed-c"
+ 		"components/service/crypto/factory/full"
+ 		"components/service/crypto/backend/mbedcrypto"
+ 		"components/service/crypto/backend/mbedcrypto/trng_adapter/linux"
+diff --git a/deployments/se-proxy/opteesp/CMakeLists.txt b/deployments/se-proxy/opteesp/CMakeLists.txt
+index 953bb716..24a8ca65 100644
+--- a/deployments/se-proxy/opteesp/CMakeLists.txt
++++ b/deployments/se-proxy/opteesp/CMakeLists.txt
+@@ -1,5 +1,5 @@
+ #-------------------------------------------------------------------------------
+-# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+ #
+ # SPDX-License-Identifier: BSD-3-Clause
+ #
+@@ -70,6 +70,8 @@ add_components(TARGET "se-proxy"
+ 		"components/service/crypto/provider/extension/key_derivation/serializer/packed-c"
+ 		"components/service/crypto/provider/extension/mac"
+ 		"components/service/crypto/provider/extension/mac/serializer/packed-c"
++		"components/service/crypto/provider/extension/aead"
++		"components/service/crypto/provider/extension/aead/serializer/packed-c"
+ 		"components/service/crypto/factory/full"
+ 		"components/service/secure_storage/include"
+ 		"components/service/secure_storage/frontend/secure_storage_provider"
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0039-Add-IV-generation-to-one-shot-cipher-operation.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0039-Add-IV-generation-to-one-shot-cipher-operation.patch
new file mode 100644
index 0000000..0c93a26
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0039-Add-IV-generation-to-one-shot-cipher-operation.patch
@@ -0,0 +1,96 @@
+From 43388a8e071980d9146f935f486a859d0a04322b Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Tue, 15 Feb 2022 15:46:58 +0000
+Subject: [PATCH] Add IV generation to one-shot cipher operation
+
+The functions psa_cipher_encrypt and psa_cipher_decrypt are
+one-shot operations that can take an arbitrary sized input.
+These operations are implemented as client-side functions
+that use multi-part cipher operations to allow large inputs
+to be handled. The existing implementations were missing the
+generation and setting of the IV at the start of the data.
+This was leading to PSA Arch test failures (248 & 249). This
+commit adds the missing IV handling and resolves the test
+failures.
+
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: I4afb555ee7062ebb387e5bb27fb1e082288ad8c7
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ .../service/crypto/client/psa/psa_cipher.c    | 40 +++++++++++++++----
+ 1 file changed, 33 insertions(+), 7 deletions(-)
+
+diff --git a/components/service/crypto/client/psa/psa_cipher.c b/components/service/crypto/client/psa/psa_cipher.c
+index 3ab8ea21..111af829 100644
+--- a/components/service/crypto/client/psa/psa_cipher.c
++++ b/components/service/crypto/client/psa/psa_cipher.c
+@@ -8,7 +8,6 @@
+ #include "psa_crypto_client.h"
+ #include "crypto_caller_selector.h"
+ 
+-
+ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
+ 	psa_key_id_t key,
+ 	psa_algorithm_t alg)
+@@ -171,9 +170,16 @@ psa_status_t psa_cipher_encrypt(psa_key_id_t key,
+ 
+ 	if (psa_status == PSA_SUCCESS) {
+ 
++		size_t ciphertext_len = 0;
++		size_t iv_len = 0;
++
++		psa_cipher_generate_iv(&operation, output, output_size, &iv_len);
++
+ 		psa_status = multi_cipher_update(&operation,
+ 			input, input_length,
+-			output, output_size, output_length);
++			&output[iv_len], output_size - iv_len, &ciphertext_len);
++
++		*output_length = iv_len + ciphertext_len;
+ 	}
+ 
+ 	return psa_status;
+@@ -187,14 +193,34 @@ psa_status_t psa_cipher_decrypt(psa_key_id_t key,
+ 	size_t output_size,
+ 	size_t *output_length)
+ {
+-	psa_cipher_operation_t operation = psa_cipher_operation_init();
+-	psa_status_t psa_status = psa_cipher_decrypt_setup(&operation, key, alg);
++	psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
++	psa_status_t psa_status = psa_get_key_attributes(key, &attributes);
+ 
+ 	if (psa_status == PSA_SUCCESS) {
+ 
+-		psa_status = multi_cipher_update(&operation,
+-			input, input_length,
+-			output, output_size, output_length);
++		psa_cipher_operation_t operation = psa_cipher_operation_init();
++		psa_status = psa_cipher_decrypt_setup(&operation, key, alg);
++
++		if (psa_status == PSA_SUCCESS) {
++
++			size_t iv_len = PSA_CIPHER_IV_LENGTH(psa_get_key_type(&attributes), alg);
++
++			if (input_length >= iv_len) {
++
++				psa_cipher_set_iv(&operation, input, iv_len);
++
++				psa_status = multi_cipher_update(&operation,
++					&input[iv_len], input_length - iv_len,
++					output, output_size, output_length);
++			}
++			else {
++
++				psa_cipher_abort(&operation);
++				psa_status = PSA_ERROR_INVALID_ARGUMENT;
++			}
++		}
++
++		psa_reset_key_attributes(&attributes);
+ 	}
+ 
+ 	return psa_status;
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0040-Fix-multi-part-termination-on-error.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0040-Fix-multi-part-termination-on-error.patch
new file mode 100644
index 0000000..bdafcea
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0040-Fix-multi-part-termination-on-error.patch
@@ -0,0 +1,241 @@
+From 07277e2ab4b54e5844c28f0cb33e64a91aa5f492 Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Wed, 16 Feb 2022 10:37:04 +0000
+Subject: [PATCH] Fix multi-part termination on error
+
+For multi-part operations, the PSA Crypto API specifies that if
+the final operation does not return PSA_SUCCESS, the abort
+operaion must be called by a client to clean-up the operation.
+This change modifies behaviour in-line with the API definition.
+
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: Ia3d3ec004164647a7ab5988cac45c39c22e76e9a
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ components/service/crypto/client/psa/psa_aead.c       |  8 ++++++++
+ components/service/crypto/client/psa/psa_cipher.c     |  4 ++++
+ components/service/crypto/client/psa/psa_hash.c       | 10 ++++++++++
+ components/service/crypto/client/psa/psa_mac.c        | 10 ++++++++++
+ .../crypto/provider/extension/aead/aead_provider.c    | 10 +++++-----
+ .../provider/extension/cipher/cipher_provider.c       |  6 +++---
+ .../crypto/provider/extension/hash/hash_provider.c    |  6 +++---
+ .../crypto/provider/extension/mac/mac_provider.c      | 11 +++++++----
+ 8 files changed, 50 insertions(+), 15 deletions(-)
+
+diff --git a/components/service/crypto/client/psa/psa_aead.c b/components/service/crypto/client/psa/psa_aead.c
+index e4579e63..559eb6a3 100644
+--- a/components/service/crypto/client/psa/psa_aead.c
++++ b/components/service/crypto/client/psa/psa_aead.c
+@@ -241,6 +241,10 @@ psa_status_t psa_aead_encrypt(psa_key_id_t key,
+ 
+ 			*aeadtext_length = bytes_output + remaining_aead_len + tag_len;
+ 		}
++		else {
++
++			psa_aead_abort(&operation);
++		}
+ 	}
+ 	else {
+ 
+@@ -292,6 +296,10 @@ psa_status_t psa_aead_decrypt(psa_key_id_t key,
+ 
+ 			*plaintext_length = bytes_output + remaining_plaintext_len;
+ 		}
++		else {
++
++			psa_aead_abort(&operation);
++		}
+ 	}
+ 	else {
+ 
+diff --git a/components/service/crypto/client/psa/psa_cipher.c b/components/service/crypto/client/psa/psa_cipher.c
+index 111af829..4e4264b6 100644
+--- a/components/service/crypto/client/psa/psa_cipher.c
++++ b/components/service/crypto/client/psa/psa_cipher.c
+@@ -146,6 +146,10 @@ static psa_status_t multi_cipher_update(psa_cipher_operation_t *operation,
+ 
+ 				*output_length = bytes_output + finish_output_len;
+ 			}
++			else {
++
++				psa_cipher_abort(operation);
++			}
+ 		}
+ 		else {
+ 
+diff --git a/components/service/crypto/client/psa/psa_hash.c b/components/service/crypto/client/psa/psa_hash.c
+index 83278de6..e5dd0030 100644
+--- a/components/service/crypto/client/psa/psa_hash.c
++++ b/components/service/crypto/client/psa/psa_hash.c
+@@ -137,6 +137,11 @@ psa_status_t psa_hash_compare(psa_algorithm_t alg,
+ 	if (psa_status == PSA_SUCCESS) {
+ 
+ 		psa_status = psa_hash_verify(&operation, hash, hash_length);
++
++		if (psa_status != PSA_SUCCESS) {
++
++			psa_hash_abort(&operation);
++		}
+ 	}
+ 
+ 	return psa_status;
+@@ -155,6 +160,11 @@ psa_status_t psa_hash_compute(psa_algorithm_t alg,
+ 	if (psa_status == PSA_SUCCESS) {
+ 
+ 		psa_status = psa_hash_finish(&operation, hash, hash_size, hash_length);
++
++		if (psa_status != PSA_SUCCESS) {
++
++			psa_hash_abort(&operation);
++		}
+ 	}
+ 
+ 	return psa_status;
+diff --git a/components/service/crypto/client/psa/psa_mac.c b/components/service/crypto/client/psa/psa_mac.c
+index 5c5eb32a..a3db8644 100644
+--- a/components/service/crypto/client/psa/psa_mac.c
++++ b/components/service/crypto/client/psa/psa_mac.c
+@@ -129,6 +129,11 @@ psa_status_t psa_mac_verify(psa_key_id_t key,
+ 	if (psa_status == PSA_SUCCESS) {
+ 
+ 		psa_status = psa_mac_verify_finish(&operation, mac, mac_length);
++
++		if (psa_status != PSA_SUCCESS) {
++
++			psa_mac_abort(&operation);
++		}
+ 	}
+ 
+ 	return psa_status;
+@@ -153,6 +158,11 @@ psa_status_t psa_mac_compute(psa_key_id_t key,
+ 	if (psa_status == PSA_SUCCESS) {
+ 
+ 		psa_status = psa_mac_sign_finish(&operation, mac, mac_size, mac_length);
++
++		if (psa_status != PSA_SUCCESS) {
++
++			psa_mac_abort(&operation);
++		}
+ 	}
+ 
+ 	return psa_status;
+diff --git a/components/service/crypto/provider/extension/aead/aead_provider.c b/components/service/crypto/provider/extension/aead/aead_provider.c
+index f4e81a03..14a25436 100644
+--- a/components/service/crypto/provider/extension/aead/aead_provider.c
++++ b/components/service/crypto/provider/extension/aead/aead_provider.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -369,9 +369,9 @@ static rpc_status_t aead_finish_handler(void *context, struct call_req *req)
+ 				rpc_status = serializer->serialize_aead_finish_resp(resp_buf,
+ 					ciphertext, ciphertext_len,
+ 					tag, tag_len);
+-			}
+ 
+-			crypto_context_pool_free(&this_instance->context_pool, crypto_context);
++				crypto_context_pool_free(&this_instance->context_pool, crypto_context);
++			}
+ 		}
+ 
+ 		call_req_set_opstatus(req, psa_status);
+@@ -418,9 +418,9 @@ static rpc_status_t aead_verify_handler(void *context, struct call_req *req)
+ 				struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ 				rpc_status = serializer->serialize_aead_verify_resp(resp_buf,
+ 					plaintext, plaintext_len);
+-			}
+ 
+-			crypto_context_pool_free(&this_instance->context_pool, crypto_context);
++				crypto_context_pool_free(&this_instance->context_pool, crypto_context);
++			}
+ 		}
+ 
+ 		call_req_set_opstatus(req, psa_status);
+diff --git a/components/service/crypto/provider/extension/cipher/cipher_provider.c b/components/service/crypto/provider/extension/cipher/cipher_provider.c
+index 8e7a86de..a5dd0371 100644
+--- a/components/service/crypto/provider/extension/cipher/cipher_provider.c
++++ b/components/service/crypto/provider/extension/cipher/cipher_provider.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -283,9 +283,9 @@ static rpc_status_t cipher_finish_handler(void *context, struct call_req* req)
+ 
+ 				struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ 				rpc_status = serializer->serialize_cipher_finish_resp(resp_buf, output, output_len);
+-			}
+ 
+-			crypto_context_pool_free(&this_instance->context_pool, crypto_context);
++				crypto_context_pool_free(&this_instance->context_pool, crypto_context);
++			}
+ 		}
+ 
+ 		call_req_set_opstatus(req, psa_status);
+diff --git a/components/service/crypto/provider/extension/hash/hash_provider.c b/components/service/crypto/provider/extension/hash/hash_provider.c
+index 2c560513..fd39d440 100644
+--- a/components/service/crypto/provider/extension/hash/hash_provider.c
++++ b/components/service/crypto/provider/extension/hash/hash_provider.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -179,9 +179,9 @@ static rpc_status_t hash_finish_handler(void *context, struct call_req* req)
+ 
+ 				struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ 				rpc_status = serializer->serialize_hash_finish_resp(resp_buf, hash, hash_len);
+-			}
+ 
+-			crypto_context_pool_free(&this_instance->context_pool, crypto_context);
++				crypto_context_pool_free(&this_instance->context_pool, crypto_context);
++			}
+ 		}
+ 
+ 		call_req_set_opstatus(req, psa_status);
+diff --git a/components/service/crypto/provider/extension/mac/mac_provider.c b/components/service/crypto/provider/extension/mac/mac_provider.c
+index 96fe4cf3..eef55586 100644
+--- a/components/service/crypto/provider/extension/mac/mac_provider.c
++++ b/components/service/crypto/provider/extension/mac/mac_provider.c
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++ * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+  *
+  * SPDX-License-Identifier: BSD-3-Clause
+  */
+@@ -181,9 +181,9 @@ static rpc_status_t mac_sign_finish_handler(void *context, struct call_req* req)
+ 
+ 				struct call_param_buf *resp_buf = call_req_get_resp_buf(req);
+ 				rpc_status = serializer->serialize_mac_sign_finish_resp(resp_buf, mac, mac_len);
+-			}
+ 
+-			crypto_context_pool_free(&this_instance->context_pool, crypto_context);
++				crypto_context_pool_free(&this_instance->context_pool, crypto_context);
++			}
+ 		}
+ 
+ 		call_req_set_opstatus(req, psa_status);
+@@ -220,7 +220,10 @@ static rpc_status_t mac_verify_finish_handler(void *context, struct call_req* re
+ 
+ 			psa_status = psa_mac_verify_finish(&crypto_context->op.mac, mac, mac_len);
+ 
+-			crypto_context_pool_free(&this_instance->context_pool, crypto_context);
++			if (psa_status == PSA_SUCCESS) {
++
++				crypto_context_pool_free(&this_instance->context_pool, crypto_context);
++			}
+ 		}
+ 
+ 		call_req_set_opstatus(req, psa_status);
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0041-Abort-AEAD-operation-if-client-provided-buffer-is-to.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0041-Abort-AEAD-operation-if-client-provided-buffer-is-to.patch
new file mode 100644
index 0000000..6a11552
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0041-Abort-AEAD-operation-if-client-provided-buffer-is-to.patch
@@ -0,0 +1,49 @@
+From 92987ec20beedb44d08d429947958c1c068d815c Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Wed, 16 Feb 2022 11:36:09 +0000
+Subject: [PATCH] Abort AEAD operation if client provided buffer is too small
+
+To enable PSA Arch test c258 to pass, handling is added in the
+PSA API client adaptor for AEAD (psa_aead.c) to abort an AEAD
+operation if an update operation is performed but the client
+provided buffer for the output is too small.
+
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: Ib4b26ebc0a83a8928e1b643fba4becd935f6deb0
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ components/service/crypto/client/psa/psa_aead.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/components/service/crypto/client/psa/psa_aead.c b/components/service/crypto/client/psa/psa_aead.c
+index 559eb6a3..c820d222 100644
+--- a/components/service/crypto/client/psa/psa_aead.c
++++ b/components/service/crypto/client/psa/psa_aead.c
+@@ -74,10 +74,22 @@ psa_status_t psa_aead_update(psa_aead_operation_t *operation,
+ 	size_t output_size,
+ 	size_t *output_length)
+ {
+-	return crypto_caller_aead_update(&psa_crypto_client_instance.base,
++	psa_status_t status = crypto_caller_aead_update(&psa_crypto_client_instance.base,
+ 		operation->handle,
+ 		input, input_length,
+ 		output, output_size, output_length);
++
++	/*
++	 * If too small a buffer has been provided for the output, the operation
++	 * state will have been updated but the result can't be put anywhere. This
++	 * is an unrecoveral condition so abort the operation.
++	 */
++	if (status == PSA_ERROR_BUFFER_TOO_SMALL) {
++
++		psa_aead_abort(operation);
++	}
++
++	return status;
+ }
+ 
+ psa_status_t psa_aead_finish(psa_aead_operation_t *operation,
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0042-Peg-to-updated-t_cose-version-fc3a4b2c.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0042-Peg-to-updated-t_cose-version-fc3a4b2c.patch
new file mode 100644
index 0000000..fedb79c
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0042-Peg-to-updated-t_cose-version-fc3a4b2c.patch
@@ -0,0 +1,94 @@
+From 75c0689513e7da7fb26bf23c1da4e1aa49783d46 Mon Sep 17 00:00:00 2001
+From: Julian Hall <julian.hall@arm.com>
+Date: Tue, 11 Jan 2022 09:43:52 +0000
+Subject: [PATCH] Peg to updated t_cose version fc3a4b2c
+
+The current version of TS fails to build due to a regression introduced
+by a new t_cose version in the upstream project.
+The issue is caused by the t_cose external component incorrectly using
+tip of master as the upstream version id, which makes strict dependency
+control impossible. Change the upstream version id to an SHA, to enable
+controlling compatibility issues introduced by future upstream updates.
+
+At the same time update the dependency to the current latest version.
+The upstream project is now compatile with mbedtls 3.0.0 API changes
+so the previously required compatibility patch has been removed.
+
+Signed-off-by: Julian Hall <julian.hall@arm.com>
+Change-Id: I9491a5210904cc369846da2af45b0f7e5913bed8
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ .../0002-add-tls3_0_0-compatibility.patch     | 31 -------------------
+ external/t_cose/t_cose.cmake                  |  5 ++-
+ 2 files changed, 2 insertions(+), 34 deletions(-)
+ delete mode 100644 external/t_cose/0002-add-tls3_0_0-compatibility.patch
+
+diff --git a/external/t_cose/0002-add-tls3_0_0-compatibility.patch b/external/t_cose/0002-add-tls3_0_0-compatibility.patch
+deleted file mode 100644
+index 20a7d131..00000000
+--- a/external/t_cose/0002-add-tls3_0_0-compatibility.patch
++++ /dev/null
+@@ -1,31 +0,0 @@
+-diff --git a/crypto_adapters/t_cose_psa_crypto.c b/crypto_adapters/t_cose_psa_crypto.c
+-index 49c5b60..3aa7b58 100644
+---- a/crypto_adapters/t_cose_psa_crypto.c
+-+++ b/crypto_adapters/t_cose_psa_crypto.c
+-@@ -99,7 +99,7 @@ static enum t_cose_err_t psa_status_to_t_cose_error_signing(psa_status_t err)
+-            err == PSA_ERROR_INVALID_SIGNATURE   ? T_COSE_ERR_SIG_VERIFY :
+-            err == PSA_ERROR_NOT_SUPPORTED       ? T_COSE_ERR_UNSUPPORTED_SIGNING_ALG:
+-            err == PSA_ERROR_INSUFFICIENT_MEMORY ? T_COSE_ERR_INSUFFICIENT_MEMORY :
+--           err == PSA_ERROR_TAMPERING_DETECTED  ? T_COSE_ERR_TAMPERING_DETECTED :
+-+           err == PSA_ERROR_CORRUPTION_DETECTED ? T_COSE_ERR_TAMPERING_DETECTED :
+-                                                   T_COSE_ERR_SIG_FAIL;
+- }
+- 
+-@@ -152,7 +152,7 @@ t_cose_crypto_pub_key_verify(int32_t               cose_algorithm_id,
+-      * Crypto ceases providing backwards compatibility then this code
+-      * has to be changed to use psa_verify_hash().
+-      */
+--    psa_result = psa_asymmetric_verify(verification_key_psa,
+-+    psa_result = psa_verify_hash(verification_key_psa,
+-                                        psa_alg_id,
+-                                        hash_to_verify.ptr,
+-                                        hash_to_verify.len,
+-@@ -212,7 +212,7 @@ t_cose_crypto_pub_key_sign(int32_t                cose_algorithm_id,
+-      * providing backwards compatibility then this code has to be
+-      * changed to use psa_sign_hash().
+-      */
+--    psa_result = psa_asymmetric_sign(signing_key_psa,
+-+    psa_result = psa_sign_hash(signing_key_psa,
+-                                      psa_alg_id,
+-                                      hash_to_sign.ptr,
+-                                      hash_to_sign.len,
+diff --git a/external/t_cose/t_cose.cmake b/external/t_cose/t_cose.cmake
+index 660824bd..9321466f 100644
+--- a/external/t_cose/t_cose.cmake
++++ b/external/t_cose/t_cose.cmake
+@@ -1,5 +1,5 @@
+ #-------------------------------------------------------------------------------
+-# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
++# Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
+ #
+ # SPDX-License-Identifier: BSD-3-Clause
+ #
+@@ -16,7 +16,7 @@ endif()
+ 
+ # External component details
+ set(T_COSE_URL "https://github.com/laurencelundblade/t_cose.git" CACHE STRING "t_cose repository URL")
+-set(T_COSE_REFSPEC "master" CACHE STRING "t_cose git refspec")
++set(T_COSE_REFSPEC "fc3a4b2c7196ff582e8242de8bd4a1bc4eec577f" CACHE STRING "t_cose git refspec")
+ set(T_COSE_INSTALL_PATH "${CMAKE_CURRENT_BINARY_DIR}/t_cose_install" CACHE PATH "t_cose installation directory")
+ set(T_COSE_PACKAGE_PATH "${T_COSE_INSTALL_PATH}/libt_cose/cmake" CACHE PATH "t_cose CMake package directory")
+ 
+@@ -37,7 +37,6 @@ FetchContent_Declare(
+ 
+ 	PATCH_COMMAND git stash
+ 		COMMAND git am ${CMAKE_CURRENT_LIST_DIR}/0001-add-install-definition.patch
+-		COMMAND git apply ${CMAKE_CURRENT_LIST_DIR}/0002-add-tls3_0_0-compatibility.patch
+ 		COMMAND git reset HEAD~1
+ 
+ )
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0043-pass-sysroot_yocto.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0043-pass-sysroot_yocto.patch
new file mode 100644
index 0000000..64ac094
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0043-pass-sysroot_yocto.patch
@@ -0,0 +1,110 @@
+From 24436d459ddde697c89ff947c821cec9c5e0906e Mon Sep 17 00:00:00 2001
+From: Vishnu Banavath <vishnu.banavath@arm.com>
+Date: Wed, 16 Feb 2022 15:55:55 +0000
+Subject: [PATCH] pass sysroot_yocto
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ deployments/libts/libts-import.cmake         |  3 +++
+ external/MbedTLS/MbedTLS.cmake               |  1 +
+ external/psa_arch_tests/psa_arch_tests.cmake | 25 +++++++++++++-------
+ 3 files changed, 20 insertions(+), 9 deletions(-)
+
+diff --git a/deployments/libts/libts-import.cmake b/deployments/libts/libts-import.cmake
+index 792ba86c..b900ce3f 100644
+--- a/deployments/libts/libts-import.cmake
++++ b/deployments/libts/libts-import.cmake
+@@ -27,9 +27,12 @@ set(LIBTS_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/_deps/libts-build" CACHE PATH
+ 
+ file(MAKE_DIRECTORY ${LIBTS_BINARY_DIR})
+ 
++set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --sysroot=${SYSROOT_YOCTO}")
++
+ #Configure the library
+ execute_process(COMMAND
+ 	${CMAKE_COMMAND}
++                -DCMAKE_SYSROOT=${SYSROOT_YOCTO}
+ 		-DCMAKE_INSTALL_PREFIX=${LIBTS_INSTALL_PATH}
+ 		-GUnix\ Makefiles
+ 		${LIBTS_SOURCE_DIR}
+diff --git a/external/MbedTLS/MbedTLS.cmake b/external/MbedTLS/MbedTLS.cmake
+index 3350d8a0..33467cf0 100644
+--- a/external/MbedTLS/MbedTLS.cmake
++++ b/external/MbedTLS/MbedTLS.cmake
+@@ -103,6 +103,7 @@ if (NOT MBEDCRYPTO_LIB_FILE)
+ 	execute_process(COMMAND
+ 		${CMAKE_COMMAND} -E env CROSS_COMPILE=${CROSS_COMPILE}
+ 			${CMAKE_COMMAND}
++                                -DCMAKE_SYSROOT=${SYSROOT_YOCTO}
+ 				-DENABLE_PROGRAMS=OFF
+ 				-DENABLE_TESTING=OFF
+ 				-DUNSAFE_BUILD=ON
+diff --git a/external/psa_arch_tests/psa_arch_tests.cmake b/external/psa_arch_tests/psa_arch_tests.cmake
+index f6d2fb9f..42f73a37 100644
+--- a/external/psa_arch_tests/psa_arch_tests.cmake
++++ b/external/psa_arch_tests/psa_arch_tests.cmake
+@@ -5,30 +5,33 @@
+ #
+ #-------------------------------------------------------------------------------
+ 
+-# Temporarily using modified tests used for tf-m verification
++# Determine the number of processes to run while running parallel builds.
++# Pass -DPROCESSOR_COUNT=<n> to cmake to override.
++if(NOT DEFINED PROCESSOR_COUNT)
++	include(ProcessorCount)
++	ProcessorCount(PROCESSOR_COUNT)
++	set(PROCESSOR_COUNT ${PROCESSOR_COUNT} CACHE STRING "Number of cores to use for parallel builds.")
++endif()
++
+ set(PSA_ARCH_TESTS_URL "https://github.com/bensze01/psa-arch-tests.git" CACHE STRING "psa-arch-tests repository URL")
+ set(PSA_ARCH_TESTS_REFSPEC "fix-multipart-aead" CACHE STRING "psa-arch-tests git refspec")
+-
+-#set(PSA_ARCH_TESTS_URL "https://github.com/ARM-software/psa-arch-tests.git" CACHE STRING "psa-arch-tests repository URL")
+-#set(PSA_ARCH_TESTS_REFSPEC "2a1852252a9b9af655cbe02d5d3c930952d0d798" CACHE STRING "psa-arch-tests v22.01_API1.4_ADAC_BETA")
+ set(PSA_ARCH_TESTS_INSTALL_PATH "${CMAKE_CURRENT_BINARY_DIR}/psa-arch-tests_install" CACHE PATH "psa-arch-tests installation directory")
+ set(PSA_ARCH_TESTS_PACKAGE_PATH "${PSA_ARCH_TESTS_INSTALL_PATH}/libpsa-arch-tests/cmake" CACHE PATH "psa-arch-tests CMake package directory")
+-set(PSA_ARCH_TESTS_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_deps/psa_arch_tests-src" CACHE PATH "psa-arch-tests source.")
++
++include(FetchContent)
+ 
+ # Checking git
+ find_program(GIT_COMMAND "git")
+ if (NOT GIT_COMMAND)
+ 	message(FATAL_ERROR "Please install git")
+ endif()
+-
++if ("${PSA_ARCH_TESTS_PATH}" STREQUAL "DOWNLOAD")
+ # Fetching psa-arch-tests
+ FetchContent_Declare(
+ 	psa-arch-tests
+ 	GIT_REPOSITORY ${PSA_ARCH_TESTS_URL}
+ 	GIT_TAG ${PSA_ARCH_TESTS_REFSPEC}
+ 	GIT_SHALLOW TRUE
+-	PATCH_COMMAND git stash
+-		COMMAND git apply ${CMAKE_CURRENT_LIST_DIR}/modify_attest_config.patch
+ )
+ 
+ # FetchContent_GetProperties exports psa-arch-tests_SOURCE_DIR and psa-arch-tests_BINARY_DIR variables
+@@ -37,7 +40,10 @@ if(NOT psa-arch-tests_POPULATED)
+ 	message(STATUS "Fetching psa-arch-tests")
+ 	FetchContent_Populate(psa-arch-tests)
+ endif()
+-
++else()
++    set(psa-arch-tests_SOURCE_DIR "${TS_ROOT}/../psa-arch-tests")
++    set(psa-arch-tests_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}")
++endif()
+ # Ensure list of include paths is separated correctly
+ string(REPLACE ";" "\\;" PSA_ARCH_TESTS_EXTERNAL_INCLUDE_PATHS "${PSA_ARCH_TESTS_EXTERNAL_INCLUDE_PATHS}")
+ 
+@@ -47,6 +53,7 @@ string(REPLACE ";" " " PSA_ARCH_TEST_EXTERNAL_DEFS "${PSA_ARCH_TEST_EXTERNAL_DEF
+ # Configure the psa-arch-test library
+ execute_process(COMMAND
+ 	${CMAKE_COMMAND}
++			-DCMAKE_SYSROOT=${SYSROOT_YOCTO}
+ 			-DTOOLCHAIN=INHERIT
+ 			-DCMAKE_TOOLCHAIN_FILE=${TS_EXTERNAL_LIB_TOOLCHAIN_FILE}
+ 			-DPSA_INCLUDE_PATHS=${PSA_ARCH_TESTS_EXTERNAL_INCLUDE_PATHS}
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0044-Fix-Crypto-interface-structure-aligned-with-tf-m-cha.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0044-Fix-Crypto-interface-structure-aligned-with-tf-m-cha.patch
new file mode 100644
index 0000000..68d0a97
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0044-Fix-Crypto-interface-structure-aligned-with-tf-m-cha.patch
@@ -0,0 +1,29 @@
+From 0a0007d594db2fceed413cd73e7f08dd8d8ddd57 Mon Sep 17 00:00:00 2001
+From: Satish Kumar <satish.kumar01@arm.com>
+Date: Sun, 13 Feb 2022 09:01:10 +0000
+Subject: [PATCH] Fix: Crypto interface structure aligned with tf-m change.
+
+NO NEED TO RAISE PR: The PR for this FIX  is raied by Emek.
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ components/service/crypto/backend/psa_ipc/crypto_ipc_backend.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/components/service/crypto/backend/psa_ipc/crypto_ipc_backend.h b/components/service/crypto/backend/psa_ipc/crypto_ipc_backend.h
+index c13c20e8..ec25eaf8 100644
+--- a/components/service/crypto/backend/psa_ipc/crypto_ipc_backend.h
++++ b/components/service/crypto/backend/psa_ipc/crypto_ipc_backend.h
+@@ -38,7 +38,8 @@ struct psa_ipc_crypto_pack_iovec {
+ 				      *   multipart operation
+ 				      */
+ 	uint32_t capacity;             /*!< Key derivation capacity */
+-
++	uint32_t ad_length;            /*!< Additional Data length for multipart AEAD */
++	uint32_t plaintext_length;     /*!< Plaintext length for multipart AEAD */
+ 	struct psa_ipc_crypto_aead_pack_input aead_in; /*!< FixMe: Temporarily used for
+ 							    *   AEAD until the API is
+ 							    *   restructured
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0045-Integrate-remaining-psa-ipc-client-APIs.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0045-Integrate-remaining-psa-ipc-client-APIs.patch
new file mode 100644
index 0000000..a08ab32
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0045-Integrate-remaining-psa-ipc-client-APIs.patch
@@ -0,0 +1,494 @@
+From b8060d9e15b1b910cf9b466a3f43088c71d7a38f Mon Sep 17 00:00:00 2001
+From: Satish Kumar <satish.kumar01@arm.com>
+Date: Sun, 13 Feb 2022 09:49:51 +0000
+Subject: [PATCH] Integrate remaining psa-ipc client APIs.
+
+Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ .../caller/psa_ipc/crypto_caller_aead.h       | 297 +++++++++++++++++-
+ .../caller/psa_ipc/crypto_caller_sign_hash.h  |  35 +++
+ .../psa_ipc/crypto_caller_verify_hash.h       |  33 +-
+ 3 files changed, 352 insertions(+), 13 deletions(-)
+
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_aead.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_aead.h
+index 78517fe3..f6aadd8b 100644
+--- a/components/service/crypto/client/caller/psa_ipc/crypto_caller_aead.h
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_aead.h
+@@ -152,7 +152,27 @@ static inline psa_status_t crypto_caller_aead_encrypt_setup(
+ 					    psa_key_id_t key,
+ 					    psa_algorithm_t alg)
+ {
+-	return PSA_ERROR_NOT_SUPPORTED;
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++	    .sfn_id = TFM_CRYPTO_AEAD_ENCRYPT_SETUP_SID,
++	    .key_id = key,
++	    .alg = alg,
++	    .op_handle = (*op_handle),
++	};
++
++	struct psa_invec in_vec[] = {
++	    {.base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec)}
++	};
++	struct psa_outvec out_vec[] = {
++	    {.base = psa_ptr_to_u32(op_handle), .len = sizeof(uint32_t)}
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++	                   IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
+ }
+ 
+ static inline psa_status_t crypto_caller_aead_decrypt_setup(
+@@ -161,7 +181,26 @@ static inline psa_status_t crypto_caller_aead_decrypt_setup(
+ 					    psa_key_id_t key,
+ 					    psa_algorithm_t alg)
+ {
+-	return PSA_ERROR_NOT_SUPPORTED;
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++	    .sfn_id = TFM_CRYPTO_AEAD_DECRYPT_SETUP_SID,
++	    .key_id = key,
++	    .alg = alg,
++	    .op_handle = (*op_handle),
++	};
++
++	struct psa_invec in_vec[] = {
++	    {.base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec)}
++	};
++	struct psa_outvec out_vec[] = {
++	    {.base = psa_ptr_to_u32(op_handle), .len = sizeof(uint32_t)}
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++	                   IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++	return status;
+ }
+ 
+ static inline psa_status_t crypto_caller_aead_generate_nonce(
+@@ -171,7 +210,27 @@ static inline psa_status_t crypto_caller_aead_generate_nonce(
+ 					     size_t nonce_size,
+ 					     size_t *nonce_length)
+ {
+-	return PSA_ERROR_NOT_SUPPORTED;
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++	    .sfn_id = TFM_CRYPTO_AEAD_GENERATE_NONCE_SID,
++	    .op_handle = op_handle,
++	};
++
++	struct psa_invec in_vec[] = {
++	    {.base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec)},
++	};
++	struct psa_outvec out_vec[] = {
++	    {.base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t)},
++	    {.base = psa_ptr_to_u32(nonce), .len = nonce_size}
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++	                   IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	*nonce_length = out_vec[1].len;
++	return status;
+ }
+ 
+ static inline psa_status_t crypto_caller_aead_set_nonce(
+@@ -180,7 +239,25 @@ static inline psa_status_t crypto_caller_aead_set_nonce(
+ 						const uint8_t *nonce,
+ 						size_t nonce_length)
+ {
+-	return PSA_ERROR_NOT_SUPPORTED;
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++	    .sfn_id = TFM_CRYPTO_AEAD_SET_NONCE_SID,
++	    .op_handle = op_handle,
++	};
++
++	struct psa_invec in_vec[] = {
++	    {.base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec)},
++	    {.base = psa_ptr_to_u32(nonce), .len = nonce_length}
++	};
++	struct psa_outvec out_vec[] = {
++	    {.base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t)}
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++	                   IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++	return status;
+ }
+ 
+ static inline psa_status_t crypto_caller_aead_set_lengths(
+@@ -189,7 +266,27 @@ static inline psa_status_t crypto_caller_aead_set_lengths(
+ 					  size_t ad_length,
+ 					  size_t plaintext_length)
+ {
+-	return PSA_ERROR_NOT_SUPPORTED;
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++	    .sfn_id = TFM_CRYPTO_AEAD_SET_LENGTHS_SID,
++	    .ad_length = ad_length,
++	    .plaintext_length = plaintext_length,
++	    .op_handle = op_handle,
++	};
++
++	struct psa_invec in_vec[] = {
++	    {.base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec)},
++	};
++	struct psa_outvec out_vec[] = {
++	    {.base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t)}
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++	                   IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	return status;
+ }
+ 
+ static inline psa_status_t crypto_caller_aead_update_ad(
+@@ -198,7 +295,35 @@ static inline psa_status_t crypto_caller_aead_update_ad(
+ 						const uint8_t *input,
+ 						size_t input_length)
+ {
+-	return PSA_ERROR_NOT_SUPPORTED;
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++	    .sfn_id = TFM_CRYPTO_AEAD_UPDATE_AD_SID,
++	    .op_handle = op_handle,
++	};
++
++	/* Sanitize the optional input */
++	if ((input == NULL) && (input_length != 0)) {
++	    return PSA_ERROR_INVALID_ARGUMENT;
++	}
++
++	struct psa_invec in_vec[] = {
++	    {.base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec)},
++	    {.base = psa_ptr_const_to_u32(input), .len = input_length}
++	};
++	struct psa_outvec out_vec[] = {
++	    {.base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t)}
++	};
++
++	size_t in_len = IOVEC_LEN(in_vec);
++
++	if (input == NULL) {
++	    in_len--;
++	}
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++	                   in_len, out_vec, IOVEC_LEN(out_vec));
++	return status;
+ }
+ 
+ static inline psa_status_t crypto_caller_aead_update(
+@@ -210,7 +335,38 @@ static inline psa_status_t crypto_caller_aead_update(
+ 					     size_t output_size,
+ 					     size_t *output_length)
+ {
+-	return PSA_ERROR_NOT_SUPPORTED;
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++	    .sfn_id = TFM_CRYPTO_AEAD_UPDATE_SID,
++	    .op_handle = op_handle,
++	};
++
++	/* Sanitize the optional input */
++	if ((input == NULL) && (input_length != 0)) {
++	    return PSA_ERROR_INVALID_ARGUMENT;
++	}
++
++	struct psa_invec in_vec[] = {
++	    {.base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec)},
++	    {.base = psa_ptr_const_to_u32(input), .len = input_length}
++	};
++	struct psa_outvec out_vec[] = {
++	    {.base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t)},
++	    {.base = psa_ptr_const_to_u32(output), .len = output_size},
++	};
++
++	size_t in_len = IOVEC_LEN(in_vec);
++
++	if (input == NULL) {
++	    in_len--;
++	}
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++	                   in_len, out_vec, IOVEC_LEN(out_vec));
++
++	*output_length = out_vec[1].len;
++	return status;
+ }
+ 
+ static inline psa_status_t crypto_caller_aead_finish(
+@@ -223,7 +379,48 @@ static inline psa_status_t crypto_caller_aead_finish(
+ 					     size_t tag_size,
+ 					     size_t *tag_length)
+ {
+-	return PSA_ERROR_NOT_SUPPORTED;
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++	    .sfn_id = TFM_CRYPTO_AEAD_FINISH_SID,
++	    .op_handle = op_handle,
++	};
++
++	/* Sanitize the optional output */
++	if ((aeadtext == NULL) && (aeadtext_size != 0)) {
++	    return PSA_ERROR_INVALID_ARGUMENT;
++	}
++
++	struct psa_invec in_vec[] = {
++	    {.base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec)},
++	};
++	struct psa_outvec out_vec[] = {
++	    {.base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t)},
++	    {.base = psa_ptr_const_to_u32(tag), .len = tag_size},
++	    {.base = psa_ptr_const_to_u32(aeadtext), .len = aeadtext_size}
++	};
++
++	size_t out_len = IOVEC_LEN(out_vec);
++
++	if (aeadtext == NULL || aeadtext_size == 0) {
++	    out_len--;
++	}
++	if ((out_len == 3) && (aeadtext_length == NULL)) {
++	    return PSA_ERROR_INVALID_ARGUMENT;
++	}
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++	                   IOVEC_LEN(in_vec), out_vec, out_len);
++
++	*tag_length = out_vec[1].len;
++
++	if (out_len == 3) {
++	    *aeadtext_length = out_vec[2].len;
++	} else {
++	    *aeadtext_length = 0;
++	}
++	return status;
+ }
+ 
+ static inline psa_status_t crypto_caller_aead_verify(
+@@ -235,14 +432,94 @@ static inline psa_status_t crypto_caller_aead_verify(
+ 					     const uint8_t *tag,
+ 					     size_t tag_length)
+ {
+-	return PSA_ERROR_NOT_SUPPORTED;
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++	    .sfn_id = TFM_CRYPTO_AEAD_VERIFY_SID,
++	    .op_handle = op_handle,
++	};
++
++	/* Sanitize the optional output */
++	if ((plaintext == NULL) && (plaintext_size != 0)) {
++	    return PSA_ERROR_INVALID_ARGUMENT;
++	}
++
++	struct psa_invec in_vec[] = {
++	    {.base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec)},
++	    {.base = psa_ptr_const_to_u32(tag), .len = tag_length}
++	};
++	struct psa_outvec out_vec[] = {
++	    {.base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t)},
++	    {.base = psa_ptr_const_to_u32(plaintext), .len = plaintext_size},
++	};
++
++	size_t out_len = IOVEC_LEN(out_vec);
++
++	if (plaintext == NULL || plaintext_size == 0) {
++	    out_len--;
++	}
++	if ((out_len == 2) && (plaintext_length == NULL)) {
++	    return PSA_ERROR_INVALID_ARGUMENT;
++	}
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++	                   IOVEC_LEN(in_vec), out_vec, out_len);
++
++	if (out_len == 2) {
++	    *plaintext_length = out_vec[1].len;
++	} else {
++	    *plaintext_length = 0;
++	}
++	return status;
+ }
+ 
+ static inline psa_status_t crypto_caller_aead_abort(
+ 					    struct service_client *context,
+ 					    uint32_t op_handle)
+ {
+-	return PSA_ERROR_NOT_SUPPORTED;
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++	    .sfn_id = TFM_CRYPTO_AEAD_ABORT_SID,
++	    .op_handle = op_handle,
++	};
++
++	struct psa_invec in_vec[] = {
++	    {.base = psa_ptr_to_u32(&iov), .len = sizeof(struct psa_ipc_crypto_pack_iovec)},
++	};
++	struct psa_outvec out_vec[] = {
++	    {.base = psa_ptr_to_u32(&op_handle), .len = sizeof(uint32_t)},
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++	                   IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++	return status;
++}
++
++static inline size_t crypto_caller_aead_max_update_size(const struct service_client *context)
++{
++       /* Returns the maximum number of bytes that may be
++        * carried as a parameter of the mac_update operation
++        *  using the packed-c encoding.
++        */
++       size_t payload_space = context->service_info.max_payload;
++       size_t overhead = iov_size;
++
++       return (payload_space > overhead) ? payload_space - overhead : 0;
++}
++
++static inline size_t crypto_caller_aead_max_update_ad_size(const struct service_client *context)
++{
++	/* Returns the maximum number of bytes that may be
++	 * carried as a parameter of the mac_update operation
++	 *  using the packed-c encoding.
++	 */
++	size_t payload_space = context->service_info.max_payload;
++	size_t overhead = iov_size;
++
++	return (payload_space > overhead) ? payload_space - overhead : 0;
+ }
+ 
+ #ifdef __cplusplus
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_sign_hash.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_sign_hash.h
+index 71d88ced..e4a2b167 100644
+--- a/components/service/crypto/client/caller/psa_ipc/crypto_caller_sign_hash.h
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_sign_hash.h
+@@ -57,6 +57,41 @@ static inline psa_status_t crypto_caller_sign_hash(struct service_client *contex
+ 	return status;
+ }
+ 
++static inline psa_status_t crypto_caller_sign_message(struct service_client *context,
++						   psa_key_id_t id,
++						   psa_algorithm_t alg,
++						   const uint8_t *hash,
++						   size_t hash_length,
++						   uint8_t *signature,
++						   size_t signature_size,
++						   size_t *signature_length)
++{
++	struct service_client *ipc = context;
++	struct rpc_caller *caller = ipc->caller;
++	psa_status_t status;
++	struct psa_ipc_crypto_pack_iovec iov = {
++		.sfn_id = TFM_CRYPTO_SIGN_MESSAGE_SID,
++		.key_id = id,
++		.alg = alg,
++	};
++	struct psa_invec in_vec[] = {
++		{ .base = psa_ptr_to_u32(&iov), .len = iov_size },
++		{ .base = psa_ptr_const_to_u32(hash), .len = hash_length },
++	};
++	struct psa_outvec out_vec[] = {
++		{ .base = psa_ptr_to_u32(signature), .len = signature_size },
++	};
++
++	status = psa_call(caller, TFM_CRYPTO_HANDLE, PSA_IPC_CALL, in_vec,
++			  IOVEC_LEN(in_vec), out_vec, IOVEC_LEN(out_vec));
++
++	*signature_length = out_vec[0].len;
++
++	return status;
++}
++
++
++
+ #ifdef __cplusplus
+ }
+ #endif
+diff --git a/components/service/crypto/client/caller/psa_ipc/crypto_caller_verify_hash.h b/components/service/crypto/client/caller/psa_ipc/crypto_caller_verify_hash.h
+index e16f6e54..cc9279ee 100644
+--- a/components/service/crypto/client/caller/psa_ipc/crypto_caller_verify_hash.h
++++ b/components/service/crypto/client/caller/psa_ipc/crypto_caller_verify_hash.h
+@@ -24,19 +24,20 @@
+ extern "C" {
+ #endif
+ 
+-static inline psa_status_t crypto_caller_verify_hash(struct service_client *context,
++static inline psa_status_t crypto_caller_common(struct service_client *context,
+ 						     psa_key_id_t id,
+ 						     psa_algorithm_t alg,
+ 						     const uint8_t *hash,
+ 						     size_t hash_length,
+ 						     const uint8_t *signature,
+-						     size_t signature_length)
++						     size_t signature_length,
++						     uint32_t sfn_id)
+ {
+ 	struct service_client *ipc = context;
+ 	struct rpc_caller *caller = ipc->caller;
+ 	psa_status_t status;
+ 	struct psa_ipc_crypto_pack_iovec iov = {
+-		.sfn_id = TFM_CRYPTO_VERIFY_HASH_SID,
++		.sfn_id = sfn_id,
+ 		.key_id = id,
+ 		.alg = alg,
+ 	};
+@@ -52,6 +53,32 @@ static inline psa_status_t crypto_caller_verify_hash(struct service_client *cont
+ 	return status;
+ }
+ 
++static inline psa_status_t crypto_caller_verify_hash(struct service_client *context,
++						     psa_key_id_t id,
++						     psa_algorithm_t alg,
++						     const uint8_t *hash,
++						     size_t hash_length,
++						     const uint8_t *signature,
++						     size_t signature_length)
++{
++
++	return crypto_caller_common(context,id,alg,hash,hash_length,
++			signature,signature_length, TFM_CRYPTO_VERIFY_HASH_SID);
++}
++
++static inline psa_status_t crypto_caller_verify_message(struct service_client *context,
++						     psa_key_id_t id,
++						     psa_algorithm_t alg,
++						     const uint8_t *hash,
++						     size_t hash_length,
++						     const uint8_t *signature,
++						     size_t signature_length)
++{
++
++	return crypto_caller_common(context,id,alg,hash,hash_length,
++			signature,signature_length, TFM_CRYPTO_VERIFY_MESSAGE_SID);
++}
++
+ #ifdef __cplusplus
+ }
+ #endif
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0046-Fix-update-psa_set_key_usage_flags-definition-to-the.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0046-Fix-update-psa_set_key_usage_flags-definition-to-the.patch
new file mode 100644
index 0000000..4bd846d
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0046-Fix-update-psa_set_key_usage_flags-definition-to-the.patch
@@ -0,0 +1,40 @@
+From a037ef21c0334117ad0741776a4b7b6e1a428d19 Mon Sep 17 00:00:00 2001
+From: Satish Kumar <satish.kumar01@arm.com>
+Date: Mon, 14 Feb 2022 17:52:00 +0000
+Subject: [PATCH] Fix : update psa_set_key_usage_flags definition to the latest
+ from the tf-m
+
+Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ components/service/crypto/include/psa/crypto_struct.h | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/components/service/crypto/include/psa/crypto_struct.h b/components/service/crypto/include/psa/crypto_struct.h
+index 1bc55e37..b4a7ed4b 100644
+--- a/components/service/crypto/include/psa/crypto_struct.h
++++ b/components/service/crypto/include/psa/crypto_struct.h
+@@ -155,9 +155,19 @@ static inline psa_key_lifetime_t psa_get_key_lifetime(
+     return( attributes->lifetime );
+ }
+ 
++static inline void psa_extend_key_usage_flags( psa_key_usage_t *usage_flags )
++{
++    if( *usage_flags & PSA_KEY_USAGE_SIGN_HASH )
++        *usage_flags |= PSA_KEY_USAGE_SIGN_MESSAGE;
++
++    if( *usage_flags & PSA_KEY_USAGE_VERIFY_HASH )
++        *usage_flags |= PSA_KEY_USAGE_VERIFY_MESSAGE;
++}
++
+ static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes,
+                                            psa_key_usage_t usage_flags)
+ {
++    psa_extend_key_usage_flags( &usage_flags );
+     attributes->usage = usage_flags;
+ }
+ 
diff --git a/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0047-Fixes-in-AEAD-for-psa-arch-test-54-and-58.patch b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0047-Fixes-in-AEAD-for-psa-arch-test-54-and-58.patch
new file mode 100644
index 0000000..4ad4be0
--- /dev/null
+++ b/meta-arm/meta-arm-bsp/recipes-security/trusted-services/secure-partitions/corstone1000/0047-Fixes-in-AEAD-for-psa-arch-test-54-and-58.patch
@@ -0,0 +1,120 @@
+From 55463b12cca39d2c6a3fd18bbd3d28ae95dff8cf Mon Sep 17 00:00:00 2001
+From: Satish Kumar <satish.kumar01@arm.com>
+Date: Mon, 14 Feb 2022 08:22:25 +0000
+Subject: [PATCH] Fixes in AEAD for psa-arch test 54 and 58.
+
+Signed-off-by: Satish Kumar <satish.kumar01@arm.com>
+
+Upstream-Status: Pending [Not submitted to upstream yet]
+Signed-off-by: Emekcan Aras <Emekcan.Aras@arm.com>
+
+
+---
+ .../crypto/client/caller/packed-c/crypto_caller_aead.h    | 1 +
+ components/service/crypto/include/psa/crypto_sizes.h      | 2 +-
+ .../crypto/provider/extension/aead/aead_provider.c        | 8 ++++++--
+ .../extension/aead/serializer/aead_provider_serializer.h  | 1 +
+ .../packed-c/packedc_aead_provider_serializer.c           | 2 ++
+ protocols/service/crypto/packed-c/aead.h                  | 1 +
+ 6 files changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/components/service/crypto/client/caller/packed-c/crypto_caller_aead.h b/components/service/crypto/client/caller/packed-c/crypto_caller_aead.h
+index c4ffb20c..a91f66c1 100644
+--- a/components/service/crypto/client/caller/packed-c/crypto_caller_aead.h
++++ b/components/service/crypto/client/caller/packed-c/crypto_caller_aead.h
+@@ -309,6 +309,7 @@ static inline psa_status_t crypto_caller_aead_update(struct service_client *cont
+ 	size_t req_len = req_fixed_len;
+ 
+ 	*output_length = 0;
++        req_msg.output_size = output_size;
+ 	req_msg.op_handle = op_handle;
+ 
+ 	/* Mandatory input data parameter */
+diff --git a/components/service/crypto/include/psa/crypto_sizes.h b/components/service/crypto/include/psa/crypto_sizes.h
+index 4d7bf6e9..e3c4df29 100644
+--- a/components/service/crypto/include/psa/crypto_sizes.h
++++ b/components/service/crypto/include/psa/crypto_sizes.h
+@@ -351,7 +351,7 @@
+  *       just the largest size that may be generated by
+  *       #psa_aead_generate_nonce().
+  */
+-#define PSA_AEAD_NONCE_MAX_SIZE 12
++#define PSA_AEAD_NONCE_MAX_SIZE 16
+ 
+ /** A sufficient output buffer size for psa_aead_update().
+  *
+diff --git a/components/service/crypto/provider/extension/aead/aead_provider.c b/components/service/crypto/provider/extension/aead/aead_provider.c
+index 14a25436..6b144db8 100644
+--- a/components/service/crypto/provider/extension/aead/aead_provider.c
++++ b/components/service/crypto/provider/extension/aead/aead_provider.c
+@@ -283,10 +283,11 @@ static rpc_status_t aead_update_handler(void *context, struct call_req *req)
+ 	uint32_t op_handle;
+ 	const uint8_t *input;
+ 	size_t input_len;
++        uint32_t recv_output_size;
+ 
+ 	if (serializer)
+ 		rpc_status = serializer->deserialize_aead_update_req(req_buf, &op_handle,
+-			&input, &input_len);
++			&recv_output_size, &input, &input_len);
+ 
+ 	if (rpc_status == TS_RPC_CALL_ACCEPTED) {
+ 
+@@ -300,9 +301,12 @@ static rpc_status_t aead_update_handler(void *context, struct call_req *req)
+ 		if (crypto_context) {
+ 
+ 			size_t output_len = 0;
+-			size_t output_size = PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(input_len);
++			size_t output_size = PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(24);
+ 			uint8_t *output = malloc(output_size);
+ 
++                        if (recv_output_size < output_size) {
++                            output_size = recv_output_size;
++                        }
+ 			if (output) {
+ 
+ 				psa_status = psa_aead_update(&crypto_context->op.aead,
+diff --git a/components/service/crypto/provider/extension/aead/serializer/aead_provider_serializer.h b/components/service/crypto/provider/extension/aead/serializer/aead_provider_serializer.h
+index bb1a2a97..0156aaba 100644
+--- a/components/service/crypto/provider/extension/aead/serializer/aead_provider_serializer.h
++++ b/components/service/crypto/provider/extension/aead/serializer/aead_provider_serializer.h
+@@ -51,6 +51,7 @@ struct aead_provider_serializer {
+ 	/* Operation: aead_update */
+ 	rpc_status_t (*deserialize_aead_update_req)(const struct call_param_buf *req_buf,
+ 		uint32_t *op_handle,
++                uint32_t *output_size,
+ 		const uint8_t **input, size_t *input_len);
+ 
+ 	rpc_status_t (*serialize_aead_update_resp)(struct call_param_buf *resp_buf,
+diff --git a/components/service/crypto/provider/extension/aead/serializer/packed-c/packedc_aead_provider_serializer.c b/components/service/crypto/provider/extension/aead/serializer/packed-c/packedc_aead_provider_serializer.c
+index 6f00b3e3..45c739ab 100644
+--- a/components/service/crypto/provider/extension/aead/serializer/packed-c/packedc_aead_provider_serializer.c
++++ b/components/service/crypto/provider/extension/aead/serializer/packed-c/packedc_aead_provider_serializer.c
+@@ -192,6 +192,7 @@ static rpc_status_t deserialize_aead_update_ad_req(const struct call_param_buf *
+ /* Operation: aead_update */
+ static rpc_status_t deserialize_aead_update_req(const struct call_param_buf *req_buf,
+ 	uint32_t *op_handle,
++        uint32_t *output_size,
+ 	const uint8_t **input, size_t *input_len)
+ {
+ 	rpc_status_t rpc_status = TS_RPC_ERROR_INVALID_REQ_BODY;
+@@ -208,6 +209,7 @@ static rpc_status_t deserialize_aead_update_req(const struct call_param_buf *req
+ 		memcpy(&recv_msg, req_buf->data, expected_fixed_len);
+ 
+ 		*op_handle = recv_msg.op_handle;
++                *output_size = recv_msg.output_size;
+ 
+ 		tlv_const_iterator_begin(&req_iter,
+ 			(uint8_t*)req_buf->data + expected_fixed_len,
+diff --git a/protocols/service/crypto/packed-c/aead.h b/protocols/service/crypto/packed-c/aead.h
+index 0be266b5..435fd3b5 100644
+--- a/protocols/service/crypto/packed-c/aead.h
++++ b/protocols/service/crypto/packed-c/aead.h
+@@ -98,6 +98,7 @@ enum
+ struct __attribute__ ((__packed__)) ts_crypto_aead_update_in
+ {
+   uint32_t op_handle;
++  uint32_t output_size;
+ };
+ 
+ /* Variable length input parameter tags */