Mercurial > illumos > illumos-gate
changeset 10334:2f82b01640c4
6855414 Deliver SPARC support for TPM
6865428 pkcs11_tpm should be installed by default, or it won't be used
line wrap: on
line diff
--- a/usr/src/cmd/cmd-crypto/Makefile Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/cmd/cmd-crypto/Makefile Mon Aug 17 20:56:15 2009 -0700 @@ -30,12 +30,8 @@ digest \ elfsign \ pktool \ - kmfcfg - -# -# tpmadm is x86 only until we have SPARC support for the TSS and TPM -# -i386_SUBDIRS = tpmadm + kmfcfg \ + tpmadm $(CLOSED_BUILD)SUBDIRS1 += \ $(CLOSED)/cmd/cmd-crypto/kcfd
--- a/usr/src/cmd/cmd-crypto/etc/pkcs11.conf Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/cmd/cmd-crypto/etc/pkcs11.conf Mon Aug 17 20:56:15 2009 -0700 @@ -2,9 +2,8 @@ # CDDL HEADER START # # The contents of this file are subject to the terms of the -# Common Development and Distribution License, Version 1.0 only -# (the "License"). You may not use this file except in compliance -# with the License. +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. @@ -19,12 +18,9 @@ # # CDDL HEADER END # -# -# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# # /etc/crypto/pkcs11.conf # # Do NOT edit this file by hand. An administrator should use cryptoadm(1m) @@ -43,4 +39,5 @@ metaslot:metaslot_status=enabled;metaslot_auto_key_migrate=enabled;metaslot_token=Sun Software PKCS#11 softtoken;metaslot_slot=Sun Crypto Softtoken /usr/lib/security/$ISA/pkcs11_kernel.so /usr/lib/security/$ISA/pkcs11_softtoken.so +/usr/lib/security/$ISA/pkcs11_tpm.so # End SUNWcsr
--- a/usr/src/cmd/devfsadm/misc_link.c Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/cmd/devfsadm/misc_link.c Mon Aug 17 20:56:15 2009 -0700 @@ -184,7 +184,10 @@ }, { "pseudo", "ddi_pseudo", "fm", TYPE_EXACT | DRV_RE, ILEVEL_1, minor_name, - } + }, + { "pseudo", "ddi_pseudo", "tpm", + TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name + }, }; DEVFSADM_CREATE_INIT_V0(misc_cbt); @@ -217,7 +220,10 @@ }, { "pseudo", "^pfil$", RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all - } + }, + { "pseudo", "^tpm$", + RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all + }, }; /* Rules for gpio devices */
--- a/usr/src/lib/pkcs11/Makefile Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/lib/pkcs11/Makefile Mon Aug 17 20:56:15 2009 -0700 @@ -39,17 +39,13 @@ libkcfd # -# The PKCS11 TPM provider is only available for x86. -# -i386_SUBDIRS = pkcs11_tpm - -# # Don't build these for OpenSolaris, since they will be replaced by # binaries that are signed by ON Gatekeepers. # $(CLOSED_BUILD)SUBDIRS += \ pkcs11_kernel \ - pkcs11_softtoken + pkcs11_softtoken \ + pkcs11_tpm $(CLOSED_BUILD)SUBDIRS += $($(MACH)_SUBDIRS)
--- a/usr/src/lib/pkcs11/pkcs11_tpm/common/api_interface.c Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/lib/pkcs11/pkcs11_tpm/common/api_interface.c Mon Aug 17 20:56:15 2009 -0700 @@ -402,7 +402,8 @@ LOG("CloseAllSessions"); if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); - if (slotID > NUMBER_SLOTS_MANAGED) + + if (!global_shm->token_available || (slotID > NUMBER_SLOTS_MANAGED)) return (CKR_SLOT_ID_INVALID); /* * Proc Mutex is locked when we remove from the seesion list in @@ -1346,17 +1347,22 @@ pInfo->cryptokiVersion.major = 2; pInfo->cryptokiVersion.minor = 20; - if (open_tss_context(&hContext)) - return (CKR_FUNCTION_FAILED); - - (void) token_get_tpm_info(hContext, &td); + if (open_tss_context(&hContext) == 0) { + /* + * Only populate the TPM info if we can establish + * a context, but don't return failure because + * the framework needs to know some of the info. + */ + (void) token_get_tpm_info(hContext, &td); - (void) Tspi_Context_Close(hContext); + (void) Tspi_Context_Close(hContext); - (void) memcpy(pInfo->manufacturerID, &(td.token_info.manufacturerID), - sizeof (pInfo->manufacturerID) - 1); + (void) memcpy(pInfo->manufacturerID, + &(td.token_info.manufacturerID), + sizeof (pInfo->manufacturerID) - 1); - pInfo->flags = td.token_info.flags; + pInfo->flags = td.token_info.flags; + } (void) strcpy((char *)pInfo->libraryDescription, "PKCS11 Interface for TPM"); @@ -1372,12 +1378,12 @@ CK_MECHANISM_INFO_PTR pInfo) { CK_RV rv; - if (API_Initialized() == FALSE) { + if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); - } - if (slotID > NUMBER_SLOTS_MANAGED) { + + if (!global_shm->token_available || (slotID > NUMBER_SLOTS_MANAGED)) return (CKR_SLOT_ID_INVALID); - } + if (FuncList.ST_GetMechanismInfo) { rv = FuncList.ST_GetMechanismInfo(slotID, type, pInfo); } else { @@ -1393,13 +1399,13 @@ { CK_RV rv; - if (API_Initialized() == FALSE) { + if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); - } + if (! pulCount) return (CKR_ARGUMENTS_BAD); - if (slotID > NUMBER_SLOTS_MANAGED) + if (!global_shm->token_available || (slotID > NUMBER_SLOTS_MANAGED)) return (CKR_SLOT_ID_INVALID); if (FuncList.ST_GetMechanismList) { @@ -1499,13 +1505,13 @@ C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { - if (API_Initialized() == FALSE) { + if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); - } - if (!pInfo) { + + if (!pInfo) return (CKR_FUNCTION_FAILED); - } - if (slotID != TPM_SLOTID) + + if (!global_shm->token_available || (slotID > NUMBER_SLOTS_MANAGED)) return (CKR_SLOT_ID_INVALID); copy_slot_info(slotID, pInfo); @@ -1528,6 +1534,13 @@ return (CKR_FUNCTION_FAILED); count = 0; + /* + * If we can't talk to the TPM, present no slots + */ + if (!global_shm->token_available) { + *pulCount = 0; + return (CKR_OK); + } copy_slot_info(TPM_SLOTID, &slotInfo); if ((slotInfo.flags & CKF_TOKEN_PRESENT)) @@ -1551,15 +1564,15 @@ { CK_RV rv; - if (API_Initialized() == FALSE) { + if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); - } - if (! pInfo) { + + if (!pInfo) return (CKR_ARGUMENTS_BAD); - } - if (slotID > NUMBER_SLOTS_MANAGED) { + + if (!global_shm->token_available || (slotID > NUMBER_SLOTS_MANAGED)) return (CKR_SLOT_ID_INVALID); - } + slotID = TPM_SLOTID; if (FuncList.ST_GetTokenInfo) { rv = FuncList.ST_GetTokenInfo(slotID, pInfo); @@ -1651,24 +1664,23 @@ CK_RV rv; ST_SESSION_T rSession; - if (API_Initialized() == FALSE) { + if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); - } - if (! pPin && ulPinLen) { + + if (! pPin && ulPinLen) return (CKR_ARGUMENTS_BAD); - } - if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) { + + if (! Valid_Session((Session_Struct_t *)hSession, &rSession)) return (CKR_SESSION_HANDLE_INVALID); - } - if (rSession.slotID > NUMBER_SLOTS_MANAGED) { + if (rSession.slotID > NUMBER_SLOTS_MANAGED) return (CKR_SLOT_ID_INVALID); - } - if (FuncList.ST_InitPIN) { + + if (FuncList.ST_InitPIN) rv = FuncList.ST_InitPIN(rSession, pPin, ulPinLen); - } else { + else rv = CKR_FUNCTION_NOT_SUPPORTED; - } + return (rv); } @@ -1680,20 +1692,23 @@ { CK_RV rv; - if (API_Initialized() == FALSE) { + if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); - } - if (! pPin && ulPinLen) { + + if (! pPin && ulPinLen) + return (CKR_ARGUMENTS_BAD); + + if (! pLabel) return (CKR_ARGUMENTS_BAD); - } - if (! pLabel) { - return (CKR_ARGUMENTS_BAD); - } - if (FuncList.ST_InitToken) { + + if (!global_shm->token_available) + return (CKR_SLOT_ID_INVALID); + + if (FuncList.ST_InitToken) rv = FuncList.ST_InitToken(slotID, pPin, ulPinLen, pLabel); - } else { + else rv = CKR_FUNCTION_NOT_SUPPORTED; - } + return (rv); } @@ -1752,22 +1767,22 @@ CK_RV rv; Session_Struct_t *apiSessp; - if (API_Initialized() == FALSE) { + if (API_Initialized() == FALSE) return (CKR_CRYPTOKI_NOT_INITIALIZED); - } - if (slotID > NUMBER_SLOTS_MANAGED) { + + if (!global_shm->token_available || (slotID > NUMBER_SLOTS_MANAGED)) return (CKR_SLOT_ID_INVALID); - } - if (! phSession) { + + if (! phSession) return (CKR_FUNCTION_FAILED); - } - if ((flags & CKF_SERIAL_SESSION) == 0) { + + if ((flags & CKF_SERIAL_SESSION) == 0) return (CKR_SESSION_PARALLEL_NOT_SUPPORTED); - } + if ((apiSessp = (Session_Struct_t *)malloc( - sizeof (Session_Struct_t))) == NULL) { + sizeof (Session_Struct_t))) == NULL) return (CKR_HOST_MEMORY); - } + if (FuncList.ST_OpenSession) { rv = FuncList.ST_OpenSession(slotID, flags, &(apiSessp->RealHandle));
--- a/usr/src/lib/pkcs11/pkcs11_tpm/common/apiutil.c Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/lib/pkcs11/pkcs11_tpm/common/apiutil.c Mon Aug 17 20:56:15 2009 -0700 @@ -453,7 +453,7 @@ int API_Initialized() { - return (Anchor != NULL); + return (Anchor != NULL && global_shm != NULL); } void
--- a/usr/src/lib/pkcs11/pkcs11_tpm/common/new_host.c Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/lib/pkcs11/pkcs11_tpm/common/new_host.c Mon Aug 17 20:56:15 2009 -0700 @@ -156,11 +156,23 @@ initedpid = getpid(); SC_SetFunctionList(); + if (flist != NULL) + (*flist) = function_list; + /* Always call the token_specific_init function.... */ rc = token_specific.t_init((char *)Correlator, SlotNumber, &hContext); - if (rc != 0) + if (rc != 0) { + /* + * The token could not be initialized, return OK, but + * present no slots. + */ + rc = CKR_OK; goto done; + } else { + /* Mark the token as available */ + global_shm->token_available = TRUE; + } } rc = load_token_data(hContext, nv_token_data); @@ -179,8 +191,6 @@ init_slot_info(nv_token_data); - if (flist != NULL) - (*flist) = function_list; done: if (hContext) Tspi_Context_Close(hContext);
--- a/usr/src/lib/pkcs11/pkcs11_tpm/common/tpmtok_int.h Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/lib/pkcs11/pkcs11_tpm/common/tpmtok_int.h Mon Aug 17 20:56:15 2009 -0700 @@ -414,6 +414,7 @@ CK_ULONG num_publ_tok_obj; CK_BBOOL priv_loaded; CK_BBOOL publ_loaded; + CK_BBOOL token_available; TOK_OBJ_ENTRY publ_tok_objs[ MAX_TOK_OBJS ]; TOK_OBJ_ENTRY priv_tok_objs[ MAX_TOK_OBJS ]; } LW_SHM_TYPE;
--- a/usr/src/lib/pkcs11/pkcs11_tpm/common/utility.c Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/lib/pkcs11/pkcs11_tpm/common/utility.c Mon Aug 17 20:56:15 2009 -0700 @@ -596,7 +596,7 @@ if (global_shm != NULL) return (CKR_OK); - global_shm = (LW_SHM_TYPE *)malloc(sizeof (LW_SHM_TYPE)); + global_shm = (LW_SHM_TYPE *)calloc(1, sizeof (LW_SHM_TYPE)); if (global_shm == NULL) { return (CKR_HOST_MEMORY); } @@ -605,14 +605,6 @@ xproclock = (void *)&global_shm->mutex; (void) XProcLock(xproclock); - global_shm->num_publ_tok_obj = 0; - global_shm->num_priv_tok_obj = 0; - - (void) memset(&global_shm->publ_tok_objs, 0x0, - 2048 * sizeof (TOK_OBJ_ENTRY)); - (void) memset(&global_shm->priv_tok_objs, 0x0, - 2048 * sizeof (TOK_OBJ_ENTRY)); - (void) XProcUnLock(xproclock); return (CKR_OK);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/pkcs11/pkcs11_tpm/sparc/Makefile Mon Aug 17 20:56:15 2009 -0700 @@ -0,0 +1,27 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com + +install: all $(ROOTLIBS) $(ROOTLINKS)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/pkcs11/pkcs11_tpm/sparcv9/Makefile Mon Aug 17 20:56:15 2009 -0700 @@ -0,0 +1,30 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +include ../Makefile.com +include $(SRC)/lib/Makefile.lib.64 + +TSSLIB=$(TSSLIB64) + +install: all $(ROOTLIBS64) $(ROOTLINKS64)
--- a/usr/src/pkgdefs/Makefile Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/pkgdefs/Makefile Mon Aug 17 20:56:15 2009 -0700 @@ -158,7 +158,6 @@ SUNWrwd \ SUNWrwn \ SUNWsi3124 \ - SUNWtpm \ SUNWuath \ SUNWural \ SUNWurtw \ @@ -493,6 +492,7 @@ SUNWtnfc \ SUNWtnfd \ SUNWtoo \ + SUNWtpm \ SUNWtsg \ SUNWtsr \ SUNWtsu \
--- a/usr/src/pkgdefs/SUNWcsl/prototype_com Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/pkgdefs/SUNWcsl/prototype_com Mon Aug 17 20:56:15 2009 -0700 @@ -358,6 +358,8 @@ s none usr/lib/security/pkcs11_kernel.so=./pkcs11_kernel.so.1 f none usr/lib/security/pkcs11_softtoken.so.1 755 root bin s none usr/lib/security/pkcs11_softtoken.so=./pkcs11_softtoken.so.1 +f none usr/lib/security/pkcs11_tpm.so.1 755 root bin +s none usr/lib/security/pkcs11_tpm.so=./pkcs11_tpm.so.1 d none usr/lib/scsi 755 root bin f none usr/lib/scsi/libscsi.so.1 755 root bin s none usr/lib/scsi/libscsi.so=./libscsi.so.1
--- a/usr/src/pkgdefs/SUNWcsl/prototype_i386 Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/pkgdefs/SUNWcsl/prototype_i386 Mon Aug 17 20:56:15 2009 -0700 @@ -152,8 +152,6 @@ s none usr/lib/security/amd64/pkcs11_softtoken.so=./pkcs11_softtoken.so.1 f none usr/lib/security/amd64/pkcs11_tpm.so.1 755 root bin s none usr/lib/security/amd64/pkcs11_tpm.so=./pkcs11_tpm.so.1 -f none usr/lib/security/pkcs11_tpm.so.1 755 root bin -s none usr/lib/security/pkcs11_tpm.so=./pkcs11_tpm.so.1 s none usr/lib/64=amd64 d none usr/lib/amd64 755 root bin f none usr/lib/amd64/libadutils.so.1 755 root bin
--- a/usr/src/pkgdefs/SUNWcsl/prototype_sparc Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/pkgdefs/SUNWcsl/prototype_sparc Mon Aug 17 20:56:15 2009 -0700 @@ -144,6 +144,8 @@ s none usr/lib/security/sparcv9/pkcs11_kernel.so=./pkcs11_kernel.so.1 f none usr/lib/security/sparcv9/pkcs11_softtoken.so.1 755 root bin s none usr/lib/security/sparcv9/pkcs11_softtoken.so=./pkcs11_softtoken.so.1 +f none usr/lib/security/sparcv9/pkcs11_tpm.so.1 755 root bin +s none usr/lib/security/sparcv9/pkcs11_tpm.so=./pkcs11_tpm.so.1 s none usr/lib/64=sparcv9 d none usr/lib/sparcv9 755 root bin f none usr/lib/sparcv9/libadutils.so.1 755 root bin
--- a/usr/src/pkgdefs/SUNWcsu/prototype_com Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/pkgdefs/SUNWcsu/prototype_com Mon Aug 17 20:56:15 2009 -0700 @@ -281,6 +281,7 @@ f none usr/bin/tip 4511 uucp bin l none usr/bin/touch=../../usr/bin/settime f none usr/bin/tplot 555 root bin +f none usr/bin/tpmadm 555 root bin f none usr/bin/tput 555 root bin f none usr/bin/tr 555 root bin f none usr/bin/true 555 root bin
--- a/usr/src/pkgdefs/SUNWcsu/prototype_i386 Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/pkgdefs/SUNWcsu/prototype_i386 Mon Aug 17 20:56:15 2009 -0700 @@ -63,7 +63,6 @@ f none usr/bin/i86/setuname 555 root bin f none usr/bin/i86/uptime 4555 root bin l none usr/bin/i86/w=uptime -f none usr/bin/tpmadm 555 root bin f none usr/kernel/drv/dump 755 root sys f none usr/kernel/drv/fssnap 755 root sys f none usr/kernel/drv/kstat 755 root sys
--- a/usr/src/pkgdefs/SUNWtpm/pkginfo.tmpl Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/pkgdefs/SUNWtpm/pkginfo.tmpl Mon Aug 17 20:56:15 2009 -0700 @@ -32,14 +32,14 @@ # this value will break upgrade until ONVERS is incremented to 11.12 # PKG="SUNWtpm" -NAME="Sun TPM pseudo driver" -ARCH="i386" +NAME="Trusted Platform Module driver" +ARCH="ISA" CATEGORY="system" BASEDIR=/ SUNW_PKGVERS="1.0" SUNW_PKGTYPE="root" CLASSES="none" -DESC="Sun TPM pseudo driver" +DESC="Trusted Platform Module driver" SUNW_PRODNAME="SunOS" SUNW_PRODVERS="RELEASE/VERSION" VERSION="ONVERS.0,REV=0.0.0"
--- a/usr/src/pkgdefs/SUNWtpm/postinstall.tmpl Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/pkgdefs/SUNWtpm/postinstall.tmpl Mon Aug 17 20:56:15 2009 -0700 @@ -28,7 +28,6 @@ DRVPERM='* 0600 root sys' ADD_DRV=/usr/sbin/add_drv -DEVLINKTB=${BASEDIR}/etc/devlink.tab ACPITABLE=${BASEDIR}/boot/solaris/devicedb/master TMP=/tmp/$$ @@ -36,12 +35,7 @@ ISA_TYPE_SPARC="sparc" ISA_TYPE="$ARCH" -# -# TPM support is only available on x86 platforms. -# -if [ "${ISA_TYPE}" != "${ISA_TYPE_I386}" ]; then - exit 0 -fi +MACH=`/usr/bin/uname -m` # # Check if the BASEDIR option is needed @@ -49,11 +43,9 @@ if [ "${BASEDIR:=/}" = "/" ]; then ADD_DRV_FLAGS="" NAME_TO_MAJOR="/etc/name_to_major" - DEVLINK_TAB="/etc/devlink.tab" else ADD_DRV_FLAGS="-b ${BASEDIR}" NAME_TO_MAJOR="${BASEDIR}/etc/name_to_major" - DEVLINK_TAB="${BASEDIR}/etc/devlink.tab" fi add_driver() @@ -73,20 +65,6 @@ } # -# add_devlink - adds an entry to ${DEVLINKTB} -# -add_devlink() -{ - PATTERN="$1" - LINK="$2" - PLINK="`echo $LINK | sed 's/[$*^|\]/\\\&/g'`" - grep -v "^$PATTERN $PLINK$" ${DEVLINKTB} >$TMP.devlink - echo "$PATTERN\t$LINK" >>$TMP.devlink - cp $TMP.devlink ${DEVLINKTB} - rm -f $TMP.devlink -} - -# # Update ACPI table if the entry is not already present. # add_acpi() @@ -97,11 +75,17 @@ fi } -# Add entry to /etc/devlink.tab if not there already -# Note: the tab after ${DRV} here is important. - -add_devlink 'type=ddi_pseudo;name=tpm' '\\D' -add_acpi -add_driver +if [ "${ISA_TYPE}" = "${ISA_TYPE_I386}" ]; then + add_acpi + add_driver +else + if [ "${ISA_TYPE}" = "${ISA_TYPE_SPARC}" -a "${MACH}" = "sun4v" ]; then + # + # sun4v TPM device has a unique identifier + # + ADD_DRV_FLAGS="${ADD_DRV_FLAGS} -i 'SUNW,sun4v-ptpm'" + add_driver + fi +fi exit 0
--- a/usr/src/pkgdefs/SUNWtpm/preremove.tmpl Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/pkgdefs/SUNWtpm/preremove.tmpl Mon Aug 17 20:56:15 2009 -0700 @@ -30,6 +30,7 @@ DRV=tpm REM_DRV=/usr/sbin/rem_drv + # # Check if the BASEDIR option is needed # @@ -43,14 +44,17 @@ ${REM_DRV} ${REM_DRV_FLAGS} ${DRV} -# Remove our entry from /etc/devlink.tab -# Note: the tab after ${DRV} here is important. +if [ "${ARCH}" = "i386" ]; then + # Remove our entry from /etc/devlink.tab + # Note: the tab after ${DRV} here is important. -grep -v "^type=ddi_pseudo;name=${DRV} " ${DEVLINK_TAB} >$TMP.devlink + grep -v "^type=ddi_pseudo;name=${DRV} " ${DEVLINK_TAB} >$TMP.devlink -# Must use 'cp' here in order to preserve the original -# mode, owner and group of devlink.tab + # Must use 'cp' here in order to preserve the original + # mode, owner and group of devlink.tab -cp $TMP.devlink ${DEVLINK_TAB} -rm -f $TMP.devlink + cp $TMP.devlink ${DEVLINK_TAB} + rm -f $TMP.devlink +fi + exit 0
--- a/usr/src/pkgdefs/SUNWtpm/prototype_com Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/pkgdefs/SUNWtpm/prototype_com Mon Aug 17 20:56:15 2009 -0700 @@ -39,13 +39,7 @@ #!<param>=<value> # puts parameter in pkg environment # # -# List files which are i386 specific here -# # source locations relative to the prototype file # # SUNWtpm # -d none kernel 0755 root sys -d none kernel/drv 0755 root sys -f none kernel/drv/tpm 755 root sys -f none kernel/drv/tpm.conf 644 root sys
--- a/usr/src/pkgdefs/SUNWtpm/prototype_i386 Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/pkgdefs/SUNWtpm/prototype_i386 Mon Aug 17 20:56:15 2009 -0700 @@ -42,5 +42,9 @@ # # SUNWtpm # +d none kernel 0755 root sys +d none kernel/drv 0755 root sys +f none kernel/drv/tpm 755 root sys +f none kernel/drv/tpm.conf 644 root sys d none kernel/drv/amd64 0755 root sys f none kernel/drv/amd64/tpm 755 root sys
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/pkgdefs/SUNWtpm/prototype_sparc Mon Aug 17 20:56:15 2009 -0700 @@ -0,0 +1,50 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# This required package information file contains a list of package contents. +# The 'pkgmk' command uses this file to identify the contents of a package +# and their location on the development machine when building the package. +# Can be created via a text editor or through use of the 'pkgproto' command. + +# packaging files +#!search <pathname pathname ...> # where to find pkg objects +#!include <filename> # include another 'prototype' file +#!default <mode> <owner> <group> # default used if not specified on entry +#!<param>=<value> # puts parameter in pkg environment +# + +!include prototype_com + +# +# List files which are sparc specific here +# +# source locations relative to the prototype file +# +# SUNWtpm +# +d none platform 0755 root sys +d none platform/sun4v 0755 root sys +d none platform/sun4v/kernel 0755 root sys +d none platform/sun4v/kernel/drv 0755 root sys +d none platform/sun4v/kernel/drv/sparcv9 0755 root sys +f none platform/sun4v/kernel/drv/sparcv9/tpm 755 root sys
--- a/usr/src/pkgdefs/common_files/i.pkcs11confbase Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/pkgdefs/common_files/i.pkcs11confbase Mon Aug 17 20:56:15 2009 -0700 @@ -20,10 +20,9 @@ # CDDL HEADER END # # -# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" while read src dest do @@ -53,6 +52,21 @@ mv -f ${dest}.$$ ${dest} + # + # Check if destination already has pkcs11_tpm + # + egrep 'pkcs11_tpm' $dest > /dev/null 2>& 1 + if [ $? != 0 ] ; then + pkcs11tpm="/usr/lib/security/\$ISA/pkcs11_tpm.so" + export pkcs11tpm + if [ $? = 0 ] ; then + nawk '/^# End SUNWcsr/ \ + { print ENVIRON["pkcs11tpm"] } \ + { print } \ + ' ${dest} > ${dest}.$$ + mv -f ${dest}.$$ ${dest} + fi + fi fi done exit 0
--- a/usr/src/uts/common/Makefile.files Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/uts/common/Makefile.files Mon Aug 17 20:56:15 2009 -0700 @@ -1927,4 +1927,4 @@ # NULLDRIVER_OBJS = nulldriver.o -TPM_OBJS = tpm.o +TPM_OBJS = tpm.o tpm_hcall.o
--- a/usr/src/uts/common/Makefile.rules Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/uts/common/Makefile.rules Mon Aug 17 20:56:15 2009 -0700 @@ -1404,6 +1404,9 @@ $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) +$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/tpm/%.s + $(COMPILE.s) -o $@ $< + # # SVM # @@ -2440,5 +2443,8 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/tpm/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) +$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/tpm/%.s + @($(LHEAD) $(LINT.c) $< $(LTAIL)) + $(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/vr/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL))
--- a/usr/src/uts/common/io/tpm/tpm.c Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/uts/common/io/tpm/tpm.c Mon Aug 17 20:56:15 2009 -0700 @@ -42,9 +42,17 @@ #include <sys/cred.h> /* used by open,close,read */ #include <sys/uio.h> /* used by read */ #include <sys/stat.h> /* defines S_IFCHR */ +#include <sys/crypto/common.h> +#include <sys/crypto/impl.h> +#include <sys/crypto/spi.h> #include <sys/byteorder.h> /* for ntohs, ntohl, htons, htonl */ +#ifdef sun4v +#include <sys/hypervisor_api.h> +#include <sys/hsvc.h> +#endif + #include <tss/platform.h> /* from SUNWtss */ #include <tss/tpm.h> /* from SUNWtss */ @@ -88,6 +96,7 @@ #define TEN_MILLISECONDS 10000 /* 10 milliseconds */ #define FOUR_HUNDRED_MILLISECONDS 400000 /* 4 hundred milliseconds */ +#define DEFAULT_LOCALITY 0 /* * TPM input/output buffer offsets */ @@ -137,7 +146,7 @@ /* Auxilliary */ static int receive_data(tpm_state_t *, uint8_t *, size_t); -static inline int tpm_lock(tpm_state_t *); +static inline int tpm_io_lock(tpm_state_t *); static inline void tpm_unlock(tpm_state_t *); static void tpm_cleanup(dev_info_t *, tpm_state_t *); @@ -211,9 +220,160 @@ NULL }; +#ifdef KCF_TPM_RNG_PROVIDER + +#define IDENT_TPMRNG "TPM Random Number Generator" +/* + * CSPI information (entry points, provider info, etc.) + */ +static void tpmrng_provider_status(crypto_provider_handle_t, uint_t *); + +static crypto_control_ops_t tpmrng_control_ops = { + tpmrng_provider_status +}; + +static int tpmrng_seed_random(crypto_provider_handle_t, crypto_session_id_t, + uchar_t *, size_t, uint_t, uint32_t, crypto_req_handle_t); + +static int tpmrng_generate_random(crypto_provider_handle_t, + crypto_session_id_t, uchar_t *, size_t, crypto_req_handle_t); + +static crypto_random_number_ops_t tpmrng_random_number_ops = { + tpmrng_seed_random, + tpmrng_generate_random +}; + +static int tpmrng_ext_info(crypto_provider_handle_t, + crypto_provider_ext_info_t *, + crypto_req_handle_t); + +static crypto_provider_management_ops_t tpmrng_extinfo_op = { + tpmrng_ext_info, + NULL, + NULL, + NULL +}; + +static int tpmrng_register(tpm_state_t *); +static int tpmrng_unregister(tpm_state_t *); + +static crypto_ops_t tpmrng_crypto_ops = { + &tpmrng_control_ops, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + &tpmrng_random_number_ops, + NULL, + NULL, + NULL, + &tpmrng_extinfo_op, + NULL, + NULL +}; + +static crypto_provider_info_t tpmrng_prov_info = { + CRYPTO_SPI_VERSION_2, + "TPM Random Number Provider", + CRYPTO_HW_PROVIDER, + NULL, + NULL, + &tpmrng_crypto_ops, + 0, + NULL, + 0, + NULL +}; +#endif /* KCF_TPM_RNG_PROVIDER */ + static void *statep = NULL; /* + * Inline code to get exclusive lock on the TPM device and to make sure + * the device is not suspended. This grabs the primary TPM mutex (pm_mutex) + * and then checks the suspend status. If suspended, it will wait until + * the device is "resumed" before releasing the pm_mutex and continuing. + */ +#define TPM_EXCLUSIVE_LOCK(tpm) { \ + mutex_enter(&tpm->pm_mutex); \ + while (tpm->suspended) \ + cv_wait(&tpm->suspend_cv, &tpm->pm_mutex); \ + mutex_exit(&tpm->pm_mutex); } + +/* + * TPM accessor functions + */ +#ifdef sun4v + +extern uint64_t +hcall_tpm_get(uint64_t, uint64_t, uint64_t, uint64_t *); + +extern uint64_t +hcall_tpm_put(uint64_t, uint64_t, uint64_t, uint64_t); + +static inline uint8_t +tpm_get8(tpm_state_t *tpm, unsigned long offset) +{ + uint64_t value; + + ASSERT(tpm != NULL); + (void) hcall_tpm_get(tpm->locality, offset, sizeof (uint8_t), &value); + return ((uint8_t)value); +} + +static inline uint32_t +tpm_get32(tpm_state_t *tpm, unsigned long offset) +{ + uint64_t value; + + ASSERT(tpm != NULL); + (void) hcall_tpm_get(tpm->locality, offset, sizeof (uint32_t), &value); + return ((uint32_t)value); +} + +static inline void +tpm_put8(tpm_state_t *tpm, unsigned long offset, uint8_t value) +{ + ASSERT(tpm != NULL); + (void) hcall_tpm_put(tpm->locality, offset, sizeof (uint8_t), value); +} + +#else + +static inline uint8_t +tpm_get8(tpm_state_t *tpm, unsigned long offset) +{ + ASSERT(tpm != NULL); + + return (ddi_get8(tpm->handle, + (uint8_t *)(TPM_LOCALITY_OFFSET(tpm->locality) | + (uintptr_t)tpm->addr + offset))); +} + +static inline uint32_t +tpm_get32(tpm_state_t *tpm, unsigned long offset) +{ + ASSERT(tpm != NULL); + return (ddi_get32(tpm->handle, + (uint32_t *)(TPM_LOCALITY_OFFSET(tpm->locality) | + (uintptr_t)tpm->addr + offset))); +} + +static inline void +tpm_put8(tpm_state_t *tpm, unsigned long offset, uint8_t value) +{ + ASSERT(tpm != NULL); + ddi_put8(tpm->handle, + (uint8_t *)(TPM_LOCALITY_OFFSET(tpm->locality) | + (uintptr_t)tpm->addr + offset), value); +} + +#endif /* sun4v */ + +/* * TPM commands to get the TPM's properties, e.g.,timeout */ /*ARGSUSED*/ @@ -580,8 +740,13 @@ /* Check the return code */ ret = load32(buf, TPM_RETURN_OFFSET); if (ret != TPM_SUCCESS) { - cmn_err(CE_WARN, "%s: command failed with ret code: %x", - myname, ret); + if (ret == TPM_E_DEACTIVATED) + cmn_err(CE_WARN, "%s: TPM is deactivated", myname); + else if (ret == TPM_E_DISABLED) + cmn_err(CE_WARN, "%s: TPM is disabled", myname); + else + cmn_err(CE_WARN, "%s: TPM error code 0x%0x", + myname, ret); return (DDI_FAILURE); } @@ -612,12 +777,8 @@ * burstcnt is stored as a little endian value * 'ntohs' doesn't work since the value is not word-aligned */ - burstcnt = ddi_get8(tpm->handle, - (uint8_t *)(tpm->addr+ - TPM_STS_(tpm->locality)+1)); - burstcnt += ddi_get8(tpm->handle, - (uint8_t *)(tpm->addr+ - TPM_STS_(tpm->locality)+2)) << 8; + burstcnt = tpm_get8(tpm, TPM_STS + 1); + burstcnt += tpm_get8(tpm, TPM_STS + 2) << 8; if (burstcnt) return (burstcnt); @@ -636,11 +797,7 @@ */ static void tpm_set_ready(tpm_state_t *tpm) { - ASSERT(tpm != NULL); - - ddi_put8(tpm->handle, - (uint8_t *)(tpm->addr+TPM_STS_(tpm->locality)), - TPM_STS_CMD_READY); + tpm_put8(tpm, TPM_STS, TPM_STS_CMD_READY); } static int @@ -657,7 +814,7 @@ while (size < bufsiz && (tpm_wait_for_stat(tpm, (TPM_STS_DATA_AVAIL|TPM_STS_VALID), - (ddi_get_lbolt() + tpm->timeout_c)) == DDI_SUCCESS)) { + tpm->timeout_c) == DDI_SUCCESS)) { /* * Burstcount should be available within TIMEOUT_D * after STS is set to valid @@ -665,18 +822,14 @@ */ burstcnt = tpm_get_burstcount(tpm); for (; burstcnt > 0 && size < bufsiz; burstcnt--) { - buf[size++] = ddi_get8(tpm->handle, - (uint8_t *)(tpm->addr + - TPM_DATA_FIFO_(tpm->locality))); + buf[size++] = tpm_get8(tpm, TPM_DATA_FIFO); } } stsbits = tis_get_status(tpm); /* check to see if we need to retry (just once) */ if (size < bufsiz && !(stsbits & TPM_STS_DATA_AVAIL) && retried == 0) { /* issue responseRetry (TIS 1.2 pg 54) */ - ddi_put8(tpm->handle, - (uint8_t *)(tpm->addr+TPM_STS_(tpm->locality)), - TPM_STS_RESPONSE_RETRY); + tpm_put8(tpm, TPM_STS, TPM_STS_RESPONSE_RETRY); /* update the retry counter so we only retry once */ retried++; /* reset the size to 0 and reread the entire response */ @@ -734,8 +887,7 @@ } /* The TPM MUST set the state to stsValid within TIMEOUT_C */ - ret = tpm_wait_for_stat(tpm, TPM_STS_VALID, - ddi_get_lbolt() + tpm->timeout_c); + ret = tpm_wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c); status = tis_get_status(tpm); if (ret != DDI_SUCCESS) { @@ -783,21 +935,12 @@ return (DDI_FAILURE); } - /* Be in the right locality (aren't we always in locality 0?) */ - if (tis_request_locality(tpm, 0) != DDI_SUCCESS) { - cmn_err(CE_WARN, "%s: tis_request_locality didn't enter " - "locality 0", myname); - return (DDI_FAILURE); - } - /* Put the TPM in ready state */ status = tis_get_status(tpm); if (!(status & TPM_STS_CMD_READY)) { tpm_set_ready(tpm); - ret = tpm_wait_for_stat(tpm, - TPM_STS_CMD_READY, - (ddi_get_lbolt() + tpm->timeout_b)); + ret = tpm_wait_for_stat(tpm, TPM_STS_CMD_READY, tpm->timeout_b); if (ret != DDI_SUCCESS) { cmn_err(CE_WARN, "%s: could not put the TPM " "in the command ready state:" @@ -823,14 +966,12 @@ } for (; burstcnt > 0 && count < bufsiz - 1; burstcnt--) { - ddi_put8(tpm->handle, (uint8_t *)(tpm->addr+ - TPM_DATA_FIFO_(tpm->locality)), buf[count]); + tpm_put8(tpm, TPM_DATA_FIFO, buf[count]); count++; } /* Wait for TPM to indicate that it is ready for more data */ ret = tpm_wait_for_stat(tpm, - (TPM_STS_VALID | TPM_STS_DATA_EXPECT), - (ddi_get_lbolt() + tpm->timeout_c)); + (TPM_STS_VALID | TPM_STS_DATA_EXPECT), tpm->timeout_c); if (ret != DDI_SUCCESS) { cmn_err(CE_WARN, "%s: TPM didn't enter stsvalid " "state after sending the data:", myname); @@ -840,13 +981,11 @@ /* We can't exit the loop above unless we wrote bufsiz-1 bytes */ /* Write last byte */ - ddi_put8(tpm->handle, (uint8_t *)(tpm->addr + - TPM_DATA_FIFO_(tpm->locality)), buf[count]); + tpm_put8(tpm, TPM_DATA_FIFO, buf[count]); count++; /* Wait for the TPM to enter Valid State */ - ret = tpm_wait_for_stat(tpm, - TPM_STS_VALID, (ddi_get_lbolt() + tpm->timeout_c)); + ret = tpm_wait_for_stat(tpm, TPM_STS_VALID, tpm->timeout_c); if (ret == DDI_FAILURE) { cmn_err(CE_WARN, "%s: tpm didn't enter Valid state", myname); goto FAIL; @@ -865,14 +1004,13 @@ * Final step: Writing TPM_STS_GO to TPM_STS * register will actually send the command. */ - ddi_put8(tpm->handle, (uint8_t *)(tpm->addr+TPM_STS_(tpm->locality)), - TPM_STS_GO); + tpm_put8(tpm, TPM_STS, TPM_STS_GO); /* Ordinal/Command_code is located in buf[6..9] */ ordinal = load32(buf, TPM_COMMAND_CODE_OFFSET); ret = tpm_wait_for_stat(tpm, TPM_STS_DATA_AVAIL | TPM_STS_VALID, - ddi_get_lbolt() + tpm_get_ordinal_duration(tpm, ordinal)); + tpm_get_ordinal_duration(tpm, ordinal)); if (ret == DDI_FAILURE) { status = tis_get_status(tpm); if (!(status & TPM_STS_DATA_AVAIL) || @@ -904,17 +1042,14 @@ ASSERT(tpm != NULL && locality >= 0 && locality < 5); if (force || - (ddi_get8(tpm->handle, - (uchar_t *)(tpm->addr+TPM_ACCESS_(locality))) - & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) - == (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) { + (tpm_get8(tpm, TPM_ACCESS) & + (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == + (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) { /* * Writing 1 to active locality bit in TPM_ACCESS * register reliquishes the control of the locality */ - ddi_put8(tpm->handle, - (uint8_t *)(tpm->addr+TPM_ACCESS_(locality)), - TPM_ACCESS_ACTIVE_LOCALITY); + tpm_put8(tpm, TPM_ACCESS, TPM_ACCESS_ACTIVE_LOCALITY); } } @@ -925,17 +1060,25 @@ static int tis_check_active_locality(tpm_state_t *tpm, char locality) { uint8_t access_bits; + uint8_t old_locality; ASSERT(tpm != NULL && locality >= 0 && locality < 5); - access_bits = ddi_get8(tpm->handle, - (uint8_t *)(tpm->addr+TPM_ACCESS_(locality))); + old_locality = tpm->locality; + tpm->locality = locality; + + /* Just check to see if the requested localit works */ + access_bits = tpm_get8(tpm, TPM_ACCESS); access_bits &= (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID); - if (access_bits == (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) + /* this was just a check, not a request to switch */ + tpm->locality = old_locality; + + if (access_bits == (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { return (DDI_SUCCESS); - else + } else { return (DDI_FAILURE); + } } /* Request the TPM to be in the given locality */ @@ -955,8 +1098,7 @@ return (DDI_SUCCESS); } - ddi_put8(tpm->handle, tpm->addr+TPM_ACCESS_(locality), - TPM_ACCESS_REQUEST_USE); + tpm_put8(tpm, TPM_ACCESS, TPM_ACCESS_REQUEST_USE); timeout = ddi_get_lbolt() + tpm->timeout_a; /* Using polling */ @@ -964,8 +1106,8 @@ != DDI_SUCCESS) { if (ddi_get_lbolt() >= timeout) { cmn_err(CE_WARN, "%s (interrupt-disabled) " - "tis_request_locality timed out", - myname); + "tis_request_locality timed out (timeout_a = %ld)", + myname, tpm->timeout_a); return (DDI_FAILURE); } delay(tpm->timeout_poll); @@ -978,21 +1120,21 @@ /* Read the status register */ static uint8_t tis_get_status(tpm_state_t *tpm) { - return (ddi_get8(tpm->handle, - (uint8_t *)(tpm->addr+TPM_STS_(tpm->locality)))); + return (tpm_get8(tpm, TPM_STS)); } static int -tpm_wait_for_stat(tpm_state_t *tpm, uint8_t mask, clock_t absolute_timeout) { +tpm_wait_for_stat(tpm_state_t *tpm, uint8_t mask, clock_t timeout) { char *myname = "tpm_wait_for_stat"; + clock_t absolute_timeout = ddi_get_lbolt() + timeout; /* Using polling */ while ((tis_get_status(tpm) & mask) != mask) { if (ddi_get_lbolt() >= absolute_timeout) { /* Timeout reached */ cmn_err(CE_WARN, "%s: using " - "polling:reached timeout", - myname); + "polling - reached timeout (%ld usecs)", + myname, drv_hztousec(timeout)); return (DDI_FAILURE); } delay(tpm->timeout_poll); @@ -1012,7 +1154,6 @@ uint32_t intf_caps; int ret; char *myname = "tis_init"; - uintptr_t aptr = (uintptr_t)tpm->addr; /* * Temporarily set up timeouts before we get the real timeouts @@ -1035,8 +1176,7 @@ tpm->duration[TPM_UNDEFINED] = drv_usectohz(TPM_DEFAULT_DURATION); /* Find out supported capabilities */ - intf_caps = ddi_get32(tpm->handle, - (uint32_t *)(aptr + TPM_INTF_CAP_(0))); + intf_caps = tpm_get32(tpm, TPM_INTF_CAP); /* Upper 3 bytes should always return 0 */ if (intf_caps & 0x7FFFFF00) { @@ -1063,9 +1203,10 @@ * Before we start writing anything to TPM's registers, * make sure we are in locality 0 */ - ret = tis_request_locality(tpm, 0); + ret = tis_request_locality(tpm, DEFAULT_LOCALITY); if (ret != DDI_SUCCESS) { - cmn_err(CE_WARN, "%s: Unable to request locality 0", myname); + cmn_err(CE_WARN, "%s: Unable to request locality %d", myname, + DEFAULT_LOCALITY); return (DDI_FAILURE); } /* Now we can refer to the locality as tpm->locality */ @@ -1114,8 +1255,10 @@ ret = ddi_soft_state_init(&statep, sizeof (tpm_state_t), 1); if (ret) +{ + cmn_err(CE_WARN, "ddi_soft_state_init failed: %d", ret); return (ret); - +} ret = mod_install(&tpm_ml); if (ret != 0) { cmn_err(CE_WARN, "_init: mod_install returned non-zero"); @@ -1141,10 +1284,11 @@ _fini() { int ret; + ret = mod_remove(&tpm_ml); - if (ret != 0) { + if (ret != 0) return (ret); - } + ddi_soft_state_fini(&statep); return (ret); @@ -1166,40 +1310,58 @@ return (DDI_SUCCESS); } +#ifdef sun4v +static uint64_t hsvc_tpm_minor = 0; +static hsvc_info_t hsvc_tpm = { + HSVC_REV_1, NULL, HSVC_GROUP_TPM, 1, 0, NULL +}; +#endif + /* * Sun DDI/DDK entry points */ static int tpm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { - int ret, idx; + int ret; int instance; - int nregs; +#ifndef sun4v + int idx, nregs; +#endif char *myname = "tpm_attach"; tpm_state_t *tpm = NULL; ASSERT(dip != NULL); instance = ddi_get_instance(dip); + if (instance < 0) + return (DDI_FAILURE); /* Nothing out of ordinary here */ switch (cmd) { case DDI_ATTACH: - ret = ddi_soft_state_zalloc(statep, instance); - if (ret != DDI_SUCCESS) { - cmn_err(CE_WARN, "%s could not allocate tpm_state_t", + if (ddi_soft_state_zalloc(statep, instance) == DDI_SUCCESS) { + tpm = ddi_get_soft_state(statep, instance); + if (tpm == NULL) { + cmn_err(CE_WARN, + "%s: cannot get state information.", + myname); + return (DDI_FAILURE); + } + tpm->dip = dip; + } else { + cmn_err(CE_WARN, + "%s: cannot allocate state information.", myname); - goto FAIL; + return (DDI_FAILURE); } - tpm = ddi_get_soft_state(statep, instance); - tpm->dip = dip; break; case DDI_RESUME: tpm = ddi_get_soft_state(statep, instance); if (tpm == NULL) { - cmn_err(CE_WARN, "%s: tpm_state_t is NULL", + cmn_err(CE_WARN, "%s: cannot get state information.", myname); - goto FAIL; + return (DDI_FAILURE); } return (tpm_resume(tpm)); default: @@ -1211,6 +1373,15 @@ /* Zeroize the flag, which is used to keep track of what is allocated */ tpm->flags = 0; +#ifdef sun4v + ret = hsvc_register(&hsvc_tpm, &hsvc_tpm_minor); + if (ret != 0) { + cmn_err(CE_WARN, "%s: failed to register with " + "hypervisor: 0x%0x", myname, ret); + goto FAIL; + } + tpm->flags |= TPM_HSVC_REGISTERED; +#else tpm->accattr.devacc_attr_version = DDI_DEVICE_ATTR_V0; tpm->accattr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; tpm->accattr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; @@ -1248,17 +1419,19 @@ goto FAIL; } tpm->flags |= TPM_DIDREGSMAP; - +#endif /* Enable TPM device according to the TIS specification */ ret = tis_init(tpm); if (ret != DDI_SUCCESS) { - cmn_err(CE_WARN, "%s: tis_init() failed ret: %d", + cmn_err(CE_WARN, "%s: tis_init() failed with error %d", myname, ret); /* We need to clean up the ddi_regs_map_setup call */ - ddi_regs_map_free(&tpm->handle); - tpm->handle = NULL; - tpm->flags &= ~TPM_DIDREGSMAP; + if (tpm->flags & TPM_DIDREGSMAP) { + ddi_regs_map_free(&tpm->handle); + tpm->handle = NULL; + tpm->flags &= ~TPM_DIDREGSMAP; + } goto FAIL; } @@ -1280,10 +1453,6 @@ /* Initialize the buffer and the lock associated with it */ tpm->bufsize = TPM_IO_BUF_SIZE; tpm->iobuf = kmem_zalloc((sizeof (uint8_t))*(tpm->bufsize), KM_SLEEP); - if (tpm->iobuf == NULL) { - cmn_err(CE_WARN, "%s: failed to allocate iobuf", myname); - goto FAIL; - } tpm->flags |= TPM_DID_IO_ALLOC; mutex_init(&tpm->iobuf_lock, NULL, MUTEX_DRIVER, NULL); @@ -1301,8 +1470,16 @@ } tpm->flags |= TPM_DIDMINOR; +#ifdef KCF_TPM_RNG_PROVIDER + /* register RNG with kcf */ + if (tpmrng_register(tpm) != DDI_SUCCESS) + cmn_err(CE_WARN, "%s: tpm RNG failed to register with kcf", + myname); +#endif + return (DDI_SUCCESS); FAIL: + cmn_err(CE_WARN, "%s: tpm failed to attach", myname); if (tpm != NULL) { tpm_cleanup(dip, tpm); ddi_soft_state_free(statep, instance); @@ -1322,6 +1499,16 @@ if (tpm == NULL) return; +#ifdef KCF_TPM_RNG_PROVIDER + (void) tpmrng_unregister(tpm); +#endif + +#ifdef sun4v + if (tpm->flags & TPM_HSVC_REGISTERED) { + (void) hsvc_unregister(&hsvc_tpm); + tpm->flags &= ~(TPM_HSVC_REGISTERED); + } +#endif if (tpm->flags & TPM_DID_MUTEX) { mutex_destroy(&tpm->dev_lock); tpm->flags &= ~(TPM_DID_MUTEX); @@ -1378,6 +1565,9 @@ ASSERT(dip != NULL); instance = ddi_get_instance(dip); + if (instance < 0) + return (DDI_FAILURE); + if ((tpm = ddi_get_soft_state(statep, instance)) == NULL) { cmn_err(CE_WARN, "%s: stored pointer to tpm state is NULL", myname); @@ -1463,10 +1653,7 @@ myname, otyp, OTYP_CHR); return (EINVAL); } - mutex_enter(&tpm->pm_mutex); - while (tpm->suspended) - cv_wait(&tpm->suspend_cv, &tpm->pm_mutex); - mutex_exit(&tpm->pm_mutex); + TPM_EXCLUSIVE_LOCK(tpm); mutex_enter(&tpm->dev_lock); if (tpm->dev_held) { @@ -1502,10 +1689,7 @@ myname, otyp, OTYP_CHR); return (EINVAL); } - mutex_enter(&tpm->pm_mutex); - while (tpm->suspended) - cv_wait(&tpm->suspend_cv, &tpm->pm_mutex); - mutex_exit(&tpm->pm_mutex); + TPM_EXCLUSIVE_LOCK(tpm); ASSERT(tpm->dev_held); @@ -1538,13 +1722,10 @@ return (EFAULT); } - mutex_enter(&tpm->pm_mutex); - while (tpm->suspended) - cv_wait(&tpm->suspend_cv, &tpm->pm_mutex); - mutex_exit(&tpm->pm_mutex); + TPM_EXCLUSIVE_LOCK(tpm); /* Receive the data after requiring the lock */ - ret = tpm_lock(tpm); + ret = tpm_io_lock(tpm); /* Timeout reached */ if (ret == ETIME) @@ -1614,10 +1795,7 @@ return (EFAULT); } - mutex_enter(&tpm->pm_mutex); - while (tpm->suspended) - cv_wait(&tpm->suspend_cv, &tpm->pm_mutex); - mutex_exit(&tpm->pm_mutex); + TPM_EXCLUSIVE_LOCK(tpm); len = uiop->uio_resid; if (len == 0) { @@ -1626,7 +1804,7 @@ } /* Get the lock for using iobuf */ - ret = tpm_lock(tpm); + ret = tpm_io_lock(tpm); /* Timeout Reached */ if (ret == ETIME) return (ret); @@ -1682,7 +1860,7 @@ * This is to deal with the contentions for the iobuf */ static inline int -tpm_lock(tpm_state_t *tpm) +tpm_io_lock(tpm_state_t *tpm) { int ret; clock_t timeout; @@ -1698,8 +1876,10 @@ if (ret <= 0) { /* Timeout reached */ mutex_exit(&tpm->iobuf_lock); - cmn_err(CE_WARN, "tpm_lock:iorequest timed out"); - return (ETIME); +#ifdef DEBUG + cmn_err(CE_WARN, "tpm_io_lock:iorequest timed out"); +#endif + return (CRYPTO_BUSY); } } tpm->iobuf_inuse = 1; @@ -1720,3 +1900,244 @@ cv_broadcast(&tpm->iobuf_cv); mutex_exit(&tpm->iobuf_lock); } + +#ifdef KCF_TPM_RNG_PROVIDER +/* + * Random number generator entry points + */ +static void +strncpy_spacepad(uchar_t *s1, char *s2, int n) +{ + int s2len = strlen(s2); + (void) strncpy((char *)s1, s2, n); + if (s2len < n) + (void) memset(s1 + s2len, ' ', n - s2len); +} + +/*ARGSUSED*/ +static int +tpmrng_ext_info(crypto_provider_handle_t prov, + crypto_provider_ext_info_t *ext_info, + crypto_req_handle_t cfreq) +{ + tpm_state_t *tpm = (tpm_state_t *)prov; + char buf[64]; + + if (tpm == NULL) + return (DDI_FAILURE); + + strncpy_spacepad(ext_info->ei_manufacturerID, + (char *)tpm->vers_info.tpmVendorID, + sizeof (ext_info->ei_manufacturerID)); + + strncpy_spacepad(ext_info->ei_model, "0", + sizeof (ext_info->ei_model)); + strncpy_spacepad(ext_info->ei_serial_number, "0", + sizeof (ext_info->ei_serial_number)); + + ext_info->ei_flags = CRYPTO_EXTF_RNG | CRYPTO_EXTF_SO_PIN_LOCKED; + ext_info->ei_max_session_count = CRYPTO_EFFECTIVELY_INFINITE; + ext_info->ei_max_pin_len = 0; + ext_info->ei_min_pin_len = 0; + ext_info->ei_total_public_memory = CRYPTO_UNAVAILABLE_INFO; + ext_info->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO; + ext_info->ei_total_private_memory = CRYPTO_UNAVAILABLE_INFO; + ext_info->ei_free_public_memory = CRYPTO_UNAVAILABLE_INFO; + ext_info->ei_time[0] = 0; + + ext_info->ei_hardware_version.cv_major = tpm->vers_info.version.major; + ext_info->ei_hardware_version.cv_minor = tpm->vers_info.version.minor; + ext_info->ei_firmware_version.cv_major = + tpm->vers_info.version.revMajor; + ext_info->ei_firmware_version.cv_minor = + tpm->vers_info.version.revMinor; + + (void) snprintf(buf, sizeof (buf), "tpmrng TPM RNG"); + + strncpy_spacepad(ext_info->ei_label, buf, + sizeof (ext_info->ei_label)); +#undef BUFSZ + return (CRYPTO_SUCCESS); + +} + +static int +tpmrng_register(tpm_state_t *tpm) +{ + int ret; + char ID[64]; + crypto_mech_name_t *rngmech; + + ASSERT(tpm != NULL); + + (void) snprintf(ID, sizeof (ID), "tpmrng %s", IDENT_TPMRNG); + + tpmrng_prov_info.pi_provider_description = ID; + tpmrng_prov_info.pi_provider_dev.pd_hw = tpm->dip; + tpmrng_prov_info.pi_provider_handle = tpm; + + ret = crypto_register_provider(&tpmrng_prov_info, &tpm->n_prov); + if (ret != CRYPTO_SUCCESS) { + tpm->n_prov = NULL; + return (DDI_FAILURE); + } + + crypto_provider_notification(tpm->n_prov, CRYPTO_PROVIDER_READY); + + rngmech = kmem_zalloc(strlen("random") + 1, KM_SLEEP); + (void) memcpy(rngmech, "random", 6); + ret = crypto_load_dev_disabled("tpm", ddi_get_instance(tpm->dip), + 1, rngmech); + if (ret != CRYPTO_SUCCESS) { + cmn_err(CE_WARN, "crypto_load_dev_disabled failed (%d)", ret); + } + return (DDI_SUCCESS); +} + +static int +tpmrng_unregister(tpm_state_t *tpm) +{ + int ret; + ASSERT(tpm != NULL); + if (tpm->n_prov) { + ret = crypto_unregister_provider(tpm->n_prov); + tpm->n_prov = NULL; + if (ret != CRYPTO_SUCCESS) + return (DDI_FAILURE); + } + return (DDI_SUCCESS); +} + +/*ARGSUSED*/ +static void +tpmrng_provider_status(crypto_provider_handle_t provider, uint_t *status) +{ + *status = CRYPTO_PROVIDER_READY; +} + +/*ARGSUSED*/ +static int +tpmrng_seed_random(crypto_provider_handle_t provider, crypto_session_id_t sid, + uchar_t *buf, size_t len, uint_t entropy_est, uint32_t flags, + crypto_req_handle_t req) +{ + int ret; + tpm_state_t *tpm; + uint32_t len32; + /* Max length of seed is 256 bytes, add 14 for header. */ + uint8_t cmdbuf[270] = { + 0, 193, /* TPM_TAG_RQU COMMAND */ + 0, 0, 0, 0x0A, /* paramsize in bytes */ + 0, 0, 0, TPM_ORD_StirRandom, + 0, 0, 0, 0 /* number of input bytes (< 256) */ + }; + uint32_t buflen; + + if (len == 0 || len > 255 || buf == NULL) + return (CRYPTO_ARGUMENTS_BAD); + + tpm = (tpm_state_t *)provider; + if (tpm == NULL) + return (CRYPTO_INVALID_CONTEXT); + + /* Acquire lock for exclusive use of TPM */ + TPM_EXCLUSIVE_LOCK(tpm); + + ret = tpm_io_lock(tpm); + /* Timeout reached */ + if (ret == CRYPTO_BUSY) + return (ret); + + /* TPM only handles 32 bit length, so truncate if too big. */ + len32 = (uint32_t)len; + buflen = len32 + 14; + + /* The length must be in network order */ + buflen = htonl(buflen); + bcopy(&buflen, cmdbuf + 2, sizeof (uint32_t)); + + /* Convert it back */ + buflen = ntohl(buflen); + + /* length must be in network order */ + len32 = htonl(len32); + bcopy(&len32, cmdbuf + 10, sizeof (uint32_t)); + + /* convert it back */ + len32 = ntohl(len32); + + bcopy(buf, cmdbuf + 14, len32); + + ret = itpm_command(tpm, cmdbuf, buflen); + tpm_unlock(tpm); + + if (ret != DDI_SUCCESS) { +#ifdef DEBUG + cmn_err(CE_WARN, "tpmrng_seed_random failed"); +#endif + return (CRYPTO_FAILED); + } + + return (CRYPTO_SUCCESS); +} + +/* ARGSUSED */ +static int +tpmrng_generate_random(crypto_provider_handle_t provider, + crypto_session_id_t sid, uchar_t *buf, size_t len, crypto_req_handle_t req) +{ + int ret; + tpm_state_t *tpm; + uint8_t hdr[14] = { + 0, 193, /* TPM_TAG_RQU COMMAND */ + 0, 0, 0, 14, /* paramsize in bytes */ + 0, 0, 0, TPM_ORD_GetRandom, + 0, 0, 0, 0 + }; + uint8_t *cmdbuf = NULL; + uint32_t len32 = (uint32_t)len; + uint32_t buflen = len32 + sizeof (hdr); + + if (len == 0 || buf == NULL) + return (CRYPTO_ARGUMENTS_BAD); + + tpm = (tpm_state_t *)provider; + if (tpm == NULL) + return (CRYPTO_INVALID_CONTEXT); + + TPM_EXCLUSIVE_LOCK(tpm); + + ret = tpm_io_lock(tpm); + /* Timeout reached */ + if (ret == CRYPTO_BUSY) + return (ret); + + cmdbuf = kmem_zalloc(buflen, KM_SLEEP); + bcopy(hdr, cmdbuf, sizeof (hdr)); + + /* Length is written in network byte order */ + len32 = htonl(len32); + bcopy(&len32, cmdbuf + 10, sizeof (uint32_t)); + + ret = itpm_command(tpm, cmdbuf, buflen); + if (ret != DDI_SUCCESS) { +#ifdef DEBUG + cmn_err(CE_WARN, "tpmrng_generate_random failed"); +#endif + kmem_free(cmdbuf, buflen); + tpm_unlock(tpm); + return (CRYPTO_FAILED); + } + + /* Find out how many bytes were really returned */ + len32 = load32(cmdbuf, 10); + + /* Copy the random bytes back to the callers buffer */ + bcopy(cmdbuf + 14, buf, len32); + + kmem_free(cmdbuf, buflen); + tpm_unlock(tpm); + + return (CRYPTO_SUCCESS); +} +#endif /* KCF_TPM_RNG_PROVIDER */
--- a/usr/src/uts/common/io/tpm/tpm.conf Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/uts/common/io/tpm/tpm.conf Mon Aug 17 20:56:15 2009 -0700 @@ -1,1 +1,1 @@ -ddi-forceattach=1; +name="tpm" parent="pseudo" instance=0;
--- a/usr/src/uts/common/io/tpm/tpm_ddi.h Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/uts/common/io/tpm/tpm_ddi.h Mon Aug 17 20:56:15 2009 -0700 @@ -52,7 +52,10 @@ TPM_DID_IO_MUTEX = 0x200, TPM_DID_IO_CV = 0x400, TPM_DID_MUTEX = 0x800, - TPM_DID_SOFT_STATE = 0x1000 + TPM_DID_SOFT_STATE = 0x1000, +#ifdef sun4v + TPM_HSVC_REGISTERED = 0x2000 +#endif }; typedef struct tpm_state tpm_state_t; @@ -104,6 +107,9 @@ kmutex_t pm_mutex; kcondvar_t suspend_cv; uint32_t suspended; + + /* For RNG */ + crypto_kcf_provider_handle_t n_prov; }; #endif /* _TPM_DDI_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/uts/common/io/tpm/tpm_hcall.s Mon Aug 17 20:56:15 2009 -0700 @@ -0,0 +1,83 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Hypervisor calls used by tpm driver + */ + +#include <sys/asm_linkage.h> + +#if defined(sun4v) +#include <sys/hypervisor_api.h> + +#if defined(lint) || defined(__lint) + +/*ARGSUSED*/ +uint64_t +hcall_tpm_get(uint64_t locality, uint64_t offset, uint64_t size, + uint64_t *value) +{ + return (0); +} + +/*ARGSUSED*/ +uint64_t +hcall_tpm_put(uint64_t locality, uint64_t offset, uint64_t size, + uint64_t value) +{ + return (0); +} + +#else /* lint || __lint */ + +/* + * hcall_tpm_get(uint64_t locality, uint64_t offset, uint64_t size, + * uint64_t *value) + */ + ENTRY(hcall_tpm_get) + mov %o3, %g1 + mov HV_TPM_GET, %o5 + ta FAST_TRAP + stx %o1, [%g1] + retl + nop + SET_SIZE(hcall_tpm_get) + +/* + * uint64_t + * hcall_tpm_put(uint64_t locality, uint64_t offset, uint64_t size, + * uint64_t value) + */ + ENTRY(hcall_tpm_put) + mov HV_TPM_PUT, %o5 + ta FAST_TRAP + retl + nop + SET_SIZE(hcall_tpm_put) + +#endif /* lint || __lint */ + +#endif /* defined(sun4v) */
--- a/usr/src/uts/common/io/tpm/tpm_tis.h Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/uts/common/io/tpm/tpm_tis.h Mon Aug 17 20:56:15 2009 -0700 @@ -36,25 +36,26 @@ #define TIS_MEM_BASE 0xFED40000 #define TIS_MEM_LEN 0x5000 -/* Different locality(x)'s Offsets for TPM Registers (TIS 1.2 pg33-36) */ +#define TPM_LOCALITY_OFFSET(x) ((x) << 12) + /* Used to gain ownership */ -#define TPM_ACCESS_(x) (0x0000 | ((x)<<12)) +#define TPM_ACCESS 0x0000 /* Enable Interrupts */ -#define TPM_INT_ENABLE_(x) (0x0008 | ((x)<<12)) +#define TPM_INT_ENABLE 0x0008 /* Interrupt vector (SIRQ values) */ -#define TPM_INT_VECTOR_(x) (0x000C | ((x)<<12)) +#define TPM_INT_VECTOR 0x000C /* What caused interrupt */ -#define TPM_INT_STATUS_(x) (0x0010 | ((x)<<12)) +#define TPM_INT_STATUS 0x0010 /* Supported Interrupts */ -#define TPM_INTF_CAP_(x) (0x0014 | ((x)<<12)) +#define TPM_INTF_CAP 0x0014 /* Status Register */ -#define TPM_STS_(x) (0x0018 | ((x)<<12)) +#define TPM_STS 0x0018 /* I/O FIFO */ -#define TPM_DATA_FIFO_(x) (0x0024 | ((x)<<12)) +#define TPM_DATA_FIFO 0x0024 /* Vendor and Device ID */ -#define TPM_DID_VID_(x) (0x0F00 | ((x)<<12)) +#define TPM_DID_VID 0x0F00 /* Revision ID */ -#define TPM_RID_(x) (0x0F04 | ((x)<<12)) +#define TPM_RID 0x0F04 /* The number of all ordinals */ #define TSC_ORDINAL_MAX 12
--- a/usr/src/uts/sun4v/Makefile.sun4v.shared Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/uts/sun4v/Makefile.sun4v.shared Mon Aug 17 20:56:15 2009 -0700 @@ -344,6 +344,7 @@ DRV_KMODS += qcn DRV_KMODS += rootnex DRV_KMODS += su +DRV_KMODS += tpm DRV_KMODS += trapstat DRV_KMODS += vcc DRV_KMODS += vdc
--- a/usr/src/uts/sun4v/sys/hsvc.h Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/uts/sun4v/sys/hsvc.h Mon Aug 17 20:56:15 2009 -0700 @@ -48,6 +48,7 @@ #define HSVC_GROUP_VSC 0x0102 #define HSVC_GROUP_NCS 0x0103 #define HSVC_GROUP_RNG 0x0104 +#define HSVC_GROUP_TPM 0x0107 #define HSVC_GROUP_NIAGARA_CPU 0x0200 #define HSVC_GROUP_FIRE_PERF 0x0201 #define HSVC_GROUP_NIAGARA2_CPU 0x0202
--- a/usr/src/uts/sun4v/sys/hypervisor_api.h Mon Aug 17 20:49:16 2009 -0700 +++ b/usr/src/uts/sun4v/sys/hypervisor_api.h Mon Aug 17 20:56:15 2009 -0700 @@ -167,6 +167,9 @@ #define MMU_STAT_AREA 0xfc #endif /* SET_MMU_STATS */ +#define HV_TPM_GET 0x176 +#define HV_TPM_PUT 0x177 + #define HV_TM_ENABLE 0x180 #define HV_RA2PA 0x200