ITS: Decouple Partition codes with service codes

"Partition codes" refers to tfm_its_req_mngr.c
"Service codes" refers to tfm_internal_trusted_storage.c

The service codes currently couples with Partition codes for
example tfm_its_set calls its_req_mngr_read.
This make the service codes couples with the Partition codes
which then couples with the Secure Partition's model and
MM-IOVEC enabled status.

This patch decouples them so that service codes does not need
to change with Partition codes.
With this patch, the service codes use the "client buffer"
directly instead of "read" data from "the client".

Change-Id: I01e8fd41cd9a217c96b26a87cceb3a2e81eebf70
Signed-off-by: Kevin Peng <kevin.peng@arm.com>
diff --git a/secure_fw/partitions/internal_trusted_storage/tfm_internal_trusted_storage.c b/secure_fw/partitions/internal_trusted_storage/tfm_internal_trusted_storage.c
index be88dae..6af320e 100644
--- a/secure_fw/partitions/internal_trusted_storage/tfm_internal_trusted_storage.c
+++ b/secure_fw/partitions/internal_trusted_storage/tfm_internal_trusted_storage.c
@@ -9,7 +9,6 @@
 
 #include "tfm_hal_its.h"
 #include "tfm_hal_ps.h"
-#include "flash/its_flash.h"
 #include "flash_fs/its_flash_fs.h"
 #include "psa_manifest/pid.h"
 #include "tfm_its_defs.h"
@@ -21,20 +20,6 @@
 #include "ps_object_defs.h"
 #endif
 
-#ifndef ITS_BUF_SIZE
-/* By default, set the ITS buffer size to the max asset size so that all
- * requests can be handled in one iteration.
- */
-#define ITS_BUF_SIZE ITS_MAX_ASSET_SIZE
-#endif
-
-/* Buffer to store asset data from the caller.
- * Note: size must be aligned to the max flash program unit to meet the
- * alignment requirement of the filesystem.
- */
-static uint8_t asset_data[ITS_UTILS_ALIGN(ITS_BUF_SIZE,
-                                          ITS_FLASH_MAX_ALIGNMENT)];
-
 static uint8_t g_fid[ITS_FILE_ID_SIZE];
 static struct its_file_info_t g_file_info;
 
@@ -228,20 +213,20 @@
     return status;
 }
 
