RSS: Enable SIC and XIP mode

Change-Id: I19222bc4b668ccc41e087927f822ae25757e33bd
Signed-off-by: Raef Coles <raef.coles@arm.com>
diff --git a/bl2/ext/mcuboot/bl2_main.c b/bl2/ext/mcuboot/bl2_main.c
index 6318a75..c45c3ba 100644
--- a/bl2/ext/mcuboot/bl2_main.c
+++ b/bl2/ext/mcuboot/bl2_main.c
@@ -48,6 +48,7 @@
 
 /* Static buffer to be used by mbedtls for memory allocation */
 static uint8_t mbedtls_mem_buf[BL2_MBEDTLS_MEM_BUF_LEN];
+struct boot_rsp rsp;
 
 static void do_boot(struct boot_rsp *rsp)
 {
@@ -88,7 +89,6 @@
 
 int main(void)
 {
-    struct boot_rsp rsp;
     fih_int fih_rc = FIH_FAILURE;
     enum tfm_plat_err_t plat_err;
     int32_t image_id;
diff --git a/docs/platform/arm/rss/readme.rst b/docs/platform/arm/rss/readme.rst
index d36e6ea..fd185f2 100644
--- a/docs/platform/arm/rss/readme.rst
+++ b/docs/platform/arm/rss/readme.rst
@@ -97,13 +97,32 @@
         <SCP BL1 image> -Binary -offset 0x320000 \
         -o flash.bin -Binary
 
+If XIP mode is enabled, the following ``srec_cat`` command should be run to
+create the flash image::
+
+    srec_cat \
+        bl2_signed.bin -Binary -offset 0x0 \
+        bl2_signed.bin -Binary -offset 0x10000 \
+        tfm_s.bin -Binary -offset 0x020000 \
+        tfm_ns.bin -Binary -offset 0x080000 \
+        tfm_s.bin -Binary -offset 0x0E0000 \
+        tfm_ns.bin -Binary -offset 0x140000 \
+        <Host AP BL1 image> -Binary -offset 0x1A0000 \
+        <SCP BL1 image> -Binary -offset 0x220000 \
+        <Host AP BL1 image>  -Binary -offset 0x2A0000 \
+        <SCP BL1 image> -Binary -offset 0x320000 \
+        tfm_s_sic_tables_signed.bin -Binary -offset 0x3A0000 \
+        tfm_ns_sic_tables_signed.bin -Binary -offset 0x3AA000 \
+        tfm_s_sic_tables_signed.bin -Binary -offset 0x3B4000 \
+        tfm_ns_sic_tables_signed.bin -Binary -offset 0x3BE000 \
+        -o flash.bin -Binary
 
 Once the flash image is created, it can be combined with the host FIP to create
 a combined host flash image::
 
     srec_cat \
             fip-tc.bin -Binary -offset 0x0\
-            flash.bin -Binary -offset 0x00400000 \
+            flash.bin -Binary -offset 0x02200000 \
             -o host_flash.bin -Binary
 
 For development purposes, the OTP image is included as a provisioning bundle in
@@ -114,8 +133,8 @@
 
 The ROM binary should be placed in RSS ROM at ``0x11000000`` and the host flash
 binary should be placed at the base of the host flash. For the TC platform,
-this is at ``0x84000000``.
+this is at ``0x08000000``.
 
 --------------
 
-*Copyright (c) 2022, Arm Limited. All rights reserved.*
+*Copyright (c) 2022-2023, Arm Limited. All rights reserved.*
diff --git a/platform/ext/target/arm/rss/common/CMakeLists.txt b/platform/ext/target/arm/rss/common/CMakeLists.txt
index 2695aaf..0aff888 100644
--- a/platform/ext/target/arm/rss/common/CMakeLists.txt
+++ b/platform/ext/target/arm/rss/common/CMakeLists.txt
@@ -18,6 +18,11 @@
         cc312
 )
 
+target_compile_definitions(platform_region_defs
+    INTERFACE
+        $<$<BOOL:${RSS_XIP}>:RSS_XIP>
+)
+
 #========================= Platform common defs ===============================#
 
 # Specify the location of platform specific build dependencies.
diff --git a/platform/ext/target/arm/rss/common/bl2/provisioning.c b/platform/ext/target/arm/rss/common/bl2/provisioning.c
index 88cac14..a265d75 100644
--- a/platform/ext/target/arm/rss/common/bl2/provisioning.c
+++ b/platform/ext/target/arm/rss/common/bl2/provisioning.c
@@ -23,6 +23,8 @@
     uint8_t bl2_rotpk_1[32];
     uint8_t bl2_rotpk_2[32];
     uint8_t bl2_rotpk_3[32];
+    uint8_t s_image_encryption_key[32];
+    uint8_t ns_image_encryption_key[32];
 
 #ifdef PLATFORM_PSA_ADAC_SECURE_DEBUG
     uint8_t secure_debug_pk[32];
@@ -94,6 +96,21 @@
 #error "No public key available for given signing algorithm."
 #endif /* MCUBOOT_SIGN_RSA_LEN */
 
+    /* Secure image encryption key; */
+    {
+        0xfc, 0x57, 0x01, 0xdc, 0x61, 0x35, 0xe1, 0x32,
+        0x38, 0x47, 0xbd, 0xc4, 0x0f, 0x04, 0xd2, 0xe5,
+        0xbe, 0xe5, 0x83, 0x3b, 0x23, 0xc2, 0x9f, 0x93,
+        0x59, 0x3d, 0x00, 0x01, 0x8c, 0xfa, 0x99, 0x94,
+    },
+    /* Non-secure image encryption key; */
+    {
+        0xfc, 0x57, 0x01, 0xdc, 0x61, 0x35, 0xe1, 0x32,
+        0x38, 0x47, 0xbd, 0xc4, 0x0f, 0x04, 0xd2, 0xe5,
+        0xbe, 0xe5, 0x83, 0x3b, 0x23, 0xc2, 0x9f, 0x93,
+        0x59, 0x3d, 0x00, 0x01, 0x8c, 0xfa, 0x99, 0x94,
+    },
+
 #ifdef PLATFORM_PSA_ADAC_SECURE_DEBUG
     {
         0xf4, 0x0c, 0x8f, 0xbf, 0x12, 0xdb, 0x78, 0x2a,
@@ -167,6 +184,19 @@
         return err;
     }
 
+    err = tfm_plat_otp_write(PLAT_OTP_ID_KEY_SECURE_ENCRYPTION,
+                             sizeof(bl2_assembly_and_test_prov_data.s_image_encryption_key),
+                             bl2_assembly_and_test_prov_data.s_image_encryption_key);
+    if (err != TFM_PLAT_ERR_SUCCESS && err != TFM_PLAT_ERR_UNSUPPORTED) {
+        return err;
+    }
+    err = tfm_plat_otp_write(PLAT_OTP_ID_KEY_NON_SECURE_ENCRYPTION,
+                             sizeof(bl2_assembly_and_test_prov_data.ns_image_encryption_key),
+                             bl2_assembly_and_test_prov_data.ns_image_encryption_key);
+    if (err != TFM_PLAT_ERR_SUCCESS && err != TFM_PLAT_ERR_UNSUPPORTED) {
+        return err;
+    }
+
 #ifdef PLATFORM_PSA_ADAC_SECURE_DEBUG
     err = tfm_plat_otp_write(PLAT_OTP_ID_SECURE_DEBUG_PK,
                              sizeof(bl2_assembly_and_test_prov_data.secure_debug_pk),
diff --git a/platform/ext/target/arm/rss/common/otp_lcm.c b/platform/ext/target/arm/rss/common/otp_lcm.c
index 3d97b18..5b0b362 100644
--- a/platform/ext/target/arm/rss/common/otp_lcm.c
+++ b/platform/ext/target/arm/rss/common/otp_lcm.c
@@ -26,6 +26,8 @@
     uint32_t iak_id_zero_bits;
     uint32_t bl2_rotpk_zero_bits[3];
     uint32_t bl2_encryption_key_zero_bits;
+    uint32_t s_image_encryption_key_zero_bits;
+    uint32_t ns_image_encryption_key_zero_bits;
     uint32_t bl1_2_image_hash_zero_bits;
     uint32_t bl2_image_hash_zero_bits;
     uint32_t bl1_rotpk_0_zero_bits;
@@ -49,6 +51,9 @@
     uint32_t bl2_nv_counter[4][128];
 
     uint32_t bl2_encryption_key[8];
+    uint32_t s_image_encryption_key[8];
+    uint32_t ns_image_encryption_key[8];
+
     uint32_t bl1_2_image_hash[8];
     uint32_t bl2_image_hash[8];
     uint32_t bl1_nv_counter[128];
@@ -233,6 +238,19 @@
         }
     }
 
