Platform: Add support to forward PSA msg in Musca-B1

PSA RoT messages can be forwarded from the SSE-200 subsystem to the
Secure Enclave in Musca-B1.

Change-Id: Iab2c525cf41eae34585fb16a4b9bab941e6c7587
Signed-off-by: Gabor Abonyi <gabor.abonyi@arm.com>
Signed-off-by: Mark Horvath <mark.horvath@arm.com>
diff --git a/bl2/ext/mcuboot/CMakeLists.txt b/bl2/ext/mcuboot/CMakeLists.txt
index d113a92..c8dd0a3 100644
--- a/bl2/ext/mcuboot/CMakeLists.txt
+++ b/bl2/ext/mcuboot/CMakeLists.txt
@@ -197,10 +197,13 @@
             DEPENDS tfm_s_ns_bin tfm_s_ns.bin
             DEPENDS signing_layout_s
 
+        # Use the non-secure key to sign the combined image if FORWARD_PROT_MSG is set.
+        # In such a configuration there is a subsystem with higher privileges controlling the
+        # the boot process and current implementation requires to use the non-secure key here.
         COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/wrapper/wrapper.py
             -v ${MCUBOOT_IMAGE_VERSION_S}
             --layout $<TARGET_OBJECTS:signing_layout_s>
-            -k ${MCUBOOT_KEY_S}
+            -k $<IF:$<BOOL:${FORWARD_PROT_MSG}>,${MCUBOOT_KEY_NS},${MCUBOOT_KEY_S}>
             --public-key-format $<IF:$<BOOL:${MCUBOOT_HW_KEY}>,full,hash>
             --align 1
             --pad
diff --git a/config/config_default.cmake b/config/config_default.cmake
index c32b782..c7fcde4 100644
--- a/config/config_default.cmake
+++ b/config/config_default.cmake
@@ -117,6 +117,8 @@
 
 set(TFM_PARTITION_AUDIT_LOG             ON          CACHE BOOL      "Enable Audit Log partition")
 
+set(FORWARD_PROT_MSG                    OFF         CACHE BOOL      "Whether to forward all PSA RoT messages to a Secure Enclave")
+
 ################################## Tests #######################################
 
 set(TFM_INTERACTIVE_TEST                OFF         CACHE BOOL      "Enable interactive tests")
diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt
index 93c45de..0f7540b 100644
--- a/interface/CMakeLists.txt
+++ b/interface/CMakeLists.txt
@@ -48,6 +48,7 @@
         $<$<OR:$<VERSION_GREATER:${TFM_ISOLATION_LEVEL},1>,$<STREQUAL:"${TEST_PSA_API}","IPC">>:CONFIG_TFM_ENABLE_MEMORY_PROTECT>
         $<$<BOOL:${TFM_MULTI_CORE_TOPOLOGY}>:TFM_MULTI_CORE_TOPOLOGY>
         $<$<BOOL:${TFM_MULTI_CORE_MULTI_CLIENT_CALL}>:TFM_MULTI_CORE_MULTI_CLIENT_CALL>
+        $<$<BOOL:${FORWARD_PROT_MSG}>:FORWARD_PROT_MSG=${FORWARD_PROT_MSG}>
 )
 
 ###################### PSA api (S lib) #########################################
diff --git a/platform/CMakeLists.txt b/platform/CMakeLists.txt
index 1db300f..b03c88e 100755
--- a/platform/CMakeLists.txt
+++ b/platform/CMakeLists.txt
@@ -40,8 +40,8 @@
 target_sources(platform_s
     PRIVATE
         ext/common/template/attest_hal.c
-        ext/common/tfm_hal_ps.c
-        ext/common/tfm_hal_its.c
+        $<$<BOOL:${TFM_PARTITION_PROTECTED_STORAGE}>:${CMAKE_CURRENT_SOURCE_DIR}/ext/common/tfm_hal_ps.c>
+        $<$<BOOL:${TFM_PARTITION_INTERNAL_TRUSTED_STORAGE}>:${CMAKE_CURRENT_SOURCE_DIR}/ext/common/tfm_hal_its.c>
         ext/common/tfm_platform.c
         $<$<BOOL:${PLATFORM_DEFAULT_UART_STDOUT}>:${CMAKE_CURRENT_SOURCE_DIR}/ext/common/uart_stdout.c>
         ext/common/tfm_hal_spm_logdev_peripheral.c
@@ -152,4 +152,5 @@
         $<$<STREQUAL:${MCUBOOT_SIGNATURE_TYPE},RSA>:MCUBOOT_SIGN_RSA_LEN=${MCUBOOT_SIGNATURE_KEY_LEN}>
         $<$<STREQUAL:${MCUBOOT_EXECUTION_SLOT},2>:LINK_TO_SECONDARY_PARTITION>
         $<$<BOOL:${TEST_PSA_API}>:PSA_API_TEST_${TEST_PSA_API}>
+        $<$<BOOL:${FORWARD_PROT_MSG}>:FORWARD_PROT_MSG=${FORWARD_PROT_MSG}>
 )
