--- grub-0.97-orig/configure.in	2009-05-01 19:28:18.000000000 +0900
+++ grub-0.97-ima/configure.in	2009-05-01 18:07:33.000000000 +0900
@@ -13,7 +13,7 @@
 dnl USE OF THIS SOFTWARE.
 
 AC_PREREQ(2.57)
-AC_INIT([GRUB], [0.97], [bug-grub@gnu.org])
+AC_INIT([GRUB], [0.97-ima-1.1.0.0], [munetoh@users.sourceforge.jp])
 AC_CONFIG_SRCDIR([stage2/stage2.c])
 AC_CONFIG_HEADER([config.h])
 AM_INIT_AUTOMAKE
@@ -743,6 +743,30 @@
 CCASFLAGS='$(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)'
 AC_SUBST(CCASFLAGS)
 
+dnl Integrity Measurement Architecture is applied to stage1, stage2 for v1.1 TPM and BIOS
+AC_ARG_ENABLE(ima,
+  [  --enable-ima         Enable IMA])
+if test x"$enable_ima" = xyes; then
+  STAGE1_CFLAGS="$STAGE1_CFLAGS -DENABLE_IMA=1 -DIMA_IGNORE_BIOS_RC3=1 -DIMA_USE_HLEE_F2=1 -DIMA_INFRA_MODE=1"
+  STAGE2_CFLAGS="$STAGE2_CFLAGS -DENABLE_IMA=1 -DIMA_IGNORE_BIOS_RC3=1 -DIMA_USE_HLEE_F2=1 -DIMA_INFRA_MODE=1"
+  CFLAGS="$CFLAGS -DIMA_INFRA_MODE=1"
+fi
+
+dnl Integrity Measurement Architecture is applied to stage1, stage2 for v1.2 TPM and BIOS, limited use of INT 1Ah call (BB00,BB07)
+AC_ARG_ENABLE(ima12,
+  [  --enable-ima12         Enable IMA12])
+if test x"$enable_ima12" = xyes; then
+  STAGE1_CFLAGS="$STAGE1_CFLAGS -DENABLE_IMA=1 -DIMA_IGNORE_BIOS_RC3=1 -DIMA_USE_CHLEE=1 -DIMA_INFRA_MODE=1"
+  STAGE2_CFLAGS="$STAGE2_CFLAGS -DENABLE_IMA=1 -DIMA_IGNORE_BIOS_RC3=1 -DIMA_USE_CHLEE=1 -DIMA_INFRA_MODE=1"
+  CFLAGS="$CFLAGS -DIMA_INFRA_MODE=1"
+fi
+
+dnl IMA discovery mode
+AC_ARG_ENABLE(imatest,
+  [  --enable-imatest         Enable IMA discovery at Stage2])
+if test x"$enable_imatest" = xyes; then
+  STAGE2_CFLAGS="$STAGE2_CFLAGS -DIMA_TEST=1"
+fi
 
 dnl Output.
 if test "x$platform" = xefi; then
--- grub-0.97-orig/stage2/Makefile.am	2009-05-01 19:28:18.000000000 +0900
+++ grub-0.97-ima/stage2/Makefile.am	2009-05-01 20:23:23.000000000 +0900
@@ -7,7 +7,7 @@
         fat.h filesys.h freebsd.h fs.h hercules.h i386-elf.h \
 	imgact_aout.h iso9660.h jfs.h mb_header.h mb_info.h md5.h \
 	nbi.h pc_slice.h serial.h shared.h smp-imps.h term.h \
-	terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h graphics.h gpt.h
+	terminfo.h tparm.h nbi.h ufs2.h vstafs.h xfs.h graphics.h gpt.h ima.h
 EXTRA_DIST = setjmp.S apm.S $(noinst_SCRIPTS)
 
 # For <stage1.h>.
@@ -23,7 +23,7 @@
 	disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_iso9660.c \
 	fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \
 	fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c stage2.c \
-	terminfo.c tparm.c graphics.c efistubs.c
+	terminfo.c tparm.c graphics.c efistubs.c ima.c
 libgrub_a_CFLAGS = $(GRUB_CFLAGS) -I$(top_srcdir)/lib \
 	-DGRUB_UTIL=1 -DFSYS_EXT2FS=1 -DFSYS_FAT=1 -DFSYS_FFS=1 \
 	-DFSYS_ISO9660=1 -DFSYS_JFS=1 -DFSYS_MINIX=1 -DFSYS_REISERFS=1 \
@@ -100,7 +100,7 @@
 	disk_io.c fsys_ext2fs.c fsys_fat.c fsys_ffs.c fsys_iso9660.c \
 	fsys_jfs.c fsys_minix.c fsys_reiserfs.c fsys_ufs2.c \
 	fsys_vstafs.c fsys_xfs.c gunzip.c md5.c serial.c stage2.c \
-	terminfo.c tparm.c efistubs.c
+	terminfo.c tparm.c efistubs.c ima.c
 libstage2_a_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
 
 if !PLATFORM_EFI
@@ -114,7 +114,7 @@
 	fsys_fat.c fsys_ffs.c fsys_iso9660.c fsys_jfs.c fsys_minix.c \
 	fsys_reiserfs.c fsys_ufs2.c fsys_vstafs.c fsys_xfs.c gunzip.c \
 	hercules.c md5.c serial.c smp-imps.c stage2.c terminfo.c tparm.c \
-	graphics.c
+	graphics.c ima.c
 pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
 pre_stage2_exec_CCASFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS)
 pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK)
--- grub-0.97-orig/stage1/stage1.h	2005-02-16 06:55:15.000000000 +0900
+++ grub-0.97-ima/stage1/stage1.h	2009-05-01 15:56:46.000000000 +0900
@@ -83,4 +83,8 @@
 /* The drive number of an invalid drive.  */
 #define GRUB_INVALID_DRIVE	0xFF
 
+#ifdef ENABLE_IMA
+#include "../stage2/ima.h"
+#endif /* ENABLE_IMA */
+
 #endif /* ! STAGE1_HEADER */
--- grub-0.97-orig/stage1/stage1.S	2009-05-01 19:28:18.000000000 +0900
+++ grub-0.97-ima/stage1/stage1.S	2009-05-01 15:56:46.000000000 +0900
@@ -18,6 +18,24 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#ifdef ENABLE_IMA
+/*
+ *  Changes:
+ *   1) Remove CHS part to get thecode space for Transitive Trust Support
+ *   2) Measure the 1st sector of stage 1.5 before jump to them
+ *
+ *  2002/12/XX Y. Yamashita  Original Patch
+ *   TCG_HashAll & TCG_LogEvent are used insted of the single
+ *   TCG_HashLogEvent call.
+ *  2004/06/28 S. Munetoh    Modified
+ *  2006/08/15 S. Munetoh    IMA_USE_HLEE_F2
+ *   use TCG_HashLogEvent call with format 2.
+ *  2007/04/19 S. Munetoh 
+ *   remove IMA_BIOS_BIGREALMODE_FIX
+ */
+#endif /* ENABLE_IMA */
+
+
 #include <stage1.h>
 	
 /*
@@ -155,6 +173,7 @@
 	/* print a notification message on the screen */
 	VMSG(notification_string)
 
+#ifndef ENABLE_IMA
 	/* do not probe LBA if the drive is a floppy */
 	testb	$STAGE1_BIOS_HD_FLAG, %dl
 	jz	chs_mode
@@ -182,6 +201,7 @@
 	jnz	lba_mode
 	andw	$1, %cx
 	jz	chs_mode
+#endif /* ENABLE_IMA */
 	
 lba_mode:
 	/* save the total number of sectors */
@@ -229,7 +249,11 @@
 	movw	$STAGE1_BUFFERSEG, %bx
 	jmp	copy_buffer
 		
-chs_mode:	
+chs_mode:
+#ifdef ENABLE_IMA
+	MSG(chs_no_support_string)
+	jmp     general_error
+#else /* ! ENABLE_IMA */
 	/*
 	 *  Determine the hard disk geometry from the BIOS!
 	 *  We do this first, so that LS-120 IDE floppies work correctly.
@@ -347,8 +371,129 @@
 	jc	read_error
 
 	movw	%es, %bx
+#endif /* ! ENABLE_IMA */
 	
 copy_buffer:
+
+#ifdef ENABLE_IMA
+
+	pusha
+#ifdef IMA_USE_HLEE_F2  /* IBM/Lenovo V11 and all V12 BIOS must work */
+/*
+ * BIOS call "INT 1Ah, (AH)=BBh,(AL)=00h" TCG_StatusCheck
+ *	Call with	%ah = 0xBB
+ *			%al = 0x00
+ *
+ *	Return:		%eax = TCG_STATUS
+ *			%ebx = 'TCPA'
+ *
+ * Ref:
+ *  TCG PC Client Specific Implementation Specification for Conventional BIOS v1.2,
+ *  Section 12.5 (page 85)
+ */
+tcg_statuscheck:
+	movw    $0xbb00, %ax		/* TCG_StatusCheck */
+	int     $0x1a
+	test	%eax, %eax
+	jnz	tcg_end			/* if eax != 0 */
+/*
+ * BIOS call "INT 1Ah, (AH)=BBh,(AL)=01h" TCG_HashLogExtendEvent
+ *	Call with	%ah = 0xBB
+ *			%al = 0x01
+ *			%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 Client Specific Implementation Specification for Conventional BIOS v1.2,
+ *  Section 12.6 (page 86)
+ */
+	/* Set tcg_pcr_event.eventSize = 0 */
+tcg_hashlogextendevent:
+	movl	%eax, ABS(tcg_pcr_event + 28) /* LogDatalen = 0, eax must be zero */
+	movw    $0xbb01, %ax		/* TCG_LogEvent */
+	movw    $ABS(ipb), %di		/* ES:DI = IPB */
+	movw	$0x8E00, %si		/* OPB = 0x8E00 */
+	xorl    %ecx, %ecx		/* ECX = 0 */
+	xorl    %edx, %edx		/* EDX = 0 */
+	int     $0x1a
+#ifndef IMA_IGNORE_BIOS_RC3
+	test	%eax, %eax
+	jz	tcg_end
+	MSG(tcg_error_string)
+#endif /* IMA_IGNORE_BIOS_RC3 */
+
+#else /* ! IMA_USE_HLEE_F2 */
+/*
+ * all V11 & V12 BIOS must work but HALT with some BIOS
+ * since there are no space to put TCG_StatusCkeck()
+ */
+/*
+ * 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
+#ifndef IMA_IGNORE_BIOS_RC3
+	test	%eax, %eax
+	jnz	tcg_error
+#endif	/* IMA_IGNORE_BIOS_RC3 */
+/*
+ * 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)
+ */
+tcg_logevent:
+	/* Set tcg_pcr_event.eventSize = 0 */
+	movl	%eax, ABS(tcg_pcr_event + 28)
+	movb	$(ipb_logevent_end - ipb), ABS(ipb_len)
+	movb	$IMA_EV_GRUB_STAGE15_PCR, ABS(ipb_pcrindex)
+	movw    $0xbb04, %ax		/* TCG_LogEvent */
+	movw	$0x8E00, %si		/* OPB = 0x8E00 */
+	int     $0x1a
+#ifndef IMA_IGNORE_BIOS_RC3
+	test	%eax, %eax
+	jz	tcg_end
+tcg_error:
+	MSG(tcg_error_string)
+#endif /* IMA_IGNORE_BIOS_RC3 */
+#endif /* ! IMA_USE_HLEE_F2 */
+tcg_end:
+	popa
+#endif /* ENABLE_IMA */
+
 	movw	ABS(stage2_segment), %es
 
 	/*
@@ -407,6 +552,10 @@
 hd_probe_error_string:	.string "Hard Disk"
 read_error_string:	.string "Read"
 general_error_string:	.string " Error"
+#ifdef ENABLE_IMA
+chs_no_support_string:	.string "CHSNA"
+tcg_error_string:	.string "TCGERR "
+#endif
 
 /*
  * message: write the string pointed to by %si
@@ -429,6 +578,55 @@
 	jne	1b	/* if not end of string, jmp to display */
 	ret
 
+#ifdef ENABLE_IMA
+
+/* TCG(TCG) BIOS Input Parameter Block */
+#ifdef IMA_USE_HLEE_F2
+/* TCG_HashLogExtendEvent Input Parameter Block Format 2 */
+ipb: /* 28 bytes */
+	.word	(ipb_end - ipb)		/*  0 block size   */
+	.word   0                       /*  2 reserved     */
+	.long   STAGE1_BUFFERSEG * 0x10 /*  4 hash data pointer */
+#ifdef IMA_INFRA_MODE
+	.long   496                     /*  8 hash data length (496 bytes) */
+#else
+	.long   512			/*  8 hash data length (512 bytes) */
+#endif
+	.long   IMA_EV_GRUB_STAGE15_PCR /*  C PCR index */
+	.long   0                       /* 10 reserved */
+	.long   ABS(tcg_pcr_event)      /* 14 LogData Ptr */
+	.long   32                      /* 18 LogData Len */
+ipb_end:
+
+#else /* ! IMA_USE_HLEE_F2 */
+ipb:
+ipb_len:
+	.word	(ipb_hashall_end - ipb)	/*  0 block size   */
+	.word   0                       /*  2 reserved     */
+	.long   STAGE1_BUFFERSEG * 0x10	/*  4 data pointer */
+#ifdef IMA_INFRA_MODE
+	.long   496                     /*  8 hash data length (496 bytes) */
+#else
+	.long   512			/*  8 hash data length (512 bytes) */
+#endif
+ipb_pcrindex:
+ipb_algorithmid:
+	.long   4                       /* AlgorighmID = TCG_ALG_SHA for HashAll*/
+					/* PCRIndex for LogEvent */
+ipb_hashall_end:
+	.long	IMA_EV_GRUB_STAGE15_TYPE /* event type	*/
+	.long   ABS(tcg_pcr_event)       /* log pointer  */
+	.long   32                       /* log size     */
+ipb_logevent_end:
+#endif /* ! IMA_USE_HLEE_F2 */
+/* TCG_PCR_EVENT structure */
+tcg_pcr_event:                            /* 32 bytes     */
+	.long   IMA_EV_GRUB_STAGE15_PCR   /* PCR index    */
+	.long   IMA_EV_GRUB_STAGE15_TYPE  /* event type   */
+/*      .space  20                        |* PCR value    */
+/*      .long   0                         |* event size   */
+#endif /* ENABLE_IMA  */
+
 	/*
 	 *  Windows NT breaks compatibility by embedding a magic
 	 *  number here.
@@ -448,6 +646,7 @@
 part_start:	
 	. = _start + STAGE1_PARTSTART
 
+#ifndef ENABLE_IMA
 probe_values:
 	.byte	36, 18, 15, 9, 0
 
@@ -495,6 +694,8 @@
 
 	jmp	final_init
 
+#endif /* ! ENABLE_IMA */
+
 	. = _start + STAGE1_PARTEND
 
 /* the last 2 bytes in the sector 0 contain the signature */
--- grub-0.97-orig/stage2/asm.S	2009-05-01 19:28:18.000000000 +0900
+++ grub-0.97-ima/stage2/asm.S	2009-05-01 15:56:46.000000000 +0900
@@ -2509,6 +2509,834 @@
 
 #endif /* STAGE1_5 */
 
