aboutsummaryrefslogtreecommitdiff
path: root/drivers/misc/mediatek/masp/asfv2/mach/hacc_tee_req.c
blob: 5144cb7d36fa686985cb9e41040cd78bf14386b4 (plain) (blame)
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/mm.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/vmalloc.h>

#include <linux/types.h>
#include "mobicore_driver_api.h"
#include "tlcApisec.h"
#include "sec_error.h"
#include "hacc_tee.h"

static const struct mc_uuid_t MC_UUID_HACC = { {
						0x05, 0x11, 0x00, 0x00,
						0x00, 0x00, 0x00, 0x00,
						0x00, 0x00, 0x00, 0x00,
						0x00, 0x00, 0x00, 0x00}
};

uint32_t deviceId = MC_DEVICE_ID_DEFAULT;
struct mc_session_handle drSessionHandle;
static dapc_tciMessage_t *pTci;
/* static int open_count = 0; */

/* DO NOT invoke this function unless you get HACC lock */
int open_sdriver_connection(void)
{
	enum mc_result mcRet = 0;
	int retryCnt = 0;

	do {
		/* Initialize session handle data */
		mcRet = mc_open_device(deviceId);
		if (MC_DRV_OK != mcRet) {
			retryCnt++;
			pr_debug("NWD HACC: mc_open_device failed: %d, retry count (%d)\n", mcRet,
				 retryCnt);
			continue;
		}
		pr_debug("NWD HACC: mc_open_device success: %d\n", mcRet);

		/* Allocating WSM for DCI */
		mcRet =
		    mc_malloc_wsm(deviceId, 0, sizeof(dapc_tciMessage_t), (uint8_t **) &pTci, 0);
		if (MC_DRV_OK != mcRet) {
			pr_debug("NWD HACC: mc_malloc_wsm failed: %d\n", mcRet);
			break;
		}

		/* Open session to the trustlet */
		memset(&drSessionHandle, 0, sizeof(drSessionHandle));
		drSessionHandle.device_id = deviceId;
		mcRet =
		    mc_open_session(&drSessionHandle, &MC_UUID_HACC, (uint8_t *) pTci,
				    (uint32_t) sizeof(dapc_tciMessage_t));

		if (MC_DRV_OK != mcRet) {
			pr_debug("NWD HACC: mc_open_session failed: %d\n", mcRet);
			break;
		}

		pr_debug("NWD HACC: mc_open_session success: %d\n", mcRet);
		break;
	} while (retryCnt < 30);

	if (MC_DRV_OK != mcRet)
		return -1;

	return 0;
}

/* DO NOT invoke this function unless you get HACC lock */
int close_sdriver_connection(void)
{
	enum mc_result mcRet = 0;

	do {
		/* Close session */
		mcRet = mc_close_session(&drSessionHandle);
		if (MC_DRV_OK != mcRet) {
			pr_debug("NWD HACC: mc_close_session failed: %d\n", mcRet);
			break;
		}
		pr_debug("NWD HACC: mc_close_session success: %d\n", mcRet);
		memset(&drSessionHandle, 0, sizeof(drSessionHandle));

		/* Free WSM for DCI */
		mcRet = mc_free_wsm(deviceId, (uint8_t *) pTci);
		if (MC_DRV_OK != mcRet) {
			pr_debug("NWD HACC: mc_free_wsm failed: %d\n", mcRet);
			break;
		}
		pTci = NULL;

		/* Close MobiCore device */
		mcRet = mc_close_device(deviceId);
		if (MC_DRV_OK != mcRet) {
			pr_debug("NWD HACC: mc_close_device failed: %d\n", mcRet);
			break;
		}
		pr_debug("NWD HACC: mc_close_device success: %d\n", mcRet);
	} while (false);

	if (MC_DRV_OK != mcRet)
		return -1;

	return 0;
}


/* DO NOT invoke this function unless you get HACC lock */
int tee_secure_request(unsigned int user, unsigned char *data, unsigned int data_size,
		       unsigned int direction, unsigned char *seed, unsigned int seed_size)
{
	int ret = SEC_OK;
	struct mc_bulk_map dataMapInfo;
	struct mc_bulk_map seedMapInfo;
	char *databuf = NULL;
	char *seedbuf = NULL;
	enum mc_result mcRet = 0;

	/* allocate data buffer to be sent to TEE */
	databuf = vmalloc(data_size);
	if (databuf == NULL) {
		ret = ERR_HACC_ALLOCATE_BUFFER_FAIL;
		goto _allocate_data_buf_err;
	}
	memcpy(databuf, data, data_size);

	if (seed_size != 0) {
		/* allocate seed buffer to be sent to TEE */
		seedbuf = vmalloc(seed_size);
		if (seedbuf == NULL) {
			ret = ERR_HACC_ALLOCATE_BUFFER_FAIL;
			goto _allocate_seed_buf_err;
		}
		memcpy(seedbuf, seed, seed_size);
	}

	/* map TCI virtual address for data buffer */
	ret = mc_map(&drSessionHandle, databuf, data_size, &dataMapInfo);
	if (MC_DRV_OK != ret) {
		pr_debug("NWD HACC: mcMap failed of data buffer: %d", ret);
		ret = ERR_HACC_MCMAP_BUFFER_FAIL;
		goto _mcmap_data_fail;
	}
	pTci->data_addr = (uint32_t) dataMapInfo.secure_virt_addr;
	pTci->data_len = data_size;

	if (seed_size != 0) {
		/* map TCI virtual address for seed buffer */
		ret = mc_map(&drSessionHandle, seedbuf, seed_size, &seedMapInfo);
		if (MC_DRV_OK != ret) {
			pr_debug("NWD HACC: mcMap failed of seed buffer: %d", ret);
			ret = ERR_HACC_MCMAP_BUFFER_FAIL;
			goto _mcmap_seed_fail;
		}
		pTci->seed_addr = (uint32_t) seedMapInfo.secure_virt_addr;
		pTci->seed_len = seed_size;
	} else {
		pTci->seed_addr = 0;
		pTci->seed_len = 0;
	}

	/* set other TCI parameter */
	pTci->hacc_user = user;
	pTci->direction = direction;

	/* set TCI command */
	pTci->cmd.header.commandId = CMD_HACC_REQUEST;

	/* notify the trustlet */
	pr_debug("NWD HACC: prepare notify\n");
	mcRet = mc_notify(&drSessionHandle);
	if (MC_DRV_OK != mcRet) {
		pr_debug("NWD HACC IRQ fail: mc_notify returned: %d\n", mcRet);
		ret = ERR_HACC_NOTIFY_TO_TRUSTLET_FAIL;
		goto _notify_to_trustlet_fail;
	}

	/* wait for response from the trustlet */
	mcRet = mc_wait_notification(&drSessionHandle, /*MC_INFINITE_TIMEOUT */ 20000);
	if (MC_DRV_OK != mcRet) {
		pr_debug("NWD HACC IRQ fail: mc_wait_notification 20s timeout: %d\n", mcRet);
		ret = ERR_HACC_NOTIFY_FROM_TRUSTLET_FAIL;
		goto _notify_from_trustlet_fail;
	}

	if (pTci->result != 0) {
		pr_debug("NWD HACC Request Fail!!!!!!!!(ret:%d, err:%d)\n", pTci->result,
			 pTci->rsp.header.returnCode);
	} else {
		pr_debug("NWD HACC Request Success!!!!!!!!\n");
		/* update result from secure buffer */
		memcpy(data, databuf, data_size);
	}

_notify_from_trustlet_fail:
_notify_to_trustlet_fail:
	if (seed_size != 0)
		mc_unmap(&drSessionHandle, seedbuf, &seedMapInfo);
_mcmap_seed_fail:
	mc_unmap(&drSessionHandle, databuf, &dataMapInfo);
_mcmap_data_fail:
	if (seed_size != 0)
		vfree(seedbuf);
_allocate_seed_buf_err:
	vfree(databuf);
_allocate_data_buf_err:

	return ret;
}