Mailing List Archive

[xen-unstable] [HVM] Add TCG BIOS extensions to the high memory area along with
# HG changeset patch
# User kaf24@localhost.localdomain
# Date 1169829512 0
# Node ID c07326324f8dea5b60e6a85383a562b4b12d1d9d
# Parent 480436ef6255aa1a38e2cafc9a63f565f633f6fc
[HVM] Add TCG BIOS extensions to the high memory area along with
some often-used libc utility functions. The TCG extensions are
described here:

https://www.trustedcomputinggroup.org/specs/PCClient/TCG_PCClientImplementationforBIOS_1-20_1-00.pdf

I have tried to keep the patching with rombios.c to a minimum, but
some amount of code needs to be inserted at various locations.

The code is currently deactivated, but can be activated by setting
BX_TCGBIOS to '1'.

Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
---
tools/firmware/rombios/32bit/32bitbios.c | 16
tools/firmware/rombios/32bit/Makefile | 27
tools/firmware/rombios/32bit/tcgbios/Makefile | 20
tools/firmware/rombios/32bit/tcgbios/tcgbios.c | 1526 +++++++++++++++++++++
tools/firmware/rombios/32bit/tcgbios/tcgbios.h | 288 +++
tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c | 180 ++
tools/firmware/rombios/32bit/tcgbios/tpm_drivers.h | 18
tools/firmware/rombios/32bit/util.c | 450 ++++++
tools/firmware/rombios/32bit/util.h | 28
tools/firmware/rombios/32bitgateway.c | 2
tools/firmware/rombios/32bitprotos.h | 41
tools/firmware/rombios/Makefile | 2
tools/firmware/rombios/rombios.c | 58
tools/firmware/rombios/tcgbios.c | 263 +++
14 files changed, 2907 insertions(+), 12 deletions(-)

diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bit/32bitbios.c
--- a/tools/firmware/rombios/32bit/32bitbios.c Fri Jan 26 16:30:48 2007 +0000
+++ b/tools/firmware/rombios/32bit/32bitbios.c Fri Jan 26 16:38:32 2007 +0000
@@ -55,6 +55,22 @@ uint32_t jumptable[IDX_LAST+1] __attribu
TABLE_ENTRY(IDX_ADD , add),
TABLE_ENTRY(IDX_SET_STATIC , set_static),

+ TABLE_ENTRY(IDX_TCPA_ACPI_INIT, tcpa_acpi_init),
+ TABLE_ENTRY(IDX_TCPA_EXTEND_ACPI_LOG, tcpa_extend_acpi_log),
+
+ TABLE_ENTRY(IDX_TCGINTERRUPTHANDLER, TCGInterruptHandler),
+
+ TABLE_ENTRY(IDX_TCPA_CALLING_INT19H, tcpa_calling_int19h),
+ TABLE_ENTRY(IDX_TCPA_RETURNED_INT19H, tcpa_returned_int19h),
+ TABLE_ENTRY(IDX_TCPA_ADD_EVENT_SEPARATORS, tcpa_add_event_separators),
+ TABLE_ENTRY(IDX_TCPA_WAKE_EVENT, tcpa_wake_event),
+ TABLE_ENTRY(IDX_TCPA_ADD_BOOTDEVICE, tcpa_add_bootdevice),
+ TABLE_ENTRY(IDX_TCPA_START_OPTION_ROM_SCAN, tcpa_start_option_rom_scan),
+ TABLE_ENTRY(IDX_TCPA_OPTION_ROM, tcpa_option_rom),
+ TABLE_ENTRY(IDX_TCPA_IPL, tcpa_ipl),
+ TABLE_ENTRY(IDX_TCPA_MEASURE_POST, tcpa_measure_post),
+
+ TABLE_ENTRY(IDX_TCPA_INITIALIZE_TPM, tcpa_initialize_tpm),

TABLE_ENTRY(IDX_LAST , 0) /* keep last */
};
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bit/Makefile
--- a/tools/firmware/rombios/32bit/Makefile Fri Jan 26 16:30:48 2007 +0000
+++ b/tools/firmware/rombios/32bit/Makefile Fri Jan 26 16:38:32 2007 +0000
@@ -4,21 +4,34 @@ CFLAGS :=
CFLAGS :=
include $(XEN_ROOT)/tools/Rules.mk

+SOURCES = util.c
TARGET = 32bitbios_flat.h

-CFLAGS += -fno-builtin -O2 -msoft-float
+CFLAGS += -fno-builtin -O2 -msoft-float -nostdlib
CFLAGS += -I../

-MODULES = 32bitbios.o
+SUBDIRS = tcgbios

-.PHONY: all
+MODULES := 32bitbios.o
+MODULES += tcgbios/tcgbiosext.o
+MODULES += util.o

-all : $(TARGET)
+.PHONY: all subdirs

-clean ::
+subdirs:
+ @for subdir in $(SUBDIRS); do \
+ $(MAKE) -C $$subdir all; \
+ done;
+
+all: subdirs $(TARGET)
+
+clean::
rm -rf *.o $(TARGET)
+ @for subdir in $(SUBDIRS); do \
+ $(MAKE) -C $$subdir $@; \
+ done;

-$(TARGET) : 32bitbios_all.o $(SOURCES)
+$(TARGET): 32bitbios_all.o $(SOURCES)
unref=`nm -u 32bitbios_all.o`
@if [ "$$unref" != "" ]; then \
echo "There are unresolved symbols in the BIOS."; \
@@ -27,5 +40,5 @@ clean ::
bash mkhex highbios_array 32bitbios_all.o > $(TARGET); \
fi