+#ifdef TRANSITIVE_TRUST
+
+#define TCG_DIGEST_SIZE     20
+#define TCG_PCR_VALUE_SIZE  20
+#define TCG_EV_GRUB         0x20
+
+/* #define TCG_DEBUG  */
+
+
+	.code16
+	.align  4
+tcg_signature:
+	.byte   'T', 'C', 'P', 'A'
+tcg_grub:
+	.byte   'G', 'R', 'U', 'B'
+
+
+	/* TCG_PassThroughToTPM Input Parameter Block */
+tcg_passthru_ipb:
+tcg_passthru_ipb_length:
+	.word   0	       /* IPBLength */
+	.word   0	       /* Reserved */
+tcg_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:
+tcg_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_HashLogExtendEvent Input Parameter Block (Format 1)*/
+tcg_hlee_ipb:
+	.word   tcg_hlee_ipb_end - tcg_hlee_ipb	 /* IPBLength, 18h */
+	.word   0				       /* Reserved */
+tcg_hlee_ipb_hashdata:
+	.long   0				       /* HashDataPtr */
+tcg_hlee_ipb_hashdatalen:
+	.long   0				       /* HashDataLen */
+tcg_hlee_ipb_pcr_index:
+	.long   0				       /* PCRIndex */
+tcg_hlee_ipb_logdata:
+	.long   0				       /* LogDataPtr */
+tcg_hlee_ipb_logdatalen:
+	.long   0				       /* LogDataLen */
+tcg_hlee_ipb_end:
+	/* TBD */
+
+	/* TCG_HashLogExtendEvent Input Parameter Block (Format 2) */
+	/* TCG_LogEvent	   Input Parameter Block */
+tcg_le_ipb:
+	.word   tcg_le_ipb_end - tcg_le_ipb	     /* IPBLength, 18h */
+	.word   0				       /* Reserved */
+tcg_le_ipb_hashdata:
+	.long   0				       /* HashDataPtr */
+tcg_le_ipb_hashdatalen:
+	.long   0				       /* HashDataLen */
+tcg_le_ipb_pcr_index:
+	.long   0				       /* PCRIndex */
+tcg_le_ipb_eventtype:
+	.long   0				       /* reserved/type */
+tcg_le_ipb_logdata:
+	.long   0				       /* LogDataPtr */
+tcg_le_ipb_logdatalen:
+	.long   0				       /* LogDataLen */
+tcg_le_ipb_end:
+
+
+	/* TCG_HashLogExtendEvent Output Parameter Block */
+	/* TCG_LogEvent	   Output Parameter Block */
+tcg_le_opb:
+	.word   tcg_le_opb_end - tcg_le_opb     /* OPBLength */
+	.word   0			       /* Reserved */
+	.long   0			       /* EventNumber */
+	.space  TCG_PCR_VALUE_SIZE	      /* Hash */
+tcg_le_opb_end:
+
+
+
+	/* TCG_HashAll Input Parameter Block */
+tcg_hashall_ipb:
+	.word   tcg_hashall_ipb_end - tcg_hashall_ipb /* IPBLength =16 */
+	.word   0				     /* Reserved */
+tcg_hashall_ipb_data_ptr:
+	.long   0				     /* HashDataPtr */
+tcg_hashall_ipb_data_len:
+	.long   0				     /* HashDataLen */
+	.long   4	      /* AlgorithmID TPM_ALG_SHA 0x00000004 */
+tcg_hashall_ipb_end:
+
+	/* TCG_HashAll Outnput Parameter Block */
+tcg_hashall_opb:
+	.space  TCG_DIGEST_SIZE	       /* Hash size = PCR size */
+tcg_hashall_opb_end:
+
+	    /* Buffer for "tpm test" command */
+tcg_chlee_buf:
+	.byte  0xBB, 0x07
+
+
+#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 "
+hashlogevent_msg:       .string "DEBUG: TCG_HashLogExtendEvent "
+compacthashlogevent_msg: .string "DEBUG: TCG_CompactHashLogExtendEvent "
+hashall_msg:            .string "DEBUG: TCG_HashAll 0816 "
+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_StatusCheck (unsigned char *major,         *OUT*
+ *	                 unsigned char *minor,         *OUT*
+ *	                 unsigned char **event_log );  *OUT*
+ * 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.
+ *
+ * TCG_StatusCheck
+ * BIOS Call "Int 1AH Function" verify the presence of TCG BIOS I/F
+ *      Call with       %ax = 0xBB00h (TCG_LogEvent)
+ *                      %ebx = "TCPA" (0x41504354)
+ *                      %ecx = 0
+ *                      %edx = 0
+ * 2006-06-20 SM revised
+ */
+ENTRY(TCG_StatusCheck)
+	push    %ebx
+	push    %ecx
+	push    %edx
+	push    %esi
+	push    %edi
+	push    %ebp
+
+	call    EXT_C(prot_to_real)
+	.code16
+
+	MSG(status_check_msg)
+
+	/*  TCG_StatusCheck */
+	movw    $0xBB00, %ax
+	int     $0x1A
+	and     %eax, %eax
+	jnz     tcg_sc_ng
+	cmpl    %ebx, ABS(tcg_signature)
+	je      tcg_sc_ok
+tcg_sc_ng:
+	MSG(ng_msg)
+	/* movw    $0x0003, %ax  # 2006-06-28 SM remove */
+	jmp     tcg_sc_goback
+tcg_sc_ok:
+	MSG(ok_msg)
+tcg_sc_goback:
+	movw    %ax, %bx
+	DATA32  call    EXT_C(real_to_prot)
+	.code32
+
+	movzwl  %bx, %eax
+	test    %eax, %eax
+	jnz     tcg_sc_skip_copy_event_log
+
+	/* *version major */
+	movl    0x1C(%esp), %edi
+	movb    %ch, (%edi)
+
+	/* *version minor */
+	movl    0x20(%esp), %edi
+	movb    %cl, (%edi)
+
+	/* *event_log */
+	movl    0x24(%esp), %edi
+	test    %edi, %edi
+	jz      tcg_sc_skip_copy_event_log
+
+	movl    %esi, (%edi)
+
+tcg_sc_skip_copy_event_log:
+	pop     %ebp
+	pop     %edi
+	pop     %esi
+	pop     %edx
+	pop     %ecx
+	pop     %ebx
+	ret
+
+/*
+ * int TCG_HashLogExtendEventF1( int pcr_index,            *IN
+ *                                 int hashdatasize          *IN
+ *                                 unsigned char *hashdeta   *IN
+ *                                 int logdatasize           *IN
+ *                                 unsigned char *logdata )  *IN
+ *
+ *  Format 1 (?)
+ *
+ * BIOS Call "Int 1AH Function" to log TCG_PCR_EVENT
+ *      Call with       %ax = 0xBB01h (TCG_HashLogExtendEvent)
+ *                      %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_HashLogExtendEventF1)
+	push    %ebp
+	movl    %esp, %ebp
+	push    %ebx
+	push    %ecx
+	push    %edx
+	push    %esi
+	push    %edi
+	/* ipb - PCR index */
+	movl    0x08(%ebp), %eax
+	movl    %eax, ABS(tcg_hlee_ipb_pcr_index)
+
+	/* ipb - Hash Data Size */
+	movl    0x0C(%ebp), %eax
+	movl    %eax, ABS(tcg_hlee_ipb_hashdatalen)
+
+	/* ipb - Hash Data Ptr */
+	movl    0x10(%ebp), %esi
+	movl    %esi, ABS(tcg_hlee_ipb_hashdata)
+
+	/* ipb - Log Data Size */
+	movl    0x14(%ebp), %eax
+	movl    %eax, ABS(tcg_hlee_ipb_logdatalen)
+
+	/* ipb - Log Data Ptr */
+	movl    0x18(%ebp), %esi
+	movl    %esi, ABS(tcg_hlee_ipb_logdata)
+
+
+	call    EXT_C(prot_to_real)
+	.code16
+
+	/* TCG_HashLogExtendEvent */
+	MSG(hashlogevent_msg)
+
+	movw    $0xBB01, %ax
+	movw    $ABS(tcg_hlee_ipb), %di
+	movw    $ABS(tcg_le_opb), %si
+	movl    ABS(tcg_signature), %ebx
+	xorl    %ecx, %ecx
+	movl    %ecx, %edx
+	int     $0x1A
+	and     %eax, %eax
+	jz      tcg_hlee_ok
+	MSG(ng_msg)
+	jmp     tcg_hlee_go_back
+
+tcg_hlee_ok:
+	MSG(ok_msg)
+
+tcg_hlee_go_back:
+	movl    %eax, %ebx /* TODO return 3h???  */
+	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_HashLogExtendEventF2( int pcr_index,              *IN
+ *                                 int hashdatasize          *IN
+ *                                 unsigned char *hashdeta   *IN
+ *                                 int logdatasize           *IN
+ *                                 unsigned char *logdata )  *IN
+ *
+ *  Format 2 (IBM/Lenove)
+ *
+ * BIOS Call "Int 1AH Function" to log TCG_PCR_EVENT
+ *      Call with       %ax = 0xBB01h (TCG_HashLogExtendEvent)
+ *                      %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_HashLogExtendEventF2)
+	push    %ebp
+	movl    %esp, %ebp
+	push    %ebx
+	push    %ecx
+	push    %edx
+	push    %esi
+	push    %edi
+	/* ipb - PCR index */
+	movl    0x08(%ebp), %eax
+	movl    %eax, ABS(tcg_le_ipb_pcr_index)
+
+	/* ipb - Hash Data Size */
+	movl    0x0C(%ebp), %eax
+	movl    %eax, ABS(tcg_le_ipb_hashdatalen)
+
+	/* ipb - Hash Data Ptr */
+	movl    0x10(%ebp), %esi
+	movl    %esi, ABS(tcg_le_ipb_hashdata)
+
+	/* ipb - Log Data Size */
+	movl    0x14(%ebp), %eax
+	movl    %eax, ABS(tcg_le_ipb_logdatalen)
+
+	/* ipb - Log Data Ptr */
+	movl    0x18(%ebp), %esi
+	movl    %esi, ABS(tcg_le_ipb_logdata)
+	/* ipb - reserved - clear */
+	xorl    %esi, %esi
+	movl    %esi, ABS(tcg_le_ipb_eventtype)
+
+	call    EXT_C(prot_to_real)
+	.code16
+
+	/* TCG_HashLogExtendEvent */
+	MSG(hashlogevent_msg)
+
+	movw    $0xBB01, %ax
+	movw    $ABS(tcg_le_ipb), %di
+	movw    $ABS(tcg_le_opb), %si
+	movl    ABS(tcg_signature), %ebx
+	xorl    %ecx, %ecx
+	movl    %ecx, %edx
+	int     $0x1A
+	and     %eax, %eax
+	jz      tcg_hlee2_ok
+	MSG(ng_msg)
+	jmp     tcg_hlee2_go_back
+
+tcg_hlee2_ok:
+	MSG(ok_msg)
+
+tcg_hlee2_go_back:
+	movl    %eax, %ebx /* TODO return 3h???  */
+	DATA32  call    EXT_C(real_to_prot)
+	.code32
+
+	movl    %ebx, %eax
+	pop     %edi
+	pop     %esi
+	pop     %edx
+	pop     %ecx
+	pop     %ebx
+	pop     %ebp
+	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(tcg_passthru_ipb_length)
+
+	cld
+	rep
+	movsb			   /* Copy operandIn to IPB */
+
+	call    EXT_C(prot_to_real)
+	.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 ima_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(ima_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     ima_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
+
+ima_extend_go_back:
+	pop     %edi
+	pop     %esi
+	pop     %edx
+	pop     %ecx
+	pop     %ebx
+	pop     %ebp
+	ret
+
+
+/*
+ * int ima_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(ima_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     ima_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
+
+ima_pcr_read_go_back:
+	pop     %edi
+	pop     %esi
+	pop     %edx
+	pop     %ecx
+	pop     %ebx
+	pop     %ebp
+	ret
+
+
+/*
+ * int TCG_LogExtend ( int pcr_index,            *IN
+ *                     int eventtype             *IN
+ *                     int loddatasize           *IN
+ *                     unsigned char *logdata )  *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_LogExtend)
+	push    %ebp
+	movl    %esp, %ebp
+	push    %ebx
+	push    %ecx
+	push    %edx
+	push    %esi
+	push    %edi
+	/* ipb - PCR index */
+	movl    0x08(%ebp), %eax
+	movl    %eax, ABS(tcg_le_ipb_pcr_index)
+
+	/* ipb - type */
+	movl    0x0C(%ebp), %eax
+	movl    %eax, ABS(tcg_le_ipb_eventtype)
+
+	/* ipb - Log Data Size */
+	movl    0x10(%ebp), %eax
+	movl    %eax, ABS(tcg_le_ipb_logdatalen)
+
+	/* ipb - Log Data Ptr */
+	movl    0x14(%ebp), %esi
+	movl    %esi, ABS(tcg_le_ipb_logdata)
+
+	/* ipb - clear Hash Data */
+	xorl    %esi, %esi
+	movl    %esi, ABS(tcg_le_ipb_hashdatalen)
+	movl    %esi, ABS(tcg_le_ipb_hashdata)
+
+
+	call    EXT_C(prot_to_real)
+	.code16
+
+	/* TCG_LogEvent */
+	MSG(logevent_msg)
+
+	movw    $0xBB04, %ax
+	movw    $ABS(tcg_le_ipb), %di
+	movw    $ABS(tcg_le_opb), %si
+	movl    ABS(tcg_signature), %ebx
+	xorl    %ecx, %ecx
+	movl    %ecx, %edx
+	int     $0x1A
+	and     %eax, %eax
+	jz      tle3_ok
+	MSG(ng_msg)
+	jmp     tle3_go_back
+
+tle3_ok:
+	MSG(ok_msg)
+
+tle3_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_HashAll ( 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_HashAll)
+        push    %ebp
+	/* movl    %esp, %ebp */
+	push    %ebx
+	push    %ecx
+	push    %edx
+	push    %esi
+	push    %edi
+
+	/* len */
+	movl    0x1c(%esp), %eax
+	movl    %eax, ABS(tcg_hashall_ipb_data_len)
+
+	/* *data */
+	movl    0x20(%esp), %esi
+	movl    %esi, ABS(tcg_hashall_ipb_data_ptr)
+
+	call    EXT_C(prot_to_real)
+	.code16
+
+	/* TCG_HashAll */
+	MSG(hashall_msg)
+
+	movw    $0xBB05, %ax
+	movw    $ABS(tcg_hashall_ipb), %di
+	movw    $ABS(tcg_hashall_opb), %si
+	movl    ABS(tcg_signature), %ebx
+	xorl    %ecx, %ecx
+	movl    %ecx, %edx
+	int     $0x1A
+	and     %eax, %eax
+	jz      tcg_hashall_ok
+	MSG(ng_msg)
+	jmp     tcg_hashall_go_back
+tcg_hashall_ok:
+	MSG(ok_msg)
+tcg_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(tcg_hashall_opb), %esi
+	movl    0x24(%esp), %edi
+	movl    $TCG_DIGEST_SIZE, %ecx
+	cld
+	rep
+	movsb
+
+	movl    %ebx, %eax
+	pop     %edi
+	pop     %esi
+	pop     %edx
+	pop     %ecx
+	pop     %ebx
+	pop     %ebp
+	ret
+
+/*
+ * int TCG_CompactHashLogExtendEvent( int pcr_index,          *IN
+ *                                 int hashdatasize           *IN
+ *                                 unsigned char *hashdeta)   *IN
+ *
+ *  Event Type  :	EV_COMPACT_HASH (0Ch) - fixed
+ *  Event Field :	4 bytes "GRUB"
+ *
+ * BIOS Call "Int 1AH Function" to log TCG_PCR_EVENT
+ *      Call with       %ax = 0xBB07h (TCG_CompactHashLogExtendEvent)
+ *                      %es = Segment of data to be hashed
+ *                      %di = Offset of data to be hashed
+ *                      %esi = event field
+ *                      %ebx = "TCPA" (0x41504354)
+ *                      %ecx = data length
+ *                      %edx = pcr index
+ *
+ *      Return          %eax = Return code
+ *                      %edx = event num
+ */
+ENTRY(TCG_CompactHashLogExtendEvent)
+	push    %ebp
+	movl    %esp, %ebp
+	push    %ebx
+	push    %ecx
+	push    %edx
+	push    %esi
+	push    %edi
+	/* PCR index */
+	movl    0x08(%ebp), %edx
+
+	/* Hash Data Size */
+		movl    0x0C(%ebp), %ecx
+
+	/* Hash Data Ptr  */
+#if 0
+	/* Sorry, this does not work yet */
+	movw    0x10(%ebp), %ax
+	shlw    $12,  %ax
+	movw	%ax, %es
+	movw    0x12(%ebp), %di
+#endif
+
+	call    EXT_C(prot_to_real)
+	.code16
+
+	/* TCG_CompactHashLogExtendEvent */
+	MSG(compacthashlogevent_msg)
+
+	movw    $0xBB07, %ax
+	movw	$ABS(tcg_chlee_buf), %di
+	movl    ABS(tcg_signature), %ebx
+	movl    ABS(tcg_grub), %esi
+	int     $0x1A
+	and     %eax, %eax
+	jz      tcg_chlee_ok
+	MSG(ng_msg)
+	jmp     tcg_chlee_go_back
+
+tcg_chlee_ok:
+	MSG(ok_msg)
+
+tcg_chlee_go_back:
+	movl    %eax, %ebx /* TODO return 3h???  */
+	DATA32  call    EXT_C(real_to_prot)
+	.code32
+
+	movl    %ebx, %eax
+	pop     %edi
+	pop     %esi
+	pop     %edx
+	pop     %ecx
+	pop     %ebx
+	pop     %ebp
+	ret
+
+#endif /* TRANSITIVE_TRUST */
+
 /*
  *  This is the area for all of the special variables.
  */
--- grub-0.97-orig/stage2/boot.c	2009-05-01 19:28:18.000000000 +0900
+++ grub-0.97-ima/stage2/boot.c	2009-05-01 19:24:41.000000000 +0900
@@ -34,6 +34,7 @@
 static int linux_mem_size;
 #endif
 
+
 /*
  *  The next two functions, 'load_image' and 'load_module', are the building
  *  blocks of the multiboot loader component.  They handle essentially all
@@ -68,6 +69,26 @@
      buffer by default */
   pu.aout = (struct exec *) buffer;
 
+
+#ifdef TRANSITIVE_TRUST
+  /* we measure the whole kernel image at this point */
+  /* thus grub read the kernel twice, sorry  */
+  if  (ima_grub_pcr_index >= 0) {
+     if (ima_debug) grub_printf("load_image\n");
+     ima_workbuf = (unsigned char *) 0x100000;
+     measure_eventdata(IMA_EV_GRUB_KERNEL_CMD_PCR,
+		      IMA_EV_GRUB_KERNEL_CMD_TYPE,
+		      grub_strlen(arg),
+		      arg); // or skip_to(0,arg));
+     /* measure kenrel image */
+     measure_file(kernel,
+		 ima_grub_pcr_index, /* set by kernel_func() in builtin.c*/
+		 ima_grub_eventtype);
+     ima_grub_pcr_index = -1;
+  }
+#endif
+
+
   if (!grub_open (kernel))
     return KERNEL_TYPE_NONE;
 
@@ -81,6 +102,9 @@
       return KERNEL_TYPE_NONE;
     }
 
+
+
+
   for (i = 0; i < len; i++)
     {
       if (MULTIBOOT_FOUND ((int) (buffer + i), len - i))
@@ -776,6 +800,27 @@
   /* if we are supposed to load on 4K boundaries */
   cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
 
+#ifdef TRANSITIVE_TRUST
+  if (ima_measure_gziped_file == 1) {
+      /* we measure the whole (gziped) module image at this point */
+      /* thus grub read the module twice, sorry  */
+      if  (ima_grub_pcr_index >= 0) {
+	  if (ima_debug) grub_printf("load_image\n");
+	  ima_workbuf = (unsigned char *) cur_addr;
+	  measure_eventdata(IMA_EV_GRUB_MODULE_CMD_PCR,
+		      IMA_EV_GRUB_MODULE_CMD_TYPE,
+		      grub_strlen(arg),
+		      arg); // or skip_to(0,arg));
+	  /* measure kenrel image */
+	  measure_file(module,
+		 ima_grub_pcr_index, /* set by kernel_func() in builtin.c*/
+		 ima_grub_eventtype);
+	  ima_grub_pcr_index = -1;
+      }
+  }
+#endif
+
+
   if (!grub_open (module))
     return 0;
 
@@ -786,6 +831,45 @@
       return 0;
     }
 