+    err = verify_zero_bits_count(USER_AREA_OFFSET(s_image_encryption_key),
+                                 USER_AREA_SIZE(s_image_encryption_key),
+                                 USER_AREA_OFFSET(s_image_encryption_key_zero_bits));
+    if (err != TFM_PLAT_ERR_SUCCESS) {
+        return err;
+    }
+    err = verify_zero_bits_count(USER_AREA_OFFSET(ns_image_encryption_key),
+                                 USER_AREA_SIZE(ns_image_encryption_key),
+                                 USER_AREA_OFFSET(ns_image_encryption_key_zero_bits));
+    if (err != TFM_PLAT_ERR_SUCCESS) {
+        return err;
+    }
+
 #ifdef BL1
     err = verify_zero_bits_count(USER_AREA_OFFSET(bl2_encryption_key),
                                  USER_AREA_SIZE(bl2_encryption_key),
@@ -480,6 +498,12 @@
         return otp_read(USER_AREA_OFFSET(host_nv_counter[2]),
                         USER_AREA_SIZE(host_nv_counter[2]), out_len, out);
 
+    case PLAT_OTP_ID_KEY_SECURE_ENCRYPTION:
+        return otp_read(USER_AREA_OFFSET(s_image_encryption_key),
+                        USER_AREA_SIZE(s_image_encryption_key), out_len, out);
+    case PLAT_OTP_ID_KEY_NON_SECURE_ENCRYPTION:
+        return otp_read(USER_AREA_OFFSET(ns_image_encryption_key),
+                        USER_AREA_SIZE(ns_image_encryption_key), out_len, out);
 #ifdef BL1
     case PLAT_OTP_ID_KEY_BL2_ENCRYPTION:
         return otp_read(USER_AREA_OFFSET(bl2_encryption_key),
@@ -624,6 +648,14 @@
         return otp_write(USER_AREA_OFFSET(host_nv_counter[2]),
                          USER_AREA_SIZE(host_nv_counter[2]), in_len, in, 0);
 
+    case PLAT_OTP_ID_KEY_SECURE_ENCRYPTION:
+        return otp_write(USER_AREA_OFFSET(s_image_encryption_key),
+                         USER_AREA_SIZE(s_image_encryption_key), in_len, in,
+                         USER_AREA_OFFSET(s_image_encryption_key_zero_bits));
+    case PLAT_OTP_ID_KEY_NON_SECURE_ENCRYPTION:
+        return otp_write(USER_AREA_OFFSET(ns_image_encryption_key),
+                         USER_AREA_SIZE(ns_image_encryption_key), in_len, in,
+                         USER_AREA_OFFSET(ns_image_encryption_key_zero_bits));
 #ifdef BL1
     case PLAT_OTP_ID_KEY_BL2_ENCRYPTION:
         return otp_write(USER_AREA_OFFSET(bl2_encryption_key),
@@ -749,6 +781,12 @@
         *size = USER_AREA_SIZE(host_nv_counter[2]);
         break;
 
+    case PLAT_OTP_ID_KEY_SECURE_ENCRYPTION:
+        *size = USER_AREA_SIZE(s_image_encryption_key);
+        break;
+    case PLAT_OTP_ID_KEY_NON_SECURE_ENCRYPTION:
+        *size = USER_AREA_SIZE(ns_image_encryption_key);
+        break;
 #ifdef BL1
     case PLAT_OTP_ID_KEY_BL2_ENCRYPTION:
         *size = USER_AREA_SIZE(bl2_encryption_key);
diff --git a/platform/ext/target/arm/rss/common/partition/platform_base_address.h b/platform/ext/target/arm/rss/common/partition/platform_base_address.h
index cd973af..162d9bb 100644
--- a/platform/ext/target/arm/rss/common/partition/platform_base_address.h
+++ b/platform/ext/target/arm/rss/common/partition/platform_base_address.h
@@ -145,6 +145,12 @@
 #define FWU_HOST_IMAGE_BASE_S            (HOST_ACCESS_BASE_S + 0x000000) /* Region to allow writing new RSS FW images */
 #define HOST_COMMS_MAPPABLE_BASE_S       (HOST_ACCESS_BASE_S + 0x100000) /* Region into which to map host comms pointers */
 
+/* SIC regions open in BL2 and runtime */
+#define RSS_RUNTIME_S_XIP_BASE_S         SIC_HOST_BASE_S              /* RSS runtime secure image XIP secure address */
+#define RSS_RUNTIME_NS_XIP_BASE_S        (SIC_HOST_BASE_S + 0x060000) /* RSS runtime non-secure image XIP secure address */
+
+#define RSS_RUNTIME_NS_XIP_BASE_NS       (SIC_HOST_BASE_NS + 0x060000) /* RSS runtime non-secure image XIP non-secure address */
+
 /* Memory map addresses exempt from memory attribution by both the SAU and IDAU */
 #define RSS_EWIC_BASE                    0xE0047000 /* External Wakeup Interrupt Controller
                                                      * Access from Non-secure software is only allowed
diff --git a/platform/ext/target/arm/rss/common/partition/region_defs.h b/platform/ext/target/arm/rss/common/partition/region_defs.h
index 35eb0f1..a3c2a23 100644
--- a/platform/ext/target/arm/rss/common/partition/region_defs.h
+++ b/platform/ext/target/arm/rss/common/partition/region_defs.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2022 Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2023 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.
@@ -107,9 +107,14 @@
             (FLASH_NS_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE)
 
 /* Secure regions */
-/* Secure Code executes from VM0 */
+/* Secure Code executes from VM0, or XIP from flash via the SIC */
+#ifdef RSS_XIP
+#define S_CODE_START    (RSS_RUNTIME_S_XIP_BASE_S)
+#define S_CODE_SIZE     (FLASH_S_PARTITION_SIZE)
+#else
 #define S_CODE_START    (S_IMAGE_LOAD_ADDRESS + BL2_HEADER_SIZE)
 #define S_CODE_SIZE     (IMAGE_S_CODE_SIZE)
+#endif /* RSS_XIP */
 #define S_CODE_LIMIT    (S_CODE_START + S_CODE_SIZE - 1)
 
 /* Secure Data stored in VM0. Size defined in flash layout */
@@ -120,19 +125,31 @@
 #define S_CODE_VECTOR_TABLE_SIZE    (0x1C0)
 
 /* Non-secure regions */
-/* Non-Secure Code executes from VM1 */
+/* Non-Secure Code executes from VM1, or XIP from flash via the SIC */
+#ifdef RSS_XIP
+#define NS_CODE_START   (RSS_RUNTIME_NS_XIP_BASE_NS)
+#define NS_CODE_SIZE    (FLASH_NS_PARTITION_SIZE)
+#else
 #define NS_CODE_START   (VM1_BASE_NS + NS_DATA_SIZE + BL2_HEADER_SIZE)
 #define NS_CODE_SIZE    (IMAGE_NS_CODE_SIZE)
+#endif /* RSS_XIP */
 #define NS_CODE_LIMIT   (NS_CODE_START + NS_CODE_SIZE - 1)
 
-/* Non-Secure Data stored in VM1. */
+/* Non-Secure Data stored after secure data, or in VM1. */
+#ifdef RSS_XIP
+#define NS_DATA_START   (VM0_BASE_NS + S_DATA_SIZE)
+#else
 #define NS_DATA_START   (VM1_BASE_NS)
+#endif
 #define NS_DATA_LIMIT   (NS_DATA_START + NS_DATA_SIZE - 1)
 
 /* NS partition information is used for MPC and SAU configuration */
+#ifdef RSS_XIP
+#define NS_PARTITION_START RSS_RUNTIME_NS_XIP_BASE_NS
+#else
 #define NS_PARTITION_START (NS_CODE_START)
-#define NS_PARTITION_SIZE (FLASH_NS_PARTITION_SIZE - BL2_HEADER_SIZE \
-                           - BL2_TRAILER_SIZE)
+#endif /* RSS_XIP */
+#define NS_PARTITION_SIZE (NS_CODE_SIZE)
 
 #define SECONDARY_PARTITION_START (FWU_HOST_IMAGE_BASE_S)
 #define SECONDARY_PARTITION_SIZE (0x100000)
diff --git a/platform/ext/target/arm/rss/common/platform_otp_ids.h b/platform/ext/target/arm/rss/common/platform_otp_ids.h
index 5991f37..46db6a5 100644
--- a/platform/ext/target/arm/rss/common/platform_otp_ids.h
+++ b/platform/ext/target/arm/rss/common/platform_otp_ids.h
@@ -44,6 +44,9 @@
     PLAT_OTP_ID_NV_COUNTER_NS_2,
 
     PLAT_OTP_ID_KEY_BL2_ENCRYPTION,
+    PLAT_OTP_ID_KEY_SECURE_ENCRYPTION,
+    PLAT_OTP_ID_KEY_NON_SECURE_ENCRYPTION,
+
     PLAT_OTP_ID_BL1_2_IMAGE,
     PLAT_OTP_ID_BL1_2_IMAGE_HASH,
     PLAT_OTP_ID_BL2_IMAGE_HASH,
diff --git a/platform/ext/target/arm/rss/common/rss_comms/rss_comms_atu_hal.h b/platform/ext/target/arm/rss/common/rss_comms/rss_comms_atu_hal.h
index 098af9f..c1caa04 100644
--- a/platform/ext/target/arm/rss/common/rss_comms/rss_comms_atu_hal.h
+++ b/platform/ext/target/arm/rss/common/rss_comms/rss_comms_atu_hal.h
@@ -8,7 +8,12 @@
 #ifndef __RSS_COMMS_ATU_HAL_H__
 #define __RSS_COMMS_ATU_HAL_H__
 
+#ifndef RSS_XIP
 #define RSS_COMMS_ATU_REGION_MIN        0
+#else
+#define RSS_COMMS_ATU_REGION_MIN        2
+#endif /* !RSS_XIP */
+
 #define RSS_COMMS_ATU_REGION_MAX        15
 /* There must be at least one region */
 #define RSS_COMMS_ATU_REGION_AM         (RSS_COMMS_ATU_REGION_MAX - \
diff --git a/platform/ext/target/arm/rss/common/target_cfg.c b/platform/ext/target/arm/rss/common/target_cfg.c
index 696ea26..c053d0c 100644
--- a/platform/ext/target/arm/rss/common/target_cfg.c
+++ b/platform/ext/target/arm/rss/common/target_cfg.c
@@ -338,6 +338,12 @@
     if (ret != ARM_DRIVER_OK) {
         return TFM_PLAT_ERR_SYSTEM_ERR;
     }
+#ifdef RSS_XIP
+    ret = Driver_SIC_MPC.Initialize();
+    if (ret != ARM_DRIVER_OK) {
+        return TFM_PLAT_ERR_SYSTEM_ERR;
+    }
+#endif /* RSS_XIP */
 
     /* Configuring primary non-secure partition.
      * It is ensured in flash_layout.h that these memory regions are located in
@@ -349,9 +355,16 @@
     if (ret != ARM_DRIVER_OK) {
         return TFM_PLAT_ERR_SYSTEM_ERR;
     }
+
+#ifdef RSS_XIP
+    ret = Driver_SIC_MPC.ConfigRegion(memory_regions.non_secure_partition_base,
+                                      memory_regions.non_secure_partition_limit,
+                                      ARM_MPC_ATTR_NONSECURE);
+#else
     ret = Driver_VM1_MPC.ConfigRegion(memory_regions.non_secure_partition_base,
                                       memory_regions.non_secure_partition_limit,
                                       ARM_MPC_ATTR_NONSECURE);
+#endif /* !RSS_XIP */
     if (ret != ARM_DRIVER_OK) {
         return TFM_PLAT_ERR_SYSTEM_ERR;
     }
@@ -366,6 +379,12 @@
     if (ret != ARM_DRIVER_OK) {
         return ret;
     }
+#ifdef RSS_XIP
+    ret = Driver_SIC_MPC.LockDown();
+    if (ret != ARM_DRIVER_OK) {
+        return ret;
+    }
+#endif /* RSS_XIP */
 
     /* Add barriers to assure the MPC configuration is done before continue
      * the execution.
@@ -380,6 +399,9 @@
 {
     Driver_VM0_MPC.ClearInterrupt();
     Driver_VM1_MPC.ClearInterrupt();
+#ifdef RSS_XIP
+    Driver_SIC_MPC.ClearInterrupt();
+#endif /* RSS_XIP */
 }
 
 /*------------------- PPC configuration functions -------------------------*/
diff --git a/platform/ext/target/arm/rss/tc/CMakeLists.txt b/platform/ext/target/arm/rss/tc/CMakeLists.txt
index 5b6cb5f..59d8709 100644
--- a/platform/ext/target/arm/rss/tc/CMakeLists.txt
+++ b/platform/ext/target/arm/rss/tc/CMakeLists.txt
@@ -17,6 +17,11 @@
         .
 )
 
