summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoss Philipson <philipsonr@ainfosec.com>2017-03-14 15:40:33 -0400
committerRoss Philipson <philipsonr@ainfosec.com>2017-03-14 15:40:33 -0400
commit4c87a1868835d05f1cadae7b8ad6a7c95d9d9c0e (patch)
tree4c090cd328f0695193d63832b0ff26c6f2f7207b
parenta04a74f8039947b0de64bab7756904ef424ab18c (diff)
downloadtboot-4c87a1868835d05f1cadae7b8ad6a7c95d9d9c0e.zip
tboot-4c87a1868835d05f1cadae7b8ad6a7c95d9d9c0e.tar.gz
tboot-4c87a1868835d05f1cadae7b8ad6a7c95d9d9c0e.tar.bz2
Initial commit of EFI TBOOT work from internal project.
Signed-off-by: Ross Philipson <philipsonr@ainfosec.com>
-rw-r--r--README167
-rw-r--r--tboot/Makefile49
-rw-r--r--tboot/README213
-rw-r--r--tboot/acmod.c991
-rw-r--r--tboot/acpi.c482
-rw-r--r--tboot/bits.S166
-rw-r--r--tboot/cmdline.c606
-rw-r--r--tboot/com.c134
-rw-r--r--tboot/efiboot.c613
-rw-r--r--tboot/eficonfig.c299
-rw-r--r--tboot/eficore.c534
-rw-r--r--tboot/efimemmap.c276
-rw-r--r--tboot/errors.c285
-rwxr-xr-xtboot/genlds.sh19
-rw-r--r--tboot/hash.c193
-rw-r--r--tboot/heap.c818
-rw-r--r--tboot/include/acpi.h518
-rw-r--r--tboot/include/atomic.h181
-rw-r--r--tboot/include/cmdline.h76
-rw-r--r--tboot/include/com.h311
-rw-r--r--tboot/include/compiler.h52
-rw-r--r--tboot/include/config.h133
-rw-r--r--tboot/include/ctype.h103
-rw-r--r--tboot/include/efibase.h46
-rw-r--r--tboot/include/eficonfig.h109
-rw-r--r--tboot/include/eficore.h134
-rw-r--r--tboot/include/hash.h123
-rw-r--r--tboot/include/integrity.h106
-rw-r--r--tboot/include/io.h91
-rw-r--r--tboot/include/lcp3.h282
-rw-r--r--tboot/include/lcp3_hlp.h117
-rw-r--r--tboot/include/misc.h95
-rw-r--r--tboot/include/mle.h96
-rw-r--r--tboot/include/msr.h90
-rw-r--r--tboot/include/mutex.h58
-rw-r--r--tboot/include/page.h66
-rw-r--r--tboot/include/paging.h122
-rw-r--r--tboot/include/pci_cfgreg.h73
-rw-r--r--tboot/include/printk.h79
-rw-r--r--tboot/include/processor.h340
-rw-r--r--tboot/include/rijndael.h58
-rw-r--r--tboot/include/sha1.h77
-rw-r--r--tboot/include/sha256.h30
-rw-r--r--tboot/include/string.h73
-rw-r--r--tboot/include/tb_error.h89
-rw-r--r--tboot/include/tb_policy.h388
-rw-r--r--tboot/include/tboot.h197
-rw-r--r--tboot/include/tpm.h521
-rw-r--r--tboot/include/tpm_20.h1503
-rw-r--r--tboot/include/txt/acmod.h195
-rw-r--r--tboot/include/txt/config_regs.h240
-rw-r--r--tboot/include/txt/errorcode.h105
-rw-r--r--tboot/include/txt/heap.h377
-rw-r--r--tboot/include/txt/mtrrs.h149
-rw-r--r--tboot/include/txt/smx.h171
-rw-r--r--tboot/include/txt/txt.h76
-rw-r--r--tboot/include/txt/verify.h57
-rw-r--r--tboot/include/txt/vmcs.h346
-rw-r--r--tboot/include/types.h104
-rw-r--r--tboot/include/uuid.h82
-rw-r--r--tboot/include/vga.h87
-rw-r--r--tboot/include/vmac.h168
-rw-r--r--tboot/launch.S484
-rw-r--r--tboot/misc.c455
-rw-r--r--tboot/mtrrs.c624
-rw-r--r--tboot/pci_cfgreg.c173
-rw-r--r--tboot/policy.c879
-rw-r--r--tboot/printk.c195
-rw-r--r--tboot/rijndael.c1270
-rw-r--r--tboot/sha1.c265
-rw-r--r--tboot/sha256.c242
-rw-r--r--tboot/string.c204
-rw-r--r--tboot/tb_error.c196
-rw-r--r--tboot/tboot.c473
-rw-r--r--tboot/tboot.cfg17
-rw-r--r--tboot/tpm.c911
-rw-r--r--tboot/tpm_12.c1952
-rw-r--r--tboot/tpm_20.c2406
-rw-r--r--tboot/txt.c755
-rw-r--r--tboot/verify.c601
-rw-r--r--tboot/vga.c140
-rw-r--r--tboot/vmac.c1228
-rw-r--r--tboot/vmcs.c603
-rw-r--r--tboot/vsprintf.c465
-rw-r--r--xen/series2
-rw-r--r--xen/xen-efi-build.patch54
-rw-r--r--xen/xen-efi-tboot-launch.patch284
-rwxr-xr-xxen/xen.cfg7
88 files changed, 29224 insertions, 0 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..3653688
--- /dev/null
+++ b/README
@@ -0,0 +1,167 @@
+==============================================================================
+ __ _ _ _ _
+ / _(_) | | | | | |
+ ___| |_ _ ______| |_| |__ ___ ___ | |_
+ / _ \ _| |______| __| '_ \ / _ \ / _ \| __|
+ | __/ | | | | |_| |_) | (_) | (_) | |_
+ \___|_| |_| \__|_.__/ \___/ \___/ \__|
+
+==============================================================================
+
+ --- EFI TBOOT ---
+
+ /!\ The EFI TBOOT project is currently under development /!\
+
+EFI TBOOT is mostly a proof of concept at this point. It is not currently
+functional. It can be built and installed as an EFI boot loader. It only works
+in conjunction with Xen at the moment. The current development work is being
+done on Fedora 25 x64.
+
+The status as of March 14, 2017 is:
+ - EFI TBOOT will boot, but it needs a few key strokes to get getting
+ going (this is for debugging purposes).
+ - EFI TBOOT will relocate itself to EFI runtime memory and setup a shared
+ runtime variable with Xen.
+ - EFI related configuration setup is done as well as standard TBOOT pre-
+ launch configuration.
+ - Xen is launched and has code to call EFI TBOOT back after EBS.
+ - EFI TBOOT then does the SENTER successfully in the callback.
+ - The post launch entry point is reached but the switch back to long mode
+ is not working.
+
+ --- Get EFI TBOOT ---
+
+The efi-tboot repository can be found here (though if you are reading this you
+probably already know that):
+
+https://github.com/rossphilipson/efi-tboot
+
+$ git clone https://github.com/rossphilipson/efi-tboot.git
+
+Contents:
+
+README - this file
+tboot - all the sources and supporting files for EFI TBOOT
+xen - patches and support files for Xen
+
+ --- Install Xen ---
+
+Xen will be patched, built and installed from sources. Get the Xen 4.7.1
+tarball:
+
+https://www.xenproject.org/downloads/xen-archives/xen-project-47-series/xen-471.html
+
+Install some needed packages to build and configure everything:
+
+$ sudo dnf builddep xen
+$ sudo dnf builddep kernel
+$ sudo dnf install mingw64-binutils.x86_64
+$ sudo dnf install mingw64-gcc.x86_64
+$ sudo dnf install mtools.x86_64
+$ sudo dnf install efibootmgr
+
+Get the latest gnu-efi package, make and install it (see README.gnuefi in the
+project). Note Fedora had a gnu-efi RPM but these was some issue with it.
+Using the latest and building it is working fine.
+
+https://sourceforge.net/projects/gnu-efi/
+
+Xen needs to be patched with the patches found under efi-tboot/xen. Use quilt:
+
+$ cd xen-4.7.1
+$ mkdir patches
+$ cp ../efi-tboot/xen/*.patch patch
+$ cp ../efi-tboot/xen/series patch
+$ quilt push -a
+
+Build and install the Xen tools:
+
+$ ./configure --prefix=/usr --libdir=/usr/lib64 --enable-systemd
+$ make dist-tools
+$ sudo make install-tools
+
+Note had to comment a bunch of modules here: /lib/modules-load.d/xen.conf
+
+#evtchn
+#gntdev
+#netbk
+#blkbk
+#xen-scsibk
+#usbbk
+#pciback
+#blktap2
+
+At this point, building Xen is more or less following the instructions here:
+
+https://wiki.xenproject.org/index.php?title=Xen_EFI&oldid=14685
+
+Note this is an early version of the instructions which is being used. The
+xen.fedora.efi.build.patch patch mentioned here is already in the efi-tboot
+patch set for Xen and applied above. We will sort out build issues like using
+the new instructions later. To build and install:
+
+$ LD_EFI=/usr/x86_64-w64-mingw32/bin/ld make xen
+$ sudo mkdir /boot/efi/EFI/Xen
+$ sudo cp /boot/vmlinuz* /boot/efi/EFI/Xen
+$ sudo cp /boot/initr* /boot/efi/EFI/Xen
+$ sudo cp xen/xen.efi /boot/efi/EFI/Xen
+$ cp ../efi-tboot/xen/xen.cfg /boot/efi/EFI/Xen
+
+Make sure the kernel and initrd lines in the xen.cfg match the ones on your
+platform. Next, create new EFI boot target:
+
+$ efibootmgr -w -L Xen -l "\EFI\Xen\xen.efi" -c
+
+The efibootmgr tool can me used to manage and re-order the EFI boot
+targets. See the man page and help for more details.
+
+Enable the needed Xen services:
+
+$ systemctl enable xenstored.socket
+$ systemctl enable xenconsoled
+$ systemctl enable xen-init-dom0
+$ systemctl start xenstored.socket
+$ systemctl start xenconsoled
+$ systemctl start xen-init-dom0
+
+Reboot and choose Xen from the EFI boot manager.
+
+ --- Install EFI TBOOT ---
+
+Build and install EFI TBOOT and needed support files:
+
+$ cd efi-tboot/tboot
+$ make
+$ sudo mkdir /boot/efi/EFI/TBOOT
+$ sudo cp tboot.efi /boot/efi/EFI/TBOOT
+$ cp tboot.cfg /boot/efi/EFI/TBOOT
+
+Create new EFI boot target:
+
+$ efibootmgr -w -L TBOOT -l "\EFI\TBOOT\tboot.efi" -c
+
+EFI TBOOT needs a number of platform support files used with TXT (called
+Authenticated Code Modules or ACMs). For convenience the packages can be
+gotten from the OpenXT mirror:
+
+http://mirror.openxt.org/
+
+Download:
+
+5-i7-sinit-67.zip
+4th-gen-i5-i7-sinit-75.zip
+5th-gen-i5-i7-sinit_79.zip
+5th_gen_i5_i7-SINIT_79.zip
+6th_gen_i5_i7-SINIT_71.zip
+7th_gen_i5_i7-SINIT_74.zip
+GM45_GS45_PM45-SINIT_51.zip
+Q35-SINIT_51.zip
+Q45_Q43-SINIT_51.zip
+Xeon-5600-3500-SINIT-v1.1.zip
+Xeon-E7-8800-4800-2800-SINIT-v1.1.zip
+i5_i7_DUAL-SINIT_51.zip
+i7_QUAD-SINIT_51.zip
+
+Each package must be unzipped and the .bin or .BIN file in the package needs
+to be copied to /boot/efi/EFI/TBOOT
+
diff --git a/tboot/Makefile b/tboot/Makefile
new file mode 100644
index 0000000..fdae048
--- /dev/null
+++ b/tboot/Makefile
@@ -0,0 +1,49 @@
+# Build with GCC compiler, note .rodata section in .lds file
+#CC = gcc
+# Build with MinGW compiler, note .rdata section in .lds file
+CC = x86_64-w64-mingw32-gcc
+LD = x86_64-w64-mingw32-ld
+CFLAGS = -ffreestanding -fPIE -fno-exceptions -fshort-wchar -mno-ms-bitfields -DTPM_TRACE
+CFLAGS += -I/usr/include/efi -I/usr/include/efi/x86_64 -I/usr/include/efi/protocol -Iinclude
+AFLAGS = -D__ASSEMBLY__ $(patsubst -std=gnu%,,$(CFLAGS))
+#LDFLAGS = -nostdlib -Wl,-pie -shared -Wl,--no-seh -Wl,--subsystem,10 -e efi_main
+LDFLAGS = -nostdlib -pie -shared --no-seh --subsystem=10 -e efi_main
+ASM = launch.S bits.S # must be in order
+SRC = $(wildcard *.c)
+OBJ = $(ASM:.S=.o) # must be first
+OBJ += $(SRC:.c=.o)
+
+# Banner
+CFLAGS += -DTBOOT_CHANGESET=\""$(shell ((hg parents --template "{isodate|isodate} {rev}:{node|short}" >/dev/null && hg parents --template "{isodate|isodate} {rev}:{node|short}") || echo "2016-05-18 12:00 -0800 1.9.4") 2>/dev/null)"\"
+
+
+.PHONY: all
+all: tboot.lds tboot.efi tboot.dsm
+
+tboot.efi: $(OBJ)
+ $(LD) tboot.lds $(LDFLAGS) $^ -o $@
+
+# With lds
+#tboot.efi: $(OBJ)
+# $(CC) -T lds/tboot2.lds $(LDFLAGS) $^ -o $@
+# $(CC) -Wl,lds/tboot2.lds $(LDFLAGS) $^ -o $@
+
+# Grrr someone is frobbing the stack
+tpm_20.o: tpm_20.c
+ $(CC) $(CFLAGS) -mno-stack-arg-probe -o $@ -c $<
+
+%.o: %.c
+ $(CC) $(CFLAGS) -o $@ -c $<
+
+%.o: %.S
+ $(CC) $(AFLAGS) -c $< -o $@
+
+tboot.lds:
+ $(PWD)/genlds.sh $(CC)
+
+tboot.dsm:
+ mingw-objdump -d tboot.efi > tboot.dsm
+
+.PHONY: clean
+clean:
+ rm -f tboot.efi *.o tboot.dsm tboot.lds
diff --git a/tboot/README b/tboot/README
new file mode 100644
index 0000000..6722143
--- /dev/null
+++ b/tboot/README
@@ -0,0 +1,213 @@
+###############################################################################
+Diffs
+
+include/types.h
+ ifdef NULL
+ Added wchar_t
+ Added TODO about x64
+ Changed uintptr_t and size_t to 64b
+
+include/acpi.h
+ Removed extern
+
+include/com.h
+ Removed extern
+
+include/vmac.h
+ Removed extern "C" and C++ stuff
+
+include/hash.h
+ Removed extern
+
+include/integrity.h
+ Removed extern
+
+include/printk.h
+ Removed extern
+
+include/misc.h
+ Removed extern
+
+include/tb_error.h
+ Removed extern
+
+include/tpm.h
+ Removed extern
+ Set tboot_alg_list size to 2
+
+include/tpm_20.h
+ Removed TRUE/FALSE
+
+include/tboot.h
+ Removed extern
+ TODO about tboot/xen shared struct
+
+include/sha1.h
+ Removed extern
+
+include/page.h
+ Use unsigned long long for PAGE UP/DOWN casts.
+
+include/ctype.h
+ Removed extern and use CTYPE_SIZE
+
+include/config.h
+ TODO about setting _start, _end
+ TODO about removing hard coded image locations.
+ Removed a bunch of old layout defines
+ All new layout map at top
+ Changed to .data# and .text# (see https://gcc.gnu.org/ml/gcc-help/2010-09/msg00088.html)
+ Removed __mlept section.
+
+include/cmdline.h
+ Stub out min_ram stuff for now
+ Removed extern
+
+include/msr.h
+ Move rd/wrmsr to assembly module
+
+include/tboot.h
+ Removed zip shit and made log buffer 0x8000, added is_init
+ Change name to begin_initial_launch
+
+include/mutex.h
+ Use 64b mutex obj
+
+include/processor.h
+ Fix 32b things - left orig commented out or comments
+ cpuid bits are fine in 64b
+
+include/txt/config_regs.h
+ TODO about warning, changed to ull
+
+include/txt/vmcs.h
+ Added ap_lock
+
+include/txt/heap.h
+ TODO about warning, changed to ull
+ Removed extern, lctx_addr
+
+include/txt/txt.h
+ TODO about loader_ctx
+ Removed extern
+ Added ap_wfs_count
+
+include/txt/acmod.h
+ Removed extern <function>
+
+include/txt/verify.h
+ Removed extern
+
+include/txt/smx.h
+ Removed extern
+
+include/txt/vmcs.h
+ Removed extern
+
+include/txt/mtrrs.h
+ Removed extern
+
+acpi.c
+ Increased to uint64_t for readl/writel etc.
+ Used unsigned long long when assigning wakeup_vector
+ Did return (struct acpi_rsdt *)(uint64_t)rsdp->rsdp1.rsdt;
+ Use EFI to get RSDP
+ Added cast to uint64_t* of ACPI struct
+
+printk.c
+ Replaced memlog with 1.7.4 one and inlined the buffer in the struct
+
+misc.c
+ Use CTYPE_SIZE for _ctype array size
+
+mtrr.c
+ Use read/write rflags
+ Fix 3 casts w/ unsigned long long
+
+vsnprintf.c
+ Cast arg in call to div64
+
+com.c
+ Removed extern
+
+policy.c
+ Fix lcp pointer in unwrap_lcp_policy unsigned long long
+ Switch to efi_launch_kernel (pre EBS only)
+ Fix externs, move to headers
+ Stub out verify modules function
+ Stub out bits of verify_module function and fix args
+ Call new LCP getter
+
+verify.c
+ Fix inline asm at top getting RFLAGS
+ Stubb out a bunch of e820 related functions w/ TODOs
+
+vmac.c
+ Removed redef of ALIGN and UINT64_C
+
+paging.c
+ Fix for 64b use unsigned long long
+
+mutex.S
+ Had to rewrite as 64b code
+ Merged into basics.S and gone
+
+tpm.c
+ Stubbed some crap so it builds, see TODOs
+ Set tboot_alg_list size to 2
+
+tpm_12.c
+ Stubbed some crap so it builds, see TODOs
+
+tpm_20.c
+ Removed loader.h and loader ctx extern (not needed)
+ Had to use -mno-stack-arg-probe to fix stack problems
+ Stubbed some crap so it builds, see TODOs
+
+hash.c
+ Modified stack buffer to not be stupid
+
+acmod.c
+ Modified a number of pointer casts to ull
+ See existing TODO about racm
+ Move global g_sinit here from txt.c
+
+heap.c
+ Removed include multiboot.h, lctx_addr check
+ Modified a number of pointer casts to ull
+ Fixed calls to verify_ext_data_elts with extra sizeof(size)
+
+error.c
+ Removed include loader.h
+ Added atomic.h inclue
+
+cmdline.c
+ Stub out min_ram stuff for now
+
+vga.c
+ Change from int to long long for writew/readw
+
+###############################################################################
+Special
+
+The following were put together bit by bit so changes are not tracked here:
+
+tboot.c
+txt.c
+
+Several small string modules were merged into string.c:
+strlen.c
+strcmp.c
+strncmp.c
+strncpy.c
+strtoul.c
+index.c
+memcmp.c
+
+###############################################################################
+--- Issues ---
+
+ - Had to initialize the cmdline to defaults otherwise the calls before loading
+the cmdline were returning garbage.
+
+ - Trying to init mwait was causing hangs on writemsr.
diff --git a/tboot/acmod.c b/tboot/acmod.c
new file mode 100644
index 0000000..6601222
--- /dev/null
+++ b/tboot/acmod.c
@@ -0,0 +1,991 @@
+/*
+ * acmod.c: support functions for use of Intel(r) TXT Authenticated
+ * Code (AC) Modules
+ *
+ * Copyright (c) 2003-2011, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef IS_INCLUDED /* defined in utils/acminfo.c */
+#include <config.h>
+#include <efibase.h>
+#include <types.h>
+#include <stdbool.h>
+#include <printk.h>
+#include <compiler.h>
+#include <string.h>
+#include <processor.h>
+#include <msr.h>
+#include <misc.h>
+#include <uuid.h>
+#include <mle.h>
+#include <hash.h>
+#include <txt/acmod.h>
+#include <txt/config_regs.h>
+#include <txt/mtrrs.h>
+#include <txt/heap.h>
+#include <txt/smx.h>
+#include <tpm.h>
+#endif /* IS_INCLUDED */
+
+__data acm_hdr_t *g_sinit = 0;
+
+static acm_info_table_t *get_acmod_info_table(const acm_hdr_t* hdr)
+{
+ uint32_t user_area_off;
+
+ /* overflow? */
+ if ( plus_overflow_u32(hdr->header_len, hdr->scratch_size) ) {
+ printk(TBOOT_ERR"ACM header length plus scratch size overflows\n");
+ return NULL;
+ }
+
+ if ( multiply_overflow_u32((hdr->header_len + hdr->scratch_size), 4) ) {
+ printk(TBOOT_ERR"ACM header length and scratch size in bytes overflows\n");
+ return NULL;
+ }
+
+
+ /* this fn assumes that the ACM has already passed at least the initial */
+ /* is_acmod() checks */
+
+ user_area_off = (hdr->header_len + hdr->scratch_size) * 4;
+
+ /* overflow? */
+ if ( plus_overflow_u32(user_area_off, sizeof(acm_info_table_t)) ) {
+ printk(TBOOT_ERR"user_area_off plus acm_info_table_t size overflows\n");
+ return NULL;
+ }
+
+ /* check that table is within module */
+ if ( user_area_off + sizeof(acm_info_table_t) > hdr->size*4 ) {
+ printk(TBOOT_ERR"ACM info table size too large: %x\n",
+ user_area_off + (uint32_t)sizeof(acm_info_table_t));
+ return NULL;
+ }
+
+ /* overflow? */
+ if ( plus_overflow_u64((uint64_t)(uintptr_t)hdr, user_area_off) ) {
+ printk(TBOOT_ERR"hdr plus user_area_off overflows\n");
+ return NULL;
+ }
+
+ return (acm_info_table_t *)((unsigned long long)hdr + user_area_off);
+}
+
+static acm_chipset_id_list_t *get_acmod_chipset_list(const acm_hdr_t* hdr)
+{
+ acm_info_table_t* info_table;
+ uint32_t size, id_list_off;
+ acm_chipset_id_list_t *chipset_id_list;
+
+ /* this fn assumes that the ACM has already passed the is_acmod() checks */
+
+ info_table = get_acmod_info_table(hdr);
+ if ( info_table == NULL )
+ return NULL;
+ id_list_off = info_table->chipset_id_list;
+
+ size = hdr->size * 4;
+
+ /* overflow? */
+ if ( plus_overflow_u32(id_list_off, sizeof(acm_chipset_id_t)) ) {
+ printk(TBOOT_ERR"id_list_off plus acm_chipset_id_t size overflows\n");
+ return NULL;
+ }
+
+ /* check that chipset id table is w/in ACM */
+ if ( id_list_off + sizeof(acm_chipset_id_t) > size ) {
+ printk(TBOOT_ERR"ACM chipset id list is too big: chipset_id_list=%x\n",
+ id_list_off);
+ return NULL;
+ }
+
+ /* overflow? */
+ if ( plus_overflow_u64((uint64_t)(uintptr_t)hdr, id_list_off) ) {
+ printk(TBOOT_ERR"hdr plus id_list_off overflows\n");
+ return NULL;
+ }
+
+ chipset_id_list = (acm_chipset_id_list_t *)
+ ((unsigned long long)hdr + id_list_off);
+
+ /* overflow? */
+ if ( multiply_overflow_u32(chipset_id_list->count,
+ sizeof(acm_chipset_id_t)) ) {
+ printk(TBOOT_ERR"size of acm_chipset_id_list overflows\n");
+ return NULL;
+ }
+ if ( plus_overflow_u32(id_list_off + sizeof(acm_chipset_id_t),
+ chipset_id_list->count * sizeof(acm_chipset_id_t)) ) {
+ printk(TBOOT_ERR"size of all entries overflows\n");
+ return NULL;
+ }
+
+ /* check that all entries are w/in ACM */
+ if ( id_list_off + sizeof(acm_chipset_id_t) +
+ chipset_id_list->count * sizeof(acm_chipset_id_t) > size ) {
+ printk(TBOOT_ERR"ACM chipset id entries are too big:"
+ " chipset_id_list->count=%x\n", chipset_id_list->count);
+ return NULL;
+ }
+
+ return chipset_id_list;
+}
+
+static acm_processor_id_list_t *get_acmod_processor_list(const acm_hdr_t* hdr)
+{
+ acm_info_table_t* info_table;
+ uint32_t size, id_list_off;
+ acm_processor_id_list_t *proc_id_list;
+
+ /* this fn assumes that the ACM has already passed the is_acmod() checks */
+
+ info_table = get_acmod_info_table(hdr);
+ if ( info_table == NULL )
+ return NULL;
+ id_list_off = info_table->processor_id_list;
+
+ size = hdr->size * 4;
+
+ /* overflow? */
+ if ( plus_overflow_u32(id_list_off, sizeof(acm_processor_id_t)) ) {
+ printk(TBOOT_ERR"id_list_off plus acm_processor_id_t size overflows\n");
+ return NULL;
+ }
+
+ /* check that processor id table is w/in ACM */
+ if ( id_list_off + sizeof(acm_processor_id_t) > size ) {
+ printk(TBOOT_ERR"ACM processor id list is too big: processor_id_list=%x\n",
+ id_list_off);
+ return NULL;
+ }
+
+ /* overflow? */
+ if ( plus_overflow_u64((unsigned long long)hdr, id_list_off) ) {
+ printk(TBOOT_ERR"hdr plus id_list_off overflows\n");
+ return NULL;
+ }
+
+ proc_id_list = (acm_processor_id_list_t *)
+ ((unsigned long long)hdr + id_list_off);
+
+ /* overflow? */
+ if ( multiply_overflow_u32(proc_id_list->count,
+ sizeof(acm_processor_id_t)) ) {
+ printk(TBOOT_ERR"size of acm_processor_id_list overflows\n");
+ return NULL;
+ }
+ if ( plus_overflow_u32(id_list_off + sizeof(acm_processor_id_t),
+ proc_id_list->count * sizeof(acm_processor_id_t)) ) {
+ printk(TBOOT_ERR"size of all entries overflows\n");
+ return NULL;
+ }
+
+ /* check that all entries are w/in ACM */
+ if ( id_list_off + sizeof(acm_processor_id_t) +
+ proc_id_list->count * sizeof(acm_processor_id_t) > size ) {
+ printk(TBOOT_ERR"ACM processor id entries are too big:"
+ " proc_id_list->count=%x\n", proc_id_list->count);
+ return NULL;
+ }
+
+ return proc_id_list;
+}
+
+tpm_info_list_t *get_tpm_info_list(const acm_hdr_t* hdr)
+{
+ acm_info_table_t* info_table;
+ uint32_t size, tpm_info_off;
+ tpm_info_list_t *tpm_info;
+
+ /* this fn assumes that the ACM has already passed the is_acmod() checks */
+
+ info_table = get_acmod_info_table(hdr);
+ if ( info_table == NULL )
+ return NULL;
+ tpm_info_off = info_table->tpm_info_list_off;
+
+ size = hdr->size * 4;
+
+ /* overflow? */
+ if ( plus_overflow_u32(tpm_info_off, sizeof(tpm_info_list_t)) ) {
+ printk("tpm_info_off plus tpm_info_list_t size overflows\n");
+ return NULL;
+ }
+
+ /* check that tpm info list is w/in ACM */
+ if ( tpm_info_off + sizeof(tpm_info_list_t) > size ) {
+ printk("TPM info list is too big: tpm_info_list=%x\n",
+ tpm_info_off);
+ return NULL;
+ }
+
+ /* overflow? */
+ if ( plus_overflow_u64((unsigned long long)hdr, tpm_info_off) ) {
+ printk("hdr plus tpm_info_off overflows\n");
+ return NULL;
+ }
+
+ tpm_info = (tpm_info_list_t *)
+ ((unsigned long long)hdr + tpm_info_off);
+
+ /* overflow? */
+ if ( multiply_overflow_u32(tpm_info->count,
+ sizeof(uint16_t)) ) {
+ printk("size of tpm_info_list overflows\n");
+ return NULL;
+ }
+ if ( plus_overflow_u32(tpm_info_off + sizeof(tpm_info_list_t),
+ tpm_info->count * sizeof(uint16_t)) ) {
+ printk("size of all entries overflows\n");
+ return NULL;
+ }
+
+ /* check that all entries are w/in ACM */
+ if ( tpm_info_off + sizeof(tpm_info_list_t) +
+ tpm_info->count * sizeof(uint16_t) > size ) {
+ printk("TPM info list entries are too big:"
+ " tpm_info_list->count=%x\n", tpm_info->count);
+ return NULL;
+ }
+
+ return tpm_info;
+}
+
+void print_txt_caps(const char *prefix, txt_caps_t caps)
+{
+ printk(TBOOT_DETA"%scapabilities: 0x%08x\n", prefix, caps._raw);
+ printk(TBOOT_DETA"%s rlp_wake_getsec: %d\n", prefix, caps.rlp_wake_getsec);
+ printk(TBOOT_DETA"%s rlp_wake_monitor: %d\n", prefix, caps.rlp_wake_monitor);
+ printk(TBOOT_DETA"%s ecx_pgtbl: %d\n", prefix, caps.ecx_pgtbl);
+ printk(TBOOT_DETA"%s stm: %d\n", prefix, caps.stm);
+ printk(TBOOT_DETA"%s pcr_map_no_legacy: %d\n", prefix, caps.pcr_map_no_legacy);
+ printk(TBOOT_DETA"%s pcr_map_da: %d\n", prefix, caps.pcr_map_da);
+ printk(TBOOT_DETA"%s platform_type: %d\n", prefix, caps.platform_type);
+ printk(TBOOT_DETA"%s max_phy_addr: %d\n", prefix, caps.max_phy_addr);
+}
+
+static void print_acm_hdr(const acm_hdr_t *hdr, const char *mod_name)
+{
+ acm_info_table_t *info_table;
+
+ printk(TBOOT_DETA"AC module header dump for %s:\n",
+ (mod_name == NULL) ? "?" : mod_name);
+
+ /* header */
+ printk(TBOOT_DETA"\t type: 0x%x ", hdr->module_type);
+ if ( hdr->module_type == ACM_TYPE_CHIPSET )
+ printk(TBOOT_DETA"(ACM_TYPE_CHIPSET)\n");
+ else
+ printk(TBOOT_INFO"(unknown)\n");
+ printk(TBOOT_DETA"\t subtype: 0x%x ", hdr->module_subtype);
+ if ( hdr->module_subtype == ACM_SUBTYPE_RESET )
+ printk(TBOOT_INFO"(execute at reset)\n");
+ else if ( hdr->module_subtype == 0 )
+ printk(TBOOT_INFO"\n");
+ else
+ printk(TBOOT_INFO"(unknown)\n");
+ printk(TBOOT_DETA"\t length: 0x%x (%u)\n", hdr->header_len, hdr->header_len);
+ printk(TBOOT_DETA"\t version: %u\n", hdr->header_ver);
+ printk(TBOOT_DETA"\t chipset_id: 0x%x\n", (uint32_t)hdr->chipset_id);
+ printk(TBOOT_DETA"\t flags: 0x%x\n", (uint32_t)hdr->flags._raw);
+ printk(TBOOT_DETA"\t\t pre_production: %d\n", (int)hdr->flags.pre_production);
+ printk(TBOOT_DETA"\t\t debug_signed: %d\n", (int)hdr->flags.debug_signed);
+ printk(TBOOT_DETA"\t vendor: 0x%x\n", hdr->module_vendor);
+ printk(TBOOT_DETA"\t date: 0x%08x\n", hdr->date);
+ printk(TBOOT_DETA"\t size*4: 0x%x (%u)\n", hdr->size*4, hdr->size*4);
+ printk(TBOOT_DETA"\t txt_svn: 0x%08x\n", hdr->txt_svn);
+ printk(TBOOT_DETA"\t se_svn: 0x%08x\n", hdr->se_svn);
+ printk(TBOOT_DETA"\t code_control: 0x%x\n", hdr->code_control);
+ printk(TBOOT_DETA"\t entry point: 0x%08x:%08x\n", hdr->seg_sel,
+ hdr->entry_point);
+ printk(TBOOT_DETA"\t scratch_size: 0x%x (%u)\n", hdr->scratch_size,
+ hdr->scratch_size);
+
+ /* info table */
+ printk(TBOOT_DETA"\t info_table:\n");
+ info_table = get_acmod_info_table(hdr);
+ if ( info_table == NULL ) {
+ printk(TBOOT_ERR"\t\t <invalid>\n");
+ return;
+ }
+ printk(TBOOT_DETA"\t\t uuid: "); print_uuid(&info_table->uuid);
+ printk(TBOOT_DETA"\n");
+ if ( are_uuids_equal(&(info_table->uuid), &((uuid_t)ACM_UUID_V3)) )
+ printk(TBOOT_DETA"\t\t ACM_UUID_V3\n");
+ else
+ printk(TBOOT_DETA"\t\t unknown\n");
+ printk(TBOOT_DETA"\t\t chipset_acm_type: 0x%x ",
+ (uint32_t)info_table->chipset_acm_type);
+ if ( info_table->chipset_acm_type == ACM_CHIPSET_TYPE_SINIT )
+ printk(TBOOT_DETA"(SINIT)\n");
+ else if ( info_table->chipset_acm_type == ACM_CHIPSET_TYPE_BIOS )
+ printk(TBOOT_DETA"(BIOS)\n");
+ else
+ printk(TBOOT_DETA"(unknown)\n");
+ printk(TBOOT_DETA"\t\t version: %u\n", (uint32_t)info_table->version);
+ printk(TBOOT_DETA"\t\t length: 0x%x (%u)\n", (uint32_t)info_table->length,
+ (uint32_t)info_table->length);
+ printk(TBOOT_DETA"\t\t chipset_id_list: 0x%x\n", info_table->chipset_id_list);
+ printk(TBOOT_DETA"\t\t os_sinit_data_ver: 0x%x\n", info_table->os_sinit_data_ver);
+ printk(TBOOT_DETA"\t\t min_mle_hdr_ver: 0x%08x\n", info_table->min_mle_hdr_ver);
+ print_txt_caps("\t\t ", info_table->capabilities);
+ printk(TBOOT_DETA"\t\t acm_ver: %u\n", (uint32_t)info_table->acm_ver);
+
+ /* chipset list */
+ printk(TBOOT_DETA"\t chipset list:\n");
+ acm_chipset_id_list_t *chipset_id_list = get_acmod_chipset_list(hdr);
+ if ( chipset_id_list == NULL ) {
+ printk(TBOOT_ERR"\t\t <invalid>\n");
+ return;
+ }
+ printk(TBOOT_DETA"\t\t count: %u\n", chipset_id_list->count);
+ for ( unsigned int i = 0; i < chipset_id_list->count; i++ ) {
+ printk(TBOOT_DETA"\t\t entry %u:\n", i);
+ acm_chipset_id_t *chipset_id = &(chipset_id_list->chipset_ids[i]);
+ printk(TBOOT_DETA"\t\t flags: 0x%x\n", chipset_id->flags);
+ printk(TBOOT_DETA"\t\t vendor_id: 0x%x\n", (uint32_t)chipset_id->vendor_id);
+ printk(TBOOT_DETA"\t\t device_id: 0x%x\n", (uint32_t)chipset_id->device_id);
+ printk(TBOOT_DETA"\t\t revision_id: 0x%x\n",
+ (uint32_t)chipset_id->revision_id);
+ printk(TBOOT_DETA"\t\t extended_id: 0x%x\n", chipset_id->extended_id);
+ }
+
+ if ( info_table->version >= 4 ) {
+ /* processor list */
+ printk(TBOOT_DETA"\t processor list:\n");
+ acm_processor_id_list_t *proc_id_list = get_acmod_processor_list(hdr);
+ if ( proc_id_list == NULL ) {
+ printk(TBOOT_ERR"\t\t <invalid>\n");
+ return;
+ }
+ printk(TBOOT_DETA"\t\t count: %u\n", proc_id_list->count);
+ for ( unsigned int i = 0; i < proc_id_list->count; i++ ) {
+ printk(TBOOT_DETA"\t\t entry %u:\n", i);
+ acm_processor_id_t *proc_id = &(proc_id_list->processor_ids[i]);
+ printk(TBOOT_DETA"\t\t fms: 0x%x\n", proc_id->fms);
+ printk(TBOOT_DETA"\t\t fms_mask: 0x%x\n", proc_id->fms_mask);
+ printk(TBOOT_DETA"\t\t platform_id: 0x%Lx\n", (unsigned long long)proc_id->platform_id);
+ printk(TBOOT_DETA"\t\t platform_mask: 0x%Lx\n", (unsigned long long)proc_id->platform_mask);
+ }
+ }
+
+ if ( info_table->version >= 5 ){
+ /* tpm infor list */
+ printk(TBOOT_DETA"\t TPM info list:\n");
+ tpm_info_list_t *info_list = get_tpm_info_list(hdr);
+ if ( info_list == NULL ) {
+ printk(TBOOT_ERR"\t\t <invalid>\n");
+ return;
+ }
+ printk(TBOOT_DETA"\t\t TPM capability:\n");
+ printk(TBOOT_DETA"\t\t ext_policy: 0x%x\n", info_list->capabilities.ext_policy);
+ printk(TBOOT_DETA"\t\t tpm_family : 0x%x\n", info_list->capabilities.tpm_family);
+ printk(TBOOT_DETA"\t\t tpm_nv_index_set : 0x%x\n", info_list->capabilities.tpm_nv_index_set);
+ printk(TBOOT_DETA"\t\t alg count: %u\n", info_list->count);
+ for ( unsigned int i = 0; i < info_list->count; i++ ) {
+ printk(TBOOT_DETA"\t\t alg_id: 0x%x\n", info_list->alg_id[i]);
+ }
+ }
+}
+
+uint32_t get_supported_os_sinit_data_ver(const acm_hdr_t* hdr)
+{
+ /* assumes that it passed is_sinit_acmod() */
+
+ acm_info_table_t *info_table = get_acmod_info_table(hdr);
+ if ( info_table == NULL )
+ return 0;
+
+ return info_table->os_sinit_data_ver;
+}
+
+txt_caps_t get_sinit_capabilities(const acm_hdr_t* hdr)
+{
+ /* assumes that it passed is_sinit_acmod() */
+
+ acm_info_table_t *info_table = get_acmod_info_table(hdr);
+ if ( info_table == NULL || info_table->version < 3 )
+ return (txt_caps_t){ 0 };
+
+ return info_table->capabilities;
+}
+
+static bool is_acmod(const void *acmod_base, uint32_t acmod_size, uint8_t *type, bool quiet)
+{
+ acm_hdr_t *acm_hdr = (acm_hdr_t *)acmod_base;
+
+ /* first check size */
+ if ( acmod_size < sizeof(acm_hdr_t) ) {
+ if ( !quiet )
+ printk(TBOOT_ERR"\t ACM size is too small: acmod_size=%x,"
+ " sizeof(acm_hdr)=%x\n", acmod_size,
+ (uint32_t)sizeof(acm_hdr) );
+ return false;
+ }
+
+ /* then check overflow */
+ if ( multiply_overflow_u32(acm_hdr->size, 4) ) {
+ if ( !quiet )
+ printk(TBOOT_ERR"\t ACM header size in bytes overflows\n");
+ return false;
+ }
+
+ /* then check size equivalency */
+ if ( acmod_size != acm_hdr->size * 4 ) {
+ if ( !quiet )
+ printk(TBOOT_ERR"\t ACM size is too small: acmod_size=%x,"
+ " acm_hdr->size*4=%x\n", acmod_size, acm_hdr->size*4);
+ return false;
+ }
+
+ /* then check type and vendor */
+ if ( (acm_hdr->module_type != ACM_TYPE_CHIPSET) ||
+ (acm_hdr->module_vendor != ACM_VENDOR_INTEL) ) {
+ if ( !quiet )
+ printk(TBOOT_ERR"\t ACM type/vendor mismatch: module_type=%x,"
+ " module_vendor=%x\n", acm_hdr->module_type,
+ acm_hdr->module_vendor);
+ return false;
+ }
+
+ acm_info_table_t *info_table = get_acmod_info_table(acm_hdr);
+ if ( info_table == NULL )
+ return false;
+
+ /* check if ACM UUID is present */
+ if ( !are_uuids_equal(&(info_table->uuid), &((uuid_t)ACM_UUID_V3)) ) {
+ if ( !quiet ) {
+ printk(TBOOT_ERR"\t unknown UUID: "); print_uuid(&info_table->uuid);
+ printk(TBOOT_ERR"\n");
+ }
+ return false;
+ }
+
+ if ( type != NULL )
+ *type = info_table->chipset_acm_type;
+
+ if ( info_table->version < 3 ) {
+ if ( !quiet )
+ printk(TBOOT_ERR"\t ACM info_table version unsupported (%u)\n",
+ (uint32_t)info_table->version);
+ return false;
+ }
+ /* there is forward compatibility, so this is just a warning */
+ else if ( info_table->version > 5 ) {
+ if ( !quiet )
+ printk(TBOOT_WARN"\t ACM info_table version mismatch (%u)\n",
+ (uint32_t)info_table->version);
+ }
+
+ return true;
+}
+
+bool is_racm_acmod(const void *acmod_base, uint32_t acmod_size, bool quiet)
+{
+ uint8_t type;
+
+ if ( !is_acmod(acmod_base, acmod_size, &type, quiet) )
+ return false;
+
+ if ( type != ACM_CHIPSET_TYPE_BIOS_REVOC &&
+ type != ACM_CHIPSET_TYPE_SINIT_REVOC ) {
+ printk(TBOOT_ERR"ACM is not an revocation ACM (%x)\n", type);
+ return false;
+ }
+
+ if ( acmod_size != 0x8000 && acmod_size != 0x10000 ) {
+ printk(TBOOT_ERR"ACM is not an RACM, bad size (0x%x)\n", acmod_size);
+ return false;
+ }
+
+ return true;
+}
+
+bool is_sinit_acmod(const void *acmod_base, uint32_t acmod_size, bool quiet)
+{
+ uint8_t type;
+
+ if ( !is_acmod(acmod_base, acmod_size, &type, quiet) )
+ return false;
+
+ if ( type != ACM_CHIPSET_TYPE_SINIT ) {
+ printk(TBOOT_ERR"ACM is not an SINIT ACM (%x)\n", type);
+ return false;
+ }
+
+ return true;
+}
+
+bool does_acmod_match_platform(const acm_hdr_t* hdr)
+{
+ /* used to ensure we don't print chipset/proc info for each module */
+ static bool printed_host_info;
+
+ /* this fn assumes that the ACM has already passed the is_acmod() checks */
+
+ /* get chipset fusing, device, and vendor id info */
+ txt_didvid_t didvid;
+ didvid._raw = read_pub_config_reg(TXTCR_DIDVID);
+ txt_ver_fsbif_qpiif_t ver;
+ ver._raw = read_pub_config_reg(TXTCR_VER_FSBIF);
+ if ( (ver._raw & 0xffffffff) == 0xffffffff ||
+ (ver._raw & 0xffffffff) == 0x00 ) /* need to use VER.QPIIF */
+ ver._raw = read_pub_config_reg(TXTCR_VER_QPIIF);
+ if ( !printed_host_info ) {
+ printk(TBOOT_DETA"chipset production fused: %x\n", ver.prod_fused );
+ printk(TBOOT_DETA"chipset ids: vendor: 0x%x, device: 0x%x, revision: 0x%x\n",
+ didvid.vendor_id, didvid.device_id, didvid.revision_id);
+ }
+
+ /* get processor family/model/stepping and platform ID */
+ uint64_t platform_id;
+ uint32_t fms = cpuid_eax(1);
+ platform_id = rdmsr(MSR_IA32_PLATFORM_ID);
+ if ( !printed_host_info ) {
+ printk(TBOOT_DETA"processor family/model/stepping: 0x%x\n", fms );
+ printk(TBOOT_DETA"platform id: 0x%Lx\n", (unsigned long long)platform_id);
+ }
+ printed_host_info = true;
+
+ /*
+ * check if chipset fusing is same
+ */
+ if ( ver.prod_fused != !hdr->flags.debug_signed ) {
+ printk(TBOOT_ERR"\t production/debug mismatch between chipset and ACM\n");
+ return false;
+ }
+
+ /*
+ * check if chipset vendor/device/revision IDs match
+ */
+ acm_chipset_id_list_t *chipset_id_list = get_acmod_chipset_list(hdr);
+ if ( chipset_id_list == NULL )
+ return false;
+
+ printk(TBOOT_DETA"\t %x ACM chipset id entries:\n", chipset_id_list->count);
+ unsigned int i;
+ for ( i = 0; i < chipset_id_list->count; i++ ) {
+ acm_chipset_id_t *chipset_id = &(chipset_id_list->chipset_ids[i]);
+ printk(TBOOT_DETA"\t vendor: 0x%x, device: 0x%x, flags: 0x%x, "
+ "revision: 0x%x, extended: 0x%x\n",
+ (uint32_t)chipset_id->vendor_id,
+ (uint32_t)chipset_id->device_id, chipset_id->flags,
+ (uint32_t)chipset_id->revision_id, chipset_id->extended_id);
+
+ if ( (didvid.vendor_id == chipset_id->vendor_id ) &&
+ (didvid.device_id == chipset_id->device_id ) &&
+ ( ( ( (chipset_id->flags & 0x1) == 0) &&
+ (didvid.revision_id == chipset_id->revision_id) ) ||
+ ( ( (chipset_id->flags & 0x1) == 1) &&
+ ( (didvid.revision_id & chipset_id->revision_id) != 0 ) ) ) )
+ break;
+ }
+ if ( i >= chipset_id_list->count ) {
+ printk(TBOOT_ERR"\t chipset id mismatch\n");
+ return false;
+ }
+
+ /*
+ * check if processor family/model/stepping and platform IDs match
+ */
+ acm_info_table_t *info_table = get_acmod_info_table(hdr);
+ if ( info_table == NULL )
+ return false;
+
+ if ( info_table->version >= 4 ) {
+ acm_processor_id_list_t *proc_id_list = get_acmod_processor_list(hdr);
+ if ( proc_id_list == NULL )
+ return false;
+
+ printk(TBOOT_DETA"\t %x ACM processor id entries:\n", proc_id_list->count);
+ for ( i = 0; i < proc_id_list->count; i++ ) {
+ acm_processor_id_t *proc_id = &(proc_id_list->processor_ids[i]);
+ printk(TBOOT_DETA"\t fms: 0x%x, fms_mask: 0x%x, platform_id: 0x%Lx, "
+ "platform_mask: 0x%Lx\n",
+ proc_id->fms, proc_id->fms_mask,
+ (unsigned long long)proc_id->platform_id,
+ (unsigned long long)proc_id->platform_mask);
+
+ if ( (proc_id->fms == (fms & proc_id->fms_mask)) &&
+ (proc_id->platform_id == (platform_id & proc_id->platform_mask))
+ )
+ break;
+ }
+ if ( i >= proc_id_list->count ) {
+ printk(TBOOT_ERR"\t processor mismatch\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#ifndef IS_INCLUDED
+acm_hdr_t *get_bios_sinit(const void *sinit_region_base)
+{
+ txt_heap_t *txt_heap = get_txt_heap();
+ bios_data_t *bios_data = get_bios_data_start(txt_heap);
+
+ if ( bios_data->bios_sinit_size == 0 )
+ return NULL;
+
+ /* BIOS has loaded an SINIT module, so verify that it is valid */
+ printk(TBOOT_INFO"BIOS has already loaded an SINIT module\n");
+
+ /* is it a valid SINIT module? */
+ if ( !is_sinit_acmod(sinit_region_base, bios_data->bios_sinit_size, false) ||
+ !does_acmod_match_platform((acm_hdr_t *)sinit_region_base) )
+ return NULL;
+
+ return (acm_hdr_t *)sinit_region_base;
+}
+
+static void *alloc_racm_region(uint32_t size)
+{
+ /* TODO: find a real unused memory place through mbi */
+ return (void *)(unsigned long long)(0x2000000 + size - size); /* 32M */
+}
+
+acm_hdr_t *copy_racm(const acm_hdr_t *racm)
+{
+ /* find a 32KB aligned memory */
+ uint32_t racm_region_size = racm->size*4;
+ void *racm_region_base = alloc_racm_region(racm_region_size);
+ printk(TBOOT_DETA"RACM.BASE: %p\n", racm_region_base);
+ printk(TBOOT_DETA"RACM.SIZE: 0x%x (%u)\n", racm_region_size, racm_region_size);
+
+ /* copy it there */
+ memcpy(racm_region_base, racm, racm->size*4);
+
+ printk(TBOOT_DETA"copied RACM (size=%x) to %p\n", racm->size*4,
+ racm_region_base);
+
+ return (acm_hdr_t *)racm_region_base;
+}
+
+acm_hdr_t *copy_sinit(const acm_hdr_t *sinit)
+{
+ /* get BIOS-reserved region from TXT.SINIT.BASE config reg */
+ void *sinit_region_base =
+ (void*)(unsigned long long)read_pub_config_reg(TXTCR_SINIT_BASE);
+ uint32_t sinit_region_size = (uint32_t)read_pub_config_reg(TXTCR_SINIT_SIZE);
+ printk(TBOOT_DETA"TXT.SINIT.BASE: %p\n", sinit_region_base);
+ printk(TBOOT_DETA"TXT.SINIT.SIZE: 0x%x (%u)\n", sinit_region_size, sinit_region_size);
+
+ /*
+ * check if BIOS already loaded an SINIT module there
+ */
+ acm_hdr_t *bios_sinit = get_bios_sinit(sinit_region_base);
+ if ( bios_sinit != NULL ) {
+ /* no other SINIT was provided so must use one BIOS provided */
+ if ( sinit == NULL ) {
+ printk(TBOOT_WARN"no SINIT provided by bootloader; using BIOS SINIT\n");
+ return bios_sinit;
+ }
+
+ /* is it newer than the one we've been provided? */
+ if ( bios_sinit->date >= sinit->date ) {
+ printk(TBOOT_INFO"BIOS-provided SINIT is newer, so using it\n");
+ return bios_sinit; /* yes */
+ }
+ else
+ printk(TBOOT_INFO"BIOS-provided SINIT is older: date=%x\n", bios_sinit->date);
+ }
+ /* our SINIT is newer than BIOS's (or BIOS did not have one) */
+
+ /* BIOS SINIT not present or not valid and none provided */
+ if ( sinit == NULL )
+ return NULL;
+
+ /* overflow? */
+ if ( multiply_overflow_u32(sinit->size, 4) ) {
+ printk(TBOOT_ERR"sinit size in bytes overflows\n");
+ return NULL;
+ }
+
+ /* make sure our SINIT fits in the reserved region */
+ if ( (sinit->size * 4) > sinit_region_size ) {
+ printk(TBOOT_ERR"BIOS-reserved SINIT size (%x) is too small for loaded "
+ "SINIT (%x)\n", sinit_region_size, sinit->size*4);
+ return NULL;
+ }
+
+ /* copy it there */
+ memcpy(sinit_region_base, sinit, sinit->size*4);
+
+ printk(TBOOT_DETA"copied SINIT (size=%x) to %p\n", sinit->size*4,
+ sinit_region_base);
+
+ return (acm_hdr_t *)sinit_region_base;
+}
+#endif /* IS_INCLUDED */
+
+bool verify_racm(const acm_hdr_t *acm_hdr)
+{
+ getsec_parameters_t params;
+ uint32_t size;
+
+ /* assumes this already passed is_acmod() test */
+
+ size = acm_hdr->size * 4; /* hdr size is in dwords, we want bytes */
+
+ /*
+ * AC mod must start on 4k page boundary
+ */
+
+ if ( (unsigned long long)acm_hdr & 0xfff ) {
+ printk(TBOOT_ERR"AC mod base not 4K aligned (%p)\n", acm_hdr);
+ return false;
+ }
+ printk(TBOOT_INFO"AC mod base alignment OK\n");
+
+ /* AC mod size must:
+ * - be multiple of 64
+ * - greater than ???
+ * - less than max supported size for this processor
+ */
+
+ if ( (size == 0) || ((size % 64) != 0) ) {
+ printk(TBOOT_ERR"AC mod size %x bogus\n", size);
+ return false;
+ }
+
+ if ( !get_parameters(&params) ) {
+ printk(TBOOT_ERR"get_parameters() failed\n");
+ return false;
+ }
+
+ if ( size > params.acm_max_size ) {
+ printk(TBOOT_ERR"AC mod size too large: %x (max=%x)\n", size,
+ params.acm_max_size);
+ return false;
+ }
+
+ printk(TBOOT_INFO"AC mod size OK\n");
+
+ /*
+ * perform checks on AC mod structure
+ */
+
+ /* print it for debugging */
+ print_acm_hdr(acm_hdr, "RACM");
+
+ /* entry point is offset from base addr so make sure it is within module */
+ if ( acm_hdr->entry_point >= size ) {
+ printk(TBOOT_ERR"AC mod entry (%08x) >= AC mod size (%08x)\n",
+ acm_hdr->entry_point, size);
+ return false;
+ }
+
+ /* overflow? */
+ if ( plus_overflow_u32(acm_hdr->seg_sel, 8) ) {
+ printk(TBOOT_ERR"seg_sel plus 8 overflows\n");
+ return false;
+ }
+
+ if ( !acm_hdr->seg_sel || /* invalid selector */
+ (acm_hdr->seg_sel & 0x07) || /* LDT, PL!=0 */
+ (acm_hdr->seg_sel + 8 > acm_hdr->gdt_limit) ) {
+ printk(TBOOT_ERR"AC mod selector [%04x] bogus\n", acm_hdr->seg_sel);
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Do some AC module sanity checks because any violations will cause
+ * an TXT.RESET. Instead detect these, print a desriptive message,
+ * and skip SENTER/ENTERACCS
+ */
+#ifndef IS_INCLUDED /* defined in utils/acminfo.c */
+void verify_IA32_se_svn_status(const acm_hdr_t *acm_hdr)
+{
+
+ printk(TBOOT_INFO"SGX:verify_IA32_se_svn_status is called\n");
+
+ //check if SGX is enabled by cpuid with ax=7, cx=0
+ if ((cpuid_ebx1(7,0) & 0x00000004) == 0){
+ printk(TBOOT_ERR"SGX is not enabled, cpuid.ebx: 0x%x\n", cpuid_ebx1(7,0));
+ return;
+ }
+ printk(TBOOT_INFO"SGX is enabled, cpuid.ebx:0x%x\n", cpuid_ebx1(7,0));
+ printk(TBOOT_INFO"Comparing se_svn with ACM Header se_svn\n");
+
+ if (((rdmsr(MSR_IA32_SE_SVN_STATUS)>>16) & 0xff) != acm_hdr->se_svn) {
+ printk(TBOOT_INFO"se_svn is not equal to ACM se_svn\n");
+ if (!g_tpm->nv_write(g_tpm, 0, g_tpm->sgx_svn_index, 0, (uint8_t *)&(acm_hdr->se_svn), 1))
+ printk(TBOOT_ERR"Write sgx_svn_index 0x%x failed. \n", g_tpm->sgx_svn_index);
+ else
+ printk(TBOOT_INFO"Write sgx_svn_index with 0x%x successful.\n", acm_hdr->se_svn);
+
+ if ((rdmsr(MSR_IA32_SE_SVN_STATUS) & 0X00000001) !=0) /* reset platform */
+ // printk(TBOOT_INFO"SGX:A reset is required in this boot\n");
+ outb(0xcf9, 0x06);
+ }
+ else
+ printk(TBOOT_INFO"se_svn is equal to ACM se_svn\n");
+
+}
+
+
+bool verify_acmod(const acm_hdr_t *acm_hdr)
+{
+ getsec_parameters_t params;
+ uint32_t size;
+
+ /* assumes this already passed is_acmod() test */
+
+ size = acm_hdr->size * 4; /* hdr size is in dwords, we want bytes */
+
+ /*
+ * AC mod must start on 4k page boundary
+ */
+
+ if ( (unsigned long long)acm_hdr & 0xfff ) {
+ printk(TBOOT_ERR"AC mod base not 4K aligned (%p)\n", acm_hdr);
+ return false;
+ }
+ printk(TBOOT_INFO"AC mod base alignment OK\n");
+
+ /* AC mod size must:
+ * - be multiple of 64
+ * - greater than ???
+ * - less than max supported size for this processor
+ */
+
+ if ( (size == 0) || ((size % 64) != 0) ) {
+ printk(TBOOT_ERR"AC mod size %x bogus\n", size);
+ return false;
+ }
+
+ if ( !get_parameters(&params) ) {
+ printk(TBOOT_ERR"get_parameters() failed\n");
+ return false;
+ }
+
+ if ( size > params.acm_max_size ) {
+ printk(TBOOT_ERR"AC mod size too large: %x (max=%x)\n", size,
+ params.acm_max_size);
+ return false;
+ }
+
+ printk(TBOOT_INFO"AC mod size OK\n");
+
+ /*
+ * perform checks on AC mod structure
+ */
+
+ /* print it for debugging */
+ print_acm_hdr(acm_hdr, "SINIT");
+
+ /* verify SE enablement status */
+ verify_IA32_se_svn_status(acm_hdr);
+
+ /* entry point is offset from base addr so make sure it is within module */
+ if ( acm_hdr->entry_point >= size ) {
+ printk(TBOOT_ERR"AC mod entry (%08x) >= AC mod size (%08x)\n",
+ acm_hdr->entry_point, size);
+ return false;
+ }
+
+ /* overflow? */
+ if ( plus_overflow_u32(acm_hdr->seg_sel, 8) ) {
+ printk(TBOOT_ERR"seg_sel plus 8 overflows\n");
+ return false;
+ }
+
+ if ( !acm_hdr->seg_sel || /* invalid selector */
+ (acm_hdr->seg_sel & 0x07) || /* LDT, PL!=0 */
+ (acm_hdr->seg_sel + 8 > acm_hdr->gdt_limit) ) {
+ printk(TBOOT_ERR"AC mod selector [%04x] bogus\n", acm_hdr->seg_sel);
+ return false;
+ }
+
+ /*
+ * check for compatibility with this MLE
+ */
+
+ acm_info_table_t *info_table = get_acmod_info_table(acm_hdr);
+ if ( info_table == NULL )
+ return false;
+
+ /* check MLE header versions */
+ if ( info_table->min_mle_hdr_ver > MLE_HDR_VER ) {
+ printk(TBOOT_ERR"AC mod requires a newer MLE (0x%08x)\n",
+ info_table->min_mle_hdr_ver);
+ return false;
+ }
+
+ /* check capabilities */
+ /* we need to match one of rlp_wake_{getsec, monitor} */
+ txt_caps_t caps_mask = { 0 };
+ caps_mask.rlp_wake_getsec = caps_mask.rlp_wake_monitor = 1;
+
+ if ( ( ( MLE_HDR_CAPS & caps_mask._raw ) &
+ ( info_table->capabilities._raw & caps_mask._raw) ) == 0 ) {
+ printk(TBOOT_ERR"SINIT and MLE not support compatible RLP wake mechanisms\n");
+ return false;
+ }
+ /* we also expect ecx_pgtbl to be set */
+ if ( !info_table->capabilities.ecx_pgtbl ) {
+ printk(TBOOT_ERR"SINIT does not support launch with MLE pagetable in ECX\n");
+ /* TODO when SINIT ready
+ * return false;
+ */
+ }
+
+ /* check for version of OS to SINIT data */
+ /* we don't support old versions */
+ if ( info_table->os_sinit_data_ver < MIN_OS_SINIT_DATA_VER ) {
+ printk(TBOOT_ERR"SINIT's os_sinit_data version unsupported (%u)\n",
+ info_table->os_sinit_data_ver);
+ return false;
+ }
+ /* only warn if SINIT supports more recent version than us */
+ else if ( info_table->os_sinit_data_ver > MAX_OS_SINIT_DATA_VER ) {
+ printk(TBOOT_WARN"SINIT's os_sinit_data version unsupported (%u)\n",
+ info_table->os_sinit_data_ver);
+ }
+
+ return true;
+}
+#endif /* IS_INCLUDED */
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/acpi.c b/tboot/acpi.c
new file mode 100644
index 0000000..c2a25a4
--- /dev/null
+++ b/tboot/acpi.c
@@ -0,0 +1,482 @@
+/*
+ * acpi.c: ACPI utility fns
+ *
+ * Copyright (c) 2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+#include <efibase.h>
+#include <types.h>
+#include <stdbool.h>
+#include <compiler.h>
+#include <processor.h>
+#include <io.h>
+#include <string.h>
+#include <printk.h>
+#include <tb_error.h>
+#include <eficore.h>
+#include <tboot.h>
+#include <acpi.h>
+#include <misc.h>
+#include <cmdline.h>
+#include <eficore.h>
+#include <pci_cfgreg.h>
+
+#ifdef ACPI_DEBUG
+#define acpi_printk printk
+#else
+#define acpi_printk(...) /* */
+#endif
+
+static struct acpi_rsdp *rsdp;
+static struct acpi_table_header *g_dmar_table;
+static __data bool g_hide_dmar;
+
+static void dump_gas(const char *reg_name,
+ const tboot_acpi_generic_address_t *reg)
+{
+ const char *space_id[] = { "memory", "I/O", "PCI config space", "EC",
+ "SMBus" };
+
+ printk(TBOOT_DETA"%s GAS @ %p:\n", reg_name, reg);
+ if ( reg == NULL )
+ return;
+
+ if ( reg->space_id >= ARRAY_SIZE(space_id) )
+ printk(TBOOT_DETA"\t space_id: unsupported (%u)\n", reg->space_id);
+ else
+ printk(TBOOT_DETA"\t space_id: %s\n", space_id[reg->space_id]);
+ printk(TBOOT_DETA"\t bit_width: %u\n", reg->bit_width);
+ printk(TBOOT_DETA"\t bit_offset: %u\n", reg->bit_offset);
+ printk(TBOOT_DETA"\t access_width: %u\n", reg->access_width);
+ printk(TBOOT_DETA"\t address: %Lx\n", reg->address);
+}
+
+static inline struct acpi_rsdt *get_rsdt(void)
+{
+ return (struct acpi_rsdt *)(uint64_t)rsdp->rsdp1.rsdt;
+}
+
+static inline struct acpi_xsdt *get_xsdt(void)
+{
+ if ( rsdp->rsdp_xsdt >= 0x100000000ULL ) {
+ printk(TBOOT_ERR"XSDT above 4GB\n");
+ return NULL;
+ }
+ return (struct acpi_xsdt *)(uintptr_t)rsdp->rsdp_xsdt;
+}
+
+static bool verify_acpi_checksum(uint8_t *start, uint8_t len)
+{
+ uint8_t sum = 0;
+ while ( len ) {
+ sum += *start++;
+ len--;
+ }
+ return (sum == 0);
+}
+
+static bool find_rsdp_in_range(void *start, void *end)
+{
+#define RSDP_BOUNDARY 16 /* rsdp ranges on 16-byte boundaries */
+#define RSDP_CHKSUM_LEN 20 /* rsdp check sum length, defined in ACPI 1.0 */
+
+ for ( ; start < end; start += RSDP_BOUNDARY ) {
+ rsdp = (struct acpi_rsdp *)start;
+
+ if ( memcmp(rsdp->rsdp1.signature, RSDP_SIG,
+ sizeof(rsdp->rsdp1.signature)) == 0 ) {
+ if ( verify_acpi_checksum((uint8_t *)rsdp, RSDP_CHKSUM_LEN) ) {
+ printk(TBOOT_DETA"RSDP (v%u, %.6s) @ %p\n", rsdp->rsdp1.revision,
+ rsdp->rsdp1.oemid, rsdp);
+ return true;
+ }
+ else {
+ printk(TBOOT_ERR"checksum failed.\n");
+ return false;
+ }
+ }
+ }
+ return false;
+}
+
+static bool find_rsdp(void)
+{
+ uint8_t *ldr_rsdp = NULL;
+
+ if ( rsdp != NULL )
+ return true;
+
+ /* We can get the RSDP from EFI */
+ ldr_rsdp = efi_get_rsdp();
+ if (ldr_rsdp != NULL) {
+ rsdp = (struct acpi_rsdp *) ldr_rsdp;
+ return true;
+ }
+
+ /* 0x00 - 0x400 */
+ if ( find_rsdp_in_range(RSDP_SCOPE1_LOW, RSDP_SCOPE1_HIGH) )
+ return true;
+
+ /* 0xE0000 - 0x100000 */
+ if ( find_rsdp_in_range(RSDP_SCOPE2_LOW, RSDP_SCOPE2_HIGH) )
+ return true;
+
+ printk(TBOOT_ERR"can't find RSDP\n");
+ rsdp = NULL;
+ return false;
+}
+
+struct acpi_rsdp
+*get_rsdp(void)
+{
+ if (rsdp != NULL)
+ return rsdp;
+ if (true == find_rsdp())
+ return rsdp;
+
+ return NULL;
+}
+
+/* this function can find dmar table whether or not it was hidden */
+static struct acpi_table_header *find_table(const char *table_name)
+{
+ if ( !find_rsdp() ) {
+ printk(TBOOT_ERR"no rsdp to use\n");
+ return NULL;
+ }
+
+ struct acpi_table_header *table = NULL;
+ struct acpi_xsdt *xsdt = get_xsdt(); /* it is ok even on 1.0 tables */
+ /* because value will be ignored */
+
+ if ( rsdp->rsdp1.revision >= 2 && xsdt != NULL ) { /* ACPI 2.0+ */
+ for ( uint64_t *curr_table = (uint64_t*)xsdt->table_offsets;
+ curr_table < (uint64_t *)((void *)xsdt + xsdt->hdr.length);
+ curr_table++ ) {
+ table = (struct acpi_table_header *)(uintptr_t)*curr_table;
+ if ( memcmp(table->signature, table_name,
+ sizeof(table->signature)) == 0 )
+ return table;
+ }
+ }
+ else { /* ACPI 1.0 */
+ struct acpi_rsdt *rsdt = get_rsdt();
+
+ if ( rsdt == NULL ) {
+ printk(TBOOT_ERR"rsdt is invalid.\n");
+ return NULL;
+ }
+
+ for ( uint32_t *curr_table = rsdt->table_offsets;
+ curr_table < (uint32_t *)((void *)rsdt + rsdt->hdr.length);
+ curr_table++ ) {
+ table = (struct acpi_table_header *)(uintptr_t)*curr_table;
+ if ( memcmp(table->signature, table_name,
+ sizeof(table->signature)) == 0 )
+ return table;
+ }
+ }
+
+ printk(TBOOT_ERR"cann't find %s table.\n", table_name);
+ return NULL;
+}
+
+static struct acpi_dmar *get_vtd_dmar_table(void)
+{
+ return (struct acpi_dmar *)find_table(DMAR_SIG);
+}
+
+bool save_vtd_dmar_table(void)
+{
+ /* find DMAR table and save it */
+ g_dmar_table = (struct acpi_table_header *)get_vtd_dmar_table();
+
+ printk(TBOOT_DETA"DMAR table @ %p saved.\n", g_dmar_table);
+ return true;
+}
+
+bool restore_vtd_dmar_table(void)
+{
+ struct acpi_table_header *hdr;
+
+ g_hide_dmar = false;
+
+ /* find DMAR table first */
+ hdr = (struct acpi_table_header *)get_vtd_dmar_table();
+ if ( hdr != NULL ) {
+ printk(TBOOT_DETA"DMAR table @ %p is still there, skip restore step.\n", hdr);
+ return true;
+ }
+
+ /* check saved DMAR table */
+ if ( g_dmar_table == NULL ) {
+ printk(TBOOT_ERR"No DMAR table saved, abort restore step.\n");
+ return false;
+ }
+
+ /* restore DMAR if needed */
+ memcpy(g_dmar_table->signature, DMAR_SIG, sizeof(g_dmar_table->signature));
+
+ /* need to hide DMAR table while resume from S3 */
+ g_hide_dmar = true;
+ printk(TBOOT_DETA"DMAR table @ %p restored.\n", hdr);
+ return true;
+}
+
+bool remove_vtd_dmar_table(void)
+{
+ struct acpi_table_header *hdr;
+
+ /* check whether it is needed */
+ if ( !g_hide_dmar ) {
+ printk(TBOOT_DETA"No need to hide DMAR table.\n");
+ return true;
+ }
+
+ /* find DMAR table */
+ hdr = (struct acpi_table_header *)get_vtd_dmar_table();
+ if ( hdr == NULL ) {
+ printk(TBOOT_DETA"No DMAR table, skip remove step.\n");
+ return true;
+ }
+
+ /* remove DMAR table */
+ hdr->signature[0] = '\0';
+ printk(TBOOT_DETA"DMAR table @ %p removed.\n", hdr);
+ return true;
+}
+
+static struct acpi_madt *get_apic_table(void)
+{
+ return (struct acpi_madt *)find_table(MADT_SIG);
+}
+
+uint32_t get_madt_apic_base(void)
+{
+ struct acpi_madt *madt = get_apic_table();
+ if ( madt == NULL ) {
+ printk(TBOOT_ERR"no MADT table found\n");
+ return 0;
+ }
+ return (uint32_t)madt->local_apic_address;
+}
+
+struct acpi_table_ioapic *get_acpi_ioapic_table(void)
+{
+ struct acpi_madt *madt = get_apic_table();
+ if ( madt == NULL ) {
+ printk(TBOOT_ERR"no MADT table found\n");
+ return NULL;
+ }
+
+ /* APIC tables begin after MADT */
+ union acpi_madt_entry *entry = (union acpi_madt_entry *)(madt + 1);
+
+ while ( (void *)entry < ((void *)madt + madt->hdr.length) ) {
+ uint8_t length = entry->madt_lapic.length;
+
+ if ( entry->madt_lapic.apic_type == ACPI_MADT_IOAPIC ) {
+ if ( length != sizeof(entry->madt_ioapic) ) {
+ printk(TBOOT_ERR"APIC length error.\n");
+ return NULL;
+ }
+ return (struct acpi_table_ioapic *)entry;
+ }
+ entry = (void *)entry + length;
+ }
+ printk(TBOOT_ERR"no IOAPIC type.\n");
+ return NULL;
+}
+
+struct acpi_mcfg *get_acpi_mcfg_table(void)
+{
+ return (struct acpi_mcfg *)find_table(MCFG_SIG);
+}
+
+static bool write_to_reg(const tboot_acpi_generic_address_t *reg,
+ uint32_t val)
+{
+ if ( reg->address >= 100000000ULL ) {
+ printk(TBOOT_ERR"GAS address >4GB (0x%Lx)\n", reg->address);
+ return false;
+ }
+ uint64_t address = (uint64_t)reg->address;
+
+ if ( reg->space_id == GAS_SYSTEM_IOSPACE ) {
+ switch ( reg->bit_width ) {
+ case 8:
+ outb(address, (uint8_t)val);
+ return true;
+ case 16:
+ outw(address, (uint16_t)val);
+ return true;
+ case 32:
+ outl(address, val);
+ return true;
+ default:
+ printk(TBOOT_ERR"unsupported GAS bit width: %u\n", reg->bit_width);
+ return false;
+ }
+ }
+ else if ( reg->space_id == GAS_SYSTEM_MEMORY ) {
+ switch ( reg->bit_width ) {
+ case 8:
+ writeb(address, (uint8_t)val);
+ return true;
+ case 16:
+ writew(address, (uint16_t)val);
+ return true;
+ case 32:
+ writel(address, val);
+ return true;
+ default:
+ printk(TBOOT_ERR"unsupported GAS bit width: %u\n", reg->bit_width);
+ return false;
+ }
+ }
+
+ printk(TBOOT_ERR"unsupported GAS addr space ID: %u\n", reg->space_id);
+ return false;
+}
+
+static bool read_from_reg(const tboot_acpi_generic_address_t *reg,
+ uint32_t *val)
+{
+ if ( reg->address >= 100000000ULL ) {
+ printk(TBOOT_ERR"GAS address >4GB (0x%Lx)\n", reg->address);
+ return false;
+ }
+ uint64_t address = (uint64_t)reg->address;
+
+ if ( reg->space_id == GAS_SYSTEM_IOSPACE ) {
+ switch ( reg->bit_width ) {
+ case 8:
+ *val = inb(address);
+ return true;
+ case 16:
+ *val = inw(address);
+ return true;
+ case 32:
+ *val = inl(address);
+ return true; default:
+ printk(TBOOT_ERR"unsupported GAS bit width: %u\n", reg->bit_width);
+ return false;
+ }
+ }
+ else if ( reg->space_id == GAS_SYSTEM_MEMORY ) {
+ switch ( reg->bit_width ) {
+ case 8:
+ *val = readb(address);
+ return true;
+ case 16:
+ *val = readw(address);
+ return true;
+ case 32:
+ *val = readl(address);
+ return true;
+ default:
+ printk(TBOOT_ERR"unsupported GAS bit width: %u\n", reg->bit_width);
+ return false;
+ }
+ }
+
+ printk(TBOOT_ERR"unsupported GAS addr space ID: %u\n", reg->space_id);
+ return false;
+}
+
+static void wait_to_sleep(const tboot_acpi_sleep_info_t *acpi_sinfo)
+{
+#define WAKE_STATUS 0x8000 /* the 15th bit */
+ while ( true ) {
+ uint32_t pm1a_value = 0, pm1b_value = 0;
+
+ if ( acpi_sinfo->pm1a_evt_blk.address ) {
+ if ( read_from_reg(&acpi_sinfo->pm1a_evt_blk, &pm1a_value) &&
+ ( pm1a_value & WAKE_STATUS ) )
+ return;
+ }
+
+ if ( acpi_sinfo->pm1b_evt_blk.address ) {
+ if ( read_from_reg(&acpi_sinfo->pm1b_evt_blk, &pm1b_value) &&
+ ( pm1b_value & WAKE_STATUS ) )
+ return;
+ }
+ }
+}
+
+bool machine_sleep(const tboot_acpi_sleep_info_t *acpi_sinfo)
+{
+ dump_gas("PM1A", &acpi_sinfo->pm1a_cnt_blk);
+ dump_gas("PM1B", &acpi_sinfo->pm1b_cnt_blk);
+
+ wbinvd();
+
+ if ( acpi_sinfo->pm1a_cnt_blk.address ) {
+ if ( !write_to_reg(&acpi_sinfo->pm1a_cnt_blk, acpi_sinfo->pm1a_cnt_val) )
+ return false;;
+ }
+
+ if ( acpi_sinfo->pm1b_cnt_blk.address ) {
+ if ( !write_to_reg(&acpi_sinfo->pm1b_cnt_blk, acpi_sinfo->pm1b_cnt_val) )
+ return false;
+ }
+
+ /* just to wait, the machine may shutdown before here */
+ wait_to_sleep(acpi_sinfo);
+ return true;
+}
+
+void set_s3_resume_vector(const tboot_acpi_sleep_info_t *acpi_sinfo,
+ uint64_t resume_vector)
+{
+ if ( acpi_sinfo->vector_width <= 32 )
+ *(uint32_t *)(unsigned long long)(acpi_sinfo->wakeup_vector) =
+ (uint32_t)resume_vector;
+ else if ( acpi_sinfo->vector_width <= 64 )
+ *(uint64_t *)(unsigned long long)(acpi_sinfo->wakeup_vector) =
+ resume_vector;
+ else
+ printk(TBOOT_WARN"vector_width error.\n");
+
+ acpi_printk(TBOOT_DETA"wakeup_vector_address = %llx\n", acpi_sinfo->wakeup_vector);
+ acpi_printk(TBOOT_DETA"wakeup_vector_value = %llxx\n", resume_vector);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/bits.S b/tboot/bits.S
new file mode 100644
index 0000000..0cf6ea1
--- /dev/null
+++ b/tboot/bits.S
@@ -0,0 +1,166 @@
+/*
+ * bits.S: Assembly support routines and bits.
+ *
+ * Copyright (c) 2017 Assured Information Security.
+ *
+ * Ross Philipson <philipsonr@ainfosec.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+
+#define REF(x) x(%rip)
+
+#define SOFF 16
+
+ENTRY(print_test_chars)
+ pushq %rcx
+ pushq %rdx
+ xorq %rcx, %rcx
+1:
+ cmpb $5, %cl
+ jz 2f
+ movw $0x3f8, %dx
+ addw $5, %dx
+3:
+ inb %dx, %al
+ testb $0x20, %al
+ jz 3b
+ movw $0x3f8, %dx
+ movb $0x41, %al
+ addb %cl, %al
+ outb %al, %dx
+ incb %cl
+ jmp 1b
+2:
+ popq %rdx
+ popq %rcx
+ ret
+
+ENTRY(memcpy)
+ pushq %rbp
+ movq %rsp, %rbp
+ movq %rcx, SOFF(%rbp) # dst
+ movq %rdx, SOFF+8(%rbp) # src
+ movq %r8, SOFF+16(%rbp) # size
+
+ movq %rcx, %rdi
+ movq %rdx, %rsi
+ movq %r8, %rcx
+ shrq $3, %rcx
+ cld
+ rep
+ movsq # mov quad words forward
+ movq %r8, %rcx
+ andq $7, %rcx
+ rep
+ movsb # mov remaining bytes forward
+ popq %rbp
+ ret
+
+ENTRY(read_msr)
+ pushq %rdx
+ /* ECX already has MSR number, go for it */
+ rdmsr
+ movq $0xffffffff, %rcx
+ andq %rcx, %rax
+ shlq $32, %rdx
+ movq $0xffffffff00000000, %rcx
+ andq %rcx, %rdx
+ orq %rdx, %rax
+ popq %rdx
+ ret
+
+ENTRY(write_msr)
+ pushq %rax
+ movq %rdx, %rax
+ shrq $32, %rdx
+ /* ECX already has MSR number */
+ wrmsr
+ popq %rax
+ ret
+
+ENTRY(read_tsc)
+ rdtsc
+ movq $0xffffffff, %rcx
+ andq %rcx, %rax
+ shlq $32, %rdx
+ movq $0xffffffff00000000, %rcx
+ andq %rcx, %rdx
+ orq %rdx, %rax
+ ret
+
+/*
+ * Mutex code ported to 64b from:
+ * $OpenBSD: mutex.S,v 1.6 2009/04/27 21:48:56 kettenis Exp $
+ *
+ * Copyright (c) 2004 Artur Grabowski <art@openbsd.org>
+ * All rights reserved.
+ *
+ * BSD 2-Clause
+ */
+
+ENTRY(mtx_init)
+ pushq %rbp
+ movq %rsp, %rbp
+ movq %rcx, SOFF(%rbp) # home var
+ movq $0, (%rcx)
+ popq %rbp
+ ret
+
+ENTRY(mtx_enter)
+ pushq %rbp
+ movq %rsp, %rbp
+1: movq %rcx, SOFF(%rbp) # home var
+ /*
+ * %rcx contains the mtx as passed from caller
+ */
+ movq $1, %rax
+ xchgq %rax, (%rcx) # test_and_set(mtx->mtx_lock)
+ testq %rax, %rax # if (already held)
+ jnz 2f
+ popq %rbp
+ ret
+2: pause
+ movq (%rcx), %rax
+ testq %rax, %rax
+ jz 1b
+ jmp 2b
+
+ENTRY(mtx_leave)
+ pushq %rbp
+ movq %rsp, %rbp
+ movq %rcx, SOFF(%rbp) # home var
+ movq $0, (%rcx)
+ popq %rbp
+ ret
+
+ENTRY(get_rip)
+ movq (%rsp), %rax
+ ret
diff --git a/tboot/cmdline.c b/tboot/cmdline.c
new file mode 100644
index 0000000..cee60a5
--- /dev/null
+++ b/tboot/cmdline.c
@@ -0,0 +1,606 @@
+/*
+ * cmdline.c: command line parsing fns
+ *
+ * Copyright (c) 2006-2012, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+#include <efibase.h>
+#include <types.h>
+#include <stdbool.h>
+#include <ctype.h>
+#include <compiler.h>
+#include <string.h>
+#include <misc.h>
+#include <printk.h>
+#include <cmdline.h>
+#include <eficore.h>
+#include <eficonfig.h>
+#include <tpm.h>
+#include <tb_error.h>
+#include <tboot.h>
+#include <mle.h>
+#include <txt/mtrrs.h>
+#include <txt/config_regs.h>
+
+/*
+ * copy of original command line
+ * part of tboot measurement (hence in .text section)
+ */
+__text char g_cmdline[CMDLINE_SIZE] = { 0 };
+
+/* Used for kernel command line parameter setup */
+typedef struct {
+ const char *name; /* set to NULL for last item in list */
+ const char *def_val;
+} cmdline_option_t;
+
+#define MAX_VALUE_LEN 64
+
+/*
+ * the option names and default values must be separate from the actual
+ * params entered
+ * this allows the names and default values to be part of the MLE measurement
+ * param_values[] need to be in .bss section so that will get cleared on launch
+ */
+
+/* global option array for command line */
+static const cmdline_option_t g_tboot_cmdline_options[] = {
+ { "loglvl", "all" }, /* all|err,warn,info|none */
+ { "logging", "serial,vga,efi" }, /* vga,serial,memory,efi|none */
+ { "serial", "115200,8n1,0x3f8" },
+ /* serial=<baud>[/<clock_hz>][,<DPS>[,<io-base>[,<irq>[,<serial-bdf>[,<bridge-bdf>]]]]] */
+ { "vga_delay", "0" }, /* # secs */
+ { "ap_wake_mwait", "false" }, /* true|false */
+ { "pcr_map", "legacy" }, /* legacy|da */
+ { "min_ram", "0" }, /* size in bytes | 0 for no min */
+ { "call_racm", "false" }, /* true|false|check */
+ { "measure_nv", "false" }, /* true|false */
+ { "extpol", "sha1" }, /* agile|embedded|sha1|sha256|sm3|... */
+ { NULL, NULL }
+};
+static char g_tboot_param_values[ARRAY_SIZE(g_tboot_cmdline_options)][MAX_VALUE_LEN];
+
+static const cmdline_option_t g_linux_cmdline_options[] = {
+ { "vga", "" },
+ { "mem", "" },
+ { NULL, NULL }
+};
+static char g_linux_param_values[ARRAY_SIZE(g_linux_cmdline_options)][MAX_VALUE_LEN];
+
+typedef struct {
+ const char *log_name;
+ uint8_t log_val;
+} tb_loglvl_map_t;
+
+/* map */
+static const tb_loglvl_map_t g_loglvl_map[] = {
+ { "none", TBOOT_LOG_LEVEL_NONE },
+ { "err", TBOOT_LOG_LEVEL_ERR },
+ { "warn", TBOOT_LOG_LEVEL_WARN },
+ { "info", TBOOT_LOG_LEVEL_INFO },
+ { "detail",TBOOT_LOG_LEVEL_DETA },
+ { "all", TBOOT_LOG_LEVEL_ALL },
+};
+
+static const char* get_option_val(const cmdline_option_t *options, char vals[][MAX_VALUE_LEN], const char *opt_name)
+{
+ for ( int i = 0; options[i].name != NULL; i++ ) {
+ if ( strcmp(options[i].name, opt_name) == 0 )
+ return vals[i];
+ }
+ printk(TBOOT_ERR"requested unknown option: %s\n", opt_name);
+ return NULL;
+}
+
+static void cmdline_parse(const char *cmdline, const cmdline_option_t *options,
+ char vals[][MAX_VALUE_LEN])
+{
+ const char *p = cmdline;
+ int i;
+
+ /* copy default values to vals[] */
+ for ( i = 0; options[i].name != NULL; i++ ) {
+ strncpy(vals[i], options[i].def_val, MAX_VALUE_LEN-1);
+ vals[i][MAX_VALUE_LEN-1] = '\0';
+ }
+
+ if ( p == NULL )
+ return;
+
+ /* parse options */
+ while ( true )
+ {
+ /* skip whitespace */
+ while ( isspace(*p) )
+ p++;
+ if ( *p == '\0' )
+ break;
+
+ /* find end of current option */
+ const char *opt_start = p;
+ const char *opt_end = strchr(opt_start, ' ');
+ if ( opt_end == NULL )
+ opt_end = opt_start + strlen(opt_start);
+ p = opt_end;
+
+ /* find value part; if no value found, use default and continue */
+ const char *val_start = strchr(opt_start, '=');
+ if ( val_start == NULL || val_start > opt_end )
+ continue;
+ val_start++;
+
+ unsigned int opt_name_size = val_start - opt_start - 1;
+ unsigned int copy_size = opt_end - val_start;
+ if ( copy_size > MAX_VALUE_LEN - 1 )
+ copy_size = MAX_VALUE_LEN - 1;
+ if ( opt_name_size == 0 || copy_size == 0 )
+ continue;
+
+ /* value found, so copy it */
+ for ( i = 0; options[i].name != NULL; i++ ) {
+ if ( strncmp(options[i].name, opt_start, opt_name_size ) == 0 ) {
+ strncpy(vals[i], val_start, copy_size);
+ vals[i][copy_size] = '\0'; /* add '\0' to the end of string */
+ break;
+ }
+ }
+ }
+}
+
+void tboot_parse_cmdline(bool defaults)
+{
+ if (!defaults)
+ cmdline_parse(g_cmdline, g_tboot_cmdline_options, g_tboot_param_values);
+ else
+ cmdline_parse(NULL, g_tboot_cmdline_options, g_tboot_param_values);
+}
+
+void linux_parse_cmdline(const char *cmdline)
+{
+ cmdline_parse(cmdline, g_linux_cmdline_options, g_linux_param_values);
+}
+
+uint8_t get_loglvl_prefix(char **pbuf, int *len)
+{
+ uint8_t log_level = TBOOT_LOG_LEVEL_ALL;
+
+ if ( *len > 2 && **pbuf == '<' && *(*pbuf+2) == '>'
+ && isdigit(*(*pbuf+1)) ) {
+ unsigned int i = *(*pbuf+1) - '0';
+ if ( i < ARRAY_SIZE(g_loglvl_map) )
+ log_level = g_loglvl_map[i].log_val;
+ *pbuf += 3;
+ *len = *len - 3;
+ }
+
+ return log_level;
+}
+
+void get_tboot_loglvl(void)
+{
+ const char *loglvl = get_option_val(g_tboot_cmdline_options,
+ g_tboot_param_values, "loglvl");
+ if ( loglvl == NULL )
+ return;
+
+ /* determine whether the target is set explicitly */
+ while ( isspace(*loglvl) )
+ loglvl++;
+
+ g_log_level = TBOOT_LOG_LEVEL_NONE;
+
+ while ( *loglvl != '\0' ) {
+ unsigned int i;
+
+ for ( i = 0; i < ARRAY_SIZE(g_loglvl_map); i++ ) {
+ if ( strncmp(loglvl, g_loglvl_map[i].log_name,
+ strlen(g_loglvl_map[i].log_name)) == 0 ) {
+ loglvl += strlen(g_loglvl_map[i].log_name);
+
+ if ( g_loglvl_map[i].log_val == TBOOT_LOG_LEVEL_NONE ) {
+ g_log_level = TBOOT_LOG_LEVEL_NONE;
+ return;
+ }
+ else {
+ g_log_level |= g_loglvl_map[i].log_val;
+ break;
+ }
+ }
+ }
+
+ if ( i == ARRAY_SIZE(g_loglvl_map) )
+ break; /* unrecognized, end loop */
+
+ /* skip ',' */
+ if ( *loglvl == ',' )
+ loglvl++;
+ else
+ break; /* unrecognized, end loop */
+ }
+}
+
+void get_tboot_log_targets(void)
+{
+ const char *targets = get_option_val(g_tboot_cmdline_options,
+ g_tboot_param_values, "logging");
+
+ /* nothing set, leave defaults */
+ if ( targets == NULL || *targets == '\0' )
+ return;
+
+ /* determine if no targets set explicitly */
+ if ( strcmp(targets, "none") == 0 ) {
+ g_log_targets = TBOOT_LOG_TARGET_NONE; /* print nothing */
+ return;
+ }
+
+ /* else init to nothing and parse the possible targets */
+ g_log_targets = TBOOT_LOG_TARGET_NONE;
+
+ while ( *targets != '\0' ) {
+ if ( strncmp(targets, "memory", 6) == 0 ) {
+ g_log_targets |= TBOOT_LOG_TARGET_MEMORY;
+ targets += 6;
+ }
+ else if ( strncmp(targets, "serial", 6) == 0 ) {
+ g_log_targets |= TBOOT_LOG_TARGET_SERIAL;
+ targets += 6;
+ }
+ else if ( strncmp(targets, "vga", 3) == 0 && g_post_ebs ) {
+ g_log_targets |= TBOOT_LOG_TARGET_VGA;
+ targets += 3;
+ }
+ else if ( strncmp(targets, "efi", 3) == 0 && !g_post_ebs ) {
+ g_log_targets |= TBOOT_LOG_TARGET_EFI;
+ targets += 3;
+ }
+ else
+ break; /* unrecognized, end loop */
+
+ if ( *targets == ',' )
+ targets++;
+ else
+ break; /* unrecognized, end loop */
+ }
+}
+
+static bool parse_pci_bdf(const char **bdf, uint32_t *bus, uint32_t *slot,
+ uint32_t *func)
+{
+ *bus = strtoul(*bdf, (char **)bdf, 16);
+ if ( **bdf != ':' )
+ return false;
+ (*bdf)++;
+ *slot = strtoul(*bdf, (char **)bdf, 16);
+ if ( **bdf != '.' )
+ return false;
+ (*bdf)++;
+ *func = strtoul(*bdf, (char **)bdf, 16);
+
+ return true;
+}
+
+bool g_psbdf_enabled = false;
+static bool parse_com_psbdf(const char **bdf)
+{
+ g_psbdf_enabled = parse_pci_bdf(bdf,
+ &g_com_port.comc_psbdf.bus,
+ &g_com_port.comc_psbdf.slot,
+ &g_com_port.comc_psbdf.func);
+
+ return g_psbdf_enabled;
+}
+
+bool g_pbbdf_enabled = false;
+static bool parse_com_pbbdf(const char **bdf)
+{
+ g_pbbdf_enabled = parse_pci_bdf(bdf,
+ &g_com_port.comc_pbbdf.bus,
+ &g_com_port.comc_pbbdf.slot,
+ &g_com_port.comc_pbbdf.func);
+
+ return g_pbbdf_enabled;
+}
+
+static bool parse_com_fmt(const char **fmt)
+{
+ /* fmt: <5|6|7|8><n|o|e|m|s><0|1> */
+ /* default 8n1 */
+ uint8_t data_bits = 8;
+ uint8_t parity = 'n';
+ uint8_t stop_bits = 1;
+
+
+ /* must specify all values */
+ if ( strlen(*fmt) < 3 )
+ return false;
+
+ /* data bits */
+ if ( **fmt >= '5' && **fmt <= '8' )
+ data_bits = **fmt - '0';
+ else
+ return false;
+ (*fmt)++;
+
+ /* parity */
+ if ( **fmt == 'n' || **fmt == 'o' || **fmt == 'e' || **fmt == 'm' ||
+ **fmt == 's' )
+ parity = **fmt;
+ else
+ return false;
+ (*fmt)++;
+
+ /* stop bits */
+ if ( **fmt == '0' || **fmt == '1' )
+ stop_bits = **fmt - '0';
+ else
+ return false;
+ (*fmt)++;
+
+ g_com_port.comc_fmt = GET_LCR_VALUE(data_bits, stop_bits, parity);
+
+ return true;
+}
+
+static bool parse_serial_param(const char *com)
+{
+ /* parse baud */
+ g_com_port.comc_curspeed = strtoul(com, (char **)&com, 10);
+ if ( (g_com_port.comc_curspeed < 1200) ||
+ (g_com_port.comc_curspeed > 115200) )
+ return false;
+
+ /* parse clock hz */
+ if ( *com == '/' ) {
+ ++com;
+ g_com_port.comc_clockhz = strtoul(com, (char **)&com, 0) << 4;
+ if ( g_com_port.comc_clockhz == 0 )
+ return false;
+ }
+
+ /* parse data_bits/parity/stop_bits */
+ if ( *com != ',' )
+ goto exit;
+ ++com;
+ while ( isspace(*com) )
+ com++;
+ if ( !parse_com_fmt(&com) )
+ return false;
+
+ /* parse IO base */
+ if ( *com != ',' )
+ goto exit;
+ ++com;
+ g_com_port.comc_port = strtoul(com, (char **)&com, 0);
+ if ( g_com_port.comc_port == 0 )
+ return false;
+
+ /* parse irq */
+ if ( *com != ',' )
+ goto exit;
+ ++com;
+ g_com_port.comc_irq = strtoul(com, (char **)&com, 10);
+ if ( g_com_port.comc_irq == 0 )
+ return false;
+
+ /* parse PCI serial controller bdf */
+ if ( *com != ',' )
+ goto exit;
+ ++com;
+ if ( !parse_com_psbdf(&com) )
+ return false;
+
+ /* parse PCI bridge bdf */
+ if ( *com != ',' )
+ goto exit;
+ ++com;
+ if ( !parse_com_pbbdf(&com) )
+ return false;
+
+ exit:
+ return true;
+}
+
+bool get_tboot_serial(void)
+{
+ const char *serial = get_option_val(g_tboot_cmdline_options,
+ g_tboot_param_values, "serial");
+ if ( serial == NULL || *serial == '\0' )
+ return false;
+
+ return parse_serial_param(serial);
+}
+
+void get_tboot_vga_delay(void)
+{
+ const char *vga_delay = get_option_val(g_tboot_cmdline_options,
+ g_tboot_param_values, "vga_delay");
+ if ( vga_delay == NULL )
+ return;
+
+ g_vga_delay = strtoul(vga_delay, NULL, 0);
+}
+
+bool get_tboot_prefer_da(void)
+{
+ const char *value = get_option_val(g_tboot_cmdline_options,
+ g_tboot_param_values, "pcr_map");
+ if ( value != NULL && strcmp(value, "da") == 0 )
+ return true;
+
+ return false;
+}
+
+uint32_t g_min_ram;
+void get_tboot_min_ram(void)
+{
+ const char *min_ram = get_option_val(g_tboot_cmdline_options,
+ g_tboot_param_values, "min_ram");
+ if ( min_ram == NULL )
+ return;
+
+ g_min_ram = strtoul(min_ram, NULL, 0);
+}
+
+bool get_tboot_mwait(void)
+{
+ const char *mwait = get_option_val(g_tboot_cmdline_options,
+ g_tboot_param_values, "ap_wake_mwait");
+ if ( mwait == NULL || strcmp(mwait, "false") == 0 )
+ return false;
+ return true;
+}
+
+bool get_tboot_call_racm(void)
+{
+ const char *call_racm = get_option_val(g_tboot_cmdline_options,
+ g_tboot_param_values, "call_racm");
+ if ( call_racm == NULL || strcmp(call_racm, "true") != 0 )
+ return false;
+ return true;
+}
+
+bool get_tboot_call_racm_check(void)
+{
+ const char *call_racm = get_option_val(g_tboot_cmdline_options,
+ g_tboot_param_values, "call_racm");
+ if ( call_racm == NULL || strcmp(call_racm, "check") != 0 )
+ return false;
+ return true;
+}
+
+bool get_tboot_measure_nv(void)
+{
+ const char *measure_nv = get_option_val(g_tboot_cmdline_options,
+ g_tboot_param_values, "measure_nv");
+ if ( measure_nv == NULL || strcmp(measure_nv, "true") != 0 )
+ return false;
+ return true;
+}
+
+
+void get_tboot_extpol(void)
+{
+ const char *extpol = get_option_val(g_tboot_cmdline_options, g_tboot_param_values, "extpol");
+
+ if ( extpol == NULL ) {
+ g_tpm->extpol = TB_EXTPOL_FIXED;
+ g_tpm->cur_alg = TB_HALG_SHA256;
+ return;
+ }
+
+ if ( strcmp(extpol, "agile") == 0 ) {
+ g_tpm->extpol = TB_EXTPOL_AGILE;
+ g_tpm->cur_alg = TB_HALG_SHA256;
+ } else if ( strcmp(extpol, "embedded") == 0 ) {
+ g_tpm->extpol = TB_EXTPOL_EMBEDDED;
+ g_tpm->cur_alg = TB_HALG_SHA256;
+ } else if ( strcmp(extpol, "sha256") == 0 ) {
+ g_tpm->extpol = TB_EXTPOL_FIXED;
+ g_tpm->cur_alg = TB_HALG_SHA256;
+ } else if ( strcmp(extpol, "sha1") == 0 ) {
+ g_tpm->extpol = TB_EXTPOL_FIXED;
+ g_tpm->cur_alg = TB_HALG_SHA1;
+ } else if ( strcmp(extpol, "sm3") == 0 ) {
+ g_tpm->extpol = TB_EXTPOL_FIXED;
+ g_tpm->cur_alg = TB_HALG_SM3;
+ }
+}
+
+/*
+ * linux kernel command line parsing
+ */
+
+bool get_linux_vga(int *vid_mode)
+{
+ const char *vga = get_option_val(g_linux_cmdline_options,
+ g_linux_param_values, "vga");
+ if ( vga == NULL || vid_mode == NULL )
+ return false;
+
+ if ( strcmp(vga, "normal") == 0 )
+ *vid_mode = 0xFFFF;
+ else if ( strcmp(vga, "ext") == 0 )
+ *vid_mode = 0xFFFE;
+ else if ( strcmp(vga, "ask") == 0 )
+ *vid_mode = 0xFFFD;
+ else
+ *vid_mode = strtoul(vga, NULL, 0);
+
+ return true;
+}
+
+bool get_linux_mem(uint64_t *max_mem)
+{
+ char *last = NULL;
+ const char *mem = get_option_val(g_linux_cmdline_options,
+ g_linux_param_values, "mem");
+ if ( mem == NULL || max_mem == NULL )
+ return false;
+
+ *max_mem = strtoul(mem, &last, 0);
+ if ( *max_mem == 0 )
+ return false;
+
+ if ( last == NULL )
+ return true;
+
+ switch ( *last ) {
+ case 'G':
+ case 'g':
+ *max_mem = *max_mem << 30;
+ return true;
+ case 'M':
+ case 'm':
+ *max_mem = *max_mem << 20;
+ return true;
+ case 'K':
+ case 'k':
+ *max_mem = *max_mem << 10;
+ return true;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/com.c b/tboot/com.c
new file mode 100644
index 0000000..c1851a6
--- /dev/null
+++ b/tboot/com.c
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 1998 Michael Smith (msmith@freebsd.org)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Portions copyright (c) 2010, Intel Corporation
+ */
+
+/*
+ * sys/boot/i386/libi386/comconsole.c
+ */
+
+#include <config.h>
+#include <efibase.h>
+#include <types.h>
+#include <stdbool.h>
+#include <misc.h>
+#include <mutex.h>
+#include <io.h>
+#include <pci_cfgreg.h>
+#include <com.h>
+
+#define COMC_TXWAIT 0x40000 /* transmit timeout */
+#define COMC_BPS(x) (115200 / (x)) /* speed to DLAB divisor */
+#define COMC_DIV2BPS(x) (115200 / (x)) /* DLAB divisor to speed */
+
+#define OUTB(add, val) outb(g_com_port.comc_port + (add), (val))
+#define INB(add) inb(g_com_port.comc_port + (add))
+
+serial_port_t g_com_port = {115200, 0, 0x3, COM1_ADDR}; /* com1,115200,8n1 */
+
+bool g_psbdf_enabled;
+bool g_pbbdf_enabled;
+struct mutex pcicfg_mtx;
+
+static void comc_putchar(int c)
+{
+ int wait;
+
+ for ( wait = COMC_TXWAIT; wait > 0; wait-- )
+ if ( INB(com_lsr) & LSR_TXRDY ) {
+ OUTB(com_data, (u_char)c);
+ break;
+ }
+}
+
+static void comc_setup(int speed)
+{
+ OUTB(com_cfcr, CFCR_DLAB | g_com_port.comc_fmt);
+ OUTB(com_dlbl, COMC_BPS(speed) & 0xff);
+ OUTB(com_dlbh, COMC_BPS(speed) >> 8);
+ OUTB(com_cfcr, g_com_port.comc_fmt);
+ OUTB(com_mcr, MCR_RTS | MCR_DTR);
+
+ for ( int wait = COMC_TXWAIT; wait > 0; wait-- ) {
+ INB(com_data);
+ if ( !(INB(com_lsr) & LSR_RXRDY) )
+ break;
+ }
+}
+
+static void comc_pci_setup(void)
+{
+ if ( g_psbdf_enabled ) {
+ if ( g_pbbdf_enabled ) {
+ pcireg_cfgwrite(g_com_port.comc_pbbdf.bus,
+ g_com_port.comc_pbbdf.slot,
+ g_com_port.comc_pbbdf.func,
+ PCIR_IOBASEL_1,
+ (g_com_port.comc_port & 0xF000)
+ | ((g_com_port.comc_port & 0xF000) >> 8),
+ 2);
+ }
+ pcireg_cfgwrite(g_com_port.comc_psbdf.bus,
+ g_com_port.comc_psbdf.slot,
+ g_com_port.comc_psbdf.func,
+ PCIR_BARS,
+ g_com_port.comc_port | 0x1,
+ 4);
+ pcireg_cfgwrite(g_com_port.comc_psbdf.bus,
+ g_com_port.comc_psbdf.slot,
+ g_com_port.comc_psbdf.func,
+ PCIR_COMMAND,
+ 0x1,
+ 2);
+
+ mtx_init(&pcicfg_mtx);
+ }
+}
+
+void comc_init(void)
+{
+ comc_pci_setup();
+ comc_setup(g_com_port.comc_curspeed);
+}
+
+void comc_puts(const char *s, unsigned int cnt)
+{
+ while ( *s && cnt-- ) {
+ if ( *s == '\n' )
+ comc_putchar('\r');
+ comc_putchar(*s++);
+ }
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/efiboot.c b/tboot/efiboot.c
new file mode 100644
index 0000000..37ff734
--- /dev/null
+++ b/tboot/efiboot.c
@@ -0,0 +1,613 @@
+/*
+ * efiboot.c: EFI boot entry, early relocation and load code.
+ *
+ * Copyright (c) 2017 Assured Information Security.
+ *
+ * Ross Philipson <philipsonr@ainfosec.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+#include <efibase.h>
+#include <string.h>
+#include <stdbool.h>
+#include <misc.h>
+#include <page.h>
+#include <printk.h>
+#include <eficore.h>
+#include <eficonfig.h>
+#include <uuid.h>
+#include <hash.h>
+#include <mle.h>
+#include <txt/acmod.h>
+#include <tb_error.h>
+#include <tboot.h>
+
+static EFI_HANDLE g_image_handle;
+static EFI_HANDLE g_device_handle;
+static EFI_DEVICE_PATH *g_device_path;
+static void *g_init_base; /* before reloc */
+ void *g_image_base; /* after reloc */
+ void *g_rtmem_base; /* base of TBOOT runtime memory */
+ uint64_t g_image_size;
+ void *g_text_base;
+ uint64_t g_text_size;
+ void *g_bss_base;
+ uint64_t g_bss_size;
+
+static efi_file_t *g_configs;
+static EFI_FILE_IO_INTERFACE *g_file_system = NULL;
+
+/* Store raw config files in MLE so they can be measured */
+static __text uint8_t g_tboot_config_file[EFI_MAX_CONFIG_FILE];
+static __text uint8_t g_xen_config_file[EFI_MAX_CONFIG_FILE];
+
+#ifdef EFI_DEBUG
+static void efi_debug_pause(void)
+{
+ EFI_STATUS status;
+ EFI_INPUT_KEY key;
+
+ ST->ConIn->Reset(ST->ConIn, FALSE);
+ while ((status = ST->ConIn->ReadKeyStroke(ST->ConIn, &key)) == EFI_NOT_READY);
+}
+
+static void efi_debug_print_g(void)
+{
+ printk("EFI global:\n");
+ printk(" g_image_handle = %p\n", g_image_handle);
+ printk(" g_device_handle = %p\n", g_device_handle);
+ printk(" g_device_path = %p\n", g_device_path);
+ printk(" g_init_base = %p\n", g_init_base);
+ printk(" g_image_base = %p\n", g_image_base);
+ printk(" g_rtmem_base = %p\n", g_rtmem_base);
+ printk(" g_image_size = %x\n", (uint32_t)g_image_size);
+
+ efi_debug_pause();
+}
+
+static void efi_begin_launch(efi_xen_tboot_data_t *xtd);
+
+static void efi_debug_print_v(efi_tboot_xen_var_t *v)
+{
+ printk("EFI shared variable:\n");
+ printk(" revision = %llx\n", v->revision);
+ printk(" xen_config = %p\n", v->xen_config);
+ printk(" xen_config_size = %llx\n", v->xen_config_size);
+ printk(" begin_launch_cb = %llx\n", v->begin_launch_cb);
+ printk(" begin_launch = %p\n", efi_begin_launch);
+
+ efi_debug_pause();
+}
+
+static void efi_debug_print_w(const char *pfx, const wchar_t *wstr)
+{
+ char *p = wtoa_alloc(wstr);
+ printk("%s %s\n", pfx, p);
+ BS->FreePool(p);
+}
+
+#define efi_debug_print_s(p, s) printk("%s %s\n", p, s)
+
+#else
+#define efi_debug_pause()
+#define efi_debug_print_g()
+#define efi_debug_print_v(s)
+#define efi_debug_print_w(p, w)
+#define efi_debug_print_s(p, s)
+#endif
+
+static EFI_STATUS efi_start_next_image(const wchar_t *path)
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ EFI_DEVICE_PATH *dev_path = NULL;
+ EFI_HANDLE image_handle = NULL;
+ EFI_LOADED_IMAGE *loaded_image;
+
+ dev_path = efi_get_device_path(path, g_device_handle);
+ if (dev_path == NULL) {
+ char *p = wtoa_alloc(path);
+ printk("Failed to get device path for file %s\n", p);
+ BS->FreePool(p);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ status = BS->LoadImage(FALSE,
+ g_image_handle,
+ dev_path,
+ NULL,
+ 0,
+ &image_handle);
+ if (EFI_ERROR(status)) {
+ printk("Failed to load image - status: %d\n", status);
+ goto out;
+ }
+
+ status = BS->HandleProtocol(image_handle,
+ &LoadedImageProtocol,
+ (VOID*)&loaded_image);
+ if (EFI_ERROR(status)) {
+ printk("Failed to get loaded image info - status: %d\n", status);
+ goto out;
+ }
+ efi_store_xen_info(loaded_image->ImageBase, loaded_image->ImageSize);
+
+ status = BS->StartImage(image_handle, NULL, NULL);
+ if (EFI_ERROR(status))
+ printk("Failed to start image - status: %d\n", status);
+
+out:
+ BS->FreePool(dev_path);
+ return status;
+}
+
+void efi_launch_kernel(void)
+{
+ EFI_STATUS status;
+ wchar_t *file_path;
+
+ file_path = atow_alloc(efi_cfg_get_value(EFI_CONFIG_TBOOT_PARSED,
+ SECTION_TBOOT, ITEM_XENPATH));
+ if (!file_path) {
+ printk("Failed to allocate buffer for Xen file\n");
+ status = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
+ status = efi_start_next_image(file_path);
+ /* If we are still here then someting failed anyway */
+out:
+ ST->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_OUT_OF_RESOURCES, 0, NULL);
+}
+
+static void efi_begin_launch(efi_xen_tboot_data_t *xtd)
+{
+ g_post_ebs = true;
+ begin_launch(xtd);
+}
+
+static EFI_STATUS efi_setup_tboot_xen_var(void)
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ efi_tboot_xen_var_t var;
+
+ memset(&var, 0, sizeof(efi_tboot_xen_var_t));
+ var.revision = EFI_TBOOT_XEN_REV;
+ var.begin_launch_cb = (uint64_t)efi_begin_launch;
+ var.xen_config = g_configs[EFI_CONFIG_XEN].u.buffer;
+ var.xen_config_size = g_configs[EFI_CONFIG_XEN].size;
+
+ status = RT->SetVariable(EFI_TBOOT_XEN_NAME,
+ &TbootXenGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(efi_tboot_xen_var_t),
+ &var);
+ if (EFI_ERROR(status))
+ printk("Failed to set shared RT variable - status: %d\n", status);
+
+ efi_debug_print_v(&var);
+
+ return status;
+}
+
+static bool efi_is_platform_sinit_module(wchar_t *file_path,
+ efi_file_t *file_out)
+{
+ EFI_STATUS status;
+
+ /* Read the TBOOT config into RT memory and store */
+ status = efi_read_file(g_file_system,
+ file_path,
+ EfiRuntimeServicesData,
+ &file_out->size,
+ &file_out->u.addr);
+ if (EFI_ERROR(status)) {
+ printk("Failed to read ACM file - status: %d\n", status);
+ return false;
+ }
+
+ if (is_sinit_acmod(file_out->u.buffer, file_out->size, true) &&
+ does_acmod_match_platform((acm_hdr_t*)file_out->u.buffer)) {
+ printk(TBOOT_DETA"SINIT matches platform\n");
+ return true;
+ }
+
+ BS->FreePages(file_out->u.addr, PFN_UP(file_out->size));
+ file_out->u.addr = 0;
+ file_out->size = 0;
+
+ return false;
+}
+
+static EFI_STATUS efi_load_core_files(void)
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ int key;
+ char keystr[16];
+ const char *value;
+ wchar_t *file_path;
+ uint32_t size;
+ efi_file_t sinit_file = {0, 0};
+
+ /* TODO we don't have any RACMs right now so kick the can down the road... */
+ /* TODO we don't use an LCP so kick the can down the road... */
+
+ for (key = 0; ; key++) {
+ snprintf(keystr, 16, "%d", key);
+ value = efi_cfg_get_value(EFI_CONFIG_TBOOT_PARSED,
+ SECTION_ACM, keystr);
+ if (!value)
+ break;
+
+ file_path = atow_cat(g_tboot_dir, value);
+ if (!file_path) {
+ printk("Failed to allocate buffer for ACM file name\n");
+ status = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
+ efi_debug_print_w("ACM:", file_path);
+
+ /* Found one */
+ if (efi_is_platform_sinit_module(file_path, &sinit_file)) {
+ BS->FreePool(file_path);
+ break;
+ }
+
+ BS->FreePool(file_path);
+
+ /* Errors not fatal but the config likely includes missing files */
+ }
+
+ if (!sinit_file.u.buffer) {
+ printk(TBOOT_ERR"no SINIT AC module found\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ /* Set the files we found */
+ efi_store_files(&sinit_file, NULL, NULL);
+out:
+ return status;
+}
+
+static void efi_form_config_path(wchar_t *path)
+{
+ wchar_t *ptr = path + wcslen(path);
+
+ efi_debug_print_w("IMAGE PATH:", path);
+
+ /* Form the config file path */
+ while (ptr >= path) {
+ if (*ptr == L'.') {
+ memcpy((ptr + 1), L"cfg\0", 8);
+ break;
+ }
+ ptr--;
+ }
+
+ efi_debug_print_w("CONFIG PATH:", path);
+}
+
+static EFI_STATUS efi_load_configs(void)
+{
+ EFI_STATUS status;
+ wchar_t *file_path = NULL;
+ EFI_PHYSICAL_ADDRESS addr = TBOOT_MAX_IMAGE_MEM;
+ void *buffer = NULL;
+ uint64_t size;
+
+ /* Get file path for TBOOT image and config */
+ status = BS->AllocatePool(EfiLoaderData,
+ (EFI_MAX_PATH + 4)*sizeof(wchar_t),
+ (void**)&file_path);
+ if (EFI_ERROR(status)) {
+ printk("Failed to alloc image path buffer - status: %d\n", status);
+ return status;
+ }
+
+ status = efi_device_path_to_text(g_device_path,
+ file_path,
+ EFI_MAX_PATH);
+ if (EFI_ERROR(status)) {
+ printk("Failed to get TBOOT config path - status: %d\n", status);
+ goto err;
+ }
+
+ /* Save a copy of the TBOOT dir for later */
+ if (!efi_cfg_copy_tboot_path(file_path)) {
+ status = EFI_INVALID_PARAMETER;
+ printk("Failed to save TBOOT path - status: %d\n", status);
+ goto err;
+ }
+
+ efi_form_config_path(file_path);
+
+ /* Read the TBOOT config into RT memory and store */
+ status = efi_read_file(g_file_system,
+ file_path,
+ EfiRuntimeServicesData,
+ &size,
+ &addr);
+ if (EFI_ERROR(status)) {
+ printk("Failed to read TBOOT config file - status: %d\n", status);
+ goto err;
+ }
+
+ if (size > EFI_MAX_CONFIG_FILE) {
+ status = EFI_INVALID_PARAMETER;
+ printk("TBOOT config file too big - size: %d\n", size);
+ goto err;
+ }
+
+ /* Make a copy of the raw TBOOT config in the MLE */
+ memcpy(g_tboot_config_file, (void*)addr, size);
+ g_configs[EFI_CONFIG_TBOOT].u.buffer = g_tboot_config_file;
+ g_configs[EFI_CONFIG_TBOOT].size = size;
+
+ /* Parse original */
+ g_configs[EFI_CONFIG_TBOOT_PARSED].u.addr = addr;
+ g_configs[EFI_CONFIG_TBOOT_PARSED].size = size;
+ efi_cfg_pre_parse(&g_configs[EFI_CONFIG_TBOOT_PARSED]);
+ BS->FreePool(file_path);
+
+ /* Get file path for Xen image and config */
+ file_path = atow_alloc(efi_cfg_get_value(EFI_CONFIG_TBOOT_PARSED,
+ SECTION_TBOOT, ITEM_XENPATH));
+ if (!file_path) {
+ printk("Failed to allocate buffer for Xen config file\n");
+ status = EFI_OUT_OF_RESOURCES;
+ goto err;
+ }
+
+ efi_form_config_path(file_path);
+
+ /* Read the Xen config (non-modified) into RT memory and store */
+ status = efi_read_file(g_file_system,
+ file_path,
+ EfiRuntimeServicesData,
+ &size,
+ &addr);
+ if (EFI_ERROR(status)) {
+ printk("Failed to read Xen config file - status: %d\n", status);
+ goto err;
+ }
+
+ if (size > EFI_MAX_CONFIG_FILE) {
+ status = EFI_INVALID_PARAMETER;
+ printk("Xen config file too big - size: %d\n", size);
+ goto err;
+ }
+
+ /* Make a copy of the raw TBOOT config in the MLE */
+ memcpy(g_xen_config_file, (void*)addr, size);
+ g_configs[EFI_CONFIG_XEN].u.buffer = g_xen_config_file;
+ g_configs[EFI_CONFIG_XEN].size = size;
+
+ /* Parse original */
+ g_configs[EFI_CONFIG_XEN_PARSED].u.addr = addr;
+ g_configs[EFI_CONFIG_XEN_PARSED].size = size;
+ efi_cfg_pre_parse(&g_configs[EFI_CONFIG_XEN_PARSED]);
+ BS->FreePool(file_path);
+
+ /* Locate and split off the kernel cmdline */
+ if (!efi_split_kernel_line()) {
+ printk("Failed to parse and find kernel entry in Xen config\n");
+ status = EFI_INVALID_PARAMETER;
+ goto err;
+ }
+ efi_debug_print_s("KERNEL CMDLINE:", g_kernel_cmdline);
+
+ return EFI_SUCCESS;
+
+err:
+ if (g_configs[EFI_CONFIG_XEN].u.buffer)
+ BS->FreePages(g_configs[EFI_CONFIG_XEN].u.addr,
+ PFN_UP(g_configs[EFI_CONFIG_XEN].size));
+ if (g_configs[EFI_CONFIG_TBOOT].u.buffer)
+ BS->FreePages(g_configs[EFI_CONFIG_TBOOT].u.addr,
+ PFN_UP(g_configs[EFI_CONFIG_TBOOT].size));
+
+ if (file_path)
+ BS->FreePool(file_path);
+
+ return status;
+}
+
+EFI_STATUS efi_start(EFI_HANDLE ImageHandle,
+ EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_STATUS status;
+
+ printk("TBOOT START Entry Point: %p\n", efi_start);
+ efi_debug_print_g();
+
+ /* Open the file system for the boot partition once up front */
+ status = BS->OpenProtocol(g_device_handle,
+ &FileSystemProtocol,
+ (void**)&g_file_system,
+ g_image_handle,
+ NULL,
+ EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
+ if (EFI_ERROR(status)) {
+ printk("Failed to open FileSystemProtocol - status: %d\n", status);
+ goto out;
+ }
+
+ efi_cfg_init();
+ g_configs = efi_get_configs();
+
+ /* Locate the .text section and length */
+ g_text_base = efi_get_pe_section(".text", g_image_base,
+ &g_text_size);
+ if (g_text_base) {
+ printk("Located .text section: %p size: %llx\n",
+ g_text_base, g_text_size);
+ /* Sanity check the location of the .text section in the image */
+ if ((g_text_base - g_image_base) != PAGE_SIZE) {
+ printk("The .text offset must be at 1 page into TBOOT image!\n");
+ goto out;
+ }
+ }
+ else {
+ printk("Failed to locate .text section\n");
+ status = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* Locate the .bss section and length */
+ g_bss_base = efi_get_pe_section(".bss", g_image_base,
+ &g_bss_size);
+ if (g_bss_base) {
+ printk("Located .bss section: %p size: %llx\n",
+ g_bss_base, g_bss_size);
+ }
+ else {
+ printk("Failed to locate .text section\n");
+ status = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
+ /* Load the configuration files and information */
+ status = efi_load_configs();
+ if (EFI_ERROR(status))
+ goto out;
+
+ /* Load the platform SINIT, RACM and LCP */
+ status = efi_load_core_files();
+ if (EFI_ERROR(status))
+ goto out;
+
+ /* Setup RT shared variable */
+ status = efi_setup_tboot_xen_var();
+ if (EFI_ERROR(status))
+ goto out;
+
+ /* Begin initial launch */
+ begin_initial_launch();
+
+ /* Start Xen here */
+ efi_launch_kernel();
+
+ /* SNO */
+ printk("FATAL: could not launch Xen!\n");
+
+out:
+ efi_debug_pause();
+
+ /* Should not reach here unless something failed */
+ ST->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
+
+ return EFI_SUCCESS;
+}
+
+static EFI_STATUS efi_reloc_and_call(void)
+{
+ EFI_STATUS status;
+ uint64_t size;
+ EFI_PHYSICAL_ADDRESS addr = TBOOT_MAX_IMAGE_MEM;
+ uint64_t efi_start_ptr;
+
+ /*
+ * TODO we may have to pick and force an address since right now we are at
+ * the mercy of EFI picking a runtime service code range. If this ends up
+ * outside the PMRs due to the crazy min_ram stuff then pain and misery
+ * will ensue.
+ */
+
+ status = BS->AllocatePages(AllocateMaxAddress,
+ EfiRuntimeServicesCode,
+ PFN_UP(g_image_size) + TBOOT_RTMEM_COUNT,
+ &addr);
+ if (EFI_ERROR(status))
+ return status;
+
+ g_rtmem_base = (void*)addr;
+ g_image_base = (void*)(addr + TBOOT_RTMEM_SIZE);
+ memset(g_rtmem_base, 0, g_image_size + TBOOT_RTMEM_SIZE);
+
+ /* Copy me to new location */
+ memcpy(g_image_base, g_init_base, g_image_size);
+
+ efi_start_ptr = (uint64_t)g_image_base +
+ ((uint64_t)efi_start - (uint64_t)g_init_base);
+
+ /* End of the line */
+ __asm__ __volatile__ (
+ "movq %0, %%rdx\n\t"
+ "movq %1, %%rcx\n\t"
+ "call *%%rax\n\t"
+ :
+ : "g" (ST), "g" (g_image_handle), "a" (efi_start_ptr));
+
+ return EFI_LOAD_ERROR; /* SNO! */
+}
+
+EFI_STATUS efi_main(EFI_HANDLE ImageHandle,
+ EFI_SYSTEM_TABLE *SystemTable)
+{
+ EFI_STATUS status;
+ EFI_LOADED_IMAGE *loaded_image;
+
+ /* Store the system table for future use in other functions */
+ ST = SystemTable;
+ BS = ST->BootServices;
+ RT = ST->RuntimeServices;
+
+ /* So we can use printk via EFI console protocol */
+ printk_init(INIT_EARLY_EFI);
+ printk("TBOOT EFI Entry Point: %p\n", efi_main);
+
+ status = BS->HandleProtocol(ImageHandle,
+ &LoadedImageProtocol,
+ (VOID*)&loaded_image);
+
+ if (!EFI_ERROR(status)) {
+ /* Device we were loaded from, EFI partition */
+ g_device_handle = loaded_image->DeviceHandle;
+ g_device_path = loaded_image->FilePath;
+ g_init_base = loaded_image->ImageBase;
+ g_image_size = loaded_image->ImageSize;
+ g_image_handle = ImageHandle;
+ }
+ else {
+ printk("TBOOT FATAL! Cannot get loaded image information\n");
+ ST->RuntimeServices->ResetSystem(EfiResetShutdown, status, 0, NULL);
+ }
+
+ efi_debug_print_g();
+
+ /* Relocate this image and call, never return */
+ status = efi_reloc_and_call();
+
+ /* Should not be here! */
+ printk("TBOOT FATAL! relocate and call failed - status: %x\n", status);
+ ST->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
+
+ return status;
+}
diff --git a/tboot/eficonfig.c b/tboot/eficonfig.c
new file mode 100644
index 0000000..2d6d699
--- /dev/null
+++ b/tboot/eficonfig.c
@@ -0,0 +1,299 @@
+/*
+ * eficonfig.c: EFI related configuration settings and data.
+ *
+ * Copyright (c) 2017 Assured Information Security.
+ *
+ * Ross Philipson <philipsonr@ainfosec.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+#include <efibase.h>
+#include <stdbool.h>
+#include <types.h>
+#include <ctype.h>
+#include <string.h>
+#include <misc.h>
+#include <eficore.h>
+#include <eficonfig.h>
+#include <printk.h>
+
+/* The main config files read from disk */
+efi_file_t g_efi_configs[EFI_CONFIG_MAX];
+
+/* Root path to TBOOT image home */
+wchar_t g_tboot_dir[EFI_MAX_PATH];
+
+/* Is this pre or post EBS */
+bool g_post_ebs = false;
+
+const char *g_kernel_cmdline = "";
+
+/* Core TXT and TBOOT files stored in EfiRuntimeServicesData */
+efi_file_t g_platform_sinit;
+efi_file_t g_platform_racm;
+efi_file_t g_lcp;
+
+/* The xen image plush the kernl and ramdisk images passed back from Xen */
+efi_file_t g_xen;
+efi_file_t g_kernel;
+efi_file_t g_ramdisk;
+
+/* EFI memory map just before EBS from Xen */
+void *g_memory_map;
+uint64_t g_memory_map_size;
+uint64_t g_memory_desc_size;
+
+/* Xen post launch callback */
+uint64_t g_xen_post_launch_cb;
+
+void efi_cfg_init(void)
+{
+ memset(&g_tboot_dir[0], 0, EFI_MAX_PATH*sizeof(wchar_t));
+ memset(&g_efi_configs[0], 0, EFI_CONFIG_MAX*sizeof(efi_file_t));
+}
+
+efi_file_t *efi_get_configs(void)
+{
+ return &g_efi_configs[0];
+}
+
+void efi_cfg_pre_parse(efi_file_t *config)
+{
+ char *ptr = config->u.buffer, *end = ptr + config->size;
+ bool start = true, comment = false;
+
+ for ( ; ptr < end; ++ptr ) {
+ if ( iscntrl(*ptr) ) {
+ comment = false;
+ start = true;
+ *ptr = 0;
+ }
+ else if ( comment || (start && isspace(*ptr)) ) {
+ *ptr = 0;
+ }
+ else if ( *ptr == '#' || (start && *ptr == ';') ) {
+ comment = true;
+ *ptr = 0;
+ }
+ else
+ start = false;
+ }
+ if ( config->size && end[-1] )
+ printk("No newline at end of config file last line will be ignored.\n");
+}
+
+char *efi_cfg_get_value(int index, const char *section,
+ const char *item)
+{
+ efi_file_t *config;
+ char *ptr, *end;
+ size_t slen = section ? strlen(section) : 0, ilen = strlen(item);
+ bool match = !slen;
+
+ if (index >= EFI_CONFIG_MAX)
+ return NULL;
+
+ config = &g_efi_configs[index];
+ ptr = config->u.buffer;
+ end = ptr + config->size;
+
+ for ( ; ptr < end; ++ptr ) {
+ switch ( *ptr ) {
+ case 0:
+ continue;
+ case '[':
+ if ( !slen )
+ break;
+ if ( match )
+ return NULL;
+ match = strncmp(++ptr, section, slen) == 0 && ptr[slen] == ']';
+ break;
+ default:
+ if ( match && strncmp(ptr, item, ilen) == 0 && ptr[ilen] == '=' ) {
+ ptr += ilen + 1;
+ /* strip off any leading spaces */
+ while ( *ptr && isspace(*ptr) )
+ ptr++;
+ return ptr;
+ }
+ break;
+ }
+ ptr += strlen(ptr);
+ }
+ return NULL;
+}
+
+bool efi_split_kernel_line(void)
+{
+ char *ptr;
+
+ ptr = efi_cfg_get_value(EFI_CONFIG_XEN_PARSED,
+ SECTION_GLOBAL, ITEM_DEFAULT);
+ if (!ptr)
+ return false;
+
+ ptr = efi_cfg_get_value(EFI_CONFIG_XEN_PARSED,
+ ptr, ITEM_KERNEL);
+ if (!ptr)
+ return false;
+
+ for ( ; *ptr && !isspace(*ptr); ptr++);
+
+ if (ptr) {
+ *ptr = 0;
+ g_kernel_cmdline = ptr + 1;
+ }
+ /* Else there is no kernel cmdline - I guess that is possible */
+
+ return true;
+}
+
+bool efi_cfg_copy_tboot_path(const wchar_t *file_path)
+{
+ uint64_t len = wcslen(file_path);
+ wchar_t *ptr = g_tboot_dir + len;
+
+ if (len >= EFI_MAX_PATH)
+ return false;
+
+ memcpy(g_tboot_dir, file_path, len*sizeof(wchar_t));
+
+ while (ptr >= g_tboot_dir) {
+ if (*ptr == L'\\') {
+ *(ptr + 1) = L'\0';
+ return true;
+ }
+ ptr--;
+ }
+
+ return false;
+}
+
+const efi_file_t *efi_get_platform_sinit(void)
+{
+ if (g_platform_sinit.size > 0)
+ return &g_platform_sinit;
+ return NULL;
+}
+
+const efi_file_t *efi_get_platform_racm(void)
+{
+ if (g_platform_racm.size > 0)
+ return &g_platform_racm;
+ return NULL;
+}
+
+const efi_file_t *efi_get_lcp(void)
+{
+ if (g_lcp.size > 0)
+ return &g_lcp;
+ return NULL;
+}
+
+void efi_store_files(const efi_file_t *platform_sinit,
+ const efi_file_t *platform_racm,
+ const efi_file_t *lcp)
+{
+ memset(&g_platform_sinit, 0, sizeof(efi_file_t));
+ memset(&g_platform_racm, 0, sizeof(efi_file_t));
+ memset(&g_lcp, 0, sizeof(efi_file_t));
+
+ if (platform_sinit && platform_sinit->u.buffer)
+ g_platform_sinit = *platform_sinit;
+ if (platform_racm && platform_racm->u.buffer)
+ g_platform_racm = *platform_racm;
+ if (lcp && lcp->u.buffer)
+ g_lcp = *lcp;
+}
+
+const efi_file_t *efi_get_xen(void)
+{
+ if (g_xen.size > 0)
+ return &g_xen;
+ return NULL;
+}
+
+const efi_file_t *efi_get_kernel(void)
+{
+ if (g_kernel.size > 0)
+ return &g_kernel;
+ return NULL;
+}
+
+const efi_file_t *efi_get_ramdisk(void)
+{
+ if (g_ramdisk.size > 0)
+ return &g_ramdisk;
+ return NULL;
+}
+
+const void *efi_get_memory_map(uint64_t *size_out, uint64_t *size_desc_out)
+{
+ *size_out = g_memory_map_size;
+ *size_desc_out = g_memory_desc_size;
+ return g_memory_map;
+}
+
+uint64_t efi_get_xen_post_launch_cb(void)
+{
+ return g_xen_post_launch_cb;
+}
+
+void efi_store_xen_info(void *base, uint64_t size)
+{
+ memset(&g_xen, 0, sizeof(efi_file_t));
+ g_xen.u.buffer = base;
+ g_xen.size = size;
+}
+
+bool efi_store_xen_tboot_data(efi_xen_tboot_data_t *xtd)
+{
+ /* sanity */
+ if ( (xtd->kernel == NULL) || (xtd->kernel_size == 0) ||
+ (xtd->ramdisk == NULL) || (xtd->ramdisk_size == 0) ||
+ (xtd->memory_map == NULL) || (xtd->memory_map_size == 0) ||
+ (xtd->memory_desc_size == 0))
+ return false;
+
+ memset(&g_kernel, 0, sizeof(efi_file_t));
+ memset(&g_ramdisk, 0, sizeof(efi_file_t));
+
+ g_kernel.u.buffer = xtd->kernel;
+ g_kernel.size = xtd->kernel_size;
+ g_ramdisk.u.buffer = xtd->ramdisk;
+ g_ramdisk.size = xtd->ramdisk_size;
+ g_memory_map = xtd->memory_map;
+ g_memory_map_size = xtd->memory_map_size;
+ g_memory_desc_size = xtd->memory_desc_size;
+ g_xen_post_launch_cb = xtd->post_launch_cb;
+
+ return true;
+}
+
diff --git a/tboot/eficore.c b/tboot/eficore.c
new file mode 100644
index 0000000..71cdc09
--- /dev/null
+++ b/tboot/eficore.c
@@ -0,0 +1,534 @@
+/*
+ * eficore.c: EFI core support code.
+ *
+ * Copyright (c) 2017 Assured Information Security.
+ *
+ * Ross Philipson <philipsonr@ainfosec.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+#include <efibase.h>
+#include <stdbool.h>
+#include <string.h>
+#include <page.h>
+#include <printk.h>
+#include <eficore.h>
+#include <eficonfig.h>
+#include <pe.h>
+#include <tb_error.h>
+#include <tboot.h>
+
+/* Global Table Pointers */
+EFI_SYSTEM_TABLE *ST;
+EFI_BOOT_SERVICES *BS;
+EFI_RUNTIME_SERVICES *RT;
+
+/* Local device paths */
+EFI_DEVICE_PATH EfiRootDevicePath[] = {
+ {END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, {END_DEVICE_PATH_LENGTH,0}}
+};
+
+EFI_DEVICE_PATH EfiEndDevicePath[] = {
+ {END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, {END_DEVICE_PATH_LENGTH, 0}}
+};
+
+EFI_DEVICE_PATH EfiEndInstanceDevicePath[] = {
+ {END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, {END_DEVICE_PATH_LENGTH, 0}}
+};
+
+
+/* EFI IDs */
+EFI_GUID EfiGlobalVariable = EFI_GLOBAL_VARIABLE;
+EFI_GUID NullGuid = { 0,0,0,{0,0,0,0,0,0,0,0} };
+EFI_GUID UnknownDevice = UNKNOWN_DEVICE_GUID;
+
+/* Protocol IDs */
+EFI_GUID DevicePathProtocol = DEVICE_PATH_PROTOCOL;
+EFI_GUID LoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
+EFI_GUID FileSystemProtocol = SIMPLE_FILE_SYSTEM_PROTOCOL;
+
+/* File system information IDs */
+EFI_GUID GenericFileInfo = EFI_FILE_INFO_ID;
+
+/* Configuration Table GUIDs */
+EFI_GUID AcpiTableGuid = ACPI_TABLE_GUID;
+EFI_GUID Acpi20TableGuid = ACPI_20_TABLE_GUID;
+EFI_GUID SMBIOSTableGuid = SMBIOS_TABLE_GUID;
+
+/* TBOOT/Xen */
+EFI_GUID TbootXenGuid = EFI_TBOOT_XEN_GUID;
+
+void atow(wchar_t *dst, const char *src, uint64_t count)
+{
+ uint64_t i;
+
+ for (i = 0; i < count; i++, dst++, src++)
+ *dst = (*src & 0x7f);
+}
+
+bool wtoa(char *dst, const wchar_t *src, uint64_t count)
+{
+ uint64_t i;
+ bool r = true;
+
+ for (i = 0; i < count; i++, dst++, src++) {
+ if (*dst <= 0x7f) {
+ *dst = *src;
+ }
+ else {
+ r = false;
+ *dst = '_';
+ }
+ }
+
+ return r;
+}
+
+uint64_t wcslen(const wchar_t *str)
+{
+ uint64_t len;
+
+ for (len = 0; *str != L'\0'; str++, len++)
+ ;
+
+ return ++len;
+}
+
+wchar_t *atow_alloc(const char *src)
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ wchar_t *dst;
+ uint64_t count, size;
+
+ if (!src)
+ return NULL;
+
+ count = strlen(src);
+ size = (count + 1)*sizeof(wchar_t);
+
+ status = BS->AllocatePool(EfiLoaderData, size, (void**)&dst);
+ if (EFI_ERROR(status))
+ return NULL;
+
+ memset(dst, 0, size);
+
+ atow(dst, src, count);
+ return dst;
+}
+
+char *wtoa_alloc(const wchar_t *src)
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ char *dst;
+ uint64_t count, size;
+
+ if (!src)
+ return NULL;
+
+ count = wcslen(src);
+ size = (count + 1)*sizeof(char);
+
+ status = BS->AllocatePool(EfiLoaderData, size, (void**)&dst);
+ if (EFI_ERROR(status))
+ return NULL;
+
+ memset(dst, 0, size);
+
+ wtoa(dst, src, count);
+ return dst;
+}
+
+wchar_t *atow_cat(const wchar_t *base, const char *tail)
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ wchar_t *dst;
+ uint64_t wcount, scount, size;
+
+ if (!base || !tail)
+ return NULL;
+
+ scount = strlen(tail);
+ wcount = wcslen(base);
+ size = (wcount + scount + 1)*sizeof(wchar_t);
+
+ status = BS->AllocatePool(EfiLoaderData, size, (void**)&dst);
+ if (EFI_ERROR(status))
+ return NULL;
+
+ memset(dst, 0, size);
+ memcpy(dst, g_tboot_dir, wcount*sizeof(wchar_t));
+ atow((dst + wcount - 1), tail, scount);
+
+ return dst;
+}
+
+uint8_t *efi_get_rsdp(void)
+{
+ EFI_CONFIGURATION_TABLE *conf_table = ST->ConfigurationTable;
+ uint8_t *acpi_rsdp = NULL;
+ uint64_t count;
+
+ for (count = 0; count < ST->NumberOfTableEntries; count++, conf_table++) {
+ if (!memcmp(&Acpi20TableGuid, &conf_table->VendorGuid, sizeof(EFI_GUID)) ||
+ !memcmp(&AcpiTableGuid, &conf_table->VendorGuid, sizeof(EFI_GUID))) {
+ acpi_rsdp = conf_table->VendorTable;
+ break;
+ }
+ }
+
+ return acpi_rsdp;
+}
+
+void *efi_get_pe_section(const char *name, void *image_base,
+ uint64_t *size_out)
+{
+#define calc_addr(b, o) (void*)(((uint8_t*)b) + o);
+ IMAGE_DOS_HEADER *dosh;
+ IMAGE_NT_HEADERS *nth;
+ IMAGE_FILE_HEADER *fh;
+ IMAGE_SECTION_HEADER *sh;
+ uint16_t i;
+ void *text = NULL;
+ size_t length = strlen(name);
+
+ dosh = (IMAGE_DOS_HEADER*)image_base;
+ nth = (IMAGE_NT_HEADERS*)calc_addr(dosh, dosh->e_lfanew);
+
+ if (dosh->e_magic != IMAGE_DOS_SIGNATURE) {
+ printk("Invalid DOS header signature: %x\n", dosh->e_magic);
+ return NULL;
+ }
+
+ if (nth->Signature != IMAGE_NT_SIGNATURE) {
+ printk("Invalid NT header signature: %x\n", nth->Signature);
+ return NULL;
+ }
+
+ fh = (IMAGE_FILE_HEADER*)calc_addr(nth, sizeof(uint32_t));
+ sh = (IMAGE_SECTION_HEADER*)calc_addr(fh, sizeof(IMAGE_FILE_HEADER) +
+ fh->SizeOfOptionalHeader);
+
+ for (i = 0; i < fh->NumberOfSections; i++, sh++) {
+ if (!memcmp(name, sh->Name, length)) {
+ text = (void*)((uint8_t*)image_base + sh->VirtualAddress);
+ *size_out = sh->Misc.VirtualSize;
+ break;
+ }
+ }
+
+ return text;
+}
+
+void efi_shutdown_system(uint32_t shutdown_type)
+{
+ switch (shutdown_type) {
+ case TB_SHUTDOWN_S5:
+ RT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
+ case TB_SHUTDOWN_REBOOT:
+ RT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+ defaut:
+ ;
+ };
+}
+
+/* Logging support */
+static void atow_log(CHAR16 *dst, const char *src, uint32_t count)
+{
+ uint32_t i;
+ char c;
+
+ for (i = 0; i < count; i++, dst++, src++) {
+ c = (*src & 0x7f);
+ if (c == '\n') {
+ *dst = L'\r';
+ dst++;
+ }
+ *dst = c;
+ }
+}
+
+void efi_puts(const char *s, unsigned int count)
+{
+ CHAR16 wbuf[2*TBOOT_LOGBUF_SIZE];
+
+ memset(wbuf, 0, sizeof(CHAR16)*2*TBOOT_LOGBUF_SIZE);
+ atow_log(wbuf, s, count);
+ (void)ST->ConOut->OutputString(ST->ConOut, wbuf);
+}
+
+static uint64_t efi_device_path_size(EFI_DEVICE_PATH *dpath)
+{
+ EFI_DEVICE_PATH *tpath = dpath;
+
+ while (!IsDevicePathEnd(tpath))
+ tpath = NextDevicePathNode(tpath);
+
+ return ((uint64_t)tpath - (uint64_t)dpath) + sizeof(EFI_DEVICE_PATH);
+}
+
+static EFI_DEVICE_PATH *efi_device_path_instance(EFI_DEVICE_PATH **dpath,
+ uint64_t *size)
+{
+ EFI_DEVICE_PATH *spath = *dpath, *npath, *tpath = *dpath;
+
+ if (!tpath)
+ return NULL;
+
+ for ( ; ; ) {
+ npath = NextDevicePathNode(tpath);
+
+ if (IsDevicePathEndType(tpath))
+ break;
+
+ tpath = npath;
+ }
+
+ if (DevicePathSubType(tpath) == END_ENTIRE_DEVICE_PATH_SUBTYPE)
+ npath = NULL;
+
+ *dpath = npath;
+
+ if (size)
+ *size = ((uint64_t)tpath) - ((uint64_t)spath);
+ return spath;
+}
+
+static EFI_DEVICE_PATH *efi_append_device_path(EFI_DEVICE_PATH *dpath1,
+ EFI_DEVICE_PATH *dpath2)
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ uint64_t size1, size2, inst = 0, size;
+ EFI_DEVICE_PATH *tpath = dpath1, *ipath, *opath;
+ uint8_t *pos;
+
+ size1 = efi_device_path_size(dpath1);
+ size2 = efi_device_path_size(dpath2);
+
+ while (efi_device_path_instance(&tpath, NULL))
+ inst++;
+
+ size = (size1 * inst) + size2;
+
+ status = BS->AllocatePool(EfiLoaderData, size, (void**)&opath);
+ if (EFI_ERROR(status))
+ return NULL;
+
+ pos = (uint8_t*)opath;
+ ipath = efi_device_path_instance(&dpath1, &size);
+
+ for ( ; ; ) {
+ if (!ipath)
+ break;
+
+ memcpy(pos, ipath, size);
+ pos += size;
+ memcpy(pos, dpath2, size2);
+ pos += size2;
+ memcpy(pos, EfiEndInstanceDevicePath, sizeof(EFI_DEVICE_PATH));
+ pos += sizeof(EFI_DEVICE_PATH);
+
+ ipath = efi_device_path_instance(&dpath1, &size);
+ }
+
+ pos -= sizeof(EFI_DEVICE_PATH);
+ memcpy(pos, EfiEndDevicePath, sizeof(EFI_DEVICE_PATH));
+
+ return opath;
+}
+
+EFI_DEVICE_PATH *efi_get_device_path(const wchar_t *path, EFI_HANDLE parent)
+{
+ EFI_STATUS status = EFI_SUCCESS;
+ FILEPATH_DEVICE_PATH *file_path = NULL;
+ EFI_DEVICE_PATH *dev_path = NULL, *parent_path, *eo_path;
+ uint64_t size = wcslen(path)*sizeof(wchar_t);
+
+ status = BS->AllocatePool(EfiLoaderData,
+ size + SIZE_OF_FILEPATH_DEVICE_PATH + sizeof(EFI_DEVICE_PATH),
+ (void**)&file_path);
+ if (EFI_ERROR(status))
+ return NULL;
+
+ status = BS->HandleProtocol(parent, &DevicePathProtocol, (void**)&parent_path);
+ if (EFI_ERROR(status)) {
+ BS->FreePool(file_path);
+ return NULL;
+ }
+
+ file_path->Header.Type = MEDIA_DEVICE_PATH;
+ file_path->Header.SubType = MEDIA_FILEPATH_DP;
+ SetDevicePathNodeLength(&file_path->Header, size + SIZE_OF_FILEPATH_DEVICE_PATH);
+ memcpy(file_path->PathName, path, size);
+ eo_path = NextDevicePathNode(&file_path->Header);
+ SetDevicePathEndNode(eo_path);
+
+ dev_path = efi_append_device_path(parent_path, (EFI_DEVICE_PATH*)file_path);
+ BS->FreePool(file_path);
+
+ return dev_path;
+}
+
+EFI_STATUS efi_device_path_to_text(EFI_DEVICE_PATH *dev_path,
+ wchar_t *path_out,
+ uint64_t count)
+{
+#define size_needed(d) (DevicePathNodeLength(d) - \
+ (sizeof(EFI_DEVICE_PATH) - sizeof(wchar_t)))
+#define copy_size(d) (DevicePathNodeLength(d) - sizeof(EFI_DEVICE_PATH))
+ EFI_STATUS status = EFI_SUCCESS;
+ FILEPATH_DEVICE_PATH *file_path;
+ uint64_t size = count*sizeof(wchar_t);
+
+ while (DevicePathType(dev_path) != END_DEVICE_PATH_TYPE) {
+ /* Space check first */
+ if (size < size_needed(dev_path))
+ return EFI_BUFFER_TOO_SMALL;
+
+ /* Copy in latest bits of the path */
+ file_path = (FILEPATH_DEVICE_PATH*)dev_path;
+ memcpy(path_out, file_path->PathName, copy_size(dev_path));
+ path_out[copy_size(dev_path)/sizeof(wchar_t)] = 0;
+ dev_path = (EFI_DEVICE_PATH*)((uint64_t)dev_path +
+ DevicePathNodeLength(dev_path));
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_FILE_INFO *efi_get_file_info(EFI_FILE *target_file,
+ EFI_MEMORY_TYPE mem_type)
+{
+ EFI_STATUS status;
+ void *buffer = NULL;
+ UINTN size = SIZE_OF_EFI_FILE_INFO + 256;
+ uint32_t i;
+
+ for (i = 0; i < 2; i++) {
+ status = BS->AllocatePool(mem_type, size, &buffer);
+ if (!buffer)
+ return NULL;
+
+ status = target_file->GetInfo(target_file,
+ &GenericFileInfo,
+ &size,
+ buffer);
+ if (EFI_ERROR(status)) {
+ BS->FreePool(buffer);
+ buffer = NULL;
+ if (status != EFI_BUFFER_TOO_SMALL)
+ return NULL;
+ continue;
+ }
+ break;
+ }
+
+ return buffer;
+}
+
+EFI_STATUS efi_read_file(EFI_FILE_IO_INTERFACE *file_system,
+ wchar_t *file_name,
+ EFI_MEMORY_TYPE mem_type,
+ uint64_t *size_out,
+ EFI_PHYSICAL_ADDRESS *addr_out)
+{
+ EFI_FILE *root_file = NULL;
+ EFI_FILE *target_file = NULL;
+ EFI_FILE_INFO *file_info;
+ EFI_STATUS status = EFI_SUCCESS;
+ uint64_t size;
+ EFI_PHYSICAL_ADDRESS addr = TBOOT_MAX_IMAGE_MEM;
+ char *print_name = wtoa_alloc(file_name);
+
+ *size_out = 0;
+ *addr_out = 0;
+
+ status = file_system->OpenVolume(file_system, &root_file);
+ if (EFI_ERROR(status)) {
+ printk("Failed to open root File handle - status: %d\n", status);
+ goto out;
+ }
+
+ status = root_file->Open(root_file,
+ &target_file,
+ file_name,
+ EFI_FILE_MODE_READ,
+ EFI_FILE_READ_ONLY);
+ if (EFI_ERROR(status)) {
+ printk("Failed to open file %s - status: %d\n", print_name, status);
+ goto out;
+ }
+
+ status = target_file->SetPosition(target_file, 0);
+ if (EFI_ERROR(status)) {
+ printk("Failed to seek 0 file %s - status: %d\n", print_name, status);
+ goto out;
+ }
+
+ file_info = efi_get_file_info(target_file, mem_type);
+ if (!file_info) {
+ printk("Failed to get file %s information\n", print_name);
+ status = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+ size = file_info->FileSize;
+ BS->FreePool(file_info);
+
+ status = BS->AllocatePages(AllocateMaxAddress,
+ mem_type,
+ PFN_UP(size),
+ &addr);
+ if (EFI_ERROR(status)) {
+ printk("Failed to allocate buffer to read file %s\n", print_name);
+ status = EFI_OUT_OF_RESOURCES;
+ goto out;
+ }
+
+ status = target_file->Read(target_file, &size, (void*)addr);
+ if (EFI_ERROR(status)) {
+ printk("Failed to read file %s\n", print_name);
+ BS->FreePages(addr, PFN_UP(size));
+ goto out;
+ }
+
+ *size_out = size;
+ *addr_out = addr;
+
+out:
+ if (target_file)
+ target_file->Close(target_file);
+
+ if (root_file)
+ root_file->Close(root_file);
+
+ if (print_name)
+ BS->FreePool(print_name);
+
+ return status;
+}
diff --git a/tboot/efimemmap.c b/tboot/efimemmap.c
new file mode 100644
index 0000000..a9ff517
--- /dev/null
+++ b/tboot/efimemmap.c
@@ -0,0 +1,276 @@
+/*
+ * efimemmap.c: EFI memory map processing and storage.
+ *
+ * Copyright (c) 2017 Assured Information Security.
+ *
+ * Ross Philipson <philipsonr@ainfosec.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+#include <efibase.h>
+#include <stdbool.h>
+#include <string.h>
+#include <atomic.h>
+#include <page.h>
+#include <printk.h>
+#include <eficore.h>
+#include <eficonfig.h>
+#include <pe.h>
+#include <tb_error.h>
+#include <tboot.h>
+#include <txt/txt.h>
+
+#define MAX_RAMMEM_BLOCKS 128
+#define MEM_NONE 0
+#define MEM_RAM 1
+#define MEM_OTHER 2
+
+typedef struct mem_map {
+ uint64_t addr;
+ uint64_t length;
+ uint64_t type;
+} mem_map_t;
+
+static __data mem_map_t g_ram_map[MAX_RAMMEM_BLOCKS];
+static __data uint64_t g_ram_map_count = 0;
+
+/* minimum size of RAM (type 1) region that cannot be marked as reserved even
+ if it comes after a reserved region; 0 for no minimum (i.e. current
+ behavior) */
+/* TODO this needs some evaluation - preserve for now. If using this causes the
+ * PMRs to not cover the MLE then game over. See the reloc code in boot.c.
+ */
+uint32_t g_min_ram = 0;
+
+/*
+ * All we really care about are conventional RAM regions. This will include
+ * coalesced RAM, EFI loader and boot services memory.
+ */
+bool efi_scan_memory_map(void)
+{
+ const EFI_MEMORY_DESCRIPTOR *desc;
+ const void *memory_map;
+ uint64_t size, size_desc, length, type, last = MEM_NONE, i;
+ mem_map_t *entry = g_ram_map - 1;
+
+ memory_map = efi_get_memory_map(&size, &size_desc);
+ if (!memory_map || size == 0 ||
+ size_desc < sizeof(EFI_MEMORY_DESCRIPTOR)) {
+ printk(TBOOT_ERR"System memory map invalid?!\n");
+ return false;
+ }
+
+ memset(g_ram_map, 0, sizeof(mem_map_t)*MAX_RAMMEM_BLOCKS);
+
+ printk(TBOOT_DETA"EFI memory map:\n");
+ for (i = 0; i < size; i += size_desc) {
+ desc = memory_map + i;
+ length = desc->NumberOfPages << EFI_PAGE_SHIFT;
+
+ printk(TBOOT_DETA" %016llx - %016llx type=%u attr=%016llx\n",
+ desc->PhysicalStart, desc->PhysicalStart + length - 1,
+ desc->Type, desc->Attribute);
+ switch (desc->Type)
+ {
+ case EfiBootServicesCode:
+ case EfiBootServicesData:
+ case EfiLoaderCode:
+ case EfiLoaderData:
+ case EfiConventionalMemory:
+ if (desc->Attribute & EFI_MEMORY_WB)
+ type = MEM_RAM;
+ else
+ type = MEM_OTHER;
+ break;
+ default:
+ type = MEM_OTHER;
+ };
+
+ if (g_ram_map_count >= MAX_RAMMEM_BLOCKS) {
+ printk(TBOOT_ERR"Exhausted RAM memory blocks\n");
+ return false;
+ }
+
+ if (g_ram_map_count && type == last &&
+ desc->PhysicalStart == entry->addr + entry->length) {
+ entry->length += length;
+ }
+ else {
+ ++entry;
+ entry->addr = desc->PhysicalStart;
+ entry->length = length;
+ entry->type = type;
+ ++g_ram_map_count;
+ }
+
+ last = type;
+ }
+
+ entry = g_ram_map;
+ printk(TBOOT_DETA"RAM map:\n");
+ for (i = 0; i < g_ram_map_count; i++, entry++) {
+ printk(TBOOT_DETA" %016llx - %016llx type: %s\n",
+ entry->addr, entry->addr + entry->length,
+ (entry->type == MEM_RAM ? "RAM" : "OTHER"));
+ }
+
+ return true;
+}
+
+bool efi_add_resmap_entry(uint64_t addr, uint64_t length)
+{
+ /*
+ * TODO Xen will have to sort things out like e820_reserve_ram in its
+ * copy of the E820 it gives to dom0. We don't do E820 around these parts.
+ */
+
+ if (_tboot_shared.reserve_map_count >= TB_RESMEM_BLOCKS) {
+ printk(TBOOT_ERR"Exhausted RES memory blocks\n");
+ return false;
+ }
+
+ _tboot_shared.reserve_map[++_tboot_shared.reserve_map_count].addr = addr;
+ _tboot_shared.reserve_map[_tboot_shared.reserve_map_count].length = length;
+
+ return true;
+}
+
+/* find highest (< <limit>) RAM region of at least <size> bytes */
+static void get_highest_sized_ram(uint64_t size, uint64_t limit,
+ uint64_t *ram_base, uint64_t *ram_size)
+{
+ uint64_t last_fit_base = 0, last_fit_size = 0, i;
+ mem_map_t *entry = g_ram_map;
+
+ if ( ram_base == NULL || ram_size == NULL )
+ return;
+
+ for ( i = 0; i < g_ram_map_count; i++, entry++ ) {
+ /* over 4GB so use the last region that fit */
+ if ( entry->addr + entry->length > limit )
+ break;
+ if ( size <= entry->length ) {
+ last_fit_base = entry->addr;
+ last_fit_size = entry->length;
+ }
+ }
+
+ *ram_base = last_fit_base;
+ *ram_size = last_fit_size;
+}
+
+bool efi_get_ram_ranges(uint64_t *min_lo_ram, uint64_t *max_lo_ram,
+ uint64_t *min_hi_ram, uint64_t *max_hi_ram)
+{
+ bool found_reserved_region = false;
+ uint64_t last_min_ram_base = 0, last_min_ram_size = 0, i;
+ mem_map_t *entry = g_ram_map;
+
+ if ( min_lo_ram == NULL || max_lo_ram == NULL ||
+ min_hi_ram == NULL || max_hi_ram == NULL )
+ return false;
+
+ *min_lo_ram = *min_hi_ram = ~0ULL;
+ *max_lo_ram = *max_hi_ram = 0;
+
+ /*
+ * if g_min_ram > 0, we will never mark a region > g_min_ram in size
+ * as reserved even if it is after a reserved region (effectively
+ * we ignore reserved regions below the last type 1 region
+ * > g_min_ram in size)
+ * so in order to reserve RAM regions above this last region, we need
+ * to find it first so that we can tell when we have passed it
+ */
+ if ( g_min_ram > 0 ) {
+ get_highest_sized_ram(g_min_ram, 0x100000000ULL, &last_min_ram_base,
+ &last_min_ram_size);
+ printk(TBOOT_DETA"highest min_ram (0x%x) region found: base=0x%Lx, size=0x%Lx\n",
+ g_min_ram, last_min_ram_base, last_min_ram_size);
+ }
+
+ for ( i = 0; i < g_ram_map_count; i++, entry++ ) {
+ uint64_t base = entry->addr;
+ uint64_t limit = entry->addr + entry->length;
+
+ if ( entry->type == MEM_RAM ) {
+ /* if range straddles 4GB boundary, that is an error */
+ if ( base < 0x100000000ULL && limit > 0x100000000ULL ) {
+ printk(TBOOT_ERR"e820 memory range straddles 4GB boundary\n");
+ return false;
+ }
+
+ /*
+ * some BIOSes put legacy USB buffers in reserved regions <4GB,
+ * which if DMA protected cause SMM to hang, so make sure that
+ * we don't overlap any of these even if that wastes RAM
+ * ...unless min_ram was specified
+ */
+ if ( !found_reserved_region || base <= last_min_ram_base ) {
+ if ( base < 0x100000000ULL && base < *min_lo_ram )
+ *min_lo_ram = base;
+ if ( limit <= 0x100000000ULL && limit > *max_lo_ram )
+ *max_lo_ram = limit;
+ }
+ else { /* need to reserve low RAM above reserved regions */
+ if ( base < 0x100000000ULL ) {
+ if (txt_is_launched()) {
+ printk(TBOOT_DETA"discarding RAM above reserved"
+ "regions: 0x%Lx - 0x%Lx\n", base, limit);
+ if ( !efi_add_resmap_entry(base, limit - base) )
+ return false;
+ }
+ }
+ }
+
+ if ( base >= 0x100000000ULL && base < *min_hi_ram )
+ *min_hi_ram = base;
+ if ( limit > 0x100000000ULL && limit > *max_hi_ram )
+ *max_hi_ram = limit;
+ }
+ else {
+ /* parts of low memory may be reserved for cseg, ISA hole,
+ etc. but these seem OK to DMA protect, so ignore reserved
+ regions <0x100000 */
+ if ( *min_lo_ram != ~0ULL && limit > 0x100000ULL )
+ found_reserved_region = true;
+ }
+ }
+
+ /* no low RAM found */
+ if ( *min_lo_ram >= *max_lo_ram ) {
+ printk(TBOOT_ERR"no low ram in e820 map\n");
+ return false;
+ }
+ /* no high RAM found */
+ if ( *min_hi_ram >= *max_hi_ram )
+ *min_hi_ram = *max_hi_ram = 0;
+
+ return true;
+}
diff --git a/tboot/errors.c b/tboot/errors.c
new file mode 100644
index 0000000..5d22b40
--- /dev/null
+++ b/tboot/errors.c
@@ -0,0 +1,285 @@
+/*
+ * errors.c: parse and return status of Intel(r) TXT error codes
+ *
+ * Copyright (c) 2003-2011, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+#include <efibase.h>
+#include <stdbool.h>
+#include <types.h>
+#include <string.h>
+#include <printk.h>
+#include <atomic.h>
+#include <uuid.h>
+#include <tb_error.h>
+#include <txt/txt.h>
+#include <txt/config_regs.h>
+#include <txt/errorcode.h>
+
+
+static void display_errors(void)
+{
+ txt_errorcode_t err;
+ txt_ests_t ests;
+ txt_e2sts_t e2sts;
+ txt_errorcode_sw_t sw_err;
+ acmod_error_t acmod_err;
+
+ /*
+ * display TXT.ERRORODE error
+ */
+ err = (txt_errorcode_t)read_pub_config_reg(TXTCR_ERRORCODE);
+ if (err._raw == 0 || err._raw == 0xc0000001 || err._raw == 0xc0000009)
+ printk(TBOOT_INFO"TXT.ERRORCODE: 0x%Lx\n", err._raw);
+ else
+ printk(TBOOT_ERR"TXT.ERRORCODE: 0x%Lx\n", err._raw);
+
+ /* AC module error (don't know how to parse other errors) */
+ if ( err.valid ) {
+ if ( err.external == 0 ) /* processor error */
+ printk(TBOOT_ERR"\t processor error 0x%x\n", (uint32_t)err.type);
+ else { /* external SW error */
+ sw_err._raw = err.type;
+ if ( sw_err.src == 1 ) /* unknown SW error */
+ printk(TBOOT_ERR"unknown SW error 0x%x:0x%x\n", sw_err.err1, sw_err.err2);
+ else { /* ACM error */
+ acmod_err._raw = sw_err._raw;
+ if ( acmod_err._raw == 0x0 || acmod_err._raw == 0x1 ||
+ acmod_err._raw == 0x9 )
+ printk(TBOOT_INFO"AC module error : acm_type=0x%x, progress=0x%02x, "
+ "error=0x%x\n", acmod_err.acm_type, acmod_err.progress,
+ acmod_err.error);
+ else
+ printk(TBOOT_ERR"AC module error : acm_type=0x%x, progress=0x%02x, "
+ "error=0x%x\n", acmod_err.acm_type, acmod_err.progress,
+ acmod_err.error);
+ /* error = 0x0a, progress = 0x0d => TPM error */
+ if ( acmod_err.error == 0x0a && acmod_err.progress == 0x0d )
+ printk(TBOOT_ERR"TPM error code = 0x%x\n", acmod_err.tpm_err);
+ /* progress = 0x10 => LCP2 error */
+ else if ( acmod_err.progress == 0x10 && acmod_err.lcp_minor != 0 )
+ printk(TBOOT_ERR"LCP2 error: minor error = 0x%x, index = %u\n",
+ acmod_err.lcp_minor, acmod_err.lcp_index);
+ }
+ }
+ }
+
+ /*
+ * display TXT.ESTS error
+ */
+ ests = (txt_ests_t)read_pub_config_reg(TXTCR_ESTS);
+ if (ests._raw == 0)
+ printk(TBOOT_INFO"TXT.ESTS: 0x%Lx\n", ests._raw);
+ else
+ printk(TBOOT_ERR"TXT.ESTS: 0x%Lx\n", ests._raw);
+
+ /*
+ * display TXT.E2STS error
+ */
+ e2sts = (txt_e2sts_t)read_pub_config_reg(TXTCR_E2STS);
+ if (e2sts._raw == 0 || e2sts._raw == 0x200000000)
+ printk(TBOOT_INFO"TXT.E2STS: 0x%Lx\n", e2sts._raw);
+ else
+ printk(TBOOT_ERR"TXT.E2STS: 0x%Lx\n", e2sts._raw);
+}
+
+bool txt_get_error(void)
+{
+ txt_errorcode_t err;
+
+ display_errors();
+
+ err = (txt_errorcode_t)read_pub_config_reg(TXTCR_ERRORCODE);
+ if ( err.valid )
+ return false;
+ else
+ return true;
+}
+
+#define CLASS_ACM_ENTRY 0x1
+enum ENUM_ACM_ENTRY {
+ ERR_LAUNCH = 1,
+ ERR_NEM_ENABLED,
+ ERR_CPU_LT_TYPE,
+ ERR_DEV_ID,
+ ERR_CPU_ID,
+ ERR_NO_UCODE_UPDATE ,
+ ERR_DEBUG_MCU,
+ ERR_DMI_LINK_DOWN,
+ ERR_ACM_REVOKED,
+ ERR_TPM_DOUBLE_AUX
+};
+#define CLASS_TPM_ACCESS 0x4
+enum ENUM_TPM_ACCESS {
+ ERR_OK, /* Indicator of successful execution of the function.*/
+ ERR_TPM_ERROR, /* TPM returned an error */
+ ERR_LOCALITY,
+ ERR_ACC_INVLD,
+ ERR_NV_UNLOCKED, /* TPM NV RAM not locked */
+ ERR_TPM_DISABLED, /* TPM is disabled */
+ ERR_TPM_DEACTIVATED, /* TPM is deactivated */
+ ERR_TPM_NV_INDEX_INVALID, /* TPM NV indices incorrectly defined */
+ ERR_TPM_INCOMPET_BIOSAC, /* Incompatible BIOS ACM */
+ ERR_TPM_INCOMPET_AUXREV, /* Incompatible AUX revision */
+ ERR_TPM_INBUF_TOO_SHORT, /* Input buffer is too short */
+ ERR_TPM_OUTBUF_TOO_SHORT, /* Output buffer is too short */
+ ERR_TPM_NV_PO_INDEX_INVALID = 0x10,
+
+ /*
+ * Errors returned by TPM driver
+ */
+ ERR_OUTPUT_BUFFER_TOO_SHORT = 0x1B, /* Output buffer for the TPM response to short */
+ ERR_INVALID_INPUT_PARA = 0x1C, /* Input parameter for the function invalid */
+ ERR_INVALID_RESPONSE_WR = 0x1D, /* The response from the TPM was invalid */
+ ERR_INVALID_RESPONSE_RD = 0x1E, /* The response from the TPM was invalid */
+ ERR_RESPONSE_TIMEOUT = 0x1F /* Time out for TPM response */
+};
+#define CLASS_MISC_CONFIG 0x8
+enum ENUM_MISC_CONFIG {
+ ERR_INTERRUPT = 1,
+ ERR_FORBIDDEN_BY_OWNER = 0x10,
+ ERR_TOOL_LAUNCH,
+ ERR_CANNOT_REVERSE,
+ ERR_ALREADY_REVOKED,
+ ERR_INVALID_RETURN_ADDR,
+ ERR_NO_TPM,
+};
+
+void txt_get_racm_error(void)
+{
+ txt_errorcode_t err;
+ acmod_error_t acmod_err;
+
+ /*
+ * display TXT.ERRORODE error
+ */
+ err = (txt_errorcode_t)read_pub_config_reg(TXTCR_ERRORCODE);
+
+ /* AC module error (don't know how to parse other errors) */
+ if ( err.valid == 0 ) {
+ printk(TBOOT_ERR
+ "Cannot retrieve status - ERRORSTS register is not valid.\n");
+ return;
+ }
+
+ if ( err.external == 0 ) { /* processor error */
+ printk(TBOOT_ERR"CPU generated error 0x%x\n", (uint32_t)err.type);
+ return;
+ }
+
+ acmod_err._raw = err.type;
+ if ( acmod_err.src == 1 ) {
+ printk(TBOOT_ERR"Unknown SW error.\n");
+ return;
+ }
+
+ if ( acmod_err.acm_type != 0x9 ) {
+ printk(TBOOT_ERR
+ "Cannot retrieve status - wrong ACM type in ERRORSTS register.\n");
+ return;
+ }
+
+ if ( acmod_err.progress == CLASS_ACM_ENTRY &&
+ acmod_err.error == ERR_TPM_DOUBLE_AUX ) {
+ printk(TBOOT_ERR
+ "Nothing to do: double AUX index is not valid TXT configuration.\n");
+ return;
+ }
+
+ if ( acmod_err.progress == CLASS_TPM_ACCESS &&
+ acmod_err.error == ERR_TPM_NV_INDEX_INVALID ) {
+ printk(TBOOT_ERR
+ "Nothing to do: invalid AUX index attributes.\n");
+ return;
+ }
+
+ if ( acmod_err.progress == CLASS_TPM_ACCESS &&
+ acmod_err.error == ERR_TPM_NV_PO_INDEX_INVALID ) {
+ printk(TBOOT_ERR
+ "Error: invalid PO index attributes.\n");
+ return;
+ }
+
+ if ( acmod_err.progress == CLASS_MISC_CONFIG &&
+ acmod_err.error == ERR_ALREADY_REVOKED ) {
+ printk(TBOOT_ERR
+ "Nothing to do: already revoked.\n");
+ return;
+ }
+
+ if ( acmod_err.progress == CLASS_MISC_CONFIG &&
+ acmod_err.error == ERR_FORBIDDEN_BY_OWNER ) {
+ printk(TBOOT_ERR
+ "Error: revocation forbidden by owner.\n");
+ return;
+ }
+
+ if ( acmod_err.progress == CLASS_MISC_CONFIG &&
+ acmod_err.error == ERR_CANNOT_REVERSE ) {
+ printk(TBOOT_ERR
+ "Error: cannot decrement revocation version.\n");
+ return;
+ }
+
+ if ( acmod_err.progress == CLASS_MISC_CONFIG &&
+ acmod_err.error == ERR_INVALID_RETURN_ADDR ) {
+ printk(TBOOT_ERR
+ "Error: invalid input address of return point.\n");
+ return;
+ }
+
+ if ( acmod_err.progress == CLASS_MISC_CONFIG &&
+ acmod_err.error == ERR_NO_TPM ) {
+ printk(TBOOT_ERR
+ "Nothing to do: No TPM present.\n");
+ return;
+ }
+
+ if ( acmod_err.progress == 0 && acmod_err.error == 0 ) {
+ printk(TBOOT_INFO
+ "Success: Revocation completed.\n");
+ return;
+ }
+
+ printk(TBOOT_ERR"RACM generated error 0x%Lx.\n", err._raw);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/genlds.sh b/tboot/genlds.sh
new file mode 100755
index 0000000..3d2806f
--- /dev/null
+++ b/tboot/genlds.sh
@@ -0,0 +1,19 @@
+#! /bin/sh
+
+RO_DATA_SECTION=".rdata"
+
+if [ "$1" == "gcc" ]; then
+ RO_DATA_SECTION=".rodata"
+fi
+
+cat << EOF >> tboot.lds
+SECTIONS
+{
+ .text : {
+ . = ALIGN(4096);
+ *(.text)
+ *($RO_DATA_SECTION)
+ *(SORT($RO_DATA_SECTION*))
+ }
+}
+EOF
diff --git a/tboot/hash.c b/tboot/hash.c
new file mode 100644
index 0000000..cc0cdd2
--- /dev/null
+++ b/tboot/hash.c
@@ -0,0 +1,193 @@
+/*
+ * hash.c: support functions for tb_hash_t type
+ *
+ * Copyright (c) 2006-2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+#include <efibase.h>
+#include <types.h>
+#include <stdbool.h>
+#include <printk.h>
+#include <compiler.h>
+#include <string.h>
+#include <misc.h>
+#include <sha1.h>
+#include <sha256.h>
+#include <hash.h>
+
+/*
+ * are_hashes_equal
+ *
+ * compare whether two hash values are equal.
+ *
+ */
+bool are_hashes_equal(const tb_hash_t *hash1, const tb_hash_t *hash2,
+ uint16_t hash_alg)
+{
+ unsigned int len;
+
+ if ( ( hash1 == NULL ) || ( hash2 == NULL ) ) {
+ printk(TBOOT_ERR"Error: hash pointer is zero.\n");
+ return false;
+ }
+
+ len = get_hash_size(hash_alg);
+ if ( len > 0 )
+ return (memcmp(hash1, hash2, len) == 0);
+ else {
+ printk(TBOOT_ERR"unsupported hash alg (%u)\n", hash_alg);
+ return false;
+ }
+}
+
+/*
+ * hash_buffer
+ *
+ * hash the buffer according to the algorithm
+ *
+ */
+bool hash_buffer(const unsigned char* buf, size_t size, tb_hash_t *hash,
+ uint16_t hash_alg)
+{
+ if ( hash == NULL ) {
+ printk(TBOOT_ERR"Error: There is no space for output hash.\n");
+ return false;
+ }
+
+ if ( hash_alg == TB_HALG_SHA1 ) {
+ sha1_buffer(buf, size, hash->sha1);
+ return true;
+ }
+ else if ( hash_alg == TB_HALG_SHA256 ) {
+ sha256_buffer(buf, size, hash->sha256);
+ return true;
+ }
+ else if ( hash_alg == TB_HALG_SM3 ) {
+ printk(TBOOT_ERR"unsupported hash alg (%u)\n", hash_alg);
+ return false;
+ }
+ else {
+ printk(TBOOT_ERR"unsupported hash alg (%u)\n", hash_alg);
+ return false;
+ }
+}
+
+/*
+ * extend_hash
+ *
+ * perform "extend" of two hashes (i.e. hash1 = SHA(hash1 || hash2)
+ *
+ */
+bool extend_hash(tb_hash_t *hash1, const tb_hash_t *hash2, uint16_t hash_alg)
+{
+ uint8_t buf[2*SHA512_LENGTH];
+
+ /* RJP this is nuts - don't do that - it freaks the compiler out:
+ uint8_t buf[2*get_hash_size(hash_alg)]; */
+
+ if ( hash1 == NULL || hash2 == NULL ) {
+ printk(TBOOT_ERR"Error: There is no space for output hash.\n");
+ return false;
+ }
+
+ if ( hash_alg == TB_HALG_SHA1 ) {
+ memcpy(buf, &(hash1->sha1), sizeof(hash1->sha1));
+ memcpy(buf + sizeof(hash1->sha1), &(hash2->sha1), sizeof(hash1->sha1));
+ sha1_buffer(buf, 2*sizeof(hash1->sha1), hash1->sha1);
+ return true;
+ }
+ else if ( hash_alg == TB_HALG_SHA256 ) {
+ memcpy(buf, &(hash1->sha256), sizeof(hash1->sha256));
+ memcpy(buf + sizeof(hash1->sha256), &(hash2->sha256), sizeof(hash1->sha256));
+ sha256_buffer(buf, 2*sizeof(hash1->sha256), hash1->sha256);
+ return true;
+ }
+ else if ( hash_alg == TB_HALG_SM3 ) {
+ printk(TBOOT_ERR"unsupported hash alg (%u)\n", hash_alg);
+ return false;
+ }
+ else {
+ printk(TBOOT_ERR"unsupported hash alg (%u)\n", hash_alg);
+ return false;
+ }
+}
+
+void print_hash(const tb_hash_t *hash, uint16_t hash_alg)
+{
+ if ( hash == NULL ) {
+ printk(TBOOT_WARN"NULL");
+ return;
+ }
+
+ if ( hash_alg == TB_HALG_SHA1 )
+ print_hex(NULL, (uint8_t *)hash->sha1, sizeof(hash->sha1));
+ else if ( hash_alg == TB_HALG_SHA256 )
+ print_hex(NULL, (uint8_t *)hash->sha256, sizeof(hash->sha256));
+ else if ( hash_alg == TB_HALG_SM3 )
+ print_hex(NULL, (uint8_t *)hash->sm3, sizeof(hash->sm3));
+ else if ( hash_alg == TB_HALG_SHA384 )
+ print_hex(NULL, (uint8_t *)hash->sha384, sizeof(hash->sha384));
+ else {
+ printk(TBOOT_WARN"unsupported hash alg (%u)\n", hash_alg);
+ return;
+ }
+}
+
+void copy_hash(tb_hash_t *dest_hash, const tb_hash_t *src_hash,
+ uint16_t hash_alg)
+{
+ unsigned int len;
+
+ if ( dest_hash == NULL || src_hash == NULL ) {
+ printk(TBOOT_WARN"hashes are NULL\n");
+ return;
+ }
+
+ len = get_hash_size(hash_alg);
+ if ( len > 0 )
+ memcpy(dest_hash, src_hash, len);
+ else
+ printk(TBOOT_WARN"unsupported hash alg (%u)\n", hash_alg);
+}
+
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/heap.c b/tboot/heap.c
new file mode 100644
index 0000000..0fadb57
--- /dev/null
+++ b/tboot/heap.c
@@ -0,0 +1,818 @@
+/*
+ * heap.c: fns for verifying and printing the Intel(r) TXT heap data structs
+ *
+ * Copyright (c) 2003-2011, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef IS_INCLUDED
+#include <config.h>
+#include <efibase.h>
+#include <types.h>
+#include <stdbool.h>
+#include <compiler.h>
+#include <processor.h>
+#include <string.h>
+#include <printk.h>
+#include <uuid.h>
+#include <mle.h>
+#include <misc.h>
+#include <hash.h>
+#include <tpm.h>
+#include <txt/mtrrs.h>
+#include <txt/config_regs.h>
+#include <txt/heap.h>
+#endif
+
+/*
+ * extended data elements
+ */
+
+/* HEAP_BIOS_SPEC_VER_ELEMENT */
+static void print_bios_spec_ver_elt(const heap_ext_data_element_t *elt)
+{
+ const heap_bios_spec_ver_elt_t *bios_spec_ver_elt =
+ (const heap_bios_spec_ver_elt_t *)elt->data;
+
+ printk(TBOOT_INFO"\t\t BIOS_SPEC_VER:\n");
+ printk(TBOOT_INFO"\t\t major: 0x%x\n", bios_spec_ver_elt->spec_ver_major);
+ printk(TBOOT_INFO"\t\t minor: 0x%x\n", bios_spec_ver_elt->spec_ver_minor);
+ printk(TBOOT_INFO"\t\t rev: 0x%x\n", bios_spec_ver_elt->spec_ver_rev);
+}
+
+static bool verify_bios_spec_ver_elt(const heap_ext_data_element_t *elt)
+{
+ const heap_bios_spec_ver_elt_t *bios_spec_ver_elt =
+ (const heap_bios_spec_ver_elt_t *)elt->data;
+
+ if ( elt->size != sizeof(*elt) + sizeof(*bios_spec_ver_elt) ) {
+ printk(TBOOT_ERR"HEAP_BIOS_SPEC_VER element has wrong size (%u)\n", elt->size);
+ return false;
+ }
+
+ /* any values are allowed */
+ return true;
+}
+
+/* HEAP_ACM_ELEMENT */
+static void print_acm_elt(const heap_ext_data_element_t *elt)
+{
+ const heap_acm_elt_t *acm_elt = (const heap_acm_elt_t *)elt->data;
+
+ printk(TBOOT_DETA"\t\t ACM:\n");
+ printk(TBOOT_DETA"\t\t num_acms: %u\n", acm_elt->num_acms);
+ for ( unsigned int i = 0; i < acm_elt->num_acms; i++ )
+ printk(TBOOT_DETA"\t\t acm_addrs[%u]: 0x%jx\n", i, acm_elt->acm_addrs[i]);
+}
+
+static bool verify_acm_elt(const heap_ext_data_element_t *elt)
+{
+ const heap_acm_elt_t *acm_elt = (const heap_acm_elt_t *)elt->data;
+
+ if ( elt->size != sizeof(*elt) + sizeof(*acm_elt) +
+ acm_elt->num_acms*sizeof(uint64_t) ) {
+ printk(TBOOT_ERR"HEAP_ACM element has wrong size (%u)\n", elt->size);
+ return false;
+ }
+
+ /* no addrs is not error, but print warning */
+ if ( acm_elt->num_acms == 0 )
+ printk(TBOOT_WARN"HEAP_ACM element has no ACM addrs\n");
+
+ for ( unsigned int i = 0; i < acm_elt->num_acms; i++ ) {
+ if ( acm_elt->acm_addrs[i] == 0 ) {
+ printk(TBOOT_ERR"HEAP_ACM element ACM addr (%u) is NULL\n", i);
+ return false;
+ }
+
+ if ( acm_elt->acm_addrs[i] >= 0x100000000UL ) {
+ printk(TBOOT_ERR"HEAP_ACM element ACM addr (%u) is >4GB (0x%jx)\n", i,
+ acm_elt->acm_addrs[i]);
+ return false;
+ }
+
+ /* not going to check if ACM addrs are valid ACMs */
+ }
+
+ return true;
+}
+
+/* HEAP_CUSTOM_ELEMENT */
+static void print_custom_elt(const heap_ext_data_element_t *elt)
+{
+ const heap_custom_elt_t *custom_elt = (const heap_custom_elt_t *)elt->data;
+
+ printk(TBOOT_DETA"\t\t CUSTOM:\n");
+ printk(TBOOT_DETA"\t\t size: %u\n", elt->size);
+ printk(TBOOT_DETA"\t\t uuid: "); print_uuid(&custom_elt->uuid);
+ printk(TBOOT_DETA"\n");
+}
+
+static bool verify_custom_elt(const heap_ext_data_element_t *elt)
+{
+ const heap_custom_elt_t *custom_elt = (const heap_custom_elt_t *)elt->data;
+
+ if ( elt->size < sizeof(*elt) + sizeof(*custom_elt) ) {
+ printk(TBOOT_ERR"HEAP_CUSTOM element has wrong size (%u)\n", elt->size);
+ return false;
+ }
+
+ /* any values are allowed */
+ return true;
+}
+
+/* HEAP_EVENT_LOG_POINTER_ELEMENT */
+static inline void print_heap_hash(const sha1_hash_t hash)
+{
+ print_hash((const tb_hash_t *)hash, TB_HALG_SHA1);
+}
+
+void print_event(const tpm12_pcr_event_t *evt)
+{
+ printk(TBOOT_DETA"\t\t\t Event:\n");
+ printk(TBOOT_DETA"\t\t\t PCRIndex: %u\n", evt->pcr_index);
+ printk(TBOOT_DETA"\t\t\t Type: 0x%x\n", evt->type);
+ printk(TBOOT_DETA"\t\t\t Digest: ");
+ print_heap_hash(evt->digest);
+ printk(TBOOT_DETA"\t\t\t Data: %u bytes", evt->data_size);
+ print_hex("\t\t\t ", evt->data, evt->data_size);
+}
+
+static void print_evt_log(const event_log_container_t *elog)
+{
+ printk(TBOOT_DETA"\t\t\t Event Log Container:\n");
+ printk(TBOOT_DETA"\t\t\t Signature: %s\n", elog->signature);
+ printk(TBOOT_DETA"\t\t\t ContainerVer: %u.%u\n",
+ elog->container_ver_major, elog->container_ver_minor);
+ printk(TBOOT_DETA"\t\t\t PCREventVer: %u.%u\n",
+ elog->pcr_event_ver_major, elog->pcr_event_ver_minor);
+ printk(TBOOT_DETA"\t\t\t Size: %u\n", elog->size);
+ printk(TBOOT_DETA"\t\t\t EventsOffset: [%u,%u)\n",
+ elog->pcr_events_offset, elog->next_event_offset);
+
+ const tpm12_pcr_event_t *curr, *next;
+ curr = (tpm12_pcr_event_t *)((void*)elog + elog->pcr_events_offset);
+ next = (tpm12_pcr_event_t *)((void*)elog + elog->next_event_offset);
+
+ while ( curr < next ) {
+ print_event(curr);
+ curr = (void *)curr + sizeof(*curr) + curr->data_size;
+ }
+}
+
+static bool verify_evt_log(const event_log_container_t *elog)
+{
+ if ( elog == NULL ) {
+ printk(TBOOT_ERR"Event log container pointer is NULL\n");
+ return false;
+ }
+
+ if ( memcmp(elog->signature, EVTLOG_SIGNATURE, sizeof(elog->signature)) ) {
+ printk(TBOOT_ERR"Bad event log container signature: %s\n", elog->signature);
+ return false;
+ }
+
+ if ( elog->size != MAX_EVENT_LOG_SIZE ) {
+ printk(TBOOT_ERR"Bad event log container size: 0x%x\n", elog->size);
+ return false;
+ }
+
+ /* no need to check versions */
+
+ if ( elog->pcr_events_offset < sizeof(*elog) ||
+ elog->next_event_offset < elog->pcr_events_offset ||
+ elog->next_event_offset > elog->size ) {
+ printk(TBOOT_ERR"Bad events offset range: [%u, %u)\n",
+ elog->pcr_events_offset, elog->next_event_offset);
+ return false;
+ }
+
+ return true;
+}
+
+static void print_evt_log_ptr_elt(const heap_ext_data_element_t *elt)
+{
+ const heap_event_log_ptr_elt_t *elog_elt =
+ (const heap_event_log_ptr_elt_t *)elt->data;
+
+ printk(TBOOT_DETA"\t\t EVENT_LOG_POINTER:\n");
+ printk(TBOOT_DETA"\t\t size: %u\n", elt->size);
+ printk(TBOOT_DETA"\t\t elog_addr: 0x%jx\n", elog_elt->event_log_phys_addr);
+
+ if ( elog_elt->event_log_phys_addr )
+ print_evt_log((event_log_container_t *)(unsigned long long)
+ elog_elt->event_log_phys_addr);
+}
+
+static bool verify_evt_log_ptr_elt(const heap_ext_data_element_t *elt)
+{
+ const heap_event_log_ptr_elt_t *elog_elt =
+ (const heap_event_log_ptr_elt_t *)elt->data;
+
+ if ( elt->size != sizeof(*elt) + sizeof(*elog_elt) ) {
+ printk(TBOOT_ERR"HEAP_EVENT_LOG_POINTER element has wrong size (%u)\n",
+ elt->size);
+ return false;
+ }
+
+ return verify_evt_log((event_log_container_t *)(unsigned long long)
+ elog_elt->event_log_phys_addr);
+}
+
+void print_event_2(void *evt, uint16_t alg)
+{
+ uint32_t hash_size, data_size;
+ void *next = evt;
+
+ hash_size = get_hash_size(alg);
+ if ( hash_size == 0 )
+ return;
+
+ printk(TBOOT_DETA"\t\t\t Event:\n");
+ printk(TBOOT_DETA"\t\t\t PCRIndex: %u\n", *((uint32_t *)next));
+
+ if ( *((uint32_t *)next) > 24 && *((uint32_t *)next) != 0xFF ) {
+ printk(TBOOT_DETA"\t\t\t Wrong Event Log.\n");
+ return;
+ }
+
+ next += sizeof(uint32_t);
+ printk(TBOOT_DETA"\t\t\t Type: 0x%x\n", *((uint32_t *)next));
+
+ if ( *((uint32_t *)next) > 0xFFF ) {
+ printk(TBOOT_DETA"\t\t\t Wrong Event Log.\n");
+ return;
+ }
+
+ next += sizeof(uint32_t);
+ printk(TBOOT_DETA"\t\t\t Digest: ");
+ print_hex(NULL, (uint8_t *)next, hash_size);
+ next += hash_size;
+ data_size = *(uint32_t *)next;
+ printk(TBOOT_DETA"\t\t\t Data: %u bytes", data_size);
+ if ( data_size > 4096 ) {
+ printk(TBOOT_DETA"\t\t\t Wrong Event Log.\n");
+ return;
+ }
+
+ next += sizeof(uint32_t);
+ if ( data_size )
+ print_hex("\t\t\t ", (uint8_t *)next, data_size);
+ else
+ printk(TBOOT_DETA"\n");
+}
+
+static void print_evt_log_ptr_elt_2(const heap_ext_data_element_t *elt)
+{
+ const heap_event_log_ptr_elt2_t *elog_elt =
+ (const heap_event_log_ptr_elt2_t *)elt->data;
+ const heap_event_log_descr_t *log_descr;
+
+ printk(TBOOT_DETA"\t\t EVENT_LOG_PTR:\n");
+ printk(TBOOT_DETA"\t\t size: %u\n", elt->size);
+ printk(TBOOT_DETA"\t\t count: %d\n", elog_elt->count);
+
+ for ( unsigned int i=0; i<elog_elt->count; i++ ) {
+ log_descr = &elog_elt->event_log_descr[i];
+ printk(TBOOT_DETA"\t\t\t Log Descrption:\n");
+ printk(TBOOT_DETA"\t\t\t Alg: %u\n", log_descr->alg);
+ printk(TBOOT_DETA"\t\t\t Size: %u\n", log_descr->size);
+ printk(TBOOT_DETA"\t\t\t EventsOffset: [%u,%u)\n",
+ log_descr->pcr_events_offset,
+ log_descr->next_event_offset);
+
+ if (log_descr->pcr_events_offset == log_descr->next_event_offset) {
+ printk(TBOOT_DETA"\t\t\t No Event Log.\n");
+ continue;
+ }
+
+ uint32_t hash_size, data_size;
+ hash_size = get_hash_size(log_descr->alg);
+ if ( hash_size == 0 )
+ return;
+
+ void *curr, *next;
+
+ curr = (void *)(unsigned long long)log_descr->phys_addr +
+ log_descr->pcr_events_offset;
+ next = (void *)(unsigned long long)log_descr->phys_addr +
+ log_descr->next_event_offset;
+
+ //It is required for each of the non-SHA1 event log the first entry to be the following
+ //TPM1.2 style TCG_PCR_EVENT record specifying type of the log:
+ //TCG_PCR_EVENT.PCRIndex = 0
+ //TCG_PCR_EVENT.EventType = 0x03 // EV_NO_ACTION per TCG EFI
+ // Platform specification
+ //TCG_PCR_EVENT.Digest = {00…00} // 20 zeros
+ //TCG_PCR_EVENT.EventDataSize = sizeof(TCG_LOG_DESCRIPTOR).
+ //TCG_PCR_EVENT.EventData = TCG_LOG_DESCRIPTOR
+ //The digest of this record MUST NOT be extended into any PCR.
+
+ if (log_descr->alg != TB_HALG_SHA1){
+ print_event_2(curr, TB_HALG_SHA1);
+ curr += sizeof(tpm12_pcr_event_t) + sizeof(tpm20_log_descr_t);
+ }
+
+ while ( curr < next ) {
+ print_event_2(curr, log_descr->alg);
+ data_size = *(uint32_t *)(curr + 2*sizeof(uint32_t) + hash_size);
+ curr += 3*sizeof(uint32_t) + hash_size + data_size;
+ }
+ }
+}
+
+static bool verify_evt_log_ptr_elt_2(const heap_ext_data_element_t *elt)
+{
+ if ( !elt )
+ return false;
+
+ return true;
+}
+
+static void print_ext_data_elts(const heap_ext_data_element_t elts[])
+{
+ const heap_ext_data_element_t *elt = elts;
+
+ printk(TBOOT_DETA"\t ext_data_elts[]:\n");
+ while ( elt->type != HEAP_EXTDATA_TYPE_END ) {
+ switch ( elt->type ) {
+ case HEAP_EXTDATA_TYPE_BIOS_SPEC_VER:
+ print_bios_spec_ver_elt(elt);
+ break;
+ case HEAP_EXTDATA_TYPE_ACM:
+ print_acm_elt(elt);
+ break;
+ case HEAP_EXTDATA_TYPE_CUSTOM:
+ print_custom_elt(elt);
+ break;
+ case HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR:
+ print_evt_log_ptr_elt(elt);
+ break;
+ case HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR_2:
+ print_evt_log_ptr_elt_2(elt);
+ break;
+ default:
+ printk(TBOOT_WARN"\t\t unknown element: type: %u, size: %u\n",
+ elt->type, elt->size);
+ break;
+ }
+ elt = (void *)elt + elt->size;
+ }
+}
+
+static bool verify_ext_data_elts(const heap_ext_data_element_t elts[],
+ size_t elts_size)
+{
+ const heap_ext_data_element_t *elt = elts;
+
+ while ( true ) {
+ if ( elts_size < sizeof(*elt) ) {
+ printk(TBOOT_ERR"heap ext data elements too small\n");
+ return false;
+ }
+ if ( elts_size < elt->size || elt->size == 0 ) {
+ printk(TBOOT_ERR"invalid element size: type: %u, size: %u\n",
+ elt->type, elt->size);
+ return false;
+ }
+ switch ( elt->type ) {
+ case HEAP_EXTDATA_TYPE_END:
+ return true;
+ case HEAP_EXTDATA_TYPE_BIOS_SPEC_VER:
+ if ( !verify_bios_spec_ver_elt(elt) )
+ return false;
+ break;
+ case HEAP_EXTDATA_TYPE_ACM:
+ if ( !verify_acm_elt(elt) )
+ return false;
+ break;
+ case HEAP_EXTDATA_TYPE_CUSTOM:
+ if ( !verify_custom_elt(elt) )
+ return false;
+ break;
+ case HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR:
+ if ( !verify_evt_log_ptr_elt(elt) )
+ return false;
+ break;
+ case HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR_2:
+ if ( !verify_evt_log_ptr_elt_2(elt) )
+ return false;
+ break;
+ default:
+ printk(TBOOT_WARN"unknown element: type: %u, size: %u\n", elt->type,
+ elt->size);
+ break;
+ }
+ elts_size -= elt->size;
+ elt = (void *)elt + elt->size;
+ }
+ return true;
+}
+
+
+static void print_bios_data(const bios_data_t *bios_data, uint64_t size)
+{
+ printk(TBOOT_DETA"bios_data (@%p, %jx):\n", bios_data,
+ *((uint64_t *)bios_data - 1));
+ printk(TBOOT_DETA"\t version: %u\n", bios_data->version);
+ printk(TBOOT_DETA"\t bios_sinit_size: 0x%x (%u)\n", bios_data->bios_sinit_size,
+ bios_data->bios_sinit_size);
+ printk(TBOOT_DETA"\t lcp_pd_base: 0x%jx\n", bios_data->lcp_pd_base);
+ printk(TBOOT_DETA"\t lcp_pd_size: 0x%jx (%ju)\n", bios_data->lcp_pd_size,
+ bios_data->lcp_pd_size);
+ printk(TBOOT_DETA"\t num_logical_procs: %u\n", bios_data->num_logical_procs);
+ if ( bios_data->version >= 3 )
+ printk(TBOOT_DETA"\t flags: 0x%08jx\n", bios_data->flags);
+ if ( bios_data->version >= 4 && size > sizeof(*bios_data) + sizeof(size) )
+ print_ext_data_elts(bios_data->ext_data_elts);
+}
+
+bool verify_bios_data(const txt_heap_t *txt_heap)
+{
+ uint64_t heap_base = read_pub_config_reg(TXTCR_HEAP_BASE);
+ uint64_t heap_size = read_pub_config_reg(TXTCR_HEAP_SIZE);
+ printk(TBOOT_DETA"TXT.HEAP.BASE: 0x%jx\n", heap_base);
+ printk(TBOOT_DETA"TXT.HEAP.SIZE: 0x%jx (%ju)\n", heap_size, heap_size);
+
+ /* verify that heap base/size are valid */
+ if ( txt_heap == NULL || heap_base == 0 || heap_size == 0 )
+ return false;
+
+ /* check size */
+ uint64_t size = get_bios_data_size(txt_heap);
+ if ( size == 0 ) {
+ printk(TBOOT_ERR"BIOS data size is 0\n");
+ return false;
+ }
+ if ( size > heap_size ) {
+ printk(TBOOT_ERR"BIOS data size is larger than heap size "
+ "(%jx, heap size=%jx)\n", size, heap_size);
+ return false;
+ }
+
+ bios_data_t *bios_data = get_bios_data_start(txt_heap);
+
+ /* check version */
+ if ( bios_data->version < 2 ) {
+ printk(TBOOT_ERR"unsupported BIOS data version (%u)\n", bios_data->version);
+ return false;
+ }
+ /* we assume backwards compatibility but print a warning */
+ if ( bios_data->version > 4 )
+ printk(TBOOT_WARN"unsupported BIOS data version (%u)\n", bios_data->version);
+
+ /* all TXT-capable CPUs support at least 1 core */
+ if ( bios_data->num_logical_procs < 1 ) {
+ printk(TBOOT_ERR"BIOS data has incorrect num_logical_procs (%u)\n",
+ bios_data->num_logical_procs);
+ return false;
+ }
+ else if ( bios_data->num_logical_procs > NR_CPUS ) {
+ printk(TBOOT_ERR"BIOS data specifies too many CPUs (%u)\n",
+ bios_data->num_logical_procs);
+ return false;
+ }
+
+ if ( bios_data->version >= 4 && size > sizeof(*bios_data) ) {
+ if ( !verify_ext_data_elts(bios_data->ext_data_elts,
+ size - sizeof(*bios_data)) )
+ return false;
+ }
+
+ print_bios_data(bios_data, size);
+
+ return true;
+}
+
+#ifndef IS_INCLUDED
+
+static void print_os_mle_data(const os_mle_data_t *os_mle_data)
+{
+ printk(TBOOT_DETA"os_mle_data (@%p, %Lx):\n", os_mle_data,
+ *((uint64_t *)os_mle_data - 1));
+ printk(TBOOT_DETA"\t version: %u\n", os_mle_data->version);
+ /* TBD: perhaps eventually print saved_mtrr_state field */
+}
+
+static bool verify_os_mle_data(const txt_heap_t *txt_heap)
+{
+ uint64_t size, heap_size;
+ os_mle_data_t *os_mle_data;
+
+ /* check size */
+ heap_size = read_priv_config_reg(TXTCR_HEAP_SIZE);
+ size = get_os_mle_data_size(txt_heap);
+ if ( size == 0 ) {
+ printk(TBOOT_ERR"OS to MLE data size is 0\n");
+ return false;
+ }
+ if ( size > heap_size ) {
+ printk(TBOOT_ERR"OS to MLE data size is larger than heap size "
+ "(%Lx, heap size=%Lx)\n", size, heap_size);
+ return false;
+ }
+ if ( size != (sizeof(os_mle_data_t) + sizeof(size)) ) {
+ printk(TBOOT_ERR"OS to MLE data size (%Lx) is not equal to "
+ "os_mle_data_t size (%x)\n", size, sizeof(os_mle_data_t));
+ return false;
+ }
+
+ os_mle_data = get_os_mle_data_start(txt_heap);
+
+ /* check version */
+ /* since this data is from our pre-launch to post-launch code only, it */
+ /* should always be this */
+ if ( os_mle_data->version != 3 ) {
+ printk(TBOOT_ERR"unsupported OS to MLE data version (%u)\n",
+ os_mle_data->version);
+ return false;
+ }
+
+ /* NOTE remove lctx_addr - not really used */
+
+ print_os_mle_data(os_mle_data);
+
+ return true;
+}
+
+/*
+ * Make sure version is in [MIN_OS_SINIT_DATA_VER, MAX_OS_SINIT_DATA_VER]
+ * before calling calc_os_sinit_data_size
+ */
+uint64_t calc_os_sinit_data_size(uint32_t version)
+{
+ uint64_t size[] = {
+ offsetof(os_sinit_data_t, efi_rsdt_ptr) + sizeof(uint64_t),
+ sizeof(os_sinit_data_t) + sizeof(uint64_t),
+ sizeof(os_sinit_data_t) + sizeof(uint64_t) +
+ 2 * sizeof(heap_ext_data_element_t) +
+ sizeof(heap_event_log_ptr_elt_t)
+ };
+
+ if ( g_tpm->major == TPM20_VER_MAJOR ) {
+ u32 count;
+ if ( g_tpm->extpol == TB_EXTPOL_AGILE )
+ count = g_tpm->banks;
+ else if ( g_tpm->extpol == TB_EXTPOL_EMBEDDED )
+ count = g_tpm->alg_count;
+ else
+ count = 1;
+
+ size[2] = sizeof(os_sinit_data_t) + sizeof(uint64_t) +
+ 2 * sizeof(heap_ext_data_element_t) +
+ 4 + count*sizeof(heap_event_log_descr_t);
+ }
+
+ if ( version >= 6 )
+ return size[2];
+ else
+ return size[version - MIN_OS_SINIT_DATA_VER];
+}
+
+void print_os_sinit_data(const os_sinit_data_t *os_sinit_data)
+{
+ printk(TBOOT_DETA"os_sinit_data (@%p, %Lx):\n", os_sinit_data,
+ *((uint64_t *)os_sinit_data - 1));
+ printk(TBOOT_DETA"\t version: %u\n", os_sinit_data->version);
+ printk(TBOOT_DETA"\t flags: %u\n", os_sinit_data->flags);
+ printk(TBOOT_DETA"\t mle_ptab: 0x%Lx\n", os_sinit_data->mle_ptab);
+ printk(TBOOT_DETA"\t mle_size: 0x%Lx (%Lu)\n", os_sinit_data->mle_size,
+ os_sinit_data->mle_size);
+ printk(TBOOT_DETA"\t mle_hdr_base: 0x%Lx\n", os_sinit_data->mle_hdr_base);
+ printk(TBOOT_DETA"\t vtd_pmr_lo_base: 0x%Lx\n", os_sinit_data->vtd_pmr_lo_base);
+ printk(TBOOT_DETA"\t vtd_pmr_lo_size: 0x%Lx\n", os_sinit_data->vtd_pmr_lo_size);
+ printk(TBOOT_DETA"\t vtd_pmr_hi_base: 0x%Lx\n", os_sinit_data->vtd_pmr_hi_base);
+ printk(TBOOT_DETA"\t vtd_pmr_hi_size: 0x%Lx\n", os_sinit_data->vtd_pmr_hi_size);
+ printk(TBOOT_DETA"\t lcp_po_base: 0x%Lx\n", os_sinit_data->lcp_po_base);
+ printk(TBOOT_DETA"\t lcp_po_size: 0x%Lx (%Lu)\n", os_sinit_data->lcp_po_size,
+ os_sinit_data->lcp_po_size);
+ print_txt_caps("\t ", os_sinit_data->capabilities);
+ if ( os_sinit_data->version >= 5 )
+ printk(TBOOT_DETA"\t efi_rsdt_ptr: 0x%Lx\n", os_sinit_data->efi_rsdt_ptr);
+ if ( os_sinit_data->version >= 6 )
+ print_ext_data_elts(os_sinit_data->ext_data_elts);
+}
+
+static bool verify_os_sinit_data(const txt_heap_t *txt_heap)
+{
+ uint64_t size, heap_size;
+ os_sinit_data_t *os_sinit_data;
+
+ /* check size */
+ heap_size = read_priv_config_reg(TXTCR_HEAP_SIZE);
+ size = get_os_sinit_data_size(txt_heap);
+ if ( size == 0 ) {
+ printk(TBOOT_ERR"OS to SINIT data size is 0\n");
+ return false;
+ }
+ if ( size > heap_size ) {
+ printk(TBOOT_ERR"OS to SINIT data size is larger than heap size "
+ "(%Lx, heap size=%Lx)\n", size, heap_size);
+ return false;
+ }
+
+ os_sinit_data = get_os_sinit_data_start(txt_heap);
+
+ /* check version (but since we create this, it should always be OK) */
+ if ( os_sinit_data->version < MIN_OS_SINIT_DATA_VER ||
+ os_sinit_data->version > MAX_OS_SINIT_DATA_VER ) {
+ printk(TBOOT_ERR"unsupported OS to SINIT data version (%u)\n",
+ os_sinit_data->version);
+ return false;
+ }
+
+ if ( size != calc_os_sinit_data_size(os_sinit_data->version) ) {
+ printk(TBOOT_ERR"OS to SINIT data size (%Lx) does not match for version (%x)\n",
+ size, sizeof(os_sinit_data_t));
+ return false;
+ }
+
+ if ( os_sinit_data->version >= 6 ) {
+ if ( !verify_ext_data_elts(os_sinit_data->ext_data_elts,
+ size - sizeof(*os_sinit_data)) )
+ return false;
+ }
+
+ print_os_sinit_data(os_sinit_data);
+
+ return true;
+}
+
+static void print_sinit_mdrs(const sinit_mdr_t mdrs[], uint32_t num_mdrs)
+{
+ static const char *mem_types[] = {"GOOD", "SMRAM OVERLAY",
+ "SMRAM NON-OVERLAY",
+ "PCIE EXTENDED CONFIG", "PROTECTED"};
+
+ printk(TBOOT_DETA"\t sinit_mdrs:\n");
+ for ( unsigned int i = 0; i < num_mdrs; i++ ) {
+ printk(TBOOT_DETA"\t\t %016Lx - %016Lx ", mdrs[i].base,
+ mdrs[i].base + mdrs[i].length);
+ if ( mdrs[i].mem_type < sizeof(mem_types)/sizeof(mem_types[0]) )
+ printk(TBOOT_DETA"(%s)\n", mem_types[mdrs[i].mem_type]);
+ else
+ printk(TBOOT_DETA"(%d)\n", (int)mdrs[i].mem_type);
+ }
+}
+
+static void print_sinit_mle_data(const sinit_mle_data_t *sinit_mle_data)
+{
+ printk(TBOOT_DETA"sinit_mle_data (@%p, %Lx):\n", sinit_mle_data,
+ *((uint64_t *)sinit_mle_data - 1));
+ printk(TBOOT_DETA"\t version: %u\n", sinit_mle_data->version);
+ printk(TBOOT_DETA"\t bios_acm_id: \n\t");
+ print_heap_hash(sinit_mle_data->bios_acm_id);
+ printk(TBOOT_DETA"\t edx_senter_flags: 0x%08x\n",
+ sinit_mle_data->edx_senter_flags);
+ printk(TBOOT_DETA"\t mseg_valid: 0x%Lx\n", sinit_mle_data->mseg_valid);
+ printk(TBOOT_DETA"\t sinit_hash:\n\t"); print_heap_hash(sinit_mle_data->sinit_hash);
+ printk(TBOOT_DETA"\t mle_hash:\n\t"); print_heap_hash(sinit_mle_data->mle_hash);
+ printk(TBOOT_DETA"\t stm_hash:\n\t"); print_heap_hash(sinit_mle_data->stm_hash);
+ printk(TBOOT_DETA"\t lcp_policy_hash:\n\t");
+ print_heap_hash(sinit_mle_data->lcp_policy_hash);
+ printk(TBOOT_DETA"\t lcp_policy_control: 0x%08x\n",
+ sinit_mle_data->lcp_policy_control);
+ printk(TBOOT_DETA"\t rlp_wakeup_addr: 0x%x\n", sinit_mle_data->rlp_wakeup_addr);
+ printk(TBOOT_DETA"\t num_mdrs: %u\n", sinit_mle_data->num_mdrs);
+ printk(TBOOT_DETA"\t mdrs_off: 0x%x\n", sinit_mle_data->mdrs_off);
+ printk(TBOOT_DETA"\t num_vtd_dmars: %u\n", sinit_mle_data->num_vtd_dmars);
+ printk(TBOOT_DETA"\t vtd_dmars_off: 0x%x\n", sinit_mle_data->vtd_dmars_off);
+ print_sinit_mdrs((sinit_mdr_t *)
+ (((void *)sinit_mle_data - sizeof(uint64_t)) +
+ sinit_mle_data->mdrs_off), sinit_mle_data->num_mdrs);
+ if ( sinit_mle_data->version >= 8 )
+ printk(TBOOT_DETA"\t proc_scrtm_status: 0x%08x\n",
+ sinit_mle_data->proc_scrtm_status);
+ if ( sinit_mle_data->version >= 9 )
+ print_ext_data_elts(sinit_mle_data->ext_data_elts);
+}
+
+static bool verify_sinit_mle_data(const txt_heap_t *txt_heap)
+{
+ uint64_t size, heap_size;
+ sinit_mle_data_t *sinit_mle_data;
+
+ /* check size */
+ heap_size = read_priv_config_reg(TXTCR_HEAP_SIZE);
+ size = get_sinit_mle_data_size(txt_heap);
+ if ( size == 0 ) {
+ printk(TBOOT_ERR"SINIT to MLE data size is 0\n");
+ return false;
+ }
+ if ( size > heap_size ) {
+ printk(TBOOT_ERR"SINIT to MLE data size is larger than heap size\n"
+ "(%Lx, heap size=%Lx)\n", size, heap_size);
+ return false;
+ }
+
+ sinit_mle_data = get_sinit_mle_data_start(txt_heap);
+
+ /* check version */
+ if ( sinit_mle_data->version < 6 ) {
+ printk(TBOOT_ERR"unsupported SINIT to MLE data version (%u)\n",
+ sinit_mle_data->version);
+ return false;
+ }
+ else if ( sinit_mle_data->version > 9 ) {
+ printk(TBOOT_WARN"unsupported SINIT to MLE data version (%u)\n",
+ sinit_mle_data->version);
+ }
+
+ /* this data is generated by SINIT and so is implicitly trustworthy, */
+ /* so we don't need to validate it's fields */
+
+ print_sinit_mle_data(sinit_mle_data);
+
+ return true;
+}
+
+bool verify_txt_heap(const txt_heap_t *txt_heap, bool bios_data_only)
+{
+ /* verify BIOS to OS data */
+ if ( !verify_bios_data(txt_heap) )
+ return false;
+
+ if ( bios_data_only )
+ return true;
+
+ /* check that total size is within the heap */
+ uint64_t size1 = get_bios_data_size(txt_heap);
+ uint64_t size2 = get_os_mle_data_size(txt_heap);
+ uint64_t size3 = get_os_sinit_data_size(txt_heap);
+ uint64_t size4 = get_sinit_mle_data_size(txt_heap);
+
+ /* overflow? */
+ if ( plus_overflow_u64(size1, size2) ) {
+ printk(TBOOT_ERR"TXT heap data size overflows\n");
+ return false;
+ }
+ if ( plus_overflow_u64(size3, size4) ) {
+ printk(TBOOT_ERR"TXT heap data size overflows\n");
+ return false;
+ }
+ if ( plus_overflow_u64(size1 + size2, size3 + size4) ) {
+ printk(TBOOT_ERR"TXT heap data size overflows\n");
+ return false;
+ }
+
+ if ( (size1 + size2 + size3 + size4) >
+ read_priv_config_reg(TXTCR_HEAP_SIZE) ) {
+ printk(TBOOT_ERR"TXT heap data sizes (%Lx, %Lx, %Lx, %Lx) are larger than\n"
+ "heap total size (%Lx)\n", size1, size2, size3, size4,
+ read_priv_config_reg(TXTCR_HEAP_SIZE));
+ return false;
+ }
+
+ /* verify OS to MLE data */
+ if ( !verify_os_mle_data(txt_heap) )
+ return false;
+
+ /* verify OS to SINIT data */
+ if ( !verify_os_sinit_data(txt_heap) )
+ return false;
+
+ /* verify SINIT to MLE data */
+ if ( !verify_sinit_mle_data(txt_heap) )
+ return false;
+
+ return true;
+}
+
+#endif
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/acpi.h b/tboot/include/acpi.h
new file mode 100644
index 0000000..430b422
--- /dev/null
+++ b/tboot/include/acpi.h
@@ -0,0 +1,518 @@
+/* $OpenBSD: acpireg.h,v 1.17 2009/04/11 08:22:48 kettenis Exp $ */
+/*
+ * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
+ * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Portions copyright (c) 2010, Intel Corporation
+ */
+
+#ifndef __ACPI_H__
+#define __ACPI_H__
+
+//#define ACPI_DEBUG
+
+#define RSDP_SCOPE1_LOW (void *)0x000000
+#define RSDP_SCOPE1_HIGH (void *)0x000400
+#define RSDP_SCOPE2_LOW (void *)0x0E0000
+#define RSDP_SCOPE2_HIGH (void *)0x100000
+
+/* Root System Descriptor Pointer (RSDP) for ACPI 1.0 */
+struct acpi_rsdp1 {
+ u_int8_t signature[8];
+#define RSDP_SIG "RSD PTR "
+
+ u_int8_t checksum; /* make sum == 0 */
+ u_int8_t oemid[6];
+ u_int8_t revision; /* 0 for v1.0, 2 for v2.0 */
+ u_int32_t rsdt; /* physical */
+} __packed;
+
+/* Root System Descriptor Pointer (RSDP) for ACPI 2.0 */
+struct acpi_rsdp {
+ struct acpi_rsdp1 rsdp1;
+ /*
+ * The following values are only valid
+ * when rsdp_revision == 2
+ */
+ u_int32_t rsdp_length; /* length of rsdp */
+ u_int64_t rsdp_xsdt; /* physical */
+ u_int8_t rsdp_extchecksum; /* entire table */
+ u_int8_t rsdp_reserved[3]; /* must be zero */
+} __packed;
+
+/* Common System Description Table Header */
+struct acpi_table_header {
+ u_int8_t signature[4];
+ u_int32_t length;
+ u_int8_t revision;
+ u_int8_t checksum;
+ u_int8_t oemid[6];
+ u_int8_t oemtableid[8];
+ u_int32_t oemrevision;
+
+ u_int8_t aslcompilerid[4];
+ u_int32_t aslcompilerrevision;
+} __packed;
+
+/* Root System Description Table (RSDT) */
+struct acpi_rsdt {
+ struct acpi_table_header hdr;
+#define RSDT_SIG "RSDT"
+
+ u_int32_t table_offsets[1];
+} __packed;
+
+/* Extended System Descriptiion Table */
+struct acpi_xsdt {
+ struct acpi_table_header hdr;
+#define XSDT_SIG "XSDT"
+
+ u_int64_t table_offsets[1];
+} __packed;
+
+
+/* Generic Address Structure */
+struct acpi_gas {
+ u_int8_t address_space_id;
+#define GAS_SYSTEM_MEMORY 0
+#define GAS_SYSTEM_IOSPACE 1
+#define GAS_PCI_CFG_SPACE 2
+#define GAS_EMBEDDED 3
+#define GAS_SMBUS 4
+#define GAS_FUNCTIONAL_FIXED 127
+ u_int8_t register_bit_width;
+ u_int8_t register_bit_offset;
+ u_int8_t access_size;
+#define GAS_ACCESS_UNDEFINED 0
+#define GAS_ACCESS_BYTE 1
+#define GAS_ACCESS_WORD 2
+#define GAS_ACCESS_DWORD 3
+#define GAS_ACCESS_QWORD 4
+ u_int64_t address;
+} __packed;
+
+/* Fixed ACPI Descriptiion Table */
+struct acpi_fadt {
+ struct acpi_table_header hdr;
+#define FADT_SIG "FACP"
+
+ u_int32_t firmware_ctl; /* phys addr FACS */
+ u_int32_t dsdt; /* phys addr DSDT */
+
+ /* int_model is defined in ACPI 1.0, in ACPI 2.0, it should be zero */
+ u_int8_t int_model; /* interrupt model (hdr_revision < 3) */
+
+#define FADT_INT_DUAL_PIC 0
+#define FADT_INT_MULTI_APIC 1
+ u_int8_t pm_profile; /* power mgmt profile */
+#define FADT_PM_UNSPEC 0
+#define FADT_PM_DESKTOP 1
+#define FADT_PM_MOBILE 2
+#define FADT_PM_WORKSTATION 3
+#define FADT_PM_ENT_SERVER 4
+#define FADT_PM_SOHO_SERVER 5
+#define FADT_PM_APPLIANCE 6
+#define FADT_PM_PERF_SERVER 7
+ u_int16_t sci_int; /* SCI interrupt */
+ u_int32_t smi_cmd; /* SMI command port */
+ u_int8_t acpi_enable; /* value to enable */
+ u_int8_t acpi_disable; /* value to disable */
+ u_int8_t s4bios_req; /* value for S4 */
+ u_int8_t pstate_cnt; /* value for performance (hdr_revision > 2) */
+ u_int32_t pm1a_evt_blk; /* power management 1a */
+ u_int32_t pm1b_evt_blk; /* power mangement 1b */
+ u_int32_t pm1a_cnt_blk; /* pm control 1a */
+ u_int32_t pm1b_cnt_blk; /* pm control 1b */
+ u_int32_t pm2_cnt_blk; /* pm control 2 */
+ u_int32_t pm_tmr_blk;
+ u_int32_t gpe0_blk;
+ u_int32_t gpe1_blk;
+ u_int8_t pm1_evt_len;
+ u_int8_t pm1_cnt_len;
+ u_int8_t pm2_cnt_len;
+ u_int8_t pm_tmr_len;
+ u_int8_t gpe0_blk_len;
+ u_int8_t gpe1_blk_len;
+ u_int8_t gpe1_base;
+ u_int8_t cst_cnt; /* (hdr_revision > 2) */
+ u_int16_t p_lvl2_lat;
+ u_int16_t p_lvl3_lat;
+ u_int16_t flush_size;
+ u_int16_t flush_stride;
+ u_int8_t duty_offset;
+ u_int8_t duty_width;
+ u_int8_t day_alrm;
+ u_int8_t mon_alrm;
+ u_int8_t century;
+ u_int16_t iapc_boot_arch; /* (hdr_revision > 2) */
+#define FADT_LEGACY_DEVICES 0x0001 /* Legacy devices supported */
+#define FADT_i8042 0x0002 /* Keyboard controller present */
+#define FADT_NO_VGA 0x0004 /* Do not probe VGA */
+ u_int8_t reserved1;
+ u_int32_t flags;
+#define FADT_WBINVD 0x00000001
+#define FADT_WBINVD_FLUSH 0x00000002
+#define FADT_PROC_C1 0x00000004
+#define FADT_P_LVL2_UP 0x00000008
+#define FADT_PWR_BUTTON 0x00000010
+#define FADT_SLP_BUTTON 0x00000020
+#define FADT_FIX_RTC 0x00000040
+#define FADT_RTC_S4 0x00000080
+#define FADT_TMR_VAL_EXT 0x00000100
+#define FADT_DCK_CAP 0x00000200
+#define FADT_RESET_REG_SUP 0x00000400
+#define FADT_SEALED_CASE 0x00000800
+#define FADT_HEADLESS 0x00001000
+#define FADT_CPU_SW_SLP 0x00002000
+#define FADT_PCI_EXP_WAK 0x00004000
+#define FADT_USE_PLATFORM_CLOCK 0x00008000
+#define FADT_S4_RTC_STS_VALID 0x00010000
+#define FADT_REMOTE_POWER_ON_CAPABLE 0x00020000
+#define FADT_FORCE_APIC_CLUSTER_MODEL 0x00040000
+#define FADT_FORCE_APIC_PHYS_DEST_MODE 0x00080000
+ /*
+ * Following values only exist when rev > 1
+ * If the extended addresses exists, they
+ * must be used in preferense to the non-
+ * extended values above
+ */
+ struct acpi_gas reset_reg;
+ u_int8_t reset_value;
+
+ u_int8_t reserved2a;
+ u_int8_t reserved2b;
+ u_int8_t reserved2c;
+
+ u_int64_t x_firmware_ctl;
+ u_int64_t x_dsdt;
+ struct acpi_gas x_pm1a_evt_blk;
+ struct acpi_gas x_pm1b_evt_blk;
+ struct acpi_gas x_pm1a_cnt_blk;
+ struct acpi_gas x_pm1b_cnt_blk;
+ struct acpi_gas x_pm2_cnt_blk;
+ struct acpi_gas x_pm_tmr_blk;
+ struct acpi_gas x_gpe0_blk;
+ struct acpi_gas x_gpe1_blk;
+} __packed;
+
+struct acpi_madt {
+ struct acpi_table_header hdr;
+#define MADT_SIG "APIC"
+
+ u_int32_t local_apic_address;
+ u_int32_t flags;
+#define ACPI_APIC_PCAT_COMPAT 0x00000001
+} __packed;
+
+struct acpi_madt_lapic {
+ u_int8_t apic_type;
+#define ACPI_MADT_LAPIC 0
+ u_int8_t length;
+ u_int8_t acpi_proc_id;
+ u_int8_t apic_id;
+ u_int32_t flags;
+#define ACPI_PROC_ENABLE 0x00000001
+} __packed;
+
+struct acpi_madt_ioapic {
+ u_int8_t apic_type;
+#define ACPI_MADT_IOAPIC 1
+ u_int8_t length;
+ u_int8_t acpi_ioapic_id;
+ u_int8_t reserved;
+ u_int32_t address;
+ u_int32_t global_int_base;
+} __packed;
+typedef struct acpi_madt_ioapic acpi_table_ioapic_t;
+
+struct acpi_madt_override {
+ u_int8_t apic_type;
+#define ACPI_MADT_OVERRIDE 2
+ u_int8_t length;
+ u_int8_t bus;
+#define ACPI_OVERRIDE_BUS_ISA 0
+ u_int8_t source;
+ u_int32_t global_int;
+ u_int16_t flags;
+#define ACPI_OVERRIDE_POLARITY_BITS 0x3
+#define ACPI_OVERRIDE_POLARITY_BUS 0x0
+#define ACPI_OVERRIDE_POLARITY_HIGH 0x1
+#define ACPI_OVERRIDE_POLARITY_LOW 0x3
+#define ACPI_OVERRIDE_TRIGGER_BITS 0xc
+#define ACPI_OVERRIDE_TRIGGER_BUS 0x0
+#define ACPI_OVERRIDE_TRIGGER_EDGE 0x4
+#define ACPI_OVERRIDE_TRIGGER_LEVEL 0xc
+} __packed;
+
+struct acpi_madt_nmi {
+ u_int8_t apic_type;
+#define ACPI_MADT_NMI 3
+ u_int8_t length;
+ u_int16_t flags; /* Same flags as acpi_madt_override */
+ u_int32_t global_int;
+} __packed;
+
+struct acpi_madt_lapic_nmi {
+ u_int8_t apic_type;
+#define ACPI_MADT_LAPIC_NMI 4
+ u_int8_t length;
+ u_int8_t acpi_proc_id;
+ u_int16_t flags; /* Same flags as acpi_madt_override */
+ u_int8_t local_apic_lint;
+} __packed;
+
+struct acpi_madt_lapic_override {
+ u_int8_t apic_type;
+#define ACPI_MADT_LAPIC_OVERRIDE 5
+ u_int8_t length;
+ u_int16_t reserved;
+ u_int64_t lapic_address;
+} __packed;
+
+struct acpi_madt_io_sapic {
+ u_int8_t apic_type;
+#define ACPI_MADT_IO_SAPIC 6
+ u_int8_t length;
+ u_int8_t iosapic_id;
+ u_int8_t reserved;
+ u_int32_t global_int_base;
+ u_int64_t iosapic_address;
+} __packed;
+
+struct acpi_madt_local_sapic {
+ u_int8_t apic_type;
+#define ACPI_MADT_LOCAL_SAPIC 7
+ u_int8_t length;
+ u_int8_t acpi_proc_id;
+ u_int8_t local_sapic_id;
+ u_int8_t local_sapic_eid;
+ u_int8_t reserved[3];
+ u_int32_t flags; /* Same flags as acpi_madt_lapic */
+ u_int32_t acpi_proc_uid;
+ u_int8_t acpi_proc_uid_string[1];
+} __packed;
+
+struct acpi_madt_platform_int {
+ u_int8_t apic_type;
+#define ACPI_MADT_PLATFORM_INT 8
+ u_int8_t length;
+ u_int16_t flags; /* Same flags as acpi_madt_override */
+ u_int8_t int_type;
+#define ACPI_MADT_PLATFORM_PMI 1
+#define ACPI_MADT_PLATFORM_INIT 2
+#define ACPI_MADT_PLATFORM_CORR_ERROR 3
+ u_int8_t proc_id;
+ u_int8_t proc_eid;
+ u_int8_t io_sapic_vec;
+ u_int32_t global_int;
+ u_int32_t platform_int_flags;
+#define ACPI_MADT_PLATFORM_CPEI 0x00000001
+} __packed;
+
+union acpi_madt_entry {
+ struct acpi_madt_lapic madt_lapic;
+ struct acpi_madt_ioapic madt_ioapic;
+ struct acpi_madt_override madt_override;
+ struct acpi_madt_nmi madt_nmi;
+ struct acpi_madt_lapic_nmi madt_lapic_nmi;
+ struct acpi_madt_lapic_override madt_lapic_override;
+ struct acpi_madt_io_sapic madt_io_sapic;
+ struct acpi_madt_local_sapic madt_local_sapic;
+ struct acpi_madt_platform_int madt_platform_int;
+} __packed;
+
+struct device_scope {
+ u_int8_t type;
+ u_int8_t length;
+ u_int16_t reserved;
+ u_int8_t enumeration_id;
+ u_int8_t start_bus_number;
+ u_int16_t path[1]; /* Path starts here */
+} __packed;
+
+struct dmar_remapping {
+ u_int16_t type;
+#define DMAR_REMAPPING_DRHD 0
+#define DMAR_REMAPPING_RMRR 1
+#define DMAR_REMAPPING_ATSR 2
+#define DMAR_REMAPPING_RHSA 3
+#define DMAR_REMAPPING_RESERVED 4
+ u_int16_t length;
+ u_int8_t flags;
+#define REMAPPING_INCLUDE_PCI_ALL Ox01
+
+ u_int8_t reserved;
+ u_int16_t segment_number;
+ u_int8_t register_base_address[8];
+ struct device_scope device_scope_entry[1]; /* Device Scope starts here */
+} __packed;
+
+struct acpi_dmar {
+ struct acpi_table_header hdr;
+#define DMAR_SIG "DMAR"
+ u_int8_t host_address_width;
+ u_int8_t flags;
+#define DMAR_INTR_REMAP 0x01
+
+ u_int8_t reserved[10];
+ struct dmar_remapping table_offsets[1]; /* dmar_remapping structure starts here */
+} __packed;
+
+struct acpi_mcfg_mmcfg {
+ u_int64_t base_address;
+ u_int16_t group_number;
+ u_int8_t start_bus_number;
+ u_int8_t end_bus_number;
+ u_int32_t reserved;
+} __packed;
+
+struct acpi_mcfg {
+ struct acpi_table_header hdr;
+#define MCFG_SIG "MCFG"
+
+ u_int64_t reserved;
+ /* struct acpi_mcfg_mmcfg table_offsets[1]; */
+ u_int32_t base_address;
+} __packed;
+typedef struct acpi_mcfg acpi_table_mcfg_t;
+
+#if 0
+
+#define ACPI_FREQUENCY 3579545 /* Per ACPI spec */
+
+/*
+ * PCI Configuration space
+ */
+#define ACPI_PCI_BUS(addr) (u_int16_t)((addr) >> 48)
+#define ACPI_PCI_DEV(addr) (u_int16_t)((addr) >> 32)
+#define ACPI_PCI_FN(addr) (u_int16_t)((addr) >> 16)
+#define ACPI_PCI_REG(addr) (u_int16_t)(addr)
+#define ACPI_PCI_ADDR(b,d,f,r) ((u_int64_t)(b)<<48LL | (u_int64_t)(d)<<32LL | (f)<<16LL | (r))
+
+/*
+ * PM1 Status Registers Fixed Hardware Feature Status Bits
+ */
+#define ACPI_PM1_STATUS 0x00
+#define ACPI_PM1_TMR_STS 0x0001
+#define ACPI_PM1_BM_STS 0x0010
+#define ACPI_PM1_GBL_STS 0x0020
+#define ACPI_PM1_PWRBTN_STS 0x0100
+#define ACPI_PM1_SLPBTN_STS 0x0200
+#define ACPI_PM1_RTC_STS 0x0400
+#define ACPI_PM1_PCIEXP_WAKE_STS 0x4000
+#define ACPI_PM1_WAK_STS 0x8000
+
+/*
+ * PM1 Enable Registers
+ */
+#define ACPI_PM1_ENABLE 0x02
+#define ACPI_PM1_TMR_EN 0x0001
+#define ACPI_PM1_GBL_EN 0x0020
+#define ACPI_PM1_PWRBTN_EN 0x0100
+#define ACPI_PM1_SLPBTN_EN 0x0200
+#define ACPI_PM1_RTC_EN 0x0400
+#define ACPI_PM1_PCIEXP_WAKE_DIS 0x4000
+
+/*
+ * PM1 Control Registers
+ */
+#define ACPI_PM1_CONTROL 0x00
+#define ACPI_PM1_SCI_EN 0x0001
+#define ACPI_PM1_BM_RLD 0x0002
+#define ACPI_PM1_GBL_RLS 0x0004
+#define ACPI_PM1_SLP_TYPX(x) ((x) << 10)
+#define ACPI_PM1_SLP_TYPX_MASK 0x1c00
+#define ACPI_PM1_SLP_EN 0x2000
+
+/*
+ * PM2 Control Registers
+ */
+#define ACPI_PM2_CONTROL 0x06
+#define ACPI_PM2_ARB_DIS 0x0001
+
+
+/*
+ * Sleeping States
+ */
+#define ACPI_STATE_S0 0
+#define ACPI_STATE_S1 1
+#define ACPI_STATE_S2 2
+#define ACPI_STATE_S3 3
+#define ACPI_STATE_S4 4
+#define ACPI_STATE_S5 5
+
+/*
+ * ACPI Device IDs
+ */
+#define ACPI_DEV_TIM "PNP0100" /* System timer */
+#define ACPI_DEV_ACPI "PNP0C08" /* ACPI device */
+#define ACPI_DEV_PCIB "PNP0A03" /* PCI bus */
+#define ACPI_DEV_GISAB "PNP0A05" /* Generic ISA Bus */
+#define ACPI_DEV_EIOB "PNP0A06" /* Extended I/O Bus */
+#define ACPI_DEV_PCIEB "PNP0A08" /* PCIe bus */
+#define ACPI_DEV_MR "PNP0C02" /* Motherboard resources */
+#define ACPI_DEV_NPROC "PNP0C04" /* Numeric data processor */
+#define ACPI_DEV_CS "PNP0C08" /* ACPI-Compliant System */
+#define ACPI_DEV_ECD "PNP0C09" /* Embedded Controller Device */
+#define ACPI_DEV_CMB "PNP0C0A" /* Control Method Battery */
+#define ACPI_DEV_FAN "PNP0C0B" /* Fan Device */
+#define ACPI_DEV_PBD "PNP0C0C" /* Power Button Device */
+#define ACPI_DEV_LD "PNP0C0D" /* Lid Device */
+#define ACPI_DEV_SBD "PNP0C0E" /* Sleep Button Device */
+#define ACPI_DEV_PILD "PNP0C0F" /* PCI Interrupt Link Device */
+#define ACPI_DEV_MEMD "PNP0C80" /* Memory Device */
+#define ACPI_DEV_SHC "ACPI0001" /* SMBus 1.0 Host Controller */
+#define ACPI_DEV_SMS1 "ACPI0002" /* Smart Battery Subsystem */
+#define ACPI_DEV_AC "ACPI0003" /* AC Device */
+#define ACPI_DEV_MD "ACPI0004" /* Module Device */
+#define ACPI_DEV_SMS2 "ACPI0005" /* SMBus 2.0 Host Controller */
+#define ACPI_DEV_GBD "ACPI0006" /* GPE Block Device */
+#define ACPI_DEV_PD "ACPI0007" /* Processor Device */
+#define ACPI_DEV_ALSD "ACPI0008" /* Ambient Light Sensor Device */
+#define ACPI_DEV_IOXA "ACPI0009" /* IO x APIC Device */
+#define ACPI_DEV_IOA "ACPI000A"/ /* IO APIC Device */
+#define ACPI_DEV_IOSA "ACPI000B" /* IO SAPIC Device */
+#define ACPI_DEV_THZ "THERMALZONE" /* Thermal Zone */
+#define ACPI_DEV_FFB "FIXEDBUTTON" /* Fixed Feature Button */
+#define ACPI_DEV_ASUS "ASUS010" /* ASUS Hotkeys */
+#define ACPI_DEV_THINKPAD "IBM0068" /* ThinkPad support */
+
+#endif
+
+bool save_vtd_dmar_table(void);
+bool restore_vtd_dmar_table(void);
+bool remove_vtd_dmar_table(void);
+
+struct acpi_table_ioapic *get_acpi_ioapic_table(void);
+struct acpi_mcfg *get_acpi_mcfg_table(void);
+void disable_smis(void);
+
+bool machine_sleep(const tboot_acpi_sleep_info_t *);
+void set_s3_resume_vector(const tboot_acpi_sleep_info_t *, uint64_t);
+struct acpi_rsdp *get_rsdp(void);
+uint32_t get_madt_apic_base(void);
+
+#endif /* __ACPI_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/atomic.h b/tboot/include/atomic.h
new file mode 100644
index 0000000..502cc36
--- /dev/null
+++ b/tboot/include/atomic.h
@@ -0,0 +1,181 @@
+/*-
+ * Copyright (c) 1998 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/i386/include/atomic.h,v 1.47.2.2.2.1 2010/02/10 00:26:20 kensmith Exp $
+ */
+/*
+ * Portions copyright (c) 2010, Intel Corporation
+ */
+
+#ifndef __ATOMIC_H__
+#define __ATOMIC_H__
+
+/*
+ * Various simple operations on memory, each of which is atomic in the
+ * presence of interrupts and multiple processors.
+ *
+ * atomic_set_char(P, V) (*(u_char *)(P) |= (V))
+ * atomic_clear_char(P, V) (*(u_char *)(P) &= ~(V))
+ * atomic_add_char(P, V) (*(u_char *)(P) += (V))
+ * atomic_subtract_char(P, V) (*(u_char *)(P) -= (V))
+ *
+ * atomic_set_short(P, V) (*(u_short *)(P) |= (V))
+ * atomic_clear_short(P, V) (*(u_short *)(P) &= ~(V))
+ * atomic_add_short(P, V) (*(u_short *)(P) += (V))
+ * atomic_subtract_short(P, V) (*(u_short *)(P) -= (V))
+ *
+ * atomic_set_int(P, V) (*(u_int *)(P) |= (V))
+ * atomic_clear_int(P, V) (*(u_int *)(P) &= ~(V))
+ * atomic_add_int(P, V) (*(u_int *)(P) += (V))
+ * atomic_subtract_int(P, V) (*(u_int *)(P) -= (V))
+ * atomic_readandclear_int(P) (return (*(u_int *)(P)); *(u_int *)(P) = 0;)
+ *
+ * atomic_set_long(P, V) (*(u_long *)(P) |= (V))
+ * atomic_clear_long(P, V) (*(u_long *)(P) &= ~(V))
+ * atomic_add_long(P, V) (*(u_long *)(P) += (V))
+ * atomic_subtract_long(P, V) (*(u_long *)(P) -= (V))
+ * atomic_readandclear_long(P) (return (*(u_long *)(P)); *(u_long *)(P) = 0;)
+ */
+
+/*
+ * The above functions are expanded inline in the statically-linked
+ * kernel. Lock prefixes are generated if an SMP kernel is being
+ * built.
+ *
+ * Kernel modules call real functions which are built into the kernel.
+ * This allows kernel modules to be portable between UP and SMP systems.
+ */
+
+/* all operations will be defined only for 'int's */
+#define atomic_t u_int
+
+#define MPLOCKED "lock ; "
+
+/*
+ * The assembly is volatilized to avoid code chunk removal by the compiler.
+ * GCC aggressively reorders operations and memory clobbering is necessary
+ * in order to avoid that for memory barriers.
+ */
+#define ATOMIC_ASM(NAME, TYPE, OP, CONS, V) \
+static __inline void \
+atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
+{ \
+ __asm __volatile(MPLOCKED OP \
+ : "=m" (*p) \
+ : CONS (V), "m" (*p)); \
+} \
+ \
+static __inline void \
+atomic_##NAME##_barr_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
+{ \
+ __asm __volatile(MPLOCKED OP \
+ : "=m" (*p) \
+ : CONS (V), "m" (*p) \
+ : "memory"); \
+} \
+struct __hack
+
+/*
+ * Atomically add the value of v to the integer pointed to by p and return
+ * the previous value of *p.
+ */
+static __inline u_int
+atomic_fetchadd_int(volatile u_int *p, u_int v)
+{
+
+ __asm __volatile(
+ " " MPLOCKED " "
+ " xaddl %0, %1 ; "
+ "# atomic_fetchadd_int"
+ : "+r" (v), /* 0 (result) */
+ "=m" (*p) /* 1 */
+ : "m" (*p)); /* 2 */
+
+ return (v);
+}
+
+#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \
+static __inline u_##TYPE \
+atomic_load_acq_##TYPE(volatile u_##TYPE *p) \
+{ \
+ u_##TYPE res; \
+ \
+ __asm __volatile(MPLOCKED LOP \
+ : "=a" (res), /* 0 */ \
+ "=m" (*p) /* 1 */ \
+ : "m" (*p) /* 2 */ \
+ : "memory"); \
+ \
+ return (res); \
+} \
+ \
+/* \
+ * The XCHG instruction asserts LOCK automagically. \
+ */ \
+static __inline void \
+atomic_store_rel_##TYPE(volatile u_##TYPE *p, u_##TYPE v)\
+{ \
+ __asm __volatile(SOP \
+ : "=m" (*p), /* 0 */ \
+ "+r" (v) /* 1 */ \
+ : "m" (*p) /* 2 */ \
+ : "memory"); \
+} \
+struct __hack
+
+ATOMIC_ASM(set, int, "orl %1,%0", "ir", v);
+ATOMIC_ASM(clear, int, "andl %1,%0", "ir", ~v);
+ATOMIC_ASM(add, int, "addl %1,%0", "ir", v);
+ATOMIC_ASM(subtract, int, "subl %1,%0", "ir", v);
+
+ATOMIC_STORE_LOAD(int, "cmpxchgl %0,%1", "xchgl %1,%0");
+
+#undef ATOMIC_ASM
+#undef ATOMIC_STORE_LOAD
+
+/* Read the current value and store a zero in the destination. */
+static __inline u_int
+atomic_readandclear_int(volatile u_int *addr)
+{
+ u_int res;
+
+ res = 0;
+ __asm __volatile(
+ " xchgl %1,%0 ; "
+ "# atomic_readandclear_int"
+ : "+r" (res), /* 0 */
+ "=m" (*addr) /* 1 */
+ : "m" (*addr));
+
+ return (res);
+}
+
+
+#define atomic_read(atom) atomic_load_acq_int(atom)
+#define atomic_inc(atom) atomic_add_int((atom), 1)
+#define atomic_dec(atom) atomic_subtract_int((atom), 1)
+#define atomic_set(atom, val) atomic_set_int((atom), (val))
+
+#endif /* __ATOMIC_H__ */
diff --git a/tboot/include/cmdline.h b/tboot/include/cmdline.h
new file mode 100644
index 0000000..4b01c20
--- /dev/null
+++ b/tboot/include/cmdline.h
@@ -0,0 +1,76 @@
+/*
+ * cmdline.h: support functions for command line parsing
+ *
+ * Copyright (c) 2006-2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __CMDLINE_H__
+#define __CMDLINE_H__
+
+#define CMDLINE_SIZE 512
+char g_cmdline[CMDLINE_SIZE];
+
+
+void tboot_parse_cmdline(bool defaults);
+void get_tboot_loglvl(void);
+void get_tboot_log_targets(void);
+bool get_tboot_serial(void);
+void get_tboot_baud(void);
+void get_tboot_fmt(void);
+void get_tboot_vga_delay(void);
+bool get_tboot_mwait(void);
+bool get_tboot_prefer_da(void);
+void get_tboot_min_ram(void);
+bool get_tboot_call_racm(void);
+bool get_tboot_call_racm_check(void);
+bool get_tboot_measure_nv(void);
+void get_tboot_extpol(void);
+
+/* for parse cmdline of linux kernel, say vga and mem */
+void linux_parse_cmdline(const char *cmdline);
+bool get_linux_vga(int *vid_mode);
+bool get_linux_mem(uint64_t *initrd_max_mem);
+
+uint8_t get_loglvl_prefix(char **pbuf, int *len);
+
+#endif /* __CMDLINE_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/com.h b/tboot/include/com.h
new file mode 100644
index 0000000..c51a9fd
--- /dev/null
+++ b/tboot/include/com.h
@@ -0,0 +1,311 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)ns16550.h 7.1 (Berkeley) 5/9/91
+ * $FreeBSD: src/sys/dev/ic/ns16550.h,v 1.20 2010/01/11 04:13:06 imp Exp $
+ */
+/*
+ * Portions copyright (c) 2010, Intel Corporation
+ */
+
+/*
+ * NS8250... UART registers.
+ */
+#ifndef __COM_H__
+#define __COM_H__
+
+/* 8250 registers #[0-6]. */
+
+#define com_data 0 /* data register (R/W) */
+#define REG_DATA com_data
+
+#define com_ier 1 /* interrupt enable register (W) */
+#define REG_IER com_ier
+#define IER_ERXRDY 0x1
+#define IER_ETXRDY 0x2
+#define IER_ERLS 0x4
+#define IER_EMSC 0x8
+
+#define IER_BITS "\20\1ERXRDY\2ETXRDY\3ERLS\4EMSC"
+
+#define com_iir 2 /* interrupt identification register (R) */
+#define REG_IIR com_iir
+#define IIR_IMASK 0xf
+#define IIR_RXTOUT 0xc
+#define IIR_BUSY 0x7
+#define IIR_RLS 0x6
+#define IIR_RXRDY 0x4
+#define IIR_TXRDY 0x2
+#define IIR_NOPEND 0x1
+#define IIR_MLSC 0x0
+#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */
+
+#define IIR_BITS "\20\1NOPEND\2TXRDY\3RXRDY"
+
+#define com_lcr 3 /* line control register (R/W) */
+#define com_cfcr com_lcr /* character format control register (R/W) */
+#define REG_LCR com_lcr
+#define LCR_DLAB 0x80
+#define CFCR_DLAB LCR_DLAB
+#define LCR_EFR_ENABLE 0xbf /* magic to enable EFR on 16650 up */
+#define CFCR_EFR_ENABLE LCR_EFR_ENABLE
+#define LCR_SBREAK 0x40
+#define CFCR_SBREAK LCR_SBREAK
+#define LCR_PZERO 0x30
+#define CFCR_PZERO LCR_PZERO
+#define LCR_PONE 0x20
+#define CFCR_PONE LCR_PONE
+#define LCR_PEVEN 0x10
+#define CFCR_PEVEN LCR_PEVEN
+#define LCR_PODD 0x00
+#define CFCR_PODD LCR_PODD
+#define LCR_PENAB 0x08
+#define CFCR_PENAB LCR_PENAB
+#define LCR_STOPB 0x04
+#define CFCR_STOPB LCR_STOPB
+#define LCR_8BITS 0x03
+#define CFCR_8BITS LCR_8BITS
+#define LCR_7BITS 0x02
+#define CFCR_7BITS LCR_7BITS
+#define LCR_6BITS 0x01
+#define CFCR_6BITS LCR_6BITS
+#define LCR_5BITS 0x00
+#define CFCR_5BITS LCR_5BITS
+
+#define LCR_ODD_PARITY (LCR_PENAB | LCR_PODD)
+#define LCR_EVEN_PARITY (LCR_PENAB | LCR_PEVEN)
+#define LCR_MARK_PARITY (LCR_PENAB | LCR_PONE)
+#define LCR_SPACE_PARITY (LCR_PENAB | LCR_PZERO)
+
+#define com_mcr 4 /* modem control register (R/W) */
+#define REG_MCR com_mcr
+#define MCR_PRESCALE 0x80 /* only available on 16650 up */
+#define MCR_LOOPBACK 0x10
+#define MCR_IE 0x08
+#define MCR_IENABLE MCR_IE
+#define MCR_DRS 0x04
+#define MCR_RTS 0x02
+#define MCR_DTR 0x01
+
+#define MCR_BITS "\20\1DTR\2RTS\3DRS\4IE\5LOOPBACK\10PRESCALE"
+
+#define com_lsr 5 /* line status register (R/W) */
+#define REG_LSR com_lsr
+#define LSR_RCV_FIFO 0x80
+#define LSR_TEMT 0x40
+#define LSR_TSRE LSR_TEMT
+#define LSR_THRE 0x20
+#define LSR_TXRDY LSR_THRE
+#define LSR_BI 0x10
+#define LSR_FE 0x08
+#define LSR_PE 0x04
+#define LSR_OE 0x02
+#define LSR_RXRDY 0x01
+#define LSR_RCV_MASK 0x1f
+
+#define LSR_BITS "\20\1RXRDY\2OE\3PE\4FE\5BI\6THRE\7TEMT\10RCV_FIFO"
+
+#define com_msr 6 /* modem status register (R/W) */
+#define REG_MSR com_msr
+#define MSR_DCD 0x80
+#define MSR_RI 0x40
+#define MSR_DSR 0x20
+#define MSR_CTS 0x10
+#define MSR_DDCD 0x08
+#define MSR_TERI 0x04
+#define MSR_DDSR 0x02
+#define MSR_DCTS 0x01
+
+#define MSR_BITS "\20\1DCTS\2DDSR\3TERI\4DDCD\5CTS\6DSR\7RI\10DCD"
+
+/* 8250 multiplexed registers #[0-1]. Access enabled by LCR[7]. */
+#define com_dll 0 /* divisor latch low (R/W) */
+#define com_dlbl com_dll
+#define com_dlm 1 /* divisor latch high (R/W) */
+#define com_dlbh com_dlm
+#define REG_DLL com_dll
+#define REG_DLH com_dlm
+
+/* 16450 register #7. Not multiplexed. */
+#define com_scr 7 /* scratch register (R/W) */
+
+/* 16550 register #2. Not multiplexed. */
+#define com_fcr 2 /* FIFO control register (W) */
+#define com_fifo com_fcr
+#define REG_FCR com_fcr
+#define FCR_ENABLE 0x01
+#define FIFO_ENABLE FCR_ENABLE
+#define FCR_RCV_RST 0x02
+#define FIFO_RCV_RST FCR_RCV_RST
+#define FCR_XMT_RST 0x04
+#define FIFO_XMT_RST FCR_XMT_RST
+#define FCR_DMA 0x08
+#define FIFO_DMA_MODE FCR_DMA
+#define FCR_RX_LOW 0x00
+#define FIFO_RX_LOW FCR_RX_LOW
+#define FCR_RX_MEDL 0x40
+#define FIFO_RX_MEDL FCR_RX_MEDL
+#define FCR_RX_MEDH 0x80
+#define FIFO_RX_MEDH FCR_RX_MEDH
+#define FCR_RX_HIGH 0xc0
+#define FIFO_RX_HIGH FCR_RX_HIGH
+
+#define FCR_BITS "\20\1ENABLE\2RCV_RST\3XMT_RST\4DMA"
+
+/* 16650 registers #2,[4-7]. Access enabled by LCR_EFR_ENABLE. */
+
+#define com_efr 2 /* enhanced features register (R/W) */
+#define REG_EFR com_efr
+#define EFR_CTS 0x80
+#define EFR_AUTOCTS EFR_CTS
+#define EFR_RTS 0x40
+#define EFR_AUTORTS EFR_RTS
+#define EFR_EFE 0x10 /* enhanced functions enable */
+
+#define com_xon1 4 /* XON 1 character (R/W) */
+#define com_xon2 5 /* XON 2 character (R/W) */
+#define com_xoff1 6 /* XOFF 1 character (R/W) */
+#define com_xoff2 7 /* XOFF 2 character (R/W) */
+
+#define com_usr 39 /* Octeon 16750/16550 Uart Status Reg */
+#define REG_USR com_usr
+#define USR_TXFIFO_NOTFULL 2 /* Uart TX FIFO Not full */
+
+/* 16950 register #1. Access enabled by ACR[7]. Also requires !LCR[7]. */
+#define com_asr 1 /* additional status register (R[0-7]/W[0-1]) */
+
+/* 16950 register #3. R/W access enabled by ACR[7]. */
+#define com_rfl 3 /* receiver fifo level (R) */
+
+/*
+ * 16950 register #4. Access enabled by ACR[7]. Also requires
+ * !LCR_EFR_ENABLE.
+ */
+#define com_tfl 4 /* transmitter fifo level (R) */
+
+/*
+ * 16950 register #5. Accessible if !LCR_EFR_ENABLE. Read access also
+ * requires ACR[6].
+ */
+#define com_icr 5 /* index control register (R/W) */
+
+/*
+ * 16950 register #7. It is the same as com_scr except it has a different
+ * abbreviation in the manufacturer's data sheet and it also serves as an
+ * index into the Indexed Control register set.
+ */
+#define com_spr com_scr /* scratch pad (and index) register (R/W) */
+#define REG_SPR com_scr
+
+/*
+ * 16950 indexed control registers #[0-0x13]. Access is via index in SPR,
+ * data in ICR (if ICR is accessible).
+ */
+
+#define com_acr 0 /* additional control register (R/W) */
+#define ACR_ASE 0x80 /* ASR/RFL/TFL enable */
+#define ACR_ICRE 0x40 /* ICR enable */
+#define ACR_TLE 0x20 /* TTL/RTL enable */
+
+#define com_cpr 1 /* clock prescaler register (R/W) */
+#define com_tcr 2 /* times clock register (R/W) */
+#define com_ttl 4 /* transmitter trigger level (R/W) */
+#define com_rtl 5 /* receiver trigger level (R/W) */
+/* ... */
+
+/* Hardware extension mode register for RSB-2000/3000. */
+#define com_emr com_msr
+#define EMR_EXBUFF 0x04
+#define EMR_CTSFLW 0x08
+#define EMR_DSRFLW 0x10
+#define EMR_RTSFLW 0x20
+#define EMR_DTRFLW 0x40
+#define EMR_EFMODE 0x80
+
+/* com port */
+#define COM1_ADDR 0x3f8
+#define COM2_ADDR 0x2f8
+#define COM3_ADDR 0x3e8
+#define COM4_ADDR 0x2e8
+
+#define GET_LCR_DATABIT(x) ({ \
+ typeof(x) val = 0; \
+ val = (((x) == 5) ? LCR_5BITS : (val)); \
+ val = (((x) == 6) ? LCR_6BITS : (val)); \
+ val = (((x) == 7) ? LCR_7BITS : (val)); \
+ val = (((x) == 8) ? LCR_8BITS : (val)); \
+ val; })
+
+#define GET_LCR_STOPBIT(x) ({ \
+ typeof(x) val = 0; \
+ val = (((x) > 1) ? LCR_STOPB : val); \
+ val; })
+
+#define GET_LCR_PARITY(x) ({ \
+ typeof(x) val = 0; \
+ val = (((x) == 'n') ? (!LCR_PENAB) : val); \
+ val = (((x) == 'o') ? LCR_ODD_PARITY : val); \
+ val = (((x) == 'e') ? LCR_EVEN_PARITY : val); \
+ val = (((x) == 'm') ? LCR_MARK_PARITY : val); \
+ val = (((x) == 's') ? LCR_SPACE_PARITY : val); \
+ val; })
+
+#define GET_LCR_VALUE(data, stop, parity) \
+ (GET_LCR_DATABIT(data) | GET_LCR_STOPBIT(stop) | GET_LCR_PARITY(parity))
+
+typedef struct __packed {
+ uint32_t bus;
+ uint32_t slot;
+ uint32_t func;
+} bdf_t;
+
+typedef struct __packed {
+ uint32_t comc_curspeed; /* baud rate */
+ uint32_t comc_clockhz; /* clock hz */
+ uint8_t comc_fmt; /* lcr value */
+ uint32_t comc_port; /* serial port, COM[1|2|3|4] */
+ uint32_t comc_irq; /* irq */
+ bdf_t comc_psbdf; /* PCI serial controller bdf */
+ bdf_t comc_pbbdf; /* PCI bridge bdf */
+} serial_port_t;
+
+void comc_init(void);
+void comc_puts(const char*, unsigned int);
+
+#endif /* __COM_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/compiler.h b/tboot/include/compiler.h
new file mode 100644
index 0000000..8987161
--- /dev/null
+++ b/tboot/include/compiler.h
@@ -0,0 +1,52 @@
+/*
+ * compiler.h: These are various compiler-related defines
+ *
+ * Copyright (c) 2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __COMPILER_H__
+#define __COMPILER_H__
+
+#define inline __inline__
+#define always_inline __inline__ __attribute__ ((always_inline))
+
+#endif /* __COMPILER_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/config.h b/tboot/include/config.h
new file mode 100644
index 0000000..9f9d8d1
--- /dev/null
+++ b/tboot/include/config.h
@@ -0,0 +1,133 @@
+/*
+ * config.h: project-wide definitions
+ *
+ * Copyright (c) 2006-2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __CONFIG_H__
+#define __CONFIG_H__
+
+/* EFI and MLE layout values */
+/* TODO MLE should cover .rdata too. Address that later */
+
+/**********************************************************
+ * TBOOT rumtime layout
+ *
+ * +---------------+ 0xXXXX0000
+ * | | Post Launch page tables
+ * | PLETP | 4K pages below 2M
+ * | | 2M pages below 4G
+ * +---------------+ 0xXXXX7000
+ * | MLEPT | Measure Launch page tables
+ * | | Cover MLE/.text section
+ * +---------------+ 0xXXXXA000
+ * | PE HDR |
+ * +---------------+ 0xXXXXB000
+ * | |
+ * | MLE | The MLE/.text section.
+ * | |
+ * +---------------+
+ * | |
+ * | DATA |
+ * | SHATED | The rest of the TBOOT image.
+ * | ETC |
+ * | |
+ * +---------------+
+ *
+ **********************************************************/
+
+/* Somewhere just below 4G */
+#define TBOOT_MAX_IMAGE_MEM 0xfffff000
+
+/* TBOOT post launch page table block */
+#define TBOOT_PLEPT_COUNT (7)
+#define TBOOT_PLEPT_SIZE (TBOOT_PLEPT_COUNT*PAGE_SIZE)
+
+/* TBOOT MLE page table block */
+#define TBOOT_MLEPT_COUNT (3)
+#define TBOOT_MLEPT_SIZE (TBOOT_MLEPT_COUNT*PAGE_SIZE)
+
+/* Totals */
+#define TBOOT_RTMEM_COUNT (TBOOT_PLEPT_COUNT + TBOOT_MLEPT_COUNT)
+#define TBOOT_RTMEM_SIZE (TBOOT_PLEPT_SIZE + TBOOT_MLEPT_SIZE)
+
+#ifndef NR_CPUS
+#define NR_CPUS 512
+#endif
+
+#ifdef __ASSEMBLY__
+#define ENTRY(name) \
+ .globl name; \
+ .align 16,0x90; \
+ name:
+#endif
+
+#define COMPILE_TIME_ASSERT(e) \
+{ \
+ struct tmp { \
+ int a : ((e) ? 1 : -1); \
+ }; \
+}
+
+#define __data __attribute__ ((__section__ (".data#")))
+#define __text __attribute__ ((__section__ (".text#")))
+
+#define __packed __attribute__ ((packed))
+
+/* tboot log level */
+#ifdef NO_TBOOT_LOGLVL
+#define TBOOT_NONE
+#define TBOOT_ERR
+#define TBOOT_WARN
+#define TBOOT_INFO
+#define TBOOT_DETA
+#define TBOOT_ALL
+#else /* NO_TBOOT_LOGLVL */
+#define TBOOT_NONE "<0>"
+#define TBOOT_ERR "<1>"
+#define TBOOT_WARN "<2>"
+#define TBOOT_INFO "<3>"
+#define TBOOT_DETA "<4>"
+#define TBOOT_ALL "<5>"
+#endif /* NO_TBOOT_LOGLVL */
+
+#endif /* __CONFIG_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/ctype.h b/tboot/include/ctype.h
new file mode 100644
index 0000000..20d6769
--- /dev/null
+++ b/tboot/include/ctype.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __CTYPE_H__
+#define __CTYPE_H__
+
+#include <stdbool.h>
+#include <types.h>
+#include <compiler.h>
+
+/* from:
+ * http://fxr.watson.org/fxr/source/dist/acpica/acutils.h?v=NETBSD5
+*/
+#define CTYPE_SIZE 257
+const uint8_t _ctype[CTYPE_SIZE];
+
+#define _XA 0x00 /* extra alphabetic - not supported */
+#define _XS 0x40 /* extra space */
+#define _BB 0x00 /* BEL, BS, etc. - not supported */
+#define _CN 0x20 /* CR, FF, HT, NL, VT */
+#define _DI 0x04 /* ''-'9' */
+#define _LO 0x02 /* 'a'-'z' */
+#define _PU 0x10 /* punctuation */
+#define _SP 0x08 /* space */
+#define _UP 0x01 /* 'A'-'Z' */
+#define _XD 0x80 /* ''-'9', 'A'-'F', 'a'-'f' */
+
+static always_inline bool isdigit(int c)
+{
+ return (_ctype[(unsigned char)(c)] & (_DI));
+}
+static always_inline bool isspace(int c)
+{
+ return (_ctype[(unsigned char)(c)] & (_SP));
+}
+static always_inline bool isxdigit(int c)
+{
+ return (_ctype[(unsigned char)(c)] & (_XD));
+}
+static always_inline bool isupper(int c)
+{
+ return (_ctype[(unsigned char)(c)] & (_UP));
+}
+static always_inline bool islower(int c)
+{
+ return (_ctype[(unsigned char)(c)] & (_LO));
+}
+static always_inline bool isprint(int c)
+{
+ return (_ctype[(unsigned char)(c)] & (_LO | _UP | _DI |
+ _SP | _PU));
+}
+static always_inline bool isalpha(int c)
+{
+ return (_ctype[(unsigned char)(c)] & (_LO | _UP));
+}
+static always_inline bool iscntrl(int c)
+{
+ return (_ctype[(unsigned char)(c)] & (_CN));
+}
+
+
+#endif /* __CTYPE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/efibase.h b/tboot/include/efibase.h
new file mode 100644
index 0000000..7138b79
--- /dev/null
+++ b/tboot/include/efibase.h
@@ -0,0 +1,46 @@
+/*
+ * efibase.h: EFI base includes.
+ *
+ * Copyright (c) 2017 Assured Information Security.
+ *
+ * Ross Philipson <philipsonr@ainfosec.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __EFIBASE_H__
+#define __EFIBASE_H__
+
+#include <efi.h>
+#include <efilib.h>
+#include <efirtlib.h>
+
+#include <efivar.h>
+#include <efigpt.h>
+
+#endif /* __EFIBASE_H__ */
diff --git a/tboot/include/eficonfig.h b/tboot/include/eficonfig.h
new file mode 100644
index 0000000..fc2cf16
--- /dev/null
+++ b/tboot/include/eficonfig.h
@@ -0,0 +1,109 @@
+/*
+ * eficonfig.h: EFI related config definitions.
+ *
+ * Copyright (c) 2017 Assured Information Security.
+ *
+ * Ross Philipson <philipsonr@ainfosec.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __EFI_CONFIG_H__
+#define __EFI_CONFIG_H__
+
+#define EFI_MAX_PATH 512
+#define EFI_MAX_CONFIG_FILE 1024 /* plenty of room for a config file */
+
+/* TBOOT config */
+#define SECTION_TBOOT "tboot"
+# define ITEM_OPTIONS "options"
+# define ITEM_XENPATH "xenpath"
+# define ITEM_LCP "lcp"
+#define SECTION_ACM "acm"
+#define SECTION_RACM "racm"
+
+/* Xen config */
+#define SECTION_GLOBAL "global"
+# define ITEM_DEFAULT "default"
+# define ITEM_KERNEL "kernel"
+
+enum {
+ EFI_CONFIG_TBOOT = 0,
+ EFI_CONFIG_TBOOT_PARSED,
+ EFI_CONFIG_XEN,
+ EFI_CONFIG_XEN_PARSED,
+ EFI_CONFIG_MAX
+};
+
+typedef struct {
+ union {
+ char *buffer;
+ EFI_PHYSICAL_ADDRESS addr;
+ } u;
+ uint64_t size;
+} efi_file_t;
+
+wchar_t g_tboot_dir[EFI_MAX_PATH];
+bool g_post_ebs;
+const char *g_kernel_cmdline;
+
+/* Locations of runtime offsets */
+void *g_rtmem_base;
+void *g_image_base;
+uint64_t g_image_size;
+void *g_text_base;
+uint64_t g_text_size;
+void *g_bss_base;
+uint64_t g_bss_size;
+
+void efi_cfg_init(void);
+efi_file_t *efi_get_configs(void);
+void efi_cfg_pre_parse(efi_file_t *config);
+char *efi_cfg_get_value(int index, const char *section,
+ const char *item);
+
+bool efi_split_kernel_line(void);
+bool efi_cfg_copy_tboot_path(const wchar_t *file_path);
+
+const efi_file_t *efi_get_platform_sinit(void);
+const efi_file_t *efi_get_platform_racm(void);
+const efi_file_t *efi_get_lcp(void);
+void efi_store_files(const efi_file_t *platform_sinit,
+ const efi_file_t *platform_racm,
+ const efi_file_t *lcp);
+
+const efi_file_t *efi_get_xen(void);
+const efi_file_t *efi_get_kernel(void);
+const efi_file_t *efi_get_ramdisk(void);
+const void *efi_get_memory_map(uint64_t *size_out, uint64_t *size_desc_out);
+uint64_t efi_get_xen_post_launch_cb(void);
+
+void efi_store_xen_info(void *base, uint64_t size);
+bool efi_store_xen_tboot_data(efi_xen_tboot_data_t *xtd);
+
+#endif /* __EFI_CONFIG_H__ */
diff --git a/tboot/include/eficore.h b/tboot/include/eficore.h
new file mode 100644
index 0000000..bea8694
--- /dev/null
+++ b/tboot/include/eficore.h
@@ -0,0 +1,134 @@
+/*
+ * eficore.h: EFI core support definitions.
+ *
+ * Copyright (c) 2017 Assured Information Security.
+ *
+ * Ross Philipson <philipsonr@ainfosec.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __EFICORE_H__
+#define __EFICORE_H__
+
+#define EFI_EARLY_PRINTK
+
+/* TODO debug only stuffs */
+#define EFI_DEBUG
+
+/* Shared RT variable between TBOOT and Xen */
+#define EFI_TBOOT_XEN_GUID \
+ { 0xf112e6cb, 0xce01, 0x4573, {0xa0, 0x52, 0xfb, 0xdb, 0x6c, 0xc0, 0xc7, 0xcb} }
+
+#define EFI_TBOOT_XEN_REV 1
+#define EFI_TBOOT_XEN_NAME L"TbootXenVar"
+
+/* Un-extern these that are defined in the GNU-EFI headers */
+EFI_SYSTEM_TABLE *ST;
+EFI_BOOT_SERVICES *BS;
+EFI_RUNTIME_SERVICES *RT;
+
+EFI_GUID EfiGlobalVariable;
+EFI_GUID NullGuid;
+EFI_GUID UnknownDevice;
+EFI_GUID DevicePathProtocol;
+EFI_GUID LoadedImageProtocol;
+EFI_GUID FileSystemProtocol;
+EFI_GUID GenericFileInfo;
+EFI_GUID AcpiTableGuid;
+EFI_GUID Acpi20TableGuid;
+EFI_GUID SMBIOSTableGuid;
+EFI_GUID TbootXenGuid;
+
+typedef void (*post_launch_t)(void *ets);
+
+typedef struct __packed efi_xen_tboot_data {
+ void *kernel;
+ uint64_t kernel_size;
+ void *ramdisk;
+ uint64_t ramdisk_size;
+ void *memory_map;
+ uint64_t memory_map_size;
+ uint64_t memory_desc_size;
+ uint64_t post_launch_cb;
+} efi_xen_tboot_data_t;
+
+typedef void (*begin_launch_t)(efi_xen_tboot_data_t *xtd);
+
+typedef struct __packed efi_tboot_xen_var {
+ uint64_t revision;
+ const char *xen_config;
+ uint64_t xen_config_size;
+ uint64_t begin_launch_cb;
+} efi_tboot_xen_var_t;
+
+/* The following routines are available before and after EBS */
+
+void atow(wchar_t *dst, const char *src, uint64_t count);
+bool wtoa(char *dst, const wchar_t *src, uint64_t count);
+uint64_t wcslen(const wchar_t *str);
+
+uint8_t *efi_get_rsdp(void);
+
+void *efi_get_pe_section(const char *name, void *image_base,
+ uint64_t *size_out);
+
+void efi_shutdown_system(uint32_t shutdown_type);
+
+/* The following routines are only available after EBS */
+
+bool efi_scan_memory_map(void);
+bool efi_add_resmap_entry(uint64_t addr, uint64_t length);
+bool efi_get_ram_ranges(uint64_t *min_lo_ram, uint64_t *max_lo_ram,
+ uint64_t *min_hi_ram, uint64_t *max_hi_ram);
+
+/* The following routines are unavailable after EBS */
+
+wchar_t *atow_alloc(const char *src);
+char *wtoa_alloc(const wchar_t *src);
+
+wchar_t *atow_cat(const wchar_t *base, const char *tail);
+
+void efi_puts(const char *s, unsigned int count);
+
+EFI_DEVICE_PATH *efi_get_device_path(const wchar_t *path,
+ EFI_HANDLE parent);
+EFI_STATUS efi_device_path_to_text(EFI_DEVICE_PATH *dev_path,
+ wchar_t *path_out,
+ uint64_t count);
+EFI_FILE_INFO *efi_get_file_info(EFI_FILE *target_file,
+ EFI_MEMORY_TYPE mem_type);
+EFI_STATUS efi_read_file(EFI_FILE_IO_INTERFACE *file_system,
+ wchar_t *file_name,
+ EFI_MEMORY_TYPE mem_type,
+ uint64_t *size_out,
+ EFI_PHYSICAL_ADDRESS *addr_out);
+
+void efi_launch_kernel(void);
+
+#endif /* __EFICORE_H__ */
diff --git a/tboot/include/hash.h b/tboot/include/hash.h
new file mode 100644
index 0000000..9d961e7
--- /dev/null
+++ b/tboot/include/hash.h
@@ -0,0 +1,123 @@
+/*
+ * hash.h: definition of and support fns for tb_hash_t type
+ *
+ * Copyright (c) 2006-2007, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __HASH_H__
+#define __HASH_H__
+
+#define TB_HALG_SHA1_LG 0x0000 /* legacy define for SHA1 */
+#define TB_HALG_SHA1 0x0004
+#define TB_HALG_SHA256 0x000B
+#define TB_HALG_SM3 0x0012
+#define TB_HALG_SHA384 0x000C
+#define TB_HALG_SHA512 0x000D
+#define TB_HALG_NULL 0x0010
+
+#define SHA1_LENGTH 20
+#define SHA256_LENGTH 32
+#define SM3_LENGTH 32
+#define SHA384_LENGTH 48
+#define SHA512_LENGTH 64
+
+typedef uint8_t sha1_hash_t[SHA1_LENGTH];
+typedef uint8_t sha256_hash_t[SHA256_LENGTH];
+typedef uint8_t sm3_hash_t[SM3_LENGTH];
+typedef uint8_t sha384_hash_t[SHA384_LENGTH];
+typedef uint8_t sha512_hash_t[SHA512_LENGTH];
+
+typedef union {
+ uint8_t sha1[SHA1_LENGTH];
+ uint8_t sha256[SHA256_LENGTH];
+ uint8_t sm3[SM3_LENGTH];
+ uint8_t sha384[SHA384_LENGTH];
+} tb_hash_t;
+
+static inline const char *hash_alg_to_string(uint16_t hash_alg)
+{
+ if ( hash_alg == TB_HALG_SHA1 || hash_alg == TB_HALG_SHA1_LG )
+ return "TB_HALG_SHA1";
+ else if ( hash_alg == TB_HALG_SHA256 )
+ return "TB_HALG_SHA256";
+ else if ( hash_alg == TB_HALG_SM3 )
+ return "TB_HALG_SM3";
+ else if ( hash_alg == TB_HALG_SHA384 )
+ return "TB_HALG_SHA384";
+ else if ( hash_alg == TB_HALG_SHA512 )
+ return "TB_HALG_SHA512";
+ else {
+ static char buf[32];
+ snprintf(buf, sizeof(buf), "unsupported (%u)", hash_alg);
+ return buf;
+ }
+}
+
+static inline unsigned int get_hash_size(uint16_t hash_alg)
+{
+ if ( hash_alg == TB_HALG_SHA1 || hash_alg == TB_HALG_SHA1_LG )
+ return SHA1_LENGTH;
+ else if ( hash_alg == TB_HALG_SHA256 )
+ return SHA256_LENGTH;
+ else if ( hash_alg == TB_HALG_SM3 )
+ return SM3_LENGTH;
+ else if ( hash_alg == TB_HALG_SHA384 )
+ return SHA384_LENGTH;
+ else if ( hash_alg == TB_HALG_SHA512 )
+ return SHA512_LENGTH;
+ else
+ return 0;
+}
+
+bool are_hashes_equal(const tb_hash_t *hash1, const tb_hash_t *hash2,
+ uint16_t hash_alg);
+bool hash_buffer(const unsigned char* buf, size_t size, tb_hash_t *hash,
+ uint16_t hash_alg);
+bool extend_hash(tb_hash_t *hash1, const tb_hash_t *hash2,
+ uint16_t hash_alg);
+void print_hash(const tb_hash_t *hash, uint16_t hash_alg);
+void copy_hash(tb_hash_t *dest_hash, const tb_hash_t *src_hash,
+ uint16_t hash_alg);
+
+
+#endif /* __HASH_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/integrity.h b/tboot/include/integrity.h
new file mode 100644
index 0000000..1051e71
--- /dev/null
+++ b/tboot/include/integrity.h
@@ -0,0 +1,106 @@
+/*
+ * integrity.h: routines for memory integrity measurement &
+ * verification. Memory integrity is protected with tpm seal
+ *
+ * Copyright (c) 2007-2009, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _TBOOT_INTEGRITY_H_
+#define _TBOOT_INTEGRITY_H_
+
+#include <vmac.h>
+#include <hash.h>
+
+/*
+ * state that must be saved across S3 and will be sealed for integrity
+ * before extending PCRs and launching kernel
+ */
+#define MAX_VL_HASHES 32
+#define MAX_ALG_NUM 5
+
+typedef struct {
+ uint16_t alg;
+ tb_hash_t hash;
+} hash_entry_t;
+
+typedef struct {
+ uint32_t count;
+ hash_entry_t entries[MAX_ALG_NUM];
+} hash_list_t;
+
+typedef struct {
+ /* low and high memory regions to protect w/ VT-d PMRs */
+ uint64_t vtd_pmr_lo_base;
+ uint64_t vtd_pmr_lo_size;
+ uint64_t vtd_pmr_hi_base;
+ uint64_t vtd_pmr_hi_size;
+ /* VL policy at time of sealing */
+ tb_hash_t pol_hash;
+ /* verified launch measurements to be re-extended in DRTM PCRs
+ * a given PCR may have more than one hash and will get extended in the
+ * order it appears in the list */
+ uint8_t num_vl_entries;
+ struct {
+ uint8_t pcr;
+ hash_list_t hl;
+ } vl_entries[MAX_VL_HASHES];
+} pre_k_s3_state_t;
+
+/*
+ * state that must be saved across S3 and will be sealed for integrity
+ * just before entering S3 (after kernel shuts down)
+ */
+typedef struct {
+ uint64_t kernel_s3_resume_vector;
+ vmac_t kernel_integ;
+} post_k_s3_state_t;
+
+
+pre_k_s3_state_t g_pre_k_s3_state;
+post_k_s3_state_t g_post_k_s3_state;
+
+bool seal_pre_k_state(void);
+bool seal_post_k_state(void);
+bool verify_integrity(void);
+
+#endif /* _TBOOT_INTEGRITY_H_ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/io.h b/tboot/include/io.h
new file mode 100644
index 0000000..71ef0ad
--- /dev/null
+++ b/tboot/include/io.h
@@ -0,0 +1,91 @@
+/*-
+ * Copyright (c) 1993 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+/*
+ * Portions copyright (c) 2010, Intel Corporation
+ */
+
+#ifndef __IO_H__
+#define __IO_H__
+
+/* from:
+ * $FreeBSD: src/sys/i386/include/cpufunc.h,v 1.158 2010/01/01 20:55:11 obrien Exp $
+ */
+
+/* modified to use tboot's types */
+
+#define readb(va) (*(volatile uint8_t *) (va))
+#define readw(va) (*(volatile uint16_t *) (va))
+#define readl(va) (*(volatile uint32_t *) (va))
+
+#define writeb(va, d) (*(volatile uint8_t *) (va) = (d))
+#define writew(va, d) (*(volatile uint16_t *) (va) = (d))
+#define writel(va, d) (*(volatile uint32_t *) (va) = (d))
+
+static inline uint8_t inb(uint16_t port)
+{
+ uint8_t data;
+
+ __asm volatile("inb %w1, %0" : "=a" (data) : "Nd" (port));
+ return (data);
+}
+
+static inline uint16_t inw(uint16_t port)
+{
+ uint16_t data;
+
+ __asm volatile("inw %w1, %0" : "=a" (data) : "Nd" (port));
+ return (data);
+}
+
+static inline uint32_t inl(uint16_t port)
+{
+ uint32_t data;
+
+ __asm volatile("inl %w1, %0" : "=a" (data) : "Nd" (port));
+ return (data);
+}
+
+static inline void outb(uint16_t port, uint8_t data)
+{
+ __asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
+}
+
+static inline void outw(uint16_t port, uint16_t data)
+{
+ __asm volatile("outw %0, %w1" : : "a" (data), "Nd" (port));
+}
+
+static inline void outl(uint16_t port, uint32_t data)
+{
+ __asm volatile("outl %0, %w1" : : "a" (data), "Nd" (port));
+}
+
+
+#endif /* __IO_H__ */
diff --git a/tboot/include/lcp3.h b/tboot/include/lcp3.h
new file mode 100644
index 0000000..4c717fe
--- /dev/null
+++ b/tboot/include/lcp3.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2014 Intel Corporation. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name Intel Corporation nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __LCP_H__
+#define __LCP_H__
+
+#ifndef __packed
+#define __packed __attribute__ ((packed))
+#endif
+
+/*
+ * Version = 3.0 - new version format of LCP Policy. Major version
+ * is incremented since layout is incompatible with previous revision.
+ */
+
+/*--------- LCP UUID ------------*/
+#define LCP_POLICY_DATA_UUID {0xab0d1925, 0xeee7, 0x48eb, 0xa9fc, \
+ {0xb, 0xac, 0x5a, 0x26, 0x2d, 0xe}}
+
+/*--------- CUSTOM ELT UUID ------------*/
+#define LCP_CUSTOM_ELEMENT_TBOOT_UUID {0xc3930641, 0xe3cb, 0x4f40, 0x91d7, \
+ {0x27, 0xf8, 0xb9, 0xe2, 0x5c, 0x86}}
+
+/*--------- LCP FILE SIGNATURE ------------*/
+#define LCP_POLICY_DATA_FILE_SIGNATURE "Intel(R) TXT LCP_POLICY_DATA\0\0\0\0"
+
+/*--------- LCP Policy Type ------------*/
+#define LCP_POLTYPE_LIST 0
+#define LCP_POLTYPE_ANY 1
+
+
+#define LCP_DEFAULT_POLICY_VERSION 0x0300
+#define LCP_DEFAULT_POLICY_CONTROL 0x00
+
+#define LCP_MAX_LISTS 8
+
+
+/*--------- with LCP_POLICY version 2.0 ------------*/
+#define SHA1_LENGTH 20
+#define SHA256_LENGTH 32
+
+typedef union {
+ uint8_t sha1[SHA1_LENGTH];
+ uint8_t sha256[SHA256_LENGTH];
+} lcp_hash_t;
+
+#define LCP_POLSALG_NONE 0
+#define LCP_POLSALG_RSA_PKCS_15 1
+
+#define LCP_SIG_EXPONENT 65537
+
+typedef struct __packed {
+ uint16_t revocation_counter;
+ uint16_t pubkey_size;
+ uint8_t pubkey_value[0];
+ uint8_t sig_block[];
+} lcp_signature_t;
+
+/* set bit 0: override PS policy for this element type */
+#define DEFAULT_POL_ELT_CONTROL 0x0001
+typedef struct __packed {
+ uint32_t size;
+ uint32_t type;
+ uint32_t policy_elt_control;
+ uint8_t data[];
+} lcp_policy_element_t;
+
+#define LCP_POLELT_TYPE_CUSTOM 3
+typedef struct __packed {
+ uuid_t uuid;
+ uint8_t data[];
+} lcp_custom_element_t;
+
+#define LCP_DEFAULT_POLICY_LIST_VERSION 0x0200
+#define LCP_TPM12_POLICY_LIST_VERSION 0x0100
+#define LCP_TPM20_POLICY_LIST_VERSION 0x0200
+typedef struct __packed {
+ uint16_t version; /* = 1.0 */
+ uint8_t reserved;
+ uint8_t sig_alg;
+ uint32_t policy_elements_size;
+ lcp_policy_element_t policy_elements[];
+ /* optionally: */
+ /* lcp_signature_t sig; */
+} lcp_policy_list_t;
+
+#define LCP_FILE_SIG_LENGTH 32
+typedef struct __packed {
+ char file_signature[LCP_FILE_SIG_LENGTH];
+ uint8_t reserved[3];
+ uint8_t num_lists;
+ lcp_policy_list_t policy_lists[];
+} lcp_policy_data_t;
+
+#define LCP_DEFAULT_POLICY_VERSION_2 0x0202
+typedef struct __packed {
+ uint16_t version;
+ uint8_t hash_alg; /* one of LCP_POLHALG_* */
+ uint8_t policy_type; /* one of LCP_POLTYPE_* */
+ uint8_t sinit_min_version;
+ uint8_t reserved1;
+ uint16_t data_revocation_counters[LCP_MAX_LISTS];
+ uint32_t policy_control;
+ uint32_t reserved2[2];
+ lcp_hash_t policy_hash;
+} lcp_policy_t;
+
+
+/*--------- LCP_POLICY version 3.0 ------------*/
+#define TPM_ALG_SHA1 0x0004
+#define TPM_ALG_SHA256 0x000B
+#define TPM_ALG_SHA384 0x000C
+#define TPM_ALG_SHA512 0x000D
+#define TPM_ALG_NULL 0x0010
+#define TPM_ALG_SM3_256 0x0012
+
+#define TPM_ALG_RSASSA 0x0014
+#define TPM_ALG_ECDSA 0x0018
+#define TPM_ALG_SM2 0x001B
+
+#define SHA1_DIGEST_SIZE 20
+#define SHA256_DIGEST_SIZE 32
+#define SHA384_DIGEST_SIZE 48
+#define SHA512_DIGEST_SIZE 64
+#define SM3_256_DIGEST_SIZE 32
+
+typedef union {
+ uint8_t sha1[SHA1_DIGEST_SIZE];
+ uint8_t sha256[SHA256_DIGEST_SIZE];
+ uint8_t sha384[SHA384_DIGEST_SIZE];
+ uint8_t sha512[SHA512_DIGEST_SIZE];
+ uint8_t sm3[SM3_256_DIGEST_SIZE];
+} lcp_hash_t2;
+
+typedef struct __packed {
+ uint16_t hash_alg;
+ uint8_t size_of_select;
+ uint8_t pcr_select[];
+} tpms_pcr_selection_t;
+
+typedef struct __packed {
+ uint32_t count;
+ tpms_pcr_selection_t pcr_selections;
+} tpml_pcr_selection_t;
+
+typedef struct __packed {
+ uint16_t size;
+ uint8_t buffer[];
+} tpm2b_digest_t;
+
+typedef struct __packed {
+ tpml_pcr_selection_t pcr_selection;
+ tpm2b_digest_t pcr_digest;
+} tpms_quote_info_t;
+
+#define LCP_POLELT_TYPE_MLE2 0x10
+typedef struct __packed {
+ uint8_t sinit_min_version;
+ uint8_t reserved;
+ uint16_t hash_alg;
+ uint16_t num_hashes;
+ lcp_hash_t2 hashes[];
+} lcp_mle_element_t2;
+
+#define LCP_POLELT_TYPE_PCONF2 0x11
+typedef struct __packed {
+ uint16_t hash_alg;
+ uint16_t num_pcr_infos;
+ tpms_quote_info_t prc_infos[];
+} lcp_pconf_element_t2;
+
+#define LCP_POLELT_TYPE_SBIOS2 0x12
+typedef struct __packed {
+ uint16_t hash_alg;
+ uint8_t reserved1[2];
+ lcp_hash_t2 fallback_hash;
+ uint16_t reserved2;
+ uint16_t num_hashes;
+ lcp_hash_t2 hashes[];
+} lcp_sbios_element_t2;
+
+#define LCP_POLELT_TYPE_CUSTOM2 0x13
+typedef struct __packed {
+ uuid_t uuid;
+ uint8_t data[];
+} lcp_custom_element_t2;
+
+#define LCP_POLELT_TYPE_STM2 0x14
+typedef struct __packed {
+ uint16_t hash_alg;
+ uint16_t num_hashes;
+ lcp_hash_t2 hashes[];
+} lcp_stm_element_t2;
+
+typedef struct __packed {
+ uint16_t version; /* = 3.0 */
+ uint16_t hash_alg; /* one of LCP_POLHALG_* */
+ uint8_t policy_type; /* one of LCP_POLTYPE_* */
+ uint8_t sinit_min_version;
+ uint16_t data_revocation_counters[LCP_MAX_LISTS];
+ uint32_t policy_control;
+ uint8_t max_sinit_min_ver; /* Defined for PO only. Reserved for PS */
+ uint8_t max_biosac_min_ver; /* Defined for PO only. Reserved for PS */
+ uint16_t lcp_hash_alg_mask; /* Mask of approved algorithms for LCP evaluation */
+ uint32_t lcp_sign_alg_mask; /* Mask of approved signature algorithms for LCP evaluation */
+ uint16_t aux_hash_alg_mask; /* Approved algorithm for auto - promotion hash */
+ uint16_t reserved2;
+ lcp_hash_t2 policy_hash;
+} lcp_policy_t2;
+
+typedef struct __packed {
+ uint16_t revocation_counter;
+ uint16_t pubkey_size;
+ uint8_t pubkey_value[0];
+ uint8_t sig_block[];
+} lcp_rsa_signature_t;
+
+typedef struct __packed {
+ uint16_t revocation_counter;
+ uint16_t pubkey_size;
+ uint32_t reserved;
+ uint8_t qx[0];
+ uint8_t qy[0];
+ uint8_t r[0];
+ uint8_t s[0];
+} lcp_ecc_signature_t;
+
+typedef union __packed {
+ lcp_rsa_signature_t rsa_signature;
+ lcp_ecc_signature_t ecc_signature;
+} lcp_signature_t2;
+
+typedef struct __packed {
+ uint16_t version; /* = 2.0 */
+ uint16_t sig_alg;
+ uint32_t policy_elements_size;
+ lcp_policy_element_t policy_elements[];
+//#if (sig_alg != TPM_ALG_NULL)
+// lcp_signature_t sig;
+//#endif
+} lcp_policy_list_t2;
+
+typedef union __packed {
+ lcp_policy_list_t tpm12_policy_list;
+ lcp_policy_list_t2 tpm20_policy_list;
+} lcp_list_t;
+
+typedef struct __packed {
+ char file_signature[32];
+ uint8_t reserved[3];
+ uint8_t num_lists;
+ lcp_list_t policy_lists[];
+} lcp_policy_data_t2;
+
+#endif /* __LCP_H__ */
diff --git a/tboot/include/lcp3_hlp.h b/tboot/include/lcp3_hlp.h
new file mode 100644
index 0000000..92061e4
--- /dev/null
+++ b/tboot/include/lcp3_hlp.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2014 Intel Corporation. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name Intel Corporation nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TXT_LCP2_HELPER_H__
+#define __TXT_LCP2_HELPER_H__
+
+static inline lcp_signature_t *get_tpm12_signature(const lcp_policy_list_t *pollist)
+{
+ if ( pollist == NULL )
+ return NULL;
+
+ if ( pollist->sig_alg != LCP_POLSALG_RSA_PKCS_15 )
+ return NULL;
+
+ return (lcp_signature_t *)((const void *)&pollist->policy_elements +
+ pollist->policy_elements_size);
+}
+
+static inline size_t get_tpm12_signature_size(const lcp_signature_t *sig)
+{
+ if ( sig == NULL )
+ return 0;
+
+ return offsetof(lcp_signature_t, pubkey_value) + 2*sig->pubkey_size;
+}
+
+static inline size_t get_tpm12_policy_list_size(const lcp_policy_list_t *pollist)
+{
+ size_t size = 0;
+
+ if ( pollist == NULL )
+ return 0;
+
+ size = offsetof(lcp_policy_list_t, policy_elements) +
+ pollist->policy_elements_size;
+
+ /* add sig size */
+ if ( pollist->sig_alg == LCP_POLSALG_RSA_PKCS_15 )
+ size += get_tpm12_signature_size(get_tpm12_signature(pollist));
+
+ return size;
+}
+
+static inline lcp_signature_t2 *get_tpm20_signature(const lcp_policy_list_t2 *pollist)
+{
+ if ( pollist == NULL || pollist->sig_alg == TPM_ALG_NULL )
+ return NULL;
+
+ return (lcp_signature_t2 *)((const void *)&pollist->policy_elements +
+ pollist->policy_elements_size);
+}
+
+static inline size_t get_tpm20_signature_size(const lcp_signature_t2 *sig,
+ const uint16_t sig_alg)
+{
+ if ( sig == NULL )
+ return 0;
+
+ if ( sig_alg == TPM_ALG_RSASSA)
+ return offsetof(lcp_rsa_signature_t, pubkey_value) +
+ 2*sig->rsa_signature.pubkey_size;
+ else if ( sig_alg == TPM_ALG_ECDSA)
+ return offsetof(lcp_ecc_signature_t, qx) +
+ 2*sig->ecc_signature.pubkey_size;
+
+ return 0;
+}
+
+static inline size_t get_tpm20_policy_list_size(const lcp_policy_list_t2 *pollist)
+{
+ size_t size = 0;
+
+ if ( pollist == NULL )
+ return 0;
+
+ size = offsetof(lcp_policy_list_t2, policy_elements) +
+ pollist->policy_elements_size;
+
+ /* add sig size */
+ if ( pollist->sig_alg == TPM_ALG_RSASSA ||
+ pollist->sig_alg == TPM_ALG_ECDSA ||
+ pollist->sig_alg == TPM_ALG_SM2 )
+ size += get_tpm20_signature_size(get_tpm20_signature(pollist),
+ pollist->sig_alg);
+
+ return size;
+}
+
+
+#endif /* __TXT_LCP3_HELPER_H__ */
diff --git a/tboot/include/misc.h b/tboot/include/misc.h
new file mode 100644
index 0000000..6c118c0
--- /dev/null
+++ b/tboot/include/misc.h
@@ -0,0 +1,95 @@
+/*
+ * misc.h: miscellaneous support fns
+ *
+ * Copyright (c) 2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MISC_H__
+#define __MISC_H__
+
+void print_hex(const char * buf, const void * prtptr, size_t size);
+
+void print_system_values(void);
+
+void print_test_chars(void);
+
+bool test_virt_to_phys(uint64_t vaddr);
+void dump_page_tables(void);
+
+void delay(int millisecs);
+
+/*
+ * These three "plus overflow" functions take a "x" value
+ * and add the "y" value to it and if the two values are
+ * greater than the size of the variable type, they will
+ * overflow the type and end up with a smaller value and
+ * return TRUE - that they did overflow. i.e.
+ * x + y <= variable type maximum.
+ */
+static inline bool plus_overflow_u64(uint64_t x, uint64_t y)
+{
+ return ((((uint64_t)(~0)) - x) < y);
+}
+
+static inline bool plus_overflow_u32(uint32_t x, uint32_t y)
+{
+ return ((((uint32_t)(~0)) - x) < y);
+}
+
+/*
+ * This checks to see if two numbers multiplied together are larger
+ * than the type that they are. Returns TRUE if OVERFLOWING.
+ * If the first parameter "x" is greater than zero and
+ * if that is true, that the largest possible value 0xFFFFFFFF / "x"
+ * is less than the second parameter "y". If "y" is zero then
+ * it will also fail because no unsigned number is less than zero.
+ */
+static inline bool multiply_overflow_u32(uint32_t x, uint32_t y)
+{
+ return (x > 0) ? ((((uint32_t)(~0))/x) < y) : false;
+}
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+#define AP_WAKE_TRIGGER_DEF 0xffffffff
+
+#endif /* __MISC_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/mle.h b/tboot/include/mle.h
new file mode 100644
index 0000000..c0d7386
--- /dev/null
+++ b/tboot/include/mle.h
@@ -0,0 +1,96 @@
+/*
+ * mle.h: Intel(r) TXT MLE header definition
+ *
+ * Copyright (c) 2003-2008, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MLE_H__
+#define __MLE_H__
+
+/*
+ * SINIT/MLE capabilities
+ */
+typedef union {
+ uint32_t _raw;
+ struct {
+ uint32_t rlp_wake_getsec : 1;
+ uint32_t rlp_wake_monitor : 1;
+ uint32_t ecx_pgtbl : 1;
+ uint32_t stm : 1;
+ uint32_t pcr_map_no_legacy : 1;
+ uint32_t pcr_map_da : 1;
+ uint32_t platform_type : 2;
+ uint32_t max_phy_addr : 1;
+ uint32_t reserved1 : 23;
+ };
+} txt_caps_t;
+
+
+/*
+ * MLE header structure
+ * describes an MLE for SINIT and OS/loader SW
+ */
+typedef struct {
+ uuid_t uuid;
+ uint32_t length;
+ uint32_t version;
+ uint32_t entry_point;
+ uint32_t first_valid_page;
+ uint32_t mle_start_off;
+ uint32_t mle_end_off;
+ txt_caps_t capabilities;
+ uint32_t cmdline_start_off;
+ uint32_t cmdline_end_off;
+} mle_hdr_t;
+
+#define MLE_HDR_UUID {0x9082ac5a, 0x476f, 0x74a7, 0x5c0f, \
+ {0x55, 0xa2, 0xcb, 0x51, 0xb6, 0x42}}
+
+/*
+ * values supported by current version of tboot
+ */
+#define MLE_HDR_VER 0x00020001 /* 2.1 */
+#define MLE_HDR_CAPS 0x00000027 /* rlp_wake_{getsec, monitor} = 1,
+ ecx_pgtbl = 1, nolg = 0, da = 1 */
+
+#endif /* __MLE_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/msr.h b/tboot/include/msr.h
new file mode 100644
index 0000000..70f1a32
--- /dev/null
+++ b/tboot/include/msr.h
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 1993 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+/*
+ * Portions copyright (c) 2010-2011, Intel Corporation
+ */
+
+
+#ifndef __MSR_H__
+#define __MSR_H__
+
+/* N.B. see processor.h, rd/wrmsr got moved and are not implemented as inline
+ * asm any longer.
+ */
+
+/*
+ * from: @(#)specialreg.h 7.1 (Berkeley) 5/9/91
+ * $FreeBSD: src/sys/i386/include/specialreg.h,v 1.53.2.1.2.2 2009/11/06 17:09:04 attilio Exp $
+ */
+
+#define MSR_IA32_PLATFORM_ID 0x017
+#define MSR_APICBASE 0x01b
+#define MSR_IA32_FEATURE_CONTROL 0x03a
+#define MSR_IA32_SMM_MONITOR_CTL 0x09b
+#define MSR_MTRRcap 0x0fe
+#define MSR_MCG_CAP 0x179
+#define MSR_MCG_STATUS 0x17a
+#define MSR_IA32_MISC_ENABLE 0x1a0
+#define MSR_IA32_MISC_ENABLE_MONITOR_FSM (1<<18)
+#define MSR_MTRRdefType 0x2ff
+#define MSR_MC0_STATUS 0x401
+#define MSR_IA32_VMX_BASIC_MSR 0x480
+#define MSR_IA32_VMX_PINBASED_CTLS_MSR 0x481
+#define MSR_IA32_VMX_PROCBASED_CTLS_MSR 0x482
+#define MSR_IA32_VMX_EXIT_CTLS_MSR 0x483
+#define MSR_IA32_VMX_ENTRY_CTLS_MSR 0x484
+#define MSR_IA32_SE_SVN_STATUS 0x500
+/*
+ * Constants related to MSR's.
+ */
+#define APICBASE_BSP 0x00000100
+
+#define MSR_IA32_SMM_MONITOR_CTL_VALID 1
+#define MSR_IA32_SMM_MONITOR_CTL_MSEG_BASE(x) (x>>12)
+
+/* MSRs & bits used for VMX enabling */
+#define IA32_FEATURE_CONTROL_MSR_LOCK 0x1
+#define IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_IN_SMX 0x2
+#define IA32_FEATURE_CONTROL_MSR_SENTER_PARAM_CTL 0x7f00
+#define IA32_FEATURE_CONTROL_MSR_ENABLE_SENTER 0x8000
+
+/* AMD64 MSR's */
+#define MSR_EFER 0xc0000080 /* extended features */
+
+/* EFER bits */
+#define _EFER_LME 8 /* Long mode enable */
+#define _EFER_LMA 10 /* Long mode active */
+
+#define MTRR_TYPE_UNCACHABLE 0
+#define MTRR_TYPE_WRTHROUGH 4
+#define MTRR_TYPE_WRBACK 6
+
+
+#endif /* __MSR_H__ */
diff --git a/tboot/include/mutex.h b/tboot/include/mutex.h
new file mode 100644
index 0000000..d61bd99
--- /dev/null
+++ b/tboot/include/mutex.h
@@ -0,0 +1,58 @@
+/* $OpenBSD: mutex.h,v 1.6 2009/04/27 21:48:56 kettenis Exp $ */
+/*
+ * Copyright (c) 2004 Artur Grabowski <art@openbsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Portions copyright (c) 2010, Intel Corporation
+ */
+
+#ifndef __MUTEX_H__
+#define __MUTEX_H__
+
+/*
+ * A mutex is:
+ * - owned by a cpu.
+ * - non-recursive.
+ * - spinning.
+ * - not providing mutual exclusion between processes, only cpus.
+ * - providing interrupt blocking when necessary.
+ *
+ * Different mutexes can be nested, but not interleaved. This is ok:
+ * "mtx_enter(foo); mtx_enter(bar); mtx_leave(bar); mtx_leave(foo);"
+ * This is _not_ ok:
+ * "mtx_enter(foo); mtx_enter(bar); mtx_leave(foo); mtx_leave(bar);"
+ */
+
+struct mutex {
+ __volatile__ uint64_t mtx_lock;
+};
+
+/*
+ * Some architectures need to do magic for the ipl, so they need a macro.
+ */
+void mtx_init(struct mutex *);
+void mtx_enter(struct mutex *);
+void mtx_leave(struct mutex *);
+
+#endif /* __MUTEX_H__ */
diff --git a/tboot/include/page.h b/tboot/include/page.h
new file mode 100644
index 0000000..b0588f6
--- /dev/null
+++ b/tboot/include/page.h
@@ -0,0 +1,66 @@
+/*
+ * page.h: definitions for page size/mask/shift/etc.
+ *
+ * Copyright (c) 2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __PAGE_H__
+#define __PAGE_H__
+
+/* From http://fxr.watson.org/fxr/source/i386/include/param.h */
+#define PAGE_SHIFT 12 /* LOG2(PAGE_SIZE) */
+#define PAGE_SIZE (1 << PAGE_SHIFT) /* bytes/page */
+/* PAGE_MASK is used to pass bits 12 and above. */
+#define PAGE_MASK (~(PAGE_SIZE-1))
+
+/* This is used to address the L2's 4MB pages */
+/* From figure 4-3 of IA64/IA32 Arch SDM vol 3A */
+#define FOURMB_PAGE_SHIFT 22
+
+/* macros to rounds things up/down to a page/pfn */
+#define PAGE_UP(p) (((unsigned long long)(p) + PAGE_SIZE- 1) & PAGE_MASK)
+#define PAGE_DOWN(p) ((unsigned long long)(p) & PAGE_MASK)
+#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+
+#endif /* __PAGE_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/paging.h b/tboot/include/paging.h
new file mode 100644
index 0000000..7896824
--- /dev/null
+++ b/tboot/include/paging.h
@@ -0,0 +1,122 @@
+/*
+ * paging.h: Definitions for paging in tboot (PAE+PSE)
+ *
+ * Copyright (c) 2006-2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __PAGING_H__
+#define __PAGING_H__
+
+/* direct map starts from 0, size 64M */
+#define DIRECTMAP_VIRT_START 0
+#define DIRECTMAP_VIRT_ORDER 26
+#define DIRECTMAP_VIRT_SIZE (1UL << DIRECTMAP_VIRT_ORDER)
+#define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + DIRECTMAP_VIRT_SIZE)
+
+/* MAC window starts from 0x80000000, size 1G */
+#define MAC_VIRT_START 0x80000000
+#define MAC_VIRT_ORDER 30
+#define MAC_VIRT_SIZE (1UL << MAC_VIRT_ORDER)
+#define MAC_VIRT_END (MAC_VIRT_START + MAC_VIRT_SIZE)
+
+/* PAE with 2-Mbyte Pages */
+#define TB_PAGETABLE_ORDER 9
+#define TB_L1_PAGETABLE_ENTRIES (1 << TB_PAGETABLE_ORDER)
+#define TB_L2_PAGETABLE_ENTRIES (1 << TB_PAGETABLE_ORDER)
+
+#define TB_L1_PAGETABLE_SHIFT 21
+#define TB_L2_PAGETABLE_SHIFT 30
+
+#define MAC_PAGE_SIZE (1UL << TB_L1_PAGETABLE_SHIFT)
+#define MAC_PAGE_MASK (~(MAC_PAGE_SIZE - 1))
+
+#define _PAGE_PRESENT 0x01
+#define _PAGE_RW 0x02
+#define _PAGE_SIZE 0x80
+
+
+#define MAKE_TB_PDE(paddr) \
+ (((uint64_t)(paddr) & ~0x00000000001FFFFF) | _PAGE_PRESENT \
+ | _PAGE_RW | _PAGE_SIZE)
+#define MAKE_TB_PDPTE(paddr) \
+ (((uint64_t)(paddr) & ~0x0000000000000FFF) | _PAGE_PRESENT)
+
+/* Given a virtual address, get an entry offset into a page table. */
+#define pd_table_offset(a) \
+ (((a) >> TB_L1_PAGETABLE_SHIFT) & (TB_L1_PAGETABLE_ENTRIES - 1))
+#define pdptr_table_offset(a) \
+ (((a) >> TB_L2_PAGETABLE_SHIFT) & (TB_L2_PAGETABLE_ENTRIES - 1))
+
+/* PAE: 52 bit physical address */
+#define PADDR_BIT 52
+#define PADDR_MASK ((1ULL << PADDR_BIT) - 1)
+
+/*
+ * PDE entry
+ * 31-bit pfn = pde[51:21]
+ * 13-bit flags = pde[12:0]
+ */
+#define PDE_FLAG_BIT 13
+#define PDE_FLAG_MASK ((1UL << PDE_FLAG_BIT) - 1)
+#define PDE_PADDR_MASK (PADDR_MASK & (~PDE_FLAG_MASK))
+#define get_pde_flags(pde) ((int)(pde) & PDE_FLAG_MASK)
+#define get_pde_paddr(pde) ((pde) & PDE_PADDR_MASK)
+
+/*
+ * PDPTE entry
+ * 40-bit pfn = pdptre[51:12]
+ * 12-bit flags = pdptre[11:0]
+ */
+#define PDPTE_FLAG_BIT 12
+#define PDPTE_FLAG_MASK ((1UL << PDPTE_FLAG_BIT) - 1)
+#define PDPTE_PADDR_MASK (PADDR_MASK & (~PDPTE_FLAG_MASK))
+#define get_pdptre_flags(pdptre) ((int)(pdptre) & PDPTE_FLAG_MASK)
+#define get_pdptre_paddr(pdptre) ((pdptre) & PDPTE_PADDR_MASK)
+
+void map_pages_to_tboot(unsigned long vstart,
+ unsigned long pfn,
+ unsigned long nr_pfns);
+void destroy_tboot_mapping(unsigned long vstart, unsigned long vend);
+bool enable_paging(void);
+bool disable_paging(void);
+
+#endif /* __PAGING_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/pci_cfgreg.h b/tboot/include/pci_cfgreg.h
new file mode 100644
index 0000000..d231e86
--- /dev/null
+++ b/tboot/include/pci_cfgreg.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/i386/include/pci_cfgreg.h,v 1.15.2.1.4.1 2010/06/14 02:09:06 kensmith Exp $
+ * $FreeBSD: src/sys/dev/pci/pcireg.h,v 1.72.2.4.2.1 2010/06/14 02:09:06 kensmith Exp $
+ */
+/*
+ * Portions copyright (c) 2010, Intel Corporation
+ */
+
+#ifndef __PCI_CFGREG_H__
+#define __PCI_CFGREG_H__
+
+#define PCI_BUSMAX 255 /* highest supported bus number */
+#define PCI_SLOTMAX 31 /* highest supported slot number */
+#define PCI_FUNCMAX 7 /* highest supported function number */
+#define PCI_REGMAX 255 /* highest supported config register addr. */
+
+#define CONF1_ADDR_PORT 0x0cf8
+#define CONF1_DATA_PORT 0x0cfc
+
+#define CONF1_ENABLE 0x80000000ul
+#define CONF1_ENABLE_CHK 0x80000000ul
+#define CONF1_ENABLE_MSK 0x7f000000ul
+#define CONF1_ENABLE_CHK1 0xff000001ul
+#define CONF1_ENABLE_MSK1 0x80000001ul
+#define CONF1_ENABLE_RES1 0x80000000ul
+
+#define CONF2_ENABLE_PORT 0x0cf8
+#define CONF2_FORWARD_PORT 0x0cfa
+
+#define CONF2_ENABLE_CHK 0x0e
+#define CONF2_ENABLE_RES 0x0e
+
+#define PCIR_COMMAND 0x04
+#define PCIR_BARS 0x10
+#define PCIR_IOBASEL_1 0x1c
+
+int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes);
+void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes);
+
+#endif /* __PCI_CFGREG_H__ */
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/printk.h b/tboot/include/printk.h
new file mode 100644
index 0000000..d72d2f2
--- /dev/null
+++ b/tboot/include/printk.h
@@ -0,0 +1,79 @@
+/*
+ * printk.h: printk to serial for very early boot stages
+ *
+ * Copyright (c) 2006-2010, Intel Corporation
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __PRINTK_H__
+#define __PRINTK_H__
+
+#include <com.h>
+#include <vga.h>
+
+#define TBOOT_LOGBUF_SIZE 256
+
+#define TBOOT_LOG_LEVEL_NONE 0x00
+#define TBOOT_LOG_LEVEL_ERR 0x01
+#define TBOOT_LOG_LEVEL_WARN 0x02
+#define TBOOT_LOG_LEVEL_INFO 0x04
+#define TBOOT_LOG_LEVEL_DETA 0x08
+#define TBOOT_LOG_LEVEL_ALL 0xFF
+
+#define TBOOT_LOG_TARGET_NONE 0x00
+#define TBOOT_LOG_TARGET_VGA 0x01
+#define TBOOT_LOG_TARGET_SERIAL 0x02
+#define TBOOT_LOG_TARGET_MEMORY 0x04
+#define TBOOT_LOG_TARGET_EFI 0x10
+
+uint8_t g_log_level;
+uint8_t g_log_targets;
+uint8_t g_vga_delay;
+serial_port_t g_com_port;
+
+#define serial_init() comc_init()
+#define serial_write(s, n) comc_puts(s, n)
+
+#define vga_write(s,n) vga_puts(s, n)
+
+#define efi_write(s,n) efi_puts(s, n)
+
+typedef enum {
+ INIT_EARLY_EFI,
+ INIT_PRE_LAUNCH,
+ INIT_POST_EBS,
+ INIT_POST_LAUNCH
+} printk_init_t;
+
+void printk_init(printk_init_t init_type);
+void printk(const char *fmt, ...)
+ __attribute__ ((format (printf, 1, 2)));
+
+#endif
diff --git a/tboot/include/processor.h b/tboot/include/processor.h
new file mode 100644
index 0000000..83b9fe4
--- /dev/null
+++ b/tboot/include/processor.h
@@ -0,0 +1,340 @@
+/* Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+/*
+ * Portions copyright (c) 2010, Intel Corporation
+ */
+
+#ifndef __PROCESSOR_H__
+#define __PROCESSOR_H__
+
+/* from: @(#)specialreg.h 7.1 (Berkeley) 5/9/91
+ * $FreeBSD: stable/8/sys/i386/include/specialreg.h 198989 2009-11-06 15:24:48Z attilio $
+ */
+
+/*
+ * EFLAGS bits
+ */
+#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */
+#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */
+#define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */
+#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */
+#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */
+#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */
+#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */
+#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */
+#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */
+#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */
+#define X86_EFLAGS_NT 0x00004000 /* Nested Task */
+#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */
+#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */
+#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */
+#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */
+#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */
+#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */
+
+/*
+ * Bits in 386 special registers:
+ */
+#define CR0_PE 0x00000001 /* Protected mode Enable */
+#define CR0_MP 0x00000002 /* "Math" (fpu) Present */
+#define CR0_EM 0x00000004 /* EMulate FPU instructions. (trap ESC only) */
+#define CR0_TS 0x00000008 /* Task Switched (if MP, trap ESC and WAIT) */
+#define CR0_ET 0x00000010 /* Extension type */
+#define CR0_PG 0x80000000 /* PaGing enable */
+
+/*
+ * Bits in 486 special registers:
+ */
+#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */
+#define CR0_WP 0x00010000 /* Write Protect (honor page protect in all modes) */
+#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */
+#define CR0_NW 0x20000000 /* Not Write-through */
+#define CR0_CD 0x40000000 /* Cache Disable */
+
+/*
+ * Bits in PPro special registers
+ */
+#define CR4_VME 0x00000001 /* Virtual 8086 mode extensions */
+#define CR4_PVI 0x00000002 /* Protected-mode virtual interrupts */
+#define CR4_TSD 0x00000004 /* Time stamp disable */
+#define CR4_DE 0x00000008 /* Debugging extensions */
+#define CR4_PSE 0x00000010 /* Page size extensions */
+#define CR4_PAE 0x00000020 /* Physical address extension */
+#define CR4_MCE 0x00000040 /* Machine check enable */
+#define CR4_PGE 0x00000080 /* Page global enable */
+#define CR4_PCE 0x00000100 /* Performance monitoring counter enable */
+#define CR4_FXSR 0x00000200/* Fast FPU save/restore used by OS */
+#define CR4_XMM 0x00000400 /* enable SIMD/MMX2 to use except 16 */
+#define CR4_VMXE 0x00002000/* enable VMX */
+#define CR4_SMXE 0x00004000/* enable SMX */
+#define CR4_PCIDE 0x00020000/* enable PCID */
+
+#ifndef __ASSEMBLY__
+
+/* from:
+ * $FreeBSD: src/sys/i386/include/cpufunc.h,v 1.158 2010/01/01 20:55:11 obrien Exp $
+ */
+
+static inline void do_cpuid(unsigned int ax, uint32_t *p)
+{
+ __asm__ __volatile__ ("cpuid"
+ : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
+ : "0" (ax));
+}
+
+static inline void do_cpuid1(unsigned int ax, unsigned int cx, uint32_t *p)
+{
+ __asm__ __volatile__ ("cpuid"
+ : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
+ : "0" (ax), "c" (cx));
+}
+
+static always_inline uint32_t cpuid_eax(unsigned int op)
+{
+ /* eax: regs[0], ebx: regs[1], ecx: regs[2], edx: regs[3] */
+ uint32_t regs[4];
+
+ do_cpuid(op, regs);
+
+ return regs[0];
+}
+
+static always_inline uint32_t cpuid_ebx(unsigned int op)
+{
+ /* eax: regs[0], ebx: regs[1], ecx: regs[2], edx: regs[3] */
+ uint32_t regs[4];
+
+ do_cpuid(op, regs);
+
+ return regs[1];
+}
+
+static always_inline uint32_t cpuid_ebx1(unsigned int op1, unsigned int op2)
+{
+ /* eax: regs[0], ebx: regs[1], ecx: regs[2], edx: regs[3] */
+ uint32_t regs[4];
+
+ do_cpuid1(op1, op2, regs);
+
+ return regs[1];
+}
+static always_inline uint32_t cpuid_ecx(unsigned int op)
+{
+ /* eax: regs[0], ebx: regs[1], ecx: regs[2], edx: regs[3] */
+ uint32_t regs[4];
+
+ do_cpuid(op, regs);
+
+ return regs[2];
+}
+
+#define CPUID_X86_FEATURE_XMM3 (1<<0)
+#define CPUID_X86_FEATURE_VMX (1<<5)
+#define CPUID_X86_FEATURE_SMX (1<<6)
+
+/* Note, removed read/write ecx, not used */
+
+static inline unsigned long long read_cr0(void)
+{
+ unsigned long long data;
+ /* 64: movl -> movq */
+ __asm__ __volatile__ ("movq %%cr0,%0" : "=r" (data));
+ return (data);
+}
+
+static inline void write_cr0(unsigned long long data)
+{
+ /* 64: movl -> movq */
+ __asm__ __volatile__("movq %0,%%cr0" : : "r" (data));
+}
+
+static inline unsigned long long read_cr4(void)
+{
+ unsigned long long data;
+ /* 64: movl -> movq */
+ __asm__ __volatile__ ("movq %%cr4,%0" : "=r" (data));
+ return (data);
+}
+
+static inline void write_cr4(unsigned long long data)
+{
+ /* 64: movl -> movq */
+ __asm__ __volatile__ ("movq %0,%%cr4" : : "r" (data));
+}
+
+static inline unsigned long long read_cr3(void)
+{
+ unsigned long long data;
+ /* 64: movl -> movq */
+ __asm__ __volatile__ ("movq %%cr3,%0" : "=r" (data));
+ return (data);
+}
+
+static inline void write_cr3(unsigned long long data)
+{
+ /* 64: movl -> movq */
+ __asm__ __volatile__("movq %0,%%cr3" : : "r" (data) : "memory");
+}
+
+static inline uint64_t read_rflags(void)
+{
+ uint64_t rf;
+ /* 32: EFLAGS stuff __asm__ __volatile__ ("pushfl; popl %0" : "=r" (ef));*/
+ __asm__ __volatile__ ("pushfq; popq %0" : "=r" (rf));
+ return (rf);
+}
+
+static inline void write_rflags(uint64_t rf)
+{
+ /* 32: EFLAGS stuff __asm__ __volatile__ ("pushl %0; popfl" : : "r" (ef));*/
+ __asm__ __volatile__ ("pushq %0; popfq" : : "r" (rf));
+}
+
+static inline void disable_intr(void)
+{
+ __asm__ __volatile__ ("cli" : : : "memory");
+}
+
+static inline void enable_intr(void)
+{
+ __asm__ __volatile__ ("sti");
+}
+
+/* was ia32_pause() */
+static inline void cpu_relax(void)
+{
+ __asm__ __volatile__ ("pause");
+}
+
+static inline void halt(void)
+{
+ __asm__ __volatile__ ("hlt");
+}
+
+static inline unsigned int get_apicid(void)
+{
+ return cpuid_ebx(1) >> 24;
+}
+
+static inline void wbinvd(void)
+{
+ __asm__ __volatile__ ("wbinvd");
+}
+
+static inline uint32_t bsrl(uint32_t mask)
+{
+ uint32_t result;
+
+ /* 64: Ok to shift 32b mask */
+ __asm__ __volatile__ ("bsrl %1,%0" : "=r" (result) : "rm" (mask) : "cc");
+ return (result);
+}
+
+static inline int fls(int mask)
+{
+ return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
+}
+
+static always_inline void mb(void)
+{
+ /* 32: __asm__ __volatile__ ("lock;addl $0,0(%%esp)" : : : "memory"); */
+ __asm__ __volatile__ ("lock;addq $0,0(%%rsp)" : : : "memory");
+}
+
+static inline void cpu_monitor(const void *addr, int extensions, int hints)
+{
+ /* 64: a=rax, c=rcx, d=rdx ints are 32b into ecx, edx */
+ __asm __volatile__ ("monitor;" : :"a" (addr), "c" (extensions), "d"(hints));
+}
+
+static inline void cpu_mwait(int extensions, int hints)
+{
+ /* 64: a=rax, c=rcx ints are 32b into eax, ecx */
+ __asm __volatile__ ("mwait;" : :"a" (hints), "c" (extensions));
+}
+
+static inline void flush_tlb(void)
+{
+ __asm__ __volatile__ (
+ "movq %%cr3, %%rax\n"
+ "movq %%rax, %%cr3\n"
+ : : : "rax");
+}
+
+typedef struct __packed lmode_desc {
+ uint16_t limit;
+ uint64_t base;
+} lmode_desc_t;
+
+static inline void store_gdt(lmode_desc_t *gdt)
+{
+ __asm__ __volatile__("sgdt %0\n\t"
+ : "=m" (*gdt) : : "memory");
+}
+
+static inline void store_idt(lmode_desc_t *idt)
+{
+ __asm__ __volatile__("sidt %0\n\t"
+ : "=m" (*idt): : "memory");
+}
+
+#define lea_reference(i, o) __asm__ __volatile__ \
+ ("lea "#i"(%%rip), %%rax\n\t" : "=a" (o))
+
+#define mov_sel(r, o) __asm__ __volatile__ \
+ ("movw %%"#r"s, %0\n\t" : "=m" (o) : : "memory");
+
+/* In inline asm, these 3 use the A constraint to specify the EDX:EAX register
+ * pair. The inline assembler was getting the code badly wrong so the
+ * implementation of these moved to the assembly module (and renamed).
+ */
+uint64_t read_msr(uint32_t msr);
+void write_msr(uint32_t msr, uint64_t newval);
+uint64_t read_tsc(void);
+
+uint64_t get_rip(void);
+uint64_t bsp_stack_ref(void);
+
+#define rdmsr read_msr
+#define wrmsr write_msr
+#define rdtsc read_tsc
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __PROCESSOR_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/rijndael.h b/tboot/include/rijndael.h
new file mode 100644
index 0000000..2974602
--- /dev/null
+++ b/tboot/include/rijndael.h
@@ -0,0 +1,58 @@
+/* $OpenBSD: rijndael.h,v 1.13 2008/06/09 07:49:45 djm Exp $ */
+
+/**
+ * rijndael-alg-fst.h
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __RIJNDAEL_H
+#define __RIJNDAEL_H
+
+#define AES_MAXKEYBITS (256)
+#define AES_MAXKEYBYTES (AES_MAXKEYBITS/8)
+/* for 256-bit keys, fewer for less */
+#define AES_MAXROUNDS 14
+
+//typedef unsigned char u8;
+//typedef unsigned short u16;
+//typedef unsigned int u32;
+
+/* The structure for key information */
+typedef struct {
+ int enc_only; /* context contains only encrypt schedule */
+ int Nr; /* key-length-dependent number of rounds */
+ u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */
+ u32 dk[4*(AES_MAXROUNDS + 1)]; /* decrypt key schedule */
+} rijndael_ctx;
+
+int rijndael_set_key(rijndael_ctx *, const u_char *, int);
+int rijndael_set_key_enc_only(rijndael_ctx *, const u_char *, int);
+void rijndael_decrypt(rijndael_ctx *, const u_char *, u_char *);
+void rijndael_encrypt(rijndael_ctx *, const u_char *, u_char *);
+
+int rijndaelKeySetupEnc(unsigned int [], const unsigned char [], int);
+int rijndaelKeySetupDec(unsigned int [], const unsigned char [], int);
+void rijndaelEncrypt(const unsigned int [], int, const unsigned char [],
+ unsigned char []);
+
+#endif /* __RIJNDAEL_H */
diff --git a/tboot/include/sha1.h b/tboot/include/sha1.h
new file mode 100644
index 0000000..10d89df
--- /dev/null
+++ b/tboot/include/sha1.h
@@ -0,0 +1,77 @@
+/*$FreeBSD: src/sys/crypto/sha1.h,v 1.8.36.1.2.1 2009/10/25 01:10:29 kensmith Exp $ */
+/*$KAME: sha1.h,v 1.5 2000/03/27 04:36:23 sumikawa Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Portions copyright (c) 2010, Intel Corporation
+ */
+
+/*
+ * FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
+ * based on: http://csrc.nist.gov/fips/fip180-1.txt
+ * implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
+ */
+
+#ifndef __SHA1_H__
+#define __SHA1_H__
+
+struct sha1_ctxt {
+ union {
+ uint8_t b8[20];
+ uint32_t b32[5];
+ } h;
+ union {
+ uint8_t b8[8];
+ uint64_t b64[1];
+ } c;
+ union {
+ uint8_t b8[64];
+ uint32_t b32[16];
+ } m;
+ uint8_t count;
+};
+
+void sha1_init(struct sha1_ctxt *);
+void sha1_pad(struct sha1_ctxt *);
+void sha1_loop(struct sha1_ctxt *, const uint8_t *, size_t);
+void sha1_result(struct sha1_ctxt *, unsigned char *);
+#define SHA1_RESULTLEN (160/8)
+
+/* compatibilty with other SHA1 source codes */
+typedef struct sha1_ctxt SHA_CTX;
+#define SHA1_Init(x) sha1_init((x))
+#define SHA1_Update(x, y, z) sha1_loop((x), (y), (z))
+#define SHA1_Final(x, y) sha1_result((y), (x))
+#define SHA_DIGEST_LENGTH SHA1_RESULTLEN
+
+int sha1_buffer(const unsigned char *buffer, size_t len,
+ unsigned char md[SHA_DIGEST_LENGTH]);
+
+#endif /* __SHA1_H__ */
diff --git a/tboot/include/sha256.h b/tboot/include/sha256.h
new file mode 100644
index 0000000..2c3fc56
--- /dev/null
+++ b/tboot/include/sha256.h
@@ -0,0 +1,30 @@
+#ifndef __SHA256_H__
+#define __SHA256_H__
+
+#define STORE64H(x, y) \
+ { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \
+ (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \
+ (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \
+ (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); }
+
+#define STORE32H(x, y) \
+ { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \
+ (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); }
+
+#define LOAD32H(x, y) \
+ { x = ((unsigned long)((y)[0] & 255)<<24) | \
+ ((unsigned long)((y)[1] & 255)<<16) | \
+ ((unsigned long)((y)[2] & 255)<<8) | \
+ ((unsigned long)((y)[3] & 255)); }
+
+typedef struct {
+ u64 length;
+ u32 state[8], curlen;
+ unsigned char buf[64];
+}sha256_state;
+
+void sha256_buffer(const unsigned char *buffer, size_t len,
+ unsigned char hash[32]);
+
+#endif /* __SHA256_H__ */
+
diff --git a/tboot/include/string.h b/tboot/include/string.h
new file mode 100644
index 0000000..30b571b
--- /dev/null
+++ b/tboot/include/string.h
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)libkern.h 8.1 (Berkeley) 6/10/93
+ * $FreeBSD: src/sys/sys/libkern.h,v 1.60 2009/02/14 11:34:57 rrs Exp $
+ */
+/*
+ * Portions copyright (c) 2010, Intel Corporation
+ */
+
+#ifndef __STRING_H__
+#define __STRING_H__
+
+#include <stdarg.h>
+#include <types.h>
+
+int memcmp(const void *b1, const void *b2, size_t len);
+char *index(const char *, int);
+int strcmp(const char *, const char *);
+size_t strlen(const char *);
+int strncmp(const char *, const char *, size_t);
+char *strncpy(char * __restrict, const char * __restrict, size_t);
+void *memcpy(void *dst, const void *src, size_t len);
+int snprintf(char *buf, size_t size, const char *fmt, ...);
+int vscnprintf(char *buf, size_t size, const char *fmt, va_list ap);
+unsigned long strtoul(const char *nptr, char **endptr, int base);
+
+static inline void *memset(void *b, int c, size_t len)
+{
+ char *bb;
+
+ for (bb = (char *)b; len--; )
+ *bb++ = c;
+
+ return (b);
+}
+
+static inline void *memmove(void *dest, const void *src, size_t n)
+{
+ return memcpy(dest, src, n);
+}
+
+static __inline char *strchr(const char *p, int ch)
+{
+ return index(p, ch);
+}
+
+#endif /* __STRING_H__ */
diff --git a/tboot/include/tb_error.h b/tboot/include/tb_error.h
new file mode 100644
index 0000000..428fd51
--- /dev/null
+++ b/tboot/include/tb_error.h
@@ -0,0 +1,89 @@
+/*
+ * tb_error.h: error code definitions
+ *
+ * Copyright (c) 2006-2007, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TB_ERROR_H__
+#define __TB_ERROR_H__
+
+typedef enum {
+ TB_ERR_NONE = 0, /* succeed */
+ TB_ERR_FIXED = 1, /* previous error has been fixed */
+
+ TB_ERR_GENERIC, /* non-fatal generic error */
+
+ TB_ERR_TPM_NOT_READY, /* tpm not ready */
+ TB_ERR_SMX_NOT_SUPPORTED, /* smx not supported */
+ TB_ERR_VMX_NOT_SUPPORTED, /* vmx not supported */
+ TB_ERR_TXT_NOT_SUPPORTED, /* txt not supported */
+
+ TB_ERR_MODULE_VERIFICATION_FAILED, /* module failed to verify against
+ policy */
+ TB_ERR_MODULES_NOT_IN_POLICY, /* modules in mbi but not in
+ policy */
+ TB_ERR_POLICY_INVALID, /* policy is invalid */
+ TB_ERR_POLICY_NOT_PRESENT, /* no policy in TPM NV */
+
+ TB_ERR_SINIT_NOT_PRESENT, /* SINIT ACM not provided */
+ TB_ERR_ACMOD_VERIFY_FAILED, /* verifying AC module failed */
+
+ TB_ERR_POST_LAUNCH_VERIFICATION, /* verification of post-launch
+ failed */
+ TB_ERR_S3_INTEGRITY, /* creation or verification of
+ S3 integrity measurements
+ failed */
+
+ TB_ERR_FATAL, /* generic fatal error */
+ TB_ERR_NV_VERIFICATION_FAILED, /* NV failed to verify against
+ policy */
+ TB_ERR_MAX
+} tb_error_t;
+
+
+void print_tb_error_msg(tb_error_t error);
+bool read_tb_error_code(tb_error_t *error);
+bool write_tb_error_code(tb_error_t error);
+bool was_last_boot_error(void);
+
+
+#endif /* __TB_ERROR_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/tb_policy.h b/tboot/include/tb_policy.h
new file mode 100644
index 0000000..118a735
--- /dev/null
+++ b/tboot/include/tb_policy.h
@@ -0,0 +1,388 @@
+/*
+ * tb_policy.h: data structures, definitions, and helper fns for tboot
+ * verified launch policies
+ *
+ * Copyright (c) 2006-2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TB_POLICY_H__
+#define __TB_POLICY_H__
+
+/*
+ * policy types
+ */
+enum {
+ TB_POLTYPE_CONT_NON_FATAL, /* ignore all non-fatal errors and */
+ /* continue */
+ TB_POLTYPE_CONT_VERIFY_FAIL, /* ignore verification errors and */
+ /* halt otherwise */
+ TB_POLTYPE_HALT, /* halt on any errors */
+ TB_POLTYPE_MAX
+};
+
+/*
+ * policy hash types
+ */
+enum {
+ TB_HTYPE_ANY,
+ TB_HTYPE_IMAGE,
+};
+
+
+#define TB_POL_MAX_MOD_NUM 127 /* largest supported module number */
+#define TB_POL_MOD_NUM_ANY 129 /* matches any module number */
+ /* (should be last entry of modules) */
+#define TB_POL_MOD_NUM_NV 130 /* indicate this is a nv index entry */
+#define TB_POL_MOD_NUM_NV_RAW 131 /* a nv entry verified by raw content */
+
+#define TB_POL_MAX_PCR 23 /* largest supported PCR number */
+#define TB_POL_PCR_NONE 255 /* don't extend measurement into a PCR */
+
+
+/*
+ * policies
+ */
+
+typedef struct __packed {
+ uint8_t mod_num; /* 0-based or TB_POL_MOD_NUM_* */
+ uint8_t pcr; /* PCR number (0-23) or TB_POL_PCR_* */
+ uint8_t hash_type; /* TB_HTYPE_* */
+ uint32_t nv_index; /* nv index to be measured, effective when */
+ /* mod_num==TB_POL_MOD_NUM_{NV | NV_RAW} */
+ /* mod_num: */
+ /* TB_POL_MOD_NUM_NV_RAW: */
+ /* check index size==hash size, */
+ /* no hashing before verify and extend */
+ /* TB_POL_MOD_NUM_NV: */
+ /* hashing before verify and extend */
+ uint8_t num_hashes;
+ tb_hash_t hashes[];
+} tb_policy_entry_t;
+
+#define TB_POLCTL_EXTEND_PCR17 0x1 /* extend policy into PCR 17 */
+
+typedef struct __packed {
+ uint8_t version; /* currently 2 */
+ uint8_t policy_type; /* TB_POLTYPE_* */
+ /* TODO should be changed to 16bit for TPM 2.0 */
+ uint8_t hash_alg; /* TB_HALG_* */
+ uint32_t policy_control; /* bitwise OR of TB_POLCTL_* */
+ uint32_t reserved;
+ uint8_t num_entries;
+ tb_policy_entry_t entries[];
+} tb_policy_t;
+
+/*
+ * TPM NV index for VL policy
+ */
+
+/* max size of policy in TPM NV (assumes 8 entries w/ 4 hashes each) */
+#define MAX_TB_POLICY_SIZE \
+ sizeof(tb_policy_t) + 8*(sizeof(tb_policy_entry_t) + 4*sizeof(tb_hash_t))
+
+#define TB_POLICY_INDEX 0x20000001 /* policy index for Verified Launch */
+
+
+/*
+ * helper fns
+ */
+#ifndef PRINT
+#define PRINT(...) {}
+#endif
+
+static inline const char *hash_type_to_string(uint8_t hash_type)
+{
+ if ( hash_type == TB_HTYPE_ANY )
+ return "TB_HTYPE_ANY";
+ else if ( hash_type == TB_HTYPE_IMAGE )
+ return "TB_HTYPE_IMAGE";
+ else {
+ static char buf[32];
+ snprintf(buf, sizeof(buf), "unsupported (%u)", hash_type);
+ return buf;
+ }
+}
+
+static inline const char *policy_type_to_string(uint8_t policy_type)
+{
+ if ( policy_type == TB_POLTYPE_CONT_NON_FATAL )
+ return "TB_POLTYPE_CONT_NON_FATAL";
+ else if ( policy_type == TB_POLTYPE_CONT_VERIFY_FAIL )
+ return "TB_POLTYPE_CONT_VERIFY_FAIL";
+ else if ( policy_type == TB_POLTYPE_HALT )
+ return "TB_POLTYPE_HALT";
+ else {
+ static char buf[32];
+ snprintf(buf, sizeof(buf), "unsupported (%u)", policy_type);
+ return buf;
+ }
+}
+
+static inline const char *policy_control_to_string(uint32_t policy_control)
+{
+ static char buf[64] = "";
+
+ if ( policy_control & TB_POLCTL_EXTEND_PCR17 )
+ strncpy(buf, "EXTEND_PCR17", sizeof(buf));
+
+ return buf;
+}
+
+static inline size_t calc_policy_entry_size(const tb_policy_entry_t *pol_entry,
+ uint16_t hash_alg)
+{
+ if ( pol_entry == NULL )
+ return 0;
+
+ size_t size = sizeof(*pol_entry);
+ /* tb_policy_entry_t has empty hash array, which isn't counted in size */
+ /* so add size of each hash */
+ size += pol_entry->num_hashes * get_hash_size(hash_alg);
+
+ return size;
+}
+
+static inline size_t calc_policy_size(const tb_policy_t *policy)
+{
+ size_t size = sizeof(*policy);
+
+ /* tb_policy_t has empty array, which isn't counted in size */
+ /* so add size of each policy */
+ const tb_policy_entry_t *pol_entry = policy->entries;
+ for ( int i = 0; i < policy->num_entries; i++ ) {
+ size_t entry_size = calc_policy_entry_size(pol_entry,
+ policy->hash_alg);
+ pol_entry = (void *)pol_entry + entry_size;
+ size += entry_size;
+ }
+
+ return size;
+}
+
+static inline tb_hash_t *get_policy_entry_hash(
+ const tb_policy_entry_t *pol_entry, uint16_t hash_alg, int i)
+{
+ /* assumes policy has already been validated */
+
+ if ( pol_entry == NULL ) {
+ PRINT(TBOOT_ERR"Error: pol_entry pointer is NULL\n");
+ return NULL;
+ }
+
+ if ( i < 0 || i >= pol_entry->num_hashes ) {
+ PRINT(TBOOT_ERR"Error: position is not correct.\n");
+ return NULL;
+ }
+
+ return (tb_hash_t *)((void *)pol_entry->hashes +
+ i * get_hash_size(hash_alg));
+}
+
+static inline tb_policy_entry_t* get_policy_entry(const tb_policy_t *policy,
+ int i)
+{
+ /* assumes policy has already been validated */
+
+ if ( policy == NULL ) {
+ PRINT(TBOOT_ERR"Error: policy pointer is NULL\n");
+ return NULL;
+ }
+
+ if ( i < 0 || i >= policy->num_entries ) {
+ PRINT(TBOOT_ERR"Error: position is not correct.\n");
+ return NULL;
+ }
+
+ tb_policy_entry_t *pol_entry = (tb_policy_entry_t *)policy->entries;
+ for ( int j = 0; j < i; j++ ) {
+ pol_entry = (void *)pol_entry +
+ calc_policy_entry_size(pol_entry, policy->hash_alg);
+ }
+
+ return pol_entry;
+}
+
+static inline tb_policy_entry_t* find_policy_entry(const tb_policy_t *policy,
+ uint8_t mod_num)
+{
+ /* assumes policy has already been validated */
+
+ if ( policy == NULL ) {
+ PRINT(TBOOT_ERR"Error: policy pointer is NULL\n");
+ return NULL;
+ }
+
+ for ( int i = 0; i < policy->num_entries; i++ ) {
+ tb_policy_entry_t *pol_entry = get_policy_entry(policy, i);
+ if ( pol_entry == NULL )
+ return NULL;
+
+ if ( pol_entry->mod_num == mod_num ||
+ pol_entry->mod_num == TB_POL_MOD_NUM_ANY )
+ return pol_entry;
+ }
+
+ return NULL;
+}
+
+/*
+ * verify and display policy
+ */
+static inline bool verify_policy(const tb_policy_t *policy, size_t size, bool print)
+{
+ if ( print ) PRINT(TBOOT_DETA"policy:\n");
+
+ if ( policy == NULL ) {
+ if ( print ) PRINT(TBOOT_ERR"policy pointer is NULL\n");
+ return false;
+ }
+
+ if ( size < sizeof(tb_policy_t) ) {
+ if ( print ) PRINT(TBOOT_ERR"size of policy is too small (%lu)\n",
+ (unsigned long)size);
+ return false;
+ }
+
+ if ( policy->version != 0x02 ) {
+ if ( print ) PRINT(TBOOT_ERR"unsupported version (%u)\n", policy->version);
+ return false;
+ }
+ if ( print ) PRINT(TBOOT_DETA"\t version: %u\n", policy->version);
+
+ if ( print ) PRINT(TBOOT_DETA"\t policy_type: %s\n",
+ policy_type_to_string(policy->policy_type));
+ if ( policy->policy_type >= TB_POLTYPE_MAX )
+ return false;
+
+ if ( print ) PRINT(TBOOT_DETA"\t hash_alg: %s\n",
+ hash_alg_to_string(policy->hash_alg));
+
+ if ( print ) PRINT(TBOOT_DETA"\t policy_control: %08x (%s)\n",
+ policy->policy_control,
+ policy_control_to_string(policy->policy_control));
+
+ if ( print ) PRINT(TBOOT_DETA"\t num_entries: %u\n", policy->num_entries);
+
+ const tb_policy_entry_t *pol_entry = policy->entries;
+ for ( int i = 0; i < policy->num_entries; i++ ) {
+ /* check header of policy entry */
+ if ( ((void *)pol_entry - (void *)policy + sizeof(*pol_entry)) >
+ size ) {
+ if ( print ) PRINT(TBOOT_ERR"size of policy entry is too small (%lu)\n",
+ (unsigned long)size);
+ return false;
+ }
+
+ if ( print ) PRINT(TBOOT_DETA"\t policy entry[%d]:\n", i);
+
+ if ( pol_entry->mod_num > TB_POL_MAX_MOD_NUM &&
+ pol_entry->mod_num != TB_POL_MOD_NUM_ANY &&
+ pol_entry->mod_num != TB_POL_MOD_NUM_NV &&
+ pol_entry->mod_num != TB_POL_MOD_NUM_NV_RAW ) {
+ if ( print ) PRINT(TBOOT_ERR"mod_num invalid (%u)\n", pol_entry->mod_num);
+ return false;
+ }
+ if ( print ) PRINT(TBOOT_DETA"\t\t mod_num: ");
+ if ( pol_entry->mod_num == TB_POL_MOD_NUM_ANY ) {
+ if ( print ) PRINT(TBOOT_DETA"any\n");
+ }
+ else if ( pol_entry->mod_num == TB_POL_MOD_NUM_NV ) {
+ if ( print )
+ PRINT(TBOOT_DETA"nv\n"
+ "\t\t nv_index: %08x\n",
+ pol_entry->nv_index);
+ }
+ else if ( pol_entry->mod_num == TB_POL_MOD_NUM_NV_RAW ) {
+ if ( print )
+ PRINT(TBOOT_DETA"nv_raw\n"
+ "\t\t nv_index: %08x\n",
+ pol_entry->nv_index);
+ }
+ else
+ if ( print ) PRINT(TBOOT_DETA"%u\n", pol_entry->mod_num);
+
+ if ( pol_entry->pcr > TB_POL_MAX_PCR &&
+ pol_entry->pcr != TB_POL_PCR_NONE ) {
+ if ( print ) PRINT(TBOOT_ERR"pcr invalid (%u)\n", pol_entry->pcr);
+ return false;
+ }
+ if ( print ) PRINT(TBOOT_DETA"\t\t pcr: ");
+ if ( pol_entry->pcr == TB_POL_PCR_NONE ) {
+ if ( print ) PRINT(TBOOT_DETA"none\n");
+ }
+ else
+ if ( print ) PRINT(TBOOT_DETA"%u\n", pol_entry->pcr);
+
+ if ( print ) PRINT(TBOOT_DETA"\t\t hash_type: %s\n",
+ hash_type_to_string(pol_entry->hash_type));
+ if ( pol_entry->hash_type > TB_HTYPE_IMAGE )
+ return false;
+
+ if ( print ) PRINT(TBOOT_DETA"\t\t num_hashes: %u\n", pol_entry->num_hashes);
+
+ /* check all of policy */
+ if ( ((void *)pol_entry - (void *)policy + sizeof(*pol_entry) +
+ pol_entry->num_hashes * get_hash_size(policy->hash_alg))
+ > size ) {
+ if ( print ) PRINT(TBOOT_ERR"size of policy entry is too small (%lu)\n",
+ (unsigned long)size);
+ return false;
+ }
+
+ for ( int j = 0; j < pol_entry->num_hashes; j++ ) {
+ if ( print ) {
+ PRINT(TBOOT_DETA"\t\t hashes[%d]: ", j);
+ print_hash(get_policy_entry_hash(pol_entry,
+ policy->hash_alg, j),
+ policy->hash_alg);
+ }
+ }
+
+ pol_entry = (void *)pol_entry +
+ calc_policy_entry_size(pol_entry, policy->hash_alg);
+ }
+
+ return true;
+}
+
+#endif /* __TB_POLICY_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff --git a/tboot/include/tboot.h b/tboot/include/tboot.h
new file mode 100644
index 0000000..ecf7dbe
--- /dev/null
+++ b/tboot/include/tboot.h
@@ -0,0 +1,197 @@
+/*
+ * tboot.h: shared data structure with MLE and kernel and functions
+ * used by kernel for runtime support
+ *
+ * Copyright (c) 2006-2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef __TBOOT_H__
+#define __TBOOT_H__
+
+#ifndef __packed
+#define __packed __attribute__ ((packed))
+#endif
+
+#define TB_CURRENT_VER 7
+
+/* define uuid_t here in case uuid.h wasn't pre-included */
+/* (i.e. so tboot.h can be self-sufficient) */
+#ifndef __UUID_H__
+typedef struct __packed {
+ uint32_t data1;
+ uint16_t data2;
+ uint16_t data3;
+ uint16_t data4;
+ uint8_t data5[6];
+} uuid_t;
+#endif
+
+/*
+ * used to communicate between tboot and the launched kernel (i.e. Xen)
+ */
+
+#define TB_KEY_SIZE 64 /* 512 bits */
+
+#define MAX_TB_MAC_REGIONS 32
+typedef struct __packed {
+ uint64_t start; /* must be 4k byte -aligned */
+ uint32_t size; /* must be 4k byte -granular */
+} tboot_mac_region_t;
+
+/* GAS - Generic Address Structure (ACPI 2.0+) */
+typedef struct __packed {
+ uint8_t space_id; /* only 0,1 (memory, I/O) are supported */
+ uint8_t bit_width;
+ uint8_t bit_offset;
+ uint8_t access_width; /* only 1-3 (byte, word, dword) are supported */
+ uint64_t address;
+} tboot_acpi_generic_address_t;
+
+typedef struct __packed {
+ tboot_acpi_generic_address_t pm1a_cnt_blk;
+ tboot_acpi_generic_address_t pm1b_cnt_blk;
+ tboot_acpi_generic_address_t pm1a_evt_blk;
+ tboot_acpi_generic_address_t pm1b_evt_blk;
+ uint16_t pm1a_cnt_val;
+ uint16_t pm1b_cnt_val;
+ uint64_t wakeup_vector;
+ uint32_t vector_width;
+ uint64_t kernel_s3_resume_vector;
+} tboot_acpi_sleep_info_t;
+
+#define TB_RESMEM_BLOCKS 128
+
+typedef struct __packed {
+ uint64_t addr;
+ uint64_t length;
+} reserve_map_t;
+
+typedef struct __packed {
+ /* version 3+ fields: */
+ uuid_t uuid; /* {663C8DFF-E8B3-4b82-AABF-19EA4D057A08} */
+ uint32_t version; /* currently 7 for EFI support */
+ uint32_t log_addr; /* physical addr of log or NULL if none */
+ uint32_t shutdown_entry; /* entry point for tboot shutdown */
+ uint32_t shutdown_type; /* type of shutdown (TB_SHUTDOWN_*) */
+ tboot_acpi_sleep_info_t
+ acpi_sinfo; /* where kernel put acpi sleep info in Sx */
+ uint32_t tboot_base; /* starting addr for tboot */
+ uint32_t tboot_size; /* size of tboot */
+ uint8_t num_mac_regions; /* number mem regions to MAC on S3 */
+ /* contig regions memory to MAC on S3 */
+ tboot_mac_region_t mac_regions[MAX_TB_MAC_REGIONS];
+ /* version 4+ fields: */
+ /* populated by tboot; will be encrypted */
+ uint8_t s3_key[TB_KEY_SIZE];
+ /* version 5+ fields: */
+ uint8_t reserved_align[3]; /* used to 4byte-align num_in_wfs */
+ uint32_t num_in_wfs; /* number of processors in wait-for-SIPI */
+ /* version 6+ fields: */
+ uint32_t flags;
+ uint64_t ap_wake_addr; /* phys addr of kernel/VMM SIPI vector */
+ uint32_t ap_wake_trigger; /* kernel/VMM writes APIC ID to wake AP */
+ /* version 7+ fields */
+ /* reserve mem blocks to adjust dom0 E820 */
+ uint64_t reserve_map_count;
+ reserve_map_t reserve_map[TB_RESMEM_BLOCKS];
+} tboot_shared_t;
+
+#define TB_SHUTDOWN_REBOOT 0
+#define TB_SHUTDOWN_S5 1
+#define TB_SHUTDOWN_S4 2
+#define TB_SHUTDOWN_S3 3
+#define TB_SHUTDOWN_HALT 4
+#define TB_SHUTDOWN_WFS 5
+
+#define TB_FLAG_AP_WAKE_SUPPORT 0x00000001 /* kernel/VMM use INIT-SIPI-SIPI
+ if clear, ap_wake_* if set */
+
+/* {663C8DFF-E8B3-4b82-AABF-19EA4D057A08} */
+#define TBOOT_SHARED_UUID {0x663c8dff, 0xe8b3, 0x4b82, 0xaabf, \
+ {0x19, 0xea, 0x4d, 0x5, 0x7a, 0x8 }}
+#define TBOOT_MEM_LOG_SIZE 0x8000
+/*
+ * used to log tboot printk output
+ */
+typedef struct {
+ uuid_t uuid;
+ bool is_init;
+ uint16_t max_size;
+ uint16_t curr_pos;
+ char buf[TBOOT_MEM_LOG_SIZE];
+} tboot_log_t;
+
+/* {C0192526-6B30-4db4-844C-A3E953B88174} */
+#define TBOOT_LOG_UUID {0xc0192526, 0x6b30, 0x4db4, 0x844c, \
+ {0xa3, 0xe9, 0x53, 0xb8, 0x81, 0x74 }}
+
+/* The tboot_shared page */
+tboot_shared_t _tboot_shared;
+
+long s3_flag;
+
+static inline void print_tboot_shared(const tboot_shared_t *tboot_shared)
+{
+ printk(TBOOT_DETA"tboot_shared data:\n");
+ printk(TBOOT_DETA"\t version: %d\n", tboot_shared->version);
+ printk(TBOOT_DETA"\t log_addr: 0x%08x\n", tboot_shared->log_addr);
+ printk(TBOOT_DETA"\t shutdown_entry: 0x%08x\n", tboot_shared->shutdown_entry);
+ printk(TBOOT_DETA"\t shutdown_type: %d\n", tboot_shared->shutdown_type);
+ printk(TBOOT_DETA"\t tboot_base: 0x%08x\n", tboot_shared->tboot_base);
+ printk(TBOOT_DETA"\t tboot_size: 0x%x\n", tboot_shared->tboot_size);
+ printk(TBOOT_DETA"\t num_in_wfs: %u\n", tboot_shared->num_in_wfs);
+ printk(TBOOT_DETA"\t flags: 0x%8.8x\n", tboot_shared->flags);
+ printk(TBOOT_DETA"\t ap_wake_addr: 0x%08x\n", (uint32_t)tboot_shared->ap_wake_addr);
+ printk(TBOOT_DETA"\t ap_wake_trigger: %u\n", tboot_shared->ap_wake_trigger);
+}
+
+void begin_initial_launch(void);
+void begin_launch(efi_xen_tboot_data_t *xtd);
+void s3_launch(void);
+void shutdown(void);
+void cpu_wakeup(uint32_t cpuid, uint64_t sipi_vec);
+
+/* policy */
+void verify_all_modules(void);
+void apply_policy(tb_error_t error);
+tb_error_t set_policy(void);
+
+#endif /* __TBOOT_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/tpm.h b/tboot/include/tpm.h
new file mode 100644
index 0000000..59ebde1
--- /dev/null
+++ b/tboot/include/tpm.h
@@ -0,0 +1,521 @@
+/*
+ * tpm.h: TPM-related support functions
+ *
+ * Copyright (c) 2006-2009, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TPM_H__
+#define __TPM_H__
+
+#include <types.h>
+#include <io.h>
+#include <hash.h>
+#include <integrity.h>
+
+/* un-comment to enable detailed command tracing */
+//#define TPM_TRACE
+
+#define TPM_IF_12 0
+#define TPM_IF_20_FIFO 1
+#define TPM_IF_20_CRB 2
+
+#define TPM_INTERFACE_ID_FIFO_20 0x0
+#define TPM_INTERFACE_ID_CRB 0x1
+#define TPM_INTERFACE_ID_FIFO_13 0xF
+
+#define TPM_LOCALITY_BASE 0xfed40000
+#define TPM_LOCALITY_0 TPM_LOCALITY_BASE
+#define TPM_LOCALITY_1 (TPM_LOCALITY_BASE | 0x1000)
+#define TPM_LOCALITY_2 (TPM_LOCALITY_BASE | 0x2000)
+#define TPM_LOCALITY_3 (TPM_LOCALITY_BASE | 0x3000)
+#define TPM_LOCALITY_4 (TPM_LOCALITY_BASE | 0x4000)
+#define TPM_LOCALITY_BASE_N(n) (TPM_LOCALITY_BASE | ((n) << 12))
+#define TPM_NR_LOCALITIES 5
+#define NR_TPM_LOCALITY_PAGES ((TPM_LOCALITY_1 - TPM_LOCALITY_0) >> PAGE_SHIFT)
+
+#define TPM_LOCALITY_CRB_BASE 0xfed40000
+#define TPM_LOCALITY_CRB_0 TPM_LOCALITY_CRB_BASE
+#define TPM_LOCALITY_CRB_1 (TPM_LOCALITY_CRB_BASE | 0x1000)
+#define TPM_LOCALITY_CRB_2 (TPM_LOCALITY_CRB_BASE | 0x2000)
+#define TPM_LOCALITY_CRB_3 (TPM_LOCALITY_CRB_BASE | 0x3000)
+#define TPM_LOCALITY_CRB_4 (TPM_LOCALITY_CRB_BASE | 0x4000)
+#define TPM_LOCALITY_CRB_BASE_N(n) (TPM_LOCALITY_CRB_BASE | ((n) << 12))
+#define TPM_NR_CRB_LOCALITIES 5
+#define NR_TPM_LOCALITY_CRB_PAGES ((TPM_LOCALITY_CRB_1 - TPM_LOCALITY_CRB_0) >> PAGE_SHIFT)
+/*
+ * Command Header Fields:
+ * 0 1 2 3 4 5 6 7 8 9 10 ...
+ * -------------------------------------------------------------
+ * | TAG | SIZE | COMMAND CODE | other ...
+ * -------------------------------------------------------------
+ *
+ * Response Header Fields:
+ * 0 1 2 3 4 5 6 7 8 9 10 ...
+ * -------------------------------------------------------------
+ * | TAG | SIZE | RETURN CODE | other ...
+ * -------------------------------------------------------------
+ */
+#define CMD_HEAD_SIZE 10
+#define RSP_HEAD_SIZE 10
+#define CMD_SIZE_OFFSET 2
+#define CMD_CC_OFFSET 6
+#define RSP_SIZE_OFFSET 2
+#define RSP_RST_OFFSET 6
+
+/*
+ * The term timeout applies to timings between various states
+ * or transitions within the interface protocol.
+ */
+#define TIMEOUT_UNIT (0x100000 / 330) /* ~1ms, 1 tpm r/w need > 330ns */
+#define TIMEOUT_A 750 /* 750ms */
+#define TIMEOUT_B 2000 /* 2s */
+#define TIMEOUT_C 75000 /* 750ms */
+#define TIMEOUT_D 750 /* 750ms */
+
+typedef struct __packed {
+ uint32_t timeout_a;
+ uint32_t timeout_b;
+ uint32_t timeout_c;
+ uint32_t timeout_d;
+} tpm_timeout_t;
+
+/*
+ * The TCG maintains a registry of all algorithms that have an
+ * assigned algorithm ID. That registry is the definitive list
+ * of algorithms that may be supported by a TPM.
+ */
+#define TPM_ALG_ERROR 0x0000
+#define TPM_ALG_FIRST 0x0001
+#define TPM_ALG_RSA 0x0001
+#define TPM_ALG_DES 0x0002
+#define TPM_ALG__3DES 0x0003
+#define TPM_ALG_SHA 0x0004
+#define TPM_ALG_SHA1 0x0004
+#define TPM_ALG_HMAC 0x0005
+#define TPM_ALG_AES 0x0006
+#define TPM_ALG_MGF1 0x0007
+#define TPM_ALG_KEYEDHASH 0x0008
+#define TPM_ALG_XOR 0x000A
+#define TPM_ALG_SHA256 0x000B
+#define TPM_ALG_SHA384 0x000C
+#define TPM_ALG_SHA512 0x000D
+#define TPM_ALG_WHIRLPOOL512 0x000E
+#define TPM_ALG_NULL 0x0010
+#define TPM_ALG_SM3_256 0x0012
+#define TPM_ALG_SM4 0x0013
+#define TPM_ALG_RSASSA 0x0014
+#define TPM_ALG_RSAES 0x0015
+#define TPM_ALG_RSAPSS 0x0016
+#define TPM_ALG_OAEP 0x0017
+#define TPM_ALG_ECDSA 0x0018
+#define TPM_ALG_ECDH 0x0019
+#define TPM_ALG_ECDAA 0x001A
+#define TPM_ALG_SM2 0x001B
+#define TPM_ALG_ECSCHNORR 0x001C
+#define TPM_ALG_KDF1_SP800_56a 0x0020
+#define TPM_ALG_KDF2 0x0021
+#define TPM_ALG_KDF1_SP800_108 0x0022
+#define TPM_ALG_ECC 0x0023
+#define TPM_ALG_SYMCIPHER 0x0025
+#define TPM_ALG_CTR 0x0040
+#define TPM_ALG_OFB 0x0041
+#define TPM_ALG_CBC 0x0042
+#define TPM_ALG_CFB 0x0043
+#define TPM_ALG_ECB 0x0044
+#define TPM_ALG_LAST 0x0044
+#define TPM_ALG_MAX_NUM (TPM_ALG_LAST - TPM_ALG_ERROR)
+
+
+// move from tpm.c
+
+/*
+ * TPM registers and data structures
+ *
+ * register values are offsets from each locality base
+ * see {read,write}_tpm_reg() for data struct format
+ */
+
+/* TPM_ACCESS_x */
+#define TPM_REG_ACCESS 0x00
+#define TPM_REG_STS 0x18
+
+typedef union {
+ u8 _raw[1]; /* 1-byte reg */
+ struct __packed {
+ u8 tpm_establishment : 1; /* RO, 0=T/OS has been established
+ before */
+ u8 request_use : 1; /* RW, 1=locality is requesting TPM use */
+ u8 pending_request : 1; /* RO, 1=other locality is requesting
+ TPM usage */
+ u8 seize : 1; /* WO, 1=seize locality */
+ u8 been_seized : 1; /* RW, 1=locality seized while active */
+ u8 active_locality : 1; /* RW, 1=locality is active */
+ u8 reserved : 1;
+ u8 tpm_reg_valid_sts : 1; /* RO, 1=other bits are valid */
+ };
+} tpm_reg_access_t;
+
+/* TPM_STS_x */
+
+typedef union {
+ u8 _raw[3]; /* 3-byte reg */
+ struct __packed {
+ u8 reserved1 : 1;
+ u8 response_retry : 1; /* WO, 1=re-send response */
+ u8 self_test_done : 1; /* RO, only for version 2 */
+ u8 expect : 1; /* RO, 1=more data for command expected */
+ u8 data_avail : 1; /* RO, 0=no more data for response */
+ u8 tpm_go : 1; /* WO, 1=execute sent command */
+ u8 command_ready : 1; /* RW, 1=TPM ready to receive new cmd */
+ u8 sts_valid : 1; /* RO, 1=data_avail and expect bits are valid */
+ u16 burst_count : 16; /* RO, # read/writes bytes before wait */
+ };
+} tpm12_reg_sts_t;
+
+typedef union {
+ u8 _raw[4]; /* 4-byte reg */
+ struct __packed {
+ u8 reserved1 : 1;
+ u8 response_retry : 1; /* WO, 1=re-send response */
+ u8 self_test_done : 1; /* RO, only for version 2 */
+ u8 expect : 1; /* RO, 1=more data for command expected */
+ u8 data_avail : 1; /* RO, 0=no more data for response */
+ u8 tpm_go : 1; /* WO, 1=execute sent command */
+ u8 command_ready : 1; /* RW, 1=TPM ready to receive new cmd */
+ u8 sts_valid : 1; /* RO, 1=data_avail and expect bits are
+ valid */
+ u16 burst_count : 16; /* RO, # read/writes bytes before wait */
+ /* version >= 2 */
+ u8 command_cancel : 1;
+ u8 reset_establishment : 1;
+ u8 tpm_family : 2;
+ u8 reserved2 : 4;
+ };
+} tpm20_reg_sts_t;
+
+//-----------------------------------------------------------------------------
+// CRB I/F related definitions, see TCG PC Client Platform TPM Profile (PTP) Specification, Level 00 Revision 00.43
+//-----------------------------------------------------------------------------
+#define TPM_REG_LOC_STATE 0x00
+#define TPM_REG_LOC_CTRL 0x8
+#define TPM_LOCALITY_STS 0x0C
+#define TPM_INTERFACE_ID 0x30
+#define TPM_CONTROL_AREA 0x40
+#define TPM_CRB_CTRL_REQ 0x40
+#define TPM_CRB_CTRL_STS 0x44
+#define TPM_CRB_CTRL_CANCEL 0x48
+#define TPM_CRB_CTRL_START 0x4C
+#define TPM_CRB_CTRL_CMD_SIZE 0x58
+#define TPM_CRB_CTRL_CMD_ADDR 0x5C
+#define TPM_CRB_CTRL_CMD_HADDR 0x60
+#define TPM_CRB_CTRL_RSP_SIZE 0x64
+#define TPM_CRB_CTRL_RSP_ADDR 0x68
+#define TPM_CRB_DATA_BUFFER 0x80
+#define TPMCRBBUF_LEN 0xF80 //3968 Bytes
+
+//#define CTRL_AREA_ADDR (uint32_t) (TPM_CRB_BASE + 0x40)
+//#define DATA_BUF_ADDR (uint32_t) (TPM_CRB_BASE + 0x80)
+
+typedef union {
+ u8 _raw[4]; /* 4-byte reg */
+ struct __packed {
+ u8 tpm_establishment : 1;
+ u8 loc_assigned : 1;
+ u8 active_locality : 3;
+ u8 reserved : 2;
+ u8 tpm_reg_valid_sts : 1; /* RO, 1=other bits are valid */
+ u8 reserved1 :8;
+ u16 reserved2 :16;
+ };
+} tpm_reg_loc_state_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed {
+ uint32_t requestAccess:1;
+ uint32_t relinquish:1;
+ uint32_t seize:1;
+ uint32_t resetEstablishment:1;
+ uint32_t reserved1:28;
+ };
+} tpm_reg_loc_ctrl_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed{
+ uint32_t Granted:1;
+ uint32_t BeenSeized:1;
+ uint32_t R:30;
+ };
+} tpm_reg_loc_sts_t;
+
+typedef union {
+ uint8_t _raw[8]; // 8-byte reg
+ struct __packed {
+ uint64_t interface_type:4;
+ uint64_t interface_version:4;
+ uint64_t interface_capability:4;
+ uint64_t interface_selector:4;
+ uint64_t rid:8;
+ uint64_t res:8;
+ uint64_t vid:16;
+ uint64_t did:16;
+ };
+} tpm_crb_interface_id_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed{
+ uint32_t cmdReady:1;
+ uint32_t goIdle:1;
+ uint32_t Reserved:30;
+ };
+ } tpm_reg_ctrl_request_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed{
+ uint32_t tpmsts:1;
+ uint32_t tpmidle:1;
+ uint32_t reserved:30;
+ };
+} tpm_reg_ctrl_sts_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed{
+ uint32_t start;
+ };
+} tpm_reg_ctrl_start_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed{
+ uint32_t cancel;
+ };
+} tpm_reg_ctrl_cancel_t;
+
+typedef union {
+ uint8_t _raw[8];
+ struct __packed{
+ uint32_t cmdladdr;
+ uint32_t cmdhaddr;
+ };
+} tpm_reg_ctrl_cmdaddr_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed{
+ uint32_t cmdsize;
+ };
+} tpm_reg_ctrl_cmdsize_t;
+
+typedef union {
+ uint8_t _raw[8];
+ struct __packed{
+ uint64_t rspaddr;
+ };
+} tpm_reg_ctrl_rspaddr_t;
+
+typedef union {
+ uint8_t _raw[4];
+ struct __packed{
+ uint32_t rspsize;
+ };
+} tpm_reg_ctrl_rspsize_t;
+
+typedef union {
+ uint8_t _raw[48];
+ struct __packed {
+ tpm_reg_ctrl_request_t Request;
+ tpm_reg_ctrl_sts_t Status;
+ tpm_reg_ctrl_cancel_t Cancel;
+ tpm_reg_ctrl_start_t Start;
+ uint64_t R;
+ tpm_reg_ctrl_cmdsize_t CmdSize;
+ tpm_reg_ctrl_cmdaddr_t CmdAddr;
+ tpm_reg_ctrl_rspsize_t RspSize;
+ tpm_reg_ctrl_rspaddr_t RspAddr;
+ };
+} tpm_ctrl_area_t;
+
+// END OF CRB I/F
+
+/*
+ * assumes that all reg types follow above format:
+ * - packed
+ * - member named '_raw' which is array whose size is that of data to read
+ */
+#define read_tpm_reg(locality, reg, pdata) _read_tpm_reg(locality, reg, (pdata)->_raw, sizeof(*(pdata)))
+
+#define write_tpm_reg(locality, reg, pdata) _write_tpm_reg(locality, reg, (pdata)->_raw, sizeof(*(pdata)))
+
+static inline void _read_tpm_reg(int locality, u32 reg, u8 *_raw, size_t size)
+{
+ for ( size_t i = 0; i < size; i++ ) _raw[i] = readb((TPM_LOCALITY_BASE_N(locality) | reg) + i);
+}
+
+static inline void _write_tpm_reg(int locality, u32 reg, u8 *_raw, size_t size)
+{
+ for ( size_t i = 0; i < size; i++ ) writeb((TPM_LOCALITY_BASE_N(locality) | reg) + i, _raw[i]);
+}
+
+
+/*
+ * the following inline function reversely copy the bytes from 'in' to
+ * 'out', the byte number to copy is given in count.
+ */
+#define reverse_copy(out, in, count) _reverse_copy((uint8_t *)(out), (uint8_t *)(in), count)
+
+static inline void _reverse_copy(uint8_t *out, uint8_t *in, uint32_t count)
+{
+ for ( uint32_t i = 0; i < count; i++ )
+ out[i] = in[count - i - 1];
+}
+
+/* alg id list supported by Tboot */
+u16 tboot_alg_list[2];
+
+typedef tb_hash_t tpm_digest_t;
+typedef tpm_digest_t tpm_pcr_value_t;
+
+/* only for tpm1.2 to (un)seal */
+tpm_pcr_value_t post_launch_pcr17;
+tpm_pcr_value_t post_launch_pcr18;
+
+struct tpm_if;
+
+struct tpm_if {
+#define TPM12_VER_MAJOR 1
+#define TPM12_VER_MINOR 2
+#define TPM20_VER_MAJOR 2
+#define TPM20_VER_MINOR 0
+ u8 major;
+ u8 minor;
+ u16 family;
+
+ tpm_timeout_t timeout;
+
+ u32 error; /* last reported error */
+ u32 cur_loc;
+
+ u16 banks;
+ u16 algs_banks[TPM_ALG_MAX_NUM];
+ u16 alg_count;
+ u16 algs[TPM_ALG_MAX_NUM];
+
+ /*
+ * Only for version>=2. PCR extend policy.
+ */
+#define TB_EXTPOL_AGILE 0
+#define TB_EXTPOL_EMBEDDED 1
+#define TB_EXTPOL_FIXED 2
+ u8 extpol;
+ u16 cur_alg;
+
+ /* NV index to be used */
+ u32 lcp_own_index;
+ u32 tb_policy_index;
+ u32 tb_err_index;
+ u32 sgx_svn_index;
+
+ bool (*init)(struct tpm_if *ti);
+
+ bool (*pcr_read)(struct tpm_if *ti, u32 locality, u32 pcr, tpm_pcr_value_t *out);
+ bool (*pcr_extend)(struct tpm_if *ti, u32 locality, u32 pcr, const hash_list_t *in);
+ bool (*pcr_reset)(struct tpm_if *ti, u32 locality, u32 pcr);
+ bool (*hash)(struct tpm_if *ti, u32 locality, const u8 *data, u32 data_size, hash_list_t *hl);
+
+ bool (*nv_read)(struct tpm_if *ti, u32 locality, u32 index, u32 offset, u8 *data, u32 *data_size);
+ bool (*nv_write)(struct tpm_if *ti, u32 locality, u32 index, u32 offset, const u8 *data, u32 data_size);
+ bool (*get_nvindex_size)(struct tpm_if *ti, u32 locality, u32 index, u32 *size);
+
+#define TPM_NV_PER_WRITE_STCLEAR (1<<14)
+#define TPM_NV_PER_WRITEDEFINE (1<<13)
+#define TPM_NV_PER_WRITEALL (1<<12)
+#define TPM_NV_PER_AUTHWRITE (1<<2)
+#define TPM_NV_PER_OWNERWRITE (1<<1)
+#define TPM_NV_PER_PPWRITE (1<<0)
+ bool (*get_nvindex_permission)(struct tpm_if *ti, u32 locality, u32 index, u32 *attribute);
+
+ bool (*seal)(struct tpm_if *ti, u32 locality, u32 in_data_size, const u8 *in_data, u32 *sealed_data_size, u8 *sealed_data);
+ bool (*unseal)(struct tpm_if *ti, u32 locality, u32 sealed_data_size, const u8 *sealed_data, u32 *secret_size, u8 *secret);
+ bool (*verify_creation)(struct tpm_if *ti, u32 sealed_data_size, u8 *sealed_data);
+
+ bool (*get_random)(struct tpm_if *ti, u32 locality, u8 *random_data, u32 *data_size);
+
+ uint32_t (*save_state)(struct tpm_if *ti, u32 locality);
+
+ bool (*cap_pcrs)(struct tpm_if *ti, u32 locality, int pcr);
+ bool (*check)(void);
+};
+
+struct tpm_if tpm_12_if;
+struct tpm_if tpm_20_if;
+struct tpm_if *g_tpm;
+uint8_t g_tpm_family;
+
+bool tpm_validate_locality(uint32_t locality);
+bool tpm_validate_locality_crb(uint32_t locality);
+bool release_locality(uint32_t locality);
+bool prepare_tpm(void);
+bool tpm_detect(void);
+void tpm_print(struct tpm_if *ti);
+bool tpm_submit_cmd(u32 locality, u8 *in, u32 in_size, u8 *out, u32 *out_size);
+bool tpm_submit_cmd_crb(u32 locality, u8 *in, u32 in_size, u8 *out, u32 *out_size);
+bool tpm_wait_cmd_ready(uint32_t locality);
+bool tpm_request_locality_crb(uint32_t locality);
+bool tpm_relinquish_locality_crb(uint32_t locality);
+bool txt_is_launched(void);
+bool tpm_workaround_crb(void);
+
+
+//#define TPM_UNIT_TEST 1
+
+#ifdef TPM_UNIT_TEST
+void tpm_unit_test(void);
+#else
+#define tpm_unit_test()
+#endif /* TPM_UNIT_TEST */
+
+
+#endif /* __TPM_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/tpm_20.h b/tboot/include/tpm_20.h
new file mode 100644
index 0000000..af7dab5
--- /dev/null
+++ b/tboot/include/tpm_20.h
@@ -0,0 +1,1503 @@
+/*
+ * tpm_20.h: TPM2.0-related structure
+ *
+ * Copyright (c) 2006-2013, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TPM20_H__
+#define __TPM20_H__
+
+/*
+ * tpm2.0 structure defined in spec.
+ */
+
+typedef struct {
+ u16 size;
+ u8 buffer[1];
+} TPM2B;
+
+// Table 205 -- SHA1 Hash Values
+#define SHA1_DIGEST_SIZE 20
+#define SHA1_BLOCK_SIZE 64
+#define SHA1_DER_SIZE 15
+#define SHA1_DER {0x30,0x21,0x30,0x09,0x06, 0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14}
+
+// Table 206 -- SHA256 Hash Values
+#define SHA256_DIGEST_SIZE 32
+#define SHA256_BLOCK_SIZE 64
+#define SHA256_DER_SIZE 19
+#define SHA256_DER {0x30,0x31,0x30,0x0d,0x06, 0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01, 0x05,0x00,0x04,0x20}
+
+// Table 207 -- SHA384 Hash Values
+#define SHA384_DIGEST_SIZE 48
+#define SHA384_BLOCK_SIZE 128
+#define SHA384_DER_SIZE 19
+#define SHA384_DER {0x30,0x41,0x30,0x0d,0x06, 0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02, 0x05,0x00,0x04,0x30}
+
+
+// Table 208 -- SHA512 Hash Values
+#define SHA512_DIGEST_SIZE 64
+#define SHA512_BLOCK_SIZE 128
+#define SHA512_DER_SIZE 19
+#define SHA512_DER {0x30,0x51,0x30,0x0d,0x06, \
+ 0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,\
+ 0x05,0x00,0x04,0x40}
+
+// Table 210 -- SM3_256 Hash Values
+#define SM3_256_DIGEST_SIZE 32
+#define SM3_256_BLOCK_SIZE 64
+#define SM3_256_DER_SIZE 18
+#define SM3_256_DER {0x30,0x30,0x30,0x0c,0x06, \
+ 0x08,0x2A,0x81,0x1C,0x81,0x45,0x01,0x83,0x11,0x05,\
+ 0x00,0x04,0x20}
+
+// Table 213 -- Logic Values
+#define YES 1
+#define NO 0
+#define SET 1
+#define CLEAR 0
+
+// Table 215 -- Implemented Algorithms
+#define ALG_RSA YES // 1
+#define ALG_SHA1 YES // 1
+#define ALG_HMAC YES // 1
+#define ALG_AES YES // 1
+#define ALG_MGF1 YES // 1
+#define ALG_XOR YES // 1
+#define ALG_KEYEDHASH YES // 1
+#define ALG_SHA256 YES // 1
+#define ALG_SHA384 YES // 0
+#define ALG_SHA512 YES // 0
+#define ALG_SM3_256 YES // 1
+#define ALG_SM4 YES // 1
+#define ALG_RSASSA YES // 1
+#define ALG_RSAES YES // 1
+#define ALG_RSAPSS YES // 1
+#define ALG_OAEP YES // 1
+#define ALG_ECC YES // 1
+#define ALG_ECDH YES // 1
+#define ALG_ECDSA YES // 1
+#define ALG_ECDAA YES // 1
+#define ALG_SM2 YES // 1
+#define ALG_ECSCHNORR YES // 1
+#define ALG_SYMCIPHER YES // 1
+#define ALG_KDF1_SP800_56a YES // 1
+#define ALG_KDF2 NO // 0
+#define ALG_KDF1_SP800_108 YES // 1
+#define ALG_CTR YES // 1
+#define ALG_OFB YES // 1
+#define ALG_CBC YES // 1
+#define ALG_CFB YES // 1
+#define ALG_ECB YES // 1
+
+#define HASH_COUNT (ALG_SHA1+ALG_SHA256+ALG_SM3_256+ALG_SHA384+ALG_SHA512)
+
+// Table 217 -- RSA Algorithm Constants
+#define RSA_KEY_SIZES_BITS {1024, 2048} // {1024,2048}
+#define MAX_RSA_KEY_BITS 2048
+#define MAX_RSA_KEY_BYTES ((MAX_RSA_KEY_BITS + 7) / 8) // 256
+
+// Table 218 -- ECC Algorithm Constants
+#define ECC_CURVES {TPM_ECC_NIST_P256,TPM_ECC_BN_P256,TPM_ECC_SM2_P256}
+#define ECC_KEY_SIZES_BITS {256}
+#define MAX_ECC_KEY_BITS 256
+#define MAX_ECC_KEY_BYTES ((MAX_ECC_KEY_BITS + 7) / 8) // 32
+
+// Table 219 -- AES Algorithm Constants
+#define AES_KEY_SIZES_BITS {128}
+#define MAX_AES_KEY_BITS 128
+#define MAX_AES_BLOCK_SIZE_BYTES 16
+#define MAX_AES_KEY_BYTES ((MAX_AES_KEY_BITS + 7) / 8) // 16
+
+// Table 221 -- Symmetric Algorithm Constants
+#define MAX_SYM_KEY_BITS MAX_AES_KEY_BITS // 128
+#define MAX_SYM_KEY_BYTES MAX_AES_KEY_BYTES // 16
+#define MAX_SYM_BLOCK_SIZE MAX_AES_BLOCK_SIZE_BYTES // 16
+
+// Table 222 -- Implementation Values
+#define FIELD_UPGRADE_IMPLEMENTED NO // 0
+typedef u16 BSIZE;
+#define BUFFER_ALIGNMENT 4
+#define IMPLEMENTATION_PCR 24
+#define PLATFORM_PCR 24
+#define DRTM_PCR 17
+#define NUM_LOCALITIES 5
+#define MAX_HANDLE_NUM 3
+#define MAX_ACTIVE_SESSIONS 64
+typedef u16 CONTEXT_SLOT;
+typedef u64 CONTEXT_COUNTER;
+#define MAX_LOADED_SESSIONS 3
+#define MAX_SESSION_NUM 3
+#define MAX_LOADED_OBJECTS 3
+#define MIN_EVICT_OBJECTS 2
+#define PCR_SELECT_MIN ((PLATFORM_PCR+7)/8) // 3
+#define PCR_SELECT_MAX ((IMPLEMENTATION_PCR+7)/8) // 3
+#define NUM_POLICY_PCR_GROUP 1
+#define NUM_AUTHVALUE_PCR_GROUP 1
+#define MAX_CONTEXT_SIZE 4000
+#define MAX_DIGEST_BUFFER 1024
+#define MAX_NV_INDEX_SIZE 1024
+#define MAX_CAP_BUFFER 1024
+#define NV_MEMORY_SIZE 16384
+#define NUM_STATIC_PCR 16
+#define MAX_ALG_LIST_SIZE 64
+#define TIMER_PRESCALE 100000
+#define PRIMARY_SEED_SIZE 32
+#define CONTEXT_ENCRYPT_ALG TPM_ALG_AES
+#define CONTEXT_ENCRYPT_KEY_BITS MAX_SYM_KEY_BITS // 128
+#define CONTEXT_ENCRYPT_KEY_BYTES ((CONTEXT_ENCRYPT_KEY_BITS+7)/8)
+#define CONTEXT_INTEGRITY_HASH_ALG TPM_ALG_SHA256
+#define CONTEXT_INTEGRITY_HASH_SIZE SHA256_DIGEST_SIZE // 32
+#define PROOF_SIZE CONTEXT_INTEGRITY_HASH_SIZE // 32
+#define NV_CLOCK_UPDATE_INTERVAL 12
+#define NUM_POLICY_PCR 1
+#define MAX_COMMAND_SIZE 4096
+#define MAX_RESPONSE_SIZE 4096
+#define ORDERLY_BITS 8
+#define MAX_ORDERLY_COUNT ((1 << ORDERLY_BITS) - 1) // 255
+#define ALG_ID_FIRST TPM_ALG_FIRST
+#define ALG_ID_LAST TPM_ALG_LAST
+#define MAX_SYM_DATA 128
+#define MAX_HASH_STATE_SIZE 512
+#define MAX_RNG_ENTROPY_SIZE 64
+#define RAM_INDEX_SPACE 512
+#define RSA_DEFAULT_PUBLIC_EXPONENT 0x00010001
+#define ENABLE_PCR_NO_INCREMENT YES // 1
+
+// Table 11 -- TPM_CC Constants <I/O,S>
+typedef u32 TPM_CC;
+
+#define TPM_CC_FIRST (TPM_CC)(0x0000011F)
+#define TPM_CC_PP_FIRST (TPM_CC)(0x0000011F)
+#define TPM_CC_NV_UndefineSpaceSpecial (TPM_CC)(0x0000011F)
+#define TPM_CC_EvictControl (TPM_CC)(0x00000120)
+#define TPM_CC_HierarchyControl (TPM_CC)(0x00000121)
+#define TPM_CC_NV_UndefineSpace (TPM_CC)(0x00000122)
+#define TPM_CC_ChangeEPS (TPM_CC)(0x00000124)
+#define TPM_CC_ChangePPS (TPM_CC)(0x00000125)
+#define TPM_CC_Clear (TPM_CC)(0x00000126)
+#define TPM_CC_ClearControl (TPM_CC)(0x00000127)
+#define TPM_CC_ClockSet (TPM_CC)(0x00000128)
+#define TPM_CC_HierarchyChangeAuth (TPM_CC)(0x00000129)
+#define TPM_CC_NV_DefineSpace (TPM_CC)(0x0000012A)
+#define TPM_CC_PCR_Allocate (TPM_CC)(0x0000012B)
+#define TPM_CC_PCR_SetAuthPolicy (TPM_CC)(0x0000012C)
+#define TPM_CC_PP_Commands (TPM_CC)(0x0000012D)
+#define TPM_CC_SetPrimaryPolicy (TPM_CC)(0x0000012E)
+#define TPM_CC_FieldUpgradeStart (TPM_CC)(0x0000012F)
+#define TPM_CC_ClockRateAdjust (TPM_CC)(0x00000130)
+#define TPM_CC_CreatePrimary (TPM_CC)(0x00000131)
+#define TPM_CC_NV_GlobalWriteLock (TPM_CC)(0x00000132)
+#define TPM_CC_PP_LAST (TPM_CC)(0x00000132)
+#define TPM_CC_GetCommandAuditDigest (TPM_CC)(0x00000133)
+#define TPM_CC_NV_Increment (TPM_CC)(0x00000134)
+#define TPM_CC_NV_SetBits (TPM_CC)(0x00000135)
+#define TPM_CC_NV_Extend (TPM_CC)(0x00000136)
+#define TPM_CC_NV_Write (TPM_CC)(0x00000137)
+#define TPM_CC_NV_WriteLock (TPM_CC)(0x00000138)
+#define TPM_CC_DictionaryAttackLockReset (TPM_CC)(0x00000139)
+#define TPM_CC_DictionaryAttackParameters (TPM_CC)(0x0000013A)
+#define TPM_CC_NV_ChangeAuth (TPM_CC)(0x0000013B)
+#define TPM_CC_PCR_Event (TPM_CC)(0x0000013C)
+#define TPM_CC_PCR_Reset (TPM_CC)(0x0000013D)
+#define TPM_CC_SequenceComplete (TPM_CC)(0x0000013E)
+#define TPM_CC_SetAlgorithmSet (TPM_CC)(0x0000013F)
+#define TPM_CC_SetCommandCodeAuditStatus (TPM_CC)(0x00000140)
+#define TPM_CC_FieldUpgradeData (TPM_CC)(0x00000141)
+#define TPM_CC_IncrementalSelfTest (TPM_CC)(0x00000142)
+#define TPM_CC_SelfTest (TPM_CC)(0x00000143)
+#define TPM_CC_Startup (TPM_CC)(0x00000144)
+#define TPM_CC_Shutdown (TPM_CC)(0x00000145)
+#define TPM_CC_StirRandom (TPM_CC)(0x00000146)
+#define TPM_CC_ActivateCredential (TPM_CC)(0x00000147)
+#define TPM_CC_Certify (TPM_CC)(0x00000148)
+#define TPM_CC_PolicyNV (TPM_CC)(0x00000149)
+#define TPM_CC_CertifyCreation (TPM_CC)(0x0000014A)
+#define TPM_CC_Duplicate (TPM_CC)(0x0000014B)
+#define TPM_CC_GetTime (TPM_CC)(0x0000014C)
+#define TPM_CC_GetSessionAuditDigest (TPM_CC)(0x0000014D)
+#define TPM_CC_NV_Read (TPM_CC)(0x0000014E)
+#define TPM_CC_NV_ReadLock (TPM_CC)(0x0000014F)
+#define TPM_CC_ObjectChangeAuth (TPM_CC)(0x00000150)
+#define TPM_CC_PolicySecret (TPM_CC)(0x00000151)
+#define TPM_CC_Rewrap (TPM_CC)(0x00000152)
+#define TPM_CC_Create (TPM_CC)(0x00000153)
+#define TPM_CC_ECDH_ZGen (TPM_CC)(0x00000154)
+#define TPM_CC_HMAC (TPM_CC)(0x00000155)
+#define TPM_CC_Import (TPM_CC)(0x00000156)
+#define TPM_CC_Load (TPM_CC)(0x00000157)
+#define TPM_CC_Quote (TPM_CC)(0x00000158)
+#define TPM_CC_RSA_Decrypt (TPM_CC)(0x00000159)
+#define TPM_CC_HMAC_Start (TPM_CC)(0x0000015B)
+#define TPM_CC_SequenceUpdate (TPM_CC)(0x0000015C)
+#define TPM_CC_Sign (TPM_CC)(0x0000015D)
+#define TPM_CC_Unseal (TPM_CC)(0x0000015E)
+#define TPM_CC_PolicySigned (TPM_CC)(0x00000160)
+#define TPM_CC_ContextLoad (TPM_CC)(0x00000161)
+#define TPM_CC_ContextSave (TPM_CC)(0x00000162)
+#define TPM_CC_ECDH_KeyGen (TPM_CC)(0x00000163)
+#define TPM_CC_EncryptDecrypt (TPM_CC)(0x00000164)
+#define TPM_CC_FlushContext (TPM_CC)(0x00000165)
+#define TPM_CC_LoadExternal (TPM_CC)(0x00000167)
+#define TPM_CC_MakeCredential (TPM_CC)(0x00000168)
+#define TPM_CC_NV_ReadPublic (TPM_CC)(0x00000169)
+#define TPM_CC_PolicyAuthorize (TPM_CC)(0x0000016A)
+#define TPM_CC_PolicyAuthValue (TPM_CC)(0x0000016B)
+#define TPM_CC_PolicyCommandCode (TPM_CC)(0x0000016C)
+#define TPM_CC_PolicyCounterTimer (TPM_CC)(0x0000016D)
+#define TPM_CC_PolicyCpHash (TPM_CC)(0x0000016E)
+#define TPM_CC_PolicyLocality (TPM_CC)(0x0000016F)
+#define TPM_CC_PolicyNameHash (TPM_CC)(0x00000170)
+#define TPM_CC_PolicyOR (TPM_CC)(0x00000171)
+#define TPM_CC_PolicyTicket (TPM_CC)(0x00000172)
+#define TPM_CC_ReadPublic (TPM_CC)(0x00000173)
+#define TPM_CC_RSA_Encrypt (TPM_CC)(0x00000174)
+#define TPM_CC_StartAuthSession (TPM_CC)(0x00000176)
+#define TPM_CC_VerifySignature (TPM_CC)(0x00000177)
+#define TPM_CC_ECC_Parameters (TPM_CC)(0x00000178)
+#define TPM_CC_FirmwareRead (TPM_CC)(0x00000179)
+#define TPM_CC_GetCapability (TPM_CC)(0x0000017A)
+#define TPM_CC_GetRandom (TPM_CC)(0x0000017B)
+#define TPM_CC_GetTestResult (TPM_CC)(0x0000017C)
+#define TPM_CC_Hash (TPM_CC)(0x0000017D)
+#define TPM_CC_PCR_Read (TPM_CC)(0x0000017E)
+#define TPM_CC_PolicyPCR (TPM_CC)(0x0000017F)
+#define TPM_CC_PolicyRestart (TPM_CC)(0x00000180)
+#define TPM_CC_ReadClock (TPM_CC)(0x00000181)
+#define TPM_CC_PCR_Extend (TPM_CC)(0x00000182)
+#define TPM_CC_PCR_SetAuthValue (TPM_CC)(0x00000183)
+#define TPM_CC_NV_Certify (TPM_CC)(0x00000184)
+#define TPM_CC_EventSequenceComplete (TPM_CC)(0x00000185)
+#define TPM_CC_HashSequenceStart (TPM_CC)(0x00000186)
+#define TPM_CC_PolicyPhysicalPresence (TPM_CC)(0x00000187)
+#define TPM_CC_PolicyDuplicationSelect (TPM_CC)(0x00000188)
+#define TPM_CC_PolicyGetDigest (TPM_CC)(0x00000189)
+#define TPM_CC_TestParms (TPM_CC)(0x0000018A)
+#define TPM_CC_Commit (TPM_CC)(0x0000018B)
+#define TPM_CC_PolicyPassword (TPM_CC)(0x0000018C)
+#define TPM_CC_SM2_ZGen (TPM_CC)(0x0000018D)
+#define TPM_CC_LAST (TPM_CC)(0x0000018D)
+
+// Table 15 -- TPM_RC Constants <O,S>
+typedef u32 TPM_RCS; // The 'safe' error codes
+typedef u32 TPM_RC;
+
+#define TPM_RC_SUCCESS (TPM_RC)(0x000)
+#define TPM_RC_BAD_TAG (TPM_RC)(0x030)
+#define RC_VER1 (TPM_RC)(0x100)
+#define TPM_RC_INITIALIZE (TPM_RC)(RC_VER1 + 0x000)
+#define TPM_RC_FAILURE (TPM_RC)(RC_VER1 + 0x001)
+#define TPM_RC_SEQUENCE (TPM_RC)(RC_VER1 + 0x003)
+#define TPM_RC_PRIVATE (TPM_RC)(RC_VER1 + 0x00B)
+#define TPM_RC_HMAC (TPM_RC)(RC_VER1 + 0x019)
+#define TPM_RC_DISABLED (TPM_RC)(RC_VER1 + 0x020)
+#define TPM_RC_EXCLUSIVE (TPM_RC)(RC_VER1 + 0x021)
+#define TPM_RC_AUTH_TYPE (TPM_RC)(RC_VER1 + 0x024)
+#define TPM_RC_AUTH_MISSING (TPM_RC)(RC_VER1 + 0x025)
+#define TPM_RC_POLICY (TPM_RC)(RC_VER1 + 0x026)
+#define TPM_RC_PCR (TPM_RC)(RC_VER1 + 0x027)
+#define TPM_RC_PCR_CHANGED (TPM_RC)(RC_VER1 + 0x028)
+#define TPM_RC_UPGRADE (TPM_RC)(RC_VER1 + 0x02D)
+#define TPM_RC_TOO_MANY_CONTEXTS (TPM_RC)(RC_VER1 + 0x02E)
+#define TPM_RC_AUTH_UNAVAILABLE (TPM_RC)(RC_VER1 + 0x02F)
+#define TPM_RC_REBOOT (TPM_RC)(RC_VER1 + 0x030)
+#define TPM_RC_UNBALANCED (TPM_RC)(RC_VER1 + 0x031)
+#define TPM_RC_COMMAND_SIZE (TPM_RC)(RC_VER1 + 0x042)
+#define TPM_RC_COMMAND_CODE (TPM_RC)(RC_VER1 + 0x043)
+#define TPM_RC_AUTHSIZE (TPM_RC)(RC_VER1 + 0x044)
+#define TPM_RC_AUTH_CONTEXT (TPM_RC)(RC_VER1 + 0x045)
+#define TPM_RC_NV_RANGE (TPM_RC)(RC_VER1 + 0x046)
+#define TPM_RC_NV_SIZE (TPM_RC)(RC_VER1 + 0x047)
+#define TPM_RC_NV_LOCKED (TPM_RC)(RC_VER1 + 0x048)
+#define TPM_RC_NV_AUTHORIZATION (TPM_RC)(RC_VER1 + 0x049)
+#define TPM_RC_NV_UNINITIALIZED (TPM_RC)(RC_VER1 + 0x04A)
+#define TPM_RC_NV_SPACE (TPM_RC)(RC_VER1 + 0x04B)
+#define TPM_RC_NV_DEFINED (TPM_RC)(RC_VER1 + 0x04C)
+#define TPM_RC_BAD_CONTEXT (TPM_RC)(RC_VER1 + 0x050)
+#define TPM_RC_CPHASH (TPM_RC)(RC_VER1 + 0x051)
+#define TPM_RC_PARENT (TPM_RC)(RC_VER1 + 0x052)
+#define TPM_RC_NEEDS_TEST (TPM_RC)(RC_VER1 + 0x053)
+#define TPM_RC_NO_RESULT (TPM_RC)(RC_VER1 + 0x054)
+#define TPM_RC_SENSITIVE (TPM_RC)(RC_VER1 + 0x055)
+#define RC_MAX_FM0 (TPM_RC)(RC_VER1 + 0x07F)
+#define RC_FMT1 (TPM_RC)(0x080)
+#define TPM_RC_ASYMMETRIC (TPM_RC)(RC_FMT1 + 0x001)
+#define TPM_RCS_ASYMMETRIC (TPM_RCS)(RC_FMT1 + 0x001)
+#define TPM_RC_ATTRIBUTES (TPM_RC)(RC_FMT1 + 0x002)
+#define TPM_RCS_ATTRIBUTES (TPM_RCS)(RC_FMT1 + 0x002)
+#define TPM_RC_HASH (TPM_RC)(RC_FMT1 + 0x003)
+#define TPM_RCS_HASH (TPM_RCS)(RC_FMT1 + 0x003)
+#define TPM_RC_VALUE (TPM_RC)(RC_FMT1 + 0x004)
+#define TPM_RCS_VALUE (TPM_RCS)(RC_FMT1 + 0x004)
+#define TPM_RC_HIERARCHY (TPM_RC)(RC_FMT1 + 0x005)
+#define TPM_RCS_HIERARCHY (TPM_RCS)(RC_FMT1 + 0x005)
+#define TPM_RC_KEY_SIZE (TPM_RC)(RC_FMT1 + 0x007)
+#define TPM_RCS_KEY_SIZE (TPM_RCS)(RC_FMT1 + 0x007)
+#define TPM_RC_MGF (TPM_RC)(RC_FMT1 + 0x008)
+#define TPM_RCS_MGF (TPM_RCS)(RC_FMT1 + 0x008)
+#define TPM_RC_MODE (TPM_RC)(RC_FMT1 + 0x009)
+#define TPM_RCS_MODE (TPM_RCS)(RC_FMT1 + 0x009)
+#define TPM_RC_TYPE (TPM_RC)(RC_FMT1 + 0x00A)
+#define TPM_RCS_TYPE (TPM_RCS)(RC_FMT1 + 0x00A)
+#define TPM_RC_HANDLE (TPM_RC)(RC_FMT1 + 0x00B)
+#define TPM_RCS_HANDLE (TPM_RCS)(RC_FMT1 + 0x00B)
+#define TPM_RC_KDF (TPM_RC)(RC_FMT1 + 0x00C)
+#define TPM_RCS_KDF (TPM_RCS)(RC_FMT1 + 0x00C)
+#define TPM_RC_RANGE (TPM_RC)(RC_FMT1 + 0x00D)
+#define TPM_RCS_RANGE (TPM_RCS)(RC_FMT1 + 0x00D)
+#define TPM_RC_AUTH_FAIL (TPM_RC)(RC_FMT1 + 0x00E)
+#define TPM_RCS_AUTH_FAIL (TPM_RCS)(RC_FMT1 + 0x00E)
+#define TPM_RC_NONCE (TPM_RC)(RC_FMT1 + 0x00F)
+#define TPM_RCS_NONCE (TPM_RCS)(RC_FMT1 + 0x00F)
+#define TPM_RC_PP (TPM_RC)(RC_FMT1 + 0x010)
+#define TPM_RCS_PP (TPM_RCS)(RC_FMT1 + 0x010)
+#define TPM_RC_SCHEME (TPM_RC)(RC_FMT1 + 0x012)
+#define TPM_RCS_SCHEME (TPM_RCS)(RC_FMT1 + 0x012)
+#define TPM_RC_SIZE (TPM_RC)(RC_FMT1 + 0x015)
+#define TPM_RCS_SIZE (TPM_RCS)(RC_FMT1 + 0x015)
+#define TPM_RC_SYMMETRIC (TPM_RC)(RC_FMT1 + 0x016)
+#define TPM_RCS_SYMMETRIC (TPM_RCS)(RC_FMT1 + 0x016)
+#define TPM_RC_TAG (TPM_RC)(RC_FMT1 + 0x017)
+#define TPM_RCS_TAG (TPM_RCS)(RC_FMT1 + 0x017)
+#define TPM_RC_SELECTOR (TPM_RC)(RC_FMT1 + 0x018)
+#define TPM_RCS_SELECTOR (TPM_RCS)(RC_FMT1 + 0x018)
+#define TPM_RC_INSUFFICIENT (TPM_RC)(RC_FMT1 + 0x01A)
+#define TPM_RCS_INSUFFICIENT (TPM_RCS)(RC_FMT1 + 0x01A)
+#define TPM_RC_SIGNATURE (TPM_RC)(RC_FMT1 + 0x01B)
+#define TPM_RCS_SIGNATURE (TPM_RCS)(RC_FMT1 + 0x01B)
+#define TPM_RC_KEY (TPM_RC)(RC_FMT1 + 0x01C)
+#define TPM_RCS_KEY (TPM_RCS)(RC_FMT1 + 0x01C)
+#define TPM_RC_POLICY_FAIL (TPM_RC)(RC_FMT1 + 0x01D)
+#define TPM_RCS_POLICY_FAIL (TPM_RCS)(RC_FMT1 + 0x01D)
+#define TPM_RC_INTEGRITY (TPM_RC)(RC_FMT1 + 0x01F)
+#define TPM_RCS_INTEGRITY (TPM_RCS)(RC_FMT1 + 0x01F)
+#define TPM_RC_TICKET (TPM_RC)(RC_FMT1 + 0x020)
+#define TPM_RCS_TICKET (TPM_RCS)(RC_FMT1 + 0x020)
+#define TPM_RC_RESERVED_BITS (TPM_RC)(RC_FMT1 + 0x021)
+#define TPM_RCS_RESERVED_BITS (TPM_RCS)(RC_FMT1 + 0x021)
+#define TPM_RC_BAD_AUTH (TPM_RC)(RC_FMT1 + 0x022)
+#define TPM_RCS_BAD_AUTH (TPM_RCS)(RC_FMT1 + 0x022)
+#define TPM_RC_EXPIRED (TPM_RC)(RC_FMT1 + 0x023)
+#define TPM_RCS_EXPIRED (TPM_RCS)(RC_FMT1 + 0x023)
+#define TPM_RC_POLICY_CC (TPM_RC)(RC_FMT1 + 0x024 )
+#define TPM_RCS_POLICY_CC (TPM_RCS)(RC_FMT1 + 0x024 )
+#define TPM_RC_BINDING (TPM_RC)(RC_FMT1 + 0x025)
+#define TPM_RCS_BINDING (TPM_RCS)(RC_FMT1 + 0x025)
+#define TPM_RC_CURVE (TPM_RC)(RC_FMT1 + 0x026)
+#define TPM_RCS_CURVE (TPM_RCS)(RC_FMT1 + 0x026)
+#define TPM_RC_ECC_POINT (TPM_RC)(RC_FMT1 + 0x027)
+#define TPM_RCS_ECC_POINT (TPM_RCS)(RC_FMT1 + 0x027)
+#define RC_WARN (TPM_RC)(0x900)
+#define TPM_RC_CONTEXT_GAP (TPM_RC)(RC_WARN + 0x001)
+#define TPM_RC_OBJECT_MEMORY (TPM_RC)(RC_WARN + 0x002)
+#define TPM_RC_SESSION_MEMORY (TPM_RC)(RC_WARN + 0x003)
+#define TPM_RC_MEMORY (TPM_RC)(RC_WARN + 0x004)
+#define TPM_RC_SESSION_HANDLES (TPM_RC)(RC_WARN + 0x005)
+#define TPM_RC_OBJECT_HANDLES (TPM_RC)(RC_WARN + 0x006)
+#define TPM_RC_LOCALITY (TPM_RC)(RC_WARN + 0x007)
+#define TPM_RC_YIELDED (TPM_RC)(RC_WARN + 0x008)
+#define TPM_RC_CANCELLED (TPM_RC)(RC_WARN + 0x009)
+#define TPM_RC_TESTING (TPM_RC)(RC_WARN + 0x00A)
+#define TPM_RC_REFERENCE_H0 (TPM_RC)(RC_WARN + 0x010)
+#define TPM_RC_REFERENCE_H1 (TPM_RC)(RC_WARN + 0x011)
+#define TPM_RC_REFERENCE_H2 (TPM_RC)(RC_WARN + 0x012)
+#define TPM_RC_REFERENCE_H3 (TPM_RC)(RC_WARN + 0x013)
+#define TPM_RC_REFERENCE_H4 (TPM_RC)(RC_WARN + 0x014)
+#define TPM_RC_REFERENCE_H5 (TPM_RC)(RC_WARN + 0x015)
+#define TPM_RC_REFERENCE_H6 (TPM_RC)(RC_WARN + 0x016)
+#define TPM_RC_REFERENCE_S0 (TPM_RC)(RC_WARN + 0x018)
+#define TPM_RC_REFERENCE_S1 (TPM_RC)(RC_WARN + 0x019)
+#define TPM_RC_REFERENCE_S2 (TPM_RC)(RC_WARN + 0x01A)
+#define TPM_RC_REFERENCE_S3 (TPM_RC)(RC_WARN + 0x01B)
+#define TPM_RC_REFERENCE_S4 (TPM_RC)(RC_WARN + 0x01C)
+#define TPM_RC_REFERENCE_S5 (TPM_RC)(RC_WARN + 0x01D)
+#define TPM_RC_REFERENCE_S6 (TPM_RC)(RC_WARN + 0x01E)
+#define TPM_RC_NV_RATE (TPM_RC)(RC_WARN + 0x020)
+#define TPM_RC_LOCKOUT (TPM_RC)(RC_WARN + 0x021)
+#define TPM_RC_RETRY (TPM_RC)(RC_WARN + 0x022)
+#define TPM_RC_NV_UNAVAILABLE (TPM_RC)(RC_WARN + 0x023)
+#define TPM_RC_NOT_USED (TPM_RC)(RC_WARN + 0x7F)
+#define TPM_RC_H (TPM_RC)(0x000)
+#define TPM_RC_P (TPM_RC)(0x040)
+#define TPM_RC_S (TPM_RC)(0x800)
+#define TPM_RC_1 (TPM_RC)(0x100)
+#define TPM_RC_2 (TPM_RC)(0x200)
+#define TPM_RC_3 (TPM_RC)(0x300)
+#define TPM_RC_4 (TPM_RC)(0x400)
+#define TPM_RC_5 (TPM_RC)(0x500)
+#define TPM_RC_6 (TPM_RC)(0x600)
+#define TPM_RC_7 (TPM_RC)(0x700)
+#define TPM_RC_8 (TPM_RC)(0x800)
+#define TPM_RC_9 (TPM_RC)(0x900)
+#define TPM_RC_A (TPM_RC)(0xA00)
+#define TPM_RC_B (TPM_RC)(0xB00)
+#define TPM_RC_C (TPM_RC)(0xC00)
+#define TPM_RC_D (TPM_RC)(0xD00)
+#define TPM_RC_E (TPM_RC)(0xE00)
+#define TPM_RC_F (TPM_RC)(0xF00)
+#define TPM_RC_N_MASK (TPM_RC)(0xF00)
+
+// Table 18 -- TPM_ST Constants <I/O,S>
+typedef u16 TPM_ST;
+
+#define TPM_ST_RSP_COMMAND (TPM_ST)(0x00C4)
+#define TPM_ST_NULL (TPM_ST)(0X8000)
+#define TPM_ST_NO_SESSIONS (TPM_ST)(0x8001)
+#define TPM_ST_SESSIONS (TPM_ST)(0x8002)
+#define TPM_ST_ATTEST_NV (TPM_ST)(0x8014)
+#define TPM_ST_ATTEST_COMMAND_AUDIT (TPM_ST)(0x8015)
+#define TPM_ST_ATTEST_SESSION_AUDIT (TPM_ST)(0x8016)
+#define TPM_ST_ATTEST_CERTIFY (TPM_ST)(0x8017)
+#define TPM_ST_ATTEST_QUOTE (TPM_ST)(0x8018)
+#define TPM_ST_ATTEST_TIME (TPM_ST)(0x8019)
+#define TPM_ST_ATTEST_CREATION (TPM_ST)(0x801A)
+#define TPM_ST_CREATION (TPM_ST)(0x8021)
+#define TPM_ST_VERIFIED (TPM_ST)(0x8022)
+#define TPM_ST_AUTH_SECRET (TPM_ST)(0x8023)
+#define TPM_ST_HASHCHECK (TPM_ST)(0x8024)
+#define TPM_ST_AUTH_SIGNED (TPM_ST)(0x8025)
+#define TPM_ST_FU_MANIFEST (TPM_ST)(0x8029)
+
+// Table 19 -- TPM_SU Constants <I>
+typedef u16 TPM_SU;
+
+#define TPM_SU_CLEAR (TPM_SU)(0x0000)
+#define TPM_SU_STATE (TPM_SU)(0x0001)
+
+// Table 21 -- TPM_CAP Constants <I/O,S>
+typedef u32 TPM_CAP;
+
+#define TPM_CAP_FIRST (TPM_CAP)(0x00000000)
+#define TPM_CAP_ALGS (TPM_CAP)(0x00000000)
+#define TPM_CAP_HANDLES (TPM_CAP)(0x00000001)
+#define TPM_CAP_COMMANDS (TPM_CAP)(0x00000002)
+#define TPM_CAP_PP_COMMANDS (TPM_CAP)(0x00000003)
+#define TPM_CAP_AUDIT_COMMANDS (TPM_CAP)(0x00000004)
+#define TPM_CAP_PCRS (TPM_CAP)(0x00000005)
+#define TPM_CAP_TPM_PROPERTIES (TPM_CAP)(0x00000006)
+#define TPM_CAP_PCR_PROPERTIES (TPM_CAP)(0x00000007)
+#define TPM_CAP_ECC_CURVES (TPM_CAP)(0x00000008)
+#define TPM_CAP_LAST (TPM_CAP)(0x00000008)
+#define TPM_CAP_VENDOR_PROPERTY (TPM_CAP)(0x00000100)
+
+// Table 25 -- Handles Types <I/O>
+typedef u32 TPM_HANDLE;
+typedef u8 TPM_HT;
+
+#define TPM_HT_PCR (TPM_HT)(0x00)
+#define TPM_HT_NV_INDEX (TPM_HT)(0x01)
+#define TPM_HT_HMAC_SESSION (TPM_HT)(0x02)
+#define TPM_HT_LOADED_SESSION (TPM_HT)(0x02)
+#define TPM_HT_POLICY_SESSION (TPM_HT)(0x03)
+#define TPM_HT_ACTIVE_SESSION (TPM_HT)(0x03)
+#define TPM_HT_PERMANENT (TPM_HT)(0x40)
+#define TPM_HT_TRANSIENT (TPM_HT)(0x80)
+#define TPM_HT_PERSISTENT (TPM_HT)(0x81)
+
+// Table 27 -- TPM_RH Constants <I,S>
+typedef u32 TPM_RH;
+
+#define TPM_RH_FIRST (TPM_RH)(0x40000000)
+#define TPM_RH_SRK (TPM_RH)(0x40000000)
+#define TPM_RH_OWNER (TPM_RH)(0x40000001)
+#define TPM_RH_REVOKE (TPM_RH)(0x40000002)
+#define TPM_RH_TRANSPORT (TPM_RH)(0x40000003)
+#define TPM_RH_OPERATOR (TPM_RH)(0x40000004)
+#define TPM_RH_ADMIN (TPM_RH)(0x40000005)
+#define TPM_RH_EK (TPM_RH)(0x40000006)
+#define TPM_RH_NULL (TPM_RH)(0x40000007)
+#define TPM_RH_UNASSIGNED (TPM_RH)(0x40000008)
+#define TPM_RS_PW (TPM_RH)(0x40000009)
+#define TPM_RH_LOCKOUT (TPM_RH)(0x4000000A)
+#define TPM_RH_ENDORSEMENT (TPM_RH)(0x4000000B)
+#define TPM_RH_PLATFORM (TPM_RH)(0x4000000C)
+#define TPM_RH_LAST (TPM_RH)(0x4000000C)
+
+// Table 29 -- TPMA_ALGORITHM Bits <I/O>
+typedef struct {
+ unsigned int asymmetric : 1;
+ unsigned int symmetric : 1;
+ unsigned int hash : 1;
+ unsigned int object : 1;
+ unsigned int reserved5 : 4;
+ unsigned int signing : 1;
+ unsigned int encrypting : 1;
+ unsigned int method : 1;
+ unsigned int reserved9 : 21;
+} TPMA_ALGORITHM ;
+
+// Table 30 -- TPMA_OBJECT Bits <I/O>
+typedef struct {
+ unsigned int reserved1 : 1;
+ unsigned int fixedTPM : 1;
+ unsigned int stClear : 1;
+ unsigned int reserved4 : 1;
+ unsigned int fixedParent : 1;
+ unsigned int sensitiveDataOrigin : 1;
+ unsigned int userWithAuth : 1;
+ unsigned int adminWithPolicy : 1;
+ unsigned int reserved9 : 2;
+ unsigned int noDA : 1;
+ unsigned int encryptedDuplication : 1;
+ unsigned int reserved12 : 4;
+ unsigned int restricted : 1; // Start of 2nd dword
+ unsigned int decrypt : 1;
+ unsigned int sign : 1;
+ unsigned int reserved16 : 13;
+} TPMA_OBJECT ;
+
+// Table 31 -- TPMA_SESSION Bits <I/O>
+typedef struct {
+ unsigned int continueSession : 1;
+ unsigned int auditExclusive : 1;
+ unsigned int auditReset : 1;
+ unsigned int reserved4 : 2;
+ unsigned int decrypt : 1;
+ unsigned int encrypt : 1;
+ unsigned int audit : 1;
+} TPMA_SESSION;
+
+// Table 32 -- TPMA_LOCALITY Bits <I/O>
+typedef struct {
+ unsigned int TPM_LOC_ZERO : 1;
+ unsigned int TPM_LOC_ONE : 1;
+ unsigned int TPM_LOC_TWO : 1;
+ unsigned int TPM_LOC_THREE : 1;
+ unsigned int TPM_LOC_FOUR : 1;
+ unsigned int reserved6 : 3;
+} TPMA_LOCALITY;
+
+// Table 66 -- TPMU_HA Union <I/O,S>
+typedef union {
+#ifdef TPM_ALG_SHA1
+ u8 sha1[SHA1_DIGEST_SIZE];
+#endif
+#ifdef TPM_ALG_SHA256
+ u8 sha256[SHA256_DIGEST_SIZE];
+#endif
+#ifdef TPM_ALG_SM3_256
+ u8 sm3_256[SM3_256_DIGEST_SIZE];
+#endif
+#ifdef TPM_ALG_SHA384
+ u8 sha384[SHA384_DIGEST_SIZE];
+#endif
+#ifdef TPM_ALG_SHA512
+ u8 sha512[SHA512_DIGEST_SIZE];
+#endif
+} TPMU_HA ;
+
+// Table 67 -- TPMT_HA Structure <I/O>
+typedef struct {
+ u16 hash_alg;
+ TPMU_HA digest;
+} TPMT_HA;
+
+// Table 68 -- TPM2B_DIGEST Structure <I/O>
+typedef struct {
+ u16 size;
+ u8 buffer[sizeof(TPMU_HA)];
+} DIGEST_2B;
+
+typedef union {
+ DIGEST_2B t;
+ TPM2B b;
+} TPM2B_DIGEST;
+
+// Table 69 -- TPM2B_DATA Structure <I/O>
+typedef struct {
+ u16 size;
+ u8 buffer[sizeof(TPMT_HA)];
+} DATA_2B;
+
+typedef union {
+ DATA_2B t;
+ TPM2B b;
+} TPM2B_DATA;
+
+// Table 70 -- TPM2B_NONCE Types <I/O>
+typedef TPM2B_DIGEST TPM2B_NONCE;
+
+// Table 71 -- TPM2B_AUTH Types <I/O>
+typedef TPM2B_DIGEST TPM2B_AUTH;
+
+// Table 73 -- TPM2B_EVENT Structure <I/O>
+typedef struct {
+ u16 size;
+ u8 buffer[1024];
+} EVENT_2B;
+
+typedef union {
+ EVENT_2B t;
+ TPM2B b;
+} TPM2B_EVENT;
+
+// Table 74 -- TPM2B_MAX_BUFFER Structure <I/O>
+typedef struct {
+ u16 size;
+ u8 buffer[MAX_DIGEST_BUFFER];
+} MAX_BUFFER_2B;
+
+typedef union {
+ MAX_BUFFER_2B t;
+ TPM2B b;
+} TPM2B_MAX_BUFFER;
+
+// Table 75 -- TPM2B_MAX_NV_BUFFER Structure <I/O>
+typedef struct {
+ u16 size;
+ u8 buffer[MAX_NV_INDEX_SIZE];
+} MAX_NV_BUFFER_2B;
+
+typedef union {
+ MAX_NV_BUFFER_2B t;
+ TPM2B b;
+} TPM2B_MAX_NV_BUFFER;
+
+// Table 79 -- TPMU_NAME Structure
+typedef union {
+ TPMT_HA digest;
+ u32 handle;
+} TPMU_NAME ;
+
+// Table 79 -- TPM2B_NAME Structure <I/O>
+typedef struct {
+ u16 size;
+ u8 name[sizeof(TPMU_NAME)];
+} NAME_2B;
+
+typedef union {
+ NAME_2B t;
+ TPM2B b;
+} TPM2B_NAME;
+
+// Table 80 -- TPMS_PCR_SELECTION Structure <I/O>
+typedef struct {
+ u16 hash;
+ u8 size_of_select;
+ u8 pcr_select[PCR_SELECT_MAX];
+} TPMS_PCR_SELECTION;
+
+// Table 84 -- TPMT_TK_CREATION Structure <I/O>
+typedef struct {
+ u16 tag;
+ u32 hierarchy;
+ TPM2B_DIGEST digest;
+} TPMT_TK_CREATION;
+
+// Table 86 -- TPMT_TK_HASHCHECK Structure <I/O>
+typedef struct {
+ u16 tag;
+ u32 hierarchy;
+ TPM2B_DIGEST digest;
+} TPMT_TK_HASHCHECK;
+
+// Table 88 -- TPMS_ALG_PROPERTY Structure <O,S>
+typedef struct {
+ u16 alg;
+ TPMA_ALGORITHM alg_pro;
+} TPMS_ALG_PROPERTY;
+
+// Table 95 -- TPML_DIGEST Structure <I/O>
+typedef struct {
+ u32 count;
+ TPM2B_DIGEST digests[8];
+} TPML_DIGEST;
+
+// Table 96 -- TPML_DIGEST_VALUES Structure <I/O>
+typedef struct {
+ u32 count;
+ TPMT_HA digests[HASH_COUNT];
+} TPML_DIGEST_VALUES;
+
+// Table 98 -- TPML_PCR_SELECTION Structure <I/O>
+typedef struct {
+ u32 count;
+ TPMS_PCR_SELECTION selections[HASH_COUNT];
+} TPML_PCR_SELECTION;
+
+#define MAX_CAP_DATA (MAX_CAP_BUFFER-sizeof(u32)-sizeof(u32))
+#define MAX_CAP_ALGS (MAX_CAP_DATA/sizeof(TPMS_ALG_PROPERTY))
+// Table 99 -- TPML_ALG_PROPERTY Structure <O,S>
+typedef struct {
+ u32 count;
+ TPMS_ALG_PROPERTY alg_pros[MAX_CAP_ALGS];
+} TPML_ALG_PROPERTY;
+
+// Table 103 -- TPMU_CAPABILITIES Union <O,S>
+typedef union {
+ TPML_ALG_PROPERTY algs;
+} TPMU_CAPABILITIES;
+
+// Table 104 -- TPMS_CAPABILITY_DATA Structure <O,S>
+typedef struct {
+ u32 capability;
+ TPMU_CAPABILITIES data;
+} TPMS_CAPABILITY_DATA;
+
+// Table 122 -- TPMU_SYM_KEY_BITS Union <I/O>
+typedef union {
+#ifdef TPM_ALG_AES
+ u16 aes;
+#endif
+#ifdef TPM_ALG_SM4
+ u16 sm4;
+#endif
+ u16 sym;
+#ifdef TPM_ALG_XOR
+ u16 xor;
+#endif
+} TPMU_SYM_KEY_BITS ;
+
+// Table 122 -- TPMU_SYM_MODE Union <I/O>
+typedef union {
+#ifdef TPM_ALG_AES
+ u16 aes;
+#endif
+#ifdef TPM_ALG_SM4
+ u16 sm4;
+#endif
+ u16 sym;
+} TPMU_SYM_MODE ;
+
+// Table 126 -- TPMT_SYM_DEF_OBJECT Structure <I/O>
+typedef struct {
+ u16 alg;
+ TPMU_SYM_KEY_BITS key_bits;
+ TPMU_SYM_MODE mode;
+} TPMT_SYM_DEF_OBJECT;
+
+// Table 126 -- TPM2B_SYM_KEY Structure <I/O>
+typedef struct {
+ u16 size;
+ u8 buffer[MAX_SYM_KEY_BYTES];
+} SYM_KEY_2B;
+
+typedef union {
+ SYM_KEY_2B t;
+ TPM2B b;
+} TPM2B_SYM_KEY;
+
+// Table 129 -- TPM2B_SENSITIVE_DATA Structure <I/O>
+typedef struct {
+ u16 size;
+ u8 buffer[MAX_SYM_DATA];
+} SENSITIVE_DATA_2B;
+
+typedef union {
+ SENSITIVE_DATA_2B t;
+ TPM2B b;
+} TPM2B_SENSITIVE_DATA;
+
+// Table 130 -- TPMS_SENSITIVE_CREATE Structure <I>
+typedef struct {
+ TPM2B_AUTH user_auth;
+ TPM2B_SENSITIVE_DATA data;
+} TPMS_SENSITIVE_CREATE;
+
+// Table 131 -- TPM2B_SENSITIVE_CREATE Structure <I,S>
+typedef struct {
+ u16 size;
+ TPMS_SENSITIVE_CREATE sensitive;
+} SENSITIVE_CREATE_2B;
+
+typedef union {
+ SENSITIVE_CREATE_2B t;
+ TPM2B b;
+} TPM2B_SENSITIVE_CREATE;
+
+// Table 132 -- TPMS_SCHEME_SIGHASH Structure <I/O>
+typedef struct {
+ u16 hash_alg;
+} TPMS_SCHEME_SIGHASH;
+
+// Table 134 -- HMAC_SIG_SCHEME Types <I/O>
+typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_HMAC;
+
+// Table 135 -- TPMS_SCHEME_XOR Structure <I/O>
+typedef struct {
+ u16 hash_alg;
+ u16 kdf;
+} TPMS_SCHEME_XOR;
+
+// Table 136 -- TPMU_SCHEME_KEYEDHASH Union <I/O,S>
+typedef union {
+#ifdef TPM_ALG_HMAC
+ TPMS_SCHEME_HMAC hmac;
+#endif
+#ifdef TPM_ALG_XOR
+ TPMS_SCHEME_XOR xor;
+#endif
+
+} TPMU_SCHEME_KEYEDHASH;
+
+// Table 137 -- TPMT_KEYEDHASH_SCHEME Structure <I/O>
+typedef struct {
+ u16 scheme;
+ TPMU_SCHEME_KEYEDHASH details;
+} TPMT_KEYEDHASH_SCHEME;
+
+// Table 138 -- RSA_SIG_SCHEMES Types <I/O>
+typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_RSASSA;
+typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_RSAPSS;
+
+// Table 139 -- ECC_SIG_SCHEMES Types <I/O>
+typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_ECDSA;
+typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_SM2;
+typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_ECSCHNORR;
+
+// Table 140 -- TPMS_SCHEME_ECDAA Structure <I/O>
+typedef struct {
+ u16 hash_alg;
+ u16 count;
+} TPMS_SCHEME_ECDAA;
+
+// Table 141 -- TPMU_SIG_SCHEME Union <I/O,S>
+typedef union {
+#ifdef TPM_ALG_RSASSA
+ TPMS_SCHEME_RSASSA rsassa;
+#endif
+#ifdef TPM_ALG_RSAPSS
+ TPMS_SCHEME_RSAPSS rsapss;
+#endif
+#ifdef TPM_ALG_ECDSA
+ TPMS_SCHEME_ECDSA ecdsa;
+#endif
+#ifdef TPM_ALG_SM2
+ TPMS_SCHEME_SM2 sm2;
+#endif
+#ifdef TPM_ALG_ECDAA
+ TPMS_SCHEME_ECDAA ecdaa;
+#endif
+#ifdef TPM_ALG_ECSCHNORR
+ TPMS_SCHEME_ECSCHNORR ec_schnorr;
+#endif
+#ifdef TPM_ALG_HMAC
+ TPMS_SCHEME_HMAC hmac;
+#endif
+ TPMS_SCHEME_SIGHASH any;
+
+} TPMU_SIG_SCHEME ;
+
+// Table 143 -- TPMS_SCHEME_OAEP Structure <I/O>
+typedef struct {
+ u16 hash_alg;
+} TPMS_SCHEME_OAEP;
+
+// Table 145 -- TPMS_SCHEME_MGF1 Structure <I/O>
+typedef struct {
+ u16 hash_alg;
+} TPMS_SCHEME_MGF1;
+
+// Table 146 -- TPMS_SCHEME_KDF1_SP800_56a Structure <I/O>
+typedef struct {
+ u16 hash_alg;
+} TPMS_SCHEME_KDF1_SP800_56a;
+
+// Table 147 -- TPMS_SCHEME_KDF2 Structure <I/O>
+typedef struct {
+ u16 hash_alg;
+} TPMS_SCHEME_KDF2;
+
+// Table 148 -- TPMS_SCHEME_KDF1_SP800_108 Structure <I/O>
+typedef struct {
+ u16 hash_alg;
+} TPMS_SCHEME_KDF1_SP800_108;
+
+// Table 149 -- TPMU_KDF_SCHEME Union <I/O,S>
+typedef union {
+#ifdef TPM_ALG_MGF1
+ TPMS_SCHEME_MGF1 mgf1;
+#endif
+#ifdef TPM_ALG_KDF1_SP800_56a
+ TPMS_SCHEME_KDF1_SP800_56a kdf1_SP800_56a;
+#endif
+#ifdef TPM_ALG_KDF2
+ TPMS_SCHEME_KDF2 kdf2;
+#endif
+#ifdef TPM_ALG_KDF1_SP800_108
+ TPMS_SCHEME_KDF1_SP800_108 kdf1_sp800_108;
+#endif
+} TPMU_KDF_SCHEME ;
+
+// Table 150 -- TPMT_KDF_SCHEME Structure <I/O>
+typedef struct {
+ u16 scheme;
+ TPMU_KDF_SCHEME details;
+} TPMT_KDF_SCHEME;
+
+// Table 152 -- TPMU_ASYM_SCHEME Union <I/O>
+typedef union {
+#ifdef TPM_ALG_RSASSA
+ TPMS_SCHEME_RSASSA rsassa;
+#endif
+#ifdef TPM_ALG_RSAPSS
+ TPMS_SCHEME_RSAPSS rsapss;
+#endif
+#ifdef TPM_ALG_OAEP
+ TPMS_SCHEME_OAEP oaep;
+#endif
+#ifdef TPM_ALG_ECDSA
+ TPMS_SCHEME_ECDSA ecdsa;
+#endif
+#ifdef TPM_ALG_SM2
+ TPMS_SCHEME_SM2 sm2;
+#endif
+#ifdef TPM_ALG_ECDAA
+ TPMS_SCHEME_ECDAA ecdaa;
+#endif
+#ifdef TPM_ALG_ECSCHNORR
+ TPMS_SCHEME_ECSCHNORR ec_schnorr;
+#endif
+ TPMS_SCHEME_SIGHASH any;
+
+} TPMU_ASYM_SCHEME;
+
+// Table 153 -- TPMT_ASYM_SCHEME Structure <>
+typedef struct {
+ u16 scheme;
+ TPMU_ASYM_SCHEME details;
+} TPMT_ASYM_SCHEME;
+
+// Table 155 -- TPMT_RSA_SCHEME Structure <I/O>
+typedef struct {
+ u16 scheme;
+ TPMU_ASYM_SCHEME details;
+} TPMT_RSA_SCHEME;
+
+// Table 158 -- TPM2B_PUBLIC_KEY_RSA Structure <I/O>
+typedef struct {
+ u16 size;
+ u8 buffer[MAX_RSA_KEY_BYTES];
+} PUBLIC_KEY_RSA_2B;
+
+typedef union {
+ PUBLIC_KEY_RSA_2B t;
+ TPM2B b;
+} TPM2B_PUBLIC_KEY_RSA;
+
+// Table 160 -- TPM2B_PRIVATE_KEY_RSA Structure <I/O>
+typedef struct {
+ u16 size;
+ u8 buffer[MAX_RSA_KEY_BYTES/2];
+} PRIVATE_KEY_RSA_2B;
+
+typedef union {
+ PRIVATE_KEY_RSA_2B t;
+ TPM2B b;
+} TPM2B_PRIVATE_KEY_RSA;
+
+// Table 161 -- TPM2B_ECC_PARAMETER Structure <I/O>
+typedef struct {
+ u16 size;
+ u8 buffer[MAX_ECC_KEY_BYTES];
+} ECC_PARAMETER_2B;
+
+typedef union {
+ ECC_PARAMETER_2B t;
+ TPM2B b;
+} TPM2B_ECC_PARAMETER;
+
+// Table 162 -- TPMS_ECC_POINT Structure <I/O>
+typedef struct {
+ TPM2B_ECC_PARAMETER x;
+ TPM2B_ECC_PARAMETER y;
+} TPMS_ECC_POINT;
+
+// Table 166 -- TPMT_ECC_SCHEME Structure <I/O>
+typedef struct {
+ u16 scheme;
+ TPMU_SIG_SCHEME details;
+} TPMT_ECC_SCHEME;
+
+// Table 176 -- TPMU_PUBLIC_ID Union <I/O,S>
+typedef union {
+#ifdef TPM_ALG_KEYEDHASH
+ TPM2B_DIGEST keyed_hash;
+#endif
+#ifdef TPM_ALG_SYMCIPHER
+ TPM2B_DIGEST sym;
+#endif
+#ifdef TPM_ALG_RSA
+ TPM2B_PUBLIC_KEY_RSA rsa;
+#endif
+#ifdef TPM_ALG_ECC
+ TPMS_ECC_POINT ecc;
+#endif
+} TPMU_PUBLIC_ID;
+
+// Table 177 -- TPMS_KEYEDHASH_PARMS Structure <I/O>
+typedef struct {
+ TPMT_KEYEDHASH_SCHEME scheme;
+} TPMS_KEYEDHASH_PARMS;
+
+// Table 178 -- TPMS_ASYM_PARMS Structure <I/O>
+typedef struct {
+ TPMT_SYM_DEF_OBJECT symmetric;
+ TPMT_ASYM_SCHEME scheme;
+} TPMS_ASYM_PARMS;
+
+// Table 179 -- TPMS_RSA_PARMS Structure <I/O>
+typedef struct {
+ TPMT_SYM_DEF_OBJECT symmetric;
+ TPMT_RSA_SCHEME scheme;
+ u16 key_bits;
+ u32 exponent;
+} TPMS_RSA_PARMS;
+
+// Table 180 -- TPMS_ECC_PARMS Structure <I/O>
+typedef struct {
+ TPMT_SYM_DEF_OBJECT symmetric;
+ TPMT_ECC_SCHEME scheme;
+ u16 curve_id;
+ TPMT_KDF_SCHEME kdf;
+} TPMS_ECC_PARMS;
+
+// Table 181 -- TPMU_PUBLIC_PARMS Union <I/O,S>
+typedef union {
+#ifdef TPM_ALG_KEYEDHASH
+ TPMS_KEYEDHASH_PARMS keyed_hash;
+#endif
+#ifdef TPM_ALG_SYMCIPHER
+ TPMT_SYM_DEF_OBJECT sym;
+#endif
+#ifdef TPM_ALG_RSA
+ TPMS_RSA_PARMS rsa;
+#endif
+#ifdef TPM_ALG_ECC
+ TPMS_ECC_PARMS ecc;
+#endif
+ TPMS_ASYM_PARMS asym;
+
+} TPMU_PUBLIC_PARMS;
+
+// Table 184 -- TPMT_PUBLIC Structure <I/O>
+typedef struct {
+ u16 type;
+ u16 name_alg;
+ TPMA_OBJECT object_attr;
+ TPM2B_DIGEST auth_policy;
+ TPMU_PUBLIC_PARMS param;
+ TPMU_PUBLIC_ID unique;
+} TPMT_PUBLIC;
+
+// Table 185 -- TPM2B_PUBLIC Structure <I/O>
+typedef struct {
+ u16 size;
+ TPMT_PUBLIC public_area;
+} PUBLIC_2B;
+
+typedef union {
+ PUBLIC_2B t;
+ TPM2B b;
+} TPM2B_PUBLIC;
+
+// Table 186 -- TPMU_SENSITIVE_COMPOSITE Union <I/O,S>
+typedef union {
+#ifdef TPM_ALG_RSA
+ TPM2B_PRIVATE_KEY_RSA rsa;
+#endif
+#ifdef TPM_ALG_ECC
+ TPM2B_ECC_PARAMETER ecc;
+#endif
+#ifdef TPM_ALG_KEYEDHASH
+ TPM2B_SENSITIVE_DATA bits;
+#endif
+#ifdef TPM_ALG_SYMCIPHER
+ TPM2B_SYM_KEY sym;
+#endif
+ TPM2B_SENSITIVE_DATA any;
+
+} TPMU_SENSITIVE_COMPOSITE ;
+
+// Table 187 -- TPMT_SENSITIVE Structure <I/O>
+typedef struct {
+ u16 type;
+ TPM2B_AUTH auth_value;
+ TPM2B_DIGEST seedValue;
+ TPMU_SENSITIVE_COMPOSITE sensitive;
+} TPMT_SENSITIVE;
+
+// Table 189 -- _PRIVATE Structure <>
+typedef struct {
+ TPM2B_DIGEST integrity_outer;
+ TPM2B_DIGEST integrity_inner;
+ TPMT_SENSITIVE sensitive;
+} _PRIVATE;
+
+// Table 190 -- TPM2B_PRIVATE Structure <I/O,S>
+typedef struct {
+ u16 size;
+ u8 buffer[sizeof(_PRIVATE)];
+} PRIVATE_2B;
+
+typedef union {
+ PRIVATE_2B t;
+ TPM2B b;
+} TPM2B_PRIVATE;
+
+// Table 195 -- TPMA_NV Bits <I/O>
+typedef struct {
+ unsigned int TPMA_NV_PPWRITE : 1;
+ unsigned int TPMA_NV_OWNERWRITE : 1;
+ unsigned int TPMA_NV_AUTHWRITE : 1;
+ unsigned int TPMA_NV_POLICYWRITE : 1;
+ unsigned int TPMA_NV_COUNTER : 1;
+ unsigned int TPMA_NV_BITS : 1;
+ unsigned int TPMA_NV_EXTEND : 1;
+ unsigned int reserved8 : 3;
+ unsigned int TPMA_NV_POLICY_DELETE : 1;
+ unsigned int TPMA_NV_WRITELOCKED : 1;
+ unsigned int TPMA_NV_WRITEALL : 1;
+ unsigned int TPMA_NV_WRITEDEFINE : 1;
+ unsigned int TPMA_NV_WRITE_STCLEAR : 1;
+ unsigned int TPMA_NV_GLOBALLOCK : 1;
+ unsigned int TPMA_NV_PPREAD : 1;
+ unsigned int TPMA_NV_OWNERREAD : 1;
+ unsigned int TPMA_NV_AUTHREAD : 1;
+ unsigned int TPMA_NV_POLICYREAD : 1;
+ unsigned int reserved19 : 5;
+ unsigned int TPMA_NV_NO_DA : 1;
+ unsigned int TPMA_NV_ORDERLY : 1;
+ unsigned int TPMA_NV_CLEAR_STCLEAR : 1;
+ unsigned int TPMA_NV_READLOCKED : 1;
+ unsigned int TPMA_NV_WRITTEN : 1;
+ unsigned int TPMA_NV_PLATFORMCREATE : 1;
+ unsigned int TPMA_NV_READ_STCLEAR : 1;
+} TPMA_NV ;
+
+// Table 196 -- TPMS_NV_PUBLIC Structure <I/O>
+typedef struct {
+ u32 index;
+ u16 name_alg;
+ TPMA_NV attr;
+ TPM2B_DIGEST auth_policy;
+ u16 data_size;
+} TPMS_NV_PUBLIC;
+
+// Table 197 -- TPM2B_NV_PUBLIC Structure <I/O>
+typedef struct {
+ u16 size;
+ TPMS_NV_PUBLIC nv_public;
+} NV_PUBLIC_2B;
+
+typedef union {
+ NV_PUBLIC_2B t;
+ TPM2B b;
+} TPM2B_NV_PUBLIC;
+
+// Table 203 -- TPMS_CREATION_DATA Structure <O,S>
+typedef struct {
+ TPML_PCR_SELECTION pcr_select;
+ TPM2B_DIGEST pcr_digest;
+ TPMA_LOCALITY locality;
+ u16 parent_name_alg;
+ TPM2B_NAME parent_name;
+ TPM2B_NAME parent_qualified_name;
+ TPM2B_DATA outside_info;
+} TPMS_CREATION_DATA;
+
+// Table 204 -- TPM2B_CREATION_DATA Structure <O,S>
+typedef struct {
+ u16 size;
+ TPMS_CREATION_DATA data;
+} CREATION_DATA_2B;
+
+typedef union {
+ CREATION_DATA_2B t;
+ TPM2B b;
+} TPM2B_CREATION_DATA;
+
+
+#define MAX_SESSIONS 3
+
+// Input structure for session data for a single session,
+typedef struct {
+ u32 session_handle;
+ TPM2B_NONCE nonce;
+ TPMA_SESSION session_attr;
+ TPM2B_AUTH hmac;
+} TPM_CMD_SESSION_DATA_IN ;
+
+// Input structure for sessions data.
+typedef struct {
+ u8 num_sessions;
+ TPM_CMD_SESSION_DATA_IN sessions[MAX_SESSION_NUM];
+} TPM_CMD_SESSIONS_IN;
+
+// Output structure for session data for a single session.
+typedef struct {
+ TPM2B_NONCE nonce;
+ TPMA_SESSION session_attr;
+ TPM2B_AUTH hmac;
+} TPM_CMD_SESSION_DATA_OUT;
+
+// Output structure for sessions data.
+typedef struct {
+ u8 num_sessions;
+ TPM_CMD_SESSION_DATA_OUT sessions[MAX_SESSION_NUM];
+} TPM_CMD_SESSIONS_OUT;
+
+
+/*
+ * command parameter related structure
+ */
+
+typedef struct {
+ TPML_PCR_SELECTION pcr_selection;
+} tpm_pcr_read_in;
+
+typedef struct {
+ u32 pcr_update_counter;
+ TPML_PCR_SELECTION pcr_selection;
+ TPML_DIGEST pcr_values;
+} tpm_pcr_read_out;
+
+typedef struct {
+ u32 pcr_handle;
+ TPM_CMD_SESSIONS_IN sessions;
+ TPML_DIGEST_VALUES digests;
+} tpm_pcr_extend_in;
+
+typedef struct {
+ TPM_CMD_SESSIONS_OUT sessions;
+} tpm_pcr_extend_out;
+
+typedef struct {
+ u32 pcr_handle;
+ TPM_CMD_SESSIONS_IN sessions;
+ TPM2B_EVENT data;
+} tpm_pcr_event_in;
+
+typedef struct {
+ TPML_DIGEST_VALUES digests;
+ TPM_CMD_SESSIONS_OUT sessions;
+} tpm_pcr_event_out;
+
+typedef struct {
+ u32 pcr_handle;
+ TPM_CMD_SESSIONS_IN sessions;
+} tpm_pcr_reset_in;
+
+typedef struct {
+ TPM_CMD_SESSIONS_OUT sessions;
+} tpm_pcr_reset_out;
+
+typedef struct {
+ TPM2B_AUTH auth;
+ u16 hash_alg;
+} tpm_sequence_start_in;
+
+typedef struct {
+ u32 handle;
+} tpm_sequence_start_out;
+
+typedef struct {
+ u32 handle;
+ TPM_CMD_SESSIONS_IN sessions;
+ TPM2B_MAX_BUFFER buf;
+} tpm_sequence_update_in;
+
+typedef struct {
+ TPM_CMD_SESSIONS_OUT sessions;
+} tpm_sequence_update_out;
+
+typedef struct {
+ u32 pcr_handle;
+ u32 seq_handle;
+ TPM_CMD_SESSIONS_IN sessions;
+ TPM2B_MAX_BUFFER buf;
+} tpm_sequence_complete_in;
+
+typedef struct {
+ TPML_DIGEST_VALUES results;
+ TPM_CMD_SESSIONS_OUT sessions;
+} tpm_sequence_complete_out;
+
+typedef struct {
+ u32 seq_handle;
+ TPM_CMD_SESSIONS_IN sessions;
+ TPM2B_MAX_BUFFER buf;
+ u32 hierarchy;
+} tpm_sequence_complete2_in;
+
+typedef struct {
+ TPML_DIGEST_VALUES results;
+ TPMT_TK_HASHCHECK validation;
+ TPM_CMD_SESSIONS_OUT sessions;
+} tpm_sequence_complete2_out;
+
+typedef struct {
+ u32 handle;
+ u32 index;
+ TPM_CMD_SESSIONS_IN sessions;
+ u16 size;
+ u16 offset;
+} tpm_nv_read_in;
+
+typedef struct {
+ TPM2B_MAX_NV_BUFFER data;
+ TPM_CMD_SESSIONS_OUT sessions;
+} tpm_nv_read_out;
+
+typedef struct {
+ u32 handle;
+ u32 index;
+ TPM_CMD_SESSIONS_IN sessions;
+ TPM2B_MAX_NV_BUFFER data;
+ u16 offset;
+} tpm_nv_write_in;
+
+typedef struct {
+ TPM_CMD_SESSIONS_OUT sessions;
+} tpm_nv_write_out;
+
+typedef struct {
+ u32 handle;
+ TPM_CMD_SESSIONS_IN sessions;
+ TPM2B_AUTH auth;
+ TPM2B_NV_PUBLIC public_info;
+} tpm_nv_define_space_in;
+
+typedef struct {
+ TPM_CMD_SESSIONS_OUT sessions;
+} tpm_nv_define_space_out;
+
+typedef struct {
+ u32 handle;
+ u32 index;
+ TPM_CMD_SESSIONS_IN sessions;
+} tpm_nv_undefine_space_in;
+
+typedef struct {
+ TPM_CMD_SESSIONS_OUT sessions;
+} tpm_nv_undefine_space_out;
+
+typedef struct {
+ u32 index;
+} tpm_nv_read_public_in;
+
+typedef struct {
+ TPM2B_NV_PUBLIC nv_public;
+ TPM2B_NAME nv_name;
+} tpm_nv_read_public_out;
+
+typedef struct {
+ u16 bytes_req;
+} tpm_get_random_in;
+
+typedef struct {
+ TPM2B_DIGEST random_bytes;
+} tpm_get_random_out;
+
+typedef struct {
+ u32 capability;
+ u32 property;
+ u32 property_count;
+} tpm_get_capability_in;
+
+typedef struct {
+ u8 more_data;
+ TPMS_CAPABILITY_DATA data;
+} tpm_get_capability_out;
+
+typedef struct {
+ u32 primary_handle;
+ TPM_CMD_SESSIONS_IN sessions;
+ TPM2B_SENSITIVE_CREATE sensitive;
+ TPM2B_PUBLIC public;
+ TPM2B_DATA outside_info;
+ TPML_PCR_SELECTION creation_pcr;
+} tpm_create_primary_in;
+
+typedef struct {
+ u32 obj_handle;
+ TPM2B_PUBLIC public;
+ TPM2B_CREATION_DATA creation_data;
+ TPM2B_DIGEST creation_hash;
+ TPMT_TK_CREATION creation_ticket;
+ TPM2B_NAME name;
+ TPM_CMD_SESSIONS_OUT sessions;
+} tpm_create_primary_out;
+
+typedef struct {
+ u32 parent_handle;
+ TPM_CMD_SESSIONS_IN sessions;
+ TPM2B_SENSITIVE_CREATE sensitive;
+ TPM2B_PUBLIC public;
+ TPM2B_DATA outside_info;
+ TPML_PCR_SELECTION creation_pcr;
+} tpm_create_in;
+
+typedef struct {
+ TPM2B_PRIVATE private;
+ TPM2B_PUBLIC public;
+ TPM2B_CREATION_DATA creation_data;
+ TPM2B_DIGEST creation_hash;
+ TPMT_TK_CREATION creation_ticket;
+ TPM_CMD_SESSIONS_OUT sessions;
+} tpm_create_out;
+
+typedef struct {
+ u32 parent_handle;
+ TPM_CMD_SESSIONS_IN sessions;
+ TPM2B_PRIVATE private;
+ TPM2B_PUBLIC public;
+} tpm_load_in;
+
+typedef struct {
+ u32 obj_handle;
+ TPM2B_NAME name;
+ TPM_CMD_SESSIONS_OUT sessions;
+} tpm_load_out;
+
+typedef struct {
+ u32 item_handle;
+ TPM_CMD_SESSIONS_IN sessions;
+} tpm_unseal_in;
+
+typedef struct {
+ TPM2B_SENSITIVE_DATA data;
+ TPM_CMD_SESSIONS_OUT sessions;
+} tpm_unseal_out;
+
+
+#endif /* __TPM20_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/txt/acmod.h b/tboot/include/txt/acmod.h
new file mode 100644
index 0000000..33f8b28
--- /dev/null
+++ b/tboot/include/txt/acmod.h
@@ -0,0 +1,195 @@
+/*
+ * acmod.c: support functions for use of Intel(r) TXT Authenticated
+ * Code (AC) Modules
+ *
+ * Copyright (c) 2003-2011, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TXT_ACMOD_H__
+#define __TXT_ACMOD_H__
+
+/*
+ * authenticated code (AC) module header (ver 0.0)
+ */
+
+typedef union {
+ uint16_t _raw;
+ struct {
+ uint16_t reserved : 14;
+ uint16_t pre_production : 1;
+ uint16_t debug_signed : 1;
+ };
+} acm_flags_t;
+
+typedef struct {
+ uint16_t module_type;
+ uint16_t module_subtype;
+ uint32_t header_len;
+ uint32_t header_ver; /* currently 0.0 */
+ uint16_t chipset_id;
+ acm_flags_t flags;
+ uint32_t module_vendor;
+ uint32_t date;
+ uint32_t size;
+ uint16_t txt_svn;
+ uint16_t se_svn;
+ uint32_t code_control;
+ uint32_t error_entry_point;
+ uint32_t gdt_limit;
+ uint32_t gdt_base;
+ uint32_t seg_sel;
+ uint32_t entry_point;
+ uint8_t reserved2[64];
+ uint32_t key_size;
+ uint32_t scratch_size;
+ uint8_t rsa2048_pubkey[256];
+ uint32_t pub_exp;
+ uint8_t rsa2048_sig[256];
+ uint32_t scratch[143];//
+ uint8_t user_area[];
+} acm_hdr_t;
+
+/* value of module_type field */
+#define ACM_TYPE_CHIPSET 0x02
+
+/* value of module_subtype field */
+#define ACM_SUBTYPE_RESET 0x01
+
+/* value of module_vendor field */
+#define ACM_VENDOR_INTEL 0x8086
+
+typedef union {
+ uint32_t _raw;
+ struct {
+ uint32_t ext_policy : 2;
+ uint32_t tpm_family : 4;
+ uint32_t tpm_nv_index_set : 1;
+ uint32_t reserved : 25;
+ };
+} tpm_cap_t;
+
+/* ext_policy field values */
+#define TPM_EXT_POLICY_ILLEGAL 0x00
+#define TPM_EXT_POLICY_ALG_AGILE_CMD 0x01
+#define TPM_EXT_POLICY_EMBEDED_ALGS 0x10
+#define TPM_EXT_POLICY_BOTH 0x11
+
+/* tpm_family field values */
+#define TPM_FAMILY_ILLEGAL 0x0000
+#define TPM_FAMILY_DTPM_12 0x0001
+#define TPM_FAMILY_DTPM_20 0x0010
+#define TPM_FAMILY_DTPM_BOTH 0x0011
+#define TPM_FAMILY_PTT_20 0x1000
+
+typedef struct {
+ tpm_cap_t capabilities;
+ uint16_t count;
+ uint16_t alg_id[];
+} tpm_info_list_t;
+
+typedef struct __packed {
+ uuid_t uuid;
+ uint8_t chipset_acm_type;
+ uint8_t version; /* currently 4 */
+ uint16_t length;
+ uint32_t chipset_id_list;
+ uint32_t os_sinit_data_ver;
+ uint32_t min_mle_hdr_ver;
+ txt_caps_t capabilities;
+ uint8_t acm_ver;
+ uint8_t reserved[3];
+ /* versions >= 4 */
+ uint32_t processor_id_list;
+ /* versions >= 5 */
+ uint32_t tpm_info_list_off;
+} acm_info_table_t;
+
+/* ACM UUID value */
+#define ACM_UUID_V3 {0x7fc03aaa, 0x46a7, 0x18db, 0xac2e, \
+ {0x69, 0x8f, 0x8d, 0x41, 0x7f, 0x5a}}
+
+/* chipset_acm_type field values */
+#define ACM_CHIPSET_TYPE_BIOS 0x00
+#define ACM_CHIPSET_TYPE_SINIT 0x01
+#define ACM_CHIPSET_TYPE_BIOS_REVOC 0x08
+#define ACM_CHIPSET_TYPE_SINIT_REVOC 0x09
+
+typedef struct __packed {
+ uint32_t flags;
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint16_t revision_id;
+ uint16_t reserved;
+ uint32_t extended_id;
+} acm_chipset_id_t;
+
+typedef struct __packed {
+ uint32_t count;
+ acm_chipset_id_t chipset_ids[];
+} acm_chipset_id_list_t;
+
+typedef struct __packed {
+ uint32_t fms;
+ uint32_t fms_mask;
+ uint64_t platform_id;
+ uint64_t platform_mask;
+} acm_processor_id_t;
+
+typedef struct __packed {
+ uint32_t count;
+ acm_processor_id_t processor_ids[];
+} acm_processor_id_list_t;
+
+acm_hdr_t *g_sinit;
+
+void print_txt_caps(const char *prefix, txt_caps_t caps);
+bool is_racm_acmod(const void *acmod_base, uint32_t acmod_size, bool quiet);
+acm_hdr_t *copy_racm(const acm_hdr_t *racm);
+bool verify_racm(const acm_hdr_t *acm_hdr);
+bool is_sinit_acmod(const void *acmod_base, uint32_t acmod_size, bool quiet);
+bool does_acmod_match_platform(const acm_hdr_t* hdr);
+acm_hdr_t *copy_sinit(const acm_hdr_t *sinit);
+bool verify_acmod(const acm_hdr_t *acm_hdr);
+uint32_t get_supported_os_sinit_data_ver(const acm_hdr_t* hdr);
+txt_caps_t get_sinit_capabilities(const acm_hdr_t* hdr);
+tpm_info_list_t *get_tpm_info_list(const acm_hdr_t* hdr);
+void verify_IA32_se_svn_status(const acm_hdr_t *acm_hdr);
+#endif /* __TXT_ACMOD_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/txt/config_regs.h b/tboot/include/txt/config_regs.h
new file mode 100644
index 0000000..4d02ea4
--- /dev/null
+++ b/tboot/include/txt/config_regs.h
@@ -0,0 +1,240 @@
+/*
+ * config_regs.h: Intel(r) TXT configuration register -related definitions
+ *
+ * Copyright (c) 2003-2011, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TXT_CONFIG_REGS_H__
+#define __TXT_CONFIG_REGS_H__
+
+/*
+ * TXT configuration registers (offsets from TXT_{PUB, PRIV}_CONFIG_REGS_BASE)
+ */
+
+#define TXT_PUB_CONFIG_REGS_BASE 0xfed30000
+#define TXT_PRIV_CONFIG_REGS_BASE 0xfed20000
+
+#define TXT_CONFIG_REGS_SIZE (TXT_PUB_CONFIG_REGS_BASE - \
+ TXT_PRIV_CONFIG_REGS_BASE)
+
+/* offsets to config regs (from either public or private _BASE) */
+#define TXTCR_STS 0x0000
+#define TXTCR_ESTS 0x0008
+#define TXTCR_ERRORCODE 0x0030
+#define TXTCR_CMD_RESET 0x0038
+#define TXTCR_CMD_CLOSE_PRIVATE 0x0048
+#define TXTCR_VER_FSBIF 0x0100
+#define TXTCR_DIDVID 0x0110
+#define TXTCR_VER_QPIIF 0x0200
+#define TXTCR_CMD_UNLOCK_MEM_CONFIG 0x0218
+#define TXTCR_SINIT_BASE 0x0270
+#define TXTCR_SINIT_SIZE 0x0278
+#define TXTCR_MLE_JOIN 0x0290
+#define TXTCR_HEAP_BASE 0x0300
+#define TXTCR_HEAP_SIZE 0x0308
+#define TXTCR_MSEG_BASE 0x0310
+#define TXTCR_MSEG_SIZE 0x0318
+#define TXTCR_DPR 0x0330
+#define TXTCR_CMD_OPEN_LOCALITY1 0x0380
+#define TXTCR_CMD_CLOSE_LOCALITY1 0x0388
+#define TXTCR_CMD_OPEN_LOCALITY2 0x0390
+#define TXTCR_CMD_CLOSE_LOCALITY2 0x0398
+#define TXTCR_PUBLIC_KEY 0x0400
+#define TXTCR_CMD_SECRETS 0x08e0
+#define TXTCR_CMD_NO_SECRETS 0x08e8
+#define TXTCR_E2STS 0x08f0
+
+/*
+ * format of ERRORCODE register
+ */
+typedef union {
+ uint64_t _raw;
+ struct {
+ uint64_t type : 30; /* external-specific error code */
+ uint64_t external : 1; /* 0=from proc, 1=from external SW */
+ uint64_t valid : 1; /* 1=valid */
+ };
+} txt_errorcode_t;
+
+/*
+ * format of ESTS register
+ */
+typedef union {
+ uint64_t _raw;
+ struct {
+ uint64_t txt_reset_sts : 1;
+ };
+} txt_ests_t;
+
+/*
+ * format of E2STS register
+ */
+typedef union {
+ uint64_t _raw;
+ struct {
+ uint64_t reserved : 1;
+ uint64_t secrets_sts : 1;
+ };
+} txt_e2sts_t;
+
+/*
+ * format of STS register
+ */
+typedef union {
+ uint64_t _raw;
+ struct {
+ uint64_t senter_done_sts : 1;
+ uint64_t sexit_done_sts : 1;
+ uint64_t reserved1 : 4;
+ uint64_t mem_config_lock_sts : 1;
+ uint64_t private_open_sts : 1;
+ uint64_t reserved2 : 7;
+ uint64_t locality_1_open_sts : 1;
+ uint64_t locality_2_open_sts : 1;
+ };
+} txt_sts_t;
+
+/*
+ * format of DIDVID register
+ */
+typedef union {
+ uint64_t _raw;
+ struct {
+ uint16_t vendor_id;
+ uint16_t device_id;
+ uint16_t revision_id;
+ uint16_t reserved;
+ };
+} txt_didvid_t;
+
+/*
+ * format of VER.FSBIF and VER.QPIIF registers
+ */
+typedef union {
+ uint64_t _raw;
+ struct {
+ uint64_t reserved : 31;
+ uint64_t prod_fused : 1;
+ };
+} txt_ver_fsbif_qpiif_t;
+
+/*
+ * format of DPR register
+ */
+typedef union {
+ uint64_t _raw;
+ struct {
+ uint64_t lock : 1;
+ uint64_t reserved1 : 3;
+ uint64_t size : 8;
+ uint64_t reserved2 : 8;
+ uint64_t top : 12;
+ uint64_t reserved3 : 32;
+ };
+} txt_dpr_t;
+
+/*
+ * RLP JOIN structure for GETSEC[WAKEUP] and MLE_JOIN register
+ */
+typedef struct {
+ uint32_t gdt_limit;
+ uint32_t gdt_base;
+ uint32_t seg_sel; /* cs (ds, es, ss are seg_sel+8) */
+ uint32_t entry_point; /* phys addr */
+} mle_join_t;
+
+/*
+ * format of MSEG header
+ */
+typedef struct {
+ uint32_t revision_id;
+ uint32_t smm_mon_feat;
+ uint32_t gdtr_limit;
+ uint32_t gdtr_base_offset;
+ uint32_t cs_sel;
+ uint32_t eip_offset;
+ uint32_t esp_offset;
+ uint32_t cr3_offset;
+} mseg_hdr_t;
+
+/* TODO these are causing warnings - changed to ull */
+
+/*
+ * fns to read/write TXT config regs
+ */
+
+#ifndef IS_INCLUDED
+static inline uint64_t read_config_reg(uint64_t config_regs_base, uint32_t reg)
+{
+ /* these are MMIO so make sure compiler doesn't optimize */
+ return *(volatile uint64_t *)(unsigned long long)(config_regs_base + reg);
+}
+#endif
+
+static inline void write_config_reg(uint64_t config_regs_base, uint32_t reg,
+ uint64_t val)
+{
+ /* these are MMIO so make sure compiler doesn't optimize */
+ *(volatile uint64_t *)(unsigned long long)(config_regs_base + reg) = val;
+}
+
+static inline uint64_t read_pub_config_reg(uint32_t reg)
+{
+ return read_config_reg(TXT_PUB_CONFIG_REGS_BASE, reg);
+}
+
+static inline void write_pub_config_reg(uint32_t reg, uint64_t val)
+{
+ write_config_reg(TXT_PUB_CONFIG_REGS_BASE, reg, val);
+}
+
+static inline uint64_t read_priv_config_reg(uint32_t reg)
+{
+ return read_config_reg(TXT_PRIV_CONFIG_REGS_BASE, reg);
+}
+
+static inline void write_priv_config_reg(uint32_t reg, uint64_t val)
+{
+ write_config_reg(TXT_PRIV_CONFIG_REGS_BASE, reg, val);
+}
+
+#endif /* __TXT_CONFIG_REGS_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/txt/errorcode.h b/tboot/include/txt/errorcode.h
new file mode 100644
index 0000000..fe85a3c
--- /dev/null
+++ b/tboot/include/txt/errorcode.h
@@ -0,0 +1,105 @@
+/*
+ * errorcode.h: Intel(r) TXT error definitions for ERRORCODE config register
+ *
+ * Copyright (c) 2003-2011, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TXT_ERRORCODE_H__
+#define __TXT_ERRORCODE_H__
+
+/*
+ * error values for processor error codes (ERRORCODE.external = 0)
+ */
+#define TXT_ERR_PROC_LEGACY_SHUTDOWN 0
+#define TXT_ERR_PROC_INVALID_ACM_MEM_TYPE 5
+#define TXT_ERR_PROC_UNSUPPORTED_ACM 6
+#define TXT_ERR_PROC_AUTH_FAIL 7
+#define TXT_ERR_PROC_INVALID_ACM_FORMAT 8
+#define TXT_ERR_PROC_UNEXPECTED_HITM 9
+#define TXT_ERR_PROC_INVALID_EVENT 10
+#define TXT_ERR_PROC_INVALID_JOIN_FORMAT 11
+#define TXT_ERR_PROC_UNRECOVERABLE_MCE 12
+#define TXT_ERR_PROC_VMX_ABORT 13
+#define TXT_ERR_PROC_ACM_CORRUPT 14
+#define TXT_ERR_PROC_INVALID_VIDB_RATIO 15
+
+/*
+ * for SW errors (ERRORCODE.external = 1)
+ */
+typedef union {
+ uint32_t _raw;
+ struct {
+ uint32_t err1 : 15; /* specific to src */
+ uint32_t src : 1; /* 0=ACM, 1=other */
+ uint32_t err2 : 14; /* specific to src */
+ uint32_t external : 1; /* always 1 for this type */
+ uint32_t valid : 1; /* always 1 */
+ };
+} txt_errorcode_sw_t;
+
+/*
+ * ACM errors (txt_errorcode_sw_t.src=0), format of err1+src+err2 fields
+ */
+typedef union __attribute__((packed)){
+ uint32_t _raw;
+ struct __attribute__((packed)){
+ uint32_t acm_type : 4; /* 0000=BIOS ACM, 0001=SINIT, */
+ /* 0010-1111=reserved */
+ uint32_t progress : 6;
+ uint32_t error : 5;
+ uint32_t src : 1; /* above value */
+ union __attribute__((packed)){
+ struct __attribute__((packed)) { /* progress=0x0d, error=1010 */
+ uint32_t tpm_err : 9;
+ uint32_t reserved1 : 5;
+ };
+ struct __attribute__((packed)) { /* progress=0x10 */
+ uint32_t lcp_minor : 6;
+ uint32_t lcp_index : 3;
+ uint32_t reserved2 : 5;
+ };
+ }; /* sub-error */
+ };
+} acmod_error_t;
+
+#endif /* __TXT_ERRORCODE_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/txt/heap.h b/tboot/include/txt/heap.h
new file mode 100644
index 0000000..c4e2d51
--- /dev/null
+++ b/tboot/include/txt/heap.h
@@ -0,0 +1,377 @@
+/*
+ * heap.h: Intel(r) TXT heap definitions
+ *
+ * Copyright (c) 2003-2011, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TXT_HEAP_H__
+#define __TXT_HEAP_H__
+
+/*
+ * Extensible TXT heap data structure
+ */
+
+typedef struct __packed {
+ uint32_t type;
+ uint32_t size;
+ uint8_t data[];
+} heap_ext_data_element_t;
+
+/*
+ * HEAP_END_ELEMENT
+ */
+#define HEAP_EXTDATA_TYPE_END 0
+
+/* size == 8; there is no data[] */
+
+/*
+ * HEAP_BIOS_SPEC_VER_ELEMENT
+ */
+#define HEAP_EXTDATA_TYPE_BIOS_SPEC_VER 1
+
+typedef struct __packed {
+ uint16_t spec_ver_major;
+ uint16_t spec_ver_minor;
+ uint16_t spec_ver_rev;
+} heap_bios_spec_ver_elt_t;
+
+/*
+ * HEAP_ACM_ELEMENT
+ */
+#define HEAP_EXTDATA_TYPE_ACM 2
+
+typedef struct __packed {
+ uint32_t num_acms;
+ uint64_t acm_addrs[];
+} heap_acm_elt_t;
+
+/*
+ * HEAP_CUSTOM_ELEMENT
+ */
+#define HEAP_EXTDATA_TYPE_CUSTOM 4
+
+typedef struct __packed {
+ uuid_t uuid;
+ uint8_t data[];
+} heap_custom_elt_t;
+
+/*
+ * HEAP_EVENT_LOG_POINTER_ELEMENT
+ */
+#define HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR 5
+
+typedef struct __packed {
+ uint64_t event_log_phys_addr;
+} heap_event_log_ptr_elt_t;
+
+typedef struct __packed {
+ uint32_t pcr_index;
+ uint32_t type;
+ sha1_hash_t digest;
+ uint32_t data_size;
+ uint8_t data[];
+} tpm12_pcr_event_t;
+
+#define EVTLOG_SIGNATURE "TXT Event Container\0"
+#define EVTLOG_CNTNR_MAJOR_VER 1
+#define EVTLOG_CNTNR_MINOR_VER 0
+#define EVTLOG_EVT_MAJOR_VER 1
+#define EVTLOG_EVT_MINOR_VER 0
+typedef struct __packed {
+ uint8_t signature[20];
+ uint8_t reserved[12];
+ uint8_t container_ver_major;
+ uint8_t container_ver_minor;
+ uint8_t pcr_event_ver_major;
+ uint8_t pcr_event_ver_minor;
+ uint32_t size;
+ uint32_t pcr_events_offset;
+ uint32_t next_event_offset;
+ tpm12_pcr_event_t pcr_events[];
+} event_log_container_t;
+
+/*
+ * HEAP_EVENT_LOG_POINTER_ELEMENT2
+ */
+#define HEAP_EXTDATA_TYPE_TPM_EVENT_LOG_PTR_2 7
+
+#define DIGEST_ALG_ID_SHA_1 0x00000001
+#define DIGEST_ALG_ID_SHA_256 0x00000002
+#define DIGEST_ALG_ID_SHA_384 0x00000003
+#define DIGEST_ALG_ID_SHA_512 0x00000004
+#define DIGEST_ALG_ID_SM3 0x00000005
+static inline unsigned int get_evtlog_digest_id(uint16_t hash_alg)
+{
+ if ( hash_alg == TB_HALG_SHA1 )
+ return DIGEST_ALG_ID_SHA_1;
+ else if ( hash_alg == TB_HALG_SHA256 )
+ return DIGEST_ALG_ID_SHA_256;
+ else if ( hash_alg == TB_HALG_SM3 )
+ return DIGEST_ALG_ID_SM3;
+ else if ( hash_alg == TB_HALG_SHA384 )
+ return DIGEST_ALG_ID_SHA_384;
+ else if ( hash_alg == TB_HALG_SHA512 )
+ return DIGEST_ALG_ID_SHA_512;
+ else
+ return 0;
+}
+
+typedef struct __packed {
+ uint8_t signature[16];
+ uint32_t revision;
+ uint32_t digest_id;
+ uint32_t digest_size;
+} tpm20_log_descr_t;
+
+typedef struct __packed {
+ uint16_t alg;
+ uint16_t reserved;
+ uint64_t phys_addr;
+ uint32_t size;
+ uint32_t pcr_events_offset;
+ uint32_t next_event_offset;
+} heap_event_log_descr_t;
+
+typedef struct __packed {
+ uint32_t count;
+ heap_event_log_descr_t event_log_descr[];
+} heap_event_log_ptr_elt2_t;
+
+
+/*
+ * data-passing structures contained in TXT heap:
+ * - BIOS
+ * - OS/loader to MLE
+ * - OS/loader to SINIT
+ * - SINIT to MLE
+ */
+
+/*
+ * BIOS structure
+ */
+typedef struct __packed {
+ uint32_t version; /* currently 2-4 */
+ uint32_t bios_sinit_size;
+ uint64_t lcp_pd_base;
+ uint64_t lcp_pd_size;
+ uint32_t num_logical_procs;
+ /* versions >= 3 */
+ uint64_t flags; /* For TPM2, it is divided into sinit_flag and mle_flag */
+ /* versions >= 4 */
+ heap_ext_data_element_t ext_data_elts[];
+} bios_data_t;
+
+/*
+ * OS/loader to MLE structure
+ * - private to tboot (so can be any format we need)
+ */
+#define MAX_LCP_PO_DATA_SIZE 64*1024 /* 64k */
+#define MAX_EVENT_LOG_SIZE 5*4*1024 /* 4k*5 */
+
+typedef struct __packed {
+ uint32_t version; /* currently 3 */
+ mtrr_state_t saved_mtrr_state; /* saved prior to changes for SINIT */
+ uint64_t saved_misc_enable_msr; /* saved prior to SENTER */
+ /* PO policy data */
+ uint8_t lcp_po_data[MAX_LCP_PO_DATA_SIZE];
+ /* buffer for tpm event log */
+ uint8_t event_log_buffer[MAX_EVENT_LOG_SIZE];
+} os_mle_data_t;
+
+#define MIN_OS_SINIT_DATA_VER 4
+#define MAX_OS_SINIT_DATA_VER 7
+#define OS_SINIT_FLAGS_EXTPOL_MASK 0x00000001
+/*
+ * OS/loader to SINIT structure
+ */
+typedef struct __packed {
+ uint32_t version; /* currently 4-7 */
+ uint32_t flags; /* For TPM2: BIT0:= PCR Extend Policy Control */
+ uint64_t mle_ptab;
+ uint64_t mle_size;
+ uint64_t mle_hdr_base;
+ uint64_t vtd_pmr_lo_base;
+ uint64_t vtd_pmr_lo_size;
+ uint64_t vtd_pmr_hi_base;
+ uint64_t vtd_pmr_hi_size;
+ uint64_t lcp_po_base;
+ uint64_t lcp_po_size;
+ txt_caps_t capabilities;
+ /* versions >= 5 */
+ uint64_t efi_rsdt_ptr;
+ /* versions >= 6 */
+ heap_ext_data_element_t ext_data_elts[];
+} os_sinit_data_t;
+
+/*
+ * SINIT to MLE structure
+ */
+#define MDR_MEMTYPE_GOOD 0x00
+#define MDR_MEMTYPE_SMM_OVERLAY 0x01
+#define MDR_MEMTYPE_SMM_NONOVERLAY 0x02
+#define MDR_MEMTYPE_PCIE_CONFIG_SPACE 0x03
+#define MDR_MEMTYPE_PROTECTED 0x04
+
+typedef struct __packed {
+ uint64_t base;
+ uint64_t length;
+ uint8_t mem_type;
+ uint8_t reserved[7];
+} sinit_mdr_t;
+
+typedef struct __packed {
+ uint32_t version; /* currently 6-9 */
+ sha1_hash_t bios_acm_id; /* only for tpm1.2 */
+ uint32_t edx_senter_flags; /* only for tpm1.2 */
+ uint64_t mseg_valid; /* only for tpm1.2 */
+ sha1_hash_t sinit_hash; /* only for tpm1.2 */
+ sha1_hash_t mle_hash; /* only for tpm1.2 */
+ sha1_hash_t stm_hash; /* only for tpm1.2 */
+ sha1_hash_t lcp_policy_hash; /* only for tpm1.2 */
+ uint32_t lcp_policy_control; /* only for tpm1.2 */
+ uint32_t rlp_wakeup_addr;
+ uint32_t reserved;
+ uint32_t num_mdrs;
+ uint32_t mdrs_off;
+ uint32_t num_vtd_dmars;
+ uint32_t vtd_dmars_off;
+ /* versions >= 8 */
+ uint32_t proc_scrtm_status; /* only for tpm1.2 */
+ /* versions >= 9 */
+ heap_ext_data_element_t ext_data_elts[];
+} sinit_mle_data_t;
+
+
+/*
+ * TXT heap data format and field accessor fns
+ */
+
+/*
+ * offset length field
+ * ------ ------ -----
+ * 0 8 bios_data_size
+ * 8 bios_data_size - 8 bios_data
+ *
+ * bios_data_size 8 os_mle_data_size
+ * bios_data_size + os_mle_data_size - 8 os_mle_data
+ * 8
+ *
+ * bios_data_size + 8 os_sinit_data_size
+ * os_mle_data_size
+ * bios_data_size + os_sinit_data_size - 8 os_sinit_data
+ * os_mle_data_size +
+ * 8
+ *
+ * bios_data_size + 8 sinit_mle_data_size
+ * os_mle_data_size +
+ * os_sinit_data_size
+ * bios_data_size + sinit_mle_data_size - 8 sinit_mle_data
+ * os_mle_data_size +
+ * os_sinit_data_size +
+ * 8
+ */
+
+typedef void txt_heap_t;
+
+/* TODO these are causing warnings - changed to ull */
+
+/* this is a common use with annoying casting, so make it an inline */
+static inline txt_heap_t *get_txt_heap(void)
+{
+ return (txt_heap_t *)(unsigned long long)read_pub_config_reg(TXTCR_HEAP_BASE);
+}
+
+static inline uint64_t get_bios_data_size(const txt_heap_t *heap)
+{
+ return *(uint64_t *)heap;
+}
+
+static inline bios_data_t *get_bios_data_start(const txt_heap_t *heap)
+{
+ return (bios_data_t *)((char*)heap + sizeof(uint64_t));
+}
+
+static inline uint64_t get_os_mle_data_size(const txt_heap_t *heap)
+{
+ return *(uint64_t *)(heap + get_bios_data_size(heap));
+}
+
+static inline os_mle_data_t *get_os_mle_data_start(const txt_heap_t *heap)
+{
+ return (os_mle_data_t *)(heap + get_bios_data_size(heap) +
+ sizeof(uint64_t));
+}
+
+static inline uint64_t get_os_sinit_data_size(const txt_heap_t *heap)
+{
+ return *(uint64_t *)(heap + get_bios_data_size(heap) +
+ get_os_mle_data_size(heap));
+}
+
+static inline os_sinit_data_t *get_os_sinit_data_start(const txt_heap_t *heap)
+{
+ return (os_sinit_data_t *)(heap + get_bios_data_size(heap) +
+ get_os_mle_data_size(heap) +
+ sizeof(uint64_t));
+}
+
+static inline uint64_t get_sinit_mle_data_size(const txt_heap_t *heap)
+{
+ return *(uint64_t *)(heap + get_bios_data_size(heap) +
+ get_os_mle_data_size(heap) +
+ get_os_sinit_data_size(heap));
+}
+
+static inline sinit_mle_data_t *get_sinit_mle_data_start(const txt_heap_t *heap)
+{
+ return (sinit_mle_data_t *)(heap + get_bios_data_size(heap) +
+ get_os_mle_data_size(heap) +
+ get_os_sinit_data_size(heap) +
+ sizeof(uint64_t));
+}
+
+uint64_t calc_os_sinit_data_size(uint32_t version);
+bool verify_txt_heap(const txt_heap_t *txt_heap, bool bios_data_only);
+bool verify_bios_data(const txt_heap_t *txt_heap);
+void print_os_sinit_data(const os_sinit_data_t *os_sinit_data);
+
+#endif /* __TXT_HEAP_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/txt/mtrrs.h b/tboot/include/txt/mtrrs.h
new file mode 100644
index 0000000..8b61f6e
--- /dev/null
+++ b/tboot/include/txt/mtrrs.h
@@ -0,0 +1,149 @@
+/*
+ * mtrrs.c: Intel(r) TXT MTRR-related definitions
+ *
+ * Copyright (c) 2003-2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TXT_MTRRS_H__
+#define __TXT_MTRRS_H__
+
+#include <txt/acmod.h>
+
+enum fix_mtrr_t {
+ MTRR_FIX64K_00000 = 0x250,
+ MTRR_FIX16K_80000 = 0x258,
+ MTRR_FIX16K_A0000 = 0x259,
+ MTRR_FIX4K_C0000 = 0x268,
+ MTRR_FIX4K_C8000 = 0x269,
+ MTRR_FIX4K_D0000 = 0x26A,
+ MTRR_FIX4K_D8000 = 0x26B,
+ MTRR_FIX4K_E0000 = 0x26C,
+ MTRR_FIX4K_E8000 = 0x26D,
+ MTRR_FIX4K_F0000 = 0x26E,
+ MTRR_FIX4K_F8000 = 0x26F
+};
+
+typedef union {
+ uint64_t raw;
+ uint8_t type[8];
+} mtrr_fix_types_t;
+
+enum var_mtrr_t {
+ MTRR_PHYS_BASE0_MSR = 0x200,
+ MTRR_PHYS_MASK0_MSR = 0x201,
+ MTRR_PHYS_BASE1_MSR = 0x202,
+ MTRR_PHYS_MASK1_MSR = 0x203,
+ MTRR_PHYS_BASE2_MSR = 0x204,
+ MTRR_PHYS_MASK2_MSR = 0x205,
+ MTRR_PHYS_BASE3_MSR = 0x206,
+ MTRR_PHYS_MASK3_MSR = 0x207,
+ MTRR_PHYS_BASE4_MSR = 0x208,
+ MTRR_PHYS_MASK4_MSR = 0x209,
+ MTRR_PHYS_BASE5_MSR = 0x20A,
+ MTRR_PHYS_MASK5_MSR = 0x20B,
+ MTRR_PHYS_BASE6_MSR = 0x20C,
+ MTRR_PHYS_MASK6_MSR = 0x20D,
+ MTRR_PHYS_BASE7_MSR = 0x20E,
+ MTRR_PHYS_MASK7_MSR = 0x20F
+};
+
+typedef union {
+ uint64_t raw;
+ struct {
+ uint64_t vcnt : 8; /* num variable MTRR pairs */
+ uint64_t fix : 1; /* fixed range MTRRs are supported */
+ uint64_t reserved1 : 1;
+ uint64_t wc : 1; /* write-combining mem type supported */
+ uint64_t reserved2 : 53;
+ };
+} mtrr_cap_t;
+
+typedef union {
+ uint64_t raw;
+ struct {
+ uint64_t type : 8;
+ uint64_t reserved1 : 2;
+ uint64_t fe : 1; /* fixed MTRR enable */
+ uint64_t e : 1; /* (all) MTRR enable */
+ uint64_t reserved2 : 52;
+ };
+} mtrr_def_type_t;
+
+typedef union {
+ uint64_t raw;
+ struct {
+ uint64_t type : 8;
+ uint64_t reserved1 : 4;
+ uint64_t base : 52; /* define as max width and mask w/ */
+ /* MAXPHYADDR when using */
+ };
+} mtrr_physbase_t;
+
+typedef union {
+ uint64_t raw;
+ struct {
+ uint64_t reserved1 : 11;
+ uint64_t v : 1; /* valid */
+ uint64_t mask : 52; /* define as max width and mask w/ */
+ /* MAXPHYADDR when using */
+ };
+} mtrr_physmask_t;
+
+/* current procs only have 8, so this should hold us for a while */
+#define MAX_VARIABLE_MTRRS 16
+
+typedef struct {
+ mtrr_def_type_t mtrr_def_type;
+ unsigned int num_var_mtrrs;
+ mtrr_physbase_t mtrr_physbases[MAX_VARIABLE_MTRRS];
+ mtrr_physmask_t mtrr_physmasks[MAX_VARIABLE_MTRRS];
+} mtrr_state_t;
+
+bool set_mtrrs_for_acmod(const acm_hdr_t *hdr);
+void save_mtrrs(mtrr_state_t *saved_state);
+void set_all_mtrrs(bool enable);
+bool set_mem_type(const void *base, uint32_t size, uint32_t mem_type);
+void restore_mtrrs(const mtrr_state_t *saved_state);
+bool validate_mtrrs(const mtrr_state_t *saved_state);
+
+#endif /*__TXT_MTRRS_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/txt/smx.h b/tboot/include/txt/smx.h
new file mode 100644
index 0000000..93645c7
--- /dev/null
+++ b/tboot/include/txt/smx.h
@@ -0,0 +1,171 @@
+/*
+ * smx.h: Intel(r) TXT SMX architecture-related definitions
+ *
+ * Copyright (c) 2003-2008, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TXT_SMX_H__
+#define __TXT_SMX_H__
+
+/*
+ * GETSEC[] instructions
+ */
+
+/* GETSEC instruction opcode */
+#define IA32_GETSEC_OPCODE ".byte 0x0f,0x37"
+
+/* GETSEC leaf function codes */
+#define IA32_GETSEC_CAPABILITIES 0
+#define IA32_GETSEC_ENTERACCS 2
+#define IA32_GETSEC_SENTER 4
+#define IA32_GETSEC_SEXIT 5
+#define IA32_GETSEC_PARAMETERS 6
+#define IA32_GETSEC_SMCTRL 7
+#define IA32_GETSEC_WAKEUP 8
+
+/*
+ * GETSEC[] leaf functions
+ */
+
+typedef union {
+ uint32_t _raw;
+ struct {
+ uint32_t chipset_present : 1;
+ uint32_t undefined1 : 1;
+ uint32_t enteraccs : 1;
+ uint32_t exitac : 1;
+ uint32_t senter : 1;
+ uint32_t sexit : 1;
+ uint32_t parameters : 1;
+ uint32_t smctrl : 1;
+ uint32_t wakeup : 1;
+ uint32_t undefined9 : 22;
+ uint32_t extended_leafs : 1;
+ };
+} capabilities_t;
+
+static inline capabilities_t __getsec_capabilities(uint32_t index)
+{
+ uint32_t cap;
+ __asm__ __volatile__ (IA32_GETSEC_OPCODE "\n"
+ : "=a"(cap)
+ : "a"(IA32_GETSEC_CAPABILITIES), "b"(index));
+ return (capabilities_t)cap;
+}
+
+/* helper fn. for getsec_capabilities */
+/* this is arbitrary and can be increased when needed */
+#define MAX_SUPPORTED_ACM_VERSIONS 16
+
+typedef struct {
+ struct {
+ uint32_t mask;
+ uint32_t version;
+ } acm_versions[MAX_SUPPORTED_ACM_VERSIONS];
+ int n_versions;
+ uint32_t acm_max_size;
+ uint32_t acm_mem_types;
+ uint32_t senter_controls;
+ bool proc_based_scrtm;
+ bool preserve_mce;
+} getsec_parameters_t;
+
+bool get_parameters(getsec_parameters_t *params);
+
+
+static inline void __getsec_senter(uint32_t sinit_base, uint32_t sinit_size)
+{
+ __asm__ __volatile__ (IA32_GETSEC_OPCODE "\n"
+ :
+ : "a"(IA32_GETSEC_SENTER),
+ "b"(sinit_base),
+ "c"(sinit_size),
+ "d"(0x0));
+}
+
+static inline void __getsec_sexit(void)
+{
+ __asm__ __volatile__ (IA32_GETSEC_OPCODE "\n"
+ : : "a"(IA32_GETSEC_SEXIT));
+}
+
+static inline void __getsec_wakeup(void)
+{
+ __asm__ __volatile__ (IA32_GETSEC_OPCODE "\n"
+ : : "a"(IA32_GETSEC_WAKEUP));
+}
+
+static inline void __getsec_smctrl(void)
+{
+ __asm__ __volatile__ (IA32_GETSEC_OPCODE "\n"
+ : : "a"(IA32_GETSEC_SMCTRL), "b"(0x0));
+}
+
+static inline void __getsec_parameters(uint32_t index, int* param_type,
+ uint32_t* peax, uint32_t* pebx,
+ uint32_t* pecx)
+{
+ uint32_t eax=0, ebx=0, ecx=0;
+ __asm__ __volatile__ (IA32_GETSEC_OPCODE "\n"
+ : "=a"(eax), "=b"(ebx), "=c"(ecx)
+ : "a"(IA32_GETSEC_PARAMETERS), "b"(index));
+
+ if ( param_type != NULL ) *param_type = eax & 0x1f;
+ if ( peax != NULL ) *peax = eax;
+ if ( pebx != NULL ) *pebx = ebx;
+ if ( pecx != NULL ) *pecx = ecx;
+}
+
+static inline void __getsec_enteraccs(uint32_t acm_base, uint32_t acm_size,
+ uint32_t fn)
+{
+ __asm__ __volatile__ (IA32_GETSEC_OPCODE "\n"
+ :
+ : "a"(IA32_GETSEC_ENTERACCS),
+ "b"(acm_base),
+ "c"(acm_size),
+ "D"(0),
+ "S"(fn));
+}
+
+
+#endif /* __TXT_SMX_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/txt/txt.h b/tboot/include/txt/txt.h
new file mode 100644
index 0000000..2555e70
--- /dev/null
+++ b/tboot/include/txt/txt.h
@@ -0,0 +1,76 @@
+/*
+ * txt.h: Intel(r) TXT support functions
+ *
+ * Copyright (c) 2003-2008, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TXT_TXT_H__
+#define __TXT_TXT_H__
+
+// #include <multiboot.h>
+
+void txt_init_mle_header(void);
+bool txt_build_mle_pagetable(void);
+bool txt_is_launched(void);
+bool txt_get_error(void);
+void txt_get_racm_error(void);
+tb_error_t supports_txt(void);
+tb_error_t txt_verify_platform(void);
+bool txt_prepare_cpu(void);
+tb_error_t txt_launch_environment(void);
+/* TODO need to address the loader business, stub out for now
+tb_error_t txt_launch_racm(loader_ctx *lctx);
+*/
+void txt_post_launch(void);
+tb_error_t txt_protect_mem_regions(void);
+tb_error_t txt_post_launch_verify_platform(void);
+bool txt_s3_launch_environment(void);
+void txt_shutdown(void);
+bool txt_is_powercycle_required(void);
+void ap_wait(unsigned int cpuid);
+
+uint32_t g_using_da;
+atomic_t ap_wfs_count;
+
+#endif /* __TXT_TXT_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff --git a/tboot/include/txt/verify.h b/tboot/include/txt/verify.h
new file mode 100644
index 0000000..659af15
--- /dev/null
+++ b/tboot/include/txt/verify.h
@@ -0,0 +1,57 @@
+/*
+ * verify.h: support functions for platform Intel(r) TXT verification
+ *
+ * Copyright (c) 2003-2008, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TXT_VERIFY_H__
+#define __TXT_VERIFY_H__
+
+void set_vtd_pmrs(os_sinit_data_t *os_sinit_data,
+ uint64_t min_lo_ram, uint64_t max_lo_ram,
+ uint64_t min_hi_ram, uint64_t max_hi_ram);
+bool verify_e820_map(sinit_mdr_t* mdrs_base, uint32_t num_mdrs);
+bool verify_stm(unsigned int cpuid);
+bool use_mwait(void);
+
+#endif /* __TXT_VERIFY_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/txt/vmcs.h b/tboot/include/txt/vmcs.h
new file mode 100644
index 0000000..74f6ecc
--- /dev/null
+++ b/tboot/include/txt/vmcs.h
@@ -0,0 +1,346 @@
+/*
+ * vmcs.h: VMCS definitions for creation of APs mini-guests
+ *
+ * Copyright (c) 2003-2009, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TXT_VMCS_H__
+#define __TXT_VMCS_H__
+
+struct vmcs_struct {
+ uint32_t vmcs_revision_id;
+ unsigned char data[0]; /* vmcs size is read from MSR */
+};
+
+union vmcs_arbytes {
+ struct arbyte_fields {
+ unsigned int seg_type : 4,
+ s : 1,
+ dpl : 2,
+ p : 1,
+ reserved0 : 4,
+ avl : 1,
+ reserved1 : 1,
+ default_ops_size: 1,
+ g : 1,
+ null_bit : 1,
+ reserved2 : 15;
+ } fields;
+ unsigned int bytes;
+};
+
+#define CPU_BASED_HLT_EXITING 0x00000080
+#define CPU_BASED_INVDPG_EXITING 0x00000200
+#define CPU_BASED_MWAIT_EXITING 0x00000400
+
+#define PIN_BASED_EXT_INTR_MASK 0x00000001
+#define PIN_BASED_NMI_EXITING 0x00000008
+
+#define VM_EXIT_IA32E_MODE 0x00000200
+#define VM_EXIT_ACK_INTR_ON_EXIT 0x00008000
+
+#define VM_ENTRY_IA32E_MODE 0x00000200
+#define VM_ENTRY_SMM 0x00000400
+#define VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800
+
+
+/* VMCS Encordings */
+enum vmcs_field {
+ GUEST_ES_SELECTOR = 0x00000800,
+ GUEST_CS_SELECTOR = 0x00000802,
+ GUEST_SS_SELECTOR = 0x00000804,
+ GUEST_DS_SELECTOR = 0x00000806,
+ GUEST_FS_SELECTOR = 0x00000808,
+ GUEST_GS_SELECTOR = 0x0000080a,
+ GUEST_LDTR_SELECTOR = 0x0000080c,
+ GUEST_TR_SELECTOR = 0x0000080e,
+ HOST_ES_SELECTOR = 0x00000c00,
+ HOST_CS_SELECTOR = 0x00000c02,
+ HOST_SS_SELECTOR = 0x00000c04,
+ HOST_DS_SELECTOR = 0x00000c06,
+ HOST_FS_SELECTOR = 0x00000c08,
+ HOST_GS_SELECTOR = 0x00000c0a,
+ HOST_TR_SELECTOR = 0x00000c0c,
+ IO_BITMAP_A = 0x00002000,
+ IO_BITMAP_A_HIGH = 0x00002001,
+ IO_BITMAP_B = 0x00002002,
+ IO_BITMAP_B_HIGH = 0x00002003,
+ VM_EXIT_MSR_STORE_ADDR = 0x00002006,
+ VM_EXIT_MSR_STORE_ADDR_HIGH = 0x00002007,
+ VM_EXIT_MSR_LOAD_ADDR = 0x00002008,
+ VM_EXIT_MSR_LOAD_ADDR_HIGH = 0x00002009,
+ VM_ENTRY_MSR_LOAD_ADDR = 0x0000200a,
+ VM_ENTRY_MSR_LOAD_ADDR_HIGH = 0x0000200b,
+ TSC_OFFSET = 0x00002010,
+ TSC_OFFSET_HIGH = 0x00002011,
+ VIRTUAL_APIC_PAGE_ADDR = 0x00002012,
+ VIRTUAL_APIC_PAGE_ADDR_HIGH = 0x00002013,
+ VMCS_LINK_POINTER = 0x00002800,
+ VMCS_LINK_POINTER_HIGH = 0x00002801,
+ GUEST_IA32_DEBUGCTL = 0x00002802,
+ GUEST_IA32_DEBUGCTL_HIGH = 0x00002803,
+ PIN_BASED_VM_EXEC_CONTROL = 0x00004000,
+ CPU_BASED_VM_EXEC_CONTROL = 0x00004002,
+ EXCEPTION_BITMAP = 0x00004004,
+ PAGE_FAULT_ERROR_CODE_MASK = 0x00004006,
+ PAGE_FAULT_ERROR_CODE_MATCH = 0x00004008,
+ CR3_TARGET_COUNT = 0x0000400a,
+ VM_EXIT_CONTROLS = 0x0000400c,
+ VM_EXIT_MSR_STORE_COUNT = 0x0000400e,
+ VM_EXIT_MSR_LOAD_COUNT = 0x00004010,
+ VM_ENTRY_CONTROLS = 0x00004012,
+ VM_ENTRY_MSR_LOAD_COUNT = 0x00004014,
+ VM_ENTRY_INTR_INFO_FIELD = 0x00004016,
+ VM_ENTRY_EXCEPTION_ERROR_CODE = 0x00004018,
+ VM_ENTRY_INSTRUCTION_LEN = 0x0000401a,
+ TPR_THRESHOLD = 0x0000401c,
+ SECONDARY_VM_EXEC_CONTROL = 0x0000401e,
+ VM_INSTRUCTION_ERROR = 0x00004400,
+ VM_EXIT_REASON = 0x00004402,
+ VM_EXIT_INTR_INFO = 0x00004404,
+ VM_EXIT_INTR_ERROR_CODE = 0x00004406,
+ IDT_VECTORING_INFO_FIELD = 0x00004408,
+ IDT_VECTORING_ERROR_CODE = 0x0000440a,
+ VM_EXIT_INSTRUCTION_LEN = 0x0000440c,
+ VMX_INSTRUCTION_INFO = 0x0000440e,
+ GUEST_ES_LIMIT = 0x00004800,
+ GUEST_CS_LIMIT = 0x00004802,
+ GUEST_SS_LIMIT = 0x00004804,
+ GUEST_DS_LIMIT = 0x00004806,
+ GUEST_FS_LIMIT = 0x00004808,
+ GUEST_GS_LIMIT = 0x0000480a,
+ GUEST_LDTR_LIMIT = 0x0000480c,
+ GUEST_TR_LIMIT = 0x0000480e,
+ GUEST_GDTR_LIMIT = 0x00004810,
+ GUEST_IDTR_LIMIT = 0x00004812,
+ GUEST_ES_AR_BYTES = 0x00004814,
+ GUEST_CS_AR_BYTES = 0x00004816,
+ GUEST_SS_AR_BYTES = 0x00004818,
+ GUEST_DS_AR_BYTES = 0x0000481a,
+ GUEST_FS_AR_BYTES = 0x0000481c,
+ GUEST_GS_AR_BYTES = 0x0000481e,
+ GUEST_LDTR_AR_BYTES = 0x00004820,
+ GUEST_TR_AR_BYTES = 0x00004822,
+ GUEST_INTERRUPTIBILITY_INFO = 0x00004824,
+ GUEST_ACTIVITY_STATE = 0x00004826,
+ GUEST_SYSENTER_CS = 0x0000482A,
+ HOST_IA32_SYSENTER_CS = 0x00004c00,
+ CR0_GUEST_HOST_MASK = 0x00006000,
+ CR4_GUEST_HOST_MASK = 0x00006002,
+ CR0_READ_SHADOW = 0x00006004,
+ CR4_READ_SHADOW = 0x00006006,
+ CR3_TARGET_VALUE0 = 0x00006008,
+ CR3_TARGET_VALUE1 = 0x0000600a,
+ CR3_TARGET_VALUE2 = 0x0000600c,
+ CR3_TARGET_VALUE3 = 0x0000600e,
+ EXIT_QUALIFICATION = 0x00006400,
+ GUEST_LINEAR_ADDRESS = 0x0000640a,
+ GUEST_CR0 = 0x00006800,
+ GUEST_CR3 = 0x00006802,
+ GUEST_CR4 = 0x00006804,
+ GUEST_ES_BASE = 0x00006806,
+ GUEST_CS_BASE = 0x00006808,
+ GUEST_SS_BASE = 0x0000680a,
+ GUEST_DS_BASE = 0x0000680c,
+ GUEST_FS_BASE = 0x0000680e,
+ GUEST_GS_BASE = 0x00006810,
+ GUEST_LDTR_BASE = 0x00006812,
+ GUEST_TR_BASE = 0x00006814,
+ GUEST_GDTR_BASE = 0x00006816,
+ GUEST_IDTR_BASE = 0x00006818,
+ GUEST_DR7 = 0x0000681a,
+ GUEST_RSP = 0x0000681c,
+ GUEST_RIP = 0x0000681e,
+ GUEST_RFLAGS = 0x00006820,
+ GUEST_PENDING_DBG_EXCEPTIONS = 0x00006822,
+ GUEST_SYSENTER_ESP = 0x00006824,
+ GUEST_SYSENTER_EIP = 0x00006826,
+ HOST_CR0 = 0x00006c00,
+ HOST_CR3 = 0x00006c02,
+ HOST_CR4 = 0x00006c04,
+ HOST_FS_BASE = 0x00006c06,
+ HOST_GS_BASE = 0x00006c08,
+ HOST_TR_BASE = 0x00006c0a,
+ HOST_GDTR_BASE = 0x00006c0c,
+ HOST_IDTR_BASE = 0x00006c0e,
+ HOST_IA32_SYSENTER_ESP = 0x00006c10,
+ HOST_IA32_SYSENTER_EIP = 0x00006c12,
+ HOST_RSP = 0x00006c14,
+ HOST_RIP = 0x00006c16,
+};
+
+enum guest_activity_state {
+ GUEST_STATE_ACTIVE = 0,
+ GUEST_STATE_HALT = 1,
+ GUEST_STATE_SHUTDOWN = 2,
+ GUEST_STATE_WAIT_SIPI = 3,
+};
+
+#define VMCALL_OPCODE ".byte 0x0f,0x01,0xc1\n"
+#define VMCLEAR_OPCODE ".byte 0x66,0x0f,0xc7\n" /* reg/opcode: /6 */
+#define VMLAUNCH_OPCODE ".byte 0x0f,0x01,0xc2\n"
+#define VMPTRLD_OPCODE ".byte 0x0f,0xc7\n" /* reg/opcode: /6 */
+#define VMPTRST_OPCODE ".byte 0x0f,0xc7\n" /* reg/opcode: /7 */
+#define VMREAD_OPCODE ".byte 0x0f,0x78\n"
+#define VMRESUME_OPCODE ".byte 0x0f,0x01,0xc3\n"
+#define VMWRITE_OPCODE ".byte 0x0f,0x79\n"
+#define VMXOFF_OPCODE ".byte 0x0f,0x01,0xc4\n"
+#define VMXON_OPCODE ".byte 0xf3,0x0f,0xc7\n"
+
+#define MODRM_EAX_06 ".byte 0x30\n" /* [EAX], with reg/opcode: /6 */
+#define MODRM_EAX_07 ".byte 0x38\n" /* [EAX], with reg/opcode: /7 */
+#define MODRM_EAX_ECX ".byte 0xc1\n" /* [EAX], [ECX] */
+
+/*
+ * Exit Reasons
+ */
+#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000
+
+#define EXIT_REASON_INIT 3
+#define EXIT_REASON_SIPI 4
+#define EXIT_REASON_VMCALL 18
+#define EXIT_REASON_INVALID_GUEST_STATE 33
+#define EXIT_REASON_MSR_LOADING 34
+#define EXIT_REASON_MACHINE_CHECK 41
+
+static inline void __vmptrld(uint64_t addr)
+{
+ /* TBD: do not crash on failure */
+ __asm__ __volatile__ ( VMPTRLD_OPCODE
+ MODRM_EAX_06
+ /* CF==1 or ZF==1 --> crash (ud2) */
+ "ja 1f ; ud2 ; 1:\n"
+ :
+ : "a" (&addr)
+ : "memory");
+}
+
+static inline void __vmptrst(uint64_t addr)
+{
+ __asm__ __volatile__ ( VMPTRST_OPCODE
+ MODRM_EAX_07
+ :
+ : "a" (&addr)
+ : "memory");
+}
+
+static inline void __vmpclear(uint64_t addr)
+{
+ /* TBD: do not crash on failure */
+ __asm__ __volatile__ ( VMCLEAR_OPCODE
+ MODRM_EAX_06
+ /* CF==1 or ZF==1 --> crash (ud2) */
+ "ja 1f ; ud2 ; 1:\n"
+ :
+ : "a" (&addr)
+ : "memory");
+}
+
+static inline unsigned long __vmread(unsigned long field)
+{
+ unsigned long ecx;
+
+ /* TBD: do not crash on failure */
+ __asm__ __volatile__ ( VMREAD_OPCODE
+ MODRM_EAX_ECX
+ /* CF==1 or ZF==1 --> crash (ud2) */
+ "ja 1f ; ud2 ; 1:\n"
+ : "=c" (ecx)
+ : "a" (field)
+ : "memory");
+
+ return ecx;
+}
+
+static inline void __vmwrite(unsigned long field, unsigned long value)
+{
+ /* TBD: do not crash on failure */
+ __asm__ __volatile__ ( VMWRITE_OPCODE
+ MODRM_EAX_ECX
+ /* CF==1 or ZF==1 --> crash (ud2) */
+ "ja 1f ; ud2 ; 1:\n"
+ :
+ : "a" (field) , "c" (value)
+ : "memory");
+}
+
+static inline void __vmlaunch (void)
+{
+ __asm__ __volatile__ ( VMLAUNCH_OPCODE
+ ::: "memory");
+}
+
+static inline void __vmresume (void)
+{
+ __asm__ __volatile__ ( VMRESUME_OPCODE
+ ::: "memory");
+}
+
+static inline void __vmxoff (void)
+{
+ __asm__ __volatile__ ( VMXOFF_OPCODE
+ ::: "memory");
+}
+
+static inline int __vmxon (uint64_t addr)
+{
+ int rc;
+
+ __asm__ __volatile__ ( VMXON_OPCODE
+ MODRM_EAX_06
+ /* CF==1 or ZF==1 --> rc = -1 */
+ "setna %b0 ; neg %0"
+ : "=q" (rc)
+ : "0" (0), "a" (&addr)
+ : "memory");
+
+ return rc;
+}
+
+void handle_init_sipi_sipi(unsigned int cpuid);
+void force_aps_exit(void);
+void init_vmcs_addrs(void);
+
+struct mutex ap_lock;
+
+#endif /* __TXT_VMCS_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/types.h b/tboot/include/types.h
new file mode 100644
index 0000000..f6fb7a2
--- /dev/null
+++ b/tboot/include/types.h
@@ -0,0 +1,104 @@
+/*
+ * types.h: defines size-based types for 32b builds
+ *
+ * Copyright (c) 2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+/* Need for other later defines. */
+#include <config.h>
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+#if !defined(__GNUC__)
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+#endif
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+typedef signed short s16;
+
+typedef unsigned char u_char;
+
+typedef unsigned int u_int;
+
+typedef unsigned char u_int8_t;
+typedef unsigned short u_int16_t;
+typedef unsigned int u_int32_t;
+
+/*
+ * This should be unsigned int but gets an error in
+ * policy.c that expects it to be an unsigned long.
+ */
+/* TODO building for x64 now */
+typedef unsigned long long size_t;
+
+typedef uint16_t wchar_t;
+
+/*
+ * This is specifically for IA32.
+ */
+/* TODO building for x64 now */
+#if !defined(__GNUC__)
+typedef unsigned long long uintptr_t;
+typedef unsigned long long uint64_t;
+#endif
+typedef unsigned long long u64;
+typedef unsigned long long u_int64_t;
+
+#define BYTES_PER_LONG 4
+
+#if __GNUC__ > 3
+#define offsetof(type, field) __builtin_offsetof(type, field)
+#else
+#define offsetof(type, member) ((size_t) &((type *)0)->member)
+#endif
+
+#endif /* __TYPES_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/uuid.h b/tboot/include/uuid.h
new file mode 100644
index 0000000..256bd02
--- /dev/null
+++ b/tboot/include/uuid.h
@@ -0,0 +1,82 @@
+/*
+ * uuid.h: support functions for UUIDs
+ *
+ * Copyright (c) 2006-2007, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __UUID_H__
+#define __UUID_H__
+
+typedef struct __packed {
+ uint32_t data1;
+ uint16_t data2;
+ uint16_t data3;
+ uint16_t data4;
+ uint8_t data5[6];
+} uuid_t;
+
+static inline bool are_uuids_equal(const uuid_t *uuid1, const uuid_t *uuid2)
+{
+ return (memcmp(uuid1, uuid2, sizeof(*uuid1)) == 0);
+}
+
+#ifndef PRINT
+#define PRINT printk
+#endif
+
+#ifndef TBOOT_DETA
+#define TBOOT_DETA "<4>"
+#endif
+
+static inline void print_uuid(const uuid_t *uuid)
+{
+ PRINT(TBOOT_DETA"{0x%08x, 0x%04x, 0x%04x, 0x%04x,\n"
+ "\t\t{0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x}}",
+ uuid->data1, (uint32_t)uuid->data2, (uint32_t)uuid->data3,
+ (uint32_t)uuid->data4, (uint32_t)uuid->data5[0],
+ (uint32_t)uuid->data5[1], (uint32_t)uuid->data5[2],
+ (uint32_t)uuid->data5[3], (uint32_t)uuid->data5[4],
+ (uint32_t)uuid->data5[5]);
+}
+
+#endif /* __UUID_H__ */
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/vga.h b/tboot/include/vga.h
new file mode 100644
index 0000000..7e9914a
--- /dev/null
+++ b/tboot/include/vga.h
@@ -0,0 +1,87 @@
+/*
+ * vga.h: definitions of and supports functions for VGA
+ *
+ * Copyright (c) 2006-2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __VGA_H__
+#define __VGA_H__
+
+#define VGA_BASE 0xb8000
+
+/* 80*25 text mode*/
+#define MAX_LINES 25
+#define MAX_COLS 80
+#define SCREEN_BUFFER (MAX_LINES*MAX_COLS*2)
+#define VGA_ADDR(x, y) (VGA_BASE + 2*(MAX_COLS*(y) + (x)))
+
+/* registers */
+#define CTL_ADDR_REG 0x3D4
+#define CTL_DATA_REG 0x3D5
+#define START_ADD_HIGH_REG 0x0C
+#define START_ADD_LOW_REG 0x0D
+
+/* colors */
+#define COLOR_BLACK 0x00
+#define COLOR_BLUE 0x01
+#define COLOR_GREEN 0x02
+#define COLOR_CYAN 0x03
+#define COLOR_RED 0x04
+#define COLOR_MAGENTA 0x05
+#define COLOR_BROWN 0x06
+#define COLOR_LTGRAY 0x07
+#define COLOR_DKGRAY 0x08
+#define COLOR_LTBLUE 0x09
+#define COLOR_LTGREEN 0x0A
+#define COLOR_LTCYAN 0x0B
+#define COLOR_LTRED 0x0C
+#define COLOR_LTMAGENTA 0x0D
+#define COLOR_LTBROWN 0x0E
+#define COLOR_WHITE 0x0F
+
+#define COLOR ((COLOR_BLACK << 4) | COLOR_LTGRAY)
+
+
+void vga_init(void);
+void vga_puts(const char *s, unsigned int cnt);
+
+#endif /* __VGA_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/include/vmac.h b/tboot/include/vmac.h
new file mode 100644
index 0000000..6104668
--- /dev/null
+++ b/tboot/include/vmac.h
@@ -0,0 +1,168 @@
+#ifndef HEADER_VMAC_H
+#define HEADER_VMAC_H
+
+/* --------------------------------------------------------------------------
+ * VMAC and VHASH Implementation by Ted Krovetz (tdk@acm.org) and Wei Dai.
+ * This implementation is herby placed in the public domain.
+ * The authors offers no warranty. Use at your own risk.
+ * Please send bug reports to the authors.
+ * Last modified: 17 APR 08, 1700 PDT
+ * ----------------------------------------------------------------------- */
+
+/* --------------------------------------------------------------------------
+ * User definable settings.
+ * ----------------------------------------------------------------------- */
+#define VMAC_TAG_LEN 64 /* Must be 64 or 128 - 64 sufficient for most */
+#define VMAC_KEY_LEN 128 /* Must be 128, 192 or 256 */
+#define VMAC_NHBYTES 4096/* Must 2^i for any 3 < i < 13. Standard = 128 */
+#define VMAC_PREFER_BIG_ENDIAN 0 /* Prefer non-x86 */
+
+#define VMAC_USE_OPENSSL 0 /* Set to non-zero to use OpenSSL's AES */
+#define VMAC_CACHE_NONCES 1 /* Set to non-zero to cause caching */
+ /* of consecutive nonces on 64-bit tags */
+
+#define VMAC_RUN_TESTS 0 /* Set to non-zero to check vectors and speed */
+#define VMAC_HZ (448e6) /* Set to hz of host machine to get speed */
+#define VMAC_HASH_ONLY 0 /* Set to non-zero to time hash only (not-mac) */
+/* Speeds of cpus I have access to
+#define hz (2400e6) glyme Core 2 "Conroe"
+#define hz (2000e6) jupiter G5
+#define hz (1592e6) titan
+#define hz (2793e6) athena/gaia
+#define hz (1250e6) isis G4
+#define hz (2160e6) imac Core 2 "Merom"
+#define hz (266e6) ppc/arm
+#define hz (400e6) mips
+*/
+
+/* --------------------------------------------------------------------------
+ * This implementation uses uint32_t and uint64_t as names for unsigned 32-
+ * and 64-bit integer types. These are defined in C99 stdint.h. The
+ * following may need adaptation if you are not running a C99 or
+ * Microsoft C environment.
+ * ----------------------------------------------------------------------- */
+#define VMAC_USE_STDINT 1 /* Set to zero if system has no stdint.h */
+
+#if VMAC_USE_STDINT && !_MSC_VER /* Try stdint.h if non-Microsoft */
+//#include <stdint.h>
+#elif (_MSC_VER) /* Microsoft C does not have stdint.h */
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#define UINT64_C(v) v ## UI64
+#else /* Guess sensibly - may need adaptation */
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+#define UINT64_C(v) v ## ULL
+#endif
+
+/* --------------------------------------------------------------------------
+ * This implementation supports two free AES implementations: OpenSSL's and
+ * Paulo Barreto's. To use OpenSSL's, you will need to include the OpenSSL
+ * crypto library (eg, gcc -lcrypto foo.c). For Barreto's, you will need
+ * to compile rijndael-alg-fst.c, last seen at http://www.iaik.tu-graz.ac.at/
+ * research/krypto/AES/old/~rijmen/rijndael/rijndael-fst-3.0.zip and
+ * http://homes.esat.kuleuven.be/~rijmen/rijndael/rijndael-fst-3.0.zip.
+ * To use a different implementation, use these definitions as a model.
+ * ----------------------------------------------------------------------- */
+#if VMAC_USE_OPENSSL
+
+#include <openssl/aes.h>
+typedef AES_KEY aes_int_key;
+
+#define aes_encryption(in,out,int_key) \
+ AES_encrypt((unsigned char *)(in),(unsigned char *)(out),(int_key))
+#define aes_key_setup(key,int_key) \
+ AES_set_encrypt_key((key),VMAC_KEY_LEN,(int_key))
+
+#else
+
+//#include "rijndael-alg-fst.h"
+typedef uint64_t vmac_t;
+#include "rijndael.h"
+typedef u32 aes_int_key[4*(VMAC_KEY_LEN/32+7)];
+
+#define aes_encryption(in,out,int_key) \
+ rijndaelEncrypt((u32 *)(int_key), \
+ ((VMAC_KEY_LEN/32)+6), \
+ (u8 *)(in), (u8 *)(out))
+#define aes_key_setup(user_key,int_key) \
+ rijndaelKeySetupEnc((u32 *)(int_key), \
+ (u8 *)(user_key), \
+ VMAC_KEY_LEN)
+#endif
+
+/* --------------------------------------------------------------------- */
+
+typedef struct {
+ uint64_t nhkey [(VMAC_NHBYTES/8)+2*(VMAC_TAG_LEN/64-1)];
+ uint64_t polykey[2*VMAC_TAG_LEN/64];
+ uint64_t l3key [2*VMAC_TAG_LEN/64];
+ uint64_t polytmp[2*VMAC_TAG_LEN/64];
+ aes_int_key cipher_key;
+ #if (VMAC_TAG_LEN == 64) && (VMAC_CACHE_NONCES)
+ uint64_t cached_nonce[2];
+ uint64_t cached_aes[2];
+ #endif
+ int first_block_processed;
+} vmac_ctx_t;
+
+/* --------------------------------------------------------------------- */
+/* --------------------------------------------------------------------------
+ * <<<<< USAGE NOTES >>>>>
+ *
+ * Given msg m (mbytes in length) and nonce buffer n
+ * this function returns a tag as its output. The tag is returned as
+ * a number. When VMAC_TAG_LEN == 64, the 'return'ed integer is the tag,
+ * and *tagl is meaningless. When VMAC_TAG_LEN == 128 the tag is the
+ * number y * 2^64 + *tagl where y is the function's return value.
+ * If you want to consider tags to be strings, then you must do so with
+ * an agreed upon endian orientation for interoperability, and convert
+ * the results appropriately. VHASH hashes m without creating any tag.
+ * Consecutive substrings forming a prefix of a message may be passed
+ * to vhash_update, with vhash or vmac being called with the remainder
+ * to produce the output.
+ *
+ * Requirements:
+ * - On 32-bit architectures with SSE2 instructions, ctx and m MUST be
+ * begin on 16-byte memory boundaries.
+ * - m MUST be your message followed by zeroes to the nearest 16-byte
+ * boundary. If m is a length multiple of 16 bytes, then it is already
+ * at a 16-byte boundary and needs no padding. mbytes should be your
+ * message length without any padding.
+ * - The first bit of the nonce buffer n must be 0. An i byte nonce, is made
+ * as the first 16-i bytes of n being zero, and the final i the nonce.
+ * - vhash_update MUST have mbytes be a positive multiple of VMAC_NHBYTES
+ * ----------------------------------------------------------------------- */
+
+#define vmac_update vhash_update
+
+void vhash_update(unsigned char m[],
+ unsigned int mbytes,
+ vmac_ctx_t *ctx);
+
+uint64_t vmac(unsigned char m[],
+ unsigned int mbytes,
+ unsigned char n[16],
+ uint64_t *tagl,
+ vmac_ctx_t *ctx);
+
+uint64_t vhash(unsigned char m[],
+ unsigned int mbytes,
+ uint64_t *tagl,
+ vmac_ctx_t *ctx);
+
+/* --------------------------------------------------------------------------
+ * When passed a VMAC_KEY_LEN bit user_key, this function initialazies ctx.
+ * ----------------------------------------------------------------------- */
+
+void vmac_set_key(unsigned char user_key[], vmac_ctx_t *ctx);
+
+/* --------------------------------------------------------------------------
+ * This function aborts current hash and resets ctx, ready for a new message.
+ * ----------------------------------------------------------------------- */
+
+void vhash_abort(vmac_ctx_t *ctx);
+
+/* --------------------------------------------------------------------- */
+
+#endif /* HEADER_AES_H */
diff --git a/tboot/launch.S b/tboot/launch.S
new file mode 100644
index 0000000..1d244ab
--- /dev/null
+++ b/tboot/launch.S
@@ -0,0 +1,484 @@
+/*
+ * launch.S: the MLE post launch entry code.
+ *
+ * Copyright (c) 2017 Assured Information Security.
+ *
+ * Ross Philipson <philipsonr@ainfosec.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+#include <msr.h>
+#include <page.h>
+#include <processor.h>
+
+/* TXT config regs addrs/offsets */
+#define TXT_PRIV_CONFIG_REGS_BASE 0xfed20000
+#define TXTCR_STS 0x0000
+#define TXTCR_ERRORCODE 0x0030
+#define TXTCR_CMD_RESET 0x0038
+#define TXTCR_CMD_UNLOCK_MEM_CONFIG 0x0218
+#define TXTCR_HEAP_BASE 0x0300
+
+/* OsSinitData field offsets */
+#define MLE_PGTBL_OFFSET 8
+
+/* 64b selectors */
+#define CS_SEL64 0x0008
+#define DS_SEL64 0x0010
+
+/* errorcode for post-launch memory layout verfication failure */
+#define LAYOUT_ERR 0xc0008001
+
+#define BSP_STACK_SIZE 0x4000
+#define AP_STACK_SIZE 0x0800
+
+.section ".text"
+ .align PAGE_SIZE, 0
+
+.code32
+
+.global _mle_start
+_mle_start:
+
+/* Original:
+ * entry point post-launch, to verify memory layout
+ * (must all be w/in one page; since _start is page-aligned, it will be;
+ * which is why we can't call much other code (e.g. printk, TPM fns, etc.)
+ * EFI:
+ * this routine is on the first page of the .text section, page aligned and
+ * far smaller than PAGE_SIZE.
+ */
+ENTRY(post_launch_entry)
+ /*
+ * Per the spec:
+ * EBX - MLE entry point physical address.
+ * ECX - MLE page table base physical address.
+ *
+ * Restore the world, get back into longer mode. EBX contains the entry
+ * point which is our only known location in protected mode. We will
+ * use it to set things right then validate it later. If it is not
+ * what it is supposed to be, the world will come crashing down. Start
+ * by creating our page tables. Store it in ESI so EBX can be used.
+ *
+ * N.B. It seems though that TXT should guarantee the register contains
+ * what it says it should per the specification. Not sure why it would
+ * need verification.
+ *
+ * TODO if we end up needing to validate EBX here we can load a stack
+ * in some scratch location, call and pop to get EIP and then frob up
+ * a location to compare.
+ */
+ cli
+ movl %ebx, %esi
+
+ /* Fixup some addresses for the GDT and long jump */
+ movl %ebx, %ecx
+ addl $(gdt_desc64 - _mle_start + 2), %ecx
+ movl %ebx, %eax
+ addl $(gdt_table64 - _mle_start), %eax
+ movl %eax, (%ecx)
+
+ movl %ebx, %ecx
+ addl $(gdt_desc64_ptr - _mle_start), %ecx
+ movl %ebx, %eax
+ addl $(gdt_desc64 - _mle_start), %eax
+ movl %eax, (%ecx)
+
+ movl %ebx, %ecx
+ addl $(jump64 - _mle_start + 1), %ecx
+ movl %ebx, %eax
+ addl $(entry64 - _mle_start), %eax
+ movl %eax, (%ecx)
+
+ /* Zero out all page table pages so there are no surprises */
+ movl %ebx, %edi
+ subl $(TBOOT_RTMEM_SIZE + PAGE_SIZE), %edi
+ xorl %eax, %eax
+ movl $(TBOOT_PLEPT_SIZE/4), %ecx
+ rep stosl
+
+ /* First page is the PML4 table with one PDP entry */
+ movl %ebx, %eax
+ subl $(TBOOT_RTMEM_SIZE + PAGE_SIZE), %eax
+ movl %eax, %ecx
+ addl $PAGE_SIZE, %ecx
+ orl $0x3, %ecx
+ movl %ecx, (%eax)
+
+ /* Second page is the PDP table with 4 PD entries */
+ addl $PAGE_SIZE, %eax
+ movl %eax, %ecx
+ xorl %edx, %edx
+1:
+ addl $PAGE_SIZE, %ecx
+ cmpb $4, %dl
+ jz 2f
+ orl $0x3, %ecx
+ movl %ecx, (%eax)
+ addl $0x8, %eax
+ incb %dl
+ jmp 1b
+2: /* EAX Page 2 + 0x20 */
+
+ /* Next 4 pages are PDs that map all of mem < 4G as 2M pages */
+ addl $(PAGE_SIZE - 0x20), %eax
+ xorl %edx, %edx
+ xorl %ecx, %ecx
+ xorl %ebx, %ebx
+ addl $0x83, %ecx
+1:
+ cmpw $512, %dx
+ jz 2f
+ movl %ecx, (%eax)
+ addl $0x8, %eax
+ addl $0x200000, %ecx
+ incw %dx
+ jmp 1b
+2:
+ cmpb $3, %bl
+ jz 3f
+ incb %bl
+ xorl %edx, %edx
+ jmp 1b
+3: /* EAX Page 7 */
+
+ /* Return to first PD entry on first PD and setup a PT entry */
+ movl %eax, %ecx
+ subl $(4*PAGE_SIZE), %eax
+ orl $0x3, %ecx
+ movl %ecx, (%eax)
+
+ /* Page 7 is a PT that maps all of mem < 2M as 4K pages */
+ addl $(4*PAGE_SIZE), %eax
+ xorl %edx, %edx
+ xorl %ecx, %ecx
+ addl $0x3, %ecx
+1:
+ cmpw $512, %dx
+ jz 2f
+ movl %ecx, (%eax)
+ addl $0x8, %eax
+ addl $0x1000, %ecx
+ incw %dx
+ jmp 1b
+2: /* EAX Page 8 */
+
+ /*
+ * And done - all memory below 4G is identity mapped. Time to get back
+ * to long mode. EAX contains the base of the page table structures.
+ */
+ subl $(7*PAGE_SIZE), %eax
+
+ /* Restore CR4, PAE must be enabled before IA-32e mode */
+ movl %cr4, %ecx
+ orl $(CR4_PAE | CR4_PGE), %ecx
+ movl %ecx, %cr4
+
+ /* Load PML4 table location into PT base register */
+ movl %eax, %cr3
+
+ /* Enable IA-32e mode and paging */
+ movl $MSR_EFER, %ecx
+ rdmsr
+ orl $_EFER_LME, %eax
+ wrmsr
+ movl %cr0, %eax
+ orl $(CR0_PG | CR0_NE | CR0_ET | CR0_MP | CR0_PE), %eax
+ movl %eax, %cr0
+ jmp 1f
+1:
+ /* Now in IA-32e compatibility mode */
+
+ /* Setup GDT and ljmp to 64b mode */
+ movl %esi, %ebx
+ addl $(gdt_desc64_ptr - _mle_start), %ebx
+ lgdt (%ebx)
+
+jump64:
+ .byte 0xea /* far jmp op */
+ .long 0x00000000 /* offset (fixed up) */
+ .word CS_SEL64 /* 64b code segment selector */
+
+.code64
+
+entry64:
+ /* Load data segment regs */
+ movw DS_SEL64, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+ movw %ax, %ss
+
+ /* ESI still has original EBX, put it back */
+ xorq %rbx, %rbx
+ movl %esi, %ebx
+
+ /*
+ * Layout check from original TBOOT. If EBX did not contain the
+ * physaddr of the entry point we would probably be lost way before
+ * we got here. But check it anyway then check the page tables passed
+ * to SENTER.
+ */
+ leaq post_launch_entry(%rip), %rax
+ cmpl %eax, %ebx
+ jne 1f
+
+ /*
+ * Verify last entry in MLE page table is the one we expected
+ * this is sufficient because: 1) all addrs must be phys increasing
+ * and 2) tboot is phys contig -- therefore if any page were moved to
+ * a different phys addr then the last page would have to be different
+ * from tboot's last page. Note in paging mode identity mapped so
+ * phys == virt for this verification.
+ *
+ * Get addr of MLE page table from OsSinitData, with the start of
+ * TXT heap == BiosDataSize.
+ */
+ movq $TXT_PRIV_CONFIG_REGS_BASE, %rcx
+ mov TXTCR_HEAP_BASE(%rcx), %rax
+ addq (%rax), %rax /* skip BiosData */
+ addq (%rax), %rax /* skip OsMleData */
+ movq (MLE_PGTBL_OFFSET + 8)(%rax), %rax /* addr of MLE page table */
+ movq (%rax), %rax /* PDP -> PD page */
+ andq $PAGE_MASK, %rax
+ movq (%rax), %rax /* PD -> PT page */
+ andq $PAGE_MASK, %rax
+ /* Get the MLE size; this value was stored in the MLE and measured */
+ leaq _mle_size(%rip), %rdx
+ movq %rdx, %rcx
+ /* Use size to move past last valid PTE then one back */
+ shrq $PAGE_SHIFT - 3, %rcx /* Like size div 512 */
+ subq $8, %rcx
+ addq %rcx, %rax
+ movq (%rax), %rax /* PTE of last page */
+ andq $PAGE_MASK, %rax
+ /* Calculate expected addr of last page */
+ addq %rdx, %rbx
+ decq %rbx /* MLE start + size - 1 addr of last byte */
+ andq $PAGE_MASK, %rbx /* ...rounded to page start */
+ /* Are they equal? */
+ cmpq %rbx, %rax
+ je start64
+ /* Else fall through and die */
+
+ /* Layout check failed so TXT RESET with a special error code */
+1:
+ movq $TXT_PRIV_CONFIG_REGS_BASE, %rcx
+ movl $LAYOUT_ERR, TXTCR_ERRORCODE(%rcx)
+ /* unlock memory config (and serialize) */
+ movb $1, TXTCR_CMD_UNLOCK_MEM_CONFIG(%rcx)
+ movq TXTCR_STS(%rcx), %rax
+ /* TXT RESET */
+ movb $1, TXTCR_CMD_RESET(%rcx)
+ movb $6, %al
+ movw $0xcf9, %dx
+ outb %al, %dx /* for debug chipsets where TXT RESET may not work */
+ ud2
+
+start64:
+ /* Clear the .bss of pre-launch stuffs */
+ leaq _bss_start(%rip), %rdi
+ leaq _bss_size(%rip), %rcx
+ xorq %rax, %rax
+ rep stosb
+
+ /* Load up a stack */
+ leaq bsp_stack(%rip), %rax
+ movq %rax, %rsp
+
+ /* Fixup IDT table and descriptor, load and STI */
+ leaq idt_desc64_end(%rip), %rax
+ leaq idt_table64(%rip), %rcx
+ movq %rcx, -8(%rax)
+
+ leaq int_handler(%rip), %rax
+ xorq %rdx, %rdx
+1:
+ cmpw $256, %dx
+ jz 1f
+ movq %rax, %rbx
+ movw %bx, (%rcx)
+ shrq $16, %rbx
+ movw %bx, 12(%rcx)
+ shrq $16, %rbx
+ movl %ebx, 16(%rcx)
+ cmpw $18, %dx
+ jnz 2f
+ /* MCE vector */
+ movl $0x8f00, 8(%rcx) /* P, DPL=0, 64b, Trap */
+2:
+ incw %dx
+ addq $16, %rcx
+ jmp 1b
+1:
+ lidt idt_desc64(%rip)
+ sti
+
+ /* Enable MCE */
+ movq %cr4, %rax
+ orq $CR4_MCE, %rax
+ movq %rax, %cr4
+
+ /* And we are outa here... */
+ callq post_launch
+ ud2
+
+/*
+ * vmexit handler
+ */
+ENTRY(vmx_asm_vmexit_handler)
+ call vmx_vmexit_handler
+ /* fall through to loop if callee returns (shouldn't happen) */
+
+ENTRY(_mini_guest)
+ pause
+ /* TODO rest */
+ ret
+
+ENTRY(bsp_stack_ref)
+ leaq bsp_stack(%rip), %rax
+ ret
+
+/*
+ * Interrupt handler
+ */
+int_handler:
+ call handle_exception
+ ud2
+
+/* GDT */
+ .align 16
+gdt_desc64:
+ .word gdt_table64_end - gdt_table64 - 1 /* Limit */
+ .long 0x00000000 /* Base */
+gdt_desc64_end:
+
+gdt_desc64_ptr:
+ .long 0x00000000 /* Pointer to GDT descriptor */
+
+ .align 16
+gdt_table64:
+ /* Null Segment */
+ .quad 0x0000000000000000
+ /* Code Segment */
+ .word 0x0000 /* Limit 1 */
+ .word 0x0000 /* Base 1 */
+ .byte 0x00 /* Base 2 */
+ .byte 0x9a /* P=1 DPL=0 11=code C=0 R=1 A=0 */
+ .byte 0x20 /* G=0 D=0 L=1 D=0 AVL=0 Limit 2 */
+ .byte 0x00 /* Base 3 */
+ /* Data Segment */
+ .word 0x0000 /* Limit 1 */
+ .word 0x0000 /* Base 1 */
+ .byte 0x00 /* Base 2 */
+ .byte 0x92 /* P=1 DPL=0 10=code C=0 W=1 A=0 */
+ .byte 0x00 /* G=0 D=0 L=0 D=0 AVL=0 Limit 2 */
+ .byte 0x00 /* Base 3 */
+gdt_table64_end:
+
+/* IDT */
+ .align 16
+idt_desc64:
+ .word idt_table64_end - idt_table64 - 1 /* Limit */
+ .quad 0x0000000000000000 /* Base */
+idt_desc64_end:
+
+ .align 16
+
+idt_table64:
+ .rept 256
+ .word 0x0000 /* Offset 15 - 0 */
+ .word CS_SEL64 /* Segment selector */
+ .word 0x8e00 /* P, DPL=0, 64b, Interrupt (default) */
+ .word 0x0000 /* Offset 31 - 16 */
+ .long 0x00000000 /* Offset 63 - 32 */
+ .long 0x00000000 /* Reserved */
+ .endr
+idt_table64_end:
+
+.global _mle_size
+_mle_size:
+ .quad 0x0000000000000000 /* MLE size */
+
+.global _bss_size
+_bss_size:
+ .quad 0x0000000000000000 /* .bss size */
+
+.section ".data"
+ .align PAGE_SIZE, 0
+
+.section ".rdata"
+ .align PAGE_SIZE, 0
+
+/*
+ * shared data page with kernel (i.e. Xen)
+ * (put at end so that not split e820 region for tboot)
+ */
+.section ".tbootsh","w"
+ .align PAGE_SIZE, 0
+
+ .globl _tboot_shared
+_tboot_shared:
+ .fill PAGE_SIZE,1,0
+ .align PAGE_SIZE, 0
+
+.section ".bss"
+ .align PAGE_SIZE, 0
+
+.global _bss_start
+_bss_start:
+
+/* Stacks */
+
+bsp_stack_end:
+ .fill BSP_STACK_SIZE, 1, 0
+bsp_stack:
+
+ap_stacks_end:
+ .fill AP_STACK_SIZE * NR_CPUS, 1, 0
+ap_stacks:
+
+/* Page Table and VMCS data for AP bringup */
+
+ .align PAGE_SIZE, 0
+ .globl idle_pg_table
+idle_pg_table:
+ .fill 1*PAGE_SIZE,1,0
+
+ .align PAGE_SIZE, 0
+ .globl host_vmcs
+host_vmcs:
+ .fill 1*PAGE_SIZE,1,0
+
+ .align PAGE_SIZE, 0
+ .global ap_vmcs /* the input info when os/vmm kerneltrap into tboot */
+ap_vmcs:
+ .fill NR_CPUS * PAGE_SIZE, 1, 0
diff --git a/tboot/misc.c b/tboot/misc.c
new file mode 100644
index 0000000..480e9da
--- /dev/null
+++ b/tboot/misc.c
@@ -0,0 +1,455 @@
+/*
+ * misc.c: miscellaneous support fns
+ *
+ * Copyright (c) 2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+#include <efibase.h>
+#include <types.h>
+#include <stdbool.h>
+#include <printk.h>
+#include <compiler.h>
+#include <processor.h>
+#include <atomic.h>
+#include <io.h>
+#include <msr.h>
+#include <page.h>
+#include <ctype.h>
+#include <misc.h>
+#include <tb_error.h>
+#include <txt/txt.h>
+
+/*
+ * if 'prefix' != NULL, print it before each line of hex string
+ */
+void print_hex(const char *prefix, const void *prtptr, size_t size)
+{
+ for ( size_t i = 0; i < size; i++ ) {
+ if ( i % 16 == 0 && prefix != NULL )
+ printk(TBOOT_DETA"\n%s", prefix);
+ printk(TBOOT_DETA"%02x ", *(uint8_t *)prtptr++);
+ }
+ printk(TBOOT_DETA"\n");
+}
+
+void print_system_values(void)
+{
+ lmode_desc_t gdt;
+ lmode_desc_t idt;
+
+ store_gdt(&gdt);
+ store_idt(&idt);
+
+ /* Note the limit is 1 less than the actual length */
+ printk(TBOOT_DETA"GDT %016llx:%04x\n", gdt.base, gdt.limit);
+ /*print_hex("GDT: ", (void*)gdt.base, gdt.limit + 1);*/
+ printk(TBOOT_DETA"IDT %016llx:%04x\n", idt.base, idt.limit);
+ /*print_hex("IDT: ", (void*)idt.base, idt.limit + 1);*/
+ printk(TBOOT_DETA"CR0: %08llx\n", read_cr0());
+ printk(TBOOT_DETA"CR3: %08llx\n", read_cr3());
+ printk(TBOOT_DETA"CR4: %08llx\n", read_cr4());
+ printk(TBOOT_DETA"IA32_EFER MSR: %016llx\n", rdmsr(MSR_EFER));
+}
+
+static bool g_calibrated = false;
+static uint64_t g_ticks_per_millisec;
+
+#define TIMER_FREQ 1193182
+#define TIMER_DIV(hz) ((TIMER_FREQ+(hz)/2)/(hz))
+
+static void wait_tsc_uip(void)
+{
+ do {
+ outb(0x43, 0xe8);
+ cpu_relax();
+ } while ( !(inb(0x42) & 0x80) );
+ do {
+ outb(0x43, 0xe8);
+ cpu_relax();
+ } while ( inb(0x42) & 0x80 );
+}
+
+static void calibrate_tsc(void)
+{
+ if ( g_calibrated )
+ return;
+
+ /* disable speeker */
+ uint8_t val = inb(0x61);
+ val = ((val & ~0x2) | 0x1);
+ outb(0x61, val);
+
+ /* 0xb6 - counter2, low then high byte write */
+ /* mode 3, binary */
+ outb(0x43, 0xb6);
+
+ /* 0x4a9 - divisor to get 1ms period time */
+ /* 1.19318 MHz / 1193 = 1000.15Hz */
+ uint16_t latch = TIMER_DIV(1000);
+ outb(0x42, latch & 0xff);
+ outb(0x42, latch >> 8);
+
+ /* 0xe8 - read back command, don't get count */
+ /* get status, counter2 select */
+ do {
+ outb(0x43, 0xe8);
+ cpu_relax();
+ } while ( inb(0x42) & 0x40 );
+
+ wait_tsc_uip();
+
+ /* get starting TSC val */
+ uint64_t start = rdtsc();
+
+ wait_tsc_uip();
+
+ uint64_t end = rdtsc();
+
+ /* # ticks in 1 millisecond */
+ g_ticks_per_millisec = end - start;
+
+ /* restore timer 1 programming */
+ outb(0x43, 0x54);
+ outb(0x41, 0x12);
+
+ g_calibrated = true;
+}
+
+void delay(int millisecs)
+{
+ if ( millisecs <= 0 )
+ return;
+
+ calibrate_tsc();
+
+ uint64_t rtc = rdtsc();
+
+ uint64_t end_ticks = rtc + millisecs * g_ticks_per_millisec;
+ while ( rtc < end_ticks ) {
+ cpu_relax();
+ rtc = rdtsc();
+ }
+}
+
+#define PAGE_IDX_MASK ((1ULL << 9) - 1) /* 0x1FF 9 bits */
+#define PHYS_ADDR_MASK ((1ULL << 52) - 0x1000) /* 0xFFFFFFFFFF000 52 bits, 4K masked */
+#define PHYS_ADDR_2M_MASK ((1ULL << 52) - 0x200000) /* 0xFFFFFFFE00000 52 bits, 2M masked */
+#define PHYS_ADDR_1G_MASK ((1ULL << 52) - 0x40000000) /* 0xFFFFFC0000000 52 bits, 1G masked */
+#define PAGE_4K_MASK 0xFFF
+#define PAGE_2M_MASK 0x1FFFFF
+#define PAGE_1G_MASK 0x3FFFFFFF
+#define ps_bit_set(e) ((e >> 7) & 1)
+#define p_bit_set(e) (e & 1)
+#define ENTRIES_PER_TABLE 512
+
+bool test_virt_to_phys(uint64_t vaddr)
+{
+ uint64_t pml4i = (vaddr >> 39) & PAGE_IDX_MASK;
+ uint64_t pdpi = (vaddr >> 30) & PAGE_IDX_MASK;
+ uint64_t pdi = (vaddr >> 21) & PAGE_IDX_MASK;
+ uint64_t pti = (vaddr >> 12) & PAGE_IDX_MASK;
+ uint64_t *pml4p, pml4e;
+ uint64_t *pdpp, pdpe;
+ uint64_t *pdp, pde;
+ uint64_t *ptp, pte;
+ uint64_t paddr;
+
+ pml4p = (uint64_t*)(read_cr3() & PAGE_MASK);
+ pml4e = pml4p[pml4i];
+ printk("V2P pml4p: %p pml4i: %016llx pml4e: %016llx\n",
+ pml4p, pml4i, pml4e);
+ if (!p_bit_set(pml4e)) {
+ printk("V2P Error pml4 entry not present!\n");
+ goto err;
+ }
+
+ pdpp = (uint64_t*)(pml4e & PHYS_ADDR_MASK);
+ pdpe = pdpp[pdpi];
+ printk("V2P pdpp: %p pdpi: %016llx pdpe: %016llx\n",
+ pdpp, pdpi, pdpe);
+ if (!p_bit_set(pdpe)) {
+ printk("V2P Error pdp entry not present!\n");
+ goto err;
+ }
+ if (ps_bit_set(pdpe)) {
+ printk("V2P 1G page\n");
+ paddr = (pdpe & PHYS_ADDR_1G_MASK) + (vaddr & PAGE_1G_MASK);
+ goto out;
+ }
+
+ pdp = (uint64_t*)(pdpe & PHYS_ADDR_MASK);
+ pde = pdp[pdi];
+ printk("V2P pdp: %p pdi: %016llx pde: %016llx\n",
+ pdp, pdi, pde);
+ if (!p_bit_set(pde)) {
+ printk("V2P Error pd entry not present!\n");
+ goto err;
+ }
+ if (ps_bit_set(pde)) {
+ printk("V2P 2M page\n");
+ paddr = (pde & PHYS_ADDR_2M_MASK) + (vaddr & PAGE_2M_MASK);
+ goto out;
+ }
+
+ ptp = (uint64_t*)(pde & PHYS_ADDR_MASK);
+ pte = ptp[pti];
+ printk("V2P ptp: %p pti: %016llx pte: %016llx\n",
+ ptp, pti, pte);
+ if (!p_bit_set(pte)) {
+ printk("V2P Error pt entry not present!\n");
+ goto err;
+ }
+
+ printk("V2P 4K page\n");
+ paddr = (pte & PHYS_ADDR_MASK) + (vaddr & PAGE_4K_MASK);
+
+out:
+ printk("V2P vaddr: %016llx paddr: %016llx\n",
+ vaddr, paddr);
+
+ if (vaddr != paddr)
+ return false;
+
+ return true;
+
+err:
+ return false;
+}
+
+void dump_page_tables(void)
+{
+ uint32_t l4i, l3i, l2i, l1i;
+ uint64_t *pml4p, *pdpp, *pdp, *ptp;
+
+ pml4p = (uint64_t*)(read_cr3() & PAGE_MASK);
+ printk("PAGE TABLE DUMP@ 0x%016llx\n", (uint64_t)pml4p);
+
+ for (l4i = 0; l4i < ENTRIES_PER_TABLE; l4i++) {
+ if (!p_bit_set(pml4p[l4i])) {
+ printk(" PML4 entry(%d) not present\n", l4i);
+ continue;
+ }
+
+ printk(" PML4 entry(%d) table: 0x%016llx\n", l4i, pml4p[l4i]);
+ pdpp = (uint64_t*)(pml4p[l4i] & PHYS_ADDR_MASK);
+ for (l3i = 0; l3i < ENTRIES_PER_TABLE; l3i++) {
+ if (!p_bit_set(pdpp[l3i])) {
+ printk(" PDP entry(%d) not present\n", l3i);
+ continue;
+ }
+ if (ps_bit_set(pdpp[l3i])) {
+ printk(" PDP entry(%d) 1G page: 0x%016llx\n", l3i, pdpp[l3i]);
+ continue;
+ }
+
+ printk(" PDP entry(%d) table: 0x%016llx\n", l3i, pdpp[l3i]);
+ pdp = (uint64_t*)(pdpp[l3i] & PHYS_ADDR_MASK);
+ for (l2i = 0; l2i < ENTRIES_PER_TABLE; l2i++) {
+ if (!p_bit_set(pdp[l2i])) {
+ printk(" PD entry(%d) not present\n", l2i);
+ continue;
+ }
+ if (ps_bit_set(pdp[l2i])) {
+ printk(" PD entry(%d) 2M page: 0x%016llx\n", l2i, pdp[l2i]);
+ continue;
+ }
+
+ printk(" PD entry(%d) table: 0x%016llx\n", l2i, pdp[l2i]);
+ ptp = (uint64_t*)(pdp[l2i] & PHYS_ADDR_MASK);
+ for (l1i = 0; l1i < ENTRIES_PER_TABLE; l1i++) {
+ if (!p_bit_set(ptp[l1i])) {
+ printk(" PT entry(%d) not present\n", l1i);
+ continue;
+ }
+ printk(" PT entry(%d) 4K page: 0x%016llx\n", l1i, ptp[l1i]);
+ }
+ }
+ }
+ }
+}
+
+/* used by isXXX() in ctype.h */
+/* originally from:
+ * http://fxr.watson.org/fxr/source/dist/acpica/utclib.c?v=NETBSD5
+ * re-licensed by Intel Corporation
+ */
+
+const uint8_t _ctype[CTYPE_SIZE] = {
+ _CN, /* 0x0 0. */
+ _CN, /* 0x1 1. */
+ _CN, /* 0x2 2. */
+ _CN, /* 0x3 3. */
+ _CN, /* 0x4 4. */
+ _CN, /* 0x5 5. */
+ _CN, /* 0x6 6. */
+ _CN, /* 0x7 7. */
+ _CN, /* 0x8 8. */
+ _CN|_SP, /* 0x9 9. */
+ _CN|_SP, /* 0xA 10. */
+ _CN|_SP, /* 0xB 11. */
+ _CN|_SP, /* 0xC 12. */
+ _CN|_SP, /* 0xD 13. */
+ _CN, /* 0xE 14. */
+ _CN, /* 0xF 15. */
+ _CN, /* 0x10 16. */
+ _CN, /* 0x11 17. */
+ _CN, /* 0x12 18. */
+ _CN, /* 0x13 19. */
+ _CN, /* 0x14 20. */
+ _CN, /* 0x15 21. */
+ _CN, /* 0x16 22. */
+ _CN, /* 0x17 23. */
+ _CN, /* 0x18 24. */
+ _CN, /* 0x19 25. */
+ _CN, /* 0x1A 26. */
+ _CN, /* 0x1B 27. */
+ _CN, /* 0x1C 28. */
+ _CN, /* 0x1D 29. */
+ _CN, /* 0x1E 30. */
+ _CN, /* 0x1F 31. */
+ _XS|_SP, /* 0x20 32. ' ' */
+ _PU, /* 0x21 33. '!' */
+ _PU, /* 0x22 34. '"' */
+ _PU, /* 0x23 35. '#' */
+ _PU, /* 0x24 36. '$' */
+ _PU, /* 0x25 37. '%' */
+ _PU, /* 0x26 38. '&' */
+ _PU, /* 0x27 39. ''' */
+ _PU, /* 0x28 40. '(' */
+ _PU, /* 0x29 41. ')' */
+ _PU, /* 0x2A 42. '*' */
+ _PU, /* 0x2B 43. '+' */
+ _PU, /* 0x2C 44. ',' */
+ _PU, /* 0x2D 45. '-' */
+ _PU, /* 0x2E 46. '.' */
+ _PU, /* 0x2F 47. '/' */
+ _XD|_DI, /* 0x30 48. '' */
+ _XD|_DI, /* 0x31 49. '1' */
+ _XD|_DI, /* 0x32 50. '2' */
+ _XD|_DI, /* 0x33 51. '3' */
+ _XD|_DI, /* 0x34 52. '4' */
+ _XD|_DI, /* 0x35 53. '5' */
+ _XD|_DI, /* 0x36 54. '6' */
+ _XD|_DI, /* 0x37 55. '7' */
+ _XD|_DI, /* 0x38 56. '8' */
+ _XD|_DI, /* 0x39 57. '9' */
+ _PU, /* 0x3A 58. ':' */
+ _PU, /* 0x3B 59. ';' */
+ _PU, /* 0x3C 60. '<' */
+ _PU, /* 0x3D 61. '=' */
+ _PU, /* 0x3E 62. '>' */
+ _PU, /* 0x3F 63. '?' */
+ _PU, /* 0x40 64. '@' */
+ _XD|_UP, /* 0x41 65. 'A' */
+ _XD|_UP, /* 0x42 66. 'B' */
+ _XD|_UP, /* 0x43 67. 'C' */
+ _XD|_UP, /* 0x44 68. 'D' */
+ _XD|_UP, /* 0x45 69. 'E' */
+ _XD|_UP, /* 0x46 70. 'F' */
+ _UP, /* 0x47 71. 'G' */
+ _UP, /* 0x48 72. 'H' */
+ _UP, /* 0x49 73. 'I' */
+ _UP, /* 0x4A 74. 'J' */
+ _UP, /* 0x4B 75. 'K' */
+ _UP, /* 0x4C 76. 'L' */
+ _UP, /* 0x4D 77. 'M' */
+ _UP, /* 0x4E 78. 'N' */
+ _UP, /* 0x4F 79. 'O' */
+ _UP, /* 0x50 80. 'P' */
+ _UP, /* 0x51 81. 'Q' */
+ _UP, /* 0x52 82. 'R' */
+ _UP, /* 0x53 83. 'S' */
+ _UP, /* 0x54 84. 'T' */
+ _UP, /* 0x55 85. 'U' */
+ _UP, /* 0x56 86. 'V' */
+ _UP, /* 0x57 87. 'W' */
+ _UP, /* 0x58 88. 'X' */
+ _UP, /* 0x59 89. 'Y' */
+ _UP, /* 0x5A 90. 'Z' */
+ _PU, /* 0x5B 91. '[' */
+ _PU, /* 0x5C 92. '\' */
+ _PU, /* 0x5D 93. ']' */
+ _PU, /* 0x5E 94. '^' */
+ _PU, /* 0x5F 95. '_' */
+ _PU, /* 0x60 96. '`' */
+ _XD|_LO, /* 0x61 97. 'a' */
+ _XD|_LO, /* 0x62 98. 'b' */
+ _XD|_LO, /* 0x63 99. 'c' */
+ _XD|_LO, /* 0x64 100. 'd' */
+ _XD|_LO, /* 0x65 101. 'e' */
+ _XD|_LO, /* 0x66 102. 'f' */
+ _LO, /* 0x67 103. 'g' */
+ _LO, /* 0x68 104. 'h' */
+ _LO, /* 0x69 105. 'i' */
+ _LO, /* 0x6A 106. 'j' */
+ _LO, /* 0x6B 107. 'k' */
+ _LO, /* 0x6C 108. 'l' */
+ _LO, /* 0x6D 109. 'm' */
+ _LO, /* 0x6E 110. 'n' */
+ _LO, /* 0x6F 111. 'o' */
+ _LO, /* 0x70 112. 'p' */
+ _LO, /* 0x71 113. 'q' */
+ _LO, /* 0x72 114. 'r' */
+ _LO, /* 0x73 115. 's' */
+ _LO, /* 0x74 116. 't' */
+ _LO, /* 0x75 117. 'u' */
+ _LO, /* 0x76 118. 'v' */
+ _LO, /* 0x77 119. 'w' */
+ _LO, /* 0x78 120. 'x' */
+ _LO, /* 0x79 121. 'y' */
+ _LO, /* 0x7A 122. 'z' */
+ _PU, /* 0x7B 123. '{' */
+ _PU, /* 0x7C 124. '|' */
+ _PU, /* 0x7D 125. '}' */
+ _PU, /* 0x7E 126. '~' */
+ _CN, /* 0x7F 127. */
+
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80 to 0x8F */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90 to 0x9F */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xA0 to 0xAF */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xB0 to 0xBF */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xC0 to 0xCF */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xD0 to 0xDF */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xE0 to 0xEF */
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 0xF0 to 0x100 */
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/mtrrs.c b/tboot/mtrrs.c
new file mode 100644
index 0000000..0d02b90
--- /dev/null
+++ b/tboot/mtrrs.c
@@ -0,0 +1,624 @@
+/*
+ * mtrrs.c: support functions for manipulating MTRRs
+ *
+ * Copyright (c) 2003-2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+#include <efibase.h>
+#include <types.h>
+#include <stdbool.h>
+#include <compiler.h>
+#include <string.h>
+#include <processor.h>
+#include <msr.h>
+#include <printk.h>
+#include <misc.h>
+#include <page.h>
+#include <tb_error.h>
+#include <eficore.h>
+#include <tboot.h>
+#include <acpi.h>
+#include <mle.h>
+#include <txt/config_regs.h>
+#include <txt/mtrrs.h>
+#include <txt/acmod.h>
+#include <tpm.h>
+
+#define MTRR_TYPE_MIXED -1
+#define MMIO_APIC_BASE 0xFEE00000
+#define NR_MMIO_APIC_PAGES 1
+#define NR_MMIO_IOAPIC_PAGES 1
+#define NR_MMIO_PCICFG_PAGES 1
+#define SINIT_MTRR_MASK 0xFFFFFF /* SINIT requires 36b mask */
+
+/* saved MTRR state or NULL if orig. MTRRs have not been changed */
+static __data mtrr_state_t *g_saved_mtrrs = NULL;
+
+static uint64_t get_maxphyaddr_mask(void)
+{
+ static bool printed_msg = false;
+ union {
+ uint32_t raw;
+ struct {
+ uint32_t num_pa_bits : 8;
+ uint32_t num_la_bits : 8;
+ uint32_t reserved : 16;
+ };
+ } num_addr_bits;
+
+ /* does CPU support 0x80000008 CPUID leaf? (all TXT CPUs should) */
+ uint32_t max_ext_fn = cpuid_eax(0x80000000);
+ if ( max_ext_fn < 0x80000008 )
+ return 0xffffff; /* if not, default is 36b support */
+
+ num_addr_bits.raw = cpuid_eax(0x80000008);
+ if ( !printed_msg ) {
+ printk(TBOOT_DETA"CPU supports %u phys address bits\n", num_addr_bits.num_pa_bits);
+ printed_msg = true;
+ }
+ return ((1ULL << num_addr_bits.num_pa_bits) - 1) >> PAGE_SHIFT;
+}
+
+/*
+ * this must be done for each processor so that all have the same
+ * memory types
+ */
+bool set_mtrrs_for_acmod(const acm_hdr_t *hdr)
+{
+ unsigned long long rflags;
+ unsigned long long cr0, cr4;
+
+ /*
+ * need to do some things before we start changing MTRRs
+ *
+ * since this will modify some of the MTRRs, they should be saved first
+ * so that they can be restored once the AC mod is done
+ */
+
+ /* disable interrupts */
+ rflags = read_rflags();
+ disable_intr();
+
+ /* save CR0 then disable cache (CRO.CD=1, CR0.NW=0) */
+ cr0 = read_cr0();
+ write_cr0((cr0 & ~CR0_NW) | CR0_CD);
+
+ /* flush caches */
+ wbinvd();
+
+ /* save CR4 and disable global pages (CR4.PGE=0) */
+ cr4 = read_cr4();
+ if (cr4 & CR4_PGE)
+ write_cr4(cr4 & ~CR4_PGE);
+ else
+ flush_tlb();
+
+ /* disable MTRRs */
+ set_all_mtrrs(false);
+
+ /*
+ * now set MTRRs for AC mod and rest of memory
+ */
+ if ( !set_mem_type(hdr, hdr->size*4, MTRR_TYPE_WRBACK) )
+ return false;
+
+ /*
+ * now undo some of earlier changes and enable our new settings
+ */
+
+ /* flush caches */
+ wbinvd();
+
+ /* enable MTRRs */
+ set_all_mtrrs(true);
+
+ /* restore CR0 (cacheing) */
+ write_cr0(cr0);
+
+ /* restore CR4 (global pages) */
+ if (cr4 & CR4_PGE)
+ write_cr4(cr4);
+
+ /* enable interrupts */
+ write_rflags(rflags);
+
+ return true;
+}
+
+void save_mtrrs(mtrr_state_t *saved_state)
+{
+ mtrr_cap_t mtrr_cap;
+
+ /* IA32_MTRR_DEF_TYPE MSR */
+ saved_state->mtrr_def_type.raw = rdmsr(MSR_MTRRdefType);
+
+ /* number variable MTTRRs */
+ mtrr_cap.raw = rdmsr(MSR_MTRRcap);
+ if ( mtrr_cap.vcnt > MAX_VARIABLE_MTRRS ) {
+ /* print warning but continue saving what we can */
+ /* (set_mem_type() won't exceed the array, so we're safe doing this) */
+ printk(TBOOT_WARN"actual # var MTRRs (%d) > MAX_VARIABLE_MTRRS (%d)\n",
+ mtrr_cap.vcnt, MAX_VARIABLE_MTRRS);
+ saved_state->num_var_mtrrs = MAX_VARIABLE_MTRRS;
+ }
+ else
+ saved_state->num_var_mtrrs = mtrr_cap.vcnt;
+
+ /* physmask's and physbase's */
+ for ( unsigned int ndx = 0; ndx < saved_state->num_var_mtrrs; ndx++ ) {
+ saved_state->mtrr_physmasks[ndx].raw =
+ rdmsr(MTRR_PHYS_MASK0_MSR + ndx*2);
+ saved_state->mtrr_physbases[ndx].raw =
+ rdmsr(MTRR_PHYS_BASE0_MSR + ndx*2);
+ }
+
+ g_saved_mtrrs = saved_state;
+}
+
+static void print_mtrrs(const mtrr_state_t *saved_state)
+{
+ printk(TBOOT_DETA"mtrr_def_type: e = %d, fe = %d, type = %x\n",
+ saved_state->mtrr_def_type.e, saved_state->mtrr_def_type.fe,
+ saved_state->mtrr_def_type.type );
+ printk(TBOOT_DETA"mtrrs:\n");
+ printk(TBOOT_DETA"\t\t base mask type v\n");
+ for ( unsigned int i = 0; i < saved_state->num_var_mtrrs; i++ ) {
+ printk(TBOOT_DETA"\t\t%13.13Lx %13.13Lx %2.2x %d\n",
+ (uint64_t)saved_state->mtrr_physbases[i].base,
+ (uint64_t)saved_state->mtrr_physmasks[i].mask,
+ saved_state->mtrr_physbases[i].type,
+ saved_state->mtrr_physmasks[i].v );
+ }
+}
+
+/* base should be 4k-bytes aligned, no invalid overlap combination */
+static int get_page_type(const mtrr_state_t *saved_state, uint32_t base)
+{
+ int type = -1;
+ bool wt = false;
+ uint64_t maxphyaddr_mask = get_maxphyaddr_mask();
+
+ /* omit whether the fix mtrrs are enabled, just check var mtrrs */
+
+ base >>= PAGE_SHIFT;
+ for ( unsigned int i = 0; i < saved_state->num_var_mtrrs; i++ ) {
+ const mtrr_physbase_t *base_i = &saved_state->mtrr_physbases[i];
+ const mtrr_physmask_t *mask_i = &saved_state->mtrr_physmasks[i];
+
+ if ( mask_i->v == 0 )
+ continue;
+ if ( (base & mask_i->mask & maxphyaddr_mask) !=
+ (base_i->base & mask_i->mask & maxphyaddr_mask) )
+ continue;
+
+ type = base_i->type;
+ if ( type == MTRR_TYPE_UNCACHABLE )
+ return MTRR_TYPE_UNCACHABLE;
+ if ( type == MTRR_TYPE_WRTHROUGH )
+ wt = true;
+ }
+ if ( wt )
+ return MTRR_TYPE_WRTHROUGH;
+ if ( type != -1 )
+ return type;
+
+ return saved_state->mtrr_def_type.type;
+}
+
+static int get_region_type(const mtrr_state_t *saved_state,
+ uint32_t base, uint32_t pages)
+{
+ int type;
+ uint32_t end;
+
+ if ( pages == 0 )
+ return MTRR_TYPE_MIXED;
+
+ /* wrap the 4G address space */
+ if ( ((uint32_t)(~0) - base) < (pages << PAGE_SHIFT) )
+ return MTRR_TYPE_MIXED;
+
+ if ( saved_state->mtrr_def_type.e == 0 )
+ return MTRR_TYPE_UNCACHABLE;
+
+ /* align to 4k page boundary */
+ base &= PAGE_MASK;
+ end = base + (pages << PAGE_SHIFT);
+
+ type = get_page_type(saved_state, base);
+ base += PAGE_SIZE;
+ for ( ; base < end; base += PAGE_SIZE )
+ if ( type != get_page_type(saved_state, base) )
+ return MTRR_TYPE_MIXED;
+
+ return type;
+}
+
+static bool validate_mmio_regions(const mtrr_state_t *saved_state)
+{
+ acpi_table_mcfg_t *acpi_table_mcfg;
+ acpi_table_ioapic_t *acpi_table_ioapic;
+
+ /* mmio space for TXT private config space should be UC */
+ if ( get_region_type(saved_state, TXT_PRIV_CONFIG_REGS_BASE,
+ TXT_CONFIG_REGS_SIZE >> PAGE_SHIFT)
+ != MTRR_TYPE_UNCACHABLE ) {
+ printk(TBOOT_ERR"MMIO space for TXT private config space should be UC\n");
+ return false;
+ }
+
+ /* mmio space for TXT public config space should be UC */
+ if ( get_region_type(saved_state, TXT_PUB_CONFIG_REGS_BASE,
+ TXT_CONFIG_REGS_SIZE >> PAGE_SHIFT)
+ != MTRR_TYPE_UNCACHABLE ) {
+ printk(TBOOT_ERR"MMIO space for TXT public config space should be UC\n");
+ return false;
+ }
+
+ /* mmio space for TPM should be UC */
+ if ( get_region_type(saved_state, TPM_LOCALITY_BASE,
+ NR_TPM_LOCALITY_PAGES * TPM_NR_LOCALITIES)
+ != MTRR_TYPE_UNCACHABLE ) {
+ printk(TBOOT_ERR"MMIO space for TPM should be UC\n");
+ return false;
+ }
+
+ /* mmio space for APIC should be UC */
+ if ( get_region_type(saved_state, MMIO_APIC_BASE, NR_MMIO_APIC_PAGES)
+ != MTRR_TYPE_UNCACHABLE ) {
+ printk(TBOOT_ERR"MMIO space for APIC should be UC\n");
+ return false;
+ }
+
+ /* TBD: is this check useful if we aren't DMA protecting ACPI? */
+ /* mmio space for IOAPIC should be UC */
+ acpi_table_ioapic = (acpi_table_ioapic_t *)get_acpi_ioapic_table();
+ if ( acpi_table_ioapic == NULL) {
+ printk(TBOOT_ERR"acpi_table_ioapic == NULL\n");
+ return false;
+ }
+ printk(TBOOT_DETA"acpi_table_ioapic @ %p, .address = %x\n",
+ acpi_table_ioapic, acpi_table_ioapic->address);
+ if ( get_region_type(saved_state, acpi_table_ioapic->address,
+ NR_MMIO_IOAPIC_PAGES)
+ != MTRR_TYPE_UNCACHABLE ) {
+ printk(TBOOT_ERR"MMIO space(%x) for IOAPIC should be UC\n",
+ acpi_table_ioapic->address);
+ return false;
+ }
+
+ /* TBD: is this check useful if we aren't DMA protecting ACPI? */
+ /* mmio space for PCI config space should be UC */
+ acpi_table_mcfg = (acpi_table_mcfg_t *)get_acpi_mcfg_table();
+ if ( acpi_table_mcfg == NULL) {
+ printk(TBOOT_ERR"acpi_table_mcfg == NULL\n");
+ return false;
+ }
+ printk(TBOOT_DETA"acpi_table_mcfg @ %p, .base_address = %x\n",
+ acpi_table_mcfg, acpi_table_mcfg->base_address);
+ if ( get_region_type(saved_state, acpi_table_mcfg->base_address,
+ NR_MMIO_PCICFG_PAGES)
+ != MTRR_TYPE_UNCACHABLE ) {
+ printk(TBOOT_ERR"MMIO space(%x) for PCI config space should be UC\n",
+ acpi_table_mcfg->base_address);
+ return false;
+ }
+
+ return true;
+}
+
+bool validate_mtrrs(const mtrr_state_t *saved_state)
+{
+ mtrr_cap_t mtrr_cap;
+ uint64_t maxphyaddr_mask = get_maxphyaddr_mask();
+ uint64_t max_pages = maxphyaddr_mask + 1; /* max # 4k pages supported */
+
+ /* check is meaningless if MTRRs were disabled */
+ if ( saved_state->mtrr_def_type.e == 0 )
+ return true;
+
+ /* number variable MTRRs */
+ mtrr_cap.raw = rdmsr(MSR_MTRRcap);
+ if ( mtrr_cap.vcnt < saved_state->num_var_mtrrs ) {
+ printk(TBOOT_ERR"actual # var MTRRs (%d) < saved # (%d)\n",
+ mtrr_cap.vcnt, saved_state->num_var_mtrrs);
+ return false;
+ }
+
+ /* variable MTRRs describing non-contiguous memory regions */
+ for ( unsigned int ndx = 0; ndx < saved_state->num_var_mtrrs; ndx++ ) {
+ uint64_t tb;
+
+ if ( saved_state->mtrr_physmasks[ndx].v == 0 )
+ continue;
+
+ for ( tb = 1; tb != max_pages; tb = tb << 1 ) {
+ if ( (tb & saved_state->mtrr_physmasks[ndx].mask & maxphyaddr_mask)
+ != 0 )
+ break;
+ }
+ for ( ; tb != max_pages; tb = tb << 1 ) {
+ if ( (tb & saved_state->mtrr_physmasks[ndx].mask & maxphyaddr_mask)
+ == 0 )
+ break;
+ }
+ if ( tb != max_pages ) {
+ printk(TBOOT_ERR"var MTRRs with non-contiguous regions: base=0x%Lx, mask=0x%Lx\n",
+ (uint64_t)saved_state->mtrr_physbases[ndx].base
+ & maxphyaddr_mask,
+ (uint64_t)saved_state->mtrr_physmasks[ndx].mask
+ & maxphyaddr_mask);
+ print_mtrrs(saved_state);
+ return false;
+ }
+ }
+
+ /* overlaping regions with invalid memory type combinations */
+ for ( unsigned int ndx = 0; ndx < saved_state->num_var_mtrrs; ndx++ ) {
+ const mtrr_physbase_t *base_ndx = &saved_state->mtrr_physbases[ndx];
+ const mtrr_physmask_t *mask_ndx = &saved_state->mtrr_physmasks[ndx];
+
+ if ( mask_ndx->v == 0 )
+ continue;
+
+ for ( unsigned int i = ndx + 1; i < saved_state->num_var_mtrrs; i++ ) {
+ const mtrr_physbase_t *base_i = &saved_state->mtrr_physbases[i];
+ const mtrr_physmask_t *mask_i = &saved_state->mtrr_physmasks[i];
+
+ if ( mask_i->v == 0 )
+ continue;
+
+ if ( (base_ndx->base & mask_ndx->mask & mask_i->mask & maxphyaddr_mask)
+ != (base_i->base & mask_i->mask & maxphyaddr_mask) &&
+ (base_i->base & mask_i->mask & mask_ndx->mask & maxphyaddr_mask)
+ != (base_ndx->base & mask_ndx->mask & maxphyaddr_mask) )
+ continue;
+
+ if ( base_ndx->type == base_i->type )
+ continue;
+ if ( base_ndx->type == MTRR_TYPE_UNCACHABLE
+ || base_i->type == MTRR_TYPE_UNCACHABLE )
+ continue;
+ if ( base_ndx->type == MTRR_TYPE_WRTHROUGH
+ && base_i->type == MTRR_TYPE_WRBACK )
+ continue;
+ if ( base_ndx->type == MTRR_TYPE_WRBACK
+ && base_i->type == MTRR_TYPE_WRTHROUGH )
+ continue;
+
+ /* 2 overlapped regions have invalid mem type combination, */
+ /* need to check whether there is a third region which has type */
+ /* of UNCACHABLE and contains at least one of these two regions. */
+ /* If there is, then the combination of these 3 region is valid */
+ unsigned int j;
+ for ( j = 0; j < saved_state->num_var_mtrrs; j++ ) {
+ const mtrr_physbase_t *base_j
+ = &saved_state->mtrr_physbases[j];
+ const mtrr_physmask_t *mask_j
+ = &saved_state->mtrr_physmasks[j];
+
+ if ( mask_j->v == 0 )
+ continue;
+
+ if ( base_j->type != MTRR_TYPE_UNCACHABLE )
+ continue;
+
+ if ( (base_ndx->base & mask_ndx->mask & mask_j->mask & maxphyaddr_mask)
+ == (base_j->base & mask_j->mask & maxphyaddr_mask)
+ && (mask_j->mask & ~mask_ndx->mask & maxphyaddr_mask) == 0 )
+ break;
+
+ if ( (base_i->base & mask_i->mask & mask_j->mask & maxphyaddr_mask)
+ == (base_j->base & mask_j->mask & maxphyaddr_mask)
+ && (mask_j->mask & ~mask_i->mask & maxphyaddr_mask) == 0 )
+ break;
+ }
+ if ( j < saved_state->num_var_mtrrs )
+ continue;
+
+ printk(TBOOT_ERR"var MTRRs overlaping regions, invalid type combinations\n");
+ print_mtrrs(saved_state);
+ return false;
+ }
+ }
+
+ if ( !validate_mmio_regions(saved_state) ) {
+ printk(TBOOT_ERR"Some mmio region should be UC type\n");
+ print_mtrrs(saved_state);
+ return false;
+ }
+
+ print_mtrrs(saved_state);
+ return true;
+}
+
+void restore_mtrrs(const mtrr_state_t *saved_state)
+{
+ /* called by apply_policy() so use saved ptr */
+ if ( saved_state == NULL )
+ saved_state = g_saved_mtrrs;
+ /* haven't saved them yet, so return */
+ if ( saved_state == NULL )
+ return;
+
+ /* disable all MTRRs first */
+ set_all_mtrrs(false);
+
+ /* physmask's and physbase's */
+ for ( unsigned int ndx = 0; ndx < saved_state->num_var_mtrrs; ndx++ ) {
+ wrmsr(MTRR_PHYS_MASK0_MSR + ndx*2,
+ saved_state->mtrr_physmasks[ndx].raw);
+ wrmsr(MTRR_PHYS_BASE0_MSR + ndx*2,
+ saved_state->mtrr_physbases[ndx].raw);
+ }
+
+ /* IA32_MTRR_DEF_TYPE MSR */
+ wrmsr(MSR_MTRRdefType, saved_state->mtrr_def_type.raw);
+}
+
+/*
+ * set the memory type for specified range (base to base+size)
+ * to mem_type and everything else to UC
+ */
+bool set_mem_type(const void *base, uint32_t size, uint32_t mem_type)
+{
+ int num_pages;
+ int ndx;
+ mtrr_def_type_t mtrr_def_type;
+ mtrr_cap_t mtrr_cap;
+ mtrr_physmask_t mtrr_physmask;
+ mtrr_physbase_t mtrr_physbase;
+
+ /*
+ * disable all fixed MTRRs
+ * set default type to UC
+ */
+ mtrr_def_type.raw = rdmsr(MSR_MTRRdefType);
+ mtrr_def_type.fe = 0;
+ mtrr_def_type.type = MTRR_TYPE_UNCACHABLE;
+ wrmsr(MSR_MTRRdefType, mtrr_def_type.raw);
+
+ /*
+ * initially disable all variable MTRRs (we'll enable the ones we use)
+ */
+ mtrr_cap.raw = rdmsr(MSR_MTRRcap);
+ for ( ndx = 0; ndx < mtrr_cap.vcnt; ndx++ ) {
+ mtrr_physmask.raw = rdmsr(MTRR_PHYS_MASK0_MSR + ndx*2);
+ mtrr_physmask.v = 0;
+ wrmsr(MTRR_PHYS_MASK0_MSR + ndx*2, mtrr_physmask.raw);
+ }
+
+ /*
+ * map all AC module pages as mem_type
+ */
+
+ num_pages = PAGE_UP(size) >> PAGE_SHIFT;
+ ndx = 0;
+
+ printk(TBOOT_DETA"setting MTRRs for acmod: base=%p, size=%x, num_pages=%d\n",
+ base, size, num_pages);
+ /*
+ * Each VAR MTRR base must be a multiple if that MTRR's Size
+ */
+ unsigned long long base_v;
+ base_v = (unsigned long long) base;
+ int i =0;
+ // mtrr size in pages
+ int mtrr_s = 1;
+ while ((base_v & 0x01) == 0) {
+ i++;
+ base_v = base_v >>1 ;
+
+ }
+ for (int j=i-12; j>0; j--) mtrr_s =mtrr_s*2; //mtrr_s = mtrr_s << 1
+ printk(TBOOT_DETA"The maximum allowed MTRR range size=%d Pages \n", mtrr_s);
+
+ while (num_pages >= mtrr_s){
+
+ /* set the base of the current MTRR */
+ mtrr_physbase.raw = rdmsr(MTRR_PHYS_BASE0_MSR + ndx*2);
+ mtrr_physbase.base = ((unsigned long long)base >> PAGE_SHIFT) &
+ SINIT_MTRR_MASK;
+ mtrr_physbase.type = mem_type;
+ wrmsr(MTRR_PHYS_BASE0_MSR + ndx*2, mtrr_physbase.raw);
+
+ mtrr_physmask.raw = rdmsr(MTRR_PHYS_MASK0_MSR + ndx*2);
+ mtrr_physmask.mask = ~(mtrr_s - 1) & SINIT_MTRR_MASK;
+ mtrr_physmask.v = 1;
+ wrmsr(MTRR_PHYS_MASK0_MSR + ndx*2, mtrr_physmask.raw);
+
+ base += (mtrr_s * PAGE_SIZE);
+ num_pages -= mtrr_s;
+ ndx++;
+ if ( ndx == mtrr_cap.vcnt ) {
+ printk(TBOOT_ERR"exceeded number of var MTRRs when mapping range\n");
+ return false;
+ }
+ }
+ while ( num_pages > 0 ) {
+ uint32_t pages_in_range;
+
+ /* set the base of the current MTRR */
+ mtrr_physbase.raw = rdmsr(MTRR_PHYS_BASE0_MSR + ndx*2);
+ mtrr_physbase.base = ((unsigned long long)base >> PAGE_SHIFT) &
+ SINIT_MTRR_MASK;
+ mtrr_physbase.type = mem_type;
+ wrmsr(MTRR_PHYS_BASE0_MSR + ndx*2, mtrr_physbase.raw);
+
+ /*
+ * calculate MTRR mask
+ * MTRRs can map pages in power of 2
+ * may need to use multiple MTRRS to map all of region
+ */
+ pages_in_range = 1 << (fls(num_pages) - 1);
+
+ mtrr_physmask.raw = rdmsr(MTRR_PHYS_MASK0_MSR + ndx*2);
+ mtrr_physmask.mask = ~(pages_in_range - 1) & SINIT_MTRR_MASK;
+ mtrr_physmask.v = 1;
+ wrmsr(MTRR_PHYS_MASK0_MSR + ndx*2, mtrr_physmask.raw);
+
+ /*prepare for the next loop depending on number of pages
+ * We figure out from the above how many pages could be used in this
+ * mtrr. Then we decrement the count, increment the base,
+ * increment the mtrr we are dealing with, and if num_pages is
+ * still not zero, we do it again.
+ */
+ base += (pages_in_range * PAGE_SIZE);
+ num_pages -= pages_in_range;
+ ndx++;
+ if ( ndx == mtrr_cap.vcnt ) {
+ printk(TBOOT_ERR"exceeded number of var MTRRs when mapping range\n");
+ return false;
+ }
+ }
+ return true;
+}
+
+/* enable/disable all MTRRs */
+void set_all_mtrrs(bool enable)
+{
+ mtrr_def_type_t mtrr_def_type;
+
+ mtrr_def_type.raw = rdmsr(MSR_MTRRdefType);
+ mtrr_def_type.e = enable ? 1 : 0;
+ wrmsr(MSR_MTRRdefType, mtrr_def_type.raw);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil * End:
+ */
diff --git a/tboot/pci_cfgreg.c b/tboot/pci_cfgreg.c
new file mode 100644
index 0000000..5007b74
--- /dev/null
+++ b/tboot/pci_cfgreg.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * Copyright (c) 2000, Michael Smith <msmith@freebsd.org>
+ * Copyright (c) 2000, BSDi
+ * Copyright (c) 2004, Scott Long <scottl@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* from:
+ * $FreeBSD: src/sys/i386/pci/pci_cfgreg.c,v 1.134.2.2.2.1 2010/06/14 02:09:06 kensmith Exp $
+ */
+/*
+ * Portions copyright (c) 2010, Intel Corporation
+ */
+
+#include <config.h>
+#include <efibase.h>
+#include <types.h>
+#include <mutex.h>
+#include <io.h>
+#include <pci_cfgreg.h>
+
+enum {
+ CFGMECH_NONE = 0,
+ CFGMECH_1,
+ CFGMECH_2,
+ CFGMECH_PCIE,
+};
+
+struct mutex pcicfg_mtx;
+static const int cfgmech = CFGMECH_1;
+
+/*
+ * Configuration space access using direct register operations
+ */
+
+/* enable configuration space accesses and return data port address */
+static int
+pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes)
+{
+ int dataport = 0;
+
+ if (bus <= PCI_BUSMAX
+ && slot <= PCI_SLOTMAX
+ && func <= PCI_FUNCMAX
+ && (unsigned)reg <= PCI_REGMAX
+ && bytes != 3
+ && (unsigned)bytes <= 4
+ && (reg & (bytes - 1)) == 0) {
+ switch (cfgmech) {
+ case CFGMECH_PCIE:
+ case CFGMECH_1:
+ outl(CONF1_ADDR_PORT, (1 << 31)
+ | (bus << 16) | (slot << 11)
+ | (func << 8) | (reg & ~0x03));
+ dataport = CONF1_DATA_PORT + (reg & 0x03);
+ break;
+ case CFGMECH_2:
+ outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1));
+ outb(CONF2_FORWARD_PORT, bus);
+ dataport = 0xc000 | (slot << 8) | reg;
+ break;
+ default:
+ break;
+ }
+ }
+ return (dataport);
+}
+
+/* disable configuration space accesses */
+static void
+pci_cfgdisable(void)
+{
+ switch (cfgmech) {
+ case CFGMECH_PCIE:
+ case CFGMECH_1:
+ /*
+ * Do nothing for the config mechanism 1 case.
+ * Writing a 0 to the address port can apparently
+ * confuse some bridges and cause spurious
+ * access failures.
+ */
+ break;
+ case CFGMECH_2:
+ outb(CONF2_ENABLE_PORT, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+int pcireg_cfgread(int bus, int slot, int func, int reg, int bytes)
+{
+ int data = -1;
+ int port;
+
+ mtx_enter(&pcicfg_mtx);
+ port = pci_cfgenable(bus, slot, func, reg, bytes);
+ if (port != 0) {
+ switch (bytes) {
+ case 1:
+ data = inb(port);
+ break;
+ case 2:
+ data = inw(port);
+ break;
+ case 4:
+ data = inl(port);
+ break;
+ default:
+ break;
+ }
+ pci_cfgdisable();
+ }
+ mtx_leave(&pcicfg_mtx);
+ return (data);
+}
+
+void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes)
+{
+ int port;
+
+ mtx_enter(&pcicfg_mtx);
+ port = pci_cfgenable(bus, slot, func, reg, bytes);
+ if (port != 0) {
+ switch (bytes) {
+ case 1:
+ outb(port, data);
+ break;
+ case 2:
+ outw(port, data);
+ break;
+ case 4:
+ outl(port, data);
+ break;
+ default:
+ break;
+ }
+ pci_cfgdisable();
+ }
+ mtx_leave(&pcicfg_mtx);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/policy.c b/tboot/policy.c
new file mode 100644
index 0000000..3c4d7d1
--- /dev/null
+++ b/tboot/policy.c
@@ -0,0 +1,879 @@
+/*
+ * policy.c: support functions for tboot verification launch
+ *
+ * Copyright (c) 2006-2014, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+#include <efibase.h>
+#include <stdarg.h>
+#include <types.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <printk.h>
+#include <compiler.h>
+#include <string.h>
+#include <processor.h>
+#include <eficore.h>
+#include <eficonfig.h>
+#include <misc.h>
+#include <uuid.h>
+#include <hash.h>
+#include <tb_error.h>
+#define PRINT printk
+#include <mle.h>
+#include <atomic.h>
+#include <tboot.h>
+#include <integrity.h>
+#include <tpm.h>
+#include <tb_policy.h>
+#include <lcp3.h>
+#include <lcp3_hlp.h>
+#include <cmdline.h>
+#include <txt/config_regs.h>
+#include <txt/mtrrs.h>
+#include <txt/txt.h>
+#include <txt/heap.h>
+
+/*
+ * policy actions
+ */
+typedef enum {
+ TB_POLACT_CONTINUE,
+ TB_POLACT_UNMEASURED_LAUNCH,
+ TB_POLACT_HALT,
+} tb_policy_action_t;
+
+/* policy map types */
+typedef struct {
+ tb_error_t error;
+ tb_policy_action_t action;
+} tb_policy_map_entry_t;
+
+typedef struct {
+ uint8_t policy_type;
+ tb_policy_action_t default_action;
+ tb_policy_map_entry_t exception_action_table[TB_ERR_MAX];
+ /* have TB_ERR_NONE as last entry */
+} tb_policy_map_t;
+
+/* map */
+static const tb_policy_map_t g_policy_map[] = {
+ { TB_POLTYPE_CONT_NON_FATAL, TB_POLACT_CONTINUE,
+ {
+ {TB_ERR_FATAL, TB_POLACT_HALT},
+ {TB_ERR_TPM_NOT_READY, TB_POLACT_UNMEASURED_LAUNCH},
+ {TB_ERR_SMX_NOT_SUPPORTED, TB_POLACT_UNMEASURED_LAUNCH},
+ {TB_ERR_VMX_NOT_SUPPORTED, TB_POLACT_UNMEASURED_LAUNCH},
+ {TB_ERR_TXT_NOT_SUPPORTED, TB_POLACT_UNMEASURED_LAUNCH},
+ {TB_ERR_SINIT_NOT_PRESENT, TB_POLACT_UNMEASURED_LAUNCH},
+ {TB_ERR_ACMOD_VERIFY_FAILED, TB_POLACT_UNMEASURED_LAUNCH},
+ {TB_ERR_NONE, TB_POLACT_CONTINUE},
+ }
+ },
+
+ { TB_POLTYPE_CONT_VERIFY_FAIL, TB_POLACT_HALT,
+ {
+ {TB_ERR_MODULE_VERIFICATION_FAILED, TB_POLACT_CONTINUE},
+ {TB_ERR_NV_VERIFICATION_FAILED, TB_POLACT_CONTINUE},
+ {TB_ERR_POLICY_NOT_PRESENT, TB_POLACT_CONTINUE},
+ {TB_ERR_POLICY_INVALID, TB_POLACT_CONTINUE},
+ {TB_ERR_NONE, TB_POLACT_CONTINUE},
+ }
+ },
+
+ { TB_POLTYPE_HALT, TB_POLACT_HALT,
+ {
+ {TB_ERR_NONE, TB_POLACT_CONTINUE},
+ }
+ },
+};
+
+/* buffer for policy as read from TPM NV */
+#define MAX_POLICY_SIZE \
+ (( MAX_TB_POLICY_SIZE > sizeof(lcp_policy_t) ) \
+ ? MAX_TB_POLICY_SIZE \
+ : sizeof(lcp_policy_t) )
+static uint8_t _policy_index_buf[MAX_POLICY_SIZE];
+
+/* default policy */
+static const tb_policy_t _def_policy = {
+ version : 2,
+ policy_type : TB_POLTYPE_CONT_NON_FATAL,
+ hash_alg : TB_HALG_SHA1,
+ policy_control : TB_POLCTL_EXTEND_PCR17,
+ num_entries : 3,
+ entries : {
+ { /* mod 0 is extended to PCR 18 by default, so don't re-extend it */
+ mod_num : 0,
+ pcr : TB_POL_PCR_NONE,
+ hash_type : TB_HTYPE_ANY,
+ num_hashes : 0
+ },
+ { /* all other modules are extended to PCR 19 */
+ mod_num : TB_POL_MOD_NUM_ANY,
+ pcr : 19,
+ hash_type : TB_HTYPE_ANY,
+ num_hashes : 0
+ },
+ { /* NV index for geo-tagging will be extended to PCR 22 */
+ mod_num : TB_POL_MOD_NUM_NV_RAW,
+ pcr : 22,
+ hash_type : TB_HTYPE_ANY,
+ nv_index : 0x40000010,
+ num_hashes : 0
+ }
+ }
+};
+
+/* default policy for Details/Authorities pcr mapping */
+static const tb_policy_t _def_policy_da = {
+ version : 2,
+ policy_type : TB_POLTYPE_CONT_NON_FATAL,
+ hash_alg : TB_HALG_SHA1,
+ policy_control : TB_POLCTL_EXTEND_PCR17,
+ num_entries : 3,
+ entries : {
+ { /* mod 0 is extended to PCR 17 by default, so don't re-extend it */
+ mod_num : 0,
+ pcr : TB_POL_PCR_NONE,
+ hash_type : TB_HTYPE_ANY,
+ num_hashes : 0
+ },
+ { /* all other modules are extended to PCR 17 */
+ mod_num : TB_POL_MOD_NUM_ANY,
+ pcr : 17,
+ hash_type : TB_HTYPE_ANY,
+ num_hashes : 0
+ },
+ { /* NV index for geo-tagging will be extended to PCR 22 */
+ mod_num : TB_POL_MOD_NUM_NV_RAW,
+ pcr : 22,
+ hash_type : TB_HTYPE_ANY,
+ nv_index : 0x40000010,
+ num_hashes : 0
+ }
+ }
+};
+
+/* current policy */
+static const tb_policy_t* g_policy = &_def_policy;
+
+/*
+ * read_policy_from_tpm
+ *
+ * read policy from TPM NV into buffer
+ *
+ * policy_index_size is in/out
+ */
+static bool read_policy_from_tpm(uint32_t index, void* policy_index, size_t *policy_index_size)
+{
+#define NV_READ_SEG_SIZE 256
+ unsigned int offset = 0;
+ unsigned int data_size = 0;
+ uint32_t ret, index_size;
+
+ if ( policy_index_size == NULL ) {
+ printk(TBOOT_ERR"size is NULL\n");
+ return false;
+ }
+
+ ret = g_tpm->get_nvindex_size(g_tpm, g_tpm->cur_loc, index, &index_size);
+ if ( !ret )
+ return false;
+
+ if ( index_size > *policy_index_size ) {
+ printk(TBOOT_WARN"policy in TPM NV %x was too big for buffer\n", index);
+ index_size = *policy_index_size;
+ }
+
+
+ do {
+ /* get data_size */
+ if ( (index_size - offset) > NV_READ_SEG_SIZE )
+ data_size = NV_READ_SEG_SIZE;
+ else
+ data_size = (uint32_t)(index_size - offset);
+
+ /* read! */
+ ret = g_tpm->nv_read(g_tpm, g_tpm->cur_loc, index, offset,
+ (uint8_t *)policy_index + offset, &data_size);
+ if ( !ret || data_size == 0 )
+ break;
+
+ /* adjust offset */
+ offset += data_size;
+ } while ( offset < index_size );
+
+ if ( offset == 0 && !ret ) {
+ printk(TBOOT_ERR"Error: read TPM error: 0x%x from index %x.\n", ret, index);
+ return false;
+ }
+
+ *policy_index_size = offset;
+
+ return true;
+}
+
+/*
+ * unwrap_lcp_policy
+ *
+ * unwrap custom element in lcp policy into tb policy
+ * assume sinit has already verified lcp policy and lcp policy data.
+ */
+static bool unwrap_lcp_policy(void)
+{
+ void* lcp_base;
+ uint32_t lcp_size;
+ const efi_file_t *lcp;
+
+ // scaffolding
+ printk(TBOOT_INFO"in unwrap_lcp_policy\n");
+
+ if ( txt_is_launched() ) {
+ txt_heap_t *txt_heap = get_txt_heap();
+ os_sinit_data_t *os_sinit_data = get_os_sinit_data_start(txt_heap);
+
+ lcp_base = (void *)(unsigned long long)os_sinit_data->lcp_po_base;
+ lcp_size = (uint32_t)os_sinit_data->lcp_po_size;
+ }
+ else {
+ lcp = efi_get_lcp();
+ if ( lcp == NULL )
+ return false;
+ lcp_base = lcp->u.buffer;
+ lcp_size = lcp->size;
+ }
+
+ /* if lcp policy data version is 2+ */
+ if ( memcmp((void *)lcp->u.buffer, LCP_POLICY_DATA_FILE_SIGNATURE,
+ LCP_FILE_SIG_LENGTH) == 0 ) {
+ lcp_policy_data_t *poldata = (lcp_policy_data_t *)lcp_base;
+ lcp_policy_list_t *pollist = &poldata->policy_lists[0];
+
+ for ( int i = 0; i < poldata->num_lists; i++ ) {
+ lcp_policy_element_t *elt = pollist->policy_elements;
+ uint32_t elts_size = 0;
+
+ while ( elt ) {
+ /* check element type */
+ if ( elt->type == LCP_POLELT_TYPE_CUSTOM ||
+ elt->type == LCP_POLELT_TYPE_CUSTOM2 ) {
+ lcp_custom_element_t *custom =
+ (lcp_custom_element_t *)&elt->data;
+
+ /* check uuid in custom element */
+ if ( are_uuids_equal(&custom->uuid,
+ &((uuid_t)LCP_CUSTOM_ELEMENT_TBOOT_UUID)) ) {
+ memcpy(_policy_index_buf, &custom->data,
+ elt->size - sizeof(*elt) - sizeof(uuid_t));
+ return true; /* find tb policy */
+ }
+ }
+
+ elts_size += elt->size;
+ if ( elts_size >= pollist->policy_elements_size )
+ break;
+
+ elt = (void *)elt + elt->size;
+ }
+ if ( pollist->version == LCP_TPM12_POLICY_LIST_VERSION )
+ pollist = (void *)pollist + get_tpm12_policy_list_size(pollist);
+ else if ( pollist->version == LCP_TPM20_POLICY_LIST_VERSION )
+ pollist = (void *)pollist + get_tpm20_policy_list_size(
+ (lcp_policy_list_t2 *)pollist);
+ }
+ }
+
+ return false;
+}
+
+/*
+ * set_policy
+ *
+ * load policy from TPM NV and validate it, else use default
+ *
+ */
+tb_error_t set_policy(void)
+{
+ /* try to read tboot policy from TB_POLICY_INDEX in TPM NV */
+ size_t policy_index_size = sizeof(_policy_index_buf);
+ printk(TBOOT_INFO"reading Verified Launch Policy from TPM NV...\n");
+ if ( read_policy_from_tpm(g_tpm->tb_policy_index,
+ _policy_index_buf, &policy_index_size) ) {
+ printk(TBOOT_DETA"\t:%lu bytes read\n", policy_index_size);
+ if ( verify_policy((tb_policy_t *)_policy_index_buf,
+ policy_index_size, true) ) {
+ goto policy_found;
+ }
+ }
+ printk(TBOOT_WARN"\t:reading failed\n");
+
+ /* tboot policy not found in TB_POLICY_INDEX, so see if it is wrapped
+ * in a custom element in the PO policy; if so, SINIT will have verified
+ * the policy and policy data for us; we just need to ensure the policy
+ * type is LCP_POLTYPE_LIST (since we could have been give a policy data
+ * file even though the policy was not a LIST */
+ printk(TBOOT_INFO"reading Launch Control Policy from TPM NV...\n");
+ if ( read_policy_from_tpm(g_tpm->lcp_own_index,
+ _policy_index_buf, &policy_index_size) ) {
+ printk(TBOOT_DETA"\t:%lu bytes read\n", policy_index_size);
+ /* assume lcp policy has been verified by sinit already */
+ lcp_policy_t *pol = (lcp_policy_t *)_policy_index_buf;
+ if ( pol->version == LCP_DEFAULT_POLICY_VERSION_2 &&
+ pol->policy_type == LCP_POLTYPE_LIST && unwrap_lcp_policy() ) {
+ if ( verify_policy((tb_policy_t *)_policy_index_buf,
+ calc_policy_size((tb_policy_t *)_policy_index_buf),
+ true) )
+ goto policy_found;
+ }
+ lcp_policy_t2 *pol2 = (lcp_policy_t2 *)_policy_index_buf;
+ if ( pol2->version == LCP_DEFAULT_POLICY_VERSION &&
+ pol2->policy_type == LCP_POLTYPE_LIST && unwrap_lcp_policy() ) {
+ if ( verify_policy((tb_policy_t *)_policy_index_buf,
+ calc_policy_size((tb_policy_t *)_policy_index_buf),
+ true) )
+ goto policy_found;
+ }
+ }
+ printk(TBOOT_WARN"\t:reading failed\n");
+
+ /* either no policy in TPM NV or policy is invalid, so use default */
+ printk(TBOOT_WARN"failed to read policy from TPM NV, using default\n");
+ g_policy = g_using_da ? &_def_policy_da : &_def_policy;
+ policy_index_size = calc_policy_size(g_policy);
+
+ /* sanity check; but if it fails something is really wrong */
+ if ( !verify_policy(g_policy, policy_index_size, true) )
+ return TB_ERR_FATAL;
+ else
+ return TB_ERR_POLICY_NOT_PRESENT;
+
+policy_found:
+ /* compatible with tb_policy tools for TPM 1.2 */
+ {
+ tb_policy_t *tmp_policy = (tb_policy_t *)_policy_index_buf;
+ if (tmp_policy->hash_alg == 0)
+ tmp_policy->hash_alg = TB_HALG_SHA1;
+ }
+ g_policy = (tb_policy_t *)_policy_index_buf;
+ return TB_ERR_NONE;
+}
+
+/* hash current policy */
+bool hash_policy(tb_hash_t *hash, uint16_t hash_alg)
+{
+ if ( hash == NULL ) {
+ printk(TBOOT_ERR"Error: input parameter is wrong.\n");
+ return false;
+ }
+
+ return hash_buffer((unsigned char *)g_policy, calc_policy_size(g_policy),
+ hash, hash_alg);
+}
+
+/* generate hash by hashing cmdline and module image */
+static bool hash_module(hash_list_t *hl,
+ const char* cmdline, void *base,
+ size_t size)
+{
+ if ( hl == NULL ) {
+ printk(TBOOT_ERR"Error: input parameter is wrong.\n");
+ return false;
+ }
+
+ /* final hash is SHA-1( SHA-1(cmdline) | SHA-1(image) ) */
+ /* where cmdline is first stripped of leading spaces, file name, then */
+ /* any spaces until the next non-space char */
+ /* (e.g. " /foo/bar baz" -> "baz"; "/foo/bar" -> "") */
+
+ /* hash command line */
+ if ( cmdline == NULL )
+ cmdline = "";
+ // else
+ // cmdline = skip_filename(cmdline);
+
+ switch (g_tpm->extpol) {
+ case TB_EXTPOL_FIXED:
+ hl->count = 1;
+ hl->entries[0].alg = g_tpm->cur_alg;
+
+ if ( !hash_buffer((const unsigned char *)cmdline, strlen(cmdline),
+ &hl->entries[0].hash, g_tpm->cur_alg) )
+ return false;
+ /* hash image and extend into cmdline hash */
+ tb_hash_t img_hash;
+ if ( !hash_buffer(base, size, &img_hash, g_tpm->cur_alg) )
+ return false;
+ if ( !extend_hash(&hl->entries[0].hash, &img_hash, g_tpm->cur_alg) )
+ return false;
+
+ break;
+
+ case TB_EXTPOL_AGILE:
+ {
+ hash_list_t img_hl, final_hl;
+ if ( !g_tpm->hash(g_tpm, 2, (const unsigned char *)cmdline,
+ strlen(cmdline), hl) ) {
+ if ( !g_tpm->hash(g_tpm, 2, base, size, hl) )
+ return false;
+ return true;
+ }
+
+ uint8_t buf[128];
+
+ if ( !g_tpm->hash(g_tpm, 2, base, size, &img_hl) )
+ return false;
+ for (unsigned int i=0; i<hl->count; i++) {
+ for (unsigned int j=0; j<img_hl.count; j++) {
+ if (hl->entries[i].alg == img_hl.entries[j].alg) {
+ copy_hash((tb_hash_t *)buf, &hl->entries[i].hash,
+ hl->entries[i].alg);
+ copy_hash((tb_hash_t *)buf + get_hash_size(hl->entries[i].alg),
+ &img_hl.entries[j].hash, hl->entries[i].alg);
+ if ( !g_tpm->hash(g_tpm, 2, buf,
+ 2*get_hash_size(hl->entries[i].alg), &final_hl) )
+ return false;
+
+ for (unsigned int k=0; k<final_hl.count; k++) {
+ if (hl->entries[i].alg == final_hl.entries[k].alg) {
+ copy_hash(&hl->entries[i].hash,
+ &final_hl.entries[k].hash,
+ hl->entries[i].alg);
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+ }
+
+ break;
+ }
+
+ case TB_EXTPOL_EMBEDDED:
+ {
+ tb_hash_t img_hash;
+ hl->count = g_tpm->alg_count;
+ for (unsigned int i=0; i<hl->count; i++) {
+ hl->entries[i].alg = g_tpm->algs[i];
+ if ( !hash_buffer((const unsigned char *)cmdline, strlen(cmdline),
+ &hl->entries[i].hash, g_tpm->algs[i]) )
+ return false;
+
+ if ( !hash_buffer(base, size, &img_hash, g_tpm->algs[i]) )
+ return false;
+ if ( !extend_hash(&hl->entries[i].hash, &img_hash, g_tpm->algs[i]) )
+ return false;
+ }
+
+ break;
+ }
+
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+static bool is_hash_in_policy_entry(const tb_policy_entry_t *pol_entry,
+ tb_hash_t *hash, uint16_t hash_alg)
+{
+ /* assumes policy entry has been validated */
+
+ if ( pol_entry == NULL || hash == NULL) {
+ printk(TBOOT_ERR"Error: input parameter is wrong.\n");
+ return false;
+ }
+
+ if ( pol_entry->hash_type == TB_HTYPE_ANY )
+ return true;
+ else if ( pol_entry->hash_type == TB_HTYPE_IMAGE ) {
+ for ( int i = 0; i < pol_entry->num_hashes; i++ ) {
+ if ( are_hashes_equal(get_policy_entry_hash(pol_entry, hash_alg,
+ i), hash, hash_alg) )
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/*
+ * map policy type + error -> action
+ */
+static tb_policy_action_t evaluate_error(tb_error_t error)
+{
+ tb_policy_action_t action = TB_POLACT_HALT;
+
+ if ( error == TB_ERR_NONE )
+ return TB_POLACT_CONTINUE;
+
+ for ( unsigned int i = 0; i < ARRAY_SIZE(g_policy_map); i++ ) {
+ if ( g_policy_map[i].policy_type == g_policy->policy_type ) {
+ action = g_policy_map[i].default_action;
+ for ( unsigned int j = 0;
+ j < ARRAY_SIZE(g_policy_map[i].exception_action_table);
+ j++ ) {
+ if ( g_policy_map[i].exception_action_table[j].error ==
+ error )
+ action = g_policy_map[i].exception_action_table[j].action;
+ if ( g_policy_map[i].exception_action_table[j].error ==
+ TB_ERR_NONE )
+ break;
+ }
+ }
+ }
+
+ return action;
+}
+
+/*
+ * apply policy according to error happened.
+ */
+void apply_policy(tb_error_t error)
+{
+ tb_policy_action_t action;
+
+ /* save the error to TPM NV */
+ write_tb_error_code(error);
+
+ if ( error != TB_ERR_NONE )
+ print_tb_error_msg(error);
+
+ action = evaluate_error(error);
+ switch ( action ) {
+ case TB_POLACT_CONTINUE:
+ return;
+ case TB_POLACT_UNMEASURED_LAUNCH:
+ /* restore mtrr state saved before */
+ restore_mtrrs(NULL);
+ if ( s3_flag )
+ s3_launch();
+ else
+ efi_launch_kernel();
+ break; /* if launch xen fails, do halt at the end */
+ case TB_POLACT_HALT:
+ break; /* do halt at the end */
+ default:
+ printk(TBOOT_ERR"Error: invalid policy action (%d)\n", action);
+ /* do halt at the end */
+ }
+
+ _tboot_shared.shutdown_type = TB_SHUTDOWN_HALT;
+ shutdown();
+}
+
+#define VL_ENTRIES(i) g_pre_k_s3_state.vl_entries[i]
+#define NUM_VL_ENTRIES g_pre_k_s3_state.num_vl_entries
+
+/*
+ * verify modules against Verified Launch policy and save hash
+ * if pol_entry is NULL, assume it is for module 0, which gets extended
+ * to PCR 18
+ */
+static tb_error_t verify_module(void *base, size_t size,
+ tb_policy_entry_t *pol_entry,
+ uint16_t hash_alg)
+{
+ /* assumes module is valid */
+
+ char *cmdline = NULL; /* TODO get from configs get_module_cmd(g_ldr_ctx, module);*/
+
+ if ( pol_entry != NULL ) {
+ /* chunk the command line into 80 byte chunks */
+#define CHUNK_SIZE 80
+ int cmdlen = strlen(cmdline);
+ char *cptr = cmdline;
+ char cmdchunk[CHUNK_SIZE+1];
+ printk(TBOOT_INFO"verifying module \"");
+ while (cmdlen > 0) {
+ strncpy(cmdchunk, cptr, CHUNK_SIZE);
+ cmdchunk[CHUNK_SIZE] = 0;
+ printk(TBOOT_INFO"\n%s", cmdchunk);
+ cmdlen -= CHUNK_SIZE;
+ cptr += CHUNK_SIZE;
+ }
+ printk(TBOOT_INFO"\"...\n");
+ }
+
+ hash_list_t hl;
+ if ( !hash_module(&hl, cmdline, base, size) ) {
+ printk(TBOOT_ERR"\t hash cannot be generated.\n");
+ return TB_ERR_MODULE_VERIFICATION_FAILED;
+ }
+
+ /* add new hash to list (unless it doesn't get put in a PCR)
+ we'll just drop it if the list is full, but that will mean S3 resume
+ PCRs won't match pre-S3
+ NULL pol_entry means this is module 0 which is extended to PCR 18 */
+ if ( NUM_VL_ENTRIES >= MAX_VL_HASHES )
+ printk(TBOOT_WARN"\t too many hashes to save\n");
+ else if ( pol_entry == NULL || pol_entry->pcr != TB_POL_PCR_NONE ) {
+ uint8_t pcr = (pol_entry == NULL ) ?
+ (g_using_da ? 17 : 18) : pol_entry->pcr;
+ VL_ENTRIES(NUM_VL_ENTRIES).pcr = pcr;
+ VL_ENTRIES(NUM_VL_ENTRIES++).hl = hl;
+ }
+
+ if ( g_tpm->extpol != TB_EXTPOL_FIXED )
+ return TB_ERR_NONE;
+
+ if ( pol_entry != NULL &&
+ !is_hash_in_policy_entry(pol_entry, &hl.entries[0].hash, hash_alg) ) {
+ printk(TBOOT_ERR"\t verification failed\n");
+ return TB_ERR_MODULE_VERIFICATION_FAILED;
+ }
+
+ if ( pol_entry != NULL ) {
+ printk(TBOOT_DETA"\t OK : "); print_hash(&hl.entries[0].hash, hash_alg);
+ }
+
+ return TB_ERR_NONE;
+}
+
+static void verify_g_policy(void)
+{
+ /* assumes mbi is valid */
+ printk(TBOOT_INFO"verifying policy \n");
+
+ /* add entry for policy control field and (optionally) policy */
+ /* hash will be <policy control field (4bytes)> | <hash policy> */
+ /* where <hash policy> will be 0s if TB_POLCTL_EXTEND_PCR17 is clear */
+ static uint8_t buf[sizeof(tb_hash_t) + sizeof(g_policy->policy_control)];
+ memset(buf, 0, sizeof(buf));
+ memcpy(buf, &g_policy->policy_control, sizeof(g_policy->policy_control));
+ if ( g_policy->policy_control & TB_POLCTL_EXTEND_PCR17 ) {
+ if ( !hash_policy((tb_hash_t *)&buf[sizeof(g_policy->policy_control)],
+ g_tpm->cur_alg) ) {
+ printk(TBOOT_ERR"policy hash failed\n");
+ apply_policy(TB_ERR_MODULE_VERIFICATION_FAILED);
+ }
+ }
+
+ u32 size = get_hash_size(g_tpm->cur_alg) + sizeof(g_policy->policy_control);
+ switch (g_tpm->extpol) {
+ case TB_EXTPOL_FIXED:
+ VL_ENTRIES(NUM_VL_ENTRIES).hl.count = 1;
+ VL_ENTRIES(NUM_VL_ENTRIES).hl.entries[0].alg = g_tpm->cur_alg;
+ if ( !hash_buffer(buf, size,
+ &VL_ENTRIES(NUM_VL_ENTRIES).hl.entries[0].hash, g_tpm->cur_alg) )
+ apply_policy(TB_ERR_MODULE_VERIFICATION_FAILED);
+
+ break;
+
+ case TB_EXTPOL_AGILE:
+ if ( !g_tpm->hash(g_tpm, 2, buf, size, &VL_ENTRIES(NUM_VL_ENTRIES).hl) )
+ apply_policy(TB_ERR_MODULE_VERIFICATION_FAILED);
+ break;
+
+ case TB_EXTPOL_EMBEDDED:
+ {
+ VL_ENTRIES(NUM_VL_ENTRIES).hl.count = g_tpm->alg_count;
+ for (int i=0; i<g_tpm->alg_count; i++) {
+ VL_ENTRIES(NUM_VL_ENTRIES).hl.entries[i].alg = g_tpm->algs[i];
+ if ( !hash_buffer(buf, size, &VL_ENTRIES(NUM_VL_ENTRIES).hl.entries[i].hash,
+ g_tpm->algs[i]) )
+ return;
+ }
+
+ break;
+ }
+
+ default:
+ apply_policy(TB_ERR_MODULE_VERIFICATION_FAILED);
+ break;
+ }
+
+ VL_ENTRIES(NUM_VL_ENTRIES++).pcr = 17;
+ if ( g_using_da ) {
+ /* copying hash of policy_control into PCR 18 */
+ if ( NUM_VL_ENTRIES >= MAX_VL_HASHES )
+ printk(TBOOT_ERR"\t too many hashes to save for DA\n");
+ else {
+ VL_ENTRIES(NUM_VL_ENTRIES).hl = VL_ENTRIES(NUM_VL_ENTRIES-1).hl;
+ VL_ENTRIES(NUM_VL_ENTRIES++).pcr = 18;
+ }
+ }
+}
+
+void verify_all_modules(void)
+{
+ /* assumes mbi is valid */
+ verify_g_policy();
+
+ /* TODO this will be done after ebs with xen passing back the module
+ * information - the modules it loaded. */
+
+ printk(TBOOT_INFO"all modules are verified\n");
+}
+
+static int find_first_nvpolicy_entry(const tb_policy_t *policy)
+{
+ if ( policy == NULL ) {
+ PRINT(TBOOT_ERR"Error: policy pointer is NULL\n");
+ return -1;
+ }
+
+ for ( int i = 0; i < policy->num_entries; i++ ) {
+ tb_policy_entry_t *pol_entry = get_policy_entry(policy, i);
+ if ( pol_entry == NULL )
+ return -1;
+
+ if ( pol_entry->mod_num == TB_POL_MOD_NUM_NV ||
+ pol_entry->mod_num == TB_POL_MOD_NUM_NV_RAW )
+ return i;
+ }
+
+ return -1;
+}
+
+static int find_next_nvpolicy_entry(const tb_policy_t *policy, int i)
+{
+ if ( policy == NULL || i < 0 || i >= policy->num_entries )
+ return -1;
+
+ for ( i++; i < policy->num_entries; i++ ) {
+ tb_policy_entry_t *pol_entry = get_policy_entry(policy, i);
+ if ( pol_entry == NULL )
+ return -1;
+
+ if ( pol_entry->mod_num == TB_POL_MOD_NUM_NV ||
+ pol_entry->mod_num == TB_POL_MOD_NUM_NV_RAW )
+ return i;
+ }
+
+ return -1;
+}
+
+static uint8_t nv_buf[4096];
+
+static tb_error_t verify_nvindex(tb_policy_entry_t *pol_entry,
+ uint16_t hash_alg)
+{
+ size_t nv_size = sizeof(nv_buf);
+ tb_hash_t digest;
+ uint32_t attribute;
+
+ if ( pol_entry == NULL )
+ return TB_ERR_NV_VERIFICATION_FAILED;
+
+ printk(TBOOT_INFO"verifying nv index 0x%08X\n", pol_entry->nv_index);
+
+ /* check nv attribute */
+ if ( !g_tpm->get_nvindex_permission(g_tpm, 0, pol_entry->nv_index,
+ &attribute) ) {
+ printk(TBOOT_ERR"\t :reading nv index permission failed\n");
+ return TB_ERR_NV_VERIFICATION_FAILED;
+ }
+ if ( !(attribute & (TPM_NV_PER_OWNERWRITE | TPM_NV_PER_AUTHWRITE)) ) {
+ printk(TBOOT_ERR"\t :nv index should be OWNERWRITE or AUTHWRITE, bad permission!\n");
+ return TB_ERR_NV_VERIFICATION_FAILED;
+ }
+
+ /* get nv content */
+ memset(nv_buf, 0, sizeof(nv_buf));
+ if ( !read_policy_from_tpm(pol_entry->nv_index,
+ nv_buf, &nv_size) ) {
+ printk(TBOOT_ERR"\t :reading nv index 0x%08X failed\n",
+ pol_entry->nv_index);
+ return TB_ERR_NV_VERIFICATION_FAILED;
+ }
+
+ /* hash the buffer if needed */
+ switch ( pol_entry->mod_num ) {
+ case TB_POL_MOD_NUM_NV:
+ if ( !hash_buffer((const uint8_t*)nv_buf, nv_size, &digest,
+ TB_HALG_SHA1) ) {
+ printk(TBOOT_ERR"\t :nv content hash failed\n");
+ return TB_ERR_NV_VERIFICATION_FAILED;
+ }
+ break;
+ case TB_POL_MOD_NUM_NV_RAW:
+ if ( nv_size != sizeof(digest.sha1) ) {
+ printk(TBOOT_ERR"\t :raw nv with wrong size (%d), should be %d\n",
+ (int)nv_size, sizeof(digest.sha1));
+ return TB_ERR_NV_VERIFICATION_FAILED;
+ }
+ memcpy(digest.sha1, nv_buf, nv_size);
+ break;
+ default:
+ printk(TBOOT_ERR"\t :bad mod number for NV measuring in policy entry: %d\n",
+ pol_entry->mod_num);
+ return TB_ERR_NV_VERIFICATION_FAILED;
+ }
+
+ /* add new hash to list (unless it doesn't get put in a PCR)
+ we'll just drop it if the list is full, but that will mean S3 resume
+ PCRs won't match pre-S3 */
+ if ( NUM_VL_ENTRIES >= MAX_VL_HASHES )
+ printk(TBOOT_WARN"\t too many hashes to save\n");
+ else if ( pol_entry->pcr != TB_POL_PCR_NONE ) {
+ VL_ENTRIES(NUM_VL_ENTRIES).pcr = pol_entry->pcr;
+ VL_ENTRIES(NUM_VL_ENTRIES).hl.count = 1;
+ VL_ENTRIES(NUM_VL_ENTRIES).hl.entries[0].alg = TB_HALG_SHA1;
+ memcpy(VL_ENTRIES(NUM_VL_ENTRIES++).hl.entries[0].hash.sha1,
+ digest.sha1, SHA1_LENGTH);
+ }
+
+ /* verify nv content */
+ if ( !is_hash_in_policy_entry(pol_entry, &digest, hash_alg) ) {
+ printk(TBOOT_ERR"\t verification failed\n");
+ return TB_ERR_NV_VERIFICATION_FAILED;
+ }
+
+ printk(TBOOT_DETA"\t OK : "); print_hash(&digest, hash_alg);
+ return TB_ERR_NONE;
+}
+
+void verify_all_nvindices(void)
+{
+ /* go through nv policies in tb policy */
+ for ( int i = find_first_nvpolicy_entry(g_policy);
+ i >= 0;
+ i = find_next_nvpolicy_entry(g_policy, i) ) {
+ tb_policy_entry_t *pol_entry = get_policy_entry(g_policy, i);
+ apply_policy(verify_nvindex(pol_entry, g_policy->hash_alg));
+ }
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/printk.c b/tboot/printk.c
new file mode 100644
index 0000000..0bc4531
--- /dev/null
+++ b/tboot/printk.c
@@ -0,0 +1,195 @@
+/*
+ * printk.c: printk() output fn and helpers
+ *
+ * Copyright (c) 2006-2010, Intel Corporation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of the Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <config.h>
+#include <efibase.h>
+#include <types.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <compiler.h>
+#include <string.h>
+#include <mutex.h>
+#include <misc.h>
+#include <printk.h>
+#include <eficore.h>
+#include <cmdline.h>
+#include <tb_error.h>
+#include <tboot.h>
+
+uint8_t g_log_level = TBOOT_LOG_LEVEL_NONE;
+uint8_t g_log_targets = TBOOT_LOG_TARGET_NONE;
+
+static struct mutex print_lock;
+
+/*
+ * memory logging
+ */
+
+/* memory-based serial log (ensure in .data section so that not cleared) */
+__data tboot_log_t g_log = {0};
+
+static void memlog_init(void)
+{
+ if ( !g_log.is_init ) {
+ g_log.uuid = (uuid_t)TBOOT_LOG_UUID;
+ g_log.curr_pos = 0;
+ g_log.max_size = TBOOT_MEM_LOG_SIZE;
+ g_log.is_init = true;
+ }
+
+ /* initialize these post-launch as well, since bad/malicious values */
+ /* could compromise environment */
+ g_log.uuid = (uuid_t)TBOOT_LOG_UUID;
+ g_log.max_size = TBOOT_MEM_LOG_SIZE;
+
+ /* if we're calling this post-launch, verify that curr_pos is valid */
+ if ( g_log.curr_pos > g_log.max_size )
+ g_log.curr_pos = 0;
+}
+
+static void memlog_write(const char *str, unsigned int count)
+{
+ if ( count > g_log.max_size )
+ return;
+
+ /* wrap to beginning if too big to fit */
+ if ( g_log.curr_pos + count >= g_log.max_size )
+ g_log.curr_pos = 0;
+
+ memcpy(&g_log.buf[g_log.curr_pos], str, count);
+ g_log.curr_pos += count;
+
+ /* if the string wasn't NULL-terminated, then NULL-terminate the log */
+ if ( str[count-1] != '\0' )
+ g_log.buf[g_log.curr_pos] = '\0';
+ else {
+ /* so that curr_pos will point to the NULL and be overwritten */
+ /* on next copy */
+ g_log.curr_pos--;
+ }
+}
+
+void printk_init(printk_init_t init_type)
+{
+ if (init_type == INIT_EARLY_EFI || init_type == INIT_POST_LAUNCH)
+ mtx_init(&print_lock);
+
+ if (init_type == INIT_EARLY_EFI) {
+ /* Default to EFI logging at early startup */
+#ifdef EFI_EARLY_PRINTK
+ g_log_targets = TBOOT_LOG_TARGET_EFI;
+ g_log_level = TBOOT_LOG_LEVEL_ALL;
+#endif
+ return;
+ }
+
+ /* parse loglvl from string to int */
+ get_tboot_loglvl();
+
+ /* parse logging targets */
+ get_tboot_log_targets();
+
+ if (init_type == INIT_POST_EBS || init_type == INIT_POST_LAUNCH) {
+ /* now we can use VGA logging, EFI console is gone */
+ if ( g_log_targets & TBOOT_LOG_TARGET_VGA ) {
+ vga_init();
+ get_tboot_vga_delay(); /* parse vga delay time */
+ }
+
+ /* cannot use EFI logging any longer also */
+ g_log_targets &= ~TBOOT_LOG_TARGET_EFI;
+ }
+
+ if (init_type == INIT_PRE_LAUNCH || init_type == INIT_POST_LAUNCH) {
+ /* parse serial settings */
+ if ( !get_tboot_serial() )
+ g_log_targets &= ~TBOOT_LOG_TARGET_SERIAL;
+
+ if ( g_log_targets & TBOOT_LOG_TARGET_SERIAL )
+ serial_init();
+
+ if ( g_log_targets & TBOOT_LOG_TARGET_MEMORY )
+ memlog_init();
+ }
+}
+
+#define WRITE_LOGS(s, n) \
+ do { \
+ if (g_log_targets & TBOOT_LOG_TARGET_EFI) efi_write(s, n); \
+ if (g_log_targets & TBOOT_LOG_TARGET_MEMORY) memlog_write(s, n); \
+ if (g_log_targets & TBOOT_LOG_TARGET_SERIAL) serial_write(s, n); \
+ if (g_log_targets & TBOOT_LOG_TARGET_VGA) vga_write(s, n); \
+ } while (0)
+
+void printk(const char *fmt, ...)
+{
+ char buf[TBOOT_LOGBUF_SIZE];
+ char *pbuf = buf;
+ int n;
+ va_list ap;
+ uint8_t log_level;
+ static bool last_line_cr = true;
+
+ memset(buf, '\0', sizeof(buf));
+ va_start(ap, fmt);
+ n = vscnprintf(buf, sizeof(buf), fmt, ap);
+
+ log_level = get_loglvl_prefix(&pbuf, &n);
+
+ if ( !(g_log_level & log_level) )
+ goto exit;
+
+ mtx_enter(&print_lock);
+ /* prepend "TBOOT: " if the last line that was printed ended with a '\n' */
+ if ( last_line_cr )
+ WRITE_LOGS("TBOOT: ", 8);
+
+ last_line_cr = (n > 0 && (*(pbuf+n-1) == '\n'));
+ WRITE_LOGS(pbuf, n);
+ mtx_leave(&print_lock);
+
+exit:
+ va_end(ap);
+}
+
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tboot/rijndael.c b/tboot/rijndael.c
new file mode 100644
index 0000000..0b49a8f
--- /dev/null
+++ b/tboot/rijndael.c
@@ -0,0 +1,1270 @@
+/* $OpenBSD: rijndael.c,v 1.19 2008/06/09 07:49:45 djm Exp $ */
+
+/**
+ * rijndael-alg-fst.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//#include <sys/param.h>
+//#include <sys/systm.h>
+
+//#include <crypto/rijndael.h>
+#include <config.h>
+#include <efibase.h>
+#include <types.h>
+#include <rijndael.h>
+
+#undef FULL_UNROLL
+
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01, 01, 01, 01];
+*/
+
+static const u32 Te0[256] = {
+ 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+ 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+ 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+ 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+ 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+ 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+ 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+ 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+ 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+ 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+ 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+ 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+ 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+ 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+ 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+ 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+ 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+ 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+ 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+ 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+ 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+ 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+ 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+ 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+ 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+ 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+ 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+ 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+ 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+ 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+ 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+ 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+ 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+ 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+ 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+ 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+ 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+ 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+ 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+ 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+ 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+ 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+ 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+ 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+ 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+ 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+ 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+ 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+ 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+ 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+ 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+ 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+ 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+ 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+ 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+ 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+ 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+ 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+ 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+ 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+ 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+ 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+ 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+ 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+static const u32 Te1[256] = {
+ 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+ 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+ 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+ 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+ 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+ 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+ 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+ 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+ 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+ 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+ 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+ 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+ 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+ 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+ 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+ 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+ 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+ 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+ 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+ 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+ 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+ 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+ 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+ 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+ 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+ 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+ 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+ 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+ 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+ 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+ 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+ 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+ 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+ 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+ 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+ 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+ 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+ 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+ 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+ 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+ 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+ 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+ 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+ 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+ 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+ 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+ 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+ 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+ 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+ 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+ 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+ 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+ 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+ 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+ 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+ 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+ 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+ 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+ 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+ 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+ 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+ 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+ 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+ 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+static const u32 Te2[256] = {
+ 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+ 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+ 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+ 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+ 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+ 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+ 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+ 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+ 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+ 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+ 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+ 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+ 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+ 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+ 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+ 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+ 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+ 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+ 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+ 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+ 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+ 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+ 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+ 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+ 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+ 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+ 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+ 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+ 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+ 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+ 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+ 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+ 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+ 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+ 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+ 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+ 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+ 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+ 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+ 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+ 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+ 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+ 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+ 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+ 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+ 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+ 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+ 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+ 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+ 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+ 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+ 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+ 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+ 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+ 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+ 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+ 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+ 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+ 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+ 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+ 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+ 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+ 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+ 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+static const u32 Te3[256] = {
+ 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+ 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+ 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+ 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+ 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+ 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+ 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+ 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+ 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+ 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+ 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+ 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+ 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+ 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+ 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+ 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+ 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+ 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+ 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+ 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+ 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+ 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+ 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+ 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+ 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+ 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+ 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+ 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+ 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+ 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+ 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+ 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+ 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+ 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+ 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+ 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+ 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+ 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+ 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+ 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+ 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+ 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+ 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+ 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+ 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+ 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+ 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+ 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+ 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+ 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+ 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+ 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+ 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+ 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+ 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+ 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+ 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+ 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+ 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+ 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+ 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+ 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+ 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+ 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+static const u32 Te4[256] = {
+ 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
+ 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
+ 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
+ 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
+ 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
+ 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
+ 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
+ 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
+ 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
+ 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
+ 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
+ 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
+ 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
+ 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
+ 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
+ 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
+ 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
+ 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
+ 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
+ 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
+ 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
+ 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
+ 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
+ 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
+ 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
+ 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
+ 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
+ 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
+ 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
+ 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
+ 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x