--- grub-0.97/stage1/stage1.h.orig	2005-02-16 06:55:15.000000000 +0900
+++ grub-0.97/stage1/stage1.h	2005-05-26 16:06:48.540868272 +0900
@@ -83,4 +83,29 @@
 /* The drive number of an invalid drive.  */
 #define GRUB_INVALID_DRIVE	0xFF
 
+
+#ifdef TCG_TRUSTED_BOOT
+
+/* The TPM PCR index for measuring grub modules (stage1.5 and 2). */
+#ifndef TCG_GRUB_PCR_INDEX
+#define TCG_GRUB_PCR_INDEX 4  
+#endif
+
+/* The TPM PCR index for measuring grub configuration file. */
+#ifndef TCG_GRUB_CONF_PCR_INDEX
+#define TCG_GRUB_CONF_PCR_INDEX 5  
+#endif
+
+/* The TPM PCR index for measuring the OS files. */
+#ifndef TCG_FILE_PCR_INDEX
+#define TCG_FILE_PCR_INDEX 8  
+#endif
+
+/* The TPM PCR EventType for measuring grub modules (stage1.5 and 2). */
+#ifndef TCG_GRUB_PCR_EVENTTYPE
+#define TCG_GRUB_PCR_EVENTTYPE 1
+#endif
+
+#endif /* TCG_TRUSTED_BOOT */
+
 #endif /* ! STAGE1_HEADER */
--- grub-0.97/stage1/stage1.S.orig	2005-02-16 06:54:31.000000000 +0900
+++ grub-0.97/stage1/stage1.S	2005-05-26 16:06:48.541868120 +0900
@@ -18,6 +18,21 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#ifdef TCG_TRUSTED_BOOT
+/*
+ *  Changes:
+ *   1) Remove CHS part to get thecode space for TCG Trusted Boot 
+ *   2) Measure the 1st sector of stage 1.5 before jump to them
+ *
+ *   TCG_HashAll & TCG_LogEvent are used insted of the single 
+ *   TCG_HashLogEvent call.
+ *
+ *  2002/12/XX Y. Yamashita  Original Patch
+ *  2004/06/28 S. Munetoh    Last Update
+ */
+#endif /* TCG_TRUSTED_BOOT */
+
+
 #include <stage1.h>
 	
 /*
@@ -153,6 +168,7 @@ real_start:	
 	/* print a notification message on the screen */
 	MSG(notification_string)
 
+#ifndef TCG_TRUSTED_BOOT
 	/* do not probe LBA if the drive is a floppy */
 	testb	$STAGE1_BIOS_HD_FLAG, %dl
 	jz	chs_mode
@@ -180,7 +196,8 @@ real_start:	
 	jnz	lba_mode
 	andw	$1, %cx
 	jz	chs_mode
-	
+#endif /* TCG_TRUSTED_BOOT */
+		
 lba_mode:
 	/* save the total number of sectors */
 	movl	0x10(%si), %ecx
@@ -227,7 +244,11 @@ lba_mode:
 	movw	$STAGE1_BUFFERSEG, %bx
 	jmp	copy_buffer
 		
-chs_mode:	
+chs_mode:
+#ifdef TCG_TRUSTED_BOOT
+	MSG(chs_no_support_string)
+	jmp     general_error
+#else /* TCG_TRUSTED_BOOT */ 	
 	/*
 	 *  Determine the hard disk geometry from the BIOS!
 	 *  We do this first, so that LS-120 IDE floppies work correctly.
@@ -345,8 +366,105 @@ setup_sectors:
 	jc	read_error
 
 	movw	%es, %bx
+#endif /* TCG_TRUSTED_BOOT */
 	
 copy_buffer:
+
+#ifdef TCG_TRUSTED_BOOT
+
+	pusha
+#ifdef TCG_BIOS_BIGREALMODE_FIX
+	cli
+
+	/* Transit to big-real-mode */
+	DATA32 lgdt gdtdesc
+
+	/* turn on protected mode */
+	movl	%cr0, %eax
+	orb	$0x01, %al 
+	movl	%eax, %cr0
+
+	movw	$0x0008, %bx
+	movw	%bx, %ds
+	movw	%bx, %es
+	
+	/* Back to real mode */
+	decb	%al
+	movl	%eax, %cr0
+	
+	/* Enable A20 gate */
+	movw	$0x2401, %ax
+	int	$0x15
+
+	sti
+#endif /* TCG_BIOS_BIGREALMODE_FIX */
+	push	%cs
+	push	%cs
+	pop	%ds
+	pop	%es
+
+/*
+ * BIOS call "INT 1Ah, (AH)=BBh,(AL)=05h" TCG_HashAll 
+ *	Call with	%ah = 0xBB
+ *			%al = 0x05
+ *			%es:%di = segment:offset of input parametor block
+ *			%ds:%si = segment:offset of output parametor block
+ *			%ebx = 'TCPA'
+ *			%ecx = 0
+ *			%edx = 0
+ *	Return:
+ *			%eax = TCG_STATUS
+ *			%ds:%si = segment:offset of referenced buffer
+ *
+ * Ref:	 TCG PC Specification v1.0, Section 8.1.8 (page 49)
+ */
+tcg_hashall:
+        movw    $0xbb05, %ax   		      /* TCG_HashAll */
+        movw    $ABS(ipb), %di		      /* ES:DI = IPB */
+        movw    $ABS(tcg_pcr_event + 8), %si /* DS:SI = OPB */
+        movl    $0x41504354, %ebx 	      /* EBX = "TCPA" */
+        xorl    %ecx, %ecx		      /* ECX = 0 */
+        xorl    %edx, %edx		      /* EDX = 0 */
+        int     $0x1a
+	/*
+	test	%eax, %eax
+	jnz	tcg_error 
+	*/
+	
+/*
+ * BIOS call "INT 1Ah, (AH)=BBh,(AL)=04h" TCG_LogEvent
+ *	Call with	%ah = 0xBB
+ *			%al = 0x04
+ *			%es:%di = segment:offset of input parametor block
+ *			%ds:%si = segment:offset of output parametor block
+ *			%ebx = 'TCPA'
+ *			%ecx = 0
+ *			%edx = 0
+ *	Return:
+ *			%eax = TCG_STATUS
+ *			%ds:%si = ?
+ *
+ * Ref:	 TCG PC Specification v1.0, Section 8.1.7 (page 47)
+ */
+	/* Set tcg_pcr_event.eventSize = 0 */
+tcg_logevent:
+	movl	%eax, ABS(tcg_pcr_event + 28)
+	movb	$(ipb_logevent_end - ipb), ABS(ipb_len)
+	movb	$TCG_GRUB_PCR_INDEX, ABS(ipb_pcrindex)
+        movw    $0xbb04, %ax   		/* TCG_LogEvent */
+	movw	$0x8E00, %si		/* OPB = 0x8E00 */
+        int     $0x1a
+#if 0
+	test	%eax, %eax
+	jz	tcg_end
+tcg_error:
+	MSG(tcg_error_string)
+#endif /* 0 */
+tcg_end:
+        popa
+
+#endif /* TCG_TRUSTED_BOOT */
+
 	movw	ABS(stage2_segment), %es
 
 	/*
@@ -405,6 +523,10 @@ geometry_error_string:	.string "Geom"
 hd_probe_error_string:	.string "Hard Disk"
 read_error_string:	.string "Read"
 general_error_string:	.string " Error"
+#ifdef TCG_TRUSTED_BOOT
+chs_no_support_string:	.string "CHSNA"
+tcg_error_string:	.string "TCGERR "
+#endif
 
 /*
  * message: write the string pointed to by %si
@@ -427,6 +549,46 @@ message:
 	jne	1b	/* if not end of string, jmp to display */
 	ret
 