+#ifdef  TRANSITIVE_TRUST
+  if (ima_measure_gziped_file !=1) {
+      if  (ima_grub_pcr_index >= 0) {
+        if (ima_debug) grub_printf("load_module\n");
+        /* measure */
+        measure_eventdata(IMA_EV_GRUB_MODULE_CMD_PCR,
+                      IMA_EV_GRUB_MODULE_CMD_TYPE,
+                      grub_strlen(arg),
+                      arg); // or skip_to(0,arg));
+        measure_mem(len,
+                (unsigned char*)cur_addr,
+                ima_grub_pcr_index,
+                ima_grub_eventtype,
+                module);
+        ima_grub_pcr_index = -1;
+      }
+  }
+#endif /* TRANSITIVE_TRUST */
+
+
+#ifdef  TRANSITIVE_TRUST
+   if (ima_measure_gziped_file !=1) {
+      if  (ima_grub_pcr_index >= 0) {
+         if (ima_debug) grub_printf("load_module\n");
+         /* measure */
+        measure_eventdata(IMA_EV_GRUB_MODULE_CMD_PCR,
+                      IMA_EV_GRUB_MODULE_CMD_TYPE,
+                      grub_strlen(arg),
+                      arg); // or skip_to(0,arg));
+        measure_mem(len,
+                (unsigned char*)cur_addr,
+                ima_grub_pcr_index,
+                ima_grub_eventtype,
+                module);
+        ima_grub_pcr_index = -1;
+      }
+  }
+#endif /* TRANSITIVE_TRUST */
+
   verbose_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 */
@@ -884,6 +968,18 @@
   lh->ramdisk_image = RAW_ADDR (moveto);
   lh->ramdisk_size = len;
 
+#ifdef  TRANSITIVE_TRUST
+  if  (ima_grub_pcr_index >= 0) {
+     if (ima_debug) grub_printf("load_initrd\n");
+    /* measure */
+      measure_mem(lh->ramdisk_size,
+                      (unsigned char*)lh->ramdisk_image,
+                      ima_grub_pcr_index,
+                      ima_grub_eventtype,
+                      initrd);
+    ima_grub_pcr_index = -1;
+  }
+#endif /* TRANSITIVE_TRUST */
 
  fail:
   

--- grub-0.97-orig/stage2/builtins.c	2009-05-01 19:28:18.000000000 +0900
+++ grub-0.97-ima/stage2/builtins.c	2009-05-01 16:13:59.000000000 +0900
@@ -111,6 +111,41 @@
 int
 check_password (char *entered, char* expected, password_t type)
 {
+#ifdef ENABLE_IMA
+  int rc=0;
+
+  switch (type)
+    {
+    case PASSWORD_PLAIN:
+      rc = strcmp (entered, expected);
+      break;
+#ifdef USE_MD5_PASSWORDS
+    case PASSWORD_MD5:
+      rc = check_md5_password (entered, expected);
+      break;
+#endif
+    default:
+      /* unsupported password type: be secure */
+      rc = 1;
+    }
+
+  if (rc != 0)
+    {
+      measure_eventdata(IMA_EV_GRUB_ACTION_PCR,
+                        IMA_EV_GRUB_ACTION_TYPE,
+                        grub_strlen(ima_password_failure),
+                        ima_password_failure);
+    }
+  else
+    {
+      measure_eventdata(IMA_EV_GRUB_ACTION_PCR,
+                       IMA_EV_GRUB_ACTION_TYPE,
+                       grub_strlen(ima_password_enter),
+                       ima_password_enter);
+    }
+  return rc;
+
+#else  /* ! ENABLE_IMA */
   switch (type)
     {
     case PASSWORD_PLAIN:
@@ -124,6 +159,7 @@
       /* unsupported password type: be secure */
       return 1;
     }
+#endif /* ENABLE_IMA */
 }
 
 /* Print which sector is read when loading a file.  */
@@ -302,17 +338,26 @@
     case KERNEL_TYPE_FREEBSD:
     case KERNEL_TYPE_NETBSD:
       /* *BSD */
+#ifdef TRANSITIVE_TRUST
+      ima_final ("Booting BSD");
+#endif /* TRANSITIVE_TRUST */
       bsd_boot (kernel_type, bootdev, (char *) mbi.cmdline);
       break;
 #endif
 
     case KERNEL_TYPE_LINUX:
       /* Linux */
+#ifdef TRANSITIVE_TRUST
+      ima_final ("Booting Linux Kenrel");
+#endif /* TRANSITIVE_TRUST */
       linux_boot ();
       break;
 
     case KERNEL_TYPE_BIG_LINUX:
       /* Big Linux */
+#ifdef TRANSITIVE_TRUST
+      ima_final ("Booting Linux Kenrel");
+#endif /* TRANSITIVE_TRUST */
       big_linux_boot ();
       break;
 
@@ -341,6 +386,9 @@
 	  set_int13_handler (bios_drive_map);
 	}
       
+#ifdef TRANSITIVE_TRUST
+      ima_final ("Chainloader");
+#endif /* TRANSITIVE_TRUST */
       gateA20 (0);
       boot_drive = saved_drive;
       chain_stage1 (0, BOOTSEC_LOCATION, boot_part_addr);
@@ -349,11 +397,17 @@
 #ifndef PLATFORM_EFI
     case KERNEL_TYPE_MULTIBOOT:
       /* Multiboot */
+#ifdef TRANSITIVE_TRUST
+      ima_final ("Booting Linux Kenrel");
+#endif /* TRANSITIVE_TRUST */
       multi_boot ((int) entry_addr, (int) &mbi);
       break;
 #endif
 
     default:
+#ifdef TRANSITIVE_TRUST
+      ima_final ("Booting Linux Kenrel");
+#endif /* TRANSITIVE_TRUST */
       errnum = ERR_BOOT_COMMAND;
       return 1;
     }
@@ -467,6 +521,11 @@
 #else
   int force = 0;
   char *file = arg;
+  //#ifdef ENABLE_IMA
+#ifdef TRANSITIVE_TRUST
+  int pcr_index = IMA_EV_GRUB_FILE_PCR;//TCG_FILE_PCR_INDEX;
+  int eventtype = IMA_EV_GRUB_FILE_TYPE;
+#endif
 
   /* If the option `--force' is specified?  */
   if (substring ("--force", arg) <= 0)
@@ -475,6 +534,27 @@
       file = skip_to (0, arg);
     }
 
+  //#ifdef ENABLE_IMA
+#ifdef TRANSITIVE_TRUST
+  if (substring ("--pcr=", file) <= 0)
+    {
+      arg = file + 6;
+      if (! safe_parse_maxint(&arg, &pcr_index))
+        return 1;
+      file = skip_to(0, arg);
+    }
+  if (substring ("--eventtype=", file) <= 0)
+    {
+      arg = file + 12;
+      if (! safe_parse_maxint(&arg, &eventtype))
+        return 1;
+      file = skip_to(0, arg);
+    }
+
+  //measure_file(file, pcr_index, 1);
+  measure_file(file, pcr_index, eventtype);
+#endif
+
   /* Open the file.  */
   if (! grub_open (file))
     {
@@ -529,9 +609,16 @@
   "chainloader",
   chainloader_func,
   BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+#ifdef ENABLE_IMA
+  "chainloader [--force] [--pcr=PCRINDEX] --eventtype=[EVENTTYPE] 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
 };
 
 
@@ -1956,6 +2043,30 @@
 static int
 initrd_func (char *arg, int flags)
 {
+#ifdef ENABLE_IMA
+  int pcr_index = IMA_EV_GRUB_INITRD_PCR;
+  int eventtype = IMA_EV_GRUB_INITRD_TYPE;
+
+  if (substring ("--pcr=", arg) <= 0)
+    {
+      arg += 6;
+      if (! safe_parse_maxint(&arg, &pcr_index))
+        return 1;
+      arg = skip_to(0, arg);
+    }
+  if (substring ("--eventtype=", arg) <= 0)
+    {
+      arg += 12;
+      if (! safe_parse_maxint(&arg, &eventtype))
+        return 1;
+      arg = skip_to(0, arg);
+    }
+
+  ima_grub_pcr_index = pcr_index;
+  ima_grub_eventtype = eventtype;
+
+#endif
+
   switch (kernel_type)
     {
     case KERNEL_TYPE_LINUX:
@@ -1977,9 +2088,17 @@
   "initrd",
   initrd_func,
   BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+#ifdef ENABLE_IMA
+  "initrd [--pcr=PCRINDEX] [--eventtype=EVENTTYPE] 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."
+  " The option --eventtype specifies Event Type 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
 };
 
 #ifndef PLATFORM_EFI
@@ -2605,6 +2724,11 @@
   int len;
   kernel_t suggested_type = KERNEL_TYPE_NONE;
   unsigned long load_flags = 0;
+  //#ifdef ENABLE_IMA
+#ifdef TRANSITIVE_TRUST
+  int pcr_index = IMA_EV_GRUB_KERNEL_PCR; //TCG_FILE_PCR_INDEX;
+  int eventtype = IMA_EV_GRUB_KERNEL_TYPE;
+#endif
 
 #ifndef AUTO_LINUX_MEM_OPT
   load_flags |= KERNEL_LOAD_NO_MEM_OPTION;
@@ -2644,6 +2768,21 @@
 	 has no effect.  */
       else if (grub_memcmp (arg, "--no-mem-option", 15) == 0)
 	load_flags |= KERNEL_LOAD_NO_MEM_OPTION;
+
+#ifdef TRANSITIVE_TRUST
+      else if (grub_memcmp (arg, "--pcr=", 6) == 0)
+        {
+          arg += 6;
+          if (! safe_parse_maxint(&arg, &pcr_index))
+            return 1;
+        }
+      else if (grub_memcmp (arg, "--eventype=", 12) == 0)
+        {
+          arg += 12;
+          if (! safe_parse_maxint(&arg, &eventtype))
+            return 1;
+        }
+#endif
       else
 	break;
 
@@ -2663,6 +2802,14 @@
 
   /* Copy the command-line to MB_CMDLINE.  */
   grub_memmove (mb_cmdline, arg, len + 1);
+
+#ifdef TRANSITIVE_TRUST
+  /* save PCR index and EventType as global for load_image() */
+  /* For command line measurement, use default assignment -- TODO  */
+  ima_grub_pcr_index =  pcr_index;
+  ima_grub_eventtype =  eventtype;
+#endif
+
   kernel_type = load_image (arg, mb_cmdline, suggested_type, load_flags);
   if (kernel_type == KERNEL_TYPE_NONE)
     return 1;
@@ -2676,6 +2823,17 @@
   "kernel",
   kernel_func,
   BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+#ifdef TRANSITIVE_TRUST
+  "kernel [--no-mem-option] [--type=TYPE] [--pcr=PCRINDEX] --eventtype=[EVENTTYPE] 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"
@@ -2684,6 +2842,7 @@
   " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and"
   " \"multiboot\". The option --no-mem-option tells GRUB not to pass a"
   " Linux's mem option automatically."
+#endif
 };
 
 
@@ -2862,6 +3021,28 @@
 module_func (char *arg, int flags)
 {
   int len = grub_strlen (arg);
+#ifdef ENABLE_IMA
+  int pcr_index = IMA_EV_GRUB_MODULE_PCR;//TCG_FILE_PCR_INDEX;
+  int eventtype = IMA_EV_GRUB_MODULE_TYPE;
+
+  if (substring ("--pcr=", arg) <= 0)
+    {
+      arg += 6;
+      if (! safe_parse_maxint(&arg, &pcr_index))
+        return 1;
+      arg = skip_to(0, arg);
+    }
+  if (substring ("--eventtype=", arg) <= 0)
+    {
+      arg += 12;
+      if (! safe_parse_maxint(&arg, &eventtype))
+        return 1;
+      arg = skip_to(0, arg);
+    }
+
+  ima_grub_pcr_index =  pcr_index;
+  ima_grub_eventtype =  eventtype;
+#endif
 
   switch (kernel_type)
     {
@@ -2896,12 +3077,23 @@
   "module",
   module_func,
   BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+#ifdef ENABLE_IMA
+  "module [--pcr=PCRINDEX] [--eventtype=EVENTTYPE] 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."
+  " The option --eventtype specifies Event Type 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
 };
 
 
@@ -2929,9 +3121,16 @@
   "modulenounzip",
   modulenounzip_func,
   BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+#ifdef ENABLE_IMA
+  "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
 };
 #endif /* !PLATFORM_EFI */
 
@@ -3223,6 +3422,22 @@
       grub_memmove (password, arg, len);
       grub_memset (password + len, 0, PASSWORD_BUFLEN - len);
       password_type = type;
+#ifdef ENABLE_IMA
+      if (type == PASSWORD_MD5)
+	{
+          measure_eventdata(IMA_EV_GRUB_ACTION_PCR,
+                            IMA_EV_GRUB_ACTION_TYPE,
+                            grub_strlen(ima_password_protection_md5),
+                            ima_password_protection_md5);
+        }
+      else
+        {
+          measure_eventdata(IMA_EV_GRUB_ACTION_PCR,
+                            IMA_EV_GRUB_ACTION_TYPE,
+                            grub_strlen(ima_password_protection),
+                            ima_password_protection);
+        }
+#endif /* ENABLE_IMA */
     }
   return 0;
 }
@@ -5129,6 +5344,169 @@
   " the information about only the mode."
 };
 #endif /* ! PLATFORM_EFI */
+
+#ifdef TRANSITIVE_TRUST
+/*
+   measure
+
+   2006-06-20 SM renew
+ */
+
+static int
+measure_func (char *arg, int flags)
+{
+	char *file = arg;
+	int pcr_index = IMA_EV_GRUB_FILE_PCR;
+	int eventtype = IMA_EV_GRUB_FILE_TYPE;
+	int rc=0;
+	int mode=0; /* 0:normal 1:data=>event */
+	int wPcr=0;
+	int wType=0;
+
+	while(1) {
+		if (substring ("--pcr=", file) <= 0) {
+			wPcr=1;
+			arg = file + 6;
+			if (! safe_parse_maxint(&arg, &pcr_index))
+				return 1;
+			file = skip_to(0, arg);
+		} else if (substring ("--eventtype=", file) <= 0) {
+			wType=1;
+			arg = file + 12;
+			if (! safe_parse_maxint(&arg, &eventtype))
+				return 1;
+			file = skip_to(0, arg);
+		} else if (substring ("--eventdata", file) <= 0) {
+			mode=1;
+			if (wPcr==0)  pcr_index = IMA_EV_GRUB_FILEDATA_PCR;
+			if (wType==0) eventtype = IMA_EV_GRUB_FILEDATA_TYPE;
+			file = skip_to(0, file);
+		} else
+			break;
+	}  // while
+
+	if (mode) { /* mode 1 eventdata = file image */
+		rc = measure_file_as_event( file, pcr_index, eventtype );
+	} else {    /* mode 0 eventdata = filename */
+		rc = measure_file( file, pcr_index, eventtype );
+	}
+	return rc;
+}
+
+static struct builtin builtin_measure =
+{
+  "measure",
+  measure_func,
+  //BUILTIN_CMDLINE | BUILTIN_MENU,
+  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
+  "measure [[--pcr=PCRINDEX] [--eventtype=EVENTTYPE] [--eventdata] | [--mbr]] FILE",
+  "Perform measurement (Transitive Trust) operation with the FILE."
+  "--eventdata : hash data = event data(filename+filedata)"
+};
+
+
+/*
+   tpm command
+
+   How about just one command for all TPM/TCG diagnostic work
+
+   2006-06-23
+ */
+static int
+tpm_func (char *arg, int flags)
+{
+
+  if (substring ("pcrs", arg) <= 0) {
+    print_pcrs();
+    return 0;
+  }
+  if (substring ("eventlog", arg) <= 0) {
+    print_eventlog();
+    return 0;
+  }
+  if (substring ("test", arg) <= 0) {
+    arg = arg + 4;
+    arg = skip_to(0, arg);
+    if (substring ("--format=1", arg) <= 0)
+      ima_diagnosis(1);
+    else
+      ima_diagnosis(2);
+    return 0;
+  }
+  if (substring ("disable", arg) <= 0) {
+    ima_disable=1;
+    return 0;
+  }
+  if (substring ("debug", arg) <= 0) {
+    ima_debug=1;
+    return 0;
+  }
+  if (substring ("benchmark", arg) <= 0) {
+    ima_benchmark=1;
+    return 0;
+  }
+  if (substring ("normal", arg) <= 0) {
+    ima_disable=0;
+    ima_benchmark=0;
+    ima_debug=0;
+    ima_measure_gziped_file=1;
+    ima_limit_pcrusage=0;
+    return 0;
+  }
+  if (substring ("fastboot", arg) <= 0) {
+    ima_measure_gziped_file=0;
+    return 0;
+  }
+  if (substring ("limit", arg) <= 0) {
+    ima_limit_pcrusage=1;
+    return 0;
+  }
+
+ usage:
+  grub_printf("GRUB %s with Transitive Trust Support (patch version : %s)\n",version_string, IMA_VERSION); // TODO
+  grub_printf("Usage:\n");
+  grub_printf("  tpm pcrs     : show PCR value\n");
+  grub_printf("  tpm eventlog : show eventlog\n");
+  grub_printf("  tpm test --format=n  : \n");
+  grub_printf("     conformance test of BIOS 1Ah calls\n");
+  grub_printf("      n: TCG_HashLogExtendEvent format, select 1 or 2(default)\n");
+  grub_printf("  tpm limit : \n");
+  grub_printf("     if this BIOS does not allow to use PCR 8 and over,\n");
+  grub_printf("     substitute PCR7 for them\n");
+  grub_printf("  tpm [debug|benchmark|disable|fastboot|normal] : \n");
+  grub_printf("     additional diagnostic mode for expert\n");
+  grub_printf("Current opration mode:\n");
+  grub_printf("    measure mode: %d (format used by TCG_HashLogExtendEvent)\n",ima_measure_mode);
+  grub_printf("    limit       : %d (limit PCR usage)\n",ima_limit_pcrusage);
+  grub_printf("    debug       : %d (show verbose messages)\n",ima_debug);
+  grub_printf("    disable     : %d (disable measurement)\n",ima_disable);
+  grub_printf("    benchmark   : %d (show elapsed time)\n",ima_benchmark);
+  grub_printf("    fastboot    : %d (fast measure of gziped file)\n",ima_measure_gziped_file);
+  grub_printf("Default assignment of pcr index and eventtype:\n");
+#ifdef ENABLE_IMA
+  grub_printf("  stage 1     :  %d   %d\n",IMA_EV_GRUB_STAGE1_PCR,IMA_EV_GRUB_STAGE1_TYPE);
+  grub_printf("  stage 1.5   :  %d   %d\n",IMA_EV_GRUB_STAGE15_PCR,IMA_EV_GRUB_STAGE15_TYPE);
+  grub_printf("  stage 2     :  %d   %d\n",IMA_EV_GRUB_STAGE2_PCR,IMA_EV_GRUB_STAGE2_TYPE);
+  grub_printf("  grub.conf   :  %d   %d\n",IMA_EV_GRUB_CONFIG_PCR,IMA_EV_GRUB_CONFIG_TYPE);
+#endif /* ENABLE_IMA */
+  grub_printf("  file*       :  %d   %d\n",IMA_EV_GRUB_FILE_PCR,IMA_EV_GRUB_FILE_TYPE);
+  grub_printf("  file(decomp):  %d   %d\n",IMA_EV_GRUB_FILE_PCR,IMA_EV_GRUB_FILE_DECOMP_TYPE);
+  grub_printf("  kernel cmd  :  %d   %d\n",IMA_EV_GRUB_CMD_PCR,IMA_EV_GRUB_CMD_TYPE);
+  grub_printf("  action      :  %d   %d\n",IMA_EV_GRUB_ACTION_PCR,IMA_EV_GRUB_ACTION_TYPE);
+  grub_printf("   *configuable\n");
+
+  return (0);
+}
+
+static struct builtin builtin_tpm =
+{
+  "tpm",
+  tpm_func,
+  BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
+  "tpm [pcrs|eventlog|test [--format=n]]",
+  "Diagnostic tool for TPM and Transtive Trust Support"
+};
+#endif /* TRANSITIVE_TRUST */
   
 
 /* The table of builtin commands. Sorted in dictionary order.  */
