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