diff --git a/platform/ext/target/musca_b1/CMakeLists.txt b/platform/ext/target/musca_b1/CMakeLists.txt
index 6f06370..c2ddc70 100644
--- a/platform/ext/target/musca_b1/CMakeLists.txt
+++ b/platform/ext/target/musca_b1/CMakeLists.txt
@@ -17,6 +17,10 @@
 
 #========================= Platform common defs ===============================#
 
+if (${CMAKE_C_COMPILER_ID} STREQUAL IAR AND FORWARD_PROT_MSG)
+    message(FATAL_ERROR "IAR is currently not supported if FORWARD_PROT_MSG is set.")
+endif()
+
 # Specify the location of platform specific build dependencies.
 target_sources(tfm_s
     PRIVATE
@@ -75,12 +79,13 @@
         partition
         services/include
         Libraries
+        $<$<BOOL:${FORWARD_PROT_MSG}>:${CMAKE_CURRENT_SOURCE_DIR}/mailbox>
 )
 
 target_sources(platform_s
     PRIVATE
-        CMSIS_Driver/Driver_QSPI_Flash.c
-        CMSIS_Driver/Driver_GFC100_EFlash.c
+        $<$<NOT:$<BOOL:${FORWARD_PROT_MSG}>>:${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_Driver/Driver_QSPI_Flash.c>
+        $<$<NOT:$<BOOL:${FORWARD_PROT_MSG}>>:${CMAKE_CURRENT_SOURCE_DIR}/CMSIS_Driver/Driver_GFC100_EFlash.c>
         CMSIS_Driver/Driver_MPC.c
         CMSIS_Driver/Driver_PPC.c
         CMSIS_Driver/Driver_USART.c
@@ -90,10 +95,10 @@
         Native_Driver/mpu_armv8m_drv.c
         Native_Driver/ppc_sse200_drv.c
         Native_Driver/gpio_cmsdk_drv.c
-        Libraries/mt25ql_flash_lib.c
-        Native_Driver/qspi_ip6514e_drv.c
-        Native_Driver/gfc100_eflash_drv.c
-        Native_Driver/musca_b1_eflash_drv.c
+        $<$<NOT:$<BOOL:${FORWARD_PROT_MSG}>>:${CMAKE_CURRENT_SOURCE_DIR}/Libraries/mt25ql_flash_lib.c>
+        $<$<NOT:$<BOOL:${FORWARD_PROT_MSG}>>:${CMAKE_CURRENT_SOURCE_DIR}/Native_Driver/qspi_ip6514e_drv.c>
+        $<$<NOT:$<BOOL:${FORWARD_PROT_MSG}>>:${CMAKE_CURRENT_SOURCE_DIR}/Native_Driver/gfc100_eflash_drv.c>
+        $<$<NOT:$<BOOL:${FORWARD_PROT_MSG}>>:${CMAKE_CURRENT_SOURCE_DIR}/Native_Driver/musca_b1_eflash_drv.c>
         Native_Driver/musca_b1_scc_drv.c
         spm_hal.c
         tfm_hal_isolation.c
@@ -105,6 +110,9 @@
         ${CMAKE_SOURCE_DIR}/platform/ext/common/tfm_hal_isolation_mpu_v8m.c
         $<$<BOOL:${TFM_PARTITION_PLATFORM}>:${CMAKE_CURRENT_SOURCE_DIR}/plat_test.c>
         $<$<BOOL:${TFM_PARTITION_PLATFORM}>:${CMAKE_CURRENT_SOURCE_DIR}/services/src/tfm_platform_system.c>
+        $<$<BOOL:${FORWARD_PROT_MSG}>:${CMAKE_CURRENT_SOURCE_DIR}/mailbox/platform_multicore.c>
+        $<$<BOOL:${FORWARD_PROT_MSG}>:${CMAKE_CURRENT_SOURCE_DIR}/mailbox/platform_ns_mailbox.c>
+        $<$<BOOL:${FORWARD_PROT_MSG}>:${CMAKE_CURRENT_SOURCE_DIR}/Native_Driver/mhu_v2_x.c>
 )
 
 target_compile_options(platform_s
@@ -112,6 +120,14 @@
         ${COMPILER_CMSE_FLAG}
 )
 
+target_compile_definitions(platform_s
+    PUBLIC
+        $<$<BOOL:${FORWARD_PROT_MSG}>:FORWARD_PROT_MSG=${FORWARD_PROT_MSG}>
+        $<$<BOOL:${FORWARD_PROT_MSG}>:PSA_PROXY_ADDR_TRANSLATION=1>
+        $<$<BOOL:${FORWARD_PROT_MSG}>:LINK_TO_EFLASH1=1>
+        $<$<BOOL:${FORWARD_PROT_MSG}>:USE_SECURE_ENCLAVE_MAILBOX=1>
+)
+
 #========================= Platform Non-Secure ================================#
 
 target_sources(platform_ns
@@ -145,7 +161,6 @@
             boot_hal.c
             Device/Source/system_core_init.c
             Device/Source/device_definition.c
-            CMSIS_Driver/Driver_QSPI_Flash.c
             CMSIS_Driver/Driver_GFC100_EFlash.c
             Native_Driver/uart_pl011_drv.c
             CMSIS_Driver/Driver_USART.c
diff --git a/platform/ext/target/musca_b1/Device/Config/device_cfg.h b/platform/ext/target/musca_b1/Device/Config/device_cfg.h
index b1d266b..d34a29e 100644
--- a/platform/ext/target/musca_b1/Device/Config/device_cfg.h
+++ b/platform/ext/target/musca_b1/Device/Config/device_cfg.h
@@ -80,6 +80,14 @@
 #define MT25QL_S
 #define MT25QL_NS
 
+#ifdef USE_SECURE_ENCLAVE_MAILBOX
+/* SE MHU */
+#define SE_MHU_SENDER_S
+#define SE_MHU_SENDER_DEV      SE_MHU_SENDER_DEV_S
+#define SE_MHU_RECEIVER_S
+#define SE_MHU_RECEIVER_DEV    SE_MHU_RECEIVER_DEV_S
+#endif
+
 /* Default UART baud rate */
 #define DEFAULT_UART_BAUDRATE 115200
 
diff --git a/platform/ext/target/musca_b1/Device/Include/device_definition.h b/platform/ext/target/musca_b1/Device/Include/device_definition.h
index a1e8bb5..6558088 100644
--- a/platform/ext/target/musca_b1/Device/Include/device_definition.h
+++ b/platform/ext/target/musca_b1/Device/Include/device_definition.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2019 Arm Limited. All rights reserved.
+ * Copyright (c) 2017-2020 Arm Limited. All rights reserved.
  *
  * Licensed under the Apache License Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -193,6 +193,25 @@
 extern struct qspi_ip6514e_dev_t QSPI_DEV_NS;
 #endif
 
+/* SE MHU */
+#ifdef SE_MHU_SENDER_S
+#include "mhu_v2_x.h"
+extern struct mhu_v2_x_dev_t SE_MHU_SENDER_DEV_S;
+#endif
+#ifdef SE_MHU_SENDER_NS
+#include "mhu_v2_x.h"
+extern struct mhu_v2_x_dev_t SE_MHU_SENDER_DEV_NS;
+#endif
+
+#ifdef SE_MHU_RECEIVER_S
+#include "mhu_v2_x.h"
+extern struct mhu_v2_x_dev_t SE_MHU_RECEIVER_DEV_S;
+#endif
+#ifdef SE_MHU_RECEIVER_NS
+#include "mhu_v2_x.h"
+extern struct mhu_v2_x_dev_t SE_MHU_RECEIVER_DEV_NS;
+#endif
+
 /* ======= External peripheral configuration structure declarations ======= */
 
 /* MT25QL Flash memory library structures */
diff --git a/platform/ext/target/musca_b1/Device/Include/platform_base_address.h b/platform/ext/target/musca_b1/Device/Include/platform_base_address.h
index 01c0263..96e2112 100644
--- a/platform/ext/target/musca_b1/Device/Include/platform_base_address.h
+++ b/platform/ext/target/musca_b1/Device/Include/platform_base_address.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2019 Arm Limited. All rights reserved.
+ * Copyright (c) 2009-2020 Arm Limited. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -68,8 +68,8 @@
 #define MUSCA_B1_PVT_NS_BASE             (0x4010E000UL)           /*!< (Non-Secure PVT sensors            ) Base Address */
 #define MUSCA_B1_SDIO_NS_BASE            (0x4010F000UL)           /*!< (Non-Secure SDIO                   ) Base Address */
 #define MUSCA_B1_GPIO_NS_BASE            (0x41000000UL)           /*!< (Non-Secure GPIO                   ) Base Address */
-#define MUSCA_B1_CI_MHU_SND_NS_BASE      (0x42600000UL)           /*!< (Non-Secure CryptoIsland MHU Send  ) Base Address */
-#define MUSCA_B1_CI_MHU_RCV_NS_BASE      (0x42700000UL)           /*!< (Non-Secure CryptoIsland MHU Rcv   ) Base Address */
+#define MUSCA_B1_SE_MHU_SND_NS_BASE      (0x42600000UL)           /*!< (Non-Secure SE MHU Sender          ) Base Address */
+#define MUSCA_B1_SE_MHU_RCV_NS_BASE      (0x42700000UL)           /*!< (Non-Secure SE MHU Receiver        ) Base Address */
 #define MUSCA_B1_QSPI_REG_NS_BASE        (0x42800000UL)           /*!< (Non-Secure QSPI registers         ) Base Address */
 
 /* Secure Peripheral and SRAM base address */
@@ -118,10 +118,10 @@
 #define MUSCA_B1_EFLASH1_MPC_S_BASE      (0x52300000UL)           /*!< (Secure Embedded Flash 1 MPC       ) Base Address */
 #define MUSCA_B1_EFLASH0_REG_MAP_S_BASE  (0x52400000UL)           /*!< (Secure GFC100 EFlash0 controller  ) Base Address */
 #define MUSCA_B1_EFLASH1_REG_MAP_S_BASE  (0x52500000UL)           /*!< (Secure GFC100 EFlash1 controller  ) Base Address */
-#define MUSCA_B1_CI_MHU_SND_S_BASE       (0x52600000UL)           /*!< (Secure CryptoIsland MHU Sender    ) Base Address */
-#define MUSCA_B1_CI_MHU_RCV_S_BASE       (0x52700000UL)           /*!< (Secure CryptoIsland MHU Receiver  ) Base Address */
+#define MUSCA_B1_SE_MHU_SND_S_BASE       (0x52600000UL)           /*!< (Secure SE MHU Sender              ) Base Address */
+#define MUSCA_B1_SE_MHU_RCV_S_BASE       (0x52700000UL)           /*!< (Secure SE MHU Receiver            ) Base Address */
 #define MUSCA_B1_QSPI_REG_S_BASE         (0x52800000UL)           /*!< (Secure QSPI registers             ) Base Address */
-#define MUSCA_B1_CRYPTO_MPC_S_BASE       (0x52E00000UL)           /*!< (Secure CryptoIsland MPC           ) Base Address */
+#define MUSCA_B1_SE_MPC_S_BASE           (0x52E00000UL)           /*!< (Secure SE MPC                     ) Base Address */
 
 /* MPC memory range bases and limits */
 /* Internal SRAM */
diff --git a/platform/ext/target/musca_b1/Device/Source/device_definition.c b/platform/ext/target/musca_b1/Device/Source/device_definition.c
index 90899d4..7c9bda3 100644
--- a/platform/ext/target/musca_b1/Device/Source/device_definition.c
+++ b/platform/ext/target/musca_b1/Device/Source/device_definition.c
@@ -442,6 +442,33 @@
 };
 #endif
 
+/* SE MHU */
+#ifdef SE_MHU_SENDER_S
+struct mhu_v2_x_dev_t SE_MHU_SENDER_DEV_S = {
+        .base = MUSCA_B1_SE_MHU_SND_S_BASE,
+        .frame = MHU_V2_X_SENDER_FRAME
+};
+#endif
+#ifdef SE_MHU_SENDER_NS
+struct mhu_v2_x_dev_t SE_MHU_SENDER_DEV_NS = {
+        .base = MUSCA_B1_SE_MHU_SND_NS_BASE,
+        .frame = MHU_V2_X_SENDER_FRAME
+};
+#endif
+
+#ifdef SE_MHU_RECEIVER_S
+struct mhu_v2_x_dev_t SE_MHU_RECEIVER_DEV_S = {
+        .base = MUSCA_B1_SE_MHU_RCV_S_BASE,
+        .frame = MHU_V2_X_RECEIVER_FRAME
+};
+#endif
+#ifdef SE_MHU_RECEIVER_NS
+struct mhu_v2_x_dev_t SE_MHU_RECEIVER_DEV_NS = {
+        .base = MUSCA_B1_SE_MHU_RCV_NS_BASE,
+        .frame = MHU_V2_X_RECEIVER_FRAME
+};
+#endif
+
 /* ======= External peripheral configuration structure definitions ======= */
 
 /* MT25QL Flash memory library structures */
diff --git a/platform/ext/target/musca_b1/Native_Driver/mhu_v2_x.c b/platform/ext/target/musca_b1/Native_Driver/mhu_v2_x.c
new file mode 100644
index 0000000..b228c3f
--- /dev/null
+++ b/platform/ext/target/musca_b1/Native_Driver/mhu_v2_x.c
@@ -0,0 +1,603 @@
+/*
+ * Copyright (c) 2020 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_x.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 & ENABLE) {
+                *channel = (j + (i * CH_PER_CH_COMB));
+                return MHU_V_2_X_ERR_NONE;
+            }
+            status >>= 1;
+        }
+    }
+
+    return MHU_V_2_X_ERR_GENERAL;
+}
diff --git a/platform/ext/target/musca_b1/Native_Driver/mhu_v2_x.h b/platform/ext/target/musca_b1/Native_Driver/mhu_v2_x.h
new file mode 100644
index 0000000..08e0dd3
--- /dev/null
+++ b/platform/ext/target/musca_b1/Native_Driver/mhu_v2_x.h
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2020 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 {
+    const 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/ext/target/musca_b1/config.cmake b/platform/ext/target/musca_b1/config.cmake
index b26e7a3..eba2508 100644
--- a/platform/ext/target/musca_b1/config.cmake
+++ b/platform/ext/target/musca_b1/config.cmake
@@ -5,12 +5,31 @@
 #
 #-------------------------------------------------------------------------------
 
+
 set(PLATFORM_DUMMY_ATTEST_HAL           FALSE       CACHE BOOL      "Use dummy boot hal implementation. Should not be used in production.")
-set(CRYPTO_HW_ACCELERATOR               ON          CACHE BOOL      "Whether to enable the crypto hardware accelerator on supported platforms")
 set(TFM_CRYPTO_TEST_ALG_CFB             OFF         CACHE BOOL      "Test CFB cryptography mode")
 
-if(CRYPTO_HW_ACCELERATOR_OTP_STATE STREQUAL "ENABLED")
-    set(PLATFORM_DUMMY_CRYPTO_KEYS      FALSE       CACHE BOOL      "Use dummy crypto keys. Should not be used in production.")
+if (NOT FORWARD_PROT_MSG)
+    set(CRYPTO_HW_ACCELERATOR               ON          CACHE BOOL      "Whether to enable the crypto hardware accelerator on supported platforms")
+    if(CRYPTO_HW_ACCELERATOR_OTP_STATE STREQUAL "ENABLED")
+        set(PLATFORM_DUMMY_CRYPTO_KEYS      FALSE       CACHE BOOL      "Use dummy crypto keys. Should not be used in production.")
+    endif()
+else()
+    set(TFM_MULTI_CORE_MULTI_CLIENT_CALL    OFF         CACHE BOOL      "Whether to enable multiple PSA client calls feature")
+    set(MCUBOOT_IMAGE_NUMBER                1           CACHE STRING    "Whether to combine S and NS into either 1 image, or sign each seperately")
+    set(MCUBOOT_MEASURED_BOOT               OFF         CACHE BOOL      "Add boot measurement values to boot status. Used for initial attestation token")
+    set(TFM_PSA_API                         ON          CACHE BOOL      "Use PSA api (IPC mode) instead of secure library mode")
+    set(TFM_PARTITION_PROTECTED_STORAGE     OFF         CACHE BOOL      "Enable Protected Storage partition")
+    set(TFM_PARTITION_INTERNAL_TRUSTED_STORAGE OFF      CACHE BOOL      "Enable Internal Trusted Storage partition")
+    set(TFM_PARTITION_CRYPTO                OFF         CACHE BOOL      "Enable Crypto partition")
+    set(TFM_PARTITION_INITIAL_ATTESTATION   OFF         CACHE BOOL      "Enable Initial Attestation partition")
+    set(TFM_PARTITION_PLATFORM              OFF         CACHE BOOL      "Enable Platform partition")
+    set(TFM_PARTITION_PSA_PROXY             ON          CACHE BOOL      "Enable PSA Proxy partition")
+    # In case of forwarding, there is no CRYPTO partition compiled,
+    # thus no need for crypto hw accelerator.
+    set(CRYPTO_HW_ACCELERATOR               OFF         CACHE BOOL      "Whether to enable the crypto hardware accelerator on supported platforms")
+    set(PS_TEST_NV_COUNTERS                 OFF         CACHE BOOL      "Use the test NV counters to test Protected Storage rollback scenarios")
+    set(BL0 ON)
 endif()
 
 set(TFM_EXTRA_GENERATED_FILE_LIST_PATH  ${CMAKE_CURRENT_SOURCE_DIR}/platform/ext/target/musca_b1/generated_file_list.yaml  CACHE PATH "Path to extra generated file list. Appended to stardard TFM generated file list." FORCE)
diff --git a/platform/ext/target/musca_b1/mailbox/platform_multicore.c b/platform/ext/target/musca_b1/mailbox/platform_multicore.c
new file mode 100644
index 0000000..1c482d7
--- /dev/null
+++ b/platform/ext/target/musca_b1/mailbox/platform_multicore.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "platform_multicore.h"
+#include "cmsis.h"
+#include "mhu_v2_x.h"
+#include "device_definition.h"
+#include "tfm_plat_psa_proxy_addr_trans.h"
+
+#define SE_MEM_BASE         (0x38000000)
+#define HOST_MEM_BASE       (0x1A200000)
+
+int tfm_platform_ns_wait_for_s_cpu_ready(void)
+{
+    mhu_v2_x_driver_init(&SE_MHU_SENDER_DEV, MHU_REV_2_0);
+    mhu_v2_x_driver_init(&SE_MHU_RECEIVER_DEV, MHU_REV_2_0);
+
+    platform_mailbox_send_msg_data(IPC_SYNC_MAGIC);
+
+    return PLATFORM_MAILBOX_SUCCESS;
+}
+
+int platform_mailbox_send_msg_data(uint32_t data)
+{
+    mhu_v2_x_initiate_transfer(&SE_MHU_SENDER_DEV);
+    mhu_v2_x_channel_send(&SE_MHU_SENDER_DEV, 0, data);
+    mhu_v2_x_close_transfer(&SE_MHU_SENDER_DEV);
+
+    return PLATFORM_MAILBOX_SUCCESS;
+}
+
+int platform_mailbox_send_msg_ptr(const void *msg_ptr)
+{
+    mhu_v2_x_initiate_transfer(&SE_MHU_SENDER_DEV);
+    mhu_v2_x_channel_send(&SE_MHU_SENDER_DEV, 0, (uint32_t)msg_ptr);
+    mhu_v2_x_close_transfer(&SE_MHU_SENDER_DEV);
+
+    return PLATFORM_MAILBOX_SUCCESS;
+}
+
+void platform_mailbox_wait_for_notify(void)
+{
+    while(NVIC_GetPendingIRQ(HostMHUR0_IRQComb_IRQn) == 0);
+}
+
+int platform_mailbox_fetch_msg_data(uint32_t *data_ptr)
+{
+    mhu_v2_x_channel_receive(&SE_MHU_RECEIVER_DEV, 0, data_ptr);
+    mhu_v2_x_channel_clear(&SE_MHU_RECEIVER_DEV, 0);
+
+    NVIC_ClearPendingIRQ(HostMHUR0_IRQComb_IRQn);
+
+    return PLATFORM_MAILBOX_SUCCESS;
+}
+
+void * translate_addr_from_host_to_se(void *addr)
+{
+    return (addr + SE_MEM_BASE - HOST_MEM_BASE);
+}
+
+void * translate_addr_from_se_to_host(void *addr)
+{
+    return (addr + HOST_MEM_BASE - SE_MEM_BASE);
+}
diff --git a/platform/ext/target/musca_b1/mailbox/platform_multicore.h b/platform/ext/target/musca_b1/mailbox/platform_multicore.h
new file mode 100644
index 0000000..cd6fa9a
--- /dev/null
+++ b/platform/ext/target/musca_b1/mailbox/platform_multicore.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _PLATFORM_MULTICORE_H_
+#define _PLATFORM_MULTICORE_H_
+
+#include <stdint.h>
+
+/* Arbitrary predefined values to sync between Host and Secure Enclave */
+#define IPC_SYNC_MAGIC                   (0x7DADE011)
+
+#define NS_MAILBOX_INIT_ENABLE           (0xAE)
+#define S_MAILBOX_READY                  (0xC3)
+
+#define PSA_CLIENT_CALL_REQ_MAGIC        (0xA5CF50C6)
+
+#define PLATFORM_MAILBOX_SUCCESS         (0x0)
+
+/**
+ * \brief Fetch a data value from mailbox message
+ *
+ * \param[out] data_ptr    The address to write the pointer value to.
+ *
+ * \retval 0               The operation succeeds.
+ * \retval else            The operation fails.
+ */
+int platform_mailbox_fetch_msg_data(uint32_t *data_ptr);
+
+/**
+ * \brief Send a pointer via mailbox message
+ *
+ * \param[in] msg_ptr      The pointer value to be sent.
+ *
+ * \retval 0               The operation succeeds.
+ * \retval else            The operation fails.
+ */
+int platform_mailbox_send_msg_ptr(const void *msg_ptr);
+
+/**
+ * \brief Send a data value via mailbox message
+ *
+ * \param[in] data         The data value to be sent
+ *
+ * \retval 0               The operation succeeds.
+ * \retval else            The operation fails.
+ */
+int platform_mailbox_send_msg_data(uint32_t data);
+
+/**
+ * \brief Wait for a mailbox notify event.
+ */
+void platform_mailbox_wait_for_notify(void);
+
+#endif /* _PLATFORM_MULTICORE_H_ */
diff --git a/platform/ext/target/musca_b1/mailbox/platform_ns_mailbox.c b/platform/ext/target/musca_b1/mailbox/platform_ns_mailbox.c
new file mode 100644
index 0000000..1b25412
--- /dev/null
+++ b/platform/ext/target/musca_b1/mailbox/platform_ns_mailbox.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#include "platform_multicore.h"
+#include "tfm_ns_mailbox.h"
+#include "tfm_plat_psa_proxy_addr_trans.h"
+
+int32_t tfm_ns_mailbox_hal_notify_peer(void)
+{
+    platform_mailbox_send_msg_data(PSA_CLIENT_CALL_REQ_MAGIC);
+
+    return MAILBOX_SUCCESS;
+}
+
+int32_t tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t *queue)
+{
+    uint32_t stage;
+
+    if (!queue) {
+        return MAILBOX_INVAL_PARAMS;
+    }
+
+    /* Wait until SPE mailbox library is ready to receive NSPE mailbox queue
+     * address.
+     */
+    while (1) {
+        platform_mailbox_wait_for_notify();
+
+        platform_mailbox_fetch_msg_data(&stage);
+        if (stage == NS_MAILBOX_INIT_ENABLE) {
+            break;
+        }
+    }
+
+    /* Send out the address */
+    platform_mailbox_send_msg_ptr(
+            (const void *)translate_addr_from_host_to_se(queue));
+
+    /* Wait until SPE mailbox service is ready */
+    while (1) {
+        platform_mailbox_wait_for_notify();
+
+        platform_mailbox_fetch_msg_data(&stage);
+        if (stage == S_MAILBOX_READY) {
+            break;
+        }
+    }
+
+    return MAILBOX_SUCCESS;
+}
+
+void tfm_ns_mailbox_hal_enter_critical(void)
+{
+    /* Protection against concurrent access should be added
+     * if more messages are sent parallel.
+     */
+}
+
+void tfm_ns_mailbox_hal_exit_critical(void)
+{
+    /* Protection against concurrent access should be added
+     * if more messages are sent parallel.
+     */
+}
+
+void tfm_ns_mailbox_hal_enter_critical_isr(void)
+{
+    /* Protection against concurrent access should be added
+     * if more messages are sent parallel.
+     */
+}
+
+void tfm_ns_mailbox_hal_exit_critical_isr(void)
+{
+    /* Protection against concurrent access should be added
+     * if more messages are sent parallel.
+     */
+}
diff --git a/platform/ext/target/musca_b1/partition/flash_layout.h b/platform/ext/target/musca_b1/partition/flash_layout.h
index ce74de5..7c26f00 100644
--- a/platform/ext/target/musca_b1/partition/flash_layout.h
+++ b/platform/ext/target/musca_b1/partition/flash_layout.h
@@ -18,7 +18,11 @@
 #ifndef __FLASH_LAYOUT_H__
 #define __FLASH_LAYOUT_H__
 
