# HG changeset patch # User root@jcihula-build.jf.intel.com # Date 1181347039 25200 # Node ID de5826b5b3026bbda07ea05448ec591795d129fa # Parent 419625d615144db2a973154c34d0fef5e502ddae Intel(r) Trusted Execution Technology (Intel(r) TXT) support for Xen sboot files. Signed-off-by: Joseph Cihula Signed-off-by: Jimmy Wei Signed-off-by: Shane Wang Signed-off-by: Zhai Edwin diff -r 419625d61514 -r de5826b5b302 Makefile --- a/Makefile Fri Jun 08 16:47:50 2007 -0700 +++ b/Makefile Fri Jun 08 16:57:19 2007 -0700 @@ -20,12 +20,18 @@ endif # build and install everything into the standard system directories .PHONY: install install: install-xen install-kernels install-tools install-docs +ifeq ($(INTEL_TXT),y) +install: install-sboot +endif .PHONY: build build: kernels $(MAKE) -C xen build $(MAKE) -C tools build $(MAKE) -C docs build +ifeq ($(INTEL_TXT),y) + $(MAKE) -C sboot build +endif # The test target is for unit tests that can run without an installation. Of # course, many tests require a machine running Xen itself, and these are @@ -37,6 +43,9 @@ test: # build and install everything into local dist directory .PHONY: dist dist: DESTDIR=$(DISTDIR)/install +ifeq ($(INTEL_TXT),y) +dist: dist-sboot +endif dist: dist-xen dist-kernels dist-tools dist-docs $(INSTALL_DIR) $(DISTDIR)/check $(INSTALL_DATA) ./COPYING $(DISTDIR) @@ -48,15 +57,20 @@ dist-%: install-% @: # do nothing # Legacy dist targets -.PHONY: xen tools kernels docs +.PHONY: xen tools kernels docs sboot xen: dist-xen tools: dist-tools kernels: dist-kernels docs: dist-docs +sboot: dist-sboot .PHONY: prep-kernels prep-kernels: for i in $(XKERNELS) ; do $(MAKE) $$i-prep || exit 1; done + +.PHONY: install-sboot +install-sboot: install-xen + $(MAKE) -C sboot install .PHONY: install-xen install-xen: @@ -112,6 +126,9 @@ clean:: $(MAKE) -C xen clean $(MAKE) -C tools clean $(MAKE) -C docs clean +ifeq ($(INTEL_TXT),y) + $(MAKE) -C sboot clean +endif # clean, but blow away kernel build tree plus tarballs .PHONY: distclean @@ -119,6 +136,9 @@ distclean: $(MAKE) -C xen distclean $(MAKE) -C tools distclean $(MAKE) -C docs distclean +ifeq ($(INTEL_TXT),y) + $(MAKE) -C sboot distclean +endif rm -rf dist patches/tmp for i in $(ALLKERNELS) ; do $(MAKE) $$i-delete ; done for i in $(ALLSPARSETREES) ; do $(MAKE) $$i-mrproper ; done @@ -136,6 +156,9 @@ help: @echo ' install-tools - build and install the control tools' @echo ' install-kernels - build and install guest kernels' @echo ' install-docs - build and install user documentation' +ifeq ($(INTEL_TXT),y) + @echo ' install-sboot - build and install the sboot module' +endif @echo '' @echo 'Building targets:' @echo ' dist - build and install everything into local dist directory' @@ -147,6 +170,9 @@ help: @echo ' kbuild - synonym for make kernels' @echo ' docs - build and install user documentation' @echo ' dev-docs - build developer-only documentation' +ifeq ($(INTEL_TXT),y) + @echo ' sboot - build and install sboot module' +endif @echo '' @echo 'Cleaning targets:' @echo ' clean - clean the Xen, tools and docs (but not guest kernel trees)' @@ -202,6 +228,9 @@ uninstall: rm -rf $(D)/usr/share/xen rm -rf $(D)/usr/share/man/man1/xen* rm -rf $(D)/usr/share/man/man8/xen* +ifeq ($(INTEL_TXT),y) + rm -rf $(D)/boot/sboot* +endif # Legacy targets for compatibility .PHONY: linux26 diff -r 419625d61514 -r de5826b5b302 sboot/COPYING --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/COPYING Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,3 @@ +Files which do not contain any copyright information are assumed to conform +to the license and copyright information in the ../xen/COPYING file. Those +containing license and/or copyright information are as specified. diff -r 419625d61514 -r de5826b5b302 sboot/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/Makefile Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,92 @@ +export BASEDIR := $(CURDIR) + +.PHONY: default +default: build + +.PHONY: dist +dist: install + +.PHONY: build install clean distclean cscope TAGS tags +build install debug clean distclean cscope TAGS tags:: + $(MAKE) -f Rules.mk _$@ + +.PHONY: _build +_build: $(TARGET).gz + +.PHONY: _install +_install: $(TARGET).gz + [ -d $(DESTDIR)/boot ] || $(INSTALL_DIR) $(DESTDIR)/boot + $(INSTALL_DATA) $(TARGET).gz $(DESTDIR)/boot/$(notdir $(TARGET)).gz + $(INSTALL_DATA) $(TARGET)-syms $(DESTDIR)/boot/$(notdir $(TARGET))-syms + +.PHONY: _debug +_debug: + objdump -D -S $(TARGET)-syms > $(TARGET).s + +.PHONY: _clean +_clean: + $(MAKE) -f $(BASEDIR)/Rules.mk -C common clean + $(MAKE) -f $(BASEDIR)/Rules.mk -C txt clean + rm -f $(TARGET)* *~ core + +.PHONY: _distclean +_distclean: clean + rm -f tags TAGS cscope.files cscope.in.out cscope.out cscope.po.out + +$(TARGET).gz: $(TARGET) + gzip -f -9 < $< > $@.new + mv $@.new $@ + +$(TARGET): dummy + [ -e include/asm ] || mkdir include/asm + [ -e include/asm/types.h ] || \ + ln -sf $(BASEDIR)/include/types.h $(BASEDIR)/include/asm/types.h + $(MAKE) -f $(BASEDIR)/Rules.mk -C common $(TARGET) + +dummy: + +SUBDIRS = common txt +define all_sources + ( find $(SUBDIRS) -name '*.[chS]' -print ) +endef + +define set_exuberant_flags + exuberant_flags=`$1 --version 2>/dev/null | grep -iq exuberant && \ + echo "-I __initdata,__exitdata,__acquires,__releases \ + -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \ + --extra=+f --c-kinds=+px"` +endef + +.PHONY: _TAGS +_TAGS: + rm -f TAGS; \ + $(call set_exuberant_flags,etags); \ + $(all_sources) | xargs etags $$exuberant_flags -a + +.PHONY: _tags +_tags: + rm -f tags; \ + $(call set_exuberant_flags,ctags); \ + $(all_sources) | xargs ctags $$exuberant_flags -a + +.PHONY: _cscope +_cscope: + $(all_sources) > cscope.files + cscope -k -b -q + +.PHONY: MAP +MAP: + $(NM) -n $(TARGET)-syms | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' > System.map +.PHONY: _MAP + +.PHONY: FORCE +FORCE: + +%.o %.i: %.c FORCE + $(MAKE) -f $(BASEDIR)/Rules.mk -C $(*D) $(@F) + +%.o %.s: %.S FORCE + $(MAKE) -f $(BASEDIR)/Rules.mk -C $(*D) $(@F) + +%/: FORCE + $(MAKE) -f $(BASEDIR)/Rules.mk -C $* built_in.o diff -r 419625d61514 -r de5826b5b302 sboot/Rules.mk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/Rules.mk Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,103 @@ + +# +# If you change any of these configuration options then you must +# 'make clean' before rebuilding. +# +verbose ?= n + +XEN_ROOT=$(BASEDIR)/.. + +# to use our include hierarchy +EXTRA_PREFIX := $(XEN_ROOT)/sboot + +include $(XEN_ROOT)/Config.mk + +# Hardcoded configuration implications and dependencies. +# Do this is a neater way if it becomes unwieldy. +ifeq ($(debug),y) +verbose := y +endif + +TARGET := $(BASEDIR)/sboot + +HDRS := $(wildcard $(BASEDIR)/include/*.h) +HDRS += $(wildcard $(BASEDIR)/include/txt/*.h) + +# Note that link order matters! +ALL_OBJS-y += $(BASEDIR)/common/built_in.o +ALL_OBJS-y += $(BASEDIR)/txt/built_in.o +ALL_OBJS := $(ALL_OBJS-y) + + +CFLAGS := $(shell echo $(CFLAGS) | sed -e s/-m64/-m32/) +LDFLAGS_DIRECT := -melf_i386 + +CFLAGS-y += -g -Werror +CFLAGS-$(verbose) += -DVERBOSE +CFLAGS-y += -nostdinc +CFLAGS-y += -fno-builtin -fno-common -fno-strict-aliasing +CFLAGS-y += -pipe +CFLAGS-y += -iwithprefix include -I$(BASEDIR)/include +# Prevent floating-point variables from creeping into Xen. +CFLAGS += -msoft-float +# Disable PIE/SSP if GCC supports them. They can break us. +CFLAGS += $(call cc-option,$(CC),-nopie,) +CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,) +CFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,) + +CFLAGS := $(strip $(CFLAGS) $(CFLAGS-y)) + +AFLAGS-y += -D__ASSEMBLY__ + +# Most CFLAGS are safe for assembly files: +# -std=gnu{89,99} gets confused by #-prefixed end-of-line comments +AFLAGS := $(strip $(AFLAGS) $(AFLAGS-y)) +AFLAGS += $(patsubst -std=gnu%,,$(CFLAGS)) + +# LDFLAGS are only passed directly to $(LD) +LDFLAGS := $(strip $(LDFLAGS) $(LDFLAGS_DIRECT)) + +include Makefile + +# Ensure each subdirectory has exactly one trailing slash. +subdir-n := $(patsubst %,%/,$(patsubst %/,%,$(subdir-n))) +subdir-y := $(patsubst %,%/,$(patsubst %/,%,$(subdir-y))) + +# Add explicitly declared subdirectories to the object list. +obj-y += $(patsubst %/,%/built_in.o,$(subdir-y)) + +# Add implicitly declared subdirectories (in the object list) to the +# subdirectory list, and rewrite the object-list entry. +subdir-y += $(filter %/,$(obj-y)) +obj-y := $(patsubst %/,%/built-in.o,$(obj-y)) + +subdir-all := $(subdir-y) $(subdir-n) + +built_in.o: $(obj-y) + $(LD) $(LDFLAGS) -r -o $@ $^ + +# Force execution of pattern rules (for which PHONY cannot be directly used). +.PHONY: FORCE +FORCE: + +%/built_in.o: FORCE + $(MAKE) -f $(BASEDIR)/Rules.mk -C $* built_in.o + +.PHONY: clean +clean:: $(addprefix _clean_, $(subdir-all)) + rm -f *.o *~ core +_clean_%/: FORCE + $(MAKE) -f $(BASEDIR)/Rules.mk -C $* clean + +%.o: %.c $(HDRS) Makefile + $(CC) $(CFLAGS) -c $< -o $@ + +%.o: %.S $(HDRS) Makefile + $(CC) $(AFLAGS) -c $< -o $@ + +%.i: %.c $(HDRS) Makefile + $(CPP) $(CFLAGS) $< -o $@ + +# -std=gnu{89,99} gets confused by # as an end-of-line comment marker +%.s: %.S $(HDRS) Makefile + $(CPP) $(AFLAGS) $< -o $@ diff -r 419625d61514 -r de5826b5b302 sboot/common/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/common/Makefile Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,37 @@ +obj-y += boot.o +obj-y += sboot.o +obj-y += string.o +obj-y += tpm.o +obj-y += lib.o +obj-y += vsprintf.o +obj-y += early_printk.o +obj-y += elf.o +obj-y += e820.o + +SYMBOLS = $(BASEDIR)/../xen/tools/symbols +MKELF = $(BASEDIR)/../xen/arch/x86/boot/mkelf32 + +$(TARGET): $(TARGET)-syms $(MKELF) + $(MKELF) $(TARGET)-syms $(TARGET) 0x100000 \ + `$(NM) -nr $(TARGET)-syms | head -n 1 | sed -e 's/^\([^ ]*\).*/0x\1/'` + +$(TARGET)-syms: $(ALL_OBJS) sboot.lds + $(MAKE) -f $(BASEDIR)/Rules.mk $(BASEDIR)/common/symbols-dummy.o + $(LD) $(LDFLAGS) -T sboot.lds -N $(ALL_OBJS) \ + $(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).0 + $(NM) -n $(@D)/.$(@F).0 | $(SYMBOLS) >$(@D)/.$(@F).0.S + $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0.o + $(LD) $(LDFLAGS) -T sboot.lds -N $(ALL_OBJS) \ + $(@D)/.$(@F).0.o -o $(@D)/.$(@F).1 + $(NM) -n $(@D)/.$(@F).1 | $(SYMBOLS) >$(@D)/.$(@F).1.S + $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1.o + $(LD) $(LDFLAGS) -T sboot.lds -N $(ALL_OBJS) $(@D)/.$(@F).1.o -o $@ + rm -f $(@D)/.$(@F).[0-9]* + +sboot.lds: sboot.lds.S $(HDRS) + $(CC) -P -E -Ui386 $(AFLAGS) -o $@ $< + +.PHONY: clean +clean:: + rm -f sboot.lds + rm -f $(BASEDIR)/.sboot-syms.[0-9]* diff -r 419625d61514 -r de5826b5b302 sboot/common/boot.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/common/boot.S Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,229 @@ +/* + * boot.S: assembly bootstrapping code for sboot module + * + * 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. + * + */ + +#include +#include +#include +#include + + +#define BSP_STACK_SIZE 4096 +#define AP_STACK_SIZE 128 +#define NR_IDT_ENTRIES 32 + +#define cs_sel 1<<3 +#define ds_sel 2<<3 + + .text + +ENTRY(start) +ENTRY(stext) +ENTRY(_stext) + jmp __copy_self + + .align 4 + +/*** MULTIBOOT HEADER ****/ +#define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_HEADER_MODS_ALIGNED | \ + MULTIBOOT_HEADER_WANT_MEMORY) + /* Magic number indicating a Multiboot header. */ + .long MULTIBOOT_HEADER_MAGIC + /* Flags to bootloader (see Multiboot spec). */ + .long MULTIBOOT_HEADER_FLAGS + /* Checksum: must be the negated sum of the first two fields. */ + .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) + + +__copy_self: + /* copy ourselves to lower memory first */ + mov $_stext,%ecx + mov $0x100000,%edi +1: mov (%edi),%eax + mov %eax,(%ecx) + add $0x04,%ecx + add $0x04,%edi + cmp $_end,%ecx + jle 1b + lea __start,%eax + jmp *%eax + +ENTRY(__start) + /* Set up a few descriptors: on entry only CS is guaranteed good. */ + lgdt %cs:gdt_descr + mov $0x10,%ecx + mov %ecx,%ds + mov %ecx,%es + mov %ecx,%fs + mov %ecx,%gs + mov %ecx,%ss + ljmp $(cs_sel),$(1f) +1: leal bsp_stack,%esp + + /* Reset EFLAGS (subsumes CLI and CLD). */ + pushl $0 + popf + + /* pass multiboot info struct and call measured launch code */ + push %ebx + call begin_launch + +/* + * vmexit handler + */ +ENTRY(vmx_asm_vmexit_handler) + call vmx_vmexit_handler + +ENTRY(_mini_guest) +1: hlt + jmp 1b + + +/* + * entry point for GETSEC[WAKEUP] + */ +ENTRY(_txt_wakeup) + # prepare this thread for C code + /* Set up a few descriptors: on entry only CS is guaranteed good. */ + lgdt %cs:gdt_descr + mov $0x10,%ecx + mov %ecx,%ds + mov %ecx,%es + mov %ecx,%fs + mov %ecx,%gs + mov %ecx,%ss + ljmp $(cs_sel),$(1f) + # this really needs to use cpuid offset from ap_stacks to allow simult +1: leal ap_stacks,%esp + + # get initial APIC ID for this processor + mov $0x01,%eax + xor %ebx,%ebx + cpuid + shr $24,%ebx + and $0xff,%ebx + + push %ebx + call txt_cpu_wakeup + + +/* + * interrupt handler + */ + +int_handler: + iret + + + +/* + * descriptors and descriptor tables + */ + + .align 8 + +/* GDT */ +gdt_descr: + .word gdt_table_end - gdt_table - 1 + .long gdt_table + .word 0 + + .align PAGE_SIZE, 0 + +gdt_table: + /* unused */ + .quad 0x0000000000000000 +cs_descr: /* cs */ + .word 0xffff /* limit = 4GB */ + .word 0x00 /* base = 0 */ + .word 0x9a00 /* read + exec */ + .word 0x00cf /* granularity = 4096 */ +ds_descr: /* ds */ + .word 0xffff /* limit = 4GB */ + .word 0x00 /* base = 0 */ + .word 0x9200 /* read + write */ + .word 0x00cf /* granularity = 4096 */ +tss_descr: /* tss */ + .word 0xffff /* limit = 4GB */ + .word 0x00 /* base = 0 */ + .word 0x8900 /* system segment, 32b available TSS */ + .word 0x008f /* granularity = 4096 XXX:need set D/B? */ + /* end (unused) */ + .quad 0x0000000000000000 +gdt_table_end: + + +/* + * stacks + */ + +.section ".bss.stack_aligned","w" + +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 +.section ".bss.page_aligned","w" +ENTRY(idle_pg_table) + .fill 1*PAGE_SIZE,1,0 + + .align PAGE_SIZE, 0 +ENTRY(host_vmcs) + .fill 1*PAGE_SIZE,1,0 + + .align PAGE_SIZE, 0 +ENTRY(ap_vmcs) + .fill 1*PAGE_SIZE,1,0 +ENTRY(vmcs_end) + + +/* + * shared data page with kernel (i.e. Xen) + * this needs to be kept in sync with mle_kernel_shared_t in sboot.h + */ +.section ".mle_kernel_shared","w" + .align PAGE_SIZE, 0 +ENTRY(_mle_kernel_shared) + mks_version: .long 0 + mks_ap_entry: .long 0 diff -r 419625d61514 -r de5826b5b302 sboot/common/e820.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/common/e820.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,357 @@ +/* + * e820.c: support functions for manipulating the e820 table + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * copy of bootloader/BIOS e820 table with adjusted entries + * this version will replace original in mbi + */ +#define MAX_E820_ENTRIES 128 +static int g_nr_map; +static memory_map_t g_copy_e820_map[MAX_E820_ENTRIES]; + +/* don't define in e820.h so as not to conflict with Xen's defn. */ +#define E820_RAM 1 + + +/* MLE/kernel shared data page (in boot.S) */ +extern mle_kernel_shared_t _mle_kernel_shared; + + +static inline void split64b(uint64_t val, uint32_t *val_lo, uint32_t *val_hi) +{ + *val_lo = (uint32_t)(val & 0xffffffff); + *val_hi = (uint32_t)(val >> 32); +} + +static inline uint64_t combine64b(uint32_t val_lo, uint32_t val_hi) +{ + return ((uint64_t)val_hi << 32) | (uint64_t)val_lo; +} + +/* + * print_e820_map + * + * Prints copied e820 map w/o any header (i.e. just entries, indented by a tab) + * + */ +static void print_map(memory_map_t *e820, int nr_map) +{ + int i; + + for ( i = 0; i < nr_map; i++ ) { + memory_map_t *entry = &e820[i]; + uint64_t base_addr, length; + + base_addr = combine64b(entry->base_addr_low, entry->base_addr_high); + length = combine64b(entry->length_low, entry->length_high); + + printk("\t%016Lx - %016Lx (%d)\n", + (unsigned long long)base_addr, + (unsigned long long)(base_addr + length), + entry->type); + } +} + +static bool insert_after_region(memory_map_t *e820map, int *nr_map, int pos, + uint64_t addr, uint64_t size, + uint32_t type) +{ + int i; + + /* no more room */ + if ( *nr_map + 1 > MAX_E820_ENTRIES ) + return false; + + /* shift (copy) everything up one entry */ + for (i = *nr_map - 1; i > pos; i--) + e820map[i+1] = e820map[i]; + + /* now add our entry */ + split64b(addr, &(e820map[pos+1].base_addr_low), + &(e820map[pos+1].base_addr_high)); + split64b(size, &(e820map[pos+1].length_low), + &(e820map[pos+1].length_high)); + e820map[pos+1].type = type; + e820map[pos+1].size = sizeof(memory_map_t) - sizeof(uint32_t); + + (*nr_map)++; + + return true; +} + +static void remove_region(memory_map_t *e820map, int *nr_map, int pos) +{ + int i; + + /* shift (copy) everything down one entry */ + for (i = pos; i < *nr_map - 1; i++) + e820map[i] = e820map[i+1]; + + (*nr_map)--; +} + +static bool protect_region(memory_map_t *e820map, int *nr_map, + uint64_t new_addr, uint64_t new_size, + uint32_t new_type) +{ + int i; + uint64_t addr, tmp_addr, size, tmp_size; + uint32_t type; + + if ( new_size == 0 ) + return true; + + /* find where our region belongs in the table and insert it */ + for (i = 0; i < *nr_map; i++) { + addr = combine64b(e820map[i].base_addr_low, e820map[i].base_addr_high); + size = combine64b(e820map[i].length_low, e820map[i].length_high); + type = e820map[i].type; + /* is our region at the beginning of the current map region? */ + if ( new_addr == addr ) { + if ( !insert_after_region(e820map, nr_map, i-1, new_addr, new_size, + new_type) ) + return false; + break; + } + /* are we w/in the current map region? */ + else if ( new_addr > addr && new_addr < (addr + size) ) { + if ( !insert_after_region(e820map, nr_map, i, new_addr, new_size, + new_type) ) + return false; + /* fixup current region */ + tmp_addr = combine64b(e820map[i].base_addr_low, + e820map[i].base_addr_high); + split64b(new_addr - tmp_addr, &(e820map[i].length_low), + &(e820map[i].length_high)); + i++; /* adjust to always be that of our region */ + /* insert a copy of current region (before adj) after us so */ + /* that rest of code can be common with previous case */ + if ( !insert_after_region(e820map, nr_map, i, addr, size, type) ) + return false; + break; + } + /* is our region in a gap in the map? */ + else if ( addr > new_addr ) { + if ( !insert_after_region(e820map, nr_map, i-1, new_addr, new_size, + new_type) ) + return false; + break; + } + } + /* if we reached the end of the map without finding an overlapping */ + /* region, insert us at the end (note that this test won't trigger */ + /* for the second case above because the insert() will have incremented */ + /* nr_map and so i++ will still be less) */ + if ( i == *nr_map ) { + if ( !insert_after_region(e820map, nr_map, i-1, new_addr, new_size, + new_type) ) + return false; + return true; + } + + i++; /* move to entry after our inserted one (we're not at end yet) */ + + tmp_addr = combine64b(e820map[i].base_addr_low, e820map[i].base_addr_high); + tmp_size = combine64b(e820map[i].length_low, e820map[i].length_high); + + /* did we split the (formerly) previous region? */ + if ( (new_addr >= tmp_addr) && + ((new_addr + new_size) < (tmp_addr + tmp_size)) ) { + /* then adjust the current region (adj size first) */ + split64b((tmp_addr + tmp_size) - (new_addr + new_size), + &(e820map[i].length_low), &(e820map[i].length_high)); + split64b(new_addr + new_size, + &(e820map[i].base_addr_low), &(e820map[i].base_addr_high)); + return true; + } + + /* if our region completely covers any existing regions, delete them */ + while ( (i < *nr_map) && ((new_addr + new_size) >= + (tmp_addr + tmp_size)) ) { + remove_region(e820map, nr_map, i); + tmp_addr = combine64b(e820map[i].base_addr_low, + e820map[i].base_addr_high); + tmp_size = combine64b(e820map[i].length_low, e820map[i].length_high); + } + + /* finally, if our region partially overlaps an existing region, */ + /* then truncate the existing region */ + tmp_addr = combine64b(e820map[i].base_addr_low, e820map[i].base_addr_high); + if ( (i < *nr_map) && ((new_addr + new_size) > tmp_addr) ) + split64b(new_addr + new_size, &(e820map[i].base_addr_low), + &(e820map[i].base_addr_high)); + + return true; +} + +/* + * copy_e820_map + * + * Copies the raw e820 map from bootloader to new table with room for expansion + * + * return: false = error (no table or table too big for new space) + */ +bool copy_e820_map(multiboot_info_t *mbi) +{ + uint32_t entry_offset; + + if ( mbi->flags & MBI_MEMMAP ) { + printk("original e820 map:\n"); + print_map((memory_map_t *)mbi->mmap_addr, + mbi->mmap_length/sizeof(memory_map_t)); + + g_nr_map = 0; + entry_offset = 0; + + while ( entry_offset < mbi->mmap_length && + g_nr_map < MAX_E820_ENTRIES ) { + memory_map_t *entry, *new_entry; + + entry = (memory_map_t *)(mbi->mmap_addr + entry_offset); + new_entry = &g_copy_e820_map[g_nr_map]; + + /* make exact copy except fix size to size of entry struct */ + /* (Xen ignores any extra data above this anyway) */ + *new_entry = *entry; + new_entry->size = sizeof(*new_entry) - sizeof(new_entry->size); + + g_nr_map++; + + entry_offset += entry->size + sizeof(entry->size); + } + if ( g_nr_map == MAX_E820_ENTRIES ) { + printk("Too many e820 entries\n"); + return false; + } + } + else if ( mbi->flags & MBI_MEMLIMITS ) { + printk("no e820 map, mem_lower=%x, mem_upper=%x\n", + mbi->mem_lower, mbi->mem_upper); + + /* lower limit is 0x00000000 - *0x400 (i.e. in kb) */ + g_copy_e820_map[0].base_addr_low = 0; + g_copy_e820_map[0].base_addr_high = 0; + g_copy_e820_map[0].length_low = mbi->mem_lower << 10; + g_copy_e820_map[0].length_high = 0; + g_copy_e820_map[0].type = E820_RAM; + g_copy_e820_map[0].size = sizeof(memory_map_t) - sizeof(uint32_t); + + /* upper limit is 0x00100000 - *0x400 */ + g_copy_e820_map[1].base_addr_low = 0x100000; + g_copy_e820_map[1].base_addr_high = 0; + split64b((uint64_t)mbi->mem_upper << 10, + &(g_copy_e820_map[1].length_low), + &(g_copy_e820_map[1].length_high)); + g_copy_e820_map[1].type = E820_RAM; + g_copy_e820_map[1].size = sizeof(memory_map_t) - sizeof(uint32_t); + + g_nr_map = 2; + } + else { + printk("no e820 map nor memory limits provided\n"); + return false; + } + + return true; +} + +void replace_e820_map(multiboot_info_t *mbi) +{ + /* replace original with the copy */ + mbi->mmap_addr = (uint32_t)g_copy_e820_map; + mbi->mmap_length = g_nr_map * sizeof(memory_map_t); + mbi->flags |= MBI_MEMMAP; /* in case only MBI_MEMLIMITS was set */ +} + +bool e820_protect_region(uint64_t addr, uint64_t size, uint32_t type) +{ + return protect_region(g_copy_e820_map, &g_nr_map, addr, size, type); +} + +void print_e820_map(void) +{ + print_map(g_copy_e820_map, g_nr_map); +} + +uint64_t get_max_ram(multiboot_info_t *mbi) +{ + uint32_t entry_offset; + memory_map_t *entry; + uint64_t max_ram, base, len; + + if ( mbi->flags & MBI_MEMMAP ) { + /* find highest RAM region */ + entry_offset = 0; + max_ram = 0; + while ( entry_offset < mbi->mmap_length ) { + entry = (memory_map_t *)(mbi->mmap_addr + entry_offset); + if ( entry->type == E820_RAM ) { + base = combine64b(entry->base_addr_low, entry->base_addr_high); + len = combine64b(entry->length_low, entry->length_high); + if ( base + len > max_ram ) + max_ram = base + len; + } + entry_offset += entry->size + sizeof(entry->size); + } + return max_ram; + } + else if ( mbi->flags & MBI_MEMLIMITS ) + return (uint64_t)mbi->mem_upper << 10; + else { + printk("no e820 map nor mem limits provided\n"); + return 0; + } +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/common/early_printk.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/common/early_printk.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,122 @@ +/* + * early_printk.c: printk to serial for very early boot stages + * + * Copyright (c) 2006-2007, Intel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DEFINE_SPINLOCK(print_lock); + +static inline unsigned char inb(unsigned short port) +{ + unsigned char _v; + + __asm__ __volatile__ ("inb %w1, %0" + : "=a" (_v) : "Nd" (port)); + + return _v; +} + +static inline void outb(unsigned char value, unsigned short port) +{ + __asm__ __volatile__ ("outb %b0, %w1" + : : "a" (value), "Nd" (port)); +} + +/* + * serial support from linux.../arch/x86_64/kernel/early_printk.c + * + * this code does not initialize the serial port and assumes COM1, so + * it will only display if GRUB has been configured for output to COM1 + */ + +#define early_serial_base 0x3f8 /* ttyS0 */ + +#define XMTRDY 0x20 + +#define DLAB 0x80 + +#define TXR 0 /* Transmit register (WRITE) */ +#define RXR 0 /* Receive register (READ) */ +#define IER 1 /* Interrupt Enable */ +#define IIR 2 /* Interrupt ID */ +#define FCR 2 /* FIFO control */ +#define LCR 3 /* Line control */ +#define MCR 4 /* Modem control */ +#define LSR 5 /* Line Status */ +#define MSR 6 /* Modem Status */ +#define DLL 0 /* Divisor Latch Low */ +#define DLH 1 /* Divisor latch High */ + +static int early_serial_putc(unsigned char ch) +{ + unsigned timeout = 0xffff; + while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) + cpu_relax(); + outb(ch, early_serial_base + TXR); + return timeout ? 0 : -1; +} + +static void early_serial_write(const char *s, unsigned int n) +{ + while (*s && n-- > 0) { + early_serial_putc(*s); + if (*s == '\n') + early_serial_putc('\r'); + s++; + } +} + +void early_serial_printk(const char *fmt, ...) +{ + char buf[256]; + int n; + va_list ap; + static bool last_line_cr = true; + + memset(buf, '\0', sizeof(buf)); + va_start(ap, fmt); + n = vscnprintf(buf, sizeof(buf), fmt, ap); + spin_lock(&print_lock); + /* prepend "SBOOT: " if the last line that was printed ended with a '\n' */ + if ( last_line_cr ) + early_serial_write("SBOOT: ", 8); + last_line_cr = (n > 0 && buf[n-1] == '\n'); + early_serial_write(buf, n); + spin_unlock(&print_lock); + va_end(ap); +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/common/elf.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/common/elf.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,408 @@ +/* + * elf.c: support functions for manipulating ELF binaries + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +static void print_mbi(multiboot_info_t *mbi) +{ + /* print mbi for debug */ + int i; + printk("print mbi ...\n"); + printk("flags = %x\n", mbi->flags); + if ((mbi->flags) & ( 1<<0 )) + printk("mem_lower = %uKB, mem_upper = %uKB\n", mbi->mem_lower, + mbi->mem_upper); + if ((mbi->flags) & ( 1<<1 )) + printk("boot_device = %x\n", mbi->boot_device); + if ((mbi->flags) & ( 1<<2 )) + printk("cmdline = %s\n", (char *)mbi->cmdline); + if ((mbi->flags) & ( 1<<3 )) { + printk("mods_count = %x, mods_addr = %x\n", mbi->mods_count, + mbi->mods_addr); + for ( i=0; imods_count; i++ ) { + module_t *p = (module_t *)(mbi->mods_addr + i*sizeof(module_t)); + printk("\t i = %x, mod_start = %x, mod_end = %x, string = %x, " + "string = %s\n", i, p->mod_start, p->mod_end, p->string, + (char *)p->string); + } + } + if ((mbi->flags) & ( 1<<4 )) { + aout_symbol_table_t *p = &(mbi->u.aout_sym); + printk("tabsize = %x, strsize = %x, addr = %x\n", p->tabsize, + p->strsize, p->addr); + } + if ((mbi->flags) & ( 1<<5 )) { + elf_section_header_table_t *p = &(mbi->u.elf_sec); + printk("num = %x, size = %x, addr = %x, shndx = %x\n", p->num, + p->size, p->addr, p->shndx); + } + if ((mbi->flags) & ( 1<<6 )) { + memory_map_t *p; + printk("mmap_length = %x, mmap_addr = %x\n", mbi->mmap_length, + mbi->mmap_addr); + for ( p = (memory_map_t *)mbi->mmap_addr; + (uint32_t)p < mbi->mmap_addr + mbi->mmap_length; + p=(memory_map_t *)((uint32_t)p + p->size + sizeof(p->size)) ) { + printk("size = %x, base_addr = 0x%x%x, length = 0x%x%x, " + "type = %x\n", p->size, p->base_addr_high, + p->base_addr_low, p->length_high, p->length_low, p->type); + } + } +} +#endif + +static bool is_mods_valid(multiboot_info_t *mbi) +{ + if (mbi == NULL) { + printk("Error: Mbi pointer is zero.\n"); + return false; + } + + if (!((mbi->flags) & (1<<3))) { + printk("Error: Mods in mbi is invalid.\n"); + return false; + } + + return true; +} + +static bool is_elf_image(const void *image, const size_t size) +{ + elf_header_t *elf; + + if (image == NULL) { + printk("Error: Pointer is zero.\n"); + return false; + } + + /* check size */ + if (sizeof(elf_header_t) > size) { + printk("Error: Image size is smaller than ELF header size.\n"); + return false; + } + + elf = (elf_header_t *)image; + + /* check magic number for ELF */ + if ((elf->e_ident[EI_MAG0] != ELFMAG0) + || (elf->e_ident[EI_MAG1] != ELFMAG1) + || (elf->e_ident[EI_MAG2] != ELFMAG2) + || (elf->e_ident[EI_MAG3] != ELFMAG3)) { + printk("Error: ELF magic number is not matched.\n"); + return false; + } + + /* check data encoding in ELF */ + if (elf->e_ident[EI_DATA] != ELFDATA2LSB) { + printk("Error: ELF data encoding is not the least significant " + "byte occupying the lowest address.\n"); + return false; + } + + /* check ELF image is executable? */ + if (elf->e_type != ET_EXEC) { + printk("Error: ELF image is not executable.\n"); + return false; + } + + /* check ELF image is for IA? */ + if (elf->e_machine != EM_386) { + printk("Error: ELF image is not for IA.\n"); + return false; + } + + /* check ELF version is valid? */ + if (elf->e_version != EV_CURRENT) { + printk("Error: ELF version is invalid.\n"); + return false; + } + + if (sizeof(elf_program_header_t) > elf->e_phentsize) { + printk("Error: Program size is smaller than program " + "header size.\n"); + return false; + } + + return true; +} + +static bool get_elf_image_range(const elf_header_t *elf, const size_t size, + void **start, void **end) +{ + int i; + uint32_t u_start, u_end; + + if (elf == NULL) { + printk("Error: ELF header pointer is zero.\n"); + return false; + } + + /* check size */ + if (sizeof(elf_header_t) > size) { + printk("Error: ELF image size is smaller than its " + "header size.\n"); + return false; + } + if (sizeof(elf_program_header_t) > elf->e_phentsize) { + printk("Error: Program size is smaller than program " + "header size.\n"); + return false; + } + + if ((start == NULL) || (end == NULL)) { + printk("Error: Output pointers are zero.\n"); + return false; + } + + u_start = 0; + u_end = 0; + for (i = 0; i < elf->e_phnum; i++) { + elf_program_header_t *ph = (elf_program_header_t *) + ((void *)elf + elf->e_phoff + i*elf->e_phentsize); + if (ph->p_type == PT_LOAD) { + if (u_start > ph->p_paddr) + u_start = ph->p_paddr; + if (u_end < ph->p_paddr+ph->p_memsz) + u_end = ph->p_paddr+ph->p_memsz; + } + } + + if (u_start >= u_end) { + *start = NULL; + *end = NULL; + return false; + } + else { + *start = (void *)u_start; + *end = (void *)u_end; + return true; + } +} + +static bool move_modules_backward(multiboot_info_t *mbi, void *dest) +{ + module_t *m, *first_module, *last_module; + int i; + size_t size; + void *src; + uint32_t shift; + + if (mbi == NULL) { + printk("Error: Mbi pointer is zero.\n"); + return false; + } + + if (!is_mods_valid(mbi)) + return false; + + if (mbi->mods_count < 1) { + printk("Warning: There is no module need to move.\n"); + return true; + } + + first_module = (module_t *)mbi->mods_addr; + src = (void *)first_module->mod_start; + + last_module = (module_t *)(mbi->mods_addr + + (mbi->mods_count - 1)*sizeof(module_t)); + size = last_module->mod_end - first_module->mod_start; + shift = dest - src; + + for (i = 0; imods_count; i++) { + m = (module_t *)(mbi->mods_addr + i*sizeof(module_t)); + + m->mod_start += shift; + m->mod_end += shift; + } + memmove(dest, src, size); + + return true; +} + +static void* delete_module(multiboot_info_t *mbi, const int module_index) +{ + module_t *m; + + if (mbi == NULL) { + printk("Error: Mbi pointer is zero.\n"); + return NULL; + } + + if (module_index < -1) { + printk("Error: Module index for deleting is wrong.\n"); + return NULL; + } + + if (mbi->mods_count <= 0) { + printk("Error: Module count incorrect for module deleting.\n"); + return NULL; + } + + if ((module_index > -1) && (module_index >= mbi->mods_count)) { + printk("Error: Module index greater than the module count.\n"); + return NULL; + } + + if (module_index != -1) { + printk("Error: Only deleting kernel is supported so far.\n"); + return NULL; + } + + if (!is_mods_valid(mbi)) + return false; + + /* delete kernel */ + m = (module_t *)mbi->mods_addr; + mbi->mods_addr += sizeof(module_t); + mbi->mods_count--; + mbi->cmdline = m->string; + mbi->flags |= MBI_CMDLINE; + return (void *)(m->mod_start); +} + +static bool expand_elf_image(const elf_header_t *elf, const size_t size, + void **entry_point) +{ + int i; + + if (elf == NULL) { + printk("Error: ELF header pointer is zero.\n"); + return false; + } + + if (entry_point == NULL) { + printk("Error: Output pointer is zero.\n"); + return false; + } + + /* check size */ + if (sizeof(elf_header_t) > size) { + printk("Error: ELF image size smaller than its header size.\n"); + return false; + } + if (sizeof(elf_program_header_t) > elf->e_phentsize) { + printk("Error: Program size smaller than program header size\n"); + return false; + } + + /* load elf image into memory */ + for (i = 0; i < elf->e_phnum; i++) { + elf_program_header_t *ph = (elf_program_header_t *) + ((void *)elf + elf->e_phoff + i*elf->e_phentsize); + + if (ph->p_type == PT_LOAD) { + memcpy((void *)ph->p_paddr, (void *)elf + ph->p_offset, + ph->p_filesz); + memset((void *)(ph->p_paddr + ph->p_filesz), 0, + ph->p_memsz - ph->p_filesz); + } + } + + *entry_point = (void *)elf->e_entry; + return true; +} + +int launch_xen(multiboot_info_t *mbi, void **kernel_entry_point) +{ + module_t *m; + void *xen_base, *xen_expanded_start, *xen_expanded_end, *xen_entry_point; + elf_header_t *xen_as_elf; + size_t xen_size; + + if (mbi == NULL) { + printk("Error: Mbi pointer is zero.\n"); + return -1; + } + + if (!is_mods_valid(mbi)) + return -1; + + m = (module_t *)mbi->mods_addr; + + xen_base = (void *)m->mod_start; + xen_size = m->mod_end - m->mod_start; + + if (!is_elf_image(xen_base, xen_size)) + return -1; + + xen_as_elf = (elf_header_t *)xen_base; + + if (!get_elf_image_range(xen_as_elf, xen_size, &xen_expanded_start, + &xen_expanded_end)) + return -1; + + xen_expanded_end = (void *)(((uint32_t)xen_expanded_end + PAGE_SIZE) & + PAGE_MASK); + + if (!move_modules_backward(mbi, xen_expanded_end)) + return -1; + + xen_base = delete_module(mbi, -1); + if (xen_base == NULL) + return -1; + + xen_as_elf = (elf_header_t *)xen_base; + + if (!expand_elf_image(xen_as_elf, xen_size, &xen_entry_point)) + return -1; + + *kernel_entry_point = xen_entry_point; + /* jump to xen start entry */ + __asm__ __volatile__ ( + " jmp *%%ecx; " + " ud2; " + :: "a" (MB_MAGIC), "b" (mbi), "c" (xen_entry_point)); + + return 0; +} + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/common/lib.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/common/lib.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,40 @@ + +#include + +/* for inc/ctype.h */ +unsigned char _ctype[] = { +_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ +_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ +_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ +_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ +_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ +_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ +_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ +_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ +_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ +_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ +_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ +_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ +_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ +_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/common/sboot.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/common/sboot.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,222 @@ +/* + * sboot.c: main entry point and "generic" routines for measured launch + * support + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char _stext[]; /* start of text section */ +extern char _end[]; /* end of module */ + +/* multiboot struct saved so that post_launch() can use it */ +static multiboot_info_t *g_mbi; + +/* entry point for next module, i.e. Xen */ +static void *g_kernel_entry_point; + +/* MLE/kernel shared data page (in boot.S) */ +extern mle_kernel_shared_t _mle_kernel_shared; + + + +static bool verify_platform(void) +{ + return txt_verify_platform(); +} + +static bool is_launched(void) +{ + return txt_is_launched(); +} + +static bool prepare_cpu(void) +{ + return txt_prepare_cpu(); +} + +static bool prepare_platform(void) +{ + return txt_prepare_platform(); +} + +static bool launch_environment(multiboot_info_t *mbi) +{ + return txt_launch_environment(mbi); +} + +static void post_launch(void) +{ + uint64_t base, size; + + /* TBD: need to handle errors here by tearing down */ + + printk("measured launch succeeded\n"); + + txt_post_launch(); + + if ( !copy_e820_map(g_mbi) ) + goto launch_xen; + + if ( !txt_protect_mem_regions() ) + goto launch_xen; + + /* protect ourselves and the page table we created */ + base = (uint64_t)((unsigned long)&_stext - 3*PAGE_SIZE); + size = (uint64_t)(unsigned long)&_end - base; + printk("protecting sboot (%Lx - %Lx) in e820 table\n", base, + (base + size - 1)); + if ( !e820_protect_region(base, size, E820_PROTECTED) ) + goto launch_xen; + + /* mark the shared MLE/kernel page as E820_MLE_SHARED */ + base = (uint32_t)&_mle_kernel_shared; + size = PAGE_SIZE; + printk("protecting MLE/kernel shared (%Lx - %Lx) in e820 table\n", + base, (base + size - 1)); + if ( !e820_protect_region(base, size, E820_MLE_SHARED) ) + goto launch_xen; + + /* replace map in mbi with copy */ + replace_e820_map(g_mbi); + + printk("adjusted e820 map:\n"); + print_e820_map(); + + /* + * init MLE/kernel shared data page + */ + memset(&_mle_kernel_shared, 0, sizeof(_mle_kernel_shared)); + _mle_kernel_shared.version = 0x01; + +launch_xen: + launch_xen(g_mbi, &g_kernel_entry_point); +} + +void cpu_wakeup(uint32_t cpuid) +{ + uint32_t ap_entry; + + printk("cpu %x waking up\n", cpuid); + + if ( _mle_kernel_shared.ap_entry == 0 ) { + printk("_mle_kernel_shared.ap_entry not set, using bsp entry\n"); + ap_entry = (uint32_t)g_kernel_entry_point; + } + else + ap_entry = _mle_kernel_shared.ap_entry; + printk("AP entry point is 0x%08x\n", ap_entry); + + /* jump to xen start entry for AP */ + __asm__ __volatile__ ( + " jmp *%%ecx; " + " ud2; " + :: "c" (ap_entry)); +} + +multiboot_info_t* begin_launch(multiboot_info_t *mbi) +{ + unsigned long apicbase; + + printk("begin launch()\n"); + + /* we should only be executing on the BSP */ + rdmsrl(MSR_IA32_APICBASE, apicbase); + if ( !(apicbase & MSR_IA32_APICBASE_BSP) ) { + printk("entry processor is not BSP\n"); + goto failed; + } + + /* we need to make sure this is a (TXT-) capable platform before using */ + /* any of the features, incl. those required to check if the environment */ + /* has already been launched */ + + /* need to verify that platform can perform measured launch */ + if ( !verify_platform() ) + goto failed; + + /* this is being called post-measured launch */ + if ( is_launched() ) { + post_launch(); + } + + /* print any errors on last boot, which must be from TXT launch */ + txt_get_error(); + + /* make the CPU ready for measured launch */ + if ( !prepare_cpu() ) + goto failed; + + /* make the platform ready for measured launch */ + if ( !prepare_platform() ) + goto failed; + + /* save for post_launch */ + g_mbi = mbi; + + /* launch the measured environment */ + if ( !launch_environment(mbi) ) + goto failed; + + /* for Intel(r) TXT, we will never get here */ + printk("we should never get here\n"); + return mbi; + + failed: + launch_xen(mbi, &g_kernel_entry_point); + return mbi; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/common/sboot.lds.S --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/common/sboot.lds.S Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,49 @@ +/* ld script to make i386 Linux kernel + * Written by Martin Mares + * Modified for i386 Xen by Keir Fraser + * Modified for sboot by Joseph Cihula + */ + +#include + +#undef ENTRY +#undef ALIGN + +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(start) +PHDRS +{ + text PT_LOAD ; +} +SECTIONS +{ + . = SBOOT_BASE_ADDR; /* 0x70000 */ + + _stext = .; /* Text and read-only data */ + .text : { + *(.text) + *(.fixup) + *(.gnu.warning) + } :text =0x9090 + _etext = .; /* End of text section */ + + .rodata : { *(.rodata) *(.rodata.*) } :text + + .data : { /* Data */ + *(.data) + CONSTRUCTORS + } :text + + . = ALIGN(4096); + + __bss_start = .; /* BSS */ + .bss : { + *(.bss.stack_aligned) + *(.bss.page_aligned) + *(.bss) + *(.mle_kernel_shared) + } :text + + _end = . ; +} diff -r 419625d61514 -r de5826b5b302 sboot/common/string.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/common/string.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,68 @@ +/* + * linux/lib/string.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +#include +#include +#include +#include +#include + +#ifndef __HAVE_ARCH_STRNLEN +/** + * strnlen - Find the length of a length-limited string + * @s: The string to be sized + * @count: The maximum number of bytes to search + */ +size_t strnlen(const char * s, size_t count) +{ + const char *sc; + + for (sc = s; count-- && *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} +#endif + +#ifndef __HAVE_ARCH_MEMMOVE +/** + * memmove - Copy one area of memory to another + * @dest: Where to copy to + * @src: Where to copy from + * @count: The size of the area. + * + * Unlike memcpy(), memmove() copes with overlapping areas. + */ +void * memmove(void * dest,const void *src,size_t count) +{ + char *tmp, *s; + + if (dest <= src) { + tmp = (char *) dest; + s = (char *) src; + while (count--) + *tmp++ = *s++; + } + else { + tmp = (char *) dest + count; + s = (char *) src + count; + while (count--) + *--tmp = *--s; + } + + return dest; +} +#endif + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 8 + * tab-width: 8 + * indent-tabs-mode: t + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/common/symbols-dummy.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/common/symbols-dummy.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,16 @@ +/* + * symbols-dummy.c: dummy symbol-table definitions for the inital partial + * link of the hypervisor image. + */ + +#include +#include + +unsigned long symbols_addresses[1]; +unsigned long symbols_num_syms; +u8 symbols_names[1]; + +u8 symbols_token_table[1]; +u16 symbols_token_index[1]; + +unsigned long symbols_markers[1]; diff -r 419625d61514 -r de5826b5b302 sboot/common/tpm.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/common/tpm.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,3032 @@ +/* + * tpm.c: TPM-related support functions + * + * 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TPM_TAG_RQU_COMMAND 0x00C1 +#define TPM_ORD_PCR_EXTEND 0x00000014 +#define TPM_ORD_PCR_READ 0x00000015 +#define TPM_ORD_PCR_RESET 0x000000C8 +#define TPM_ORD_NV_READ_VALUE 0x000000CF +#define TPM_ORD_NV_WRITE_VALUE 0x000000CD + +#define readb(x) (*(volatile char *)(x)) +#define writeb(d,x) (*(volatile char *)(x) = (d)) + +/* + * 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 +typedef union { + u8 _raw[1]; /* 1-byte reg */ + struct { + 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 */ + } __attribute__ ((packed)); +} tpm_reg_access_t; + +/* TPM_STS_x */ +#define TPM_REG_STS 0x18 +typedef union { + u8 _raw[3]; /* 3-byte reg */ + struct { + u8 reserved1 : 1; + u8 response_retry : 1; /* WO, 1=re-send response */ + u8 reserved2 : 1; + 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 */ + } __attribute__ ((packed)); +} tpm_reg_sts_t; + +/* TPM_DATA_FIFO_x */ +#define TPM_REG_DATA_FIFO 0x24 +typedef union { + uint8_t _raw[1]; /* 1-byte reg */ +} tpm_reg_data_fifo_t; + +/* + * 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 void _read_tpm_reg(int locality, u32 reg, u8 *_raw, size_t size) +{ + size_t i; + for ( i = 0; i < size; i++ ) + _raw[i] = readb((TPM_LOCALITY_BASE_N(locality) | reg) + i); +} + +static void _write_tpm_reg(int locality, u32 reg, u8 *_raw, size_t size) +{ + size_t i; + for ( i = 0; i < size; i++ ) + writeb(_raw[i], (TPM_LOCALITY_BASE_N(locality) | reg) + 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) +{ + uint32_t i; + for ( i = 0; i < count; i++ ) + out[i] = in[count - i - 1]; +} + +#define TPM_VALIDATE_LOCALITY_TIME_OUT 0x100 + +static bool tpm_validate_locality(uint32_t locality) +{ + tpm_reg_access_t reg_acc; + uint32_t i; + + for ( i = 0; i < TPM_VALIDATE_LOCALITY_TIME_OUT; i++ ) { + /* + * TCG spec defines reg_acc.tpm_reg_valid_sts bit to indicate whether + * other bits of access reg are valid.( but this bit will also be 1 + * while this locality is not available, so check seize bit too) + * It also defines that reading reg_acc.seize should always return 0 + */ + read_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); + if ( reg_acc.tpm_reg_valid_sts == 1 && reg_acc.seize == 0) + return true; + cpu_relax(); + } + + return false; +} + +#define TPM_ACTIVE_LOCALITY_TIME_OUT 0x800 +#define TPM_STS_VALID_TIME_OUT 0x100 +#define TPM_CMD_READY_TIME_OUT 0x100 +#define TPM_CMD_WRITE_TIME_OUT 0x100 +#define TPM_DATA_AVAIL_TIME_OUT 0x100 +#define TPM_RSP_READ_TIME_OUT 0x100 + +static uint32_t tpm_wait_cmd_ready(uint32_t locality) +{ + uint32_t i; + tpm_reg_access_t reg_acc; + tpm_reg_sts_t reg_sts; + + /* ensure the contents of the ACCESS register are valid */ + read_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); + printk("TPM: Access reg content: 0x%02x\n", (uint32_t)reg_acc._raw[0]); + if ( reg_acc.tpm_reg_valid_sts == 0 ) { + printk("TPM: Access reg not valid\n"); + return TPM_FAIL; + } + + /* request access to the TPM from locality N */ + reg_acc._raw[0] = 0; + reg_acc.request_use = 1; + write_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); + + for ( i = TPM_ACTIVE_LOCALITY_TIME_OUT; i > 0; i-- ) { + read_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); + if ( reg_acc.active_locality == 1 ) + break; + else + cpu_relax(); + } + + if ( i <= 0 ) { + printk("TPM: request use timeout\n"); + return TPM_FAIL; + } + + /* ensure the contents of the STATUS register are valid */ + for ( i = TPM_STS_VALID_TIME_OUT; i > 0; i-- ) { + read_tpm_reg(locality, TPM_REG_STS, ®_sts); + if ( reg_sts.sts_valid == 1 ) + break; + else + cpu_relax(); + } + + if ( i <= 0 ) { + printk("TPM: status register not valid\n"); + goto RelinquishControl; + } + + /* write 1 to TPM_STS_x.commandReady to let TPM enter the ready status */ + memset((void *)®_sts, 0, sizeof(reg_sts)); + reg_sts.command_ready = 1; + write_tpm_reg(locality, TPM_REG_STS, ®_sts); + + /* ensure the TPM is ready to accept a command */ + printk("TPM: wait for cmd ready "); + for ( i = TPM_CMD_READY_TIME_OUT; i > 0; i-- ) { + read_tpm_reg(locality, TPM_REG_STS, ®_sts); + printk("."); + if ( reg_sts.command_ready == 1 ) + break; + else + cpu_relax(); + } + printk("\n"); + + if ( i <= 0 ) { + printk("TPM: status reg content: %02x %02x %02x\n", + (uint32_t)reg_sts._raw[0], + (uint32_t)reg_sts._raw[1], + (uint32_t)reg_sts._raw[2]); + printk("TPM: tpm timeout for command_ready\n"); + goto RelinquishControl; + } + return TPM_SUCCESS; + +RelinquishControl: + /* deactivate current locality */ + reg_acc._raw[0] = 0; + reg_acc.active_locality = 1; + write_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); + + return TPM_FAIL; +} + +/* + * locality : TPM locality (0 - 3) + * in : All bytes for a single TPM command, including TAG, SIZE, + * ORDINAL, and other arguments. All data should be in big-endian + * style. The in MUST NOT be NULL, containing at least 10 bytes. + * 0 1 2 3 4 5 6 7 8 9 10 ... + * ------------------------------------------------------------- + * | TAG | SIZE | ORDINAL | arguments ... + * ------------------------------------------------------------- + * in_size : The size of the whole command contained within the in buffer. + * It should equal to the SIZE contained in the in buffer. + * out : All bytes of the TPM response to a single command. All data + * within it will be in big-endian style. The out MUST not be + * NULL, and will return at least 10 bytes. + * 0 1 2 3 4 5 6 7 8 9 10 ... + * ------------------------------------------------------------- + * | TAG | SIZE | RETURN CODE | other data ... + * ------------------------------------------------------------- + * out_size : In/out paramter. As in, it is the size of the out buffer; + * as out, it is the size of the response within the out buffer. + * The out_size MUST NOT be NULL. + * return : 0 = success; if not 0, it equal to the RETURN CODE in out buf. + */ +#define CMD_HEAD_SIZE 10 +#define RSP_HEAD_SIZE 10 +#define CMD_SIZE_OFFSET 2 +#define CMD_ORD_OFFSET 6 +#define RSP_SIZE_OFFSET 2 +#define RSP_RST_OFFSET 6 + +static uint32_t tpm_write_cmd_fifo(uint32_t locality, uint8_t *in, + uint32_t in_size, uint8_t *out, + uint32_t *out_size) +{ + uint32_t i, rsp_size, offset, ret; + uint16_t row_size; + tpm_reg_access_t reg_acc; + tpm_reg_sts_t reg_sts; + + if ( locality >= TPM_NR_LOCALITIES ) { + printk("TPM: Invalid parameter\n"); + return TPM_BAD_PARAMETER; + } + if ( in == NULL || out == NULL || out_size == NULL ) { + printk("TPM: Invalid parameter\n"); + return TPM_BAD_PARAMETER; + } + if ( in_size < CMD_HEAD_SIZE || *out_size < RSP_HEAD_SIZE ) { + printk("TPM: in/out buf size must be larger than 10 bytes.\n"); + return TPM_BAD_PARAMETER; + } + + if ( !tpm_validate_locality(locality) ) { + printk("TPM: Locality %d is not opened.\n", locality); + return TPM_FAIL; + } + + ret = tpm_wait_cmd_ready(locality); + if ( ret != TPM_SUCCESS ) + return ret; + + { + uint32_t i; + printk("TPM: cmd size = %d\nTPM: cmd content: ", in_size); + for ( i = 0; i < in_size; i++ ) { + if ( i % 16 == 0 ) + printk("\nTPM: \t"); + printk("%02x ", (uint32_t)in[i]); + } + printk("\n"); + } + + /* write the command to the TPM FIFO */ + offset = 0; + do { + for ( i = TPM_CMD_WRITE_TIME_OUT; i > 0; i-- ) { + read_tpm_reg(locality, TPM_REG_STS, ®_sts); + /* find out how many bytes the TPM can accept in a row */ + row_size = reg_sts.burst_count; + if ( row_size > 0 ) + break; + else + cpu_relax(); + } + if ( i <= 0 ) { + printk("TPM: write cmd timeout.\n"); + ret = TPM_FAIL; + goto RelinquishControl; + } + + for ( ; row_size > 0 && offset < in_size; row_size--, offset++ ) + write_tpm_reg(locality, TPM_REG_DATA_FIFO, + (tpm_reg_data_fifo_t *)&in[offset]); + } while ( offset < in_size ); + + /* command has been written to the TPM, it is time to execute it. */ + memset(®_sts, 0, sizeof(reg_sts)); + reg_sts.tpm_go = 1; + write_tpm_reg(locality, TPM_REG_STS, ®_sts); + + /* check for data available */ + for ( i = TPM_DATA_AVAIL_TIME_OUT; i > 0; i-- ) { + read_tpm_reg(locality,TPM_REG_STS, ®_sts); + if ( reg_sts.data_avail == 1 ) + break; + else + cpu_relax(); + } + if ( i <= 0 ) { + printk("TPM: wait for data available timeout.\n"); + ret = TPM_FAIL; + goto RelinquishControl; + } + + rsp_size = 0; + offset = 0; + do { + /* find out how many bytes the TPM returned in a row */ + for ( i = TPM_RSP_READ_TIME_OUT; i > 0; i-- ) { + read_tpm_reg(locality, TPM_REG_STS, ®_sts); + row_size = reg_sts.burst_count; + if ( row_size > 0 ) + break; + else + cpu_relax(); + } + if ( i <= 0 ) { + printk("TPM: read rsp timeout.\n"); + ret = TPM_FAIL; + goto RelinquishControl; + } + + for ( ; row_size > 0 && offset < *out_size; row_size--, offset++ ) { + if ( offset < *out_size ) + read_tpm_reg(locality, TPM_REG_DATA_FIFO, + (tpm_reg_data_fifo_t *)&out[offset]); + else { + /* discard the responded bytes exceeding out buf size */ + tpm_reg_data_fifo_t discard; + read_tpm_reg(locality, TPM_REG_DATA_FIFO, + (tpm_reg_data_fifo_t *)&discard); + } + + /* get outgoing data size */ + if ( offset == RSP_RST_OFFSET ) { + reverse_copy(&rsp_size, &out[RSP_SIZE_OFFSET], + sizeof(rsp_size)); + } + } + } while ( offset < RSP_RST_OFFSET || + (offset < rsp_size && offset < *out_size) ); + + *out_size = (*out_size > rsp_size) ? rsp_size : *out_size; + + /* out buffer contains the complete outgoing data, get return code */ + reverse_copy(&ret, &out[RSP_RST_OFFSET], sizeof(ret)); + + { + uint32_t i; + printk("TPM: response size = %d\n", *out_size); + printk("TPM: response content: "); + for ( i = 0; i < *out_size; i++ ) { + if ( i % 16 == 0 ) + printk("\nTPM: \t"); + printk("%02x ", (uint32_t)out[i]); + } + printk("\n"); + } + +RelinquishControl: + /* deactivate current locality */ + reg_acc._raw[0] = 0; + reg_acc.active_locality = 1; + write_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); + + return ret; +} + +/* + * The tpm_submit_cmd function comes with 2 global buffers: cmd_buf & rsp_buf. + * Before calling, caller should fill cmd arguements into cmd_buf via + * WRAPPER_IN_BUF macro. After calling, caller should fetch result from + * rsp_buffer via WRAPPER_OUT_BUF macro. + * cmd_buf content: + * 0 1 2 3 4 5 6 7 8 9 10 ... + * ------------------------------------------------------------- + * | TAG | SIZE | ORDINAL | arguments ... + * ------------------------------------------------------------- + * rsp_buf content: + * 0 1 2 3 4 5 6 7 8 9 10 ... + * ------------------------------------------------------------- + * | TAG | SIZE | RETURN CODE | other data ... + * ------------------------------------------------------------- + * + * locality : TPM locality (0 - 4) + * cmd : The TPM command ordinal + * arg_size : Size of argument data. + * out_size : IN/OUT paramter. The IN is the expected size of out data; + * the OUT is the size of output data within out buffer. + * The out_size MUST NOT be NULL. + * return : TPM_SUCCESS for success, for other error code, refer to the .h + */ +static uint8_t cmd_buf[TPM_CMD_SIZE_MAX]; +static uint8_t rsp_buf[TPM_RSP_SIZE_MAX]; +#define WRAPPER_IN_BUF (cmd_buf + CMD_HEAD_SIZE) +#define WRAPPER_OUT_BUF (rsp_buf + RSP_HEAD_SIZE) +#define WRAPPER_IN_MAX_SIZE (TPM_CMD_SIZE_MAX - CMD_HEAD_SIZE) +#define WRAPPER_OUT_MAX_SIZE (TPM_RSP_SIZE_MAX - RSP_HEAD_SIZE) + +static uint32_t tpm_submit_cmd(uint32_t locality, uint32_t cmd, + uint32_t arg_size, uint32_t *out_size) +{ + uint32_t ret; + uint16_t tag = TPM_TAG_RQU_COMMAND; + uint32_t cmd_size, rsp_size = 0; + + if ( out_size == NULL ) { + printk("TPM: invalid param for tpm_submit_cmd()\n"); + return TPM_BAD_PARAMETER; + } + + /* + * real cmd size should add 10 more bytes: + * 2 bytes for tag + * 4 bytes for size + * 4 bytes for ordinal + */ + cmd_size = CMD_HEAD_SIZE + arg_size; + + if ( cmd_size > TPM_CMD_SIZE_MAX ) { + printk("TPM: cmd exceeds the max supported size.\n"); + return TPM_BAD_PARAMETER; + } + + /* copy tag, size & ordinal into buf in a reversed byte order */ + reverse_copy(cmd_buf, &tag, sizeof(tag)); + reverse_copy(cmd_buf + CMD_SIZE_OFFSET, &cmd_size, sizeof(cmd_size)); + reverse_copy(cmd_buf + CMD_ORD_OFFSET, &cmd, sizeof(cmd)); + + rsp_size = RSP_HEAD_SIZE + *out_size; + rsp_size = (rsp_size > TPM_RSP_SIZE_MAX) ? TPM_RSP_SIZE_MAX: rsp_size; + ret = tpm_write_cmd_fifo(locality, cmd_buf, cmd_size, rsp_buf, &rsp_size); + + /* + * should subtract 10 bytes from real response size: + * 2 bytes for tag + * 4 bytes for size + * 4 bytes for return code + */ + rsp_size -= (rsp_size > RSP_HEAD_SIZE) ? RSP_HEAD_SIZE : rsp_size; + + if ( ret != TPM_SUCCESS ) + return ret; + + if ( *out_size == 0 || rsp_size == 0 ) + *out_size = 0; + else + *out_size = (rsp_size < *out_size) ? rsp_size : *out_size; + + return ret; +} + +uint32_t tpm_pcr_read(uint32_t locality, uint32_t pcr, tpm_pcr_value_t *out) +{ + uint32_t ret, out_size = sizeof(*out); + + if ( out == NULL ) + return TPM_BAD_PARAMETER; + if ( pcr >= TPM_NR_PCRS ) + return TPM_BAD_PARAMETER; + + /* copy pcr into buf in reversed byte order */ + reverse_copy(WRAPPER_IN_BUF, &pcr, sizeof(pcr)); + + ret = tpm_submit_cmd(locality, TPM_ORD_PCR_READ, sizeof(pcr), &out_size); + + printk("TPM: Pcr %d Read return value = %08X\n", pcr, ret); + if ( ret != TPM_SUCCESS ) + return ret; + + if ( out_size > sizeof(*out) ) + out_size = sizeof(*out); + memcpy((void *)out, WRAPPER_OUT_BUF, out_size); + + { + uint32_t i; + printk("TPM: "); + for ( i = 0; i < out_size; i++ ) + printk("%02X ", (uint32_t)out->digest[i]); + printk("\n"); + } + + return ret; +} + +uint32_t tpm_pcr_extend(uint32_t locality, uint32_t pcr, + const tpm_digest_t* in, tpm_pcr_value_t* out) +{ + uint32_t ret, in_size = 0, out_size; + + if ( in == NULL ) + return TPM_BAD_PARAMETER; + if ( pcr >= TPM_NR_PCRS ) + return TPM_BAD_PARAMETER; + if ( out == NULL ) + out_size = 0; + else + out_size = sizeof(*out); + + /* copy pcr into buf in reversed byte order, then copy in data */ + reverse_copy(WRAPPER_IN_BUF, &pcr, sizeof(pcr)); + in_size += sizeof(pcr); + memcpy(WRAPPER_IN_BUF + in_size, (void *)in, sizeof(*in)); + in_size += sizeof(*in); + + ret = tpm_submit_cmd(locality, TPM_ORD_PCR_EXTEND, in_size, &out_size); + + printk("TPM: Pcr %d extend, return value = %08X\n", pcr, ret); + if ( ret != TPM_SUCCESS ) + return ret; + + if ( out != NULL && out_size > 0 ) { + out_size = (out_size > sizeof(*out)) ? sizeof(*out) : out_size; + memcpy((void *)out, WRAPPER_OUT_BUF, out_size); + } + + { + uint32_t i; + printk("TPM: "); + for ( i = 0; i < out_size; i++ ) + printk("%02X ", (uint32_t)out->digest[i]); + printk("\n"); + } + + return ret; +} + +typedef struct { + uint16_t size_of_select; + uint8_t pcr_select[3]; +} __attribute__ ((packed)) tpm_pcr_selection_t; + +uint32_t tpm_pcr_reset(uint32_t locality, uint32_t pcr) +{ + uint32_t ret, in_size, out_size = 0; + uint16_t size_of_select; + tpm_pcr_selection_t pcr_sel = {0,{0,}}; + + if ( pcr >= TPM_NR_PCRS || pcr < TPM_PCR_RESETABLE_MIN ) + return TPM_BAD_PARAMETER; + + /* the pcr_sel.pcr_select[size_of_select - 1] should not be 0 */ + size_of_select = pcr / 8 + 1; + reverse_copy(&pcr_sel.size_of_select, &size_of_select, + sizeof(size_of_select)); + pcr_sel.pcr_select[pcr / 8] = 1 << (pcr % 8); + + in_size = sizeof(pcr_sel); + memcpy(WRAPPER_IN_BUF, (void *)&pcr_sel, in_size); + + ret = tpm_submit_cmd(locality, TPM_ORD_PCR_RESET, in_size, &out_size); + + printk("TPM: Pcr %d reset, return value = %08X\n", pcr, ret); + + return ret; +} + +uint32_t tpm_nv_read_value(uint32_t locality, tpm_nv_index_t index, + uint32_t offset, uint8_t *data, + uint32_t *data_size) +{ + uint32_t ret, in_size = 0, out_size; + + if ( data == NULL || data_size == NULL ) + return TPM_BAD_PARAMETER; + if ( *data_size == 0 ) + return TPM_BAD_PARAMETER; + if ( *data_size > TPM_NV_READ_VALUE_DATA_SIZE_MAX ) + *data_size = TPM_NV_READ_VALUE_DATA_SIZE_MAX; + + /* copy the index, offset and *data_size into buf in reversed byte order */ + reverse_copy(WRAPPER_IN_BUF, &index, sizeof(index)); + in_size += sizeof(index); + reverse_copy(WRAPPER_IN_BUF + in_size, &offset, sizeof(offset)); + in_size += sizeof(offset); + reverse_copy(WRAPPER_IN_BUF + in_size, data_size, sizeof(*data_size)); + in_size += sizeof(*data_size); + + out_size = *data_size + sizeof(*data_size); + ret = tpm_submit_cmd(locality, TPM_ORD_NV_READ_VALUE, in_size, &out_size); + + printk("TPM: read nv index %08x from offset %08x, return value = %08X\n", + index, offset, ret); + if ( ret != TPM_SUCCESS ) + return ret; + + { + uint32_t i; + printk("TPM: "); + for ( i = 0; i < out_size; i++ ) + printk("%02X ", (uint32_t)WRAPPER_OUT_BUF[i]); + printk("\n"); + } + + if ( out_size <= sizeof(*data_size) ) { + *data_size = 0; + return ret; + } + + out_size -= sizeof(*data_size); + reverse_copy(data_size, WRAPPER_OUT_BUF, sizeof(*data_size)); + *data_size = (*data_size > out_size) ? out_size : *data_size; + if( *data_size > 0 ) + memcpy(data, WRAPPER_OUT_BUF + sizeof(*data_size), *data_size); + + return ret; +} + +uint32_t tpm_nv_write_value(uint32_t locality, tpm_nv_index_t index, + uint32_t offset, const uint8_t *data, + uint32_t data_size) +{ + uint32_t ret, in_size = 0, out_size = 0; + + if ( data == NULL ) + return TPM_BAD_PARAMETER; + if ( data_size == 0 || data_size > TPM_NV_WRITE_VALUE_DATA_SIZE_MAX ) + return TPM_BAD_PARAMETER; + + /* copy index, offset and *data_size into buf in reversed byte order */ + reverse_copy(WRAPPER_IN_BUF, &index, sizeof(index)); + in_size += sizeof(index); + reverse_copy(WRAPPER_IN_BUF + in_size, &offset, sizeof(offset)); + in_size += sizeof(offset); + reverse_copy(WRAPPER_IN_BUF + in_size, &data_size, sizeof(data_size)); + in_size += sizeof(data_size); + memcpy(WRAPPER_IN_BUF + in_size, data, data_size); + in_size += data_size; + + ret = tpm_submit_cmd(locality, TPM_ORD_NV_WRITE_VALUE, + in_size, &out_size); + + printk("TPM: write nv %08x, offset %08x, %08x bytes, return = %08X\n", + index, offset, data_size, ret); + + return ret; +} + +/* ensure TPM is ready to accept commands */ +bool is_tpm_ready(uint32_t locality) +{ + tpm_reg_access_t reg_acc; + + if ( !tpm_validate_locality(locality) ) { + printk("TPM is not available.\n"); + return false; + } + + /* + * must ensure TPM_ACCESS_0.activeLocality bit is clear + * (: locality is not active) + */ + read_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); + if ( reg_acc.active_locality != 0 ) { + /* make inactive by writing a 1 */ + reg_acc.active_locality = 1; + write_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); + } + + printk("TPM is ready\n"); + + return true; +} + +#ifdef TPM_UNIT_TEST + +static void clean_buf(void) +{ + memset(cmd_buf, 0, TPM_CMD_SIZE_MAX); + memset(rsp_buf, 0, TPM_RSP_SIZE_MAX); +} + +static bool check_buf(uint8_t *exp_cmd, uint32_t cmd_size, + uint8_t *exp_rsp, uint32_t rsp_size) +{ + if ( memcmp(exp_cmd, cmd_buf, cmd_size) != 0 ) + return false; + if ( memcmp(exp_rsp, rsp_buf, rsp_size) != 0 ) + return false; + return true; +} + +static bool UNIT_PE_V_01(void) +{ + uint32_t locality = 0; + uint32_t pcr = 16; + tpm_digest_t in = {{ + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4}}; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + tpm_pcr_value_t exp_out = {{ + 0xfd, 0x60, 0xed, 0x16, 0xe5, 0x04, 0x04, 0x0a, + 0xaf, 0xa1, 0xc1, 0xcc, 0xed, 0x33, 0x8f, 0x1d, + 0x68, 0xd1, 0x39, 0x61}}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, + 0x04, 0x04}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0xfd, 0x60, 0xed, 0x16, 0xe5, 0x04, + 0x04, 0x0a, 0xaf, 0xa1, 0xc1, 0xcc, 0xed, 0x33, + 0x8f, 0x1d, 0x68, 0xd1, 0x39, 0x61}; + + clean_buf(); + ret = tpm_pcr_extend(locality, pcr, &in, &out); + if ( ret != exp_ret ) + return false; + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PE_V_02(void) +{ + uint32_t locality = 0; + uint32_t pcr = 16; + tpm_digest_t in = {{ + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4}}; + tpm_pcr_value_t *out = NULL; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, + 0x04, 0x04}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00}; + + clean_buf(); + ret = tpm_pcr_extend(locality, pcr, &in, out); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PE_V_03(void) +{ + uint32_t locality = 2; + uint32_t pcr = 16; + tpm_digest_t in = {{ + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4}}; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + tpm_pcr_value_t exp_out = {{ + 0xfd, 0x60, 0xed, 0x16, 0xe5, 0x04, 0x04, 0x0a, + 0xaf, 0xa1, 0xc1, 0xcc, 0xed, 0x33, 0x8f, 0x1d, + 0x68, 0xd1, 0x39, 0x61}}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x10, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, + 0x04, 0x04}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0xfd, 0x60, 0xed, 0x16, 0xe5, 0x04, + 0x04, 0x0a, 0xaf, 0xa1, 0xc1, 0xcc, 0xed, 0x33, + 0x8f, 0x1d, 0x68, 0xd1, 0x39, 0x61}; + + clean_buf(); + ret = tpm_pcr_extend(locality, pcr, &in, &out); + if ( ret != exp_ret ) + return false; + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PE_V_04(void) +{ + uint32_t locality = 2; + uint32_t pcr = 17; + tpm_digest_t in = {{ + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4}}; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + tpm_pcr_value_t exp_out = {{ + /* for SDP3/TEP */ + 0xe2, 0x76, 0x21, 0x70, 0x8d, 0x8b, 0x74, 0x20, + 0x5e, 0x61, 0x3c, 0xe6, 0xd3, 0x39, 0xf8, 0x0b, + 0x3d, 0x83, 0x18, 0x42}}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x11, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, + 0x04, 0x04}; + uint8_t exp_rsp[] = { + /* for SDP3/TEP */ + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0xe2, 0x76, 0x21, 0x70, 0x8d, 0x8b, + 0x74, 0x20, 0x5e, 0x61, 0x3c, 0xe6, 0xd3, 0x39, + 0xf8, 0x0b, 0x3d, 0x83, 0x18, 0x42}; + + clean_buf(); + ret = tpm_pcr_extend(locality, pcr, &in, &out); + if ( ret != exp_ret ) + return false; + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PE_V_05(void) +{ + uint32_t locality = 2; + uint32_t pcr = 18; + tpm_digest_t in = {{ + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4}}; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + /* + tpm_pcr_value_t exp_out = {{ + 0xe5, 0x9b, 0x4b, 0xf8, 0xd3, 0x42, 0x3f, 0xe7, + 0xeb, 0xc4, 0x2c, 0xe3, 0xb0, 0xf8, 0x98, 0x35, + 0x09, 0x9e, 0x2b, 0x96}}; + */ + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x12, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, + 0x04, 0x04}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00/*, 0xe5, 0x9b, 0x4b, 0xf8, 0xd3, 0x42, + 0x3f, 0xe7, 0xeb, 0xc4, 0x2c, 0xe3, 0xb0, 0xf8, + 0x98, 0x35, 0x09, 0x9e, 0x2b, 0x96*/}; + + clean_buf(); + ret = tpm_pcr_extend(locality, pcr, &in, &out); + if ( ret != exp_ret ) + return false; + /* + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + */ + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PE_V_06(void) +{ + uint32_t locality = 2; + uint32_t pcr = 19; + tpm_digest_t in = {{ + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4}}; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + tpm_pcr_value_t exp_out = {{ + 0xfd, 0x60, 0xed, 0x16, 0xe5, 0x04, 0x04, 0x0a, + 0xaf, 0xa1, 0xc1, 0xcc, 0xed, 0x33, 0x8f, 0x1d, + 0x68, 0xd1, 0x39, 0x61}}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x13, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, + 0x04, 0x04}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0xfd, 0x60, 0xed, 0x16, 0xe5, 0x04, + 0x04, 0x0a, 0xaf, 0xa1, 0xc1, 0xcc, 0xed, 0x33, + 0x8f, 0x1d, 0x68, 0xd1, 0x39, 0x61}; + + clean_buf(); + ret = tpm_pcr_extend(locality, pcr, &in, &out); + if ( ret != exp_ret ) + return false; + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PE_V_07(void) +{ + uint32_t locality = 2; + uint32_t pcr = 20; + tpm_digest_t in = {{ + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4}}; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + tpm_pcr_value_t exp_out = {{ + 0xfd, 0x60, 0xed, 0x16, 0xe5, 0x04, 0x04, 0x0a, + 0xaf, 0xa1, 0xc1, 0xcc, 0xed, 0x33, 0x8f, 0x1d, + 0x68, 0xd1, 0x39, 0x61}}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, + 0x04, 0x04}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0xfd, 0x60, 0xed, 0x16, 0xe5, 0x04, + 0x04, 0x0a, 0xaf, 0xa1, 0xc1, 0xcc, 0xed, 0x33, + 0x8f, 0x1d, 0x68, 0xd1, 0x39, 0x61}; + + clean_buf(); + ret = tpm_pcr_extend(locality, pcr, &in, &out); + if ( ret != exp_ret ) + return false; + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PE_IV_01(void) +{ + uint32_t locality = 0; + uint32_t pcr = 16; + tpm_digest_t *in = NULL; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_BAD_PARAMETER; + + clean_buf(); + ret = tpm_pcr_extend(locality, pcr, in, &out); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_PE_IV_02(void) +{ + uint32_t locality = 5; + uint32_t pcr = 16; + tpm_digest_t in = {{ + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4}}; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_BAD_PARAMETER; + + clean_buf(); + ret = tpm_pcr_extend(locality, pcr, &in, &out); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_PE_IV_03(void) +{ + uint32_t locality = 0; + uint32_t pcr = 24; + tpm_digest_t in = {{ + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4}}; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_BAD_PARAMETER; + + clean_buf(); + ret = tpm_pcr_extend(locality, pcr, &in, &out); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_PE_IV_04(void) +{ + uint32_t locality = 2; + uint32_t pcr = 16; + tpm_digest_t in = {{ + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4}}; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_FAIL; + + clean_buf(); + ret = tpm_pcr_extend(locality, pcr, &in, &out); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_PE_IV_05(void) +{ + uint32_t locality = 1; + uint32_t pcr = 16; + tpm_digest_t in = {{ + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4}}; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_FAIL; + + clean_buf(); + ret = tpm_pcr_extend(locality, pcr, &in, &out); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_PE_IV_06(void) +{ + uint32_t locality = 0; + uint32_t pcr = 17; + tpm_digest_t in = {{ + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4}}; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_BAD_LOCALITY;/* in SPD 3 whould be TPM_NOTLOCAL */ + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x11, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, + 0x04, 0x04}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x3d}; + + clean_buf(); + ret = tpm_pcr_extend(locality, pcr, &in, &out); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PR_V_01(void) +{ + uint32_t locality = 0; + uint32_t pcr = 16; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + tpm_pcr_value_t exp_out = {{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x15, 0x00, 0x00, 0x00, 0x10}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + clean_buf(); + ret = tpm_pcr_read(locality, pcr, &out); + if ( ret != exp_ret ) + return false; + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PR_V_02(void) +{ + uint32_t locality = 0; + uint32_t pcr = 16; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + tpm_pcr_value_t exp_out = {{ + 0xfd, 0x60, 0xed, 0x16, 0xe5, 0x04, 0x04, 0x0a, + 0xaf, 0xa1, 0xc1, 0xcc, 0xed, 0x33, 0x8f, 0x1d, + 0x68, 0xd1, 0x39, 0x61}}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x15, 0x00, 0x00, 0x00, 0x10}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0xfd, 0x60, 0xed, 0x16, 0xe5, 0x04, + 0x04, 0x0a, 0xaf, 0xa1, 0xc1, 0xcc, 0xed, 0x33, + 0x8f, 0x1d, 0x68, 0xd1, 0x39, 0x61}; + + clean_buf(); + ret = tpm_pcr_read(locality, pcr, &out); + if ( ret != exp_ret ) + return false; + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PR_V_03(void) +{ + uint32_t locality = 2; + uint32_t pcr = 16; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + tpm_pcr_value_t exp_out = {{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x15, 0x00, 0x00, 0x00, 0x10}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + clean_buf(); + ret = tpm_pcr_read(locality, pcr, &out); + if ( ret != exp_ret ) + return false; + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PR_V_04(void) +{ + uint32_t locality = 2; + uint32_t pcr = 16; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + tpm_pcr_value_t exp_out = {{ + 0xfd, 0x60, 0xed, 0x16, 0xe5, 0x04, 0x04, 0x0a, + 0xaf, 0xa1, 0xc1, 0xcc, 0xed, 0x33, 0x8f, 0x1d, + 0x68, 0xd1, 0x39, 0x61}}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x15, 0x00, 0x00, 0x00, 0x10}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0xfd, 0x60, 0xed, 0x16, 0xe5, 0x04, + 0x04, 0x0a, 0xaf, 0xa1, 0xc1, 0xcc, 0xed, 0x33, + 0x8f, 0x1d, 0x68, 0xd1, 0x39, 0x61}; + + clean_buf(); + ret = tpm_pcr_read(locality, pcr, &out); + if ( ret != exp_ret ) + return false; + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PR_V_05(void) +{ + uint32_t locality = 2; + uint32_t pcr = 17; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + tpm_pcr_value_t exp_out = {{ + /* for SDP3/TEP */ + 0xf8, 0xf2, 0xfb, 0x54, 0xdb, 0x1b, 0xcb, 0xdf, + 0xcf, 0x48, 0xbe, 0xde, 0xb4, 0xf6, 0x94, 0x97, + 0x19, 0x25, 0xbd, 0x9b}}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x15, 0x00, 0x00, 0x00, 0x11}; + uint8_t exp_rsp[] = { + /* for SDP3/TEP */ + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0xf8, 0xf2, 0xfb, 0x54, 0xdb, 0x1b, + 0xcb, 0xdf, 0xcf, 0x48, 0xbe, 0xde, 0xb4, 0xf6, + 0x94, 0x97, 0x19, 0x25, 0xbd, 0x9b}; + + clean_buf(); + ret = tpm_pcr_read(locality, pcr, &out); + if ( ret != exp_ret ) + return false; + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PR_V_06(void) +{ + uint32_t locality = 2; + uint32_t pcr = 18; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + /* + tpm_pcr_value_t exp_out = {{ + 0x8d, 0x84, 0xdb, 0x02, 0xc0, 0x13, 0x9d, 0x2c, + 0x51, 0xdb, 0x15, 0xd8, 0xc6, 0xc4, 0x1b, 0xc0, + 0x6b, 0x34, 0xbe, 0xeb}}; + */ + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x15, 0x00, 0x00, 0x00, 0x12}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00/*, 0x8d, 0x84, 0xdb, 0x02, 0xc0, 0x13, + 0x9d, 0x2c, 0x51, 0xdb, 0x15, 0xd8, 0xc6, 0xc4, + 0x1b, 0xc0, 0x6b, 0x34, 0xbe, 0xeb*/}; + + clean_buf(); + ret = tpm_pcr_read(locality, pcr, &out); + if ( ret != exp_ret ) + return false; + /* + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + */ + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PR_V_07(void) +{ + uint32_t locality = 2; + uint32_t pcr = 19; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + tpm_pcr_value_t exp_out = {{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x15, 0x00, 0x00, 0x00, 0x13}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + clean_buf(); + ret = tpm_pcr_read(locality, pcr, &out); + if ( ret != exp_ret ) + return false; + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PR_V_08(void) +{ + uint32_t locality = 2; + uint32_t pcr = 20; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + tpm_pcr_value_t exp_out = {{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x15, 0x00, 0x00, 0x00, 0x14}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + clean_buf(); + ret = tpm_pcr_read(locality, pcr, &out); + if ( ret != exp_ret ) + return false; + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PR_V_09(void) +{ + uint32_t locality = 0; + uint32_t pcr = 17; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + tpm_pcr_value_t exp_out = {{ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff}}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, + 0x00, 0x15, 0x00, 0x00, 0x00, 0x11}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + + clean_buf(); + ret = tpm_pcr_read(locality, pcr, &out); + if ( ret != exp_ret ) + return false; + if ( memcmp(&out, &exp_out, sizeof(out)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PR_IV_01(void) +{ + uint32_t locality = 5; + uint32_t pcr = 16; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_BAD_PARAMETER; + + clean_buf(); + ret = tpm_pcr_read(locality, pcr, &out); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_PR_IV_02(void) +{ + uint32_t locality = 0; + uint32_t pcr = 24; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_BAD_PARAMETER; + + clean_buf(); + ret = tpm_pcr_read(locality, pcr, &out); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_PR_IV_03(void) +{ + uint32_t locality = 2; + uint32_t pcr = 16; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_FAIL; + + clean_buf(); + ret = tpm_pcr_read(locality, pcr, &out); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_PR_IV_04(void) +{ + uint32_t locality = 1; + uint32_t pcr = 16; + tpm_pcr_value_t out = {{0,}}; + uint32_t ret; + + uint32_t exp_ret = TPM_FAIL; + + clean_buf(); + ret = tpm_pcr_read(locality, pcr, &out); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_PS_V_01(void) +{ + uint32_t locality = 0; + uint32_t pcr = 16; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, + 0x00, 0xc8, 0x00, 0x03, 0x00, 0x00, 0x01}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x00}; + + clean_buf(); + ret = tpm_pcr_reset(locality, pcr); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PS_V_02(void) +{ + uint32_t locality = 2; + uint32_t pcr = 16; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, + 0x00, 0xc8, 0x00, 0x03, 0x00, 0x00, 0x01}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x00}; + + clean_buf(); + ret = tpm_pcr_reset(locality, pcr); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PS_V_03(void) +{ + uint32_t locality = 2; + uint32_t pcr = 20; + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, + 0x00, 0xc8, 0x00, 0x03, 0x00, 0x00, 0x10}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x00}; + + clean_buf(); + ret = tpm_pcr_reset(locality, pcr); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PS_IV_01(void) +{ + uint32_t locality = 0; + uint32_t pcr = 15; + uint32_t ret; + + uint32_t exp_ret = TPM_BAD_PARAMETER; + + clean_buf(); + ret = tpm_pcr_reset(locality, pcr); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_PS_IV_02(void) +{ + uint32_t locality = 0; + uint32_t pcr = 24; + uint32_t ret; + + uint32_t exp_ret = TPM_BAD_PARAMETER; + + clean_buf(); + ret = tpm_pcr_reset(locality, pcr); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_PS_IV_03(void) +{ + uint32_t locality = 5; + uint32_t pcr = 16; + uint32_t ret; + + uint32_t exp_ret = TPM_BAD_PARAMETER; + + clean_buf(); + ret = tpm_pcr_reset(locality, pcr); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_PS_IV_04(void) +{ + uint32_t locality = 0; + uint32_t pcr = 20; + uint32_t ret; + + uint32_t exp_ret = TPM_NOTLOCAL; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, + 0x00, 0xc8, 0x00, 0x03, 0x00, 0x00, 0x10}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x33}; + + clean_buf(); + ret = tpm_pcr_reset(locality, pcr); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_PS_IV_05(void) +{ + uint32_t locality = 2; + uint32_t pcr = 17; + uint32_t ret; + + uint32_t exp_ret = TPM_NOTLOCAL; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, + 0x00, 0xc8, 0x00, 0x03, 0x00, 0x00, 0x02}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x33}; + + clean_buf(); + ret = tpm_pcr_reset(locality, pcr); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +#define TPM_NV_INDEX_LCP_OWN 0x40000002 +#define TPM_NV_INDEX_SELFDEF 0x400000ff +#define TPM_NV_INDEX_UNDEF 0x400000ee + +static bool UNIT_NW_V_01(void) +{ + uint32_t locality = 0; + uint32_t index = TPM_NV_INDEX_LCP_OWN; + uint32_t offset = 0; + uint8_t data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, + 0x00, 0xcd, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x1b, 0x1c}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x00}; + + clean_buf(); + ret = tpm_nv_write_value(locality, index, offset, data, data_size); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_NW_V_02(void) +{ + uint32_t locality = 0; + uint32_t index = TPM_NV_INDEX_SELFDEF; + uint32_t offset = 0; + static uint8_t data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 256 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 512 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09}; /* 746 */ + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + static uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0xcd, 0x40, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0xea, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}; /* 768 */ + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x00}; + + clean_buf(); + ret = tpm_nv_write_value(locality, index, offset, + (uint8_t *)data, data_size); + if ( ret != exp_ret ) + return false; + if ( !check_buf((uint8_t *)exp_cmd, sizeof(exp_cmd), + exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_NW_V_03(void) +{ + uint32_t locality = 0; + uint32_t index = TPM_NV_INDEX_SELFDEF; + uint32_t offset = 746; + uint8_t data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, + 0x00, 0xcd, 0x40, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x02, 0xea, 0x00, 0x00, 0x00, 0x16, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x00}; + + clean_buf(); + ret = tpm_nv_write_value(locality, index, offset, data, data_size); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_NW_V_04(void) +{ + uint32_t locality = 2; + uint32_t index = TPM_NV_INDEX_LCP_OWN; + uint32_t offset = 0; + uint8_t data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, + 0x00, 0xcd, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x00}; + + clean_buf(); + ret = tpm_nv_write_value(locality, index, offset, data, data_size); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_NW_IV_01(void) +{ + uint32_t locality = 5; + uint32_t index = TPM_NV_INDEX_LCP_OWN; + uint32_t offset = 0; + uint8_t data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_BAD_PARAMETER; + + clean_buf(); + ret = tpm_nv_write_value(locality, index, offset, data, data_size); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_NW_IV_02(void) +{ + uint32_t locality = 2; + uint32_t index = TPM_NV_INDEX_LCP_OWN; + uint32_t offset = 0; + uint8_t data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_FAIL; + + clean_buf(); + ret = tpm_nv_write_value(locality, index, offset, data, data_size); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_NW_IV_03(void) +{ + uint32_t locality = 0; + uint32_t index = TPM_NV_INDEX_UNDEF; + uint32_t offset = 0; + uint8_t data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_BADINDEX; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, + 0x00, 0xcd, 0x40, 0x00, 0x00, 0xee, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x02}; + + clean_buf(); + ret = tpm_nv_write_value(locality, index, offset, data, data_size); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_NW_IV_04(void) +{ + uint32_t locality = 0; + uint32_t index = TPM_NV_INDEX_LCP_OWN; + uint32_t offset = 29; + uint8_t data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_NOSPACE; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, + 0x00, 0xcd, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x1d, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x11}; + + clean_buf(); + ret = tpm_nv_write_value(locality, index, offset, data, data_size); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_NW_IV_05(void) +{ + uint32_t locality = 0; + uint32_t index = TPM_NV_INDEX_LCP_OWN; + uint32_t offset = 20; + uint8_t data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_NOSPACE; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, + 0x00, 0xcd, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x11}; + + clean_buf(); + ret = tpm_nv_write_value(locality, index, offset, data, data_size); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_NW_IV_06(void) +{ + uint32_t locality = 0; + uint32_t index = TPM_NV_INDEX_SELFDEF; + uint32_t offset = 0; + static uint8_t data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 256 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 512 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a}; /* 747 */ + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_BAD_PARAMETER; + + clean_buf(); + ret = tpm_nv_write_value(locality, index, offset, + (uint8_t *)data, data_size); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_NR_V_01(void) +{ + uint32_t locality = 0; + uint32_t index = TPM_NV_INDEX_LCP_OWN; + uint32_t offset = 0; + uint8_t data[29] = {0,}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + uint32_t exp_size = sizeof(data); + uint8_t exp_data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0xcf, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x1b, 0x1c}; + + clean_buf(); + ret = tpm_nv_read_value(locality, index, offset, data, &data_size); + if ( ret != exp_ret ) + return false; + if ( data_size != exp_size ) + return false; + if ( memcmp(data, &exp_data, sizeof(data)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_NR_V_02(void) +{ + uint32_t locality = 0; + uint32_t index = TPM_NV_INDEX_SELFDEF; + uint32_t offset = 0; + static uint8_t data[TPM_NV_READ_VALUE_DATA_SIZE_MAX] = {0,}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + uint32_t exp_size = sizeof(data); + static uint8_t exp_data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 256 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 512 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, }; /* 754 */ + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0xcf, 0x40, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0xf2}; + static uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0xf2, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; /* 768 */ + + clean_buf(); + ret = tpm_nv_read_value(locality, index, offset, + (uint8_t *)data, &data_size); + if ( ret != exp_ret ) + return false; + if ( data_size != exp_size ) + return false; + if ( memcmp((uint8_t *)data, (uint8_t *)exp_data, sizeof(data)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), + (uint8_t *)exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_NR_V_03(void) +{ + uint32_t locality = 0; + uint32_t index = TPM_NV_INDEX_SELFDEF; + uint32_t offset = 754; + uint8_t data[14] = {0,}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + uint32_t exp_size = sizeof(data); + uint8_t exp_data[] = { + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0xcf, 0x40, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x02, 0xf2, 0x00, 0x00, 0x00, 0x0e}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15}; + + clean_buf(); + ret = tpm_nv_read_value(locality, index, offset, data, &data_size); + if ( ret != exp_ret ) + return false; + if ( data_size != exp_size ) + return false; + if ( memcmp(data, &exp_data, sizeof(data)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_NR_V_04(void) +{ + uint32_t locality = 2; + uint32_t index = TPM_NV_INDEX_LCP_OWN; + uint32_t offset = 0; + uint8_t data[20] = {0,}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + uint32_t exp_size = sizeof(data); + uint8_t exp_data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13}; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0xcf, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x14}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, + 0x12, 0x13}; + + clean_buf(); + ret = tpm_nv_read_value(locality, index, offset, data, &data_size); + if ( ret != exp_ret ) + return false; + if ( data_size != exp_size ) + return false; + if ( memcmp(data, &exp_data, sizeof(data)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_NR_IV_01(void) +{ + uint32_t locality = 5; + uint32_t index = TPM_NV_INDEX_LCP_OWN; + uint32_t offset = 0; + uint8_t data[20] = {0,}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_BAD_PARAMETER; + + clean_buf(); + ret = tpm_nv_read_value(locality, index, offset, data, &data_size); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_NR_IV_02(void) +{ + uint32_t locality = 2; + uint32_t index = TPM_NV_INDEX_LCP_OWN; + uint32_t offset = 0; + uint8_t data[20] = {0,}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_FAIL; + + clean_buf(); + ret = tpm_nv_read_value(locality, index, offset, data, &data_size); + if ( ret != exp_ret ) + return false; + + return true; +} + +static bool UNIT_NR_IV_03(void) +{ + uint32_t locality = 0; + uint32_t index = TPM_NV_INDEX_UNDEF; + uint32_t offset = 0; + uint8_t data[20] = {0,}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_BADINDEX; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0xcf, 0x40, 0x00, 0x00, 0xee, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x14}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x02}; + + clean_buf(); + ret = tpm_nv_read_value(locality, index, offset, data, &data_size); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_NR_IV_04(void) +{ + uint32_t locality = 0; + uint32_t index = TPM_NV_INDEX_LCP_OWN; + uint32_t offset = 29; + uint8_t data[20] = {0,}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_NOSPACE; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0xcf, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x1d, 0x00, 0x00, 0x00, 0x14}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x11}; + + clean_buf(); + ret = tpm_nv_read_value(locality, index, offset, data, &data_size); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_NR_IV_05(void) +{ + uint32_t locality = 0; + uint32_t index = TPM_NV_INDEX_LCP_OWN; + uint32_t offset = 20; + uint8_t data[20] = {0,}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_NOSPACE; + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0xcf, 0x40, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x14, 0x00, 0x00, 0x00, 0x14}; + uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, + 0x00, 0x11}; + + clean_buf(); + ret = tpm_nv_read_value(locality, index, offset, data, &data_size); + if ( ret != exp_ret ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +static bool UNIT_NR_IV_06(void) +{ + uint32_t locality = 0; + uint32_t index = TPM_NV_INDEX_SELFDEF; + uint32_t offset = 0; + static uint8_t data[TPM_NV_READ_VALUE_DATA_SIZE_MAX + 1] = {0,}; + uint32_t data_size = sizeof(data); + uint32_t ret; + + uint32_t exp_ret = TPM_SUCCESS; + uint32_t exp_size = TPM_NV_READ_VALUE_DATA_SIZE_MAX; + static uint8_t exp_data[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 256 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 512 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x06, 0x07, }; /* 754 */ + uint8_t exp_cmd[] = { + 0x00, 0xc1, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x00, 0xcf, 0x40, 0x00, 0x00, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0xf2}; + static uint8_t exp_rsp[] = { + 0x00, 0xc4, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0xf2, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, + 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; /* 768 */ + + clean_buf(); + ret = tpm_nv_read_value(locality, index, offset, + (uint8_t *)data, &data_size); + if ( ret != exp_ret ) + return false; + if ( data_size != exp_size ) + return false; + if ( memcmp((uint8_t *)data, (uint8_t *)exp_data, sizeof(data)) != 0 ) + return false; + if ( !check_buf(exp_cmd, sizeof(exp_cmd), + (uint8_t *)exp_rsp, sizeof(exp_rsp)) ) + return false; + + return true; +} + +#define RUN_CASE(caseid) {\ + if ( caseid() )\ + printk("TPM_UNIT_TEST: " #caseid " passed\n");\ + else\ + printk("TPM_UNIT_TEST: " #caseid " failed\n");\ +} + +void tpm_unit_test_before_senter(void) +{ + RUN_CASE(UNIT_PR_V_01 ); /* Pcr16 */ + RUN_CASE(UNIT_PE_V_01 ); /* Pcr16, out != NULL */ + RUN_CASE(UNIT_PR_V_02 ); /* Pcr16 */ + RUN_CASE(UNIT_PS_V_01 ); /* Pcr16 */ + RUN_CASE(UNIT_PE_V_02 ); /* Pcr16, out = NULL */ + RUN_CASE(UNIT_PR_V_09 ); /* Pcr17 */ + RUN_CASE(UNIT_PE_IV_01); /* in = NULL */ + RUN_CASE(UNIT_PE_IV_02); /* locality = 5 */ + RUN_CASE(UNIT_PE_IV_03); /* pcr24 */ + RUN_CASE(UNIT_PE_IV_04); /* locality = 2 */ + RUN_CASE(UNIT_PE_IV_06); /* pcr17 */ + RUN_CASE(UNIT_PR_IV_01); /* locality = 5 */ + RUN_CASE(UNIT_PR_IV_02); /* Pcr24 */ + RUN_CASE(UNIT_PR_IV_03); /* Locality = 2 */ + RUN_CASE(UNIT_PS_IV_01); /* Pcr15 */ + RUN_CASE(UNIT_PS_IV_02); /* Pcr24 */ + RUN_CASE(UNIT_PS_IV_03); /* Locality = 5 */ + RUN_CASE(UNIT_PS_IV_04); /* Pcr20, locality = 0 */ + RUN_CASE(UNIT_NW_V_01 ); /* LCP_OWN, off 0, 29 bytes */ + RUN_CASE(UNIT_NR_V_01 ); /* LCP_OWN, off 0, 29 bytes */ + RUN_CASE(UNIT_NW_V_02 ); /* SELFDEF, off 0, 746 bytes */ + RUN_CASE(UNIT_NW_V_03 ); /* SELFDEF, off 746, 22bytes */ + RUN_CASE(UNIT_NR_V_02 ); /* SELFDEF, off 0, 754 bytes */ + RUN_CASE(UNIT_NR_V_03 ); /* SELFDEF, off 754, 14bytes */ + RUN_CASE(UNIT_NW_IV_01); /* Locality = 5 */ + RUN_CASE(UNIT_NW_IV_02); /* Locality = 2 */ + RUN_CASE(UNIT_NW_IV_03); /* UNDEF */ + RUN_CASE(UNIT_NW_IV_04); /* LCP_OWN, off 29 */ + RUN_CASE(UNIT_NW_IV_05); /* LCP_OWN, off 20, 20bytes */ + RUN_CASE(UNIT_NW_IV_06); /* SELFDEF, off 0, 747bytes */ + RUN_CASE(UNIT_NR_IV_01); /* Locality = 5 */ + RUN_CASE(UNIT_NR_IV_02); /* Locality = 2 */ + RUN_CASE(UNIT_NR_IV_03); /* UNDEF */ + RUN_CASE(UNIT_NR_IV_04); /* LCP_OWN, off 29 */ + RUN_CASE(UNIT_NR_IV_05); /* LCP_OWN, off 20, 20bytes */ + RUN_CASE(UNIT_NR_IV_06); /* SELFDEF, off 0, 755bytes */ +} + +void tpm_unit_test_after_senter(void) +{ + RUN_CASE(UNIT_PS_V_02 ); /* Pcr16 */ + RUN_CASE(UNIT_PR_V_03 ); /* Pcr16 */ + RUN_CASE(UNIT_PE_V_03 ); /* pcr16, out != NULL */ + RUN_CASE(UNIT_PR_V_04 ); /* Pcr16 */ + RUN_CASE(UNIT_PR_V_05 ); /* Pcr17 */ + RUN_CASE(UNIT_PE_V_04 ); /* Pcr17, out != NULL */ + RUN_CASE(UNIT_PR_V_06 ); /* Pcr18 */ + RUN_CASE(UNIT_PE_V_05 ); /* Pcr18, out != NULL */ + RUN_CASE(UNIT_PR_V_07 ); /* Pcr19 */ + RUN_CASE(UNIT_PE_V_06 ); /* Pcr19, out != NULL */ + RUN_CASE(UNIT_PR_V_08 ); /* Pcr20 */ + RUN_CASE(UNIT_PE_V_07 ); /* Pcr20, out != NULL */ + RUN_CASE(UNIT_PS_V_03 ); /* Pcr20 */ + RUN_CASE(UNIT_PE_IV_05); /* locality = 1 */ + RUN_CASE(UNIT_PR_IV_04); /* locality = 1 */ + RUN_CASE(UNIT_PS_IV_05); /* Pcr17, Locality = 2 */ + RUN_CASE(UNIT_NW_V_04); /* LCP_OWN, off 0, 20 bytes */ + RUN_CASE(UNIT_NR_V_04); /* LCP_OWN, off 0, 20 bytes */ +} + +#endif /* TPM_UNIT_TEST */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/common/vsprintf.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/common/vsprintf.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,523 @@ +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +/* + * Fri Jul 13 2001 Crutcher Dunnavant + * - changed to provide snprintf and vsnprintf functions + * So Feb 1 16:51:32 CET 2004 Juergen Quade + * - scnprintf and vscnprintf + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static int skip_atoi(const char **s) +{ + int i=0; + + while (isdigit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + +static char * number(char * buf, char * end, unsigned long long num, int base, int size, int precision, int type) +{ + char c,sign,tmp[66]; + const char *digits; + static const char small_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + static const char large_digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int i; + + digits = (type & LARGE) ? large_digits : small_digits; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return NULL; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if ((signed long long) num < 0) { + sign = '-'; + num = - (signed long long) num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_div(num,base)]; +#if 0 + else + { + /* XXX KAF: force unsigned mod and div. */ + unsigned long long num2=(unsigned long long)num; + unsigned int base2=(unsigned int)base; + while (num2 != 0) { tmp[i++] = digits[num2%base2]; num2 /= base2; } + } +#endif + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) { + while(size-->0) { + if (buf <= end) + *buf = ' '; + ++buf; + } + } + if (sign) { + if (buf <= end) + *buf = sign; + ++buf; + } + if (type & SPECIAL) { + if (base==8) { + if (buf <= end) + *buf = '0'; + ++buf; + } else if (base==16) { + if (buf <= end) + *buf = '0'; + ++buf; + if (buf <= end) + *buf = digits[33]; + ++buf; + } + } + if (!(type & LEFT)) { + while (size-- > 0) { + if (buf <= end) + *buf = c; + ++buf; + } + } + while (i < precision--) { + if (buf <= end) + *buf = '0'; + ++buf; + } + while (i-- > 0) { + if (buf <= end) + *buf = tmp[i]; + ++buf; + } + while (size-- > 0) { + if (buf <= end) + *buf = ' '; + ++buf; + } + return buf; +} + +/** + * vsnprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @args: Arguments for the format string + * + * The return value is the number of characters which would + * be generated for the given input, excluding the trailing + * '\0', as per ISO C99. If you want to have the exact + * number of characters written into @buf as return value + * (not including the trailing '\0'), use vscnprintf. If the + * return is greater than or equal to @size, the resulting + * string is truncated. + * + * Call this function if you are already dealing with a va_list. + * You probably want snprintf instead. + */ +int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + int len; + unsigned long long num; + int i, base; + char *str, *end, c; + const char *s; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'L' for integer fields */ + /* 'z' support added 23/7/1999 S.H. */ + /* 'z' changed to 'Z' --davidm 1/25/99 */ + + /* Reject out-of-range values early */ + BUG_ON((int)size < 0); + + str = buf; + end = buf + size - 1; + + if (end < buf - 1) { + end = ((void *) -1); + size = end - buf + 1; + } + + for (; *fmt ; ++fmt) { + if (*fmt != '%') { + if (str <= end) + *str = *fmt; + ++str; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (isdigit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || + *fmt =='Z' || *fmt == 'z') { + qualifier = *fmt; + ++fmt; + if (qualifier == 'l' && *fmt == 'l') { + qualifier = 'L'; + ++fmt; + } + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) { + while (--field_width > 0) { + if (str <= end) + *str = ' '; + ++str; + } + } + c = (unsigned char) va_arg(args, int); + if (str <= end) + *str = c; + ++str; + while (--field_width > 0) { + if (str <= end) + *str = ' '; + ++str; + } + continue; + + case 's': + s = va_arg(args, char *); + if ((unsigned long)s < PAGE_SIZE) + s = ""; + + len = strnlen(s, precision); + + if (!(flags & LEFT)) { + while (len < field_width--) { + if (str <= end) + *str = ' '; + ++str; + } + } + for (i = 0; i < len; ++i) { + if (str <= end) + *str = *s; + ++str; ++s; + } + while (len < field_width--) { + if (str <= end) + *str = ' '; + ++str; + } + continue; + + case 'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + str = number(str, end, + (unsigned long) va_arg(args, void *), + 16, field_width, precision, flags); + continue; + + + case 'n': + /* FIXME: + * What does C99 say about the overflow case here? */ + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = (str - buf); + } else if (qualifier == 'Z' || qualifier == 'z') { + size_t * ip = va_arg(args, size_t *); + *ip = (str - buf); + } else { + int * ip = va_arg(args, int *); + *ip = (str - buf); + } + continue; + + case '%': + if (str <= end) + *str = '%'; + ++str; + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'X': + flags |= LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + if (str <= end) + *str = '%'; + ++str; + if (*fmt) { + if (str <= end) + *str = *fmt; + ++str; + } else { + --fmt; + } + continue; + } + if (qualifier == 'L') + num = va_arg(args, long long); + else if (qualifier == 'l') { + num = va_arg(args, unsigned long); + if (flags & SIGN) + num = (signed long) num; + } else if (qualifier == 'Z' || qualifier == 'z') { + num = va_arg(args, size_t); + } else if (qualifier == 'h') { + num = (unsigned short) va_arg(args, int); + if (flags & SIGN) + num = (signed short) num; + } else { + num = va_arg(args, unsigned int); + if (flags & SIGN) + num = (signed int) num; + } + + str = number(str, end, num, base, + field_width, precision, flags); + } + if (str <= end) + *str = '\0'; + else if (size > 0) + /* don't write out a null byte if the buf size is zero */ + *end = '\0'; + /* the trailing null byte doesn't count towards the total + * ++str; + */ + return str-buf; +} + +EXPORT_SYMBOL(vsnprintf); + +/** + * vscnprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @args: Arguments for the format string + * + * The return value is the number of characters which have been written into + * the @buf not including the trailing '\0'. If @size is <= 0 the function + * returns 0. + * + * Call this function if you are already dealing with a va_list. + * You probably want scnprintf instead. + */ +int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + int i; + + i=vsnprintf(buf,size,fmt,args); + return (i >= size) ? (size - 1) : i; +} + +EXPORT_SYMBOL(vscnprintf); + +/** + * snprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @...: Arguments for the format string + * + * The return value is the number of characters which would be + * generated for the given input, excluding the trailing null, + * as per ISO C99. If the return is greater than or equal to + * @size, the resulting string is truncated. + */ +int snprintf(char * buf, size_t size, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=vsnprintf(buf,size,fmt,args); + va_end(args); + return i; +} + +EXPORT_SYMBOL(snprintf); + +/** + * scnprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @size: The size of the buffer, including the trailing null space + * @fmt: The format string to use + * @...: Arguments for the format string + * + * The return value is the number of characters written into @buf not including + * the trailing '\0'. If @size is <= 0 the function returns 0. If the return is + * greater than or equal to @size, the resulting string is truncated. + */ + +int scnprintf(char * buf, size_t size, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vsnprintf(buf, size, fmt, args); + va_end(args); + return (i >= size) ? (size - 1) : i; +} +EXPORT_SYMBOL(scnprintf); + +/** + * vsprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @fmt: The format string to use + * @args: Arguments for the format string + * + * The function returns the number of characters written + * into @buf. Use vsnprintf or vscnprintf in order to avoid + * buffer overflows. + * + * Call this function if you are already dealing with a va_list. + * You probably want sprintf instead. + */ +int vsprintf(char *buf, const char *fmt, va_list args) +{ + return vsnprintf(buf, INT_MAX, fmt, args); +} + +EXPORT_SYMBOL(vsprintf); + +/** + * sprintf - Format a string and place it in a buffer + * @buf: The buffer to place the result into + * @fmt: The format string to use + * @...: Arguments for the format string + * + * The function returns the number of characters written + * into @buf. Use snprintf or scnprintf in order to avoid + * buffer overflows. + */ +int sprintf(char * buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=vsnprintf(buf, INT_MAX, fmt, args); + va_end(args); + return i; +} + +EXPORT_SYMBOL(sprintf); + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/include/compiler.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/compiler.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,56 @@ +#ifndef __LINUX_COMPILER_H +#define __LINUX_COMPILER_H + +#if !defined(__GNUC__) || (__GNUC__ < 3) +#error Sorry, your compiler is too old/not recognized. +#endif + +#define barrier() __asm__ __volatile__("": : :"memory") + +#define likely(x) __builtin_expect((x),1) +#define unlikely(x) __builtin_expect((x),0) + +#define inline __inline__ +#define always_inline __inline__ __attribute__ ((always_inline)) +#define noinline __attribute__((noinline)) + +#define __attribute_pure__ __attribute__((pure)) +#define __attribute_const__ __attribute__((__const__)) + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) +#define __attribute_used__ __attribute__((__used__)) +#else +#define __attribute_used__ __attribute__((__unused__)) +#endif + +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define __must_check __attribute__((warn_unused_result)) +#else +#define __must_check +#endif + +#if __GNUC__ > 3 +#define offsetof(a,b) __builtin_offsetof(a,b) +#else +#define offsetof(a,b) ((unsigned long)&(((a *)0)->b)) +#endif + +#ifdef GCC_HAS_VISIBILITY_ATTRIBUTE +/* Results in more efficient PIC code (no indirections through GOT or PLT). */ +#pragma GCC visibility push(hidden) +#endif + +/* This macro obfuscates arithmetic on a variable address so that gcc + shouldn't recognize the original var, and make assumptions about it */ +/* + * Versions of the ppc64 compiler before 4.1 had a bug where use of + * RELOC_HIDE could trash r30. The bug can be worked around by changing + * the inline assembly constraint from =g to =r, in this particular + * case either is valid. + */ +#define RELOC_HIDE(ptr, off) \ + ({ unsigned long __ptr; \ + __asm__ ("" : "=r"(__ptr) : "0"(ptr)); \ + (typeof(ptr)) (__ptr + (off)); }) + +#endif /* __LINUX_COMPILER_H */ diff -r 419625d61514 -r de5826b5b302 sboot/include/config.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/config.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,47 @@ +/****************************************************************************** + * config.h + * + * A Linux-style configuration list. + */ + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +/* + * build/support flags + */ + +#define DEBUG + +/* TBD: remove this when only support BLK A1+ and no SDP3 */ +#define CHIPSET_REVID_BUG + + +/* address that sboot will execute at */ +#define SBOOT_BASE_ADDR 0x70000 + +#ifdef MAX_PHYS_CPUS +#define NR_CPUS MAX_PHYS_CPUS +#else +#define NR_CPUS 32 +#endif + +/* Linkage for x86 */ +#ifdef __ASSEMBLY__ +#define ENTRY(name) \ + .globl name; \ + .align 16,0x90; \ + name: +#endif + +#define ELFSIZE 32 + +/* For generic assembly code: use macros to define operation/operand sizes. */ +#define __OS "l" /* Operation Suffix */ +#define __OP "e" /* Operand Prefix */ +#define __FIXUP_ALIGN ".align 4" +#define __FIXUP_WORD ".long" + +#define EXPORT_SYMBOL(var) + +#endif /* __CONFIG_H__ */ diff -r 419625d61514 -r de5826b5b302 sboot/include/cpufeature.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/cpufeature.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,153 @@ +/* + * cpufeature.h + * + * Defines x86 CPU feature bits + */ + +#ifndef __ASM_I386_CPUFEATURE_H +#define __ASM_I386_CPUFEATURE_H + +//#include + +#define NCAPINTS 7 /* N 32-bit words worth of info */ + +/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ +#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */ +#define X86_FEATURE_VME (0*32+ 1) /* Virtual Mode Extensions */ +#define X86_FEATURE_DE (0*32+ 2) /* Debugging Extensions */ +#define X86_FEATURE_PSE (0*32+ 3) /* Page Size Extensions */ +#define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */ +#define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers, RDMSR, WRMSR */ +#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */ +#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Architecture */ +#define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */ +#define X86_FEATURE_APIC (0*32+ 9) /* Onboard APIC */ +#define X86_FEATURE_SEP (0*32+11) /* SYSENTER/SYSEXIT */ +#define X86_FEATURE_MTRR (0*32+12) /* Memory Type Range Registers */ +#define X86_FEATURE_PGE (0*32+13) /* Page Global Enable */ +#define X86_FEATURE_MCA (0*32+14) /* Machine Check Architecture */ +#define X86_FEATURE_CMOV (0*32+15) /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */ +#define X86_FEATURE_PAT (0*32+16) /* Page Attribute Table */ +#define X86_FEATURE_PSE36 (0*32+17) /* 36-bit PSEs */ +#define X86_FEATURE_PN (0*32+18) /* Processor serial number */ +#define X86_FEATURE_CLFLSH (0*32+19) /* Supports the CLFLUSH instruction */ +#define X86_FEATURE_DTES (0*32+21) /* Debug Trace Store */ +#define X86_FEATURE_ACPI (0*32+22) /* ACPI via MSR */ +#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */ +#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */ + /* of FPU context), and CR4.OSFXSR available */ +#define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */ +#define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */ +#define X86_FEATURE_SELFSNOOP (0*32+27) /* CPU self snoop */ +#define X86_FEATURE_HT (0*32+28) /* Hyper-Threading */ +#define X86_FEATURE_ACC (0*32+29) /* Automatic clock control */ +#define X86_FEATURE_IA64 (0*32+30) /* IA-64 processor */ + +/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ +/* Don't duplicate feature flags which are redundant with Intel! */ +#define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */ +#define X86_FEATURE_MP (1*32+19) /* MP Capable. */ +#define X86_FEATURE_NX (1*32+20) /* Execute Disable */ +#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ +#define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */ +#define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */ +#define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */ + +/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ +#define X86_FEATURE_RECOVERY (2*32+ 0) /* CPU in recovery mode */ +#define X86_FEATURE_LONGRUN (2*32+ 1) /* Longrun power control */ +#define X86_FEATURE_LRTI (2*32+ 3) /* LongRun table interface */ + +/* Other features, Linux-defined mapping, word 3 */ +/* This range is used for feature bits which conflict or are synthesized */ +#define X86_FEATURE_CXMMX (3*32+ 0) /* Cyrix MMX extensions */ +#define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */ +#define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */ +#define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */ +/* cpu types for specific tunings: */ +#define X86_FEATURE_K8 (3*32+ 4) /* Opteron, Athlon64 */ +#define X86_FEATURE_K7 (3*32+ 5) /* Athlon */ +#define X86_FEATURE_P3 (3*32+ 6) /* P3 */ +#define X86_FEATURE_P4 (3*32+ 7) /* P4 */ +#define X86_FEATURE_CONSTANT_TSC (3*32+ 8) /* TSC ticks at a constant rate */ + +/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ +#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */ +#define X86_FEATURE_MWAIT (4*32+ 3) /* Monitor/Mwait support */ +#define X86_FEATURE_DSCPL (4*32+ 4) /* CPL Qualified Debug Store */ +#define X86_FEATURE_VMXE (4*32+ 5) /* Virtual Machine Extensions */ +#define X86_FEATURE_SMXE (4*32+ 6) /* Safer Mode Extensions */ +#define X86_FEATURE_EST (4*32+ 7) /* Enhanced SpeedStep */ +#define X86_FEATURE_TM2 (4*32+ 8) /* Thermal Monitor 2 */ +#define X86_FEATURE_CID (4*32+10) /* Context ID */ +#define X86_FEATURE_CX16 (4*32+13) /* CMPXCHG16B */ +#define X86_FEATURE_XTPR (4*32+14) /* Send Task Priority Messages */ + +/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */ +#define X86_FEATURE_XSTORE (5*32+ 2) /* on-CPU RNG present (xstore insn) */ +#define X86_FEATURE_XSTORE_EN (5*32+ 3) /* on-CPU RNG enabled */ +#define X86_FEATURE_XCRYPT (5*32+ 6) /* on-CPU crypto (xcrypt insn) */ +#define X86_FEATURE_XCRYPT_EN (5*32+ 7) /* on-CPU crypto enabled */ + +/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ +#define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */ +#define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */ +#define X86_FEATURE_SVME (6*32+ 2) /* Secure Virtual Machine */ + +#define cpu_has(c, bit) test_bit(bit, (c)->x86_capability) +#define boot_cpu_has(bit) test_bit(bit, boot_cpu_data.x86_capability) + +#ifdef __i386__ +#define cpu_has_vme boot_cpu_has(X86_FEATURE_VME) +#define cpu_has_de boot_cpu_has(X86_FEATURE_DE) +#define cpu_has_pse boot_cpu_has(X86_FEATURE_PSE) +#define cpu_has_tsc boot_cpu_has(X86_FEATURE_TSC) +#define cpu_has_pae boot_cpu_has(X86_FEATURE_PAE) +#define cpu_has_pge boot_cpu_has(X86_FEATURE_PGE) +#define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) +#define cpu_has_sep boot_cpu_has(X86_FEATURE_SEP) +#define cpu_has_mtrr boot_cpu_has(X86_FEATURE_MTRR) +#define cpu_has_mmx boot_cpu_has(X86_FEATURE_MMX) +#define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) +#define cpu_has_xmm boot_cpu_has(X86_FEATURE_XMM) +#define cpu_has_xmm2 boot_cpu_has(X86_FEATURE_XMM2) +#define cpu_has_xmm3 boot_cpu_has(X86_FEATURE_XMM3) +#define cpu_has_ht boot_cpu_has(X86_FEATURE_HT) +#define cpu_has_mp boot_cpu_has(X86_FEATURE_MP) +#define cpu_has_nx boot_cpu_has(X86_FEATURE_NX) +#define cpu_has_k6_mtrr boot_cpu_has(X86_FEATURE_K6_MTRR) +#define cpu_has_cyrix_arr boot_cpu_has(X86_FEATURE_CYRIX_ARR) +#define cpu_has_centaur_mcr boot_cpu_has(X86_FEATURE_CENTAUR_MCR) +#define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLSH) +#else /* __x86_64__ */ +#define cpu_has_vme 0 +#define cpu_has_de 1 +#define cpu_has_pse 1 +#define cpu_has_tsc 1 +#define cpu_has_pae 1 +#define cpu_has_pge 1 +#define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) +#define cpu_has_sep 0 +#define cpu_has_mtrr 1 +#define cpu_has_mmx 1 +#define cpu_has_fxsr 1 +#define cpu_has_xmm 1 +#define cpu_has_xmm2 1 +#define cpu_has_xmm3 boot_cpu_has(X86_FEATURE_XMM3) +#define cpu_has_ht boot_cpu_has(X86_FEATURE_HT) +#define cpu_has_mp 1 +#define cpu_has_nx boot_cpu_has(X86_FEATURE_NX) +#define cpu_has_k6_mtrr 0 +#define cpu_has_cyrix_arr 0 +#define cpu_has_centaur_mcr 0 +#define cpu_has_clflush boot_cpu_has(X86_FEATURE_CLFLSH) +#endif + +#endif /* __ASM_I386_CPUFEATURE_H */ + +/* + * Local Variables: + * mode:c + * comment-column:42 + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/include/ctype.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/ctype.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,54 @@ +#ifndef _LINUX_CTYPE_H +#define _LINUX_CTYPE_H + +/* + * NOTE! This ctype does not handle EOF like the standard C + * library is required to. + */ + +#define _U 0x01 /* upper */ +#define _L 0x02 /* lower */ +#define _D 0x04 /* digit */ +#define _C 0x08 /* cntrl */ +#define _P 0x10 /* punct */ +#define _S 0x20 /* white space (space/lf/tab) */ +#define _X 0x40 /* hex digit */ +#define _SP 0x80 /* hard space (0x20) */ + +extern unsigned char _ctype[]; + +#define __ismask(x) (_ctype[(int)(unsigned char)(x)]) + +#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) +#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) +#define iscntrl(c) ((__ismask(c)&(_C)) != 0) +#define isdigit(c) ((__ismask(c)&(_D)) != 0) +#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0) +#define islower(c) ((__ismask(c)&(_L)) != 0) +#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0) +#define ispunct(c) ((__ismask(c)&(_P)) != 0) +#define isspace(c) ((__ismask(c)&(_S)) != 0) +#define isupper(c) ((__ismask(c)&(_U)) != 0) +#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) + +#define isascii(c) (((unsigned char)(c))<=0x7f) +#define toascii(c) (((unsigned char)(c))&0x7f) + +static inline unsigned char __tolower(unsigned char c) +{ + if (isupper(c)) + c -= 'A'-'a'; + return c; +} + +static inline unsigned char __toupper(unsigned char c) +{ + if (islower(c)) + c -= 'a'-'A'; + return c; +} + +#define tolower(c) __tolower(c) +#define toupper(c) __toupper(c) + +#endif diff -r 419625d61514 -r de5826b5b302 sboot/include/div64.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/div64.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,46 @@ +#ifndef __I386_DIV64 +#define __I386_DIV64 + +#include + +#if BITS_PER_LONG == 64 + +# define do_div(n,base) ({ \ + uint32_t __base = (base); \ + uint32_t __rem; \ + __rem = ((uint64_t)(n)) % __base; \ + (n) = ((uint64_t)(n)) / __base; \ + __rem; \ + }) + +#else + +/* + * do_div() is NOT a C function. It wants to return + * two values (the quotient and the remainder), but + * since that doesn't work very well in C, what it + * does is: + * + * - modifies the 64-bit dividend _in_place_ + * - returns the 32-bit remainder + * + * This ends up being the most efficient "calling + * convention" on x86. + */ +#define do_div(n,base) ({ \ + unsigned long __upper, __low, __high, __mod, __base; \ + __base = (base); \ + asm("":"=a" (__low), "=d" (__high):"A" (n)); \ + __upper = __high; \ + if (__high) { \ + __upper = __high % (__base); \ + __high = __high / (__base); \ + } \ + asm("divl %2":"=a" (__low), "=d" (__mod):"rm" (__base), "0" (__low), "1" (__upper)); \ + asm("":"=A" (n):"a" (__low),"d" (__high)); \ + __mod; \ +}) + +#endif + +#endif diff -r 419625d61514 -r de5826b5b302 sboot/include/e820.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/e820.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,61 @@ +/* + * e820.h: support functions for manipulating the e820 table + * + * 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 __E820_H__ +#define __E820_H__ + +#define E820_PROTECTED 30 /* memory only available to kernel */ +#define E820_MLE_SHARED 40 /* shared page between MLE and kernel */ + +#ifndef __XEN__ +extern bool copy_e820_map(multiboot_info_t *mbi); +extern bool e820_protect_region(uint64_t addr, uint64_t size, uint32_t type); +extern void print_e820_map(void); +extern void replace_e820_map(multiboot_info_t *mbi); +extern uint64_t get_max_ram(multiboot_info_t *mbi); +#endif /* __XEN__ */ + +#endif /* __E820_H__ */ + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/include/elf.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/elf.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,151 @@ +/* + * elf.h: support functions for manipulating ELF binaries + * + * 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 __ELF_H__ +#define __ELF_H__ + +#include +#include + +/* Elf header */ +typedef struct { + unsigned char e_ident[16]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint32_t e_entry; + uint32_t e_phoff; + uint32_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsz; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +} elf_header_t; + +/* e_ident[] Identification Indexes */ +#define EI_MAG0 0 /* File identification */ +#define EI_MAG1 1 /* File identification */ +#define EI_MAG2 2 /* File identification */ +#define EI_MAG3 3 /* File identification */ +#define EI_CLASS 4 /* File class */ +#define EI_DATA 5 /* Data encoding */ +#define EI_VERSION 6 /* File version */ +#define EI_PAD 7 /* Start of padding bytes */ +#define EI_NIDENT 8 /* Size of e_ident[] */ + +/* Magic number */ +#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */ +#define ELFMAG1 'E' /* e_ident[EI_MAG1] */ +#define ELFMAG2 'L' /* e_ident[EI_MAG2] */ +#define ELFMAG3 'F' /* e_ident[EI_MAG3] */ + +/* e_ident[EI_CLASS] */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ + +/* e_ident[EI_DATA] */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* Least significant byte */ +#define ELFDATA2MSB 2 /* Most significant byte */ + +/* e_type */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_LOPROC 0xff00 /* Processor-specific */ +#define ET_HIPROC 0xffff /* Processor-specific */ + +/* e_machine */ +#define ET_NONE 0 /* No machine */ +#define EM_M32 1 /* At&t We 32100 */ +#define EM_SPARC 2 /* SPARC */ +#define EM_386 3 /* Intel architecture */ +#define EM_68K 4 /* Motorola 68000 */ +#define EM_88K 5 /* Motorola 88000 */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS RS3000 Big-Endian */ +#define EM_MIPS_RS4_BE 10 /* MIPS RS4000 Big-Endian */ + +/* e_version */ +#define EV_NONE 0 /* Invalid version */ +#define EV_CURRENT 1 /* Current version */ + +/* Program header */ +typedef struct { + uint32_t p_type; + uint32_t p_offset; + uint32_t p_vaddr; + uint32_t p_paddr; + uint32_t p_filesz; + uint32_t p_memsz; + uint32_t p_flags; + uint32_t p_align; +} elf_program_header_t; + +/* p_type */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +/* multiboot magic */ +#define MB_MAGIC 0x2badb002 + +int launch_xen(multiboot_info_t *mbi, void **kernel_entry_point); + +#endif /* __ELF_H__ */ + + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/include/misc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/misc.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,69 @@ +#ifndef __MISC_H__ +#define __MISC_H__ + +/* + * from system.h + */ + +#define wbinvd() \ + __asm__ __volatile__ ("wbinvd": : :"memory"); + +#define __save_flags(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */) +#define __restore_flags(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc") +#define __cli() __asm__ __volatile__("cli": : :"memory") + +/* + * from x86/bitops.h + */ + +/** + * fls - find last bit set + * @x: the word to search + * + * This is defined the same way as ffs. + */ +static inline int fls(unsigned long x) +{ + long r; + + __asm__("bsr %1,%0\n\t" + "jnz 1f\n\t" + "mov $-1,%0\n" + "1:" : "=r" (r) : "rm" (x)); + return (int)r+1; +} + +/* + * from lib.h + */ +#include + +#define BUG() /**/ +#define BUG_ON(_p) do { if (_p) BUG(); } while ( 0 ) + +/* vsprintf.c */ +extern int sprintf(char * buf, const char * fmt, ...) + __attribute__ ((format (printf, 2, 3))); +extern int vsprintf(char *buf, const char *, va_list) + __attribute__ ((format (printf, 2, 0))); +extern int snprintf(char * buf, size_t size, const char * fmt, ...) + __attribute__ ((format (printf, 3, 4))); +extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args) + __attribute__ ((format (printf, 3, 0))); +extern int scnprintf(char * buf, size_t size, const char * fmt, ...) + __attribute__ ((format (printf, 3, 4))); +extern int vscnprintf(char *buf, size_t size, const char *fmt, va_list args) + __attribute__ ((format (printf, 3, 0))); + +#endif /* __MISC_H__ */ + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/include/msr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/msr.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,339 @@ +#ifndef __ASM_MSR_H +#define __ASM_MSR_H + +#ifndef __ASSEMBLY__ + +#define rdmsr(msr,val1,val2) \ + __asm__ __volatile__("rdmsr" \ + : "=a" (val1), "=d" (val2) \ + : "c" (msr)) + +#define rdmsrl(msr,val) do { unsigned long a__,b__; \ + __asm__ __volatile__("rdmsr" \ + : "=a" (a__), "=d" (b__) \ + : "c" (msr)); \ + val = a__ | ((u64)b__<<32); \ +} while(0); + +#define wrmsr(msr,val1,val2) \ + __asm__ __volatile__("wrmsr" \ + : /* no outputs */ \ + : "c" (msr), "a" (val1), "d" (val2)) + +static inline void wrmsrl(unsigned int msr, __u64 val) +{ + __u32 lo, hi; + lo = (__u32)val; + hi = (__u32)(val >> 32); + wrmsr(msr, lo, hi); +} + +/* rdmsr with exception handling */ +#define rdmsr_safe(msr,val1,val2) ({\ + int _rc; \ + __asm__ __volatile__( \ + "1: rdmsr\n2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: movl %5,%2\n; jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " "__FIXUP_ALIGN"\n" \ + " "__FIXUP_WORD" 1b,3b\n" \ + ".previous\n" \ + : "=a" (val1), "=d" (val2), "=&r" (_rc) \ + : "c" (msr), "2" (0), "i" (-EFAULT)); \ + _rc; }) + +/* wrmsr with exception handling */ +#define wrmsr_safe(msr,val1,val2) ({\ + int _rc; \ + __asm__ __volatile__( \ + "1: wrmsr\n2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: movl %5,%0\n; jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " "__FIXUP_ALIGN"\n" \ + " "__FIXUP_WORD" 1b,3b\n" \ + ".previous\n" \ + : "=&r" (_rc) \ + : "c" (msr), "a" (val1), "d" (val2), "0" (0), "i" (-EFAULT)); \ + _rc; }) + +#define rdtsc(low,high) \ + __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) + +#define rdtscl(low) \ + __asm__ __volatile__("rdtsc" : "=a" (low) : : "edx") + +#define rdtscll(val) \ + __asm__ __volatile__("rdtsc" : "=A" (val)) + +#define write_tsc(val1,val2) wrmsr(0x10, val1, val2) + +#define rdpmc(counter,low,high) \ + __asm__ __volatile__("rdpmc" \ + : "=a" (low), "=d" (high) \ + : "c" (counter)) + +#endif /* !__ASSEMBLY__ */ + +/* symbolic names for some interesting MSRs */ +/* Intel defined MSRs. */ +#define MSR_IA32_P5_MC_ADDR 0 +#define MSR_IA32_P5_MC_TYPE 1 +#define MSR_IA32_TIME_STAMP_COUNTER 0x10 +#define MSR_IA32_PLATFORM_ID 0x17 +#define MSR_IA32_EBL_CR_POWERON 0x2a + +#define MSR_IA32_APICBASE 0x1b +#define MSR_IA32_APICBASE_BSP (1<<8) +#define MSR_IA32_APICBASE_ENABLE (1<<11) +#define MSR_IA32_APICBASE_BASE (0xfffff<<12) + +#define MSR_IA32_UCODE_WRITE 0x79 +#define MSR_IA32_UCODE_REV 0x8b + +#define MSR_P6_PERFCTR0 0xc1 +#define MSR_P6_PERFCTR1 0xc2 + +/* MSRs & bits used for VMX enabling */ +#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_VMX_MISC_MSR 0x485 +#define MSR_IA32_VMX_CR0_FIXED0 0x486 +#define MSR_IA32_VMX_CR0_FIXED1 0x487 +#define MSR_IA32_VMX_CR4_FIXED0 0x488 +#define MSR_IA32_VMX_CR4_FIXED1 0x489 +#define IA32_FEATURE_CONTROL_MSR 0x3a +#define IA32_FEATURE_CONTROL_MSR_LOCK 0x1 +#define IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_IN_SMX 0x2 +#define IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_OUT_SMX 0x4 +#define IA32_FEATURE_CONTROL_MSR_SENTER_PARAM_CTL 0x7f00 +#define IA32_FEATURE_CONTROL_MSR_ENABLE_SENTER 0x8000 + +/* AMD/K8 specific MSRs */ +#define MSR_EFER 0xc0000080 /* extended feature register */ +#define MSR_STAR 0xc0000081 /* legacy mode SYSCALL target */ +#define MSR_LSTAR 0xc0000082 /* long mode SYSCALL target */ +#define MSR_CSTAR 0xc0000083 /* compatibility mode SYSCALL target */ +#define MSR_SYSCALL_MASK 0xc0000084 /* EFLAGS mask for syscall */ +#define MSR_FS_BASE 0xc0000100 /* 64bit GS base */ +#define MSR_GS_BASE 0xc0000101 /* 64bit FS base */ +#define MSR_SHADOW_GS_BASE 0xc0000102 /* SwapGS GS shadow */ +/* EFER bits: */ +#define _EFER_SCE 0 /* SYSCALL/SYSRET */ +#define _EFER_LME 8 /* Long mode enable */ +#define _EFER_LMA 10 /* Long mode active (read-only) */ +#define _EFER_NX 11 /* No execute enable */ +#define _EFER_SVME 12 + +#define EFER_SCE (1<<_EFER_SCE) +#define EFER_LME (1<<_EFER_LME) +#define EFER_LMA (1<<_EFER_LMA) +#define EFER_NX (1<<_EFER_NX) +#define EFER_SVME (1<<_EFER_SVME) + +/* Intel MSRs. Some also available on other CPUs */ +#define MSR_IA32_PLATFORM_ID 0x17 + +#define MSR_MTRRcap 0x0fe +#define MSR_IA32_MTRRCAP MSR_MTRRcap +#define MSR_IA32_MTRR_DEF_TYPE 0x2ff +#define MSR_IA32_BBL_CR_CTL 0x119 + +#define MSR_IA32_SYSENTER_CS 0x174 +#define MSR_IA32_SYSENTER_ESP 0x175 +#define MSR_IA32_SYSENTER_EIP 0x176 + +#define MSR_IA32_MCG_CAP 0x179 +#define MSR_IA32_MCG_STATUS 0x17a +#define MSR_IA32_MCG_CTL 0x17b + +/* P4/Xeon+ specific */ +#define MSR_IA32_MCG_EAX 0x180 +#define MSR_IA32_MCG_EBX 0x181 +#define MSR_IA32_MCG_ECX 0x182 +#define MSR_IA32_MCG_EDX 0x183 +#define MSR_IA32_MCG_ESI 0x184 +#define MSR_IA32_MCG_EDI 0x185 +#define MSR_IA32_MCG_EBP 0x186 +#define MSR_IA32_MCG_ESP 0x187 +#define MSR_IA32_MCG_EFLAGS 0x188 +#define MSR_IA32_MCG_EIP 0x189 +#define MSR_IA32_MCG_RESERVED 0x18A + +#define MSR_P6_EVNTSEL0 0x186 +#define MSR_P6_EVNTSEL1 0x187 + +#define MSR_IA32_PERF_STATUS 0x198 +#define MSR_IA32_PERF_CTL 0x199 + +#define MSR_IA32_THERM_CONTROL 0x19a +#define MSR_IA32_THERM_INTERRUPT 0x19b +#define MSR_IA32_THERM_STATUS 0x19c +#define MSR_IA32_MISC_ENABLE 0x1a0 + +#define MSR_IA32_MISC_ENABLE_PERF_AVAIL (1<<7) +#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL (1<<11) +#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL (1<<12) + +#define MSR_IA32_DEBUGCTLMSR 0x1d9 +#define MSR_IA32_LASTBRANCHFROMIP 0x1db +#define MSR_IA32_LASTBRANCHTOIP 0x1dc +#define MSR_IA32_LASTINTFROMIP 0x1dd +#define MSR_IA32_LASTINTTOIP 0x1de + +#define MSR_IA32_MC0_CTL 0x400 +#define MSR_IA32_MC0_STATUS 0x401 +#define MSR_IA32_MC0_ADDR 0x402 +#define MSR_IA32_MC0_MISC 0x403 + +/* Pentium IV performance counter MSRs */ +#define MSR_P4_BPU_PERFCTR0 0x300 +#define MSR_P4_BPU_PERFCTR1 0x301 +#define MSR_P4_BPU_PERFCTR2 0x302 +#define MSR_P4_BPU_PERFCTR3 0x303 +#define MSR_P4_MS_PERFCTR0 0x304 +#define MSR_P4_MS_PERFCTR1 0x305 +#define MSR_P4_MS_PERFCTR2 0x306 +#define MSR_P4_MS_PERFCTR3 0x307 +#define MSR_P4_FLAME_PERFCTR0 0x308 +#define MSR_P4_FLAME_PERFCTR1 0x309 +#define MSR_P4_FLAME_PERFCTR2 0x30a +#define MSR_P4_FLAME_PERFCTR3 0x30b +#define MSR_P4_IQ_PERFCTR0 0x30c +#define MSR_P4_IQ_PERFCTR1 0x30d +#define MSR_P4_IQ_PERFCTR2 0x30e +#define MSR_P4_IQ_PERFCTR3 0x30f +#define MSR_P4_IQ_PERFCTR4 0x310 +#define MSR_P4_IQ_PERFCTR5 0x311 +#define MSR_P4_BPU_CCCR0 0x360 +#define MSR_P4_BPU_CCCR1 0x361 +#define MSR_P4_BPU_CCCR2 0x362 +#define MSR_P4_BPU_CCCR3 0x363 +#define MSR_P4_MS_CCCR0 0x364 +#define MSR_P4_MS_CCCR1 0x365 +#define MSR_P4_MS_CCCR2 0x366 +#define MSR_P4_MS_CCCR3 0x367 +#define MSR_P4_FLAME_CCCR0 0x368 +#define MSR_P4_FLAME_CCCR1 0x369 +#define MSR_P4_FLAME_CCCR2 0x36a +#define MSR_P4_FLAME_CCCR3 0x36b +#define MSR_P4_IQ_CCCR0 0x36c +#define MSR_P4_IQ_CCCR1 0x36d +#define MSR_P4_IQ_CCCR2 0x36e +#define MSR_P4_IQ_CCCR3 0x36f +#define MSR_P4_IQ_CCCR4 0x370 +#define MSR_P4_IQ_CCCR5 0x371 +#define MSR_P4_ALF_ESCR0 0x3ca +#define MSR_P4_ALF_ESCR1 0x3cb +#define MSR_P4_BPU_ESCR0 0x3b2 +#define MSR_P4_BPU_ESCR1 0x3b3 +#define MSR_P4_BSU_ESCR0 0x3a0 +#define MSR_P4_BSU_ESCR1 0x3a1 +#define MSR_P4_CRU_ESCR0 0x3b8 +#define MSR_P4_CRU_ESCR1 0x3b9 +#define MSR_P4_CRU_ESCR2 0x3cc +#define MSR_P4_CRU_ESCR3 0x3cd +#define MSR_P4_CRU_ESCR4 0x3e0 +#define MSR_P4_CRU_ESCR5 0x3e1 +#define MSR_P4_DAC_ESCR0 0x3a8 +#define MSR_P4_DAC_ESCR1 0x3a9 +#define MSR_P4_FIRM_ESCR0 0x3a4 +#define MSR_P4_FIRM_ESCR1 0x3a5 +#define MSR_P4_FLAME_ESCR0 0x3a6 +#define MSR_P4_FLAME_ESCR1 0x3a7 +#define MSR_P4_FSB_ESCR0 0x3a2 +#define MSR_P4_FSB_ESCR1 0x3a3 +#define MSR_P4_IQ_ESCR0 0x3ba +#define MSR_P4_IQ_ESCR1 0x3bb +#define MSR_P4_IS_ESCR0 0x3b4 +#define MSR_P4_IS_ESCR1 0x3b5 +#define MSR_P4_ITLB_ESCR0 0x3b6 +#define MSR_P4_ITLB_ESCR1 0x3b7 +#define MSR_P4_IX_ESCR0 0x3c8 +#define MSR_P4_IX_ESCR1 0x3c9 +#define MSR_P4_MOB_ESCR0 0x3aa +#define MSR_P4_MOB_ESCR1 0x3ab +#define MSR_P4_MS_ESCR0 0x3c0 +#define MSR_P4_MS_ESCR1 0x3c1 +#define MSR_P4_PMH_ESCR0 0x3ac +#define MSR_P4_PMH_ESCR1 0x3ad +#define MSR_P4_RAT_ESCR0 0x3bc +#define MSR_P4_RAT_ESCR1 0x3bd +#define MSR_P4_SAAT_ESCR0 0x3ae +#define MSR_P4_SAAT_ESCR1 0x3af +#define MSR_P4_SSU_ESCR0 0x3be +#define MSR_P4_SSU_ESCR1 0x3bf /* guess: not defined in manual */ +#define MSR_P4_TBPU_ESCR0 0x3c2 +#define MSR_P4_TBPU_ESCR1 0x3c3 +#define MSR_P4_TC_ESCR0 0x3c4 +#define MSR_P4_TC_ESCR1 0x3c5 +#define MSR_P4_U2L_ESCR0 0x3b0 +#define MSR_P4_U2L_ESCR1 0x3b1 + +#define MSR_K6_EFER 0xC0000080 +#define MSR_K6_STAR 0xC0000081 +#define MSR_K6_WHCR 0xC0000082 +#define MSR_K6_UWCCR 0xC0000085 +#define MSR_K6_EPMR 0xC0000086 +#define MSR_K6_PSOR 0xC0000087 +#define MSR_K6_PFIR 0xC0000088 + +#define MSR_K7_EVNTSEL0 0xC0010000 +#define MSR_K7_EVNTSEL1 0xC0010001 +#define MSR_K7_EVNTSEL2 0xC0010002 +#define MSR_K7_EVNTSEL3 0xC0010003 +#define MSR_K7_PERFCTR0 0xC0010004 +#define MSR_K7_PERFCTR1 0xC0010005 +#define MSR_K7_PERFCTR2 0xC0010006 +#define MSR_K7_PERFCTR3 0xC0010007 +#define MSR_K7_HWCR 0xC0010015 +#define MSR_K7_CLK_CTL 0xC001001b +#define MSR_K7_FID_VID_CTL 0xC0010041 +#define MSR_K7_FID_VID_STATUS 0xC0010042 + +#define MSR_K8_TOP_MEM1 0xC001001A +#define MSR_K8_TOP_MEM2 0xC001001D +#define MSR_K8_SYSCFG 0xC0010010 +#define MSR_K8_HWCR 0xC0010015 +#define MSR_K8_VM_CR 0xC0010114 +#define MSR_K8_VM_HSAVE_PA 0xC0010117 + +/* MSR_K8_VM_CR bits: */ +#define _K8_VMCR_SVME_DISABLE 4 +#define K8_VMCR_SVME_DISABLE (1 << _K8_VMCR_SVME_DISABLE) + +/* Centaur-Hauls/IDT defined MSRs. */ +#define MSR_IDT_FCR1 0x107 +#define MSR_IDT_FCR2 0x108 +#define MSR_IDT_FCR3 0x109 +#define MSR_IDT_FCR4 0x10a + +#define MSR_IDT_MCR0 0x110 +#define MSR_IDT_MCR1 0x111 +#define MSR_IDT_MCR2 0x112 +#define MSR_IDT_MCR3 0x113 +#define MSR_IDT_MCR4 0x114 +#define MSR_IDT_MCR5 0x115 +#define MSR_IDT_MCR6 0x116 +#define MSR_IDT_MCR7 0x117 +#define MSR_IDT_MCR_CTRL 0x120 + +/* VIA Cyrix defined MSRs*/ +#define MSR_VIA_FCR 0x1107 +#define MSR_VIA_LONGHAUL 0x110a +#define MSR_VIA_RNG 0x110b +#define MSR_VIA_BCR2 0x1147 + +/* Transmeta defined MSRs */ +#define MSR_TMTA_LONGRUN_CTRL 0x80868010 +#define MSR_TMTA_LONGRUN_FLAGS 0x80868011 +#define MSR_TMTA_LRTI_READOUT 0x80868018 +#define MSR_TMTA_LRTI_VOLT_MHZ 0x8086801a + +#endif /* __ASM_MSR_H */ diff -r 419625d61514 -r de5826b5b302 sboot/include/mtrr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/mtrr.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,14 @@ +#ifndef __ASM_X86_MTRR_H__ +#define __ASM_X86_MTRR_H__ + +#include + +/* These are the region types. They match the architectural specification. */ +#define MTRR_TYPE_UNCACHABLE 0 +#define MTRR_TYPE_WRCOMB 1 +#define MTRR_TYPE_WRTHROUGH 4 +#define MTRR_TYPE_WRPROT 5 +#define MTRR_TYPE_WRBACK 6 +#define MTRR_NUM_TYPES 7 + +#endif /* __ASM_X86_MTRR_H__ */ diff -r 419625d61514 -r de5826b5b302 sboot/include/multiboot.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/multiboot.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,112 @@ +/* multiboot.h - the header for Multiboot */ +/* Copyright (C) 1999, 2001 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef __MULTIBOOT_H__ +#define __MULTIBOOT_H__ + + +/* + * Multiboot header structure. + */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 +#define MULTIBOOT_HEADER_MODS_ALIGNED 0x00000001 +#define MULTIBOOT_HEADER_WANT_MEMORY 0x00000002 +#define MULTIBOOT_HEADER_HAS_VBE 0x00000004 +#define MULTIBOOT_HEADER_HAS_ADDR 0x00010000 + +/* The magic number passed by a Multiboot-compliant boot loader. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +#define MBI_MEMLIMITS (1<<0) +#define MBI_DRIVES (1<<1) +#define MBI_CMDLINE (1<<2) +#define MBI_MODULES (1<<3) +#define MBI_AOUT_SYMS (1<<4) +#define MBI_ELF_SYMS (1<<5) +#define MBI_MEMMAP (1<<6) +#define MBI_LOADERNAME (1<<9) + +#ifndef __ASSEMBLY__ + +/* The symbol table for a.out. */ +typedef struct { + u32 tabsize; + u32 strsize; + u32 addr; + u32 reserved; +} aout_symbol_table_t; + +/* The section header table for ELF. */ +typedef struct { + u32 num; + u32 size; + u32 addr; + u32 shndx; +} elf_section_header_table_t; + +/* The Multiboot information. */ +typedef struct { + u32 flags; + + /* Valid if flags sets MBI_MEMLIMITS */ + u32 mem_lower; + u32 mem_upper; + + /* Valid if flags sets MBI_DRIVES */ + u32 boot_device; + + /* Valid if flags sets MBI_CMDLINE */ + u32 cmdline; + + /* Valid if flags sets MBI_MODULES */ + u32 mods_count; + u32 mods_addr; + + /* Valid if flags sets ... */ + union { + aout_symbol_table_t aout_sym; /* ... MBI_AOUT_SYMS */ + elf_section_header_table_t elf_sec; /* ... MBI_ELF_SYMS */ + } u; + + /* Valid if flags sets MBI_MEMMAP */ + u32 mmap_length; + u32 mmap_addr; +} multiboot_info_t; + +/* The module structure. */ +typedef struct { + u32 mod_start; + u32 mod_end; + u32 string; + u32 reserved; +} module_t; + +/* The memory map. Be careful that the offset 0 is base_addr_low + but no size. */ +typedef struct { + u32 size; + u32 base_addr_low; + u32 base_addr_high; + u32 length_low; + u32 length_high; + u32 type; +} memory_map_t; + + +#endif /* __ASSEMBLY__ */ + +#endif /* __MULTIBOOT_H__ */ diff -r 419625d61514 -r de5826b5b302 sboot/include/page.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/page.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,33 @@ + +#ifndef __X86_PAGE_H__ +#define __X86_PAGE_H__ + +/* + * It is important that the masks are signed quantities. This ensures that + * the compiler sign-extends a 32-bit mask to 64 bits if that is required. + */ +#define PAGE_SHIFT 12 + +#ifndef __ASSEMBLY__ +#define PAGE_SIZE (1L << PAGE_SHIFT) +#else +#define PAGE_SIZE (1 << PAGE_SHIFT) +#endif +#define PAGE_MASK (~(PAGE_SIZE-1)) +#define PAGE_FLAG_MASK (~0) + + +#define L1_PAGETABLE_SHIFT 12 +#define L2_PAGETABLE_SHIFT 22 + +#endif /* __X86_PAGE_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/include/printk.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/printk.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,14 @@ +#ifndef __PRINTK_H__ +#define __PRINTK_H__ + +#ifdef DEBUG +#define printk early_serial_printk +#else +#define printk /**/ +#endif + +extern void early_serial_printk(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + + +#endif diff -r 419625d61514 -r de5826b5b302 sboot/include/processor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/processor.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,322 @@ + +/* Portions are: Copyright (c) 1994 Linus Torvalds */ + +#ifndef __ASM_X86_PROCESSOR_H +#define __ASM_X86_PROCESSOR_H + +/* + * CPU vendor IDs + */ +#define X86_VENDOR_INTEL 0 +#define X86_VENDOR_CYRIX 1 +#define X86_VENDOR_AMD 2 +#define X86_VENDOR_UMC 3 +#define X86_VENDOR_NEXGEN 4 +#define X86_VENDOR_CENTAUR 5 +#define X86_VENDOR_RISE 6 +#define X86_VENDOR_TRANSMETA 7 +#define X86_VENDOR_NSC 8 +#define X86_VENDOR_NUM 9 +#define X86_VENDOR_UNKNOWN 0xff + +/* + * 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 */ + +/* + * Intel CPU flags in CR0 + */ +#define X86_CR0_PE 0x00000001 /* Enable Protected Mode (RW) */ +#define X86_CR0_MP 0x00000002 /* Monitor Coprocessor (RW) */ +#define X86_CR0_EM 0x00000004 /* Require FPU Emulation (RO) */ +#define X86_CR0_TS 0x00000008 /* Task Switched (RW) */ +#define X86_CR0_ET 0x00000010 /* Extension type (RO) */ +#define X86_CR0_NE 0x00000020 /* Numeric Error Reporting (RW) */ +#define X86_CR0_WP 0x00010000 /* Supervisor Write Protect (RW) */ +#define X86_CR0_AM 0x00040000 /* Alignment Checking (RW) */ +#define X86_CR0_NW 0x20000000 /* Not Write-Through (RW) */ +#define X86_CR0_CD 0x40000000 /* Cache Disable (RW) */ +#define X86_CR0_PG 0x80000000 /* Paging (RW) */ + +/* + * Intel CPU features in CR4 + */ +#define X86_CR4_VME 0x0001 /* enable vm86 extensions */ +#define X86_CR4_PVI 0x0002 /* virtual interrupts flag enable */ +#define X86_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */ +#define X86_CR4_DE 0x0008 /* enable debugging extensions */ +#define X86_CR4_PSE 0x0010 /* enable page size extensions */ +#define X86_CR4_PAE 0x0020 /* enable physical address extensions */ +#define X86_CR4_MCE 0x0040 /* Machine check enable */ +#define X86_CR4_PGE 0x0080 /* enable global pages */ +#define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */ +#define X86_CR4_OSFXSR 0x0200 /* enable fast FPU save and restore */ +#define X86_CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */ +#define X86_CR4_VMXE 0x2000 /* enable VMX */ +#define X86_CR4_SMXE 0x4000 /* enable SMX */ + +/* + * Trap/fault mnemonics. + */ +#define TRAP_divide_error 0 +#define TRAP_debug 1 +#define TRAP_nmi 2 +#define TRAP_int3 3 +#define TRAP_overflow 4 +#define TRAP_bounds 5 +#define TRAP_invalid_op 6 +#define TRAP_no_device 7 +#define TRAP_double_fault 8 +#define TRAP_copro_seg 9 +#define TRAP_invalid_tss 10 +#define TRAP_no_segment 11 +#define TRAP_stack_error 12 +#define TRAP_gp_fault 13 +#define TRAP_page_fault 14 +#define TRAP_spurious_int 15 +#define TRAP_copro_error 16 +#define TRAP_alignment_check 17 +#define TRAP_machine_check 18 +#define TRAP_simd_error 19 +#define TRAP_deferred_nmi 31 + +/* Set for entry via SYSCALL. Informs return code to use SYSRETQ not IRETQ. */ +/* NB. Same as VGCF_in_syscall. No bits in common with any other TRAP_ defn. */ +#define TRAP_syscall 256 + +/* + * Non-fatal fault/trap handlers return an error code to the caller. If the + * code is non-zero, it means that either the exception was not due to a fault + * (i.e., it was a trap) or that the fault has been fixed up so the instruction + * replay ought to succeed. + */ +#define EXCRET_not_a_fault 1 /* It was a trap. No instruction replay needed. */ +#define EXCRET_fault_fixed 1 /* It was fault that we fixed: try a replay. */ + +/* 'trap_bounce' flags values */ +#define TBF_EXCEPTION 1 +#define TBF_EXCEPTION_ERRCODE 2 +#define TBF_INTERRUPT 8 +#define TBF_FAILSAFE 16 + +/* 'arch_vcpu' flags values */ +#define _TF_kernel_mode 0 +#define TF_kernel_mode (1<<_TF_kernel_mode) + +/* #PF error code values. */ +#define PFEC_page_present (1U<<0) +#define PFEC_write_access (1U<<1) +#define PFEC_user_mode (1U<<2) +#define PFEC_reserved_bit (1U<<3) +#define PFEC_insn_fetch (1U<<4) + +/* + * Generic CPUID function + * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx + * resulting in stale register contents being returned. + */ +#define cpuid(_op,_eax,_ebx,_ecx,_edx) \ + __asm__ __volatile__ ("cpuid" \ + : "=a" (*(int *)(_eax)), \ + "=b" (*(int *)(_ebx)), \ + "=c" (*(int *)(_ecx)), \ + "=d" (*(int *)(_edx)) \ + : "0" (_op), "2" (0)) + +/* Some CPUID calls want 'count' to be placed in ecx */ +static inline void cpuid_count( + int op, + int count, + unsigned int *eax, + unsigned int *ebx, + unsigned int *ecx, + unsigned int *edx) +{ + __asm__ __volatile__ ("cpuid" + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) + : "0" (op), "c" (count)); +} + +/* + * CPUID functions returning a single datum + */ +static always_inline unsigned int cpuid_eax(unsigned int op) +{ + unsigned int eax; + + __asm__ __volatile__ ("cpuid" + : "=a" (eax) + : "0" (op) + : "bx", "cx", "dx"); + return eax; +} +static always_inline unsigned int cpuid_ebx(unsigned int op) +{ + unsigned int eax, ebx; + + __asm__ __volatile__ ("cpuid" + : "=a" (eax), "=b" (ebx) + : "0" (op) + : "cx", "dx" ); + return ebx; +} +static always_inline unsigned int cpuid_ecx(unsigned int op) +{ + unsigned int eax, ecx; + + __asm__ __volatile__ ("cpuid" + : "=a" (eax), "=c" (ecx) + : "0" (op) + : "bx", "dx" ); + return ecx; +} +static always_inline unsigned int cpuid_edx(unsigned int op) +{ + unsigned int eax, edx; + + __asm__ __volatile__ ("cpuid" + : "=a" (eax), "=d" (edx) + : "0" (op) + : "bx", "cx"); + return edx; +} + + + +static inline unsigned long read_cr0(void) +{ + unsigned long __cr0; + __asm__ __volatile__ ("mov %%cr0,%0\n\t" :"=r" (__cr0)); + return __cr0; +} + +static inline void write_cr0(unsigned long val) +{ + __asm__ __volatile__ ("mov %0,%%cr0": :"r" ((unsigned long)val)); +} + +static inline unsigned long read_cr2(void) +{ + unsigned long __cr2; + __asm__ __volatile__ ("mov %%cr2,%0\n\t" :"=r" (__cr2)); + return __cr2; +} + +static inline unsigned long read_cr4(void) +{ + unsigned long __cr4; + __asm__ __volatile__ ("mov %%cr4,%0\n\t" :"=r" (__cr4)); + return __cr4; +} + +static inline void write_cr4(unsigned long val) +{ + __asm__ __volatile__ ("mov %0,%%cr4": :"r" ((unsigned long)val)); +} + +/* Read pagetable base. */ +static inline unsigned long read_cr3(void) +{ + unsigned long cr3; + __asm__ __volatile__ ("mov %%cr3, %0" : "=r" (cr3) : ); + return cr3; +} + +static inline void write_cr3(unsigned long cr3) +{ + __asm__ __volatile__ ( "mov %0, %%cr3" : : "r" (cr3) : "memory" ); +} + +static always_inline void set_in_cr4 (unsigned long mask) +{ + unsigned long dummy; + __asm__ __volatile__ ( + "mov %%cr4,%0\n\t" + "or %1,%0\n\t" + "mov %0,%%cr4\n" + : "=&r" (dummy) : "irg" (mask) ); +} + +static always_inline void clear_in_cr4 (unsigned long mask) +{ + unsigned long dummy; + __asm__ __volatile__ ( + "mov %%cr4,%0\n\t" + "and %1,%0\n\t" + "mov %0,%%cr4\n" + : "=&r" (dummy) : "irg" (~mask) ); +} + +/* Clear and set 'TS' bit respectively */ +static inline void clts(void) +{ + __asm__ __volatile__ ("clts"); +} + +static inline void stts(void) +{ + write_cr0(X86_CR0_TS|read_cr0()); +} + + +/* Stop speculative execution */ +static inline void sync_core(void) +{ + int tmp; + __asm__ __volatile__ ("cpuid" : "=a" (tmp) : "0" (1) + : "ebx","ecx","edx","memory"); +} + +static always_inline void __monitor(const void *eax, unsigned long ecx, + unsigned long edx) +{ + /* "monitor %eax,%ecx,%edx;" */ + __asm__ __volatile__ ( + ".byte 0x0f,0x01,0xc8;" + : :"a" (eax), "c" (ecx), "d"(edx)); +} + +static always_inline void __mwait(unsigned long eax, unsigned long ecx) +{ + /* "mwait %eax,%ecx;" */ + __asm__ __volatile__ ( + ".byte 0x0f,0x01,0xc9;" + : :"a" (eax), "c" (ecx)); +} + +/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ +static always_inline void rep_nop(void) +{ + __asm__ __volatile__ ( "rep;nop" : : : "memory" ); +} + +#define cpu_relax() rep_nop() + +#endif /* __ASM_X86_PROCESSOR_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/include/sboot.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/sboot.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,210 @@ +/* + * sboot.h: shared data structure with MLE and kernel and functions + * used by kernel for runtime support + * + * 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 __SBOOT_H__ +#define __SBOOT_H__ + +/* + * used to communicate between sboot and the launched kernel (i.e. Xen) + */ +typedef struct { + uint32_t version; /* 0x01 */ + uint32_t ap_entry; /* (protected mode) entry point for APs */ +} mle_kernel_shared_t; + +/* + * these are only used in Xen + */ + +#ifdef __XEN__ +#include +#include +#include +#include +#include +#include + +extern mle_kernel_shared_t *g_mle_shared; + +static inline bool sboot_in_measured_env(void) +{ + return (g_mle_shared != NULL); +} + +static inline uint64_t sboot_read_priv_config_reg(uint32_t reg) +{ + /* these are MMIO so make sure compiler doesn't optimize */ + return *(volatile uint64_t *)(fix_to_virt(FIX_TXT_PRIV_BASE) + reg); +} + +static inline void sboot_write_priv_config_reg(uint32_t reg, uint64_t val) +{ + /* these are MMIO so make sure compiler doesn't optimize */ + *(volatile uint64_t *)(unsigned long) + (fix_to_virt(FIX_TXT_PRIV_BASE) + reg) = val; +} + +static inline uint64_t sboot_read_pub_config_reg(uint32_t reg) +{ + /* these are MMIO so make sure compiler doesn't optimize */ + return *(volatile uint64_t *)(fix_to_virt(FIX_TXT_PUB_BASE) + reg); +} + +static inline void sboot_shutdown(void (*caller)(void *data), void *data) +{ + int i; + int timeout = 10; + + printk("SBOOT: in sboot_shutdown()\n"); + + /* if this is not called on BSP then invoke it on BSP and wait for */ + /* smp_send_stop() to halt us */ + if ( GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_physical_apicid ) { + printk("SBOOT: sboot_shutdown() not called on BSP\n"); + on_selected_cpus(cpumask_of_cpu(0), (void *)caller, + data, 1, 0); + printk("SBOOT: AP going into safe_halt loop\n"); + for ( ; ; ) + safe_halt(); + printk("SBOOT: AP should not get here\n"); + } + + watchdog_disable(); + console_start_sync(); + + local_irq_enable(); + + /* if we never launched the measured env then just cleanup and return */ + if ( !sboot_in_measured_env() ) { + /* now shutdown APs */ + smp_send_stop(); + + disable_IO_APIC(); + + hvm_disable(); + + return; + } + + /* + * before removing isolation protections (e.g. VMX) on any processor + * we need to return the env to a "safe" state (e.g. clear any secrets, + * cap PCRs, etc.) + */ + + /* scrub any secrets by clearing their memory */ + /* we don't have any secrets to scrub, however */ + ; + + /* need to access TXT private config space, so map it now (no reason to */ + /* map it sooner) */ + for ( i = 0; i < NR_TXT_CONFIG_PAGES; i++ ) { + set_fixmap_nocache(FIX_TXT_PRIV_BASE + i, + TXT_PRIV_CONFIG_REGS_BASE + i*PAGE_SIZE); + set_fixmap_nocache(FIX_TXT_PUB_BASE + i, + TXT_PUB_CONFIG_REGS_BASE + i*PAGE_SIZE); + } + + /* flush chipset caches and buffers */ + wbinvd(); + sboot_write_priv_config_reg(TXTCR_CMD_FLUSH_WB, 0x01); + printk("SBOOT: caches flushed\n"); + + /* TBD: cap dynamic PCRs (17, 18) */ + + /* set LT.CMD.NO-SECRETS flag (i.e. clear SECRETS flag) */ + sboot_write_priv_config_reg(TXTCR_CMD_NO_SECRETS, 0x01); + sboot_read_priv_config_reg(TXTCR_E2STS); /* fence */ + printk("SBOOT: secrets flag cleared\n"); + + /* close TXT private config space */ + sboot_read_priv_config_reg(TXTCR_E2STS); /* fence */ + sboot_write_priv_config_reg(TXTCR_CMD_CLOSE_PRIVATE, 0x01); + sboot_read_pub_config_reg(TXTCR_E2STS); /* fence */ + printk("SBOOT: private config space closed\n"); + + printk("SBOOT: num_online_cpus=%d\n", num_online_cpus()); + + /* now shutdown APs */ + smp_send_stop(); + + disable_IO_APIC(); + + hvm_disable(); + + /* if we never launched the measured env then we're done, so return */ + if ( !sboot_in_measured_env() ) + return; + + /* BSP needs to wait until all APs have gone through shutdown (disabled */ + /* VMX, etc.) before calling GETSEC[SEXIT] else will hang */ + /* but we won't wait forever */ + while ( num_online_cpus() > 1 && timeout > 0 ) { + /* TBD: determine why this printk is necessary to prevent timeout */ + printk("SBOOT: loop: num_online_cpus=%d\n", num_online_cpus()); + /* if not all APs have shutdown, wait a little */ + udelay(5); + timeout--; + } + + /* don't call SEXIT if not all APs have shutdown, since it will just */ + /* fault anyway, and this will hang system */ + if ( timeout != 0 ) { + /* SMXE may not be enabled any more, so set it to make sure */ + write_cr4(read_cr4() | X86_CR4_SMXE); + + /* call GETSEC[SEXIT] */ + __getsec_sexit(); + printk("SBOOT: GETSEC[SEXIT] measured environment torn down\n"); + } + else + printk("SBOOT: timeout before all APs shutdown; not doing SEXIT\n"); +} + +#endif /* __XEN__ */ + +#endif /* __SBOOT_H__ */ + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/include/spinlock.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/spinlock.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,49 @@ +#ifndef __SPINLOCK_H__ +#define __SPINLOCK_H__ +#include + +/* simple spinlock as part of sboot(WAKEUP) are smp */ +typedef struct { + volatile s16 lock; + s8 recurse_cpu; + u8 recurse_cnt; +} spinlock_t; + +#define SPIN_LOCK_UNLOCKED /*(spinlock_t)*/ { 1, -1, 0 } + +#define spin_lock_init(x) do { *(x) = (spinlock_t) SPIN_LOCK_UNLOCKED; } while(0) +#define spin_is_locked(x) (*(volatile char *)(&(x)->lock) <= 0) +static inline void _raw_spin_lock(spinlock_t *lock) +{ + __asm__ __volatile__ ( + "1: lock; decb %0 \n" + " js 2f \n" + ".section .text.lock,\"ax\"\n" + "2: cmpb $0,%0 \n" + " rep; nop \n" + " jle 2b \n" + " jmp 1b \n" + ".previous" + : "=m" (lock->lock) : : "memory" ); +} + +static inline void _raw_spin_unlock(spinlock_t *lock) +{ +#if !defined(CONFIG_X86_OOSTORE) +/* ASSERT(spin_is_locked(lock));*/ + __asm__ __volatile__ ( + "movb $1,%0" + : "=m" (lock->lock) : : "memory" ); +#else + char oldval = 1; +/* ASSERT(spin_is_locked(lock));*/ + __asm__ __volatile__ ( + "xchgb %b0, %1" + : "=q" (oldval), "=m" (lock->lock) : "0" (oldval) : "memory" ); +#endif +} +#define spin_lock(_lock) _raw_spin_lock(_lock) +#define spin_unlock(_lock) _raw_spin_unlock(_lock) +#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED + +#endif /* __SPINLOCK_H__ */ diff -r 419625d61514 -r de5826b5b302 sboot/include/string.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/string.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,231 @@ +#ifndef __X86_STRING_H__ +#define __X86_STRING_H__ + +#include + +static inline void *__variable_memcpy(void *to, const void *from, size_t n) +{ + long d0, d1, d2; + __asm__ __volatile__ ( + " rep ; movs"__OS"\n" + " mov %4,%3 \n" + " rep ; movsb \n" + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + : "0" (n/BYTES_PER_LONG), "r" (n%BYTES_PER_LONG), "1" (to), "2" (from) + : "memory" ); + return to; +} + +/* + * This looks horribly ugly, but the compiler can optimize it totally, + * as the count is constant. + */ +static always_inline void * __constant_memcpy( + void * to, const void * from, size_t n) +{ + switch ( n ) + { + case 0: + return to; + case 1: + *(u8 *)to = *(const u8 *)from; + return to; + case 2: + *(u16 *)to = *(const u16 *)from; + return to; + case 3: + *(u16 *)to = *(const u16 *)from; + *(2+(u8 *)to) = *(2+(const u8 *)from); + return to; + case 4: + *(u32 *)to = *(const u32 *)from; + return to; + case 5: + *(u32 *)to = *(const u32 *)from; + *(4+(u8 *)to) = *(4+(const u8 *)from); + return to; + case 6: + *(u32 *)to = *(const u32 *)from; + *(2+(u16 *)to) = *(2+(const u16 *)from); + return to; + case 7: + *(u32 *)to = *(const u32 *)from; + *(2+(u16 *)to) = *(2+(const u16 *)from); + *(6+(u8 *)to) = *(6+(const u8 *)from); + return to; + case 8: + *(u64 *)to = *(const u64 *)from; + return to; + case 12: + *(u64 *)to = *(const u64 *)from; + *(2+(u32 *)to) = *(2+(const u32 *)from); + return to; + case 16: + *(u64 *)to = *(const u64 *)from; + *(1+(u64 *)to) = *(1+(const u64 *)from); + return to; + case 20: + *(u64 *)to = *(const u64 *)from; + *(1+(u64 *)to) = *(1+(const u64 *)from); + *(4+(u32 *)to) = *(4+(const u32 *)from); + return to; + } +#define COMMON(x) \ + __asm__ __volatile__ ( \ + "rep ; movs"__OS \ + x \ + : "=&c" (d0), "=&D" (d1), "=&S" (d2) \ + : "0" (n/BYTES_PER_LONG), "1" (to), "2" (from) \ + : "memory" ); + { + long d0, d1, d2; + switch ( n % BYTES_PER_LONG ) + { + case 0: COMMON(""); return to; + case 1: COMMON("\n\tmovsb"); return to; + case 2: COMMON("\n\tmovsw"); return to; + case 3: COMMON("\n\tmovsw\n\tmovsb"); return to; + case 4: COMMON("\n\tmovsl"); return to; + case 5: COMMON("\n\tmovsl\n\tmovsb"); return to; + case 6: COMMON("\n\tmovsl\n\tmovsw"); return to; + case 7: COMMON("\n\tmovsl\n\tmovsw\n\tmovsb"); return to; + } + } +#undef COMMON + return to; +} + +#define __HAVE_ARCH_MEMCPY +#define memcpy(t,f,n) (__memcpy((t),(f),(n))) +static always_inline +void *__memcpy(void *t, const void *f, size_t n) +{ + return (__builtin_constant_p(n) ? + __constant_memcpy((t),(f),(n)) : + __variable_memcpy((t),(f),(n))); +} + +#define __HAVE_ARCH_MEMCMP +#define memcmp __builtin_memcmp + +static inline void *__memset_generic(void *s, char c, size_t count) +{ + long d0, d1; + __asm__ __volatile__ ( + "rep ; stosb" + : "=&c" (d0), "=&D" (d1) : "a" (c), "1" (s), "0" (count) : "memory" ); + return s; +} + +/* we might want to write optimized versions of these later */ +#define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count)) + +/* + * memset(x,0,y) is a reasonably common thing to do, so we want to fill + * things 32 bits at a time even when we don't know the size of the + * area at compile-time.. + */ +static inline void *__constant_c_memset(void *s, unsigned long c, size_t count) +{ + long d0, d1; + __asm__ __volatile__( + " rep ; stos"__OS"\n" + " mov %3,%4 \n" + " rep ; stosb \n" + : "=&c" (d0), "=&D" (d1) + : "a" (c), "r" (count%BYTES_PER_LONG), + "0" (count/BYTES_PER_LONG), "1" (s) + : "memory" ); + return s; +} + +/* + * This looks horribly ugly, but the compiler can optimize it totally, + * as we by now know that both pattern and count is constant.. + */ +static always_inline void *__constant_c_and_count_memset( + void *s, unsigned long pattern, size_t count) +{ + switch ( count ) + { + case 0: + return s; + case 1: + *(u8 *)s = pattern; + return s; + case 2: + *(u16 *)s = pattern; + return s; + case 3: + *(u16 *)s = pattern; + *(2+(u8 *)s) = pattern; + return s; + case 4: + *(u32 *)s = pattern; + return s; + case 5: + *(u32 *)s = pattern; + *(4+(u8 *)s) = pattern; + return s; + case 6: + *(u32 *)s = pattern; + *(2+(u16 *)s) = pattern; + return s; + case 7: + *(u32 *)s = pattern; + *(2+(u16 *)s) = pattern; + *(6+(u8 *)s) = pattern; + return s; + case 8: + *(u64 *)s = pattern; + return s; + } +#define COMMON(x) \ + __asm__ __volatile__ ( \ + "rep ; stos"__OS \ + x \ + : "=&c" (d0), "=&D" (d1) \ + : "a" (pattern), "0" (count/BYTES_PER_LONG), "1" (s) \ + : "memory" ) + { + long d0, d1; + switch ( count % BYTES_PER_LONG ) + { + case 0: COMMON(""); return s; + case 1: COMMON("\n\tstosb"); return s; + case 2: COMMON("\n\tstosw"); return s; + case 3: COMMON("\n\tstosw\n\tstosb"); return s; + case 4: COMMON("\n\tstosl"); return s; + case 5: COMMON("\n\tstosl\n\tstosb"); return s; + case 6: COMMON("\n\tstosl\n\tstosw"); return s; + case 7: COMMON("\n\tstosl\n\tstosw\n\tstosb"); return s; + } + } +#undef COMMON + return s; +} + +#define __constant_c_x_memset(s, c, count) \ +(__builtin_constant_p(count) ? \ + __constant_c_and_count_memset((s),(c),(count)) : \ + __constant_c_memset((s),(c),(count))) + +#define __var_x_memset(s, c, count) \ +(__builtin_constant_p(count) ? \ + __constant_count_memset((s),(c),(count)) : \ + __memset_generic((s),(c),(count))) + +#ifdef CONFIG_X86_64 +#define MEMSET_PATTERN_MUL 0x0101010101010101UL +#else +#define MEMSET_PATTERN_MUL 0x01010101UL +#endif + +#define __HAVE_ARCH_MEMSET +#define memset(s, c, count) (__memset((s),(c),(count))) +#define __memset(s, c, count) \ +(__builtin_constant_p(c) ? \ + __constant_c_x_memset((s),(MEMSET_PATTERN_MUL*(unsigned char)(c)),(count)) : \ + __var_x_memset((s),(c),(count))) + +#endif /* __X86_STRING_H__ */ diff -r 419625d61514 -r de5826b5b302 sboot/include/string2.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/string2.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,15 @@ +#ifndef _LINUX_STRING_H_ +#define _LINUX_STRING_H_ + +#include /* for size_t */ + +/* + * Include machine specific inline routines + */ +#include + +extern size_t strnlen(const char *,size_t); + +extern void * memmove(void *,const void *,size_t); + +#endif /* _LINUX_STRING_H_ */ diff -r 419625d61514 -r de5826b5b302 sboot/include/tpm.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/tpm.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,189 @@ +/* + * tpm.h: TPM-related support functions + * + * 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 __TPM_H__ +#define __TPM_H__ + +#define TPM_LOCALITY_BASE 0xfed40000 +#define NR_TPM_LOCALITY_PAGES ((TPM_LOCALITY_1 - TPM_LOCALITY_0) >> \ + PAGE_SHIFT) + +#define TPM_LOCALITY_0 TPM_LOCALITY_BASE +#define TPM_LOCALITY_1 (TPM_LOCALITY_BASE | 0x1000) +#define TPM_LOCALITY_2 (TPM_LOCALITY_BASE | 0x2000) +/* these localities (3+4) are mostly not usable by Xen */ +#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 + +/* + * return code: + * The TPM has five types of return code. One indicates successful operation + * and four indicate failure. + * TPM_SUCCESS (00000000) indicates successful execution. + * The failure reports are: + * TPM defined fatal errors (00000001 to 000003FF) + * vendor defined fatal errors (00000400 to 000007FF) + * TPM defined non-fatal errors (00000800 to 00000BFF) + * vendor defined non-fatal errors (00000C00 to 00000FFF). + * Here only give definitions for a few commonly used return code. + */ +#define TPM_BASE 0X00000000 +#define TPM_SUCCESS TPM_BASE +#define TPM_BADINDEX (TPM_BASE + 2) +#define TPM_BAD_PARAMETER (TPM_BASE + 3) +#define TPM_DEACTIVATED (TPM_BASE + 6) +#define TPM_DISABLED (TPM_BASE + 7) +#define TPM_FAIL (TPM_BASE + 9) +#define TPM_BAD_ORDINAL (TPM_BASE + 10) +#define TPM_NOSPACE (TPM_BASE + 17) +#define TPM_NOTRESETABLE (TPM_BASE + 50) +#define TPM_NOTLOCAL (TPM_BASE + 51) +#define TPM_BAD_LOCALITY (TPM_BASE + 61) +#define TPM_READ_ONLY (TPM_BASE + 62) +#define TPM_NOT_FULLWRITE (TPM_BASE + 70) + +extern bool is_tpm_ready(uint32_t locality); + +#define TPM_DIGEST_SIZE 20 +typedef struct { + uint8_t digest[TPM_DIGEST_SIZE]; +} __attribute__ ((packed)) tpm_digest_t; +typedef tpm_digest_t tpm_pcr_value_t; + +/* + * specified as minimum cmd buffer size should be supported by all 1.2 TPM + * device in the TCG_PCClientTPMSpecification_1-20_1-00_FINAL.pdf + */ +#define TPM_CMD_SIZE_MAX 768 +#define TPM_RSP_SIZE_MAX 768 + +#define TPM_NR_PCRS 24 + +/* + * tpm_pcr_read fetchs the current value of given PCR vai given locality. + * locality : TPM locality (0 - 4) + * pcr : PCR index (0 - 23) + * out : PCR value buffer, out parameter, should not be NULL + * return : TPM_SUCCESS for success, error code defined as TPM_xxx + */ +extern uint32_t tpm_pcr_read(uint32_t locality, uint32_t pcr, + tpm_pcr_value_t *pcr_value); + +/* + * tpm_pcr_extend extends data octets into given PCR via given locality, + * and return the PCR value after extending if required. + * locality : TPM locality (0 - 4) + * pcr : PCR index (0 - 23) + * in : Hash value to be extended into PCR, should not be NULL + * out : Out buffer for PCR value after extending, may be NULL + * return : TPM_SUCCESS for success, error code defined as TPM_xxx + */ +extern uint32_t tpm_pcr_extend(uint32_t locality, uint32_t pcr, + const tpm_digest_t* in, tpm_pcr_value_t* out); + +/* PCRs lower than 16 are not resetable */ +#define TPM_PCR_RESETABLE_MIN 16 + +/* + * tpm_pcr_reset resets given PCR via given locality. + * locality : TPM locality (0 - 4) + * pcr : PCR index (16 - 23) + * return : TPM_SUCCESS for success, error code defined as TPM_xxx + */ +extern uint32_t tpm_pcr_reset(uint32_t locality, uint32_t pcr); + +#define TPM_NV_READ_VALUE_DATA_SIZE_MAX (TPM_RSP_SIZE_MAX - 14) + +typedef uint32_t tpm_nv_index_t; + +/* + * tpm_nv_read_value reads data from TPM NV ram in the given locality. + * locality : TPM locality (0 - 4) + * index : Predefined index for certain NV space + * offset : Start reading from offset given by this parameter. + * data : Out buffer for read data, should not be NULL + * data_size : As IN, give the size required to read, should not be NULL; + * : as OUT, return the size really read from TPM. + * : The largest nv data size can be read in a single call is + * : defined by TPM_NV_READ_VALUE_DATA_SIZE_MAX. + * return : TPM_SUCCESS for success, error code defined as TPM_xxx + */ +extern uint32_t tpm_nv_read_value(uint32_t locality, tpm_nv_index_t index, + uint32_t offset, uint8_t *data, + uint32_t *data_size); + +#define TPM_NV_WRITE_VALUE_DATA_SIZE_MAX (TPM_CMD_SIZE_MAX - 22) + +/* + * tpm_nv_write_value writes data into TPM NV ram in the given locality. + * locality : TPM locality (0 - 4) + * index : Predefined index for certain NV space + * offset : Start writing from offset given by this parameter. + * data : Data to be written to TPM NV, should not be NULL + * data_size : The size of data to be written. + * : The largest nv data size can be written in a single call + * : is defined by TPM_NV_WRITE_VALUE_DATA_SIZE_MAX. + * return : TPM_SUCCESS for success, error code defined as TPM_xxx + */ +extern uint32_t tpm_nv_write_value(uint32_t locality, tpm_nv_index_t index, + uint32_t offset, const uint8_t *data, + uint32_t data_size); + +/* #define TPM_UNIT_TEST 1 */ + +#ifdef TPM_UNIT_TEST +void tpm_unit_test_before_senter(void); +void tpm_unit_test_after_senter(void); +#else +#define tpm_unit_test_before_senter() +#define tpm_unit_test_after_senter() +#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 -r 419625d61514 -r de5826b5b302 sboot/include/txt/acmod.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/txt/acmod.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,96 @@ +/* + * acmod.c: support functions for use of Intel(r) TXT Authenticated + * Code (AC) Modules + * + * Copyright (c) 2003-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 __TXT_ACMOD_H__ +#define __TXT_ACMOD_H__ + +#include +#include +#include + +/* + * authenticated code (AC) module header (ver 0.0) + */ + +typedef struct { + uint32_t module_type; + uint32_t header_len; + uint32_t header_ver; + uint32_t module_id; + uint32_t module_vendor; + uint32_t date; + uint32_t size; + uint32_t reserved1; + 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 mod_type field */ +#define ACM_TYPE_CHIPSET 0x02 + +/* value of module_vendor field */ +#define ACM_VENDOR_INTEL 0x8086 + +extern bool is_sinit_acmod(void *acmod_base, uint32_t acmod_size); +extern bool does_acmod_match_chipset(acm_hdr_t* hdr); +extern acm_hdr_t *copy_sinit(acm_hdr_t *sinit); +extern bool verify_acmod(acm_hdr_t *acm_hdr); +extern void set_mtrrs_for_acmod(acm_hdr_t *hdr); +extern uint32_t get_supported_os_sinit_data_ver(acm_hdr_t* hdr); + +#endif /* __TXT_ACMOD_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/include/txt/config_regs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/txt/config_regs.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,194 @@ +/* + * config_regs.h: Intel(r) TXT configuration register -related definitions + * + * Copyright (c) 2003-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 __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 + +/* # pages for each config regs space - used by fixmap */ +#define NR_TXT_CONFIG_PAGES ((TXT_PUB_CONFIG_REGS_BASE - \ + TXT_PRIV_CONFIG_REGS_BASE) >> \ + PAGE_SHIFT) + +/* 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_SYS_RESET 0x0038 +#define TXTCR_CMD_OPEN_PRIVATE 0x0040 +#define TXTCR_CMD_CLOSE_PRIVATE 0x0048 +#define TXTCR_DIDVID 0x0110 /* TBD: need to publish */ +#define TXTCR_CMD_FLUSH_WB 0x0258 +#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_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 : 16; /* external-specific error code */ + uint64_t reserved : 14; + 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 reserved1 : 1; + uint64_t txt_rogue_sts : 1; + uint64_t bm_write_attack : 1; + uint64_t bm_read_attack : 1; + uint64_t fsb_write_attack : 1; + uint64_t fsb_read_attack : 1; + uint64_t txt_wake_error_sts : 1; + uint64_t reserved2 : 1; + }; +} txt_ests_t; + +/* + * format of E2STS register + */ +typedef union { + uint64_t _raw; + struct { + uint64_t slp_entry_error_sts : 1; + uint64_t secrets_sts : 1; + uint64_t block_mem_sts : 1; + uint64_t reset_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 : 2; + uint64_t mem_unlock_sts : 1; + uint64_t nodma_en_sts : 1; + uint64_t mem_config_lock_sts : 1; + uint64_t private_open_sts : 1; + uint64_t reserved2 : 1; + uint64_t nodma_cache_sts : 1; + uint64_t nodma_table_prot_sts : 1; + uint64_t mem_config_ok_sts : 1; + }; +} txt_sts_t; + +/* TBD: need to publish */ +/* + * 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; + + +/* + * fns to read/write TXT config regs + */ + +static inline uint64_t read_config_reg(uint32_t config_regs_base, uint32_t reg) +{ + /* these are MMIO so make sure compiler doesn't optimize */ + return *(volatile uint64_t *)(unsigned long)(config_regs_base + reg); +} + +static inline void write_config_reg(uint32_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)(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 -r 419625d61514 -r de5826b5b302 sboot/include/txt/errorcode.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/txt/errorcode.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,91 @@ +/* + * errorcode.h: Intel(r) TXT error definitions for ERRORCODE config register + * + * Copyright (c) 2003-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 __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 { + uint16_t _raw; + struct { + uint16_t err : 15; /* specific to src */ + uint16_t src : 1; /* 0=ACM, 1=other */ + }; +} txt_errorcode_sw_t; + +/* + * ACM errors (txt_errorcode_sw_t.src=0), format of err field + */ +typedef union { + uint16_t _raw; + struct { + uint16_t type : 4; /* 0000=BIOS ACM, 0001=SINIT, */ + /* 0010-1111=reserved */ + uint16_t progress : 6; + uint16_t error : 4; + uint16_t reserved : 1; + }; +} 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 -r 419625d61514 -r de5826b5b302 sboot/include/txt/heap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/txt/heap.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,209 @@ +/* + * heap.h: Intel(r) TXT heap definitions + * + * Copyright (c) 2003-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 __TXT_HEAP_H__ +#define __TXT_HEAP_H__ + +#include +#include +#include +#include + +/* + * data-passing structures contained in TXT heap: + * - BIOS to OS/loader + * - OS/loader to MLE + * - OS/loader to SINIT + * - SINIT to MLE + */ + +/* + * BIOS to OS/loader structure + * - not used by current Xen + */ +typedef struct { + uint32_t version; /* SDP3/TEP=0x00 */ + uint32_t bios_sinit_size; +} bios_os_data_t; + +/* + * OS/loader to MLE structure v1 + * - private to Xen (so can be any format we need) + */ +typedef struct { + uint32_t version; /* will be 0x01 */ + mtrr_state_t saved_mtrr_state; /* saved prior to changes for SINIT */ + multiboot_info_t *mbi; /* needs to be restored to ebx */ +} os_mle_data_t; + +/* + * OS/loader to SINIT structure v1 + */ +typedef struct { + uint32_t version; /* SDP3/TEP=0x01 */ + uint32_t reserved; + uint64_t mle_ptab; + uint64_t mle_size; + uint64_t mle_hdr_base; +} 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 __attribute__ ((packed)) { + uint64_t base; + uint64_t length; + uint8_t mem_type; + uint8_t reserved[7]; +} sinit_mdr_t; + +#define SHA1_SIZE 20 +typedef uint8_t sha1_hash_t[SHA1_SIZE]; + +typedef struct { + uint32_t version; /* SDP3/TEP=0x01 */ + union { + struct { + uint32_t num_mdrs; + sinit_mdr_t mdrs[]; + } v1; + }; +} sinit_mle_data_t; + + +/* + * TXT heap data format and field accessor fns + */ + +/* + * offset length field + * ------ ------ ----- + * 0 8 bios_os_data_size + * 8 bios_os_data_size - 8 bios_os_data + * + * bios_os_data_size 8 os_mle_data_size + * bios_os_data_size + os_mle_data_size - 8 os_mle_data + * 8 + * + * bios_os_data_size + 8 os_sinit_data_size + * os_mle_data_size + * bios_os_data_size + os_sinit_data_size - 8 os_sinit_data + * os_mle_data_size + + * 8 + * + * bios_os_data_size + 8 sinit_mle_data_size + * os_mle_data_size + + * os_sinit_data_size + * bios_os_data_size + sinit_mle_data_size - 8 sinit_mle_data + * os_mle_data_size + + * os_sinit_data_size + + * 8 + */ + +typedef void txt_heap_t; + +/* 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)read_pub_config_reg(TXTCR_HEAP_BASE); +} + +static inline uint64_t get_bios_os_data_size(txt_heap_t *heap) +{ + return *(uint64_t *)heap; +} + +static inline bios_os_data_t *get_bios_os_data_start(txt_heap_t *heap) +{ + return (bios_os_data_t *)((char*)heap + sizeof(uint64_t)); +} + +static inline uint64_t get_os_mle_data_size(txt_heap_t *heap) +{ + return *(uint64_t *)(heap + get_bios_os_data_size(heap)); +} + +static inline os_mle_data_t *get_os_mle_data_start(txt_heap_t *heap) +{ + return (os_mle_data_t *)(heap + get_bios_os_data_size(heap) + + sizeof(uint64_t)); +} + +static inline uint64_t get_os_sinit_data_size(txt_heap_t *heap) +{ + return *(uint64_t *)(heap + get_bios_os_data_size(heap) + + get_os_mle_data_size(heap)); +} + +static inline os_sinit_data_t *get_os_sinit_data_start(txt_heap_t *heap) +{ + return (os_sinit_data_t *)(heap + get_bios_os_data_size(heap) + + get_os_mle_data_size(heap) + + sizeof(uint64_t)); +} + +static inline uint64_t get_sinit_mle_data_size(txt_heap_t *heap) +{ + return *(uint64_t *)(heap + get_bios_os_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(txt_heap_t *heap) +{ + return (sinit_mle_data_t *)(heap + get_bios_os_data_size(heap) + + get_os_mle_data_size(heap) + + get_os_sinit_data_size(heap) + + sizeof(uint64_t)); +} + +#endif /* __TXT_HEAP_H__ */ + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/include/txt/mtrrs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/txt/mtrrs.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,129 @@ +/* + * mtrrs.c: Intel(r) TXT MTRR-related definitions + * + * Copyright (c) 2003-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 __TXT_MTRRS_H__ +#define __TXT_MTRRS_H__ + +#include +#include + +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 : 24; + uint64_t reserved2 : 28; + }; +} mtrr_physbase_t; + +typedef union { + uint64_t raw; + struct { + uint64_t reserved1 : 11; + uint64_t v : 1; /* valid */ + uint64_t mask : 24; + uint64_t reserved2 : 28; + }; +} 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; + int num_var_mtrrs; + mtrr_physbase_t mtrr_physbases[MAX_VARIABLE_MTRRS]; + mtrr_physmask_t mtrr_physmasks[MAX_VARIABLE_MTRRS]; +} mtrr_state_t; + +extern void save_mtrrs(mtrr_state_t *saved_state); +extern void set_all_mtrrs(bool enable); +extern bool set_mem_type(void *base, uint32_t size, uint32_t mem_type); +extern void restore_mtrrs(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 -r 419625d61514 -r de5826b5b302 sboot/include/txt/smx.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/txt/smx.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,138 @@ +/* + * smx.h: Intel(r) TXT SMX architecture-related definitions + * + * Copyright (c) 2003-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 __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_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; +} + +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; +} + + +#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 -r 419625d61514 -r de5826b5b302 sboot/include/txt/txt.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/txt/txt.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,90 @@ +/* + * txt.h: Intel(r) TXT general definitions and support functions + * + * Copyright (c) 2003-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 __TXT_TXT_H__ +#define __TXT_TXT_H__ + +#include + +/* + * MLE header structure + * describes an MLE for SINIT and OS/loader SW + */ +typedef struct { + uint32_t guid[4]; + uint32_t length; + uint32_t version; + uint32_t entry_point; + uint32_t req_mem_size; + uint32_t features; +} mle_hdr_t; + + +/* + * RLP JOIN structure for GETSEC[WAKEUP] + */ +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; + +extern bool txt_is_launched(void); +extern bool txt_get_error(void); +extern bool txt_verify_platform(void); +extern bool txt_prepare_cpu(void); +extern bool txt_prepare_platform(void); +extern bool txt_launch_environment(multiboot_info_t *mbi); +extern bool txt_post_launch(void); +extern bool txt_protect_mem_regions(void); +extern bool txt_post_launch_verify_platform(void); + +/* in common/sboot.c */ +extern void cpu_wakeup(uint32_t cpuid); + + +#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 -r 419625d61514 -r de5826b5b302 sboot/include/txt/verify.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/txt/verify.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,53 @@ +/* + * verify.h: support functions for platform Intel(r) TXT verification + * + * Copyright (c) 2003-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 __TXT_VERIFY_H__ +#define __TXT_VERIFY_H__ + +extern bool verify_txt_heap(txt_heap_t *txt_heap, bool bios_os_data_only); +extern void print_os_sinit_data(os_sinit_data_t *os_sinit_data); + +#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 -r 419625d61514 -r de5826b5b302 sboot/include/txt/vmcs.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/txt/vmcs.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,327 @@ +#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, +}; + +/* VMX stuff */ +enum ap_init_state { + AP_WAIT_INIT = 0, + AP_WAIT_SIPI1 = 1, + AP_WAIT_SIPI2 = 2, + AP_WAIT_DONE = 3, +}; + +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_INVALID_GUEST_STATE 33 +#define EXIT_REASON_MSR_LOADING 34 + +#define EXIT_REASON_MACHINE_CHECK 41 + +static inline void __vmptrld(uint64_t addr) +{ + __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) +{ + __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; + + __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) +{ + __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 unsigned long __vmread_safe(unsigned long field, int *error) +{ + unsigned long ecx; + + __asm__ __volatile__ ( VMREAD_OPCODE + MODRM_EAX_ECX + /* CF==1 or ZF==1 --> rc = -1 */ + "setna %b0 ; neg %0" + : "=q" (*error), "=c" (ecx) + : "0" (0), "a" (field) + : "memory"); + + return ecx; +} + +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; +} + +extern void handle_init_sipi_sipi(void); + +#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 -r 419625d61514 -r de5826b5b302 sboot/include/types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/types.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,54 @@ +#ifndef __TYPES_H__ +#define __TYPES_H__ + +#include +#include + +#define BITS_TO_LONGS(bits) \ + (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) +#define DECLARE_BITMAP(name,bits) \ + unsigned long name[BITS_TO_LONGS(bits)] + +#ifndef NULL +#define NULL ((void*)0) +#endif + +#define INT_MAX ((int)(~0U>>1)) +#define INT_MIN (-INT_MAX - 1) +#define UINT_MAX (~0U) +#define LONG_MAX ((long)(~0UL>>1)) +#define LONG_MIN (-LONG_MAX - 1) +#define ULONG_MAX (~0UL) + +#ifndef __ASSEMBLY__ + +/* bsd */ +typedef unsigned char u_char; +typedef unsigned short u_short; +typedef unsigned int u_int; +typedef unsigned long u_long; + +/* sysv */ +typedef unsigned char unchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; + +typedef __u8 uint8_t; +typedef __u8 u_int8_t; +typedef __s8 int8_t; + +typedef __u16 uint16_t; +typedef __u16 u_int16_t; +typedef __s16 int16_t; + +typedef __u32 uint32_t; +typedef __u32 u_int32_t; +typedef __s32 int32_t; + +typedef __u64 uint64_t; +typedef __u64 u_int64_t; +typedef __s64 int64_t; +#endif /* __ASSEMBLY__ */ + +#endif /* __TYPES_H__ */ diff -r 419625d61514 -r de5826b5b302 sboot/include/uuid.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/uuid.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,74 @@ +/* + * 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 __attribute__ ((__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); +} + +static inline void print_uuid(const uuid_t *uuid) +{ + printk("{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 -r 419625d61514 -r de5826b5b302 sboot/include/x86_types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/include/x86_types.h Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,49 @@ +#ifndef __X86_TYPES_H__ +#define __X86_TYPES_H__ + +#ifndef __ASSEMBLY__ + +#include + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +typedef __signed__ long long __s64; +typedef unsigned long long __u64; +#endif + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; +#if defined(CONFIG_X86_PAE) +typedef u64 paddr_t; +#define PRIpaddr "016llx" +#else +typedef unsigned long paddr_t; +#define PRIpaddr "08lx" +#endif + +typedef unsigned long size_t; + +#endif /* __ASSEMBLY__ */ + +#define BITS_PER_LONG 32 +#define BYTES_PER_LONG 4 +#define LONG_BYTEORDER 2 + +#endif /* __X86_TYPES_H__ */ diff -r 419625d61514 -r de5826b5b302 sboot/txt/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/txt/Makefile Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,8 @@ +obj-y += errors.o +obj-y += txt.o +obj-y += verify.o +obj-y += mtrrs.o +obj-y += acmod.o +obj-y += verify.o +obj-y += vmcs.o + diff -r 419625d61514 -r de5826b5b302 sboot/txt/acmod.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/txt/acmod.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,537 @@ +/* + * acmod.c: support functions for use of Intel(r) TXT Authenticated + * Code (AC) Modules + * + * Copyright (c) 2003-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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + union { + struct { + uint8_t chipset_acm_type; + uint8_t version; + uint16_t length; + uint32_t chipset_id_list; + } v1; + }; +} acm_info_table_t; + + +/* chipset_acm_type field values */ +#define ACM_CHIPSET_TYPE_SINIT 0x01 + +typedef struct { + 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 { + uint32_t count; + acm_chipset_id_t chipset_id[]; +} acm_chipset_id_list_t; + + +#define ACM_MEM_TYPE_UC 0x0100 +#define ACM_MEM_TYPE_WC 0x0200 +#define ACM_MEM_TYPE_WT 0x1000 +#define ACM_MEM_TYPE_WP 0x2000 +#define ACM_MEM_TYPE_WB 0x4000 + +/* 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; +} getsec_parameters_t; + +#define DEF_ACM_MAX_SIZE 0x8000 +#define DEF_ACM_VER_MASK 0xffffffff +#define DEF_ACM_VER_SUPPORTED 0x00 +#define DEF_ACM_MEM_TYPES ACM_MEM_TYPE_UC +#define DEF_SENTER_CTRLS 0x00 + +static bool get_parameters(getsec_parameters_t *params) +{ + unsigned long cr4; + uint32_t index, eax, ebx, ecx; + int param_type; + + /* sanity check because GETSEC[PARAMETERS] will fail if not set */ + cr4 = read_cr4(); + if ( !(cr4 & X86_CR4_SMXE) ) { + printk("SMXE not enabled, can't read parameters\n"); + return false; + } + + memset(params, 0, sizeof(*params)); + params->acm_max_size = DEF_ACM_MAX_SIZE; + params->acm_mem_types = DEF_ACM_MEM_TYPES; + params->senter_controls = DEF_SENTER_CTRLS; + index = 0; + do { + __getsec_parameters(index++, ¶m_type, &eax, &ebx, &ecx); + /* the code generated for a 'switch' statement doesn't work in this */ + /* environment, so use if/else blocks instead */ + if ( param_type == 0 ) + ; + else if ( param_type == 1 ) { + if ( params->n_versions == MAX_SUPPORTED_ACM_VERSIONS ) + printk("number of supported ACM version exceeds " + "MAX_SUPPORTED_ACM_VERSIONS\n"); + else { + params->acm_versions[params->n_versions].mask = ebx; + params->acm_versions[params->n_versions].version = ecx; + params->n_versions++; + } + } + else if ( param_type == 2 ) + params->acm_max_size = eax & 0xffffffe0; + else if ( param_type == 3 ) + params->acm_mem_types = eax & 0xffffffe0; + else if ( param_type == 4 ) + params->senter_controls = (eax & 0x00007fff) >> 8; + else { + printk("unknown GETSEC[PARAMETERS] type: %d\n", param_type); + param_type = 0; /* set so that we break out of the loop */ + } + } while ( param_type != 0 ); + + if ( params->n_versions == 0 ) { + params->acm_versions[0].mask = DEF_ACM_VER_MASK; + params->acm_versions[0].version = DEF_ACM_VER_SUPPORTED; + params->n_versions = 1; + } + + return true; +} + +static acm_info_table_t *get_acmod_info_table(acm_hdr_t* hdr) +{ + uint32_t user_area_off; + + /* 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; + /* check that table is within module */ + if ( user_area_off + sizeof(acm_info_table_t) > hdr->size*4 ) { + printk("ACM info table size too large: %x\n", + user_area_off + sizeof(acm_info_table_t)); + return NULL; + } + + return (acm_info_table_t *)((uint32_t)hdr + user_area_off); +} + +static void print_acm_hdr(acm_hdr_t *hdr, const char *mod_name) +{ + acm_info_table_t *info_table; + + printk("AC module header dump for %s:\n", + (mod_name == NULL) ? "?" : mod_name); + printk("\t type=%x\n", hdr->module_type); + printk("\t length=%x\n", hdr->header_len); + printk("\t version=%x\n", hdr->header_ver); + printk("\t id=%x\n", hdr->module_id); + printk("\t vendor=%x\n", hdr->module_vendor); + printk("\t date=%08x\n", hdr->date); + printk("\t size*4=%x\n", hdr->size*4); + printk("\t entry point=%08x:%08x\n", hdr->seg_sel, + hdr->entry_point); + printk("\t scratch_size=%x\n", hdr->scratch_size); + + printk("\t info_table:\n"); + info_table = get_acmod_info_table(hdr); + if ( info_table == NULL ) { + printk("\t\t \n"); + return; + } + printk("\t\tchipset_acm_type=%x\n", + (uint32_t)info_table->v1.chipset_acm_type); + printk("\t\tversion=%x\n", (uint32_t)info_table->v1.version); + printk("\t\tlength=%x\n", (uint32_t)info_table->v1.length); + printk("\t\tchipset_id_list=%x\n", + (uint32_t)info_table->v1.chipset_id_list); +} + +uint32_t get_supported_os_sinit_data_ver(acm_hdr_t* hdr) +{ + acm_info_table_t *info_table; + + /* assumes that it passed is_sinit_acmod() */ + + info_table = get_acmod_info_table(hdr); + if ( info_table == NULL ) + return 0x00; + + return 0x01; +} + +static bool is_acmod(void *acmod_base, uint32_t acmod_size, uint8_t *type) +{ + acm_hdr_t *acm_hdr; + acm_info_table_t *info_table; + + acm_hdr = (acm_hdr_t *)acmod_base; + + /* first check size */ + if ( acmod_size < sizeof(acm_hdr_t) ) { + printk("ACM size is too small: acmod_size=%x," + " sizeof(acm_hdr)=%x\n", acmod_size, sizeof(acm_hdr) ); + return false; + } + if ( acmod_size != acm_hdr->size * 4 ) { + printk("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) ) { + printk("ACM type/vendor mismatch: module_type=%x," + " module_vendor=%x\n", acm_hdr->module_type, + acm_hdr->module_vendor); + return false; + } + + info_table = get_acmod_info_table(acm_hdr); + if ( info_table == NULL ) + return false; + + if ( type != NULL ) + *type = info_table->v1.chipset_acm_type; + /* there is forward compatibility, so this is just a warning */ + if ( info_table->v1.version != 0x01 ) + printk("ACM info_table version mismatch (%x)\n", + (unsigned int)info_table->v1.version); + + return true; +} + +bool is_sinit_acmod(void *acmod_base, uint32_t acmod_size) +{ + uint8_t type; + + if ( !is_acmod(acmod_base, acmod_size, &type) ) + return false; + + if ( type != ACM_CHIPSET_TYPE_SINIT ) { + printk("ACM is not an SINIT ACM (%x)\n", type); + return false; + } + + return true; +} + +bool does_acmod_match_chipset(acm_hdr_t* hdr) +{ + acm_info_table_t *info_table; + acm_chipset_id_list_t *chipset_id_list; + acm_chipset_id_t *chipset_id; + txt_didvid_t didvid; + uint32_t size, id_list_off; + int i; + + /* 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 false; + id_list_off = info_table->v1.chipset_id_list; + + size = hdr->size * 4; + + /* check that chipset id table is w/in ACM */ + if ( id_list_off + sizeof(acm_chipset_id_t) > size ) { + printk("ACM chipset id list is too big: chipset_id_list=%x\n", + id_list_off); + return false; + } + + chipset_id_list = (acm_chipset_id_list_t *)((uint32_t)hdr + id_list_off); + + /* 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("ACM chipset id entries are too big:" + " chipset_id_list->count=%x\n", chipset_id_list->count); + return false; + } + + /* get chipset device and vendor id info */ + didvid._raw = read_pub_config_reg(TXTCR_DIDVID); + printk("chipset ids: vendor=%x, device=%x, revision=%x\n", + didvid.vendor_id, didvid.device_id, didvid.revision_id); + + printk("%x ACM chipset id entries:\n", chipset_id_list->count); + for ( i = 0; i < chipset_id_list->count; i++ ) { + chipset_id = &(chipset_id_list->chipset_id[i]); + printk("\tvendor=%x, device=%x, flags=%x, revision=%x, " + "extended=%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 ) ) ) ) + return true; + } + + printk("ACM does not match chipset\n"); + +#ifdef CHIPSET_REVID_BUG + return true; +#else + return false; +#endif +} + +acm_hdr_t *copy_sinit(acm_hdr_t *sinit) +{ + void *sinit_region_base; + uint32_t sinit_region_size; + txt_heap_t *txt_heap; + bios_os_data_t *bios_os_data; + + /* get BIOS-reserved region from LT.SINIT.BASE config reg */ + sinit_region_base = (void*)(uint32_t)read_pub_config_reg(TXTCR_SINIT_BASE); + sinit_region_size = (uint32_t)read_pub_config_reg(TXTCR_SINIT_SIZE); + + /* + * check if BIOS already loaded an SINIT module there + */ + txt_heap = get_txt_heap(); + bios_os_data = get_bios_os_data_start(txt_heap); + /* BIOS has loaded an SINIT module, so verify that it is valid */ + if ( bios_os_data->bios_sinit_size != 0 ) { + printk("BIOS has already loaded an SINIT module\n"); + /* is it a valid SINIT module? */ + if ( is_sinit_acmod(sinit_region_base, + bios_os_data->bios_sinit_size) ) { + /* is it newer than the one we've been provided? */ + if ( ((acm_hdr_t *)sinit_region_base)->date >= sinit->date ) + return (acm_hdr_t *)sinit_region_base; /* yes */ + else + printk("BIOS SINIT is older: date=%x\n", + ((acm_hdr_t *)sinit_region_base)->date); + } + } + /* our SINIT is newer than BIOS's (or BIOS did not have one) */ + + /* make sure our SINIT fits in the reserved region */ + if ( (sinit->size * 4) > sinit_region_size ) { + printk("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("copied SINIT (size=%x) to %p\n", sinit->size*4, + sinit_region_base); + + return (acm_hdr_t *)sinit_region_base; +} + + +/* + * 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 + */ +bool verify_acmod(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)acm_hdr & 0xfff ) { + printk("AC mod base not 4K aligned (%p)\n", acm_hdr); + return false; + } + printk("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("AC mod size %x bogus\n", size); + return false; + } + + if ( get_parameters(¶ms) == -1 ) { + printk("get_parameters() failed\n"); + return false; + } + + if ( size > params.acm_max_size ) { + printk("AC mod size too large: %x (max=%x)\n", size, + params.acm_max_size); + return false; + } + + printk("AC mod size OK\n"); + + /* + * perform checks on AC mod structure + */ + + /* print it for debugging */ + print_acm_hdr(acm_hdr, "SINIT"); + + /* entry point is offset from base addr so make sure it is within module */ + if ( acm_hdr->entry_point >= size ) { + printk("AC mod entry (%08x) >= AC mod size (%08x)\n", + acm_hdr->entry_point, size); + 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("AC mod selector [%04x] bogus\n", acm_hdr->seg_sel); + return false; + } + + return true; +} + +/* + * this must be done for each processor so that all have the same + * memory types + */ +void set_mtrrs_for_acmod(acm_hdr_t *hdr) +{ + unsigned long eflags; + unsigned 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 */ + __save_flags(eflags); + __cli(); + + /* save CR0 then disable cache (CRO.CD=1, CR0.NW=0) */ + cr0 = read_cr0(); + write_cr0((cr0 & ~X86_CR0_NW) | X86_CR0_CD); + + /* flush caches */ + wbinvd(); + + /* save CR4 and disable global pages (CR4.PGE=0) */ + cr4 = read_cr4(); + write_cr4(cr4 & ~X86_CR4_PGE); + + /* disable MTRRs */ + set_all_mtrrs(false); + + /* + * now set MTRRs for AC mod and rest of memory + */ + set_mem_type(hdr, hdr->size*4, MTRR_TYPE_WRBACK); + + /* + * 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) */ + write_cr4(cr4); + + /* enable interrupts */ + __restore_flags(eflags); +} + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/txt/errors.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/txt/errors.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,113 @@ +/* + * errors.c: parse and return status of Intel(r) TXT error codes + * + * Copyright (c) 2003-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. + * + */ + +#include +#include +#include +#include +#include +#include +#include + + +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 LT.ERRORODE error + */ + err = (txt_errorcode_t)read_pub_config_reg(TXTCR_ERRORCODE); + printk("LT.ERRORCODE=%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("\t processor error %x\n", (uint32_t)err.type); + else { /* external SW error */ + sw_err._raw = err.type; + if ( sw_err.src == 1 ) /* unknown SW error */ + printk("unknown SW error %x\n", (uint32_t)sw_err.err); + else { /* ACM error */ + acmod_err._raw = sw_err.err; + printk("AC module error : type=%x, progress=%02x, error=%x\n", + (uint32_t)acmod_err.type, (uint32_t)acmod_err.progress, + (uint32_t)acmod_err.error); + } + } + } + + /* + * display LT.ESTS error + */ + ests = (txt_ests_t)read_pub_config_reg(TXTCR_ESTS); + printk("LT.ESTS=%Lx\n", ests._raw); + + /* + * display LT.E2STS error + * - only valid if LT.WAKE-ERROR.STS set in LT.STS reg + */ + if ( ests.txt_wake_error_sts ) { + e2sts = (txt_e2sts_t)read_pub_config_reg(TXTCR_E2STS); + printk("LT.E2STS=%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; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/txt/mtrrs.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/txt/mtrrs.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,193 @@ +/* + * mtrrs.c: support functions for manipulating MTRRs + * + * Copyright (c) 2003-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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +void save_mtrrs(mtrr_state_t *saved_state) +{ + mtrr_cap_t mtrr_cap; + int ndx; + + /* IA32_MTRR_DEF_TYPE MSR */ + rdmsrl(MSR_IA32_MTRR_DEF_TYPE, saved_state->mtrr_def_type.raw); + + /* number variable MTTRRs */ + rdmsrl(MSR_IA32_MTRRCAP, mtrr_cap.raw); + 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("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 ( ndx = 0; ndx < saved_state->num_var_mtrrs; ndx++ ) { + rdmsrl(MTRR_PHYS_MASK0_MSR + ndx*2, + saved_state->mtrr_physmasks[ndx].raw); + rdmsrl(MTRR_PHYS_BASE0_MSR + ndx*2, + saved_state->mtrr_physbases[ndx].raw); + } +} + +void restore_mtrrs(mtrr_state_t *saved_state) +{ + int ndx; + + /* TBD: we need to check these for validity (e.g. overlaping regions */ + /* with invalid memory type combinations and variable MTRRs describing */ + /* non-contiguous memory regions) */ + + /* IA32_MTRR_DEF_TYPE MSR */ + wrmsrl(MSR_IA32_MTRR_DEF_TYPE, saved_state->mtrr_def_type.raw); + + /* physmask's and physbase's */ + for ( ndx = 0; ndx < saved_state->num_var_mtrrs; ndx++ ) { + wrmsrl(MTRR_PHYS_MASK0_MSR + ndx*2, + saved_state->mtrr_physmasks[ndx].raw); + wrmsrl(MTRR_PHYS_BASE0_MSR + ndx*2, + saved_state->mtrr_physbases[ndx].raw); + } +} + +/* + * set the memory type for specified range (base to base+size) + * to mem_type and everything else to UC + */ +bool set_mem_type(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 + */ + rdmsrl(MSR_IA32_MTRR_DEF_TYPE, mtrr_def_type.raw); + mtrr_def_type.fe = 0; + mtrr_def_type.type = MTRR_TYPE_UNCACHABLE; + wrmsrl(MSR_IA32_MTRR_DEF_TYPE, mtrr_def_type.raw); + + /* + * initially disable all variable MTRRs (we'll enable the ones we use) + */ + rdmsrl(MSR_IA32_MTRRCAP, mtrr_cap.raw); + for ( ndx = 0; ndx < mtrr_cap.vcnt; ndx++ ) { + rdmsrl(MTRR_PHYS_MASK0_MSR + ndx*2, mtrr_physmask.raw); + mtrr_physmask.v = 0; + wrmsrl(MTRR_PHYS_MASK0_MSR + ndx*2, mtrr_physmask.raw); + } + + /* + * map all AC module pages as mem_type + */ + + num_pages = (size + PAGE_SIZE) >> PAGE_SHIFT; + ndx = 0; + + printk("setting MTRRs for acmod: base=%p, size=%x, num_pages=%d\n", + base, size, num_pages); + + while ( num_pages > 0 ) { + uint32_t pages_in_range; + + /* set the base of the current MTRR */ + rdmsrl(MTRR_PHYS_BASE0_MSR + ndx*2, mtrr_physbase.raw); + mtrr_physbase.base = (unsigned long)base >> PAGE_SHIFT; + mtrr_physbase.type = mem_type; + wrmsrl(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); + + rdmsrl(MTRR_PHYS_MASK0_MSR + ndx*2, mtrr_physmask.raw); + mtrr_physmask.mask = ~(pages_in_range - 1); + mtrr_physmask.v = 1; + wrmsrl(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("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; + + rdmsrl(MSR_IA32_MTRR_DEF_TYPE, mtrr_def_type.raw); + mtrr_def_type.e = enable ? 1 : 0; + wrmsrl(MSR_IA32_MTRR_DEF_TYPE, 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 -r 419625d61514 -r de5826b5b302 sboot/txt/txt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/txt/txt.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,580 @@ +/* + * txt.c: Intel(r) TXT support functions, including initiating measured + * launch, post-launch, AP wakeup, etc. + * + * Copyright (c) 2003-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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char _stext[]; /* start of text section */ +extern char __start[]; /* sboot entry point in boot.S */ +extern char _txt_wakeup[]; /* RLP join address for GETSEC[WAKEUP] */ +extern char _end[]; /* end of module */ + +/* MLE/kernel shared data page (in boot.S) */ +extern mle_kernel_shared_t _mle_kernel_shared; + +/* + * this is the structure whose addr we'll put in TXT heap + */ +static mle_hdr_t g_mle_hdr = { + guid : {0x9082ac5a, 0x74a7476f, 0xa2555c0f, 0x42b651cb}, + length : sizeof(mle_hdr_t), + version : 0x00010000, + entry_point : (uint32_t)&__start - SBOOT_BASE_ADDR, + req_mem_size : 0, /* we don't use this */ + features : 0x00000000 /* nor this */ +}; + +static void print_file_info(void) +{ + printk("file addresses:\n"); + printk("\t &_stext=%p\n", &_stext); + printk("\t &__start=%p\n", &__start); + printk("\t &_end=%p\n", &_end); + printk("\t &_txt_wakeup=%p\n", &_txt_wakeup); + printk("\t &g_mle_hdr=%p\n", &g_mle_hdr); +} + +static void print_mle_hdr(mle_hdr_t *mle_hdr) +{ + printk("MLE header:\n"); + printk("\t guid="); print_uuid((uuid_t *)mle_hdr->guid); printk("\n"); + printk("\t length=%x\n", mle_hdr->length); + printk("\t version=%08x\n", mle_hdr->version); + printk("\t entry_point=%08x\n", mle_hdr->entry_point); + printk("\t req_mem_size=%x\n", mle_hdr->req_mem_size); + printk("\t features=%08x\n", mle_hdr->features); +} + +/* + * build_mle_pagetable() + */ + +/* page dir/table entry is phys addr + P + R/W + PWT */ +#define MAKE_PDTE(addr) (((uint64_t)(unsigned long)(addr) & PAGE_MASK) | 0x01) + +/* we assume/know that our image is <2MB and thus fits w/in a single */ +/* PT (512*4KB = 2MB) and thus fixed to 1 pg dir ptr and 1 pgdir and */ +/* 1 ptable = 3 pages and just 1 loop loop for ptable MLE page table */ +/* can only contain 4k pages */ + +static void *build_mle_pagetable(uint32_t mle_start, uint32_t mle_end) +{ + void *ptab_base; + uint32_t mle_size, ptab_size, mle_off; + void *pg_dir_ptr_tab, *pg_dir, *pg_tab; + uint64_t *pte; + + mle_size = mle_end - mle_start; + printk("MLE start=%x, end=%x, size=%x\n", mle_start, mle_end, + mle_size); + if ( mle_size > 512*PAGE_SIZE ) { + printk("MLE size too big for single page table\n"); + return NULL; + } + + + /* should start on page boundary */ + if ( mle_start & ~PAGE_MASK ) { + printk("MLE start is not page-aligned\n"); + return NULL; + } + + /* place ptab_base below MLE */ + ptab_size = 3 * PAGE_SIZE; /* pgdir ptr + pgdir + ptab = 3 */ + ptab_base = (void *)((mle_start - ptab_size) & PAGE_MASK); + memset(ptab_base, 0, ptab_size); + printk("ptab_size=%x, ptab_base=%p\n", ptab_size, ptab_base); + + pg_dir_ptr_tab = ptab_base; + pg_dir = pg_dir_ptr_tab + PAGE_SIZE; + pg_tab = pg_dir + PAGE_SIZE; + + /* only use first entry in page dir ptr table */ + *(uint64_t *)pg_dir_ptr_tab = MAKE_PDTE(pg_dir); + + /* only use first entry in page dir */ + *(uint64_t *)pg_dir = MAKE_PDTE(pg_tab); + + pte = pg_tab; + mle_off = 0; + do { + *pte = MAKE_PDTE(mle_start + mle_off); + + pte++; + mle_off += PAGE_SIZE; + } while ( mle_off < mle_size ); + + return ptab_base; +} + +/* size can be NULL */ +static bool find_sinit(multiboot_info_t *mbi, void **base, uint32_t *size) +{ + module_t *mods; + uint32_t size2 = 0; + void *base2 = NULL; + int i; + + if ( base == NULL ) { + printk("find_sinit() base is NULL\n"); + return false; + } + *base = NULL; + if ( size != NULL ) + *size = 0; + + if ( mbi->mods_addr == 0 || mbi->mods_count == 0 ) { + printk("no module info\n"); + return false; + } + + mods = (module_t *)(mbi->mods_addr); + for ( i = mbi->mods_count - 1; i > 0; i-- ) { + base2 = (void *)mods[i].mod_start; + size2 = mods[i].mod_end - (unsigned long)(base2); + /* check if this is really an SINIT AC module */ + if ( is_sinit_acmod(base2, size2) ) + break; + } + /* not found */ + if ( i == 0 ) { + printk("no SINIT AC module found\n"); + return false; + } + + *base = base2; + if ( size != NULL ) + *size = size2; + return true; +} + +/* + * sets up TXT heap + */ +static txt_heap_t *init_txt_heap(void *ptab_base, acm_hdr_t *sinit, + multiboot_info_t *mbi) +{ + txt_heap_t *txt_heap; + os_mle_data_t *os_mle_data; + os_sinit_data_t *os_sinit_data; + uint64_t *size; + uint32_t os_sinit_data_ver; + + txt_heap = get_txt_heap(); + + /* + * BIOS to OS/loader data already setup by BIOS + */ + if ( !verify_txt_heap(txt_heap, true) ) + return NULL; + + /* + * OS/loader to MLE data + */ + os_mle_data = get_os_mle_data_start(txt_heap); + size = (uint64_t *)((uint32_t)os_mle_data - sizeof(uint64_t)); + *size = sizeof(*os_mle_data) + sizeof(uint64_t); + memset(os_mle_data, 0, sizeof(*os_mle_data)); + os_mle_data->version = 0x01; + os_mle_data->mbi = mbi; + + /* + * OS/loader to SINIT data + */ + os_sinit_data_ver = get_supported_os_sinit_data_ver(sinit); + printk("SINIT supports os_sinit_data version %x\n", + os_sinit_data_ver); + /* warn if SINIT supports more recent OS to SINIT data version than us */ + if ( os_sinit_data_ver > 0x01 ) + printk("SINIT's os_sinit_data version unsupported (%x)\n", + os_sinit_data_ver); + os_sinit_data = get_os_sinit_data_start(txt_heap); + size = (uint64_t *)((uint32_t)os_sinit_data - sizeof(uint64_t)); + *size = sizeof(*os_sinit_data) + sizeof(uint64_t); + memset(os_sinit_data, 0, sizeof(*os_sinit_data)); + /* common to all versions */ + /* this is phys addr */ + os_sinit_data->mle_ptab = (uint64_t)(unsigned long)ptab_base; + os_sinit_data->mle_size = (uint64_t)&_end - (uint64_t)&_stext; + /* this is linear addr (offset from MLE base) of mle header */ + os_sinit_data->mle_hdr_base = (uint64_t)&g_mle_hdr - (uint64_t)&_stext; + os_sinit_data->version = 0x01; + print_os_sinit_data(os_sinit_data); + + /* + * SINIT to MLE data will be setup by SINIT + */ + + return txt_heap; +} + +static void txt_wakeup_cpus(void) +{ + struct { + uint16_t limit; + uint32_t base; + } gdt; + uint16_t cs; + mle_join_t mle_join; + + /* RLPs will use our GDT and CS */ + __asm__ __volatile__ ("sgdt (%0) \n" :: "a"(&gdt) : "memory"); + __asm__ __volatile__ ("movl %%cs, %0\n" : "=r"(cs)); + + mle_join.entry_point = (uint32_t)(unsigned long)&_txt_wakeup; + mle_join.seg_sel = cs; + mle_join.gdt_base = gdt.base; + mle_join.gdt_limit = gdt.limit; + + printk("mle_join.entry_point = %x\n", mle_join.entry_point); + printk("mle_join.seg_sel = %x\n", mle_join.seg_sel); + printk("mle_join.gdt_base = %x\n", mle_join.gdt_base); + printk("mle_join.gdt_limit = %x\n", mle_join.gdt_limit); + + write_priv_config_reg(TXTCR_MLE_JOIN, (uint64_t)(unsigned long)&mle_join); + + printk("joining RLPs to MLE with GETSEC[WAKEUP]\n"); + __getsec_wakeup(); + + /* TBD: maybe need wait here for AP to launch mini guest */ + + printk("GETSEC[WAKEUP] completed\n"); +} + +bool txt_is_launched(void) +{ + txt_sts_t sts; + + sts._raw = read_pub_config_reg(TXTCR_STS); + + return sts.senter_done_sts; +} + +bool txt_launch_environment(multiboot_info_t *mbi) +{ + acm_hdr_t *sinit; + void *mle_ptab_base; + os_mle_data_t *os_mle_data; + txt_heap_t *txt_heap; + + /* + * find SINIT AC module in modules list (it should be one of last three) + */ + if ( !find_sinit(mbi, (void **)&sinit, NULL) ) + return false; + + /* check if it matches chipset */ + if ( !does_acmod_match_chipset(sinit) ) { + printk("SINIT does not match chipset\n"); + return false; + } + + /* if it is newer than BIOS-provided version, then copy it to */ + /* BIOS reserved region */ + sinit = copy_sinit(sinit); + if ( sinit == NULL ) + return false; + + /* do some checks on it */ + if ( !verify_acmod(sinit) ) + return false; + + /* print some debug info */ + print_file_info(); + print_mle_hdr(&g_mle_hdr); + + /* create MLE page table */ + mle_ptab_base = build_mle_pagetable((uint32_t)&_stext, (uint32_t)&_end); + if ( mle_ptab_base == NULL ) + return false; + + /* initialize TXT heap */ + txt_heap = init_txt_heap(mle_ptab_base, sinit, mbi); + + /* save MTRRs before we alter them for SINIT launch */ + os_mle_data = get_os_mle_data_start(txt_heap); + save_mtrrs(&(os_mle_data->saved_mtrr_state)); + + /* set MTRRs properly for AC module (SINIT) */ + set_mtrrs_for_acmod(sinit); + + printk("executing GETSEC[SENTER]...\n"); + __getsec_senter((uint32_t)sinit, (sinit->size)*4); + printk("ERROR--we should not get here!\n"); + return false; +} + +bool txt_prepare_platform(void) +{ + tpm_unit_test_before_senter(); + if ( is_tpm_ready(0) ) + return true; + else + return false; +} + +bool txt_prepare_cpu(void) +{ + unsigned long eflags, cr0; + uint64_t mcg_cap, mcg_stat; + int i; + + /* must be running at CPL 0 => this is implicit in even getting this far */ + /* since our bootstrap code loads a GDT, etc. */ + + cr0 = read_cr0(); + + /* must be in protected mode */ + if ( !(cr0 & X86_CR0_PE) ) { + printk("ERR: not in protected mode\n"); + return false; + } + + /* cache must be enabled (CR0.CD = CR0.NW = 0) */ + if ( cr0 & X86_CR0_CD ) { + printk("CR0.CD set\n"); + cr0 &= ~X86_CR0_CD; + } + if ( cr0 & X86_CR0_NW ) { + printk("CR0.NW set\n"); + cr0 &= ~X86_CR0_NW; + } + + /* native FPU error reporting must be enabled for proper */ + /* interaction behavior */ + if ( !(cr0 & X86_CR0_NE) ) { + printk("CR0.NE not set\n"); + cr0 |= X86_CR0_NE; + } + + write_cr0(cr0); + + /* cannot be in virtual-8086 mode (EFLAGS.VM=1) */ + __save_flags(eflags); + if ( eflags & X86_EFLAGS_VM ) { + printk("EFLAGS.VM set\n"); + __restore_flags(eflags | ~X86_EFLAGS_VM); + } + + printk("CR0 and EFLAGS OK\n"); + + /* + * verify that we're not already in a protected environment + */ + if ( txt_is_launched() ) { + printk("already in protected environment\n"); + return false; + } + + /* + * verify all machine check status registers are clear + */ + + /* no machine check in progress (IA32_MCG_STATUS.MCIP=1) */ + rdmsrl(MSR_IA32_MCG_STATUS, mcg_stat); + if ( mcg_stat & 0x04 ) { + printk("machine check in progress\n"); + return false; + } + + /* all machine check regs are clear */ + rdmsrl(MSR_IA32_MCG_CAP, mcg_cap); + for (i = 0; i < (mcg_cap & 0xff); i++) { + rdmsrl(MSR_IA32_MC0_STATUS + 4*i, mcg_stat); + if ( mcg_stat & (1ULL << 63) ) { + printk("MCG[%d] = %Lx ERROR\n", i, mcg_stat); + return false; + } + } + + printk("no machine check errors\n"); + + /* all is well with the processor state */ + printk("CPU is ready for SENTER\n"); + + return true; +} + +bool txt_post_launch(void) +{ + txt_heap_t *txt_heap; + os_mle_data_t *os_mle_data; + + /* TBD: need to handle this gracefully */ + if ( !txt_post_launch_verify_platform() ) + printk("failed to verify platform\n"); + + /* clear error config registers so that we start fresh */ + write_priv_config_reg(TXTCR_ERRORCODE, 0x00000000); + write_priv_config_reg(TXTCR_ESTS, 0xffffffff); /* write 1's to clear */ + + tpm_unit_test_after_senter(); + + /* always set the LT.CMD.SECRETS flag */ + write_priv_config_reg(TXTCR_CMD_SECRETS, 0x01); + read_priv_config_reg(TXTCR_E2STS); /* just a fence, so ignore return */ + printk("set LT.CMD.SECRETS flag\n"); + + /* get saved OS state (os_mvmm_data_t) from LT heap */ + txt_heap = get_txt_heap(); + os_mle_data = get_os_mle_data_start(txt_heap); + + /* restore pre-SENTER MTRRs that were overwritten for SINIT launch */ + /* TBD: we need to validate these before restoring them */ + restore_mtrrs(&(os_mle_data->saved_mtrr_state)); + + /* bring RLPs into environment */ + txt_wakeup_cpus(); + + /* enable SMIs (do this after APs have been awakened and sync'ed w/ BSP) */ + __getsec_smctrl(); + + return true; +} + +void txt_cpu_wakeup(uint32_t cpuid) +{ + txt_heap_t *txt_heap; + os_mle_data_t *os_mle_data; + + printk("cpu %x waking up from TXT sleep\n", cpuid); + + txt_heap = get_txt_heap(); + os_mle_data = get_os_mle_data_start(txt_heap); + + /* apply (validated) (pre-SENTER) MTRRs from BSP to each AP */ + restore_mtrrs(&(os_mle_data->saved_mtrr_state)); + + handle_init_sipi_sipi(); +} + +bool txt_protect_mem_regions(void) +{ + uint64_t base, size; + + /* + * TXT has 2 regions of RAM that need to be reserved for use by only the + * hypervisor; not even dom0 should have access: + * TXT heap, SINIT AC module + */ + + /* TXT heap */ + base = read_pub_config_reg(TXTCR_HEAP_BASE); + size = read_pub_config_reg(TXTCR_HEAP_SIZE); + printk("protecting TXT heap (%Lx - %Lx) in e820 table\n", base, + (base + size - 1)); + if ( !e820_protect_region(base, size, E820_PROTECTED) ) + return false; + + /* SINIT */ + base = read_pub_config_reg(TXTCR_SINIT_BASE); + size = read_pub_config_reg(TXTCR_SINIT_SIZE); + printk("protecting SINIT (%Lx - %Lx) in e820 table\n", base, + (base + size - 1)); + if ( !e820_protect_region(base, size, E820_PROTECTED) ) + return false; + + /* TBD: we will need to parse sinit_mle_data.mdrs records and ensure */ + /* that we don't use inappropriate memory for domains */ + +#if 0 + /* + * some BIOSes mark the TPM and LT public space as reserved + * this will cause xen to give these regions to dom_io instead of dom0 + * however, if we mark them as protected, then they won't be given + * to dom_io and dom0 will be allowed to map them as MMIO (not as RAM) + * this should have no effect on system's whose BIOS doesn't do this + */ + + /* TPM localities */ + base = TPM_LOCALITY_BASE; + size = NR_TPM_LOCALITY_PAGES * PAGE_SIZE; + printk("protecting TPM localities (%Lx - %Lx) in e820 table\n", + base, (base + size - 1)); + if ( !e820_protect_region(base, size, E820_PROTECTED) ) + return false; + + /* TXT public space */ + base = TXT_PUB_CONFIG_REGS_BASE; + size = NR_TXT_CONFIG_PAGES * PAGE_SIZE; + printk("protecting TXT Public Space (%Lx - %Lx) in e820 table\n", + base, (base + size - 1)); + if ( !e820_protect_region(base, size, E820_PROTECTED) ) + return false; +#endif + + /* TXT private space */ + base = TXT_PRIV_CONFIG_REGS_BASE; + size = NR_TXT_CONFIG_PAGES * PAGE_SIZE; + printk("protecting TXT Private Space (%Lx - %Lx) in e820 table\n", + base, (base + size - 1)); + if ( !e820_protect_region(base, size, E820_PROTECTED) ) + 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 -r 419625d61514 -r de5826b5b302 sboot/txt/verify.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/txt/verify.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,489 @@ +/* + * verify.c: verify that platform and processor supports Intel(r) TXT + * + * Copyright (c) 2003-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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char _stext[]; /* start of text section */ +extern char _end[]; /* end of module */ + +/* + * CPUID extended feature info + */ +static unsigned int g_cpuid_ext_feat_info; + +/* + * IA32_FEATURE_CONTROL_MSR + */ +static unsigned long g_feat_ctrl_msr; + + +static void read_processor_info(void) +{ + unsigned long f1, f2; + + /* is CPUID supported? */ + /* (it's supported if ID flag in EFLAGS can be set and cleared) */ + asm("pushf\n\t" + "pushf\n\t" + "pop %0\n\t" + "mov %0,%1\n\t" + "xor %2,%0\n\t" + "push %0\n\t" + "popf\n\t" + "pushf\n\t" + "pop %0\n\t" + "popf\n\t" + : "=&r" (f1), "=&r" (f2) + : "ir" (X86_EFLAGS_ID)); + if ( ((f1^f2) & X86_EFLAGS_ID) == 0 ) { + g_cpuid_ext_feat_info = 0; + return; + } + + g_cpuid_ext_feat_info = cpuid_ecx(1); + + rdmsrl(IA32_FEATURE_CONTROL_MSR, g_feat_ctrl_msr); +} + +static bool supports_vmx(void) +{ + /* check that processor supports VMX instructions */ + if ( !(g_cpuid_ext_feat_info & X86_FEATURE_VMXE) ) { + printk("ERR: CPU does not support VMX\n"); + return false; + } + printk("CPU is VMX-capable\n"); + + /* and that VMX is enabled in the feature control MSR */ + if ( !(g_feat_ctrl_msr & IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_IN_SMX) ) { + printk("ERR: VMXON disabled by feature control MSR (%lx)\n", + g_feat_ctrl_msr); + return false; + } + + return true; +} + +static bool supports_smx(void) +{ + /* check that processor supports SMX instructions */ + if ( !(g_cpuid_ext_feat_info & X86_FEATURE_SMXE) ) { + printk("ERR: CPU does not support SMX\n"); + return false; + } + printk("CPU is SMX-capable\n"); + + /* + * and that SMX is enabled in the feature control MSR + */ + + /* check that the MSR is locked -- BIOS should always lock it */ + if ( !(g_feat_ctrl_msr & IA32_FEATURE_CONTROL_MSR_LOCK) ) { + printk("ERR: IA32_FEATURE_CONTROL_MSR_LOCK is not locked\n"); + /* in general this should not happen, as BIOS is required to lock */ + /* the MSR; but it may be desirable to allow it sometimes */ +#ifdef PERMISSIVE_BOOT + /* we enable VMX outside of SMX as well so that if there was some */ + /* error in the TXT boot, VMX will continue to work */ + g_feat_ctrl_msr |= IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_IN_SMX | + IA32_FEATURE_CONTROL_MSR_ENABLE_VMX_OUT_SMX | + IA32_FEATURE_CONTROL_MSR_ENABLE_SENTER | + IA32_FEATURE_CONTROL_MSR_SENTER_PARAM_CTL | + IA32_FEATURE_CONTROL_MSR_LOCK; + wrmsrl(IA32_FEATURE_CONTROL_MSR, g_feat_ctrl_msr); + return true; +#else + return false; +#endif + } + + /* check that SENTER (w/ full params) is enabled */ + if ( !(g_feat_ctrl_msr & (IA32_FEATURE_CONTROL_MSR_ENABLE_SENTER | + IA32_FEATURE_CONTROL_MSR_SENTER_PARAM_CTL)) ) { + printk("ERR: SENTER disabled by feature control MSR (%lx)\n", + g_feat_ctrl_msr); + return false; + } + + return true; +} + +static bool supports_txt(void) +{ + capabilities_t cap; + + /* processor must support SMX */ + if ( !supports_smx() || !supports_vmx() ) + return false; + + /* testing for chipset support requires enabling SMX on the processor */ + write_cr4(read_cr4() | X86_CR4_SMXE); + printk("SMX is enabled\n"); + + /* + * verify that an TXT-capable chipset is present and + * check that all needed SMX capabilities are supported + */ + + cap = __getsec_capabilities(0); + if ( cap.chipset_present ) { + if ( cap.senter && cap.sexit && cap.parameters && cap.smctrl && + cap.wakeup ) { + printk("TXT chipset and all needed capabilities present\n"); + return true; + } + else + printk("ERR: insufficient SMX capabilities (%x)\n", cap._raw); + } + else + printk("ERR: TXT-capable chipset not present\n"); + + /* since we are failing, we should clear the SMX flag */ + write_cr4(read_cr4() & ~X86_CR4_SMXE); + + return false; +} + +static void print_bios_os_data(bios_os_data_t *bios_os_data) +{ + printk("bios_os_data:\n"); + printk("\t version=%x\n", bios_os_data->version); + printk("\t bios_sinit_size=%x\n", bios_os_data->bios_sinit_size); +} + +static bool verify_bios_os_data(txt_heap_t *txt_heap) +{ + uint64_t size, heap_size; + bios_os_data_t *bios_os_data; + + /* check size */ + heap_size = read_priv_config_reg(TXTCR_HEAP_SIZE); + size = get_bios_os_data_size(txt_heap); + if ( size == 0 ) { + printk("BIOS to OS data size is 0\n"); + return false; + } + if ( size > heap_size ) { + printk("BIOS to OS data size is larger than heap size " + "(%Lx, heap size=%Lx)\n", size, heap_size); + return false; + } + /* TBD: if we add more versions then this will need to change */ + if ( size < sizeof(bios_os_data_t) ) { + printk("BIOS to OS data size (%Lx) is smaller than " + "bios_os_data_t size (%x)\n", size, sizeof(bios_os_data_t)); + return false; + } + + bios_os_data = get_bios_os_data_start(txt_heap); + + /* check version */ + /* we assume backwards compatibility but print a warning */ + if ( bios_os_data->version > 0x01 ) + printk("unsupported BIOS to OS data version (%x)\n", + bios_os_data->version); + + /* no field checks (bios_sinit_size field can be 0) */ + + print_bios_os_data(bios_os_data); + + return true; +} + +static void print_os_mle_data(os_mle_data_t *os_mle_data) +{ + printk("os_mle_data:\n"); + printk("\t version=%x\n", os_mle_data->version); + /* TBD: perhaps eventually print saved_mtrr_state field */ + printk("\t mbi=%p\n", os_mle_data->mbi); +} + +static bool verify_os_mle_data(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("OS to MLE data size is 0\n"); + return false; + } + if ( size > heap_size ) { + printk("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) ) { + printk("OS to MLE data size (%Lx) is smaller than " + "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 != 0x01 ) { + printk("unsupported OS to MLE data version (%x)\n", + os_mle_data->version); + return false; + } + + /* field checks */ + if ( os_mle_data->mbi == NULL ) { + printk("OS to MLE data mbi field is NULL\n"); + return false; + } + + print_os_mle_data(os_mle_data); + + return true; +} + +void print_os_sinit_data(os_sinit_data_t *os_sinit_data) +{ + printk("os_sinit_data:\n"); + printk("\t version=%x\n", os_sinit_data->version); + printk("\t mle_ptab=%Lx\n", os_sinit_data->mle_ptab); + printk("\t mle_size=%Lx\n", os_sinit_data->mle_size); + printk("\t mle_hdr_base=%Lx\n", os_sinit_data->mle_hdr_base); +} + +static bool verify_os_sinit_data(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("OS to SINIT data size is 0\n"); + return false; + } + if ( size > heap_size ) { + printk("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 */ + if ( os_sinit_data->version > 0x03 ) { + printk("unsupported OS to SINIT data version (%x)\n", + os_sinit_data->version); + return false; + } + + /* if it is version 0x01 then none of the fields get used post-launch */ + /* so no need to verify them (SINIT will have done that) */ + + print_os_sinit_data(os_sinit_data); + + return true; +} + +static void print_sinit_mdrs(sinit_mdr_t mdrs[], uint32_t num_mdrs) +{ + int i; + static char *mem_types[] = {"GOOD", "SMRAM OVERLAY", "SMRAM NON-OVERLAY", + "PCIE EXTENDED CONFIG", "PROTECTED"}; + + printk("\t sinit_mdrs:\n"); + for ( i = 0; i < num_mdrs; i++ ) { + printk("\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("(%s)\n", mem_types[mdrs[i].mem_type]); + else + printk("(%d)\n", (int)mdrs[i].mem_type); + } +} + +static void print_sinit_mle_data(sinit_mle_data_t *sinit_mle_data) +{ + printk("sinit_mle_data:\n"); + printk("\t version=%x\n", sinit_mle_data->version); + if ( sinit_mle_data->version == 0x01 ) + print_sinit_mdrs(sinit_mle_data->v1.mdrs, sinit_mle_data->v1.num_mdrs); +} + +static bool verify_sinit_mle_data(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("SINIT to MLE data size is 0\n"); + return false; + } + if ( size > heap_size ) { + printk("SINIT to MLE data size is larger than heap size\n" + "(%Lx, heap size=%Lx)\n", size, heap_size); + /* TBD: un-comment this when have fixed SINIT + return false; */ + } + + sinit_mle_data = get_sinit_mle_data_start(txt_heap); + + /* check version */ + sinit_mle_data = get_sinit_mle_data_start(txt_heap); + if ( sinit_mle_data->version > 0x01 ) + { + printk("unsupported SINIT to MLE data version (%x)\n", + sinit_mle_data->version); + return false; + } + + /* 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(txt_heap_t *txt_heap, bool bios_os_data_only) +{ + uint64_t size1, size2, size3, size4; + + /* verify BIOS to OS data */ + if ( !verify_bios_os_data(txt_heap) ) + return false; + + if ( bios_os_data_only ) + return true; + + /* check that total size is within the heap */ + size1 = get_bios_os_data_size(txt_heap); + size2 = get_os_mle_data_size(txt_heap); + size3 = get_os_sinit_data_size(txt_heap); + size4 = get_sinit_mle_data_size(txt_heap); + if ( (size1 + size2 + size3 + size4) > + read_priv_config_reg(TXTCR_HEAP_SIZE) ) { + printk("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)); + /* TBD: un-comment this when have fixed SINIT + 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; +} + +bool txt_verify_platform(void) +{ + txt_heap_t *txt_heap; + bios_os_data_t *bios_os_data; + + read_processor_info(); + + /* support Intel(r) TXT (this includes TPM support) */ + if ( !supports_txt() ) + return false; + + /* check that we support the BIOS to OS data version */ + txt_heap = get_txt_heap(); + bios_os_data = get_bios_os_data_start(txt_heap); + if ( bios_os_data->version > 0x01 ) { + printk("BIOS to OS data version incompatible (%x)\n", + bios_os_data->version); + return false; + } + + return true; +} + +bool txt_post_launch_verify_platform(void) +{ + txt_heap_t *txt_heap; + + /* + * verify some of the heap structures + */ + txt_heap = get_txt_heap(); + + if ( !verify_txt_heap(txt_heap, false) ) + return false; + + /* TBD: verify the saved MTRRs */ + + /* TBD: verify the e820 table against the SINIT MDRs */ + + return true; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 419625d61514 -r de5826b5b302 sboot/txt/vmcs.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sboot/txt/vmcs.c Fri Jun 08 16:57:19 2007 -0700 @@ -0,0 +1,622 @@ +/* + * vmcs.c: create and manage mini-VT VM for APs to handle INIT-SIPI-SIPI + * + * Copyright (c) 2003-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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* no vmexit on external intr as mini guest only handle INIT & SIPI */ +#define MONITOR_PIN_BASED_EXEC_CONTROLS \ + (PIN_BASED_NMI_EXITING) + +#define MONITOR_CPU_BASED_EXEC_CONTROLS_SUBARCH 0 + +#define MONITOR_VM_EXIT_CONTROLS_SUBARCH 0 + +/* no vmexit on hlt as guest only run this instruction */ +#define MONITOR_CPU_BASED_EXEC_CONTROLS \ + ( MONITOR_CPU_BASED_EXEC_CONTROLS_SUBARCH | \ + CPU_BASED_INVDPG_EXITING | \ + CPU_BASED_MWAIT_EXITING ) + +#define MONITOR_VM_EXIT_CONTROLS \ + ( MONITOR_VM_EXIT_CONTROLS_SUBARCH | \ + VM_EXIT_ACK_INTR_ON_EXIT ) + +/* Basic flags for VM-Entry controls. */ +#define MONITOR_VM_ENTRY_CONTROLS 0x00000000 + +#define GUEST_SEGMENT_LIMIT 0xffffffff +#define EXCEPTION_BITMAP_BP (1 << 3) /* Breakpoint */ +#define EXCEPTION_BITMAP_PG (1 << 14) /* Page Fault */ +#define MONITOR_DEFAULT_EXCEPTION_BITMAP \ + ( EXCEPTION_BITMAP_PG | \ + EXCEPTION_BITMAP_BP ) + +#define load_TR(n) __asm__ __volatile__ ("ltr %%ax" : : "a" ((n)<<3) ) + +DEFINE_SPINLOCK(ap_init_lock); + +/* Dynamic (run-time adjusted) execution control flags. */ +static uint32_t vmx_pin_based_exec_control; +static uint32_t vmx_cpu_based_exec_control; +static uint32_t vmx_vmexit_control; +static uint32_t vmx_vmentry_control; + +static uint32_t vmcs_revision_id; + +extern void print_cr0(const char *s); + +static uint32_t adjust_vmx_controls(uint32_t ctrls, uint32_t msr) +{ + uint32_t vmx_msr_low, vmx_msr_high; + + rdmsr(msr, vmx_msr_low, vmx_msr_high); + + /* TBD: need to handle this error */ + /* Bit == 0 means must be zero. */ + BUG_ON(ctrls & ~vmx_msr_high); + + /* Bit == 1 means must be one. */ + ctrls |= vmx_msr_low; + + return ctrls; +} + +static void vmx_init_vmcs_config(void) +{ + uint32_t vmx_msr_low, vmx_msr_high; + uint32_t _vmx_pin_based_exec_control; + uint32_t _vmx_cpu_based_exec_control; + uint32_t _vmx_vmexit_control; + uint32_t _vmx_vmentry_control; + static int vmcs_config_init = 0; + + _vmx_pin_based_exec_control = + adjust_vmx_controls(MONITOR_PIN_BASED_EXEC_CONTROLS, + MSR_IA32_VMX_PINBASED_CTLS_MSR); + _vmx_cpu_based_exec_control = + adjust_vmx_controls(MONITOR_CPU_BASED_EXEC_CONTROLS, + MSR_IA32_VMX_PROCBASED_CTLS_MSR); + _vmx_vmexit_control = + adjust_vmx_controls(MONITOR_VM_EXIT_CONTROLS, + MSR_IA32_VMX_EXIT_CTLS_MSR); + _vmx_vmentry_control = + adjust_vmx_controls(MONITOR_VM_ENTRY_CONTROLS, + MSR_IA32_VMX_ENTRY_CTLS_MSR); + + rdmsr(MSR_IA32_VMX_BASIC_MSR, vmx_msr_low, vmx_msr_high); + + if ( vmcs_config_init == 0 ) { + vmcs_revision_id = vmx_msr_low; + vmx_pin_based_exec_control = _vmx_pin_based_exec_control; + vmx_cpu_based_exec_control = _vmx_cpu_based_exec_control; + vmx_vmexit_control = _vmx_vmexit_control; + vmx_vmentry_control = _vmx_vmentry_control; + vmcs_config_init = 1; + } + else if ( (vmcs_revision_id != vmx_msr_low) || + (vmx_pin_based_exec_control != _vmx_pin_based_exec_control) || + (vmx_cpu_based_exec_control != _vmx_cpu_based_exec_control) || + (vmx_vmexit_control != _vmx_vmexit_control) || + (vmx_vmentry_control != _vmx_vmentry_control) ) + printk("vmx_init_config different on different AP.\n"); + + /* TBD: handle this as an error */ + /* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */ + if ( (vmx_msr_high & 0x1fff) > PAGE_SIZE ) + printk("vmcs size wrong.\n"); +} + +extern uint32_t idle_pg_table[PAGE_SIZE / 4]; +extern char vmcs_end[]; /* end of vmcs region */ + +/* build a 1-level identity-map page table on AP for vmxon*/ +static void build_ap_pagetable(void) +{ + uint32_t pt_entry = 0xe3; /* PRESENT+RW+A+D+4MB */ + uint32_t *pte = &idle_pg_table[0]; + uint32_t sboot_end = (uint32_t)&vmcs_end; + while ( pt_entry <= sboot_end + 0xe3 ) { + *pte = pt_entry; + pt_entry += ( 1 << L2_PAGETABLE_SHIFT ); + pte++; + } + printk("build 4M page table %p.\n", idle_pg_table); +} + +extern char host_vmcs[PAGE_SIZE]; +extern char ap_vmcs[PAGE_SIZE]; + +static bool start_vmx(void) +{ + uint32_t eax, edx; + struct vmcs_struct *vmcs; + + vmcs = (struct vmcs_struct*)host_vmcs; + memset(vmcs, 0, PAGE_SIZE); + + set_in_cr4(X86_CR4_VMXE); + + vmx_init_vmcs_config(); + vmcs->vmcs_revision_id = vmcs_revision_id; + + rdmsr(MSR_EFER, eax, edx); + + /* enable paging as required by vmentry */ + build_ap_pagetable(); + write_cr3((unsigned long)idle_pg_table); + set_in_cr4(X86_CR4_PSE); + write_cr0(read_cr0() | X86_CR0_PG); + + if ( __vmxon((unsigned long)vmcs) ) { + clear_in_cr4(X86_CR4_VMXE); + clear_in_cr4(X86_CR4_PSE); + write_cr0(read_cr0() & ~X86_CR0_PG); + printk("VMXON failed\n"); + return false; + } + + printk("VMXON done.\n"); + return true; +} + +static void stop_vmx(void) +{ + if ( !(read_cr4() & X86_CR4_VMXE) ) + return; + + __vmpclear((unsigned long)ap_vmcs); + __vmxoff(); + + clear_in_cr4(X86_CR4_VMXE); + + /* diable paging to restore AP's state to boot xen */ + write_cr0(read_cr0() & ~X86_CR0_PG); + clear_in_cr4(X86_CR4_PSE); +} + +/* Dump a section of VMCS */ +static void print_section(const char *header, uint32_t start, uint32_t end, + int incr) +{ + uint32_t addr, j; + unsigned long val; + int code, rc; + static char *fmt[4] = {"0x%04lx ", "0x%016lx ", "0x%08lx ", "0x%016lx "}; + static char *err[4] = {"------ ", "------------------ ", "---------- ", + "------------------ "}; + + /* Find width of the field (encoded in bits 14:13 of address) */ + code = (start >> 13) & 3; + + if ( header ) + printk("\t %s", header); + + for ( addr = start, j = 0; addr <= end; addr += incr, j++ ) { + if ( !(j & 3) ) + printk("\n\t 0x%08x: ", addr); + + val = __vmread_safe(addr, &rc); + if ( rc == 0 ) + printk(fmt[code], val); + else + printk("%s", err[code]); + } + + printk("\n"); +} + +/* Dump current VMCS */ +static void vmcs_dump_vcpu(void) +{ + print_section("16-bit Guest-State Fields", 0x800, 0x80e, 2); + print_section("16-bit Host-State Fields", 0xc00, 0xc0c, 2); + print_section("64-bit Control Fields", 0x2000, 0x2013, 1); + print_section("64-bit Guest-State Fields", 0x2800, 0x2803, 1); + print_section("32-bit Control Fields", 0x4000, 0x401c, 2); + print_section("32-bit RO Data Fields", 0x4400, 0x440e, 2); + print_section("32-bit Guest-State Fields", 0x4800, 0x482a, 2); + print_section("32-bit Host-State Fields", 0x4c00, 0x4c00, 2); + print_section("Natural 64-bit Control Fields", 0x6000, 0x600e, 2); + print_section("64-bit RO Data Fields", 0x6400, 0x640A, 2); + print_section("Natural 64-bit Guest-State Fields", 0x6800, 0x6826, 2); + print_section("Natural 64-bit Host-State Fields", 0x6c00, 0x6c16, 2); +} + +/* in sboot/common/boot.S */ +extern void vmx_asm_vmexit_handler(void); +extern void _mini_guest(void); + +/* consturct guest/host vmcs: + * make guest vmcs from physical environment, + * so only one binary switch between root and non-root + */ +static void construct_vmcs(void) +{ + struct { + uint16_t limit; + uint32_t base; + } __attribute__ ((packed)) xdt; + unsigned long cr0, cr3, cr4, eflags, rsp; + unsigned int tr; + union vmcs_arbytes arbytes; + uint16_t seg; + + __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control); + __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control); + __vmwrite(VM_ENTRY_CONTROLS, vmx_vmentry_control); + __vmwrite(CPU_BASED_VM_EXEC_CONTROL, vmx_cpu_based_exec_control); + + /* segments selectors. */ + __asm__ __volatile__ ("movl %%ss, %0\n" : "=r"(seg)); + __vmwrite(HOST_SS_SELECTOR, seg); + __vmwrite(GUEST_SS_SELECTOR, seg); + + __asm__ __volatile__ ("movl %%ds, %0\n" : "=r"(seg)); + __vmwrite(HOST_DS_SELECTOR, seg); + __vmwrite(GUEST_DS_SELECTOR, seg); + + __asm__ __volatile__ ("movl %%es, %0\n" : "=r"(seg)); + __vmwrite(HOST_ES_SELECTOR, seg); + __vmwrite(GUEST_ES_SELECTOR, seg); + + __asm__ __volatile__ ("movl %%fs, %0\n" : "=r"(seg)); + __vmwrite(HOST_FS_SELECTOR, seg); + __vmwrite(GUEST_FS_SELECTOR, seg); + + __asm__ __volatile__ ("movl %%gs, %0\n" : "=r"(seg)); + __vmwrite(HOST_GS_SELECTOR, seg); + __vmwrite(GUEST_GS_SELECTOR, seg); + + __asm__ __volatile__ ("movl %%cs, %0\n" : "=r"(seg)); + __vmwrite(GUEST_CS_SELECTOR, seg); + __vmwrite(GUEST_RIP, (uint32_t)&_mini_guest); + + __vmwrite(HOST_CS_SELECTOR, seg); + __vmwrite(HOST_RIP, (unsigned long)vmx_asm_vmexit_handler); + + /* segment limits */ + __vmwrite(GUEST_ES_LIMIT, GUEST_SEGMENT_LIMIT); + __vmwrite(GUEST_SS_LIMIT, GUEST_SEGMENT_LIMIT); + __vmwrite(GUEST_DS_LIMIT, GUEST_SEGMENT_LIMIT); + __vmwrite(GUEST_FS_LIMIT, GUEST_SEGMENT_LIMIT); + __vmwrite(GUEST_GS_LIMIT, GUEST_SEGMENT_LIMIT); + __vmwrite(GUEST_CS_LIMIT, GUEST_SEGMENT_LIMIT); + + /* segment AR bytes, see boot.S for details */ + arbytes.bytes = 0; + arbytes.fields.seg_type = 0x3; /* type = 3 */ + arbytes.fields.s = 1; /* code or data, i.e. not system */ + arbytes.fields.dpl = 0; /* DPL = 0 */ + arbytes.fields.p = 1; /* segment present */ + arbytes.fields.default_ops_size = 1; /* 32-bit */ + arbytes.fields.g = 1; + + arbytes.fields.null_bit = 0; /* not null */ + __vmwrite(GUEST_ES_AR_BYTES, arbytes.bytes); + __vmwrite(GUEST_SS_AR_BYTES, arbytes.bytes); + __vmwrite(GUEST_DS_AR_BYTES, arbytes.bytes); + __vmwrite(GUEST_FS_AR_BYTES, arbytes.bytes); + __vmwrite(GUEST_GS_AR_BYTES, arbytes.bytes); + + arbytes.fields.seg_type = 0xb; /* type = 0xb */ + __vmwrite(GUEST_CS_AR_BYTES, arbytes.bytes); + + /* segment BASE */ + __vmwrite(GUEST_ES_BASE, 0); + __vmwrite(GUEST_SS_BASE, 0); + __vmwrite(GUEST_DS_BASE, 0); + __vmwrite(GUEST_FS_BASE, 0); + __vmwrite(GUEST_GS_BASE, 0); + __vmwrite(GUEST_CS_BASE, 0); + + __vmwrite(HOST_FS_BASE, 0); + __vmwrite(HOST_GS_BASE, 0); + + /* Guest LDT and TSS */ + __vmwrite(GUEST_LDTR_SELECTOR, 0); + __vmwrite(GUEST_LDTR_BASE, 0); + __vmwrite(GUEST_LDTR_LIMIT, 0xffff); + + __asm__ __volatile__ ("str (%0) \n" :: "a"(&tr) : "memory"); + if ( tr == 0 ) + printk("tr is 0 on ap, may vmlaunch fail.\n"); + __vmwrite(GUEST_TR_SELECTOR, tr); + __vmwrite(GUEST_TR_BASE, 0); + __vmwrite(GUEST_TR_LIMIT, 0xffff); + + __vmwrite(HOST_TR_SELECTOR, tr); + __vmwrite(HOST_TR_BASE, 0); + + + /* sboot do not use ldt */ + arbytes.bytes = 0; + arbytes.fields.s = 0; /* not code or data segement */ + arbytes.fields.seg_type = 0x2; /* LTD */ + arbytes.fields.p = 1; /* segment present */ + arbytes.fields.default_ops_size = 0; /* 16-bit */ + arbytes.fields.g = 1; + __vmwrite(GUEST_LDTR_AR_BYTES, arbytes.bytes); + + /* setup a TSS for vmentry as zero TR is not allowed */ + arbytes.bytes = 0; + arbytes.fields.s = 0; /* not code or data seg */ + arbytes.fields.seg_type = 0xb; /* 32-bit TSS (busy) */ + arbytes.fields.p = 1; /* segment present */ + arbytes.fields.default_ops_size = 0; /* 16-bit */ + arbytes.fields.g = 1; + __vmwrite(GUEST_TR_AR_BYTES, arbytes.bytes); + + /* GDT */ + __asm__ __volatile__ ("sgdt (%0) \n" :: "a"(&xdt) : "memory"); + __vmwrite(GUEST_GDTR_BASE, xdt.base); + __vmwrite(GUEST_GDTR_LIMIT, xdt.limit); + + __vmwrite(HOST_GDTR_BASE, xdt.base); + + /* IDT */ + __asm__ __volatile__ ("sidt (%0) \n" :: "a"(&xdt) : "memory"); + printk("idt.base=0x%x, limit=0x%x.\n", xdt.base, xdt.limit); + /* TBD: sboot's idt base is not cannonical, so use 0 */ + __vmwrite(GUEST_IDTR_BASE, 0); + __vmwrite(GUEST_IDTR_LIMIT, xdt.limit); + + __vmwrite(HOST_IDTR_BASE, xdt.base); + + /* control registers. */ + cr0 = read_cr0(); + cr3 = read_cr3(); + cr4 = read_cr4(); + __vmwrite(HOST_CR0, cr0); + __vmwrite(HOST_CR4, cr4); + __vmwrite(HOST_CR3, cr3); + + __vmwrite(GUEST_CR0, cr0); + __vmwrite(CR0_READ_SHADOW, cr0); + __vmwrite(GUEST_CR4, cr4); + __vmwrite(CR4_READ_SHADOW, cr4); + __vmwrite(GUEST_CR3, cr3); + + /* debug register */ + __vmwrite(GUEST_DR7, 0); + + /* rflags & rsp */ + __save_flags(eflags); + __vmwrite(GUEST_RFLAGS, eflags); + + __asm__ __volatile__ ("mov %%esp,%0\n\t" :"=r" (rsp)); + __vmwrite(GUEST_RSP, rsp); + __vmwrite(HOST_RSP, rsp); + + /* MSR intercepts. */ + __vmwrite(VM_EXIT_MSR_LOAD_ADDR, 0); + __vmwrite(VM_EXIT_MSR_STORE_ADDR, 0); + __vmwrite(VM_EXIT_MSR_STORE_COUNT, 0); + __vmwrite(VM_EXIT_MSR_LOAD_COUNT, 0); + __vmwrite(VM_ENTRY_MSR_LOAD_COUNT, 0); + + __vmwrite(VM_ENTRY_INTR_INFO_FIELD, 0); + + __vmwrite(CR0_GUEST_HOST_MASK, ~0UL); + __vmwrite(CR4_GUEST_HOST_MASK, ~0UL); + + __vmwrite(PAGE_FAULT_ERROR_CODE_MASK, 0); + __vmwrite(PAGE_FAULT_ERROR_CODE_MATCH, 0); + + __vmwrite(CR3_TARGET_COUNT, 0); + + /* guest need do nothing but vmexit when INIT-SIPI-SIPI */ + __vmwrite(GUEST_ACTIVITY_STATE, GUEST_STATE_HALT); + + __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0); + __vmwrite(VMCS_LINK_POINTER, ~0UL); + + __vmwrite(VMCS_LINK_POINTER_HIGH, ~0UL); + + __vmwrite(EXCEPTION_BITMAP, MONITOR_DEFAULT_EXCEPTION_BITMAP); + + printk("vmcs setup done.\n"); +} + +static void vmx_create_vmcs(void) +{ + struct vmcs_struct *vmcs = (struct vmcs_struct*)ap_vmcs; + + memset(vmcs, 0, PAGE_SIZE); + + vmcs->vmcs_revision_id = vmcs_revision_id; + + /* vir addr equal to phy addr as we setup identity page table */ + __vmpclear((unsigned long)vmcs); + + __vmptrld((unsigned long)vmcs); + + construct_vmcs(); +} + +static void launch_mini_guest(void) +{ + unsigned long error; + + __vmlaunch(); + + /* should not reach here */ + error = __vmread(VM_INSTRUCTION_ERROR); + printk(" error code %lx\n", error); + printk("************* VMCS Area **************\n"); + vmcs_dump_vcpu(); + printk("**************************************\n"); +} + +static void vmx_failed_vmentry(unsigned int exit_reason) +{ + unsigned int failed_vmentry_reason = (uint16_t)exit_reason; + unsigned long exit_qualification; + + exit_qualification = __vmread(EXIT_QUALIFICATION); + printk("Failed vm entry (exit reason 0x%x) ", exit_reason); + switch ( failed_vmentry_reason ) + { + case EXIT_REASON_INVALID_GUEST_STATE: + printk("caused by invalid guest state (%ld).\n", + exit_qualification); + break; + case EXIT_REASON_MSR_LOADING: + printk("caused by MSR entry %ld loading.\n", exit_qualification); + break; + case EXIT_REASON_MACHINE_CHECK: + printk("caused by machine check.\n"); + break; + default: + printk("reason not known yet!"); + break; + } + + printk("************* VMCS Area **************\n"); + vmcs_dump_vcpu(); + printk("**************************************\n"); +} + +/* Vmexit handler for physical INIT-SIPI-SIPI from the BSP + * Do not use printk in this critical path as BSP only + * wait for a short time + */ +void vmx_vmexit_handler(void) +{ + unsigned long error; + unsigned int exit_reason, apicid; + static int state = AP_WAIT_INIT; + + exit_reason = __vmread(VM_EXIT_REASON); +/* printk("vmx_vmexit_handler, exit_reason=%x.\n", exit_reason);*/ + + if ( (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) ) { + printk("failed vmentry.\n"); + vmx_failed_vmentry(exit_reason); + goto out; + } + + switch ( exit_reason ) + { + case EXIT_REASON_INIT: + if ( state == AP_WAIT_INIT ) { + state = AP_WAIT_SIPI1; + __vmwrite(GUEST_ACTIVITY_STATE, GUEST_STATE_WAIT_SIPI); + } + break; + case EXIT_REASON_SIPI: + if ( state == AP_WAIT_SIPI1 ) { + state = AP_WAIT_SIPI2; + __vmwrite(GUEST_ACTIVITY_STATE, GUEST_STATE_WAIT_SIPI); + } + else if ( state == AP_WAIT_SIPI2 ) + state = AP_WAIT_DONE; + break; + default: + printk("can't handle vmexit due to 0x%x.\n", exit_reason); + } + + if ( state == AP_WAIT_DONE ) { /* disable VT then jump to xen code */ +/* printk("sucessfully handle INIT-SIPI-SIPI on AP.\n");*/ + stop_vmx(); + state = AP_WAIT_INIT; + spin_unlock(&ap_init_lock); + apicid = cpuid_ebx(1) >> 24; + cpu_wakeup(apicid); + return; + } + + /* resume mini guest to handle following signal */ + __vmresume(); + + /* should not reach here */ + error = __vmread(VM_INSTRUCTION_ERROR); + printk(" error code %lx\n", error); + +out: + printk("************* VMCS Area **************\n"); + vmcs_dump_vcpu(); + printk("**************************************\n"); + + spin_unlock(&ap_init_lock); +} + +/* Launch a mini guest to handle the physical INIT-SIPI-SIPI from BSP */ +void handle_init_sipi_sipi(void) +{ + /* setup a dummy tss as vmentry require a non-zero host TR */ + load_TR(3); + + /* handle APs one by one by a big spinlock, */ + spin_lock(&ap_init_lock); + + /* prepare a guest for INIT-SIPI-SIPI handling */ + /* 1: setup VMX environment and VMXON */ + if ( !start_vmx() ) + goto out; + + /* 2: setup VMCS */ + vmx_create_vmcs(); + + /* 3: launch VM */ + launch_mini_guest(); + +out: + spin_unlock(&ap_init_lock); +} + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */