1 /*****************************************************************************
2  * Copyright (c) 2015-2020 IBM Corporation
3  * All rights reserved.
4  * This program and the accompanying materials
5  * are made available under the terms of the BSD License
6  * which accompanies this distribution, and is available at
7  * http://www.opensource.org/licenses/bsd-license.php
8  *
9  * Contributors:
10  *     IBM Corporation - initial implementation
11  *****************************************************************************/
12 
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <stdbool.h>
16 
17 #include "string.h"
18 #include "helpers.h"
19 #include "byteorder.h"
20 #include "tcgbios_int.h"
21 #include "tpm_drivers.h"
22 #include "libhvcall.h"
23 #include "paflof.h"
24 
25 #undef PAPR_VTPM_DEBUG
26 //#define PAPR_VTPM_DEBUG
27 #ifdef PAPR_VTPM_DEBUG
28 #define dprintf(_x ...) do { printf("VTPM CRQ: " _x); } while(0)
29 #else
30 #define dprintf(_x ...)
31 #endif
32 
33 #define MIN(a, b) ((a) > (b) ? (b) : (a))
34 
35 /* layout of the command request queue for vTPM; all fields are big endian */
36 struct crq {
37 	uint8_t valid;
38 	uint8_t msg;
39 	uint16_t len;
40 	uint32_t data;
41 	uint64_t reserved;
42 } __attribute__((packed));
43 
44 #define PAPR_VTPM_INIT_CRQ_COMMAND      0xC0
45 #define PAPR_VTPM_VALID_COMMAND         0x80
46 #define PAPR_VTPM_MSG_RESULT            0x80
47 
48 /* crq.msg request types when crq.valid = PAPR_VTPM_INIT_CRQ_COMMAND */
49 #define PAPR_VTPM_INIT_CRQ_RESULT       0x1
50 
51 /* crq.msg request types when crq.valid = PAPR_VTPM_VALID_COMMAND */
52 #define PAPR_VTPM_GET_VERSION           0x1
53 #define PAPR_VTPM_TPM_COMMAND           0x2
54 #define PAPR_VTPM_GET_RTCE_BUFFER_SIZE  0x3
55 
56 #define TPM2_DEFAULT_DURATION_SHORT       750000 /* us */
57 #define TPM2_DEFAULT_DURATION_MEDIUM     2000000 /* us */
58 #define TPM2_DEFAULT_DURATION_LONG       2000000 /* us */
59 
60 static const uint32_t tpm2_durations[3] = {
61 	TPM2_DEFAULT_DURATION_SHORT,
62 	TPM2_DEFAULT_DURATION_MEDIUM,
63 	TPM2_DEFAULT_DURATION_LONG,
64 };
65 
66 #define QUEUE_SIZE 4096
67 
68 /* state of the PAPR CRQ VTPM driver */
69 static struct {
70 	/* whether it driver been initialized */
71 	bool initialized;
72 
73 	/* unit number */
74 	unsigned long unit;
75 
76 	/* CRQ queue address and size */
77 	unsigned char *qaddr;
78 	unsigned long qsize;
79 
80 	/* current q_entry */
81 	unsigned int curr_q_entry;
82 
83 	/* current response CRQ */
84 	struct crq *response;
85 
86 	/* power firmware defined state and error code */
87 	vtpm_drv_state driver_state;
88 	vtpm_drv_error driver_error;
89 
90 	/* size of buffer supported by hypervisor */
91 	unsigned int buffer_size;
92 
93 	/* buffer for commands and responses */
94 	char *buffer;
95 } spapr_vtpm = {
96 	.qsize = QUEUE_SIZE,
97 	.driver_state = VTPM_DRV_STATE_INVALID,
98 	.driver_error = VTPM_DRV_ERROR_NO_FAILURE,
99 };
100 
vtpm_drv_state_set(vtpm_drv_state s,vtpm_drv_error e)101 static void vtpm_drv_state_set(vtpm_drv_state s, vtpm_drv_error e)
102 {
103 	spapr_vtpm.driver_state = s;
104 	spapr_vtpm.driver_error = e;
105 }
106 
vtpm_drv_error_get(void)107 static vtpm_drv_error vtpm_drv_error_get(void)
108 {
109 	return spapr_vtpm.driver_error;
110 }
111 
spapr_get_crq(void * qaddr,unsigned long q_entry)112 static struct crq *spapr_get_crq(void *qaddr, unsigned long q_entry)
113 {
114 	return &((struct crq *)qaddr)[q_entry];
115 }
116 
117 /*
118  * Get the crq where the response will be found. This
119  * function will clear the CRQ's valid field and advance
120  * the entry counter to the next entry.
121  */
spapr_get_response_crq(void)122 static struct crq *spapr_get_response_crq(void)
123 {
124 	struct crq *crq;
125 
126 	dprintf("curr_q_entry = %d\n", spapr_vtpm.curr_q_entry);
127 
128 	crq = spapr_get_crq(spapr_vtpm.qaddr, spapr_vtpm.curr_q_entry);
129 	memset(crq, 0, sizeof(*crq));
130 
131 	spapr_vtpm.curr_q_entry += 1;
132 	if (spapr_vtpm.curr_q_entry == (spapr_vtpm.qsize / sizeof(struct crq)))
133 		spapr_vtpm.curr_q_entry = 0;
134 
135 	return crq;
136 }
137 
138 /*
139  * Send a message via CRQ and wait for the response
140  */
spapr_send_crq_and_wait(unsigned long unit,struct crq * crq,struct crq ** response,unsigned timeout,vtpm_drv_state state1,vtpm_drv_state state2)141 static bool spapr_send_crq_and_wait(unsigned long unit,
142 				    struct crq *crq,
143 				    struct crq **response,
144 				    unsigned timeout,
145 				    vtpm_drv_state state1,
146 				    vtpm_drv_state state2)
147 {
148 	long rc;
149 	unsigned i;
150 
151 	*response = spapr_get_response_crq();
152 
153 	vtpm_drv_state_set(state1, VTPM_DRV_ERROR_NO_FAILURE);
154 
155 	rc = hv_send_crq(unit, (uint64_t *)crq);
156 	if (rc != H_SUCCESS) {
157 		vtpm_drv_state_set(VTPM_DRV_STATE_WAIT_INIT,
158 				   VTPM_DRV_ERROR_TPM_CRQ_ERROR);
159 		return false;
160 	}
161 
162 	vtpm_drv_state_set(state2, VTPM_DRV_ERROR_NO_FAILURE);
163 
164 	for (i = 0; i < timeout; i += 1000) {
165 		if (((*response)->valid & PAPR_VTPM_MSG_RESULT))
166 			return true;
167 		SLOF_usleep(1000);
168 	}
169 
170 	vtpm_drv_state_set(VTPM_DRV_STATE_FAILURE,
171 			   VTPM_DRV_ERROR_WAIT_TIMEOUT);
172 
173 	dprintf("Received no response from CRQ\n");
174 	return false;
175 }
176 
177 /*
178  * Get parameters from the CRQ
179  */
spapr_vtpm_get_params(void)180 static bool spapr_vtpm_get_params(void)
181 {
182 	struct crq crq, *response;
183 	static bool completed = false; /* only once */
184 
185 	if (completed)
186 		return true;
187 
188 	/* get the TPM's buffer size */
189 	crq.valid = PAPR_VTPM_VALID_COMMAND;
190 	crq.msg = PAPR_VTPM_GET_RTCE_BUFFER_SIZE;
191 
192 	if (!spapr_send_crq_and_wait(spapr_vtpm.unit, &crq, &response, 10,
193 				     VTPM_DRV_STATE_SEND_BUFSIZE_REQ,
194 				     VTPM_DRV_STATE_WAIT_BUFSIZE)) {
195 		printf("%s: Failure getting RTCE buffer size from CRQ\n",
196 		       __func__);
197 		return false;
198 	}
199 
200 	vtpm_drv_state_set(VTPM_DRV_STATE_ALLOC_RTCE_BUF,
201 			   VTPM_DRV_ERROR_NO_FAILURE);
202 
203 	dprintf("RTCE buffer size: %u\n", be16_to_cpu(response->len));
204 	spapr_vtpm.buffer_size = be16_to_cpu(response->len);
205 	if (spapr_vtpm.buffer_size < 1024) {
206 		printf("%s: RTCE buffer size of %u bytes is too small. "
207 		       "Minimum is 1024 bytes.\n", __func__,
208 		       spapr_vtpm.buffer_size);
209 		vtpm_drv_state_set(VTPM_DRV_STATE_FAILURE,
210 				   VTPM_DRV_ERROR_BAD_RTCE_SIZE);
211 		return false;
212 	}
213 	spapr_vtpm.buffer = SLOF_alloc_mem(spapr_vtpm.buffer_size);
214 	if (!spapr_vtpm.buffer) {
215 		printf("%s: Could not allocate buffer of size %u.\n",
216 		       __func__, spapr_vtpm.buffer_size);
217 		vtpm_drv_state_set(VTPM_DRV_STATE_FAILURE,
218 				   VTPM_DRV_ERROR_BAD_RTCE_SIZE);
219 		return false;
220 	}
221 
222 	completed = true;
223 
224 	return true;
225 }
226 
spapr_vtpm_activate(void)227 static bool spapr_vtpm_activate(void)
228 {
229 	long rc;
230 	struct crq crq, *response;
231 
232 	if (vtpm_drv_error_get() != VTPM_DRV_ERROR_NO_FAILURE) {
233 		printf("%s: CRQ: In failure mode\n", __func__);
234 		return false;
235 	}
236 
237 	vtpm_drv_state_set(VTPM_DRV_STATE_REG_CRQ,
238 			   VTPM_DRV_ERROR_NO_FAILURE);
239 
240 	rc = hv_reg_crq(spapr_vtpm.unit, (unsigned long)spapr_vtpm.qaddr,
241 			spapr_vtpm.qsize);
242 	if (rc != H_SUCCESS) {
243 		vtpm_drv_state_set(VTPM_DRV_STATE_WAIT_INIT,
244 				   VTPM_DRV_ERROR_UNEXPECTED_REG_ERROR);
245 		printf("%s: CRQ registration failed\n", __func__);
246 		return false;
247 	}
248 
249 	/* we always start with curr_q_entry 0 */
250 	spapr_vtpm.curr_q_entry = 0;
251 
252 	if (!spapr_vtpm.initialized) {
253 
254 		crq.valid = PAPR_VTPM_INIT_CRQ_COMMAND;
255 		crq.msg = PAPR_VTPM_INIT_CRQ_RESULT;
256 
257 		if (!spapr_send_crq_and_wait(spapr_vtpm.unit,
258 					     &crq,
259 					     &response,
260 					     10,
261 					     VTPM_DRV_STATE_SEND_INIT,
262 					     VTPM_DRV_STATE_WAIT_INIT_COMP)) {
263 			printf("%s: Initializing CRQ failed\n", __func__);
264 			goto err_exit;
265 		}
266 		dprintf("Successfully initialized CRQ\n");
267 
268 		spapr_vtpm.initialized = true;
269 	}
270 
271 	if (spapr_vtpm_get_params())
272 		return true;
273 
274 err_exit:
275 	hv_free_crq(spapr_vtpm.unit);
276 	spapr_vtpm.unit = 0;
277 
278 	return false;
279 }
280 
spapr_vtpm_finalize(void)281 void spapr_vtpm_finalize(void)
282 {
283 	if (spapr_vtpm.unit) {
284 		hv_free_crq(spapr_vtpm.unit);
285 		spapr_vtpm.unit = 0;
286 	}
287 }
288 
289 /*
290  * Check whether we have a CRQ underneath us; if we do, the CRQ will
291  * be left open.
292  */
spapr_vtpm_probe(void)293 static bool spapr_vtpm_probe(void)
294 {
295 	if (!spapr_vtpm.qaddr) {
296 		spapr_vtpm.qaddr = SLOF_alloc_mem(spapr_vtpm.qsize);
297 		if (!spapr_vtpm.qaddr) {
298 			printf("%s: Unable to allocate memory\n", __func__);
299 			return false;
300 		}
301 		memset(spapr_vtpm.qaddr, 0, spapr_vtpm.qsize);
302 
303 		dprintf("getting FORTH vtpm-unit\n");
304 		spapr_vtpm.unit = SLOF_get_vtpm_unit();
305 		if (!spapr_vtpm.unit) {
306 			printf("%s: Could not get valid vtpm-unit\n", __func__);
307 			return false;
308 		}
309 	}
310 
311 	dprintf("vtpm_unit = %lx, buffer = %p\n",
312 		spapr_vtpm.unit, spapr_vtpm.qaddr);
313 
314 	if (!spapr_vtpm_activate())
315 		return false;
316 
317 	return true;
318 }
319 
spapr_vtpm_senddata(const uint8_t * const data,uint32_t len)320 static bool spapr_vtpm_senddata(const uint8_t *const data, uint32_t len)
321 {
322 	struct crq crq;
323 	long rc;
324 
325 	if (vtpm_drv_error_get() != VTPM_DRV_ERROR_NO_FAILURE) {
326 		printf("%s: VTPM CRQ: In failure mode\n", __func__);
327 		return false;
328 	}
329 
330 	if (len > spapr_vtpm.buffer_size) {
331 		printf("%s: VTPM CRQ: Send buffer too large: %u > %u\n",
332 		       __func__, len, spapr_vtpm.buffer_size);
333 		return false;
334 	}
335 
336 	spapr_vtpm.response = spapr_get_response_crq();
337 	spapr_vtpm.response->data = (uint64_t)spapr_vtpm.buffer;
338 
339 	crq.valid = PAPR_VTPM_VALID_COMMAND;
340 	crq.msg = PAPR_VTPM_TPM_COMMAND;
341 	crq.len = cpu_to_be16(len);
342 	crq.data = (uint64_t)spapr_vtpm.buffer;
343 	memcpy(spapr_vtpm.buffer, data, MIN(len, spapr_vtpm.buffer_size));
344 
345 	vtpm_drv_state_set(VTPM_DRV_STATE_SEND_TPM_CMD,
346 			   VTPM_DRV_ERROR_NO_FAILURE);
347 
348 	rc = hv_send_crq(spapr_vtpm.unit, (uint64_t *)&crq);
349 
350 	if (rc == H_SUCCESS)
351 		vtpm_drv_state_set(VTPM_DRV_STATE_WAIT_TPM_RSP,
352 				   VTPM_DRV_ERROR_NO_FAILURE);
353 	else
354 		vtpm_drv_state_set(VTPM_DRV_STATE_WAIT_INIT,
355 				   VTPM_DRV_ERROR_UNEXPECTED_SEND_ERROR);
356 
357 	return (rc == H_SUCCESS);
358 }
359 
spapr_vtpm_waitresponseready(enum tpm_duration_type to_t)360 static bool spapr_vtpm_waitresponseready(enum tpm_duration_type to_t)
361 {
362 	uint32_t timeout = tpm2_durations[to_t];
363 	int i;
364 
365 	if (vtpm_drv_error_get() != VTPM_DRV_ERROR_NO_FAILURE) {
366 		printf("%s: VTPM CRQ: In failure mode\n", __func__);
367 		return false;
368 	}
369 
370 	for (i = 0; i < timeout; i += 1000) {
371 		if (spapr_vtpm.response->valid & PAPR_VTPM_MSG_RESULT) {
372 			/* TPM responded: move to Send tpm-cmd state */
373 			vtpm_drv_state_set(VTPM_DRV_STATE_SEND_TPM_CMD,
374 					   VTPM_DRV_ERROR_NO_FAILURE);
375 			dprintf("Received response to TPM command\n");
376 			return true;
377 		}
378 		SLOF_usleep(1000);
379 	}
380 
381 	vtpm_drv_state_set(VTPM_DRV_STATE_FAILURE,
382 			   VTPM_DRV_ERROR_WAIT_TIMEOUT);
383 
384 	dprintf("Received NO response to TPM command");
385 
386 	return false;
387 }
388 
spapr_vtpm_readresponse(uint8_t * buffer,uint32_t * len)389 static bool spapr_vtpm_readresponse(uint8_t *buffer, uint32_t *len)
390 {
391 	uint32_t length;
392 
393 	if (vtpm_drv_error_get() != VTPM_DRV_ERROR_NO_FAILURE) {
394 		printf("%s: VTPM CRQ: In failure mode\n", __func__);
395 		return false;
396 	}
397 
398 	length = MIN(*len, be32_to_cpu(spapr_vtpm.response->len));
399 
400 	memcpy(buffer, (void *)(uint64_t)spapr_vtpm.response->data, length);
401 
402 	dprintf("Length of copied response: %d\n", length);
403 
404 	spapr_vtpm.response = NULL;
405 	*len = length;
406 
407 	return true;
408 }
409 
410 /**** higher layer interface ****/
411 
spapr_vtpm_get_error(void)412 vtpm_drv_error spapr_vtpm_get_error(void)
413 {
414 	return vtpm_drv_error_get();
415 }
416 
spapr_vtpm_set_error(vtpm_drv_error errcode)417 void spapr_vtpm_set_error(vtpm_drv_error errcode)
418 {
419 	spapr_vtpm.driver_error = errcode;
420 }
421 
spapr_is_vtpm_present(void)422 bool spapr_is_vtpm_present(void)
423 {
424 	return spapr_vtpm_probe();
425 }
426 
spapr_transmit(uint8_t locty,struct tpm_req_header * req,void * respbuffer,uint32_t * respbufferlen,enum tpm_duration_type to_t)427 int spapr_transmit(uint8_t locty, struct tpm_req_header *req,
428 		   void *respbuffer, uint32_t *respbufferlen,
429 		   enum tpm_duration_type to_t)
430 {
431 	if (!spapr_vtpm_senddata((uint8_t *)req, be32_to_cpu(req->totlen)) ||
432 	    !spapr_vtpm_waitresponseready(to_t) ||
433 	    !spapr_vtpm_readresponse(respbuffer, respbufferlen) ||
434 	    *respbufferlen < sizeof(struct tpm_rsp_header))
435 		return -1;
436 	return 0;
437 }
438