-32bitbios_all.o : 32bitbios.o $(MODULES)
+32bitbios_all.o: $(MODULES)
ld $(LDFLAGS_DIRECT) -r $(MODULES) -o 32bitbios_all.o
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bit/tcgbios/Makefile
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/tcgbios/Makefile Fri Jan 26 16:38:32 2007 +0000
@@ -0,0 +1,20 @@
+
+override XEN_TARGET_ARCH = x86_32
+XEN_ROOT = ../../../../..
+CFLAGS :=
+include $(XEN_ROOT)/tools/Rules.mk
+
+TARGET = tcgbiosext.o
+FILES = tcgbios tpm_drivers
+OBJECTS = $(foreach f,$(FILES),$(f).o)
+
+CFLAGS += -fno-builtin -O2 -msoft-float -nostdlib
+CFLAGS += -I../ -I../../
+
+all: $(TARGET)
+
+clean::
+ rm -rf *.o $(TARGET)
+
+$(TARGET): $(OBJECTS)
+ ld $(LDFLAGS_DIRECT) -r $^ -o $@
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bit/tcgbios/tcgbios.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c Fri Jan 26 16:38:32 2007 +0000
@@ -0,0 +1,1526 @@
+/*
+ * Implementation of the TCG BIOS extension according to the specification
+ * described in
+ * https://www.trustedcomputinggroup.org/specs/PCClient/TCG_PCClientImplementationforBIOS_1-20_1-00.pdf
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright (C) IBM Corporation, 2006
+ *
+ * Author: Stefan Berger <stefanb@us.ibm.com>
+ */
+#include "rombios_compat.h"
+#include "tpm_drivers.h"
+
+#include "tcgbios.h"
+#include "32bitprotos.h"
+#include "util.h"
+
+
+/* local structure and variables */
+struct ptti_cust {
+ uint16_t ipblength;
+ uint16_t reserved;
+ uint16_t opblength;
+ uint16_t reserved2;
+ uint8_t tpmoperandin[18];
+} __attribute__((packed));
+
+struct ptti_cust CMD_TPM_Startup_0x01_IPB = {
+ 0x8+0xc, 0x00, 4+10, 0x00,
+ { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x99, 0x00, 0x01 },
+};
+
+struct ptti_cust CMD_TSC_PhysicalPresence_0x20_IPB = {
+ 0x8+0xc, 0x00, 4+10, 0x00,
+ { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x20 },
+};
+
+struct ptti_cust CMD_TSC_PhysicalPresence_0x08_IPB = {
+ 0x8+0xc, 0x00, 4+10, 0x00,
+ { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x08 },
+};
+
+struct ptti_cust CMD_TSC_PhysicalPresence_0x100_IPB = {
+ 0x8+0xc, 0x00, 4+10, 0x00,
+ { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x01, 0x00 },
+};
+
+struct ptti_cust CMD_TSC_PhysicalPresence_0x10_IPB = {
+ 0x8+0xc, 0x00, 4+10, 0x00,
+ { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x10 },
+};
+
+struct ptti_cust CMD_TPM_PhysicalEnable_IPB = {
+ 0x8+0xa, 0x00, 4+10, 0x00,
+ { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x6f },
+};
+
+struct ptti_cust CMD_TPM_PhysicalSetDeactivated_0x00_IPB = {
+ 0x8+0xb, 0x00, 4+10, 0x00,
+ { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x72, 0x00 }
+};
+struct ptti_cust CMD_TPM_SHA1Start_IPB = {
+ 0x8+0xa, 0x00, 4+10, 0x00,
+ { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa0 },
+};
+
+struct ptti_cust CMD_TPM_GetCap_Version_IPB = {
+ 0x8+0x12, 0x00, 4+18, 0x00,
+ {0x00, 0xc1, 0x00, 0x00, 0x00, 0x12,
+ 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00 },
+};
+
+struct ptti_cust *TCG_CommandList[] = {
+ &CMD_TPM_Startup_0x01_IPB,
+ &CMD_TSC_PhysicalPresence_0x20_IPB,
+ &CMD_TSC_PhysicalPresence_0x08_IPB,
+ &CMD_TSC_PhysicalPresence_0x100_IPB,
+ &CMD_TSC_PhysicalPresence_0x10_IPB,
+ &CMD_TPM_PhysicalEnable_IPB,
+ &CMD_TPM_PhysicalSetDeactivated_0x00_IPB,
+ &CMD_TPM_SHA1Start_IPB,
+};
+
+/* local function prototypes */
+static void sha1(const unsigned char *data, uint32_t length, unsigned char *hash);
+static uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx);
+static uint32_t HashAll32(struct hai *hai, unsigned char *hash,
+ uint32_t magic, uint32_t ecx, uint32_t edx);
+static uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s,
+ struct hleeo *hleeo,
+ uint32_t magic, uint32_t ecx, uint32_t edx);
+static uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo,
+ uint32_t ebx, uint32_t ecx, uint32_t edx);
+static uint32_t PassThroughToTPM32(struct pttti *pttti, struct pttto *pttto,
+ uint32_t magic, uint32_t ecx, uint32_t edx);
+static uint32_t MA_Transmit(unsigned char *cmdbuffer,
+ unsigned char *respbuffer,
+ uint32_t respbufferlen);
+
+static unsigned char *tcpa_get_lasa_last_ptr(void);
+static unsigned char *tcpa_get_lasa_base_ptr(void);
+static void tcpa_reset_acpi_log(void);
+static uint32_t tcpa_get_laml(void);
+
+
+extern struct tpm_driver tpm_drivers[];
+
+/* utility functions */
+
+static inline uint32_t bswap(uint32_t a)
+{
+ return ( ( a >> 24 ) & 0x000000ff) |
+ ( ( a >> 8 ) & 0x0000ff00) |
+ ( ( a << 8 ) & 0x00ff0000) |
+ ( ( a << 24 ) & 0xff000000);
+}
+
+/********************************************************
+ Extensions for TCG-enabled BIOS
+ *******************************************************/
+
+typedef struct {
+ struct acpi_20_tcpa *tcpa_ptr;
+ unsigned char *lasa_last_ptr;
+ uint16_t entry_count;
+ uint16_t flags;
+} tcpa_acpi_t;
+
+static tcpa_acpi_t tcpa_acpi;
+
+
+/* low level driver implementation */
+static int tpm_driver_to_use = TPM_INVALID_DRIVER;
+
+static
+uint32_t MA_IsTPMPresent()
+{
+ uint32_t rc = 0;
+ unsigned int i;
+ for (i = 0; i < TPM_NUM_DRIVERS; i++) {
+ struct tpm_driver *td = &tpm_drivers[i];
+ if (td->probe(td->baseaddr) != 0) {
+ tpm_driver_to_use = i;
+ rc = 1;
+ break;
+ }
+ }
+ return rc;
+}
+
+static
+uint32_t MA_InitTPM(uint16_t startupcode)
+{
+ uint32_t rc = 0;
+ /* low-level initialize the TPM */
+ unsigned char command[sizeof(CMD_TPM_Startup_0x01_IPB.tpmoperandin)];
+ unsigned char response[10];
+ uint32_t response_size = sizeof(response);
+
+ memcpy(command,
+ CMD_TPM_Startup_0x01_IPB.tpmoperandin,
+ sizeof(CMD_TPM_Startup_0x01_IPB.tpmoperandin));
+ command[10] = (startupcode >> 8) & 0xff;
+ command[11] = (startupcode >> 0) & 0xff;
+ rc = MA_Transmit(command, response, response_size);
+
+ return rc;
+}
+
+static
+uint32_t MA_Transmit(unsigned char *cmdbuffer,
+ unsigned char *respbuffer,
+ uint32_t respbufferlen)
+{
+ uint32_t rc = 0;
+ uint32_t irc;
+ struct tpm_driver *td;
+
+ if (tpm_driver_to_use == TPM_INVALID_DRIVER)
+ return TCG_FATAL_COM_ERROR;
+
+ td = &tpm_drivers[tpm_driver_to_use];
+
+ if (rc == 0) {
+ irc = td->activate(td->baseaddr);
+ if (irc == 0) {
+ /* tpm could not be activated */
+ rc = TCG_FATAL_COM_ERROR;
+ }
+ }
+
+ if (rc == 0) {
+ uint32_t *tmp = (uint32_t *)&cmdbuffer[2];
+ uint32_t len = bswap(*tmp);
+ irc = td->senddata(td->baseaddr,
+ cmdbuffer,
+ len);
+ if (irc != 0) {
+ rc = TCG_FATAL_COM_ERROR;
+ }
+ }
+
+ if (rc == 0) {
+ irc = td->waitdatavalid(td->baseaddr);
+ if (irc != 0) {
+ rc = TCG_FATAL_COM_ERROR;
+ }
+ }
+
+ if (rc == 0) {
+ irc = td->waitrespready(td->baseaddr, 2000);
+ if (irc != 0) {
+ rc = TCG_FATAL_COM_ERROR;
+ }
+ }
+
+ if (rc == 0) {
+ irc = td->readresp(td->baseaddr,
+ respbuffer,
+ respbufferlen);
+ if (irc != 0) {
+ rc = TCG_FATAL_COM_ERROR;
+ }
+ }
+
+ if (rc == 0) {
+ irc = td->ready(td->baseaddr);
+ }
+
+ return rc;
+}
+
+
+static
+uint8_t acpi_validate_entry(struct acpi_header *hdr)
+{
+ uint8_t sum = 0;
+ unsigned int length = hdr->length;
+ unsigned int ctr;
+ unsigned char *addr = (unsigned char *)hdr;
+
+ for (ctr = 0; ctr < length; ctr++)
+ sum += addr[ctr];
+
+ return sum;
+}
+
+
+void tcpa_acpi_init(void)
+{
+ struct acpi_20_rsdt *rsdt;
+ uint32_t length;
+ struct acpi_20_tcpa *tcpa;
+ uint16_t found = 0;
+ uint16_t rsdp_off;
+ uint16_t off;
+ struct acpi_20_rsdp *rsdp;
+
+ if (MA_IsTPMPresent() == 0) {
+ return;
+ }
+
+ /* scan memory in steps of 16 bytes in the ACPI_SEGMENT segment */
+ found = 0;
+ for (rsdp_off = 0; rsdp_off < 0xfff0; rsdp_off += 0x10) {
+ char *_rsdp = (char *)(ACPI_SEGMENT << 4);
+ /* check for expected string */
+ if (!strncmp( &_rsdp[rsdp_off], "RSD PTR ", 8)) {
+ found = 1;
+ rsdp = (struct acpi_20_rsdp *)&_rsdp[rsdp_off];
+ break;
+ }
+ }
+
+ if (rsdp) {
+ uint32_t ctr = 0;
+ /* get RSDT from RSDP */
+ rsdt = (struct acpi_20_rsdt *)rsdp->rsdt_address;
+ /* rsdt may be anywhere in 32bit space */
+ length = rsdt->header.length;
+ off = 36;
+ while ((off + 3) < length) {
+ /* try all pointers to structures */
+ tcpa = (struct acpi_20_tcpa *)rsdt->entry[ctr];
+ /* valid TCPA ACPI table ? */
+ if (ACPI_2_0_TCPA_SIGNATURE == tcpa->header.signature &&
+ acpi_validate_entry(&tcpa->header) == 0) {
+ found = 1;
+ break;
+ }
+ off += 4;
+ ctr++;
+ }
+ }
+
+ if (found == 0) {
+ printf("TCPA ACPI was NOT found!\n");
+ tcpa = 0;
+ }
+
+ /* initialize the TCPA part of the EBDA with our data */
+ tcpa_acpi.tcpa_ptr = tcpa;
+ tcpa_acpi.lasa_last_ptr = 0;
+ tcpa_acpi.entry_count = 0;
+ tcpa_acpi.flags = 0;
+ tcpa_reset_acpi_log();
+}
+
+/* clear the ACPI log */
+static void tcpa_reset_acpi_log(void)
+{
+ unsigned char *lasa = tcpa_get_lasa_base_ptr();
+ if (lasa)
+ memset(lasa, 0x0, tcpa_get_laml());
+}
+
+
+uint32_t tcpa_extend_acpi_log(uint32_t entry_ptr)
+{
+ uint32_t res = 0;
+ unsigned char *lasa_last = tcpa_get_lasa_last_ptr();
+ unsigned char *lasa_base = tcpa_get_lasa_base_ptr();
+ uint32_t size;
+ uint16_t entry_count = tcpa_acpi.entry_count;
+ struct pcpes *pcpes = (struct pcpes *)entry_ptr;
+
+ if (lasa_last == 0) {
+ lasa_last = lasa_base;
+ } else {
+ struct pcpes *pcpes = (struct pcpes *)lasa_last;
+ /* skip the last entry in the log */
+ size = pcpes->eventdatasize;
+ size += 32;
+ lasa_last += size;
+ }
+
+ if (lasa_last == 0) {
+ res = ((uint32_t)TCG_PC_LOGOVERFLOW << 16);
+ }
+
+ if (res == 0) {
+ uint32_t laml = tcpa_get_laml();
+ size = pcpes->eventdatasize;
+ size += 32;
+ if ((lasa_last + size - lasa_base) > laml) {
+ res = (TCG_PC_LOGOVERFLOW << 16);
+ }
+ }
+
+ if (res == 0) {
+ /* copy the log entry into the ACPI log */
+ memcpy((char *)lasa_last, (char *)entry_ptr, size);
+ /*
+ * update the pointers and entry counter that were modified
+ * due to the new entry in the log
+ */
+ tcpa_acpi.lasa_last_ptr = lasa_last;
+ entry_count++;
+ tcpa_acpi.entry_count = entry_count;
+
+ res = entry_count;
+ }
+ return res;
+}
+
+static
+unsigned char *tcpa_get_lasa_last_ptr(void)
+{
+ return tcpa_acpi.lasa_last_ptr;
+}
+
+static
+unsigned char *tcpa_get_lasa_base_ptr(void)
+{
+ unsigned char *lasa = 0;
+ struct acpi_20_tcpa *tcpa = tcpa_acpi.tcpa_ptr;
+ if (tcpa != 0) {
+ uint32_t class = tcpa->platform_class;
+ if (class == TCPA_ACPI_CLASS_CLIENT) {
+ /* client type */
+ lasa = (unsigned char *)(long)tcpa->u.client.lasa;
+ } else if (class == TCPA_ACPI_CLASS_SERVER) {
+ /* server type */
+ lasa = (unsigned char *)(long)tcpa->u.server.lasa;
+ }
+ }
+ return lasa;
+}
+
+static
+uint32_t tcpa_get_laml(void)
+{
+ uint32_t laml = 0;
+ struct acpi_20_tcpa *tcpa = tcpa_acpi.tcpa_ptr;
+ if (tcpa != 0) {
+ uint32_t class = tcpa->platform_class;
+ if (class == TCPA_ACPI_CLASS_CLIENT) {
+ /* client type */
+ laml = tcpa->u.client.laml;
+ } else if (class == TCPA_ACPI_CLASS_SERVER) {
+ laml = tcpa->u.server.laml;
+ }
+ }
+ return laml;
+}
+
+
+
+/*
+ * Add a measurement to the log; the data at data_seg:data/length are
+ * appended to the TCG_PCClientPCREventStruct
+ *
+ * Input parameters:
+ * pcrIndex : which PCR to extend
+ * event_type : type of event; specs 10.4.1
+ * event_id : (unused)
+ * data : pointer to the data (i.e., string) to be added to the log
+ * length : length of the data
+ */
+static uint16_t
+tcpa_add_measurement_to_log(uint32_t pcrIndex,
+ uint32_t event_type,
+ uint32_t event_id,
+ const char *data_ptr,
+ uint32_t length)
+{
+ uint32_t rc = 0;
+ struct hleei_short hleei;
+ struct hleeo hleeo;
+ uint8_t _pcpes[32+400];
+ struct pcpes *pcpes = (struct pcpes *)_pcpes;
+ uint8_t *data = (uint8_t *)data_ptr;
+
+ if (length < sizeof(_pcpes)-32) {
+ memset(pcpes, 0x0, 32);
+ pcpes->pcrindex = pcrIndex;
+ pcpes->eventtype = event_type;
+ pcpes->eventdatasize = length;
+ memcpy(&_pcpes[32], data, length);
+
+ hleei.ipblength = 0x18;
+ hleei.reserved = 0x0;
+ hleei.hashdataptr = (uint32_t)&_pcpes[32];
+ hleei.hashdatalen = length;
+ hleei.pcrindex = pcrIndex;
+ hleei.logdataptr = (uint32_t)_pcpes;
+ hleei.logdatalen = length + 32;
+ rc = HashLogExtendEvent32(&hleei,
+ &hleeo,
+ TCG_MAGIC,
+ 0x0,
+ 0x0);
+ } else {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_GENERAL_ERROR << 16));
+ }
+
+ return rc;
+}
+
+static
+uint16_t tcpa_add_pcpes_to_log(struct pcpes *pcpes)
+{
+ uint32_t rc = 0;
+ struct hleei_short hleei;
+ struct hleeo hleeo;
+
+ hleei.ipblength = 0x18;
+ hleei.reserved = 0x0;
+ hleei.hashdataptr = 0;
+ hleei.hashdatalen = 0;
+ hleei.pcrindex = pcpes->pcrindex;
+ hleei.logdataptr = (uint32_t)pcpes;
+ hleei.logdatalen = sizeof(pcpes);
+
+ rc = HashLogExtendEvent32(&hleei,
+ &hleeo,
+ TCG_MAGIC,
+ 0x0,
+ 0x0);
+
+ return rc;
+}
+
+
+/*
+ * Add a measurement to the log; further description of the data
+ * that are to be hashed are NOT appended to the TCG_PCClientPCREventStruc.
+ * Input parameters:
+ * pcrIndex : PCR to extend
+ * event_type : type of event; specs 10.4.1
+ * ptr : 32 bit pointer to the data to be hashed
+ * length : length of the data to be hashed
+ *
+ * Returns lower 16 bit of return code of TCG_HashLogExtendEvent. '0' means
+ * success, otherwise an error is indicated.
+ */
+static
+uint16_t tcpa_add_measurement_to_log_simple(uint32_t pcrIndex,
+ uint16_t event_type,
+ uint8_t *ptr, uint32_t length)
+{
+ uint32_t rc = 0;
+ struct hleei_short hleei;
+ struct hleeo hleeo;
+ struct pcpes pcpes;
+
+ memset(&pcpes, 0x0, sizeof(pcpes));
+ pcpes.pcrindex = pcrIndex;
+ pcpes.eventtype = event_type;
+ pcpes.eventdatasize = length;
+
+ hleei.ipblength = 0x18;
+ hleei.reserved = 0x0;
+ hleei.hashdataptr = (uint32_t)ptr;
+ hleei.hashdatalen = length;
+ hleei.pcrindex = pcrIndex;
+ hleei.logdataptr = (uint32_t)&pcpes;
+ hleei.logdatalen = 32;
+
+ rc = HashLogExtendEvent32(&hleei,
+ &hleeo,
+ TCG_MAGIC,
+ 0x0,
+ 0x0);
+ return rc;
+}
+
+/* table of event types according to 10.4.1 / table 11 */
+static const char ev_action[][23] = {
+ /* 0 */ "Calling INT 19h",
+ "Returned INT 19h",
+ "Returned via INT 18h",
+ "",
+ "",
+ /* 5 */ "",
+ "",
+ "",
+ "",
+ "",
+ /* 10 */ "",
+ "",
+ "",
+ "",
+ "Start Option ROM Scan"
+};
+
+
+static char evt_separator[] = "---------------";
+static char wake_event_1[] = "Wake Event 1";
+
+
+/*
+ * Add a measurement to the list of measurements
+ * pcrIndex : PCR to be extended
+ * event_type : type of event; specs 10.4.1
+ * data : additional parameter; used as parameter for 10.4.3
+ * 'action index'
+ */
+void tcpa_add_measurement(uint32_t pcrIndex,
+ uint16_t event_type,
+ uint32_t data)
+{
+ const char *string;
+
+ switch (event_type) {
+ case EV_SEPARATOR:
+ tcpa_add_measurement_to_log(pcrIndex,
+ event_type,
+ 0,
+ evt_separator,
+ strlen(evt_separator));
+ break;
+ case EV_ACTION:
+ string = ev_action[data /* event_id */];
+ tcpa_add_measurement_to_log(pcrIndex,
+ event_type,
+ data,
+ string,
+ strlen(string));
+
+ break;
+ }
+}
+
+
+/*
+ * Add measurement to log about call of int 19h
+ */
+void tcpa_calling_int19h()
+{
+ tcpa_add_measurement(4, EV_ACTION, 0);
+}
+
+/*
+ * Add measurement to log about retuning from int 19h
+ */
+void tcpa_returned_int19h()
+{
+ tcpa_add_measurement(4, EV_ACTION, 1);
+}
+
+/*
+ * Add event separators for PCRs 0 to 7; specs 8.2.3
+ */
+void tcpa_add_event_separators()
+{
+ uint32_t pcrIndex = 0;
+ while (pcrIndex <= 7) {
+ tcpa_add_measurement(pcrIndex, EV_SEPARATOR, 0);
+ pcrIndex ++;
+ }
+}
+
+
+/*
+ * Add a wake event to the log
+ */
+void tcpa_wake_event()
+{
+ tcpa_add_measurement_to_log(6,
+ EV_ACTION,
+ 10,
+ wake_event_1,
+ strlen(wake_event_1));
+}
+
+/*
+ * add the boot device to the measurement log
+ */
+void tcpa_add_bootdevice(uint32_t bootcd, uint32_t bootdrv)
+{
+ char *string;
+ if (bootcd == 0) {
+ if (bootdrv == 0) {
+ string = "Booting BCV device 00h (Floppy)";
+ } else if (bootdrv == 0x80) {
+ string = "Booting BCV device 80h (HDD)";
+ } else {
+ string = "Booting unknown device";
+ }
+ } else {
+ string = "Booting from CD ROM device";
+ }
+ tcpa_add_measurement_to_log(4, 5, 0,
+ string, strlen(string));
+}
+
+/*
+ * Add measurement to the log about option rom scan
+ * 10.4.3 : action 14
+ */
+void tcpa_start_option_rom_scan()
+{
+ tcpa_add_measurement(2, EV_ACTION, 14);
+}
+
+
+/*
+ * Add measurement to the log about an option rom
+ */
+void tcpa_option_rom(uint32_t seg)
+{
+ uint32_t len = read_byte(seg, 2) << 9;
+ uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,0);
+ char append[32]; /* TCG_PCClientTaggedEventStruct and
+ OptionROMExecuteStructure; specs 10.4.2.1 */
+ struct hai hai; /* HashAll Input Block; specs 12.10 */
+
+ memset(append, 0x0, sizeof(append));
+
+ append[0] = 7; /* Option ROM Execute */
+ append[4] = 24;/* size of OptionROMExecute Structure */
+ /* leave the rest to '0' */
+
+ /* 12.10 table 21 */
+ hai.ipblength = 0x10;
+ hai.reserved = 0;
+ hai.hashdataptr = (uint32_t)addr;
+ hai.hashdatalen = len;
+ hai.algorithmid = TPM_ALG_SHA;
+
+ HashAll32(&hai,
+ (unsigned char *)append+12,
+ TCG_MAGIC,
+ 0,
+ 0);
+
+ tcpa_add_measurement_to_log(2,
+ EV_EVENT_TAG,
+ 0,
+ append,
+ 32);
+}
+
+/*
+ * Add a measurement to the log in support of 8.2.5.3
+ * Creates two log entries
+ *
+ * Input parameter:
+ * seg : segment where the IPL data are located
+ */
+void tcpa_ipl(Bit32u seg)
+{
+ /* specs: 8.2.5.3 */
+ uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,0);
+ /* equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum */
+ tcpa_add_measurement_to_log_simple(4,
+ EV_IPL,
+ addr,
+ 0x1b8);
+ /* equivalent to: dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum */
+ tcpa_add_measurement_to_log_simple(5,
+ EV_IPL_PARTITION_DATA,
+ addr + 0x1b8,
+ 0x48);
+}
+
+void tcpa_measure_post(Bit32u from, Bit32u to)
+{
+ struct pcpes pcpes; /* PCClientPCREventStruc */
+ memset(&pcpes, 0x0, sizeof(pcpes));
+ int len = to - from;
+
+ if (len > 0) {
+ sha1((unsigned char *)from,
+ to-from,
+ (unsigned char *)&pcpes.digest);
+
+ pcpes.eventtype = EV_POST_CODE;
+ pcpes.eventdatasize = 0;
+ pcpes.pcrindex = 0;
+ tcpa_add_pcpes_to_log(&pcpes);
+ }
+}
+
+static
+uint32_t SendCommand32(uint32_t idx,
+ struct pttto *pttto,
+ uint32_t size_ptto)
+{
+ uint32_t rc = 0;
+ struct pttti *pttti = (struct pttti *)TCG_CommandList[idx];
+ uint8_t _pttto[30];
+
+ if (size_ptto > 0 && size_ptto < 14) {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_INVALID_INPUT_PARA << 16));
+ }
+
+ if (rc == 0) {
+ if (size_ptto == 0) {
+ pttto = (struct pttto *)_pttto;
+ size_ptto = sizeof(_pttto);
+ }
+ pttti->opblength = size_ptto;
+ }
+
+ if (rc == 0) {
+ if (pttti->opblength > size_ptto) {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_OUTPUT_BUFFER_TOO_SHORT << 16));
+ }
+ }
+
+ if (rc == 0) {
+ rc = PassThroughToTPM32(pttti,
+ pttto,
+ TCG_MAGIC,
+ 0x0,
+ 0x0);
+ }
+
+ return rc;
+}
+
+
+uint32_t tcpa_initialize_tpm(uint32_t physpres)
+{
+ uint32_t rc = 0;
+ uint8_t _pttto[40];
+ struct pttto *pttto = (struct pttto *)_pttto;
+ uint32_t pttto_size = sizeof(_pttto);
+
+ if (rc == 0) {
+ rc = SendCommand32(IDX_CMD_TPM_Startup_0x01, pttto, pttto_size);
+ }
+
+ if (rc == 0 && physpres != 0) {
+ rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x20,
+ pttto, pttto_size);
+ }
+
+ if (rc == 0 && physpres != 0) {
+ rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x08,
+ pttto, pttto_size);
+ }
+
+ if (rc == 0 && physpres != 0) {
+ rc = SendCommand32(IDX_CMD_TPM_PhysicalEnable,
+ pttto, pttto_size);
+ }
+
+ if (rc == 0 && physpres != 0) {
+ rc = SendCommand32(IDX_CMD_TPM_PhysicalSetDeactivated_0x00,
+ pttto, pttto_size);
+ }
+
+ if (rc == 0) {
+ rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x100,
+ pttto, pttto_size);
+ }
+
+ if (rc == 0) {
+ rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x10,
+ pttto, pttto_size);
+ }
+ return rc;
+}
+
+
+uint16_t TCG_IsShutdownPreBootInterface(void)
+{
+ return tcpa_acpi.flags & STATUS_FLAG_SHUTDOWN;
+}
+
+
+static
+uint32_t _TCG_TPM_Extend(unsigned char *hash, uint32_t pcrindex)
+{
+ uint32_t rc;
+ uint8_t _pttti[8+34];
+ uint8_t _pttto[4+30];
+ struct pttti *pttti = (struct pttti*)&_pttti;
+ struct pttto *pttto = (struct pttto*)&_pttto;
+
+ pttti->ipblength = 8 + 34;
+ pttti->reserved = 0;
+ pttti->opblength = 4 + 30;
+ pttti->reserved2 = 0;
+
+ _pttti[8 + 0] = 0x0;
+ _pttti[8 + 1] = 0xc1;
+ *(uint32_t *)&_pttti[8 + 2] = bswap(34);
+ *(uint32_t *)&_pttti[8 + 6] = bswap(0x14);
+ *(uint32_t *)&_pttti[8 + 10]= bswap(pcrindex);
+ memcpy(&_pttti[8+14], hash, 20);
+
+ rc = PassThroughToTPM32(pttti,
+ pttto,
+ TCG_MAGIC,
+ 0x0,
+ 0x0);
+ /* sanity check of result */
+ if (_pttto[4] != 0x00 || _pttto[5] != 0xc4) {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_FATAL_COM_ERROR << 16));
+ }
+
+ if (rc != 0) {
+ /*
+ Invalidate the log since system did not process this
+ extend properly.
+ */
+ tcpa_reset_acpi_log();
+ memset(&tcpa_acpi, 0x0, sizeof(tcpa_acpi));
+ TCG_ShutdownPreBootInterface(0);
+ }
+ return rc;
+}
+
+
+static
+uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s,
+ struct hleeo *hleeo,
+ uint32_t magic,
+ uint32_t ecx,
+ uint32_t edx)
+{
+ uint32_t rc = 0;
+ uint16_t size;
+ struct hlei hlei ; /* HashLogEventInput block */
+ struct hleo hleo; /* HashLogEventOutput block */
+ struct hleei_long *hleei_l = (struct hleei_long *)hleei_s;
+ int sh;
+ uint32_t logdataptr;
+
+ if (TCG_IsShutdownPreBootInterface() != 0) {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
+ }
+
+ if (rc == 0) {
+ /* short or long version? */
+ size = hleei_s->ipblength;
+ if (size == 0x18) {
+ /* short */
+ sh = 1;
+ } else if (size == 0x1c) {
+ /* long */
+ sh = 0;
+ } else {
+ /* bad input block */
+ rc = TCG_PC_TPMERROR |
+ ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
+ }
+ }
+
+ if (rc == 0) {
+ uint32_t hashdataptr;
+ uint32_t hashdatalen;
+ uint32_t pcrindex;
+ uint32_t logeventtype;
+ uint32_t logdatalen;
+ uint32_t eventnumber;
+ uint8_t hash[20];
+ struct pcpes *pcpes;
+
+ hashdataptr = hleei_s->hashdataptr;
+ hashdatalen = hleei_s->hashdatalen;
+ pcrindex = hleei_s->pcrindex;
+ if (sh) {
+ logdataptr = hleei_s->logdataptr;
+ logdatalen = hleei_s->logdatalen;
+ } else {
+ logdataptr = hleei_l->logdataptr;
+ logdatalen = hleei_l->logdatalen;
+ }
+
+ pcpes = (struct pcpes *)logdataptr;
+ logeventtype = pcpes->eventtype;
+
+ /* fill out HashLogEventInput block 'hlie' */
+ hlei.ipblength = 0x1c;
+ hlei.reserved = 0;
+ hlei.hashdataptr = hashdataptr;
+ hlei.hashdatalen = hashdatalen;
+ hlei.pcrindex = pcrindex;
+ hlei.logeventtype= logeventtype;
+ hlei.logdataptr = logdataptr;
+ hlei.logdatalen = logdatalen;
+
+ rc = HashLogEvent32(&hlei,
+ &hleo,
+ TCG_MAGIC,
+ 0x0,
+ 0x0);
+ eventnumber = hleo.eventnumber;
+
+ hleeo->opblength = 8 + 20;
+ hleeo->reserved = 0;
+ hleeo->eventnumber = eventnumber;
+
+ memcpy(hash, (unsigned char *)logdataptr + 0x8, 20);
+ _TCG_TPM_Extend(hash, pcrindex);
+ }
+
+ if (rc != 0) {
+ hleeo->opblength = 4;
+ hleeo->reserved = 0;
+ }
+ return rc;
+
+}
+
+
+static
+uint32_t PassThroughToTPM32(struct pttti *pttti,
+ struct pttto *pttto,
+ uint32_t magic,
+ uint32_t ecx,
+ uint32_t edx)
+{
+ uint32_t rc = 0;
+ uint8_t *cmd32;
+ uint32_t resbuflen;
+
+ if (TCG_IsShutdownPreBootInterface() != 0) {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
+ }
+
+ if (rc == 0) {
+ if (pttti->ipblength < 0x8 + 10) {
+ rc = TCG_PC_TPMERROR |
+ ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
+ }
+ }
+
+ if (rc == 0) {
+ if (pttti->opblength < 0x4) {
+ rc = TCG_PC_TPMERROR |
+ ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
+ }
+ }
+
+ if (rc == 0) {
+ uint8_t *resbuf32;
+
+ cmd32 = &pttti->tpmoperandin[0];
+ resbuflen = pttti->opblength - 4;
+ resbuf32 = &pttto->tpmoperandout[0];
+
+ rc = MA_Transmit(cmd32, resbuf32, resbuflen);
+ }
+
+ if (rc == 0) {
+ pttto->opblength = resbuflen+4;
+ pttto->reserved = 0;
+ }
+
+ if (rc != 0) {
+ pttto->opblength = 0;
+ pttto->reserved = 0;
+ }
+
+ return rc;
+}
+
+
+static
+uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx)
+{
+ uint32_t rc = 0;
+ if (TCG_IsShutdownPreBootInterface() == 0) {
+ tcpa_acpi.flags |= STATUS_FLAG_SHUTDOWN;
+ } else {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
+ }
+ return rc;
+}
+
+
+static
+uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo,
+ uint32_t ebx,
+ uint32_t ecx,
+ uint32_t edx)
+{
+ uint32_t rc = 0;
+ uint16_t size;
+ uint32_t logdataptr;
+ uint32_t logdatalen;
+ uint32_t hashdataptr;
+ uint32_t hashdatalen;
+
+ if (TCG_IsShutdownPreBootInterface() != 0) {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
+ }
+
+ if (rc == 0) {
+ size = hlei->ipblength;
+ if (size != 0x1c) {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
+ }
+ }
+
+ if (rc == 0) {
+ struct pcpes *pcpes;
+ logdataptr = hlei->logdataptr;
+ logdatalen = hlei->logdatalen;
+ pcpes = (struct pcpes *)logdataptr;
+ if (pcpes->pcrindex != hlei->pcrindex) {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
+ }
+ }
+
+ if (rc == 0) {
+ struct pcpes *pcpes= (struct pcpes *)logdataptr;
+ if (pcpes->eventtype != hlei->logeventtype) {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
+ }
+ }
+
+ if (rc == 0) {
+ uint32_t entry;
+ hashdataptr = hlei->hashdataptr;
+ hashdatalen = hlei->hashdatalen;
+
+ if ((hashdataptr != 0) | (hashdatalen != 0)) {
+ uint8_t hash[20];
+ struct hai hai; /* HashAll Input Block */
+ hai.ipblength = 0x10;
+ hai.reserved = 0x0;
+ hai.hashdataptr = hashdataptr;
+ hai.hashdatalen = hashdatalen;
+ hai.algorithmid = TPM_ALG_SHA;
+ rc = HashAll32(&hai,
+ hash,
+ TCG_MAGIC,
+ 0x0,
+ 0x0);
+
+ if (rc == 0) {
+ /* hashing was done ok */
+ memcpy((unsigned char *)logdataptr + 8,
+ hash,
+ 20);
+ }
+ }
+
+ if (rc == 0) {
+ /* extend the log with this event */
+ entry = tcpa_extend_acpi_log(logdataptr);
+ if ((uint16_t)entry == 0) {
+ /* upper 16 bits hold error code */
+ rc = (entry >> 16);
+ }
+ }
+
+ if (rc == 0) {
+ /* updating the log was fine */
+ hleo->opblength = 8;
+ hleo->reserved = 0;
+ hleo->eventnumber = entry;
+ }
+ }
+
+ if (rc != 0) {
+ hleo->opblength = 2;
+ hleo->reserved = 0;
+ }
+
+ return rc;
+}
+
+static
+uint32_t HashAll32(struct hai *hai, unsigned char *hash,
+ uint32_t magic,
+ uint32_t ecx,
+ uint32_t edx)
+{
+ uint32_t rc = 0;
+
+ if (TCG_IsShutdownPreBootInterface() != 0) {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
+ }
+
+ if (rc == 0) {
+ if (hai->ipblength != 0x10) {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
+ }
+ }
+
+ if (rc == 0) {
+ if (hai->algorithmid != TPM_ALG_SHA) {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
+ }
+ }
+
+ if (rc == 0) {
+ uint8_t *hashdataptr32;
+ uint32_t hashdatalen32;
+
+ hashdataptr32 = (uint8_t *)hai->hashdataptr;
+ hashdatalen32 = hai->hashdatalen;
+
+ sha1(hashdataptr32,
+ hashdatalen32,
+ hash);
+ }
+
+ return rc;
+}
+
+
+static
+uint32_t TSS32(struct ti *ti, struct to *to,
+ uint32_t ebx,
+ uint32_t ecx,
+ uint32_t edx)
+{
+ uint32_t rc = 0;
+ if (TCG_IsShutdownPreBootInterface() == 0) {
+ rc = TCG_PC_UNSUPPORTED;
+ } else {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
+ }
+
+ if (rc != 0) {
+ to->opblength = 4;
+ to->reserved = 0;
+ }
+
+ return rc;
+}
+
+static
+uint32_t CompactHashLogExtendEvent32(unsigned char *buffer,
+ uint32_t info,
+ uint32_t magic,
+ uint32_t length,
+ uint32_t pcrindex,
+ uint32_t *edx_ptr)
+{
+ uint32_t rc = 0;
+ struct hleeo hleeo;
+
+ if (TCG_IsShutdownPreBootInterface() != 0) {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
+ }
+
+ if (buffer == 0) {
+ rc = (TCG_PC_TPMERROR |
+ ((uint32_t)TCG_INVALID_INPUT_PARA << 16));
+ }
+
+ if (rc == 0) {
+ struct hleei_short hleei;
+ struct pcpes pcpes;
+ uint8_t *logdataptr;
+ uint8_t *hashdataptr;
+
+ logdataptr = (uint8_t*)&pcpes;
+ hashdataptr = buffer;
+
+ hleei.ipblength = 0x18;
+ hleei.reserved = 0x0;
+ hleei.hashdataptr = (uint32_t)hashdataptr;
+ hleei.hashdatalen = length;
+ hleei.pcrindex = pcrindex;
+ hleei.logdataptr = (uint32_t)logdataptr;
+ hleei.logdatalen = 32;
+
+ memset(&pcpes, 0x0, 32);
+ pcpes.pcrindex = pcrindex;
+ pcpes.eventtype = 12; /* EV_COMPACT_HASH */
+ pcpes.eventdatasize = 4;
+ pcpes.event = info;
+
+ rc = HashLogExtendEvent32(&hleei,
+ &hleeo,
+ TCG_MAGIC,
+ 0x0,
+ 0x0);
+ }
+
+ if (rc == 0) {
+ *edx_ptr = hleeo.eventnumber;
+ }
+
+ return rc;
+}
+
+
+
+/*******************************************************************
+ Calculation of SHA1 in SW
+
+ See: RFC3174, Wikipedia's SHA1 alogrithm description
+ ******************************************************************/
+typedef struct _sha1_ctx {
+ uint32_t h[5];
+} sha1_ctx;
+
+
+static inline uint32_t rol(val, rol)
+ uint32_t val;
+ uint16_t rol;
+{
+ return (val << rol) | (val >> (32 - rol));
+}
+
+static const uint32_t sha_ko[4] = { 0x5a827999,
+ 0x6ed9eba1,
+ 0x8f1bbcdc,
+ 0xca62c1d6 };
+
+
+static void sha1_block(uint32_t *w, sha1_ctx *ctx)
+{
+ uint32_t i;
+ uint32_t a,b,c,d,e,f;
+ uint32_t tmp;
+ uint32_t idx;
+
+ /* change endianess of given data */
+ for (i = 0; i < 16; i++) {
+ w[i] = bswap(w[i]);
+ }
+
+ for (i = 16; i <= 79; i++) {
+ tmp = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
+ w[i] = rol(tmp,1);
+ }
+
+ a = ctx->h[0];
+ b = ctx->h[1];
+ c = ctx->h[2];
+ d = ctx->h[3];
+ e = ctx->h[4];
+
+ for (i = 0; i <= 79; i++) {
+ if (i <= 19) {
+ f = (b & c) | ((b ^ 0xffffffff) & d);
+ idx = 0;
+ } else if (i <= 39) {
+ f = b ^ c ^ d;
+ idx = 1;
+ } else if (i <= 59) {
+ f = (b & c) | (b & d) | (c & d);
+ idx = 2;
+ } else {
+ f = b ^ c ^ d;
+ idx = 3;
+ }
+
+ tmp = rol(a, 5) +
+ f +
+ e +
+ sha_ko[idx] +
+ w[i];
+ e = d;
+ d = c;
+ c = rol(b, 30);
+ b = a;
+ a = tmp;
+ }
+
+ ctx->h[0] += a;
+ ctx->h[1] += b;
+ ctx->h[2] += c;
+ ctx->h[3] += d;
+ ctx->h[4] += e;
+}
+
+static
+void sha1_do(sha1_ctx *ctx, const unsigned char *data32, uint32_t length)
+{
+ uint32_t offset;
+ uint16_t num;
+ uint32_t bits = 0;
+ uint32_t w[80];
+ uint32_t tmp;
+
+ /* treat data in 64-byte chunks */
+ for (offset = 0; length - offset >= 64; offset += 64) {
+ /* copy into the 'w' array */
+ memcpy(w, data32 + offset, 64);
+ /* hash the block in the 'w' array */
+ sha1_block((uint32_t *)w, ctx);
+ bits += (64 * 8);
+ }
+
+ /* last block with less than 64 bytes */
+ num = length - offset;
+ bits += (num << 3);
+
+ memset(w, 0x0, 64);
+ memcpy(w, data32 + offset, num);
+ ((uint8_t *)w)[num] = 0x80;
+
+ if (num >= 56) {
+ /* cannot append number of bits here */
+ sha1_block((uint32_t *)w, ctx);
+ memset(w, 0x0, 60);
+ }
+
+ /* write number of bits to end of block */
+ tmp = bswap(bits);
+ memcpy(&w[15], &tmp, 4);
+
+ sha1_block(w, ctx);
+
+ /* need to switch result's endianess */
+ for (num = 0; num < 5; num++)
+ ctx->h[num] = bswap(ctx->h[num]);
+}
+
+/* sha1 initialization constants */
+static const uint32_t sha_const[5] = {
+ 0x67452301,
+ 0xefcdab89,
+ 0x98badcfe,
+ 0x10325476,
+ 0xc3d2e1f0
+};
+
+static
+void sha1(const unsigned char *data, uint32_t length, unsigned char *hash)
+{
+ sha1_ctx ctx;
+
+ memcpy(&ctx.h[0], sha_const, 20);
+ sha1_do(&ctx, data, length);
+ memcpy(hash, &ctx.h[0], 20);
+}
+
+
+uint32_t TCGInterruptHandler(pushad_regs_t *regs, uint32_t esds, uint32_t flags_ptr)
+{
+ uint16_t DS = esds >> 16;
+ uint16_t ES = esds & 0xffff;
+ uint16_t *FLAGS = (uint16_t *)flags_ptr;
+
+ switch(regs->u.r8.al) {
+ case 0x00:
+ if (MA_IsTPMPresent() == 0) {
+ /* no TPM available */
+ regs->u.r32.eax = TCG_PC_TPMERROR |
+ ((uint32_t)(TCG_PC_TPM_NOT_PRESENT) << 16);
+ } else {
+ regs->u.r32.eax = MA_InitTPM(TPM_ST_CLEAR);
+ if (regs->u.r32.eax == 0) {
+ regs->u.r32.ebx = TCG_MAGIC;
+ regs->u.r8.ch = TCG_VERSION_MAJOR;
+ regs->u.r8.cl = TCG_VERSION_MINOR;
+ regs->u.r32.edx = 0x0;
+ regs->u.r32.esi =
+ (Bit32u)tcpa_get_lasa_base_ptr();
+ regs->u.r32.edi =
+ (Bit32u)tcpa_get_lasa_last_ptr();
+ CLEAR_CF();
+ }
+ }
+ break;
+
+ case 0x01:
+ regs->u.r32.eax =
+ HashLogExtendEvent32((struct hleei_short*)
+ ADDR_FROM_SEG_OFF(ES,
+ regs->u.r16.di),
+ (struct hleeo*)
+ ADDR_FROM_SEG_OFF(DS,
+ regs->u.r16.si),
+ regs->u.r32.ebx,
+ regs->u.r32.ecx,
+ regs->u.r32.edx);
+ CLEAR_CF();
+ break;
+ case 0x02:
+ regs->u.r32.eax =
+ PassThroughToTPM32((struct pttti *)
+ ADDR_FROM_SEG_OFF(ES,
+ regs->u.r16.di),
+ (struct pttto *)
+ ADDR_FROM_SEG_OFF(DS,
+ regs->u.r16.si),
+ regs->u.r32.ebx,
+ regs->u.r32.ecx,
+ regs->u.r32.edx);
+ CLEAR_CF();
+ break;
+ case 0x03:
+ regs->u.r32.eax =
+ TCG_ShutdownPreBootInterface(regs->u.r32.ebx);
+ CLEAR_CF();
+ break;
+ case 0x04:
+ regs->u.r32.eax =
+ HashLogEvent32((struct hlei*)
+ ADDR_FROM_SEG_OFF(ES,
+ regs->u.r16.di),
+ (struct hleo*)
+ ADDR_FROM_SEG_OFF(DS,
+ regs->u.r16.si),
+ regs->u.r32.ebx,
+ regs->u.r32.ecx,
+ regs->u.r32.edx);
+ CLEAR_CF();
+ break;
+ case 0x05:
+ regs->u.r32.eax =
+ HashAll32((struct hai*)
+ ADDR_FROM_SEG_OFF(ES,
+ regs->u.r16.di),
+ (unsigned char *)
+ ADDR_FROM_SEG_OFF(DS,
+ regs->u.r16.si),
+ regs->u.r32.ebx,
+ regs->u.r32.ecx,
+ regs->u.r32.edx);
+ CLEAR_CF();
+ break;
+ case 0x06:
+ regs->u.r32.eax =
+ TSS32((struct ti*)ADDR_FROM_SEG_OFF(ES,
+ regs->u.r16.di),
+ (struct to*)ADDR_FROM_SEG_OFF(DS,
+ regs->u.r16.si),
+ regs->u.r32.ebx,
+ regs->u.r32.ecx,
+ regs->u.r32.edx);
+ CLEAR_CF();
+ break;
+ case 0x07:
+ regs->u.r32.eax =
+ CompactHashLogExtendEvent32((unsigned char *)
+ ADDR_FROM_SEG_OFF(ES,
+ regs->u.r16.di),
+ regs->u.r32.esi,
+ regs->u.r32.ebx,
+ regs->u.r32.ecx,
+ regs->u.r32.edx,
+ &regs->u.r32.edx);
+ CLEAR_CF();
+ break;
+ default:
+ SET_CF();
+ }
+
+ return 0;
+}
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bit/tcgbios/tcgbios.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.h Fri Jan 26 16:38:32 2007 +0000
@@ -0,0 +1,288 @@
+#ifndef TCGBIOS_H
+#define TCGBIOS_H
+
+
+/* TCPA ACPI definitions */
+#define TCPA_ACPI_CLASS_CLIENT 0
+#define TCPA_ACPI_CLASS_SERVER 1
+
+/* 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
+#define TCG_GENERAL_ERROR (TPM_RET_BASE + 0x0)
+#define TCG_TPM_IS_LOCKED (TPM_RET_BASE + 0x1)
+#define TCG_NO_RESPONSE (TPM_RET_BASE + 0x2)
+#define TCG_INVALID_RESPONSE (TPM_RET_BASE + 0x3)
+#define TCG_INVALID_ACCESS_REQUEST (TPM_RET_BASE + 0x4)
+#define TCG_FIRMWARE_ERROR (TPM_RET_BASE + 0x5)
+#define TCG_INTEGRITY_CHECK_FAILED (TPM_RET_BASE + 0x6)
+#define TCG_INVALID_DEVICE_ID (TPM_RET_BASE + 0x7)
+#define TCG_INVALID_VENDOR_ID (TPM_RET_BASE + 0x8)
+#define TCG_UNABLE_TO_OPEN (TPM_RET_BASE + 0x9)
+#define TCG_UNABLE_TO_CLOSE (TPM_RET_BASE + 0xa)
+#define TCG_RESPONSE_TIMEOUT (TPM_RET_BASE + 0xb)
+#define TCG_INVALID_COM_REQUEST (TPM_RET_BASE + 0xc)
+#define TCG_INVALID_ADR_REQUEST (TPM_RET_BASE + 0xd)
+#define TCG_WRITE_BYTE_ERROR (TPM_RET_BASE + 0xe)
+#define TCG_READ_BYTE_ERROR (TPM_RET_BASE + 0xf)
+#define TCG_BLOCK_WRITE_TIMEOUT (TPM_RET_BASE + 0x10)
+#define TCG_CHAR_WRITE_TIMEOUT (TPM_RET_BASE + 0x11)
+#define TCG_CHAR_READ_TIMEOUT (TPM_RET_BASE + 0x12)
+#define TCG_BLOCK_READ_TIMEOUT (TPM_RET_BASE + 0x13)
+#define TCG_TRANSFER_ABORT (TPM_RET_BASE + 0x14)
+#define TCG_INVALID_DRV_FUNCTION (TPM_RET_BASE + 0x15)
+#define TCG_OUTPUT_BUFFER_TOO_SHORT (TPM_RET_BASE + 0x16)
+#define TCG_FATAL_COM_ERROR (TPM_RET_BASE + 0x17)
+#define TCG_INVALID_INPUT_PARA (TPM_RET_BASE + 0x18)
+#define TCG_TCG_COMMAND_ERROR (TPM_RET_BASE + 0x19)
+#define TCG_INTERFACE_SHUTDOWN (TPM_RET_BASE + 0x20)
+//define TCG_PC_UNSUPPORTED (TPM_RET_BASE + 0x21)
+#define TCG_PC_TPM_NOT_PRESENT (TPM_RET_BASE + 0x22)
+#define TCG_PC_TPM_DEACTIVATED (TPM_RET_BASE + 0x23)
+
+
+#define TPM_INVALID_ADR_REQUEST TCG_INVALID_ADR_REQUEST
+#define TPM_IS_LOCKED TCG_TPM_IS_LOCKED
+#define TPM_INVALID_DEVICE_ID TCG_INVALID_DEVICE_ID
+#define TPM_INVALID_VENDOR_ID TCG_INVALID_VENDOR_ID
+//define TPM_RESERVED_REG_INVALID
+#define TPM_FIRMWARE_ERROR TCG_FIRMWARE_ERROR
+#define TPM_UNABLE_TO_OPEN TCG_UNABLE_TO_OPEN
+#define TPM_UNABLE_TO_CLOSE TCG_UNABLE_TO_CLOSE
+#define TPM_INVALID_RESPONSE TCG_INVALID_RESPONSE
+#define TPM_RESPONSE_TIMEOUT TCG_RESPONSE_TIMEOUT
+#define TPM_INVALID_ACCESS_REQUEST TCG_INVALID_ACCESS_REQUEST
+#define TPM_TRANSFER_ABORT TCG_TRANSFER_ABORT
+#define TPM_GENERAL_ERROR TCG_GENERAL_ERROR
+
+#define TPM_ST_CLEAR 0x0
+#define TPM_ST_STATE 0x1
+#define TPM_ST_DEACTIVATED 0x2
+
+/* 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
+
+
+// MA Driver defines
+#define CODE_MAInitTPM 0x01
+#define CODE_MAHashAllExtendTPM 0x02
+#define CODE_MAPhysicalPresenceTPM 0x03
+/* vendor specific ones */
+#define CODE_MAIsTPMPresent 0x80
+#define CODE_MAHashAll 0x81
+#define CODE_MATransmit 0x82
+
+/*
+ indices for commands to be sent via proprietary
+ _TCG_SendCommand function
+ */
+#define IDX_CMD_TPM_Startup_0x01 0
+#define IDX_CMD_TSC_PhysicalPresence_0x20 1
+#define IDX_CMD_TSC_PhysicalPresence_0x08 2
+#define IDX_CMD_TSC_PhysicalPresence_0x100 3
+#define IDX_CMD_TSC_PhysicalPresence_0x10 4
+#define IDX_CMD_TPM_PhysicalEnable 5
+#define IDX_CMD_TPM_PhysicalSetDeactivated_0x00 6
+#define IDX_CMD_TPM_SHA1Start 7
+
+
+/* hardware registers for TPM TIS */
+#define TPM_ACCESS 0x0
+#define TPM_INT_ENABLE 0x8
+#define TPM_INT_VECTOR 0xc
+#define TPM_INT_STATUS 0x10
+#define TPM_INTF_CAPABILITY 0x14
+#define TPM_STS 0x18
+#define TPM_DATA_FIFO 0x24
+#define TPM_DID_VID 0xf00
+#define TPM_RID 0xf04
+
+/* address of locality 0 (TIS) */
+#define TPM_TIS_BASE_ADDRESS 0xfed40000
+
+#define ASCII32(a,b,c,d) ((((Bit32u)a) << 0) | (((Bit32u)b) << 8) | \
+ (((Bit32u)c) << 16) | (((Bit32u)d) << 24) )
+#define ACPI_2_0_TCPA_SIGNATURE ASCII32('T','C','P','A') /* "TCPA" */
+
+
+#define STATUS_FLAG_SHUTDOWN (1 << 0)
+
+#define ACPI_SEGMENT 0xE000
+
+/* Input and Output blocks for the TCG BIOS commands */
+
+struct hleei_short
+{
+ uint16_t ipblength;
+ uint16_t reserved;
+ uint32_t hashdataptr;
+ uint32_t hashdatalen;
+ uint32_t pcrindex;
+ uint32_t logdataptr;
+ uint32_t logdatalen;
+} __attribute__((packed));
+
+struct hleei_long
+{
+ uint16_t ipblength;
+ uint16_t reserved;
+ uint32_t hashdataptr;
+ uint32_t hashdatalen;
+ uint32_t pcrindex;
+ uint32_t reserved2;
+ uint32_t logdataptr;
+ uint32_t logdatalen;
+} __attribute__((packed));
+
+struct hleeo
+{
+ uint16_t opblength;
+ uint16_t reserved;
+ uint32_t eventnumber;
+ uint8_t hashvalue[20];
+} __attribute__((packed));
+
+
+
+struct pttti
+{
+ uint16_t ipblength;
+ uint16_t reserved;
+ uint16_t opblength;
+ uint16_t reserved2;
+ uint8_t tpmoperandin[0];
+} __attribute__((packed));
+
+struct pttto
+{
+ uint16_t opblength;
+ uint16_t reserved;
+ uint8_t tpmoperandout[0];
+};
+
+
+struct hlei
+{
+ uint16_t ipblength;
+ uint16_t reserved;
+ uint32_t hashdataptr;
+ uint32_t hashdatalen;
+ uint32_t pcrindex;
+ uint32_t logeventtype;
+ uint32_t logdataptr;
+ uint32_t logdatalen;
+} __attribute__((packed));
+
+struct hleo
+{
+ uint16_t opblength;
+ uint16_t reserved;
+ uint32_t eventnumber;
+} __attribute__((packed));
+
+struct hai
+{
+ uint16_t ipblength;
+ uint16_t reserved;
+ uint32_t hashdataptr;
+ uint32_t hashdatalen;
+ uint32_t algorithmid;
+} __attribute__((packed));
+
+struct ti
+{
+ uint16_t ipblength;
+ uint16_t reserved;
+ uint16_t opblength;
+ uint16_t reserved2;
+ uint8_t tssoperandin[0];
+} __attribute__((packed));
+
+struct to
+{
+ uint16_t opblength;
+ uint16_t reserved;
+ uint8_t tssoperandout[0];
+} __attribute__((packed));
+
+
+struct pcpes
+{
+ uint32_t pcrindex;
+ uint32_t eventtype;
+ uint8_t digest[20];
+ uint32_t eventdatasize;
+ uint32_t event;
+} __attribute__((packed));
+
+
+struct acpi_header
+{
+ uint32_t signature;
+ uint32_t length;
+ uint8_t revision;
+ uint8_t checksum;
+ uint8_t oem_id[6];
+ uint64_t oem_table_id;
+ uint32_t oem_revision;
+ uint32_t creator_id;
+ uint32_t creator_revision;
+} __attribute__((packed));
+
+struct acpi_20_rsdt {
+ struct acpi_header header;
+ uint32_t entry[1];
+} __attribute__((packed));
+
+struct acpi_20_rsdp {
+ uint64_t signature;
+ uint8_t checksum;
+ uint8_t oem_id[6];
+ uint8_t revision;
+ uint32_t rsdt_address;
+ uint32_t length;
+ uint64_t xsdt_address;
+ uint8_t extended_checksum;
+ uint8_t reserved[3];
+} __attribute__((packed));
+
+struct acpi_20_tcpa_client {
+ uint32_t laml;
+ uint64_t lasa;
+} __attribute__((packed));
+
+struct acpi_20_tcpa_server {
+ uint16_t reserved;
+ uint32_t laml;
+ uint64_t lasa;
+ /* more here */
+} __attribute__((packed));
+
+struct acpi_20_tcpa {
+ struct acpi_header header;
+ uint16_t platform_class;
+ union {
+ struct acpi_20_tcpa_client client;
+ struct acpi_20_tcpa_server server;
+ } u;
+} __attribute__((packed));
+
+
+#endif
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c Fri Jan 26 16:38:32 2007 +0000
@@ -0,0 +1,180 @@
+/*
+ * Implementation of the TCG BIOS extension according to the specification
+ * described in
+ * https://www.trustedcomputinggroup.org/specs/PCClient/TCG_PCClientImplementationforBIOS_1-20_1-00.pdf
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright (C) IBM Corporation, 2006
+ *
+ * Author: Stefan Berger <stefanb@us.ibm.com>
+ */
+#include "rombios_compat.h"
+#include "util.h"
+
+#include "tpm_drivers.h"
+#include "tcgbios.h"
+
+static uint32_t tis_wait_sts(uint8_t *addr, uint32_t time,
+ uint8_t mask, uint8_t expect)
+{
+ uint32_t rc = 0;
+ while (time > 0) {
+ uint8_t sts = addr[TPM_STS];
+ if ((sts & mask) == expect) {
+ rc = 1;
+ break;
+ }
+ mssleep(1);
+ time--;
+ }
+ return rc;
+}
+
+static uint32_t tis_activate(uint32_t baseaddr)
+{
+ uint32_t rc = 0;
+ uint8_t *tis_addr = (uint8_t*)baseaddr;
+ uint8_t acc;
+ /* request access to locality */
+ tis_addr[TPM_ACCESS] = 0x2;
+
+ acc = tis_addr[TPM_ACCESS];
+ if ((acc & 0x20) != 0) {
+ tis_addr[TPM_STS] = 0x40;
+ rc = tis_wait_sts(tis_addr, 100, 0x40, 0x40);
+ }
+ return rc;
+}
+
+uint32_t tis_ready(uint32_t baseaddr)
+{
+ uint32_t rc = 0;
+ uint8_t *tis_addr = (uint8_t*)baseaddr;
+
+ tis_addr[TPM_STS] = 0x40;
+ rc = tis_wait_sts(tis_addr, 100, 0x40, 0x40);
+
+ return rc;
+}
+
+uint32_t tis_senddata(uint32_t baseaddr, unsigned char *data, uint32_t len)
+{
+ uint32_t rc = 0;
+ uint8_t *tis_addr = (uint8_t*)baseaddr;
+ uint32_t offset = 0;
+ uint32_t end = 0;
+
+ do {
+ uint16_t burst = 0;
+ uint32_t ctr = 0;
+ while (burst == 0 && ctr < 2000) {
+ burst = (((uint16_t)tis_addr[TPM_STS+1]) ) +
+ (((uint16_t)tis_addr[TPM_STS+2]) << 8);
+ if (burst == 0) {
+ mssleep(1);
+ ctr++;
+ }
+ }
+
+ if (burst == 0) {
+ rc = TCG_RESPONSE_TIMEOUT;
+ break;
+ }
+
+ while (1) {
+ tis_addr[TPM_DATA_FIFO] = data[offset];
+ offset++;
+ burst--;
+
+ if (burst == 0 || offset == len) {
+ break;
+ }
+ }
+
+ if (offset == len) {
+ end = 1;
+ }
+ } while (end == 0);
+
+ return rc;
+}
+
+uint32_t tis_readresp(uint32_t baseaddr, unsigned char *buffer, uint32_t len)
+{
+ uint32_t rc = 0;
+ uint32_t offset = 0;
+ uint8_t *tis_addr = (uint8_t*)baseaddr;
+ uint32_t sts;
+
+ while (offset < len) {
+ buffer[offset] = tis_addr[TPM_DATA_FIFO];
+ offset++;
+ sts = tis_addr[TPM_STS];
+ /* data left ? */
+ if ((sts & 0x10) == 0) {
+ break;
+ }
+ }
+ return rc;
+}
+
+
+uint32_t tis_waitdatavalid(uint32_t baseaddr)
+{
+ uint8_t *tis_addr = (uint8_t*)baseaddr;
+ uint32_t rc = 0;
+ if (tis_wait_sts(tis_addr, 1000, 0x80, 0x80) == 0) {
+ rc = TCG_NO_RESPONSE;
+ }
+ return rc;
+}
+
+uint32_t tis_waitrespready(uint32_t baseaddr, uint32_t timeout)
+{
+ uint32_t rc = 0;
+ uint8_t *tis_addr = (uint8_t*)baseaddr;
+ tis_addr[TPM_STS] = 0x20;
+ if (tis_wait_sts(tis_addr, timeout, 0x10, 0x10) == 0) {
+ rc = TCG_NO_RESPONSE;
+ }
+ return rc;
+}
+
+/* if device is not there, return '0', '1' otherwise */
+uint32_t tis_probe(uint32_t baseaddr)
+{
+ uint32_t rc = 0;
+ uint8_t *tis_addr = (uint8_t*)baseaddr;
+ uint32_t didvid = *(uint32_t*)&tis_addr[TPM_DID_VID];
+ if ((didvid != 0) && (didvid != 0xffffffff)) {
+ rc = 1;
+ }
+ return rc;
+}
+
+
+struct tpm_driver tpm_drivers[TPM_NUM_DRIVERS] = {
+ {
+ .baseaddr = TPM_TIS_BASE_ADDRESS,
+ .activate = tis_activate,
+ .ready = tis_ready,
+ .senddata = tis_senddata,
+ .readresp = tis_readresp,
+ .waitdatavalid = tis_waitdatavalid,
+ .waitrespready = tis_waitrespready,
+ .probe = tis_probe,
+ },
+};
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bit/tcgbios/tpm_drivers.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.h Fri Jan 26 16:38:32 2007 +0000
@@ -0,0 +1,18 @@
+#ifndef TPM_DRIVER_H
+/* low level driver implementation */
+struct tpm_driver {
+ uint32_t baseaddr;
+ uint32_t (*activate)(uint32_t baseaddr);
+ uint32_t (*ready)(uint32_t baseaddr);
+ uint32_t (*senddata)(uint32_t baseaddr, unsigned char *data, uint32_t len);
+ uint32_t (*readresp)(uint32_t baseaddr, unsigned char *buffer, uint32_t len);
+ uint32_t (*waitdatavalid)(uint32_t baseaddr);
+ uint32_t (*waitrespready)(uint32_t baseaddr, uint32_t timeout);
+ uint32_t (*probe)(uint32_t baseaddr);
+};
+
+#define TPM_NUM_DRIVERS 1
+
+#define TPM_INVALID_DRIVER -1
+
+#endif
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bit/util.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/util.c Fri Jan 26 16:38:32 2007 +0000
@@ -0,0 +1,450 @@
+/*
+ * util.c: Helper library functions for HVMLoader.
+ *
+ * Leendert van Doorn, leendert@watson.ibm.com
+ * Copyright (c) 2005, International Business Machines Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include <stdarg.h>
+#include <stdint.h>
+#include "util.h"
+
+static void putchar(char c);
+#define isdigit(c) ((c) >= '0' && (c) <= '9')
+
+void outb(uint16_t addr, uint8_t val)
+{
+ __asm__ __volatile__ ( "outb %%al, %%dx" :: "d"(addr), "a"(val) );
+}
+
+void outw(uint16_t addr, uint16_t val)
+{
+ __asm__ __volatile__ ( "outw %%ax, %%dx" :: "d"(addr), "a"(val) );
+}
+
+void outl(uint16_t addr, uint32_t val)
+{
+ __asm__ __volatile__ ( "outl %%eax, %%dx" :: "d"(addr), "a"(val) );
+}
+
+uint8_t inb(uint16_t addr)
+{
+ uint8_t val;
+ __asm__ __volatile__ ( "inb %%dx,%%al" : "=a" (val) : "d" (addr) );
+ return val;
+}
+
+uint16_t inw(uint16_t addr)
+{
+ uint16_t val;
+ __asm__ __volatile__ ( "inw %%dx,%%ax" : "=a" (val) : "d" (addr) );
+ return val;
+}
+
+uint32_t inl(uint16_t addr)
+{
+ uint32_t val;
+ __asm__ __volatile__ ( "inl %%dx,%%eax" : "=a" (val) : "d" (addr) );
+ return val;
+}
+
+char *itoa(char *a, unsigned int i)
+{
+ unsigned int _i = i, x = 0;
+
+ do {
+ x++;
+ _i /= 10;
+ } while ( _i != 0 );
+
+ a += x;
+ *a-- = '\0';
+
+ do {
+ *a-- = (i % 10) + '0';
+ i /= 10;
+ } while ( i != 0 );
+
+ return a + 1;
+}
+
+int strcmp(const char *cs, const char *ct)
+{
+ signed char res;
+
+ while ( ((res = *cs - *ct++) == 0) && (*cs++ != '\0') )
+ continue;
+
+ return res;
+}
+
+int strncmp(const char *s1, const char *s2, uint32_t n)
+{
+ uint32_t ctr;
+ for (ctr = 0; ctr < n; ctr++)
+ if (s1[ctr] != s2[ctr])
+ return (int)(s1[ctr] - s2[ctr]);
+ return 0;
+}
+
+void *memcpy(void *dest, const void *src, unsigned n)
+{
+ int t0, t1, t2;
+
+ __asm__ __volatile__ (
+ "cld\n"
+ "rep; movsl\n"
+ "testb $2,%b4\n"
+ "je 1f\n"
+ "movsw\n"
+ "1: testb $1,%b4\n"
+ "je 2f\n"
+ "movsb\n"
+ "2:"
+ : "=&c" (t0), "=&D" (t1), "=&S" (t2)
+ : "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
+ : "memory" );
+ return dest;
+}
+
+void *memmove(void *dest, const void *src, unsigned n)
+{
+ if ( (long)dest > (long)src )
+ {
+ n--;
+ while ( n > 0 )
+ {
+ ((char *)dest)[n] = ((char *)src)[n];
+ n--;
+ }
+ }
+ else
+ {
+ memcpy(dest, src, n);
+ }
+ return dest;
+}
+
+char *
+strcpy(char *dest, const char *src)
+{
+ char *p = dest;
+ while ( *src )
+ *p++ = *src++;
+ *p = 0;
+ return dest;
+}
+
+char *
+strncpy(char *dest, const char *src, unsigned n)
+{
+ int i = 0;
+ char *p = dest;
+
+ /* write non-NUL characters from src into dest until we run
+ out of room in dest or encounter a NUL in src */
+ while ( (i < n) && *src )
+ {
+ *p++ = *src++;
+ i++;
+ }
+
+ /* pad remaining bytes of dest with NUL bytes */
+ while ( i < n )
+ {
+ *p++ = 0;
+ i++;
+ }
+
+ return dest;
+}
+
+unsigned
+strlen(const char *s)
+{
+ int i = 0;
+ while ( *s++ )
+ i++;
+ return i;
+}
+
+void *
+memset(void *s, int c, unsigned n)
+{
+ uint8_t b = (uint8_t) c;
+ uint8_t *p = (uint8_t *)s;
+ int i;
+ for ( i = 0; i < n; i++ )
+ *p++ = b;
+ return s;
+}
+
+int
+memcmp(const void *s1, const void *s2, unsigned n)
+{
+ unsigned i;
+ uint8_t *p1 = (uint8_t *) s1;
+ uint8_t *p2 = (uint8_t *) s2;
+
+ for ( i = 0; i < n; i++ )
+ {
+ if ( p1[i] < p2[i] )
+ return -1;
+ else if ( p1[i] > p2[i] )
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
+{
+ __asm__ __volatile__ (
+ "cpuid"
+ : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
+ : "0" (idx) );
+}
+
+/* Write a two-character hex representation of 'byte' to digits[].
+ Pre-condition: sizeof(digits) >= 2 */
+void
+byte_to_hex(char *digits, uint8_t byte)
+{
+ uint8_t nybbel = byte >> 4;
+
+ if ( nybbel > 9 )
+ digits[0] = 'a' + nybbel-10;
+ else
+ digits[0] = '0' + nybbel;
+
+ nybbel = byte & 0x0f;
+ if ( nybbel > 9 )
+ digits[1] = 'a' + nybbel-10;
+ else
+ digits[1] = '0' + nybbel;
+}
+
+/* Convert an array of 16 unsigned bytes to a DCE/OSF formatted UUID
+ string.
+
+ Pre-condition: sizeof(dest) >= 37 */
+void
+uuid_to_string(char *dest, uint8_t *uuid)
+{
+ int i = 0;
+ char *p = dest;
+
+ for ( i = 0; i < 4; i++ )
+ {
+ byte_to_hex(p, uuid[i]);
+ p += 2;
+ }
+ *p++ = '-';
+ for ( i = 4; i < 6; i++ )
+ {
+ byte_to_hex(p, uuid[i]);
+ p += 2;
+ }
+ *p++ = '-';
+ for ( i = 6; i < 8; i++ )
+ {
+ byte_to_hex(p, uuid[i]);
+ p += 2;
+ }
+ *p++ = '-';
+ for ( i = 8; i < 10; i++ )
+ {
+ byte_to_hex(p, uuid[i]);
+ p += 2;
+ }
+ *p++ = '-';
+ for ( i = 10; i < 16; i++ )
+ {
+ byte_to_hex(p, uuid[i]);
+ p += 2;
+ }
+ *p = '\0';
+}
+
+static char *printnum(char *p, unsigned long num, int base)
+{
+ unsigned long n;
+
+ if ( (n = num/base) > 0 )
+ p = printnum(p, n, base);
+ *p++ = "0123456789abcdef"[(int)(num % base)];
+ *p = '\0';
+ return p;
+}
+
+static void _doprint(void (*put)(char), char const *fmt, va_list ap)
+{
+ register char *str, c;
+ int lflag, zflag, nflag;
+ char buffer[17];
+ unsigned value;
+ int i, slen, pad;
+
+ for ( ; *fmt != '\0'; fmt++ )
+ {
+ if ( *fmt != '%' )
+ {
+ put(*fmt);
+ continue;
+ }
+
+ pad = zflag = nflag = lflag = 0;
+ c = *++fmt;
+ if ( (c == '-') || isdigit(c) )
+ {
+ if ( c == '-' )
+ {
+ nflag = 1;
+ c = *++fmt;
+ }
+ zflag = c == '0';
+ for ( pad = 0; isdigit(c); c = *++fmt )
+ pad = (pad * 10) + c - '0';
+ }
+ if ( c == 'l' ) /* long extension */
+ {
+ lflag = 1;
+ c = *++fmt;
+ }
+ if ( (c == 'd') || (c == 'u') || (c == 'o') || (c == 'x') )
+ {
+ if ( lflag )
+ value = va_arg(ap, unsigned);
+ else
+ value = (unsigned) va_arg(ap, unsigned int);
+ str = buffer;
+ printnum(str, value,
+ c == 'o' ? 8 : (c == 'x' ? 16 : 10));
+ goto printn;
+ }
+ else if ( (c == 'O') || (c == 'D') || (c == 'X') )
+ {
+ value = va_arg(ap, unsigned);
+ str = buffer;
+ printnum(str, value,
+ c == 'O' ? 8 : (c == 'X' ? 16 : 10));
+ printn:
+ slen = strlen(str);
+ for ( i = pad - slen; i > 0; i-- )
+ put(zflag ? '0' : ' ');
+ while ( *str )
+ put(*str++);
+ }
+ else if ( c == 's' )
+ {
+ str = va_arg(ap, char *);
+ slen = strlen(str);
+ if ( nflag == 0 )
+ for ( i = pad - slen; i > 0; i-- )
+ put(' ');
+ while ( *str )
+ put(*str++);
+ if ( nflag )
+ for ( i = pad - slen; i > 0; i-- )
+ put(' ');
+ }
+ else if ( c == 'c' )
+ {
+ put(va_arg(ap, int));
+ }
+ else
+ {
+ put(*fmt);
+ }
+ }
+}
+
+static void putchar(char c)
+{
+ outb(0xe9, c);
+}
+
+int printf(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ _doprint(putchar, fmt, ap);
+ va_end(ap);
+
+ return 0;
+}
+
+int vprintf(const char *fmt, va_list ap)
+{
+ _doprint(putchar, fmt, ap);
+ return 0;
+}
+
+
+/*
+ * sleep by synchronizing with the PIT on channel 2
+ * http://bochs.sourceforge.net/techspec/intel-82c54-timer.pdf.gz
+ */
+#define PIT_CTR2 0x80
+#define PIT_CTR1 0x40
+#define PIT_CTR0 0x00
+
+#define PIT_RW_LSB 0x10
+
+#define PIT_MODE0 0x0
+
+#define PIT_CTR_16BIT 0x0
+
+#define PIT_CMD_LATCH 0x0
+
+#define PORT_PIT_CMD 0x43
+#define PORT_PIT_CTR2 0x42
+#define PORT_PIT_CTR1 0x41
+#define PORT_PIT_CTR0 0x40
+
+#define PIT_FREQ 1193182 /* Hz */
+
+#define PORT_PPI 0x61
+
+void mssleep(uint32_t waittime)
+{
+ long int timeout = 0;
+ uint8_t last = 0x0;
+ uint8_t old_ppi = inb(PORT_PPI);
+
+ /* use ctr2; ctr0 is used by the Bochs BIOS */
+ /* ctr2 drives speaker -- turn it off */
+ outb(PORT_PPI, old_ppi & 0xfc);
+
+ outb(PORT_PIT_CMD, PIT_CTR2 | PIT_RW_LSB | PIT_MODE0 | PIT_CTR_16BIT);
+ outb(PORT_PIT_CTR2, last); /* start countdown */
+
+ while (timeout < (waittime * PIT_FREQ / 1000)) {
+ uint8_t cur, delta;
+ outb(PORT_PIT_CMD, PIT_CTR2 | PIT_CMD_LATCH);
+ cur = inb(PORT_PIT_CTR2);
+ delta = last - cur;
+ timeout += delta;
+ last = cur;
+ }
+ /* turn ctr2 off */
+ outb(PORT_PIT_CMD, PIT_CTR2 | PIT_RW_LSB | PIT_MODE0 | PIT_CTR_16BIT);
+ outb(PORT_PIT_CTR2, 0xff); /* start countdown */
+ outb(PORT_PIT_CTR2, 0x0); /* stop */
+
+ outb(PORT_PPI, old_ppi);
+}
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bit/util.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/32bit/util.h Fri Jan 26 16:38:32 2007 +0000
@@ -0,0 +1,28 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+void outb(uint16_t addr, uint8_t val);
+void outw(uint16_t addr, uint16_t val);
+void outl(uint16_t addr, uint32_t val);
+uint8_t inb(uint16_t addr);
+uint16_t inw(uint16_t addr);
+uint32_t inl(uint16_t addr);
+void mssleep(uint32_t time);
+
+char *itoa(char *a, unsigned int i);
+int strcmp(const char *cs, const char *ct);
+int strncmp(const char *s1, const char *s2, uint32_t n);
+void *memcpy(void *dest, const void *src, unsigned n);
+void *memmove(void *dest, const void *src, unsigned n);
+char *strcpy(char *dest, const char *src);
+char *strncpy(char *dest, const char *src, unsigned n);
+unsigned strlen(const char *s);
+void * memset(void *s, int c, unsigned n);
+int memcmp(const void *s1, const void *s2, unsigned n);
+void cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
+void byte_to_hex(char *digits, uint8_t byte);
+void uuid_to_string(char *dest, uint8_t *uuid);
+int printf(const char *fmt, ...);
+
+
+#endif
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bitgateway.c
--- a/tools/firmware/rombios/32bitgateway.c Fri Jan 26 16:30:48 2007 +0000
+++ b/tools/firmware/rombios/32bitgateway.c Fri Jan 26 16:38:32 2007 +0000
@@ -484,3 +484,5 @@ test_gateway()
printf("working correctly\n");
}
}
+
+#include "tcgbios.c"
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/32bitprotos.h
--- a/tools/firmware/rombios/32bitprotos.h Fri Jan 26 16:30:48 2007 +0000
+++ b/tools/firmware/rombios/32bitprotos.h Fri Jan 26 16:38:32 2007 +0000
@@ -1,11 +1,29 @@
#ifndef PROTOS_HIGHBIOS
#define PROTOS_HIGHBIOS

