summaryrefslogtreecommitdiff
path: root/arch/arm/mach-ux500/tee_ux500.c
blob: ab3782a323c7949b43a0139fa721bbfad66c65ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/*
 * TEE service to handle the calls to trusted applications.
 *
 * Copyright (C) ST-Ericsson SA 2010
 * Author: Joakim Bech <joakim.xx.bech@stericsson.com>
 * License terms: GNU General Public License (GPL) version 2
 */
#include <linux/kernel.h>
#include <linux/tee.h>
#include <linux/io.h>

#include <mach/hardware.h>

#define BOOT_BRIDGE_FUNC (U8500_BOOT_ROM_BASE + 0x18300)

#define ISSWAPI_EXECUTE_TA 0x11000001
#define ISSWAPI_CLOSE_TA   0x11000002

#define SEC_ROM_NO_FLAG_MASK    0x0000

static u32 call_sec_rom_bridge(u32 service_id, u32 cfg, ...)
{
	typedef u32 (*bridge_func)(u32, u32, va_list);
	static bridge_func hw_sec_rom_pub_bridge;
	va_list ap;
	u32 ret;

	hw_sec_rom_pub_bridge =
		(bridge_func)((u32)IO_ADDRESS(BOOT_BRIDGE_FUNC));

	va_start(ap, cfg);
	ret = hw_sec_rom_pub_bridge(service_id, cfg, ap);
	va_end(ap);

	return ret;
}

int call_sec_world(struct tee_session *ts, int sec_cmd)
{
	/*
	 * ts->ta and ts->uuid is set to NULL when opening the device,
	 * hence it should be safe to just do the call here.
	 */

	switch (sec_cmd) {
	case TEED_INVOKE:
	if (!ts->uuid) {
		call_sec_rom_bridge(ISSWAPI_EXECUTE_TA,
				SEC_ROM_NO_FLAG_MASK,
				virt_to_phys(&ts->id),
				NULL,
				virt_to_phys(ts->ta),
				ts->cmd,
				virt_to_phys((void *)(ts->op)),
				virt_to_phys((void *)(&ts->origin)));
	} else {
		call_sec_rom_bridge(ISSWAPI_EXECUTE_TA,
				SEC_ROM_NO_FLAG_MASK,
				virt_to_phys(&ts->id),
				virt_to_phys(ts->uuid),
				virt_to_phys(ts->ta),
				ts->cmd,
				virt_to_phys((void *)(ts->op)),
				virt_to_phys((void *)(&ts->origin)));
	}
	break;

	case TEED_CLOSE_SESSION:
		call_sec_rom_bridge(ISSWAPI_CLOSE_TA,
				SEC_ROM_NO_FLAG_MASK,
				ts->id,
				NULL,
				virt_to_phys(ts->ta),
				virt_to_phys((void *)(&ts->origin)));
	break;
	}

	return 0;
}