ia64/xen-unstable

view tools/firmware/rombios/32bit/tcgbios/tcgbios.c @ 17413:29389310884f

hvmloader: Build with -Werror.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Apr 09 13:52:52 2008 +0100 (2008-04-09)
parents fd09283562e2
children 750eee596adf
line source
1 /*
2 * Implementation of the TCG BIOS extension according to the specification
3 * described in
4 * https://www.trustedcomputinggroup.org/specs/PCClient/TCG_PCClientImplementationforBIOS_1-20_1-00.pdf
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * Copyright (C) IBM Corporation, 2006
21 *
22 * Author: Stefan Berger <stefanb@us.ibm.com>
23 */
24 #include "rombios_compat.h"
25 #include "tpm_drivers.h"
27 #include "tcgbios.h"
28 #include "32bitprotos.h"
29 #include "util.h"
32 /* local structure and variables */
33 struct ptti_cust {
34 uint16_t ipblength;
35 uint16_t reserved;
36 uint16_t opblength;
37 uint16_t reserved2;
38 uint8_t tpmoperandin[18];
39 } __attribute__((packed));
41 struct ptti_cust CMD_TPM_Startup_0x01_IPB = {
42 0x8+0xc, 0x00, 4+10, 0x00,
43 { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x99, 0x00, 0x01 },
44 };
46 struct ptti_cust CMD_TSC_PhysicalPresence_0x20_IPB = {
47 0x8+0xc, 0x00, 4+10, 0x00,
48 { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x20 },
49 };
51 struct ptti_cust CMD_TSC_PhysicalPresence_0x08_IPB = {
52 0x8+0xc, 0x00, 4+10, 0x00,
53 { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x08 },
54 };
56 struct ptti_cust CMD_TSC_PhysicalPresence_0x100_IPB = {
57 0x8+0xc, 0x00, 4+10, 0x00,
58 { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x01, 0x00 },
59 };
61 struct ptti_cust CMD_TSC_PhysicalPresence_0x10_IPB = {
62 0x8+0xc, 0x00, 4+10, 0x00,
63 { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x0a, 0x00, 0x10 },
64 };
66 struct ptti_cust CMD_TPM_PhysicalEnable_IPB = {
67 0x8+0xa, 0x00, 4+10, 0x00,
68 { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x6f },
69 };
71 struct ptti_cust CMD_TPM_PhysicalSetDeactivated_0x00_IPB = {
72 0x8+0xb, 0x00, 4+10, 0x00,
73 { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x72, 0x00 }
74 };
75 struct ptti_cust CMD_TPM_SHA1Start_IPB = {
76 0x8+0xa, 0x00, 4+10, 0x00,
77 { 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xa0 },
78 };
80 struct ptti_cust CMD_TPM_GetCap_Version_IPB = {
81 0x8+0x12, 0x00, 4+18, 0x00,
82 {0x00, 0xc1, 0x00, 0x00, 0x00, 0x12,
83 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00 },
84 };
86 struct ptti_cust *TCG_CommandList[] = {
87 &CMD_TPM_Startup_0x01_IPB,
88 &CMD_TSC_PhysicalPresence_0x20_IPB,
89 &CMD_TSC_PhysicalPresence_0x08_IPB,
90 &CMD_TSC_PhysicalPresence_0x100_IPB,
91 &CMD_TSC_PhysicalPresence_0x10_IPB,
92 &CMD_TPM_PhysicalEnable_IPB,
93 &CMD_TPM_PhysicalSetDeactivated_0x00_IPB,
94 &CMD_TPM_SHA1Start_IPB,
95 };
97 /* local function prototypes */
98 static void sha1(const unsigned char *data, uint32_t length,
99 unsigned char *hash);
100 static uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx);
101 static uint32_t HashAll32(struct hai *hai, unsigned char *hash,
102 uint32_t magic, uint32_t ecx, uint32_t edx);
103 static uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s,
104 struct hleeo *hleeo,
105 uint32_t magic, uint32_t ecx,
106 uint32_t edx);
107 static uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo,
108 uint32_t ebx, uint32_t ecx, uint32_t edx);
109 static uint32_t PassThroughToTPM32(struct pttti *pttti, struct pttto *pttto,
110 uint32_t magic, uint32_t ecx, uint32_t edx);
111 static uint32_t MA_Transmit(unsigned char *cmdbuffer,
112 unsigned char *respbuffer,
113 uint32_t respbufferlen);
115 static unsigned char *tcpa_get_lasa_last_ptr(void);
116 static unsigned char *tcpa_get_lasa_base_ptr(void);
117 static void tcpa_reset_acpi_log(void);
118 static uint32_t tcpa_get_laml(void);
121 extern struct tpm_driver tpm_drivers[];
123 /* utility functions */
125 static inline uint32_t bswap(uint32_t a)
126 {
127 return ( ( a >> 24 ) & 0x000000ff) |
128 ( ( a >> 8 ) & 0x0000ff00) |
129 ( ( a << 8 ) & 0x00ff0000) |
130 ( ( a << 24 ) & 0xff000000);
131 }
133 /********************************************************
134 Extensions for TCG-enabled BIOS
135 *******************************************************/
137 typedef struct {
138 struct acpi_20_tcpa *tcpa_ptr;
139 unsigned char *lasa_last_ptr;
140 uint16_t entry_count;
141 uint16_t flags;
142 } tcpa_acpi_t;
144 static tcpa_acpi_t tcpa_acpi;
147 /* low level driver implementation */
148 static int tpm_driver_to_use = TPM_INVALID_DRIVER;
150 static
151 uint32_t MA_IsTPMPresent(void)
152 {
153 uint32_t rc = 0;
154 unsigned int i;
155 for (i = 0; i < TPM_NUM_DRIVERS; i++) {
156 struct tpm_driver *td = &tpm_drivers[i];
157 if (td->probe(td->baseaddr) != 0) {
158 tpm_driver_to_use = i;
159 rc = 1;
160 break;
161 }
162 }
163 return rc;
164 }
166 static
167 uint32_t MA_InitTPM(uint16_t startupcode)
168 {
169 uint32_t rc = 0;
170 /* low-level initialize the TPM */
171 unsigned char command[sizeof(CMD_TPM_Startup_0x01_IPB.tpmoperandin)];
172 unsigned char response[10];
173 uint32_t response_size = sizeof(response);
175 memcpy(command,
176 CMD_TPM_Startup_0x01_IPB.tpmoperandin,
177 sizeof(CMD_TPM_Startup_0x01_IPB.tpmoperandin));
178 command[10] = (startupcode >> 8) & 0xff;
179 command[11] = (startupcode >> 0) & 0xff;
180 rc = MA_Transmit(command, response, response_size);
182 return rc;
183 }
185 static
186 uint32_t MA_Transmit(unsigned char *cmdbuffer, unsigned char *respbuffer,
187 uint32_t respbufferlen)
188 {
189 uint32_t rc = 0;
190 uint32_t irc;
191 struct tpm_driver *td;
193 if (tpm_driver_to_use == TPM_INVALID_DRIVER)
194 return TCG_FATAL_COM_ERROR;
196 td = &tpm_drivers[tpm_driver_to_use];
198 if (rc == 0) {
199 irc = td->activate(td->baseaddr);
200 if (irc == 0) {
201 /* tpm could not be activated */
202 rc = TCG_FATAL_COM_ERROR;
203 }
204 }
206 if (rc == 0) {
207 uint32_t *tmp = (uint32_t *)&cmdbuffer[2];
208 uint32_t len = bswap(*tmp);
209 irc = td->senddata(td->baseaddr,
210 cmdbuffer,
211 len);
212 if (irc != 0) {
213 rc = TCG_FATAL_COM_ERROR;
214 }
215 }
217 if (rc == 0) {
218 irc = td->waitdatavalid(td->baseaddr);
219 if (irc != 0) {
220 rc = TCG_FATAL_COM_ERROR;
221 }
222 }
224 if (rc == 0) {
225 irc = td->waitrespready(td->baseaddr, 2000);
226 if (irc != 0) {
227 rc = TCG_FATAL_COM_ERROR;
228 }
229 }
231 if (rc == 0) {
232 irc = td->readresp(td->baseaddr,
233 respbuffer,
234 respbufferlen);
235 if (irc != 0) {
236 rc = TCG_FATAL_COM_ERROR;
237 }
238 }
240 if (rc == 0) {
241 irc = td->ready(td->baseaddr);
242 }
244 return rc;
245 }
248 static
249 uint8_t acpi_validate_entry(struct acpi_header *hdr)
250 {
251 uint8_t sum = 0;
252 unsigned int length = hdr->length;
253 unsigned int ctr;
254 unsigned char *addr = (unsigned char *)hdr;
256 for (ctr = 0; ctr < length; ctr++)
257 sum += addr[ctr];
259 return sum;
260 }
263 /*
264 * Search for the RSDP ACPI table in the memory starting at addr and
265 * ending at addr + len - 1.
266 */
267 static struct acpi_20_rsdp *find_rsdp(const void *start, unsigned int len)
268 {
269 char *rsdp = (char *)start;
270 char *end = rsdp + len;
271 /* scan memory in steps of 16 bytes */
272 while (rsdp < end) {
273 /* check for expected string */
274 if (!strncmp( rsdp, "RSD PTR ", 8))
275 return (struct acpi_20_rsdp *)rsdp;
276 rsdp += 0x10;
277 }
278 return 0;
279 }
281 void tcpa_acpi_init(void)
282 {
283 struct acpi_20_rsdt *rsdt;
284 struct acpi_20_tcpa *tcpa = (void *)0;
285 struct acpi_20_rsdp *rsdp;
286 uint32_t length;
287 uint16_t off;
288 int found = 0;
289 uint16_t ebda_seg;
291 if (MA_IsTPMPresent() == 0) {
292 return;
293 }
295 /* RSDP in EBDA? */
296 ebda_seg = *(uint16_t *)ADDR_FROM_SEG_OFF(0x40, 0xe);
297 rsdp = find_rsdp((void *)(ebda_seg << 16), 1024);
299 if (!rsdp)
300 rsdp = find_rsdp((void *)(ACPI_SEGMENT << 4), 0x20000);
302 if (rsdp) {
303 uint32_t ctr = 0;
304 /* get RSDT from RSDP */
305 rsdt = (struct acpi_20_rsdt *)rsdp->rsdt_address;
306 length = rsdt->header.length;
307 off = 36;
308 while ((off + 3) < length) {
309 /* try all pointers to structures */
310 tcpa = (struct acpi_20_tcpa *)rsdt->entry[ctr];
311 /* valid TCPA ACPI table ? */
312 if (ACPI_2_0_TCPA_SIGNATURE == tcpa->header.signature
313 && acpi_validate_entry(&tcpa->header) == 0) {
314 found = 1;
315 break;
316 }
317 off += 4;
318 ctr++;
319 }
320 }
322 if (found == 0) {
323 printf("TCPA ACPI was NOT found!\n");
324 tcpa = 0;
325 }
327 tcpa_acpi.tcpa_ptr = tcpa;
328 tcpa_acpi.lasa_last_ptr = 0;
329 tcpa_acpi.entry_count = 0;
330 tcpa_acpi.flags = 0;
331 tcpa_reset_acpi_log();
332 }
334 /* clear the ACPI log */
335 static void tcpa_reset_acpi_log(void)
336 {
337 unsigned char *lasa = tcpa_get_lasa_base_ptr();
338 if (lasa)
339 memset(lasa, 0x0, tcpa_get_laml());
340 }
343 uint32_t tcpa_extend_acpi_log(uint32_t entry_ptr)
344 {
345 uint32_t res = 0;
346 unsigned char *lasa_last = tcpa_get_lasa_last_ptr();
347 unsigned char *lasa_base = tcpa_get_lasa_base_ptr();
348 uint32_t size;
349 uint16_t entry_count = tcpa_acpi.entry_count;
350 struct pcpes *pcpes = (struct pcpes *)entry_ptr;
352 if (lasa_last == 0) {
353 lasa_last = lasa_base;
354 } else {
355 struct pcpes *pcpes = (struct pcpes *)lasa_last;
356 /* skip the last entry in the log */
357 size = pcpes->eventdatasize;
358 size += 32;
359 lasa_last += size;
360 }
362 if (lasa_last == 0) {
363 res = ((uint32_t)TCG_PC_LOGOVERFLOW << 16);
364 }
366 if (res == 0) {
367 uint32_t laml = tcpa_get_laml();
368 size = pcpes->eventdatasize;
369 size += 32;
370 if ((lasa_last + size - lasa_base) > laml) {
371 res = (TCG_PC_LOGOVERFLOW << 16);
372 }
373 }
375 if (res == 0) {
376 /* copy the log entry into the ACPI log */
377 memcpy((char *)lasa_last, (char *)entry_ptr, size);
378 /*
379 * update the pointers and entry counter that were modified
380 * due to the new entry in the log
381 */
382 tcpa_acpi.lasa_last_ptr = lasa_last;
383 entry_count++;
384 tcpa_acpi.entry_count = entry_count;
386 res = entry_count;
387 }
388 return res;
389 }
391 static
392 unsigned char *tcpa_get_lasa_last_ptr(void)
393 {
394 return tcpa_acpi.lasa_last_ptr;
395 }
397 static
398 unsigned char *tcpa_get_lasa_base_ptr(void)
399 {
400 unsigned char *lasa = 0;
401 struct acpi_20_tcpa *tcpa = tcpa_acpi.tcpa_ptr;
402 if (tcpa != 0) {
403 uint32_t class = tcpa->platform_class;
404 if (class == TCPA_ACPI_CLASS_CLIENT) {
405 /* client type */
406 lasa = (unsigned char *)(long)tcpa->u.client.lasa;
407 } else if (class == TCPA_ACPI_CLASS_SERVER) {
408 /* server type */
409 lasa = (unsigned char *)(long)tcpa->u.server.lasa;
410 }
411 }
412 return lasa;
413 }
415 static
416 uint32_t tcpa_get_laml(void)
417 {
418 uint32_t laml = 0;
419 struct acpi_20_tcpa *tcpa = tcpa_acpi.tcpa_ptr;
420 if (tcpa != 0) {
421 uint32_t class = tcpa->platform_class;
422 if (class == TCPA_ACPI_CLASS_CLIENT) {
423 /* client type */
424 laml = tcpa->u.client.laml;
425 } else if (class == TCPA_ACPI_CLASS_SERVER) {
426 laml = tcpa->u.server.laml;
427 }
428 }
429 return laml;
430 }
434 /*
435 * Add a measurement to the log; the data at data_seg:data/length are
436 * appended to the TCG_PCClientPCREventStruct
437 *
438 * Input parameters:
439 * pcrIndex : which PCR to extend
440 * event_type : type of event; specs 10.4.1
441 * event_id : (unused)
442 * data : pointer to the data (i.e., string) to be added to the log
443 * length : length of the data
444 */
445 static uint16_t
446 tcpa_add_measurement_to_log(uint32_t pcrIndex,
447 uint32_t event_type,
448 uint32_t event_id,
449 const char *data_ptr,
450 uint32_t length)
451 {
452 uint32_t rc = 0;
453 struct hleei_short hleei;
454 struct hleeo hleeo;
455 uint8_t _pcpes[32+400];
456 struct pcpes *pcpes = (struct pcpes *)_pcpes;
457 uint8_t *data = (uint8_t *)data_ptr;
459 if (length < sizeof(_pcpes)-32) {
460 memset(pcpes, 0x0, 32);
461 pcpes->pcrindex = pcrIndex;
462 pcpes->eventtype = event_type;
463 pcpes->eventdatasize = length;
464 memcpy(&_pcpes[32], data, length);
466 hleei.ipblength = 0x18;
467 hleei.reserved = 0x0;
468 hleei.hashdataptr = (uint32_t)&_pcpes[32];
469 hleei.hashdatalen = length;
470 hleei.pcrindex = pcrIndex;
471 hleei.logdataptr = (uint32_t)_pcpes;
472 hleei.logdatalen = length + 32;
473 rc = HashLogExtendEvent32(&hleei,
474 &hleeo,
475 TCG_MAGIC,
476 0x0,
477 0x0);
478 } else {
479 rc = (TCG_PC_TPMERROR |
480 ((uint32_t)TCG_GENERAL_ERROR << 16));
481 }
483 return rc;
484 }
486 static
487 uint16_t tcpa_add_pcpes_to_log(struct pcpes *pcpes)
488 {
489 uint32_t rc = 0;
490 struct hleei_short hleei;
491 struct hleeo hleeo;
493 hleei.ipblength = 0x18;
494 hleei.reserved = 0x0;
495 hleei.hashdataptr = 0;
496 hleei.hashdatalen = 0;
497 hleei.pcrindex = pcpes->pcrindex;
498 hleei.logdataptr = (uint32_t)pcpes;
499 hleei.logdatalen = sizeof(pcpes);
501 rc = HashLogExtendEvent32(&hleei,
502 &hleeo,
503 TCG_MAGIC,
504 0x0,
505 0x0);
507 return rc;
508 }
511 /*
512 * Add a measurement to the log; further description of the data
513 * that are to be hashed are NOT appended to the TCG_PCClientPCREventStruc.
514 * Input parameters:
515 * pcrIndex : PCR to extend
516 * event_type : type of event; specs 10.4.1
517 * ptr : 32 bit pointer to the data to be hashed
518 * length : length of the data to be hashed
519 *
520 * Returns lower 16 bit of return code of TCG_HashLogExtendEvent. '0' means
521 * success, otherwise an error is indicated.
522 */
523 static
524 uint16_t tcpa_add_measurement_to_log_simple(uint32_t pcrIndex,
525 uint16_t event_type,
526 uint8_t *ptr, uint32_t length)
527 {
528 uint32_t rc = 0;
529 struct hleei_short hleei;
530 struct hleeo hleeo;
531 struct pcpes pcpes;
533 memset(&pcpes, 0x0, sizeof(pcpes));
534 pcpes.pcrindex = pcrIndex;
535 pcpes.eventtype = event_type;
536 /* specs: 10.4.1, EV_IPL eventfield should not contain the code.*/
537 pcpes.eventdatasize = 0;
539 hleei.ipblength = 0x18;
540 hleei.reserved = 0x0;
541 hleei.hashdataptr = (uint32_t)ptr;
542 hleei.hashdatalen = length;
543 hleei.pcrindex = pcrIndex;
544 hleei.logdataptr = (uint32_t)&pcpes;
545 hleei.logdatalen = 32;
547 rc = HashLogExtendEvent32(&hleei,
548 &hleeo,
549 TCG_MAGIC,
550 0x0,
551 0x0);
552 return rc;
553 }
555 /* table of event types according to 10.4.1 / table 11 */
556 static const char ev_action[][23] = {
557 /* 0 */ "Calling INT 19h",
558 "Returned INT 19h",
559 "Returned via INT 18h",
560 "",
561 "",
562 /* 5 */ "",
563 "",
564 "",
565 "",
566 "",
567 /* 10 */ "",
568 "",
569 "",
570 "",
571 "Start Option ROM Scan"
572 };
574 static char evt_separator[] = {0xff,0xff,0xff,0xff};
575 static char wake_event_1[] = "Wake Event 1";
577 /*
578 * Add a measurement to the list of measurements
579 * pcrIndex : PCR to be extended
580 * event_type : type of event; specs 10.4.1
581 * data : additional parameter; used as parameter for 10.4.3
582 * 'action index'
583 */
584 void tcpa_add_measurement(uint32_t pcrIndex,
585 uint16_t event_type,
586 uint32_t data)
587 {
588 const char *string;
590 switch (event_type) {
591 case EV_SEPARATOR:
592 tcpa_add_measurement_to_log_simple(pcrIndex,
593 event_type,
594 (uint8_t *)evt_separator,
595 4);
596 break;
597 case EV_ACTION:
598 string = ev_action[data /* event_id */];
599 tcpa_add_measurement_to_log(pcrIndex,
600 event_type,
601 data,
602 string,
603 strlen(string));
605 break;
606 }
607 }
610 /*
611 * Add measurement to log about call of int 19h
612 */
613 void tcpa_calling_int19h()
614 {
615 tcpa_add_measurement(4, EV_ACTION, 0);
616 }
618 /*
619 * Add measurement to log about retuning from int 19h
620 */
621 void tcpa_returned_int19h()
622 {
623 tcpa_add_measurement(4, EV_ACTION, 1);
624 }
626 /*
627 * Add event separators for PCRs 0 to 7; specs 8.2.3
628 */
629 void tcpa_add_event_separators()
630 {
631 uint32_t pcrIndex = 0;
632 while (pcrIndex <= 7) {
633 tcpa_add_measurement(pcrIndex, EV_SEPARATOR, 0);
634 pcrIndex ++;
635 }
636 }
639 /*
640 * Add a wake event to the log
641 */
642 void tcpa_wake_event()
643 {
644 tcpa_add_measurement_to_log(6,
645 EV_ACTION,
646 10,
647 wake_event_1,
648 strlen(wake_event_1));
649 }
651 /*
652 * add the boot device to the measurement log
653 */
654 void tcpa_add_bootdevice(uint32_t bootcd, uint32_t bootdrv)
655 {
656 char *string;
657 if (bootcd == 0) {
658 if (bootdrv == 0) {
659 string = "Booting BCV device 00h (Floppy)";
660 } else if (bootdrv == 0x80) {
661 string = "Booting BCV device 80h (HDD)";
662 } else {
663 string = "Booting unknown device";
664 }
665 } else {
666 string = "Booting from CD ROM device";
667 }
668 tcpa_add_measurement_to_log(4, 5, 0,
669 string, strlen(string));
670 }
672 /*
673 * Add measurement to the log about option rom scan
674 * 10.4.3 : action 14
675 */
676 void tcpa_start_option_rom_scan()
677 {
678 tcpa_add_measurement(2, EV_ACTION, 14);
679 }
682 /*
683 * Add measurement to the log about an option rom
684 */
685 void tcpa_option_rom(uint32_t seg)
686 {
687 uint32_t len = read_byte(seg, 2) << 9;
688 uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,0);
689 char append[32]; /* TCG_PCClientTaggedEventStruct and
690 OptionROMExecuteStructure; specs 10.4.2.1 */
691 struct hai hai; /* HashAll Input Block; specs 12.10 */
693 memset(append, 0x0, sizeof(append));
695 append[0] = 7; /* Option ROM Execute */
696 append[4] = 24;/* size of OptionROMExecute Structure */
697 /* leave the rest to '0' */
699 /* 12.10 table 21 */
700 hai.ipblength = 0x10;
701 hai.reserved = 0;
702 hai.hashdataptr = (uint32_t)addr;
703 hai.hashdatalen = len;
704 hai.algorithmid = TPM_ALG_SHA;
706 HashAll32(&hai,
707 (unsigned char *)append+12,
708 TCG_MAGIC,
709 0,
710 0);
712 tcpa_add_measurement_to_log(2,
713 EV_EVENT_TAG,
714 0,
715 append,
716 32);
717 }
719 /*
720 * Add a measurement to the log in support of 8.2.5.3
721 * Creates two log entries
722 *
723 * Input parameter:
724 * bootcd : 0: MBR of hdd, 1: boot image, 2: boot catalog of El Torito
725 * seg : segment where the IPL data are located
726 * off : offset where the IPL data are located
727 * count : length in bytes
728 */
729 void tcpa_ipl(Bit32u bootcd,Bit32u seg,Bit32u off,Bit32u count)
730 {
731 uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,off);
732 if (bootcd == 1) {
733 /* specs: 8.2.5.6 El Torito */
734 tcpa_add_measurement_to_log_simple(4,
735 EV_IPL,
736 addr,
737 count);
738 }
739 else if (bootcd == 2) { /* Boot Catalog */
741 /* specs: 8.2.5.6 El Torito */
742 tcpa_add_measurement_to_log_simple(5,
743 EV_IPL_PARTITION_DATA,
744 addr,
745 count);
746 }
747 else {
748 /* specs: 8.2.5.3 */
749 /* equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum */
750 tcpa_add_measurement_to_log_simple(4,
751 EV_IPL,
752 addr,
753 0x1b8);
756 /* equivalent to: dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum */
757 tcpa_add_measurement_to_log_simple(5,
758 EV_IPL_PARTITION_DATA,
759 addr + 0x1b8,
760 0x48);
761 }
762 }
764 void tcpa_measure_post(Bit32u from, Bit32u to)
765 {
766 struct pcpes pcpes; /* PCClientPCREventStruc */
767 int len = to - from;
768 memset(&pcpes, 0x0, sizeof(pcpes));
770 if (len > 0) {
771 sha1((unsigned char *)from,
772 to-from,
773 (unsigned char *)&pcpes.digest);
775 pcpes.eventtype = EV_POST_CODE;
776 pcpes.eventdatasize = 0;
777 pcpes.pcrindex = 0;
778 tcpa_add_pcpes_to_log(&pcpes);
779 }
780 }
782 static
783 uint32_t SendCommand32(uint32_t idx, struct pttto *pttto, uint32_t size_ptto)
784 {
785 uint32_t rc = 0;
786 struct pttti *pttti = (struct pttti *)TCG_CommandList[idx];
787 uint8_t _pttto[30];
789 if (size_ptto > 0 && size_ptto < 14) {
790 rc = (TCG_PC_TPMERROR |
791 ((uint32_t)TCG_INVALID_INPUT_PARA << 16));
792 }
794 if (rc == 0) {
795 if (size_ptto == 0) {
796 pttto = (struct pttto *)_pttto;
797 size_ptto = sizeof(_pttto);
798 }
799 pttti->opblength = size_ptto;
800 }
802 if (rc == 0) {
803 if (pttti->opblength > size_ptto) {
804 rc = (TCG_PC_TPMERROR |
805 ((uint32_t)TCG_OUTPUT_BUFFER_TOO_SHORT << 16));
806 }
807 }
809 if (rc == 0) {
810 rc = PassThroughToTPM32(pttti,
811 pttto,
812 TCG_MAGIC,
813 0x0,
814 0x0);
815 }
817 return rc;
818 }
821 uint32_t tcpa_initialize_tpm(uint32_t physpres)
822 {
823 uint32_t rc = 0;
824 uint8_t _pttto[40];
825 struct pttto *pttto = (struct pttto *)_pttto;
826 uint32_t pttto_size = sizeof(_pttto);
828 if (rc == 0) {
829 rc = SendCommand32(IDX_CMD_TPM_Startup_0x01, pttto,
830 pttto_size);
831 }
833 if (rc == 0 && physpres != 0) {
834 rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x20,
835 pttto, pttto_size);
836 }
838 if (rc == 0 && physpres != 0) {
839 rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x08,
840 pttto, pttto_size);
841 }
843 if (rc == 0 && physpres != 0) {
844 rc = SendCommand32(IDX_CMD_TPM_PhysicalEnable,
845 pttto, pttto_size);
846 }
848 if (rc == 0 && physpres != 0) {
849 rc = SendCommand32(IDX_CMD_TPM_PhysicalSetDeactivated_0x00,
850 pttto, pttto_size);
851 }
853 if (rc == 0) {
854 rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x100,
855 pttto, pttto_size);
856 }
858 if (rc == 0) {
859 rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x10,
860 pttto, pttto_size);
861 }
862 return rc;
863 }
866 uint16_t TCG_IsShutdownPreBootInterface(void)
867 {
868 return tcpa_acpi.flags & STATUS_FLAG_SHUTDOWN;
869 }
872 static
873 uint32_t _TCG_TPM_Extend(unsigned char *hash, uint32_t pcrindex)
874 {
875 uint32_t rc;
876 uint8_t _pttti[8+34];
877 uint8_t _pttto[4+30];
878 struct pttti *pttti = (struct pttti*)&_pttti;
879 struct pttto *pttto = (struct pttto*)&_pttto;
881 pttti->ipblength = 8 + 34;
882 pttti->reserved = 0;
883 pttti->opblength = 4 + 30;
884 pttti->reserved2 = 0;
886 _pttti[8 + 0] = 0x0;
887 _pttti[8 + 1] = 0xc1;
888 *(uint32_t *)&_pttti[8 + 2] = bswap(34);
889 *(uint32_t *)&_pttti[8 + 6] = bswap(0x14);
890 *(uint32_t *)&_pttti[8 + 10]= bswap(pcrindex);
891 memcpy(&_pttti[8+14], hash, 20);
893 rc = PassThroughToTPM32(pttti,
894 pttto,
895 TCG_MAGIC,
896 0x0,
897 0x0);
898 /* sanity check of result */
899 if (_pttto[4] != 0x00 || _pttto[5] != 0xc4) {
900 rc = (TCG_PC_TPMERROR |
901 ((uint32_t)TCG_FATAL_COM_ERROR << 16));
902 }
904 if (rc != 0) {
905 /*
906 Invalidate the log since system did not process this
907 extend properly.
908 */
909 tcpa_reset_acpi_log();
910 memset(&tcpa_acpi, 0x0, sizeof(tcpa_acpi));
911 TCG_ShutdownPreBootInterface(0);
912 }
913 return rc;
914 }
917 static
918 uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s, struct hleeo *hleeo,
919 uint32_t magic, uint32_t ecx, uint32_t edx)
920 {
921 uint32_t rc = 0;
922 uint16_t size;
923 struct hlei hlei ; /* HashLogEventInput block */
924 struct hleo hleo; /* HashLogEventOutput block */
925 struct hleei_long *hleei_l = (struct hleei_long *)hleei_s;
926 int sh = 0;
927 uint32_t logdataptr;
929 if (TCG_IsShutdownPreBootInterface() != 0) {
930 rc = (TCG_PC_TPMERROR |
931 ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
932 }
934 if (rc == 0) {
935 /* short or long version? */
936 size = hleei_s->ipblength;
937 if (size == 0x18) {
938 /* short */
939 sh = 1;
940 } else if (size == 0x1c) {
941 /* long */
942 sh = 0;
943 } else {
944 /* bad input block */
945 rc = TCG_PC_TPMERROR |
946 ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
947 }
948 }
950 if (rc == 0) {
951 uint32_t hashdataptr;
952 uint32_t hashdatalen;
953 uint32_t pcrindex;
954 uint32_t logeventtype;
955 uint32_t logdatalen;
956 uint32_t eventnumber;
957 uint8_t hash[20];
958 struct pcpes *pcpes;
960 hashdataptr = hleei_s->hashdataptr;
961 hashdatalen = hleei_s->hashdatalen;
962 pcrindex = hleei_s->pcrindex;
963 if (sh) {
964 logdataptr = hleei_s->logdataptr;
965 logdatalen = hleei_s->logdatalen;
966 } else {
967 logdataptr = hleei_l->logdataptr;
968 logdatalen = hleei_l->logdatalen;
969 }
971 pcpes = (struct pcpes *)logdataptr;
972 logeventtype = pcpes->eventtype;
974 /* fill out HashLogEventInput block 'hlie' */
975 hlei.ipblength = 0x1c;
976 hlei.reserved = 0;
977 hlei.hashdataptr = hashdataptr;
978 hlei.hashdatalen = hashdatalen;
979 hlei.pcrindex = pcrindex;
980 hlei.logeventtype= logeventtype;
981 hlei.logdataptr = logdataptr;
982 hlei.logdatalen = logdatalen;
984 rc = HashLogEvent32(&hlei,
985 &hleo,
986 TCG_MAGIC,
987 0x0,
988 0x0);
989 eventnumber = hleo.eventnumber;
991 hleeo->opblength = 8 + 20;
992 hleeo->reserved = 0;
993 hleeo->eventnumber = eventnumber;
995 memcpy(hash, (unsigned char *)logdataptr + 0x8, 20);
996 _TCG_TPM_Extend(hash, pcrindex);
997 }
999 if (rc != 0) {
1000 hleeo->opblength = 4;
1001 hleeo->reserved = 0;
1003 return rc;
1008 static
1009 uint32_t PassThroughToTPM32(struct pttti *pttti, struct pttto *pttto,
1010 uint32_t magic, uint32_t ecx, uint32_t edx)
1012 uint32_t rc = 0;
1013 uint8_t *cmd32;
1014 uint32_t resbuflen = 0;
1016 if (TCG_IsShutdownPreBootInterface() != 0) {
1017 rc = (TCG_PC_TPMERROR |
1018 ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1021 if (rc == 0) {
1022 if (pttti->ipblength < 0x8 + 10) {
1023 rc = TCG_PC_TPMERROR |
1024 ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
1028 if (rc == 0) {
1029 if (pttti->opblength < 0x4) {
1030 rc = TCG_PC_TPMERROR |
1031 ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
1035 if (rc == 0) {
1036 uint8_t *resbuf32;
1038 cmd32 = &pttti->tpmoperandin[0];
1039 resbuflen = pttti->opblength - 4;
1040 resbuf32 = &pttto->tpmoperandout[0];
1042 rc = MA_Transmit(cmd32, resbuf32, resbuflen);
1045 if (rc == 0) {
1046 pttto->opblength = resbuflen+4;
1047 pttto->reserved = 0;
1050 if (rc != 0) {
1051 pttto->opblength = 0;
1052 pttto->reserved = 0;
1055 return rc;
1059 static
1060 uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx)
1062 uint32_t rc = 0;
1063 if (TCG_IsShutdownPreBootInterface() == 0) {
1064 tcpa_acpi.flags |= STATUS_FLAG_SHUTDOWN;
1065 } else {
1066 rc = (TCG_PC_TPMERROR |
1067 ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1069 return rc;
1073 static
1074 uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo,
1075 uint32_t ebx, uint32_t ecx, uint32_t edx)
1077 uint32_t rc = 0;
1078 uint16_t size;
1079 uint32_t logdataptr;
1080 uint32_t logdatalen;
1081 uint32_t hashdataptr;
1082 uint32_t hashdatalen;
1084 if (TCG_IsShutdownPreBootInterface() != 0) {
1085 rc = (TCG_PC_TPMERROR |
1086 ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1089 if (rc == 0) {
1090 size = hlei->ipblength;
1091 if (size != 0x1c) {
1092 rc = (TCG_PC_TPMERROR |
1093 ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1097 if (rc == 0) {
1098 struct pcpes *pcpes;
1099 logdataptr = hlei->logdataptr;
1100 logdatalen = hlei->logdatalen;
1101 pcpes = (struct pcpes *)logdataptr;
1102 if (pcpes->pcrindex != hlei->pcrindex) {
1103 rc = (TCG_PC_TPMERROR |
1104 ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1108 if (rc == 0) {
1109 struct pcpes *pcpes= (struct pcpes *)logdataptr;
1110 if (pcpes->eventtype != hlei->logeventtype) {
1111 rc = (TCG_PC_TPMERROR |
1112 ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1116 if (rc == 0) {
1117 uint32_t entry;
1118 hashdataptr = hlei->hashdataptr;
1119 hashdatalen = hlei->hashdatalen;
1121 if ((hashdataptr != 0) | (hashdatalen != 0)) {
1122 uint8_t hash[20];
1123 struct hai hai; /* HashAll Input Block */
1124 hai.ipblength = 0x10;
1125 hai.reserved = 0x0;
1126 hai.hashdataptr = hashdataptr;
1127 hai.hashdatalen = hashdatalen;
1128 hai.algorithmid = TPM_ALG_SHA;
1129 rc = HashAll32(&hai,
1130 hash,
1131 TCG_MAGIC,
1132 0x0,
1133 0x0);
1135 if (rc == 0) {
1136 /* hashing was done ok */
1137 memcpy((unsigned char *)logdataptr + 8,
1138 hash,
1139 20);
1143 if (rc == 0) {
1144 /* extend the log with this event */
1145 entry = tcpa_extend_acpi_log(logdataptr);
1146 if ((uint16_t)entry == 0) {
1147 /* upper 16 bits hold error code */
1148 rc = (entry >> 16);
1152 if (rc == 0) {
1153 /* updating the log was fine */
1154 hleo->opblength = 8;
1155 hleo->reserved = 0;
1156 hleo->eventnumber = entry;
1160 if (rc != 0) {
1161 hleo->opblength = 2;
1162 hleo->reserved = 0;
1165 return rc;
1168 static
1169 uint32_t HashAll32(struct hai *hai, unsigned char *hash,
1170 uint32_t magic, uint32_t ecx, uint32_t edx)
1172 uint32_t rc = 0;
1174 if (TCG_IsShutdownPreBootInterface() != 0) {
1175 rc = (TCG_PC_TPMERROR |
1176 ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1179 if (rc == 0) {
1180 if (hai->ipblength != 0x10) {
1181 rc = (TCG_PC_TPMERROR |
1182 ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1186 if (rc == 0) {
1187 if (hai->algorithmid != TPM_ALG_SHA) {
1188 rc = (TCG_PC_TPMERROR |
1189 ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1193 if (rc == 0) {
1194 uint8_t *hashdataptr32;
1195 uint32_t hashdatalen32;
1197 hashdataptr32 = (uint8_t *)hai->hashdataptr;
1198 hashdatalen32 = hai->hashdatalen;
1200 sha1(hashdataptr32,
1201 hashdatalen32,
1202 hash);
1205 return rc;
1209 static
1210 uint32_t TSS32(struct ti *ti, struct to *to,
1211 uint32_t ebx, uint32_t ecx, uint32_t edx)
1213 uint32_t rc = 0;
1214 if (TCG_IsShutdownPreBootInterface() == 0) {
1215 rc = TCG_PC_UNSUPPORTED;
1216 } else {
1217 rc = (TCG_PC_TPMERROR |
1218 ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1221 if (rc != 0) {
1222 to->opblength = 4;
1223 to->reserved = 0;
1226 return rc;
1229 static
1230 uint32_t CompactHashLogExtendEvent32(unsigned char *buffer,
1231 uint32_t info,
1232 uint32_t magic,
1233 uint32_t length,
1234 uint32_t pcrindex,
1235 uint32_t *edx_ptr)
1237 uint32_t rc = 0;
1238 struct hleeo hleeo;
1240 if (TCG_IsShutdownPreBootInterface() != 0) {
1241 rc = (TCG_PC_TPMERROR |
1242 ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1245 if (buffer == 0) {
1246 rc = (TCG_PC_TPMERROR |
1247 ((uint32_t)TCG_INVALID_INPUT_PARA << 16));
1250 if (rc == 0) {
1251 struct hleei_short hleei;
1252 struct pcpes pcpes;
1253 uint8_t *logdataptr;
1254 uint8_t *hashdataptr;
1256 logdataptr = (uint8_t*)&pcpes;
1257 hashdataptr = buffer;
1259 hleei.ipblength = 0x18;
1260 hleei.reserved = 0x0;
1261 hleei.hashdataptr = (uint32_t)hashdataptr;
1262 hleei.hashdatalen = length;
1263 hleei.pcrindex = pcrindex;
1264 hleei.logdataptr = (uint32_t)logdataptr;
1265 hleei.logdatalen = 32;
1267 memset(&pcpes, 0x0, 32);
1268 pcpes.pcrindex = pcrindex;
1269 pcpes.eventtype = 12; /* EV_COMPACT_HASH */
1270 pcpes.eventdatasize = 4;
1271 pcpes.event = info;
1273 rc = HashLogExtendEvent32(&hleei,
1274 &hleeo,
1275 TCG_MAGIC,
1276 0x0,
1277 0x0);
1280 if (rc == 0) {
1281 *edx_ptr = hleeo.eventnumber;
1284 return rc;
1289 /*******************************************************************
1290 Calculation of SHA1 in SW
1292 See: RFC3174, Wikipedia's SHA1 alogrithm description
1293 ******************************************************************/
1294 typedef struct _sha1_ctx {
1295 uint32_t h[5];
1296 } sha1_ctx;
1299 static inline uint32_t rol(uint32_t val, uint16_t rol)
1301 return (val << rol) | (val >> (32 - rol));
1304 static const uint32_t sha_ko[4] = { 0x5a827999,
1305 0x6ed9eba1,
1306 0x8f1bbcdc,
1307 0xca62c1d6 };
1310 static void sha1_block(uint32_t *w, sha1_ctx *ctx)
1312 uint32_t i;
1313 uint32_t a,b,c,d,e,f;
1314 uint32_t tmp;
1315 uint32_t idx;
1317 /* change endianess of given data */
1318 for (i = 0; i < 16; i++) {
1319 w[i] = bswap(w[i]);
1322 for (i = 16; i <= 79; i++) {
1323 tmp = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
1324 w[i] = rol(tmp,1);
1327 a = ctx->h[0];
1328 b = ctx->h[1];
1329 c = ctx->h[2];
1330 d = ctx->h[3];
1331 e = ctx->h[4];
1333 for (i = 0; i <= 79; i++) {
1334 if (i <= 19) {
1335 f = (b & c) | ((b ^ 0xffffffff) & d);
1336 idx = 0;
1337 } else if (i <= 39) {
1338 f = b ^ c ^ d;
1339 idx = 1;
1340 } else if (i <= 59) {
1341 f = (b & c) | (b & d) | (c & d);
1342 idx = 2;
1343 } else {
1344 f = b ^ c ^ d;
1345 idx = 3;
1348 tmp = rol(a, 5) +
1349 f +
1350 e +
1351 sha_ko[idx] +
1352 w[i];
1353 e = d;
1354 d = c;
1355 c = rol(b, 30);
1356 b = a;
1357 a = tmp;
1360 ctx->h[0] += a;
1361 ctx->h[1] += b;
1362 ctx->h[2] += c;
1363 ctx->h[3] += d;
1364 ctx->h[4] += e;
1367 static
1368 void sha1_do(sha1_ctx *ctx, const unsigned char *data32, uint32_t length)
1370 uint32_t offset;
1371 uint16_t num;
1372 uint32_t bits = 0;
1373 uint32_t w[80];
1374 uint32_t tmp;
1376 /* treat data in 64-byte chunks */
1377 for (offset = 0; length - offset >= 64; offset += 64) {
1378 memcpy(w, data32 + offset, 64);
1379 sha1_block((uint32_t *)w, ctx);
1380 bits += (64 * 8);
1383 /* last block with less than 64 bytes */
1384 num = length - offset;
1385 bits += (num << 3);
1387 memset(w, 0x0, 64);
1388 memcpy(w, data32 + offset, num);
1389 ((uint8_t *)w)[num] = 0x80;
1391 if (num >= 56) {
1392 /* cannot append number of bits here */
1393 sha1_block((uint32_t *)w, ctx);
1394 memset(w, 0x0, 60);
1397 /* write number of bits to end of block */
1398 tmp = bswap(bits);
1399 memcpy(&w[15], &tmp, 4);
1401 sha1_block(w, ctx);
1403 /* need to switch result's endianess */
1404 for (num = 0; num < 5; num++)
1405 ctx->h[num] = bswap(ctx->h[num]);
1408 /* sha1 initialization constants */
1409 static const uint32_t sha_const[5] = {
1410 0x67452301,
1411 0xefcdab89,
1412 0x98badcfe,
1413 0x10325476,
1414 0xc3d2e1f0
1415 };
1417 static
1418 void sha1(const unsigned char *data, uint32_t length, unsigned char *hash)
1420 sha1_ctx ctx;
1422 memcpy(&ctx.h[0], sha_const, 20);
1423 sha1_do(&ctx, data, length);
1424 memcpy(hash, &ctx.h[0], 20);
1428 uint32_t TCGInterruptHandler(pushad_regs_t *regs, uint32_t esds,
1429 uint32_t flags_ptr)
1431 uint16_t DS = esds >> 16;
1432 uint16_t ES = esds & 0xffff;
1433 uint16_t *FLAGS = (uint16_t *)flags_ptr;
1435 switch(regs->u.r8.al) {
1436 case 0x00:
1437 if (MA_IsTPMPresent() == 0) {
1438 /* no TPM available */
1439 regs->u.r32.eax = TCG_PC_TPMERROR |
1440 ((uint32_t)(TCG_PC_TPM_NOT_PRESENT) << 16);
1441 } else {
1442 regs->u.r32.eax = MA_InitTPM(TPM_ST_CLEAR);
1443 if (regs->u.r32.eax == 0) {
1444 regs->u.r32.ebx = TCG_MAGIC;
1445 regs->u.r8.ch = TCG_VERSION_MAJOR;
1446 regs->u.r8.cl = TCG_VERSION_MINOR;
1447 regs->u.r32.edx = 0x0;
1448 regs->u.r32.esi =
1449 (Bit32u)tcpa_get_lasa_base_ptr();
1450 regs->u.r32.edi =
1451 (Bit32u)tcpa_get_lasa_last_ptr();
1452 CLEAR_CF();
1455 break;
1456 case 0x01:
1457 regs->u.r32.eax =
1458 HashLogExtendEvent32((struct hleei_short*)
1459 ADDR_FROM_SEG_OFF(ES,
1460 regs->u.r16.di),
1461 (struct hleeo*)
1462 ADDR_FROM_SEG_OFF(DS,
1463 regs->u.r16.si),
1464 regs->u.r32.ebx,
1465 regs->u.r32.ecx,
1466 regs->u.r32.edx);
1467 CLEAR_CF();
1468 break;
1469 case 0x02:
1470 regs->u.r32.eax =
1471 PassThroughToTPM32((struct pttti *)
1472 ADDR_FROM_SEG_OFF(ES,
1473 regs->u.r16.di),
1474 (struct pttto *)
1475 ADDR_FROM_SEG_OFF(DS,
1476 regs->u.r16.si),
1477 regs->u.r32.ebx,
1478 regs->u.r32.ecx,
1479 regs->u.r32.edx);
1480 CLEAR_CF();
1481 break;
1482 case 0x03:
1483 regs->u.r32.eax =
1484 TCG_ShutdownPreBootInterface(regs->u.r32.ebx);
1485 CLEAR_CF();
1486 break;
1487 case 0x04:
1488 regs->u.r32.eax =
1489 HashLogEvent32((struct hlei*)
1490 ADDR_FROM_SEG_OFF(ES,
1491 regs->u.r16.di),
1492 (struct hleo*)
1493 ADDR_FROM_SEG_OFF(DS,
1494 regs->u.r16.si),
1495 regs->u.r32.ebx,
1496 regs->u.r32.ecx,
1497 regs->u.r32.edx);
1498 CLEAR_CF();
1499 break;
1500 case 0x05:
1501 regs->u.r32.eax =
1502 HashAll32((struct hai*)
1503 ADDR_FROM_SEG_OFF(ES,
1504 regs->u.r16.di),
1505 (unsigned char *)
1506 ADDR_FROM_SEG_OFF(DS,
1507 regs->u.r16.si),
1508 regs->u.r32.ebx,
1509 regs->u.r32.ecx,
1510 regs->u.r32.edx);
1511 CLEAR_CF();
1512 break;
1513 case 0x06:
1514 regs->u.r32.eax =
1515 TSS32((struct ti*)ADDR_FROM_SEG_OFF(ES,
1516 regs->u.r16.di),
1517 (struct to*)ADDR_FROM_SEG_OFF(DS,
1518 regs->u.r16.si),
1519 regs->u.r32.ebx,
1520 regs->u.r32.ecx,
1521 regs->u.r32.edx);
1522 CLEAR_CF();
1523 break;
1524 case 0x07:
1525 regs->u.r32.eax =
1526 CompactHashLogExtendEvent32((unsigned char *)
1527 ADDR_FROM_SEG_OFF(ES,
1528 regs->u.r16.di),
1529 regs->u.r32.esi,
1530 regs->u.r32.ebx,
1531 regs->u.r32.ecx,
1532 regs->u.r32.edx,
1533 &regs->u.r32.edx);
1534 CLEAR_CF();
1535 break;
1536 default:
1537 SET_CF();
1540 return 0;