+
+/* shared include file for bcc and gcc */
+
/* bcc does not like 'enum' */
-#define IDX_MULTIPLY 0
-#define IDX_ADD 1
-#define IDX_SET_STATIC 2
-#define IDX_LAST 3 /* keep last! */
+#define IDX_MULTIPLY 0
+#define IDX_ADD 1
+#define IDX_SET_STATIC 2
+
+#define IDX_TCGINTERRUPTHANDLER 3
+#define IDX_TCPA_ACPI_INIT 4
+#define IDX_TCPA_EXTEND_ACPI_LOG 5
+#define IDX_TCPA_CALLING_INT19H 6
+#define IDX_TCPA_RETURNED_INT19H 7
+#define IDX_TCPA_ADD_EVENT_SEPARATORS 8
+#define IDX_TCPA_WAKE_EVENT 9
+#define IDX_TCPA_ADD_BOOTDEVICE 10
+#define IDX_TCPA_START_OPTION_ROM_SCAN 11
+#define IDX_TCPA_OPTION_ROM 12
+#define IDX_TCPA_IPL 13
+#define IDX_TCPA_INITIALIZE_TPM 14
+#define IDX_TCPA_MEASURE_POST 15
+
+#define IDX_LAST 16 /* keep last! */


#ifdef GCC_PROTOS
@@ -19,4 +37,19 @@ Bit32u add( PARMS(Bit32u a, Bit32u b) );
Bit32u add( PARMS(Bit32u a, Bit32u b) );
Bit32u set_static( PARMS(Bit32u) );

