xtest 6012: Persistent File Creation

Test with specific persistent file creation:
optional object (can be NULL), and creation overwrite
using flag TEE_DATA_FLAG_OVERWRITE, on an existing file.

This reproduces https://github.com/OP-TEE/optee_os/issues/745

Change-Id: I6ed67a94e006325971e9ae494cd588d90586d964
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Signed-off-by: Pascal Brand <pascal.brand@st.com>
diff --git a/host/xtest/xtest_6000.c b/host/xtest/xtest_6000.c
index 4fd3dc1..3ca872e 100644
--- a/host/xtest/xtest_6000.c
+++ b/host/xtest/xtest_6000.c
@@ -45,6 +45,10 @@
 	0x03, 0x13, 0x03
 };
 
+static uint8_t file_04[] = {
+	0x00, 0x01, 0x02
+};
+
 static uint8_t data_00[] = {
 	0x00, 0x6E, 0x04, 0x57, 0x08, 0xFB, 0x71, 0x96,
 	0x00, 0x2E, 0x55, 0x3D, 0x02, 0xC3, 0xA6, 0x92,
@@ -112,6 +116,25 @@
 	return res;
 }
 
+static TEEC_Result fs_create_overwrite(TEEC_Session *sess, void *id,
+				       uint32_t id_size)
+{
+	TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
+	TEEC_Result res;
+	uint32_t org;
+
+	op.params[0].tmpref.buffer = id;
+	op.params[0].tmpref.size = id_size;
+
+	op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
+					 TEEC_NONE, TEEC_NONE,
+					 TEEC_NONE);
+
+	res = TEEC_InvokeCommand(sess, TA_STORAGE_CMD_CREATE_OVERWRITE, &op, &org);
+
+	return res;
+}
+
 static TEEC_Result fs_close(TEEC_Session *sess, uint32_t obj)
 {
 	TEEC_Operation op = TEEC_OPERATION_INITIALIZER;
@@ -1188,6 +1211,49 @@
 }
 #endif
 
+static void xtest_tee_test_6012(ADBG_Case_t *c)
+{
+	TEEC_Session sess;
+	uint32_t orig;
+	uint32_t obj;
+
+	if (!ADBG_EXPECT_TEEC_SUCCESS(c,
+		xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig)))
+		return;
+
+	if (!ADBG_EXPECT_TEEC_SUCCESS(c,
+		fs_create_overwrite(&sess, file_04, sizeof(file_04))))
+		goto exit;
+
+	TEEC_CloseSession(&sess);
+
+	/* re-create the same */
+	if (!ADBG_EXPECT_TEEC_SUCCESS(c,
+		xtest_teec_open_session(&sess, &storage_ta_uuid, NULL, &orig)))
+		return;
+
+	if (!ADBG_EXPECT_TEEC_SUCCESS(c,
+		fs_create_overwrite(&sess, file_04, sizeof(file_04))))
+		goto exit;
+
+	/*
+	 * recreate it with an object, and remove it so that xtest 6009
+	 * can be replayed
+	 */
+	 if (!ADBG_EXPECT_TEEC_SUCCESS(c,
+		fs_create(&sess, file_04, sizeof(file_04),
+			  TEE_DATA_FLAG_ACCESS_WRITE |
+			  TEE_DATA_FLAG_ACCESS_WRITE_META | TEE_DATA_FLAG_OVERWRITE, 0, NULL, 0, &obj)))
+			goto exit;
+
+	/* clean */
+	if (!ADBG_EXPECT_TEEC_SUCCESS(c, fs_unlink(&sess, obj)))
+		goto exit;
+
+exit:
+	TEEC_CloseSession(&sess);
+}
+
 ADBG_CASE_DEFINE(
 	XTEST_TEE_6001, xtest_tee_test_6001,
 	/* Title */
@@ -1321,3 +1387,15 @@
     "Description of how to implement ..."
 );
 #endif
+
+ADBG_CASE_DEFINE(
+    XTEST_TEE_6012, xtest_tee_test_6012,
+    /* Title */
+    "Test TEE GP TTA DS init objects",
+    /* Short description */
+    "Short description ...",
+    /* Requirement IDs */
+    "TEE-??",
+    /* How to implement */
+    "Description of how to implement ..."
+);
diff --git a/host/xtest/xtest_main.c b/host/xtest/xtest_main.c
index da1054d..534c39f 100644
--- a/host/xtest/xtest_main.c
+++ b/host/xtest/xtest_main.c
@@ -63,6 +63,7 @@
 ADBG_SUITE_ENTRY(XTEST_TEE_6010, NULL)
 ADBG_SUITE_ENTRY(XTEST_TEE_6011, NULL)
 #endif