+#ifdef TCG_TRUSTED_BOOT
+
+/* TCG Signature */
+gdtdesc:
+	.word	(gdt_end - gdt - 1)	/* limit */
+	.long	ABS(gdt)		/* addr */
+	.p2align	2	/* force 4-byte alignment */
+gdt:
+	.word	0, 0
+	.byte	0, 0, 0, 0
+	/* 32 bit data segment */
+	.word	0xFFFF, 0
+	.byte	0, 0x92, 0xCF, 0
+gdt_end:
+
+/* TCG(TCG) BIOS Input Parameter Block */
+ipb:
+ipb_len: .word	(ipb_hashall_end - ipb)	 /*  0 block size   */
+         .word   0                       /*  4 reserved     */
+         .long   STAGE1_BUFFERSEG * 0x10 /*  8 data pointer */
+         .long   0x200                   /* 16 data size (512 bytes) */
+ipb_pcrindex:
+ipb_algorithmid:
+         .long   4                       /* AlgorighmID = TCG_ALG_SHA for HashAll*/ 
+					 /* PCRIndex for LogEvent */
+ipb_hashall_end:
+	.long	TCG_GRUB_PCR_EVENTTYPE	 /* event type	*/
+        .long   ABS(tcg_pcr_event)      /* log pointer  */
+        .long   32                       /* log size     */
+ipb_logevent_end:
+
+	/* TCG_PCR_EVENT structure */
+tcg_pcr_event:                         /* 32 bytes     */
+        .long   TCG_GRUB_PCR_INDEX      /* PCR index    */
+        .long   TCG_GRUB_PCR_EVENTTYPE  /* event type   */
+/*      .space  20                      |* PCR value    */
+/*      .long   0                       |* event size   */
+
+#endif /* TCG_TRUSTED_BOOT  */
+	
 	/*
 	 *  Windows NT breaks compatibility by embedding a magic
 	 *  number here.
@@ -446,6 +608,7 @@ nt_magic:	
 part_start:	
 	. = _start + STAGE1_PARTSTART
 
+#ifndef TCG_TRUSTED_BOOT
 probe_values:
 	.byte	36, 18, 15, 9, 0
 
@@ -493,6 +656,8 @@ fd_probe_error_string:	.string "Floppy"
 
 	jmp	final_init
 
+#endif /* TCG_TRUSTED_BOOT */
+
 	. = _start + STAGE1_PARTEND
 
 /* the last 2 bytes in the sector 0 contain the signature */