@@ -5197,6 +5575,9 @@
 #ifdef USE_MD5_PASSWORDS
   &builtin_md5crypt,
 #endif /* USE_MD5_PASSWORDS */
+#ifdef TRANSITIVE_TRUST
+  &builtin_measure, /* new */
+#endif /* TRANSITIVE_TRUST */
 #ifndef PLATFORM_EFI
   &builtin_module,
   &builtin_modulenounzip,
@@ -5242,6 +5623,9 @@
 #endif /* SUPPORT_NETBOOT */
   &builtin_timeout,
   &builtin_title,
+#ifdef TRANSITIVE_TRUST
+  &builtin_tpm,
+#endif /* TRANSITIVE_TRUST */
   &builtin_unhide,
 #ifndef PLATFORM_EFI
   &builtin_uppermem,
--- grub-0.97-orig/stage2/shared.h	2009-05-01 19:28:18.000000000 +0900
+++ grub-0.97-ima/stage2/shared.h	2009-05-01 16:18:11.000000000 +0900
@@ -379,6 +379,14 @@
 #define strtok_r grub_strtok_r
 #endif /* WITHOUT_LIBC_STUBS */
 
+#if defined(ENABLE_IMA) || (!defined(STAGE1_5)&&defined(IMA_TEST))
+#define TRANSITIVE_TRUST 1 /* for ASM code region */
+#include "ima.h"
+#endif // TRANSITIVE_TRUST
+#if defined(IMA_TEST)
+#define ENABLE_IMA_STEPBYSTEP
+#endif // IMA_TEST
+
 #ifndef ASM_FILE
 /*
  *  Below this should be ONLY defines and other constructs for C code.
@@ -1025,6 +1032,147 @@
 int grub_load_linux (char *kernel, char *arg);
 int grub_load_initrd (char *initrd);
 int grub_chainloader (char *filename);
+
+#if defined(ENABLE_IMA) || (!defined(STAGE1_5)&&defined(IMA_TEST))
+#define TRANSITIVE_TRUST 1 /* for C code region */
+
+/* TCG BIOS Return Code (spec v1.2, 12.3, p84) */
+#define TCG_PC_OK          0x0000
+#define TCG_PC_TPMERROR    0x0001
+#define TCG_PC_LOGOVERFLOW 0x0002
+#define TCG_PC_UNSUPPORTED 0x0003
+
+/* TCG BIOS Return Code (spec v1.2, 13, p96) */
+#define TCG_OK          0x00
+#define TPM_RET_BASE    0x01
+#define TCG_GENERAL_ERROR    TPM_RET_BASE + 0x00
+#define TCG_TPM_IS_LOCKED    TPM_RET_BASE + 0x01
+
+
+#if !defined(IMA_VERSION)
+#define IMA_VERSION "1.1.0.0"
+#endif
+
+#define IMA_EV_GRUB_ACTION_PASSWORD_PROTECTION     "Password Protection"
+#define IMA_EV_GRUB_ACTION_PASSWORD_PROTECTION_MD5 "Password Protection using MD5"
+#define IMA_EV_GRUB_ACTION_PASSWORD_ENTER      "Password Entered"
+#define IMA_EV_GRUB_ACTION_PASSWORD_FAILURE    "Password Failure"
+#define IMA_EV_GRUB_ACTION_USER_INTERVENTION   "Boot Sequance User Intervention"
+#define IMA_EV_GRUB_ACTION_EVENT_SEPARATOR     "Grub Event Separator"
+#define IMA_EV_GRUB_ACTION_OS_EVENT_SEPARATOR  "OS Event Separator"
+
+
+/* ima.c */
+extern int ima_disable;
+extern int ima_debug;
+extern unsigned char *ima_workbuf;
+extern int ima_benchmark;
+extern int ima_measurefile;
+extern int ima_measure_mode;
+extern int ima_grub_pcr_index;
+extern int ima_grub_eventtype;
+extern char *ima_grub_log; /* TBD */
+extern int ima_limit_pcrusage;
+
+extern int ima_measure_gziped_file;
+
+/* ima.h */
+extern char *ima_password_protection;
+extern char *ima_password_protection_md5;
+extern char *ima_password_enter;
+extern char *ima_password_failure;
+extern char *ima_user_intervention;
+extern char *ima_grub_separator;
+extern char *ima_os_separator;
+
+extern int ima_user_intervention_state;
+
+/* asm.S */
+int TCG_StatusCheck(unsigned char *major,
+		     unsigned char *minor,
+		     unsigned char **event_log);
+int TCG_HashLogExtendEventF1(int pcr_index,
+			     int hashdatasize,
+			     unsigned char *hashdeta,
+			     int logdatasize,
+			     unsigned char *logdeta);
+int TCG_HashLogExtendEventF2(int pcr_index,
+			     int hashdatasize,
+			     unsigned char *hashdeta,
+			     int logdatasize,
+			     unsigned char *logdeta);
+/* TCG_PassThroughToTPM  */
+int ima_extend(int pcr_index, unsigned char *digest,
+                   unsigned char *pcr_value);
+int ima_pcr_read(int pcr_index, unsigned char *pcr_value);
+int TCG_LogExtend(int pcr_index,
+		  int type,
+		  int logdatasize,
+		  unsigned char *logdata);
+int TCG_HashAll(int data_len, unsigned char *data, unsigned char *digest);
+int TCG_CompactHashLogExtendEvent(int pcr_index,
+				  int hashdatasize,
+				  unsigned char *hashdeta);
+
+/* ima.c */
+int ima_status(unsigned char **addr);
+int measure_eventdata(int pcr_index,
+		      int eventtype,
+		      int eventsize,
+		      unsigned char * eventdata);
+int measure_file(char *filename,
+		 int pcr_index,
+		 int eventtype);
+int measure_file_as_event(char *filename,
+		  int pcr_index,
+		  int eventtype);
+int measure_mem(int len,
+		unsigned char *addr,
+		int pcr_index,
+		int eventtype,
+		char* eventdata);
+
+int ima_start_os_measurement(void);
+int ima_final(char *msg);
+
+int print_digest (unsigned char *digest, int len);
+int print_u32 (unsigned int in);
+int print_rc (char* msg, unsigned int in);
+int print_pcrs(void);
+int print_eventlog(void);
+
+int ima_diagnosis (int format);
+
+#define SHA1_DIGEST_SIZE 20
+// #define TCG_EVENT_SIZE 512 /* for MBR */
+
+typedef struct tdTCG_PCR_EVENT
+{
+  unsigned int pcrIndex;
+  unsigned int eventType;
+  unsigned char digest[SHA1_DIGEST_SIZE];
+  unsigned int eventDataSize;
+  unsigned char event[0];
+} TCG_PCR_EVENT;
+/* 4 + 4 + 20 + 4 + n = 32+n */
+
+#define TCG_PCR_EVENT_BASE_SIZE 32
+
+
+typedef struct {
+    unsigned int    eventID;
+    unsigned int    eventDataSize;
+    /* (eventDataSize) bytes of event data follows */
+} PC_SPECIFIC_EVENT;
+
+
+typedef struct {
+    unsigned int    filenameSize;
+    unsigned int    filedataSize;
+    unsigned char   data[0];
+    /* (filenameSize + filedataSize) bytes of filedata follows */
+} GRUB_SPECIFIC_EVENT;
+#endif /* ENABLE_IMA */ 
 #endif /* ASM_FILE */
 
 #endif /* ! GRUB_SHARED_HEADER */
--- grub-0.97-orig/stage2/start.S	2009-05-01 19:28:18.000000000 +0900
+++ grub-0.97-ima/stage2/start.S	2009-05-01 15:56:46.000000000 +0900
@@ -89,11 +89,13 @@
 	je	bootit
 
 setup_sectors:	
+#ifndef ENABLE_IMA
 	/* check if we use LBA or CHS */
 	cmpb	$0, -1(%si)
 
 	/* jump to chs_mode if zero */
 	je	chs_mode
+#endif /* !ENABLE_IMA */
 
 lba_mode:	
 	/* load logical sector start */
@@ -161,6 +163,7 @@
 	jc	read_error
 
 	movw	$BUFFERSEG, %bx
+#ifndef ENABLE_IMA
 	jmp	copy_buffer
 			
 chs_mode:	
@@ -260,7 +263,8 @@
 
 	/* save source segment */
 	movw	%es, %bx
-	
+#endif /* !ENABLE_IMA */
+
 copy_buffer:	
 
 	/* load addresses for copy from disk buffer to destination */
@@ -287,6 +291,14 @@
 	xorw	%si, %si	/* zero offset of source addresses */
 	movw	%bx, %ds	/* restore the source segment */
 
+#ifdef  ENABLE_IMA
+	/*
+	 * ds:si = buffer address
+	 * cx : size
+	 */
+	call    tcg_measure
+#endif
+
 	cld		/* sets the copy direction to forward */
 
 	/* perform copy */
@@ -316,7 +328,11 @@
 	VMSG(notification_done)
 	popw	%dx	/* this makes sure %dl is our "boot" drive */
 #ifdef STAGE1_5
+#ifdef IMA_INFRA_MODE
+	ljmp	$0, $0x2270
+#else /* ! IMA_INFRA_MODE */
 	ljmp	$0, $0x2200
+#endif /* IMA_INFRA_MODE */
 #else /* ! STAGE1_5 */
 	ljmp	$0, $0x8200
 #endif /* ! STAGE1_5 */
@@ -342,18 +358,256 @@
 stop:	jmp	stop
 
 #ifdef STAGE1_5
+#ifdef ENABLE_IMA
+/* set version here to see the IMA version and also generate unique digest */
+notification_string:	.string "Loading stage1.5(ima1100)"
+#else
 notification_string:	.string "Loading stage1.5"
+#endif /* ENABLE_IMA */
 #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 ENABLE_IMA
+ima_debug_string:	.string "<T>"
+/*
+ * ds:si = buffer address
+ * cx    = size
+ */
+tcg_measure:
+	pushal
+	push    %ds
+	push    %es
+
+#ifdef IMA_USE_HLEE_F2
+/*
+ * set datasize
+ */
+	movw    %ds, %di
+	xorw    %ax, %ax		/* ax =0 */
+	movw    %ax, %ds		/* ds =0 */
+	movw    %ax, %es		/* es =0 */
+	movzx   %si, %esi
+	movzx   %di, %edi
+	shll    $4,  %edi
+	addl    %edi,%esi		/* esi= (32-bit phisical address) */
+
+	// NG movw	%cx, ABS(hlee_ipb_datasize)
+	movw    $ABS(hlee_ipb), %di	/* ES:DI = IPB */
+	movl    %esi, 4(%di)		/* HashDataPtr */
+	movw    %cx,  8(%di)		/* HashDataLen */
+
+/*
+ * BIOS call "INT 1Ah, (AH)=BBh,(AL)=00h" TCG_StatusCheck
+ *	Call with
+ *	  %ah = 0xBB
+ *			%al = 0x00
+ *	Return:
+ *			%eax = TCG_STATUS
+ *			%ebx = 'TCPA'
+ *
+ * Ref:
+ *  TCG PC Client Specific Implementation Specification for Conventional BIOS v1.2,
+ *  Section 12.5 (page 85)
+ */
+tcg_statuscheck:
+	movw    $0xbb00, %ax		/* TCG_LogEvent */
+	int     $0x1a
+	test	%eax, %eax
+	jnz	tcg_goback
+/*
+ * BIOS call "INT 1Ah, (AH)=BBh,(AL)=01h" TCG_HashLogExtendEvent
+ *	Call with
+ *          %ah = 0xBB
+ *			%al = 0x01
+ *			%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 Client Specific Implementation Specification for Conventional BIOS v1.2,
+ *  Section 12.6 (page 86)
+ *
+ */
+tcg_hashlogextendevent:
+	/* Setup IPB */
+
+	movw    $ABS(hlee_ipb), %di	/* ES:DI = IPB */
+#ifdef IMA_INFRA_MODE
+	/* Fix the size */
+	addl	$0x70, 4(%di)		/* HashDataPtr + 0x70 */
+	subl    $0x70, 8(%di)		/* HashDataLen - 0x70 */
+	//subl    $0x70, ABS(hlee_ipb_datasize)
+#endif
+	/* Call */
+	movw    $0xbb01, %ax		/* TCG_LogEvent */
+	movw	$0x2E00, %si		/* OPB OK */
+	xorl    %ecx, %ecx		/* ECX = 0 */
+	xorl    %edx, %edx		/* EDX = 0 */
+	int     $0x1a
+
+
+#ifndef IMA_IGNORE_BIOS_RC3
+	test	%eax, %eax
+	jz	tcg_end
+tcg_error:
+	MSG(tcg_error_string)
+#endif /*  IMA_IGNORE_BIOS_RC3 */
+
+#else /* IMA_USE_HLEE_F2 */
+/*
+ * 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) */
+
+	/* Setup IPB */
+	movw    $ABS(ha_ipb), %di	/* di=IPB */
+	movl    %esi, 4(%di)		/* HashDataPtr */
+	movw    %cx,  8(%di)		/* HashDataLen */
+#ifdef IMA_INFRA_MODE
+	/* Fix the size */
+	addl	$0x70, 4(%di)		/* HashDataPtr + 0x70 */
+	subl    $0x70, 8(%di)		/* HashDataLen - 0x70 */
+#endif
+
+	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
+	*/
+
+#ifndef IMA_IGNORE_BIOS_RC3 /* for DEBUG. Skip LogEvent */
+	test	%eax, %eax
+	jnz	tcg_goback
+#endif /* IMA_IGNORE_BIOS_RC3 */
+
+
+/*
+ * 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
+#endif /* IMA_USE_HLEE_F2 */
+tcg_goback:
+	pop     %es
+	pop     %ds
+	popal
+	ret
+
+#ifdef IMA_USE_HLEE_F2
+/* TCG_HashLogExtendEvent Input Parameter Block Format 2. p88 Table 15 */
+hlee_ipb:
+	.word   (hlee_ipb_end - hlee_ipb)	/*  0 block size   */
+	.word   0				/*  2 reserved     */
+//	.long   0x00070070			/*  4 data pointer */
+#ifdef IMA_INFRA_MODE
+	.long   BUFFERSEG * 0x10 + 0x70		/*  4 data pointer */
+#else /* ! IMA_INFRA_MODE */
+	.long   BUFFERSEG * 0x10		/*  4 data pointer */
+#endif /* ! IMA_INFRA_MODE */
+hlee_ipb_datasize:
+	.long   0x00002190			/*  8 data size   TODO  */
+	.long   IMA_EV_GRUB_STAGE15FS_PCR	/*  C PCR index    */
+	.long	0				/* 10 event type	*/
+	.long   ABS(tcg_pcr_event)		/* 14 log pointer  */
+	.long   32				/* 18 log size     */
+hlee_ipb_end:
+#else /* IMA_USE_HLEE_F2 */
+/* HashAll Input Parameter Block (16-bytes) p49 */
+ha_ipb:
+	.word   (ha_ipb_end - ha_ipb)	/* 0 block size   */
+	.word   0                       /* 2 reserved     */
+	.long   0                       /* 4 data pointer */
+	.long   0x200                   /* 8 data size =512 (def)   */
+	.long   4                       /* C Algorithm id = TCG_ALG_SHA = 4 */
+ha_ipb_end:
+
+/* LogEvent Input Parameter Block (28-bytes) p47 */
+le_ipb:
+	.word   (le_ipb_end - le_ipb)	 /*  0 block size   */
+	.word   0                        /*  2 reserved     */
+	.long   0                        /*  4 data pointer */
+	.long   0                        /*  8 data size    */
+	.long   IMA_EV_GRUB_STAGE15FS_PCR  /*  C PCR index    */
+	.long	IMA_EV_GRUB_STAGE15FS_TYPE /* 10 event type	*/
+	.long   ABS(tcg_pcr_event)       /* 14 log pointer  */
+	.long   32                       /* 18 log size     */
+le_ipb_end:
+#endif /* IMA_USE_HLEE_F2 */
+
+/* TCG_PCR_EVENT data structure 32-bytes */
+tcg_pcr_event: /* 32 bytes */
+	.long   IMA_EV_GRUB_STAGE15FS_PCR          /* PCR index    */
+tcg_pcr_event_type:
+	.long   IMA_EV_GRUB_STAGE15FS_TYPE         /* event type   */
+/* HashAll Output Parameter Block (20-bytes) p49 */
+tpe_pcrvalue:
+	.space  20                      /* PCR value    */
+	.long   0                       /* event size   */
+tcg_sig:
+        .string "TCPA" /* */
+#if 0
+tcg_memo:
+        .long 0
+tcg_memo_len:
+        .long 0
+#endif // 0
+#endif /* ENABLE_IMA */
+
 /*
  * message: write the string pointed to by %si
  *
--- grub-0.97-orig/stage2/stage1_5.c	2009-05-01 19:28:18.000000000 +0900
+++ grub-0.97-ima/stage2/stage1_5.c	2009-05-01 16:20:04.000000000 +0900
@@ -31,7 +31,11 @@
 cmain (void)
 {
   if (0)
+#ifdef ENABLE_IMA
+    grub_printf ("\n\nGRUB loading (Stage2 w/ Transitive Trust), please wait...\n");
+#else
     grub_printf ("\n\nGRUB loading, please wait...\n");
+#endif /* TCG*/
 
   /*
    *  Here load the true second-stage boot-loader.
@@ -48,7 +52,7 @@
       /* Sanity check: catch an internal error.  */
       if (saved_sector == -1)
 	{
-	  grub_printf ("internal error: the second sector of Stage 2 is unknown.");
+	  grub_printf ("internal error: the second sector of Stage 2 is unknown. 0816");
 	  stop ();
 	}
       