+target_compile_definitions(platform_region_defs
+    INTERFACE
+        $<$<BOOL:${RSS_XIP}>:RSS_XIP>
+)
+
 #========================= Platform BL2 =======================================#
 
 target_sources(platform_bl2
@@ -24,6 +29,7 @@
         bl2/boot_hal_bl2.c
         bl2/flash_map_bl2.c
         bl2/host_flash_atu.c
+        $<$<BOOL:${RSS_XIP}>:${CMAKE_CURRENT_SOURCE_DIR}/bl2/sic_boot.c>
 )
 
 target_compile_definitions(platform_bl2
@@ -36,3 +42,149 @@
     PUBLIC
         $<$<BOOL:${PLATFORM_HAS_BOOT_DMA}>:${CMAKE_CURRENT_SOURCE_DIR}/../common/bl2>
 )
+
+############################### IMAGE SIGNING ##################################
+
+if (RSS_XIP)
+    find_package(Python3)
+
+    add_custom_target(tfm_s_sic_tables
+        SOURCES bin/tfm_s_sic_tables.bin
+    )
+
+    add_custom_command(OUTPUT bin/tfm_s_sic_tables.bin
+        DEPENDS $<TARGET_FILE_DIR:tfm_s>/tfm_s.bin
+        DEPENDS tfm_s_bin
+        COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/bl2/create_xip_tables.py
+            --input_image $<TARGET_FILE_DIR:tfm_s>/tfm_s.bin
+            --table_output_file tfm_s_sic_tables.bin
+            --encrypted_image_output_file tfm_s_encrypted.bin
+            --image_version ${MCUBOOT_SECURITY_COUNTER_S}
+        COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/tfm_s_sic_tables.bin $<TARGET_FILE_DIR:tfm_s>
+        COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/tfm_s_encrypted.bin $<TARGET_FILE_DIR:tfm_s>
+    )
+
+    add_custom_target(tfm_ns_sic_tables
+        SOURCES bin/tfm_ns_sic_tables.bin
+    )
+
+    add_custom_command(OUTPUT bin/tfm_ns_sic_tables.bin
+        DEPENDS $<TARGET_FILE_DIR:tfm_ns>/tfm_ns.bin
+        DEPENDS tfm_ns_bin
+        COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/bl2/create_xip_tables.py
+            --input_image $<TARGET_FILE_DIR:tfm_ns>/tfm_ns.bin
+            --table_output_file tfm_ns_sic_tables.bin
+            --encrypted_image_output_file tfm_ns_encrypted.bin
+            --image_version ${MCUBOOT_SECURITY_COUNTER_NS}
+        COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/tfm_ns_sic_tables.bin $<TARGET_FILE_DIR:tfm_ns>
+        COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/tfm_ns_encrypted.bin $<TARGET_FILE_DIR:tfm_s>
+    )
+
+    set(IMAGE_TYPE "S_IMAGE")
+    set(FLASH_AREA_NUM ${MCUBOOT_S_IMAGE_FLASH_AREA_NUM})
+    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/bl2/signing_layout_sic_tables.c.in signing_layout_s.c @ONLY)
+    add_library(signing_layout_s OBJECT ${CMAKE_CURRENT_BINARY_DIR}/signing_layout_s.c)
+
+    target_compile_options(signing_layout_s
+        PRIVATE
+            $<$<C_COMPILER_ID:GNU>:-E\;-xc>
+            $<$<C_COMPILER_ID:ARMClang>:-E\;-xc>
+            $<$<C_COMPILER_ID:IAR>:--preprocess=ns\;$<TARGET_OBJECTS:signing_layout_s>>
+    )
+    target_compile_definitions(signing_layout_s
+        PRIVATE
+            $<$<BOOL:${BL2}>:BL2>
+            $<$<BOOL:${MCUBOOT_IMAGE_NUMBER}>:MCUBOOT_IMAGE_NUMBER=${MCUBOOT_IMAGE_NUMBER}>
+            $<$<STREQUAL:${MCUBOOT_UPGRADE_STRATEGY},DIRECT_XIP>:IMAGE_ROM_FIXED>
+    )
+    target_link_libraries(signing_layout_s
+        PRIVATE
+            platform_bl2
+    )
+
+    add_custom_target(tfm_s_sic_tables_signed_bin
+        SOURCES bin/tfm_s_sic_tables_signed.bin
+    )
+    add_custom_command(OUTPUT bin/tfm_s_sic_tables_signed.bin
+        DEPENDS tfm_s_sic_tables
+        DEPENDS tfm_s_bin signing_layout_s
+        WORKING_DIRECTORY ${MCUBOOT_PATH}/scripts
+
+        #Sign secure binary image with provided secret key
+        COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/bl2/ext/mcuboot/scripts/wrapper/wrapper.py
+            -v ${MCUBOOT_IMAGE_VERSION_S}
+            --layout $<TARGET_OBJECTS:signing_layout_s>
+            -k ${MCUBOOT_KEY_S}
+            --public-key-format $<IF:$<BOOL:${MCUBOOT_HW_KEY}>,full,hash>
+            --align ${MCUBOOT_ALIGN_VAL}
+            --pad
+            --pad-header
+            -H ${BL2_HEADER_SIZE}
+            -s ${MCUBOOT_SECURITY_COUNTER_S}
+            -L ${MCUBOOT_ENC_KEY_LEN}
+            -d \"\(1,${MCUBOOT_NS_IMAGE_MIN_VER}\)\"
+            $<$<STREQUAL:${MCUBOOT_UPGRADE_STRATEGY},OVERWRITE_ONLY>:--overwrite-only>
+            $<$<BOOL:${MCUBOOT_ENC_IMAGES}>:-E${MCUBOOT_KEY_ENC}>
+            $<$<BOOL:${MCUBOOT_MEASURED_BOOT}>:--measured-boot-record>
+            $<TARGET_FILE_DIR:tfm_s>/tfm_s_sic_tables.bin
+            ${CMAKE_CURRENT_BINARY_DIR}/tfm_s_sic_tables_signed.bin
+        COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/tfm_s_sic_tables_signed.bin $<TARGET_FILE_DIR:bl2>
+    )
+
+    set(IMAGE_TYPE "NS_IMAGE")
+    set(FLASH_AREA_NUM ${MCUBOOT_NS_IMAGE_FLASH_AREA_NUM})
+    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/bl2/signing_layout_sic_tables.c.in signing_layout_ns.c @ONLY)
+    add_library(signing_layout_ns OBJECT ${CMAKE_CURRENT_BINARY_DIR}/signing_layout_ns.c)
+
+    target_compile_options(signing_layout_ns
+        PRIVATE
+            $<$<C_COMPILER_ID:GNU>:-E\;-xc>
+            $<$<C_COMPILER_ID:ARMClang>:-E\;-xc>
+            $<$<C_COMPILER_ID:IAR>:--preprocess=ns\;$<TARGET_OBJECTS:signing_layout_ns>>
+    )
+    target_compile_definitions(signing_layout_ns
+        PRIVATE
+            $<$<BOOL:${BL2}>:BL2>
+            $<$<BOOL:${MCUBOOT_IMAGE_NUMBER}>:MCUBOOT_IMAGE_NUMBER=${MCUBOOT_IMAGE_NUMBER}>
+            $<$<STREQUAL:${MCUBOOT_UPGRADE_STRATEGY},DIRECT_XIP>:IMAGE_ROM_FIXED>
+    )
+    target_link_libraries(signing_layout_ns
+        PRIVATE
+            platform_bl2
+    )
+
+    add_custom_target(tfm_ns_sic_tables_signed_bin
+        SOURCES bin/tfm_ns_sic_tables_signed.bin
+    )
+    add_custom_command(OUTPUT bin/tfm_ns_sic_tables_signed.bin
+        DEPENDS tfm_ns_sic_tables
+        DEPENDS tfm_ns_bin signing_layout_ns
+        WORKING_DIRECTORY ${MCUBOOT_PATH}/scripts
+
+        #Sign non-secure binary image with provided secret key
+        COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/bl2/ext/mcuboot/scripts/wrapper/wrapper.py
+            -v ${MCUBOOT_IMAGE_VERSION_NS}
+            --layout $<TARGET_OBJECTS:signing_layout_ns>
+            -k ${MCUBOOT_KEY_NS}
+            --public-key-format $<IF:$<BOOL:${MCUBOOT_HW_KEY}>,full,hash>
+            --align ${MCUBOOT_ALIGN_VAL}
+            --pad
+            --pad-header
+            -H ${BL2_HEADER_SIZE}
+            -s ${MCUBOOT_SECURITY_COUNTER_NS}
+            -L ${MCUBOOT_ENC_KEY_LEN}
+            -d \"\(0, ${MCUBOOT_S_IMAGE_MIN_VER}\)\"
+            $<TARGET_FILE_DIR:tfm_ns>/tfm_ns_sic_tables.bin
+            $<$<STREQUAL:${MCUBOOT_UPGRADE_STRATEGY},OVERWRITE_ONLY>:--overwrite-only>
+            $<$<BOOL:${MCUBOOT_ENC_IMAGES}>:-E${MCUBOOT_KEY_ENC}>
+            $<$<BOOL:${MCUBOOT_MEASURED_BOOT}>:--measured-boot-record>
+            ${CMAKE_CURRENT_BINARY_DIR}/tfm_ns_sic_tables_signed.bin
+        COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/tfm_ns_sic_tables_signed.bin $<TARGET_FILE_DIR:bl2>
+    )
+
+    add_custom_target(signed_images
+        ALL
+        DEPENDS bin/tfm_s_sic_tables_signed.bin
+        DEPENDS bin/tfm_ns_sic_tables_signed.bin
+    )
+endif()
diff --git a/platform/ext/target/arm/rss/tc/bl2/boot_hal_bl2.c b/platform/ext/target/arm/rss/tc/bl2/boot_hal_bl2.c
index eb49cbe..3e0a4ec 100644
--- a/platform/ext/target/arm/rss/tc/bl2/boot_hal_bl2.c
+++ b/platform/ext/target/arm/rss/tc/bl2/boot_hal_bl2.c
@@ -14,6 +14,7 @@
 #endif /* PLATFORM_HAS_BOOT_DMA */
 #include "flash_layout.h"
 #include "bootutil/bootutil_log.h"
