Add regression 1022 to test dlopen()/dlsym()/dlclose()

Adds a new test case for the dynamic link API in libdl.
- A new shared library is added in ta/os_test_lib_dl.
- In xtest 1022, the dl API is used to load the test library and
  retrieve pointers to functions.

Signed-off-by: Jerome Forissier <jerome.forissier@linaro.org>
Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
diff --git a/ta/os_test/Makefile b/ta/os_test/Makefile
index 0f2e8ff..a3d66bf 100644
--- a/ta/os_test/Makefile
+++ b/ta/os_test/Makefile
@@ -10,4 +10,6 @@
 LDADD = -L$(subst os_test,os_test_lib,$(abspath $(link-out-dir))) -los_test
 endif
 
+LDADD += -ldl
+
 include ../ta_common.mk
diff --git a/ta/os_test/include/os_test.h b/ta/os_test/include/os_test.h
index 57f8470..708d80f 100644
--- a/ta/os_test/include/os_test.h
+++ b/ta/os_test/include/os_test.h
@@ -44,5 +44,7 @@
 TEE_Result ta_entry_params(uint32_t param_types, TEE_Param params[4]);
 TEE_Result ta_entry_call_lib(uint32_t param_types, TEE_Param params[4]);
 TEE_Result ta_entry_call_lib_panic(uint32_t param_types, TEE_Param params[4]);
+TEE_Result ta_entry_call_lib_dl(uint32_t param_types, TEE_Param params[4]);
+TEE_Result ta_entry_call_lib_dl_panic(uint32_t param_types, TEE_Param params[4]);
 
 #endif /*OS_TEST_H */
diff --git a/ta/os_test/include/ta_os_test.h b/ta/os_test/include/ta_os_test.h
index 4292823..6a15128 100644
--- a/ta/os_test/include/ta_os_test.h
+++ b/ta/os_test/include/ta_os_test.h
@@ -46,5 +46,7 @@
 #define TA_OS_TEST_CMD_PARAMS               13
 #define TA_OS_TEST_CMD_CALL_LIB             14
 #define TA_OS_TEST_CMD_CALL_LIB_PANIC       15
+#define TA_OS_TEST_CMD_CALL_LIB_DL          16
+#define TA_OS_TEST_CMD_CALL_LIB_DL_PANIC    17
 
 #endif /*TA_OS_TEST_H */
diff --git a/ta/os_test/os_test.c b/ta/os_test/os_test.c
index feca6b4..84c850b 100644
--- a/ta/os_test/os_test.c
+++ b/ta/os_test/os_test.c
@@ -25,6 +25,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <compiler.h>
+#include <dlfcn.h>
 #include <setjmp.h>
 #include <stdint.h>
 #include <string.h>
@@ -1086,3 +1087,75 @@
 
 	return TEE_ERROR_GENERIC;
 }
+
+TEE_Result ta_entry_call_lib_dl(uint32_t param_types __maybe_unused,
+				TEE_Param params[4] __unused)
+{
+	int (*add_func)(int a, int b) = NULL;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	void *handle = NULL;
+	void *hnull = NULL;
+
+	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
+					   TEE_PARAM_TYPE_NONE,
+					   TEE_PARAM_TYPE_NONE,
+					   TEE_PARAM_TYPE_NONE))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	handle = dlopen("b3091a65-9751-4784-abf7-0298a7cc35ba",
+			RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
+	if (!handle)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	add_func = dlsym(handle, "os_test_shlib_dl_add");
+	if (!add_func)
+		goto err;
+	if (add_func(3, 4) != 7)
+		goto err;
+
+	hnull = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
+	if (!hnull) {
+		res = TEE_ERROR_OUT_OF_MEMORY;
+		goto err;
+	}
+
+	add_func = dlsym(hnull, "os_test_shlib_dl_add");
+	if (!add_func)
+		goto err;
+	if (add_func(5, 6) != 11)
+		goto err;
+
+	res = TEE_SUCCESS;
+	dlclose(hnull);
+err:
+	dlclose(handle);
+	return res;
+}
+
+TEE_Result ta_entry_call_lib_dl_panic(uint32_t param_types __maybe_unused,
+				      TEE_Param params[4] __unused)
+{
+	int (*panic_func)(void) = NULL;
+	void *handle = NULL;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
+					   TEE_PARAM_TYPE_NONE,
+					   TEE_PARAM_TYPE_NONE,
+					   TEE_PARAM_TYPE_NONE))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	handle = dlopen("b3091a65-9751-4784-abf7-0298a7cc35ba",
+			RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE);
+	if (!handle)
+		return res;
+
+	panic_func = dlsym(handle, "os_test_shlib_dl_panic");
+	if (!panic_func)
+		goto err;
+	panic_func();
+	return TEE_ERROR_GENERIC;
+err:
+	dlclose(handle);
+	return res;
+}
diff --git a/ta/os_test/ta_entry.c b/ta/os_test/ta_entry.c
index e35e75a..52c378e 100644
--- a/ta/os_test/ta_entry.c
+++ b/ta/os_test/ta_entry.c
@@ -115,6 +115,12 @@
 	case TA_OS_TEST_CMD_CALL_LIB_PANIC:
 		return ta_entry_call_lib_panic(nParamTypes, pParams);
 
+	case TA_OS_TEST_CMD_CALL_LIB_DL:
+		return ta_entry_call_lib_dl(nParamTypes, pParams);
+
+	case TA_OS_TEST_CMD_CALL_LIB_DL_PANIC:
+		return ta_entry_call_lib_dl_panic(nParamTypes, pParams);
+
 	default:
 		return TEE_ERROR_BAD_PARAMETERS;
 	}