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