--- grub-0.97/stage2/shared.h.orig	2004-06-20 01:40:09.000000000 +0900
+++ grub-0.97/stage2/shared.h	2005-05-26 16:06:48.542867968 +0900
@@ -991,6 +991,26 @@ int check_password(char *entered, char* 
 
 void init_bios_info (void);
 
+#ifdef TCG_TRUSTED_BOOT
+
+/* SM DEBUG */
+/*  #define TCG_TRUSTED_BOOT_STEPBYSTEP */
+
+int measure_file(char *filename, int pcr_index, int logevent);
+int tcg_status_check(unsigned char **event_log);
+int tcg_extend(int pcr_index, unsigned char *digest,
+                   unsigned char *pcr_value);
+int tcg_log_extend(int pcr_index, unsigned char *digest);
+int tcg_pcr_read(int pcr_index, unsigned char *pcr_value);
+int tcg_hash_all(int data_len, unsigned char *data, unsigned char *digest);
+
+#define SHA1_DIGEST_SIZE 20
+
+/* builtins.c */
+extern int   tcg_grub_pcr_index;
+extern char *tcg_grub_log; /* TBD */
+#endif /* TCG_TRUSTED_BOOT */
+
 #endif /* ASM_FILE */
 
 #endif /* ! GRUB_SHARED_HEADER */
--- grub-0.97/stage2/start.S.orig	2003-07-09 20:45:53.000000000 +0900
+++ grub-0.97/stage2/start.S	2005-05-26 16:06:48.544867664 +0900
@@ -86,11 +86,13 @@ bootloop:
 	je	bootit
 
 setup_sectors:	
+#ifndef TCG_TRUSTED_BOOT
 	/* check if we use LBA or CHS */
 	cmpb	$0, -1(%si)
 
 	/* jump to chs_mode if zero */
 	je	chs_mode
+#endif /* !TCG_TRUSTED_BOOT */
 
 lba_mode:	
 	/* load logical sector start */
@@ -158,6 +160,7 @@ lba_mode:	
 	jc	read_error
 
 	movw	$BUFFERSEG, %bx
+#ifndef TCG_TRUSTED_BOOT
 	jmp	copy_buffer
 			
 chs_mode:	
@@ -257,7 +260,8 @@ chs_mode:	
 
 	/* save source segment */
 	movw	%es, %bx
-	
+#endif /* !TCG_TRUSTED_BOOT */
+
 copy_buffer:	
 
 	/* load addresses for copy from disk buffer to destination */
@@ -284,6 +288,10 @@ copy_buffer:	
 	xorw	%si, %si	/* zero offset of source addresses */
 	movw	%bx, %ds	/* restore the source segment */
 
+#ifdef  TCG_TRUSTED_BOOT
+        call    tcg_measure
+#endif
+
 	cld		/* sets the copy direction to forward */
 
 	/* perform copy */
@@ -339,18 +347,205 @@ general_error:
 stop:	jmp	stop
 
 #ifdef STAGE1_5
+#ifdef TCG_TRUSTED_BOOT
+notification_string:	.string "Loading stage1.5t"
+#else
 notification_string:	.string "Loading stage1.5"
+#endif /* TCG_TRUSTED_BOOT */
 #else
 notification_string:	.string "Loading stage2"
 #endif
 
-notification_step:	.string "."
+notification_step:	.string "<+>"
 notification_done:	.string "\r\n"
 	
 geometry_error_string:	.string "Geom"
 read_error_string:	.string "Read"
 general_error_string:	.string " Error"
 
+#ifdef TCG_TRUSTED_BOOT
+tcg_debug_string:	.string "<T>"
+/*
+ * ds:si = buffer
+ * cx    = size
+ */	
+tcg_measure:
+
+        pushal
+        push    %ds
+        push    %es
+
+#ifdef TCG_BIOS_BIGREALMODE_FIX
+        //cli
+
+        /* Transit to big-real-mode */
+        DATA32 lgdt gdtdesc
+
+        /* turn on protected mode */
+        movl    %cr0, %eax
+        orb     $0x01, %al 
+        movl    %eax, %cr0
+
+        movw    $0x0008, %bx
+        movw    %bx, %ds
+        movw    %bx, %es
+        
+        /* Back to real mode */
+        decb    %al
+        movl    %eax, %cr0
+	
+        /* Enable A20 gate */
+        movw    $0x2401, %ax
+        int     $0x15
+
+        //sti
+#endif	/* TCG_BIOS_BIGREALMODE_FIX */
+	
+/*
+ * BIOS call "INT 1Ah, (AH)=BBh,(AL)=05h" TCG_HashAll 
+ *	Call with	%ah = 0xBB
+ *			%al = 0x05
+ *			%es:%di = segment:offset of input parametor block
+ *			%ds:%si = segment:offset of output parametor block
+ *			%ebx = 'TCPA'
+ *			%ecx = 0
+ *			%edx = 0
+ *	Return:
+ *			%eax = TCG_STATUS
+ *			%ds:%si = segment:offset of referenced buffer
+ *
+ * Ref:	 TCG PC Specification v1.0, Section 8.1.8 (page 49)
+ */	
+        movw    %ds, %di
+        xorw    %ax, %ax		/* ax =0 */
+        movw    %ax, %ds		/* ds =0 */
+        movw    %ax, %es		/* es =0 */
+	movw    $0xbb05, %ax            /* ah=BBh,al=05h, TCG_HashAll */
+        movzx   %si, %esi
+        movzx   %di, %edi
+        shll    $4,  %edi
+        addl    %edi,%esi		/* esi= (32-bit phisical address) */
+	
+        movw    $ABS(tcg_memo), %di	/* IPB */
+        movl    %esi,0(%di)		/* HashDataPtr */
+        movw    %cx, 4(%di)		/* HashDataLen */
+
+	/* Setup IPB */	
+        movw    $ABS(ha_ipb), %di	/* di=IPB */
+        movl    %esi, 4(%di)		/* HashDataPtr */
+        movw    %cx,  8(%di)		/* HashDataLen */
+
+        movw    $ABS(tpe_pcrvalue),%si  /* si=OPB */
+        movl    ABS(tcg_sig), %ebx	/* (EBX)='TCPA' */
+        xorl    %ecx, %ecx		/* (ECX)=xero */
+        movl    %ecx, %edx		/* (EDX)=xero */
+	
+        int     $0x1a			/* INT 1Ah */
+
+	/*
+	(EAX)=TCG_STATUS
+	(DS:SI)=Referenced buffer updated to provide return result 
+	*/
+	
+#if 1 /* Hash[0] hold lenth */
+        /* movl    %esi, 0(%si) */		/* HashDataPtr */
+        movw    ABS(tcg_memo_w),  %si		/* HashDataLen */
+#endif	
+
+#if 0 /* for DEBUG. Skip LogEvent */
+	test	%eax, %eax
+	jnz	tcg_goback
+#endif /* 0*/
+
+	
+/*
+ * BIOS call "INT 1Ah, (AH)=BBh,(AL)=04h" TCG_LogEvent
+ *	Call with	%ah = 0xBB
+ *			%al = 0x04
+ *			%es:%di = segment:offset of input parametor block
+ *			%ds:%si = segment:offset of output parametor block
+ *			%ebx = 'TCPA'
+ *			%ecx = 0
+ *			%edx = 0
+ *	Return:
+ *			%eax = TCG_STATUS
+ *			%ds:%si = na
+ *
+ * Ref:	 TCG PC Specification v1.0, Section 8.1.7 (page 47)
+ */	
+        movw    $0xbb04, %ax   		/* TCG_LogEvent */
+        movw    $ABS(le_ipb), %di	/* di=IPB */
+	movw	$0x7FF0, %si		/* si=OPB = 0x7FF0 */
+	movw	$ABS(ha_ipb), %si		/* use ha_ipb (TBD) */
+        int     $0x1a
+	test	%eax, %eax
+
+tcg_goback:
+        pop     %es
+        pop     %ds
+        popal
+        ret
+
+//hlee_opb:
+//        .word   0                       /* OPB size     */
+//        .word   0                       /* reserved     */
+//        .long   0                       /* event number */
+//        .space  20                      /* hash result  */
+
+/* HashAll Input Parameter Block (16-bytes) p49 */
+ha_ipb:
+        .word   (ha_ipb_end - ha_ipb)	/* block size   */
+        .word   0                       /* reserved     */
+        .long   0                       /* data pointer */
+        .long   0x200                   /* data size =512 (def)   */
+        .long   4                       /* Algorithm id = TCG_ALG_SHA = 4 */
+ha_ipb_end:
+
+/* LogEvent Input Parameter Block (28-bytes) p47 */
+le_ipb:    	                        
+        .word   (le_ipb_end - le_ipb) 	/* block size   */
+        .word   0                       /* reserved     */
+        .long   0                       /* data pointer */
+        .long   0                       /* data size    */
+        .long   TCG_GRUB_PCR_INDEX          /* PCR index    */
+	.long	1			/* event type	*/
+        .long   ABS(tcg_pcr_event)     /* log pointer  */
+        .long   32                      /* log size     */
+le_ipb_end:
+
+
+/* TCG_PCR_EVENT data structure 32-bytes */
+tcg_pcr_event:                         
+        .long   TCG_GRUB_PCR_INDEX          /* PCR index    */
+tcg_pcr_event_type:                    
+        .long   1                       /* event type   */
+/* HashAll Output Parameter Block (20-bytes) p49 */
+tpe_pcrvalue:
+        .space  20                      /* PCR value    */
+        .long   0                       /* event size   */
+tcg_sig:
+        .string "TCPA" /* */
+tcg_memo:
+        .long 0
+tcg_memo_w:
+        .word 0
+
+gdtdesc:
+        .word   (gdt_end - gdt - 1)     /* limit */
+        .long   ABS(gdt)                /* addr */
+
+        .p2align        2       /* force 4-byte alignment */
+gdt:
+        .word   0, 0
+        .byte   0, 0, 0, 0
+
+        /* 32 bit data segment */
+        .word   0xFFFF, 0
+        .byte   0, 0x92, 0xCF, 0
+gdt_end:
+	
+#endif /* TCG_TRUSTED_BOOT */
+
 /*
  * message: write the string pointed to by %si
  *
--- grub-0.97/stage2/asm.S.orig	2004-06-20 01:55:22.000000000 +0900
+++ grub-0.97/stage2/asm.S	2005-05-26 16:06:48.547867208 +0900
@@ -2283,6 +2283,635 @@ ENTRY(currticks)
 
 #endif /* STAGE1_5 */
 
+#ifdef TCG_TRUSTED_BOOT
+
+#define TCG_DIGEST_SIZE     20
+#define TCG_PCR_VALUE_SIZE  20
+
+        .code16
+        .align  4
+tcg_signature:
+        .byte   'T', 'C', 'P', 'A'
+        
+        /* TCG_PassThroughToTPM Input Parameter Block */
+tcg_passthru_ipb:
+passthru_ipb_length:
+        .word   0               /* IPBLength */
+        .word   0               /* Reserved */
+passthru_Ipb_opb_length:        /* OPBLength */
+        .word   tcg_passthru_opb_end - tcg_passthru_opb
+        .word   0               /* Reserved */
+tpm_operand_in_buff:
+        .space  34              /* TPMOperandIn */
+tpm_operand_in_buff_end:
+
+
+        /* TCG_PassThroughToTPM Output Parameter Block */
+tcg_passthru_opb:
+passthru_opb_length:            /* OPBLength */
+        .word   tcg_passthru_opb_end - tcg_passthru_opb
+        .word   0               /* Reserved */
+tpm_operand_out_buff:
+        .space  2               /* tag */
+        .space  4               /* paramSize */
+tpm_operand_out_return_code:
+        .space  4               /* returnCode */
+        .space  20              /* Buffer for output values */
+tpm_operand_out_buff_end:
+tcg_passthru_opb_end:
+
+        /* TPM_Extend Input (Note: TPM Operands are Network-Byte-Order */
+tpm_extend_in:
+        .byte   0,0xC1          /* tag = TPM_TAG_RQU_COMMAND */
+        .byte   0,0,0,tpm_extend_in_end - tpm_extend_in
+                                /* paramSize */
+        .byte   0,0,0,20        /* ordinal = TPM_ORD_Extend  */
+        .byte   0,0,0           /* pcrNum (Bit 31-8) */
+tpm_extend_pcr_num:
+        .byte   0               /* pcrNum (Bit 7-0) */
+tpm_extend_digest:
+        .space  TCG_DIGEST_SIZE
+tpm_extend_in_end:
+
+
+
+        /* TPM_Extend Output parameter offsets */
+tpm_extend_pcr_value = 10       
+
+
+        /* TPM_PcrRead Input (Note: TPM Operands are Network-Byte-Order */
+tpm_pcrread_in:
+        .byte   0,0xC1          /* tag = TPM_TAG_RQU_COMMAND */
+        .byte   0,0,0,tpm_pcrread_in_end - tpm_pcrread_in
+                                /* paramSize */
+        .byte   0,0,0,21        /* ordinal = TPM_ORD_PcrRead  */
+        .byte   0,0,0           /* pcrNum (Bit 31-8) */
+tpm_pcrread_pcrindex:
+        .byte   0               /* pcrNum (Bit 7-0) */
+tpm_pcrread_in_end:
+
+
+        /* TPM_PcrRead Output parameter offsets */
+tpm_pcrread_pcr_value = 10
+
+
+        /* TCG_LogEvent Input Parameter Block */
+logevent_ipb:
+        .word   logevent_ipb_end - logevent_ipb         /* IPBLength */
+        .word   0                                       /* Reserved */
+        .long   0                                       /* HashDataPtr */
+        .long   0                                       /* HashDataLen */
+logevent_pcr_index:
+        .long   0                                       /* PCRIndex */
+        .long   1                       /* LogEventType = EV_CODE_NOCERT */
+        .long   ABS(tcg_pcr_event)                     /* LogDataPtr */
+        .long   tcg_pcr_event_end - tcg_pcr_event     /* LogDataLen */
+logevent_ipb_end:
+
+tcg_pcr_event:
+tpe_pcr_index:
+        .long   0                               /* PCRIndex */
+        .long   1                       /* eventType = EV_CODE_NOCERT */
+tpe_pcr_value:
+        .space  TCG_PCR_VALUE_SIZE          /* PCRValue */
+        .long   0                       /* eventSize */
+tpe_event:                              /* event = null */      
+tpe_event_end:
+tcg_pcr_event_end:
+
+        /* TCG_LogEvent Outnput Parameter Block */
+logevent_opb:
+        .word   logevent_opb_end - logevent_opb /* OPBLength */
+        .word   0                               /* Reserved */
+        .long   0                               /* EventNumber */
+        .space  TCG_PCR_VALUE_SIZE                  /* Reserved */
+logevent_opb_end:
+
+
+        /* TCG_HashAll Input Parameter Block */
+hashall_ipb:
+        .word   hashall_ipb_end - hashall_ipb         /* IPBLength */
+        .word   0                                     /* Reserved */
+hashall_data_ptr:
+        .long   0                                     /* HashDataPtr */
+hashall_data_len:
+        .long   0                                     /* HashDataLen */
+        .long   4                                     /* AlgorithmID TPM_ALG_SHA 0x00000004 */
+hashall_ipb_end:
+
+        /* TCG_HashAll Outnput Parameter Block */
+hashall_opb:
+        .space  TCG_DIGEST_SIZE               /* Hash size = PCR size */
+hashall_opb_end:
+
+/* 2004-10-14 SM  TODO remove */
+/* #define TCG_DEBUG */
+	
+#ifdef TCG_DEBUG
+        /* DEBUG: Display debug message */
+debugmsg:
+        push    %ax
+        push    %bx
+        cld
+debugmsg_loop:
+        lodsb
+        cmpb    $0, %al
+        je      debugmsg_ret
+        movw    $0x0001, %bx
+        movb    $0xe, %ah
+        int     $0x10   /* Display a byte */
+        jmp     debugmsg_loop
+debugmsg_ret:
+        pop     %bx
+        pop     %ax
+        ret
+
+#define MSG(x)  push %si; movw $ABS(x), %si; call debugmsg; pop %si
+
+status_check_msg:       .string "DEBUG: TCG_StatusCheck "
+tcg_passthru_msg:       .string "DEBUG: TCG_PassThru "
+logevent_msg:           .string "DEBUG: TCG_LogEvent "
+hashall_msg:            .string "DEBUG: TCG_HashAll 100142245 "
+ok_msg:                 .string "ok\r\n"
+ng_msg:                 .string "ng\r\n"
+        /* DEBUG: End of debug messages */
+#else  /* TCG_DEBUG */
+#define MSG(x)
+#endif /* TCG_DEBUG */
+
+        .code32
+
+/*
+ * int tcg_status_check ( unsigned char **event_log );
+ * Check TCG status.
+ * This returns 0 if the BIOS has TCG function.
+ * If system does not have TCG BIOS, TCG_PC_UNSUPPORTED(0x0003) is
+ * returned.
+ */
+ENTRY(tcg_status_check)
+        push    %ebx
+        push    %ecx
+        push    %edx
+        push    %esi
+        push    %edi
+        push    %ebp
+
+#ifdef TCG_BIOS_BIGREALMODE_FIX 
+        call    EXT_C(prot_to_big_real)
+#else	
+        call    EXT_C(prot_to_real)
+#endif /* TCG_BIOS_BIGREALMODE_FIX */
+        .code16
+
+        MSG(status_check_msg)
+
+        /*  TCG_StatusCheck */
+        movw    $0xBB00, %ax
+        int     $0x1A
+        and     %eax, %eax
+        jnz     tcg_bios_ng
+        cmpl    %ebx, ABS(tcg_signature)
+        je      tcg_bios_ok
+tcg_bios_ng:
+        MSG(ng_msg)
+        movw    $0x0003, %ax
+        jmp     go_back1
+tcg_bios_ok:
+        MSG(ok_msg)
+go_back1:
+        movw    %ax, %bx
+        DATA32  call    EXT_C(real_to_prot)
+        .code32
+
+        movzwl  %bx, %eax
+        test    %eax, %eax
+        jnz     skip_copy_event_log
+
+        movl    0x1C(%esp), %edi         /* *event_log */
+        test    %edi, %edi
+        jz      skip_copy_event_log
+
+        movl    %esi, (%edi)
+
+skip_copy_event_log:
+        pop     %ebp
+        pop     %edi
+        pop     %esi
+        pop     %edx
+        pop     %ecx
+        pop     %ebx
+        ret
+
+/*
+ * TCG PassthroughToTPM
+ *      Call with   (%esi) = TPM OperandIn
+ *
+ *      Return with %eex = Return code
+ *                  (%esi) = TPM OperandOut (= $tpm_operand_out_buff )
+ *
+ *      Modified registers: ebx, ecx, edx, edi
+ *
+ * BIOS Call "Int 1AH Function" to send a TPM operation.
+ *      Call with       %ax = 0xBB02h (TCG_PassThroughToTPM)
+ *                      %es = Segment of the TPM input parameter block
+ *                      %di = Offset of the TPM input parameter block
+ *                      %ds = Segment of the TPM output parameter block
+ *                      %si = Offset of the TPM output parameter block
+ *                      %ebx = "TCG" (0x41504354)
+ *                      %ecx = 0
+ *                      %edx = 0
+ */
+tcg_passthru_to_tpm:
+        movl    $ABS(tpm_operand_in_buff), %edi
+        movl    2(%esi), %ecx           /* Load operandIn paramSize */
+        bswap   %ecx                    /* ecx = operandIn size */
+        movl    $(tpm_operand_in_buff - tcg_passthru_ipb), %eax
+        addl    %ecx, %eax              /* eax = IPB size */
+        movl    %eax, ABS(passthru_ipb_length)
+
+        cld
+        rep
+        movsb                           /* Copy operandIn to IPB */
+
+#ifdef TCG_BIOS_BIGREALMODE_FIX 
+        call    EXT_C(prot_to_big_real)
+#else	
+        call    EXT_C(prot_to_real)
+#endif /* TCG_BIOS_BIGREALMODE_FIX */
+        .code16
+
+        MSG(tcg_passthru_msg)
+        movw    $0xBB02, %ax
+        movw    $ABS(tcg_passthru_ipb), %di
+        movw    $ABS(tcg_passthru_opb), %si
+        movl    ABS(tcg_signature), %ebx
+        xorl    %ecx, %ecx
+        movl    %ecx, %edx
+        int     $0x1A
+        and     %eax, %eax
+        jnz     tcg_passthru_ng
+        cmpl    %eax, ABS(tpm_operand_out_return_code)
+        je      tcg_passthru_ok
+        movl    $0x0004, %eax
+
+tcg_passthru_ng:
+        MSG(ng_msg)
+        jmp     tcg_passthru_return
+
+tcg_passthru_ok:
+        MSG(ok_msg)
+
+tcg_passthru_return:
+        movl    %eax, %ebx
+        DATA32  call    EXT_C(real_to_prot)
+        .code32
+
+        movl    $ABS(tpm_operand_out_buff), %esi
+        movl    %ebx, %eax
+        ret
+
+/*
+ * int tcg_extend (  int pcr_index,                     *IN*
+ *                   unsigned char *digest,             *IN*
+ *                   unsigned char *pcr_value );        *OUT*
+ * Send TPM_Extend.
+ * This returns 0 if successful. As defined by TCG PC Specification 1.00
+ * (8.1.2 Return Codes, Page 40)
+ */
+
+ENTRY(tcg_extend)
+        push    %ebp
+        movl    %esp, %ebp
+        push    %ebx
+        push    %ecx
+        push    %edx
+        push    %esi
+        push    %edi
+
+        movl    0x8(%ebp), %eax         /* pcr_index */
+        movb    %al, ABS(tpm_extend_pcr_num)
+
+        movl    0xC(%ebp), %esi         /* *digest */
+        movl    $ABS(tpm_extend_digest), %edi
+        movl    $TCG_DIGEST_SIZE, %ecx
+        cld
+        rep
+        movsb
+
+        movl    $ABS(tpm_extend_in), %esi
+        call    EXT_C(tcg_passthru_to_tpm)
+        test    %eax, %eax
+        jnz     tcg_extend_go_back
+
+        /* Return PCR value */
+        addl    $(tpm_extend_pcr_value), %esi
+        movl    0x24(%esp), %edi         /* *pcr_value */
+        movl    $(TCG_PCR_VALUE_SIZE), %ecx
+        cld
+        rep
+        movsb
+
+tcg_extend_go_back:
+        pop     %edi
+        pop     %esi
+        pop     %edx
+        pop     %ecx
+        pop     %ebx
+        pop     %ebp
+        ret
+
+/*
+ * int tcg_log_extend ( int pcr_index,                 *IN
+ *                       unsigned char *digest );       *IN
+ * Log PCR event and extend.
+ * This returns 0 if successful. As defined by TCG PC Specification 1.00
+ * (8.1.2 Return Codes, Page 40)
+ * BIOS Call "Int 1AH Function" to log TCG_PCR_EVENT
+ *      Call with       %ax = 0xBB04h (TCG_LogEvent)
+ *                      %es = Segment of the TPM input parameter block
+ *                      %di = Offset of the TPM input parameter block
+ *                      %ds = Segment of the TPM output parameter block
+ *                      %si = Offset of the TPM output parameter block
+ *                      %ebx = "TCPA" (0x41504354)
+ *                      %ecx = 0
+ *                      %edx = 0
+ */
+ENTRY(tcg_log_extend)
+        push    %ebp
+        movl    %esp, %ebp
+        push    %ebx
+        push    %ecx
+        push    %edx
+        push    %esi
+        push    %edi
+
+        movl    0x8(%ebp), %eax         /* pcr_index */
+        movl    %eax, ABS(logevent_pcr_index)
+        movl    %eax, ABS(tpe_pcr_index)
+
+        /* Note: TCG BIOS expects PCRValue field in TCG_PCR_EVENT structure
+         *       to have the digest for TPM_Extend operation, 
+         *       not PCR value, despite its name.
+         */
+        movl    0xC(%ebp), %esi         /* *digest */
+        movl    $ABS(tpe_pcr_value), %edi
+        movl    $TCG_DIGEST_SIZE, %ecx
+        cld
+        rep
+        movsb
+
+#ifdef TCG_BIOS_BIGREALMODE_FIX 
+        call    EXT_C(prot_to_big_real)
+#else	
+        call    EXT_C(prot_to_real)
+#endif /* TCG_BIOS_BIGREALMODE_FIX */
+        .code16
+
+        /* TCG_LogEvent */
+        MSG(logevent_msg)
+
+        movw    $0xBB04, %ax
+        movw    $ABS(logevent_ipb), %di
+        movw    $ABS(logevent_opb), %si
+        movl    ABS(tcg_signature), %ebx
+        xorl    %ecx, %ecx
+        movl    %ecx, %edx
+        int     $0x1A
+        and     %eax, %eax
+        jz      logevent_ok
+        MSG(ng_msg)
+        jmp     logevent_go_back
+
+logevent_ok:
+        MSG(ok_msg)
+
+logevent_go_back:
+        movl    %eax, %ebx
+        DATA32  call    EXT_C(real_to_prot)
+        .code32
+
+        movl    %ebx, %eax
+        pop     %edi
+        pop     %esi
+        pop     %edx
+        pop     %ecx
+        pop     %ebx
+        pop     %ebp
+        ret
+
+
+	
+/*
+ * int tcg_pcr_read (  int pcr_index,                   *IN*
+ *                     unsigned char *pcr_value );      *OUT*
+ * Send TPM_PcrRead.
+ * This returns 0 if successful. As defined by TCG PC Specification 1.00
+ * (8.1.2 Return Codes, Page 40)
+ */
+
+ENTRY(tcg_pcr_read)
+        push    %ebp
+        movl    %esp, %ebp
+        push    %ebx
+        push    %ecx
+        push    %edx
+        push    %esi
+        push    %edi
+
+        movl    0x1C(%esp), %eax                /* pcr_index */
+        movb    %al, ABS(tpm_pcrread_pcrindex)
+
+        movl    $ABS(tpm_pcrread_in), %esi
+        call    EXT_C(tcg_passthru_to_tpm)
+        test    %eax, %eax
+        jnz     tcg_pcr_read_go_back
+
+        /* Return PCR value */
+        addl    $(tpm_pcrread_pcr_value), %esi
+        movl    0x20(%esp), %edi         /* *pcr_value */
+        movl    $(TCG_PCR_VALUE_SIZE), %ecx
+        cld
+        rep
+        movsb
+
+tcg_pcr_read_go_back:
+        pop     %edi
+        pop     %esi
+        pop     %edx
+        pop     %ecx
+        pop     %ebx
+        pop     %ebp
+        ret
+
+/*
+ * int tcg_hash_all ( int len,                 *IN
+ *	              unsigned char *data,     *IN
+ *                    unsigned char *digest ); *OUT
+ * Hash the data
+ * This returns 0 if successful. As defined by TCG PC Specification 1.1
+ * (8.1.9 Return Codes, Page 50)
+ * BIOS Call "Int 1AH Function" to Hash the Data
+ *      Call with       %ax = 0xBB05h (TCG_HashAll)
+ *                      %es = Segment of the TPM input parameter block
+ *                      %di = Offset of the TPM input parameter block
+ *                      %ds = Segment of the TPM output parameter block
+ *                      %si = Offset of the TPM output parameter block
+ *                      %ebx = "TCPA" (0x41504354)
+ *                      %ecx = 0
+ *                      %edx = 0
+ *
+ * 2004-10-15 S. Munetoh added
+ *
+ */
+ENTRY(tcg_hash_all)
+        push    %ebp
+        /* movl    %esp, %ebp */
+        push    %ebx
+        push    %ecx
+        push    %edx
+        push    %esi
+        push    %edi
+
+	/* len */
+        /* movl    0x8(%ebp), %eax */         
+        movl    0x1c(%esp), %eax         /* len */
+        movl    %eax, ABS(hashall_data_len)
+
+	/* *data */
+        /* movl    0xC(%ebp), %esi  */       
+        movl    0x20(%esp), %esi         
+        movl    %esi, ABS(hashall_data_ptr)
+	
+
+#ifdef TCG_BIOS_BIGREALMODE_FIX 
+        call    EXT_C(prot_to_big_real)
+#else	
+        call    EXT_C(prot_to_real)
+#endif /* TCG_BIOS_BIGREALMODE_FIX */
+        .code16
+
+        /* TCG_HashAll */
+        MSG(hashall_msg)
+
+        movw    $0xBB05, %ax
+        movw    $ABS(hashall_ipb), %di
+        movw    $ABS(hashall_opb), %si
+        movl    ABS(tcg_signature), %ebx
+        xorl    %ecx, %ecx
+        movl    %ecx, %edx
+        int     $0x1A
+        and     %eax, %eax
+        jz      hashall_ok
+        MSG(ng_msg)
+        jmp     hashall_go_back
+
+hashall_ok:
+        MSG(ok_msg)
+
+hashall_go_back:
+        movl    %eax, %ebx
+        DATA32  call    EXT_C(real_to_prot)
+        .code32
+	
+        /* Return Digest value, whether call is ok or not, this will copy the digest */
+        movl    $ABS(hashall_opb), %esi
+        /* movl    0x10(%ebp), %edi */       
+        movl    0x24(%esp), %edi       
+        movl    $TCG_DIGEST_SIZE, %ecx 
+        cld
+        rep
+        movsb
+
+        /* DEBUG movl    $TCG_DIGEST_SIZE, 0x10(%ebp) */
+
+	
+        movl    %ebx, %eax
+        pop     %edi
+        pop     %esi
+        pop     %edx
+        pop     %ecx
+        pop     %ebx
+        pop     %ebp
+        ret
+
+
+	
+#ifdef TCG_BIOS_BIGREALMODE_FIX
+/*
+ *  "prot_to_big_real" enters into "Big Real Mode" which differs
+ *  from real mode in that "Big Real Mode" has no segment limit of 64KB.
+ *  Int 1AH for TCG functions assumes the "Big Real Mode".
+ *
+ *  NOTE:  Use of this function messes up %eax and %ebp.
+ */
+
+ENTRY(prot_to_big_real)
+        /* just in case, set GDT */
+        lgdt    gdtdesc
+
+        /* save the protected mode stack */
+        movl    %esp, %eax
+        movl    %eax, protstack
+
+        /* get the return address */
+        movl    (%esp), %eax
+        movl    %eax, STACKOFF
+
+        /* set up new stack */
+        movl    $STACKOFF, %eax
+        movl    %eax, %esp
+        movl    %eax, %ebp
+
+        /* set up segment limits */
+        movw    $PROT_MODE_DSEG, %ax
+        movw    %ax, %ds
+        movw    %ax, %es
+        movw    %ax, %fs
+        movw    %ax, %gs
+        movw    %ax, %ss
+
+        /* this might be an extra step */
+        ljmp    $PSEUDO_RM_CSEG, $tmpcsegb      /* jump to a 16 bit segment */
+
+tmpcsegb:
+        .code16
+
+        /* clear the PE bit of CR0 */
+        movl    %cr0, %eax
+        andl    $CR0_PE_OFF, %eax
+        movl    %eax, %cr0
+
+        /* flush prefetch queue, reload %cs */
+        DATA32  ljmp    $0, $realcsegb
+
+realcsegb:
+        /* we are in real mode now
+         * set up the real mode segment registers : DS, SS, ES
+         */
+        /* zero %eax */
+        xorl    %eax, %eax
+
+        movw    %ax, %ds
+        movw    %ax, %es
+        movw    %ax, %fs
+        movw    %ax, %gs
+        movw    %ax, %ss
+
+        /* Enable A20 gate for the case it's disabled */
+        movw    $0x2401, %ax
+        int     $0x15
+
+        /* restore interrupts */
+        sti
+
+        /* return on new stack! */
+        DATA32  ret
+
+        .code32
+#endif /* TCG_BIOS_BIGREALMODE_FIX */
+
+#endif /* TCG_TRUSTED_BOOT */
+	
 /*
  *  This is the area for all of the special variables.
  */
--- grub-0.97/stage2/stage1_5.c.orig	2003-07-09 20:45:53.000000000 +0900
+++ grub-0.97/stage2/stage1_5.c	2005-05-26 16:06:48.548867056 +0900
@@ -30,7 +30,11 @@ disk_read_savesect_func (int sector, int
 void
 cmain (void)
 {
+#ifdef TCG_TRUSTED_BOOT
+  grub_printf ("\n\nTCG-GRUB Stage2 loading, please wait...\n");
+#else
   grub_printf ("\n\nGRUB loading, please wait...\n");
+#endif /* TCG*/
 
   /*
    *  Here load the true second-stage boot-loader.
@@ -55,8 +59,35 @@ cmain (void)
       
       grub_close ();
 
+#ifdef TCG_TRUSTED_BOOT
+      if (ret) {
+          /* If stage2 was loaded and TCG BIOS presents */
+          if (!tcg_status_check( NULL )) 
+            {
+              unsigned char sha1_hash[SHA1_DIGEST_SIZE];
+              int retcode,i;
+
+              /* Get SHA-1 hash of stage2 */
+              retcode = tcg_hash_all( SECTOR_SIZE * 2 + ret,
+				      (char*)0x8000,
+				      sha1_hash);
+              grub_printf("TCG-GRUB Measureing stage2. - (TCG_HashAll) ");
+              grub_printf(" start=%u len=%u Hash=\n ",0x8000,SECTOR_SIZE * 2 + ret);
+              for (i=0;i<20;i++) printf("%u,",sha1_hash[i]);
+              grub_printf("\n");
+
+              /* Perform TSS_LogEvent and TPM_Extend */
+              retcode = tcg_log_extend(TCG_GRUB_PCR_INDEX, sha1_hash);
+              grub_printf("TCG-GRUB PCR%u was Extended\n",TCG_GRUB_PCR_INDEX);
+
+            }
+	chain_stage2 (0, 0x8200, saved_sector);
+      }
+#else
       if (ret)
 	chain_stage2 (0, 0x8200, saved_sector);
+#endif
+
     }
 
   /*
--- grub-0.97/stage2/stage2.c.orig	2005-03-20 02:51:57.000000000 +0900
+++ grub-0.97/stage2/stage2.c	2005-05-26 16:06:48.550866752 +0900
@@ -912,6 +912,16 @@ cmain (void)
 	      is_opened = is_preset = open_preset_menu ();
 	      if (! is_opened)
 		{
+#ifdef TCG_TRUSTED_BOOT
+                  measure_file(config_file, TCG_GRUB_CONF_PCR_INDEX, 1);
+#ifdef TCG_TRUSTED_BOOT_STEPBYSTEP
+                  /* Pause for confirmation of the stage1/1.5 messages */
+                  printf("TCG-GRUB grub.conf was measured and PCR%u was extended\n",
+                         TCG_GRUB_CONF_PCR_INDEX);
+                  printf("TCG-GRUB Press any key to enter the GRUB Stage2\n"); 
+                  getkey ();
+#endif
+#endif
 		  is_opened = grub_open (config_file);
 		  errnum = ERR_NONE;
 		}
