# 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) +{