[vbox-dev] Virtual TPM device
Alberto Borsetta
alberto.borsetta at gmail.com
Fri Oct 16 15:45:53 PDT 2009
Hello to all
I've developed a Virtual TPM device for VirtualBox. I have worked with
3.0.6 release but i think it's easy to patch also the current release.
The device implemente an Atmel TPM (there are the device driver for
Linux and for Windows Vista/Seven) and use the TPM emulator available
to http://tpm-emulator.berlios.de
If you would like to test and use the vTPM device, you have to install
the TPM emulator (be shure to change the constant TPM_COMMAND_TIMEOUT
in tpmd.c file from 30 to 300 or more) and start it, the start a
Virtual Machine with an OS which has the Atmel device driver and a TSS
(TrouSerS in linux). I have test the vTPM device with the IBM
testsuite and with tpm manager.
Now I'm trying to change the bios to make possible the remote
attestation and use trusted grub.
Thanks to all for testing the system
Alberto Borsetta
diff -ruN a/.dep.inc b/.dep.inc
--- a/.dep.inc 1970-01-01 01:00:00.000000000 +0100
+++ b/.dep.inc 2009-10-02 10:53:16.000000000 +0200
@@ -0,0 +1,5 @@
+# This code depends on make tool being used
+DEPFILES=$(wildcard $(addsuffix .d, ${OBJECTFILES}))
+ifneq (${DEPFILES},)
+include ${DEPFILES}
+endif
diff -ruN a/include/VBox/log.h b/include/VBox/log.h
--- a/include/VBox/log.h 2009-04-27 19:54:17.000000000 +0200
+++ b/include/VBox/log.h 2009-09-24 21:42:04.000000000 +0200
@@ -129,6 +129,8 @@
LOG_GROUP_DEV_PIT,
/** RTC Device group. */
LOG_GROUP_DEV_RTC,
+ /** TPM Device group */
+ LOG_GROUP_DEV_TPM,
/** Serial Device group */
LOG_GROUP_DEV_SERIAL,
/** System Management Controller Device group. */
@@ -163,6 +165,8 @@
LOG_GROUP_DRV_HOST_FLOPPY,
/** Host Parallel Driver group */
LOG_GROUP_DRV_HOST_PARALLEL,
+ /** TPM Driver Group */
+ LOG_GROUP_DRV_TPM,
/** Host Serial Driver Group */
LOG_GROUP_DRV_HOST_SERIAL,
/** The internal networking transport driver group. */
diff -ruN a/include/VBox/pdmdev.h b/include/VBox/pdmdev.h
--- a/include/VBox/pdmdev.h 2009-04-27 19:54:17.000000000 +0200
+++ b/include/VBox/pdmdev.h 2009-09-23 12:23:48.000000000 +0200
@@ -391,6 +391,8 @@
#define PDM_DEVREG_CLASS_SERIAL RT_BIT(16)
/** Parallel controller device */
#define PDM_DEVREG_CLASS_PARALLEL RT_BIT(17)
+/** TPM device. */
+#define PDM_DEVREG_CLASS_TPM RT_BIT(18)
/** Misc devices (always last). */
#define PDM_DEVREG_CLASS_MISC RT_BIT(31)
/** @} */
diff -ruN a/include/VBox/pdmifs.h b/include/VBox/pdmifs.h
--- a/include/VBox/pdmifs.h 2009-04-27 19:54:17.000000000 +0200
+++ b/include/VBox/pdmifs.h 2009-10-01 22:27:12.000000000 +0200
@@ -69,8 +69,12 @@
/** PDMICHARPORT - The char notify interface.
(Down) Coupled with PDMINTERFACE_CHAR. */
PDMINTERFACE_CHAR_PORT,
/** PDMICHAR - The char driver interface.
(Up) Coupled with PDMINTERFACE_CHAR_PORT. */
- PDMINTERFACE_CHAR,
- /** PDMISTREAM - The stream driver interface
(Up) No coupling.
+ PDMINTERFACE_CHAR,
+ /** PDMITPMPORT - The TPM notify interface.
(Down) Coupled with PDMINTERFACE_TPM. */
+ PDMINTERFACE_TPM_PORT,
+ /** PDMITPM - The TPM driver interface.
(Up) Coupled with PDMINTERFACE_TPM_PORT. */
+ PDMINTERFACE_TPM,
+ /** PDMISTREAM - The stream driver interface
(Up) No coupling.
* Used by a char driver to implement PDMINTERFACE_CHAR. */
PDMINTERFACE_STREAM,
/** PDMIBLOCKPORT - The block notify interface
(Down) Coupled with PDMINTERFACE_BLOCK. */
@@ -1501,6 +1505,68 @@
DECLR3CALLBACKMEMBER(int,
pfnNotifyStatusLinesChanged,(PPDMICHARPORT pInterface, uint32_t
fNewStatusLines));
} PDMICHARPORT;
+/** Pointer to a TPM device interface. */
+typedef struct PDMITPMPORT *PPDMITPMPORT;
+/**
+ * TPM port interface.
+ * Pair with PDMITPM.
+ */
+typedef struct PDMITPMPORT
+{
+ /**
+ * Deliver data read to the device/driver.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure
containing the called function pointer.
+ * @param pvBuf Where the read bits are stored.
+ * @param pcbRead Number of bytes available for
reading/having been read.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnNotifyRead,(PPDMITPMPORT pInterface,
const void *pvBuf, size_t *pcbRead));
+
+ /**
+ * Notify the device/driver when the status lines changed.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure
containing the called function pointer.
+ * @param fNewStatusLine New state of the status line pins.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int,
pfnNotifyStatusLinesChanged,(PPDMITPMPORT pInterface, uint32_t
fNewStatusLines));
+} PDMITPMPORT;
+
+/** Pointer to a char interface. */
+typedef struct PDMITPM *PPDMITPM;
+/**
+ * TPM interface.
+ * Pair with PDMITPMPORT.
+ */
+typedef struct PDMITPM
+{
+
+ /**
+ * Read bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure
containing the called function pointer.
+ * @param pvBuf Where to store the read bits.
+ * @param cbRead Number of bytes to read/bytes actually read.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRead,(PPDMITPM pInterface, void
*pvBuf, size_t *cbRead));
+
+ /**
+ * Write bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure
containing the called function pointer.
+ * @param pvBuf Where to store the write bits.
+ * @param cbWrite Number of bytes to write.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMITPM pInterface, const
void *pvBuf, size_t *cbWrite));
+
+} PDMITPM;
/** Pointer to a char interface. */
typedef struct PDMICHAR *PPDMICHAR;
diff -ruN a/Makefile.kmk b/Makefile.kmk
--- a/Makefile.kmk 2009-04-27 21:01:29.000000000 +0200
+++ b/Makefile.kmk 2009-09-23 12:17:44.000000000 +0200
@@ -377,6 +377,7 @@
src/VBox/Devices/Networking \
src/VBox/Devices/PC \
src/VBox/Devices/PC/BIOS \
+ src/VBox/Devices/TPM \
src/VBox/Devices/Parallel \
src/VBox/Devices/Serial \
src/VBox/Devices/Storage \
diff -ruN a/src/VBox/Devices/Builtins.cpp b/src/VBox/Devices/Builtins.cpp
--- a/src/VBox/Devices/Builtins.cpp 2009-10-08 10:19:26.000000000 +0200
+++ b/src/VBox/Devices/Builtins.cpp 2009-09-21 16:36:00.000000000 +0200
@@ -153,6 +153,9 @@
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceSerialPort);
if (RT_FAILURE(rc))
return rc;
+ rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceTPMPort);
+ if (RT_FAILURE(rc))
+ return rc;
rc = pCallbacks->pfnRegister(pCallbacks, &g_DeviceParallelPort);
if (RT_FAILURE(rc))
return rc;
@@ -267,6 +270,9 @@
rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostSerial);
if (RT_FAILURE(rc))
return rc;
+ rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvTPM);
+ if (RT_FAILURE(rc))
+ return rc;
#endif
#if defined(VBOX_WITH_PDM_ASYNC_COMPLETION)
diff -ruN a/src/VBox/Devices/Builtins.h b/src/VBox/Devices/Builtins.h
--- a/src/VBox/Devices/Builtins.h 2009-10-08 10:20:06.000000000 +0200
+++ b/src/VBox/Devices/Builtins.h 2009-09-26 11:00:43.000000000 +0200
@@ -61,6 +61,7 @@
extern const PDMDEVREG g_DeviceDMA;
extern const PDMDEVREG g_DeviceFloppyController;
extern const PDMDEVREG g_DeviceSerialPort;
+extern const PDMDEVREG g_DeviceTPMPort;
extern const PDMDEVREG g_DeviceParallelPort;
#ifdef VBOX_WITH_AHCI
extern const PDMDEVREG g_DeviceAHCI;
@@ -106,6 +107,7 @@
extern const PDMDRVREG g_DrvNamedPipe;
extern const PDMDRVREG g_DrvHostParallel;
extern const PDMDRVREG g_DrvHostSerial;
+extern const PDMDRVREG g_DrvTPM;
#ifdef VBOX_WITH_USB
extern const PDMUSBREG g_UsbDevProxy;
diff -ruN a/src/VBox/Devices/Makefile.kmk b/src/VBox/Devices/Makefile.kmk
--- a/src/VBox/Devices/Makefile.kmk 2009-09-15 23:40:03.000000000 +0200
+++ b/src/VBox/Devices/Makefile.kmk 2009-09-26 10:57:49.000000000 +0200
@@ -278,6 +278,7 @@
PC/DevDMA.cpp \
Storage/fdc.c \
Serial/DevSerial.cpp \
+ TPM/DevTPM.cpp \
Parallel/DevParallel.cpp
ifdef VBOX_WITH_E1000
@@ -427,6 +428,7 @@
Storage/DevATA.cpp \
Network/DevPCNet.cpp \
Serial/DevSerial.cpp \
+ TPM/DevTPM.cpp \
Parallel/DevParallel.cpp
ifdef VBOX_WITH_E1000
@@ -503,6 +505,7 @@
Storage/DevATA.cpp \
Network/DevPCNet.cpp \
Serial/DevSerial.cpp \
+ TPM/DevTPM.cpp \
Parallel/DevParallel.cpp
ifdef VBOX_WITH_E1000
@@ -625,6 +628,7 @@
PC/DrvACPI.cpp \
Serial/DrvChar.cpp \
Serial/DrvNamedPipe.cpp \
+ TPM/DrvTPM.cpp \
Storage/DrvBlock.cpp \
Storage/DrvHostBase.cpp \
Storage/DrvHostDVD.cpp \
@@ -695,6 +699,7 @@
, $(Drivers_SOURCES)) \
Audio/coreaudio.c
Drivers_SOURCES.darwin = \
+ TPM/DrvTPM.cpp \
Serial/DrvHostSerial.cpp
endif # darwin
@@ -734,6 +739,7 @@
Network/DrvTAP.cpp \
Audio/ossaudio.c \
Parallel/DrvHostParallel.cpp \
+ TPM/DrvTPM.cpp \
Serial/DrvHostSerial.cpp
ifeq ($(KBUILD_TARGET),os2)
@@ -750,6 +756,7 @@
Audio/solaudio.c \
Storage/DrvHostBase.cpp \
Storage/DrvHostDVD.cpp \
+ TPM/DrvTPM.cpp \
Serial/DrvHostSerial.cpp
ifdef VBOX_WITH_CROSSBOW
Drivers_SOURCES += Network/solaris/vbox-libdlpi.cpp
@@ -762,6 +769,7 @@
Drivers_SOURCES.win = \
Audio/dsoundaudio.c \
+ TPM/DrvTPM.cpp \
Serial/DrvHostSerial.cpp
if defined(VBOX_WITH_NETFLT)
diff -ruN a/src/VBox/Devices/TPM/DevTPM.cpp b/src/VBox/Devices/TPM/DevTPM.cpp
--- a/src/VBox/Devices/TPM/DevTPM.cpp 1970-01-01 01:00:00.000000000 +0100
+++ b/src/VBox/Devices/TPM/DevTPM.cpp 2009-10-03 01:27:57.000000000 +0200
@@ -0,0 +1,748 @@
+/*******************************************************************************
+* Header Files
*
+*******************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEV_TPM
+#include <VBox/pdmdev.h>
+#include <iprt/assert.h>
+#include <iprt/uuid.h>
+#include <iprt/string.h>
+#include <iprt/semaphore.h>
+#include <iprt/critsect.h>
+
+#include "../Builtins.h"
+
+/*******************************************************************************
+* Defined Constants And Macros
*
+*******************************************************************************/
+
+#define TPM_SAVED_STATE_VERSION 1
+
+#define TPM_MAX_PKT 2048
+
+#define TPM_ADDR 0x4E
+/* just choose a free port */
+#define TPM_PORT_LO 0x00
+#define TPM_PORT_HI 0x67
+#define TPM_PORT ((TPM_PORT_HI << 8) | TPM_PORT_LO)
+
+/* write status bits */
+enum tpm_atmel_write_status {
+ ATML_STATUS_ABORT = 0x01,
+ ATML_STATUS_LASTBYTE = 0x04
+};
+
+/* read status bits */
+enum tpm_atmel_read_status {
+ ATML_STATUS_BUSY = 0x01,
+ ATML_STATUS_DATA_AVAIL = 0x02,
+ ATML_STATUS_REWRITE = 0x04,
+ ATML_STATUS_READY = 0x08
+};
+
+/*******************************************************************************
+* Structures and Typedefs
*
+*******************************************************************************/
+
+typedef struct TPMSTATE {
+
+ /** Access critical section. */
+ PDMCRITSECT CritSect;
+ /** Pointer to the device instance - R3 Ptr. */
+ PPDMDEVINSR3 pDevInsR3;
+ /** Pointer to the device instance - R0 Ptr. */
+ PPDMDEVINSR0 pDevInsR0;
+ /** Pointer to the device instance - RC Ptr. */
+ PPDMDEVINSRC pDevInsRC;
+ RTRCPTR Alignment0; /**< Alignment. */
+ /** The base interface. */
+ PDMIBASE IBase;
+ /** The character port interface. */
+ PDMITPMPORT ICharPort;
+ /** Pointer to the attached base driver. */
+ R3PTRTYPE(PPDMIBASE) pDrvBase;
+ /** Pointer to the attached character driver. */
+ R3PTRTYPE(PPDMITPM) pDrvTPM;
+
+ RTSEMEVENT ReceiveSem;
+
+ bool fGCEnabled;
+ bool fR0Enabled;
+ bool fYieldOnLSRRead;
+
+ unsigned char last_init_input;
+ unsigned char last_status_input;
+ unsigned char send_data[TPM_MAX_PKT];
+ unsigned char recv_data[TPM_MAX_PKT];
+ unsigned int send_data_index;
+ unsigned int recv_data_pos;
+ unsigned int recv_data_length;
+ /* boolean flags */
+ int data_to_send;
+ int data_to_recv;
+
+} tpmState;
+
+
+#ifndef VBOX_DEVICE_STRUCT_TESTCASE
+
+#define PDMIBASE_2_TPMSTATE(pInstance) ( (tpmState
*)((uintptr_t)(pInterface) - RT_OFFSETOF(tpmState, IBase)) )
+
+#define PDMICHARPORT_2_TPMSTATE(pInstance) ( (tpmState
*)((uintptr_t)(pInterface) - RT_OFFSETOF(tpmState, ICharPort)) )
+
+/*******************************************************************************/
+/* Internal Functions
*/
+/*******************************************************************************/
+
+__BEGIN_DECLS
+PDMBOTHCBDECL(int) TPMIOPortRead(PPDMDEVINS pDevIns, void *pvUser,
RTIOPORT Port, uint32_t *pu32, unsigned cb);
+PDMBOTHCBDECL(int) TPMIOPortWrite(PPDMDEVINS pDevIns, void *pvUser,
RTIOPORT Port, uint32_t u32, unsigned cb);
+PDMBOTHCBDECL(int) TPMinitPortRead(PPDMDEVINS pDevIns, void *pvUser,
RTIOPORT Port, uint32_t *pu32, unsigned cb);
+PDMBOTHCBDECL(int) TPMinitPortWrite(PPDMDEVINS pDevIns, void *pvUser,
RTIOPORT Port, uint32_t u32, unsigned cb);
+__END_DECLS
+
+#ifdef IN_RING3
+
+/**
+ * Read a byte from tpm internal buffer
+ */
+
+static uint32_t tpm_ioport_read_data(void *opaque, uint32_t addr)
+{
+ tpmState* s=(tpmState*)opaque;
+ if (s->recv_data_pos >= s->recv_data_length) {
+ return 0;
+ }
+ return s->recv_data[s->recv_data_pos++];
+}
+
+/**
+ * Write a byte to tpm internal buffer
+ */
+
+static void tpm_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
+{
+ tpmState* s=(tpmState*)opaque;
+ if (s->data_to_recv) {
+ return;
+ }
+ s->send_data[s->send_data_index++] = (char) (val & 0xFF);
+ s->data_to_send = 1;
+}
+
+/**
+ * Read status data from tpm
+ */
+
+static uint32_t tpm_ioport_read_status(void *opaque, uint32_t addr)
+{
+ tpmState* s=(tpmState*)opaque;
+ unsigned char status;
+
+ status = 0;
+/*
+ * This is a bit unclean: On the first status request we trigger sending
+ * the data to the tpm.
+ */
+ if (s->data_to_send) {
+ if (s->pDrvTPM->pfnWrite(s->pDrvTPM, s->send_data,
&s->send_data_index) != VINF_SUCCESS) {
+ LogRel(("TPM: Failed to write data to tpm!\n"));
+ return ATML_STATUS_BUSY;
+ }
+ s->send_data_index = 0;
+ s->recv_data_pos = 0;
+ s->recv_data_length = 0;
+ s->data_to_send = 0;
+ s->data_to_recv = 1;
+ }
+ if (s->data_to_recv) {
+ if (s->pDrvTPM->pfnRead(s->pDrvTPM, s->recv_data,
&s->recv_data_length) != VINF_SUCCESS) {
+ LogRel(("TPM: Failed to read data from tpm!\n"));
+ return ATML_STATUS_BUSY;
+ }
+ s->recv_data_pos = 0;
+ s->data_to_recv = 0;
+ }
+
+ if (s->recv_data_length > s->recv_data_pos)
+ status |= ATML_STATUS_DATA_AVAIL;
+ if (s->data_to_recv)
+ status |= ATML_STATUS_BUSY;
+ if (!status)
+ status = ATML_STATUS_READY;
+
+ return status;
+}
+
+/**
+ * Write status data to tpm
+ */
+
+static void tpm_ioport_write_status(void *opaque, uint32_t addr, uint32_t val)
+{
+ tpmState* s=(tpmState*)opaque;
+ s->last_status_input = (char) (val & 0xFF);
+}
+
+/**
+ * Read init data from tpm
+ */
+
+static uint32_t tpm_ioport_read_init(void *opaque, uint32_t addr, int *pRC)
+{
+ tpmState* s=(tpmState*)opaque;
+
+ *pRC = VINF_SUCCESS;
+ switch (s->last_init_input) {
+ /* see atmel_verify_tpm11() in the linux device driver sources */
+ case 0:
+ case 1:
+ return 1;
+ case 4:
+ return 'A';
+ case 5:
+ return 'T';
+ case 6:
+ return 'M';
+ case 7:
+ return 'L';
+ case 8:
+ return TPM_PORT_LO;
+ case 9:
+ return TPM_PORT_HI;
+ }
+
+ return 0;
+}
+
+/**
+ * Write init data to tpm
+ */
+
+static void tpm_ioport_write_init(void *opaque, uint32_t addr, uint32_t val)
+{
+ tpmState* s=(tpmState*)opaque;
+ s->last_init_input = (char) (val & 0xFF);
+}
+
+/**
+ * Read data from tpm
+ */
+
+static uint32_t tpm_ioport_read(void *opaque, uint32_t addr, int *pRC)
+{
+ tpmState* s=(tpmState*)opaque;
+ uint32_t ret = ~0U;
+
+ *pRC = VINF_SUCCESS;
+
+ addr &= 1;
+ switch(addr) {
+ default:
+ case 0:
+ ret = tpm_ioport_read_data(s, addr);
+ break;
+ case 1:
+ ret = tpm_ioport_read_status(s, addr);
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * Write data to tpm
+ */
+
+static int tpm_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ tpmState* s=(tpmState*)opaque;
+ unsigned char ch;
+
+ addr &= 1;
+
+ switch(addr) {
+ default:
+ case 0:
+ tpm_ioport_write_data(s, addr, val);
+ break;
+ case 1:
+ tpm_ioport_write_status(s, addr, val);
+ break;
+ }
+ return VINF_SUCCESS;
+}
+
+/****************************************************************************/
+/* VirtualBox code start */
+/****************************************************************************/
+
+/**
+ * Implements the TPM port interface
+ */
+
+static DECLCALLBACK(int) TPMNotifyRead(PPDMITPMPORT pInterface, const
void *pvBuf, size_t *pcbRead)
+{
+ return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) TPMNotifyStatusLinesChanged(PPDMITPMPORT
pInterface, uint32_t newStatusLines)
+{
+ return VINF_SUCCESS;
+}
+
+/**
+ * Port I/O Handler for IN operations.
+ *
+ * @returns VBox status code.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param Port Port number used for the IN operation.
+ * @param u32 The value in input.
+ * @param cb The value size in bytes.
+ */
+PDMBOTHCBDECL(int) TPMIOPortRead(PPDMDEVINS pDevIns, void *pvUser,
+ RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ tpmState *s = PDMINS_2_DATA(pDevIns, tpmState *);
+ int rc = VINF_SUCCESS;
+
+ if (cb == 1)
+ {
+ rc = PDMCritSectEnter(&s->CritSect, VINF_IOM_HC_IOPORT_READ);
+ if (rc == VINF_SUCCESS)
+ {
+ *pu32 = tpm_ioport_read(s, Port, &rc);
+ LogRel(("%s: port=%#06x val=%#04x\n", __FUNCTION__, Port, *pu32));
+ PDMCritSectLeave(&s->CritSect);
+ }
+ }
+ else
+ rc = VERR_IOM_IOPORT_UNUSED;
+
+ return rc;
+}
+
+/**
+ * Port I/O Handler for OUT operations.
+ *
+ * @returns VBox status code.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param Port Port number used for the OUT operation.
+ * @param u32 The value to output.
+ * @param cb The value size in bytes.
+ */
+PDMBOTHCBDECL(int) TPMIOPortWrite(PPDMDEVINS pDevIns, void *pvUser,
+ RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ tpmState *s = PDMINS_2_DATA(pDevIns, tpmState *);
+ int rc = VINF_SUCCESS;
+
+ if (cb == 1)
+ {
+ rc = PDMCritSectEnter(&s->CritSect, VINF_IOM_HC_IOPORT_WRITE);
+ if (rc == VINF_SUCCESS)
+ {
+ LogRel(("%s: port=%#06x val=%#04x\n", __FUNCTION__, Port, u32));
+ rc = tpm_ioport_write(s, Port, u32);
+ PDMCritSectLeave(&s->CritSect);
+ }
+ }
+ else
+ LogRel(("%s: failed to write data. port=%#06x cb=%d
u32=%#04x", __FUNCTION__, Port, cb, u32));
+
+ return rc;
+}
+
+/**
+ * Port I/O Handler for read init operations.
+ *
+ * @returns VBox status code.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param Port Port number used for the IN operation.
+ * @param u32 The value in input.
+ * @param cb The value size in bytes.
+ */
+PDMBOTHCBDECL(int) TPMinitPortRead(PPDMDEVINS pDevIns, void *pvUser,
RTIOPORT Port, uint32_t *pu32, unsigned cb)
+{
+ tpmState *s = PDMINS_2_DATA(pDevIns, tpmState *);
+ int rc = VINF_SUCCESS;
+
+ if (cb == 1)
+ {
+ rc = PDMCritSectEnter(&s->CritSect, VINF_IOM_HC_IOPORT_READ);
+ if (rc == VINF_SUCCESS)
+ {
+ *pu32 = tpm_ioport_read_init(s, Port, &rc);
+ LogRel(("%s: port=%#06x val=%#04x\n", __FUNCTION__, Port, *pu32));
+ PDMCritSectLeave(&s->CritSect);
+ }
+ }
+ else
+ rc = VERR_IOM_IOPORT_UNUSED;
+
+ return rc;
+}
+
+/**
+ * Port I/O Handler for write init operations.
+ *
+ * @returns VBox status code.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param Port Port number used for the OUT operation.
+ * @param u32 The value to output.
+ * @param cb The value size in bytes.
+ */
+PDMBOTHCBDECL(int) TPMinitPortWrite(PPDMDEVINS pDevIns, void *pvUser,
RTIOPORT Port, uint32_t u32, unsigned cb)
+{
+ tpmState *s = PDMINS_2_DATA(pDevIns, tpmState *);
+ int rc = VINF_SUCCESS;
+
+ if (cb == 1)
+ {
+ rc = PDMCritSectEnter(&s->CritSect, VINF_IOM_HC_IOPORT_WRITE);
+ if (rc == VINF_SUCCESS)
+ {
+ LogRel(("%s: port=%#06x val=%#04x\n", __FUNCTION__, Port, u32));
+ tpm_ioport_write_init(s, Port, u32);
+ PDMCritSectLeave(&s->CritSect);
+ }
+ }
+ else
+ LogRel(("%s: failed to write init. port=%#x cb=%d u32=%#x\n",
__FUNCTION__, Port, cb, u32));
+
+ return rc;
+}
+
+/**
+ * Loads a saved TPM port device state.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pSSMHandle The handle to the saved state.
+ * @param u32Version The data unit version number.
+ */
+static DECLCALLBACK(int) TPMLoadExec(PPDMDEVINS pDevIns,
+ PSSMHANDLE pSSMHandle,
+ uint32_t u32Version)
+{
+ tpmState *s = PDMINS_2_DATA(pDevIns, tpmState *);
+
+ if (u32Version != TPM_SAVED_STATE_VERSION)
+ return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
+
+ SSMR3GetU8(pSSMHandle, &s->last_init_input);
+ SSMR3GetU8(pSSMHandle, &s->last_status_input);
+
+ SSMR3GetMem(pSSMHandle, &s->send_data, TPM_MAX_PKT);
+ SSMR3GetMem(pSSMHandle, &s->recv_data, TPM_MAX_PKT);
+
+ SSMR3GetU32(pSSMHandle, &s->send_data_index);
+ SSMR3GetU32(pSSMHandle, &s->recv_data_pos);
+ SSMR3GetU32(pSSMHandle, &s->recv_data_length);
+
+ SSMR3GetS32(pSSMHandle, &s->data_to_send);
+ SSMR3GetS32(pSSMHandle, &s->data_to_recv);
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Saves a state of the TPM port device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pSSMHandle The handle to save the state to.
+ */
+static DECLCALLBACK(int) TPMSaveExec(PPDMDEVINS pDevIns,
+ PSSMHANDLE pSSMHandle)
+{
+ tpmState *s = PDMINS_2_DATA(pDevIns, tpmState *);
+
+ SSMR3PutU8(pSSMHandle, s->last_init_input);
+ SSMR3PutU8(pSSMHandle, s->last_status_input);
+
+ SSMR3PutMem(pSSMHandle, s->send_data, TPM_MAX_PKT);
+ SSMR3PutMem(pSSMHandle, s->recv_data, TPM_MAX_PKT);
+
+ SSMR3PutU32(pSSMHandle, s->send_data_index);
+ SSMR3PutU32(pSSMHandle, s->recv_data_pos);
+ SSMR3PutU32(pSSMHandle, s->recv_data_length);
+
+ SSMR3PutS32(pSSMHandle, s->data_to_send);
+ SSMR3PutS32(pSSMHandle, s->data_to_recv);
+
+ return SSMR3PutU32(pSSMHandle, ~0); /* sanity/terminator */
+}
+
+/**
+ * @copydoc FNPDMDEVRELOCATE
+ */
+static DECLCALLBACK(void) TPMRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
+{
+ tpmState *s = PDMINS_2_DATA(pDevIns, tpmState *);
+ s->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+}
+
+
+/**
+ * @copyfrom PIBASE::pfnqueryInterface
+ */
+static DECLCALLBACK(void *) TPMQueryInterface(PPDMIBASE pInterface,
PDMINTERFACE enmInterface)
+{
+ tpmState *s = PDMIBASE_2_TPMSTATE(pInterface);
+ switch (enmInterface)
+ {
+ case PDMINTERFACE_BASE:
+ return &s->IBase;
+ case PDMINTERFACE_TPM_PORT:
+ return &s->ICharPort;
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * Destruct a device instance.
+ *
+ * Most VM resources are freed by the VM. This callback is provided
so that any non-VM
+ * resources can be freed correctly.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data.
+ */
+static DECLCALLBACK(int) TPMDestruct(PPDMDEVINS pDevIns)
+{
+ tpmState *s = PDMINS_2_DATA(pDevIns, tpmState *);
+
+ RTSemEventDestroy(s->ReceiveSem);
+ s->ReceiveSem = NIL_RTSEMEVENT;
+
+ PDMR3CritSectDelete(&s->CritSect);
+ return VINF_SUCCESS;
+}
+
+/**
+ * Construct a device instance for a VM.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data.
+ * If the registration structure is needed,
pDevIns->pDevReg points to it.
+ * @param iInstance Instance number. Use this to figure out which
registers and such to use.
+ * The device number is also found in
pDevIns->iInstance, but since it's
+ * likely to be freqently used PDM passes it as parameter.
+ * @param pCfgHandle Configuration node handle for the device. Use
this to obtain the configuration
+ * of the device instance. It's also found in
pDevIns->pCfgHandle, but like
+ * iInstance it's expected to be used a bit in
this function.
+ */
+static DECLCALLBACK(int) TPMConstruct(PPDMDEVINS pDevIns,
+ int iInstance,
+ PCFGMNODE pCfgHandle)
+{
+ int rc;
+ tpmState *s = PDMINS_2_DATA(pDevIns, tpmState*);
+
+ Assert(iInstance < 4);
+
+ /*
+ * Initialize the instance data.
+ */
+
+ s->pDevInsR3 = pDevIns;
+ s->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
+ s->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
+ s->ReceiveSem = NIL_RTSEMEVENT;
+
+ /* IBase */
+ s->IBase.pfnQueryInterface = TPMQueryInterface;
+
+ /* ICharPort */
+ s->ICharPort.pfnNotifyRead = TPMNotifyRead;
+ s->ICharPort.pfnNotifyStatusLinesChanged = TPMNotifyStatusLinesChanged;
+
+ /*
+ * Initialize critical section and the semaphore.
+ * This must of course be done before attaching drivers or
anything else which can call us back..
+ */
+
+ char szName[24];
+ RTStrPrintf(szName, sizeof(szName), "TPM#%d", iInstance);
+ rc = PDMDevHlpCritSectInit(pDevIns, &s->CritSect, szName);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ rc = RTSemEventCreate(&s->ReceiveSem);
+ AssertRC(rc);
+
+ /*
+ * Register the I/O ports.
+ */
+
+ rc = PDMDevHlpIOPortRegister(pDevIns, TPM_PORT, 8, 0,
+ TPMIOPortWrite, TPMIOPortRead,
+ NULL, NULL, "TPM");
+ if (RT_FAILURE(rc))
+ {
+ LogRel(("%s: failed to register tpm IO port. rc=%Rrc\n",
__FUNCTION__, rc));
+ return rc;
+ }
+
+ if (s->fGCEnabled)
+ rc = PDMDevHlpIOPortRegisterGC(pDevIns, TPM_PORT, 8, 0,
"TPMIOPortWrite",
+ "TPMIOPortRead", NULL, NULL, "TPM");
+
+ if (s->fR0Enabled)
+ rc = PDMDevHlpIOPortRegisterR0(pDevIns, TPM_PORT, 8, 0,
"TPMIOPortWrite",
+ "TPMIOPortRead", NULL, NULL, "TPM");
+
+ /*
+ * Register the init ports.
+ */
+
+ rc = PDMDevHlpIOPortRegister(pDevIns, TPM_ADDR, 8, 0,
+ TPMinitPortWrite, TPMinitPortRead,
+ NULL, NULL, "TPM_init");
+ if (RT_FAILURE(rc))
+ {
+ LogRel(("%s: failed to register tpm init port. rc=%Rrc\n",
__FUNCTION__, rc));
+ return rc;
+ }
+
+ if (s->fGCEnabled)
+ rc = PDMDevHlpIOPortRegisterGC(pDevIns, TPM_ADDR, 8, 0,
"TPMinitPortWrite",
+ "TPMinitPortRead", NULL, NULL,
"TPM_init");
+
+ if (s->fR0Enabled)
+ rc = PDMDevHlpIOPortRegisterR0(pDevIns, TPM_ADDR, 8, 0,
"TPMinitPortWrite",
+ "TPMinitPortRead", NULL, NULL,
"TPM_init");
+
+ /*
+ * Saved state.
+ */
+
+ rc = PDMDevHlpSSMRegister(
+ pDevIns, /* pDevIns */
+ pDevIns->pDevReg->szDeviceName, /* pszName */
+ iInstance, /* u32Instance */
+ TPM_SAVED_STATE_VERSION, /* u32Version */
+ sizeof (*s), /* cbGuess */
+ NULL, /* pfnSavePrep */
+ TPMSaveExec, /* pfnSaveExec */
+ NULL, /* pfnSaveDone */
+ NULL, /* pfnLoadPrep */
+ TPMLoadExec, /* pfnLoadExec */
+ NULL /* pfnLoadDone */
+ );
+ if (RT_FAILURE(rc))
+ {
+ LogRel(("%s: failed to register tpm saved state manager port.
rc=%Rrc\n", __FUNCTION__, rc));
+ return rc;
+ }
+
+ /*
+ * Attach the char driver and get the interfaces.
+ * For now no run-time changes are supported.
+ */
+
+ rc = PDMDevHlpDriverAttach(pDevIns, 0, &s->IBase, &s->pDrvBase,
"TPM Char");
+ if (RT_SUCCESS(rc))
+ {
+ s->pDrvTPM = (PDMITPM
*)s->pDrvBase->pfnQueryInterface(s->pDrvBase, PDMINTERFACE_TPM);
+ if (!s->pDrvTPM)
+ {
+ LogRel(("%s: failed to configure char interface\n", __FUNCTION__));
+ return VERR_PDM_MISSING_INTERFACE;
+ }
+ }
+ else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
+ {
+ s->pDrvBase = NULL;
+ s->pDrvTPM = NULL;
+ LogRel(("%s: no tpm unit available\n", __FUNCTION__));
+ }
+ else
+ {
+ LogRel(("%s: failed to attach to char driver. rc=%Rrc\n",
__FUNCTION__, rc));
+ return rc;
+ }
+
+ /*
+ * Initialize tpmState
+ */
+
+ s->last_init_input = 0;
+ s->last_status_input = 0;
+ s->send_data_index = 0;
+ s->recv_data_length = 0;
+ s->recv_data_pos = 0;
+ s->data_to_send = 0;
+ s->data_to_recv = 0;
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * The device registration structure.
+ */
+const PDMDEVREG g_DeviceTPMPort =
+{
+ /* u32Version */
+ PDM_DEVREG_VERSION,
+ /* szDeviceName */
+ "TPM",
+ /* szRCMod */
+ "VBoxDDGC.gc",
+ /* szR0Mod */
+ "VBoxDDR0.r0",
+ /* pszDescription */
+ "Trusted Platform Module",
+ /* fFlags */
+ PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
+ /* fClass */
+ PDM_DEVREG_CLASS_TPM,
+ /* cMaxInstances */
+ 1,
+ /* cbInstance */
+ sizeof(tpmState),
+ /* pfnConstruct */
+ TPMConstruct,
+ /* pfnDestruct */
+ TPMDestruct,
+ /* pfnRelocate */
+ TPMRelocate,
+ /* pfnIOCtl */
+ NULL,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ NULL,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ NULL,
+ /* pfnAttach */
+ NULL,
+ /* pfnDetach */
+ NULL,
+ /* pfnQueryInterface. */
+ NULL,
+ /* pfnInitComplete */
+ NULL,
+ /* pfnPowerOff */
+ NULL,
+ /* pfnSoftReset */
+ NULL,
+ /* u32VersionEnd */
+ PDM_DEVREG_VERSION
+};
+
+#endif /* IN_RING3 */
+
+#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
+
diff -ruN a/src/VBox/Devices/TPM/DrvTPM.cpp b/src/VBox/Devices/TPM/DrvTPM.cpp
--- a/src/VBox/Devices/TPM/DrvTPM.cpp 1970-01-01 01:00:00.000000000 +0100
+++ b/src/VBox/Devices/TPM/DrvTPM.cpp 2009-10-10 13:59:06.000000000 +0200
@@ -0,0 +1,300 @@
+/** @file DrvTPM.cpp
+ *
+ * VBox TPM Driver
+ */
+
+
+/*******************************************************************************
+* Header Files
*
+*******************************************************************************/
+
+#define LOG_GROUP LOG_GROUP_DRV_TPM
+
+#define TPM_MAX_PKT 2048
+
+#include <VBox/pdmdrv.h>
+#include <iprt/assert.h>
+#include <iprt/file.h>
+#include <iprt/stream.h>
+#include <iprt/alloc.h>
+#include <iprt/string.h>
+#include <iprt/semaphore.h>
+
+#include "../Builtins.h"
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+/*******************************************************************************
+* Structures and Typedefs
*
+*******************************************************************************/
+
+/**
+ * TPM driver instance data.
+ */
+typedef struct TPMDRV
+{
+ /** Pointer to the driver instance. */
+ PPDMDRVINS pDrvIns;
+ /** Pointer to the char port interface of the driver/device above us. */
+ PPDMITPMPORT pCharPort;
+ /** Our host device interface. */
+ PDMITPM IStream;
+ /** Our host device port interface. */
+ PDMITPMPORT ICharPort;
+ /** Pointer to the TPM file name. */
+ char *pszLocation;
+ /** Socket handle of the local socket. */
+ RTSOCKET LocalSocket;
+} tpmDrv;
+
+
+#define PDMITPM_2_DRVTPM(pInterface) ( (tpmDrv
*)((uintptr_t)pInterface - RT_OFFSETOF(tpmDrv, IStream)) )
+
+#define PDMIBASE_2_DRVINS(pInterface) (
(PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
+
+/*******************************************************************************
+* Internal Functions
*
+*******************************************************************************/
+
+/**
+ * @copydoc PDMISTREAM::pfnRead
+ */
+static DECLCALLBACK(int) drvTPMRead(PPDMITPM pInterface, void *pvBuf,
size_t *pcbRead)
+{
+ int rc = VINF_SUCCESS;
+ tpmDrv* s = PDMITPM_2_DRVTPM(pInterface);
+ LogRel(("%s: pvBuf=%p *pcbRead=%#x (%s)\n", __FUNCTION__, pvBuf,
*pcbRead, s->pszLocation));
+
+ Assert(pvBuf);
+
+ if (s->LocalSocket != NIL_RTSOCKET)
+ {
+ ssize_t cbReallyRead;
+ cbReallyRead = recv(s->LocalSocket, pvBuf, TPM_MAX_PKT, 0);
+ LogRel(("%s: read from tpm %d bytes\n", __FUNCTION__, cbReallyRead));
+ if (cbReallyRead == 0)
+ {
+ RTSOCKET tmp = s->LocalSocket;
+ s->LocalSocket = NIL_RTSOCKET;
+ close(tmp);
+ }
+ else if (cbReallyRead == -1)
+ {
+ cbReallyRead = 0;
+ rc = RTErrConvertFromErrno(errno);
+ }
+ *pcbRead = cbReallyRead;
+ }
+ else
+ {
+ RTThreadSleep(100);
+ *pcbRead = 0;
+ }
+
+ LogRel(("%s: *pcbRead=%zu returns %Rrc\n", __FUNCTION__, *pcbRead, rc));
+ return rc;
+}
+
+/**
+ * @copydoc PDMISTREAM::pfnWrite
+ */
+static DECLCALLBACK(int) drvTPMWrite(PPDMITPM pInterface, const void
*pvBuf, size_t *pcbWrite)
+{
+ int rc = VINF_SUCCESS;
+ tpmDrv* s = PDMITPM_2_DRVTPM(pInterface);
+ LogRel(("%s: pvBuf=%p *pcbWrite=%#x (%s)\n", __FUNCTION__, pvBuf,
*pcbWrite, s->pszLocation));
+
+ Assert(pvBuf);
+
+ if (s->LocalSocket != NIL_RTSOCKET)
+ {
+ ssize_t cbWritten;
+ cbWritten = send(s->LocalSocket, pvBuf, *pcbWrite, 0);
+ LogRel(("%s: write to tpm %d bytes\n", __FUNCTION__, cbWritten));
+ if (cbWritten == 0)
+ {
+ RTSOCKET tmp = s->LocalSocket;
+ s->LocalSocket = NIL_RTSOCKET;
+ close(tmp);
+ }
+ else if (cbWritten == -1)
+ {
+ cbWritten = 0;
+ rc = RTErrConvertFromErrno(errno);
+ }
+ *pcbWrite = cbWritten;
+ }
+
+ LogRel(("%s: returns %Rrc\n", __FUNCTION__, rc));
+ return rc;
+}
+
+/**
+ * Queries an interface to the driver.
+ *
+ * @returns Pointer to interface.
+ * @returns NULL if the interface was not supported by the driver.
+ * @param pInterface Pointer to this interface structure.
+ * @param enmInterface The requested interface identification.
+ * @thread Any thread.
+ */
+static DECLCALLBACK(void *) drvTPMQueryInterface(PPDMIBASE
pInterface, PDMINTERFACE enmInterface)
+{
+ PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
+ tpmDrv* pDrv = PDMINS_2_DATA(pDrvIns, tpmDrv *);
+ switch (enmInterface)
+ {
+ case PDMINTERFACE_BASE:
+ return &pDrvIns->IBase;
+ case PDMINTERFACE_TPM:
+ return &pDrv->IStream;
+ default:
+ return NULL;
+ }
+}
+
+/**
+ * Construct a TPM stream driver instance.
+ *
+ * @returns VBox status.
+ * @param pDrvIns The driver instance data.
+ * If the registration structure is needed,
pDrvIns->pDrvReg points to it.
+ * @param pCfgHandle Configuration node handle for the driver. Use
this to obtain the configuration
+ * of the driver instance. It's also found in
pDrvIns->pCfgHandle, but like
+ * iInstance it's expected to be used a bit in
this function.
+ */
+static DECLCALLBACK(int) drvTPMConstruct(PPDMDRVINS pDrvIns,
PCFGMNODE pCfgHandle)
+{
+ char *pszLocation = NULL;
+ tpmDrv* s = PDMINS_2_DATA(pDrvIns, tpmDrv *);
+
+ /*
+ * Init the static parts.
+ */
+
+ s->pDrvIns = pDrvIns;
+ s->pszLocation = NULL;
+ s->LocalSocket = NIL_RTSOCKET;
+ /* IBase */
+ pDrvIns->IBase.pfnQueryInterface = drvTPMQueryInterface;
+ /* IStream */
+ s->IStream.pfnRead = drvTPMRead;
+ s->IStream.pfnWrite = drvTPMWrite;
+
+ /*
+ * Read the configuration.
+ */
+
+ s->pszLocation = pszLocation = "/var/run/tpm/tpmd_socket:0";
+
+ int sock;
+ struct sockaddr_un addr;
+
+ /*
+ * Create the local socket.
+ */
+
+ if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
+ return PDMDrvHlpVMSetError(pDrvIns,
RTErrConvertFromErrno(errno), RT_SRC_POS, N_("TPM#%d failed to create
local socket"), pDrvIns->iInstance);
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, pszLocation, sizeof(addr.sun_path)-1);
+
+ /*
+ * Connect to the local socket.
+ */
+
+ if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1)
+ return PDMDrvHlpVMSetError(pDrvIns,
RTErrConvertFromErrno(errno), RT_SRC_POS, N_("TPM#%d failed to connect
to local socket %s"), pDrvIns->iInstance, pszLocation);
+ s->LocalSocket = sock;
+
+ /*
+ * Get the ICharPort interface of the above driver/device.
+ */
+
+ s->pCharPort =
(PPDMITPMPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase,
PDMINTERFACE_TPM_PORT);
+ if (!s->pCharPort)
+ return PDMDrvHlpVMSetError(pDrvIns,
VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("TPM#%d has no TPM
port interface above"),
+ pDrvIns->iInstance);
+
+ LogRel(("%s: location %s \n", __FUNCTION__, pszLocation));
+
+ return VINF_SUCCESS;
+}
+
+/**
+ * Destruct a TPM stream driver instance.
+ *
+ * Most VM resources are freed by the VM. This callback is provided so that
+ * any non-VM resources can be freed correctly.
+ *
+ * @param pDrvIns The driver instance data.
+ */
+static DECLCALLBACK(void) drvTPMDestruct(PPDMDRVINS pDrvIns)
+{
+ tpmDrv* s = PDMINS_2_DATA(pDrvIns, tpmDrv *);
+ LogRel(("%s: %s\n", __FUNCTION__, s->pszLocation));
+
+ if (s->pszLocation)
+ MMR3HeapFree(s->pszLocation);
+}
+
+/**
+ * Power off a TPM stream driver instance.
+ *
+ * This does most of the destruction work, to avoid ordering dependencies.
+ *
+ * @param pDrvIns The driver instance data.
+ */
+static DECLCALLBACK(void) drvTPMPowerOff(PPDMDRVINS pDrvIns)
+{
+ tpmDrv* s = PDMINS_2_DATA(pDrvIns, tpmDrv *);
+ LogFlow(("%s: %s\n", __FUNCTION__, s->pszLocation));
+
+ if (s->LocalSocket != NIL_RTSOCKET)
+ close(s->LocalSocket);
+}
+
+/**
+ * TPM driver registration record.
+ */
+const PDMDRVREG g_DrvTPM =
+{
+ /* u32Version */
+ PDM_DRVREG_VERSION,
+ /* szDriverName */
+ "TPM",
+ /* pszDescription */
+ "TPM stream driver.",
+ /* fFlags */
+ PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
+ /* fClass. */
+ PDM_DRVREG_CLASS_STREAM,
+ /* cMaxInstances */
+ ~0,
+ /* cbInstance */
+ sizeof(tpmDrv),
+ /* pfnConstruct */
+ drvTPMConstruct,
+ /* pfnDestruct */
+ drvTPMDestruct,
+ /* pfnIOCtl */
+ NULL,
+ /* pfnPowerOn */
+ NULL,
+ /* pfnReset */
+ NULL,
+ /* pfnSuspend */
+ NULL,
+ /* pfnResume */
+ NULL,
+ /* pfnDetach */
+ NULL,
+ /* pfnPowerOff */
+ drvTPMPowerOff,
+};
diff -ruN a/src/VBox/Devices/vl_vbox.h b/src/VBox/Devices/vl_vbox.h
--- a/src/VBox/Devices/vl_vbox.h 2009-04-27 19:56:56.000000000 +0200
+++ b/src/VBox/Devices/vl_vbox.h 2009-09-25 17:50:03.000000000 +0200
@@ -77,8 +77,6 @@
typedef PCIDEVICE PCIDevice;
typedef RTGCUINTREG target_ulong;
-
-
/*
* Timers.
*/
diff -ruN a/src/VBox/Main/ConsoleImpl2.cpp b/src/VBox/Main/ConsoleImpl2.cpp
--- a/src/VBox/Main/ConsoleImpl2.cpp 2009-04-27 19:57:14.000000000 +0200
+++ b/src/VBox/Main/ConsoleImpl2.cpp 2009-09-30 15:56:53.000000000 +0200
@@ -2032,6 +2032,18 @@
}
+ /*
+ * TPM Device
+ */
+ rc = CFGMR3InsertNode(pDevices, "TPM", &pDev);
RC_CHECK();
+
+ rc = CFGMR3InsertNode(pDev, "0", &pInst);
RC_CHECK();
+ rc = CFGMR3InsertNode(pInst, "Config", &pCfg);
RC_CHECK();
+ rc = CFGMR3InsertNode(pInst, "LUN#0", &pLunL0);
RC_CHECK();
+ rc = CFGMR3InsertString(pLunL0, "Driver", "TPM");
RC_CHECK();
+ rc = CFGMR3InsertNode(pLunL0, "AttachedDriver", &pLunL1);
RC_CHECK();
+ rc = CFGMR3InsertString(pLunL1, "Driver", "TPM");
RC_CHECK();
+
/*
* Serial (UART) Ports
*/
More information about the vbox-dev
mailing list