+Bit32u TCGInterruptHandler( PARMS(pushad_regs_t *regs, Bit32u esds, Bit32u flags_ptr));
+
+void tcpa_acpi_init( PARMS(void) );
+Bit32u tcpa_extend_acpi_log( PARMS(Bit32u entry_ptr) );
+void tcpa_calling_int19h( PARMS(void) );
+void tcpa_returned_int19h( PARMS(void) );
+void tcpa_add_event_separators( PARMS(void) );
+void tcpa_wake_event( PARMS(void) );
+void tcpa_add_bootdevice( PARMS(Bit32u bootcd, Bit32u bootdrv) );
+void tcpa_start_option_rom_scan( PARMS(void) );
+void tcpa_option_rom( PARMS(Bit32u seg) );
+void tcpa_ipl( PARMS(Bit32u seg) );
+void tcpa_measure_post( PARMS(Bit32u from, Bit32u to) );
+Bit32u tcpa_initialize_tpm( PARMS(Bit32u physpres) );
+
#endif
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/Makefile
--- a/tools/firmware/rombios/Makefile Fri Jan 26 16:30:48 2007 +0000
+++ b/tools/firmware/rombios/Makefile Fri Jan 26 16:38:32 2007 +0000
@@ -12,7 +12,7 @@ clean:
rm -f rombios*.txt rombios*.sym usage biossums
rm -f BIOS-bochs-*