+#include "bootutil/bootutil.h"
 #include "device_definition.h"
 #include "host_base_address.h"
 #include "platform_base_address.h"
@@ -26,11 +27,14 @@
 #include "bl2_image_id.h"
 #include "Driver_Flash.h"
 #include "host_flash_atu.h"
+#include "sic_boot.h"
 
 #ifdef FLASH_DEV_NAME
 extern ARM_DRIVER_FLASH FLASH_DEV_NAME;
 #endif /* FLASH_DEV_NAME */
 
+extern struct boot_rsp rsp;
+
 int32_t boot_platform_post_init(void)
 {
     enum mhu_v2_x_error_t status;
@@ -72,6 +76,13 @@
     BOOT_LOG_INF("DMA350 driver initialized successfully.");
 #endif /* PLATFORM_HAS_BOOT_DMA */
 
+#ifdef RSS_XIP
+    result = sic_boot_init();
+    if (result) {
+        return result;
+    }
+#endif /* RSS_XIP */
+
     return 0;
 }
 
@@ -82,7 +93,14 @@
 
 int boot_platform_post_load(uint32_t image_id)
 {
-    enum atu_error_t err;
+    int err;
+
+#ifdef RSS_XIP
+    err = sic_boot_post_load(image_id, rsp.br_image_off);
+    if (err) {
+        return err;
+    }
+#endif /* RSS_XIP */
 
     if (image_id == RSS_BL2_IMAGE_SCP) {
         uint32_t channel_stat = 0;
@@ -120,3 +138,71 @@
 
     return 0;
 }
+
+void boot_platform_quit(struct boot_arm_vector_table *vt)
+{
+    /* Clang at O0, stores variables on the stack with SP relative addressing.
+     * When manually set the SP then the place of reset vector is lost.
+     * Static variables are stored in 'data' or 'bss' section, change of SP has
+     * no effect on them.
+     */
+    static struct boot_arm_vector_table *vt_cpy;
+    int32_t result;
+
+    vt_cpy = vt;
+
+#ifdef RSS_XIP
+    result = sic_boot_pre_quit(&vt_cpy);
+    if (result) {
+        while(1){}
+    }
+#endif /* RSS_XIP */
+
+#ifdef CRYPTO_HW_ACCELERATOR
+    result = crypto_hw_accelerator_finish();
+    if (result) {
+        while(1){}
+    }
+#endif /* CRYPTO_HW_ACCELERATOR */
+
+#ifdef FLASH_DEV_NAME
+    result = FLASH_DEV_NAME.Uninitialize();
+    if (result != ARM_DRIVER_OK) {
+        while(1){}
+    }
+#endif /* FLASH_DEV_NAME */
+#ifdef FLASH_DEV_NAME_2
+    result = FLASH_DEV_NAME_2.Uninitialize();
+    if (result != ARM_DRIVER_OK) {
+        while(1){}
+    }
+#endif /* FLASH_DEV_NAME_2 */
+#ifdef FLASH_DEV_NAME_3
+    result = FLASH_DEV_NAME_3.Uninitialize();
+    if (result != ARM_DRIVER_OK) {
+        while(1){}
+    }
+#endif /* FLASH_DEV_NAME_3 */
+#ifdef FLASH_DEV_NAME_SCRATCH
+    result = FLASH_DEV_NAME_SCRATCH.Uninitialize();
+    if (result != ARM_DRIVER_OK) {
+        while(1){}
+    }
+#endif /* FLASH_DEV_NAME_SCRATCH */
+
+#if defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) \
+ || defined(__ARM_ARCH_8_1M_MAIN__)
+    /* Restore the Main Stack Pointer Limit register's reset value
+     * before passing execution to runtime firmware to make the
+     * bootloader transparent to it.
+     */
+    __set_MSPLIM(0);
+#endif /* defined(__ARM_ARCH_8M_MAIN__) || defined(__ARM_ARCH_8M_BASE__) \
+       || defined(__ARM_ARCH_8_1M_MAIN__) */
+
+    __set_MSP(vt_cpy->msp);
+    __DSB();
+    __ISB();
+
+    boot_jump_to_next_image(vt_cpy->reset);
+}
diff --git a/platform/ext/target/arm/rss/tc/bl2/create_xip_tables.py b/platform/ext/target/arm/rss/tc/bl2/create_xip_tables.py
new file mode 100644
index 0000000..18fec91
--- /dev/null
+++ b/platform/ext/target/arm/rss/tc/bl2/create_xip_tables.py
@@ -0,0 +1,78 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+import argparse
+import hashlib
+from functools import reduce
+from operator import add
+from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
+import struct
+import secrets
+
+sic_page_size = 1024
+
+def struct_pack(objects, pad_to=0):
+    defstring = "<"
+    for obj in objects:
+        defstring += str(len(obj)) + "s"
+
+    size = struct.calcsize(defstring)
+    if size < pad_to:
+        defstring += str(pad_to - size) + "x"
+
+    return (bytes(struct.pack(defstring, *objects)))
+
+def chunk_bytes(x, n):
+    return [x[i:i+n] for i in range(0, len(x), n)]
+
+parser = argparse.ArgumentParser()
+parser.add_argument("--input_image", help="the image to create table from", required=True)
+parser.add_argument("--encrypt_key_file", help="Key to encrypt image with", required=False)
+parser.add_argument("--image_version", help="Version of the image", required=True)
+parser.add_argument("--table_output_file", help="table output file", required=True)
+parser.add_argument("--encrypted_image_output_file", help="encrupted image output file", required=True)
+args = parser.parse_args()
+
+with open(args.input_image, "rb") as in_file:
+    image = in_file.read()
+
+# TODO derive a key from the main key based on the security counter / fw
+# version, as we do for BL2. This requires tweaks to crypto in BL2 first.
+if args.encrypt_key_file is not None:
+    with open(args.encrypt_key, "rb") as in_file:
+        encrypt_key = in_file.read()
+else:
+    encrypt_key = bytearray([0xfc, 0x57, 0x01, 0xdc, 0x61, 0x35, 0xe1, 0x32,
+                             0x38, 0x47, 0xbd, 0xc4, 0x0f, 0x04, 0xd2, 0xe5,
+                             0xbe, 0xe5, 0x83, 0x3b, 0x23, 0xc2, 0x9f, 0x93,
+                             0x59, 0x3d, 0x00, 0x01, 0x8c, 0xfa, 0x99, 0x94,])
+
+
+fw_version_bytes = int(args.image_version, 0).to_bytes(4, 'little')
+nonce_bytes = secrets.token_bytes(8)
+
+# Provided the image starts at the beginning of the DR, we can start the line
+# index at 0.
+counter_val = struct_pack([nonce_bytes, fw_version_bytes], pad_to=16)
+
+cipher = Cipher(algorithms.AES(encrypt_key), modes.CTR(counter_val))
+enc_image = cipher.encryptor().update(image)
+
+htr = reduce(add, map(lambda x:hashlib.sha256(x).digest(), chunk_bytes(enc_image, sic_page_size)), b"")
+
+table = struct_pack([
+            fw_version_bytes,
+            nonce_bytes,
+            len(htr).to_bytes(4, 'little'),
+            htr
+            ], pad_to=8192)
+
+with open(args.table_output_file, "wb") as out_file:
+    out_file.write(table)
+
+with open(args.encrypted_image_output_file, "wb") as out_file:
+    out_file.write(enc_image)
diff --git a/platform/ext/target/arm/rss/tc/bl2/flash_map_bl2.c b/platform/ext/target/arm/rss/tc/bl2/flash_map_bl2.c
index eebd85a..fdd4693 100644
--- a/platform/ext/target/arm/rss/tc/bl2/flash_map_bl2.c
+++ b/platform/ext/target/arm/rss/tc/bl2/flash_map_bl2.c
@@ -23,6 +23,36 @@
 const int flash_driver_entry_num = ARRAY_SIZE(flash_driver);
 
 const struct flash_area flash_map[] = {
+#ifdef RSS_XIP
+    {
+        .fa_id = FLASH_AREA_10_ID,
+        .fa_device_id = FLASH_DEVICE_ID,
+        .fa_driver = &FLASH_DEV_NAME,
+        .fa_off = FLASH_AREA_10_OFFSET,
+        .fa_size = FLASH_AREA_10_SIZE,
+    },
+    {
+        .fa_id = FLASH_AREA_11_ID,
+        .fa_device_id = FLASH_DEVICE_ID,
+        .fa_driver = &FLASH_DEV_NAME,
+        .fa_off = FLASH_AREA_11_OFFSET,
+        .fa_size = FLASH_AREA_11_SIZE,
+    },
+    {
+        .fa_id = FLASH_AREA_12_ID,
+        .fa_device_id = FLASH_DEVICE_ID,
+        .fa_driver = &FLASH_DEV_NAME,
+        .fa_off = FLASH_AREA_12_OFFSET,
+        .fa_size = FLASH_AREA_12_SIZE,
+    },
+    {
+        .fa_id = FLASH_AREA_13_ID,
+        .fa_device_id = FLASH_DEVICE_ID,
+        .fa_driver = &FLASH_DEV_NAME,
+        .fa_off = FLASH_AREA_13_OFFSET,
+        .fa_size = FLASH_AREA_13_SIZE,
+    },
+#else
     {
         .fa_id = FLASH_AREA_2_ID,
         .fa_device_id = FLASH_DEVICE_ID,
@@ -51,6 +81,7 @@
         .fa_off = FLASH_AREA_5_OFFSET,
         .fa_size = FLASH_AREA_5_SIZE,
     },
+#endif /* RSS_XIP */
     {
         .fa_id = FLASH_AREA_6_ID,
         .fa_device_id = FLASH_DEVICE_ID,
diff --git a/platform/ext/target/arm/rss/tc/bl2/host_flash_atu.c b/platform/ext/target/arm/rss/tc/bl2/host_flash_atu.c
index f05933b..2d9747c 100644
--- a/platform/ext/target/arm/rss/tc/bl2/host_flash_atu.c
+++ b/platform/ext/target/arm/rss/tc/bl2/host_flash_atu.c
@@ -12,9 +12,9 @@
 #include "device_definition.h"
 #include "flash_map/flash_map.h"
 
-#define RSS_ATU_REGION_INPUT_IMAGE_SLOT_0 0
-#define RSS_ATU_REGION_INPUT_IMAGE_SLOT_1 1
-#define RSS_ATU_REGION_OUTPUT_IMAGE_SLOT  2
+#define RSS_ATU_REGION_INPUT_IMAGE_SLOT_0 2
+#define RSS_ATU_REGION_INPUT_IMAGE_SLOT_1 3
+#define RSS_ATU_REGION_OUTPUT_IMAGE_SLOT  4
 
 #define HOST_BOOT_AP_LOAD_BASE_S  HOST_BOOT_IMAGE0_LOAD_BASE_S
 #define HOST_BOOT_SCP_LOAD_BASE_S HOST_BOOT_IMAGE1_LOAD_BASE_S
diff --git a/platform/ext/target/arm/rss/tc/bl2/sic_boot.c b/platform/ext/target/arm/rss/tc/bl2/sic_boot.c
new file mode 100644
index 0000000..8da41f8
--- /dev/null
+++ b/platform/ext/target/arm/rss/tc/bl2/sic_boot.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "sic_boot.h"
+
+#include "device_definition.h"
+#include "bl2_image_id.h"
+#include "region_defs.h"
+#include "tfm_plat_otp.h"
+
+#define RSS_ATU_S_IMAGE_XIP_REGION  0
+#define RSS_ATU_NS_IMAGE_XIP_REGION 1
+
+#define RSS_SIC_S_IMAGE_DECRYPT_REGION  0
+#define RSS_SIC_NS_IMAGE_DECRYPT_REGION 1
+
+#define FLASH_SIC_HTR_SIZE 0x800
+
+struct rss_xip_htr_table {
+    uint32_t fw_revision;
+    uint32_t nonce[2];
+    size_t htr_size;
+    uint8_t htr[FLASH_SIC_HTR_SIZE];
+};
+
+
+int sic_boot_init(void)
+{
+    enum sic_error_t sic_err;
+
+    sic_err = sic_auth_init(&SIC_DEV_S, SIC_DIGEST_SIZE_256,
+                            SIC_DIGEST_COMPARE_FIRST_QWORD,
+                            RSS_RUNTIME_S_XIP_BASE_S, FLASH_S_PARTITION_SIZE);
+    if (sic_err != SIC_ERROR_NONE) {
+        return 1;
+    }
+
+    sic_err = sic_decrypt_init(&SIC_DEV_S, SIC_DECRYPT_KEYSIZE_256, false);
+    if (sic_err != SIC_ERROR_NONE) {
+        return 1;
+    }
+
+    return 0;
+}
+
+int sic_boot_post_load(uint32_t image_id, uint32_t image_load_offset)
+{
+    enum sic_error_t sic_err;
+    struct rss_xip_htr_table *table;
+    enum atu_error_t atu_err;
+    uint32_t key[8];
+    enum tfm_plat_err_t plat_err;
+    size_t sic_page_size;
+    enum tfm_otp_element_id_t decrypt_key_otp_id;
+    uint32_t decrypt_region;
+    uint32_t xip_region_base_addr;
+    uint32_t xip_region_size;
+
+    sic_page_size = sic_page_size_get(&SIC_DEV_S);
+
+    switch (image_id) {
+    case RSS_BL2_IMAGE_NS:
+        table = (struct rss_xip_htr_table*)(BL2_XIP_TABLES_START
+                                            + FLASH_SIC_TABLE_SIZE
+                                            + BL2_HEADER_SIZE);
+
+        if (image_load_offset == FLASH_AREA_11_OFFSET) {
+            atu_err = atu_initialize_region(&ATU_DEV_S,
+                                        RSS_ATU_NS_IMAGE_XIP_REGION,
+                                        RSS_RUNTIME_NS_XIP_BASE_S,
+                                        HOST_FLASH0_BASE + FLASH_AREA_3_OFFSET,
+                                        FLASH_AREA_3_SIZE);
+            if (atu_err != ATU_ERR_NONE) {
+                return 1;
+            }
+        } else if (image_load_offset == FLASH_AREA_13_OFFSET) {
+            atu_err = atu_initialize_region(&ATU_DEV_S,
+                                        RSS_ATU_NS_IMAGE_XIP_REGION,
+                                        RSS_RUNTIME_NS_XIP_BASE_S,
+                                        HOST_FLASH0_BASE + FLASH_AREA_5_OFFSET,
+                                        FLASH_AREA_5_SIZE);
+            if (atu_err != ATU_ERR_NONE) {
+                return 1;
+            }
+        } else {
+            return 1;
+        }
+
+        decrypt_key_otp_id = PLAT_OTP_ID_KEY_NON_SECURE_ENCRYPTION;
+        decrypt_region = RSS_SIC_NS_IMAGE_DECRYPT_REGION;
+        xip_region_base_addr = RSS_RUNTIME_NS_XIP_BASE_S;
+        xip_region_size      = NS_CODE_SIZE;
+
+        break;
+    case RSS_BL2_IMAGE_S:
+        table = (struct rss_xip_htr_table*)(BL2_XIP_TABLES_START + BL2_HEADER_SIZE);
+
+        if (image_load_offset == FLASH_AREA_10_OFFSET) {
+            atu_err = atu_initialize_region(&ATU_DEV_S,
+                                        RSS_ATU_S_IMAGE_XIP_REGION,
+                                        RSS_RUNTIME_S_XIP_BASE_S,
+                                        HOST_FLASH0_BASE + FLASH_AREA_2_OFFSET,
+                                        FLASH_AREA_2_SIZE);
+            if (atu_err != ATU_ERR_NONE) {
+                return 1;
+            }
+        } else if (image_load_offset == FLASH_AREA_12_OFFSET) {
+            atu_err = atu_initialize_region(&ATU_DEV_S,
+                                        RSS_ATU_S_IMAGE_XIP_REGION,
+                                        RSS_RUNTIME_S_XIP_BASE_S,
+                                        HOST_FLASH0_BASE + FLASH_AREA_4_OFFSET,
+                                        FLASH_AREA_4_SIZE);
+            if (atu_err != ATU_ERR_NONE) {
+                return 1;
+            }
+        } else {
+            return 1;
+        }
+
+        decrypt_key_otp_id = PLAT_OTP_ID_KEY_SECURE_ENCRYPTION;
+        decrypt_region = RSS_SIC_S_IMAGE_DECRYPT_REGION;
+        xip_region_base_addr = RSS_RUNTIME_S_XIP_BASE_S;
+        xip_region_size      = S_CODE_SIZE;
+
+        break;
+
+    case RSS_BL2_IMAGE_AP:
+    case RSS_BL2_IMAGE_SCP:
+        return 0;
+    default:
+        return 1;
+    }
+
+    sic_err = sic_auth_table_set(&SIC_DEV_S, (uint32_t*)(table->htr),
+                                 table->htr_size, (xip_region_base_addr
+                                                   - SIC_HOST_BASE_S)
+                                                  / sic_page_size * 32);
+    if (sic_err != SIC_ERROR_NONE) {
+        return 1;
+    }
+
+    plat_err = tfm_plat_otp_read(decrypt_key_otp_id, sizeof(key), (uint8_t*)key);
+    if (plat_err != TFM_PLAT_ERR_SUCCESS) {
+        return 1;
+    }
+
+    sic_err = sic_decrypt_region_enable(&SIC_DEV_S,
+                                        decrypt_region, xip_region_base_addr,
+                                        xip_region_size,
+                                        image_load_offset, table->nonce,
+                                        key);
+    if (sic_err != SIC_ERROR_NONE) {
+        memset(key, 0, sizeof(key));
+        return 1;
+    }
+
+
+    memset(key, 0, sizeof(key));
+
+    return 0;
+}
+
+int sic_boot_pre_quit(struct boot_arm_vector_table **vt_cpy)
+{
+    enum sic_error_t sic_err;
+
+    sic_err = sic_auth_enable(&SIC_DEV_S);
+    if (sic_err != SIC_ERROR_NONE) {
+        return 1;
+    }
+
+    sic_err = sic_enable(&SIC_DEV_S);
+    if (sic_err != SIC_ERROR_NONE) {
+        return 1;
+    }
+
+    *vt_cpy = (struct boot_arm_vector_table *)RSS_RUNTIME_S_XIP_BASE_S;
+
+    return 0;
+}
diff --git a/platform/ext/target/arm/rss/tc/bl2/sic_boot.h b/platform/ext/target/arm/rss/tc/bl2/sic_boot.h
new file mode 100644
index 0000000..24fd399
--- /dev/null
+++ b/platform/ext/target/arm/rss/tc/bl2/sic_boot.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __SIC_BOOT_H__
+#define __SIC_BOOT_H__
+
+#include <stdint.h>
+
+#include "boot_hal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief                  Initialise Secure I-Cache, and begin configuration.
+ *
+ * \return                 0 if operation completed successfully, another value
+ *                         on error.
+ */
+int sic_boot_init(void);
+
+/**
+ * \brief                        Perform post-image-load steps to setup SIC,
+ *                               for a given image.
+ *
+ * \param[in]  image_id          The image id to setup the SIC for.
+ * \param[in]  image_load_offset The flash offset the image was loaded from.
+ *                               This is used to detect which of the primary /
+ *                               secondary images was loaded and determine which
+ *                               code should be run through the SIC.
+ *
+ * \return                       0 if operation completed successfully, another
+ *                               value on error.
+ */
+int sic_boot_post_load(uint32_t image_id, uint32_t image_load_offset);
+
+/**
+ * \brief                  Perform SIC configuration that needs to be run just
+ *                         before the bootloader is exited to jump to the new
+ *                         image.
+ *
+ * \param[out] vt_cpy      A pointer to the vector table pointer that is to be
+ *                         jumped to. This is updated to the correct address
+ *                         where the image can be executed via the SIC.
+ *
+ * \return                 0 if operation completed successfully, another value
+ *                         on error.
+ */
+int sic_boot_pre_quit(struct boot_arm_vector_table **vt_cpy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SIC_BOOT_H__ */
diff --git a/platform/ext/target/arm/rss/tc/bl2/signing_layout_sic_tables.c.in b/platform/ext/target/arm/rss/tc/bl2/signing_layout_sic_tables.c.in
new file mode 100644
index 0000000..3799563
--- /dev/null
+++ b/platform/ext/target/arm/rss/tc/bl2/signing_layout_sic_tables.c.in
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include "region_defs.h"
+/* Enumeration that is used by the assemble.py and imgtool.py scripts
+ * for correct binary generation when nested macros are used
+ */
+enum image_attributes {
+    RE_SECURE_IMAGE_MAX_SIZE     = FLASH_SIC_TABLE_SIZE,
+    RE_NON_SECURE_IMAGE_MAX_SIZE = FLASH_SIC_TABLE_SIZE,
+#ifdef @IMAGE_TYPE@_LOAD_ADDRESS
+    RE_IMAGE_LOAD_ADDRESS        = @IMAGE_TYPE@_LOAD_ADDRESS,
+#endif
+    RE_SIGN_BIN_SIZE = FLASH_AREA_@FLASH_AREA_NUM@_SIZE,
+};
diff --git a/platform/ext/target/arm/rss/tc/config.cmake b/platform/ext/target/arm/rss/tc/config.cmake
index f3e8b6e..98d24d2 100644
--- a/platform/ext/target/arm/rss/tc/config.cmake
+++ b/platform/ext/target/arm/rss/tc/config.cmake
@@ -5,5 +5,14 @@
 #
 #-------------------------------------------------------------------------------
 
+if (RSS_XIP)
+set(PLATFORM_DEFAULT_IMAGE_SIGNING      OFF       CACHE BOOL    "Use default image signing implementation")
+set(BL2_HEADER_SIZE                     0x400     CACHE STRING  "BL2 Header size")
+set(BL2_TRAILER_SIZE                    0x400     CACHE STRING  "BL2 Trailer size")
+
+set(MCUBOOT_S_IMAGE_FLASH_AREA_NUM      10        CACHE STRING  "ID of the flash area containing the primary Secure image")
+set(MCUBOOT_NS_IMAGE_FLASH_AREA_NUM     11        CACHE STRING  "ID of the flash area containing the primary Non-Secure image")
+endif()
+
 # Once all options are set, set common options as fallback
 include(${CMAKE_CURRENT_LIST_DIR}/../common/config.cmake)
diff --git a/platform/ext/target/arm/rss/tc/flash_layout.h b/platform/ext/target/arm/rss/tc/flash_layout.h
index ffb9e73..644cdf0 100644
--- a/platform/ext/target/arm/rss/tc/flash_layout.h
+++ b/platform/ext/target/arm/rss/tc/flash_layout.h
@@ -32,6 +32,14 @@
  * 0x842A_0000 AP BL1  secondary slot (512 KiB)
  * 0x8432_0000 SCP BL1 secondary slot (512 KiB)
  * 0x843A_0000 Unused
+ *
+ * If XIP mode is enabled, 4 more flash regions are defined:
+ *
+ * 0x843A_0000 Secure image SIC tables     primary slot (10 KiB)
+ * 0x843A_A000 Non-secure image SIC tables primary slot (10 KiB)
+ * 0x843B_4000 Secure image SIC tables     secondary slot (10 KiB)
+ * 0x843B_E000 Non-secure image SIC tables secondary slot (10 KiB)
+ * 0x843C_8000 Unused
  */
 
 /* This header file is included from linker scatter file as well, where only a
@@ -53,6 +61,13 @@
                                          FLASH_S_PARTITION_SIZE :    \
                                          FLASH_NS_PARTITION_SIZE)
 
+#ifdef RSS_XIP
+/* Each table contains a bit less that 8KiB of HTR and 2KiB of mcuboot headers.
+ * The spare space in the 8KiB is used for decryption IVs.
+ */
+#define FLASH_SIC_TABLE_SIZE            (0xA000) /* 10KiB */
+#endif /* RSS_XIP */
+
 /* Sector size of the flash hardware; same as FLASH0_SECTOR_SIZE */
 #define FLASH_AREA_IMAGE_SECTOR_SIZE    (0x1000)    /* 4 KB */
 /* Same as FLASH0_SIZE */
@@ -109,6 +124,25 @@
 #define FLASH_AREA_9_OFFSET        (FLASH_AREA_8_OFFSET + FLASH_AREA_8_SIZE)
 #define FLASH_AREA_9_SIZE          (FLASH_SCP_PARTITION_SIZE)
 
+#ifdef RSS_XIP
+/* Secure image SIC tables primary slot */
+#define FLASH_AREA_10_ID            (FLASH_AREA_9_ID + 1)
+#define FLASH_AREA_10_OFFSET        (FLASH_AREA_9_OFFSET + FLASH_AREA_9_SIZE)
+#define FLASH_AREA_10_SIZE          (FLASH_SIC_TABLE_SIZE)
+/* Non-secure image SIC tables primary slot */
+#define FLASH_AREA_11_ID            (FLASH_AREA_10_ID + 1)
+#define FLASH_AREA_11_OFFSET        (FLASH_AREA_10_OFFSET + FLASH_AREA_10_SIZE)
+#define FLASH_AREA_11_SIZE          (FLASH_SIC_TABLE_SIZE)
+/* Secure image SIC tables secondary slot */
+#define FLASH_AREA_12_ID            (FLASH_AREA_11_ID + 1)
+#define FLASH_AREA_12_OFFSET        (FLASH_AREA_11_OFFSET + FLASH_AREA_11_SIZE)
+#define FLASH_AREA_12_SIZE          (FLASH_SIC_TABLE_SIZE)
+/* Non-secure image SIC tables secondary slot */
+#define FLASH_AREA_13_ID            (FLASH_AREA_12_ID + 1)
+#define FLASH_AREA_13_OFFSET        (FLASH_AREA_12_OFFSET + FLASH_AREA_12_SIZE)
+#define FLASH_AREA_13_SIZE          (FLASH_SIC_TABLE_SIZE)
+#endif /* RSS_XIP */
+
 
 /* Maximum number of image sectors supported by the bootloader. */
 #define MCUBOOT_MAX_IMG_SECTORS    (FLASH_MAX_PARTITION_SIZE / \
@@ -119,6 +153,19 @@
 #error "Out of Flash memory!"
 #endif
 
+#ifdef RSS_XIP
+#define FLASH_AREA_IMAGE_PRIMARY(x)     (((x) == 0) ? FLASH_AREA_10_ID : \
+                                         ((x) == 1) ? FLASH_AREA_11_ID : \
+                                         ((x) == 2) ? FLASH_AREA_6_ID : \
+                                         ((x) == 3) ? FLASH_AREA_7_ID : \
+                                                      255)
+#define FLASH_AREA_IMAGE_SECONDARY(x)   (((x) == 0) ? FLASH_AREA_12_ID : \
+                                         ((x) == 1) ? FLASH_AREA_13_ID : \
+                                         ((x) == 2) ? FLASH_AREA_8_ID : \
+                                         ((x) == 3) ? FLASH_AREA_9_ID : \
+                                                      255)
+
+#else
 #define FLASH_AREA_IMAGE_PRIMARY(x)     (((x) == 0) ? FLASH_AREA_2_ID : \
                                          ((x) == 1) ? FLASH_AREA_3_ID : \
                                          ((x) == 2) ? FLASH_AREA_6_ID : \
@@ -129,6 +176,7 @@
                                          ((x) == 2) ? FLASH_AREA_8_ID : \
                                          ((x) == 3) ? FLASH_AREA_9_ID : \
                                                       255)
+#endif /* RSS_XIP */
 
 /* Scratch area is not used with RAM loading firmware upgrade */
 #define FLASH_AREA_IMAGE_SCRATCH        255
@@ -141,12 +189,23 @@
                                          SECURE_IMAGE_MAX_SIZE)
 #define NON_SECURE_IMAGE_MAX_SIZE       FLASH_NS_PARTITION_SIZE
 