--- grub-0.97/stage2/boot.c.orig	2004-03-30 20:44:08.000000000 +0900
+++ grub-0.97/stage2/boot.c	2005-05-26 16:06:48.552866448 +0900
@@ -776,6 +776,33 @@ load_module (char *module, char *arg)
       return 0;
     }
 
+
+#ifdef  TCG_TRUSTED_BOOT
+  if  (tcg_grub_pcr_index >= 0) {
+    /* measure */
+    {
+      unsigned char sha1_hash[20];
+      int rc=0;
+      rc=tcg_hash_all( len,
+		       cur_addr, 
+		       sha1_hash);
+      rc = tcg_log_extend(tcg_grub_pcr_index, sha1_hash);
+    }
+
+#ifdef TCG_TRUSTED_BOOT_STEPBYSTEP
+    /* Pause for confirmation of the stage1/1.5 messages */
+    printf("TCG-GRUB: module %s (0x%x,%d) was measured and PCR%u was extended\n",
+	    module, cur_addr,len,tcg_grub_pcr_index);
+    printf("TCG-GRUB: Press any key to go nest step....\n");
+    getkey ();
+#endif
+
+    tcg_grub_pcr_index = -1;
+
+  }
+#endif
+
+
   printf ("   [Multiboot-module @ 0x%x, 0x%x bytes]\n", cur_addr, len);
 
   /* these two simply need to be set if any modules are loaded at all */