-/* Flash layout on Musca-B1 with BL2 (multiple image boot, boot from eFlash 0):
+#ifndef FORWARD_PROT_MSG
+/* Flash layouts if FORWARD_PROT_MSG is OFF
+ *
+ *
+ * Flash layout on Musca-B1 with BL2 (multiple image boot, boot from eFlash 0):
  *
  * 0x0A00_0000 BL2 - MCUBoot (128 KB)
  * 0x0A02_0000 Secure image     primary slot (384 KB)
@@ -79,7 +83,6 @@
 #define QSPI_FLASH_TOTAL_SIZE             (0x800000) /* 8 MB */
 
 /* Flash layout info for BL2 bootloader */
-/* Same as MUSCA_B1_EFLASH0_S_BASE */
 #define FLASH_BASE_ADDRESS              (0x1A000000)
 
 /* Offset and size definitions of the flash partitions that are handled by the
@@ -230,4 +233,85 @@
 #define TOTAL_ROM_SIZE FLASH_TOTAL_SIZE
 #define TOTAL_RAM_SIZE (0x80000)     /* 512 KB */
 
+#else /* FORWARD_PROT_MSG */
+
+/* Flash layout information if FORWARD_PROT_MSG is ON.
+ * For information you can check Musca-B1 Secure Enclave's flash_layout.h
+ */
+
+#define FLASH_S_PARTITION_SIZE          (0x30000) /* S partition: 192 KB */
+#define FLASH_NS_PARTITION_SIZE         (0x50000) /* NS partition: 320 KB */
+
+/* Offset and size definition in flash area used by assemble.py */
+#define SECURE_IMAGE_OFFSET             (0x0)
+#define SECURE_IMAGE_MAX_SIZE           FLASH_S_PARTITION_SIZE
+
+#define NON_SECURE_IMAGE_OFFSET         (SECURE_IMAGE_OFFSET + \
+                                         SECURE_IMAGE_MAX_SIZE)
+#define NON_SECURE_IMAGE_MAX_SIZE       FLASH_NS_PARTITION_SIZE
+
+/* Image placed in eFlash 1 */
+#define FLASH_BASE_ADDRESS              (0x1A200000)
+
+#if (MCUBOOT_IMAGE_NUMBER != 1)
+#error "If FORWARD_PROT_MSG is ON MCUBOOT_IMAGE_NUMBER must be 1"
+#endif
+
+/* Secure + Non-secure image primary slot */
+#define FLASH_AREA_0_ID            (1)
+#define FLASH_AREA_0_OFFSET        (0x60000) /* Address comes from SE */
+#define FLASH_AREA_0_SIZE          (FLASH_S_PARTITION_SIZE + \
+                                    FLASH_NS_PARTITION_SIZE)
+/* Secure + Non-secure secondary slot */
+#define FLASH_AREA_2_ID            (FLASH_AREA_0_ID + 1)
+#define FLASH_AREA_2_OFFSET        (0x160000) /* Address comes from SE */
+#define FLASH_AREA_2_SIZE          (FLASH_S_PARTITION_SIZE + \
+                                    FLASH_NS_PARTITION_SIZE)
+
+/* Image placed in eFlash 1 */
+#define S_ROM_ALIAS_BASE    (0x1A200000)
+#define NS_ROM_ALIAS_BASE   (0x0A200000)
+
+#define S_RAM_ALIAS_BASE    (0x30000000)
+#define NS_RAM_ALIAS_BASE   (0x20000000)
+
+#define TOTAL_RAM_SIZE      (0x80000)     /* 512 KB */
+
+/* Macros needed for tests, these values are copied from Secure Enclave's flash
+ * layout.
+ */
+#ifdef PSA_API_TEST_CRYPTO
+/* Need larger asset size for PSA API Crypto compliance suite */
+#define ITS_MAX_ASSET_SIZE      (1229)
+#else
+#define ITS_MAX_ASSET_SIZE      (512)
+#endif
+
+#define PS_MAX_ASSET_SIZE      (2048)
+
+/* Macros needed for BL2 build with dummy values.
+ * This BL2 instance is not used, but the BL2 macro needs to be set, and this
+ * macro and BL2 build is entangled. If this is fixed the following macros can
+ * be deleted.
+ */
+#define FLASH_AREA_IMAGE_SECTOR_SIZE    0
+
+#define MCUBOOT_STATUS_MAX_ENTRIES      0
+#define MCUBOOT_MAX_IMG_SECTORS         32
+
+#define FLASH_AREA_SCRATCH_ID           0
+#define FLASH_AREA_SCRATCH_OFFSET       0
+#define FLASH_AREA_SCRATCH_SIZE         0
+
+#define FLASH_DEV_NAME                  Driver_EFLASH0
+#define FLASH_AREA_BL2_OFFSET           0
+#define FLASH_AREA_BL2_SIZE             0x20000
+
+#define TFM_NV_COUNTERS_AREA_ADDR       0
+#define TFM_NV_COUNTERS_AREA_SIZE       8
+#define TFM_NV_COUNTERS_SECTOR_ADDR     0
+#define TFM_NV_COUNTERS_SECTOR_SIZE     8
+
+#endif /* FORWARD_PROT_MSG */
+
 #endif /* __FLASH_LAYOUT_H__ */
