debuggers.hg

view tools/firmware/rombios/32bit/tcgbios/tcgbios.c @ 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>
author kaf24@localhost.localdomain
date Fri Jan 26 16:38:32 2007 +0000 (2007-01-26)
parents
children e212203d7d34
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, unsigned char *hash);
99 static uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx);
100 static uint32_t HashAll32(struct hai *hai, unsigned char *hash,
101 uint32_t magic, uint32_t ecx, uint32_t edx);
102 static uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s,
103 struct hleeo *hleeo,
104 uint32_t magic, uint32_t ecx, uint32_t edx);
105 static uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo,
106 uint32_t ebx, uint32_t ecx, uint32_t edx);
107 static uint32_t PassThroughToTPM32(struct pttti *pttti, struct pttto *pttto,
108 uint32_t magic, uint32_t ecx, uint32_t edx);
109 static uint32_t MA_Transmit(unsigned char *cmdbuffer,
110 unsigned char *respbuffer,
111 uint32_t respbufferlen);
113 static unsigned char *tcpa_get_lasa_last_ptr(void);
114 static unsigned char *tcpa_get_lasa_base_ptr(void);
115 static void tcpa_reset_acpi_log(void);
116 static uint32_t tcpa_get_laml(void);
119 extern struct tpm_driver tpm_drivers[];
121 /* utility functions */
123 static inline uint32_t bswap(uint32_t a)
124 {
125 return ( ( a >> 24 ) & 0x000000ff) |
126 ( ( a >> 8 ) & 0x0000ff00) |
127 ( ( a << 8 ) & 0x00ff0000) |
128 ( ( a << 24 ) & 0xff000000);
129 }
131 /********************************************************
132 Extensions for TCG-enabled BIOS
133 *******************************************************/
135 typedef struct {
136 struct acpi_20_tcpa *tcpa_ptr;
137 unsigned char *lasa_last_ptr;
138 uint16_t entry_count;
139 uint16_t flags;
140 } tcpa_acpi_t;
142 static tcpa_acpi_t tcpa_acpi;
145 /* low level driver implementation */
146 static int tpm_driver_to_use = TPM_INVALID_DRIVER;
148 static
149 uint32_t MA_IsTPMPresent()
150 {
151 uint32_t rc = 0;
152 unsigned int i;
153 for (i = 0; i < TPM_NUM_DRIVERS; i++) {
154 struct tpm_driver *td = &tpm_drivers[i];
155 if (td->probe(td->baseaddr) != 0) {
156 tpm_driver_to_use = i;
157 rc = 1;
158 break;
159 }
160 }
161 return rc;
162 }
164 static
165 uint32_t MA_InitTPM(uint16_t startupcode)
166 {
167 uint32_t rc = 0;
168 /* low-level initialize the TPM */
169 unsigned char command[sizeof(CMD_TPM_Startup_0x01_IPB.tpmoperandin)];
170 unsigned char response[10];
171 uint32_t response_size = sizeof(response);
173 memcpy(command,
174 CMD_TPM_Startup_0x01_IPB.tpmoperandin,
175 sizeof(CMD_TPM_Startup_0x01_IPB.tpmoperandin));
176 command[10] = (startupcode >> 8) & 0xff;
177 command[11] = (startupcode >> 0) & 0xff;
178 rc = MA_Transmit(command, response, response_size);
180 return rc;
181 }
183 static
184 uint32_t MA_Transmit(unsigned char *cmdbuffer,
185 unsigned char *respbuffer,
186 uint32_t respbufferlen)
187 {
188 uint32_t rc = 0;
189 uint32_t irc;
190 struct tpm_driver *td;
192 if (tpm_driver_to_use == TPM_INVALID_DRIVER)
193 return TCG_FATAL_COM_ERROR;
195 td = &tpm_drivers[tpm_driver_to_use];
197 if (rc == 0) {
198 irc = td->activate(td->baseaddr);
199 if (irc == 0) {
200 /* tpm could not be activated */
201 rc = TCG_FATAL_COM_ERROR;
202 }
203 }
205 if (rc == 0) {
206 uint32_t *tmp = (uint32_t *)&cmdbuffer[2];
207 uint32_t len = bswap(*tmp);
208 irc = td->senddata(td->baseaddr,
209 cmdbuffer,
210 len);
211 if (irc != 0) {
212 rc = TCG_FATAL_COM_ERROR;
213 }
214 }
216 if (rc == 0) {
217 irc = td->waitdatavalid(td->baseaddr);
218 if (irc != 0) {
219 rc = TCG_FATAL_COM_ERROR;
220 }
221 }
223 if (rc == 0) {
224 irc = td->waitrespready(td->baseaddr, 2000);
225 if (irc != 0) {
226 rc = TCG_FATAL_COM_ERROR;
227 }
228 }
230 if (rc == 0) {
231 irc = td->readresp(td->baseaddr,
232 respbuffer,
233 respbufferlen);
234 if (irc != 0) {
235 rc = TCG_FATAL_COM_ERROR;
236 }
237 }
239 if (rc == 0) {
240 irc = td->ready(td->baseaddr);
241 }
243 return rc;
244 }
247 static
248 uint8_t acpi_validate_entry(struct acpi_header *hdr)
249 {
250 uint8_t sum = 0;
251 unsigned int length = hdr->length;
252 unsigned int ctr;
253 unsigned char *addr = (unsigned char *)hdr;
255 for (ctr = 0; ctr < length; ctr++)
256 sum += addr[ctr];
258 return sum;
259 }
262 void tcpa_acpi_init(void)
263 {
264 struct acpi_20_rsdt *rsdt;
265 uint32_t length;
266 struct acpi_20_tcpa *tcpa;
267 uint16_t found = 0;
268 uint16_t rsdp_off;
269 uint16_t off;
270 struct acpi_20_rsdp *rsdp;
272 if (MA_IsTPMPresent() == 0) {
273 return;
274 }
276 /* scan memory in steps of 16 bytes in the ACPI_SEGMENT segment */
277 found = 0;
278 for (rsdp_off = 0; rsdp_off < 0xfff0; rsdp_off += 0x10) {
279 char *_rsdp = (char *)(ACPI_SEGMENT << 4);
280 /* check for expected string */
281 if (!strncmp( &_rsdp[rsdp_off], "RSD PTR ", 8)) {
282 found = 1;
283 rsdp = (struct acpi_20_rsdp *)&_rsdp[rsdp_off];
284 break;
285 }
286 }
288 if (rsdp) {
289 uint32_t ctr = 0;
290 /* get RSDT from RSDP */
291 rsdt = (struct acpi_20_rsdt *)rsdp->rsdt_address;
292 /* rsdt may be anywhere in 32bit space */
293 length = rsdt->header.length;
294 off = 36;
295 while ((off + 3) < length) {
296 /* try all pointers to structures */
297 tcpa = (struct acpi_20_tcpa *)rsdt->entry[ctr];
298 /* valid TCPA ACPI table ? */
299 if (ACPI_2_0_TCPA_SIGNATURE == tcpa->header.signature &&
300 acpi_validate_entry(&tcpa->header) == 0) {
301 found = 1;
302 break;
303 }
304 off += 4;
305 ctr++;
306 }
307 }
309 if (found == 0) {
310 printf("TCPA ACPI was NOT found!\n");
311 tcpa = 0;
312 }
314 /* initialize the TCPA part of the EBDA with our data */
315 tcpa_acpi.tcpa_ptr = tcpa;
316 tcpa_acpi.lasa_last_ptr = 0;
317 tcpa_acpi.entry_count = 0;
318 tcpa_acpi.flags = 0;
319 tcpa_reset_acpi_log();
320 }
322 /* clear the ACPI log */
323 static void tcpa_reset_acpi_log(void)
324 {
325 unsigned char *lasa = tcpa_get_lasa_base_ptr();
326 if (lasa)
327 memset(lasa, 0x0, tcpa_get_laml());
328 }
331 uint32_t tcpa_extend_acpi_log(uint32_t entry_ptr)
332 {
333 uint32_t res = 0;
334 unsigned char *lasa_last = tcpa_get_lasa_last_ptr();
335 unsigned char *lasa_base = tcpa_get_lasa_base_ptr();
336 uint32_t size;
337 uint16_t entry_count = tcpa_acpi.entry_count;
338 struct pcpes *pcpes = (struct pcpes *)entry_ptr;
340 if (lasa_last == 0) {
341 lasa_last = lasa_base;
342 } else {
343 struct pcpes *pcpes = (struct pcpes *)lasa_last;
344 /* skip the last entry in the log */
345 size = pcpes->eventdatasize;
346 size += 32;
347 lasa_last += size;
348 }
350 if (lasa_last == 0) {
351 res = ((uint32_t)TCG_PC_LOGOVERFLOW << 16);
352 }
354 if (res == 0) {
355 uint32_t laml = tcpa_get_laml();
356 size = pcpes->eventdatasize;
357 size += 32;
358 if ((lasa_last + size - lasa_base) > laml) {
359 res = (TCG_PC_LOGOVERFLOW << 16);
360 }
361 }
363 if (res == 0) {
364 /* copy the log entry into the ACPI log */
365 memcpy((char *)lasa_last, (char *)entry_ptr, size);
366 /*
367 * update the pointers and entry counter that were modified
368 * due to the new entry in the log
369 */
370 tcpa_acpi.lasa_last_ptr = lasa_last;
371 entry_count++;
372 tcpa_acpi.entry_count = entry_count;
374 res = entry_count;
375 }
376 return res;
377 }
379 static
380 unsigned char *tcpa_get_lasa_last_ptr(void)
381 {
382 return tcpa_acpi.lasa_last_ptr;
383 }
385 static
386 unsigned char *tcpa_get_lasa_base_ptr(void)
387 {
388 unsigned char *lasa = 0;
389 struct acpi_20_tcpa *tcpa = tcpa_acpi.tcpa_ptr;
390 if (tcpa != 0) {
391 uint32_t class = tcpa->platform_class;
392 if (class == TCPA_ACPI_CLASS_CLIENT) {
393 /* client type */
394 lasa = (unsigned char *)(long)tcpa->u.client.lasa;
395 } else if (class == TCPA_ACPI_CLASS_SERVER) {
396 /* server type */
397 lasa = (unsigned char *)(long)tcpa->u.server.lasa;
398 }
399 }
400 return lasa;
401 }
403 static
404 uint32_t tcpa_get_laml(void)
405 {
406 uint32_t laml = 0;
407 struct acpi_20_tcpa *tcpa = tcpa_acpi.tcpa_ptr;
408 if (tcpa != 0) {
409 uint32_t class = tcpa->platform_class;
410 if (class == TCPA_ACPI_CLASS_CLIENT) {
411 /* client type */
412 laml = tcpa->u.client.laml;
413 } else if (class == TCPA_ACPI_CLASS_SERVER) {
414 laml = tcpa->u.server.laml;
415 }
416 }
417 return laml;
418 }
422 /*
423 * Add a measurement to the log; the data at data_seg:data/length are
424 * appended to the TCG_PCClientPCREventStruct
425 *
426 * Input parameters:
427 * pcrIndex : which PCR to extend
428 * event_type : type of event; specs 10.4.1
429 * event_id : (unused)
430 * data : pointer to the data (i.e., string) to be added to the log
431 * length : length of the data
432 */
433 static uint16_t
434 tcpa_add_measurement_to_log(uint32_t pcrIndex,
435 uint32_t event_type,
436 uint32_t event_id,
437 const char *data_ptr,
438 uint32_t length)
439 {
440 uint32_t rc = 0;
441 struct hleei_short hleei;
442 struct hleeo hleeo;
443 uint8_t _pcpes[32+400];
444 struct pcpes *pcpes = (struct pcpes *)_pcpes;
445 uint8_t *data = (uint8_t *)data_ptr;
447 if (length < sizeof(_pcpes)-32) {
448 memset(pcpes, 0x0, 32);
449 pcpes->pcrindex = pcrIndex;
450 pcpes->eventtype = event_type;
451 pcpes->eventdatasize = length;
452 memcpy(&_pcpes[32], data, length);
454 hleei.ipblength = 0x18;
455 hleei.reserved = 0x0;
456 hleei.hashdataptr = (uint32_t)&_pcpes[32];
457 hleei.hashdatalen = length;
458 hleei.pcrindex = pcrIndex;
459 hleei.logdataptr = (uint32_t)_pcpes;
460 hleei.logdatalen = length + 32;
461 rc = HashLogExtendEvent32(&hleei,
462 &hleeo,
463 TCG_MAGIC,
464 0x0,
465 0x0);
466 } else {
467 rc = (TCG_PC_TPMERROR |
468 ((uint32_t)TCG_GENERAL_ERROR << 16));
469 }
471 return rc;
472 }
474 static
475 uint16_t tcpa_add_pcpes_to_log(struct pcpes *pcpes)
476 {
477 uint32_t rc = 0;
478 struct hleei_short hleei;
479 struct hleeo hleeo;
481 hleei.ipblength = 0x18;
482 hleei.reserved = 0x0;
483 hleei.hashdataptr = 0;
484 hleei.hashdatalen = 0;
485 hleei.pcrindex = pcpes->pcrindex;
486 hleei.logdataptr = (uint32_t)pcpes;
487 hleei.logdatalen = sizeof(pcpes);
489 rc = HashLogExtendEvent32(&hleei,
490 &hleeo,
491 TCG_MAGIC,
492 0x0,
493 0x0);
495 return rc;
496 }
499 /*
500 * Add a measurement to the log; further description of the data
501 * that are to be hashed are NOT appended to the TCG_PCClientPCREventStruc.
502 * Input parameters:
503 * pcrIndex : PCR to extend
504 * event_type : type of event; specs 10.4.1
505 * ptr : 32 bit pointer to the data to be hashed
506 * length : length of the data to be hashed
507 *
508 * Returns lower 16 bit of return code of TCG_HashLogExtendEvent. '0' means
509 * success, otherwise an error is indicated.
510 */
511 static
512 uint16_t tcpa_add_measurement_to_log_simple(uint32_t pcrIndex,
513 uint16_t event_type,
514 uint8_t *ptr, uint32_t length)
515 {
516 uint32_t rc = 0;
517 struct hleei_short hleei;
518 struct hleeo hleeo;
519 struct pcpes pcpes;
521 memset(&pcpes, 0x0, sizeof(pcpes));
522 pcpes.pcrindex = pcrIndex;
523 pcpes.eventtype = event_type;
524 pcpes.eventdatasize = length;
526 hleei.ipblength = 0x18;
527 hleei.reserved = 0x0;
528 hleei.hashdataptr = (uint32_t)ptr;
529 hleei.hashdatalen = length;
530 hleei.pcrindex = pcrIndex;
531 hleei.logdataptr = (uint32_t)&pcpes;
532 hleei.logdatalen = 32;
534 rc = HashLogExtendEvent32(&hleei,
535 &hleeo,
536 TCG_MAGIC,
537 0x0,
538 0x0);
539 return rc;
540 }
542 /* table of event types according to 10.4.1 / table 11 */
543 static const char ev_action[][23] = {
544 /* 0 */ "Calling INT 19h",
545 "Returned INT 19h",
546 "Returned via INT 18h",
547 "",
548 "",
549 /* 5 */ "",
550 "",
551 "",
552 "",
553 "",
554 /* 10 */ "",
555 "",
556 "",
557 "",
558 "Start Option ROM Scan"
559 };
562 static char evt_separator[] = "---------------";
563 static char wake_event_1[] = "Wake Event 1";
566 /*
567 * Add a measurement to the list of measurements
568 * pcrIndex : PCR to be extended
569 * event_type : type of event; specs 10.4.1
570 * data : additional parameter; used as parameter for 10.4.3
571 * 'action index'
572 */
573 void tcpa_add_measurement(uint32_t pcrIndex,
574 uint16_t event_type,
575 uint32_t data)
576 {
577 const char *string;
579 switch (event_type) {
580 case EV_SEPARATOR:
581 tcpa_add_measurement_to_log(pcrIndex,
582 event_type,
583 0,
584 evt_separator,
585 strlen(evt_separator));
586 break;
587 case EV_ACTION:
588 string = ev_action[data /* event_id */];
589 tcpa_add_measurement_to_log(pcrIndex,
590 event_type,
591 data,
592 string,
593 strlen(string));
595 break;
596 }
597 }
600 /*
601 * Add measurement to log about call of int 19h
602 */
603 void tcpa_calling_int19h()
604 {
605 tcpa_add_measurement(4, EV_ACTION, 0);
606 }
608 /*
609 * Add measurement to log about retuning from int 19h
610 */
611 void tcpa_returned_int19h()
612 {
613 tcpa_add_measurement(4, EV_ACTION, 1);
614 }
616 /*
617 * Add event separators for PCRs 0 to 7; specs 8.2.3
618 */
619 void tcpa_add_event_separators()
620 {
621 uint32_t pcrIndex = 0;
622 while (pcrIndex <= 7) {
623 tcpa_add_measurement(pcrIndex, EV_SEPARATOR, 0);
624 pcrIndex ++;
625 }
626 }
629 /*
630 * Add a wake event to the log
631 */
632 void tcpa_wake_event()
633 {
634 tcpa_add_measurement_to_log(6,
635 EV_ACTION,
636 10,
637 wake_event_1,
638 strlen(wake_event_1));
639 }
641 /*
642 * add the boot device to the measurement log
643 */
644 void tcpa_add_bootdevice(uint32_t bootcd, uint32_t bootdrv)
645 {
646 char *string;
647 if (bootcd == 0) {
648 if (bootdrv == 0) {
649 string = "Booting BCV device 00h (Floppy)";
650 } else if (bootdrv == 0x80) {
651 string = "Booting BCV device 80h (HDD)";
652 } else {
653 string = "Booting unknown device";
654 }
655 } else {
656 string = "Booting from CD ROM device";
657 }
658 tcpa_add_measurement_to_log(4, 5, 0,
659 string, strlen(string));
660 }
662 /*
663 * Add measurement to the log about option rom scan
664 * 10.4.3 : action 14
665 */
666 void tcpa_start_option_rom_scan()
667 {
668 tcpa_add_measurement(2, EV_ACTION, 14);
669 }
672 /*
673 * Add measurement to the log about an option rom
674 */
675 void tcpa_option_rom(uint32_t seg)
676 {
677 uint32_t len = read_byte(seg, 2) << 9;
678 uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,0);
679 char append[32]; /* TCG_PCClientTaggedEventStruct and
680 OptionROMExecuteStructure; specs 10.4.2.1 */
681 struct hai hai; /* HashAll Input Block; specs 12.10 */
683 memset(append, 0x0, sizeof(append));
685 append[0] = 7; /* Option ROM Execute */
686 append[4] = 24;/* size of OptionROMExecute Structure */
687 /* leave the rest to '0' */
689 /* 12.10 table 21 */
690 hai.ipblength = 0x10;
691 hai.reserved = 0;
692 hai.hashdataptr = (uint32_t)addr;
693 hai.hashdatalen = len;
694 hai.algorithmid = TPM_ALG_SHA;
696 HashAll32(&hai,
697 (unsigned char *)append+12,
698 TCG_MAGIC,
699 0,
700 0);
702 tcpa_add_measurement_to_log(2,
703 EV_EVENT_TAG,
704 0,
705 append,
706 32);
707 }
709 /*
710 * Add a measurement to the log in support of 8.2.5.3
711 * Creates two log entries
712 *
713 * Input parameter:
714 * seg : segment where the IPL data are located
715 */
716 void tcpa_ipl(Bit32u seg)
717 {
718 /* specs: 8.2.5.3 */
719 uint8_t *addr = (uint8_t *)ADDR_FROM_SEG_OFF(seg,0);
720 /* equivalent to: dd if=/dev/hda ibs=1 count=440 | sha1sum */
721 tcpa_add_measurement_to_log_simple(4,
722 EV_IPL,
723 addr,
724 0x1b8);
725 /* equivalent to: dd if=/dev/hda ibs=1 count=72 skip=440 | sha1sum */
726 tcpa_add_measurement_to_log_simple(5,
727 EV_IPL_PARTITION_DATA,
728 addr + 0x1b8,
729 0x48);
730 }
732 void tcpa_measure_post(Bit32u from, Bit32u to)
733 {
734 struct pcpes pcpes; /* PCClientPCREventStruc */
735 memset(&pcpes, 0x0, sizeof(pcpes));
736 int len = to - from;
738 if (len > 0) {
739 sha1((unsigned char *)from,
740 to-from,
741 (unsigned char *)&pcpes.digest);
743 pcpes.eventtype = EV_POST_CODE;
744 pcpes.eventdatasize = 0;
745 pcpes.pcrindex = 0;
746 tcpa_add_pcpes_to_log(&pcpes);
747 }
748 }
750 static
751 uint32_t SendCommand32(uint32_t idx,
752 struct pttto *pttto,
753 uint32_t size_ptto)
754 {
755 uint32_t rc = 0;
756 struct pttti *pttti = (struct pttti *)TCG_CommandList[idx];
757 uint8_t _pttto[30];
759 if (size_ptto > 0 && size_ptto < 14) {
760 rc = (TCG_PC_TPMERROR |
761 ((uint32_t)TCG_INVALID_INPUT_PARA << 16));
762 }
764 if (rc == 0) {
765 if (size_ptto == 0) {
766 pttto = (struct pttto *)_pttto;
767 size_ptto = sizeof(_pttto);
768 }
769 pttti->opblength = size_ptto;
770 }
772 if (rc == 0) {
773 if (pttti->opblength > size_ptto) {
774 rc = (TCG_PC_TPMERROR |
775 ((uint32_t)TCG_OUTPUT_BUFFER_TOO_SHORT << 16));
776 }
777 }
779 if (rc == 0) {
780 rc = PassThroughToTPM32(pttti,
781 pttto,
782 TCG_MAGIC,
783 0x0,
784 0x0);
785 }
787 return rc;
788 }
791 uint32_t tcpa_initialize_tpm(uint32_t physpres)
792 {
793 uint32_t rc = 0;
794 uint8_t _pttto[40];
795 struct pttto *pttto = (struct pttto *)_pttto;
796 uint32_t pttto_size = sizeof(_pttto);
798 if (rc == 0) {
799 rc = SendCommand32(IDX_CMD_TPM_Startup_0x01, pttto, pttto_size);
800 }
802 if (rc == 0 && physpres != 0) {
803 rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x20,
804 pttto, pttto_size);
805 }
807 if (rc == 0 && physpres != 0) {
808 rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x08,
809 pttto, pttto_size);
810 }
812 if (rc == 0 && physpres != 0) {
813 rc = SendCommand32(IDX_CMD_TPM_PhysicalEnable,
814 pttto, pttto_size);
815 }
817 if (rc == 0 && physpres != 0) {
818 rc = SendCommand32(IDX_CMD_TPM_PhysicalSetDeactivated_0x00,
819 pttto, pttto_size);
820 }
822 if (rc == 0) {
823 rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x100,
824 pttto, pttto_size);
825 }
827 if (rc == 0) {
828 rc = SendCommand32(IDX_CMD_TSC_PhysicalPresence_0x10,
829 pttto, pttto_size);
830 }
831 return rc;
832 }
835 uint16_t TCG_IsShutdownPreBootInterface(void)
836 {
837 return tcpa_acpi.flags & STATUS_FLAG_SHUTDOWN;
838 }
841 static
842 uint32_t _TCG_TPM_Extend(unsigned char *hash, uint32_t pcrindex)
843 {
844 uint32_t rc;
845 uint8_t _pttti[8+34];
846 uint8_t _pttto[4+30];
847 struct pttti *pttti = (struct pttti*)&_pttti;
848 struct pttto *pttto = (struct pttto*)&_pttto;
850 pttti->ipblength = 8 + 34;
851 pttti->reserved = 0;
852 pttti->opblength = 4 + 30;
853 pttti->reserved2 = 0;
855 _pttti[8 + 0] = 0x0;
856 _pttti[8 + 1] = 0xc1;
857 *(uint32_t *)&_pttti[8 + 2] = bswap(34);
858 *(uint32_t *)&_pttti[8 + 6] = bswap(0x14);
859 *(uint32_t *)&_pttti[8 + 10]= bswap(pcrindex);
860 memcpy(&_pttti[8+14], hash, 20);
862 rc = PassThroughToTPM32(pttti,
863 pttto,
864 TCG_MAGIC,
865 0x0,
866 0x0);
867 /* sanity check of result */
868 if (_pttto[4] != 0x00 || _pttto[5] != 0xc4) {
869 rc = (TCG_PC_TPMERROR |
870 ((uint32_t)TCG_FATAL_COM_ERROR << 16));
871 }
873 if (rc != 0) {
874 /*
875 Invalidate the log since system did not process this
876 extend properly.
877 */
878 tcpa_reset_acpi_log();
879 memset(&tcpa_acpi, 0x0, sizeof(tcpa_acpi));
880 TCG_ShutdownPreBootInterface(0);
881 }
882 return rc;
883 }
886 static
887 uint32_t HashLogExtendEvent32(struct hleei_short *hleei_s,
888 struct hleeo *hleeo,
889 uint32_t magic,
890 uint32_t ecx,
891 uint32_t edx)
892 {
893 uint32_t rc = 0;
894 uint16_t size;
895 struct hlei hlei ; /* HashLogEventInput block */
896 struct hleo hleo; /* HashLogEventOutput block */
897 struct hleei_long *hleei_l = (struct hleei_long *)hleei_s;
898 int sh;
899 uint32_t logdataptr;
901 if (TCG_IsShutdownPreBootInterface() != 0) {
902 rc = (TCG_PC_TPMERROR |
903 ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
904 }
906 if (rc == 0) {
907 /* short or long version? */
908 size = hleei_s->ipblength;
909 if (size == 0x18) {
910 /* short */
911 sh = 1;
912 } else if (size == 0x1c) {
913 /* long */
914 sh = 0;
915 } else {
916 /* bad input block */
917 rc = TCG_PC_TPMERROR |
918 ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
919 }
920 }
922 if (rc == 0) {
923 uint32_t hashdataptr;
924 uint32_t hashdatalen;
925 uint32_t pcrindex;
926 uint32_t logeventtype;
927 uint32_t logdatalen;
928 uint32_t eventnumber;
929 uint8_t hash[20];
930 struct pcpes *pcpes;
932 hashdataptr = hleei_s->hashdataptr;
933 hashdatalen = hleei_s->hashdatalen;
934 pcrindex = hleei_s->pcrindex;
935 if (sh) {
936 logdataptr = hleei_s->logdataptr;
937 logdatalen = hleei_s->logdatalen;
938 } else {
939 logdataptr = hleei_l->logdataptr;
940 logdatalen = hleei_l->logdatalen;
941 }
943 pcpes = (struct pcpes *)logdataptr;
944 logeventtype = pcpes->eventtype;
946 /* fill out HashLogEventInput block 'hlie' */
947 hlei.ipblength = 0x1c;
948 hlei.reserved = 0;
949 hlei.hashdataptr = hashdataptr;
950 hlei.hashdatalen = hashdatalen;
951 hlei.pcrindex = pcrindex;
952 hlei.logeventtype= logeventtype;
953 hlei.logdataptr = logdataptr;
954 hlei.logdatalen = logdatalen;
956 rc = HashLogEvent32(&hlei,
957 &hleo,
958 TCG_MAGIC,
959 0x0,
960 0x0);
961 eventnumber = hleo.eventnumber;
963 hleeo->opblength = 8 + 20;
964 hleeo->reserved = 0;
965 hleeo->eventnumber = eventnumber;
967 memcpy(hash, (unsigned char *)logdataptr + 0x8, 20);
968 _TCG_TPM_Extend(hash, pcrindex);
969 }
971 if (rc != 0) {
972 hleeo->opblength = 4;
973 hleeo->reserved = 0;
974 }
975 return rc;
977 }
980 static
981 uint32_t PassThroughToTPM32(struct pttti *pttti,
982 struct pttto *pttto,
983 uint32_t magic,
984 uint32_t ecx,
985 uint32_t edx)
986 {
987 uint32_t rc = 0;
988 uint8_t *cmd32;
989 uint32_t resbuflen;
991 if (TCG_IsShutdownPreBootInterface() != 0) {
992 rc = (TCG_PC_TPMERROR |
993 ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
994 }
996 if (rc == 0) {
997 if (pttti->ipblength < 0x8 + 10) {
998 rc = TCG_PC_TPMERROR |
999 ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
1003 if (rc == 0) {
1004 if (pttti->opblength < 0x4) {
1005 rc = TCG_PC_TPMERROR |
1006 ((uint32_t)(TCG_INVALID_ACCESS_REQUEST << 16));
1010 if (rc == 0) {
1011 uint8_t *resbuf32;
1013 cmd32 = &pttti->tpmoperandin[0];
1014 resbuflen = pttti->opblength - 4;
1015 resbuf32 = &pttto->tpmoperandout[0];
1017 rc = MA_Transmit(cmd32, resbuf32, resbuflen);
1020 if (rc == 0) {
1021 pttto->opblength = resbuflen+4;
1022 pttto->reserved = 0;
1025 if (rc != 0) {
1026 pttto->opblength = 0;
1027 pttto->reserved = 0;
1030 return rc;
1034 static
1035 uint32_t TCG_ShutdownPreBootInterface(uint32_t ebx)
1037 uint32_t rc = 0;
1038 if (TCG_IsShutdownPreBootInterface() == 0) {
1039 tcpa_acpi.flags |= STATUS_FLAG_SHUTDOWN;
1040 } else {
1041 rc = (TCG_PC_TPMERROR |
1042 ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1044 return rc;
1048 static
1049 uint32_t HashLogEvent32(struct hlei *hlei, struct hleo *hleo,
1050 uint32_t ebx,
1051 uint32_t ecx,
1052 uint32_t edx)
1054 uint32_t rc = 0;
1055 uint16_t size;
1056 uint32_t logdataptr;
1057 uint32_t logdatalen;
1058 uint32_t hashdataptr;
1059 uint32_t hashdatalen;
1061 if (TCG_IsShutdownPreBootInterface() != 0) {
1062 rc = (TCG_PC_TPMERROR |
1063 ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1066 if (rc == 0) {
1067 size = hlei->ipblength;
1068 if (size != 0x1c) {
1069 rc = (TCG_PC_TPMERROR |
1070 ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1074 if (rc == 0) {
1075 struct pcpes *pcpes;
1076 logdataptr = hlei->logdataptr;
1077 logdatalen = hlei->logdatalen;
1078 pcpes = (struct pcpes *)logdataptr;
1079 if (pcpes->pcrindex != hlei->pcrindex) {
1080 rc = (TCG_PC_TPMERROR |
1081 ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1085 if (rc == 0) {
1086 struct pcpes *pcpes= (struct pcpes *)logdataptr;
1087 if (pcpes->eventtype != hlei->logeventtype) {
1088 rc = (TCG_PC_TPMERROR |
1089 ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1093 if (rc == 0) {
1094 uint32_t entry;
1095 hashdataptr = hlei->hashdataptr;
1096 hashdatalen = hlei->hashdatalen;
1098 if ((hashdataptr != 0) | (hashdatalen != 0)) {
1099 uint8_t hash[20];
1100 struct hai hai; /* HashAll Input Block */
1101 hai.ipblength = 0x10;
1102 hai.reserved = 0x0;
1103 hai.hashdataptr = hashdataptr;
1104 hai.hashdatalen = hashdatalen;
1105 hai.algorithmid = TPM_ALG_SHA;
1106 rc = HashAll32(&hai,
1107 hash,
1108 TCG_MAGIC,
1109 0x0,
1110 0x0);
1112 if (rc == 0) {
1113 /* hashing was done ok */
1114 memcpy((unsigned char *)logdataptr + 8,
1115 hash,
1116 20);
1120 if (rc == 0) {
1121 /* extend the log with this event */
1122 entry = tcpa_extend_acpi_log(logdataptr);
1123 if ((uint16_t)entry == 0) {
1124 /* upper 16 bits hold error code */
1125 rc = (entry >> 16);
1129 if (rc == 0) {
1130 /* updating the log was fine */
1131 hleo->opblength = 8;
1132 hleo->reserved = 0;
1133 hleo->eventnumber = entry;
1137 if (rc != 0) {
1138 hleo->opblength = 2;
1139 hleo->reserved = 0;
1142 return rc;
1145 static
1146 uint32_t HashAll32(struct hai *hai, unsigned char *hash,
1147 uint32_t magic,
1148 uint32_t ecx,
1149 uint32_t edx)
1151 uint32_t rc = 0;
1153 if (TCG_IsShutdownPreBootInterface() != 0) {
1154 rc = (TCG_PC_TPMERROR |
1155 ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1158 if (rc == 0) {
1159 if (hai->ipblength != 0x10) {
1160 rc = (TCG_PC_TPMERROR |
1161 ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1165 if (rc == 0) {
1166 if (hai->algorithmid != TPM_ALG_SHA) {
1167 rc = (TCG_PC_TPMERROR |
1168 ((uint32_t)TCG_INVALID_ACCESS_REQUEST << 16));
1172 if (rc == 0) {
1173 uint8_t *hashdataptr32;
1174 uint32_t hashdatalen32;
1176 hashdataptr32 = (uint8_t *)hai->hashdataptr;
1177 hashdatalen32 = hai->hashdatalen;
1179 sha1(hashdataptr32,
1180 hashdatalen32,
1181 hash);
1184 return rc;
1188 static
1189 uint32_t TSS32(struct ti *ti, struct to *to,
1190 uint32_t ebx,
1191 uint32_t ecx,
1192 uint32_t edx)
1194 uint32_t rc = 0;
1195 if (TCG_IsShutdownPreBootInterface() == 0) {
1196 rc = TCG_PC_UNSUPPORTED;
1197 } else {
1198 rc = (TCG_PC_TPMERROR |
1199 ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1202 if (rc != 0) {
1203 to->opblength = 4;
1204 to->reserved = 0;
1207 return rc;
1210 static
1211 uint32_t CompactHashLogExtendEvent32(unsigned char *buffer,
1212 uint32_t info,
1213 uint32_t magic,
1214 uint32_t length,
1215 uint32_t pcrindex,
1216 uint32_t *edx_ptr)
1218 uint32_t rc = 0;
1219 struct hleeo hleeo;
1221 if (TCG_IsShutdownPreBootInterface() != 0) {
1222 rc = (TCG_PC_TPMERROR |
1223 ((uint32_t)TCG_INTERFACE_SHUTDOWN << 16));
1226 if (buffer == 0) {
1227 rc = (TCG_PC_TPMERROR |
1228 ((uint32_t)TCG_INVALID_INPUT_PARA << 16));
1231 if (rc == 0) {
1232 struct hleei_short hleei;
1233 struct pcpes pcpes;
1234 uint8_t *logdataptr;
1235 uint8_t *hashdataptr;
1237 logdataptr = (uint8_t*)&pcpes;
1238 hashdataptr = buffer;
1240 hleei.ipblength = 0x18;
1241 hleei.reserved = 0x0;
1242 hleei.hashdataptr = (uint32_t)hashdataptr;
1243 hleei.hashdatalen = length;
1244 hleei.pcrindex = pcrindex;
1245 hleei.logdataptr = (uint32_t)logdataptr;
1246 hleei.logdatalen = 32;
1248 memset(&pcpes, 0x0, 32);
1249 pcpes.pcrindex = pcrindex;
1250 pcpes.eventtype = 12; /* EV_COMPACT_HASH */
1251 pcpes.eventdatasize = 4;
1252 pcpes.event = info;
1254 rc = HashLogExtendEvent32(&hleei,
1255 &hleeo,
1256 TCG_MAGIC,
1257 0x0,
1258 0x0);
1261 if (rc == 0) {
1262 *edx_ptr = hleeo.eventnumber;
1265 return rc;
1270 /*******************************************************************
1271 Calculation of SHA1 in SW
1273 See: RFC3174, Wikipedia's SHA1 alogrithm description
1274 ******************************************************************/
1275 typedef struct _sha1_ctx {
1276 uint32_t h[5];
1277 } sha1_ctx;
1280 static inline uint32_t rol(val, rol)
1281 uint32_t val;
1282 uint16_t rol;
1284 return (val << rol) | (val >> (32 - rol));
1287 static const uint32_t sha_ko[4] = { 0x5a827999,
1288 0x6ed9eba1,
1289 0x8f1bbcdc,
1290 0xca62c1d6 };
1293 static void sha1_block(uint32_t *w, sha1_ctx *ctx)
1295 uint32_t i;
1296 uint32_t a,b,c,d,e,f;
1297 uint32_t tmp;
1298 uint32_t idx;
1300 /* change endianess of given data */
1301 for (i = 0; i < 16; i++) {
1302 w[i] = bswap(w[i]);
1305 for (i = 16; i <= 79; i++) {
1306 tmp = w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16];
1307 w[i] = rol(tmp,1);
1310 a = ctx->h[0];
1311 b = ctx->h[1];
1312 c = ctx->h[2];
1313 d = ctx->h[3];
1314 e = ctx->h[4];
1316 for (i = 0; i <= 79; i++) {
1317 if (i <= 19) {
1318 f = (b & c) | ((b ^ 0xffffffff) & d);
1319 idx = 0;
1320 } else if (i <= 39) {
1321 f = b ^ c ^ d;
1322 idx = 1;
1323 } else if (i <= 59) {
1324 f = (b & c) | (b & d) | (c & d);
1325 idx = 2;
1326 } else {
1327 f = b ^ c ^ d;
1328 idx = 3;
1331 tmp = rol(a, 5) +
1332 f +
1333 e +
1334 sha_ko[idx] +
1335 w[i];
1336 e = d;
1337 d = c;
1338 c = rol(b, 30);
1339 b = a;
1340 a = tmp;
1343 ctx->h[0] += a;
1344 ctx->h[1] += b;
1345 ctx->h[2] += c;
1346 ctx->h[3] += d;
1347 ctx->h[4] += e;
1350 static
1351 void sha1_do(sha1_ctx *ctx, const unsigned char *data32, uint32_t length)
1353 uint32_t offset;
1354 uint16_t num;
1355 uint32_t bits = 0;
1356 uint32_t w[80];
1357 uint32_t tmp;
1359 /* treat data in 64-byte chunks */
1360 for (offset = 0; length - offset >= 64; offset += 64) {
1361 /* copy into the 'w' array */
1362 memcpy(w, data32 + offset, 64);
1363 /* hash the block in the 'w' array */
1364 sha1_block((uint32_t *)w, ctx);
1365 bits += (64 * 8);
1368 /* last block with less than 64 bytes */
1369 num = length - offset;
1370 bits += (num << 3);
1372 memset(w, 0x0, 64);
1373 memcpy(w, data32 + offset, num);
1374 ((uint8_t *)w)[num] = 0x80;
1376 if (num >= 56) {
1377 /* cannot append number of bits here */
1378 sha1_block((uint32_t *)w, ctx);
1379 memset(w, 0x0, 60);
1382 /* write number of bits to end of block */
1383 tmp = bswap(bits);
1384 memcpy(&w[15], &tmp, 4);
1386 sha1_block(w, ctx);
1388 /* need to switch result's endianess */
1389 for (num = 0; num < 5; num++)
1390 ctx->h[num] = bswap(ctx->h[num]);
1393 /* sha1 initialization constants */
1394 static const uint32_t sha_const[5] = {
1395 0x67452301,
1396 0xefcdab89,
1397 0x98badcfe,
1398 0x10325476,
1399 0xc3d2e1f0
1400 };
1402 static
1403 void sha1(const unsigned char *data, uint32_t length, unsigned char *hash)
1405 sha1_ctx ctx;
1407 memcpy(&ctx.h[0], sha_const, 20);
1408 sha1_do(&ctx, data, length);
1409 memcpy(hash, &ctx.h[0], 20);
1413 uint32_t TCGInterruptHandler(pushad_regs_t *regs, uint32_t esds, uint32_t flags_ptr)
1415 uint16_t DS = esds >> 16;
1416 uint16_t ES = esds & 0xffff;
1417 uint16_t *FLAGS = (uint16_t *)flags_ptr;
1419 switch(regs->u.r8.al) {
1420 case 0x00:
1421 if (MA_IsTPMPresent() == 0) {
1422 /* no TPM available */
1423 regs->u.r32.eax = TCG_PC_TPMERROR |
1424 ((uint32_t)(TCG_PC_TPM_NOT_PRESENT) << 16);
1425 } else {
1426 regs->u.r32.eax = MA_InitTPM(TPM_ST_CLEAR);
1427 if (regs->u.r32.eax == 0) {
1428 regs->u.r32.ebx = TCG_MAGIC;
1429 regs->u.r8.ch = TCG_VERSION_MAJOR;
1430 regs->u.r8.cl = TCG_VERSION_MINOR;
1431 regs->u.r32.edx = 0x0;
1432 regs->u.r32.esi =
1433 (Bit32u)tcpa_get_lasa_base_ptr();
1434 regs->u.r32.edi =
1435 (Bit32u)tcpa_get_lasa_last_ptr();
1436 CLEAR_CF();
1439 break;
1441 case 0x01:
1442 regs->u.r32.eax =
1443 HashLogExtendEvent32((struct hleei_short*)
1444 ADDR_FROM_SEG_OFF(ES,
1445 regs->u.r16.di),
1446 (struct hleeo*)
1447 ADDR_FROM_SEG_OFF(DS,
1448 regs->u.r16.si),
1449 regs->u.r32.ebx,
1450 regs->u.r32.ecx,
1451 regs->u.r32.edx);
1452 CLEAR_CF();
1453 break;
1454 case 0x02:
1455 regs->u.r32.eax =
1456 PassThroughToTPM32((struct pttti *)
1457 ADDR_FROM_SEG_OFF(ES,
1458 regs->u.r16.di),
1459 (struct pttto *)
1460 ADDR_FROM_SEG_OFF(DS,
1461 regs->u.r16.si),
1462 regs->u.r32.ebx,
1463 regs->u.r32.ecx,
1464 regs->u.r32.edx);
1465 CLEAR_CF();
1466 break;
1467 case 0x03:
1468 regs->u.r32.eax =
1469 TCG_ShutdownPreBootInterface(regs->u.r32.ebx);
1470 CLEAR_CF();
1471 break;
1472 case 0x04:
1473 regs->u.r32.eax =
1474 HashLogEvent32((struct hlei*)
1475 ADDR_FROM_SEG_OFF(ES,
1476 regs->u.r16.di),
1477 (struct hleo*)
1478 ADDR_FROM_SEG_OFF(DS,
1479 regs->u.r16.si),
1480 regs->u.r32.ebx,
1481 regs->u.r32.ecx,
1482 regs->u.r32.edx);
1483 CLEAR_CF();
1484 break;
1485 case 0x05:
1486 regs->u.r32.eax =
1487 HashAll32((struct hai*)
1488 ADDR_FROM_SEG_OFF(ES,
1489 regs->u.r16.di),
1490 (unsigned char *)
1491 ADDR_FROM_SEG_OFF(DS,
1492 regs->u.r16.si),
1493 regs->u.r32.ebx,
1494 regs->u.r32.ecx,
1495 regs->u.r32.edx);
1496 CLEAR_CF();
1497 break;
1498 case 0x06:
1499 regs->u.r32.eax =
1500 TSS32((struct ti*)ADDR_FROM_SEG_OFF(ES,
1501 regs->u.r16.di),
1502 (struct to*)ADDR_FROM_SEG_OFF(DS,
1503 regs->u.r16.si),
1504 regs->u.r32.ebx,
1505 regs->u.r32.ecx,
1506 regs->u.r32.edx);
1507 CLEAR_CF();
1508 break;
1509 case 0x07:
1510 regs->u.r32.eax =
1511 CompactHashLogExtendEvent32((unsigned char *)
1512 ADDR_FROM_SEG_OFF(ES,
1513 regs->u.r16.di),
1514 regs->u.r32.esi,
1515 regs->u.r32.ebx,
1516 regs->u.r32.ecx,
1517 regs->u.r32.edx,
1518 &regs->u.r32.edx);
1519 CLEAR_CF();
1520 break;
1521 default:
1522 SET_CF();
1525 return 0;