-psa_status_t tfm_its_set(int32_t client_id,
-                         psa_storage_uid_t uid,
-                         size_t data_length,
-                         psa_storage_create_flags_t create_flags)
+psa_status_t tfm_its_set(struct its_asset_info *asset_info,
+                         uint8_t *data_buf,
+                         size_t max_size,
+                         size_t size_to_write,
+                         size_t offset)
 {
     psa_status_t status;
-    size_t write_size;
-    size_t offset;
-    uint32_t flags;
+    psa_storage_uid_t uid;
+    psa_storage_create_flags_t create_flags;
+    int32_t client_id;
 
-    /* Check that the UID is valid */
-    if (uid == TFM_ITS_INVALID_UID) {
-        return PSA_ERROR_INVALID_ARGUMENT;
-    }
+    uid = asset_info->uid;
+    create_flags = asset_info->create_flags;
+    client_id = asset_info->client_id;
 
     /* Check that the create_flags does not contain any unsupported flags */
     if (create_flags & ~(PSA_STORAGE_FLAG_WRITE_ONCE |
@@ -250,69 +235,68 @@
         return PSA_ERROR_NOT_SUPPORTED;
     }
 
-    /* Set file id */
-    tfm_its_get_fid(client_id, uid, g_fid);
+    if (offset == 0) {
+        /* First time creating an asset */
 
-    /* Read file info */
-    status = its_flash_fs_file_get_info(get_fs_ctx(client_id), g_fid,
-                                        &g_file_info);
-    if (status == PSA_SUCCESS) {
-        /* If the object exists and has the write once flag set, then it
-         * cannot be modified.
-         */
-        if (g_file_info.flags & PSA_STORAGE_FLAG_WRITE_ONCE) {
-            return PSA_ERROR_NOT_PERMITTED;
+        /* Check that the UID is valid */
+        if (uid == TFM_ITS_INVALID_UID) {
+            return PSA_ERROR_INVALID_ARGUMENT;
         }
-    } else if (status != PSA_ERROR_DOES_NOT_EXIST) {
-        /* If the file does not exist, then do nothing.
-         * If other error occurred, return it
-         */
-        return status;
-    }
 
-    offset = 0;
-    flags = (uint32_t)create_flags |
-            ITS_FLASH_FS_FLAG_CREATE | ITS_FLASH_FS_FLAG_TRUNCATE;
+        /* Set file id */
+        tfm_its_get_fid(client_id, uid, g_fid);
 
-    /* Iteratively read data from the caller and write it to the filesystem, in
-     * chunks no larger than the size of the asset_data buffer.
-     */
-    do {
-        /* Write as much of the data as will fit in the asset_data buffer */
-        write_size = ITS_UTILS_MIN(data_length, sizeof(asset_data));
-
-        /* Read asset data from the caller */
-        (void)its_req_mngr_read(asset_data, write_size);
-
-        /* Write to the file in the file system */
-        status = its_flash_fs_file_write(get_fs_ctx(client_id), g_fid, flags,
-                                         data_length, write_size, offset,
-                                         asset_data);
-        if (status != PSA_SUCCESS) {
+        /* Read file info */
+        status = its_flash_fs_file_get_info(get_fs_ctx(client_id), g_fid,
+                                            &g_file_info);
+        if (status == PSA_SUCCESS) {
+            /*
+             * If the object exists and has the write once flag set, then it
+             * cannot be modified.
+             */
+            if (g_file_info.flags & PSA_STORAGE_FLAG_WRITE_ONCE) {
+                return PSA_ERROR_NOT_PERMITTED;
+            }
+        } else if (status != PSA_ERROR_DOES_NOT_EXIST) {
+            /*
+             * If the file does not exist, then do nothing.
+             * If other error occurred, return it
+             */
             return status;
         }
 
-        /* Do not create or truncate after the first iteration */
-        flags &= ~(ITS_FLASH_FS_FLAG_CREATE | ITS_FLASH_FS_FLAG_TRUNCATE);
+        create_flags |= ITS_FLASH_FS_FLAG_CREATE | ITS_FLASH_FS_FLAG_TRUNCATE;
+    }
 
-        offset += write_size;
-        data_length -= write_size;
-    } while (data_length > 0);
+    /* Write to the file in the file system */
+    status = its_flash_fs_file_write(get_fs_ctx(client_id),
+                                     g_fid,
+                                     create_flags, max_size,
+                                     size_to_write, offset, data_buf);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
 
     return PSA_SUCCESS;
 }
 
-psa_status_t tfm_its_get(int32_t client_id,
-                         psa_storage_uid_t uid,
-                         size_t data_offset,
-                         size_t data_size,
-                         size_t *p_data_length)
+psa_status_t tfm_its_get(struct its_asset_info *asset_info,
+                         uint8_t *data_buf,
+                         size_t size_to_read,
+                         size_t offset,
+                         size_t *size_read,
+                         bool first_get)
 {
     psa_status_t status;
-    size_t read_size;
+    int32_t client_id;
+    psa_storage_uid_t uid;
+
+    client_id = asset_info->client_id;
+    uid = asset_info->uid;
 
 #ifdef TFM_PARTITION_TEST_PS
-    /* The PS test partition can call tfm_its_get() through PS code. Treat it
+    /*
+     * The PS test partition can call tfm_its_get() through PS code. Treat it
      * as if it were PS.
      */
     if (client_id == TFM_SP_PS_TEST) {
@@ -320,54 +304,42 @@
     }
 #endif
 
-    /* Check that the UID is valid */
-    if (uid == TFM_ITS_INVALID_UID) {
-        return PSA_ERROR_INVALID_ARGUMENT;
-    }
+    if (first_get) {
+        /* Check that the UID is valid */
+        if (uid == TFM_ITS_INVALID_UID) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
 
-    /* Set file id */
-    tfm_its_get_fid(client_id, uid, g_fid);
+        /* Set file id */
+        tfm_its_get_fid(client_id, uid, g_fid);
 
-    /* Read file info */
-    status = its_flash_fs_file_get_info(get_fs_ctx(client_id), g_fid,
-                                        &g_file_info);
-    if (status != PSA_SUCCESS) {
-        return status;
+        /* Read file info */
+        status = its_flash_fs_file_get_info(get_fs_ctx(client_id), g_fid,
+                                            &g_file_info);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
     }
 
     /* Boundary check the incoming request */
-    if (data_offset > g_file_info.size_current) {
+    if (offset > g_file_info.size_current) {
         return PSA_ERROR_INVALID_ARGUMENT;
     }
 
     /* Copy the object data only from within the file boundary */
-    data_size = ITS_UTILS_MIN(data_size,
-                              g_file_info.size_current - data_offset);
+    size_to_read = ITS_UTILS_MIN(size_to_read,
+                                 g_file_info.size_current - offset);
+
+    /* Read file data from the filesystem */
+    status = its_flash_fs_file_read(get_fs_ctx(client_id),
+                                    g_fid, size_to_read,
+                                    offset, data_buf);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
 
     /* Update the size of the output data */
-    *p_data_length = data_size;
-
-    /* Iteratively read data from the filesystem and write it to the caller, in
-     * chunks no larger than the size of the asset_data buffer.
-     */
-    do {
-        /* Read as much of the data as will fit in the asset_data buffer */
-        read_size = ITS_UTILS_MIN(data_size, sizeof(asset_data));
-
-        /* Read file data from the filesystem */
-        status = its_flash_fs_file_read(get_fs_ctx(client_id), g_fid, read_size,
-                                        data_offset, asset_data);
-        if (status != PSA_SUCCESS) {
-            *p_data_length = 0;
-            return status;
-        }
-
-        /* Write asset data to the caller */
-        its_req_mngr_write(asset_data, read_size);
-
-        data_offset += read_size;
-        data_size -= read_size;
-    } while (data_size > 0);
+    *size_read = size_to_read;
 
     return PSA_SUCCESS;
 }
diff --git a/secure_fw/partitions/internal_trusted_storage/tfm_internal_trusted_storage.h b/secure_fw/partitions/internal_trusted_storage/tfm_internal_trusted_storage.h
index 6748844..1e44fa7 100644
--- a/secure_fw/partitions/internal_trusted_storage/tfm_internal_trusted_storage.h
+++ b/secure_fw/partitions/internal_trusted_storage/tfm_internal_trusted_storage.h
@@ -10,14 +10,24 @@
 
 #include <stddef.h>
 #include <stdint.h>
+#include <stdbool.h>
 
 #include "psa/error.h"
 #include "psa/storage_common.h"
 
+#include "flash_fs/its_flash_fs.h"
+#include "its_utils.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+struct its_asset_info {
+    psa_storage_uid_t uid;
+    int32_t client_id;
+    psa_storage_create_flags_t create_flags;
+};
+
 /**
  * \brief Initializes the internal trusted storage system.
  *
@@ -38,18 +48,17 @@
  *
  * Stores data in the internal storage.
  *
- * \param[in] client_id     Identifier of the asset's owner (client)
- * \param[in] uid           The identifier for the data
- * \param[in] data_length   The size in bytes of the data in `p_data`
- * \param[in] create_flags  The flags that the data will be stored with
+ * \param[in] asset_info    The asset info include UID, client, etc...
+ * \param[in] data_buf      The asset data buffer to be stored
+ * \param[in] max_size      Size of the asset file to be set. Ignored if
+ *                          the file is not being created.
+ * \param[in] size_to_write Size in bytes of data to write in a single call
+ * \param[in] offset        Offset in the file to write. Must be less than or
+ *                          equal to the current file size.
  *
  * \return A status indicating the success/failure of the operation
  *
  * \retval PSA_SUCCESS                     The operation completed successfully
- * \retval PSA_ERROR_NOT_PERMITTED         The operation failed because the
- *                                         provided `uid` value was already
- *                                         created with
- *                                         PSA_STORAGE_FLAG_WRITE_ONCE
  * \retval PSA_ERROR_NOT_SUPPORTED         The operation failed because one or
  *                                         more of the flags provided in
  *                                         `create_flags` is not supported or is
@@ -66,10 +75,11 @@
  *                                         references memory the caller cannot
  *                                         access
  */
-psa_status_t tfm_its_set(int32_t client_id,
-                         psa_storage_uid_t uid,
-                         size_t data_length,
-                         psa_storage_create_flags_t create_flags);
+psa_status_t tfm_its_set(struct its_asset_info *asset_info,
+                         uint8_t *data_buf,
+                         size_t max_size,
+                         size_t size_to_write,
+                         size_t offset);
 
 /**
  * \brief Retrieve data associated with a provided UID
@@ -81,12 +91,13 @@
  * `p_data_length`. If `data_size` is 0, the contents of `p_data_length` will
  * be set to zero.
  *
- * \param[in]  client_id      Identifier of the asset's owner (client)
- * \param[in]  uid            The uid value
- * \param[in]  data_offset    The starting offset of the data requested
- * \param[in]  data_size      The amount of data requested
- * \param[out] p_data_length  On success, this will contain size of the data
- *                            placed in `p_data`.
+ * \param[in]  asset_info     The asset info include UID, client, etc...
+ * \param[out] data_buf       The buffer to stored the asset data
+ * \param[in]  size_to_read   The amount of data requested
+ * \param[in]  offset         The starting offset of the data requested
+ * \param[out] size_read      On success, this will contain size of the data
+ *                            placed in `data_buf`.
+ * \param[in] first_get       Indicator of if it is the first call of a series
  *
  * \return A status indicating the success/failure of the operation
  *
@@ -106,11 +117,12 @@
  *                                     larger than the size of the data
  *                                     associated with `uid`.
  */
-psa_status_t tfm_its_get(int32_t client_id,
-                         psa_storage_uid_t uid,
-                         size_t data_offset,
-                         size_t data_size,
-                         size_t *p_data_length);
+psa_status_t tfm_its_get(struct its_asset_info *asset_info,
+                         uint8_t *data_buf,
+                         size_t size_to_read,
+                         size_t offset,
+                         size_t *size_read,
+                         bool first_get);
 
 /**
  * \brief Retrieve the metadata about the provided uid
diff --git a/secure_fw/partitions/internal_trusted_storage/tfm_its_req_mngr.c b/secure_fw/partitions/internal_trusted_storage/tfm_its_req_mngr.c
index 021ddbe..b34d805 100644
--- a/secure_fw/partitions/internal_trusted_storage/tfm_its_req_mngr.c
+++ b/secure_fw/partitions/internal_trusted_storage/tfm_its_req_mngr.c
@@ -9,6 +9,7 @@
 
 #include <stdint.h>
 #include <string.h>
+#include <stdbool.h>
 
 #include "psa/storage_common.h"
 #include "tfm_internal_trusted_storage.h"
@@ -18,15 +19,30 @@
 #include "psa/service.h"
 #include "psa_manifest/tfm_internal_trusted_storage.h"
 #include "tfm_its_defs.h"
+#include "flash/its_flash.h"
 #else
 #include <stdbool.h>
 #include "tfm_secure_api.h"
 #include "tfm_api.h"
 #endif
 
-#ifndef TFM_PSA_API
-static uint8_t *p_data;
+#if defined(TFM_PSA_API)
+#ifndef ITS_BUF_SIZE
+/* By default, set the ITS buffer size to the max asset size so that all
+ * requests can be handled in one iteration.
+ */
+#define ITS_BUF_SIZE ITS_MAX_ASSET_SIZE
+#endif
 
+/* Buffer to store asset data from the caller.
+ * Note: size must be aligned to the max flash program unit to meet the
+ * alignment requirement of the filesystem.
+ */
+static uint8_t asset_data[ITS_UTILS_ALIGN(ITS_BUF_SIZE,
+                                          ITS_FLASH_MAX_ALIGNMENT)];
+#endif
+
+#ifndef TFM_PSA_API
 /**
  * \brief Indicates whether ITS has been initialised.
  */
@@ -36,8 +52,10 @@
                              psa_outvec *out_vec, size_t out_len)
 {
     psa_storage_uid_t uid;
+    uint8_t *p_data;
     size_t data_length;
     psa_storage_create_flags_t create_flags;
+    struct its_asset_info asset_info;
     int32_t client_id;
 
     (void)out_vec;
@@ -69,13 +87,20 @@
         return PSA_ERROR_PROGRAMMER_ERROR;
     }
 
-    return tfm_its_set(client_id, uid, data_length, create_flags);
+    asset_info.uid = uid;
+    asset_info.client_id = client_id;
+    asset_info.create_flags = create_flags;
+
+    return tfm_its_set(&asset_info, p_data, data_length,
+                       data_length, 0);
 }
 
 psa_status_t tfm_its_get_req(psa_invec *in_vec, size_t in_len,
                              psa_outvec *out_vec, size_t out_len)
 {
     psa_storage_uid_t uid;
+    struct its_asset_info asset_info;
+    uint8_t *p_data;
     size_t data_offset;
     size_t data_size;
     size_t *p_data_length;
@@ -110,7 +135,11 @@
         return PSA_ERROR_PROGRAMMER_ERROR;
     }
 
-    return tfm_its_get(client_id, uid, data_offset, data_size, p_data_length);
+    asset_info.uid = uid;
+    asset_info.client_id = client_id;
+
+    return tfm_its_get(&asset_info, p_data, data_size,
+                       data_offset, p_data_length, true);
 }
 
 psa_status_t tfm_its_get_info_req(psa_invec *in_vec, size_t in_len,
@@ -180,13 +209,15 @@
 }
 
 #else /* !defined(TFM_PSA_API) */
-static const psa_msg_t *p_msg;
-
 static psa_status_t tfm_its_set_req(const psa_msg_t *msg)
 {
+    psa_status_t status;
     psa_storage_uid_t uid;
-    size_t data_length;
+    uint8_t *data_buf;
+    size_t size_remaining;
+    size_t offset;
     psa_storage_create_flags_t create_flags;
+    struct its_asset_info asset_info;
     size_t num;
 
     if (msg->in_size[0] != sizeof(uid) ||
@@ -195,8 +226,6 @@
         return PSA_ERROR_PROGRAMMER_ERROR;
     }
 
-    data_length = msg->in_size[1];
-
     num = psa_read(msg->handle, 0, &uid, sizeof(uid));
     if (num != sizeof(uid)) {
         return PSA_ERROR_PROGRAMMER_ERROR;
@@ -207,16 +236,43 @@
         return PSA_ERROR_PROGRAMMER_ERROR;
     }
 
-    return tfm_its_set(msg->client_id, uid, data_length, create_flags);
+    asset_info.uid = uid;
+    asset_info.client_id = msg->client_id;
+    asset_info.create_flags = create_flags;
+
+    size_remaining = msg->in_size[1];
+    offset = 0;
+
+    data_buf = asset_data;
+    do {
+        num = psa_read(msg->handle, 1, asset_data,
+                       ITS_UTILS_MIN(size_remaining, sizeof(asset_data)));
+
+        status = tfm_its_set(&asset_info, data_buf, size_remaining,
+                             num, offset);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+
+        size_remaining -= num;
+        offset += num;
+    } while (size_remaining);
+
+    return PSA_SUCCESS;
 }
 
 static psa_status_t tfm_its_get_req(const psa_msg_t *msg)
 {
+    psa_status_t status;
     psa_storage_uid_t uid;
+    uint8_t *data_buf;
+    size_t size_to_read;
     size_t data_offset;
-    size_t data_size;
-    size_t data_length;
+    size_t out_size;
+    size_t size_read;
     size_t num;
+    struct its_asset_info asset_info;
+    bool first_get;
 
     if (msg->in_size[0] != sizeof(uid) ||
         msg->in_size[1] != sizeof(data_offset)) {
@@ -224,8 +280,6 @@
         return PSA_ERROR_PROGRAMMER_ERROR;
     }
 
-    data_size = msg->out_size[0];
-
     num = psa_read(msg->handle, 0, &uid, sizeof(uid));
     if (num != sizeof(uid)) {
         return PSA_ERROR_PROGRAMMER_ERROR;
@@ -236,8 +290,33 @@
         return PSA_ERROR_PROGRAMMER_ERROR;
     }
 
-    return tfm_its_get(msg->client_id, uid, data_offset, data_size,
-                       &data_length);
+    asset_info.uid = uid;
+    asset_info.client_id = msg->client_id;
+    out_size = msg->out_size[0];
+    first_get = true;
+
+    /* Fill in the outvec unless no data left */
+    data_buf = asset_data;
+    do {
+        size_to_read = ITS_UTILS_MIN(out_size, sizeof(asset_data));
+        status = tfm_its_get(&asset_info, data_buf, size_to_read,
+                             data_offset, &size_read, first_get);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+        if (size_read == 0) {
+            /* No more data */
+            return PSA_SUCCESS;
+        }
+
+        psa_write(msg->handle, 0, data_buf, size_read);
+
+        first_get = false;
+        out_size -= size_read;
+        data_offset += size_read;
+    } while (out_size > 0);
+
+    return PSA_SUCCESS;
 }
 
 static psa_status_t tfm_its_get_info_req(const psa_msg_t *msg)
@@ -302,8 +381,6 @@
 #ifdef TFM_PSA_API
 psa_status_t tfm_internal_trusted_storage_service_sfn(const psa_msg_t *msg)
 {
-    p_msg = msg;
-
     switch (msg->type) {
     case TFM_ITS_SET:
         return tfm_its_set_req(msg);
@@ -320,24 +397,3 @@
     return PSA_ERROR_GENERIC_ERROR;
 }
 #endif /* TFM_PSA_API */
-
-size_t its_req_mngr_read(uint8_t *buf, size_t num_bytes)
-{
-#ifdef TFM_PSA_API
-    return psa_read(p_msg->handle, 1, buf, num_bytes);
-#else
-    (void)memcpy(buf, p_data, num_bytes);
-    p_data += num_bytes;
-    return num_bytes;
-#endif
-}
-
-void its_req_mngr_write(const uint8_t *buf, size_t num_bytes)
-{
-#ifdef TFM_PSA_API
-    psa_write(p_msg->handle, 0, buf, num_bytes);
-#else
-    (void)memcpy(p_data, buf, num_bytes);
-    p_data += num_bytes;
-#endif
-}
diff --git a/secure_fw/partitions/internal_trusted_storage/tfm_its_req_mngr.h b/secure_fw/partitions/internal_trusted_storage/tfm_its_req_mngr.h
index 050eab7..11dca29 100644
--- a/secure_fw/partitions/internal_trusted_storage/tfm_its_req_mngr.h
+++ b/secure_fw/partitions/internal_trusted_storage/tfm_its_req_mngr.h
@@ -82,24 +82,6 @@
                                 psa_outvec *out_vec, size_t out_len);
 #endif /* NOT TFM_PSA_API */
 
-/**
- * \brief Reads asset data from the caller.
- *
- * \param[out] buf        Buffer to copy the data to
- * \param[in]  num_bytes  Number of bytes to copy
- *
- * \return Number of bytes copied
- */
-size_t its_req_mngr_read(uint8_t *buf, size_t num_bytes);
-
-/**
- * \brief Writes asset data to the caller.
- *
- * \param[in] buf        Buffer to copy the data from
- * \param[in] num_bytes  Number of bytes to copy
- */
-void its_req_mngr_write(const uint8_t *buf, size_t num_bytes);
-
 #ifdef __cplusplus
 }
 #endif