[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH V2 4/8] Implementation of the TCG BIOS extensions
From: |
Stefan Berger |
Subject: |
[Qemu-devel] [PATCH V2 4/8] Implementation of the TCG BIOS extensions |
Date: |
Mon, 04 Apr 2011 21:29:43 -0400 |
User-agent: |
quilt/0.48-1 |
This patch implements the main part of the TCG BIOS extensions. It provides
the following functionality:
- initialization of the TCPA ACPI table used for logging of measurements
- initialization of the TPM by sending a sequence of commands to it
- proper setup of the TPM once the BIOS hands over control to the bootloader
- support for S3 resume; BIOS sends TPM_Startup(ST_STATE) to TPM
- enable configuration of SeaBIOS to be built with TCGBIOS extensions
depending on COREBOOT not being selected
All TCG BIOS extensions are activated with CONFIG_TCGBIOS.
Structures that are needed in subsequent patches are also included in
tcgbios.h at this point.
-v2:
- replace mssleep() with calls to msleep()
- Moving Kconfig patch to this file
- converting code to call dprintf(DEBUG_tcg, ...)
- use the get_rsdp call to get hold of the RSDP
- use util.c:checksum()
- Adapting tcgbios.c to be under LGPLv3
- using if (!CONFIG_TCGBIOS) everywhere
Signed-off-by: Stefan Berger <address@hidden>
---
src/Kconfig | 8 +
src/boot.c | 2
src/config.h | 1
src/post.c | 5
src/resume.c | 2
src/tcgbios.c | 394 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/tcgbios.h | 312 +++++++++++++++++++++++++++++++++++++++++++++
src/util.h | 3
8 files changed, 727 insertions(+)
Index: seabios/src/util.h
===================================================================
--- seabios.orig/src/util.h
+++ seabios/src/util.h
@@ -497,4 +497,7 @@ extern u8 BiosChecksum;
// version (auto generated file out/version.c)
extern const char VERSION[];
+// TCG BIOS extensions
+void tcpa_interrupt_handler16(struct bregs *regs);
+
#endif // util.h
Index: seabios/src/post.c
===================================================================
--- seabios.orig/src/post.c
+++ seabios/src/post.c
@@ -25,6 +25,7 @@
#include "paravirt.h" // qemu_cfg_port_probe
#include "ps2port.h" // ps2port_setup
#include "virtio-blk.h" // virtio_blk_setup
+#include "tcgbios.h" // tcpa_*
/****************************************************************
@@ -238,6 +239,10 @@ maininit(void)
mouse_setup();
init_bios_tables();
+ // Initialize tpm (after acpi tables were written)
+ tcpa_acpi_init();
+ tcpa_startup();
+
// Run vga option rom
vga_setup();
Index: seabios/src/boot.c
===================================================================
--- seabios.orig/src/boot.c
+++ seabios/src/boot.c
@@ -14,6 +14,7 @@
#include "cmos.h" // inb_cmos
#include "paravirt.h" // romfile_loadfile
#include "pci.h" //pci_bdf_to_*
+#include "tcgbios.h" // tcpa_*
/****************************************************************
@@ -449,6 +450,7 @@ boot_prep(void)
// Allow user to modify BCV/IPL order.
interactive_bootmenu();
wait_threads();
+ tcpa_leave_bios();
// Map drives and populate BEV list
struct bootentry_s *pos = BootList;
Index: seabios/src/resume.c
===================================================================
--- seabios.orig/src/resume.c
+++ seabios/src/resume.c
@@ -10,6 +10,7 @@
#include "biosvar.h" // struct bios_data_area_s
#include "bregs.h" // struct bregs
#include "acpi.h" // find_resume_vector
+#include "tcgbios.h" // tcpa_s3_resume
// Reset DMA controller
void
@@ -116,6 +117,7 @@ s3_resume(void)
if (s3_resume_vector) {
dprintf(1, "Jump to resume vector (%x)\n", s3_resume_vector);
br.code = FLATPTR_TO_SEGOFF((void*)s3_resume_vector);
+ tcpa_s3_resume();
} else {
dprintf(1, "No resume vector set!\n");
// Jump to the post vector to restart with a normal boot.
Index: seabios/src/config.h
===================================================================
--- seabios.orig/src/config.h
+++ seabios/src/config.h
@@ -119,5 +119,6 @@
#define DEBUG_unimplemented 2
#define DEBUG_invalid 3
#define DEBUG_thread 2
+#define DEBUG_tcg 20
#endif // config.h
Index: seabios/src/Kconfig
===================================================================
--- seabios.orig/src/Kconfig
+++ seabios/src/Kconfig
@@ -314,6 +314,14 @@ menu "BIOS interfaces"
default n
help
Disable A20 on 16bit boot.
+
+ config TCGBIOS
+ depends on !COREBOOT
+ bool "TPM support and TCG BIOS extensions"
+ default y
+ help
+ Provide TPM support along with TCG BIOS extensions
+
endmenu
menu "BIOS Tables"
Index: seabios/src/tcgbios.h
===================================================================
--- seabios.orig/src/tcgbios.h
+++ seabios/src/tcgbios.h
@@ -1,6 +1,22 @@
#ifndef TCGBIOS_H
#define TCGBIOS_H
+#include "types.h"
+#include "bregs.h" /* struct bregs */
+
+#define TCG_MAGIC 0x41504354L
+
+/* Define for section 12.3 */
+#define TCG_PC_OK 0x0
+#define TCG_PC_TPMERROR 0x1
+#define TCG_PC_LOGOVERFLOW 0x2
+#define TCG_PC_UNSUPPORTED 0x3
+
+#define TPM_ALG_SHA 0x4
+
+#define TCG_MAGIC 0x41504354L
+#define TCG_VERSION_MAJOR 1
+#define TCG_VERSION_MINOR 2
#define TPM_OK 0x0
#define TPM_RET_BASE 0x1
@@ -51,7 +67,303 @@
#define TPM_GENERAL_ERROR TCG_GENERAL_ERROR
+#define TPM_ORD_SelfTestFull 0x00000050
+#define TPM_ORD_ForceClear 0x0000005d
+#define TPM_ORD_GetCapability 0x00000065
+#define TPM_ORD_PhysicalEnable 0x0000006f
+#define TPM_ORD_PhysicalDisable 0x00000070
+#define TPM_ORD_SetOwnerInstall 0x00000071
+#define TPM_ORD_PhysicalSetDeactivated 0x00000072
+#define TPM_ORD_Startup 0x00000099
+#define TPM_ORD_PhysicalPresence 0x4000000a
+#define TPM_ORD_Extend 0x00000014
+#define TPM_ORD_SHA1Start 0x000000a0
+#define TPM_ORD_SHA1Update 0x000000a1
+#define TPM_ORD_SHA1Complete 0x000000a2
+
+
+#define TPM_ST_CLEAR 0x1
+#define TPM_ST_STATE 0x2
+#define TPM_ST_DEACTIVATED 0x3
+
+
+/* interrupt identifiers (al register) */
+enum irq_ids {
+ TCG_StatusCheck = 0,
+ TCG_HashLogExtendEvent = 1,
+ TCG_PassThroughToTPM = 2,
+ TCG_ShutdownPreBootInterface = 3,
+ TCG_HashLogEvent = 4,
+ TCG_HashAll = 5,
+ TCG_TSS = 6,
+ TCG_CompactHashLogExtendEvent = 7,
+};
+
+/* event types: 10.4.1 / table 11 */
+#define EV_POST_CODE 1
+#define EV_SEPARATOR 4
+#define EV_ACTION 5
+#define EV_EVENT_TAG 6
+#define EV_COMPACT_HASH 12
+#define EV_IPL 13
+#define EV_IPL_PARTITION_DATA 14
+
+
+#define STATUS_FLAG_SHUTDOWN (1 << 0)
+
+#define SHA1_BUFSIZE 20
+
+
+struct iovec
+{
+ size_t length;
+ void *data;
+};
+
+
+/* Input and Output blocks for the TCG BIOS commands */
+
+struct hleei_short
+{
+ u16 ipblength;
+ u16 reserved;
+ const void *hashdataptr;
+ u32 hashdatalen;
+ u32 pcrindex;
+ const void *logdataptr;
+ u32 logdatalen;
+} PACKED;
+
+
+struct hleei_long
+{
+ u16 ipblength;
+ u16 reserved;
+ void *hashdataptr;
+ u32 hashdatalen;
+ u32 pcrindex;
+ u32 reserved2;
+ void *logdataptr;
+ u32 logdatalen;
+} PACKED;
+
+
+struct hleeo
+{
+ u16 opblength;
+ u16 reserved;
+ u32 eventnumber;
+ u8 digest[SHA1_BUFSIZE];
+} PACKED;
+
+
+struct pttti
+{
+ u16 ipblength;
+ u16 reserved;
+ u16 opblength;
+ u16 reserved2;
+ u8 tpmopin[0];
+} PACKED;
+
+
+struct pttto
+{
+ u16 opblength;
+ u16 reserved;
+ u8 tpmopout[0];
+};
+
+
+struct hlei
+{
+ u16 ipblength;
+ u16 reserved;
+ const void *hashdataptr;
+ u32 hashdatalen;
+ u32 pcrindex;
+ u32 logeventtype;
+ const void *logdataptr;
+ u32 logdatalen;
+} PACKED;
+
+
+struct hleo
+{
+ u16 opblength;
+ u16 reserved;
+ u32 eventnumber;
+} PACKED;
+
+
+struct hai
+{
+ u16 ipblength;
+ u16 reserved;
+ const void *hashdataptr;
+ u32 hashdatalen;
+ u32 algorithmid;
+} PACKED;
+
+
+struct ti
+{
+ u16 ipblength;
+ u16 reserved;
+ u16 opblength;
+ u16 reserved2;
+ u8 tssoperandin[0];
+} PACKED;
+
+
+struct to
+{
+ u16 opblength;
+ u16 reserved;
+ u8 tssoperandout[0];
+} PACKED;
+
+
+struct pcpes
+{
+ u32 pcrindex;
+ u32 eventtype;
+ u8 digest[SHA1_BUFSIZE];
+ u32 eventdatasize;
+ u32 event;
+} PACKED;
+
+
+/* 10.4.2.1 */
+struct pcctes
+{
+ u32 eventid;
+ u32 eventdatasize;
+ u8 digest[SHA1_BUFSIZE];
+} PACKED;
+
+/* 10.4.2.1 w/ 10.4.2.2.1 embedded */
+struct pcctes_romex
+{
+ u32 eventid;
+ u32 eventdatasize;
+ u16 reserved;
+ u16 pfa;
+ u8 digest[SHA1_BUFSIZE];
+} PACKED;
+
+
+#define TPM_REQ_HEADER \
+ u16 tag; \
+ u32 totlen; \
+ u32 ordinal;
+
+#define TPM_REQ_HEADER_SIZE (sizeof(u16) + sizeof(u32) + sizeof(u32))
+
+#define TPM_RSP_HEADER \
+ u16 tag; \
+ u32 totlen; \
+ u32 errcode;
+
+#define TPM_RSP_HEADER_SIZE (sizeof(u16) + sizeof(u32) + sizeof(u32))
+
+struct tpm_req_header {
+ TPM_REQ_HEADER;
+} PACKED;
+
+
+struct tpm_rsp_header {
+ TPM_RSP_HEADER;
+} PACKED;
+
+
+struct tpm_req_extend {
+ TPM_REQ_HEADER
+ u32 pcrindex;
+ u8 digest[SHA1_BUFSIZE];
+} PACKED;
+
+
+struct tpm_rsp_extend {
+ TPM_RSP_HEADER
+ u8 digest[SHA1_BUFSIZE];
+} PACKED;
+
+
+struct tpm_req_getcap_perm_flags {
+ TPM_REQ_HEADER
+ u32 capArea;
+ u32 subCapSize;
+ u32 subCap;
+} PACKED;
+
+
+struct tpm_permanent_flags {
+ u16 tag;
+ u8 flags[20];
+} PACKED;
+
+
+enum permFlagsIndex {
+ PERM_FLAG_IDX_DISABLE = 0,
+ PERM_FLAG_IDX_OWNERSHIP,
+ PERM_FLAG_IDX_DEACTIVATED,
+ PERM_FLAG_IDX_READPUBEK,
+ PERM_FLAG_IDX_DISABLEOWNERCLEAR,
+ PERM_FLAG_IDX_ALLOW_MAINTENANCE,
+ PERM_FLAG_IDX_PHYSICAL_PRESENCE_LIFETIME_LOCK,
+ PERM_FLAG_IDX_PHYSICAL_PRESENCE_HW_ENABLE,
+};
+
+
+struct tpm_res_getcap_perm_flags {
+ TPM_RSP_HEADER
+ u32 size;
+ struct tpm_permanent_flags perm_flags;
+} PACKED;
+
+
+struct tpm_res_getcap_ownerauth {
+ TPM_RSP_HEADER
+ u32 size;
+ u8 flag;
+} PACKED;
+
+
+struct tpm_res_sha1start {
+ TPM_RSP_HEADER
+ u32 max_num_bytes;
+} PACKED;
+
+
+struct tpm_res_sha1complete {
+ TPM_RSP_HEADER
+ u8 hash[20];
+} PACKED;
+
+struct pttti_extend {
+ struct pttti pttti;
+ struct tpm_req_extend req;
+} PACKED;
+
+
+struct pttto_extend {
+ struct pttto pttto;
+ struct tpm_rsp_extend rsp;
+} PACKED;
+
+
+enum ipltype {
+ IPL_BCV = 0,
+ IPL_EL_TORITO_1,
+ IPL_EL_TORITO_2
+};
+
+void tcpa_acpi_init(void);
int has_working_tpm(void);
+u32 tcpa_startup(void);
+u32 tcpa_leave_bios(void);
+u32 tcpa_s3_resume(void);
#endif /* TCGBIOS_H */
Index: seabios/src/tcgbios.c
===================================================================
--- seabios.orig/src/tcgbios.c
+++ seabios/src/tcgbios.c
@@ -12,6 +12,48 @@
#include "types.h"
#include "tpm_drivers.h" // tpm_drivers[]
+#include "util.h" // printf, get_keystroke
+#include "tcgbios.h"// tcpa_*, prototypes
+#include "acpi.h" // RSDP_SIGNATURE, rsdt_descriptor
+
+
+static const u8 Startup_ST_CLEAR[2] = { 0x00, TPM_ST_CLEAR };
+static const u8 Startup_ST_STATE[2] = { 0x00, TPM_ST_STATE };
+
+static const u8 PhysicalPresence_CMD_ENABLE[2] = { 0x00, 0x20 };
+static const u8 PhysicalPresence_CMD_DISABLE[2] = { 0x01, 0x00 };
+static const u8 PhysicalPresence_PRESENT[2] = { 0x00, 0x08 };
+static const u8 PhysicalPresence_NOT_PRESENT[2] = { 0x00, 0x10 };
+static const u8 PhysicalPresence_LOCK[2] = { 0x00, 0x04 };
+
+static const u8 CommandFlag_FALSE[1] = { 0x00 };
+static const u8 CommandFlag_TRUE[1] = { 0x01 };
+
+static const u8 GetCapability_Permanent_Flags[12] = {
+ 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x01, 0x08
+};
+
+static const u8 GetCapability_OwnerAuth[12] = {
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x01, 0x11
+};
+
+
+#define RSDP_CAST(ptr) ((struct rsdp_descriptor *)ptr)
+
+
+/* helper functions */
+
+static inline void *input_buf32(struct bregs *regs)
+{
+ return MAKE_FLATPTR(regs->es, regs->di);
+}
+
+static inline void *output_buf32(struct bregs *regs)
+{
+ return MAKE_FLATPTR(regs->ds, regs->si);
+}
typedef struct {
@@ -58,6 +100,9 @@ is_tpm_present(void)
int
has_working_tpm(void)
{
+ if (!CONFIG_TCGBIOS)
+ return 0;
+
if (!tcpa_state.tpm_probed) {
tcpa_state.tpm_probed = 1;
tcpa_state.tpm_found = (is_tpm_present() != 0);
@@ -70,3 +115,352 @@ has_working_tpm(void)
}
+static struct tcpa_descriptor_rev2 *
+find_tcpa_by_rsdp(struct rsdp_descriptor *rsdp)
+{
+ u32 ctr = 0;
+ struct tcpa_descriptor_rev2 *tcpa = NULL;
+ struct rsdt_descriptor *rsdt;
+ u32 length;
+ u16 off;
+
+ rsdt = (struct rsdt_descriptor *)rsdp->rsdt_physical_address;
+ if (!rsdt)
+ return NULL;
+
+ length = rsdt->length;
+ off = offsetof(struct rsdt_descriptor, entry);
+
+ while ((off + sizeof(rsdt->entry[0])) <= length) {
+ /* try all pointers to structures */
+ tcpa = (struct tcpa_descriptor_rev2 *)(int)rsdt->entry[ctr];
+
+ /* valid TCPA ACPI table ? */
+ if (tcpa->signature == TCPA_SIGNATURE &&
+ checksum((u8 *)tcpa, tcpa->length) == 0)
+ break;
+
+ tcpa = NULL;
+ off += sizeof(rsdt->entry[0]);
+ ctr++;
+ }
+
+ return tcpa;
+}
+
+
+static struct tcpa_descriptor_rev2 *
+find_tcpa_table(void)
+{
+ struct tcpa_descriptor_rev2 *tcpa = NULL;
+ struct rsdp_descriptor *rsdp;
+
+ rsdp = get_rsdp();
+
+ if (rsdp)
+ tcpa = find_tcpa_by_rsdp(rsdp);
+ else
+ tcpa_state.if_shutdown = 1;
+
+ if (!rsdp)
+ dprintf(DEBUG_tcg,
+ "TCGBIOS: RSDP was NOT found! -- Disabling interface.\n");
+ else if (!tcpa)
+ dprintf(DEBUG_tcg, "TCGBIOS: TCPA ACPI was NOT found!\n");
+
+ return tcpa;
+}
+
+
+static u8 *
+get_lasa_base_ptr(u32 *laml)
+{
+ u8 *lasa = 0;
+ struct tcpa_descriptor_rev2 *tcpa = find_tcpa_table();
+
+ if (tcpa) {
+ lasa = (u8 *)(long)tcpa->lasa;
+ if (laml)
+ *laml = tcpa->laml;
+ }
+
+ return lasa;
+}
+
+
+/* clear the ACPI log */
+static void
+reset_acpi_log(void)
+{
+ u32 laml;
+ u8 *lasa = get_lasa_base_ptr(&laml);
+
+ if (lasa)
+ memset(lasa, 0x0, laml);
+}
+
+
+/*
+ initialize the TCPA ACPI subsystem; find the ACPI tables and determine
+ where the TCPA table is.
+ */
+void
+tcpa_acpi_init(void)
+{
+ if (!CONFIG_TCGBIOS)
+ return;
+
+ tcpa_state.if_shutdown = 0;
+ tcpa_state.tpm_probed = 0;
+ tcpa_state.tpm_found = 0;
+ tcpa_state.tpm_working = 0;
+
+ if (!has_working_tpm()) {
+ tcpa_state.if_shutdown = 1;
+ return;
+ }
+
+ reset_acpi_log();
+}
+
+
+static u32
+transmit(u8 locty, const struct iovec iovec[],
+ u8 *respbuffer, u32 *respbufferlen)
+{
+ u32 rc = 0;
+ u32 irc;
+ struct tpm_driver *td;
+ unsigned int i;
+
+ if (tcpa_state.tpm_driver_to_use == TPM_INVALID_DRIVER)
+ return TCG_FATAL_COM_ERROR;
+
+ td = &tpm_drivers[tcpa_state.tpm_driver_to_use];
+
+ irc = td->activate(locty);
+ if (irc != 0) {
+ /* tpm could not be activated */
+ return TCG_FATAL_COM_ERROR;
+ }
+
+ for (i = 0; iovec[i].length; i++) {
+ irc = td->senddata(iovec[i].data,
+ iovec[i].length);
+ if (irc != 0)
+ return TCG_FATAL_COM_ERROR;
+ }
+
+ irc = td->waitdatavalid();
+ if (irc != 0)
+ return TCG_FATAL_COM_ERROR;
+
+ irc = td->waitrespready(10000);
+ if (irc != 0)
+ return TCG_FATAL_COM_ERROR;
+
+ irc = td->readresp(respbuffer,
+ respbufferlen);
+ if (irc != 0)
+ return TCG_FATAL_COM_ERROR;
+
+ td->ready();
+
+ return rc;
+}
+
+
+/*
+ * Send a TPM command with the given ordinal. Append the given buffer
+ * containing all data in network byte order to the command (this is
+ * the custom part per command) and expect a response of the given size.
+ * If a buffer is provided, the response will be copied into it.
+ */
+static u32
+build_and_send_cmd_od(u32 ordinal, const u8 *append, u32 append_size,
+ u8 *resbuffer, u32 return_size, u32 *returnCode,
+ const u8 *otherdata, u32 otherdata_size)
+{
+#define MAX_APPEND_SIZE 12
+#define MAX_RESPONSE_SIZE sizeof(struct tpm_res_getcap_perm_flags)
+ u32 rc;
+ u8 ibuffer[TPM_REQ_HEADER_SIZE + MAX_APPEND_SIZE];
+ u8 obuffer[MAX_RESPONSE_SIZE];
+ struct tpm_req_header *trqh = (struct tpm_req_header *)ibuffer;
+ struct tpm_rsp_header *trsh = (struct tpm_rsp_header *)obuffer;
+ u8 locty = 0;
+ struct iovec iovec[3];
+ u32 obuffer_len = sizeof(obuffer);
+ u32 idx = 1;
+
+ if (append_size > MAX_APPEND_SIZE ||
+ return_size > MAX_RESPONSE_SIZE) {
+ dprintf(DEBUG_tcg, "TCGBIOS: size of requested buffers too big.");
+ return TCG_FIRMWARE_ERROR;
+ }
+
+ iovec[0].data = trqh;
+ iovec[0].length = TPM_REQ_HEADER_SIZE + append_size;
+
+ if (otherdata) {
+ iovec[1].data = (void *)otherdata;
+ iovec[1].length = otherdata_size;
+ idx = 2;
+ }
+
+ iovec[idx].data = NULL;
+ iovec[idx].length = 0;
+
+ memset(ibuffer, 0x0, sizeof(ibuffer));
+ memset(obuffer, 0x0, sizeof(obuffer));
+
+ trqh->tag = htons(0xc1);
+ trqh->totlen = htonl(TPM_REQ_HEADER_SIZE + append_size + otherdata_size);
+ trqh->ordinal = htonl(ordinal);
+
+ if (append_size)
+ memcpy((char *)trqh + sizeof(*trqh),
+ append, append_size);
+
+ rc = transmit(locty, iovec, obuffer, &obuffer_len);
+ if (rc)
+ return rc;
+
+ *returnCode = ntohl(trsh->errcode);
+
+ if (resbuffer)
+ memcpy(resbuffer, trsh, return_size);
+
+ return 0;
+}
+
+
+static u32
+build_and_send_cmd(u32 ordinal, const u8 *append, u32 append_size,
+ u8 *resbuffer, u32 return_size, u32 *returnCode)
+{
+ return build_and_send_cmd_od(ordinal, append, append_size,
+ resbuffer, return_size, returnCode,
+ NULL, 0);
+}
+
+
+u32
+tcpa_startup(void)
+{
+ u32 rc;
+ u32 returnCode;
+
+ if (!CONFIG_TCGBIOS)
+ return 0;
+
+ if (!has_working_tpm())
+ return 0;
+
+ dprintf(DEBUG_tcg, "TCGBIOS: Starting with TPM_Startup(ST_CLEAR)\n");
+ rc = build_and_send_cmd(TPM_ORD_Startup,
+ Startup_ST_CLEAR, sizeof(Startup_ST_CLEAR),
+ NULL, 10, &returnCode);
+
+ dprintf(DEBUG_tcg, "Return code from TPM_Startup = 0x%08x\n",
+ returnCode);
+
+ if (rc && returnCode)
+ goto err_exit;
+
+ rc = build_and_send_cmd(TPM_ORD_SelfTestFull, NULL, 0,
+ NULL, 10, &returnCode);
+
+ dprintf(DEBUG_tcg, "Return code from TPM_SelfTestFull = 0x%08x\n",
+ returnCode);
+
+ if (rc || returnCode)
+ goto err_exit;
+
+ return 0;
+
+err_exit:
+ dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
+
+ tcpa_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCG_TCG_COMMAND_ERROR;
+}
+
+
+u32
+tcpa_leave_bios(void)
+{
+ u32 rc;
+ u32 returnCode;
+
+ if (!CONFIG_TCGBIOS)
+ return 0;
+
+ if (!has_working_tpm())
+ return 0;
+
+ rc = build_and_send_cmd(TPM_ORD_PhysicalPresence,
+ PhysicalPresence_CMD_ENABLE,
+ sizeof(PhysicalPresence_CMD_ENABLE),
+ NULL, 10, &returnCode);
+ if (rc || returnCode)
+ goto err_exit;
+
+ rc = build_and_send_cmd(TPM_ORD_PhysicalPresence,
+ PhysicalPresence_NOT_PRESENT,
+ sizeof(PhysicalPresence_NOT_PRESENT),
+ NULL, 10, &returnCode);
+ if (rc || returnCode)
+ goto err_exit;
+
+ return 0;
+
+err_exit:
+ dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
+
+ tcpa_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCG_TCG_COMMAND_ERROR;
+}
+
+
+u32
+tcpa_s3_resume(void)
+{
+ u32 rc;
+ u32 returnCode;
+
+ if (!CONFIG_TCGBIOS)
+ return 0;
+
+ if (!has_working_tpm())
+ return 0;
+
+ rc = build_and_send_cmd(TPM_ORD_Startup,
+ Startup_ST_STATE,
+ sizeof(Startup_ST_STATE),
+ NULL, 10, &returnCode);
+
+ dprintf(DEBUG_tcg, "TCGBIOS: Resuming with TPM_Startup(ST_STATE)\n");
+ dprintf(DEBUG_tcg, "TCGBIOS: ReturnCode from TPM_Startup = 0x%08x\n",
+ returnCode);
+
+ if (rc || returnCode)
+ goto err_exit;
+
+ return 0;
+
+err_exit:
+ dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
+
+ tcpa_state.tpm_working = 0;
+ if (rc)
+ return rc;
+ return TCG_TCG_COMMAND_ERROR;
+}
+
+
+
- [Qemu-devel] [PATCH V2 0/8] Add TPM support to SeaBIOS, Stefan Berger, 2011/04/04
- [Qemu-devel] [PATCH V2 3/8] Add public get_rsdp function, Stefan Berger, 2011/04/04
- [Qemu-devel] [PATCH V2 1/8] Add an implementation for a TPM TIS driver, Stefan Berger, 2011/04/04
- [Qemu-devel] [PATCH V2 4/8] Implementation of the TCG BIOS extensions,
Stefan Berger <=
- [Qemu-devel] [PATCH V2 5/8] Support for BIOS interrupt handler, Stefan Berger, 2011/04/04
- [Qemu-devel] [PATCH V2 7/8] Add a menu for TPM control, Stefan Berger, 2011/04/04
- [Qemu-devel] [PATCH V2 6/8] Add measurement code to the BIOS, Stefan Berger, 2011/04/04
- [Qemu-devel] [PATCH V2 8/8] Optional tests for the TIS interface, Stefan Berger, 2011/04/04
- [Qemu-devel] [PATCH V2 2/8] Provide ACPI SSDT table for TPM device + S3 resume support, Stefan Berger, 2011/04/04
- [Qemu-devel] Re: [SeaBIOS] [PATCH V2 0/8] Add TPM support to SeaBIOS, Kevin O'Connor, 2011/04/05