Tests added

Signed-off-by: Pascal Brand <pascal.brand@st.com>
diff --git a/ta/os_test/os_test.c b/ta/os_test/os_test.c
new file mode 100644
index 0000000..6fcbc7c
--- /dev/null
+++ b/ta/os_test/os_test.c
@@ -0,0 +1,670 @@
+/*
+ * Copyright (c) 2014, STMicroelectronics International N.V.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdint.h>
+
+#include <compiler.h>
+#include <ta_crypt.h>
+#include <ta_os_test.h>
+#include <tee_internal_api_extensions.h>
+
+#include "os_test.h"
+#include "testframework.h"
+
+enum p_type {
+	P_TYPE_BOOL,
+	P_TYPE_INT,
+	P_TYPE_UUID,
+	P_TYPE_IDENTITY,
+	P_TYPE_STRING,
+	P_TYPE_BINARY_BLOCK,
+};
+
+struct p_attr {
+	const char *str;
+	enum p_type type;
+	bool retrieved;
+};
+
+static TEE_Result print_properties(TEE_PropSetHandle h,
+				   TEE_PropSetHandle prop_set,
+				   struct p_attr *p_attrs, size_t num_p_attrs)
+{
+TEE_Result res;
+size_t n;
+
+TEE_StartPropertyEnumerator(h, prop_set);
+
+while (true) {
+	char nbuf[80];
+	char vbuf[80];
+	char vbuf2[80];
+	size_t nblen = sizeof(nbuf);
+	size_t vblen = sizeof(vbuf);
+	size_t vblen2 = sizeof(vbuf2);
+
+	res = TEE_GetPropertyName(h, nbuf, &nblen);
+	if (res != TEE_SUCCESS) {
+		EMSG("TEE_GetPropertyName returned 0x%x\n",
+		     (unsigned int)res);
+		return res;
+	}
+
+	res = TEE_GetPropertyAsString(h, NULL, vbuf, &vblen);
+	if (res != TEE_SUCCESS) {
+		EMSG("1TEE_GetPropertyAsString(\"%s\") returned 0x%x\n",
+		     nbuf, (unsigned int)res);
+		return res;
+	}
+	res = TEE_GetPropertyAsString(prop_set, nbuf, vbuf2, &vblen2);
+	if (res != TEE_SUCCESS) {
+		EMSG("2TEE_GetPropertyAsString(\"%s\") returned 0x%x\n",
+		     nbuf, (unsigned int)res);
+		return res;
+	}
+	if (my_strcmp(vbuf, vbuf2) != 0) {
+		EMSG("String of \"%s\" differs\n", nbuf);
+		return TEE_ERROR_GENERIC;
+	}
+
+	DMSG("Found \"%s\" value \"%s\"\n", nbuf, vbuf);
+
+	for (n = 0; n < num_p_attrs; n++) {
+		if (my_strcmp(nbuf, p_attrs[n].str) != 0)
+			continue;
+
+		if (p_attrs[n].retrieved) {
+			EMSG("Value \"%s\" already retrieved\n",
+			     p_attrs[n].str);
+			return TEE_ERROR_GENERIC;
+		}
+		p_attrs[n].retrieved = true;
+
+		switch (p_attrs[n].type) {
+		case P_TYPE_BOOL:
+			{
+				bool v;
+
+				res =
+				    TEE_GetPropertyAsBool(h, NULL, &v);
+				if (res != TEE_SUCCESS) {
+					EMSG(
+					"TEE_GetPropertyAsBool(\"%s\") returned 0x%x\n",
+					nbuf, (unsigned int)res);
+					return res;
+				}
+			}
+			break;
+
+		case P_TYPE_INT:
+			{
+				uint32_t v;
+
+				res = TEE_GetPropertyAsU32(h, NULL, &v);
+				if (res != TEE_SUCCESS) {
+					EMSG(
+					"TEE_GetPropertyAsU32(\"%s\") returned 0x%x\n",
+					nbuf, (unsigned int)res);
+					return res;
+				}
+			}
+			break;
+
+		case P_TYPE_UUID:
+			{
+				TEE_UUID v;
+
+				res =
+				    TEE_GetPropertyAsUUID(h, NULL, &v);
+				if (res != TEE_SUCCESS) {
+					EMSG(
+					"TEE_GetPropertyAsUUID(\"%s\") returned 0x%x\n",
+					nbuf, (unsigned int)res);
+					return res;
+				}
+			}
+			break;
+
+		case P_TYPE_IDENTITY:
+			{
+				TEE_Identity v;
+
+				res =
+				    TEE_GetPropertyAsIdentity(h, NULL,
+							      &v);
+				if (res != TEE_SUCCESS) {
+					EMSG(
+					"TEE_GetPropertyAsIdentity(\"%s\") returned 0x%x\n",
+					nbuf, (unsigned int)res);
+					return res;
+				}
+			}
+			break;
+
+		case P_TYPE_STRING:
+			/* Already read as string */
+			break;
+
+		case P_TYPE_BINARY_BLOCK:
+			{
+				char bbuf[80];
+				size_t bblen = sizeof(bbuf);
+
+				res =
+				    TEE_GetPropertyAsBinaryBlock(h,
+								 NULL,
+								 bbuf,
+								 &bblen);
+				if (res != TEE_SUCCESS) {
+					EMSG(
+					"TEE_GetPropertyAsBinaryBlock(\"%s\") returned 0x%x\n",
+					nbuf, (unsigned int)res);
+					return res;
+				}
+				if (my_strcmp
+				    ("myprop.binaryblock", nbuf) == 0) {
+					const char exp_bin_value[] =
+					    "Hello world!";
+
+					if (bblen !=
+					    my_strlen(exp_bin_value)
+					    ||
+					    TEE_MemCompare
+					    (exp_bin_value, bbuf,
+					     bblen) != 0) {
+						EMSG(
+						"Binary buffer of \"%s\" differs from \"%s\"\n",
+							nbuf, exp_bin_value);
+						EMSG(
+						"Got \"%s\"\n",
+						     bbuf);
+						return
+						    TEE_ERROR_GENERIC;
+					}
+				}
+
+			}
+			break;
+
+		default:
+			EMSG("Unknown type (%d) for \"%s\"\n",
+			     p_attrs[n].type, p_attrs[n].str);
+			return TEE_ERROR_GENERIC;
+		}
+	}
+
+	res = TEE_GetNextProperty(h);
+	if (res != TEE_SUCCESS) {
+		if (res == TEE_ERROR_ITEM_NOT_FOUND)
+			return TEE_SUCCESS;
+		return res;
+	}
+}
+}
+
+static TEE_Result test_malloc(void)
+{
+	void *p = TEE_Malloc(4, 0);
+
+	if (p == NULL) {
+		EMSG("TEE_Malloc failed\n");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+	TEE_Free(p);
+	TEE_Free(NULL);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result test_properties(void)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	TEE_PropSetHandle h;
+	struct p_attr p_attrs[] = {
+		{"gpd.ta.appID", P_TYPE_UUID},
+		{"gpd.ta.singleInstance", P_TYPE_BOOL},
+		{"gpd.ta.multiSession", P_TYPE_BOOL},
+		{"gpd.ta.instanceKeepAlive", P_TYPE_BOOL},
+		{"gpd.ta.dataSize", P_TYPE_INT},
+		{"gpd.ta.stackSize", P_TYPE_INT},
+		{"gpd.ta.version", P_TYPE_STRING},
+		{"gpd.ta.description", P_TYPE_STRING},
+		{"gpd.client.identity", P_TYPE_IDENTITY},
+		{"gpd.tee.apiversion", P_TYPE_STRING},
+		{"gpd.tee.description", P_TYPE_STRING},
+		{"gpd.tee.deviceID", P_TYPE_UUID},
+		{"gpd.tee.systemTime.protectionLevel", P_TYPE_INT},
+		{"gpd.tee.TAPersistentTime.protectionLevel", P_TYPE_INT},
+		{"gpd.tee.arith.maxBigIntSize", P_TYPE_INT},
+		{"gpd.tee.cryptography.ecc", P_TYPE_BOOL},
+		{"gpd.tee.trustedStorage.antiRollback.protectionLevel", P_TYPE_INT},
+		{"gpd.tee.trustedos.implementation.version", P_TYPE_STRING},
+		{"gpd.tee.trustedos.implementation.binaryversion", P_TYPE_INT},
+		{"gpd.tee.trustedos.manufacturer", P_TYPE_STRING},
+		{"gpd.tee.firmware.implementation.version", P_TYPE_STRING},
+		{"gpd.tee.firmware.implementation.binaryversion", P_TYPE_INT},
+		{"gpd.tee.firmware.manufacturer", P_TYPE_STRING},
+		{"myprop.true", P_TYPE_BOOL},
+		{"myprop.42", P_TYPE_INT},
+		{"myprop.123", P_TYPE_UUID},
+		{"myprop.1234", P_TYPE_IDENTITY},
+		{"myprop.hello", P_TYPE_STRING},
+		{"myprop.binaryblock", P_TYPE_BINARY_BLOCK},
+	};
+	const size_t num_p_attrs = sizeof(p_attrs) / sizeof(p_attrs[0]);
+	size_t n;
+
+	res = TEE_AllocatePropertyEnumerator(&h);
+	if (res != TEE_SUCCESS) {
+		EMSG("TEE_AllocatePropertyEnumerator: returned 0x%x\n",
+		     (unsigned int)res);
+		return TEE_ERROR_GENERIC;
+	}
+
+	printf("Getting properties for current TA\n");
+	res = print_properties(h, TEE_PROPSET_CURRENT_TA, p_attrs, num_p_attrs);
+	if (res != TEE_SUCCESS)
+		goto cleanup_return;
+
+	printf("Getting properties for current client\n");
+	res = print_properties(h, TEE_PROPSET_CURRENT_CLIENT, p_attrs,
+			       num_p_attrs);
+	if (res != TEE_SUCCESS)
+		goto cleanup_return;
+
+	printf("Getting properties for implementation\n");
+	res = print_properties(h, TEE_PROPSET_TEE_IMPLEMENTATION, p_attrs,
+			       num_p_attrs);
+	if (res != TEE_SUCCESS)
+		goto cleanup_return;
+
+	for (n = 0; n < num_p_attrs; n++) {
+		if (!p_attrs[n].retrieved) {
+			EMSG("\"%s\" not retrieved\n", p_attrs[n].str);
+			res = TEE_ERROR_GENERIC;
+			goto cleanup_return;
+		}
+	}
+
+cleanup_return:
+	TEE_FreePropertyEnumerator(h);
+	return res;
+}
+
+static TEE_Result test_mem_access_right(uint32_t param_types,
+					TEE_Param params[4])
+{
+	static const TEE_UUID test_uuid = TA_OS_TEST_UUID;
+	TEE_Result res;
+	uint32_t ret_orig;
+	uint32_t l_pts;
+	TEE_Param l_params[4] = { { {0} } };
+	uint8_t buf[32];
+	TEE_TASessionHandle sess = TEE_HANDLE_NULL;
+
+	if (param_types !=
+	    TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0, 0))
+		return TEE_ERROR_GENERIC;
+	res =
+	    TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
+					TEE_MEMORY_ACCESS_ANY_OWNER,
+					params[0].memref.buffer,
+					params[0].memref.size);
+	if (res != TEE_SUCCESS)
+		return res;
+	res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
+					  params[0].memref.buffer,
+					  params[0].memref.size);
+	if (res != TEE_ERROR_ACCESS_DENIED)
+		return TEE_ERROR_GENERIC;
+
+	res = TEE_OpenTASession(&test_uuid, 0, 0, NULL, &sess, &ret_orig);
+	if (res != TEE_SUCCESS) {
+		EMSG("test_mem_access_right: TEE_OpenTASession failed\n");
+		goto cleanup_return;
+	}
+
+	l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0, 0);
+	l_params[0].memref.buffer = buf;
+	l_params[0].memref.size = sizeof(buf);
+	res = TEE_InvokeTACommand(sess, 0, TA_OS_TEST_CMD_PRIVATE_PARAMS,
+				  l_pts, l_params, &ret_orig);
+	if (res != TEE_SUCCESS) {
+		EMSG("test_mem_access_right: TEE_InvokeTACommand failed\n");
+		goto cleanup_return;
+	}
+
+cleanup_return:
+	TEE_CloseTASession(sess);
+	return res;
+}
+
+static TEE_Result test_time(void)
+{
+	TEE_Result res;
+	TEE_Time t;
+	TEE_Time sys_t;
+
+	static const TEE_Time null_time = { 0, 0 };
+	static const TEE_Time wrap_time = { UINT32_MAX, 999 };
+
+	TEE_GetSystemTime(&sys_t);
+	printf("system time %u.%03u\n", (unsigned int)sys_t.seconds,
+	       (unsigned int)sys_t.millis);
+
+	TEE_GetREETime(&t);
+	printf("REE time %u.%03u\n", (unsigned int)t.seconds,
+	       (unsigned int)t.millis);
+
+	res = TEE_GetTAPersistentTime(&t);
+	switch (res) {
+	case TEE_SUCCESS:
+		printf("Stored TA time %u.%03u\n", (unsigned int)t.seconds,
+		       (unsigned int)t.millis);
+		break;
+	case TEE_ERROR_OVERFLOW:
+		EMSG("Stored TA time overflowed %u.%03u\n",
+		     (unsigned int)t.seconds, (unsigned int)t.millis);
+		break;
+	case TEE_ERROR_TIME_NOT_SET:
+		EMSG("TA time not stored\n");
+		break;
+	case TEE_ERROR_TIME_NEEDS_RESET:
+		EMSG("TA time needs reset\n");
+		break;
+	default:
+		return res;
+	}
+
+	res = TEE_SetTAPersistentTime(&null_time);
+	if (res != TEE_SUCCESS) {
+		EMSG("TEE_SetTAPersistentTime: failed\n");
+		return res;
+	}
+
+	res = TEE_GetTAPersistentTime(&t);
+	if (res != TEE_SUCCESS) {
+		EMSG("TEE_GetTAPersistentTime null: failed\n");
+		return res;
+	}
+	printf("TA time %u.%03u\n", (unsigned int)t.seconds,
+	       (unsigned int)t.millis);
+	/*
+	 * The time between TEE_SetTAPersistentTime() and
+	 * TEE_GetTAPersistentTime() should be much less than 1 second, in fact
+	 * it's not even a millisecond.
+	 */
+	if (t.seconds > 1 || t.millis >= 1000) {
+		EMSG("Unexpected stored TA time %u.%03u\n",
+		     (unsigned int)t.seconds, (unsigned int)t.millis);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	res = TEE_SetTAPersistentTime(&wrap_time);
+	if (res != TEE_SUCCESS) {
+		EMSG("TEE_SetTAPersistentTime wrap: failed\n");
+		return res;
+	}
+
+	res = TEE_Wait(1000);
+	if (res != TEE_SUCCESS)
+		EMSG("TEE_Wait wrap: failed\n");
+
+	res = TEE_GetTAPersistentTime(&t);
+	if (res != TEE_ERROR_OVERFLOW) {
+		EMSG("TEE_GetTAPersistentTime: failed\n");
+		return TEE_ERROR_BAD_STATE;
+	}
+	printf("TA time %u.%03u\n", (unsigned int)t.seconds,
+	       (unsigned int)t.millis);
+
+	if (t.seconds > sys_t.seconds) {
+		EMSG("Unexpected wrapped time %u.%03u (sys_t %u.%03u)\n",
+		     (unsigned int)t.seconds, (unsigned int)t.millis,
+		     (unsigned int)sys_t.seconds, (unsigned int)sys_t.millis);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	return TEE_SUCCESS;
+}
+
+TEE_Result ta_entry_basic(uint32_t param_types, TEE_Param params[4])
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	printf("ta_entry_basic: enter\n");
+
+	res = test_malloc();
+	if (res != TEE_SUCCESS)
+		return res;
+
+	res = test_properties();
+	if (res != TEE_SUCCESS)
+		return res;
+
+	res = test_mem_access_right(param_types, params);
+	if (res != TEE_SUCCESS)
+		return res;
+
+	res = test_time();
+	if (res != TEE_SUCCESS)
+		return res;
+
+	/* mpa lib test bench, panics TA on failure */
+	tb_main();
+
+	return TEE_SUCCESS;
+}
+
+TEE_Result ta_entry_panic(uint32_t param_types, TEE_Param params[4])
+{
+	volatile bool mytrue = true;
+	(void)param_types;
+	(void)params;
+
+	printf("ta_entry_panic: enter\n");
+	/*
+	 * Somewhat clumsy way of avoiding compile errors if TEE_Panic() has
+	 * the __noreturn attribute.
+	 */
+	if (mytrue)
+		TEE_Panic(0xbeef);
+
+	/*
+	 * Should not be reached, but if it is the testsuite can detect that
+	 * TEE_Panic() returned instead of panicking the TA.
+	 */
+	return TEE_SUCCESS;
+}
+
+TEE_Result ta_entry_client_with_timeout(uint32_t param_types,
+					TEE_Param params[4])
+{
+	static const TEE_UUID os_test_uuid = TA_OS_TEST_UUID;
+	TEE_Result res;
+	TEE_TASessionHandle sess;
+	uint32_t ret_orig;
+
+	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+					   TEE_PARAM_TYPE_NONE,
+					   TEE_PARAM_TYPE_NONE,
+					   TEE_PARAM_TYPE_NONE)) {
+		EMSG("ta_entry_client_with_timeout: bad parameters\n");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	res = TEE_OpenTASession(&os_test_uuid, 0, 0, NULL, &sess, &ret_orig);
+	if (res != TEE_SUCCESS) {
+		EMSG(
+		"ta_entry_client_with_timeout: TEE_OpenTASession failed\n");
+		return res;
+	}
+
+	res =
+	    TEE_InvokeTACommand(sess, params[0].value.a / 2,
+				TA_OS_TEST_CMD_WAIT, param_types, params,
+				&ret_orig);
+
+	if (ret_orig != TEE_ORIGIN_TRUSTED_APP || res != TEE_ERROR_CANCEL) {
+		EMSG("ta_entry_client_with_timeout: TEE_InvokeTACommand: "
+		     "res 0x%x ret_orig 0x%x\n", (unsigned int)res,
+		     (unsigned int)ret_orig);
+		res = TEE_ERROR_GENERIC;
+	} else
+		res = TEE_SUCCESS;
+
+	TEE_CloseTASession(sess);
+	return res;
+
+}
+
+TEE_Result ta_entry_client(uint32_t param_types, TEE_Param params[4])
+{
+	static const TEE_UUID crypt_uuid = TA_CRYPT_UUID;
+	TEE_Result res;
+	uint32_t l_pts;
+	TEE_Param l_params[4] = { { {0} } };
+	TEE_TASessionHandle sess;
+	uint32_t ret_orig;
+	static const uint8_t sha256_in[] = { 'a', 'b', 'c' };
+	static const uint8_t sha256_out[] = {
+		0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
+		0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
+		0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
+		0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
+	};
+	uint8_t out[32] = { 0 };
+	void *in = NULL;
+
+	(void)param_types;
+	(void)params;
+
+	printf("ta_entry_client: enter\n");
+
+	in = TEE_Malloc(sizeof(sha256_in), 0);
+	if (in == NULL)
+		return TEE_ERROR_OUT_OF_MEMORY;
+	TEE_MemMove(in, sha256_in, sizeof(sha256_in));
+
+	res = TEE_OpenTASession(&crypt_uuid, 0, 0, NULL, &sess, &ret_orig);
+	if (res != TEE_SUCCESS) {
+		EMSG("ta_entry_client: TEE_OpenTASession failed\n");
+		goto cleanup_return;
+	}
+
+	l_pts = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
+				TEE_PARAM_TYPE_MEMREF_OUTPUT, 0, 0);
+	l_params[0].memref.buffer = in;
+	l_params[0].memref.size = sizeof(sha256_in);
+	l_params[1].memref.buffer = out;
+	l_params[1].memref.size = sizeof(out);
+
+	res = TEE_InvokeTACommand(sess, 0, TA_CRYPT_CMD_SHA256, l_pts, l_params,
+				  &ret_orig);
+	if (res != TEE_SUCCESS) {
+		EMSG("ta_entry_client: TEE_InvokeTACommand failed\n");
+		goto cleanup_return;
+	}
+
+	if (TEE_MemCompare(sha256_out, out, sizeof(sha256_out)) != 0) {
+		EMSG("ta_entry_client: out parameter failed\n");
+		res = TEE_ERROR_GENERIC;
+		goto cleanup_return;
+	}
+
+cleanup_return:
+	TEE_Free(in);
+	TEE_CloseTASession(sess);
+	return res;
+}
+
+TEE_Result ta_entry_private_params(uint32_t param_types, TEE_Param params[4])
+{
+	TEE_Result res;
+
+	if (param_types !=
+	    TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 0, 0, 0))
+		return TEE_ERROR_GENERIC;
+	res =
+	    TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ |
+					TEE_MEMORY_ACCESS_ANY_OWNER,
+					params[0].memref.buffer,
+					params[0].memref.size);
+	if (res != TEE_SUCCESS)
+		return res;
+
+	res = TEE_CheckMemoryAccessRights(TEE_MEMORY_ACCESS_READ,
+					  params[0].memref.buffer,
+					  params[0].memref.size);
+
+	return res;
+}
+
+TEE_Result ta_entry_wait(uint32_t param_types, TEE_Param params[4])
+{
+	TEE_Result res = TEE_SUCCESS;
+	(void)param_types;
+
+	printf("ta_entry_wait: waiting %d\n", (unsigned int)params[0].value.a);
+	/* Wait */
+	res = TEE_Wait(params[0].value.a);
+
+	return res;
+}
+
+TEE_Result ta_entry_bad_mem_access(uint32_t param_types, TEE_Param params[4])
+{
+	long stack;
+	long stack_addr = (long)&stack;
+
+	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT, 0, 0, 0))
+		return TEE_ERROR_GENERIC;
+
+	switch (params[0].value.a) {
+	case 1:
+		*((uint32_t *) 0) = 0;
+		break;
+	case 2:
+		*((uint32_t *)(stack_addr + 0x40000000)) = 0;
+		break;
+	case 3:
+		((void (*)(void))0) ();
+		break;
+	case 4:
+		((void (*)(void))(stack_addr + 0x40000000)) ();
+		break;
+	case 5:
+		{
+			static const uint32_t my_undef = 0xffffffff;
+			((void (*)(void))(uintptr_t) &my_undef) ();
+		}
+		break;
+	default:
+		break;
+	}
+
+	return TEE_SUCCESS;
+}