direct-io.hg

changeset 13643:c07326324f8d

[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>
author kaf24@localhost.localdomain
date Fri Jan 26 16:38:32 2007 +0000 (2007-01-26)
parents 480436ef6255
children edbff1762a55
files tools/firmware/rombios/32bit/32bitbios.c tools/firmware/rombios/32bit/Makefile tools/firmware/rombios/32bit/tcgbios/Makefile tools/firmware/rombios/32bit/tcgbios/tcgbios.c tools/firmware/rombios/32bit/tcgbios/tcgbios.h tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c tools/firmware/rombios/32bit/tcgbios/tpm_drivers.h tools/firmware/rombios/32bit/util.c tools/firmware/rombios/32bit/util.h tools/firmware/rombios/32bitgateway.c tools/firmware/rombios/32bitprotos.h tools/firmware/rombios/Makefile tools/firmware/rombios/rombios.c tools/firmware/rombios/tcgbios.c
line diff
     1.1 --- a/tools/firmware/rombios/32bit/32bitbios.c	Fri Jan 26 16:30:48 2007 +0000
     1.2 +++ b/tools/firmware/rombios/32bit/32bitbios.c	Fri Jan 26 16:38:32 2007 +0000
     1.3 @@ -55,6 +55,22 @@ uint32_t jumptable[IDX_LAST+1] __attribu
     1.4  	TABLE_ENTRY(IDX_ADD        , add),
     1.5  	TABLE_ENTRY(IDX_SET_STATIC , set_static),
     1.6  
     1.7 +	TABLE_ENTRY(IDX_TCPA_ACPI_INIT, tcpa_acpi_init),
     1.8 +	TABLE_ENTRY(IDX_TCPA_EXTEND_ACPI_LOG, tcpa_extend_acpi_log),
     1.9 +
    1.10 +	TABLE_ENTRY(IDX_TCGINTERRUPTHANDLER, TCGInterruptHandler),
    1.11 +
    1.12 +	TABLE_ENTRY(IDX_TCPA_CALLING_INT19H, tcpa_calling_int19h),
    1.13 +	TABLE_ENTRY(IDX_TCPA_RETURNED_INT19H, tcpa_returned_int19h),
    1.14 +	TABLE_ENTRY(IDX_TCPA_ADD_EVENT_SEPARATORS, tcpa_add_event_separators),
    1.15 +	TABLE_ENTRY(IDX_TCPA_WAKE_EVENT, tcpa_wake_event),
    1.16 +	TABLE_ENTRY(IDX_TCPA_ADD_BOOTDEVICE, tcpa_add_bootdevice),
    1.17 +	TABLE_ENTRY(IDX_TCPA_START_OPTION_ROM_SCAN, tcpa_start_option_rom_scan),
    1.18 +	TABLE_ENTRY(IDX_TCPA_OPTION_ROM, tcpa_option_rom),
    1.19 +	TABLE_ENTRY(IDX_TCPA_IPL, tcpa_ipl),
    1.20 +	TABLE_ENTRY(IDX_TCPA_MEASURE_POST, tcpa_measure_post),
    1.21 +
    1.22 +	TABLE_ENTRY(IDX_TCPA_INITIALIZE_TPM, tcpa_initialize_tpm),
    1.23  
    1.24  	TABLE_ENTRY(IDX_LAST       , 0)     /* keep last */
    1.25  };
     2.1 --- a/tools/firmware/rombios/32bit/Makefile	Fri Jan 26 16:30:48 2007 +0000
     2.2 +++ b/tools/firmware/rombios/32bit/Makefile	Fri Jan 26 16:38:32 2007 +0000
     2.3 @@ -4,21 +4,34 @@ XEN_ROOT = ../../../..
     2.4  CFLAGS :=
     2.5  include $(XEN_ROOT)/tools/Rules.mk
     2.6  
     2.7 +SOURCES = util.c
     2.8  TARGET = 32bitbios_flat.h
     2.9  
    2.10 -CFLAGS += -fno-builtin -O2 -msoft-float
    2.11 +CFLAGS += -fno-builtin -O2 -msoft-float -nostdlib
    2.12  CFLAGS += -I../
    2.13  
    2.14 -MODULES = 32bitbios.o
    2.15 +SUBDIRS = tcgbios
    2.16  
    2.17 -.PHONY: all
    2.18 +MODULES := 32bitbios.o
    2.19 +MODULES += tcgbios/tcgbiosext.o
    2.20 +MODULES += util.o
    2.21 +
    2.22 +.PHONY: all subdirs
    2.23  
    2.24 -all : $(TARGET)
    2.25 +subdirs:
    2.26 +	@for subdir in $(SUBDIRS); do \
    2.27 +		$(MAKE) -C $$subdir all; \
    2.28 +	done;
    2.29 +
    2.30 +all: subdirs $(TARGET)
    2.31  
    2.32 -clean ::
    2.33 +clean::
    2.34  	rm -rf *.o $(TARGET)
    2.35 +	@for subdir in $(SUBDIRS); do \
    2.36 +		$(MAKE) -C $$subdir $@; \
    2.37 +	done;
    2.38  
    2.39 -$(TARGET) : 32bitbios_all.o $(SOURCES)
    2.40 +$(TARGET): 32bitbios_all.o $(SOURCES)
    2.41  	unref=`nm -u 32bitbios_all.o`
    2.42  	@if [ "$$unref" != "" ]; then \
    2.43  		echo "There are unresolved symbols in the BIOS.";	\
    2.44 @@ -27,5 +40,5 @@ clean ::
    2.45  		bash mkhex highbios_array 32bitbios_all.o > $(TARGET); \
    2.46  	fi
    2.47  
    2.48 -32bitbios_all.o : 32bitbios.o $(MODULES)
    2.49 +32bitbios_all.o: $(MODULES)
    2.50  	ld $(LDFLAGS_DIRECT) -r $(MODULES) -o 32bitbios_all.o
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/firmware/rombios/32bit/tcgbios/Makefile	Fri Jan 26 16:38:32 2007 +0000
     3.3 @@ -0,0 +1,20 @@
     3.4 +
     3.5 +override XEN_TARGET_ARCH = x86_32
     3.6 +XEN_ROOT = ../../../../..
     3.7 +CFLAGS :=
     3.8 +include $(XEN_ROOT)/tools/Rules.mk
     3.9 +
    3.10 +TARGET  = tcgbiosext.o
    3.11 +FILES   = tcgbios tpm_drivers
    3.12 +OBJECTS = $(foreach f,$(FILES),$(f).o)
    3.13 +
    3.14 +CFLAGS += -fno-builtin -O2 -msoft-float -nostdlib
    3.15 +CFLAGS += -I../ -I../../
    3.16 +
    3.17 +all: $(TARGET)
    3.18 +
    3.19 +clean::
    3.20 +	rm -rf *.o $(TARGET)
    3.21 +
    3.22 +$(TARGET): $(OBJECTS)
    3.23 +	ld $(LDFLAGS_DIRECT) -r $^ -o $@
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c	Fri Jan 26 16:38:32 2007 +0000
     4.3 @@ -0,0 +1,1526 @@
     4.4 +/*
     4.5 + *  Implementation of the TCG BIOS extension according to the specification
     4.6 + *  described in
     4.7 + *  https://www.trustedcomputinggroup.org/specs/PCClient/TCG_PCClientImplementationforBIOS_1-20_1-00.pdf
     4.8 + *
     4.9 + *  This library is free software; you can redistribute it and/or
    4.10 + *  modify it under the terms of the GNU Lesser General Public
    4.11 + *  License as published by the Free Software Foundation; either
    4.12 + *  version 2 of the License, or (at your option) any later version.
    4.13 + *
    4.14 + *  This library is distributed in the hope that it will be useful,
    4.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    4.17 + *  Lesser General Public License for more details.
    4.18 + *
    4.19 + *  You should have received a copy of the GNU Lesser General Public
    4.20 + *  License along with this library; if not, write to the Free Software
    4.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    4.22 + *
    4.23 + * Copyright (C) IBM Corporation, 2006
    4.24 + *
    4.25 + * Author: Stefan Berger <stefanb@us.ibm.com>
    4.26 + */
    4.27 +#include "rombios_compat.h"
    4.28 +#include "tpm_drivers.h"
    4.29 +
    4.30 +#include "tcgbios.h"
    4.31 +#include "32bitprotos.h"
    4.32 +#include "util.h"
    4.33 +
    4.34 +
    4.35 +/* local structure and variables */
    4.36 +struct ptti_cust {
    4.37 +	uint16_t    ipblength;
    4.38 +	uint16_t    reserved;
    4.39 +	uint16_t    opblength;
    4.40 +	uint16_t    reserved2;
    4.41 +	uint8_t     tpmoperandin[18];
    4.42 +} __attribute__((packed));
    4.43 +
    4.44 +struct ptti_cust CMD_TPM_Startup_0x01_IPB = {
    4.45 +    0x8+0xc, 0x00, 4+10, 0x00,
    4.46 +    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x99, 0x00, 0x01 },
    4.47 +};
    4.48 +
    4.49 +struct ptti_cust CMD_TSC_PhysicalPresence_0x20_IPB = {
    4.50 +    0x8+0xc, 0x00, 4+10, 0x00,
    4.51 +    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x20 },
    4.52 +};
    4.53 +
    4.54 +struct ptti_cust CMD_TSC_PhysicalPresence_0x08_IPB = {
    4.55 +    0x8+0xc, 0x00, 4+10, 0x00,
    4.56 +    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x08 },
    4.57 +};
    4.58 +
    4.59 +struct ptti_cust CMD_TSC_PhysicalPresence_0x100_IPB = {
    4.60 +    0x8+0xc, 0x00, 4+10, 0x00,
    4.61 +    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x01, 0x00 },
    4.62 +};
    4.63 +
    4.64 +struct ptti_cust CMD_TSC_PhysicalPresence_0x10_IPB = {
    4.65 +    0x8+0xc, 0x00, 4+10, 0x00,
    4.66 +    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x10 },
    4.67 +};
    4.68 +
    4.69 +struct ptti_cust CMD_TPM_PhysicalEnable_IPB = {
    4.70 +    0x8+0xa, 0x00, 4+10, 0x00,
    4.71 +    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x6f },
    4.72 +};
    4.73 +
    4.74 +struct ptti_cust CMD_TPM_PhysicalSetDeactivated_0x00_IPB = {
    4.75 +    0x8+0xb, 0x00, 4+10, 0x00,
    4.76 +    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x72, 0x00 }
    4.77 +};
    4.78 +struct ptti_cust CMD_TPM_SHA1Start_IPB = {
    4.79 +    0x8+0xa, 0x00, 4+10, 0x00,
    4.80 +    { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa0 },
    4.81 +};
    4.82 +
    4.83 +struct ptti_cust CMD_TPM_GetCap_Version_IPB = {
    4.84 +    0x8+0x12, 0x00, 4+18, 0x00,
    4.85 +    {0x00, 0xc1, 0x00, 0x00, 0x00, 0x12,
    4.86 +     0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00 },
    4.87 +};
    4.88 +
    4.89 +struct ptti_cust *TCG_CommandList[] = {
    4.90 +	&CMD_TPM_Startup_0x01_IPB,
    4.91 +	&CMD_TSC_PhysicalPresence_0x20_IPB,
    4.92 +	&CMD_TSC_PhysicalPresence_0x08_IPB,
    4.93 +	&CMD_TSC_PhysicalPresence_0x100_IPB,
    4.94 +	&CMD_TSC_PhysicalPresence_0x10_IPB,
    4.95 +	&CMD_TPM_PhysicalEnable_IPB,
    4.96 +	&CMD_TPM_PhysicalSetDeactivated_0x00_IPB,
    4.97 +	&CMD_TPM_SHA1Start_IPB,
    4.98 +};
    4.99 +
   4.100 +/* local function prototypes */
   4.101 +static void sha1(const unsigned char *data, uint32_t length, unsigned char *hash);
   4.102 +static uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx);
   4.103 +static uint32_t HashAll32(struct hai *hai, unsigned char *hash,
   4.104 +                          uint32_t magic, uint32_t ecx, uint32_t edx);
   4.105 +static uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s,
   4.106 +                                     struct hleeo *hleeo,
   4.107 +                                     uint32_t magic, uint32_t ecx, uint32_t edx);
   4.108 +static uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo,
   4.109 +                               uint32_t ebx, uint32_t ecx, uint32_t edx);
   4.110 +static uint32_t PassThroughToTPM32(struct pttti *pttti, struct pttto *pttto,
   4.111 +                                   uint32_t magic, uint32_t ecx, uint32_t edx);
   4.112 +static uint32_t MA_Transmit(unsigned char *cmdbuffer,
   4.113 +                            unsigned char *respbuffer,
   4.114 +                            uint32_t respbufferlen);
   4.115 +
   4.116 +static unsigned char *tcpa_get_lasa_last_ptr(void);
   4.117 +static unsigned char *tcpa_get_lasa_base_ptr(void);
   4.118 +static void tcpa_reset_acpi_log(void);
   4.119 +static uint32_t tcpa_get_laml(void);
   4.120 +
   4.121 +
   4.122 +extern struct tpm_driver tpm_drivers[];
   4.123 +
   4.124 +/* utility functions */
   4.125 +
   4.126 +static inline uint32_t bswap(uint32_t a)
   4.127 +{
   4.128 +	return ( ( a >> 24 ) & 0x000000ff) |
   4.129 +	       ( ( a >> 8  ) & 0x0000ff00) |
   4.130 +	       ( ( a << 8  ) & 0x00ff0000) |
   4.131 +	       ( ( a << 24 ) & 0xff000000);
   4.132 +}
   4.133 +
   4.134 +/********************************************************
   4.135 +  Extensions for TCG-enabled BIOS
   4.136 + *******************************************************/
   4.137 +
   4.138 +typedef struct {
   4.139 +	struct acpi_20_tcpa *tcpa_ptr;
   4.140 +	unsigned char       *lasa_last_ptr;
   4.141 +	uint16_t            entry_count;
   4.142 +	uint16_t            flags;
   4.143 +} tcpa_acpi_t;
   4.144 +
   4.145 +static tcpa_acpi_t tcpa_acpi;
   4.146 +
   4.147 +
   4.148 +/* low level driver implementation */
   4.149 +static int tpm_driver_to_use = TPM_INVALID_DRIVER;
   4.150 +
   4.151 +static
   4.152 +uint32_t MA_IsTPMPresent()
   4.153 +{
   4.154 +	uint32_t rc = 0;
   4.155 +	unsigned int i;
   4.156 +	for (i = 0; i < TPM_NUM_DRIVERS; i++) {
   4.157 +		struct tpm_driver *td = &tpm_drivers[i];
   4.158 +		if (td->probe(td->baseaddr) != 0) {
   4.159 +			tpm_driver_to_use = i;
   4.160 +			rc = 1;
   4.161 +			break;
   4.162 +		}
   4.163 +	}
   4.164 +	return rc;
   4.165 +}
   4.166 +
   4.167 +static
   4.168 +uint32_t MA_InitTPM(uint16_t startupcode)
   4.169 +{
   4.170 +	uint32_t rc = 0;
   4.171 +	/* low-level initialize the TPM */
   4.172 +	unsigned char command[sizeof(CMD_TPM_Startup_0x01_IPB.tpmoperandin)];
   4.173 +	unsigned char response[10];
   4.174 +	uint32_t response_size = sizeof(response);
   4.175 +
   4.176 +	memcpy(command,
   4.177 +	       CMD_TPM_Startup_0x01_IPB.tpmoperandin,
   4.178 +	       sizeof(CMD_TPM_Startup_0x01_IPB.tpmoperandin));
   4.179 +	command[10] = (startupcode >> 8) & 0xff;
   4.180 +	command[11] = (startupcode >> 0) & 0xff;
   4.181 +	rc = MA_Transmit(command, response, response_size);
   4.182 +
   4.183 +	return rc;
   4.184 +}
   4.185 +
   4.186 +static
   4.187 +uint32_t MA_Transmit(unsigned char *cmdbuffer,
   4.188 +                     unsigned char *respbuffer,
   4.189 +                     uint32_t respbufferlen)
   4.190 +{
   4.191 +	uint32_t rc = 0;
   4.192 +	uint32_t irc;
   4.193 +	struct tpm_driver *td;
   4.194 +
   4.195 +	if (tpm_driver_to_use == TPM_INVALID_DRIVER)
   4.196 +		return TCG_FATAL_COM_ERROR;
   4.197 +
   4.198 +	td = &tpm_drivers[tpm_driver_to_use];
   4.199 +
   4.200 +	if (rc == 0) {
   4.201 +		irc = td->activate(td->baseaddr);
   4.202 +		if (irc == 0) {
   4.203 +			/* tpm could not be activated */
   4.204 +			rc = TCG_FATAL_COM_ERROR;
   4.205 +		}
   4.206 +	}
   4.207 +
   4.208 +	if (rc == 0) {
   4.209 +		uint32_t *tmp = (uint32_t *)&cmdbuffer[2];
   4.210 +		uint32_t len = bswap(*tmp);
   4.211 +		irc = td->senddata(td->baseaddr,
   4.212 +		                   cmdbuffer,
   4.213 +		                   len);
   4.214 +		if (irc != 0) {
   4.215 +			rc = TCG_FATAL_COM_ERROR;
   4.216 +		}
   4.217 +	}
   4.218 +
   4.219 +	if (rc == 0) {
   4.220 +		irc = td->waitdatavalid(td->baseaddr);
   4.221 +		if (irc != 0) {
   4.222 +			rc = TCG_FATAL_COM_ERROR;
   4.223 +		}
   4.224 +	}
   4.225 +
   4.226 +	if (rc == 0) {
   4.227 +		irc = td->waitrespready(td->baseaddr, 2000);
   4.228 +		if (irc != 0) {
   4.229 +			rc = TCG_FATAL_COM_ERROR;
   4.230 +		}
   4.231 +	}
   4.232 +
   4.233 +	if (rc == 0) {
   4.234 +		irc = td->readresp(td->baseaddr,
   4.235 +		                   respbuffer,
   4.236 +		                   respbufferlen);
   4.237 +		if (irc != 0) {
   4.238 +			rc = TCG_FATAL_COM_ERROR;
   4.239 +		}
   4.240 +	}
   4.241 +
   4.242 +	if (rc == 0) {
   4.243 +		irc = td->ready(td->baseaddr);
   4.244 +	}
   4.245 +
   4.246 +	return rc;
   4.247 +}
   4.248 +
   4.249 +
   4.250 +static
   4.251 +uint8_t acpi_validate_entry(struct acpi_header *hdr)
   4.252 +{
   4.253 +	uint8_t sum = 0;
   4.254 +	unsigned int length = hdr->length;
   4.255 +	unsigned int ctr;
   4.256 +	unsigned char *addr = (unsigned char *)hdr;
   4.257 +
   4.258 +	for (ctr = 0; ctr < length; ctr++)
   4.259 +		sum += addr[ctr];
   4.260 +
   4.261 +	return sum;
   4.262 +}
   4.263 +
   4.264 +
   4.265 +void tcpa_acpi_init(void)
   4.266 +{
   4.267 +	struct acpi_20_rsdt *rsdt;
   4.268 +	uint32_t length;
   4.269 +	struct acpi_20_tcpa *tcpa;
   4.270 +	uint16_t found = 0;
   4.271 +	uint16_t rsdp_off;
   4.272 +	uint16_t off;
   4.273 +	struct acpi_20_rsdp *rsdp;
   4.274 +
   4.275 +	if (MA_IsTPMPresent() == 0) {
   4.276 +		return;
   4.277 +	}
   4.278 +
   4.279 +	/* scan memory in steps of  16 bytes in the ACPI_SEGMENT segment */
   4.280 +	found = 0;
   4.281 +	for (rsdp_off = 0; rsdp_off < 0xfff0; rsdp_off += 0x10) {
   4.282 +		char *_rsdp = (char *)(ACPI_SEGMENT << 4);
   4.283 +		/* check for expected string */
   4.284 +		if (!strncmp( &_rsdp[rsdp_off], "RSD PTR ", 8)) {
   4.285 +			found = 1;
   4.286 +			rsdp = (struct acpi_20_rsdp *)&_rsdp[rsdp_off];
   4.287 +			break;
   4.288 +		}
   4.289 +	}
   4.290 +
   4.291 +	if (rsdp) {
   4.292 +		uint32_t ctr = 0;
   4.293 +		/* get RSDT from RSDP */
   4.294 +		rsdt   = (struct acpi_20_rsdt *)rsdp->rsdt_address;
   4.295 +		/* rsdt may be anywhere in 32bit space */
   4.296 +		length = rsdt->header.length;
   4.297 +		off = 36;
   4.298 +		while ((off + 3) < length) {
   4.299 +			/* try all pointers to structures */
   4.300 +			tcpa = (struct acpi_20_tcpa *)rsdt->entry[ctr];
   4.301 +			/* valid TCPA ACPI table ? */
   4.302 +			if (ACPI_2_0_TCPA_SIGNATURE == tcpa->header.signature &&
   4.303 +			    acpi_validate_entry(&tcpa->header) == 0) {
   4.304 +				found = 1;
   4.305 +				break;
   4.306 +			}
   4.307 +			off += 4;
   4.308 +			ctr++;
   4.309 +		}
   4.310 +	}
   4.311 +
   4.312 +	if (found == 0) {
   4.313 +		printf("TCPA ACPI was NOT found!\n");
   4.314 +		tcpa = 0;
   4.315 +	}
   4.316 +
   4.317 +	/* initialize the TCPA part of the EBDA with our data */
   4.318 +	tcpa_acpi.tcpa_ptr = tcpa;
   4.319 +	tcpa_acpi.lasa_last_ptr = 0;
   4.320 +	tcpa_acpi.entry_count = 0;
   4.321 +	tcpa_acpi.flags = 0;
   4.322 +	tcpa_reset_acpi_log();
   4.323 +}
   4.324 +
   4.325 +/* clear the ACPI log */
   4.326 +static void tcpa_reset_acpi_log(void)
   4.327 +{
   4.328 +	unsigned char *lasa = tcpa_get_lasa_base_ptr();
   4.329 +	if (lasa)
   4.330 +		memset(lasa, 0x0, tcpa_get_laml());
   4.331 +}
   4.332 +
   4.333 +
   4.334 +uint32_t tcpa_extend_acpi_log(uint32_t entry_ptr)
   4.335 +{
   4.336 +	uint32_t res = 0;
   4.337 +	unsigned char *lasa_last = tcpa_get_lasa_last_ptr();
   4.338 +	unsigned char *lasa_base = tcpa_get_lasa_base_ptr();
   4.339 +	uint32_t size;
   4.340 +	uint16_t entry_count = tcpa_acpi.entry_count;
   4.341 +	struct pcpes *pcpes = (struct pcpes *)entry_ptr;
   4.342 +
   4.343 +	if (lasa_last == 0) {
   4.344 +		lasa_last = lasa_base;
   4.345 +	} else {
   4.346 +		struct pcpes *pcpes = (struct pcpes *)lasa_last;
   4.347 +		/* skip the last entry in the log */
   4.348 +		size = pcpes->eventdatasize;
   4.349 +		size += 32;
   4.350 +		lasa_last += size;
   4.351 +	}
   4.352 +
   4.353 +	if (lasa_last == 0) {
   4.354 +		res = ((uint32_t)TCG_PC_LOGOVERFLOW << 16);
   4.355 +	}
   4.356 +
   4.357 +	if (res == 0) {
   4.358 +		uint32_t laml = tcpa_get_laml();
   4.359 +		size = pcpes->eventdatasize;
   4.360 +		size += 32;
   4.361 +		if ((lasa_last + size - lasa_base) > laml) {
   4.362 +			res = (TCG_PC_LOGOVERFLOW << 16);
   4.363 +		}
   4.364 +	}
   4.365 +
   4.366 +	if (res == 0) {
   4.367 +		/* copy the log entry into the ACPI log */
   4.368 +		memcpy((char *)lasa_last, (char *)entry_ptr, size);
   4.369 +		/*
   4.370 +		 * update the pointers and entry counter that were modified
   4.371 +		 * due to the new entry in the log
   4.372 +		 */
   4.373 +		tcpa_acpi.lasa_last_ptr = lasa_last;
   4.374 +		entry_count++;
   4.375 +		tcpa_acpi.entry_count = entry_count;
   4.376 +
   4.377 +		res = entry_count;
   4.378 +	}
   4.379 +	return res;
   4.380 +}
   4.381 +
   4.382 +static
   4.383 +unsigned char *tcpa_get_lasa_last_ptr(void)
   4.384 +{
   4.385 +	return tcpa_acpi.lasa_last_ptr;
   4.386 +}
   4.387 +
   4.388 +static
   4.389 +unsigned char *tcpa_get_lasa_base_ptr(void)
   4.390 +{
   4.391 +	unsigned char *lasa = 0;
   4.392 +	struct acpi_20_tcpa *tcpa = tcpa_acpi.tcpa_ptr;
   4.393 +	if (tcpa != 0) {
   4.394 +		uint32_t class = tcpa->platform_class;
   4.395 +		if (class == TCPA_ACPI_CLASS_CLIENT) {
   4.396 +			/* client type */
   4.397 +			lasa = (unsigned char *)(long)tcpa->u.client.lasa;
   4.398 +		} else if (class == TCPA_ACPI_CLASS_SERVER) {
   4.399 +			/* server type */
   4.400 +			lasa = (unsigned char *)(long)tcpa->u.server.lasa;
   4.401 +		}
   4.402 +	}
   4.403 +	return lasa;
   4.404 +}
   4.405 +
   4.406 +static
   4.407 +uint32_t tcpa_get_laml(void)
   4.408 +{
   4.409 +	uint32_t laml = 0;
   4.410 +	struct acpi_20_tcpa *tcpa = tcpa_acpi.tcpa_ptr;
   4.411 +	if (tcpa != 0) {
   4.412 +		uint32_t class = tcpa->platform_class;
   4.413 +		if (class == TCPA_ACPI_CLASS_CLIENT) {
   4.414 +			/* client type */
   4.415 +			laml = tcpa->u.client.laml;
   4.416 +		} else if (class == TCPA_ACPI_CLASS_SERVER) {
   4.417 +			laml = tcpa->u.server.laml;
   4.418 +		}
   4.419 +	}
   4.420 +	return laml;
   4.421 +}
   4.422 +
   4.423 +
   4.424 +
   4.425 +/*
   4.426 + * Add a measurement to the log; the data at data_seg:data/length are
   4.427 + * appended to the TCG_PCClientPCREventStruct
   4.428 + *
   4.429 + * Input parameters:
   4.430 + *  pcrIndex   : which PCR to extend
   4.431 + *  event_type : type of event; specs 10.4.1
   4.432 + *  event_id   : (unused)
   4.433 + *  data       : pointer to the data (i.e., string) to be added to the log
   4.434 + *  length     : length of the data
   4.435 + */
   4.436 +static uint16_t
   4.437 +tcpa_add_measurement_to_log(uint32_t pcrIndex,
   4.438 +                            uint32_t event_type,
   4.439 +                            uint32_t event_id,
   4.440 +                            const char *data_ptr,
   4.441 +                            uint32_t length)
   4.442 +{
   4.443 +	uint32_t rc = 0;
   4.444 +	struct hleei_short hleei;
   4.445 +	struct hleeo hleeo;
   4.446 +	uint8_t _pcpes[32+400];
   4.447 +	struct pcpes *pcpes = (struct pcpes *)_pcpes;
   4.448 +	uint8_t *data = (uint8_t *)data_ptr;
   4.449 +
   4.450 +	if (length < sizeof(_pcpes)-32) {
   4.451 +		memset(pcpes, 0x0, 32);
   4.452 +		pcpes->pcrindex   = pcrIndex;
   4.453 +		pcpes->eventtype = event_type;
   4.454 +		pcpes->eventdatasize = length;
   4.455 +		memcpy(&_pcpes[32], data, length);
   4.456 +
   4.457 +		hleei.ipblength = 0x18;
   4.458 +		hleei.reserved  = 0x0;
   4.459 +		hleei.hashdataptr = (uint32_t)&_pcpes[32];
   4.460 +		hleei.hashdatalen = length;
   4.461 +		hleei.pcrindex    = pcrIndex;
   4.462 +		hleei.logdataptr  = (uint32_t)_pcpes;
   4.463 +		hleei.logdatalen  = length + 32;
   4.464 +		rc = HashLogExtendEvent32(&hleei,
   4.465 +		                          &hleeo,
   4.466 +			                  TCG_MAGIC,
   4.467 +		                          0x0,
   4.468 +		                          0x0);
   4.469 +	} else {
   4.470 +		rc = (TCG_PC_TPMERROR |
   4.471 +		      ((uint32_t)TCG_GENERAL_ERROR << 16));
   4.472 +	}
   4.473 +
   4.474 +	return rc;
   4.475 +}
   4.476 +
   4.477 +static
   4.478 +uint16_t tcpa_add_pcpes_to_log(struct pcpes *pcpes)
   4.479 +{
   4.480 +	uint32_t rc = 0;
   4.481 +	struct hleei_short hleei;
   4.482 +	struct hleeo hleeo;
   4.483 +
   4.484 +	hleei.ipblength = 0x18;
   4.485 +	hleei.reserved  = 0x0;
   4.486 +	hleei.hashdataptr = 0;
   4.487 +	hleei.hashdatalen = 0;
   4.488 +	hleei.pcrindex    = pcpes->pcrindex;
   4.489 +	hleei.logdataptr  = (uint32_t)pcpes;
   4.490 +	hleei.logdatalen  = sizeof(pcpes);
   4.491 +
   4.492 +	rc = HashLogExtendEvent32(&hleei,
   4.493 +	                          &hleeo,
   4.494 +		                  TCG_MAGIC,
   4.495 +	                          0x0,
   4.496 +	                          0x0);
   4.497 +
   4.498 +	return rc;
   4.499 +}
   4.500 +
   4.501 +
   4.502 +/*
   4.503 + * Add a measurement to the log; further description of the data
   4.504 + * that are to be hashed are NOT appended to the TCG_PCClientPCREventStruc.
   4.505 + * Input parameters:
   4.506 + *  pcrIndex   : PCR to extend
   4.507 + *  event_type : type of event; specs 10.4.1
   4.508 + *  ptr        : 32 bit pointer to the data to be hashed
   4.509 + *  length     : length of the data to be hashed
   4.510 + *
   4.511 + * Returns lower 16 bit of return code of TCG_HashLogExtendEvent. '0' means
   4.512 + * success, otherwise an error is indicated.
   4.513 + */
   4.514 +static
   4.515 +uint16_t tcpa_add_measurement_to_log_simple(uint32_t pcrIndex,
   4.516 +                                            uint16_t event_type,
   4.517 +                                            uint8_t *ptr, uint32_t length)
   4.518 +{
   4.519 +	uint32_t rc = 0;
   4.520 +	struct hleei_short hleei;
   4.521 +	struct hleeo hleeo;
   4.522 +	struct pcpes pcpes;
   4.523 +
   4.524 +	memset(&pcpes, 0x0, sizeof(pcpes));
   4.525 +	pcpes.pcrindex = pcrIndex;
   4.526 +	pcpes.eventtype = event_type;
   4.527 +	pcpes.eventdatasize = length;
   4.528 +
   4.529 +	hleei.ipblength = 0x18;
   4.530 +	hleei.reserved  = 0x0;
   4.531 +	hleei.hashdataptr = (uint32_t)ptr;
   4.532 +	hleei.hashdatalen = length;
   4.533 +	hleei.pcrindex = pcrIndex;
   4.534 +	hleei.logdataptr = (uint32_t)&pcpes;
   4.535 +	hleei.logdatalen = 32;
   4.536 +
   4.537 +	rc = HashLogExtendEvent32(&hleei,
   4.538 +	                          &hleeo,
   4.539 +	                          TCG_MAGIC,
   4.540 +	                          0x0,
   4.541 +	                          0x0);
   4.542 +	return rc;
   4.543 +}
   4.544 +
   4.545 +/* table of event types according to 10.4.1 / table 11 */
   4.546 +static const char ev_action[][23] = {
   4.547 +  /*  0 */ "Calling INT 19h",
   4.548 +           "Returned INT 19h",
   4.549 +           "Returned via INT 18h",
   4.550 +           "",
   4.551 +           "",
   4.552 +  /*  5 */ "",
   4.553 +           "",
   4.554 +           "",
   4.555 +           "",
   4.556 +           "",
   4.557 +  /* 10 */ "",
   4.558 +           "",
   4.559 +           "",
   4.560 +           "",
   4.561 +           "Start Option ROM Scan"
   4.562 +};
   4.563 +
   4.564 +
   4.565 +static char evt_separator[] = "---------------";
   4.566 +static char wake_event_1[]    = "Wake Event 1";
   4.567 +
   4.568 +
   4.569 +/*
   4.570 + * Add a measurement to the list of measurements
   4.571 + * pcrIndex   : PCR to be extended
   4.572 + * event_type : type of event; specs 10.4.1
   4.573 + * data       : additional parameter; used as parameter for 10.4.3
   4.574 + *              'action index'
   4.575 + */
   4.576 +void tcpa_add_measurement(uint32_t pcrIndex,
   4.577 +                          uint16_t event_type,
   4.578 +                          uint32_t data)
   4.579 +{
   4.580 +	const char *string;
   4.581 +
   4.582 +	switch (event_type) {
   4.583 +	case EV_SEPARATOR:
   4.584 +		tcpa_add_measurement_to_log(pcrIndex,
   4.585 +		                            event_type,
   4.586 +		                            0,
   4.587 +		                            evt_separator,
   4.588 +		                            strlen(evt_separator));
   4.589 +	break;
   4.590 +	case EV_ACTION:
   4.591 +		string = ev_action[data /* event_id */];
   4.592 +		tcpa_add_measurement_to_log(pcrIndex,
   4.593 +		                            event_type,
   4.594 +		                            data,
   4.595 +		                            string,
   4.596 +		                            strlen(string));
   4.597 +
   4.598 +	break;
   4.599 +	}
   4.600 +}
   4.601 +
   4.602 +
   4.603 +/*
   4.604 + * Add measurement to log about call of int 19h
   4.605 + */
   4.606 +void tcpa_calling_int19h()
   4.607 +{
   4.608 +	tcpa_add_measurement(4, EV_ACTION, 0);
   4.609 +}
   4.610 +
   4.611 +/*
   4.612 + * Add measurement to log about retuning from int 19h
   4.613 + */
   4.614 +void tcpa_returned_int19h()
   4.615 +{
   4.616 +	tcpa_add_measurement(4, EV_ACTION, 1);
   4.617 +}
   4.618 +
   4.619 +/*
   4.620 + * Add event separators for PCRs 0 to 7; specs 8.2.3
   4.621 + */
   4.622 +void tcpa_add_event_separators()
   4.623 +{
   4.624 +	uint32_t pcrIndex = 0;
   4.625 +	while (pcrIndex <= 7) {
   4.626 +		tcpa_add_measurement(pcrIndex, EV_SEPARATOR, 0);
   4.627 +		pcrIndex ++;
   4.628 +	}
   4.629 +}
   4.630 +
   4.631 +
   4.632 +/*
   4.633 + * Add a wake event to the log
   4.634 + */
   4.635 +void tcpa_wake_event()
   4.636 +{
   4.637 +	tcpa_add_measurement_to_log(6,
   4.638 +	                            EV_ACTION,
   4.639 +	                            10,
   4.640 +	                            wake_event_1,
   4.641 +	                            strlen(wake_event_1));
   4.642 +}
   4.643 +
   4.644 +/*
   4.645 + * add the boot device to the measurement log
   4.646 + */
   4.647 +void tcpa_add_bootdevice(uint32_t bootcd, uint32_t bootdrv)
   4.648 +{
   4.649 +	char *string;
   4.650 +	if (bootcd == 0) {
   4.651 +		if (bootdrv == 0) {
   4.652 +			string = "Booting BCV device 00h (Floppy)";
   4.653 +		} else if (bootdrv == 0x80) {
   4.654 +			string = "Booting BCV device 80h (HDD)";
   4.655 +		} else {
   4.656 +			string = "Booting unknown device";
   4.657 +		}
   4.658 +	} else {
   4.659 +		string = "Booting from CD ROM device";
   4.660 +	}
   4.661 +	tcpa_add_measurement_to_log(4, 5, 0,
   4.662 +	                            string, strlen(string));
   4.663 +}
   4.664 +
   4.665 +/*
   4.666 + * Add measurement to the log about option rom scan
   4.667 + * 10.4.3 : action 14
   4.668 + */
   4.669 +void tcpa_start_option_rom_scan()
   4.670 +{
   4.671 +	tcpa_add_measurement(2, EV_ACTION, 14);
   4.672 +}
   4.673 +
   4.674 +
   4.675 +/*
   4.676 + * Add measurement to the log about an option rom
   4.677 + */
   4.678 +void tcpa_option_rom(uint32_t seg)
   4.679 +{
   4.680 +	uint32_t len = read_byte(seg, 2) << 9;
   4.681 +	uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,0);
   4.682 +	char append[32]; /* TCG_PCClientTaggedEventStruct and
   4.683 +	                     OptionROMExecuteStructure; specs 10.4.2.1 */
   4.684 +	struct hai hai;   /* HashAll Input Block; specs 12.10 */
   4.685 +
   4.686 +	memset(append, 0x0, sizeof(append));
   4.687 +
   4.688 +	append[0] = 7; /* Option ROM Execute */
   4.689 +	append[4] = 24;/* size of OptionROMExecute Structure */
   4.690 +	/* leave the rest to '0' */
   4.691 +
   4.692 +	/* 12.10 table 21 */
   4.693 +	hai.ipblength   = 0x10;
   4.694 +	hai.reserved    = 0;
   4.695 +	hai.hashdataptr = (uint32_t)addr;
   4.696 +	hai.hashdatalen = len;
   4.697 +	hai.algorithmid = TPM_ALG_SHA;
   4.698 +
   4.699 +	HashAll32(&hai,
   4.700 +	          (unsigned char *)append+12,
   4.701 +	          TCG_MAGIC,
   4.702 +	          0,
   4.703 +	          0);
   4.704 +
   4.705 +	tcpa_add_measurement_to_log(2,
   4.706 +	                            EV_EVENT_TAG,
   4.707 +	                            0,
   4.708 +	                            append,
   4.709 +	                            32);
   4.710 +}
   4.711 +
   4.712 +/*
   4.713 + * Add a measurement to the log in support of 8.2.5.3
   4.714 + * Creates two log entries
   4.715 + *
   4.716 + * Input parameter:
   4.717 + *  seg    : segment where the IPL data are located
   4.718 + */
   4.719 +void tcpa_ipl(Bit32u seg)
   4.720 +{
   4.721 +	/* specs: 8.2.5.3 */
   4.722 +	uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,0);
   4.723 +	/* equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum */
   4.724 +	tcpa_add_measurement_to_log_simple(4,
   4.725 +	                                   EV_IPL,
   4.726 +	                                   addr,
   4.727 +	                                   0x1b8);
   4.728 +	/* equivalent to: dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum */
   4.729 +	tcpa_add_measurement_to_log_simple(5,
   4.730 +	                                   EV_IPL_PARTITION_DATA,
   4.731 +	                                   addr + 0x1b8,
   4.732 +	                                   0x48);
   4.733 +}
   4.734 +
   4.735 +void tcpa_measure_post(Bit32u from, Bit32u to)
   4.736 +{
   4.737 +	struct pcpes pcpes; /* PCClientPCREventStruc */
   4.738 +	memset(&pcpes, 0x0, sizeof(pcpes));
   4.739 +	int len = to - from;
   4.740 +
   4.741 +	if (len > 0) {
   4.742 +		sha1((unsigned char *)from,
   4.743 +		     to-from,
   4.744 +		     (unsigned char *)&pcpes.digest);
   4.745 +
   4.746 +		pcpes.eventtype = EV_POST_CODE;
   4.747 +		pcpes.eventdatasize = 0;
   4.748 +		pcpes.pcrindex = 0;
   4.749 +		tcpa_add_pcpes_to_log(&pcpes);
   4.750 +	}
   4.751 +}
   4.752 +
   4.753 +static
   4.754 +uint32_t SendCommand32(uint32_t idx,
   4.755 +                     struct pttto *pttto,
   4.756 +                     uint32_t size_ptto)
   4.757 +{
   4.758 +	uint32_t rc = 0;
   4.759 +	struct pttti *pttti = (struct pttti *)TCG_CommandList[idx];
   4.760 +	uint8_t _pttto[30];
   4.761 +
   4.762 +	if (size_ptto > 0 && size_ptto < 14) {
   4.763 +		rc = (TCG_PC_TPMERROR |
   4.764 +		      ((uint32_t)TCG_INVALID_INPUT_PARA << 16));
   4.765 +	}
   4.766 +
   4.767 +	if (rc == 0) {
   4.768 +		if (size_ptto == 0) {
   4.769 +			pttto = (struct pttto *)_pttto;
   4.770 +			size_ptto = sizeof(_pttto);
   4.771 +		}
   4.772 +		pttti->opblength = size_ptto;
   4.773 +	}
   4.774 +
   4.775 +	if (rc == 0) {
   4.776 +		if (pttti->opblength > size_ptto) {
   4.777 +			rc = (TCG_PC_TPMERROR |
   4.778 +			      ((uint32_t)TCG_OUTPUT_BUFFER_TOO_SHORT << 16));
   4.779 +		}
   4.780 +	}
   4.781 +
   4.782 +	if (rc == 0) {
   4.783 +		rc = PassThroughToTPM32(pttti,
   4.784 +		                        pttto,
   4.785 +		                        TCG_MAGIC,
   4.786 +		                        0x0,
   4.787 +		                        0x0);
   4.788 +	}
   4.789 +
   4.790 +	return rc;
   4.791 +}
   4.792 +
   4.793 +
   4.794 +uint32_t tcpa_initialize_tpm(uint32_t physpres)
   4.795 +{
   4.796 +	uint32_t rc = 0;
   4.797 +	uint8_t _pttto[40];
   4.798 +	struct pttto *pttto = (struct pttto *)_pttto;
   4.799 +	uint32_t pttto_size = sizeof(_pttto);
   4.800 +
   4.801 +	if (rc == 0) {
   4.802 +		rc = SendCommand32(IDX_CMD_TPM_Startup_0x01, pttto, pttto_size);
   4.803 +	}
   4.804 +
   4.805 +	if (rc == 0 && physpres != 0) {
   4.806 +		rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x20,
   4.807 +		                   pttto, pttto_size);
   4.808 +	}
   4.809 +
   4.810 +	if (rc == 0 && physpres != 0) {
   4.811 +		rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x08,
   4.812 +		                   pttto, pttto_size);
   4.813 +	}
   4.814 +
   4.815 +	if (rc == 0 && physpres != 0) {
   4.816 +		rc = SendCommand32(IDX_CMD_TPM_PhysicalEnable,
   4.817 +		                   pttto, pttto_size);
   4.818 +	}
   4.819 +
   4.820 +	if (rc == 0 && physpres != 0) {
   4.821 +		rc = SendCommand32(IDX_CMD_TPM_PhysicalSetDeactivated_0x00,
   4.822 +		                   pttto, pttto_size);
   4.823 +	}
   4.824 +
   4.825 +	if (rc == 0) {
   4.826 +		rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x100,
   4.827 +		                   pttto, pttto_size);
   4.828 +	}
   4.829 +
   4.830 +	if (rc == 0) {
   4.831 +		rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x10,
   4.832 +		                   pttto, pttto_size);
   4.833 +	}
   4.834 +	return rc;
   4.835 +}
   4.836 +
   4.837 +
   4.838 +uint16_t TCG_IsShutdownPreBootInterface(void)
   4.839 +{
   4.840 +	return tcpa_acpi.flags & STATUS_FLAG_SHUTDOWN;
   4.841 +}
   4.842 +
   4.843 +
   4.844 +static
   4.845 +uint32_t _TCG_TPM_Extend(unsigned char *hash, uint32_t pcrindex)
   4.846 +{
   4.847 +	uint32_t rc;
   4.848 +	uint8_t _pttti[8+34];
   4.849 +	uint8_t _pttto[4+30];
   4.850 +	struct pttti *pttti = (struct pttti*)&_pttti;
   4.851 +	struct pttto *pttto = (struct pttto*)&_pttto;
   4.852 +
   4.853 +	pttti->ipblength = 8 + 34;
   4.854 +	pttti->reserved  = 0;
   4.855 +	pttti->opblength = 4 + 30;
   4.856 +	pttti->reserved2 = 0;
   4.857 +
   4.858 +	_pttti[8 + 0] = 0x0;
   4.859 +	_pttti[8 + 1] = 0xc1;
   4.860 +	*(uint32_t *)&_pttti[8 + 2] = bswap(34);
   4.861 +	*(uint32_t *)&_pttti[8 + 6] = bswap(0x14);
   4.862 +	*(uint32_t *)&_pttti[8 + 10]= bswap(pcrindex);
   4.863 +	memcpy(&_pttti[8+14], hash, 20);
   4.864 +
   4.865 +	rc = PassThroughToTPM32(pttti,
   4.866 +	                        pttto,
   4.867 +	                        TCG_MAGIC,
   4.868 +	                        0x0,
   4.869 +	                        0x0);
   4.870 +	/* sanity check of result */
   4.871 +	if (_pttto[4] != 0x00 || _pttto[5] != 0xc4) {
   4.872 +		rc = (TCG_PC_TPMERROR |
   4.873 +		      ((uint32_t)TCG_FATAL_COM_ERROR << 16));
   4.874 +	}
   4.875 +
   4.876 +	if (rc != 0) {
   4.877 +		/*
   4.878 +		   Invalidate the log since system did not process this
   4.879 +		   extend properly.
   4.880 +		 */
   4.881 +		tcpa_reset_acpi_log();
   4.882 +		memset(&tcpa_acpi, 0x0, sizeof(tcpa_acpi));
   4.883 +		TCG_ShutdownPreBootInterface(0);
   4.884 +	}
   4.885 +	return rc;
   4.886 +}
   4.887 +
   4.888 +
   4.889 +static
   4.890 +uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s,
   4.891 +                            struct hleeo *hleeo,
   4.892 +                            uint32_t magic,
   4.893 +                            uint32_t ecx,
   4.894 +                            uint32_t edx)
   4.895 +{
   4.896 +	uint32_t rc = 0;
   4.897 +	uint16_t size;
   4.898 +	struct hlei hlei ; /* HashLogEventInput block */
   4.899 +	struct hleo hleo;  /* HashLogEventOutput block */
   4.900 +	struct hleei_long *hleei_l = (struct hleei_long *)hleei_s;
   4.901 +	int sh;
   4.902 +	uint32_t logdataptr;
   4.903 +
   4.904 +	if (TCG_IsShutdownPreBootInterface() != 0) {
   4.905 +		rc = (TCG_PC_TPMERROR |
   4.906 +		      ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
   4.907 +	}
   4.908 +
   4.909 +	if (rc == 0) {
   4.910 +		/* short or long version? */
   4.911 +		size = hleei_s->ipblength;
   4.912 +		if (size == 0x18) {
   4.913 +			/* short */
   4.914 +			sh = 1;
   4.915 +		} else if (size == 0x1c) {
   4.916 +			/* long */
   4.917 +			sh = 0;
   4.918 +		} else {
   4.919 +			/* bad input block */
   4.920 +			rc = TCG_PC_TPMERROR |
   4.921 +			     ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
   4.922 +		}
   4.923 +	}
   4.924 +
   4.925 +	if (rc == 0) {
   4.926 +		uint32_t hashdataptr;
   4.927 +		uint32_t hashdatalen;
   4.928 +		uint32_t pcrindex;
   4.929 +		uint32_t logeventtype;
   4.930 +		uint32_t logdatalen;
   4.931 +		uint32_t eventnumber;
   4.932 +		uint8_t hash[20];
   4.933 +		struct pcpes *pcpes;
   4.934 +
   4.935 +		hashdataptr = hleei_s->hashdataptr;
   4.936 +		hashdatalen = hleei_s->hashdatalen;
   4.937 +		pcrindex    = hleei_s->pcrindex;
   4.938 +		if (sh) {
   4.939 +			logdataptr = hleei_s->logdataptr;
   4.940 +			logdatalen = hleei_s->logdatalen;
   4.941 +		} else {
   4.942 +			logdataptr = hleei_l->logdataptr;
   4.943 +			logdatalen = hleei_l->logdatalen;
   4.944 +		}
   4.945 +
   4.946 +		pcpes = (struct pcpes *)logdataptr;
   4.947 +		logeventtype = pcpes->eventtype;
   4.948 +
   4.949 +		/* fill out HashLogEventInput block 'hlie' */
   4.950 +		hlei.ipblength = 0x1c;
   4.951 +		hlei.reserved = 0;
   4.952 +		hlei.hashdataptr = hashdataptr;
   4.953 +		hlei.hashdatalen = hashdatalen;
   4.954 +		hlei.pcrindex    = pcrindex;
   4.955 +		hlei.logeventtype= logeventtype;
   4.956 +		hlei.logdataptr  = logdataptr;
   4.957 +		hlei.logdatalen  = logdatalen;
   4.958 +
   4.959 +		rc = HashLogEvent32(&hlei,
   4.960 +		                    &hleo,
   4.961 +		                    TCG_MAGIC,
   4.962 +		                    0x0,
   4.963 +		                    0x0);
   4.964 +		eventnumber = hleo.eventnumber;
   4.965 +
   4.966 +		hleeo->opblength = 8 + 20;
   4.967 +		hleeo->reserved  = 0;
   4.968 +		hleeo->eventnumber = eventnumber;
   4.969 +
   4.970 +		memcpy(hash, (unsigned char *)logdataptr + 0x8, 20);
   4.971 +		_TCG_TPM_Extend(hash, pcrindex);
   4.972 +	}
   4.973 +
   4.974 +	if (rc != 0) {
   4.975 +		hleeo->opblength = 4;
   4.976 +		hleeo->reserved  = 0;
   4.977 +	}
   4.978 +	return rc;
   4.979 +
   4.980 +}
   4.981 +
   4.982 +
   4.983 +static
   4.984 +uint32_t PassThroughToTPM32(struct pttti *pttti,
   4.985 +                          struct pttto *pttto,
   4.986 +                          uint32_t magic,
   4.987 +                          uint32_t ecx,
   4.988 +                          uint32_t edx)
   4.989 +{
   4.990 +	uint32_t rc = 0;
   4.991 +	uint8_t *cmd32;
   4.992 +	uint32_t resbuflen;
   4.993 +
   4.994 +	if (TCG_IsShutdownPreBootInterface() != 0) {
   4.995 +		rc = (TCG_PC_TPMERROR |
   4.996 +		      ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
   4.997 +	}
   4.998 +
   4.999 +	if (rc == 0) {
  4.1000 +		if (pttti->ipblength < 0x8 + 10) {
  4.1001 +			rc = TCG_PC_TPMERROR |
  4.1002 +			     ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
  4.1003 +		}
  4.1004 +	}
  4.1005 +
  4.1006 +	if (rc == 0) {
  4.1007 +		if (pttti->opblength < 0x4) {
  4.1008 +			rc = TCG_PC_TPMERROR |
  4.1009 +			     ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
  4.1010 +		}
  4.1011 +	}
  4.1012 +
  4.1013 +	if (rc == 0) {
  4.1014 +		uint8_t *resbuf32;
  4.1015 +
  4.1016 +		cmd32 = &pttti->tpmoperandin[0];
  4.1017 +		resbuflen = pttti->opblength - 4;
  4.1018 +		resbuf32  = &pttto->tpmoperandout[0];
  4.1019 +
  4.1020 +		rc = MA_Transmit(cmd32, resbuf32, resbuflen);
  4.1021 +	}
  4.1022 +
  4.1023 +	if (rc == 0) {
  4.1024 +		pttto->opblength = resbuflen+4;
  4.1025 +		pttto->reserved  = 0;
  4.1026 +	}
  4.1027 +
  4.1028 +	if (rc != 0) {
  4.1029 +		pttto->opblength = 0;
  4.1030 +		pttto->reserved = 0;
  4.1031 +	}
  4.1032 +
  4.1033 +	return rc;
  4.1034 +}
  4.1035 +
  4.1036 +
  4.1037 +static
  4.1038 +uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx)
  4.1039 +{
  4.1040 +	uint32_t rc = 0;
  4.1041 +	if (TCG_IsShutdownPreBootInterface() == 0) {
  4.1042 +		tcpa_acpi.flags |= STATUS_FLAG_SHUTDOWN;
  4.1043 +	} else {
  4.1044 +		rc = (TCG_PC_TPMERROR |
  4.1045 +		      ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
  4.1046 +	}
  4.1047 +	return rc;
  4.1048 +}
  4.1049 +
  4.1050 +
  4.1051 +static
  4.1052 +uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo,
  4.1053 +                      uint32_t ebx,
  4.1054 +                      uint32_t ecx,
  4.1055 +                      uint32_t edx)
  4.1056 +{
  4.1057 +	uint32_t rc = 0;
  4.1058 +	uint16_t size;
  4.1059 +	uint32_t logdataptr;
  4.1060 +	uint32_t logdatalen;
  4.1061 +	uint32_t hashdataptr;
  4.1062 +	uint32_t hashdatalen;
  4.1063 +
  4.1064 +	if (TCG_IsShutdownPreBootInterface() != 0) {
  4.1065 +		rc = (TCG_PC_TPMERROR |
  4.1066 +		      ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
  4.1067 +	}
  4.1068 +
  4.1069 +	if (rc == 0) {
  4.1070 +		size = hlei->ipblength;
  4.1071 +		if (size != 0x1c) {
  4.1072 +			rc = (TCG_PC_TPMERROR |
  4.1073 +			      ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
  4.1074 +		}
  4.1075 +	}
  4.1076 +
  4.1077 +	if (rc == 0) {
  4.1078 +		struct pcpes *pcpes;
  4.1079 +		logdataptr = hlei->logdataptr;
  4.1080 +		logdatalen = hlei->logdatalen;
  4.1081 +		pcpes = (struct pcpes *)logdataptr;
  4.1082 +		if (pcpes->pcrindex != hlei->pcrindex) {
  4.1083 +			rc = (TCG_PC_TPMERROR |
  4.1084 +			      ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
  4.1085 +		}
  4.1086 +	}
  4.1087 +
  4.1088 +	if (rc == 0) {
  4.1089 +		struct pcpes *pcpes= (struct pcpes *)logdataptr;
  4.1090 +		if (pcpes->eventtype != hlei->logeventtype) {
  4.1091 +			rc = (TCG_PC_TPMERROR |
  4.1092 +			      ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
  4.1093 +		}
  4.1094 +	}
  4.1095 +
  4.1096 +	if (rc == 0) {
  4.1097 +		uint32_t entry;
  4.1098 +		hashdataptr = hlei->hashdataptr;
  4.1099 +		hashdatalen = hlei->hashdatalen;
  4.1100 +
  4.1101 +		if ((hashdataptr != 0) | (hashdatalen != 0)) {
  4.1102 +			uint8_t hash[20];
  4.1103 +			struct hai hai; /* HashAll Input Block */
  4.1104 +			hai.ipblength = 0x10;
  4.1105 +			hai.reserved  = 0x0;
  4.1106 +			hai.hashdataptr = hashdataptr;
  4.1107 +			hai.hashdatalen = hashdatalen;
  4.1108 +			hai.algorithmid = TPM_ALG_SHA;
  4.1109 +			rc = HashAll32(&hai,
  4.1110 +				       hash,
  4.1111 +			               TCG_MAGIC,
  4.1112 +			               0x0,
  4.1113 +			               0x0);
  4.1114 +
  4.1115 +			if (rc == 0) {
  4.1116 +				/* hashing was done ok */
  4.1117 +				memcpy((unsigned char *)logdataptr + 8,
  4.1118 +				       hash,
  4.1119 +				       20);
  4.1120 +			}
  4.1121 +		}
  4.1122 +
  4.1123 +		if (rc == 0) {
  4.1124 +			/* extend the log with this event */
  4.1125 +			entry = tcpa_extend_acpi_log(logdataptr);
  4.1126 +			if ((uint16_t)entry == 0) {
  4.1127 +				/* upper 16 bits hold error code */
  4.1128 +				rc = (entry >> 16);
  4.1129 +			}
  4.1130 +		}
  4.1131 +
  4.1132 +		if (rc == 0) {
  4.1133 +			/* updating the log was fine */
  4.1134 +			hleo->opblength = 8;
  4.1135 +			hleo->reserved  = 0;
  4.1136 +			hleo->eventnumber = entry;
  4.1137 +		}
  4.1138 +	}
  4.1139 +
  4.1140 +	if (rc != 0) {
  4.1141 +		hleo->opblength = 2;
  4.1142 +		hleo->reserved = 0;
  4.1143 +	}
  4.1144 +
  4.1145 +	return rc;
  4.1146 +}
  4.1147 +
  4.1148 +static
  4.1149 +uint32_t HashAll32(struct hai *hai, unsigned char *hash,
  4.1150 +                 uint32_t magic,
  4.1151 +                 uint32_t ecx,
  4.1152 +                 uint32_t edx)
  4.1153 +{
  4.1154 +	uint32_t rc = 0;
  4.1155 +
  4.1156 +	if (TCG_IsShutdownPreBootInterface() != 0) {
  4.1157 +		rc = (TCG_PC_TPMERROR |
  4.1158 +		      ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
  4.1159 +	}
  4.1160 +
  4.1161 +	if (rc == 0) {
  4.1162 +		if (hai->ipblength != 0x10) {
  4.1163 +			rc = (TCG_PC_TPMERROR |
  4.1164 +			      ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
  4.1165 +		}
  4.1166 +	}
  4.1167 +
  4.1168 +	if (rc == 0) {
  4.1169 +		if (hai->algorithmid != TPM_ALG_SHA) {
  4.1170 +			rc = (TCG_PC_TPMERROR |
  4.1171 +			     ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
  4.1172 +		}
  4.1173 +	}
  4.1174 +
  4.1175 +	if (rc == 0) {
  4.1176 +		uint8_t *hashdataptr32;
  4.1177 +		uint32_t hashdatalen32;
  4.1178 +
  4.1179 +		hashdataptr32 = (uint8_t *)hai->hashdataptr;
  4.1180 +		hashdatalen32 = hai->hashdatalen;
  4.1181 +
  4.1182 +		sha1(hashdataptr32,
  4.1183 +		     hashdatalen32,
  4.1184 +		     hash);
  4.1185 +	}
  4.1186 +
  4.1187 +	return rc;
  4.1188 +}
  4.1189 +
  4.1190 +
  4.1191 +static
  4.1192 +uint32_t TSS32(struct ti *ti, struct to *to,
  4.1193 +             uint32_t ebx,
  4.1194 +             uint32_t ecx,
  4.1195 +             uint32_t edx)
  4.1196 +{
  4.1197 +	uint32_t rc = 0;
  4.1198 +	if (TCG_IsShutdownPreBootInterface() == 0) {
  4.1199 +		rc = TCG_PC_UNSUPPORTED;
  4.1200 +	} else {
  4.1201 +		rc = (TCG_PC_TPMERROR |
  4.1202 +		      ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
  4.1203 +	}
  4.1204 +
  4.1205 +	if (rc != 0) {
  4.1206 +		to->opblength = 4;
  4.1207 +		to->reserved  = 0;
  4.1208 +	}
  4.1209 +
  4.1210 +	return rc;
  4.1211 +}
  4.1212 +
  4.1213 +static
  4.1214 +uint32_t CompactHashLogExtendEvent32(unsigned char *buffer,
  4.1215 +                                   uint32_t info,
  4.1216 +                                   uint32_t magic,
  4.1217 +                                   uint32_t length,
  4.1218 +                                   uint32_t pcrindex,
  4.1219 +                                   uint32_t *edx_ptr)
  4.1220 +{
  4.1221 +	uint32_t rc = 0;
  4.1222 +	struct hleeo hleeo;
  4.1223 +
  4.1224 +	if (TCG_IsShutdownPreBootInterface() != 0) {
  4.1225 +		rc = (TCG_PC_TPMERROR |
  4.1226 +		      ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
  4.1227 +	}
  4.1228 +
  4.1229 +	if (buffer == 0) {
  4.1230 +		rc = (TCG_PC_TPMERROR |
  4.1231 +		      ((uint32_t)TCG_INVALID_INPUT_PARA << 16));
  4.1232 +	}
  4.1233 +
  4.1234 +	if (rc == 0) {
  4.1235 +		struct hleei_short hleei;
  4.1236 +		struct pcpes pcpes;
  4.1237 +		uint8_t *logdataptr;
  4.1238 +		uint8_t *hashdataptr;
  4.1239 +
  4.1240 +		logdataptr = (uint8_t*)&pcpes;
  4.1241 +		hashdataptr = buffer;
  4.1242 +
  4.1243 +		hleei.ipblength = 0x18;
  4.1244 +		hleei.reserved  = 0x0;
  4.1245 +		hleei.hashdataptr = (uint32_t)hashdataptr;
  4.1246 +		hleei.hashdatalen = length;
  4.1247 +		hleei.pcrindex = pcrindex;
  4.1248 +		hleei.logdataptr = (uint32_t)logdataptr;
  4.1249 +		hleei.logdatalen = 32;
  4.1250 +
  4.1251 +		memset(&pcpes, 0x0, 32);
  4.1252 +		pcpes.pcrindex = pcrindex;
  4.1253 +		pcpes.eventtype = 12; /* EV_COMPACT_HASH */
  4.1254 +		pcpes.eventdatasize = 4;
  4.1255 +		pcpes.event = info;
  4.1256 +
  4.1257 +		rc = HashLogExtendEvent32(&hleei,
  4.1258 +		                          &hleeo,
  4.1259 +		                          TCG_MAGIC,
  4.1260 +		                          0x0,
  4.1261 +		                          0x0);
  4.1262 +	}
  4.1263 +
  4.1264 +	if (rc == 0) {
  4.1265 +		*edx_ptr = hleeo.eventnumber;
  4.1266 +	}
  4.1267 +
  4.1268 +	return rc;
  4.1269 +}
  4.1270 +
  4.1271 +
  4.1272 +
  4.1273 +/*******************************************************************
  4.1274 +  Calculation of SHA1 in SW
  4.1275 +
  4.1276 +  See: RFC3174, Wikipedia's SHA1 alogrithm description
  4.1277 + ******************************************************************/
  4.1278 +typedef struct _sha1_ctx {
  4.1279 +	uint32_t h[5];
  4.1280 +} sha1_ctx;
  4.1281 +
  4.1282 +
  4.1283 +static inline uint32_t rol(val, rol)
  4.1284 +  uint32_t val;
  4.1285 +  uint16_t rol;
  4.1286 +{
  4.1287 +	return (val << rol) | (val >> (32 - rol));
  4.1288 +}
  4.1289 +
  4.1290 +static const uint32_t sha_ko[4] = { 0x5a827999,
  4.1291 +                                    0x6ed9eba1,
  4.1292 +                                    0x8f1bbcdc,
  4.1293 +                                    0xca62c1d6 };
  4.1294 +
  4.1295 +
  4.1296 +static void sha1_block(uint32_t *w, sha1_ctx *ctx)
  4.1297 +{
  4.1298 +	uint32_t i;
  4.1299 +	uint32_t a,b,c,d,e,f;
  4.1300 +	uint32_t tmp;
  4.1301 +	uint32_t idx;
  4.1302 +
  4.1303 +	/* change endianess of given data */
  4.1304 +	for (i = 0; i < 16; i++) {
  4.1305 +		w[i] = bswap(w[i]);
  4.1306 +	}
  4.1307 +
  4.1308 +	for (i = 16; i <= 79; i++) {
  4.1309 +		tmp = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
  4.1310 +		w[i] = rol(tmp,1);
  4.1311 +	}
  4.1312 +
  4.1313 +	a = ctx->h[0];
  4.1314 +	b = ctx->h[1];
  4.1315 +	c = ctx->h[2];
  4.1316 +	d = ctx->h[3];
  4.1317 +	e = ctx->h[4];
  4.1318 +
  4.1319 +	for (i = 0; i <= 79; i++) {
  4.1320 +		if (i <= 19) {
  4.1321 +			f = (b & c) | ((b ^ 0xffffffff) & d);
  4.1322 +			idx = 0;
  4.1323 +		} else if (i <= 39) {
  4.1324 +			f = b ^ c ^ d;
  4.1325 +			idx = 1;
  4.1326 +		} else if (i <= 59) {
  4.1327 +			f = (b & c) | (b & d) | (c & d);
  4.1328 +			idx = 2;
  4.1329 +		} else {
  4.1330 +			f = b ^ c ^ d;
  4.1331 +			idx = 3;
  4.1332 +		}
  4.1333 +
  4.1334 +		tmp = rol(a, 5) +
  4.1335 +		      f +
  4.1336 +		      e +
  4.1337 +		      sha_ko[idx] +
  4.1338 +		      w[i];
  4.1339 +		e = d;
  4.1340 +		d = c;
  4.1341 +		c = rol(b, 30);
  4.1342 +		b = a;
  4.1343 +		a = tmp;
  4.1344 +	}
  4.1345 +
  4.1346 +	ctx->h[0] += a;
  4.1347 +	ctx->h[1] += b;
  4.1348 +	ctx->h[2] += c;
  4.1349 +	ctx->h[3] += d;
  4.1350 +	ctx->h[4] += e;
  4.1351 +}
  4.1352 +
  4.1353 +static
  4.1354 +void sha1_do(sha1_ctx *ctx, const unsigned char *data32, uint32_t length)
  4.1355 +{
  4.1356 +	uint32_t offset;
  4.1357 +	uint16_t num;
  4.1358 +	uint32_t bits = 0;
  4.1359 +	uint32_t w[80];
  4.1360 +	uint32_t tmp;
  4.1361 +
  4.1362 +	/* treat data in 64-byte chunks */
  4.1363 +	for (offset = 0; length - offset >= 64; offset += 64) {
  4.1364 +		/* copy into the 'w' array */
  4.1365 +		memcpy(w, data32 + offset, 64);
  4.1366 +		/* hash the block in the 'w' array */
  4.1367 +		sha1_block((uint32_t *)w, ctx);
  4.1368 +		bits += (64 * 8);
  4.1369 +	}
  4.1370 +
  4.1371 +	/* last block with less than 64 bytes */
  4.1372 +	num = length - offset;
  4.1373 +	bits += (num << 3);
  4.1374 +
  4.1375 +	memset(w, 0x0, 64);
  4.1376 +	memcpy(w, data32 + offset, num);
  4.1377 +	((uint8_t *)w)[num] = 0x80;
  4.1378 +
  4.1379 +	if (num >= 56) {
  4.1380 +		/* cannot append number of bits here */
  4.1381 +		sha1_block((uint32_t *)w, ctx);
  4.1382 +		memset(w, 0x0, 60);
  4.1383 +	}
  4.1384 +
  4.1385 +	/* write number of bits to end of block */
  4.1386 +	tmp = bswap(bits);
  4.1387 +	memcpy(&w[15], &tmp, 4);
  4.1388 +
  4.1389 +	sha1_block(w, ctx);
  4.1390 +
  4.1391 +	/* need to switch result's endianess */
  4.1392 +	for (num = 0; num < 5; num++)
  4.1393 +		ctx->h[num] = bswap(ctx->h[num]);
  4.1394 +}
  4.1395 +
  4.1396 +/* sha1 initialization constants */
  4.1397 +static const uint32_t sha_const[5] = {
  4.1398 +	0x67452301,
  4.1399 +	0xefcdab89,
  4.1400 +	0x98badcfe,
  4.1401 +	0x10325476,
  4.1402 +	0xc3d2e1f0
  4.1403 +};
  4.1404 +
  4.1405 +static
  4.1406 +void sha1(const unsigned char *data, uint32_t length, unsigned char *hash)
  4.1407 +{
  4.1408 +	sha1_ctx ctx;
  4.1409 +
  4.1410 +	memcpy(&ctx.h[0], sha_const, 20);
  4.1411 +	sha1_do(&ctx, data, length);
  4.1412 +	memcpy(hash, &ctx.h[0], 20);
  4.1413 +}
  4.1414 +
  4.1415 +
  4.1416 +uint32_t TCGInterruptHandler(pushad_regs_t *regs, uint32_t esds, uint32_t flags_ptr)
  4.1417 +{
  4.1418 +	uint16_t DS = esds >> 16;
  4.1419 +	uint16_t ES = esds & 0xffff;
  4.1420 +	uint16_t *FLAGS = (uint16_t *)flags_ptr;
  4.1421 +
  4.1422 +	switch(regs->u.r8.al) {
  4.1423 +	case 0x00:
  4.1424 +		if (MA_IsTPMPresent() == 0) {
  4.1425 +			/* no TPM available */
  4.1426 +			regs->u.r32.eax = TCG_PC_TPMERROR |
  4.1427 +			     ((uint32_t)(TCG_PC_TPM_NOT_PRESENT) << 16);
  4.1428 +		} else {
  4.1429 +			regs->u.r32.eax = MA_InitTPM(TPM_ST_CLEAR);
  4.1430 +			if (regs->u.r32.eax == 0) {
  4.1431 +				regs->u.r32.ebx = TCG_MAGIC;
  4.1432 +				regs->u.r8.ch = TCG_VERSION_MAJOR;
  4.1433 +				regs->u.r8.cl = TCG_VERSION_MINOR;
  4.1434 +				regs->u.r32.edx = 0x0;
  4.1435 +				regs->u.r32.esi =
  4.1436 +				             (Bit32u)tcpa_get_lasa_base_ptr();
  4.1437 +				regs->u.r32.edi =
  4.1438 +				             (Bit32u)tcpa_get_lasa_last_ptr();
  4.1439 +				CLEAR_CF();
  4.1440 +			}
  4.1441 +		}
  4.1442 +		break;
  4.1443 +
  4.1444 +	case 0x01:
  4.1445 +		regs->u.r32.eax =
  4.1446 +			HashLogExtendEvent32((struct hleei_short*)
  4.1447 +			                        ADDR_FROM_SEG_OFF(ES,
  4.1448 +			                              regs->u.r16.di),
  4.1449 +			                    (struct hleeo*)
  4.1450 +			                        ADDR_FROM_SEG_OFF(DS,
  4.1451 +			                              regs->u.r16.si),
  4.1452 +			                    regs->u.r32.ebx,
  4.1453 +			                    regs->u.r32.ecx,
  4.1454 +			                    regs->u.r32.edx);
  4.1455 +		CLEAR_CF();
  4.1456 +		break;
  4.1457 +	case 0x02:
  4.1458 +		regs->u.r32.eax =
  4.1459 +			PassThroughToTPM32((struct pttti *)
  4.1460 +			                        ADDR_FROM_SEG_OFF(ES,
  4.1461 +			                              regs->u.r16.di),
  4.1462 +			                   (struct pttto *)
  4.1463 +			                        ADDR_FROM_SEG_OFF(DS,
  4.1464 +			                              regs->u.r16.si),
  4.1465 +			                   regs->u.r32.ebx,
  4.1466 +			                   regs->u.r32.ecx,
  4.1467 +			                   regs->u.r32.edx);
  4.1468 +		CLEAR_CF();
  4.1469 +		break;
  4.1470 +	case 0x03:
  4.1471 +		regs->u.r32.eax =
  4.1472 +			TCG_ShutdownPreBootInterface(regs->u.r32.ebx);
  4.1473 +		CLEAR_CF();
  4.1474 +		break;
  4.1475 +	case 0x04:
  4.1476 +		regs->u.r32.eax =
  4.1477 +			HashLogEvent32((struct hlei*)
  4.1478 +			                        ADDR_FROM_SEG_OFF(ES,
  4.1479 +					              regs->u.r16.di),
  4.1480 +		                       (struct hleo*)
  4.1481 +			                        ADDR_FROM_SEG_OFF(DS,
  4.1482 +			                              regs->u.r16.si),
  4.1483 +			                   regs->u.r32.ebx,
  4.1484 +			                   regs->u.r32.ecx,
  4.1485 +			                   regs->u.r32.edx);
  4.1486 +		CLEAR_CF();
  4.1487 +		break;
  4.1488 +	case 0x05:
  4.1489 +		regs->u.r32.eax =
  4.1490 +			HashAll32((struct hai*)
  4.1491 +					ADDR_FROM_SEG_OFF(ES,
  4.1492 +			                                  regs->u.r16.di),
  4.1493 +			         (unsigned char *)
  4.1494 +			                ADDR_FROM_SEG_OFF(DS,
  4.1495 +			                                  regs->u.r16.si),
  4.1496 +			           regs->u.r32.ebx,
  4.1497 +			           regs->u.r32.ecx,
  4.1498 +			           regs->u.r32.edx);
  4.1499 +		CLEAR_CF();
  4.1500 +		break;
  4.1501 +	case 0x06:
  4.1502 +		regs->u.r32.eax =
  4.1503 +			TSS32((struct ti*)ADDR_FROM_SEG_OFF(ES,
  4.1504 +			                                    regs->u.r16.di),
  4.1505 +			      (struct to*)ADDR_FROM_SEG_OFF(DS,
  4.1506 +			                                    regs->u.r16.si),
  4.1507 +			      regs->u.r32.ebx,
  4.1508 +			      regs->u.r32.ecx,
  4.1509 +			      regs->u.r32.edx);
  4.1510 +		CLEAR_CF();
  4.1511 +		break;
  4.1512 +	case 0x07:
  4.1513 +		regs->u.r32.eax =
  4.1514 +		  CompactHashLogExtendEvent32((unsigned char *)
  4.1515 +		                                  ADDR_FROM_SEG_OFF(ES,
  4.1516 +		                                        regs->u.r16.di),
  4.1517 +		                              regs->u.r32.esi,
  4.1518 +		                              regs->u.r32.ebx,
  4.1519 +		                              regs->u.r32.ecx,
  4.1520 +		                              regs->u.r32.edx,
  4.1521 +		                              &regs->u.r32.edx);
  4.1522 +		CLEAR_CF();
  4.1523 +		break;
  4.1524 +	default:
  4.1525 +		SET_CF();
  4.1526 +	}
  4.1527 +
  4.1528 +	return 0;
  4.1529 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.h	Fri Jan 26 16:38:32 2007 +0000
     5.3 @@ -0,0 +1,288 @@
     5.4 +#ifndef TCGBIOS_H
     5.5 +#define TCGBIOS_H
     5.6 +
     5.7 +
     5.8 +/* TCPA ACPI definitions */
     5.9 +#define TCPA_ACPI_CLASS_CLIENT          0
    5.10 +#define TCPA_ACPI_CLASS_SERVER          1
    5.11 +
    5.12 +/* Define for section 12.3 */
    5.13 +#define TCG_PC_OK                       0x0
    5.14 +#define TCG_PC_TPMERROR                 0x1
    5.15 +#define TCG_PC_LOGOVERFLOW              0x2
    5.16 +#define TCG_PC_UNSUPPORTED              0x3
    5.17 +
    5.18 +#define TPM_ALG_SHA                     0x4
    5.19 +
    5.20 +#define TCG_MAGIC                       0x41504354L
    5.21 +#define TCG_VERSION_MAJOR               1
    5.22 +#define TCG_VERSION_MINOR               2
    5.23 +
    5.24 +#define TPM_OK                          0x0
    5.25 +#define TPM_RET_BASE                    0x1
    5.26 +#define TCG_GENERAL_ERROR               (TPM_RET_BASE + 0x0)
    5.27 +#define TCG_TPM_IS_LOCKED               (TPM_RET_BASE + 0x1)
    5.28 +#define TCG_NO_RESPONSE                 (TPM_RET_BASE + 0x2)
    5.29 +#define TCG_INVALID_RESPONSE            (TPM_RET_BASE + 0x3)
    5.30 +#define TCG_INVALID_ACCESS_REQUEST      (TPM_RET_BASE + 0x4)
    5.31 +#define TCG_FIRMWARE_ERROR              (TPM_RET_BASE + 0x5)
    5.32 +#define TCG_INTEGRITY_CHECK_FAILED      (TPM_RET_BASE + 0x6)
    5.33 +#define TCG_INVALID_DEVICE_ID           (TPM_RET_BASE + 0x7)
    5.34 +#define TCG_INVALID_VENDOR_ID           (TPM_RET_BASE + 0x8)
    5.35 +#define TCG_UNABLE_TO_OPEN              (TPM_RET_BASE + 0x9)
    5.36 +#define TCG_UNABLE_TO_CLOSE             (TPM_RET_BASE + 0xa)
    5.37 +#define TCG_RESPONSE_TIMEOUT            (TPM_RET_BASE + 0xb)
    5.38 +#define TCG_INVALID_COM_REQUEST         (TPM_RET_BASE + 0xc)
    5.39 +#define TCG_INVALID_ADR_REQUEST         (TPM_RET_BASE + 0xd)
    5.40 +#define TCG_WRITE_BYTE_ERROR            (TPM_RET_BASE + 0xe)
    5.41 +#define TCG_READ_BYTE_ERROR             (TPM_RET_BASE + 0xf)
    5.42 +#define TCG_BLOCK_WRITE_TIMEOUT         (TPM_RET_BASE + 0x10)
    5.43 +#define TCG_CHAR_WRITE_TIMEOUT          (TPM_RET_BASE + 0x11)
    5.44 +#define TCG_CHAR_READ_TIMEOUT           (TPM_RET_BASE + 0x12)
    5.45 +#define TCG_BLOCK_READ_TIMEOUT          (TPM_RET_BASE + 0x13)
    5.46 +#define TCG_TRANSFER_ABORT              (TPM_RET_BASE + 0x14)
    5.47 +#define TCG_INVALID_DRV_FUNCTION        (TPM_RET_BASE + 0x15)
    5.48 +#define TCG_OUTPUT_BUFFER_TOO_SHORT     (TPM_RET_BASE + 0x16)
    5.49 +#define TCG_FATAL_COM_ERROR             (TPM_RET_BASE + 0x17)
    5.50 +#define TCG_INVALID_INPUT_PARA          (TPM_RET_BASE + 0x18)
    5.51 +#define TCG_TCG_COMMAND_ERROR           (TPM_RET_BASE + 0x19)
    5.52 +#define TCG_INTERFACE_SHUTDOWN          (TPM_RET_BASE + 0x20)
    5.53 +//define TCG_PC_UNSUPPORTED             (TPM_RET_BASE + 0x21)
    5.54 +#define TCG_PC_TPM_NOT_PRESENT          (TPM_RET_BASE + 0x22)
    5.55 +#define TCG_PC_TPM_DEACTIVATED          (TPM_RET_BASE + 0x23)
    5.56 +
    5.57 +
    5.58 +#define TPM_INVALID_ADR_REQUEST          TCG_INVALID_ADR_REQUEST
    5.59 +#define TPM_IS_LOCKED                    TCG_TPM_IS_LOCKED
    5.60 +#define TPM_INVALID_DEVICE_ID            TCG_INVALID_DEVICE_ID
    5.61 +#define TPM_INVALID_VENDOR_ID            TCG_INVALID_VENDOR_ID
    5.62 +//define TPM_RESERVED_REG_INVALID
    5.63 +#define TPM_FIRMWARE_ERROR               TCG_FIRMWARE_ERROR
    5.64 +#define TPM_UNABLE_TO_OPEN               TCG_UNABLE_TO_OPEN
    5.65 +#define TPM_UNABLE_TO_CLOSE              TCG_UNABLE_TO_CLOSE
    5.66 +#define TPM_INVALID_RESPONSE             TCG_INVALID_RESPONSE
    5.67 +#define TPM_RESPONSE_TIMEOUT             TCG_RESPONSE_TIMEOUT
    5.68 +#define TPM_INVALID_ACCESS_REQUEST       TCG_INVALID_ACCESS_REQUEST
    5.69 +#define TPM_TRANSFER_ABORT               TCG_TRANSFER_ABORT
    5.70 +#define TPM_GENERAL_ERROR                TCG_GENERAL_ERROR
    5.71 +
    5.72 +#define TPM_ST_CLEAR                      0x0
    5.73 +#define TPM_ST_STATE                      0x1
    5.74 +#define TPM_ST_DEACTIVATED                0x2
    5.75 +
    5.76 +/* event types: 10.4.1 / table 11 */
    5.77 +#define EV_POST_CODE             1
    5.78 +#define EV_SEPARATOR             4
    5.79 +#define EV_ACTION                5
    5.80 +#define EV_EVENT_TAG             6
    5.81 +#define EV_COMPACT_HASH         12
    5.82 +#define EV_IPL                  13
    5.83 +#define EV_IPL_PARTITION_DATA   14
    5.84 +
    5.85 +
    5.86 +// MA Driver defines
    5.87 +#define CODE_MAInitTPM                    0x01
    5.88 +#define CODE_MAHashAllExtendTPM           0x02
    5.89 +#define CODE_MAPhysicalPresenceTPM        0x03
    5.90 +/* vendor specific ones */
    5.91 +#define CODE_MAIsTPMPresent               0x80
    5.92 +#define CODE_MAHashAll                    0x81
    5.93 +#define CODE_MATransmit                   0x82
    5.94 +
    5.95 +/*
    5.96 +  indices for commands to be sent via proprietary
    5.97 +   _TCG_SendCommand function
    5.98 + */
    5.99 +#define IDX_CMD_TPM_Startup_0x01                0
   5.100 +#define IDX_CMD_TSC_PhysicalPresence_0x20       1
   5.101 +#define IDX_CMD_TSC_PhysicalPresence_0x08       2
   5.102 +#define IDX_CMD_TSC_PhysicalPresence_0x100      3
   5.103 +#define IDX_CMD_TSC_PhysicalPresence_0x10       4
   5.104 +#define IDX_CMD_TPM_PhysicalEnable              5
   5.105 +#define IDX_CMD_TPM_PhysicalSetDeactivated_0x00 6
   5.106 +#define IDX_CMD_TPM_SHA1Start                   7
   5.107 +
   5.108 +
   5.109 +/* hardware registers for TPM TIS */
   5.110 +#define TPM_ACCESS                 0x0
   5.111 +#define TPM_INT_ENABLE             0x8
   5.112 +#define TPM_INT_VECTOR             0xc
   5.113 +#define TPM_INT_STATUS             0x10
   5.114 +#define TPM_INTF_CAPABILITY        0x14
   5.115 +#define TPM_STS                    0x18
   5.116 +#define TPM_DATA_FIFO              0x24
   5.117 +#define TPM_DID_VID                0xf00
   5.118 +#define TPM_RID                    0xf04
   5.119 +
   5.120 +/* address of locality 0 (TIS) */
   5.121 +#define TPM_TIS_BASE_ADDRESS        0xfed40000
   5.122 +
   5.123 +#define ASCII32(a,b,c,d)     ((((Bit32u)a) <<  0) | (((Bit32u)b) <<  8) | \
   5.124 +                              (((Bit32u)c) << 16) | (((Bit32u)d) << 24)  )
   5.125 +#define ACPI_2_0_TCPA_SIGNATURE ASCII32('T','C','P','A') /* "TCPA" */
   5.126 +
   5.127 +
   5.128 +#define STATUS_FLAG_SHUTDOWN                (1 << 0)
   5.129 +
   5.130 +#define ACPI_SEGMENT    0xE000
   5.131 +
   5.132 +/* Input and Output blocks for the TCG BIOS commands */
   5.133 +
   5.134 +struct hleei_short
   5.135 +{
   5.136 +	uint16_t   ipblength;
   5.137 +	uint16_t   reserved;
   5.138 +	uint32_t   hashdataptr;
   5.139 +	uint32_t   hashdatalen;
   5.140 +	uint32_t   pcrindex;
   5.141 +	uint32_t   logdataptr;
   5.142 +	uint32_t   logdatalen;
   5.143 +} __attribute__((packed));
   5.144 +
   5.145 +struct hleei_long
   5.146 +{
   5.147 +	uint16_t   ipblength;
   5.148 +	uint16_t   reserved;
   5.149 +	uint32_t   hashdataptr;
   5.150 +	uint32_t   hashdatalen;
   5.151 +	uint32_t   pcrindex;
   5.152 +	uint32_t   reserved2;
   5.153 +	uint32_t   logdataptr;
   5.154 +	uint32_t   logdatalen;
   5.155 +} __attribute__((packed));
   5.156 +
   5.157 +struct hleeo
   5.158 +{
   5.159 +	uint16_t    opblength;
   5.160 +	uint16_t    reserved;
   5.161 +	uint32_t    eventnumber;
   5.162 +	uint8_t     hashvalue[20];
   5.163 +} __attribute__((packed));
   5.164 +
   5.165 +
   5.166 +
   5.167 +struct pttti
   5.168 +{
   5.169 +	uint16_t    ipblength;
   5.170 +	uint16_t    reserved;
   5.171 +	uint16_t    opblength;
   5.172 +	uint16_t    reserved2;
   5.173 +	uint8_t     tpmoperandin[0];
   5.174 +} __attribute__((packed));
   5.175 +
   5.176 +struct pttto
   5.177 +{
   5.178 +	uint16_t    opblength;
   5.179 +	uint16_t    reserved;
   5.180 +	uint8_t     tpmoperandout[0];
   5.181 +};
   5.182 +
   5.183 +
   5.184 +struct hlei
   5.185 +{
   5.186 +	uint16_t    ipblength;
   5.187 +	uint16_t    reserved;
   5.188 +	uint32_t    hashdataptr;
   5.189 +	uint32_t    hashdatalen;
   5.190 +	uint32_t    pcrindex;
   5.191 +	uint32_t    logeventtype;
   5.192 +	uint32_t    logdataptr;
   5.193 +	uint32_t    logdatalen;
   5.194 +} __attribute__((packed));
   5.195 +
   5.196 +struct hleo
   5.197 +{
   5.198 +	uint16_t    opblength;
   5.199 +	uint16_t    reserved;
   5.200 +	uint32_t    eventnumber;
   5.201 +} __attribute__((packed));
   5.202 +
   5.203 +struct hai
   5.204 +{
   5.205 +	uint16_t    ipblength;
   5.206 +	uint16_t    reserved;
   5.207 +	uint32_t    hashdataptr;
   5.208 +	uint32_t    hashdatalen;
   5.209 +	uint32_t    algorithmid;
   5.210 +} __attribute__((packed));
   5.211 +
   5.212 +struct ti
   5.213 +{
   5.214 +	uint16_t    ipblength;
   5.215 +	uint16_t    reserved;
   5.216 +        uint16_t    opblength;
   5.217 +        uint16_t    reserved2;
   5.218 +        uint8_t     tssoperandin[0];
   5.219 +} __attribute__((packed));
   5.220 +
   5.221 +struct to
   5.222 +{
   5.223 +	uint16_t    opblength;
   5.224 +	uint16_t    reserved;
   5.225 +	uint8_t     tssoperandout[0];
   5.226 +} __attribute__((packed));
   5.227 +
   5.228 +
   5.229 +struct pcpes
   5.230 +{
   5.231 +	uint32_t    pcrindex;
   5.232 +	uint32_t    eventtype;
   5.233 +	uint8_t     digest[20];
   5.234 +	uint32_t    eventdatasize;
   5.235 +	uint32_t    event;
   5.236 +} __attribute__((packed));
   5.237 +
   5.238 +
   5.239 +struct acpi_header
   5.240 +{
   5.241 +	uint32_t signature;
   5.242 +	uint32_t length;
   5.243 +	uint8_t  revision;
   5.244 +	uint8_t  checksum;
   5.245 +	uint8_t  oem_id[6];
   5.246 +	uint64_t oem_table_id;
   5.247 +	uint32_t oem_revision;
   5.248 +	uint32_t creator_id;
   5.249 +	uint32_t creator_revision;
   5.250 +} __attribute__((packed));
   5.251 +
   5.252 +struct acpi_20_rsdt {
   5.253 +	struct acpi_header header;
   5.254 +	uint32_t entry[1];
   5.255 +} __attribute__((packed));
   5.256 +
   5.257 +struct acpi_20_rsdp {
   5.258 +	uint64_t signature;
   5.259 +	uint8_t  checksum;
   5.260 +	uint8_t  oem_id[6];
   5.261 +	uint8_t  revision;
   5.262 +	uint32_t rsdt_address;
   5.263 +	uint32_t length;
   5.264 +	uint64_t xsdt_address;
   5.265 +	uint8_t  extended_checksum;
   5.266 +	uint8_t  reserved[3];
   5.267 +} __attribute__((packed));
   5.268 +
   5.269 +struct acpi_20_tcpa_client {
   5.270 +	uint32_t laml;
   5.271 +	uint64_t lasa;
   5.272 +} __attribute__((packed));
   5.273 +
   5.274 +struct acpi_20_tcpa_server {
   5.275 +	uint16_t reserved;
   5.276 +	uint32_t laml;
   5.277 +	uint64_t lasa;
   5.278 +	/* more here */
   5.279 +} __attribute__((packed));
   5.280 +
   5.281 +struct acpi_20_tcpa {
   5.282 +	struct acpi_header header;
   5.283 +	uint16_t platform_class;
   5.284 +	union {
   5.285 +		struct acpi_20_tcpa_client client;
   5.286 +		struct acpi_20_tcpa_server server;
   5.287 +	} u;
   5.288 +} __attribute__((packed));
   5.289 +
   5.290 +
   5.291 +#endif
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c	Fri Jan 26 16:38:32 2007 +0000
     6.3 @@ -0,0 +1,180 @@
     6.4 +/*
     6.5 + *  Implementation of the TCG BIOS extension according to the specification
     6.6 + *  described in
     6.7 + *  https://www.trustedcomputinggroup.org/specs/PCClient/TCG_PCClientImplementationforBIOS_1-20_1-00.pdf
     6.8 + *
     6.9 + *  This library is free software; you can redistribute it and/or
    6.10 + *  modify it under the terms of the GNU Lesser General Public
    6.11 + *  License as published by the Free Software Foundation; either
    6.12 + *  version 2 of the License, or (at your option) any later version.
    6.13 + *
    6.14 + *  This library is distributed in the hope that it will be useful,
    6.15 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.16 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    6.17 + *  Lesser General Public License for more details.
    6.18 + *
    6.19 + *  You should have received a copy of the GNU Lesser General Public
    6.20 + *  License along with this library; if not, write to the Free Software
    6.21 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    6.22 + *
    6.23 + * Copyright (C) IBM Corporation, 2006
    6.24 + *
    6.25 + * Author: Stefan Berger <stefanb@us.ibm.com>
    6.26 + */
    6.27 +#include "rombios_compat.h"
    6.28 +#include "util.h"
    6.29 +
    6.30 +#include "tpm_drivers.h"
    6.31 +#include "tcgbios.h"
    6.32 +
    6.33 +static uint32_t tis_wait_sts(uint8_t *addr, uint32_t time,
    6.34 +                             uint8_t mask, uint8_t expect)
    6.35 +{
    6.36 +	uint32_t rc = 0;
    6.37 +	while (time > 0) {
    6.38 +		uint8_t sts = addr[TPM_STS];
    6.39 +		if ((sts & mask) == expect) {
    6.40 +			rc = 1;
    6.41 +			break;
    6.42 +		}
    6.43 +		mssleep(1);
    6.44 +		time--;
    6.45 +	}
    6.46 +	return rc;
    6.47 +}
    6.48 +
    6.49 +static uint32_t tis_activate(uint32_t baseaddr)
    6.50 +{
    6.51 +	uint32_t rc = 0;
    6.52 +	uint8_t *tis_addr = (uint8_t*)baseaddr;
    6.53 +	uint8_t acc;
    6.54 +	/* request access to locality */
    6.55 +	tis_addr[TPM_ACCESS] = 0x2;
    6.56 +
    6.57 +	acc = tis_addr[TPM_ACCESS];
    6.58 +	if ((acc & 0x20) != 0) {
    6.59 +		tis_addr[TPM_STS] = 0x40;
    6.60 +		rc = tis_wait_sts(tis_addr, 100, 0x40, 0x40);
    6.61 +	}
    6.62 +	return rc;
    6.63 +}
    6.64 +
    6.65 +uint32_t tis_ready(uint32_t baseaddr)
    6.66 +{
    6.67 +	uint32_t rc = 0;
    6.68 +	uint8_t *tis_addr = (uint8_t*)baseaddr;
    6.69 +
    6.70 +	tis_addr[TPM_STS] = 0x40;
    6.71 +	rc = tis_wait_sts(tis_addr, 100, 0x40, 0x40);
    6.72 +
    6.73 +	return rc;
    6.74 +}
    6.75 +
    6.76 +uint32_t tis_senddata(uint32_t baseaddr, unsigned char *data, uint32_t len)
    6.77 +{
    6.78 +	uint32_t rc = 0;
    6.79 +	uint8_t *tis_addr = (uint8_t*)baseaddr;
    6.80 +	uint32_t offset = 0;
    6.81 +	uint32_t end = 0;
    6.82 +
    6.83 +	do {
    6.84 +		uint16_t burst = 0;
    6.85 +		uint32_t ctr = 0;
    6.86 +		while (burst == 0 && ctr < 2000) {
    6.87 +			burst = (((uint16_t)tis_addr[TPM_STS+1])     ) +
    6.88 +			        (((uint16_t)tis_addr[TPM_STS+2]) << 8);
    6.89 +			if (burst == 0) {
    6.90 +				mssleep(1);
    6.91 +				ctr++;
    6.92 +			}
    6.93 +		}
    6.94 +
    6.95 +		if (burst == 0) {
    6.96 +			rc = TCG_RESPONSE_TIMEOUT;
    6.97 +			break;
    6.98 +		}
    6.99 +
   6.100 +		while (1) {
   6.101 +			tis_addr[TPM_DATA_FIFO] = data[offset];
   6.102 +			offset++;
   6.103 +			burst--;
   6.104 +
   6.105 +			if (burst == 0 || offset == len) {
   6.106 +				break;
   6.107 +			}
   6.108 +		}
   6.109 +
   6.110 +		if (offset == len) {
   6.111 +			end = 1;
   6.112 +		}
   6.113 +	} while (end == 0);
   6.114 +
   6.115 +	return rc;
   6.116 +}
   6.117 +
   6.118 +uint32_t tis_readresp(uint32_t baseaddr, unsigned char *buffer, uint32_t len)
   6.119 +{
   6.120 +	uint32_t rc = 0;
   6.121 +	uint32_t offset = 0;
   6.122 +	uint8_t *tis_addr = (uint8_t*)baseaddr;
   6.123 +	uint32_t sts;
   6.124 +
   6.125 +	while (offset < len) {
   6.126 +		buffer[offset] = tis_addr[TPM_DATA_FIFO];
   6.127 +		offset++;
   6.128 +		sts = tis_addr[TPM_STS];
   6.129 +		/* data left ? */
   6.130 +		if ((sts & 0x10) == 0) {
   6.131 +			break;
   6.132 +		}
   6.133 +	}
   6.134 +	return rc;
   6.135 +}
   6.136 +
   6.137 +
   6.138 +uint32_t tis_waitdatavalid(uint32_t baseaddr)
   6.139 +{
   6.140 +	uint8_t *tis_addr = (uint8_t*)baseaddr;
   6.141 +	uint32_t rc = 0;
   6.142 +	if (tis_wait_sts(tis_addr, 1000, 0x80, 0x80) == 0) {
   6.143 +		rc = TCG_NO_RESPONSE;
   6.144 +	}
   6.145 +	return rc;
   6.146 +}
   6.147 +
   6.148 +uint32_t tis_waitrespready(uint32_t baseaddr, uint32_t timeout)
   6.149 +{
   6.150 +	uint32_t rc = 0;
   6.151 +	uint8_t *tis_addr = (uint8_t*)baseaddr;
   6.152 +	tis_addr[TPM_STS] = 0x20;
   6.153 +	if (tis_wait_sts(tis_addr, timeout, 0x10, 0x10) == 0) {
   6.154 +		rc = TCG_NO_RESPONSE;
   6.155 +	}
   6.156 +	return rc;
   6.157 +}
   6.158 +
   6.159 +/* if device is not there, return '0', '1' otherwise */
   6.160 +uint32_t tis_probe(uint32_t baseaddr)
   6.161 +{
   6.162 +	uint32_t rc = 0;
   6.163 +	uint8_t *tis_addr = (uint8_t*)baseaddr;
   6.164 +	uint32_t didvid = *(uint32_t*)&tis_addr[TPM_DID_VID];
   6.165 +	if ((didvid != 0) && (didvid != 0xffffffff)) {
   6.166 +		rc = 1;
   6.167 +	}
   6.168 +	return rc;
   6.169 +}
   6.170 +
   6.171 +
   6.172 +struct tpm_driver tpm_drivers[TPM_NUM_DRIVERS] = {
   6.173 +	{
   6.174 +		.baseaddr      = TPM_TIS_BASE_ADDRESS,
   6.175 +		.activate      = tis_activate,
   6.176 +		.ready         = tis_ready,
   6.177 +		.senddata      = tis_senddata,
   6.178 +		.readresp      = tis_readresp,
   6.179 +		.waitdatavalid = tis_waitdatavalid,
   6.180 +		.waitrespready = tis_waitrespready,
   6.181 +		.probe         = tis_probe,
   6.182 +	},
   6.183 +};
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.h	Fri Jan 26 16:38:32 2007 +0000
     7.3 @@ -0,0 +1,18 @@
     7.4 +#ifndef TPM_DRIVER_H
     7.5 +/* low level driver implementation */
     7.6 +struct tpm_driver {
     7.7 +	uint32_t baseaddr;
     7.8 +	uint32_t (*activate)(uint32_t baseaddr);
     7.9 +	uint32_t (*ready)(uint32_t baseaddr);
    7.10 +	uint32_t (*senddata)(uint32_t baseaddr, unsigned char *data, uint32_t len);
    7.11 +	uint32_t (*readresp)(uint32_t baseaddr, unsigned char *buffer, uint32_t len);
    7.12 +	uint32_t (*waitdatavalid)(uint32_t baseaddr);
    7.13 +	uint32_t (*waitrespready)(uint32_t baseaddr, uint32_t timeout);
    7.14 +	uint32_t (*probe)(uint32_t baseaddr);
    7.15 +};
    7.16 +
    7.17 +#define TPM_NUM_DRIVERS      1
    7.18 +
    7.19 +#define TPM_INVALID_DRIVER  -1
    7.20 +
    7.21 +#endif
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/firmware/rombios/32bit/util.c	Fri Jan 26 16:38:32 2007 +0000
     8.3 @@ -0,0 +1,450 @@
     8.4 +/*
     8.5 + * util.c: Helper library functions for HVMLoader.
     8.6 + *
     8.7 + * Leendert van Doorn, leendert@watson.ibm.com
     8.8 + * Copyright (c) 2005, International Business Machines Corporation.
     8.9 + *
    8.10 + * This program is free software; you can redistribute it and/or modify it
    8.11 + * under the terms and conditions of the GNU General Public License,
    8.12 + * version 2, as published by the Free Software Foundation.
    8.13 + *
    8.14 + * This program is distributed in the hope it will be useful, but WITHOUT
    8.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    8.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
    8.17 + * more details.
    8.18 + *
    8.19 + * You should have received a copy of the GNU General Public License along with
    8.20 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    8.21 + * Place - Suite 330, Boston, MA 02111-1307 USA.
    8.22 + */
    8.23 +#include <stdarg.h>
    8.24 +#include <stdint.h>
    8.25 +#include "util.h"
    8.26 +
    8.27 +static void putchar(char c);
    8.28 +#define isdigit(c) ((c) >= '0' && (c) <= '9')
    8.29 +
    8.30 +void outb(uint16_t addr, uint8_t val)
    8.31 +{
    8.32 +    __asm__ __volatile__ ( "outb %%al, %%dx" :: "d"(addr), "a"(val) );
    8.33 +}
    8.34 +
    8.35 +void outw(uint16_t addr, uint16_t val)
    8.36 +{
    8.37 +    __asm__ __volatile__ ( "outw %%ax, %%dx" :: "d"(addr), "a"(val) );
    8.38 +}
    8.39 +
    8.40 +void outl(uint16_t addr, uint32_t val)
    8.41 +{
    8.42 +    __asm__ __volatile__ ( "outl %%eax, %%dx" :: "d"(addr), "a"(val) );
    8.43 +}
    8.44 +
    8.45 +uint8_t inb(uint16_t addr)
    8.46 +{
    8.47 +    uint8_t val;
    8.48 +    __asm__ __volatile__ ( "inb %%dx,%%al" : "=a" (val) : "d" (addr) );
    8.49 +    return val;
    8.50 +}
    8.51 +
    8.52 +uint16_t inw(uint16_t addr)
    8.53 +{
    8.54 +    uint16_t val;
    8.55 +    __asm__ __volatile__ ( "inw %%dx,%%ax" : "=a" (val) : "d" (addr) );
    8.56 +    return val;
    8.57 +}
    8.58 +
    8.59 +uint32_t inl(uint16_t addr)
    8.60 +{
    8.61 +    uint32_t val;
    8.62 +    __asm__ __volatile__ ( "inl %%dx,%%eax" : "=a" (val) : "d" (addr) );
    8.63 +    return val;
    8.64 +}
    8.65 +
    8.66 +char *itoa(char *a, unsigned int i)
    8.67 +{
    8.68 +    unsigned int _i = i, x = 0;
    8.69 +
    8.70 +    do {
    8.71 +        x++;
    8.72 +        _i /= 10;
    8.73 +    } while ( _i != 0 );
    8.74 +
    8.75 +    a += x;
    8.76 +    *a-- = '\0';
    8.77 +
    8.78 +    do {
    8.79 +        *a-- = (i % 10) + '0';
    8.80 +        i /= 10;
    8.81 +    } while ( i != 0 );
    8.82 +
    8.83 +    return a + 1;
    8.84 +}
    8.85 +
    8.86 +int strcmp(const char *cs, const char *ct)
    8.87 +{
    8.88 +    signed char res;
    8.89 +
    8.90 +    while ( ((res = *cs - *ct++) == 0) && (*cs++ != '\0') )
    8.91 +        continue;
    8.92 +
    8.93 +    return res;
    8.94 +}
    8.95 +
    8.96 +int strncmp(const char *s1, const char *s2, uint32_t n)
    8.97 +{
    8.98 +	uint32_t ctr;
    8.99 +	for (ctr = 0; ctr < n; ctr++)
   8.100 +		if (s1[ctr] != s2[ctr])
   8.101 +			return (int)(s1[ctr] - s2[ctr]);
   8.102 +	return 0;
   8.103 +}
   8.104 +
   8.105 +void *memcpy(void *dest, const void *src, unsigned n)
   8.106 +{
   8.107 +    int t0, t1, t2;
   8.108 +
   8.109 +    __asm__ __volatile__ (
   8.110 +        "cld\n"
   8.111 +        "rep; movsl\n"
   8.112 +        "testb $2,%b4\n"
   8.113 +        "je 1f\n"
   8.114 +        "movsw\n"
   8.115 +        "1: testb $1,%b4\n"
   8.116 +        "je 2f\n"
   8.117 +        "movsb\n"
   8.118 +        "2:"
   8.119 +        : "=&c" (t0), "=&D" (t1), "=&S" (t2)
   8.120 +        : "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
   8.121 +        : "memory" );
   8.122 +    return dest;
   8.123 +}
   8.124 +
   8.125 +void *memmove(void *dest, const void *src, unsigned n)
   8.126 +{
   8.127 +    if ( (long)dest > (long)src )
   8.128 +    {
   8.129 +        n--;
   8.130 +        while ( n > 0 )
   8.131 +        {
   8.132 +            ((char *)dest)[n] = ((char *)src)[n];
   8.133 +            n--;
   8.134 +        }
   8.135 +    }
   8.136 +    else
   8.137 +    {
   8.138 +        memcpy(dest, src, n);
   8.139 +    }
   8.140 +    return dest;
   8.141 +}
   8.142 +
   8.143 +char *
   8.144 +strcpy(char *dest, const char *src)
   8.145 +{
   8.146 +    char *p = dest;
   8.147 +    while ( *src )
   8.148 +        *p++ = *src++;
   8.149 +    *p = 0;
   8.150 +    return dest;
   8.151 +}
   8.152 +
   8.153 +char *
   8.154 +strncpy(char *dest, const char *src, unsigned n)
   8.155 +{
   8.156 +    int i = 0;
   8.157 +    char *p = dest;
   8.158 +
   8.159 +    /* write non-NUL characters from src into dest until we run
   8.160 +       out of room in dest or encounter a NUL in src */
   8.161 +    while ( (i < n) && *src )
   8.162 +    {
   8.163 +        *p++ = *src++;
   8.164 +        i++;
   8.165 +    }
   8.166 +
   8.167 +    /* pad remaining bytes of dest with NUL bytes */
   8.168 +    while ( i < n )
   8.169 +    {
   8.170 +        *p++ = 0;
   8.171 +        i++;
   8.172 +    }
   8.173 +
   8.174 +    return dest;
   8.175 +}
   8.176 +
   8.177 +unsigned
   8.178 +strlen(const char *s)
   8.179 +{
   8.180 +    int i = 0;
   8.181 +    while ( *s++ )
   8.182 +        i++;
   8.183 +    return i;
   8.184 +}
   8.185 +
   8.186 +void *
   8.187 +memset(void *s, int c, unsigned n)
   8.188 +{
   8.189 +    uint8_t b = (uint8_t) c;
   8.190 +    uint8_t *p = (uint8_t *)s;
   8.191 +    int i;
   8.192 +    for ( i = 0; i < n; i++ )
   8.193 +        *p++ = b;
   8.194 +    return s;
   8.195 +}
   8.196 +
   8.197 +int
   8.198 +memcmp(const void *s1, const void *s2, unsigned n)
   8.199 +{
   8.200 +    unsigned i;
   8.201 +    uint8_t *p1 = (uint8_t *) s1;
   8.202 +    uint8_t *p2 = (uint8_t *) s2;
   8.203 +
   8.204 +    for ( i = 0; i < n; i++ )
   8.205 +    {
   8.206 +        if ( p1[i] < p2[i] )
   8.207 +            return -1;
   8.208 +        else if ( p1[i] > p2[i] )
   8.209 +            return 1;
   8.210 +    }
   8.211 +
   8.212 +    return 0;
   8.213 +}
   8.214 +
   8.215 +void
   8.216 +cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
   8.217 +{
   8.218 +    __asm__ __volatile__ (
   8.219 +        "cpuid"
   8.220 +        : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
   8.221 +        : "0" (idx) );
   8.222 +}
   8.223 +
   8.224 +/* Write a two-character hex representation of 'byte' to digits[].
   8.225 +   Pre-condition: sizeof(digits) >= 2 */
   8.226 +void
   8.227 +byte_to_hex(char *digits, uint8_t byte)
   8.228 +{
   8.229 +    uint8_t nybbel = byte >> 4;
   8.230 +
   8.231 +    if ( nybbel > 9 )
   8.232 +        digits[0] = 'a' + nybbel-10;
   8.233 +    else
   8.234 +        digits[0] = '0' + nybbel;
   8.235 +
   8.236 +    nybbel = byte & 0x0f;
   8.237 +    if ( nybbel > 9 )
   8.238 +        digits[1] = 'a' + nybbel-10;
   8.239 +    else
   8.240 +        digits[1] = '0' + nybbel;
   8.241 +}
   8.242 +
   8.243 +/* Convert an array of 16 unsigned bytes to a DCE/OSF formatted UUID
   8.244 +   string.
   8.245 +
   8.246 +   Pre-condition: sizeof(dest) >= 37 */
   8.247 +void
   8.248 +uuid_to_string(char *dest, uint8_t *uuid)
   8.249 +{
   8.250 +    int i = 0;
   8.251 +    char *p = dest;
   8.252 +
   8.253 +    for ( i = 0; i < 4; i++ )
   8.254 +    {
   8.255 +        byte_to_hex(p, uuid[i]);
   8.256 +        p += 2;
   8.257 +    }
   8.258 +    *p++ = '-';
   8.259 +    for ( i = 4; i < 6; i++ )
   8.260 +    {
   8.261 +        byte_to_hex(p, uuid[i]);
   8.262 +        p += 2;
   8.263 +    }
   8.264 +    *p++ = '-';
   8.265 +    for ( i = 6; i < 8; i++ )
   8.266 +    {
   8.267 +        byte_to_hex(p, uuid[i]);
   8.268 +        p += 2;
   8.269 +    }
   8.270 +    *p++ = '-';
   8.271 +    for ( i = 8; i < 10; i++ )
   8.272 +    {
   8.273 +        byte_to_hex(p, uuid[i]);
   8.274 +        p += 2;
   8.275 +    }
   8.276 +    *p++ = '-';
   8.277 +    for ( i = 10; i < 16; i++ )
   8.278 +    {
   8.279 +        byte_to_hex(p, uuid[i]);
   8.280 +        p += 2;
   8.281 +    }
   8.282 +    *p = '\0';
   8.283 +}
   8.284 +
   8.285 +static char *printnum(char *p, unsigned long num, int base)
   8.286 +{
   8.287 +    unsigned long n;
   8.288 +
   8.289 +    if ( (n = num/base) > 0 )
   8.290 +        p = printnum(p, n, base);
   8.291 +    *p++ = "0123456789abcdef"[(int)(num % base)];
   8.292 +    *p = '\0';
   8.293 +    return p;
   8.294 +}
   8.295 +
   8.296 +static void _doprint(void (*put)(char), char const *fmt, va_list ap)
   8.297 +{
   8.298 +    register char *str, c;
   8.299 +    int lflag, zflag, nflag;
   8.300 +    char buffer[17];
   8.301 +    unsigned value;
   8.302 +    int i, slen, pad;
   8.303 +
   8.304 +    for ( ; *fmt != '\0'; fmt++ )
   8.305 +    {
   8.306 +        if ( *fmt != '%' )
   8.307 +        {
   8.308 +            put(*fmt);
   8.309 +            continue;
   8.310 +        }
   8.311 +
   8.312 +        pad = zflag = nflag = lflag = 0;
   8.313 +        c = *++fmt;
   8.314 +        if ( (c == '-') || isdigit(c) )
   8.315 +        {
   8.316 +            if ( c == '-' )
   8.317 +            {
   8.318 +                nflag = 1;
   8.319 +                c = *++fmt;
   8.320 +            }
   8.321 +            zflag = c == '0';
   8.322 +            for ( pad = 0; isdigit(c); c = *++fmt )
   8.323 +                pad = (pad * 10) + c - '0';
   8.324 +        }
   8.325 +        if ( c == 'l' ) /* long extension */
   8.326 +        {
   8.327 +            lflag = 1;
   8.328 +            c = *++fmt;
   8.329 +        }
   8.330 +        if ( (c == 'd') || (c == 'u') || (c == 'o') || (c == 'x') )
   8.331 +        {
   8.332 +            if ( lflag )
   8.333 +                value = va_arg(ap, unsigned);
   8.334 +            else
   8.335 +                value = (unsigned) va_arg(ap, unsigned int);
   8.336 +            str = buffer;
   8.337 +            printnum(str, value,
   8.338 +                     c == 'o' ? 8 : (c == 'x' ? 16 : 10));
   8.339 +            goto printn;
   8.340 +        }
   8.341 +        else if ( (c == 'O') || (c == 'D') || (c == 'X') )
   8.342 +        {
   8.343 +            value = va_arg(ap, unsigned);
   8.344 +            str = buffer;
   8.345 +            printnum(str, value,
   8.346 +                     c == 'O' ? 8 : (c == 'X' ? 16 : 10));
   8.347 +        printn:
   8.348 +            slen = strlen(str);
   8.349 +            for ( i = pad - slen; i > 0; i-- )
   8.350 +                put(zflag ? '0' : ' ');
   8.351 +            while ( *str )
   8.352 +                put(*str++);
   8.353 +        }
   8.354 +        else if ( c == 's' )
   8.355 +        {
   8.356 +            str = va_arg(ap, char *);
   8.357 +            slen = strlen(str);
   8.358 +            if ( nflag == 0 )
   8.359 +                for ( i = pad - slen; i > 0; i-- )
   8.360 +                    put(' ');
   8.361 +            while ( *str )
   8.362 +                put(*str++);
   8.363 +            if ( nflag )
   8.364 +                for ( i = pad - slen; i > 0; i-- )
   8.365 +                    put(' ');
   8.366 +        }
   8.367 +        else if ( c == 'c' )
   8.368 +        {
   8.369 +            put(va_arg(ap, int));
   8.370 +        }
   8.371 +        else
   8.372 +        {
   8.373 +            put(*fmt);
   8.374 +        }
   8.375 +    }
   8.376 +}
   8.377 +
   8.378 +static void putchar(char c)
   8.379 +{
   8.380 +    outb(0xe9, c);
   8.381 +}
   8.382 +
   8.383 +int printf(const char *fmt, ...)
   8.384 +{
   8.385 +    va_list ap;
   8.386 +
   8.387 +    va_start(ap, fmt);
   8.388 +    _doprint(putchar, fmt, ap);
   8.389 +    va_end(ap);
   8.390 +
   8.391 +    return 0;
   8.392 +}
   8.393 +
   8.394 +int vprintf(const char *fmt, va_list ap)
   8.395 +{
   8.396 +    _doprint(putchar, fmt, ap);
   8.397 +    return 0;
   8.398 +}
   8.399 +
   8.400 +
   8.401 +/*
   8.402 + * sleep by synchronizing with the PIT on channel 2
   8.403 + * http://bochs.sourceforge.net/techspec/intel-82c54-timer.pdf.gz
   8.404 + */
   8.405 +#define PIT_CTR2       0x80
   8.406 +#define PIT_CTR1       0x40
   8.407 +#define PIT_CTR0       0x00
   8.408 +
   8.409 +#define PIT_RW_LSB     0x10
   8.410 +
   8.411 +#define PIT_MODE0      0x0
   8.412 +
   8.413 +#define PIT_CTR_16BIT  0x0
   8.414 +
   8.415 +#define PIT_CMD_LATCH  0x0
   8.416 +
   8.417 +#define PORT_PIT_CMD     0x43
   8.418 +#define PORT_PIT_CTR2    0x42
   8.419 +#define PORT_PIT_CTR1    0x41
   8.420 +#define PORT_PIT_CTR0    0x40
   8.421 +
   8.422 +#define PIT_FREQ         1193182 /* Hz */
   8.423 +
   8.424 +#define PORT_PPI         0x61
   8.425 +
   8.426 +void mssleep(uint32_t waittime)
   8.427 +{
   8.428 +	long int timeout = 0;
   8.429 +	uint8_t last = 0x0;
   8.430 +	uint8_t old_ppi = inb(PORT_PPI);
   8.431 +
   8.432 +	/* use ctr2; ctr0 is used by the Bochs BIOS */
   8.433 +	/* ctr2 drives speaker -- turn it off */
   8.434 +	outb(PORT_PPI, old_ppi & 0xfc);
   8.435 +
   8.436 +	outb(PORT_PIT_CMD, PIT_CTR2 | PIT_RW_LSB | PIT_MODE0 | PIT_CTR_16BIT);
   8.437 +	outb(PORT_PIT_CTR2, last);         /* start countdown */
   8.438 +
   8.439 +	while (timeout < (waittime * PIT_FREQ / 1000)) {
   8.440 +		uint8_t cur, delta;
   8.441 +		outb(PORT_PIT_CMD, PIT_CTR2 | PIT_CMD_LATCH);
   8.442 +		cur = inb(PORT_PIT_CTR2);
   8.443 +		delta = last - cur;
   8.444 +		timeout += delta;
   8.445 +		last = cur;
   8.446 +	}
   8.447 +	/* turn ctr2 off */
   8.448 +	outb(PORT_PIT_CMD, PIT_CTR2 | PIT_RW_LSB | PIT_MODE0 | PIT_CTR_16BIT);
   8.449 +	outb(PORT_PIT_CTR2, 0xff); /* start countdown */
   8.450 +	outb(PORT_PIT_CTR2, 0x0);  /* stop */
   8.451 +
   8.452 +	outb(PORT_PPI, old_ppi);
   8.453 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/firmware/rombios/32bit/util.h	Fri Jan 26 16:38:32 2007 +0000
     9.3 @@ -0,0 +1,28 @@
     9.4 +#ifndef UTIL_H
     9.5 +#define UTIL_H
     9.6 +
     9.7 +void outb(uint16_t addr, uint8_t val);
     9.8 +void outw(uint16_t addr, uint16_t val);
     9.9 +void outl(uint16_t addr, uint32_t val);
    9.10 +uint8_t inb(uint16_t addr);
    9.11 +uint16_t inw(uint16_t addr);
    9.12 +uint32_t inl(uint16_t addr);
    9.13 +void mssleep(uint32_t time);
    9.14 +
    9.15 +char *itoa(char *a, unsigned int i);
    9.16 +int strcmp(const char *cs, const char *ct);
    9.17 +int strncmp(const char *s1, const char *s2, uint32_t n);
    9.18 +void *memcpy(void *dest, const void *src, unsigned n);
    9.19 +void *memmove(void *dest, const void *src, unsigned n);
    9.20 +char *strcpy(char *dest, const char *src);
    9.21 +char *strncpy(char *dest, const char *src, unsigned n);
    9.22 +unsigned strlen(const char *s);
    9.23 +void * memset(void *s, int c, unsigned n);
    9.24 +int memcmp(const void *s1, const void *s2, unsigned n);
    9.25 +void cpuid(uint32_t idx, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
    9.26 +void byte_to_hex(char *digits, uint8_t byte);
    9.27 +void uuid_to_string(char *dest, uint8_t *uuid);
    9.28 +int printf(const char *fmt, ...);
    9.29 +
    9.30 +
    9.31 +#endif
    10.1 --- a/tools/firmware/rombios/32bitgateway.c	Fri Jan 26 16:30:48 2007 +0000
    10.2 +++ b/tools/firmware/rombios/32bitgateway.c	Fri Jan 26 16:38:32 2007 +0000
    10.3 @@ -484,3 +484,5 @@ test_gateway()
    10.4  		printf("working correctly\n");
    10.5  	}
    10.6  }
    10.7 +
    10.8 +#include "tcgbios.c"
    11.1 --- a/tools/firmware/rombios/32bitprotos.h	Fri Jan 26 16:30:48 2007 +0000
    11.2 +++ b/tools/firmware/rombios/32bitprotos.h	Fri Jan 26 16:38:32 2007 +0000
    11.3 @@ -1,11 +1,29 @@
    11.4  #ifndef PROTOS_HIGHBIOS
    11.5  #define PROTOS_HIGHBIOS
    11.6  
    11.7 +
    11.8 +/* shared include file for bcc and gcc */
    11.9 +
   11.10  /* bcc does not like 'enum' */
   11.11 -#define IDX_MULTIPLY   0
   11.12 -#define IDX_ADD        1
   11.13 -#define IDX_SET_STATIC 2
   11.14 -#define IDX_LAST       3 /* keep last! */
   11.15 +#define IDX_MULTIPLY                       0
   11.16 +#define IDX_ADD                            1
   11.17 +#define IDX_SET_STATIC                     2
   11.18 +
   11.19 +#define IDX_TCGINTERRUPTHANDLER            3
   11.20 +#define IDX_TCPA_ACPI_INIT                 4
   11.21 +#define IDX_TCPA_EXTEND_ACPI_LOG           5
   11.22 +#define IDX_TCPA_CALLING_INT19H            6
   11.23 +#define IDX_TCPA_RETURNED_INT19H           7
   11.24 +#define IDX_TCPA_ADD_EVENT_SEPARATORS      8
   11.25 +#define IDX_TCPA_WAKE_EVENT                9
   11.26 +#define IDX_TCPA_ADD_BOOTDEVICE            10
   11.27 +#define IDX_TCPA_START_OPTION_ROM_SCAN     11
   11.28 +#define IDX_TCPA_OPTION_ROM                12
   11.29 +#define IDX_TCPA_IPL                       13
   11.30 +#define IDX_TCPA_INITIALIZE_TPM            14
   11.31 +#define IDX_TCPA_MEASURE_POST              15
   11.32 +
   11.33 +#define IDX_LAST                           16 /* keep last! */
   11.34  
   11.35  
   11.36  #ifdef GCC_PROTOS
   11.37 @@ -19,4 +37,19 @@ Bit32u multiply( PARMS(Bit32u a, Bit32u 
   11.38  Bit32u add( PARMS(Bit32u a, Bit32u b) );
   11.39  Bit32u set_static( PARMS(Bit32u) );
   11.40  
   11.41 +Bit32u TCGInterruptHandler( PARMS(pushad_regs_t *regs, Bit32u esds, Bit32u flags_ptr));
   11.42 +
   11.43 +void tcpa_acpi_init( PARMS(void) );
   11.44 +Bit32u tcpa_extend_acpi_log( PARMS(Bit32u entry_ptr) );
   11.45 +void tcpa_calling_int19h( PARMS(void) );
   11.46 +void tcpa_returned_int19h( PARMS(void) );
   11.47 +void tcpa_add_event_separators( PARMS(void) );
   11.48 +void tcpa_wake_event( PARMS(void) );
   11.49 +void tcpa_add_bootdevice( PARMS(Bit32u bootcd, Bit32u bootdrv) );
   11.50 +void tcpa_start_option_rom_scan( PARMS(void) );
   11.51 +void tcpa_option_rom( PARMS(Bit32u seg) );
   11.52 +void tcpa_ipl( PARMS(Bit32u seg) );
   11.53 +void tcpa_measure_post( PARMS(Bit32u from, Bit32u to) );
   11.54 +Bit32u tcpa_initialize_tpm( PARMS(Bit32u physpres) );
   11.55 +
   11.56  #endif
    12.1 --- a/tools/firmware/rombios/Makefile	Fri Jan 26 16:30:48 2007 +0000
    12.2 +++ b/tools/firmware/rombios/Makefile	Fri Jan 26 16:38:32 2007 +0000
    12.3 @@ -12,7 +12,7 @@ clean:
    12.4  	rm -f  rombios*.txt rombios*.sym usage biossums
    12.5  	rm -f  BIOS-bochs-*
    12.6  
    12.7 -BIOS-bochs-latest: rombios.c biossums 32bitgateway.c
    12.8 +BIOS-bochs-latest: rombios.c biossums 32bitgateway.c tcgbios.c
    12.9  	gcc -DBX_SMP_PROCESSORS=1 -E -P $< > _rombios_.c
   12.10  	bcc -o rombios.s -C-c -D__i86__ -0 -S _rombios_.c
   12.11  	sed -e 's/^\.text//' -e 's/^\.data//' rombios.s > _rombios_.s
    13.1 --- a/tools/firmware/rombios/rombios.c	Fri Jan 26 16:30:48 2007 +0000
    13.2 +++ b/tools/firmware/rombios/rombios.c	Fri Jan 26 16:38:32 2007 +0000
    13.3 @@ -154,6 +154,8 @@
    13.4  #define BX_USE_ATADRV    1
    13.5  #define BX_ELTORITO_BOOT 1
    13.6  
    13.7 +#define BX_TCGBIOS       0              /* main switch for TCG BIOS ext. */
    13.8 +
    13.9  #define BX_MAX_ATA_INTERFACES   4
   13.10  #define BX_MAX_ATA_DEVICES      (BX_MAX_ATA_INTERFACES*2)
   13.11  
   13.12 @@ -1854,6 +1856,9 @@ print_bios_banner()
   13.13  {
   13.14    printf(BX_APPNAME" BIOS, %d cpu%s, ", BX_SMP_PROCESSORS, BX_SMP_PROCESSORS>1?"s":"");
   13.15    printf("%s %s\n", bios_cvs_version_string, bios_date_string);
   13.16 +#if BX_TCGBIOS
   13.17 +  printf("TCG-enabled BIOS.\n");
   13.18 +#endif
   13.19    printf("\n");
   13.20    test_gateway();
   13.21  }
   13.22 @@ -5717,6 +5722,10 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, 
   13.23      BX_INFO("int13_cdemu: function %02x, emulation not active for DL= %02x\n", GET_AH(), GET_DL());
   13.24      goto int13_fail;
   13.25      }
   13.26 +
   13.27 +#if BX_TCGBIOS
   13.28 +  tcpa_ipl((Bit32u)bootseg);               /* specs: 8.2.3 steps 4 and 5 */
   13.29 +#endif
   13.30    
   13.31    switch (GET_AH()) {
   13.32  
   13.33 @@ -9504,6 +9513,9 @@ rom_scan:
   13.34    ;;   2         ROM length in 512-byte blocks
   13.35    ;;   3         ROM initialization entry point (FAR CALL)
   13.36  
   13.37 +#if BX_TCGBIOS
   13.38 +  call _tcpa_start_option_rom_scan    /* specs: 3.2.3.3 + 10.4.3 */
   13.39 +#endif
   13.40    mov  cx, #0xc000
   13.41  rom_scan_loop:
   13.42    mov  ds, cx
   13.43 @@ -9522,6 +9534,20 @@ rom_scan_loop:
   13.44    add  al, #0x04
   13.45  block_count_rounded:
   13.46  
   13.47 +#if BX_TCGBIOS
   13.48 +  push ax
   13.49 +  push ds
   13.50 +  push ecx
   13.51 +  xor ax, ax
   13.52 +  mov ds, ax
   13.53 +  and ecx, #0xffff
   13.54 +  push ecx       ;; segment where option rom is located at
   13.55 +  call _tcpa_option_rom                   /* specs: 3.2.3.3 */
   13.56 +  add sp, #4    ;; pop segment
   13.57 +  pop ecx	;; original ecx
   13.58 +  pop ds
   13.59 +  pop ax
   13.60 +#endif
   13.61    xor  bx, bx   ;; Restore DS back to 0000:
   13.62    mov  ds, bx
   13.63    push ax       ;; Save AX
   13.64 @@ -9827,6 +9853,16 @@ post_default_ints:
   13.65    in   al, 0x71
   13.66    mov  0x0410, ax
   13.67  
   13.68 +#if BX_TCGBIOS
   13.69 +  call _tcpa_acpi_init
   13.70 +
   13.71 +  push dword #0
   13.72 +  call _tcpa_initialize_tpm
   13.73 +  add sp, #4
   13.74 +
   13.75 +  call _tcpa_do_measure_POSTs
   13.76 +  call _tcpa_wake_event     /* specs: 3.2.3.7 */
   13.77 +#endif
   13.78  
   13.79    ;; Parallel setup
   13.80    SET_INT_VECTOR(0x0F, #0xF000, #dummy_iret_handler)
   13.81 @@ -9949,9 +9985,16 @@ post_default_ints:
   13.82    ;;
   13.83  #endif // BX_ELTORITO_BOOT
   13.84   
   13.85 +#if BX_TCGBIOS
   13.86 +  call _tcpa_calling_int19h          /* specs: 8.2.3 step 1 */
   13.87 +  call _tcpa_add_event_separators    /* specs: 8.2.3 step 2 */
   13.88 +#endif
   13.89    int  #0x19
   13.90    //JMP_EP(0x0064) ; INT 19h location
   13.91  
   13.92 +#if BX_TCGBIOS
   13.93 +  call _tcpa_returned_int19h         /* specs: 8.2.3 step 3/7 */
   13.94 +#endif
   13.95  
   13.96  .org 0xe2c3 ; NMI Handler Entry Point
   13.97  nmi:
   13.98 @@ -10434,6 +10477,21 @@ db 0x00    ;; base  23:16
   13.99  ;----------
  13.100  .org 0xfe6e ; INT 1Ah Time-of-day Service Entry Point
  13.101  int1a_handler:
  13.102 +#if BX_TCGBIOS
  13.103 +  cmp  ah, #0xbb
  13.104 +  jne  no_tcg
  13.105 +  pushf
  13.106 +  push ds
  13.107 +  push es
  13.108 +  pushad
  13.109 +  call _int1a_function32
  13.110 +  popad
  13.111 +  pop es
  13.112 +  pop ds
  13.113 +  popf
  13.114 +  iret
  13.115 +no_tcg:
  13.116 +#endif
  13.117  #if BX_PCIBIOS
  13.118    cmp  ah, #0xb1
  13.119    jne  int1a_normal
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/firmware/rombios/tcgbios.c	Fri Jan 26 16:38:32 2007 +0000
    14.3 @@ -0,0 +1,263 @@
    14.4 +/*
    14.5 + * Implementation of stub functions for calls to the TCG BIOS
    14.6 + * extension in 32bit memory area.
    14.7 + *
    14.8 + *  This library is free software; you can redistribute it and/or
    14.9 + *  modify it under the terms of the GNU Lesser General Public
   14.10 + *  License as published by the Free Software Foundation; either
   14.11 + *  version 2 of the License, or (at your option) any later version.
   14.12 + *
   14.13 + *  This library is distributed in the hope that it will be useful,
   14.14 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   14.15 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14.16 + *  Lesser General Public License for more details.
   14.17 + *
   14.18 + *  You should have received a copy of the GNU Lesser General Public
   14.19 + *  License along with this library; if not, write to the Free Software
   14.20 + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   14.21 + *
   14.22 + * Copyright (C) IBM Corporation, 2006
   14.23 + *
   14.24 + * Author: Stefan Berger <stefanb@us.ibm.com>
   14.25 + */
   14.26 +
   14.27 +/*******************************************************************
   14.28 +  Support for TCPA ACPI logging
   14.29 + ******************************************************************/
   14.30 +
   14.31 +/*
   14.32 + * Extend the ACPI log with the given entry by copying the
   14.33 + * entry data into the log.
   14.34 + * Input
   14.35 + *  Pointer to the structure to be copied into the log
   14.36 + *
   14.37 + * Output:
   14.38 + *  lower 16 bits of return code contain entry number
   14.39 + *  if entry number is '0', then upper 16 bits contain error code.
   14.40 + */
   14.41 +Bit32u tcpa_extend_acpi_log(entry_ptr)
   14.42 +    Bit32u entry_ptr;
   14.43 +{
   14.44 +	ASM_START
   14.45 +	DoUpcall IDX_TCPA_EXTEND_ACPI_LOG
   14.46 +	ASM_END
   14.47 +}
   14.48 +
   14.49 +
   14.50 +/*
   14.51 +   initialize the TCPA ACPI subsystem; find the ACPI tables and determine
   14.52 +   where the TCPA table is.
   14.53 + */
   14.54 + void
   14.55 +tcpa_acpi_init()
   14.56 +{
   14.57 +	ASM_START
   14.58 +	DoUpcall IDX_TCPA_ACPI_INIT
   14.59 +	ASM_END
   14.60 +}
   14.61 +
   14.62 +
   14.63 +/*
   14.64 + * Add measurement to log about call of int 19h
   14.65 + */
   14.66 + void
   14.67 +tcpa_calling_int19h()
   14.68 +{
   14.69 +	ASM_START
   14.70 +	DoUpcall IDX_TCPA_CALLING_INT19H
   14.71 +	ASM_END
   14.72 +}
   14.73 +
   14.74 +/*
   14.75 + * Add measurement to log about retuning from int 19h
   14.76 + */
   14.77 + void
   14.78 +tcpa_returned_int19h()
   14.79 +{
   14.80 +	ASM_START
   14.81 +	DoUpcall IDX_TCPA_RETURNED_INT19H
   14.82 +	ASM_END
   14.83 +}
   14.84 +
   14.85 +/*
   14.86 + * Add event separators for PCRs 0 to 7; specs 8.2.3
   14.87 + */
   14.88 + void
   14.89 +tcpa_add_event_separators()
   14.90 +{
   14.91 +	ASM_START
   14.92 +	DoUpcall IDX_TCPA_ADD_EVENT_SEPARATORS
   14.93 +	ASM_END
   14.94 +}
   14.95 +
   14.96 +
   14.97 +/*
   14.98 + * Add a wake event to the log
   14.99 + */
  14.100 + void
  14.101 +tcpa_wake_event()
  14.102 +{
  14.103 +	ASM_START
  14.104 +	DoUpcall IDX_TCPA_WAKE_EVENT
  14.105 +	ASM_END
  14.106 +}
  14.107 +
  14.108 +
  14.109 +/*
  14.110 + * Add measurement to the log about option rom scan
  14.111 + * 10.4.3 : action 14
  14.112 + */
  14.113 + void
  14.114 +tcpa_start_option_rom_scan()
  14.115 +{
  14.116 +	ASM_START
  14.117 +	DoUpcall IDX_TCPA_START_OPTION_ROM_SCAN
  14.118 +	ASM_END
  14.119 +}
  14.120 +
  14.121 +
  14.122 +/*
  14.123 + * Add measurement to the log about an option rom
  14.124 + */
  14.125 + void
  14.126 +tcpa_option_rom(seg)
  14.127 +    Bit32u seg;
  14.128 +{
  14.129 +	ASM_START
  14.130 +	DoUpcall IDX_TCPA_OPTION_ROM
  14.131 +	ASM_END
  14.132 +}
  14.133 +
  14.134 +/*
  14.135 + * Add a measurement regarding the boot device (CDRom, Floppy, HDD) to
  14.136 + * the list of measurements.
  14.137 + */
  14.138 +void
  14.139 + tcpa_add_bootdevice(bootcd, bootdrv)
  14.140 +  Bit32u bootcd;
  14.141 +  Bit32u bootdrv;
  14.142 +{
  14.143 +	ASM_START
  14.144 +	DoUpcall IDX_TCPA_ADD_BOOTDEVICE
  14.145 +	ASM_END
  14.146 +}
  14.147 +
  14.148 +/*
  14.149 + * Add a measurement to the log in support of 8.2.5.3
  14.150 + * Creates two log entries
  14.151 + *
  14.152 + * Input parameter:
  14.153 + *  seg    : segment where the IPL data are located
  14.154 + */
  14.155 + void
  14.156 +tcpa_ipl(seg)
  14.157 +    Bit32u seg;
  14.158 +{
  14.159 +	ASM_START
  14.160 +	DoUpcall IDX_TCPA_IPL
  14.161 +	ASM_END
  14.162 +}
  14.163 +
  14.164 +
  14.165 +Bit32u
  14.166 +tcpa_initialize_tpm(physpres)
  14.167 +  Bit32u physpres;
  14.168 +{
  14.169 +	ASM_START
  14.170 +	DoUpcall IDX_TCPA_INITIALIZE_TPM
  14.171 +	ASM_END
  14.172 +}
  14.173 +
  14.174 +void
  14.175 +tcpa_measure_post(from, to)
  14.176 +   Bit32u from;
  14.177 +   Bit32u to;
  14.178 +{
  14.179 +	ASM_START
  14.180 +	DoUpcall IDX_TCPA_MEASURE_POST
  14.181 +	ASM_END
  14.182 +}
  14.183 +
  14.184 +ASM_START
  14.185 +MACRO POST_MEASURE
  14.186 +	push word #0x000f
  14.187 +	push #?2
  14.188 +	push word #0x000f
  14.189 +	push #?1
  14.190 +	call _tcpa_measure_post
  14.191 +	add sp, #8
  14.192 +MEND
  14.193 +ASM_END
  14.194 +
  14.195 +void
  14.196 +tcpa_do_measure_POSTs()
  14.197 +{
  14.198 +	ASM_START
  14.199 +
  14.200 +	POST_MEASURE post, nmi
  14.201 +	POST_MEASURE floppy_drive_post, hard_drive_post
  14.202 +	POST_MEASURE hard_drive_post, ebda_post
  14.203 +	POST_MEASURE ebda_post, eoi_jmp_post
  14.204 +	POST_MEASURE eoi_jmp_post, timer_tick_post
  14.205 +	POST_MEASURE timer_tick_post, int76_handler
  14.206 +
  14.207 +	ret
  14.208 +	ASM_END
  14.209 +}
  14.210 +
  14.211 +Bit32u
  14.212 +TCGInterruptHandler(regs_ptr, es, ds, flags_ptr)
  14.213 +   Bit32u regs_ptr;
  14.214 +   Bit16u es;
  14.215 +   Bit16u ds;
  14.216 +   Bit32u flags_ptr;
  14.217 +{
  14.218 +	ASM_START
  14.219 +	DoUpcall IDX_TCGINTERRUPTHANDLER
  14.220 +	ASM_END
  14.221 +}
  14.222 +
  14.223 +/*
  14.224 + * C-dispatcher for the TCG BIOS functions
  14.225 + */
  14.226 +#define TCG_MAGIC 0x41504354L
  14.227 +  void
  14.228 +int1a_function32(regs, ES, DS, FLAGS)
  14.229 +  pushad_regs_t regs;
  14.230 +  Bit16u ES, DS, FLAGS;
  14.231 +{
  14.232 +	Bit16u rc;
  14.233 +
  14.234 +	switch (regs.u.r8.ah) {
  14.235 +	case 0xbb:
  14.236 +		/*
  14.237 +		 * all functions except for TCG_StatusCheck need to have the
  14.238 +		 * TCG_MAGIC in 'ebx'.
  14.239 +		 */
  14.240 +		if (regs.u.r8.al != 0 &&
  14.241 +		    regs.u.r32.ebx != TCG_MAGIC) {
  14.242 +		    SET_CF();
  14.243 +		    return;
  14.244 +		}
  14.245 +		switch(regs.u.r8.al) {
  14.246 +		case 0x00:
  14.247 +		case 0x01:
  14.248 +		case 0x02:
  14.249 +		case 0x03:
  14.250 +		case 0x04:
  14.251 +		case 0x05:
  14.252 +		case 0x06:
  14.253 +		case 0x07:
  14.254 +			TCGInterruptHandler(((Bit32u)get_SS() << 4) + (Bit32u)&regs,
  14.255 +			                    ES, DS,
  14.256 +			                    ((Bit32u)get_SS() << 4) + (Bit32u)&FLAGS);
  14.257 +			break;
  14.258 +
  14.259 +		default:
  14.260 +			SET_CF();
  14.261 +		}
  14.262 +	default:
  14.263 +		SET_CF();
  14.264 +		break;
  14.265 +	}
  14.266 +}