@@ -56,8 +60,78 @@
       
       grub_close ();
 
+#ifdef IMA_TEST
+      grub_printf("stage1_5.c measure (file = %s)\n",config_file);
+#endif
+#ifdef ENABLE_IMA
+      if (ret) {
+#if 1
+	unsigned char major,minor;
+	//int major,minor;
+	int rc;
+	// if (TCG_StatusCheck(&major,&minor,NULL)>0) {
+	if (TCG_StatusCheck(&major,&minor,NULL)==0) { /* OK if rc==0 */
+	  TCG_PCR_EVENT logdata;
+	  int i;
+#ifdef IMA_USE_HLEE_F2
+	  logdata.pcrIndex  = IMA_EV_GRUB_STAGE2_PCR;
+	  logdata.eventType = IMA_EV_GRUB_STAGE2_TYPE;
+	  logdata.eventDataSize = 0; /* no eventdata - TODO */
+	  rc = TCG_HashLogExtendEventF2(
+				 IMA_EV_GRUB_STAGE2_PCR,
+				 SECTOR_SIZE * 2 + ret,
+			     (char*)0x8000,
+			     TCG_PCR_EVENT_BASE_SIZE,
+			     (unsigned char *)&logdata);
+#else /* IMA_USE_HLEE_F2 */
+	  rc = TCG_HashAll( SECTOR_SIZE * 2 + ret,
+			     (char*)0x8000,
+			     logdata.digest);
+	  grub_printf("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,",logdata.digest[i]);
+	  //grub_printf("\n");
+
+	  logdata.pcrIndex  = IMA_EV_GRUB_STAGE2_PCR;
+	  logdata.eventType = IMA_EV_GRUB_STAGE2_TYPE;
+	  logdata.eventDataSize = 0; /* no eventdata - TODO */
+	  rc = TCG_LogExtend(IMA_EV_GRUB_STAGE2_PCR,
+			     IMA_EV_GRUB_STAGE2_TYPE,
+			     TCG_PCR_EVENT_BASE_SIZE,
+			     (unsigned char *)&logdata);
+#endif /* IMA_USE_HLEE_F2 */
+
+	}
+
+#else
+          /* If stage2 was loaded and TCG BIOS presents */
+          if (!ima_status_check( NULL ))
+            {
+              unsigned char sha1_hash[SHA1_DIGEST_SIZE];
+              int retcode,i;
+
+              /* Get SHA-1 hash of stage2 */
+              retcode = ima_hash_all( SECTOR_SIZE * 2 + ret,
+				      (char*)0x8000,
+				      sha1_hash);
+              grub_printf("Measureing stage2. - (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 = ima_log_extend(TCG_GRUB_PCR_INDEX, sha1_hash);
+              grub_printf("PCR%u was Extended\n",TCG_GRUB_PCR_INDEX);
+
+            }
+#endif /* 1 */
+	chain_stage2 (0, 0x8200, saved_sector);
+      }
+#else
       if (ret)
 	chain_stage2 (0, 0x8200, saved_sector);
+#endif
+
     }
 
   /*
--- grub-0.97-orig/stage2/stage2.c	2009-05-01 19:28:18.000000000 +0900
+++ grub-0.97-ima/stage2/stage2.c	2009-05-01 15:56:46.000000000 +0900
@@ -581,6 +581,18 @@
 		break;
 	    }
 
+#ifdef ENABLE_IMA
+          if (ima_user_intervention_state==0)
+            {
+              /* extend 1st intervention only */
+              measure_eventdata(IMA_EV_GRUB_ACTION_PCR,
+                                IMA_EV_GRUB_ACTION_TYPE,
+                                grub_strlen(ima_user_intervention),
+                                ima_user_intervention);
+              ima_user_intervention_state=1;
+            }
+#endif /* ENABLE_IMA */
+
 	  if (! auth && password)
 	    {
 	      if (c == 'p')
@@ -1015,6 +1027,15 @@
 	      is_opened = is_preset = open_preset_menu ();
 	      if (! is_opened)
 		{
+#ifdef IMA_TEST
+		  printf("stage2.c measure grub.conf\n");
+#endif
+#ifdef ENABLE_IMA
+			ima_start_os_measurement();
+			measure_file(config_file,
+				IMA_EV_GRUB_CONFIG_PCR,
+				IMA_EV_GRUB_CONFIG_TYPE);
+#endif /* ENABLE_IMA */
 		  is_opened = grub_open (config_file);
 		  errnum = ERR_NONE;
 		}
--- grub-0.97-orig/stage2/ima.h	1970-01-01 09:00:00.000000000 +0900
+++ grub-0.97-ima/stage2/ima.h	2009-05-01 15:56:46.000000000 +0900
@@ -0,0 +1,79 @@
+
+#ifndef __IMA_H
+#define __IMA_H
+
+/*
+ * PCR index & event type assignment
+ *
+ * EventType to identify the components in Grub (TBD)
+ *
+ *    bit
+ *   --------------------------------
+ *    8-15  Used by GRUB
+ *    0- 7  defined by TCG PC Spec
+ *   --------------------------------
+ *
+ * Ref: PC Spec v1.2 rev.1, Table 11 in page 76
+ *
+ */
+/* Stage1 is measured by BIOS, this assigment does not work for.. but  */
+#define IMA_EV_GRUB_STAGE1_PCR       0x04
+#define IMA_EV_GRUB_STAGE1_TYPE           0x0D /* 0x0Dh: v1.2 */
+
+#define IMA_EV_GRUB_STAGE15_PCR      0x04
+#define IMA_EV_GRUB_STAGE15_TYPE          0x0D
+
+#define IMA_EV_GRUB_STAGE15FS_PCR    0x04
+#define IMA_EV_GRUB_STAGE15FS_TYPE        0x0D
+
+#define IMA_EV_GRUB_STAGE2_PCR       0x04
+#define IMA_EV_GRUB_STAGE2_TYPE           0x0D
+
+#define IMA_EV_GRUB_MBR_PCR          0x04
+#define IMA_EV_GRUB_MBR_TYPE              0x06    // as part of PC Specific event
+#define IMA_EV_GRUB_MBR_PCTYPE            0x21    // TODO
+
+#define IMA_EV_GRUB_CONFIG_PCR       0x05
+#define IMA_EV_GRUB_CONFIG_TYPE           0x0E
+
+#define IMA_EV_GRUB_CMD_PCR          0x05
+#define IMA_EV_GRUB_CMD_TYPE              0x05
+
+#define IMA_EV_GRUB_ACTION_PCR       0x05
+#define IMA_EV_GRUB_ACTION_TYPE           0x05
+
+#define IMA_EV_GRUB_SEPARATOR_TYPE        0x04
+
+/* TODO changed by user*/
+
+#define IMA_EV_GRUB_BOOT_MSG_PCR     0x08
+#define IMA_EV_GRUB_BOOT_MSG_TYPE         0x1005
+
+#define IMA_EV_GRUB_FILE_PCR         0x08
+#define IMA_EV_GRUB_FILE_TYPE             0x1505
+#define IMA_EV_GRUB_FILE_DECOMP_TYPE      0x1605
+
+#define IMA_EV_GRUB_FILEDATA_PCR     0x08
+#define IMA_EV_GRUB_FILEDATA_TYPE         0x1700
+
+#define IMA_EV_GRUB_KERNEL_CMD_PCR   0x05
+#define IMA_EV_GRUB_KERNEL_CMD_TYPE       0x1105
+
+#define IMA_EV_GRUB_KERNEL_PCR       0x08
+#define IMA_EV_GRUB_KERNEL_TYPE           0x1205
+
+#define IMA_EV_GRUB_INITRD_PCR       0x08
+#define IMA_EV_GRUB_INITRD_TYPE           0x1305
+
+#define IMA_EV_GRUB_MODULE_PCR       0x08
+#define IMA_EV_GRUB_MODULE_TYPE           0x1405
+
+#define IMA_EV_GRUB_MODULE_CMD_PCR   0x05
+#define IMA_EV_GRUB_MODULE_CMD_TYPE       0x1505
+
+
+//#define TCG_EVENTDATA_SIZE  128
+#define TCG_EVENTDATA_SIZE  1024
+
+
+#endif /* __IMA_H */
--- grub-0.97-orig/stage2/ima.c	1970-01-01 09:00:00.000000000 +0900
+++ grub-0.97-ima/stage2/ima.c	2009-05-01 15:56:46.000000000 +0900
@@ -0,0 +1,1453 @@
+/*
+
+ Transitive Trust Functions
+
+ 2007-01-29 S.Munetoh update for Xen
+ 2006-08-15 S.Munetoh functions moved from boot.c
+
+ */
+
+#include "shared.h"
+
+#ifdef TRANSITIVE_TRUST
+
+inline unsigned long long int rdtsc(void);
+int ima_hlee_select(
+        int eventsize,
+        unsigned char * eventdata,
+        int logdatasize,
+        TCG_PCR_EVENT *logdata);
+int print_pcrs(void);
+int print_eventlog(void);
+int get_last_event(unsigned char *digest);
+int verify_extend(
+        int pcr_index,
+        unsigned char *pcr_value,
+        unsigned char *digest,
+        int option);
+int ima_print_digest2(
+        char *msg1, unsigned char *digest1,
+        char *msg2, unsigned char *digest2);
+
+static unsigned long long int ima_benchmark_rdtsc; /* start ticks */
+
+#define TCG_PCR_EVENT_DATA_SIZE 128
+static unsigned char tcg_event_buf[TCG_PCR_EVENT_BASE_SIZE+TCG_PCR_EVENT_DATA_SIZE];
+
+
+/* TDOD really need them? */
+int ima_grub_pcr_index = -1;
+int ima_grub_eventtype = IMA_EV_GRUB_FILE_TYPE;
+char *ima_grub_log; /**/
+
+int ima_disable = 0; /* for DEBUG */
+#ifdef IMA_TEST
+int ima_debug = 1; /* for DEBUG */
+#else
+int ima_debug = 0; /* normal op */
+#endif
+
+//unsigned int tcg_buffer = 0x100000; /* TODO */
+unsigned char * ima_workbuf = (unsigned char *) 0x100000; /* default, this will be overwrited by kernel image */
+int ima_benchmark=0; /* benchmark */
+int ima_measurefile=1; /* 1:measure file 0:measure memory*/
+int ima_limit_pcrusage=0; /* 1: limit pcrusage, substitute PCR7 for PCR 8 and above*/
+
+int ima_measure_gziped_file=1; /* 1:measure file 0:measure memory*/
+
+#ifdef IMA_USE_HLEE_F2
+int ima_measure_mode=2;
+#else/* IMA_USE_HLEE_F2 */
+int ima_measure_mode=1;
+#endif /* IMA_USE_HLEE_F2 */
+
+int ima_grub_pcr_usage[24]; // TODO fixed value, 24
+
+static char *err_no_tcg = " BIOS does not suppot TCG APIs.\n";
+
+char *ima_password_protection     = IMA_EV_GRUB_ACTION_PASSWORD_PROTECTION;
+char *ima_password_protection_md5 = IMA_EV_GRUB_ACTION_PASSWORD_PROTECTION_MD5;
+
+char *ima_password_enter      = IMA_EV_GRUB_ACTION_PASSWORD_ENTER;
+char *ima_password_failure    = IMA_EV_GRUB_ACTION_PASSWORD_FAILURE;
+char *ima_user_intervention   = IMA_EV_GRUB_ACTION_USER_INTERVENTION;
+
+char *ima_grub_separator      = IMA_EV_GRUB_ACTION_EVENT_SEPARATOR;
+char *ima_os_separator        = IMA_EV_GRUB_ACTION_OS_EVENT_SEPARATOR;
+
+int ima_user_intervention_state = 0; /* 0:no -(extend)-> 1:yes */
+
+/* TODO to be simple*/
+static int
+print_hex (unsigned char hex)
+{
+    unsigned char l = 0x0F & hex;
+    unsigned char u = hex>>4;
+    if (u>=10) grub_printf("%c",u+55);
+    else grub_printf("%d",u);
+    if (l>=10) grub_printf("%c",l+55);
+    else grub_printf("%d",l);
+    return 0;
+}
+
+int
+print_digest (unsigned char *digest, int len)
+{
+    int i;
+    for (i=0;i<len;i++) {
+	print_hex(digest[i]);
+    }
+    return 0;
+}
+
+int
+print_u32 (unsigned int in)
+{
+    print_hex(0xff & in>>24);
+    print_hex(0xff & in>>16);
+    print_hex(0xff & in>>8);
+    print_hex(0xff & in);
+    return 0;
+}
+
+int
+print_rc (char *msg, unsigned int in)
+{
+    grub_printf("%s rc = 0x",msg);
+    print_u32(in);
+    grub_printf("\n"); /* TODO add error msg */
+    return 0;
+}
+
+inline unsigned long long int rdtsc(void) {
+	unsigned long long int t;
+	__asm__(".byte 0x0f,0x31" : "=A" (t));
+	return t;
+}
+
+/*
+ check tcg status
+ return:
+ 0x0000 : N/A
+ 0x0101 : OK v 1.1
+ 0x0102 : OK v 1.2
+
+ TODO
+ - Answer ipb format of HashLogExtendEvent, Format 1 or Format2
+
+ */
+
+#define TCG_V11 0x0101
+#define TCG_V12 0x0102
+
+int ima_status(unsigned char **addr)
+{
+	int rc=0;
+	unsigned char major;
+	unsigned char minor;
+	unsigned char *log_addr;
+
+	rc = TCG_StatusCheck(
+			&major,
+			&minor,
+			&log_addr );
+
+	if (rc!=0){ /* TODO is this work for non-TCG BIOS? */
+		grub_printf (err_no_tcg);
+		/* disable TCG*/
+		if (ima_debug==0) ima_disable=1;
+		return 0;
+	}
+
+	if (addr != NULL)
+		*addr = log_addr;
+
+	/* Check the BIOS TCG Version */
+	if ((major==1) && (minor==0))
+		return TCG_V11;
+
+	if ((major==1) && (minor==2))
+		return TCG_V12;
+
+	return 0;
+}
+
+/*
+ * BIOS Call for measurement
+ * Due to the ambiguous specification, we may have four options:-(
+ * ima_measure_mode
+ * 0 : HashAll + LogExtend default
+ * 1 : HashLogExtendEvent Format1(N/G for old IBM BIOS)
+ * 2 : HashLogExtendEvent Format2IMA_USE_HLEE_F2
+ * 3 : CompactHashLogExtendEvent (TBD)
+ */
+
+int ima_hlee_select(
+	int eventsize,
+	unsigned char * eventdata,
+	int logdatasize,
+	TCG_PCR_EVENT *logdata) {
+	int rc=0;
+
+	if (ima_limit_pcrusage==1) {
+		if (logdata->pcrIndex>7) {
+			logdata->pcrIndex = 7;
+		}
+	}
+
+	if (ima_measure_mode == 2) { // HLEE
+		rc = TCG_HashLogExtendEventF2(
+				logdata->pcrIndex,
+				eventsize,
+				eventdata,
+				logdatasize,
+				(unsigned char*)logdata);
+	} else {
+		/* Hash the file image */
+		rc = TCG_HashAll(
+				eventsize,
+				eventdata,
+				logdata->digest);
+		/* TODO check rc */
+		rc = TCG_LogExtend(
+				logdata->pcrIndex,
+				logdata->eventType,
+				logdatasize,
+				(unsigned char *)logdata);
+	}
+	return rc;
+}
+
+
+/*
+ *  measure & extend the eventdata
+ *
+ *    PCRn       = SHA1(PCRn-1 + eventdata)
+ *    event data = eventdata
+ *
+ *   2006-06-09 SM new
+ */
+int
+measure_eventdata (
+	int pcr_index,
+	int eventtype,
+	int eventsize,
+	unsigned char * eventdata)
+{
+	int rc=0;
+	TCG_PCR_EVENT *logdata;
+	int logdatasize;
+
+	if (ima_disable) return -1;
+
+	if (eventsize == 0) {
+		grub_printf("measure_eventdata: eventsize == 0 ??\n");
+		return -1;
+	}
+
+
+	if (eventsize > TCG_PCR_EVENT_DATA_SIZE) {
+	    logdata = (TCG_PCR_EVENT *) ima_workbuf; // TODO halt if assigned buffer is wrong
+	} else {
+	    logdata = (TCG_PCR_EVENT *) tcg_event_buf;
+	}
+
+	if (ima_status(NULL)) {
+		if (ima_benchmark) {
+			ima_benchmark_rdtsc = rdtsc();
+		}
+
+		logdata->pcrIndex=pcr_index;
+		logdata->eventType=eventtype; /* TODO*/
+		logdata->eventDataSize=eventsize;
+		memcpy(logdata->event,eventdata,logdata->eventDataSize);
+		logdatasize = TCG_PCR_EVENT_BASE_SIZE + eventsize;
+
+		ima_grub_pcr_usage[pcr_index] ++; /* Check the PCR usage*/
+
+		/* Call */
+		rc = ima_hlee_select(
+			logdata->eventDataSize,
+			logdata->event,
+			logdatasize,
+			logdata);
+
+		if (ima_benchmark)
+			grub_printf("measure_eventdata: %d bytes - %d msec(@2GHzCPU)\n",
+				logdata->eventDataSize,
+				(rdtsc() - ima_benchmark_rdtsc)>>21);
+
+		if (ima_debug) {
+			grub_printf("measure_eventdata (using TCG_HashLogExtendEventF2 call)\n");
+			grub_printf("pcr=%d,type=%d,eventdatasize=%d(to be hashed)\n",
+				logdata->pcrIndex,
+				logdata->eventType,
+				logdata->eventDataSize);
+			grub_printf("\nPress any key to go next step....\n");
+			getkey ();
+		}
+		if (rc!=0) {
+			if (rc == 3) {
+				/* TODO IBM BIOS return 3 */
+			} else {
+				print_rc("Error ",rc);
+				grub_printf("measure_event (TCG_HashLogExtendEvent) was failed?\n");
+			}
+		}
+		return rc;
+	} else {
+		//grub_printf (err_no_tcg);
+		return -1;
+	}
+}
+
+
+/*
+ *  measure a file
+ *
+ *    PCRn       = SHA1(PCRn-1 + file image)
+ *    event data = file name
+ *
+ *    2006-06-18 SM new
+ */
+int
+measure_file (
+	char *filename,
+	int pcr_index,
+	int eventtype)
+{
+	int rc=0;
+	TCG_PCR_EVENT *logdata;
+	int logdatasize;
+	int eventdatasize;
+	unsigned char *buf;
+
+	if (ima_disable) return -1;
+
+	/* status check */
+	if (ima_status(NULL)) {
+
+		if (ima_benchmark) {
+			ima_benchmark_rdtsc = rdtsc();
+		}
+
+		logdata = (TCG_PCR_EVENT *)  ima_workbuf;
+		logdata->pcrIndex=pcr_index;
+		logdata->eventType=eventtype; /* TODO*/
+
+		/* eventdata: image-> name*/
+		/* nul terminate the filename (let use logdata->event as tmp buf)*/
+		memcpy(logdata->event,filename,grub_strlen(filename)+1);
+		nul_terminate (logdata->event);
+		logdata->eventDataSize = grub_strlen(logdata->event);
+		logdatasize = TCG_PCR_EVENT_BASE_SIZE+logdata->eventDataSize;
+
+		buf = (unsigned char *) ima_workbuf + logdatasize;
+
+		ima_grub_pcr_usage[pcr_index] ++; /* Check the PCR usage*/
+
+#ifndef NO_DECOMPRESSION
+		if (ima_measure_gziped_file == 1)
+		    no_decompression = 1;
+#endif
+		/* Open the file */
+		if (! grub_open (filename))
+			return errnum;
+
+		eventdatasize= grub_read(buf, -1);
+		grub_close ();
+
+#ifndef NO_DECOMPRESSION
+  no_decompression = 0;
+#endif
+		if (eventdatasize<0)
+			return -1;
+
+		if (ima_benchmark)
+			grub_printf("measure_file: %d bytes - %d msec(@2GHzCPU) - load file \n",
+					eventdatasize,
+					(rdtsc() - ima_benchmark_rdtsc)>>21);
+
+		/* Call */
+		 rc = ima_hlee_select(
+				eventdatasize,
+				buf,
+				logdatasize,
+				logdata);
+
+		if (ima_benchmark) {
+			grub_printf("measure_file: %d bytes - %d msec(@2GHzCPU) - HashAll+LogExtend\n",
+				eventdatasize,
+				(rdtsc() - ima_benchmark_rdtsc)>>21);
+		}
+
+		if (ima_debug) {
+			grub_printf("measure_file(pcr=%d,type=%d,size=%d,no_decomp=%d)\ndigest=",
+				logdata->pcrIndex,
+				logdata->eventType,
+				logdata->eventDataSize,
+				no_decompression);
+			print_digest(logdata->digest, 20);
+			grub_printf("\nPress any key to go next step....\n");
+			getkey ();
+		}
+
+
+		if (rc!=0) {
+			if (rc == 3) {
+				/* TODO IBM BIOS return 3 */
+			} else {
+				print_rc("Error ",rc);
+				grub_printf("measure_file (TCG_LogExtend) was failed?\n");
+			}
+		}
+		return rc;
+	} else {
+		//grub_printf (err_no_tcg);
+		return -1;
+	}
+}
+
+
+/*
+ *  measure a file (2)
+ *
+ *   PCRn       = SHA1(PCRn-1 + file image)
+ *   event data =
+ *     UINT32 filename size
+ *     BYTE*  filename
+ *     UINT32 file size
+ *     BYTE*  filedata
+ *
+ *   2006-06-19 SM new
+ *   2006-11-03 SM update, new eventdata format
+ *              event data = file image << OLD
+ */
+int
+measure_file_as_event (
+	char *filename,
+	int pcr_index,
+	int eventtype)
+{
+	int rc=0;
+	TCG_PCR_EVENT *logdata;
+	GRUB_SPECIFIC_EVENT *grubdata;
+	int logdatasize;
+
+	if (ima_disable) return -1;
+
+	/* status check */
+	if (ima_status(NULL)) {
+		if (ima_benchmark)
+			ima_benchmark_rdtsc = rdtsc();
+
+		/* Open the file */
+		if (! grub_open (filename))
+			return errnum;
+
+		/* Read */
+		logdata = (TCG_PCR_EVENT *) ima_workbuf;
+		logdata->pcrIndex=pcr_index;
+		logdata->eventType=eventtype;
+
+		grubdata = (GRUB_SPECIFIC_EVENT *) logdata->event;
+
+		/* File name */
+		memcpy(grubdata->data,filename,grub_strlen(filename)+1);
+		nul_terminate (grubdata->data);
+		grubdata->filenameSize = grub_strlen(grubdata->data);
+
+		/* File Data */
+		grubdata->filedataSize = grub_read(&grubdata->data[grubdata->filenameSize], -1);
+
+		logdata->eventDataSize = 8 + grubdata->filenameSize + grubdata->filedataSize;
+		logdatasize = TCG_PCR_EVENT_BASE_SIZE + logdata->eventDataSize;
+
+		if (logdatasize>TCG_EVENTDATA_SIZE) {
+		  /* TODO */
+		  logdata->eventDataSize = 0;
+		  logdatasize = TCG_PCR_EVENT_BASE_SIZE;
+		}
+
+		ima_grub_pcr_usage[pcr_index] ++; /* Check the PCR usage*/
+
+		/* Close */
+		grub_close ();
+
+		if (logdata->eventDataSize<0)
+			return -1;
+
+		if (ima_benchmark) {
+			grub_printf("measure_file2: %d bytes - %d msec(@2GHzCPU) - load file\n",
+				logdata->eventDataSize,
+				(rdtsc() - ima_benchmark_rdtsc)>>21);
+			ima_benchmark_rdtsc = rdtsc();
+		}
+
+		/* BIOS Call */
+		rc = ima_hlee_select(
+			logdata->eventDataSize,
+			logdata->event,
+			logdatasize,
+			logdata);
+
+		if (ima_benchmark)
+			grub_printf("measure_file2: %d bytes - %d msec(@2GHzCPU) - HashLogExtendEvent\n",
+				logdata->eventDataSize,
+				(rdtsc() - ima_benchmark_rdtsc)>>21);
+
+		if (ima_debug){
+			grub_printf("measure_file2(pcr=%d,type=%d,size=%d(hashed=eventdata),no_decomp=%d)\n",
+				logdata->pcrIndex,
+				logdata->eventType,
+				logdata->eventDataSize,
+				no_decompression);
+			grub_printf("Press any key to go next step....\n");
+			getkey ();
+		}
+
+		if (rc!=0) {
+			if (rc == 3) {
+				/* TODO IBM BIOS return 3 */
+			} else {
+				print_rc("Error ",rc);
+				grub_printf("measure_file2 (TCG_HashLogExtendEvent) was failed?\n");
+			}
+			return (rc);
+		}
+	} else {
+		//grub_printf (err_no_tcg);
+		return -1;
+	}
+	return 0;
+}
+
+
+/*
+ *  measure mem
+ *
+ *    PCRn = SHA1(PCRn-1 + image)
+ *    event data = name
+ *
+ *  2006-06-23 SM new
+ */
+int
+measure_mem (
+	int len,
+	unsigned char *addr,
+	int pcr_index,
+	int eventtype,
+	char* eventdata)
+{
+	int rc=0;
+	TCG_PCR_EVENT *logdata;
+	int eventsize;
+	int logdatasize;
+
+	if (ima_disable) return -1;
+
+	/* status check */
+	if (ima_status(NULL)) {
+
+		if (ima_benchmark)
+			ima_benchmark_rdtsc = rdtsc();
+
+		eventsize = grub_strlen(eventdata);
+		if (eventsize > TCG_PCR_EVENT_DATA_SIZE) {
+			grub_printf("Eventsize = %d (MAX %d) is too large\n",
+			eventsize,TCG_PCR_EVENT_DATA_SIZE);
+			return -1;
+		} else {
+			logdata = (TCG_PCR_EVENT *) tcg_event_buf;
+		}
+
+		logdata->pcrIndex=pcr_index;
+		logdata->eventType=eventtype; /* TODO*/
+
+		logdata->eventDataSize = eventsize;
+		memcpy(logdata->event,eventdata,logdata->eventDataSize+1);
+		nul_terminate (logdata->event); /* delete command part */
+
+		logdatasize = TCG_PCR_EVENT_BASE_SIZE+logdata->eventDataSize;
+
+		ima_grub_pcr_usage[pcr_index] ++; /* Check the PCR usage*/
+
+		/* BIOS Call */
+		 rc = ima_hlee_select(
+			len,
+			addr,
+			logdatasize,
+			logdata);
+
+		if (ima_benchmark)
+			grub_printf("measure_mem: %d bytes - %d msec(@2GHzCPU) HashAll+LogExtend\n",
+				len,
+				(rdtsc() - ima_benchmark_rdtsc)>>21);
+
+		if (ima_debug) {
+			grub_printf("measure_mem(pcr=%d,type=%d,size=%d)\ndigest=",
+				logdata->pcrIndex,
+				logdata->eventType,
+				logdata->eventDataSize);
+				print_digest(logdata->digest, 20);
+			grub_printf("\nPress any key to go next step....\n");
+			getkey ();
+		}
+
+		if (rc!=0) {
+			if (rc == 3) {
+				/* TODO IBM BIOS return 3 */
+			} else {
+				print_rc("Error ",rc);
+				grub_printf("measure_mem (TCG_LogExtend) was failed?\n");
+			}
+		}
+		return rc;
+	} else {  // Status
+			//grub_printf (err_no_tcg);
+		return -1;
+	}
+}
+
+/*
+ *
+ *
+ *
+ */
+int
+ima_start_os_measurement(void){
+	int i;
+	unsigned char mbr[SECTOR_SIZE+8];
+	PC_SPECIFIC_EVENT *pcEvent;
+	pcEvent = (PC_SPECIFIC_EVENT *) mbr;
+
+	if (! rawread (saved_drive, 0, 0, SECTOR_SIZE, &mbr[8])) {
+		// TODO add error message
+	} else {
+		pcEvent->eventID=IMA_EV_GRUB_MBR_PCTYPE;
+		pcEvent->eventDataSize=446;
+		measure_eventdata(
+			IMA_EV_GRUB_MBR_PCR,
+			IMA_EV_GRUB_MBR_TYPE,
+			8+446,
+			mbr);
+	}
+
+	//  add Separator to PCR[4]
+	measure_eventdata(IMA_EV_GRUB_STAGE1_PCR,
+		          IMA_EV_GRUB_SEPARATOR_TYPE,
+		          grub_strlen(ima_grub_separator),
+	              ima_grub_separator);
+	//  add Separator to PCR[5]
+	measure_eventdata(IMA_EV_GRUB_CONFIG_PCR,
+		          IMA_EV_GRUB_SEPARATOR_TYPE,
+		          grub_strlen(ima_grub_separator),
+	              ima_grub_separator);
+
+
+	//  init usage flag
+	for (i=0;i<24;i++) {
+		ima_grub_pcr_usage[i]=0;
+	}
+	return 0; // TODO
+}
+/*
+ *  Measure Event Sepatator and final boot message
+ *
+ */
+int
+ima_final(char *msg){
+	int i;
+	// add event separator
+	for (i=0;i<24;i++) {
+		if (ima_grub_pcr_usage[i]>0){
+	     measure_eventdata(i,
+		               IMA_EV_GRUB_SEPARATOR_TYPE,
+		               grub_strlen(ima_os_separator),
+	                   ima_os_separator);
+		}
+	}
+	// add final message
+     measure_eventdata(IMA_EV_GRUB_BOOT_MSG_PCR,
+	              IMA_EV_GRUB_BOOT_MSG_TYPE,
+                    grub_strlen(msg),
+                    msg);
+	return 0; // TODO
+}
+
+
+/*
+ * Functions for "tpm" command
+ *  - print_pcrs
+ *
+ */
+
+int print_pcrs(void){
+	int i;
+	int pcrs=16;
+	int rc;
+	unsigned char pcr_value[SHA1_DIGEST_SIZE];
+
+	if (ima_disable) return -1;
+
+	/* status check */
+	rc =ima_status(NULL);
+
+	/* TODO To get PCR #, use GetCapability */
+	if (rc== TCG_V11) pcrs=16;
+	else if (rc== TCG_V12) pcrs=24;
+	else return -1;
+
+	/* Read pcr value */
+	for (i=0;i<pcrs;i++) {
+		rc = ima_pcr_read(i, pcr_value);
+		if (rc != 0) {
+			print_rc("Error at ima_pcr_read",rc);
+			return 0;
+		}
+		if (i<10) grub_printf("PCR[ %d]=",i);
+		else grub_printf("PCR[%d]=",i);
+		print_digest(pcr_value, 20);
+		grub_printf("\n");
+	}
+	return 0;
+}
+
+
+/*
+ *  Print Event Log
+ */
+int
+print_eventlog(void)
+{
+	unsigned char *log_addr;
+	unsigned char *log_addr_limit;
+	int i = 0;
+	int log_num = -1;
+
+	if (ima_disable) return -1;
+
+	/* status check */
+	if (ima_status( &log_addr )==0) {
+		grub_printf (err_no_tcg);
+		return -1;
+	}
+
+	log_addr_limit = log_addr + 0x10000;
+
+	while (log_addr < log_addr_limit) {
+		TCG_PCR_EVENT *event = (TCG_PCR_EVENT*)log_addr;
+		if (event->eventType == 0 && event->eventDataSize == 0) break;
+
+		if (log_num < 0 || i == log_num) {
+			// 2006-06-16 same as ascii out of tpm_bios
+			//grub_printf("[%d] ",i);
+
+			if ((event->pcrIndex<0) || (event->pcrIndex>=24)) { // TODO
+				grub_printf("wrong PCR index, broken table?\ndump=");
+				for (i=0;i<64;i++) {
+					print_hex(log_addr[i]);
+				}
+				grub_printf("...\nand dump(fw)=....");
+				log_addr -= 40;
+				for (i=0;i<40;i++) {
+					print_hex(log_addr[i]);
+				}
+				grub_printf("\n");
+				return (-1);
+			}
+
+			if (event->pcrIndex<10) grub_printf(" ");
+
+			grub_printf("%d ",event->pcrIndex);
+
+			print_digest(event->digest, 20);
+
+			if (event->eventType<10) grub_printf("  ");
+			else grub_printf(" ");
+			grub_printf("%d ",event->eventType);
+			//grub_printf(" %d ",event->eventSize);
+
+			switch((0xFF && event->eventType)) { // mask, low byte is BIOS compatible
+				case 5: {
+					char buff[40];
+					//char *src = (char *)(log_addr + sizeof(TCG_PCR_EVENT));
+					char *src = (char *)(log_addr + TCG_PCR_EVENT_BASE_SIZE);
+					int size = event->eventDataSize;
+					if (size >= sizeof(buff)) size = sizeof(buff) - 1;
+					memcpy(buff, src, size);
+					buff[size] = 0; /* add null for %s */
+					grub_printf("[");
+					grub_printf(buff);
+					grub_printf("]");
+				}
+				break;
+				case 6: { /* Platform specific */
+					PC_SPECIFIC_EVENT *pc =
+						(PC_SPECIFIC_EVENT*)(log_addr + sizeof(TCG_PCR_EVENT));
+					switch (pc->eventID) {
+						case 1:
+							grub_printf("[SMBIOS]");
+							break;
+						case 5:
+							grub_printf("[CMOS]");
+							break;
+						case 6:
+							grub_printf("[NVRAM]");
+							break;
+						case IMA_EV_GRUB_MBR_PCTYPE:
+							grub_printf("[MBR by GRUB]");
+							break;
+						default:
+							grub_printf("{PC ID=%d size=%d}", pc->eventID, pc->eventDataSize);
+						}
+					}
+					break;
+				default:
+					grub_printf("{EventSize=%d}", event->eventDataSize);
+			} // switch
+			grub_printf("\n");
+		} // if
+
+		if (ima_debug) {
+			unsigned char *buf;
+			buf = (unsigned char *)log_addr;
+			for (i=0;i<TCG_PCR_EVENT_BASE_SIZE + event->eventDataSize;i++) {
+				print_hex(buf[i]);
+			}
+			grub_printf("\n");
+		}
+
+		log_addr += TCG_PCR_EVENT_BASE_SIZE + event->eventDataSize;
+		i++;
+	} // while
+	return (0);
+}
+
+/*
+ * get digest in the last event
+ */
+int get_last_event(unsigned char *digest){
+	int rc = 0;
+	unsigned char *log_addr;
+	unsigned char *log_addr_limit;
+	int i = 0;
+	//int log_num = -1;
+	TCG_PCR_EVENT *event;
+	TCG_PCR_EVENT *event_pre;
+
+	if (ima_disable) return -1;
+
+	/* status check */
+	if (ima_status( &log_addr )==0) {
+		grub_printf (err_no_tcg);
+		return -1;
+	}
+
+	log_addr_limit = log_addr + 0x10000;
+	event = (TCG_PCR_EVENT *)log_addr;
+	event_pre = event;
+
+	while (log_addr < log_addr_limit) {
+		event_pre = event;
+		event = (TCG_PCR_EVENT *)log_addr;
+		if (event->eventType == 0 && event->eventDataSize == 0) break;
+
+		if ((event->pcrIndex<0) || (event->pcrIndex>=24)) { // TODO
+			grub_printf("wrong PCR index, broken table?\ndump=");
+			for (i=0;i<64;i++) {
+				print_hex(log_addr[i]);
+			}
+			grub_printf("...\nand dump(fw)=....");
+			log_addr -= 40;
+			for (i=0;i<40;i++) {
+				print_hex(log_addr[i]);
+			}
+			grub_printf("\n");
+			return (-1);
+		}
+
+		log_addr += TCG_PCR_EVENT_BASE_SIZE + event->eventDataSize;
+	}
+
+	/* copy last one */
+	/* TODO event is null, just use one before is correct? */
+	memcpy(digest,event_pre->digest,20);
+
+	return rc;
+}
+
+/*
+ *Verify PCR Extend Operation
+ *Return
+ *0 : OK
+ * -1 : Fail
+ */
+
+int verify_extend(
+	int pcr_index,
+	unsigned char *pcr_value,
+	unsigned char *digest,
+	int option) // 2:extend twice
+{
+	int rc = -1;
+	unsigned char new_pcr_value[20];
+	unsigned char exp_pcr_value[20];
+	unsigned char extend_buffer[40];
+
+	/* read current PCR */
+	rc = ima_pcr_read(pcr_index, new_pcr_value);
+	// TODO check rc
+
+	/* calc expected PCR */
+	memcpy(extend_buffer,pcr_value,20);
+	memcpy(&extend_buffer[20],digest,20);
+	rc = TCG_HashAll(40,extend_buffer,exp_pcr_value);
+	// TODO check rc
+
+	if (option==2) { // try again
+		memcpy(extend_buffer,exp_pcr_value,20);
+		memcpy(&extend_buffer[20],digest,20);
+		rc = TCG_HashAll(40,extend_buffer,exp_pcr_value);
+	// TODO check rc
+	}
+
+	if (grub_memcmp(new_pcr_value,exp_pcr_value,20) == 0) {
+		rc=0;
+	} else {
+		rc=-1;
+		grub_printf(" Wrong PCR Value = ");
+		print_digest (new_pcr_value, 20);
+		grub_printf("\n");
+		grub_printf("       should be = ");
+		print_digest (exp_pcr_value, 20);
+		grub_printf("\n");
+	}
+	return rc;
+}
+
+/*
+ Test Vectors
+
+ input[2] BB01
+ output[20]
+ input[2] BB01
+ output[20]
+
+
+ */
+
+#define BB01_PCRINDEX   15
+#define BB0401_PCRINDEX 14
+#define BB0402_PCRINDEX 13
+#define BB07_PCRINDEX   12
+
+/*
+ * 2006-08-16 BUG or SPEC?
+ * If type=1 IBM v1.1 BIOS just override the eventDataSize to zero
+ * but not delete the eventdata. thus BIOS broke the eventlog structure.
+ *    1h EV_POST_CODE NG
+ *    5h EV_ACTION    OK but must be string
+ *   0Dh EV_IPL
+ */
+#define BB01_EVENTTYPE    0x0D  /* EV_IPV v1.2*/
+#define BB04_EVENTTYPE    0x0D  /* EV_IPV v1.2*/
+
+#define REPORT_PCRINDEX   0x0F
+#define REPORT_EVENTTYPE  0x0D
+
+
+/* For Extend the TEST result as logevent */
+typedef struct tdTCG_BIOS_STATUS_REPORT {
+	int version;
+	unsigned char major;
+	unsigned char minor;
+	int BB00_status;
+	int BB01_status;
+	int BB02_status;
+	int BB03_status;
+	int BB04_status;
+	int BB05_status;
+	int BB06_status;
+	int BB07_status;
+} TCG_BIOS_STATUS_REPORT;
+
+// 32 BIT = 32 type
+#define TCG_BIOS_CALL_STATUS_OK		0x00000000
+#define TCG_BIOS_CALL_STATUS_UNKNOWN		0x00000100
+#define TCG_BIOS_CALL_STATUS_FAIL		0x00000200
+#define TCG_BIOS_CALL_STATUS_WRONG_PCR		0x00001000
+#define TCG_BIOS_CALL_STATUS_WRONG_EVENTLOG	0x00002000
+#define TCG_BIOS_CALL_STATUS_WRONG_DIGEST	0x00003000
+
+#define TCG_BIOS_CALL_STATUS_IBM_RC3		0x00010000
+#define TCG_BIOS_CALL_STATUS_IBM_HLEE_F2	0x00020000
+#define TCG_BIOS_CALL_STATUS_IBM_LE_WITH_EXTEND	0x00040000
+
+// MASK
+#define TCG_BIOS_CALL_STATUS_FATAL       0x0000FFFF
+#define TCG_BIOS_CALL_STATUS_BUGGY       0xFFFF0000
+
+
+int
+ima_print_digest2(
+	char *msg1, unsigned char *digest1,
+	char *msg2, unsigned char *digest2)
+{
+	grub_printf(msg1);
+	print_digest (digest1, 20);
+	grub_printf("\n");
+	grub_printf(msg2);
+	print_digest (digest2, 20);
+	grub_printf("\n");
+	return 0;
+}
+
+
+static unsigned char SHA1_BB01[20]=
+	{0xf9,0x04,0x7a,0x61,0xa3,0x30,0x0b,0xb1,0x57,0x94,0x3f,0x0e,0xc4,0x18,0x08,0x35,0xa7,0xc3,0xf8,0x8e};
+//static unsigned char SHA1_BB04[20]=
+//{0xa4,0x1a,0x39,0x8f,0x1d,0xa2,0x0a,0x7b,0x6d,0x04,0x16,0xc3,0x80,0xec,0x21,0x8d,0xe4,0x1d,0x3b,0x8f,};
+static unsigned char SHA1_BB0401[20]=
+	{0xcc,0xdd,0xff,0x40,0xae,0x48,0xba,0x23,0xa8,0xbf,0x13,0x55,0x71,0xbe,0x57,0x48,0x9f,0x85,0x62,0x10};
+static unsigned char SHA1_BB0402[20]=
+	{0xe7,0x7e,0x64,0x4d,0x32,0x46,0xaf,0x8c,0x16,0x2f,0x1f,0xde,0xb1,0xc1,0xc7,0x85,0x88,0x93,0xd8,0xc5};
+static unsigned char SHA1_BB05[20]=
+	{0x1f,0x44,0x7d,0xf3,0xef,0xef,0xbb,0xd5,0xc5,0x65,0x0a,0xad,0x38,0xbe,0x5e,0xb7,0x38,0x32,0x03,0x91};
+static unsigned char SHA1_BB07[20]=
+	{0x93,0xbe,0x85,0xc3,0x7c,0xf3,0x35,0x6a,0xbf,0x5f,0xee,0x97,0x7a,0x4d,0xb6,0xe3,0xb5,0xc4,0x60,0xff};
+
+
+static unsigned char BB01[2]   = {0xBB,0x01};
+//static unsigned char BB04[2] = {0xBB,0x04};
+static unsigned char BB0401[3] = {0xBB,0x04,0x01};
+static unsigned char BB0402[3] = {0xBB,0x04,0x02};
+static unsigned char BB05[2]   = {0xBB,0x05};
+static unsigned char BB07[2]   = {0xBB,0x07};
+
+int
+ima_diagnosis (int format)
+{
+	int rc=0;
+	int rc2=0;
+	unsigned char major;
+	unsigned char minor;
+	unsigned char *log_addr;
+	//unsigned char buf[20]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+	unsigned char digest[20]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+	//unsigned char str[11]={'T','C','G',' ','T','E','S','T','0',0,0};
+
+	unsigned char pcr_value[20]; /* For PCR Verification */
+	TCG_PCR_EVENT *logdata;
+	TCG_BIOS_STATUS_REPORT report;
+
+	grub_printf("Start BIOS TCG compliance check\n");
+
+	/*
+	 * TCG_StatusCheck - INT 1Ah (AH)=BBh,(AL)=00h
+	 *
+	 */
+	grub_printf("0) TCG_StatusCheck - INT 1Ah (AH)=BBh,(AL)=00h\n");
+	/* input - none */
+
+	/* call */
+	rc = TCG_StatusCheck(&major,&minor,&log_addr );
+
+	/* output */
+	if (rc) {
+		print_rc("Error ",rc);
+		return rc; /* TEST was Finish */
+	} else {
+		grub_printf("TCG Version major   : %d\n",major);
+		grub_printf("TCG Version minor   : %d\n",minor);
+		//grub_printf("BIOS EventTable ptr : 0x");
+		//print_u32((unsigned int)log_addr);
+		//grub_printf("\n");
+		report.major = major; // TODO remove local ver
+		report.minor = minor;
+		report.BB00_status = TCG_BIOS_CALL_STATUS_OK;
+	}
+
+	/*
+	 * TCG_HashLogExtendEvent - INT 1Ah (AH)=BBh,(AL)=01h
+	 * This call has two input parametor block formats.
+	 * V1.1 IBM BIOS was using the "Format 2" and HALT with "Format 1" :-(
+	 * Thus, the reguler test should use "Format 2" temporary.
+	 */
+	grub_printf("1) TCG_HashLogExtendEvent - INT 1Ah (AH)=BBh,(AL)=01h (v1.1 & v1.2)");
+
+	/* Check PCR value before extend */
+	rc = ima_pcr_read(BB01_PCRINDEX, pcr_value);
+
+	/* input */
+	//logdata = (TCG_PCR_EVENT *) RAW_ADDR (0x100000);
+	logdata = (TCG_PCR_EVENT *) ima_workbuf;
+	logdata->pcrIndex=BB01_PCRINDEX;
+	logdata->event[0]=BB01[0];
+	logdata->event[1]=BB01[1];
+
+	logdata->eventType=BB01_EVENTTYPE; /* If type=1 IBM v1.1 BIOS override the eventDataSize to zero */
+	logdata->eventDataSize=2;
+
+	report.BB01_status = TCG_BIOS_CALL_STATUS_OK;
+
+	/* call */
+	if (format==2) {
+		grub_printf(" (Format 2)\n");
+		report.BB01_status |= TCG_BIOS_CALL_STATUS_IBM_HLEE_F2;
+
+		rc = TCG_HashLogExtendEventF2(
+				logdata->pcrIndex,
+				logdata->eventDataSize,
+				logdata->event,
+				32 + 2,
+				(unsigned char*)logdata);
+	} else {
+		grub_printf(" (Format 1)\n");
+		rc = TCG_HashLogExtendEventF1(
+				logdata->pcrIndex,
+				logdata->eventDataSize,
+				logdata->event,
+				32 + 2,
+				(unsigned char*)logdata);
+	}
+
+	/* output */
+	rc2=get_last_event(digest);
+
+	if (rc==0) {
+		if (grub_memcmp(digest,SHA1_BB01,20)==0) {
+			/* PCR */
+			if (verify_extend(BB01_PCRINDEX, pcr_value,SHA1_BB01,0) != 0) {
+				grub_printf(" Event Log is OK, but PCR[%d] has wrong value\n",BB01_PCRINDEX);
+				report.BB01_status |= TCG_BIOS_CALL_STATUS_WRONG_PCR;
+			} else {
+				grub_printf(" Good Eventlog & PCR - OK\n");
+			}
+		} else {
+			ima_print_digest2(
+				" Wrong digest = ",digest,
+				"    should be = ", SHA1_BB01);
+			report.BB01_status |= TCG_BIOS_CALL_STATUS_WRONG_EVENTLOG;
+		}
+	} else if (rc==3) {
+		if (grub_memcmp(digest,SHA1_BB01,20)==0) {
+			/* PCR */
+			if (verify_extend(BB01_PCRINDEX, pcr_value,SHA1_BB01,0) != 0) {
+				grub_printf(" Event Log is OK, but PCR[%d] has wrong value\n",BB01_PCRINDEX);
+				report.BB01_status |= TCG_BIOS_CALL_STATUS_WRONG_PCR;
+			} else {
+				report.BB01_status |= TCG_BIOS_CALL_STATUS_IBM_RC3;
+				grub_printf(" (rc=3 but it seems work, OLD IBM BIOS?) ");
+				grub_printf(" Good Eventlog & PCR - OK\n");
+			}
+		} else { /* Not supported */
+			report.BB01_status |= TCG_BIOS_CALL_STATUS_FAIL;
+			report.BB01_status |= rc;
+			grub_printf(" rc=3, BIOS Call is not supported\n");
+		}
+	} else {
+		print_rc("Error ",rc);
+		grub_printf(" Error TCG_HashLogExtendEvent Fomat %d, rc = %d\n",
+		rc,format);
+		report.BB01_status |= TCG_BIOS_CALL_STATUS_FAIL;
+		report.BB01_status |= rc;
+	}
+
+	/*
+	 * TCG_PassThroughToTPM - INT 1Ah (AH)=BBh,(AL)=02h
+	 *
+	 */
+	grub_printf("2) TCG_PassThroughToTPM - INT 1Ah (AH)=BBh,(AL)=02h\n");
+	/* input */
+	/* call */
+	rc = ima_pcr_read(BB01_PCRINDEX, digest);
+	/* output */
+	if (rc) {
+		print_rc("Error ",rc);
+		report.BB02_status = TCG_BIOS_CALL_STATUS_FAIL;
+		report.BB02_status |= rc;
+	} else {
+		grub_printf(" OK\n");
+		grub_printf("   PCR[%d]=",BB01_PCRINDEX);
+		print_digest(digest, 20);
+		grub_printf("\n");
+		report.BB02_status = TCG_BIOS_CALL_STATUS_OK;
+	}
+
+	grub_printf("3) TCG_ShutdownPreBootInterface - INT 1Ah (AH)=BBh,(AL)=03h - NA\n");
+	/* input */
+	/* call */
+	/* output */
+	grub_printf(" SKIP\n");
+	report.BB03_status = TCG_BIOS_CALL_STATUS_UNKNOWN;
+
+
+	/*
+	 *TCG_LogEvent - INT 1Ah (AH)=BBh,(AL)=04h (v1.1)
+	 * v1.1 spec is ambiguous, IBM BIOS do extend with this call.
+	 */
+	grub_printf("4-1) TCG_LogEvent (w/ Extend) - INT 1Ah (AH)=BBh,(AL)=04h (IBM/Lenovo only?)\n");
+
+	/* Check PCR value before extend */
+	rc = ima_pcr_read(BB0401_PCRINDEX, pcr_value);
+
+	/* input */
+	//logdata = (TCG_PCR_EVENT *) RAW_ADDR (0x100000);
+	logdata = (TCG_PCR_EVENT *) ima_workbuf;
+	logdata->pcrIndex=BB0401_PCRINDEX;
+	logdata->eventType=BB04_EVENTTYPE;
+	logdata->eventDataSize=3;
+	logdata->event[0]=BB0401[0];
+	logdata->event[1]=BB0401[1];
+	logdata->event[2]=BB0401[2];
+	memcpy(logdata->digest,SHA1_BB0401,20);
+
+	report.BB04_status = TCG_BIOS_CALL_STATUS_IBM_LE_WITH_EXTEND;
+
+	/* call */
+	rc = TCG_LogExtend(
+			logdata->pcrIndex,
+			logdata->eventType,
+			32 + 3, // logdata->eventDataSize,
+			(unsigned char *)logdata);
+
+	/* output */
+	rc2=get_last_event(digest);
+
+	if (rc==0) {
+		if (grub_memcmp(digest,SHA1_BB0401,20)==0) {
+			/* PCR */
+			if (verify_extend(BB0401_PCRINDEX, pcr_value,SHA1_BB0401,0) != 0) {
+				grub_printf(" Event Log is OK, but PCR[%d] has wrong value\n",BB0401_PCRINDEX);
+				report.BB04_status |= TCG_BIOS_CALL_STATUS_WRONG_PCR;
+			} else {
+				grub_printf(" Good Eventlog & PCR - OK\n");
+			}
+		} else {
+			ima_print_digest2(
+				" Wrong digest = ", digest,
+				"    should be = ", SHA1_BB0401);
+			report.BB04_status |= TCG_BIOS_CALL_STATUS_WRONG_DIGEST;
+		}
+	} else if (rc==3) {
+		if (grub_memcmp(digest,SHA1_BB0401,20)==0) {
+			/* PCR */
+			if (verify_extend(BB0401_PCRINDEX, pcr_value,SHA1_BB0401,0) != 0) {
+				grub_printf(" Event Log is OK, but PCR[%d] has wrong value\n",BB0401_PCRINDEX);
+				report.BB04_status |= TCG_BIOS_CALL_STATUS_WRONG_PCR;
+			} else {
+				report.BB04_status |= TCG_BIOS_CALL_STATUS_IBM_RC3;
+				grub_printf(" (rc=3 but it seems work, OLD IBM BIOS?) "); // TODO change the loc
+				grub_printf(" Good Eventlog & PCR - OK\n");
+			}
+		} else {
+			report.BB04_status |= TCG_BIOS_CALL_STATUS_WRONG_DIGEST;
+			report.BB04_status |= rc;
+			grub_printf(" rc=3, BIOS Call is not supported\n");
+			}
+	} else {
+		print_rc("Error ",rc);
+		grub_printf(" Error TCG_HashLogEvent Fomat %d, rc = %d\n",
+			rc,format);
+		report.BB04_status |= TCG_BIOS_CALL_STATUS_FAIL;
+		report.BB04_status |= rc;
+	}
+
+
+	/*
+	 *TCG_LogEvent - INT 1Ah (AH)=BBh,(AL)=04h (v1.2)
+	 * v1.2 spec said, this call DID NOT "extend" PCR.
+	 */
+	grub_printf("4-2) TCG_HashLogEvent (w/o Extend) - INT 1Ah (AH)=BBh,(AL)=04h (v1.2)\n");
+
+	//if (report.BB04_status & TCG_BIOS_CALL_STATUS_FATAL) { // V1.2 BIOS TODO ck ver
+	if (report.BB04_status ) { // TODO TRUE anytime
+		/* Check PCR value before extend */
+		rc = ima_pcr_read(BB0402_PCRINDEX, pcr_value);
+
+		/* Extend */
+		ima_extend(BB0402_PCRINDEX,SHA1_BB0402,digest);
+
+		/* input */
+		//logdata = (TCG_PCR_EVENT *) RAW_ADDR (0x100000);
+		logdata = (TCG_PCR_EVENT *) ima_workbuf;
+		logdata->pcrIndex=BB0402_PCRINDEX;
+		logdata->eventType=BB04_EVENTTYPE;
+		logdata->eventDataSize=3;
+		logdata->event[0]=BB0402[0];
+		logdata->event[1]=BB0402[1];
+		logdata->event[2]=BB0402[2];
+		memcpy(logdata->digest,SHA1_BB0402,20);
+
+		report.BB04_status = TCG_BIOS_CALL_STATUS_OK; /* clear BB04 state */
+
+		/* call */
+		rc = TCG_LogExtend(
+			logdata->pcrIndex,
+			logdata->eventType,
+			32 + 3,// logdata->eventDataSize,
+			(unsigned char *)logdata);
+
+		/* output */
+		rc2=get_last_event(digest);
+
+		if (rc==0) {
+			if (grub_memcmp(digest,SHA1_BB0402,20)==0) {
+				/* PCR */
+				if (verify_extend(BB0402_PCRINDEX, pcr_value,SHA1_BB0402,0) != 0) {
+					if (verify_extend(BB0402_PCRINDEX, pcr_value,SHA1_BB0402,2) != 0) {
+						grub_printf(" Event Log is OK, but PCR[%d] has wrong value\n",BB0402_PCRINDEX);
+						report.BB04_status |= TCG_BIOS_CALL_STATUS_WRONG_PCR;
+					} else {
+						report.BB04_status |= TCG_BIOS_CALL_STATUS_IBM_LE_WITH_EXTEND;
+						grub_printf(" Check PCR again...I see!\n");
+						grub_printf(" Since TCG_HashLogEvent did Extend, noncompliant BIOS with the v1.2 spec?\n");
+					}
+				} else {
+					grub_printf(" Good Eventlog & PCR - OK\n");
+				}
+			} else {
+				ima_print_digest2(
+					" Wrong digest = ", digest,
+					"    should be = ", SHA1_BB0402);
+				report.BB04_status |= TCG_BIOS_CALL_STATUS_WRONG_DIGEST;
+			}
+		} else if (rc==3) {
+			if (grub_memcmp(digest,SHA1_BB0402,20)==0) {
+				/* PCR */
+				if (verify_extend(BB0402_PCRINDEX, pcr_value,SHA1_BB0402,0) != 0) {
+					if (verify_extend(BB0402_PCRINDEX, pcr_value,SHA1_BB0402,2) != 0) {
+						grub_printf(" Event Log is OK, but PCR[%d] has wrong value\n",BB0402_PCRINDEX);
+						report.BB04_status |= TCG_BIOS_CALL_STATUS_WRONG_PCR;
+					} else {
+						report.BB04_status |= TCG_BIOS_CALL_STATUS_IBM_RC3;
+						report.BB04_status |= TCG_BIOS_CALL_STATUS_IBM_LE_WITH_EXTEND;
+						grub_printf(" Check PCR again...I see!\n");
+						grub_printf(" Since TCG_HashLogEvent did Extend, noncompliant BIOS with the v1.2 spec?\n");
+					}
+				} else {
+					report.BB04_status |= TCG_BIOS_CALL_STATUS_IBM_RC3;
+					grub_printf(" (rc=3 but it seems work, OLD IBM BIOS?) ");  // TODO change the loc
+					grub_printf(" Good Eventlog & PCR - OK\n");
+				}
+			} else {
+				report.BB04_status |= TCG_BIOS_CALL_STATUS_FAIL;
+				report.BB04_status |= rc;
+				grub_printf(" rc=3, BIOS Call is not supported\n");
+			}
+		} else {
+			print_rc("Error ",rc);
+			grub_printf(" Error TCG_HashLogEvent Fomat %d, rc = %d\n",
+				rc,format);
+			report.BB04_status |= TCG_BIOS_CALL_STATUS_FAIL;
+			report.BB04_status |= rc;
+			}
+
+	} else { // v1.1?
+		grub_printf("Skip this test since the BIOS is v1.1 IBM\n");
+		// TODO v1.2 BIOS?
+	}
+
+	/*
+	 *  TCG_HashAll - INT 1Ah (AH)=BBh,(AL)=05h
+	 *
+	 */
+	grub_printf("5) TCG_HashAll - INT 1Ah (AH)=BBh,(AL)=05h\n");
+
+	/* input */
+	/* call */
+	rc = TCG_HashAll(2,BB05,digest);
+
+	/* output */
+	if (rc) {
+		print_rc("Error ",rc);
+		report.BB05_status = TCG_BIOS_CALL_STATUS_FAIL;
+		report.BB05_status |= rc;
+	} else {
+		if (grub_memcmp(digest,SHA1_BB05,20)==0) {
+			grub_printf(" OK!\n");
+			report.BB05_status = TCG_BIOS_CALL_STATUS_OK;
+		} else {
+			ima_print_digest2(
+				" Wrong digest = ", digest,
+				"    should be = ", SHA1_BB05);
+		report.BB05_status = TCG_BIOS_CALL_STATUS_WRONG_DIGEST;
+		}
+	}
+
+	/*
+	 *  TCG_TSS - INT 1Ah (AH)=BBh,(AL)=06h- TBD
+	 */
+	grub_printf("6) TCG_TSS - INT 1Ah (AH)=BBh,(AL)=06h- TBD \n");
+	grub_printf(" SKIP\n");
+	report.BB06_status = TCG_BIOS_CALL_STATUS_UNKNOWN;
+
+	/*
+	 * TCG_CompactHashLogExtendEvent - INT 1Ah (AH)=BBh,(AL)=07h (v1.2)
+	 * PCR index = 12
+	 * EventType = 0x0c = 12
+	 */
+	grub_printf("7) TCG_CompactHashLogExtendEvent - INT 1Ah (AH)=BBh,(AL)=07h\n");
+
+	/* Check PCR value before extend */
+	rc = ima_pcr_read(BB07_PCRINDEX, pcr_value);
+
+	report.BB07_status = TCG_BIOS_CALL_STATUS_OK;
+
+	//grub_printf("BB07 addr = ");print_u32(BB07);grub_printf("\n");
+
+	/* call */
+	rc = TCG_CompactHashLogExtendEvent(
+			BB07_PCRINDEX,	// PCR index
+			2,		// size
+			BB07);		// ptr
+
+	/* output*/
+	if (rc) {
+		print_rc("Error ",rc);
+		report.BB07_status = TCG_BIOS_CALL_STATUS_FAIL;
+		report.BB07_status |= rc;
+	} else {
+		get_last_event(digest);
+		if (grub_memcmp(digest,SHA1_BB07,20)==0) {
+			/* PCR */
+			if (verify_extend(BB07_PCRINDEX, pcr_value,SHA1_BB07,0) != 0) {
+				grub_printf(" Event Log is OK, but PCR[%d] has wrong value\n",BB07_PCRINDEX);
+				report.BB07_status = TCG_BIOS_CALL_STATUS_WRONG_PCR;
+			} else {
+				grub_printf(" OK!\n"); // GOOD!!
+			}
+		} else {
+			ima_print_digest2(
+				" Wrong digest = ", digest,
+				"    should be = ", SHA1_BB07);
+			report.BB07_status = TCG_BIOS_CALL_STATUS_WRONG_EVENTLOG;
+			grub_printf(" Sorry, This might be a BUG of Transitive Trust patch\n");
+		}
+	}
+
+#if 0
+	/* Option - Extend Test Summary */
+	report.version = 0x00000200; // TODO 0.2.0
+	grub_printf("\nBB00 ");print_u32(report.BB00_status);
+	grub_printf("\nBB01 ");print_u32(report.BB01_status);
+	grub_printf("\nBB02 ");print_u32(report.BB02_status);
+	grub_printf("\nBB03 ");print_u32(report.BB03_status);
+	grub_printf("\nBB04 ");print_u32(report.BB04_status);
+	grub_printf("\nBB05 ");print_u32(report.BB05_status);
+	grub_printf("\nBB06 ");print_u32(report.BB06_status);
+	grub_printf("\nBB07 ");print_u32(report.BB07_status);
+
+	/* Extend 6 Log the TEST report */
+	measure_eventdata (
+        REPORT_PCRINDEX,
+        REPORT_EVENTTYPE,
+        4+2+32,// TODO int eventsize,
+        (unsigned char *)&report);
+#endif
+	return (0);
+}
+
+
+#endif /* TRANSITIVE_TRUST */
--- grub-0.97-orig/stage2/start_eltorito.S	2004-03-28 01:14:20.000000000 +0900
+++ grub-0.97-ima/stage2/start_eltorito.S	2009-05-01 15:56:46.000000000 +0900
@@ -24,6 +24,7 @@
  It has been very heavily modified.
 */
 
+
 #define ASM_FILE
 #include "stage1.h"
 #include "shared.h"
@@ -108,7 +109,9 @@
 	call	getlinsec
 	mov	%ds, %ax
 	mov	%ax, %es
-
+#ifdef  ENABLE_IMA
+	call    tcg_measure
+#endif
 	MSG(notification_done)
 bootit:
 	/* save the sector number of the second sector in %ebp */
@@ -201,8 +204,10 @@
 
 .real_error:
 	MSG(read_error_string)
+#ifndef ENABLE_IMA
 	mov	%dl, %al
 	call	printhex2
+#endif /* ENABLE_IMA */
 	popal
 	jmp	stop
 
@@ -230,6 +235,7 @@
 	jne	1b		/* if not end of string, jmp to display */
 	ret
 
+#ifndef ENABLE_IMA
 /*
  * printhex[248]: Write a hex number in (AL, AX, EAX) to the console
  */
@@ -263,18 +269,33 @@
 	loop	1b
 	popal
 	ret
+#endif /* ENABLE_IMA */
+
+
 
 /**************************************************************************/
+#ifdef  ENABLE_IMA
+#ifdef STAGE1_5
+notification_string:	.string "s1.5"
+#else
+notification_string:	.string "s2"
+#endif
+#else /* ! ENABLE_IMA */
 #ifdef STAGE1_5
 notification_string:	.string "Loading stage1.5 "
 #else
 notification_string:	.string "Loading stage2 "
 #endif
+#endif /* ! ENABLE_IMA */
 
 notification_step:	.string "."
 notification_done:	.string "\r\n"
 
+#ifdef  ENABLE_IMA
+read_error_string:	.string "RE 0x"
+#else /* ! ENABLE_IMA */
 read_error_string:	.string "Read error 0x"
+#endif /* ! ENABLE_IMA */
 
 /*
  * EBIOS disk address packet
@@ -295,6 +316,108 @@
 VARIABLE(RetryCount)
 	.byte 0
 
+#ifdef ENABLE_IMA
+/*
+ *  Please call this routine after all image was loaded into STAGE_ADDR,
+ *  note) we remove printhex call to get space of this.
+ *
+ *  TCG_StatusCheck and TCG_HashLogExtendEvent are used so it must work on 1.1b and 1.2 PCs.
+ */
+tcg_measure:
+	pushal
+	push    %ds
+	push    %es
+
+	/* Setup IPB */
+	movw    %ds, %di
+	xorw    %ax, %ax		/* ax =0 */
+	movw    %ax, %ds		/* ds =0 */
+	movw    %ax, %es		/* es =0 */
+
+/*
+ * BIOS call "INT 1Ah, (AH)=BBh,(AL)=00h" TCG_StatusCheck
+ *	Call with
+ *          %ah = 0xBB
+ *	    %al = 0x00
+ *	Return:
+ *	    %eax = TCG_STATUS
+ *	    %ebx = 'TCPA'
+ *
+ * Ref:
+ *  TCG PC Client Specific Implementation Specification for Conventional BIOS v1.2,
+ *  Section 12.5 (page 85)
+ */
+tcg_statuscheck:
+	movw    $0xbb00, %ax		/* TCG_LogEvent */
+	int     $0x1a
+	test	%eax, %eax
+	jnz	tcg_goback
+/*
+ * BIOS call "INT 1Ah, (AH)=BBh,(AL)=01h" TCG_HashLogExtendEvent
+ *	Call with
+ *          %ah = 0xBB
+ *	    %al = 0x01
+ *          %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 Client Specific Implementation Specification for Conventional BIOS v1.2,
+ *  Section 12.6 (page 86)
+ *
+ */
+tcg_hashlogextendevent:
+
+	movw    $ABS(hlee_ipb), %di	/* ES:DI = IPB */
+	mov	ABS(bi_length), %eax	/* HashDataLen */
+	movl    %eax,  8(%di)		/* set to IPB */
+
+	/* Call */
+	movw    $0xbb01, %ax		/* TCG_LogEvent */
+	movw	$0x2E00, %si		/* OPB = 0x2E00 */
+	xorl    %ecx, %ecx		/* ECX = 0 */
+	xorl    %edx, %edx		/* EDX = 0 */
+	int     $0x1a
+
+#ifndef IMA_IGNORE_BIOS_RC3
+	test	%eax, %eax
+	jz	tcg_end
+tcg_error:
+	MSG(tcg_error_string)
+#endif /*  IMA_IGNORE_BIOS_RC3 */
+
+tcg_goback:
+	pop     %es
+	pop     %ds
+	popal
+	ret
+
+/* TCG_HashLogExtendEvent Input Parameter Block Format 2. p88 Table 15 */
+hlee_ipb: /* 28 bytes */
+hlee_opb: /* 28 bytes */
+	.word   (hlee_ipb_end - hlee_ipb)	/*  0 block size   */
+	.word   0				/*  2 reserved     */
+	.long   STAGE_ADDR			/*  4 data pointer */
+	.long   0x0816				/*  8 data size  (init by DEBUG Signature)  */
+	.long   IMA_EV_GRUB_STAGE15_PCR		/*  C PCR index    */
+	.long	0				/* 10 reserved (event type)	*/
+	.long   ABS(tcg_pcr_event)		/* 14 log pointer  */
+	.long   32				/* 18 log size     */
+hlee_ipb_end:
+
+/* TCG_PCR_EVENT data structure 32-bytes */
+tcg_pcr_event:
+	.long   IMA_EV_GRUB_STAGE15_PCR		/* PCR index    */
+tcg_pcr_event_type:
+	.long   IMA_EV_GRUB_STAGE15_TYPE	/* event type   */
+	.space  20				/* PCR value    */
+	.long   0				/* event size   */
+#endif /* ENABLE_IMA */
 
 /*
  *  This area is an empty space between the main body of code below which
@@ -305,9 +428,9 @@
 
 	.word 0
 	.word 0
-
+#if 1
 	. = _start + SECTOR_SIZE - BOOTSEC_LISTSIZE
-
+#endif
 	/* fill the first data listing with the default */
 blocklist_default_start:/* this is the sector start parameter, in logical
 			   sectors from the start of the disk, sector 0 */
--- grub-0.97-grig/efi/efimisc.c	2010-02-06 07:07:26.820525547 +0900
+++ grub-0.97-ima/efi/efimisc.c	2010-02-06 07:20:55.854524724 +0900
@@ -605,3 +605,59 @@
   Call_Service_1 (file->close, file);
   return ret;
 }