@@ -844,6 +871,32 @@ load_initrd (char *initrd)
 
   grub_close ();
 
+#ifdef  TCG_TRUSTED_BOOT
+  if  (tcg_grub_pcr_index >= 0) {
+    /* measure */ 
+    {
+      unsigned char sha1_hash[20];
+      int rc=0;
+      rc=tcg_hash_all( lh->ramdisk_size,
+		       lh->ramdisk_image,
+		       sha1_hash);
+      rc = tcg_log_extend(tcg_grub_pcr_index, sha1_hash);
+    }
+
+#ifdef TCG_TRUSTED_BOOT_STEPBYSTEP
+    /* Pause for confirmation of the stage1/1.5 messages */
+    printf("TCG-GRUB: initrd %s (0x%x,%d) was measured and PCR%u was extended\n",
+	   initrd, lh->ramdisk_image, lh->ramdisk_size,
+	   tcg_grub_pcr_index);
+    printf("TCG-GRUB: Press any key to go nest step....\n");
+    getkey ();
+#endif
+
+    tcg_grub_pcr_index = -1;
+
+  }
+#endif
+
  fail:
   
 #ifndef NO_DECOMPRESSION
--- grub-0.97/stage2/builtins.c.orig	2005-02-16 06:58:23.000000000 +0900
+++ grub-0.97/stage2/builtins.c	2005-05-26 16:06:48.564864624 +0900
@@ -49,6 +49,11 @@
 # include <md5.h>
 #endif
 