+ADBG_SUITE_ENTRY(XTEST_TEE_6012, NULL)
 ADBG_SUITE_ENTRY(XTEST_TEE_7001, NULL)
 /* FVP    ADBG_SUITE_ENTRY(XTEST_TEE_7002, NULL) */
 ADBG_SUITE_ENTRY(XTEST_TEE_7003, NULL)
diff --git a/host/xtest/xtest_test.h b/host/xtest/xtest_test.h
index ae36270..3cb546a 100644
--- a/host/xtest/xtest_test.h
+++ b/host/xtest/xtest_test.h
@@ -58,6 +58,7 @@
 ADBG_CASE_DECLARE(XTEST_TEE_6010);
 ADBG_CASE_DECLARE(XTEST_TEE_6011);
 #endif
+ADBG_CASE_DECLARE(XTEST_TEE_6012);
 ADBG_CASE_DECLARE(XTEST_TEE_7001);
 ADBG_CASE_DECLARE(XTEST_TEE_7002);
 ADBG_CASE_DECLARE(XTEST_TEE_7003);
diff --git a/ta/storage/include/storage.h b/ta/storage/include/storage.h
index 3767666..0dd8e16 100644
--- a/ta/storage/include/storage.h
+++ b/ta/storage/include/storage.h
@@ -32,6 +32,7 @@
 
 TEE_Result ta_storage_cmd_open(uint32_t param_types, TEE_Param params[4]);
 TEE_Result ta_storage_cmd_create(uint32_t param_types, TEE_Param params[4]);
+TEE_Result ta_storage_cmd_create_overwrite(uint32_t param_types, TEE_Param params[4]);
 TEE_Result ta_storage_cmd_close(uint32_t param_types, TEE_Param params[4]);
 TEE_Result ta_storage_cmd_read(uint32_t param_types, TEE_Param params[4]);
 TEE_Result ta_storage_cmd_write(uint32_t param_types, TEE_Param params[4]);
diff --git a/ta/storage/include/ta_storage.h b/ta/storage/include/ta_storage.h
index c4f3e31..e322a99 100644
--- a/ta/storage/include/ta_storage.h
+++ b/ta/storage/include/ta_storage.h
@@ -45,5 +45,6 @@
 #define TA_STORAGE_CMD_RESET_ENUM     11
 #define TA_STORAGE_CMD_START_ENUM     12
 #define TA_STORAGE_CMD_NEXT_ENUM      13
+#define TA_STORAGE_CMD_CREATE_OVERWRITE	14
 
 #endif /*TA_SKELETON_H */
diff --git a/ta/storage/storage.c b/ta/storage/storage.c
index 6d4f892..5f3360e 100644
--- a/ta/storage/storage.c
+++ b/ta/storage/storage.c
@@ -76,6 +76,24 @@
 	return res;
 }
 
+TEE_Result ta_storage_cmd_create_overwrite(uint32_t param_types,
+					   TEE_Param params[4])
+{
+	TEE_Result res;
+
+	ASSERT_PARAM_TYPE(TEE_PARAM_TYPES
+			  (TEE_PARAM_TYPE_MEMREF_INPUT,
+			   TEE_PARAM_TYPE_NONE,
+			   TEE_PARAM_TYPE_NONE,
+			   TEE_PARAM_TYPE_NONE));
+
+	res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
+		 params[0].memref.buffer, params[0].memref.size,
+		 TEE_DATA_FLAG_OVERWRITE,
+		 NULL, NULL, 0, NULL);
+	return res;
+}
+
 TEE_Result ta_storage_cmd_close(uint32_t param_types, TEE_Param params[4])
 {
 	ASSERT_PARAM_TYPE(TEE_PARAM_TYPES
diff --git a/ta/storage/ta_entry.c b/ta/storage/ta_entry.c
index 1ba800e..5a55fed 100644
--- a/ta/storage/ta_entry.c
+++ b/ta/storage/ta_entry.c
@@ -85,6 +85,9 @@
 	case TA_STORAGE_CMD_CREATE:
 		return ta_storage_cmd_create(nParamTypes, pParams);
 
+	case TA_STORAGE_CMD_CREATE_OVERWRITE:
+		return ta_storage_cmd_create_overwrite(nParamTypes, pParams);
+
 	case TA_STORAGE_CMD_SEEK:
 		return ta_storage_cmd_seek(nParamTypes, pParams);