summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Gaignard <benjamin.gaignard@linaro.org>2015-05-27 10:00:47 +0200
committerBenjamin Gaignard <benjamin.gaignard@linaro.org>2015-05-27 10:00:47 +0200
commit89fb0ba2933a433df907c90d2af7470c86e76d63 (patch)
tree978a256d37d889249b83593bcb08c2f7a48a101b
downloadoptee-sdp-89fb0ba2933a433df907c90d2af7470c86e76d63.tar.gz
Initial commit
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
-rw-r--r--Makefile15
-rw-r--r--faked_armv7_uta_signed_header.binbin0 -> 336 bytes
-rw-r--r--platform/stub.c248
-rw-r--r--sdp_platform_api.h139
-rw-r--r--sdp_ta.c201
-rw-r--r--sub.mk2
-rw-r--r--ta_sdp.h50
-rw-r--r--user_ta_header_defines.h17
8 files changed, 672 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..e5e161d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,15 @@
+CFG_TEE_TA_LOG_LEVEL ?= 2
+CPPFLAGS += -DCFG_TEE_TA_LOG_LEVEL=$(CFG_TEE_TA_LOG_LEVEL)
+BINARY=b9aa5f00-d229-11e4-925c0002a5d5c51b
+
+include $(TA_DEV_KIT_DIR)/mk/ta_dev_kit.mk
+
+all: $(BINARY).ta
+
+$(BINARY).ta: $(BINARY).bin
+ rm -f $@
+ cat faked_armv7_uta_signed_header.bin $< > $@
+
+clean:
+ rm -f $(BINARY).*
+ rm -f *.o
diff --git a/faked_armv7_uta_signed_header.bin b/faked_armv7_uta_signed_header.bin
new file mode 100644
index 0000000..7d5d2ad
--- /dev/null
+++ b/faked_armv7_uta_signed_header.bin
Binary files differ
diff --git a/platform/stub.c b/platform/stub.c
new file mode 100644
index 0000000..e2cb206
--- /dev/null
+++ b/platform/stub.c
@@ -0,0 +1,248 @@
+/*
+ * stub.c
+ *
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "../sdp_platform_api.h"
+#include "string_ext.h"
+
+#define ARRAY_SIZE(x) (int)(sizeof(x) / sizeof(*(x)))
+
+struct secure_device {
+ const char name[MAX_NAME_SIZE];
+ uint32_t id;
+ void (*inc_refcount)(void);
+ void (*dec_refcount)(void);
+};
+
+static int delta_refcount;
+static int bdisp_refcount;
+static int sti_refcount;
+
+static void delta_inc_refcount(void)
+{
+ delta_refcount++;
+}
+
+static void delta_dec_refcount(void)
+{
+ delta_refcount--;
+}
+
+static void bdisp_inc_refcount(void)
+{
+ bdisp_refcount++;
+}
+
+static void bdisp_dec_refcount(void)
+{
+ bdisp_refcount--;
+}
+
+static void sti_inc_refcount(void)
+{
+ sti_refcount++;
+}
+
+static void sti_dec_refcount(void)
+{
+ sti_refcount--;
+}
+
+struct secure_device stm_devices[] = {
+ { "delta" , DECODER | VIDEO, &delta_inc_refcount, &delta_dec_refcount },
+ { "bdisp" , TRANSFORMER | VIDEO, &bdisp_inc_refcount, &bdisp_dec_refcount },
+ { "sti" , SINK | VIDEO, &sti_inc_refcount, &sti_dec_refcount },
+};
+
+struct region {
+ uint64_t addr;
+ uint32_t size;
+ uint32_t writer;
+ uint32_t attached[3];
+ uint32_t direction[3];
+};
+
+#define MAX_REGIONS 20
+static struct region regions[MAX_REGIONS];
+
+static int find_free_region(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_REGIONS; i++)
+ if (regions[i].addr == 0)
+ return i;
+
+ return -1;
+}
+
+int platform_init(void)
+{
+ delta_refcount = 0;
+ bdisp_refcount = 0;
+ sti_refcount = 0;
+
+ memset(&regions, 0, sizeof(regions));
+
+ return 0;
+}
+
+int platform_create_region(uint64_t addr, uint32_t size)
+{
+ int index = find_free_region();
+
+ if (index < 0)
+ return index;
+
+ regions[index].addr = addr;
+ regions[index].size = size;
+
+ return index;
+}
+
+int platform_destroy_region(int index)
+{
+ if(index > MAX_REGIONS)
+ return -1;
+
+ memset(&regions[index], 0, sizeof(regions[index]));
+
+ return 0;
+}
+
+struct region* platform_find_region_by_id(int index)
+{
+ if(index > MAX_REGIONS)
+ return NULL;
+
+ return &regions[index];
+}
+
+struct secure_device* platform_find_device_by_name(char *name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(stm_devices); i++) {
+ if (!strcmp(stm_devices[i].name, name))
+ return &stm_devices[i];
+ }
+
+ return NULL;
+}
+
+/* return 0 if we can add the device to the region */
+int platform_check_permissions(struct region *region, struct secure_device* device, int dir)
+{
+ if ((region->writer == 0) && (dir == DIR_WRITE))
+ return 0;
+
+ if ((region->writer == device->id) && (dir == DIR_WRITE))
+ return 0;
+
+ if (IS_DECODER(region->writer) && (dir == DIR_READ) && IS_TRANSFORMER(device->id))
+ if (STREAM_TYPE(region->writer) == STREAM_TYPE(device->id))
+ return 0;
+
+ if (IS_DECODER(region->writer) && (dir == DIR_READ) && IS_SINK(device->id))
+ if (STREAM_TYPE(region->writer) == STREAM_TYPE(device->id))
+ return 0;
+
+ if (IS_TRANSFORMER(region->writer) && (dir == DIR_READ) && IS_SINK(device->id))
+ if (STREAM_TYPE(region->writer) == STREAM_TYPE(device->id))
+ return 0;
+
+ return 1;
+}
+
+int platform_add_device_to_region(struct region *region, struct secure_device* device, int dir)
+{
+ int i;
+
+ if (dir == DIR_WRITE) {
+ region->writer = device->id;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(stm_devices); i++) {
+ if (region->attached[i] == 0 || region->attached[i] == device->id) {
+ region->attached[i] = device->id;
+ region->direction[i] = dir;
+ goto inc_dev;
+ }
+ }
+
+ return 1;
+
+inc_dev:
+ device->inc_refcount();
+
+ return 0;
+}
+
+int platform_remove_device_from_region(struct region *region, struct secure_device* device)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(stm_devices); i++) {
+ if (region->attached[i] == device->id) {
+ region->attached[i] = 0;
+ region->direction[i] = 0;
+ goto dec_dev;
+ }
+ }
+
+ return 1;
+
+dec_dev:
+ device->dec_refcount();
+ return 0;
+}
+
+int platform_dump_status(char *dump, int size)
+{
+ int i, j, writed;
+ char *tmp = dump;
+
+ writed = snprintf(tmp, size, "SDP STUB platform\n");
+ tmp += writed;
+ size -= writed;
+
+ for (i = 0; i < ARRAY_SIZE(stm_devices); i++) {
+ writed = snprintf(tmp, size ,"device name %s id 0x%x\n", stm_devices[i].name, stm_devices[i].id);
+ tmp += writed;
+ size -= writed;
+ }
+
+ writed = snprintf(tmp, size, "delta (decoder) refcount %d\n", delta_refcount);
+ tmp += writed;
+ size -= writed;
+
+ writed = snprintf(tmp, size, "bdisp (transform) refcount %d\n", bdisp_refcount);
+ tmp += writed;
+ size -= writed;
+
+ writed = snprintf(tmp, size, "sti (display) refcount %d\n", sti_refcount);
+ tmp += writed;
+ size -= writed;
+
+ for (i = 0; i < MAX_REGIONS; i++) {
+ if (regions[i].addr) {
+ struct region *region = &regions[i];
+ writed = snprintf(tmp, size, "region addr 0x%x size %d writer 0x%x\n", (uint32_t)region->addr, region->size, region->writer);
+ tmp += writed;
+ size -= writed;
+
+ for (j = 0; j < ARRAY_SIZE(stm_devices); j++)
+ if (region->attached[j]) {
+ writed = snprintf(tmp, size, "attached 0x%x direction %d\n", region->attached[j], region->direction[j]);
+ tmp += writed;
+ size -= writed;
+ }
+ }
+
+ }
+ return 0;
+}
diff --git a/sdp_platform_api.h b/sdp_platform_api.h
new file mode 100644
index 0000000..7bdd8df
--- /dev/null
+++ b/sdp_platform_api.h
@@ -0,0 +1,139 @@
+/*
+ * sdp_platform_api.h
+ *
+ */
+#ifndef _SDP_PLATFORM_API_H_
+#define _SDP_PLATFORM_API_H_
+
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+
+/* those definitions need to be aligned
+ * with enum dma_data_direction definitions */
+#define DIR_RW 0
+#define DIR_READ 1
+#define DIR_WRITE 2
+
+#define MAX_NAME_SIZE 64
+
+/* define some typical type of device */
+#define DECRYPTER (1 << 24)
+#define PARSER (2 << 24)
+#define DECODER (3 << 24)
+#define TRANSFORMER (4 << 24)
+#define SINK (5 << 24)
+
+/* streams type */
+#define VIDEO (1 << 16)
+#define AUDIO (2 << 16)
+
+/* helpers */
+#define IS_DECRYPTER(x) ((x & 0xFF000000) == DECRYPTER)
+#define IS_PARSER(x) ((x & 0xFF000000) == PARSER)
+#define IS_DECODER(x) ((x & 0xFF000000) == DECODER)
+#define IS_TRANSFORMER(x) ((x & 0xFF000000) == TRANSFORMER)
+#define IS_SINK(x) ((x & 0xFF000000) == SINK)
+
+#define IS_VIDEO(x) ((x & 0x00FF0000) == VIDEO)
+#define IS_AUDIO(x) ((x & 0x00FF0000) == AUDIO)
+#define STREAM_TYPE(x) (x & 0x00FF0000)
+
+/**
+ * struct secure_device - opaque structure where each
+ * platform can implement it own services
+ */
+struct secure_device;
+
+/**
+ * struct region - opaque structure to be customize
+ * by each platform to macth with hardware requirement
+ */
+struct region;
+
+/* prototypes of platform specific functions which need
+ * to be implemented by the platform */
+
+/**
+ * platform_init - call when the instance of TA is created
+ */
+int platform_init(void);
+
+/**
+ * platform_create_region - request the creation of a region
+ *
+ * @addr: start address of the memory
+ * @size: lenght of the memory
+ *
+ * if success return a (unique) region identifier
+ * else return a negative value
+ */
+int platform_create_region(uint64_t addr, uint32_t size);
+
+/**
+ * platform_destroy_region - destroy a specific region
+ *
+ * @id: the region identifier to be destroy
+ *
+ * return 0 if success
+ */
+int platform_destroy_region(int id);
+
+/**
+ * platform_find_region_by_id - find a region by using it identifier
+ * identifier should have been provide by platform_create_region()
+ *
+ * @id: the region identifier to be find
+ *
+ * return a struct region * if the region has been found
+ * else return NULL
+ */
+struct region *platform_find_region_by_id(int id);
+
+/**
+ * platform_find_device_by_name - find a device by using it name
+ *
+ * @name: the name of the device (device->driver->name)
+ *
+ * return a struct secure_device * if the device has been found
+ * else return NULL
+ */
+struct secure_device *platform_find_device_by_name(char *name);
+
+/**
+ * platform_check_permissions - check if the given device can have access
+ * to a specific region
+ *
+ * @region: targeted region
+ * @device: the device requesting the access
+ * @dir: access direction (read and/or write)
+ */
+int platform_check_permissions(struct region *region, struct secure_device* device, int dir);
+
+/**
+ * platform_add_device_to_region - add device access to a region
+ * call after platform_check_permissions() to set access to specific region
+ * for the device
+ *
+ * @region: targeted region
+ * @device: the device requesting the access
+ * @dir: access direction (read and/or write)
+ */
+int platform_add_device_to_region(struct region *region, struct secure_device* device, int dir);
+
+/**
+ * platform_remove_device_from_region - remove a device from a region
+ *
+ * @region: targeted region
+ * @device: the device to be remove
+ */
+int platform_remove_device_from_region(struct region *region, struct secure_device* device);
+
+/**
+ * platform_dump_status - request to platform code to write a status
+ *
+ * @dump: string to be filled by platform code
+ * @size: size of the buffer
+ */
+int platform_dump_status(char *dump, int size);
+
+#endif
diff --git a/sdp_ta.c b/sdp_ta.c
new file mode 100644
index 0000000..87bb105
--- /dev/null
+++ b/sdp_ta.c
@@ -0,0 +1,201 @@
+/*
+ * sdp_ta.c
+ *
+ */
+
+#define STR_TRACE_USER_TA "SDP"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
+
+#include "ta_sdp.h"
+#include "sdp_platform_api.h"
+#include "string_ext.h"
+
+/*
+ * Called when the instance of the TA is created. This is the first call in
+ * the TA.
+ */
+TEE_Result TA_CreateEntryPoint(void)
+{
+ platform_init();
+ return TEE_SUCCESS;
+}
+
+/*
+ * Called when the instance of the TA is destroyed if the TA has not
+ * crashed or panicked. This is the last call in the TA.
+ */
+void TA_DestroyEntryPoint(void)
+{
+}
+
+/*
+ * Called when a new session is opened to the TA. *sess_ctx can be updated
+ * with a value to be able to identify this session in subsequent calls to the
+ * TA.
+ */
+TEE_Result TA_OpenSessionEntryPoint(uint32_t param_types,
+ TEE_Param params[4], void **sess_ctx)
+{
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+
+ if (param_types != exp_param_types)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ /* Unused parameters */
+ (void)&params;
+ (void)&sess_ctx;
+
+ /* If return value != TEE_SUCCESS the session will not be created. */
+ return TEE_SUCCESS;
+}
+
+/*
+ * Called when a session is closed, sess_ctx hold the value that was
+ * assigned by TA_OpenSessionEntryPoint().
+ */
+void TA_CloseSessionEntryPoint(void *sess_ctx)
+{
+ (void)&sess_ctx; /* Unused parameter */
+ IMSG("Goodbye SDP\n");
+}
+
+static TEE_Result create_region(uint32_t param_types, TEE_Param params[4])
+{
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_VALUE_OUTPUT,
+ TEE_PARAM_TYPE_NONE);
+ uint64_t addr;
+ int index;
+
+ if (param_types != exp_param_types) {
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ addr = params[0].value.b;
+
+ index = platform_create_region(addr, params[1].value.a);
+ if (index < 0)
+ return TEE_ERROR_BAD_PARAMETERS;
+
+ params[2].value.a = index;
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result destroy_region(uint32_t param_types, TEE_Param params[4])
+{
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+ uint32_t id;
+
+ if (param_types != exp_param_types) {
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ id = params[0].value.a;
+ platform_destroy_region(id);
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result update_region(uint32_t param_types, TEE_Param params[4])
+{
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_MEMREF_INPUT,
+ TEE_PARAM_TYPE_VALUE_INPUT,
+ TEE_PARAM_TYPE_NONE);
+ uint32_t region_id;
+ bool add;
+ int dir;
+ char *name;
+ struct secure_device *device;
+ struct region *region;
+
+ if (param_types != exp_param_types) {
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ region_id = params[0].value.a;
+ add = params[0].value.b;
+
+ name = params[1].memref.buffer;
+
+ dir = params[2].value.a;
+
+ device = platform_find_device_by_name(name);
+ if (device == 0) {
+ IMSG("Can't find device %s\n", name);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ region = platform_find_region_by_id(region_id);
+ if (region == NULL) {
+ IMSG("Can't find region id %d\n", region_id);
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ if (add) {
+ if (platform_check_permissions(region, device, dir)) {
+ IMSG("check permissions failed\n");
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ platform_add_device_to_region(region, device, dir);
+ } else {
+ platform_remove_device_from_region(region, device);
+ }
+
+ return TEE_SUCCESS;
+}
+
+static TEE_Result dump_status(uint32_t param_types, TEE_Param params[4])
+{
+ uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE,
+ TEE_PARAM_TYPE_NONE);
+ if (param_types != exp_param_types) {
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+
+ platform_dump_status(params[0].memref.buffer, params[0].memref.size);
+
+ return TEE_SUCCESS;
+}
+
+/*
+ * Called when a TA is invoked. sess_ctx hold that value that was
+ * assigned by TA_OpenSessionEntryPoint(). The rest of the paramters
+ * comes from normal world.
+ */
+TEE_Result TA_InvokeCommandEntryPoint(void *sess_ctx, uint32_t cmd_id,
+ uint32_t param_types, TEE_Param params[4])
+{
+ (void)&sess_ctx; /* Unused parameter */
+
+
+ switch (cmd_id) {
+ case TA_SDP_CREATE_REGION:
+ return create_region(param_types, params);
+ case TA_SDP_DESTROY_REGION:
+ return destroy_region(param_types, params);
+ case TA_SDP_UPDATE_REGION:
+ return update_region(param_types, params);
+ case TA_SDP_DUMP_STATUS:
+ return dump_status(param_types, params);
+ default:
+ return TEE_ERROR_BAD_PARAMETERS;
+ }
+}
diff --git a/sub.mk b/sub.mk
new file mode 100644
index 0000000..e283df2
--- /dev/null
+++ b/sub.mk
@@ -0,0 +1,2 @@
+srcs-y += sdp_ta.c
+srcs-y += platform/stub.c
diff --git a/ta_sdp.h b/ta_sdp.h
new file mode 100644
index 0000000..dc319e4
--- /dev/null
+++ b/ta_sdp.h
@@ -0,0 +1,50 @@
+#ifndef TA_SDP_H
+#define TA_SDP_H
+
+/* This UUID is generated with uuidgen
+ the ITU-T UUID generator at http://www.itu.int/ITU-T/asn1/uuid.html */
+#define TA_SDP_UUID { 0xb9aa5f00, 0xd229, 0x11e4, \
+ { 0x92, 0x5c, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b} }
+
+/**
+ * TA_SDP_CREATE_REGION have 3 parameters:
+ * - TEE_PARAM_TYPE_VALUE_INPUT
+ * param[0].value.a: memory region address MSB (to be tested for 64bits)
+ * param[0].value.b: memory region address LSB
+ * - TEE_PARAM_TYPE_VALUE_INPUT
+ * param[1].value.a: size of the memory region
+ * - TEE_PARAM_TYPE_VALUE_OUTPUT
+ * param[2].value.a: region identifier
+ */
+#define TA_SDP_CREATE_REGION 0
+
+/**
+ * TA_SDP_DESTROY_REGION have 1 parameter:
+ * - TEE_PARAM_TYPE_VALUE_INPUT
+ * param[0].value.a: region identifier
+ */
+#define TA_SDP_DESTROY_REGION 1
+
+/*
+ * TA_SDP_UPDATE_REGION have 3 parameters
+ * - TEE_PARAM_TYPE_VALUE_INPUT
+ * param[0].value.a: region identifier
+ * param[0].value.b: inditicated if the permissions have to be added or
+ * removed to the memory region
+ * - TEE_PARAM_TYPE_MEMREF_INPUT
+ * params[1].memref.buffer: the device name
+ * params[1].memref.size: lenght of the string
+ * - TEE_PARAM_TYPE_VALUE_INPUT
+ * params[2].value.a: access request direction (read/write)
+ */
+#define TA_SDP_UPDATE_REGION 2
+
+/*
+ * TA_SDP_DUMP_STATUS have 1 parameter
+ * - TEE_PARAM_TYPE_MEMREF_OUTPUT
+ * params[0].memref.buffer: status string
+ * params[0].memref.size: lenght of the string
+ */
+#define TA_SDP_DUMP_STATUS 3
+
+#endif /*TA_SDP_H*/
diff --git a/user_ta_header_defines.h b/user_ta_header_defines.h
new file mode 100644
index 0000000..edc5ffe
--- /dev/null
+++ b/user_ta_header_defines.h
@@ -0,0 +1,17 @@
+#ifndef USER_TA_HEADER_DEFINES_H
+#define USER_TA_HEADER_DEFINES_H
+
+#include <ta_sdp.h> /* To get the TA_SDP_UUID define */
+
+#define TA_UUID TA_SDP_UUID
+
+#define TA_FLAGS (TA_FLAG_MULTI_SESSION | TA_FLAG_EXEC_DDR)
+#define TA_STACK_SIZE (2 * 1024)
+#define TA_DATA_SIZE (32 * 1024)
+
+#define TA_CURRENT_TA_EXT_PROPERTIES \
+ { "gp.ta.description", USER_TA_PROP_TYPE_STRING, \
+ "Secure Data Path TA" }, \
+ { "gp.ta.version", USER_TA_PROP_TYPE_U32, &(const uint32_t){ 0x0010 } }
+
+#endif /*USER_TA_HEADER_DEFINES_H*/