+#ifdef TCG_TRUSTED_BOOT
+int   tcg_grub_pcr_index = -1;
+char *tcg_grub_log; /**/
+#endif /* TCG_TRUSTED_BOOT */
+
 /* The type of kernel loaded.  */
 kernel_t kernel_type;
 /* The boot device.  */
@@ -404,6 +409,9 @@ chainloader_func (char *arg, int flags)
 {
   int force = 0;
   char *file = arg;
+#ifdef TCG_TRUSTED_BOOT
+  int pcr_index = TCG_FILE_PCR_INDEX;
+#endif
 
   /* If the option `--force' is specified?  */
   if (substring ("--force", arg) <= 0)
@@ -412,6 +420,18 @@ chainloader_func (char *arg, int flags)
       file = skip_to (0, arg);
     }
 
+#ifdef TCG_TRUSTED_BOOT
+  if (substring ("--pcr=", file) <= 0)
+    {
+      arg = file + 6;
+      if (! safe_parse_maxint(&arg, &pcr_index))
+        return 1;
+      file = skip_to(0, arg);
+    }
+
+  measure_file(file, pcr_index, 1);
+#endif
+
   /* Open the file.  */
   if (! grub_open (file))
     {
@@ -465,9 +485,16 @@ static struct builtin builtin_chainloade
   "chainloader",
   chainloader_func,
   BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+#ifdef TCG_TRUSTED_BOOT
+  "chainloader [--force] [--pcr=PCRINDEX] FILE",
+  "Load the chain-loader FILE. If --force is specified, then load it"
+  " forcibly, whether the boot loader signature is present or not."
+  " The option --pcr specifies PCR index for measuring the FILE."
+#else
   "chainloader [--force] FILE",
   "Load the chain-loader FILE. If --force is specified, then load it"
   " forcibly, whether the boot loader signature is present or not."
+#endif
 };
 
 
@@ -1712,6 +1739,21 @@ static struct builtin builtin_impsprobe 
 static int
 initrd_func (char *arg, int flags)
 {
+#ifdef TCG_TRUSTED_BOOT
+  int pcr_index = TCG_FILE_PCR_INDEX;
+
+  if (substring ("--pcr=", arg) <= 0)
+    {
+      arg += 6;
+      if (! safe_parse_maxint(&arg, &pcr_index))
+        return 1;
+      arg = skip_to(0, arg);
+    }
+
+  tcg_grub_pcr_index = pcr_index;
+
+#endif
+
   switch (kernel_type)
     {
     case KERNEL_TYPE_LINUX:
@@ -1733,9 +1775,16 @@ static struct builtin builtin_initrd =
   "initrd",
   initrd_func,
   BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+#ifdef TCG_TRUSTED_BOOT
+  "initrd [--pcr=PCRINDEX] FILE [ARG ...]",
+  "Load an initial ramdisk FILE for a Linux format boot image and set the"
+  " appropriate parameters in the Linux setup area in memory."
+  " The option --pcr specifies PCR index for measuring the FILE."
+#else
   "initrd FILE [ARG ...]",
   "Load an initial ramdisk FILE for a Linux format boot image and set the"
   " appropriate parameters in the Linux setup area in memory."
+#endif
 };
 
 
@@ -2331,6 +2380,9 @@ kernel_func (char *arg, int flags)
   int len;
   kernel_t suggested_type = KERNEL_TYPE_NONE;
   unsigned long load_flags = 0;
+#ifdef TCG_TRUSTED_BOOT
+  int pcr_index = TCG_FILE_PCR_INDEX;
+#endif
 
 #ifndef AUTO_LINUX_MEM_OPT
   load_flags |= KERNEL_LOAD_NO_MEM_OPTION;
@@ -2370,6 +2422,14 @@ kernel_func (char *arg, int flags)
 	 has no effect.  */
       else if (grub_memcmp (arg, "--no-mem-option", 15) == 0)
 	load_flags |= KERNEL_LOAD_NO_MEM_OPTION;
+#ifdef TCG_TRUSTED_BOOT
+      else if (grub_memcmp (arg, "--pcr=", 6) == 0)
+        {
+          arg += 6;
+          if (! safe_parse_maxint(&arg, &pcr_index))
+            return 1;
+        }
+#endif
       else
 	break;
 
@@ -2387,6 +2447,10 @@ kernel_func (char *arg, int flags)
       return 1;
     }
 