diff --git a/platform/ext/target/musca_b1/partition/region_defs.h b/platform/ext/target/musca_b1/partition/region_defs.h
index 566a5f9..1f6ce14 100644
--- a/platform/ext/target/musca_b1/partition/region_defs.h
+++ b/platform/ext/target/musca_b1/partition/region_defs.h
@@ -106,6 +106,12 @@
 /* CMSE Veneers region */
 #define CMSE_VENEER_REGION_START  (S_CODE_LIMIT + 1)
 
+/* Shared memory used by PSA Proxy partition */
+#ifdef TFM_PARTITION_PSA_PROXY
+#define PSA_PROXY_SHARED_MEMORY_BASE (0x1A408000)
+#define PSA_PROXY_SHARED_MEMORY_SIZE (0x00078000) /* 476 KiB */
+#endif /* TFM_PARTITION_PSA_PROXY */
+
 /* Non-secure regions */
 #define NS_IMAGE_PRIMARY_AREA_OFFSET \
                         (NS_IMAGE_PRIMARY_PARTITION_OFFSET + BL2_HEADER_SIZE)
diff --git a/platform/ext/target/musca_b1/target_cfg.c b/platform/ext/target/musca_b1/target_cfg.c
index f7a0404..3b0f42f 100644
--- a/platform/ext/target/musca_b1/target_cfg.c
+++ b/platform/ext/target/musca_b1/target_cfg.c
@@ -63,7 +63,15 @@
 #define NSCCFG_CODENSC  1
 
 /* Import MPC driver */