+#ifdef RSS_XIP
+#define S_DATA_SIZE                     (0x18000) /* 96KiB */
+#define NS_DATA_SIZE                    (0x08000) /* 32KiB */
+#else
 #define S_DATA_SIZE                     (0x20000) /* 128KiB */
 #define NS_DATA_SIZE                    (0x20000) /* 128KiB */
+#endif /* RSS_XIP */
 
 /* Image load addresses used by imgtool.py */
+#ifdef RSS_XIP
+#define S_IMAGE_LOAD_ADDRESS            (VM0_BASE_S + BOOT_TFM_SHARED_DATA_SIZE)
+#define NS_IMAGE_LOAD_ADDRESS           (S_IMAGE_LOAD_ADDRESS + \
+                                         FLASH_SIC_TABLE_SIZE)
+#else
 #define S_IMAGE_LOAD_ADDRESS            (VM0_BASE_S + S_DATA_SIZE)
 #define NS_IMAGE_LOAD_ADDRESS           (VM1_BASE_S + NS_DATA_SIZE)
+#endif
 
 /* Flash device name used by BL2
  * Name is defined in flash driver file: Driver_Flash.c
diff --git a/platform/ext/target/arm/rss/tc/rss_memory_sizes.h b/platform/ext/target/arm/rss/tc/rss_memory_sizes.h
index 567a264..206524b 100644
--- a/platform/ext/target/arm/rss/tc/rss_memory_sizes.h
+++ b/platform/ext/target/arm/rss/tc/rss_memory_sizes.h
@@ -17,7 +17,12 @@
 #ifndef __RSS_MEMORY_SIZES_H__
 #define __RSS_MEMORY_SIZES_H__
 
+#ifdef RSS_XIP
+#define VM0_SIZE                         0x00010000 /* 64 KiB */
+#define VM1_SIZE                         0x00010000 /* 64 KiB */
+#else
 #define VM0_SIZE                         0x00080000 /* 512 KiB */
 #define VM1_SIZE                         0x00080000 /* 512 KiB */
+#endif /* RSS_XIP */
 
 #endif /* __RSS_MEMORY_SIZES_H__ */