+#ifdef TCG_TRUSTED_BOOT
+  measure_file(arg, pcr_index, 1);
+#endif
+
   /* Copy the command-line to MB_CMDLINE.  */
   grub_memmove (mb_cmdline, arg, len + 1);
   kernel_type = load_image (arg, mb_cmdline, suggested_type, load_flags);
@@ -2402,6 +2466,17 @@ static struct builtin builtin_kernel =
   "kernel",
   kernel_func,
   BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+#ifdef TCG_TRUSTED_BOOT
+  "kernel [--no-mem-option] [--type=TYPE] [--pcr=PCRINDEX] FILE [ARG ...]",
+  "Attempt to load the primary boot image from FILE. The rest of the"
+  " line is passed verbatim as the \"kernel command line\".  Any modules"
+  " must be reloaded after using this command. The option --type is used"
+  " to suggest what type of kernel to be loaded. TYPE must be either of"
+  " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and"
+  " \"multiboot\". The option --no-mem-option tells GRUB not to pass a"
+  " Linux's mem option automatically."
+  " The option --pcr specifies PCR index for measuring the FILE."
+#else
   "kernel [--no-mem-option] [--type=TYPE] FILE [ARG ...]",
   "Attempt to load the primary boot image from FILE. The rest of the"
   " line is passed verbatim as the \"kernel command line\".  Any modules"
@@ -2410,6 +2485,7 @@ static struct builtin builtin_kernel =
   " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and"
   " \"multiboot\". The option --no-mem-option tells GRUB not to pass a"
   " Linux's mem option automatically."
+#endif
 };
 
 
@@ -2585,6 +2661,19 @@ static int
 module_func (char *arg, int flags)
 {
   int len = grub_strlen (arg);
+#ifdef TCG_TRUSTED_BOOT
+  int pcr_index = TCG_FILE_PCR_INDEX;
+
+  if (substring ("--pcr=", arg) <= 0)
+    {
+      arg += 6;
+      if (! safe_parse_maxint(&arg, &pcr_index))
+        return 1;
+      arg = skip_to(0, arg);
+    }
+
+  tcg_grub_pcr_index =  pcr_index;
+#endif
 
   switch (kernel_type)
     {
@@ -2619,12 +2708,22 @@ static struct builtin builtin_module =
   "module",
   module_func,
   BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+#ifdef TCG_TRUSTED_BOOT
+  "module [--pcr=PCRINDEX] FILE [ARG ...]",
+  "Load a boot module FILE for a Multiboot format boot image (no"
+  " interpretation of the file contents is made, so users of this"
+  " command must know what the kernel in question expects). The"
+  " rest of the line is passed as the \"module command line\", like"
+  " the `kernel' command."
+  " The option --pcr specifies PCR index for measuring the FILE."
+#else
   "module FILE [ARG ...]",
   "Load a boot module FILE for a Multiboot format boot image (no"
   " interpretation of the file contents is made, so users of this"
   " command must know what the kernel in question expects). The"
   " rest of the line is passed as the \"module command line\", like"
   " the `kernel' command."
+#endif
 };
 
 
@@ -2652,9 +2751,16 @@ static struct builtin builtin_modulenoun
   "modulenounzip",
   modulenounzip_func,
   BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+#ifdef TCG_TRUSTED_BOOT
+  "modulenounzip [--pcr=PCRINDEX] FILE [ARG ...]",
+  "The same as `module', except that automatic decompression is"
+  " disabled."
+  " The option --pcr specifies PCR index for measuring the FILE."
+#else
   "modulenounzip FILE [ARG ...]",
   "The same as `module', except that automatic decompression is"
   " disabled."
+#endif
 };
 
 
@@ -4790,6 +4896,240 @@ static struct builtin builtin_vbeprobe =
   "Probe VBE information. If the mode number MODE is specified, show only"
   " the information about only the mode."
 };
+
+
+#ifdef TCG_TRUSTED_BOOT
+
+/* print hash */
+static void
+println_hash(unsigned char *hash) {
+    int i;
+    for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
+        grub_printf("%d ", hash[i]);
+    }
+    grub_printf("\n");
+}
+
+static char *err_no_tcg = " TCG not available.\n";
+static char *err_tcg_rc = " TCG BIOS returned error=%x.\n";
+
+
+/* measure a file  */
+/* 2004-10-21 SM last update */
+int
+measure_file (char *filename, int pcr_index, int logevent)
+{
+    char *buffer; 
+    int bytes_read;
+    unsigned char sha1_hash[SHA1_DIGEST_SIZE];
+    unsigned char pcr_value[SHA1_DIGEST_SIZE];
+    int rc=0;
+
+    /* TCG status check */
+    if (tcg_status_check( NULL )) {
+        grub_printf (err_no_tcg);
+        return -1;
+    }
+
+    buffer = (char *) RAW_ADDR (0x100000); 
+
+    /* Read the file */
+    if (! grub_open (filename))
+        return errnum;    
+    bytes_read = grub_read(buffer, -1);
+    grub_close ();
+
+    if (bytes_read<0) {
+      return -1;
+    }
+
+    /* Hash the file */
+    tcg_hash_all( bytes_read,
+		  buffer,
+		  sha1_hash);
+    //println_hash( sha1_hash );
+
+
+    if (logevent) {
+        /* TSS_LogEvent and TPM_Extend */
+        rc = tcg_log_extend(pcr_index, sha1_hash);
+    } else {
+        /* TPM_Extend */
+        rc = tcg_extend(pcr_index, sha1_hash, pcr_value);
+    }
+    return (rc);
+}
+
+
+
+
+/* measure */
+static int
+measure_func (char *arg, int flags)
+{
+    int pcr_index;
+    char *pcr_arg = skip_to(0,arg);
+    char *nolog_arg = skip_to(0, pcr_arg);
+    int logevent = 1;
+    int rc=0;
+
+    if (! *pcr_arg
+     || ! safe_parse_maxint(&pcr_arg, &pcr_index)) {
+        errnum = ERR_BAD_ARGUMENT;
+        return 1;
+    }
+    if ( *nolog_arg
+     && grub_strcmp(nolog_arg, "nolog") == 0) {
+        logevent = 0;
+    }
+
+    rc = measure_file( arg, pcr_index, logevent );
+
+    return rc;
+}
+
+static struct builtin builtin_measure =
+{
+  "measure",
+  measure_func,
+  //BUILTIN_CMDLINE | BUILTIN_MENU,
+  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
+  "measure FILE PCRINDEX [nolog]",
+  "Perform TCG measurement operation with the FILE."
+};
+
+typedef struct {
+    unsigned int    PCRIndex;       
+    unsigned int    eventType;
+    unsigned char    PCRValue[SHA1_DIGEST_SIZE];
+    unsigned int    eventSize;
+    /* (eventSize) bytes of event data follows */
+} TCG_PCR_EVENT;
+
+typedef struct {
+    unsigned int    eventID;
+    unsigned int    eventDataSize;
+    /* (eventDataSize) bytes of event data follows */
+} PC_SPECIFIC_EVENT;
+
+/* tcg_log_func */
+static int
+tcglog_func (char *arg, int flags)
+{
+    unsigned char *log_addr;
+    unsigned char *log_addr_limit;
+    int i = 0;
+    int log_num = -1;
+
+    /* TCG status check */
+    if (tcg_status_check( &log_addr )) {
+        grub_printf (err_no_tcg);
+        return -1;
+    }
+    log_addr_limit = log_addr + 0x10000;
+
+    if (*arg) {
+        safe_parse_maxint(&arg, &log_num);
+    }
+
+    while (log_addr < log_addr_limit) {
+        TCG_PCR_EVENT *event = (TCG_PCR_EVENT*)log_addr;
+        if (event->eventType == 0 && event->eventSize == 0) break;
+        
+        if (log_num < 0 || i == log_num) {
+            grub_printf("[%d] PCR%d Type=%d ",
+                        i,
+                        event->PCRIndex,
+                        event->eventType);
+
+            switch(event->eventType) {
+            case 5: {
+                char buff[40];
+                char *src = (char *)(log_addr + sizeof(TCG_PCR_EVENT));
+                int size = event->eventSize;
+                if (size >= sizeof(buff)) size = sizeof(buff) - 1;
+                memcpy(buff, src, size);
+                buff[size] = 0;
+                grub_printf(buff);
+                }
+                break;
+            case 6: { /* Platform specific */
+                PC_SPECIFIC_EVENT *pc = (PC_SPECIFIC_EVENT*)(log_addr + sizeof(TCG_PCR_EVENT));
+                grub_printf("ID=%d size=%d", pc->eventID, pc->eventDataSize);
+                }
+                break;
+            default: 
+                grub_printf("Size=%d", event->eventSize);
+            }
+            grub_printf("\n");
+        
+            if (i == log_num) {
+                grub_printf("Hash = ");
+                println_hash( event->PCRValue );
+            }
+        }
+        log_addr += sizeof(TCG_PCR_EVENT) + event->eventSize;
+        i++;
+    }
+
+    return (0);
+}
+
+static struct builtin builtin_tcglog =
+{
+  "tcglog",
+  tcglog_func,
+  //BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
+  "tcglog [LOGNUM]",
+  "Display TCG event log entry at LOGNUM. If LOGNUM is not specified, "
+  "all log entries are displayed."
+};
+
+/* read_pcr_func */
+static int
+pcrread_func (char *arg, int flags)
+{
+    int pcr_index = -1;
+    int rc;
+    unsigned char pcr_value[SHA1_DIGEST_SIZE];
+
+    if (! *arg
+     || ! safe_parse_maxint(&arg, &pcr_index)) {
+        errnum = ERR_BAD_ARGUMENT;
+        return 1;
+    }
+
+    /* TCG status check */
+    if (tcg_status_check( NULL )) {
+        grub_printf (err_no_tcg);
+        return 0;
+    }
+
+    /* Read pcr value */
+    rc = tcg_pcr_read(pcr_index, pcr_value);
+    if (rc != 0) {
+        grub_printf(err_tcg_rc, rc);
+        return 0;
+    }
+    println_hash( pcr_value );
+    return (0);
+}
+
+static struct builtin builtin_pcrread =
+{
+  "pcrread",
+  pcrread_func,
+  //BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
+  "pcrread [PCRINDEX]",
+  "Display current value of PCR(Platform Configuration Register) "
+  "at index, PCRINDEX."
+};
+
+#endif /* TCG_TRUSTED_BOOT */
+  
+
   
 
 /* The table of builtin commands. Sorted in dictionary order.  */