-extern ARM_DRIVER_MPC Driver_CODE_SRAM_MPC, Driver_EFLASH0_MPC;
+extern ARM_DRIVER_MPC Driver_CODE_SRAM_MPC;
+#ifndef LINK_TO_EFLASH1
+extern ARM_DRIVER_MPC Driver_EFLASH0_MPC;
+#define EFLASH_MPC Driver_EFLASH0_MPC
+#else
+extern ARM_DRIVER_MPC Driver_EFLASH1_MPC;
+#define EFLASH_MPC Driver_EFLASH1_MPC
+#endif
+
 extern ARM_DRIVER_MPC Driver_ISRAM0_MPC, Driver_ISRAM1_MPC;
 extern ARM_DRIVER_MPC Driver_ISRAM2_MPC, Driver_ISRAM3_MPC;
 
@@ -275,7 +283,7 @@
     int32_t ret = ARM_DRIVER_OK;
 
     /* MPC interrupt enabling */
-    ret = Driver_EFLASH0_MPC.EnableInterrupt();
+    ret = EFLASH_MPC.EnableInterrupt();
     if (ret != ARM_DRIVER_OK) {
         return TFM_PLAT_ERR_SYSTEM_ERR;
     }
@@ -380,28 +388,28 @@
     ARM_DRIVER_MPC* mpc_data_region2 = &Driver_ISRAM2_MPC;
     ARM_DRIVER_MPC* mpc_data_region3 = &Driver_ISRAM3_MPC;
 