+
+#if defined(ENABLE_IMA)
+int TCG_StatusCheck(unsigned char *major,
+                     unsigned char *minor,
+                     unsigned char **event_log)
+{
+	return -1;
+};
+
+int TCG_HashLogExtendEventF1(int pcr_index,
+                             int hashdatasize,
+                             unsigned char *hashdeta,
+                             int logdatasize,
+                             unsigned char *logdeta)
+{
+	return -1;
+};
+
+int TCG_HashLogExtendEventF2(int pcr_index,
+                             int hashdatasize,
+                             unsigned char *hashdeta,
+                             int logdatasize,
+                             unsigned char *logdeta)
+{
+	return -1;
+};
+
+/* TCG_PassThroughToTPM  */
+int ima_extend(int pcr_index, unsigned char *digest,
+                   unsigned char *pcr_value)
+{
+	return -1;
+};
+int ima_pcr_read(int pcr_index, unsigned char *pcr_value)
+{
+	return -1;
+};
+
+int TCG_LogExtend(int pcr_index,
+                  int type,
+                  int logdatasize,
+                  unsigned char *logdata)
+{
+	return -1;
+};
+int TCG_HashAll(int data_len, unsigned char *data, unsigned char *digest)
+{
+	return -1;
+};
+int TCG_CompactHashLogExtendEvent(int pcr_index,
+                                  int hashdatasize,
+                                  unsigned char *hashdeta)
+{
+	return -1;
+};
+#endif /* ENABLE_IMA */ 
