Add platform specific TRNG driver

Adds platform specific TRNG driver to Crypto opteesp deployment.
Fetches and builds the TZ-TRNG driver from its external
repo and includes it when the crypto/opteesp is built for
the arm/fvp/fvp_base_revc-2xaemv8a platform.  Device region
information provided as external configuration data is
not yet integrated to the TRNG hardware is not yet used.

Signed-off-by: Julian Hall <julian.hall@arm.com>
Change-Id: I8a2946643a279dfcc3aff608427c85e674f0e084
diff --git a/platform/drivers/arm/tztrng/driver.cmake b/platform/drivers/arm/tztrng/driver.cmake
new file mode 100644
index 0000000..58d98c8
--- /dev/null
+++ b/platform/drivers/arm/tztrng/driver.cmake
@@ -0,0 +1,68 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+# Driver source location and version
+set(ARM_TZTRNG_URL "https://github.com/ARM-software/TZ-TRNG.git" CACHE STRING "Arm TZ-TRNG driver repository URL")
+set(ARM_TZTRNG_REFSPEC "1.0.0" CACHE STRING "Arm TZ-TRNG driver git refspec")
+
+# Fetch driver source code from remote repository
+include(FetchContent)
+
+FetchContent_Declare(
+	arm-tztrng
+	GIT_REPOSITORY ${ARM_TZTRNG_URL}
+	GIT_TAG ${ARM_TZTRNG_REFSPEC}
+	GIT_SHALLOW TRUE
+)
+
+# FetchContent_GetProperties exports arm-tztrng_SOURCE_DIR and arm-tztrng_BINARY_DIR variables
+FetchContent_GetProperties(arm-tztrng)
+if(NOT arm-tztrng_POPULATED)
+	message(STATUS "Fetching arm-tztrng")
+	FetchContent_Populate(arm-tztrng)
+endif()
+
+# The driver has no cmake build support so it is necessary to bridge cmake variables to
+# driver build parameters.
+
+# Determine ARCH parameter
+if (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm")
+	set(_arm-tztrng_ARCH "arm64")
+	set(_arm-tztrng_builddir "build-aarch64-linux-gnu")
+else()
+	message(FATAL_ERROR "Only arm builds of TZ-TRNG supported.")
+endif()
+
+# Determine the full path for the generated library and public header
+set(_arm-tztrng_genlib "${arm-tztrng_SOURCE_DIR}/host/src/tztrng_lib/${_arm-tztrng_builddir}/libcc_tztrng.a")
+set(_arm-tztrng_host_incpath "${arm-tztrng_SOURCE_DIR}/host/src/tztrng_lib/include")
+set(_arm-tztrng_shared_incpath "${arm-tztrng_SOURCE_DIR}/shared/hw/include")
+
+# Set HOST_PROJ_ROOT parameter to use TS provided build defines
+set(_arm-tztrng_HOST_PROJ_ROOT ${CMAKE_CURRENT_LIST_DIR})
+
+# Add custom command to build the driver library using the TZ-TRNG provided makefile
+add_custom_command(
+	OUTPUT ${_arm-tztrng_genlib}
+	COMMAND make ARGS "ARCH=${_arm-tztrng_ARCH}"
+	WORKING_DIRECTORY "${arm-tztrng_SOURCE_DIR}/host/src/tztrng_lib/"
+)
+
+# Define target for the library
+add_custom_target(
+	libcc_tztrng
+	DEPENDS ${_arm-tztrng_genlib}
+)
+
+# Add generated library to build target
+target_include_directories(${TGT} PRIVATE "${_arm-tztrng_host_incpath}")
+target_include_directories(${TGT} PRIVATE "${_arm-tztrng_shared_incpath}")
+target_link_libraries(${TGT} PRIVATE ${_arm-tztrng_genlib})
+add_dependencies(${TGT} libcc_tztrng)
+
+# Add adapter to map platform trng interface to tz-trng driver
+target_sources(${TGT} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/tztrng_trng.c")
diff --git a/platform/drivers/arm/tztrng/tztrng_trng.c b/platform/drivers/arm/tztrng/tztrng_trng.c
new file mode 100644
index 0000000..f52eeaa
--- /dev/null
+++ b/platform/drivers/arm/tztrng/tztrng_trng.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <platform/interface/trng.h>
+#include <platform/interface/device_region.h>
+#include <tztrng.h>
+#include <tztrng_defs.h>
+#include <stdlib.h>
+#include <limits.h>
+
+/*
+ * A platform trng driver that uses the tz-trng driver to provide a
+ * hardware entropy source.
+ */
+struct tztrng_instance
+{
+    struct device_region trng_device_region;
+};
+
+
+static int trng_poll(void *context, unsigned char *output, size_t nbyte, size_t *len)
+{
+    struct tztrng_instance *this_instance = (struct tztrng_instance*)context;
+    int status = 0;
+
+    *len = 0;
+
+    if (nbyte >= sizeof(unsigned char)) {
+
+        if (this_instance) {
+
+            status = CC_TrngGetSource((unsigned long)this_instance->trng_device_region.base_addr,
+                            output, len, nbyte * CHAR_BIT);
+        }
+        else {
+            /* No context for TRNG instance */
+            /*   status = LLF_RND_STATE_PTR_INVALID_ERROR;  @todo mbedcrypto segfaults when an error is returned */
+            *len = sizeof(unsigned char);
+        }
+    }
+
+    return status;
+}
+
+int platform_trng_create(struct platform_trng_driver *driver,
+                            const struct device_region *device_region)
+{
+    static const struct platform_trng_iface iface =  { .poll = trng_poll };
+
+    /*
+     * Default to leaving the driver in a safe but inoperable state.
+     */
+    driver->iface = &iface;
+    driver->context = NULL;
+
+    if (device_region) {
+
+        /*
+         * A device region has been provided, possibly from an external configuation.
+         * Check that it's a sensible size to defend against a bogus configuration.
+         */
+        struct tztrng_instance *new_instance = malloc(sizeof(struct tztrng_instance));
+
+        if (new_instance) {
+
+            new_instance->trng_device_region = *device_region;
+            driver->context = new_instance;
+        }
+    }
+
+    return 0;
+}
+
+void platform_trng_destroy(struct platform_trng_driver *driver)
+{
+    free(driver->context);
+}