@@ -4841,6 +5181,9 @@ struct builtin *builtin_table[] =
 #ifdef USE_MD5_PASSWORDS
   &builtin_md5crypt,
 #endif /* USE_MD5_PASSWORDS */
+#ifdef TCG_TRUSTED_BOOT
+  &builtin_measure,
+#endif /* TCG_TRUSTED_BOOT */
   &builtin_module,
   &builtin_modulenounzip,
   &builtin_pager,
@@ -4848,6 +5191,9 @@ struct builtin *builtin_table[] =
   &builtin_parttype,
   &builtin_password,
   &builtin_pause,
+#ifdef TCG_TRUSTED_BOOT
+  &builtin_pcrread,
+#endif /* TCG_TRUSTED_BOOT */
 #ifdef GRUB_UTIL
   &builtin_quit,
 #endif /* GRUB_UTIL */
@@ -4864,6 +5210,9 @@ struct builtin *builtin_table[] =
 #endif /* SUPPORT_SERIAL */
   &builtin_setkey,
   &builtin_setup,
+#ifdef TCG_TRUSTED_BOOT
+  &builtin_tcglog,
+#endif /* TCG_TRUSTED_BOOT */
 #if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
   &builtin_terminal,
 #endif /* SUPPORT_SERIAL || SUPPORT_HERCULES */
--- grub-0.97/configure.ac.orig	2005-05-08 11:36:03.000000000 +0900
+++ grub-0.97/configure.ac	2005-05-26 16:06:48.565864472 +0900
@@ -660,6 +660,15 @@ dnl Because recent automake complains ab
 CCASFLAGS='$(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)'
 AC_SUBST(CCASFLAGS)
 
+dnl TCG Trusted Boot support is only applyed for Stage1 and Stage2 
+AC_ARG_ENABLE(tcg,
+  [  --disable-tcg         disable TCG Trusted Boot])
+
+if test x"$enable_tcg" != xno; then
+  STAGE1_CFLAGS="$STAGE1_CFLAGS -DTCG_TRUSTED_BOOT=1"
+  STAGE2_CFLAGS="$STAGE2_CFLAGS -DTCG_TRUSTED_BOOT=1"
+fi
+
 
 dnl Output.
 AC_CONFIG_FILES([Makefile stage1/Makefile stage2/Makefile \
--- grub-0.97/ChangeLog.orig	2005-05-08 11:47:02.000000000 +0900
+++ grub-0.97/ChangeLog	2005-05-26 16:20:13.813448232 +0900
@@ -1,3 +1,67 @@
+2005-05-26  Seiji Munetoh  <munetoh@jp.ibm.com>
+       
+	Added support for TCG Trusted Boot capability.
+	Co-authors:Taiga Nakamura, Yuhji Yamashita and Yoshiaki Funaki.
+		
+	* stage1/stage1.h [TCG_TRUSTED_BOOT]: Added definitions for TCG 
+	measurement.
+	(TCG_GRUB_PCR_INDEX): The TPM PCR index for measuring grub 
+	modules (stage1.5 and 2).
+	(TCG_GRUB_CONF_PCR_INDEX): The TPM PCR index for measuring grub 
+	configuration file.
+	(TCG_FILE_PCR_INDEX): The TPM PCR index for measuring the OS 
+	files.
+	(TCG_GRUB_PCR_EVENTTYPE): The TPM PCR EventType for measuring 
+	grub modules.
+	
+	* stage1/stage1.S [TCG_TRUSTED_BOOT]: Measure stage1.5 after 
+	loading it. CHS support was disabled to make the space.  
+	(tcg_hashall): BIOS call "INT 1Ah, (AH)=BBh,(AL)=05h" TCG_HashAll
+	(tcg_logevent): BIOS call "INT 1Ah, (AH)=BBh,(AL)=04h" TCG_LogEvent
+	
+	* stage2/shared.h [TCG_TRUSTED_BOOT]: Added definitions for 
+	externs and wrapping functions.
+	
+	* stage2/start.S [TCG_TRUSTED_BOOT]: Measure sector 2+ of 
+	stage1.5.
+	
+	* stage2/asm.S [TCG_TRUSTED_BOOT]: Added following functions, 
+	for TCG operations.
+	(tcg_status_check): Check TCG status.
+	(tcg_extend): Send TPM_Extend.
+	(tcg_log_extend): Log PCR event and extend.
+	(tcg_pcr_read): Send TPM_PcrRead.
+	(tcg_hash_all): Hash the data
+	
+	* stage2/stage1_5.c [TCG_TRUSTED_BOOT]: Measure stage2 after 
+	loading it.
+	(cmain): Added measurement of stage 2.
+	
+	* stage2/stage2.c [TCG_TRUSTED_BOOT]: Measure configuration file.
+	(cmain): Added measurement of config file.
+	
+	* stage2/boot.c [TCG_TRUSTED_BOOT]: Added built in commands for TCG 
+	operations.
+	(load_module): Added measurement
+	(load_initrd): Added measurement
+	
+	* stage2/builtins.c [TCG_TRUSTED_BOOT]: Added built in commands for 
+	TCG operations.
+	(chainloader): Added measurement, new option [--pcr=PCRINDEX]
+	(initrd): Added measurement, new option [--pcr=PCRINDEX]
+	(initrd_func): Added measurement, new option [--pcr=PCRINDEX]
+	(kernel): Added measurement, new option [--pcr=PCRINDEX]
+	(module): Added measurement, new option [--pcr=PCRINDEX]
+	(modulenounzip): Added measurement, new option [--pcr=PCRINDEX]
+	(measure_file): Measure given file 
+	(measure_func): New command, Perform TCG measurement operation.
+	(tcglog_func): New command, Display TCG event log.
+	(pcrread_func): New command, Display current value of PCR.
+	
+	* configure.ac: Added --disable-tcg option, in case user 
+	does not want the new TCG interface.
+
+
 2005-05-08  Yoshinori K. Okuji  <okuji@enbug.org>
 
 	* configure.ac (AC_INIT): Upgraded to 0.97.
