xref: /onnv-gate/usr/src/uts/common/io/tpm/tpm.c (revision 10334:2f82b01640c4)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * TPM 1.2 Driver for the TPMs that follow TIS v1.2
29  */
30 
31 #include <sys/devops.h>		/* used by dev_ops */
32 #include <sys/conf.h>		/* used by dev_ops,cb_ops */
33 #include <sys/modctl.h>		/* for _init,_info,_fini,mod_* */
34 #include <sys/ddi.h>		/* used by all entry points */
35 #include <sys/sunddi.h>		/* used by all entry points */
36 #include <sys/cmn_err.h>	/* used for debug outputs */
37 #include <sys/types.h>		/* used by prop_op, ddi_prop_op */
38 
39 #include <sys/file.h>		/* used by open, close */
40 #include <sys/errno.h>		/* used by open,close,read,write */
41 #include <sys/open.h>		/* used by open,close,read,write */
42 #include <sys/cred.h>		/* used by open,close,read */
43 #include <sys/uio.h>		/* used by read */
44 #include <sys/stat.h>		/* defines S_IFCHR */
45 #include <sys/crypto/common.h>
46 #include <sys/crypto/impl.h>
47 #include <sys/crypto/spi.h>
48 
49 #include <sys/byteorder.h>	/* for ntohs, ntohl, htons, htonl */
50 
51 #ifdef sun4v
52 #include <sys/hypervisor_api.h>
53 #include <sys/hsvc.h>
54 #endif
55 
56 #include <tss/platform.h> 	/* from SUNWtss */
57 #include <tss/tpm.h> 		/* from SUNWtss */
58 
59 #include "tpm_tis.h"
60 #include "tpm_ddi.h"
61 #include "tpm_duration.h"
62 
63 #define	TPM_HEADER_SIZE 10
64 typedef enum {
65 	TPM_TAG_OFFSET = 0,
66 	TPM_PARAMSIZE_OFFSET = 2,
67 	TPM_RETURN_OFFSET = 6,
68 	TPM_COMMAND_CODE_OFFSET = 6,
69 } TPM_HEADER_OFFSET_T;
70 
71 /*
72  * This is to address some TPMs that does not report the correct duration
73  * and timeouts.  In our experience with the production TPMs, we encountered
74  * time errors such as GetCapability command from TPM reporting the timeout
75  * and durations in milliseconds rather than microseconds.  Some other TPMs
76  * report the value 0's
77  *
78  * Short Duration is based on section 11.3.4 of TIS speciciation, that
79  * TPM_GetCapability (short duration) commands should not be longer than 750ms
80  * and that section 11.3.7 states that TPM_ContinueSelfTest (medium duration)
81  * should not be longer than 1 second.
82  */
83 #define	DEFAULT_SHORT_DURATION	750000
84 #define	DEFAULT_MEDIUM_DURATION	1000000
85 #define	DEFAULT_LONG_DURATION	300000000
86 #define	DEFAULT_TIMEOUT_A	750000
87 #define	DEFAULT_TIMEOUT_B	2000000
88 #define	DEFAULT_TIMEOUT_C	750000
89 #define	DEFAULT_TIMEOUT_D	750000
90 
91 /*
92  * In order to test the 'millisecond bug', we test if DURATIONS and TIMEOUTS
93  * are unreasonably low...such as 10 milliseconds (TPM isn't that fast).
94  * and 400 milliseconds for long duration
95  */
96 #define	TEN_MILLISECONDS	10000	/* 10 milliseconds */
97 #define	FOUR_HUNDRED_MILLISECONDS 400000	/* 4 hundred milliseconds */
98 
99 #define	DEFAULT_LOCALITY 0
100 /*
101  * TPM input/output buffer offsets
102  */
103 
104 typedef enum {
105 	TPM_CAP_RESPSIZE_OFFSET = 10,
106 	TPM_CAP_RESP_OFFSET = 14,
107 } TPM_CAP_RET_OFFSET_T;
108 
109 typedef enum {
110 	TPM_CAP_TIMEOUT_A_OFFSET = 14,
111 	TPM_CAP_TIMEOUT_B_OFFSET = 18,
112 	TPM_CAP_TIMEOUT_C_OFFSET = 22,
113 	TPM_CAP_TIMEOUT_D_OFFSET = 26,
114 } TPM_CAP_TIMEOUT_OFFSET_T;
115 
116 typedef enum {
117 	TPM_CAP_DUR_SHORT_OFFSET = 14,
118 	TPM_CAP_DUR_MEDIUM_OFFSET = 18,
119 	TPM_CAP_DUR_LONG_OFFSET = 22,
120 } TPM_CAP_DURATION_OFFSET_T;
121 
122 #define	TPM_CAP_VERSION_INFO_OFFSET	14
123 #define	TPM_CAP_VERSION_INFO_SIZE	15
124 
125 /*
126  * Internal TPM command functions
127  */
128 static int itpm_command(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz);
129 static int tpm_get_timeouts(tpm_state_t *tpm);
130 static int tpm_get_duration(tpm_state_t *tpm);
131 static int tpm_get_version(tpm_state_t *tpm);
132 static int tpm_continue_selftest(tpm_state_t *tpm);
133 
134 /*
135  * Internal TIS related functions
136  */
137 static int tpm_wait_for_stat(tpm_state_t *, uint8_t, clock_t);
138 static clock_t tpm_get_ordinal_duration(tpm_state_t *, uint8_t);
139 static int tis_check_active_locality(tpm_state_t *, char);
140 static int tis_request_locality(tpm_state_t *, char);
141 static void tis_release_locality(tpm_state_t *, char, int);
142 static int tis_init(tpm_state_t *);
143 static uint8_t tis_get_status(tpm_state_t *);
144 static int tis_send_data(tpm_state_t *, uint8_t *, size_t);
145 static int tis_recv_data(tpm_state_t *, uint8_t *, size_t);
146 
147 /* Auxilliary */
148 static int receive_data(tpm_state_t *, uint8_t *, size_t);
149 static inline int tpm_io_lock(tpm_state_t *);
150 static inline void tpm_unlock(tpm_state_t *);
151 static void tpm_cleanup(dev_info_t *, tpm_state_t *);
152 
153 /*
154  * Sun DDI/DDK entry points
155  */
156 
157 /* Declaration of autoconfig functions */
158 static int tpm_attach(dev_info_t *, ddi_attach_cmd_t);
159 static int tpm_detach(dev_info_t *, ddi_detach_cmd_t);
160 static int tpm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
161 static int tpm_quiesce(dev_info_t *);
162 /* End of autoconfig functions */
163 
164 /* Declaration of driver entry point functions */
165 static int tpm_open(dev_t *, int, int, cred_t *);
166 static int tpm_close(dev_t, int, int, cred_t *);
167 static int tpm_read(dev_t, struct uio *, cred_t *);
168 static int tpm_write(dev_t, struct uio *, cred_t *);
169 /* End of driver entry point functions */
170 
171 /* cb_ops structure */
172 static struct cb_ops tpm_cb_ops = {
173 	tpm_open,
174 	tpm_close,
175 	nodev,		/* no strategy - nodev returns ENXIO */
176 	nodev,		/* no print */
177 	nodev,		/* no dump */
178 	tpm_read,
179 	tpm_write,
180 	nodev,		/* no ioctl */
181 	nodev,		/* no devmap */
182 	nodev,		/* no mmap */
183 	nodev,		/* no segmap */
184 	nochpoll,	/* returns ENXIO for non-pollable devices */
185 	ddi_prop_op,
186 	NULL,		/* streamtab struc */
187 	D_MP,		/* compatibility flags */
188 	CB_REV,		/* cb_ops revision number */
189 	nodev,		/* no aread */
190 	nodev		/* no awrite */
191 };
192 
193 /* dev_ops structure */
194 static struct dev_ops tpm_dev_ops = {
195 	DEVO_REV,
196 	0,		/* reference count */
197 	tpm_getinfo,
198 	nulldev,	/* no identify - nulldev returns 0 */
199 	nulldev,
200 	tpm_attach,
201 	tpm_detach,
202 	nodev,		/* no reset - nodev returns ENXIO */
203 	&tpm_cb_ops,
204 	(struct bus_ops *)NULL,
205 	nodev,		/* no power */
206 	tpm_quiesce
207 };
208 
209 /* modldrv structure */
210 static struct modldrv modldrv = {
211 	&mod_driverops,		/* Type: This is a driver */
212 	"TPM 1.2 driver",	/* Name of the module. */
213 	&tpm_dev_ops
214 };
215 
216 /* modlinkage structure */
217 static struct modlinkage tpm_ml = {
218 	MODREV_1,
219 	&modldrv,
220 	NULL
221 };
222 
223 #ifdef KCF_TPM_RNG_PROVIDER
224 
225 #define	IDENT_TPMRNG	"TPM Random Number Generator"
226 /*
227  * CSPI information (entry points, provider info, etc.)
228  */
229 static void tpmrng_provider_status(crypto_provider_handle_t, uint_t *);
230 
231 static crypto_control_ops_t tpmrng_control_ops = {
232 	tpmrng_provider_status
233 };
234 
235 static int tpmrng_seed_random(crypto_provider_handle_t, crypto_session_id_t,
236     uchar_t *, size_t, uint_t, uint32_t, crypto_req_handle_t);
237 
238 static int tpmrng_generate_random(crypto_provider_handle_t,
239     crypto_session_id_t, uchar_t *, size_t, crypto_req_handle_t);
240 
241 static crypto_random_number_ops_t tpmrng_random_number_ops = {
242 	tpmrng_seed_random,
243 	tpmrng_generate_random
244 };
245 
246 static int tpmrng_ext_info(crypto_provider_handle_t,
247 	crypto_provider_ext_info_t *,
248 	crypto_req_handle_t);
249 
250 static crypto_provider_management_ops_t tpmrng_extinfo_op = {
251 	tpmrng_ext_info,
252 	NULL,
253 	NULL,
254 	NULL
255 };
256 
257 static int tpmrng_register(tpm_state_t *);
258 static int tpmrng_unregister(tpm_state_t *);
259 
260 static crypto_ops_t tpmrng_crypto_ops = {
261 	&tpmrng_control_ops,
262 	NULL,
263 	NULL,
264 	NULL,
265 	NULL,
266 	NULL,
267 	NULL,
268 	NULL,
269 	&tpmrng_random_number_ops,
270 	NULL,
271 	NULL,
272 	NULL,
273 	&tpmrng_extinfo_op,
274 	NULL,
275 	NULL
276 };
277 
278 static crypto_provider_info_t tpmrng_prov_info = {
279 	CRYPTO_SPI_VERSION_2,
280 	"TPM Random Number Provider",
281 	CRYPTO_HW_PROVIDER,
282 	NULL,
283 	NULL,
284 	&tpmrng_crypto_ops,
285 	0,
286 	NULL,
287 	0,
288 	NULL
289 };
290 #endif /* KCF_TPM_RNG_PROVIDER */
291 
292 static void *statep = NULL;
293 
294 /*
295  * Inline code to get exclusive lock on the TPM device and to make sure
296  * the device is not suspended.  This grabs the primary TPM mutex (pm_mutex)
297  * and then checks the suspend status.  If suspended, it will wait until
298  * the device is "resumed" before releasing the pm_mutex and continuing.
299  */
300 #define	TPM_EXCLUSIVE_LOCK(tpm)  { \
301 	mutex_enter(&tpm->pm_mutex); \
302 	while (tpm->suspended) \
303 		cv_wait(&tpm->suspend_cv, &tpm->pm_mutex); \
304 	mutex_exit(&tpm->pm_mutex); }
305 
306 /*
307  * TPM accessor functions
308  */
309 #ifdef sun4v
310 
311 extern uint64_t
312 hcall_tpm_get(uint64_t, uint64_t, uint64_t, uint64_t *);
313 
314 extern uint64_t
315 hcall_tpm_put(uint64_t, uint64_t, uint64_t, uint64_t);
316 
317 static inline uint8_t
318 tpm_get8(tpm_state_t *tpm, unsigned long offset)
319 {
320 	uint64_t value;
321 
322 	ASSERT(tpm != NULL);
323 	(void) hcall_tpm_get(tpm->locality, offset, sizeof (uint8_t), &value);
324 	return ((uint8_t)value);
325 }
326 
327 static inline uint32_t
328 tpm_get32(tpm_state_t *tpm, unsigned long offset)
329 {
330 	uint64_t value;
331 
332 	ASSERT(tpm != NULL);
333 	(void) hcall_tpm_get(tpm->locality, offset, sizeof (uint32_t), &value);
334 	return ((uint32_t)value);
335 }
336 
337 static inline void
338 tpm_put8(tpm_state_t *tpm, unsigned long offset, uint8_t value)
339 {
340 	ASSERT(tpm != NULL);
341 	(void) hcall_tpm_put(tpm->locality, offset, sizeof (uint8_t), value);
342 }
343 
344 #else
345 
346 static inline uint8_t
347 tpm_get8(tpm_state_t *tpm, unsigned long offset)
348 {
349 	ASSERT(tpm != NULL);
350 
351 	return (ddi_get8(tpm->handle,
352 	    (uint8_t *)(TPM_LOCALITY_OFFSET(tpm->locality) |
353 	    (uintptr_t)tpm->addr + offset)));
354 }
355 
356 static inline uint32_t
357 tpm_get32(tpm_state_t *tpm, unsigned long offset)
358 {
359 	ASSERT(tpm != NULL);
360 	return (ddi_get32(tpm->handle,
361 	    (uint32_t *)(TPM_LOCALITY_OFFSET(tpm->locality) |
362 	    (uintptr_t)tpm->addr + offset)));
363 }
364 
365 static inline void
366 tpm_put8(tpm_state_t *tpm, unsigned long offset, uint8_t value)
367 {
368 	ASSERT(tpm != NULL);
369 	ddi_put8(tpm->handle,
370 	    (uint8_t *)(TPM_LOCALITY_OFFSET(tpm->locality) |
371 	    (uintptr_t)tpm->addr + offset), value);
372 }
373 
374 #endif /* sun4v */
375 
376 /*
377  * TPM commands to get the TPM's properties, e.g.,timeout
378  */
379 /*ARGSUSED*/
380 static int
381 tpm_quiesce(dev_info_t *dip)
382 {
383 	return (DDI_SUCCESS);
384 }
385 
386 static uint32_t
387 load32(uchar_t *ptr, uint32_t offset)
388 {
389 	uint32_t val;
390 	bcopy(ptr + offset, &val, sizeof (uint32_t));
391 
392 	return (ntohl(val));
393 }
394 
395 /*
396  * Get the actual timeouts supported by the TPM by issuing TPM_GetCapability
397  * with the subcommand TPM_CAP_PROP_TIS_TIMEOUT
398  * TPM_GetCapability (TPM Main Part 3 Rev. 94, pg.38)
399  */
400 static int
401 tpm_get_timeouts(tpm_state_t *tpm)
402 {
403 	int ret;
404 	uint32_t timeout;   /* in milliseconds */
405 	uint32_t len;
406 
407 	/* The buffer size (30) needs room for 4 timeout values (uint32_t) */
408 	uint8_t buf[30] = {
409 		0, 193,		/* TPM_TAG_RQU_COMMAND */
410 		0, 0, 0, 22,	/* paramsize in bytes */
411 		0, 0, 0, 101,	/* TPM_ORD_GetCapability */
412 		0, 0, 0, 5,	/* TPM_CAP_Prop */
413 		0, 0, 0, 4,	/* SUB_CAP size in bytes */
414 		0, 0, 1, 21	/* TPM_CAP_PROP_TIS_TIMEOUT(0x115) */
415 	};
416 	char *myname = "tpm_get_timeout";
417 
418 	ASSERT(tpm != NULL);
419 
420 	ret = itpm_command(tpm, buf, sizeof (buf));
421 	if (ret != DDI_SUCCESS) {
422 		cmn_err(CE_WARN, "%s: itpm_command failed", myname);
423 		return (DDI_FAILURE);
424 	}
425 
426 	/*
427 	 * Get the length of the returned buffer
428 	 * Make sure that there are 4 timeout values returned
429 	 * length of the capability response is stored in data[10-13]
430 	 * Also the TPM is in network byte order
431 	 */
432 	len = load32(buf, TPM_CAP_RESPSIZE_OFFSET);
433 	if (len != 4 * sizeof (uint32_t)) {
434 		cmn_err(CE_WARN, "%s: capability response size should be %d"
435 		    "instead it's %d",
436 		    myname, (int)(4 * sizeof (uint32_t)), (int)len);
437 		return (DDI_FAILURE);
438 	}
439 
440 	/* Get the four timeout's: a,b,c,d (they are 4 bytes long each) */
441 	timeout = load32(buf, TPM_CAP_TIMEOUT_A_OFFSET);
442 	if (timeout == 0) {
443 		timeout = DEFAULT_TIMEOUT_A;
444 	} else if (timeout < TEN_MILLISECONDS) {
445 		/* timeout is in millisecond range (should be microseconds) */
446 		timeout *= 1000;
447 	}
448 	tpm->timeout_a = drv_usectohz(timeout);
449 
450 	timeout = load32(buf, TPM_CAP_TIMEOUT_B_OFFSET);
451 	if (timeout == 0) {
452 		timeout = DEFAULT_TIMEOUT_B;
453 	} else if (timeout < TEN_MILLISECONDS) {
454 		/* timeout is in millisecond range (should be microseconds) */
455 		timeout *= 1000;
456 	}
457 	tpm->timeout_b = drv_usectohz(timeout);
458 
459 	timeout = load32(buf, TPM_CAP_TIMEOUT_C_OFFSET);
460 	if (timeout == 0) {
461 		timeout = DEFAULT_TIMEOUT_C;
462 	} else if (timeout < TEN_MILLISECONDS) {
463 		/* timeout is in millisecond range (should be microseconds) */
464 		timeout *= 1000;
465 	}
466 	tpm->timeout_c = drv_usectohz(timeout);
467 
468 	timeout = load32(buf, TPM_CAP_TIMEOUT_D_OFFSET);
469 	if (timeout == 0) {
470 		timeout = DEFAULT_TIMEOUT_D;
471 	} else if (timeout < TEN_MILLISECONDS) {
472 		/* timeout is in millisecond range (should be microseconds) */
473 		timeout *= 1000;
474 	}
475 	tpm->timeout_d = drv_usectohz(timeout);
476 
477 	return (DDI_SUCCESS);
478 }
479 
480 /*
481  * Get the actual timeouts supported by the TPM by issuing TPM_GetCapability
482  * with the subcommand TPM_CAP_PROP_TIS_DURATION
483  * TPM_GetCapability (TPM Main Part 3 Rev. 94, pg.38)
484  */
485 static int
486 tpm_get_duration(tpm_state_t *tpm) {
487 	int ret;
488 	uint32_t duration;
489 	uint32_t len;
490 	uint8_t buf[30] = {
491 		0, 193,		/* TPM_TAG_RQU_COMMAND */
492 		0, 0, 0, 22,	/* paramsize in bytes */
493 		0, 0, 0, 101,	/* TPM_ORD_GetCapability */
494 		0, 0, 0, 5,	/* TPM_CAP_Prop */
495 		0, 0, 0, 4,	/* SUB_CAP size in bytes */
496 		0, 0, 1, 32	/* TPM_CAP_PROP_TIS_DURATION(0x120) */
497 	};
498 	char *myname = "tpm_get_duration";
499 
500 	ASSERT(tpm != NULL);
501 
502 	ret = itpm_command(tpm, buf, sizeof (buf));
503 	if (ret != DDI_SUCCESS) {
504 		cmn_err(CE_WARN, "%s: itpm_command failed with ret code: 0x%x",
505 			myname, ret);
506 		return (DDI_FAILURE);
507 	}
508 
509 	/*
510 	 * Get the length of the returned buffer
511 	 * Make sure that there are 3 duration values (S,M,L: in that order)
512 	 * length of the capability response is stored in data[10-13]
513 	 * Also the TPM is in network byte order
514 	 */
515 	len = load32(buf, TPM_CAP_RESPSIZE_OFFSET);
516 	if (len != 3 * sizeof (uint32_t)) {
517 		cmn_err(CE_WARN, "%s: capability response should be %d, "
518 		    "instead, it's %d",
519 		    myname, (int)(3 * sizeof (uint32_t)), (int)len);
520 		return (DDI_FAILURE);
521 	}
522 
523 	duration = load32(buf, TPM_CAP_DUR_SHORT_OFFSET);
524 	if (duration == 0) {
525 		duration = DEFAULT_SHORT_DURATION;
526 	} else if (duration < TEN_MILLISECONDS) {
527 		duration *= 1000;
528 	}
529 	tpm->duration[TPM_SHORT] = drv_usectohz(duration);
530 
531 	duration = load32(buf, TPM_CAP_DUR_MEDIUM_OFFSET);
532 	if (duration == 0) {
533 		duration = DEFAULT_MEDIUM_DURATION;
534 	} else if (duration < TEN_MILLISECONDS) {
535 		duration *= 1000;
536 	}
537 	tpm->duration[TPM_MEDIUM] = drv_usectohz(duration);
538 
539 	duration = load32(buf, TPM_CAP_DUR_LONG_OFFSET);
540 	if (duration == 0) {
541 		duration = DEFAULT_LONG_DURATION;
542 	} else if (duration < FOUR_HUNDRED_MILLISECONDS) {
543 		duration *= 1000;
544 	}
545 	tpm->duration[TPM_LONG] = drv_usectohz(duration);
546 
547 	/* Just make the undefined duration be the same as the LONG */
548 	tpm->duration[TPM_UNDEFINED] = tpm->duration[TPM_LONG];
549 
550 	return (DDI_SUCCESS);
551 }
552 
553 /*
554  * Get the actual timeouts supported by the TPM by issuing TPM_GetCapability
555  * with the subcommand TPM_CAP_PROP_TIS_DURATION
556  * TPM_GetCapability (TPM Main Part 3 Rev. 94, pg.38)
557  */
558 static int
559 tpm_get_version(tpm_state_t *tpm) {
560 	int ret;
561 	uint32_t len;
562 	char vendorId[5];
563 	/* If this buf is too small, the "vendor specific" data won't fit */
564 	uint8_t buf[64] = {
565 		0, 193,		/* TPM_TAG_RQU_COMMAND */
566 		0, 0, 0, 18,	/* paramsize in bytes */
567 		0, 0, 0, 101,	/* TPM_ORD_GetCapability */
568 		0, 0, 0, 0x1A,	/* TPM_CAP_VERSION_VAL */
569 		0, 0, 0, 0,	/* SUB_CAP size in bytes */
570 	};
571 	char *myname = "tpm_get_version";
572 
573 	ASSERT(tpm != NULL);
574 
575 	ret = itpm_command(tpm, buf, sizeof (buf));
576 	if (ret != DDI_SUCCESS) {
577 		cmn_err(CE_WARN, "%s: itpm_command failed with ret code: 0x%x",
578 			myname, ret);
579 		return (DDI_FAILURE);
580 	}
581 
582 	/*
583 	 * Get the length of the returned buffer.
584 	 */
585 	len = load32(buf, TPM_CAP_RESPSIZE_OFFSET);
586 	if (len < TPM_CAP_VERSION_INFO_SIZE) {
587 		cmn_err(CE_WARN, "%s: capability response should be greater"
588 		    " than %d, instead, it's %d",
589 		    myname,
590 		    TPM_CAP_VERSION_INFO_SIZE,
591 		    len);
592 		return (DDI_FAILURE);
593 	}
594 
595 	bcopy(buf + TPM_CAP_VERSION_INFO_OFFSET, &tpm->vers_info,
596 	    TPM_CAP_VERSION_INFO_SIZE);
597 
598 	bcopy(tpm->vers_info.tpmVendorID, vendorId,
599 	    sizeof (tpm->vers_info.tpmVendorID));
600 	vendorId[4] = '\0';
601 
602 	cmn_err(CE_NOTE, "!TPM found: Ver %d.%d, Rev %d.%d, "
603 	    "SpecLevel %d, errataRev %d, VendorId '%s'",
604 	    tpm->vers_info.version.major,	/* Version */
605 	    tpm->vers_info.version.minor,
606 	    tpm->vers_info.version.revMajor,	/* Revision */
607 	    tpm->vers_info.version.revMinor,
608 	    (int)ntohs(tpm->vers_info.specLevel),
609 	    tpm->vers_info.errataRev,
610 	    vendorId);
611 
612 	/*
613 	 * This driver only supports TPM Version 1.2
614 	 */
615 	if (tpm->vers_info.version.major != 1 &&
616 	    tpm->vers_info.version.minor != 2) {
617 		cmn_err(CE_WARN, "%s: Unsupported TPM version (%d.%d)",
618 		    myname,
619 		    tpm->vers_info.version.major,		/* Version */
620 		    tpm->vers_info.version.minor);
621 		return (DDI_FAILURE);
622 	}
623 
624 	return (DDI_SUCCESS);
625 }
626 
627 /*
628  * To prevent the TPM from complaining that certain functions are not tested
629  * we run this command when the driver attaches.
630  * For details see Section 4.2 of TPM Main Part 3 Command Specification
631  */
632 static int
633 tpm_continue_selftest(tpm_state_t *tpm) {
634 	int ret;
635 	uint8_t buf[10] = {
636 		0, 193,		/* TPM_TAG_RQU COMMAND */
637 		0, 0, 0, 10,	/* paramsize in bytes */
638 		0, 0, 0, 83	/* TPM_ORD_ContinueSelfTest */
639 	};
640 	char *myname = "tpm_continue_selftest";
641 
642 	/* Need a longer timeout */
643 	ret = itpm_command(tpm, buf, sizeof (buf));
644 	if (ret != DDI_SUCCESS) {
645 		cmn_err(CE_WARN, "%s: itpm_command failed", myname);
646 		return (DDI_FAILURE);
647 	}
648 
649 	return (DDI_SUCCESS);
650 }
651 /*
652  * Auxilary Functions
653  */
654 
655 /*
656  * Find out how long we should wait for the TPM command to complete a command
657  */
658 static clock_t
659 tpm_get_ordinal_duration(tpm_state_t *tpm, uint8_t ordinal)
660 {
661 	uint8_t index;
662 	char *myname = "tpm_get_ordinal_duration";
663 
664 	ASSERT(tpm != NULL);
665 
666 	/* Default and failure case for IFX */
667 	/* Is it a TSC_ORDINAL? */
668 	if (ordinal & TSC_ORDINAL_MASK) {
669 		if (ordinal > TSC_ORDINAL_MAX) {
670 			cmn_err(CE_WARN,
671 			    "%s: tsc ordinal: %d exceeds MAX: %d",
672 			    myname, ordinal, TSC_ORDINAL_MAX);
673 			return (0);
674 		}
675 		index = tsc_ords_duration[ordinal];
676 	} else {
677 		if (ordinal > TPM_ORDINAL_MAX) {
678 			cmn_err(CE_WARN,
679 			    "%s: ordinal %d exceeds MAX: %d",
680 			    myname, ordinal, TPM_ORDINAL_MAX);
681 			return (0);
682 		}
683 		index = tpm_ords_duration[ordinal];
684 	}
685 
686 	if (index > TPM_DURATION_MAX_IDX) {
687 		cmn_err(CE_WARN, "%s: FATAL:index '%d' is out of bound",
688 		    myname, index);
689 		return (0);
690 	}
691 	return (tpm->duration[index]);
692 }
693 
694 /*
695  * Internal TPM Transmit Function:
696  * Calls implementation specific sendto and receive
697  * The code assumes that the buffer is in network byte order
698  */
699 static int
700 itpm_command(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz)
701 {
702 	int ret;
703 	uint32_t count;
704 	char *myname = "itpm_command";
705 
706 	ASSERT(tpm != NULL && buf != NULL);
707 
708 	/* The byte order is network byte order so convert it */
709 	count = load32(buf, TPM_PARAMSIZE_OFFSET);
710 
711 	if (count == 0) {
712 		cmn_err(CE_WARN, "%s: count=0, no data? %d", myname,
713 		    (int)bufsiz);
714 		return (DDI_FAILURE);
715 	}
716 	if (count > bufsiz) {
717 		cmn_err(CE_WARN, "%s: invalid count value:count:%d > bufsiz %d",
718 		    myname, (int)count, (int)bufsiz);
719 		return (DDI_FAILURE);
720 	}
721 
722 	/* Send the command */
723 	ret = tis_send_data(tpm, buf, count);
724 	if (ret != DDI_SUCCESS) {
725 		cmn_err(CE_WARN, "%s: tis_send_data failed with error %x",
726 		    myname, ret);
727 		return (DDI_FAILURE);
728 	}
729 
730 	/*
731 	 * Now receive the data from the tpm
732 	 * Should at least receive "the common" 10 bytes (TPM_HEADER_SIZE)
733 	 */
734 	ret = tis_recv_data(tpm, buf, bufsiz);
735 	if (ret < TPM_HEADER_SIZE) {
736 		cmn_err(CE_WARN, "%s: tis_recv_data failed", myname);
737 		return (DDI_FAILURE);
738 	}
739 
740 	/* Check the return code */
741 	ret = load32(buf, TPM_RETURN_OFFSET);
742 	if (ret != TPM_SUCCESS) {
743 		if (ret == TPM_E_DEACTIVATED)
744 			cmn_err(CE_WARN, "%s: TPM is deactivated", myname);
745 		else if (ret == TPM_E_DISABLED)
746 			cmn_err(CE_WARN, "%s: TPM is disabled", myname);
747 		else
748 			cmn_err(CE_WARN, "%s: TPM error code 0x%0x",
749 			    myname, ret);
750 		return (DDI_FAILURE);
751 	}
752 
753 	return (DDI_SUCCESS);
754 }
755 
756 /*
757  * Whenever the driver wants to write to the DATA_IO register, it must need
758  * to figure out the burstcount.  This is the amount of bytes it can write
759  * before having to wait for long LPC bus cycle
760  *
761  * Returns: 0 if error, burst count if sucess
762  */
763 static uint16_t
764 tpm_get_burstcount(tpm_state_t *tpm) {
765 	clock_t stop;
766 	uint16_t burstcnt;
767 
768 	ASSERT(tpm != NULL);
769 
770 	/*
771 	 * Spec says timeout should be TIMEOUT_D
772 	 * burst count is TPM_STS bits 8..23
773 	 */
774 	stop = ddi_get_lbolt() + tpm->timeout_d;
775 	do {
776 		/*
777 		 * burstcnt is stored as a little endian value
778 		 * 'ntohs' doesn't work since the value is not word-aligned
779 		 */
780 		burstcnt = tpm_get8(tpm, TPM_STS + 1);
781 		burstcnt += tpm_get8(tpm, TPM_STS + 2) << 8;
782 
783 		if (burstcnt)
784 			return (burstcnt);
785 
786 		delay(tpm->timeout_poll);
787 	} while (ddi_get_lbolt() < stop);
788 
789 	return (0);
790 }
791 
792 /*
793  * Writing 1 to TPM_STS_CMD_READY bit in TPM_STS will do the following:
794  * 1. The TPM will clears IO buffers if any
795  * 2. The TPM will enters either Idle or Ready state within TIMEOUT_B
796  * (checked in the calling function)
797  */
798 static void
799 tpm_set_ready(tpm_state_t *tpm) {
800 	tpm_put8(tpm, TPM_STS, TPM_STS_CMD_READY);
801 }
802 
803 static int
804 receive_data(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz) {
805 	int size = 0;
806 	int retried = 0;
807 	uint8_t stsbits;
808 
809 	/* A number of consecutive bytes that can be written to TPM */
810 	uint16_t burstcnt;
811 
812 	ASSERT(tpm != NULL && buf != NULL);
813 retry:
814 	while (size < bufsiz &&
815 		(tpm_wait_for_stat(tpm,
816 		    (TPM_STS_DATA_AVAIL|TPM_STS_VALID),
817 		    tpm->timeout_c) == DDI_SUCCESS)) {
818 		/*
819 		 * Burstcount should be available within TIMEOUT_D
820 		 * after STS is set to valid
821 		 * burstcount is dynamic, so have to get it each time
822 		 */
823 		burstcnt = tpm_get_burstcount(tpm);
824 		for (; burstcnt > 0 && size < bufsiz; burstcnt--) {
825 			buf[size++] = tpm_get8(tpm, TPM_DATA_FIFO);
826 		}
827 	}
828 	stsbits = tis_get_status(tpm);
829 	/* check to see if we need to retry (just once) */
830 	if (size < bufsiz && !(stsbits & TPM_STS_DATA_AVAIL) && retried == 0) {
831 		/* issue responseRetry (TIS 1.2 pg 54) */
832 		tpm_put8(tpm, TPM_STS, TPM_STS_RESPONSE_RETRY);
833 		/* update the retry counter so we only retry once */
834 		retried++;
835 		/* reset the size to 0 and reread the entire response */
836 		size = 0;
837 		goto retry;
838 	}
839 	return (size);
840 }
841 
842 /* Receive the data from the TPM */
843 static int
844 tis_recv_data(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz) {
845 	int ret;
846 	int size = 0;
847 	uint32_t expected, status;
848 	uint32_t cmdresult;
849 	char *myname = "tis_recv_data";
850 
851 	ASSERT(tpm != NULL && buf != NULL);
852 
853 	if (bufsiz < TPM_HEADER_SIZE) {
854 		/* There should be at least tag,paramsize,return code */
855 		cmn_err(CE_WARN, "%s: received data should contain at least "
856 		    "the header which is %d bytes long",
857 		    myname, TPM_HEADER_SIZE);
858 		goto OUT;
859 	}
860 
861 	/* Read tag(2 bytes), paramsize(4), and result(4) */
862 	size = receive_data(tpm, buf, TPM_HEADER_SIZE);
863 	if (size < TPM_HEADER_SIZE) {
864 		cmn_err(CE_WARN, "%s: getting the TPM_HEADER failed: size=%d",
865 		    myname, size);
866 		goto OUT;
867 	}
868 
869 	cmdresult = load32(buf, TPM_RETURN_OFFSET);
870 
871 	/* Get 'paramsize'(4 bytes)--it includes tag and paramsize */
872 	expected = load32(buf, TPM_PARAMSIZE_OFFSET);
873 	if (expected > bufsiz) {
874 		cmn_err(CE_WARN, "%s: paramSize is bigger "
875 		    "than the requested size: paramSize=%d bufsiz=%d result=%d",
876 		    myname, (int)expected, (int)bufsiz, cmdresult);
877 		goto OUT;
878 	}
879 
880 	/* Read in the rest of the data from the TPM */
881 	size += receive_data(tpm, (uint8_t *)&buf[TPM_HEADER_SIZE],
882 	    expected - TPM_HEADER_SIZE);
883 	if (size < expected) {
884 		cmn_err(CE_WARN, "%s: received data length=%d "
885 		    "is less than expected = %d", myname, size, expected);
886 		goto OUT;
887 	}
888 
889 	/* The TPM MUST set the state to stsValid within TIMEOUT_C */
890 	ret = tpm_wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c);
891 
892 	status = tis_get_status(tpm);
893 	if (ret != DDI_SUCCESS) {
894 		cmn_err(CE_WARN, "%s: TPM didn't set stsValid after its I/O: "
895 		    "status = 0x%08X", myname, status);
896 		goto OUT;
897 	}
898 
899 	/* There is still more data? */
900 	if (status & TPM_STS_DATA_AVAIL) {
901 		cmn_err(CE_WARN, "%s: Status TPM_STS_DATA_AVAIL set:0x%08X",
902 		    myname, status);
903 		goto OUT;
904 	}
905 
906 	/*
907 	 * Release the control of the TPM after we are done with it
908 	 * it...so others can also get a chance to send data
909 	 */
910 	tis_release_locality(tpm, tpm->locality, 0);
911 
912 OUT:
913 	tpm_set_ready(tpm);
914 	tis_release_locality(tpm, tpm->locality, 0);
915 	return (size);
916 }
917 
918 /*
919  * Send the data (TPM commands) to the Data IO register
920  */
921 static int
922 tis_send_data(tpm_state_t *tpm, uint8_t *buf, size_t bufsiz) {
923 	int ret;
924 	uint8_t status;
925 	uint16_t burstcnt;
926 	uint32_t ordinal;
927 	size_t count = 0;
928 	char *myname = "tis_send_data";
929 
930 	ASSERT(tpm != NULL && buf != NULL);
931 
932 	if (bufsiz == 0) {
933 		cmn_err(CE_WARN, "%s: passed in argument bufsize is zero",
934 		    myname);
935 		return (DDI_FAILURE);
936 	}
937 
938 	/* Put the TPM in ready state */
939 	status = tis_get_status(tpm);
940 
941 	if (!(status & TPM_STS_CMD_READY)) {
942 		tpm_set_ready(tpm);
943 		ret = tpm_wait_for_stat(tpm, TPM_STS_CMD_READY, tpm->timeout_b);
944 		if (ret != DDI_SUCCESS) {
945 			cmn_err(CE_WARN, "%s: could not put the TPM "
946 			    "in the command ready state:"
947 			    "tpm_wait_for_stat returned error",
948 			    myname);
949 			goto FAIL;
950 		}
951 	}
952 
953 	/*
954 	 * Now we are ready to send command
955 	 * TPM's burstcount dictates how many bytes we can write at a time
956 	 * Burstcount is dynamic if INTF_CAPABILITY for static burstcount is
957 	 * not set.
958 	 */
959 	while (count < bufsiz - 1) {
960 		burstcnt = tpm_get_burstcount(tpm);
961 		if (burstcnt == 0) {
962 			cmn_err(CE_WARN, "%s: tpm_get_burstcnt returned error",
963 			    myname);
964 			ret = DDI_FAILURE;
965 			goto FAIL;
966 		}
967 
968 		for (; burstcnt > 0 && count < bufsiz - 1; burstcnt--) {
969 			tpm_put8(tpm, TPM_DATA_FIFO, buf[count]);
970 			count++;
971 		}
972 		/* Wait for TPM to indicate that it is ready for more data */
973 		ret = tpm_wait_for_stat(tpm,
974 		    (TPM_STS_VALID | TPM_STS_DATA_EXPECT), tpm->timeout_c);
975 		if (ret != DDI_SUCCESS) {
976 			cmn_err(CE_WARN, "%s: TPM didn't enter stsvalid "
977 			    "state after sending the data:", myname);
978 			goto FAIL;
979 		}
980 	}
981 	/* We can't exit the loop above unless we wrote bufsiz-1 bytes */
982 
983 	/* Write last byte */
984 	tpm_put8(tpm, TPM_DATA_FIFO, buf[count]);
985 	count++;
986 
987 	/* Wait for the TPM to enter Valid State */
988 	ret = tpm_wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c);
989 	if (ret == DDI_FAILURE) {
990 		cmn_err(CE_WARN, "%s: tpm didn't enter Valid state", myname);
991 		goto FAIL;
992 	}
993 
994 	status = tis_get_status(tpm);
995 	/* The TPM should NOT be expecing more data at this point */
996 	if ((status & TPM_STS_DATA_EXPECT) != 0) {
997 		cmn_err(CE_WARN, "%s: DATA_EXPECT is set (shouldn't be) after "
998 		    "writing the last byte: status=0x%08X", myname, status);
999 		ret = DDI_FAILURE;
1000 		goto FAIL;
1001 	}
1002 
1003 	/*
1004 	 * Final step: Writing TPM_STS_GO to TPM_STS
1005 	 * register will actually send the command.
1006 	 */
1007 	tpm_put8(tpm, TPM_STS, TPM_STS_GO);
1008 
1009 	/* Ordinal/Command_code is located in buf[6..9] */
1010 	ordinal = load32(buf, TPM_COMMAND_CODE_OFFSET);
1011 
1012 	ret = tpm_wait_for_stat(tpm, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
1013 	    tpm_get_ordinal_duration(tpm, ordinal));
1014 	if (ret == DDI_FAILURE) {
1015 		status = tis_get_status(tpm);
1016 		if (!(status & TPM_STS_DATA_AVAIL) ||
1017 		    !(status & TPM_STS_VALID)) {
1018 			cmn_err(CE_WARN, "%s: TPM not ready or valid "
1019 			    "(ordinal = %d timeout = %ld)",
1020 			    myname, ordinal,
1021 			    tpm_get_ordinal_duration(tpm, ordinal));
1022 		} else {
1023 			cmn_err(CE_WARN, "%s: tpm_wait_for_stat "
1024 			    "(DATA_AVAIL | VALID) failed: STS = 0x%0X",
1025 			    myname, status);
1026 		}
1027 		goto FAIL;
1028 	}
1029 	return (DDI_SUCCESS);
1030 
1031 FAIL:
1032 	tpm_set_ready(tpm);
1033 	tis_release_locality(tpm, tpm->locality, 0);
1034 	return (ret);
1035 }
1036 
1037 /*
1038  * Clear XrequestUse and Xactivelocality, where X is the current locality
1039  */
1040 static void
1041 tis_release_locality(tpm_state_t *tpm, char locality, int force) {
1042 	ASSERT(tpm != NULL && locality >= 0 && locality < 5);
1043 
1044 	if (force ||
1045 	    (tpm_get8(tpm, TPM_ACCESS) &
1046 	    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
1047 	    (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) {
1048 		/*
1049 		 * Writing 1 to active locality bit in TPM_ACCESS
1050 		 * register reliquishes the control of the locality
1051 		 */
1052 		tpm_put8(tpm, TPM_ACCESS, TPM_ACCESS_ACTIVE_LOCALITY);
1053 	}
1054 }
1055 
1056 /*
1057  * Checks whether the given locality is active
1058  * Use TPM_ACCESS register and the masks TPM_ACCESS_VALID,TPM_ACTIVE_LOCALITY
1059  */
1060 static int
1061 tis_check_active_locality(tpm_state_t *tpm, char locality) {
1062 	uint8_t access_bits;
1063 	uint8_t old_locality;
1064 
1065 	ASSERT(tpm != NULL && locality >= 0 && locality < 5);
1066 
1067 	old_locality = tpm->locality;
1068 	tpm->locality = locality;
1069 
1070 	/* Just check to see if the requested localit works */
1071 	access_bits = tpm_get8(tpm, TPM_ACCESS);
1072 	access_bits &= (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID);
1073 
1074 	/* this was just a check, not a request to switch */
1075 	tpm->locality = old_locality;
1076 
1077 	if (access_bits == (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
1078 		return (DDI_SUCCESS);
1079 	} else {
1080 		return (DDI_FAILURE);
1081 	}
1082 }
1083 
1084 /* Request the TPM to be in the given locality */
1085 static int
1086 tis_request_locality(tpm_state_t *tpm, char locality) {
1087 	clock_t timeout;
1088 	int ret;
1089 	char *myname = "tis_request_locality";
1090 
1091 	ASSERT(tpm != NULL && locality >= 0 && locality < 5);
1092 
1093 	ret = tis_check_active_locality(tpm, locality);
1094 
1095 	if (ret == DDI_SUCCESS) {
1096 		/* Locality is already active */
1097 		tpm->locality = locality;
1098 		return (DDI_SUCCESS);
1099 	}
1100 
1101 	tpm_put8(tpm, TPM_ACCESS, TPM_ACCESS_REQUEST_USE);
1102 	timeout = ddi_get_lbolt() + tpm->timeout_a;
1103 
1104 	/* Using polling */
1105 	while (tis_check_active_locality(tpm, locality)
1106 		!= DDI_SUCCESS) {
1107 		if (ddi_get_lbolt() >= timeout) {
1108 			cmn_err(CE_WARN, "%s (interrupt-disabled) "
1109 			    "tis_request_locality timed out (timeout_a = %ld)",
1110 			    myname, tpm->timeout_a);
1111 			return (DDI_FAILURE);
1112 		}
1113 		delay(tpm->timeout_poll);
1114 	}
1115 
1116 	tpm->locality = locality;
1117 	return (DDI_SUCCESS);
1118 }
1119 
1120 /* Read the status register */
1121 static uint8_t
1122 tis_get_status(tpm_state_t *tpm) {
1123 	return (tpm_get8(tpm, TPM_STS));
1124 }
1125 
1126 static int
1127 tpm_wait_for_stat(tpm_state_t *tpm, uint8_t mask, clock_t timeout) {
1128 	char *myname = "tpm_wait_for_stat";
1129 	clock_t absolute_timeout = ddi_get_lbolt() + timeout;
1130 
1131 	/* Using polling */
1132 	while ((tis_get_status(tpm) & mask) != mask) {
1133 		if (ddi_get_lbolt() >= absolute_timeout) {
1134 			/* Timeout reached */
1135 			cmn_err(CE_WARN, "%s: using "
1136 			    "polling - reached timeout (%ld usecs)",
1137 			    myname, drv_hztousec(timeout));
1138 			return (DDI_FAILURE);
1139 		}
1140 		delay(tpm->timeout_poll);
1141 	}
1142 	return (DDI_SUCCESS);
1143 }
1144 
1145 /*
1146  * Initialize TPM device
1147  * 1. Find out supported interrupt capabilities
1148  * 2. Set up interrupt handler if supported (some BIOSes don't support
1149  * interrupts for TPMS, in which case we set up polling)
1150  * 3. Determine timeouts and commands duration
1151  */
1152 static int
1153 tis_init(tpm_state_t *tpm) {
1154 	uint32_t intf_caps;
1155 	int ret;
1156 	char *myname = "tis_init";
1157 
1158 	/*
1159 	 * Temporarily set up timeouts before we get the real timeouts
1160 	 * by issuing TPM_CAP commands (but to issue TPM_CAP commands,
1161 	 * you need TIMEOUTs defined...chicken and egg problem here.
1162 	 * TPM timeouts: Convert the milliseconds to clock cycles
1163 	 */
1164 	tpm->timeout_a = drv_usectohz(TIS_TIMEOUT_A);
1165 	tpm->timeout_b = drv_usectohz(TIS_TIMEOUT_B);
1166 	tpm->timeout_c = drv_usectohz(TIS_TIMEOUT_C);
1167 	tpm->timeout_d = drv_usectohz(TIS_TIMEOUT_D);
1168 	/*
1169 	 * Do the same with the duration (real duration will be filled out
1170 	 * when we call TPM_GetCapability to get the duration values from
1171 	 * the TPM itself).
1172 	 */
1173 	tpm->duration[TPM_SHORT] = drv_usectohz(TPM_DEFAULT_DURATION);
1174 	tpm->duration[TPM_MEDIUM] = drv_usectohz(TPM_DEFAULT_DURATION);
1175 	tpm->duration[TPM_LONG] = drv_usectohz(TPM_DEFAULT_DURATION);
1176 	tpm->duration[TPM_UNDEFINED] = drv_usectohz(TPM_DEFAULT_DURATION);
1177 
1178 	/* Find out supported capabilities */
1179 	intf_caps = tpm_get32(tpm, TPM_INTF_CAP);
1180 
1181 	/* Upper 3 bytes should always return 0 */
1182 	if (intf_caps & 0x7FFFFF00) {
1183 #ifdef DEBUG
1184 		cmn_err(CE_WARN, "%s: bad intf_caps value 0x%0X",
1185 		    myname, intf_caps);
1186 #endif
1187 		return (DDI_FAILURE);
1188 	}
1189 
1190 	/* These two interrupts are mandatory */
1191 	if (!(intf_caps & TPM_INTF_INT_LOCALITY_CHANGE_INT)) {
1192 		cmn_err(CE_WARN, "%s: Mandatory capability Locality Change Int "
1193 		    "not supported", myname);
1194 		return (DDI_FAILURE);
1195 	}
1196 	if (!(intf_caps & TPM_INTF_INT_DATA_AVAIL_INT)) {
1197 		cmn_err(CE_WARN, "%s: Mandatory capability Data Available Int "
1198 		    "not supported", myname);
1199 		return (DDI_FAILURE);
1200 	}
1201 
1202 	/*
1203 	 * Before we start writing anything to TPM's registers,
1204 	 * make sure we are in locality 0
1205 	 */
1206 	ret = tis_request_locality(tpm, DEFAULT_LOCALITY);
1207 	if (ret != DDI_SUCCESS) {
1208 		cmn_err(CE_WARN, "%s: Unable to request locality %d", myname,
1209 		    DEFAULT_LOCALITY);
1210 		return (DDI_FAILURE);
1211 	} /* Now we can refer to the locality as tpm->locality */
1212 
1213 	tpm->timeout_poll = drv_usectohz(TPM_POLLING_TIMEOUT);
1214 	tpm->intr_enabled = 0;
1215 
1216 	/* Get the real timeouts from the TPM */
1217 	ret = tpm_get_timeouts(tpm);
1218 	if (ret != DDI_SUCCESS) {
1219 		cmn_err(CE_WARN, "%s: tpm_get_timeouts error", myname);
1220 		return (DDI_FAILURE);
1221 	}
1222 
1223 	ret = tpm_get_duration(tpm);
1224 	if (ret != DDI_SUCCESS) {
1225 		cmn_err(CE_WARN, "%s: tpm_get_duration error", myname);
1226 		return (DDI_FAILURE);
1227 	}
1228 
1229 	/* This gets the TPM version information */
1230 	ret = tpm_get_version(tpm);
1231 	if (ret != DDI_SUCCESS) {
1232 		cmn_err(CE_WARN, "%s: tpm_get_version error", myname);
1233 		return (DDI_FAILURE);
1234 	}
1235 
1236 	/*
1237 	 * Unless the TPM completes the test of its commands,
1238 	 * it can return an error when the untested commands are called
1239 	 */
1240 	ret = tpm_continue_selftest(tpm);
1241 	if (ret != DDI_SUCCESS) {
1242 		cmn_err(CE_WARN, "%s: tpm_continue_selftest error", myname);
1243 		return (DDI_FAILURE);
1244 	}
1245 	return (DDI_SUCCESS);
1246 }
1247 
1248 /*
1249  * Module Entry points
1250  */
1251 int
1252 _init(void)
1253 {
1254 	int ret;
1255 
1256 	ret = ddi_soft_state_init(&statep, sizeof (tpm_state_t), 1);
1257 	if (ret)
1258 {
1259 		cmn_err(CE_WARN, "ddi_soft_state_init failed: %d", ret);
1260 		return (ret);
1261 }
1262 	ret = mod_install(&tpm_ml);
1263 	if (ret != 0) {
1264 		cmn_err(CE_WARN, "_init: mod_install returned non-zero");
1265 		ddi_soft_state_fini(&statep);
1266 		return (ret);
1267 	}
1268 
1269 	return (ret);
1270 }
1271 
1272 int
1273 _info(struct modinfo *modinfop)
1274 {
1275 	int ret;
1276 	ret = mod_info(&tpm_ml, modinfop);
1277 	if (ret == 0)
1278 		cmn_err(CE_WARN, "mod_info failed: %d", ret);
1279 
1280 	return (ret);
1281 }
1282 
1283 int
1284 _fini()
1285 {
1286 	int ret;
1287 
1288 	ret = mod_remove(&tpm_ml);
1289 	if (ret != 0)
1290 		return (ret);
1291 
1292 	ddi_soft_state_fini(&statep);
1293 
1294 	return (ret);
1295 }
1296 /* End of driver configuration functions */
1297 
1298 static int
1299 tpm_resume(tpm_state_t *tpm)
1300 {
1301 	mutex_enter(&tpm->pm_mutex);
1302 	if (!tpm->suspended) {
1303 		mutex_exit(&tpm->pm_mutex);
1304 		return (DDI_FAILURE);
1305 	}
1306 	tpm->suspended = 0;
1307 	cv_broadcast(&tpm->suspend_cv);
1308 	mutex_exit(&tpm->pm_mutex);
1309 
1310 	return (DDI_SUCCESS);
1311 }
1312 
1313 #ifdef sun4v
1314 static uint64_t hsvc_tpm_minor = 0;
1315 static hsvc_info_t hsvc_tpm = {
1316 	HSVC_REV_1, NULL, HSVC_GROUP_TPM, 1, 0, NULL
1317 };
1318 #endif
1319 
1320 /*
1321  * Sun DDI/DDK entry points
1322  */
1323 static int
1324 tpm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1325 {
1326 	int ret;
1327 	int instance;
1328 #ifndef sun4v
1329 	int idx, nregs;
1330 #endif
1331 	char *myname = "tpm_attach";
1332 	tpm_state_t *tpm = NULL;
1333 
1334 	ASSERT(dip != NULL);
1335 
1336 	instance = ddi_get_instance(dip);
1337 	if (instance < 0)
1338 		return (DDI_FAILURE);
1339 
1340 	/* Nothing out of ordinary here */
1341 	switch (cmd) {
1342 	case DDI_ATTACH:
1343 		if (ddi_soft_state_zalloc(statep, instance) == DDI_SUCCESS) {
1344 			tpm = ddi_get_soft_state(statep, instance);
1345 			if (tpm == NULL) {
1346 				cmn_err(CE_WARN,
1347 				    "%s: cannot get state information.",
1348 				    myname);
1349 				return (DDI_FAILURE);
1350 			}
1351 			tpm->dip = dip;
1352 		} else {
1353 			cmn_err(CE_WARN,
1354 			    "%s: cannot allocate state information.",
1355 			    myname);
1356 			return (DDI_FAILURE);
1357 		}
1358 		break;
1359 	case DDI_RESUME:
1360 		tpm = ddi_get_soft_state(statep, instance);
1361 		if (tpm == NULL) {
1362 			cmn_err(CE_WARN, "%s: cannot get state information.",
1363 			    myname);
1364 			return (DDI_FAILURE);
1365 		}
1366 		return (tpm_resume(tpm));
1367 	default:
1368 		cmn_err(CE_WARN, "%s: cmd %d is not implemented", myname, cmd);
1369 		ret = DDI_FAILURE;
1370 		goto FAIL;
1371 	}
1372 
1373 	/* Zeroize the flag, which is used to keep track of what is allocated */
1374 	tpm->flags = 0;
1375 
1376 #ifdef sun4v
1377 	ret = hsvc_register(&hsvc_tpm, &hsvc_tpm_minor);
1378 	if (ret != 0) {
1379 		cmn_err(CE_WARN, "%s: failed to register with "
1380 		    "hypervisor: 0x%0x", myname, ret);
1381 		goto FAIL;
1382 	}
1383 	tpm->flags |= TPM_HSVC_REGISTERED;
1384 #else
1385 	tpm->accattr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
1386 	tpm->accattr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
1387 	tpm->accattr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1388 
1389 	idx = 0;
1390 	ret = ddi_dev_nregs(tpm->dip, &nregs);
1391 	if (ret != DDI_SUCCESS)
1392 		goto FAIL;
1393 
1394 	/*
1395 	 * TPM vendors put the TPM registers in different
1396 	 * slots in their register lists.  They are not always
1397 	 * the 1st set of registers, for instance.
1398 	 * Loop until we find the set that matches the expected
1399 	 * register size (0x5000).
1400 	 */
1401 	for (idx = 0; idx < nregs; idx++) {
1402 		off_t regsize;
1403 
1404 		if ((ret = ddi_dev_regsize(tpm->dip, idx, &regsize)) !=
1405 		    DDI_SUCCESS)
1406 			goto FAIL;
1407 		/* The TIS spec says the TPM registers must be 0x5000 bytes */
1408 		if (regsize == 0x5000)
1409 			break;
1410 	}
1411 	if (idx == nregs)
1412 		return (DDI_FAILURE);
1413 
1414 	ret = ddi_regs_map_setup(tpm->dip, idx, (caddr_t *)&tpm->addr,
1415 	    (offset_t)0, (offset_t)0x5000,
1416 	    &tpm->accattr, &tpm->handle);
1417 
1418 	if (ret != DDI_SUCCESS) {
1419 		goto FAIL;
1420 	}
1421 	tpm->flags |= TPM_DIDREGSMAP;
1422 #endif
1423 	/* Enable TPM device according to the TIS specification */
1424 	ret = tis_init(tpm);
1425 	if (ret != DDI_SUCCESS) {
1426 		cmn_err(CE_WARN, "%s: tis_init() failed with error %d",
1427 		    myname, ret);
1428 
1429 		/* We need to clean up the ddi_regs_map_setup call */
1430 		if (tpm->flags & TPM_DIDREGSMAP) {
1431 			ddi_regs_map_free(&tpm->handle);
1432 			tpm->handle = NULL;
1433 			tpm->flags &= ~TPM_DIDREGSMAP;
1434 		}
1435 		goto FAIL;
1436 	}
1437 
1438 	/* Initialize the inter-process lock */
1439 	mutex_init(&tpm->dev_lock, NULL, MUTEX_DRIVER, NULL);
1440 	mutex_init(&tpm->pm_mutex, NULL, MUTEX_DRIVER, NULL);
1441 	cv_init(&tpm->suspend_cv, NULL, CV_DRIVER, NULL);
1442 
1443 	/* Set the suspend/resume property */
1444 	(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
1445 	    "pm-hardware-state", "needs-suspend-resume");
1446 
1447 	mutex_enter(&tpm->pm_mutex);
1448 	tpm->suspended = 0;
1449 	mutex_exit(&tpm->pm_mutex);
1450 
1451 	tpm->flags |= TPM_DID_MUTEX;
1452 
1453 	/* Initialize the buffer and the lock associated with it */
1454 	tpm->bufsize = TPM_IO_BUF_SIZE;
1455 	tpm->iobuf = kmem_zalloc((sizeof (uint8_t))*(tpm->bufsize), KM_SLEEP);
1456 	tpm->flags |= TPM_DID_IO_ALLOC;
1457 
1458 	mutex_init(&tpm->iobuf_lock, NULL, MUTEX_DRIVER, NULL);
1459 	tpm->flags |= TPM_DID_IO_MUTEX;
1460 
1461 	cv_init(&tpm->iobuf_cv, NULL, CV_DRIVER, NULL);
1462 	tpm->flags |= TPM_DID_IO_CV;
1463 
1464 	/* Create minor node */
1465 	ret = ddi_create_minor_node(dip, "tpm", S_IFCHR, ddi_get_instance(dip),
1466 	    DDI_PSEUDO, 0);
1467 	if (ret != DDI_SUCCESS) {
1468 		cmn_err(CE_WARN, "%s: ddi_create_minor_node failed", myname);
1469 		goto FAIL;
1470 	}
1471 	tpm->flags |= TPM_DIDMINOR;
1472 
1473 #ifdef KCF_TPM_RNG_PROVIDER
1474 	/* register RNG with kcf */
1475 	if (tpmrng_register(tpm) != DDI_SUCCESS)
1476 		cmn_err(CE_WARN, "%s: tpm RNG failed to register with kcf",
1477 		    myname);
1478 #endif
1479 
1480 	return (DDI_SUCCESS);
1481 FAIL:
1482 	cmn_err(CE_WARN, "%s: tpm failed to attach", myname);
1483 	if (tpm != NULL) {
1484 		tpm_cleanup(dip, tpm);
1485 		ddi_soft_state_free(statep, instance);
1486 		tpm = NULL;
1487 	}
1488 
1489 	return (DDI_FAILURE);
1490 }
1491 
1492 /*
1493  * Called by tpm_detach and tpm_attach (only on failure)
1494  * Free up the resources that are allocated
1495  */
1496 static void
1497 tpm_cleanup(dev_info_t *dip, tpm_state_t *tpm)
1498 {
1499 	if (tpm == NULL)
1500 		return;
1501 
1502 #ifdef KCF_TPM_RNG_PROVIDER
1503 	(void) tpmrng_unregister(tpm);
1504 #endif
1505 
1506 #ifdef sun4v
1507 	if (tpm->flags & TPM_HSVC_REGISTERED) {
1508 		(void) hsvc_unregister(&hsvc_tpm);
1509 		tpm->flags &= ~(TPM_HSVC_REGISTERED);
1510 	}
1511 #endif
1512 	if (tpm->flags & TPM_DID_MUTEX) {
1513 		mutex_destroy(&tpm->dev_lock);
1514 		tpm->flags &= ~(TPM_DID_MUTEX);
1515 	}
1516 	if (tpm->flags & TPM_DID_IO_ALLOC) {
1517 		ASSERT(tpm->iobuf != NULL);
1518 		kmem_free(tpm->iobuf, (sizeof (uint8_t))*(tpm->bufsize));
1519 		tpm->flags &= ~(TPM_DID_IO_ALLOC);
1520 	}
1521 	if (tpm->flags & TPM_DID_IO_MUTEX) {
1522 		mutex_destroy(&tpm->iobuf_lock);
1523 		tpm->flags &= ~(TPM_DID_IO_MUTEX);
1524 	}
1525 	if (tpm->flags & TPM_DID_IO_CV) {
1526 		cv_destroy(&tpm->iobuf_cv);
1527 		tpm->flags &= ~(TPM_DID_IO_CV);
1528 	}
1529 	if (tpm->flags & TPM_DIDREGSMAP) {
1530 		/* Free the mapped addresses */
1531 		if (tpm->handle != NULL)
1532 			ddi_regs_map_free(&tpm->handle);
1533 		tpm->flags &= ~(TPM_DIDREGSMAP);
1534 	}
1535 	if (tpm->flags & TPM_DIDMINOR) {
1536 		/* Remove minor node */
1537 		ddi_remove_minor_node(dip, NULL);
1538 		tpm->flags &= ~(TPM_DIDMINOR);
1539 	}
1540 }
1541 
1542 static int
1543 tpm_suspend(tpm_state_t *tpm)
1544 {
1545 	if (tpm == NULL)
1546 		return (DDI_FAILURE);
1547 	mutex_enter(&tpm->pm_mutex);
1548 	if (tpm->suspended) {
1549 		mutex_exit(&tpm->pm_mutex);
1550 		return (DDI_SUCCESS);
1551 	}
1552 	tpm->suspended = 1;
1553 	mutex_exit(&tpm->pm_mutex);
1554 
1555 	return (DDI_SUCCESS);
1556 }
1557 
1558 static int
1559 tpm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1560 {
1561 	char *myname = "tpm_detach";
1562 	int instance;
1563 	tpm_state_t *tpm;
1564 
1565 	ASSERT(dip != NULL);
1566 
1567 	instance = ddi_get_instance(dip);
1568 	if (instance < 0)
1569 		return (DDI_FAILURE);
1570 
1571 	if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
1572 		cmn_err(CE_WARN, "%s: stored pointer to tpm state is NULL",
1573 		    myname);
1574 		return (ENXIO);
1575 	}
1576 
1577 	switch (cmd) {
1578 	case DDI_DETACH:
1579 		/* Body is after the switch stmt */
1580 		break;
1581 	case DDI_SUSPEND:
1582 		return (tpm_suspend(tpm));
1583 	default:
1584 		cmn_err(CE_WARN, "%s: case %d not implemented", myname, cmd);
1585 		return (DDI_FAILURE);
1586 	}
1587 
1588 	/* Since we are freeing tpm structure, we need to gain the lock */
1589 
1590 	tpm_cleanup(dip, tpm);
1591 
1592 	mutex_destroy(&tpm->pm_mutex);
1593 	cv_destroy(&tpm->suspend_cv);
1594 
1595 	/* Free the soft state */
1596 	ddi_soft_state_free(statep, instance);
1597 	tpm = NULL;
1598 
1599 	return (DDI_SUCCESS);
1600 }
1601 
1602 /*ARGSUSED*/
1603 static int
1604 tpm_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp)
1605 {
1606 	char *myname = "tpm_getinfo";
1607 	int instance;
1608 	tpm_state_t *tpm;
1609 
1610 	instance = ddi_get_instance(dip);
1611 	if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
1612 		cmn_err(CE_WARN, "%s: stored pointer to tpm state is NULL",
1613 		    myname);
1614 		return (DDI_FAILURE);
1615 	}
1616 
1617 	switch (cmd) {
1618 	case DDI_INFO_DEVT2DEVINFO:
1619 		*resultp = tpm->dip;
1620 		break;
1621 	case DDI_INFO_DEVT2INSTANCE:
1622 		*resultp = 0;
1623 		break;
1624 	default:
1625 		cmn_err(CE_WARN, "%s: cmd %d is not implemented", myname, cmd);
1626 		return (DDI_FAILURE);
1627 	}
1628 	return (DDI_SUCCESS);
1629 }
1630 
1631 /*
1632  * Driver entry points
1633  */
1634 
1635 /*ARGSUSED*/
1636 static int
1637 tpm_open(dev_t *devp, int flag, int otyp, cred_t *cred)
1638 {
1639 	char *myname = "tpm_open";
1640 	int instance;
1641 	tpm_state_t *tpm;
1642 
1643 	ASSERT(devp != NULL);
1644 
1645 	instance = getminor(*devp);
1646 	if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
1647 		cmn_err(CE_WARN, "%s: stored pointer to tpm state is NULL",
1648 		    myname);
1649 		return (ENXIO);
1650 	}
1651 	if (otyp != OTYP_CHR) {
1652 		cmn_err(CE_WARN, "%s: otyp(%d) != OTYP_CHR(%d)",
1653 		    myname, otyp, OTYP_CHR);
1654 		return (EINVAL);
1655 	}
1656 	TPM_EXCLUSIVE_LOCK(tpm);
1657 
1658 	mutex_enter(&tpm->dev_lock);
1659 	if (tpm->dev_held) {
1660 		cmn_err(CE_WARN, "%s: the device is already being used",
1661 		    myname);
1662 		mutex_exit(&tpm->dev_lock);
1663 		return (EBUSY);
1664 	}
1665 
1666 	/* The device is free so mark it busy */
1667 	tpm->dev_held = 1;
1668 	mutex_exit(&tpm->dev_lock);
1669 
1670 	return (0);
1671 }
1672 
1673 /*ARGSUSED*/
1674 static int
1675 tpm_close(dev_t dev, int flag, int otyp, cred_t *cred)
1676 {
1677 	char *myname = "tpm_close";
1678 	int instance;
1679 	tpm_state_t *tpm;
1680 
1681 	instance = getminor(dev);
1682 	if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
1683 		cmn_err(CE_WARN, "%s: stored pointer to tpm state is NULL",
1684 		    myname);
1685 		return (ENXIO);
1686 	}
1687 	if (otyp != OTYP_CHR) {
1688 		cmn_err(CE_WARN, "%s: otyp(%d) != OTYP_CHR(%d)",
1689 		    myname, otyp, OTYP_CHR);
1690 		return (EINVAL);
1691 	}
1692 	TPM_EXCLUSIVE_LOCK(tpm);
1693 
1694 	ASSERT(tpm->dev_held);
1695 
1696 	mutex_enter(&tpm->dev_lock);
1697 	ASSERT(mutex_owned(&tpm->dev_lock));
1698 	tpm->dev_held = 0;
1699 	mutex_exit(&tpm->dev_lock);
1700 
1701 	return (0);
1702 }
1703 
1704 /*ARGSUSED*/
1705 static int
1706 tpm_read(dev_t dev, struct uio *uiop, cred_t *credp)
1707 {
1708 	int ret;
1709 	uint32_t size;
1710 	char *myname = "tpm_read";
1711 	int instance;
1712 	tpm_state_t *tpm;
1713 
1714 	instance = getminor(dev);
1715 	if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
1716 		cmn_err(CE_WARN, "%s: stored pointer to tpm state is NULL",
1717 		    myname);
1718 		return (ENXIO);
1719 	}
1720 	if (uiop == NULL) {
1721 		cmn_err(CE_WARN, "%s: passed in uiop is NULL", myname);
1722 		return (EFAULT);
1723 	}
1724 
1725 	TPM_EXCLUSIVE_LOCK(tpm);
1726 
1727 	/* Receive the data after requiring the lock */
1728 	ret = tpm_io_lock(tpm);
1729 
1730 	/* Timeout reached */
1731 	if (ret == ETIME)
1732 		return (ret);
1733 
1734 	if (uiop->uio_resid > tpm->bufsize) {
1735 		cmn_err(CE_WARN, "%s: read_in data is bigger "
1736 		    "than tpm->bufsize:read in:%d, bufsiz:%d",
1737 		    myname, (int)uiop->uio_resid, (int)tpm->bufsize);
1738 		ret = EIO;
1739 		goto OUT;
1740 	}
1741 
1742 	ret = tis_recv_data(tpm, tpm->iobuf, tpm->bufsize);
1743 	if (ret < TPM_HEADER_SIZE) {
1744 		cmn_err(CE_WARN, "%s: tis_recv_data returned error", myname);
1745 		ret = EIO;
1746 		goto OUT;
1747 	}
1748 
1749 	size = load32(tpm->iobuf, 2);
1750 	if (ret != size) {
1751 		cmn_err(CE_WARN, "%s: tis_recv_data:"
1752 		    "expected size=%d, actually read=%d",
1753 		    myname, size, ret);
1754 		ret = EIO;
1755 		goto OUT;
1756 	}
1757 
1758 	/* Send the buffer from the kernel to the userspace */
1759 	ret = uiomove(tpm->iobuf, size, UIO_READ, uiop);
1760 	if (ret) {
1761 		cmn_err(CE_WARN, "%s: uiomove returned error", myname);
1762 		goto OUT;
1763 	}
1764 
1765 	/* Zeroize the buffer... */
1766 	bzero(tpm->iobuf, tpm->bufsize);
1767 	ret = DDI_SUCCESS;
1768 OUT:
1769 	/* We are done now: wake up the waiting threads */
1770 	tpm_unlock(tpm);
1771 
1772 	return (ret);
1773 }
1774 
1775 /*ARGSUSED*/
1776 static int
1777 tpm_write(dev_t dev, struct uio *uiop, cred_t *credp)
1778 {
1779 	int ret;
1780 	size_t len;
1781 	uint32_t size;
1782 	char *myname = "tpm_write";
1783 	int instance;
1784 	tpm_state_t *tpm;
1785 
1786 	instance = getminor(dev);
1787 	if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) {
1788 		cmn_err(CE_WARN, "%s: stored pointer to tpm state is NULL",
1789 		    myname);
1790 		return (ENXIO);
1791 	}
1792 
1793 	if (uiop == NULL) {
1794 		cmn_err(CE_WARN, "%s: passed in uiop is NULL", myname);
1795 		return (EFAULT);
1796 	}
1797 
1798 	TPM_EXCLUSIVE_LOCK(tpm);
1799 
1800 	len = uiop->uio_resid;
1801 	if (len == 0) {
1802 		cmn_err(CE_WARN, "%s: requested read of len 0", myname);
1803 		return (0);
1804 	}
1805 
1806 	/* Get the lock for using iobuf */
1807 	ret = tpm_io_lock(tpm);
1808 	/* Timeout Reached */
1809 	if (ret == ETIME)
1810 		return (ret);
1811 
1812 	/* Copy the header and parse the structure to find out the size... */
1813 	ret = uiomove(tpm->iobuf, TPM_HEADER_SIZE, UIO_WRITE, uiop);
1814 	if (ret) {
1815 		cmn_err(CE_WARN, "%s: uiomove returned error"
1816 		    "while getting the the header",
1817 		    myname);
1818 		goto OUT;
1819 	}
1820 
1821 	/* Get the buffersize from the command buffer structure */
1822 	size = load32(tpm->iobuf, TPM_PARAMSIZE_OFFSET);
1823 
1824 	/* Copy the command to the contiguous buffer */
1825 	if (size > tpm->bufsize) {
1826 		cmn_err(CE_WARN, "%s: size %d is greater than "
1827 		    "the tpm's input buffer size %d",
1828 		    myname, (int)size, (int)tpm->bufsize);
1829 		ret = ENXIO;
1830 		goto OUT;
1831 	}
1832 
1833 	/* Copy the buffer from the userspace to kernel */
1834 	ret = uiomove(tpm->iobuf+TPM_HEADER_SIZE, size-TPM_HEADER_SIZE,
1835 	    UIO_WRITE, uiop);
1836 
1837 	if (ret) {
1838 		cmn_err(CE_WARN, "%s: uiomove returned error"
1839 		    "while getting the rest of the command", myname);
1840 		goto OUT;
1841 	}
1842 
1843 	/* Send the command */
1844 	ret = tis_send_data(tpm, tpm->iobuf, size);
1845 	if (ret != DDI_SUCCESS) {
1846 		cmn_err(CE_WARN, "%s: tis_send_data returned error", myname);
1847 		ret = EFAULT;
1848 		goto OUT;
1849 	}
1850 
1851 	/* Zeroize the buffer... */
1852 	bzero(tpm->iobuf, tpm->bufsize);
1853 	ret = DDI_SUCCESS;
1854 OUT:
1855 	tpm_unlock(tpm);
1856 	return (ret);
1857 }
1858 
1859 /*
1860  * This is to deal with the contentions for the iobuf
1861  */
1862 static inline int
1863 tpm_io_lock(tpm_state_t *tpm)
1864 {
1865 	int ret;
1866 	clock_t timeout;
1867 
1868 	mutex_enter(&tpm->iobuf_lock);
1869 	ASSERT(mutex_owned(&tpm->iobuf_lock));
1870 
1871 	timeout = ddi_get_lbolt() + drv_usectohz(TPM_IO_TIMEOUT);
1872 
1873 	/* Wait until the iobuf becomes free with the timeout */
1874 	while (tpm->iobuf_inuse) {
1875 		ret = cv_timedwait(&tpm->iobuf_cv, &tpm->iobuf_lock, timeout);
1876 		if (ret <= 0) {
1877 			/* Timeout reached */
1878 			mutex_exit(&tpm->iobuf_lock);
1879 #ifdef DEBUG
1880 			cmn_err(CE_WARN, "tpm_io_lock:iorequest timed out");
1881 #endif
1882 			return (CRYPTO_BUSY);
1883 		}
1884 	}
1885 	tpm->iobuf_inuse = 1;
1886 	mutex_exit(&tpm->iobuf_lock);
1887 	return (0);
1888 }
1889 
1890 /*
1891  * This is to deal with the contentions for the iobuf
1892  */
1893 static inline void
1894 tpm_unlock(tpm_state_t *tpm)
1895 {
1896 	/* Wake up the waiting threads */
1897 	mutex_enter(&tpm->iobuf_lock);
1898 	ASSERT(tpm->iobuf_inuse == 1 && mutex_owned(&tpm->iobuf_lock));
1899 	tpm->iobuf_inuse = 0;
1900 	cv_broadcast(&tpm->iobuf_cv);
1901 	mutex_exit(&tpm->iobuf_lock);
1902 }
1903 
1904 #ifdef KCF_TPM_RNG_PROVIDER
1905 /*
1906  * Random number generator entry points
1907  */
1908 static void
1909 strncpy_spacepad(uchar_t *s1, char *s2, int n)
1910 {
1911 	int s2len = strlen(s2);
1912 	(void) strncpy((char *)s1, s2, n);
1913 	if (s2len < n)
1914 		(void) memset(s1 + s2len, ' ', n - s2len);
1915 }
1916 
1917 /*ARGSUSED*/
1918 static int
1919 tpmrng_ext_info(crypto_provider_handle_t prov,
1920 	crypto_provider_ext_info_t *ext_info,
1921 	crypto_req_handle_t cfreq)
1922 {
1923 	tpm_state_t *tpm = (tpm_state_t *)prov;
1924 	char buf[64];
1925 
1926 	if (tpm == NULL)
1927 		return (DDI_FAILURE);
1928 
1929 	strncpy_spacepad(ext_info->ei_manufacturerID,
1930 	    (char *)tpm->vers_info.tpmVendorID,
1931 	    sizeof (ext_info->ei_manufacturerID));
1932 
1933 	strncpy_spacepad(ext_info->ei_model, "0",
1934 	    sizeof (ext_info->ei_model));
1935 	strncpy_spacepad(ext_info->ei_serial_number, "0",
1936 	    sizeof (ext_info->ei_serial_number));
1937 
1938 	ext_info->ei_flags = CRYPTO_EXTF_RNG | CRYPTO_EXTF_SO_PIN_LOCKED;
1939 	ext_info->ei_max_session_count = CRYPTO_EFFECTIVELY_INFINITE;
1940 	ext_info->ei_max_pin_len = 0;
1941 	ext_info->ei_min_pin_len = 0;
1942 	ext_info->ei_total_public_memory = CRYPTO_UNAVAILABLE_INFO;
1943 	ext_info->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO;
1944 	ext_info->ei_total_private_memory = CRYPTO_UNAVAILABLE_INFO;
1945 	ext_info->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO;
1946 	ext_info->ei_time[0] = 0;
1947 
1948 	ext_info->ei_hardware_version.cv_major = tpm->vers_info.version.major;
1949 	ext_info->ei_hardware_version.cv_minor = tpm->vers_info.version.minor;
1950 	ext_info->ei_firmware_version.cv_major =
1951 	    tpm->vers_info.version.revMajor;
1952 	ext_info->ei_firmware_version.cv_minor =
1953 	    tpm->vers_info.version.revMinor;
1954 
1955 	(void) snprintf(buf, sizeof (buf), "tpmrng TPM RNG");
1956 
1957 	strncpy_spacepad(ext_info->ei_label, buf,
1958 	    sizeof (ext_info->ei_label));
1959 #undef	BUFSZ
1960 	return (CRYPTO_SUCCESS);
1961 
1962 }
1963 
1964 static int
1965 tpmrng_register(tpm_state_t *tpm)
1966 {
1967 	int		ret;
1968 	char 		ID[64];
1969 	crypto_mech_name_t	*rngmech;
1970 
1971 	ASSERT(tpm != NULL);
1972 
1973 	(void) snprintf(ID, sizeof (ID), "tpmrng %s", IDENT_TPMRNG);
1974 
1975 	tpmrng_prov_info.pi_provider_description = ID;
1976 	tpmrng_prov_info.pi_provider_dev.pd_hw = tpm->dip;
1977 	tpmrng_prov_info.pi_provider_handle = tpm;
1978 
1979 	ret = crypto_register_provider(&tpmrng_prov_info, &tpm->n_prov);
1980 	if (ret != CRYPTO_SUCCESS) {
1981 		tpm->n_prov = NULL;
1982 		return (DDI_FAILURE);
1983 	}
1984 
1985 	crypto_provider_notification(tpm->n_prov, CRYPTO_PROVIDER_READY);
1986 
1987 	rngmech = kmem_zalloc(strlen("random") + 1, KM_SLEEP);
1988 	(void) memcpy(rngmech, "random", 6);
1989 	ret = crypto_load_dev_disabled("tpm", ddi_get_instance(tpm->dip),
1990 	    1, rngmech);
1991 	if (ret != CRYPTO_SUCCESS) {
1992 		cmn_err(CE_WARN, "crypto_load_dev_disabled failed (%d)", ret);
1993 	}
1994 	return (DDI_SUCCESS);
1995 }
1996 
1997 static int
1998 tpmrng_unregister(tpm_state_t *tpm)
1999 {
2000 	int ret;
2001 	ASSERT(tpm != NULL);
2002 	if (tpm->n_prov) {
2003 		ret = crypto_unregister_provider(tpm->n_prov);
2004 		tpm->n_prov = NULL;
2005 		if (ret != CRYPTO_SUCCESS)
2006 			return (DDI_FAILURE);
2007 	}
2008 	return (DDI_SUCCESS);
2009 }
2010 
2011 /*ARGSUSED*/
2012 static void
2013 tpmrng_provider_status(crypto_provider_handle_t provider, uint_t *status)
2014 {
2015 	*status = CRYPTO_PROVIDER_READY;
2016 }
2017 
2018 /*ARGSUSED*/
2019 static int
2020 tpmrng_seed_random(crypto_provider_handle_t provider, crypto_session_id_t sid,
2021     uchar_t *buf, size_t len, uint_t entropy_est, uint32_t flags,
2022     crypto_req_handle_t req)
2023 {
2024 	int ret;
2025 	tpm_state_t *tpm;
2026 	uint32_t len32;
2027 	/* Max length of seed is 256 bytes, add 14 for header. */
2028 	uint8_t cmdbuf[270] = {
2029 		0, 193,		/* TPM_TAG_RQU COMMAND */
2030 		0, 0, 0, 0x0A,	/* paramsize in bytes */
2031 		0, 0, 0, TPM_ORD_StirRandom,
2032 		0, 0, 0, 0 	/* number of input bytes (< 256) */
2033 	};
2034 	uint32_t buflen;
2035 
2036 	if (len == 0 || len > 255 || buf == NULL)
2037 		return (CRYPTO_ARGUMENTS_BAD);
2038 
2039 	tpm = (tpm_state_t *)provider;
2040 	if (tpm == NULL)
2041 		return (CRYPTO_INVALID_CONTEXT);
2042 
2043 	/* Acquire lock for exclusive use of TPM */
2044 	TPM_EXCLUSIVE_LOCK(tpm);
2045 
2046 	ret = tpm_io_lock(tpm);
2047 	/* Timeout reached */
2048 	if (ret == CRYPTO_BUSY)
2049 		return (ret);
2050 
2051 	/* TPM only handles 32 bit length, so truncate if too big. */
2052 	len32 = (uint32_t)len;
2053 	buflen = len32 + 14;
2054 
2055 	/* The length must be in network order */
2056 	buflen = htonl(buflen);
2057 	bcopy(&buflen, cmdbuf + 2, sizeof (uint32_t));
2058 
2059 	/* Convert it back */
2060 	buflen = ntohl(buflen);
2061 
2062 	/* length must be in network order */
2063 	len32 = htonl(len32);
2064 	bcopy(&len32, cmdbuf + 10, sizeof (uint32_t));
2065 
2066 	/* convert it back */
2067 	len32 = ntohl(len32);
2068 
2069 	bcopy(buf,  cmdbuf + 14, len32);
2070 
2071 	ret = itpm_command(tpm, cmdbuf, buflen);
2072 	tpm_unlock(tpm);
2073 
2074 	if (ret != DDI_SUCCESS) {
2075 #ifdef DEBUG
2076 		cmn_err(CE_WARN, "tpmrng_seed_random failed");
2077 #endif
2078 		return (CRYPTO_FAILED);
2079 	}
2080 
2081 	return (CRYPTO_SUCCESS);
2082 }
2083 
2084 /* ARGSUSED */
2085 static int
2086 tpmrng_generate_random(crypto_provider_handle_t provider,
2087     crypto_session_id_t sid, uchar_t *buf, size_t len, crypto_req_handle_t req)
2088 {
2089 	int ret;
2090 	tpm_state_t *tpm;
2091 	uint8_t hdr[14] = {
2092 		0, 193,		/* TPM_TAG_RQU COMMAND */
2093 		0, 0, 0, 14,	/* paramsize in bytes */
2094 		0, 0, 0, TPM_ORD_GetRandom,
2095 		0, 0, 0, 0
2096 	};
2097 	uint8_t *cmdbuf = NULL;
2098 	uint32_t len32 = (uint32_t)len;
2099 	uint32_t buflen = len32 + sizeof (hdr);
2100 
2101 	if (len == 0 || buf == NULL)
2102 		return (CRYPTO_ARGUMENTS_BAD);
2103 
2104 	tpm = (tpm_state_t *)provider;
2105 	if (tpm == NULL)
2106 		return (CRYPTO_INVALID_CONTEXT);
2107 
2108 	TPM_EXCLUSIVE_LOCK(tpm);
2109 
2110 	ret = tpm_io_lock(tpm);
2111 	/* Timeout reached */
2112 	if (ret == CRYPTO_BUSY)
2113 		return (ret);
2114 
2115 	cmdbuf = kmem_zalloc(buflen, KM_SLEEP);
2116 	bcopy(hdr, cmdbuf, sizeof (hdr));
2117 
2118 	/* Length is written in network byte order */
2119 	len32 = htonl(len32);
2120 	bcopy(&len32, cmdbuf + 10, sizeof (uint32_t));
2121 
2122 	ret = itpm_command(tpm, cmdbuf, buflen);
2123 	if (ret != DDI_SUCCESS) {
2124 #ifdef DEBUG
2125 		cmn_err(CE_WARN, "tpmrng_generate_random failed");
2126 #endif
2127 		kmem_free(cmdbuf, buflen);
2128 		tpm_unlock(tpm);
2129 		return (CRYPTO_FAILED);
2130 	}
2131 
2132 	/* Find out how many bytes were really returned */
2133 	len32 = load32(cmdbuf, 10);
2134 
2135 	/* Copy the random bytes back to the callers buffer */
2136 	bcopy(cmdbuf + 14, buf, len32);
2137 
2138 	kmem_free(cmdbuf, buflen);
2139 	tpm_unlock(tpm);
2140 
2141 	return (CRYPTO_SUCCESS);
2142 }
2143 #endif /* KCF_TPM_RNG_PROVIDER */
2144