-    ret = Driver_EFLASH0_MPC.Initialize();
+    ret = EFLASH_MPC.Initialize();
     if (ret != ARM_DRIVER_OK) {
         return ret;
     }
-    ret = Driver_EFLASH0_MPC.ConfigRegion(
-                                      memory_regions.non_secure_partition_base,
-                                      memory_regions.non_secure_partition_limit,
-                                      ARM_MPC_ATTR_NONSECURE);
+    ret = EFLASH_MPC.ConfigRegion(memory_regions.non_secure_partition_base,
+                                  memory_regions.non_secure_partition_limit,
+                                  ARM_MPC_ATTR_NONSECURE);
     if (ret != ARM_DRIVER_OK) {
         return ret;
     }
 
+#ifndef LINK_TO_EFLASH1
 #ifdef BL2
     /* Secondary image region */
-    ret = Driver_EFLASH0_MPC.ConfigRegion(
-                                       memory_regions.secondary_partition_base,
-                                       memory_regions.secondary_partition_limit,
-                                       ARM_MPC_ATTR_NONSECURE);
+    ret = EFLASH_MPC.ConfigRegion(memory_regions.secondary_partition_base,
+                                  memory_regions.secondary_partition_limit,
+                                  ARM_MPC_ATTR_NONSECURE);
     if (ret != ARM_DRIVER_OK) {
         return ret;
     }
 #endif /* BL2 */
+#endif
 
     /* SRAM MPC device needs to be initialialized so that the interrupt can be
      * enabled later. The default (secure only) config is used.
@@ -469,9 +477,9 @@
     ARM_DRIVER_MPC* mpc_data_region2 = &Driver_ISRAM2_MPC;
     ARM_DRIVER_MPC* mpc_data_region3 = &Driver_ISRAM3_MPC;
 
-    Driver_EFLASH0_MPC.ConfigRegion(MPC_EFLASH0_RANGE_BASE_S,
-                                    MPC_EFLASH0_RANGE_LIMIT_S,
-                                    ARM_MPC_ATTR_SECURE);
+    EFLASH_MPC.ConfigRegion(MPC_EFLASH0_RANGE_BASE_S,
+                            MPC_EFLASH0_RANGE_LIMIT_S,
+                            ARM_MPC_ATTR_SECURE);
 
     mpc_data_region2->ConfigRegion(MPC_ISRAM2_RANGE_BASE_S,
                                    MPC_ISRAM2_RANGE_LIMIT_S,