-BIOS-bochs-latest: rombios.c biossums 32bitgateway.c
+BIOS-bochs-latest: rombios.c biossums 32bitgateway.c tcgbios.c
gcc -DBX_SMP_PROCESSORS=1 -E -P $< > _rombios_.c
bcc -o rombios.s -C-c -D__i86__ -0 -S _rombios_.c
sed -e 's/^\.text//' -e 's/^\.data//' rombios.s > _rombios_.s
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/rombios.c
--- a/tools/firmware/rombios/rombios.c Fri Jan 26 16:30:48 2007 +0000
+++ b/tools/firmware/rombios/rombios.c Fri Jan 26 16:38:32 2007 +0000
@@ -153,6 +153,8 @@

#define BX_USE_ATADRV 1
#define BX_ELTORITO_BOOT 1
+
+#define BX_TCGBIOS 0 /* main switch for TCG BIOS ext. */

#define BX_MAX_ATA_INTERFACES 4
#define BX_MAX_ATA_DEVICES (BX_MAX_ATA_INTERFACES*2)
@@ -1854,6 +1856,9 @@ print_bios_banner()
{
printf(BX_APPNAME" BIOS, %d cpu%s, ", BX_SMP_PROCESSORS, BX_SMP_PROCESSORS>1?"s":"");
printf("%s %s\n", bios_cvs_version_string, bios_date_string);
+#if BX_TCGBIOS
+ printf("TCG-enabled BIOS.\n");
+#endif
printf("\n");
test_gateway();
}
@@ -5717,6 +5722,10 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX,
BX_INFO("int13_cdemu: function %02x, emulation not active for DL= %02x\n", GET_AH(), GET_DL());
goto int13_fail;
}
+
+#if BX_TCGBIOS
+ tcpa_ipl((Bit32u)bootseg); /* specs: 8.2.3 steps 4 and 5 */
+#endif

switch (GET_AH()) {

@@ -9504,6 +9513,9 @@ rom_scan:
;; 2 ROM length in 512-byte blocks
;; 3 ROM initialization entry point (FAR CALL)

+#if BX_TCGBIOS
+ call _tcpa_start_option_rom_scan /* specs: 3.2.3.3 + 10.4.3 */
+#endif
mov cx, #0xc000
rom_scan_loop:
mov ds, cx
@@ -9522,6 +9534,20 @@ rom_scan_loop:
add al, #0x04
block_count_rounded:

+#if BX_TCGBIOS
+ push ax
+ push ds
+ push ecx
+ xor ax, ax
+ mov ds, ax
+ and ecx, #0xffff
+ push ecx ;; segment where option rom is located at
+ call _tcpa_option_rom /* specs: 3.2.3.3 */
+ add sp, #4 ;; pop segment
+ pop ecx ;; original ecx
+ pop ds
+ pop ax
+#endif
xor bx, bx ;; Restore DS back to 0000:
mov ds, bx
push ax ;; Save AX
@@ -9827,6 +9853,16 @@ post_default_ints:
in al, 0x71
mov 0x0410, ax

+#if BX_TCGBIOS
+ call _tcpa_acpi_init
+
+ push dword #0
+ call _tcpa_initialize_tpm
+ add sp, #4
+
+ call _tcpa_do_measure_POSTs
+ call _tcpa_wake_event /* specs: 3.2.3.7 */
+#endif

;; Parallel setup
SET_INT_VECTOR(0x0F, #0xF000, #dummy_iret_handler)
@@ -9949,9 +9985,16 @@ post_default_ints:
;;
#endif // BX_ELTORITO_BOOT

+#if BX_TCGBIOS
+ call _tcpa_calling_int19h /* specs: 8.2.3 step 1 */
+ call _tcpa_add_event_separators /* specs: 8.2.3 step 2 */
+#endif
int #0x19
//JMP_EP(0x0064) ; INT 19h location

+#if BX_TCGBIOS
+ call _tcpa_returned_int19h /* specs: 8.2.3 step 3/7 */
+#endif

.org 0xe2c3 ; NMI Handler Entry Point
nmi:
@@ -10434,6 +10477,21 @@ db 0x00 ;; base 23:16
;----------
.org 0xfe6e ; INT 1Ah Time-of-day Service Entry Point
int1a_handler:
+#if BX_TCGBIOS
+ cmp ah, #0xbb
+ jne no_tcg
+ pushf
+ push ds
+ push es
+ pushad
+ call _int1a_function32
+ popad
+ pop es
+ pop ds
+ popf
+ iret
+no_tcg:
+#endif
#if BX_PCIBIOS
cmp ah, #0xb1
jne int1a_normal
diff -r 480436ef6255 -r c07326324f8d tools/firmware/rombios/tcgbios.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/firmware/rombios/tcgbios.c Fri Jan 26 16:38:32 2007 +0000
@@ -0,0 +1,263 @@
+/*
+ * Implementation of stub functions for calls to the TCG BIOS
+ * extension in 32bit memory area.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Copyright (C) IBM Corporation, 2006
+ *
+ * Author: Stefan Berger <stefanb@us.ibm.com>
+ */
+
+/*******************************************************************
+ Support for TCPA ACPI logging
+ ******************************************************************/
+
+/*
+ * Extend the ACPI log with the given entry by copying the
+ * entry data into the log.
+ * Input
+ * Pointer to the structure to be copied into the log
+ *
+ * Output:
+ * lower 16 bits of return code contain entry number
+ * if entry number is '0', then upper 16 bits contain error code.
+ */
+Bit32u tcpa_extend_acpi_log(entry_ptr)
+ Bit32u entry_ptr;
+{
+ ASM_START
+ DoUpcall IDX_TCPA_EXTEND_ACPI_LOG
+ ASM_END
+}
+
+
+/*
+ initialize the TCPA ACPI subsystem; find the ACPI tables and determine
+ where the TCPA table is.
+ */
+ void
+tcpa_acpi_init()
+{
+ ASM_START
+ DoUpcall IDX_TCPA_ACPI_INIT
+ ASM_END
+}
+
+
+/*
+ * Add measurement to log about call of int 19h
+ */
+ void
+tcpa_calling_int19h()
+{
+ ASM_START
+ DoUpcall IDX_TCPA_CALLING_INT19H
+ ASM_END
+}
+
+/*
+ * Add measurement to log about retuning from int 19h
+ */
+ void
+tcpa_returned_int19h()
+{
+ ASM_START
+ DoUpcall IDX_TCPA_RETURNED_INT19H
+ ASM_END
+}
+
+/*
+ * Add event separators for PCRs 0 to 7; specs 8.2.3
+ */
+ void
+tcpa_add_event_separators()
+{
+ ASM_START
+ DoUpcall IDX_TCPA_ADD_EVENT_SEPARATORS
+ ASM_END
+}
+
+
+/*
+ * Add a wake event to the log
+ */
+ void
+tcpa_wake_event()
+{
+ ASM_START
+ DoUpcall IDX_TCPA_WAKE_EVENT
+ ASM_END
+}
+
+
+/*
+ * Add measurement to the log about option rom scan
+ * 10.4.3 : action 14
+ */
+ void
+tcpa_start_option_rom_scan()
+{
+ ASM_START
+ DoUpcall IDX_TCPA_START_OPTION_ROM_SCAN
+ ASM_END
+}
+
+
+/*
+ * Add measurement to the log about an option rom
+ */
+ void
+tcpa_option_rom(seg)
+ Bit32u seg;
+{
+ ASM_START
+ DoUpcall IDX_TCPA_OPTION_ROM
+ ASM_END
+}
+
+/*
+ * Add a measurement regarding the boot device (CDRom, Floppy, HDD) to
+ * the list of measurements.
+ */
+void
+ tcpa_add_bootdevice(bootcd, bootdrv)
+ Bit32u bootcd;
+ Bit32u bootdrv;
+{
+ ASM_START
+ DoUpcall IDX_TCPA_ADD_BOOTDEVICE
+ ASM_END
+}
+
+/*
+ * Add a measurement to the log in support of 8.2.5.3
+ * Creates two log entries
+ *
+ * Input parameter:
+ * seg : segment where the IPL data are located
+ */
+ void
+tcpa_ipl(seg)
+ Bit32u seg;
+{
+ ASM_START
+ DoUpcall IDX_TCPA_IPL
+ ASM_END
+}
+
+
+Bit32u
+tcpa_initialize_tpm(physpres)
+ Bit32u physpres;
+{
+ ASM_START
+ DoUpcall IDX_TCPA_INITIALIZE_TPM
+ ASM_END
+}
+
+void
+tcpa_measure_post(from, to)
+ Bit32u from;
+ Bit32u to;
+{
+ ASM_START
+ DoUpcall IDX_TCPA_MEASURE_POST
+ ASM_END
+}
+
+ASM_START
+MACRO POST_MEASURE
+ push word #0x000f
+ push #?2
+ push word #0x000f
+ push #?1
+ call _tcpa_measure_post
+ add sp, #8
+MEND
+ASM_END
+
+void
+tcpa_do_measure_POSTs()
+{
+ ASM_START
+
+ POST_MEASURE post, nmi
+ POST_MEASURE floppy_drive_post, hard_drive_post
+ POST_MEASURE hard_drive_post, ebda_post
+ POST_MEASURE ebda_post, eoi_jmp_post
+ POST_MEASURE eoi_jmp_post, timer_tick_post
+ POST_MEASURE timer_tick_post, int76_handler
+
+ ret
+ ASM_END
+}
+
+Bit32u
+TCGInterruptHandler(regs_ptr, es, ds, flags_ptr)
+ Bit32u regs_ptr;
+ Bit16u es;
+ Bit16u ds;
+ Bit32u flags_ptr;
+{
+ ASM_START
+ DoUpcall IDX_TCGINTERRUPTHANDLER
+ ASM_END
+}
+
+/*
+ * C-dispatcher for the TCG BIOS functions
+ */
+#define TCG_MAGIC 0x41504354L
+ void
+int1a_function32(regs, ES, DS, FLAGS)
+ pushad_regs_t regs;
+ Bit16u ES, DS, FLAGS;
+{
+ Bit16u rc;
+
+ switch (regs.u.r8.ah) {
+ case 0xbb:
+ /*
+ * all functions except for TCG_StatusCheck need to have the
+ * TCG_MAGIC in 'ebx'.
+ */
+ if (regs.u.r8.al != 0 &&
+ regs.u.r32.ebx != TCG_MAGIC) {
+ SET_CF();
+ return;
+ }
+ switch(regs.u.r8.al) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ TCGInterruptHandler(((Bit32u)get_SS() << 4) + (Bit32u)&regs,
+ ES, DS,
+ ((Bit32u)get_SS() << 4) + (Bit32u)&FLAGS);
+ break;
+
+ default:
+ SET_CF();
+ }
+ default:
+ SET_CF();
+ break;
+ }
+}

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog