debuggers.hg
changeset 13681: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>
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>
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 + ®s->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)®s, 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 +}