FWU: Add the IPC model support

Change-Id: I555169f7bf9c6fa9ab5b5a1d71d196fe3fd11817
Signed-off-by: Sherry Zhang <sherry.zhang2@arm.com>
diff --git a/cmake/install.cmake b/cmake/install.cmake
index f13d3bf..048c900 100644
--- a/cmake/install.cmake
+++ b/cmake/install.cmake
@@ -229,7 +229,10 @@
 endif()
 
 if(TFM_PARTITION_FIRMWARE_UPDATE)
-    if(NOT TFM_PSA_API)
+    if(TFM_PSA_API)
+        install(FILES       ${INTERFACE_SRC_DIR}/tfm_firmware_update_ipc_api.c
+                DESTINATION ${INSTALL_INTERFACE_SRC_DIR})
+    else()
         install(FILES       ${INTERFACE_SRC_DIR}/tfm_firmware_update_func_api.c
                 DESTINATION ${INSTALL_INTERFACE_SRC_DIR})
     endif()
diff --git a/config/check_config.cmake b/config/check_config.cmake
index fa87e3b..0378f1d 100644
--- a/config/check_config.cmake
+++ b/config/check_config.cmake
@@ -69,4 +69,3 @@
 tfm_invalid_config(TFM_PARTITION_FIRMWARE_UPDATE AND NOT TFM_PARTITION_PLATFORM)
 tfm_invalid_config((MCUBOOT_UPGRADE_STRATEGY STREQUAL "DIRECT_XIP" OR MCUBOOT_UPGRADE_STRATEGY STREQUAL "RAM_LOAD") AND TFM_PARTITION_FIRMWARE_UPDATE)
 tfm_invalid_config(TFM_PARTITION_FIRMWARE_UPDATE AND NOT MCUBOOT_DATA_SHARING)
-tfm_invalid_config(TFM_PARTITION_FIRMWARE_UPDATE AND TFM_PSA_API)
diff --git a/config/tfm_ipc_config_default.cmake b/config/tfm_ipc_config_default.cmake
index 28f9e6d..14512e9 100644
--- a/config/tfm_ipc_config_default.cmake
+++ b/config/tfm_ipc_config_default.cmake
@@ -8,5 +8,3 @@
 ############################ Partitions ########################################
 
 set(TFM_PARTITION_AUDIT_LOG             OFF          CACHE BOOL      "Enable Audit Log partition")
-set(TFM_PARTITION_FIRMWARE_UPDATE       OFF          CACHE BOOL      "Enable firmware update partition")
-set(MCUBOOT_DATA_SHARING                OFF          CACHE BOOL      "Add sharing of application specific data using the same shared data area as for the measured boot")
diff --git a/interface/src/tfm_firmware_update_ipc_api.c b/interface/src/tfm_firmware_update_ipc_api.c
new file mode 100644
index 0000000..0118488
--- /dev/null
+++ b/interface/src/tfm_firmware_update_ipc_api.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "psa/update.h"
+#include "tfm_api.h"
+
+#include "psa/client.h"
+#include "psa_manifest/sid.h"
+
+#define IOVEC_LEN(x) (uint32_t)(sizeof(x)/sizeof(x[0]))
+
+psa_status_t psa_fwu_write(const psa_image_id_t image_id,
+                           size_t block_offset,
+                           const void *block,
+                           size_t block_size)
+{
+    psa_status_t status;
+    psa_handle_t handle;
+
+    psa_invec in_vec[] = {
+        { .base = &image_id, .len = sizeof(image_id) },
+        { .base = &block_offset, .len = sizeof(block_offset) },
+        { .base = block, .len = block_size }
+    };
+
+    handle = psa_connect(TFM_FWU_WRITE_SID, TFM_FWU_WRITE_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL,
+                      0);
+
+    psa_close(handle);
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+psa_status_t psa_fwu_install(const psa_image_id_t image_id,
+                             psa_image_id_t *dependency_uuid,
+                             psa_image_version_t *dependency_version)
+{
+    psa_status_t status;
+    psa_handle_t handle;
+
+    psa_invec in_vec[] = {
+        { .base = &image_id, .len = sizeof(image_id) }
+    };
+
+    psa_outvec out_vec[] = {
+        { .base = dependency_uuid, .len = sizeof(*dependency_uuid) },
+        { .base = dependency_version, .len = sizeof(*dependency_version)}
+    };
+
+    if ((dependency_uuid == NULL) || (dependency_version == NULL)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    handle = psa_connect(TFM_FWU_INSTALL_SID, TFM_FWU_INSTALL_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec),
+                      out_vec, IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+psa_status_t psa_fwu_abort(const psa_image_id_t image_id)
+{
+    psa_status_t status;
+    psa_handle_t handle;
+
+    psa_invec in_vec[] = {
+        { .base = &image_id, .len = sizeof(image_id) }
+    };
+
+    handle = psa_connect(TFM_FWU_ABORT_SID, TFM_FWU_ABORT_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL,
+                      0);
+
+    psa_close(handle);
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+psa_status_t psa_fwu_query(const psa_image_id_t image_id, psa_image_info_t *info)
+{
+    psa_status_t status;
+    psa_handle_t handle;
+
+    psa_invec in_vec[] = {
+        { .base = &image_id, .len = sizeof(image_id) }
+    };
+    psa_outvec out_vec[] = {
+        { .base = info, .len = sizeof(*info)}
+    };
+
+    handle = psa_connect(TFM_FWU_QUERY_SID, TFM_FWU_QUERY_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec,
+                      IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+psa_status_t psa_fwu_request_reboot(void)
+{
+    psa_handle_t handle;
+    psa_status_t status;
+
+    handle = psa_connect(TFM_FWU_REQUEST_REBOOT_SID,
+                         TFM_FWU_REQUEST_REBOOT_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, NULL, 0, NULL, 0);
+
+    psa_close(handle);
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+psa_status_t psa_fwu_accept(void)
+{
+    psa_handle_t handle;
+    psa_status_t status;
+
+    handle = psa_connect(TFM_FWU_ACCEPT_SID,
+                         TFM_FWU_ACCEPT_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, NULL, 0, NULL, 0);
+
+    psa_close(handle);
+
+    if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return status;
+}
+
+psa_status_t psa_fwu_set_manifest(psa_image_id_t image_id,
+                                  const void *manifest,
+                                  size_t manifest_size,
+                                  psa_hash_t *manifest_dependency)
+{
+    psa_status_t status;
+
+    status = PSA_ERROR_NOT_SUPPORTED;
+
+    return status;
+}
diff --git a/platform/ext/target/musca_b1/sse_200/config.cmake b/platform/ext/target/musca_b1/sse_200/config.cmake
index baec32d..13fb636 100644
--- a/platform/ext/target/musca_b1/sse_200/config.cmake
+++ b/platform/ext/target/musca_b1/sse_200/config.cmake
@@ -14,12 +14,8 @@
     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()
-
-    # Currently, Firmware Update Partition is not supported in IPC mode.
-    if(NOT TFM_PSA_API)
-        set(MCUBOOT_DATA_SHARING                ON         CACHE BOOL      "Add sharing of application specific data using the same shared data area as for the measured boot")
-        set(TFM_PARTITION_FIRMWARE_UPDATE       ON         CACHE BOOL      "Enable firmware update partition")
-    endif()
+    set(MCUBOOT_DATA_SHARING                ON         CACHE BOOL      "Add sharing of application specific data using the same shared data area as for the measured boot")
+    set(TFM_PARTITION_FIRMWARE_UPDATE       ON         CACHE BOOL      "Enable firmware update partition")
     set(BL0 OFF)
 else()
     set(MCUBOOT_IMAGE_NUMBER                1           CACHE STRING    "Whether to combine S and NS into either 1 image, or sign each seperately")
diff --git a/secure_fw/partitions/firmware_update/CMakeLists.txt b/secure_fw/partitions/firmware_update/CMakeLists.txt
index b3bfe2d..360d44e 100644
--- a/secure_fw/partitions/firmware_update/CMakeLists.txt
+++ b/secure_fw/partitions/firmware_update/CMakeLists.txt
@@ -24,7 +24,9 @@
     PRIVATE
         tfm_fwu_req_mngr.c
         tfm_fwu.c
-)
+        $<$<BOOL:${TFM_PSA_API}>:
+        ${CMAKE_BINARY_DIR}/generated/secure_fw/partitions/firmware_update/auto_generated/intermedia_tfm_firmware_update.c>
+        )
 
 # Include the bootloader specific configuration.
 if ((NOT TFM_FWU_BOOTLOADER_LIB) OR (NOT EXISTS ${TFM_FWU_BOOTLOADER_LIB}))
diff --git a/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c b/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c
index 19256fa..507d9f9 100644
--- a/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c
+++ b/secure_fw/partitions/firmware_update/tfm_fwu_req_mngr.c
@@ -16,6 +16,7 @@
 #ifdef TFM_PSA_API
 #include "psa/service.h"
 #include "psa_manifest/tfm_firmware_update.h"
+#include "tfm_memory_utils.h"
 #endif
 
 typedef struct tfm_fwu_ctx_s {
@@ -260,9 +261,263 @@
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 }
+#else
+typedef psa_status_t (*fwu_func_t)(void);
+static psa_msg_t msg;
+
+static psa_status_t tfm_fwu_write_ipc(void)
+{
+    psa_image_id_t image_id;
+    size_t block_offset;
+    size_t data_length, num;
+    psa_status_t status = PSA_SUCCESS;
+    uint8_t data_block[PSA_FWU_MAX_BLOCK_SIZE];
+    uint8_t image_index;
+
+    /* Check input parameters. */
+    if (msg.in_size[0] != sizeof(image_id) ||
+        msg.in_size[1] != sizeof(block_offset)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    num = psa_read(msg.handle, 0, &image_id, sizeof(image_id));
+    if (num != sizeof(image_id)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    num = psa_read(msg.handle, 1, &block_offset, sizeof(block_offset));
+    if (num != sizeof(block_offset)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    tfm_memset(data_block, 0, sizeof(data_block));
+    data_length = msg.in_size[2];
+    num = psa_read(msg.handle, 2, data_block, data_length);
+    if (num != data_length) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    if (get_image_index(image_id, &image_index)) {
+        /* The image is in FWU process. */
+        if ((fwu_ctx[image_index].image_state != PSA_IMAGE_CANDIDATE) &&
+            (fwu_ctx[image_index].image_state != PSA_IMAGE_REJECTED)) {
+            return PSA_ERROR_CURRENTLY_INSTALLING;
+        }
+    } else {
+        /* The image is not in FWU process. */
+        if (get_next_free_index(&image_index)) {
+            /* Get a free index. Start the FWU process of this image. */
+            status = tfm_internal_fwu_initialize(image_id);
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+            fwu_ctx[image_index].in_use = true;
+            fwu_ctx[image_index].image_id = image_id;
+            fwu_ctx[image_index].image_state = PSA_IMAGE_CANDIDATE;
+        } else {
+            /* No more resource can be used. */
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        }
+    }
+
+    return tfm_internal_fwu_write(image_id,
+                                  block_offset,
+                                  data_block,
+                                  data_length);
+}
+
+static psa_status_t tfm_fwu_install_ipc(void)
+{
+    psa_image_id_t image_id;
+    psa_image_id_t dependency_id;
+    psa_image_version_t dependency_version;
+    size_t num;
+    psa_status_t status;
+    uint8_t image_index;
+
+    /* Check input parameters. */
+    if (msg.in_size[0] != sizeof(image_id) ||
+        msg.out_size[0] != sizeof(dependency_id) ||
+        msg.out_size[1] != sizeof(dependency_version)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    num = psa_read(msg.handle, 0, &image_id, sizeof(image_id));
+    if (num != sizeof(image_id)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    if ((!get_image_index(image_id, &image_index)) ||
+       (fwu_ctx[image_index].image_state != PSA_IMAGE_CANDIDATE)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    } else {
+        status = tfm_internal_fwu_install(image_id,
+                                          &dependency_id,
+                                          &dependency_version);
+        if (status == PSA_SUCCESS) {
+            fwu_ctx[image_index].image_state = PSA_IMAGE_INSTALLED;
+
+            /* The image has been successfully installed, free the index. */
+            fwu_ctx[image_index].in_use = false;
+        } else if (status == PSA_SUCCESS_REBOOT) {
+            fwu_ctx[image_index].image_state = PSA_IMAGE_REBOOT_NEEDED;
+        } else if (status == PSA_ERROR_DEPENDENCY_NEEDED) {
+            psa_write(msg.handle, 0, &dependency_id, sizeof(dependency_id));
+            psa_write(msg.handle, 1, &dependency_version,
+                      sizeof(dependency_version));
+            fwu_ctx[image_index].image_state = PSA_IMAGE_REJECTED;
+        } else {
+            fwu_ctx[image_index].image_state = PSA_IMAGE_REJECTED;
+        }
+
+        return status;
+    }
+}
+
+static psa_status_t tfm_fwu_query_ipc(void)
+{
+    psa_image_id_t image_id;
+    size_t num;
+    psa_image_info_t info;
+    psa_status_t result;
+    uint8_t image_index;
+
+    /* Check input parameters. */
+    if (msg.in_size[0] != sizeof(image_id)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+    num = psa_read(msg.handle, 0, &image_id, sizeof(image_id));
+    if (num != sizeof(image_id)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+    result = tfm_internal_fwu_query(image_id, &info);
+    if (result == PSA_SUCCESS) {
+        /* Fill the image state if the query image is not the running image. */
+        if (info.state == PSA_IMAGE_UNDEFINED) {
+            if (get_image_index(image_id, &image_index)) {
+                /* The queried image is the currently updating image. */
+                info.state = fwu_ctx[image_index].image_state;
+            }
+        }
+
+        psa_write(msg.handle, 0, &info, sizeof(info));
+    }
+
+    return result;
+}
+
+static psa_status_t tfm_fwu_request_reboot_ipc(void)
+{
+    tfm_internal_fwu_request_reboot();
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t tfm_fwu_accept_ipc(void)
+{
+    /* This operation set the running image to INSTALLED state, the images
+     * in the staging area does not impact this operation.
+     */
+    return tfm_internal_fwu_accept();
+}
+
+static psa_status_t tfm_fwu_abort_ipc(void)
+{
+    psa_image_id_t image_id;
+    size_t num;
+    uint8_t image_index;
+    psa_status_t status;
+
+    if (msg.in_size[0] != sizeof(image_id)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    num = psa_read(msg.handle, 0, &image_id, sizeof(image_id));
+    if (num != sizeof(image_id)) {
+        return PSA_ERROR_PROGRAMMER_ERROR;
+    }
+
+    if (get_image_index(image_id, &image_index)) {
+        /* The image is in FWU process. */
+        if ((fwu_ctx[image_index].image_state == PSA_IMAGE_CANDIDATE) ||
+           (fwu_ctx[image_index].image_state == PSA_IMAGE_REBOOT_NEEDED) ||
+           (fwu_ctx[image_index].image_state == PSA_IMAGE_REJECTED)) {
+            status = tfm_internal_fwu_abort(image_id);
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+
+            fwu_ctx[image_index].image_state = PSA_IMAGE_UNDEFINED;
+            fwu_ctx[image_index].in_use = false;
+            fwu_ctx[image_index].image_id = TFM_FWU_INVALID_IMAGE_ID;
+            return PSA_SUCCESS;
+        } else {
+            /* If the image is in INSTALLED state or UNDEFINED, it should not in
+             * a FWU process.
+             */
+            return PSA_ERROR_PROGRAMMER_ERROR;
+        }
+    } else {
+        /* No image with the provided image_id is not in FWU process. */
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+}
+
+static void fwu_signal_handle(psa_signal_t signal, fwu_func_t pfn)
+{
+    psa_status_t status;
+
+    status = psa_get(signal, &msg);
+    if (status != PSA_SUCCESS) {
+        return;
+    }
+
+    switch (msg.type) {
+    case PSA_IPC_CONNECT:
+        psa_reply(msg.handle, PSA_SUCCESS);
+        break;
+    case PSA_IPC_CALL:
+        status = pfn();
+        psa_reply(msg.handle, status);
+        break;
+    case PSA_IPC_DISCONNECT:
+        psa_reply(msg.handle, PSA_SUCCESS);
+        break;
+    default:
+        psa_panic();
+    }
+}
 #endif
 
 psa_status_t tfm_fwu_init(void)
 {
+#ifdef TFM_PSA_API
+    psa_signal_t signals = 0;
+
+    if (fwu_bootloader_init() != 0) {
+        psa_panic();
+    }
+
+    while (1) {
+        signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
+        if (signals & TFM_FWU_WRITE_SIGNAL) {
+            fwu_signal_handle(TFM_FWU_WRITE_SIGNAL, tfm_fwu_write_ipc);
+        } else if (signals & TFM_FWU_INSTALL_SIGNAL) {
+            fwu_signal_handle(TFM_FWU_INSTALL_SIGNAL, tfm_fwu_install_ipc);
+        } else if (signals & TFM_FWU_ABORT_SIGNAL) {
+            fwu_signal_handle(TFM_FWU_ABORT_SIGNAL, tfm_fwu_abort_ipc);
+        } else if (signals & TFM_FWU_QUERY_SIGNAL) {
+            fwu_signal_handle(TFM_FWU_QUERY_SIGNAL, tfm_fwu_query_ipc);
+        } else if (signals & TFM_FWU_REQUEST_REBOOT_SIGNAL) {
+            fwu_signal_handle(TFM_FWU_REQUEST_REBOOT_SIGNAL,
+                              tfm_fwu_request_reboot_ipc);
+        } else if (signals & TFM_FWU_ACCEPT_SIGNAL) {
+            fwu_signal_handle(TFM_FWU_ACCEPT_SIGNAL, tfm_fwu_accept_ipc);
+        } else {
+            psa_panic();
+        }
+    }
+#else
     return fwu_bootloader_init();
+#endif
 }
diff --git a/secure_fw/partitions/firmware_update/tfm_fwu_secure_api.c b/secure_fw/partitions/firmware_update/tfm_fwu_secure_api.c
index 815927a..de4f45c 100644
--- a/secure_fw/partitions/firmware_update/tfm_fwu_secure_api.c
+++ b/secure_fw/partitions/firmware_update/tfm_fwu_secure_api.c
@@ -23,6 +23,9 @@
                            size_t block_size)
 {
     psa_status_t status;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
     psa_invec in_vec[] = {
         { .base = &image_id, .len = sizeof(image_id) },
@@ -30,10 +33,21 @@
         { .base = block, .len = block_size }
     };
 
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_FWU_WRITE_SID, TFM_FWU_WRITE_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0);
+
+    psa_close(handle);
+#else
     status = tfm_tfm_fwu_write_req_veneer(in_vec,
                                           IOVEC_LEN(in_vec),
                                           NULL,
                                           0);
+#endif
 
     /* A parameter with a buffer pointer where its data length is longer than
      * maximum permitted, it is treated as a secure violation.
@@ -53,6 +67,9 @@
                              psa_image_version_t *dependency_version)
 {
     psa_status_t status;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
     psa_invec in_vec[] = {
         { .base = &image_id, .len = sizeof(image_id) }
@@ -67,8 +84,20 @@
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_FWU_INSTALL_SID, TFM_FWU_INSTALL_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec),
+                      out_vec, IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+#else
     status = tfm_tfm_fwu_install_req_veneer(in_vec, IOVEC_LEN(in_vec),
                                             out_vec, IOVEC_LEN(out_vec));
+#endif
 
     /* A parameter with a buffer pointer where its data length is longer than
      * maximum permitted, it is treated as a secure violation.
@@ -86,13 +115,28 @@
 psa_status_t psa_fwu_abort(psa_image_id_t image_id)
 {
     psa_status_t status;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
     psa_invec in_vec[] = {
         { .base = &image_id, .len = sizeof(image_id) }
     };
 
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_FWU_ABORT_SID, TFM_FWU_ABORT_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec),
+                      NULL, 0);
+
+    psa_close(handle);
+#else
     status = tfm_tfm_fwu_abort_req_veneer(in_vec, IOVEC_LEN(in_vec),
                                           NULL, 0);
+#endif
 
     /* A parameter with a buffer pointer where its data length is longer than
      * maximum permitted, it is treated as a secure violation.
@@ -110,6 +154,9 @@
 psa_status_t psa_fwu_query(psa_image_id_t image_id, psa_image_info_t *info)
 {
     psa_status_t status;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
     psa_invec in_vec[] = {
         { .base = &image_id, .len = sizeof(image_id) }
@@ -118,8 +165,20 @@
         { .base = info, .len = sizeof(*info)}
     };
 
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_FWU_QUERY_SID, TFM_FWU_QUERY_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec),
+                      out_vec, IOVEC_LEN(out_vec));
+
+    psa_close(handle);
+#else
     status = tfm_tfm_fwu_query_req_veneer(in_vec, IOVEC_LEN(in_vec),
                                           out_vec, IOVEC_LEN(out_vec));
+#endif
 
     if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
         return PSA_ERROR_INVALID_ARGUMENT;
@@ -131,11 +190,23 @@
 psa_status_t psa_fwu_request_reboot(void)
 {
     psa_status_t status;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
-    status = tfm_tfm_fwu_request_reboot_req_veneer(NULL,
-                                                   0,
-                                                   NULL,
-                                                   0);
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_FWU_REQUEST_REBOOT_SID,
+                         TFM_FWU_REQUEST_REBOOT_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, NULL, 0, NULL, 0);
+
+    psa_close(handle);
+#else
+    status = tfm_tfm_fwu_request_reboot_req_veneer(NULL, 0, NULL, 0);
+#endif
 
     if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
         return PSA_ERROR_INVALID_ARGUMENT;
@@ -147,11 +218,23 @@
 psa_status_t psa_fwu_accept(void)
 {
     psa_status_t status;
+#ifdef TFM_PSA_API
+    psa_handle_t handle;
+#endif
 
-    status = tfm_tfm_fwu_accept_req_veneer(NULL,
-                                           0,
-                                           NULL,
-                                           0);
+#ifdef TFM_PSA_API
+    handle = psa_connect(TFM_FWU_ACCEPT_SID,
+                         TFM_FWU_ACCEPT_VERSION);
+    if (!PSA_HANDLE_IS_VALID(handle)) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    status = psa_call(handle, PSA_IPC_CALL, NULL, 0, NULL, 0);
+
+    psa_close(handle);
+#else
+    status = tfm_tfm_fwu_accept_req_veneer(NULL, 0, NULL, 0);
+#endif
 
     if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) {
         return PSA_ERROR_INVALID_ARGUMENT;