diff --git a/trenchboot/skboot/.gitignore b/trenchboot/skboot/.gitignore new file mode 100644 index 0000000..1863ced --- /dev/null +++ b/trenchboot/skboot/.gitignore @@ -0,0 +1,7 @@ +*.o +*.efi +*.dsm +*.hex +*.gz +skboot +skboot-syms diff --git a/trenchboot/skboot/Config.mk b/trenchboot/skboot/Config.mk new file mode 100644 index 0000000..0f290d6 --- /dev/null +++ b/trenchboot/skboot/Config.mk @@ -0,0 +1,77 @@ +# Copyright (c) 2006-2010, Intel Corporation +# All rights reserved. + +# -*- mode: Makefile; -*- + +# debug build +debug ?= n + +# cc-option: Check if compiler supports first option, else fall back to second. +# Usage: cflags-y += $(call cc-option,$(CC),-march=winchip-c6,-march=i586) +cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \ + /dev/null 2>&1`"; then echo "$(2)"; else echo "$(3)"; fi ;) + +CFLAGS_WARN = -Wall -Wformat-security -Werror -Wstrict-prototypes \ + -Wextra -Winit-self -Wswitch-default -Wunused-parameter \ + -Wwrite-strings \ + $(call cc-option,$(CC),-Wlogical-op,) \ + -Wno-missing-field-initializers + +AS = as +LD = ld +CC = gcc +CPP = cpp +AR = ar +RANLIB = ranlib +NM = nm +STRIP = strip +OBJCOPY = objcopy +OBJDUMP = objdump + +CFLAGS += $(CFLAGS_WARN) -fno-strict-aliasing -std=gnu99 +# due to bug in gcc v4.2,3,? +CFLAGS += $(call cc-option,$(CC),-Wno-array-bounds,) + + +ifeq ($(debug),y) +CFLAGS += -g -DDEBUG +else +CFLAGS += -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 +endif + +# +# slboot-specific build settings +# +RELEASEVER := "1.0.0" +RELEASETIME := "2021-08-01 15:00 +0800" + +# if target arch is 64b, then convert -m64 to -m32 (skboot is always 32b) +CFLAGS += -m32 +CFLAGS += -march=i686 +CFLAGS += -nostdinc +CFLAGS += -fno-builtin -fno-common -fno-strict-aliasing +CFLAGS += -fomit-frame-pointer +CFLAGS += -pipe +CFLAGS += -iwithprefix include +CFLAGS += -I$(CURDIR)/include +# ensure no floating-point variables +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 += $(call cc-option,$(CC),-fno-stack-check,) + +# changeset variable for banner +CFLAGS += -DSKBOOT_CHANGESET=\""$(shell ((hg parents --template "{isodate|isodate} {rev}:{node|short}" >/dev/null && hg parents --template "{isodate|isodate} {rev}:{node|short}") || echo "$(RELEASETIME) $(RELEASEVER)") 2>/dev/null)"\" + + +AFLAGS += -D__ASSEMBLY__ + +# Most CFLAGS are safe for assembly files: +# -std=gnu{89,99} gets confused by #-prefixed end-of-line comments +AFLAGS += $(patsubst -std=gnu%,,$(CFLAGS)) + + +# LDFLAGS are only passed directly to $(LD) +LDFLAGS = -melf_i386 diff --git a/trenchboot/skboot/Makefile b/trenchboot/skboot/Makefile new file mode 100644 index 0000000..786bf3c --- /dev/null +++ b/trenchboot/skboot/Makefile @@ -0,0 +1,138 @@ +# Copyright (c) 2006-2010, Intel Corporation +# All rights reserved. + +# -*- mode: Makefile; -*- + +# +# skboot makefile +# + +include $(CURDIR)/Config.mk + +TARGET := $(CURDIR)/skboot + +# boot.o must be first +obj-y := common/boot.o +obj-y += common/cmdline.o common/com.o common/e820.o +obj-y += common/linux.o common/loader.o +obj-y += common/misc.o common/pci.o common/printk.o +obj-y += common/string.o common/skboot.o common/skl.o +obj-y += common/sha1.o common/sha256.o +obj-y += common/tpm.o common/tpm_12.o common/tpm_20.o +obj-y += common/vga.o + +OBJS := $(obj-y) + + +TARGET_LDS := $(CURDIR)/common/skboot.lds + +$(TARGET).gz : $(TARGET) + gzip -n -f -9 < $< > $@ + +$(TARGET) : $(OBJS) $(TARGET_LDS) + $(LD) $(LDFLAGS) -T $(TARGET_LDS) -N $(OBJS) -o $(@D)/.$(@F).0 + $(NM) -n $(@D)/.$(@F).0 >$(TARGET)-syms + $(LD) $(LDFLAGS) -T $(TARGET_LDS) $(LDFLAGS_STRIP) $(@D)/.$(@F).0 -o $(TARGET) + rm -f $(@D)/.$(@F).0 + +#$(TARGET_LDS) : $(TARGET_LDS).x $(HDRS) +# $(CPP) -P -E -Ui386 $(AFLAGS) -o $@ $< + +#$(TARGET_LDS).x : FORCE + +#.PHONY: FORCE +#FORCE : +# @: # do nothing +# +# universal rules +# +dist : install + + +build : $(TARGET).gz + + +install : $(DISTDIR)/boot/$(TARGET).gz + +$(DISTDIR)/boot/$(TARGET).gz : $(TARGET).gz + [ -d $(DISTDIR)/boot ] || $(INSTALL_DIR) $(DISTDIR)/boot + $(INSTALL_DATA) $(TARGET).gz $(DISTDIR)/boot/$(notdir $(TARGET)).gz + $(INSTALL_DATA) $(TARGET)-syms $(DISTDIR)/boot/$(notdir $(TARGET))-syms + [ -d $(DISTDIR)/etc/grub.d ] || $(INSTALL_DIR) $(DISTDIR)/etc/grub.d + $(INSTALL) -m755 -t $(DISTDIR)/etc/grub.d 20* + + +clean : + rm -f $(TARGET)* *~ include/*~ include/txt/*~ *.o common/*~ txt/*~ common/*.o txt/*.o + rm -f tags TAGS cscope.files cscope.in.out cscope.out cscope.po.out + + +distclean : clean + + +# +# TAGS / tags +# +define all_sources + ( find . -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 \ + --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 + +# +# cscope +# +.PHONY: cscope +cscope : + $(all_sources) > cscope.files + cscope -k -b -q + +# +# MAP +# +.PHONY: MAP +MAP : + $(NM) -n $(TARGET)-syms | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' > System.map + +# +# implicit rules +# + +HDRS := $(wildcard $(CURDIR)/include/*.h) +HDRS += $(wildcard $(CURDIR)/include/txt/*.h) + +BUILD_DEPS := $(CURDIR)/Config.mk $(CURDIR)/Makefile + +# fix case where gcc doesn't use builtin memcmp() when built w/o optimizations +ifeq ($(debug),y) +CFLAGS += -O2 +endif + +%.o : %.c $(HDRS) $(BUILD_DEPS) + $(CC) $(CFLAGS) -c $< -o $@ + +%.o : %.S $(HDRS) $(BUILD_DEPS) + $(CC) $(AFLAGS) -c $< -o $@ + +%.i : %.c $(HDRS) $(BUILD_DEPS) + $(CPP) $(CFLAGS) $< -o $@ + +# -std=gnu{89,99} gets confused by # as an end-of-line comment marker +%.s : %.S $(HDRS) $(BUILD_DEPS) + $(CPP) $(AFLAGS) $< -o $@ diff --git a/trenchboot/skboot/common/boot.S b/trenchboot/skboot/common/boot.S new file mode 100644 index 0000000..5980f93 --- /dev/null +++ b/trenchboot/skboot/common/boot.S @@ -0,0 +1,219 @@ +/* + * boot.S: assembly bootstrapping code for skboot module + * + * Copyright (c) 2006-2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include + +#define BSP_STACK_SIZE 0x2000 + +#define cs_sel 1<<3 +#define ds_sel 2<<3 +#define cs16_sel 4<<3 +#define ds16_sel 5<<3 + +.section ".skboot_multiboot_header","w" + .align 4 +/* multiboot header */ +multiboot_header: +#define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_HEADER_MODS_ALIGNED | \ + MULTIBOOT_HEADER_WANT_MEMORY) + /* magic number for multiboot header */ + .long MULTIBOOT_HEADER_MAGIC + /* flags for bootloader */ + .long MULTIBOOT_HEADER_FLAGS + /* checksum: negated sum of above */ + .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) + +/* multiboot2 header */ + .align 8 +multiboot2_header: + .long MB2_HEADER_MAGIC + .long MB2_ARCH_X86 + .long multiboot2_header_end - multiboot2_header + /* checksum */ + .long -(MB2_HEADER_MAGIC + MB2_ARCH_X86 + (multiboot2_header_end - multiboot2_header)) +multiboot2_header_end: + /* tag requests here--RLM, fix me!! Well, maybe! */ + .short MB2_HDR_TAG_END + .short 0 + .long 8 + + .text + +ENTRY(start) +ENTRY(_start) + jmp __start + +ENTRY(__start) + /* Set up a few descriptors: on entry only CS is guaranteed good. */ + lgdt %cs:gdt_descr + mov $(ds_sel),%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 + + /* preserve EAX to be a param to begin_launch--it should + * contain either MULTIBOOT_MAGIC or MULTIBOOT2_MAGIC--we'll need + * to figure out which */ + mov %eax,%edx + + /* Initialize BSS (no nasty surprises!) */ + mov $__bss_start,%edi + mov $_end,%ecx + sub %edi,%ecx + xor %eax,%eax + rep stosb + + /* Load IDT */ + lidt idt_descr + + /* enable MCE */ + mov %cr4,%eax + or $CR4_MCE,%eax + mov %eax,%cr4 + + /* pass multiboot info struct, magic and call measured launch code */ + push %edx + push %ebx + call begin_launch + ud2 + +/* + * interrupt handler + */ + +int_handler: + call handle_exception + ud2 + +/* + * descriptors and descriptor tables + */ + + .align 8 + +/* GDT */ +gdt_descr: + .word gdt_table_end - gdt_table - 1 + .long gdt_table + + .align PAGE_SIZE, 0 + +ENTRY(gdt_table) + /* unused */ + .quad 0x0000000000000000 +cs_descr: /* cs */ + .word 0xffff /* limit = 4GB */ + .word 0x00 /* base = 0 */ + .word 0x9b00 /* read + exec + accessed */ + .word 0x00cf /* granularity = 4096 */ +ds_descr: /* ds */ + .word 0xffff /* limit = 4GB */ + .word 0x00 /* base = 0 */ + .word 0x9300 /* read + write + accessed */ + .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 */ +cs16_desc: /* cs16 */ + .word 0xffff /* limit = 4GB */ + .word 0x0000 /* base = 0 */ + .word 0x9b00 /* read + exec + accessed */ + .word 0x008f /* granularity = 4096, D = 0 */ +ds16_desc: /* ds16 */ + .word 0xffff /* limit = 4GB */ + .word 0x0000 /* base = 0 */ + .word 0x9300 /* read + exec + accessed */ + .word 0x008f /* granularity = 4096, D = 0 */ + /* end (unused) */ + .quad 0x0000000000000000 +ENTRY(gdt_table_end) + +/* IDT */ +idt_descr: + .word idt_table_end - idt_table - 1 + .long idt_table + + .align 8 + +idt_table: + .rept 18 + .word int_handler - _start + .word cs_sel + .word 0x8e00 /* present, DPL=0, 32b, interrupt */ + .word (int_handler - _start + SKBOOT_START) >> 16 + .endr + /* for machine-check exception */ + .word int_handler - _start + .word cs_sel + .word 0x8f00 /* present, DPL=0, 32b, trap */ + .word (int_handler - _start + SKBOOT_START) >> 16 + .rept 237 + .word int_handler - _start + .word cs_sel + .word 0x8e00 /* present, DPL=0, 32b, interrupt */ + .word (int_handler - _start + SKBOOT_START) >> 16 + .endr +idt_table_end: + +/* + * stacks + */ + +.section ".bss.stack_aligned","w" + +bsp_stack_end: + .fill BSP_STACK_SIZE, 1, 0 +bsp_stack: + +/* + * misc. bss data + */ +.section ".bss" + +.section ".data" + +ENTRY(_end) diff --git a/trenchboot/skboot/common/cmdline.c b/trenchboot/skboot/common/cmdline.c new file mode 100644 index 0000000..05b89a0 --- /dev/null +++ b/trenchboot/skboot/common/cmdline.c @@ -0,0 +1,535 @@ +/* + * cmdline.c: command line parsing fns + * + * Copyright (c) 2006-2012, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef IS_INCLUDED +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif +/* + * copy of original command line + * part of skboot measurement (hence in .text section) + */ +__data char g_cmdline[CMDLINE_SIZE] = { 0 }; + +/* Used for kernel command line parameter setup */ +typedef struct { + const char *name; /* set to NULL for last item in list */ + const char *def_val; +} cmdline_option_t; + +#define MAX_VALUE_LEN 64 + +/* + * the option names and default values must be separate from the actual + * params entered + * this allows the names and default values to be part of the MLE measurement + * param_values[] need to be in .bss section so that will get cleared on launch + */ + +/* global option array for command line */ +static const cmdline_option_t g_skboot_cmdline_options[] = { + { "loglvl", "all" }, /* all|err,warn,info|none */ + { "logging", "serial,vga" }, /* vga,serial,memory|none */ + { "serial", "115200,8n1,0x3f8" }, + /* serial=[/][,[,[,[,[,]]]]] */ + { "vga_delay", "0" }, /* # secs */ + { "min_ram", "0" }, /* size in bytes | 0 for no min */ + { "error_shutdown", "halt"}, /* shutdown|reboot|halt */ + { NULL, NULL } +}; +static char g_skboot_param_values[ARRAY_SIZE(g_skboot_cmdline_options)][MAX_VALUE_LEN]; + +static const cmdline_option_t g_linux_cmdline_options[] = { + { "vga", "" }, + { "mem", "" }, + { NULL, NULL } +}; +static char g_linux_param_values[ARRAY_SIZE(g_linux_cmdline_options)][MAX_VALUE_LEN]; + +typedef struct { + const char *log_name; + uint8_t log_val; +} sk_loglvl_map_t; + +/* map */ +static const sk_loglvl_map_t g_loglvl_map[] = { + { "none", SKBOOT_LOG_LEVEL_NONE }, + { "err", SKBOOT_LOG_LEVEL_ERR }, + { "warn", SKBOOT_LOG_LEVEL_WARN }, + { "info", SKBOOT_LOG_LEVEL_INFO }, + { "detail",SKBOOT_LOG_LEVEL_DETA }, + { "all", SKBOOT_LOG_LEVEL_ALL }, +}; + +static const char* get_option_val(const cmdline_option_t *options, char vals[][MAX_VALUE_LEN], const char *opt_name) +{ + for ( int i = 0; options[i].name != NULL; i++ ) { + if ( sk_strcmp(options[i].name, opt_name) == 0 ) + return vals[i]; + } + printk(SKBOOT_ERR"requested unknown option: %s\n", opt_name); + return NULL; +} + +static void cmdline_parse(const char *cmdline, const cmdline_option_t *options, + char vals[][MAX_VALUE_LEN]) +{ + const char *p = cmdline; + int i; + + /* copy default values to vals[] */ + for ( i = 0; options[i].name != NULL; i++ ) { + sk_strncpy(vals[i], options[i].def_val, MAX_VALUE_LEN-1); + vals[i][MAX_VALUE_LEN-1] = '\0'; + } + + if ( p == NULL ) + return; + + /* parse options */ + while ( true ) + { + /* skip whitespace */ + while ( isspace(*p) ) + p++; + if ( *p == '\0' ) + break; + + /* find end of current option */ + const char *opt_start = p; + const char *opt_end = sk_strchr(opt_start, ' '); + if ( opt_end == NULL ) + opt_end = opt_start + sk_strlen(opt_start); + p = opt_end; + + /* find value part; if no value found, use default and continue */ + const char *val_start = sk_strchr(opt_start, '='); + if ( val_start == NULL || val_start > opt_end ) + continue; + val_start++; + + unsigned int opt_name_size = val_start - opt_start - 1; + unsigned int copy_size = opt_end - val_start; + if ( copy_size > MAX_VALUE_LEN - 1 ) + copy_size = MAX_VALUE_LEN - 1; + if ( opt_name_size == 0 || copy_size == 0 ) + continue; + + /* value found, so copy it */ + for ( i = 0; options[i].name != NULL; i++ ) { + if ( sk_strncmp(options[i].name, opt_start, opt_name_size ) == 0 ) { + sk_strncpy(vals[i], val_start, copy_size); + vals[i][copy_size] = '\0'; /* add '\0' to the end of string */ + break; + } + } + } +} + +void skboot_parse_cmdline(void) +{ + cmdline_parse(g_cmdline, g_skboot_cmdline_options, g_skboot_param_values); +} + +void linux_parse_cmdline(const char *cmdline) +{ + cmdline_parse(cmdline, g_linux_cmdline_options, g_linux_param_values); +} + +uint8_t get_loglvl_prefix(char **pbuf, int *len) +{ + uint8_t log_level = SKBOOT_LOG_LEVEL_ALL; + + if ( *len > 2 && **pbuf == '<' && *(*pbuf+2) == '>' + && isdigit(*(*pbuf+1)) ) { + unsigned int i = *(*pbuf+1) - '0'; + if ( i < ARRAY_SIZE(g_loglvl_map) ) + log_level = g_loglvl_map[i].log_val; + *pbuf += 3; + *len = *len - 3; + } + + return log_level; +} + +void get_skboot_loglvl(void) +{ + const char *loglvl = get_option_val(g_skboot_cmdline_options, + g_skboot_param_values, "loglvl"); + if ( loglvl == NULL ) + return; + + /* determine whether the target is set explicitly */ + while ( isspace(*loglvl) ) + loglvl++; + + g_log_level = SKBOOT_LOG_LEVEL_NONE; + + while ( *loglvl != '\0' ) { + unsigned int i; + + for ( i = 0; i < ARRAY_SIZE(g_loglvl_map); i++ ) { + if ( sk_strncmp(loglvl, g_loglvl_map[i].log_name, + sk_strlen(g_loglvl_map[i].log_name)) == 0 ) { + loglvl += sk_strlen(g_loglvl_map[i].log_name); + + if ( g_loglvl_map[i].log_val == SKBOOT_LOG_LEVEL_NONE ) { + g_log_level = SKBOOT_LOG_LEVEL_NONE; + return; + } + else { + g_log_level |= g_loglvl_map[i].log_val; + break; + } + } + } + + if ( i == ARRAY_SIZE(g_loglvl_map) ) + break; /* unrecognized, end loop */ + + /* skip ',' */ + if ( *loglvl == ',' ) + loglvl++; + else + break; /* unrecognized, end loop */ + } +} + +void get_skboot_log_targets(void) +{ + const char *targets = get_option_val(g_skboot_cmdline_options, + g_skboot_param_values, "logging"); + + /* nothing set, leave defaults */ + if ( targets == NULL || *targets == '\0' ) + return; + + /* determine if no targets set explicitly */ + if ( sk_strcmp(targets, "none") == 0 ) { + g_log_targets = SKBOOT_LOG_TARGET_NONE; /* print nothing */ + return; + } + + /* else init to nothing and parse the possible targets */ + g_log_targets = SKBOOT_LOG_TARGET_NONE; + + while ( *targets != '\0' ) { + if ( sk_strncmp(targets, "memory", 6) == 0 ) { + g_log_targets |= SKBOOT_LOG_TARGET_MEMORY; + targets += 6; + } + else if ( sk_strncmp(targets, "serial", 6) == 0 ) { + g_log_targets |= SKBOOT_LOG_TARGET_SERIAL; + targets += 6; + } + else if ( sk_strncmp(targets, "vga", 3) == 0 ) { + g_log_targets |= SKBOOT_LOG_TARGET_VGA; + targets += 3; + } + else + break; /* unrecognized, end loop */ + + if ( *targets == ',' ) + targets++; + else + break; /* unrecognized, end loop */ + } +} + +static bool parse_pci_bdf(const char **bdf, uint32_t *bus, uint32_t *slot, + uint32_t *func) +{ + *bus = sk_strtoul(*bdf, (char **)bdf, 16); + if ( **bdf != ':' ) + return false; + (*bdf)++; + *slot = sk_strtoul(*bdf, (char **)bdf, 16); + if ( **bdf != '.' ) + return false; + (*bdf)++; + *func = sk_strtoul(*bdf, (char **)bdf, 16); + + return true; +} + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" +bool g_psbdf_enabled = false; +static bool parse_com_psbdf(const char **bdf) +{ + g_psbdf_enabled = parse_pci_bdf(bdf, + &g_com_port.comc_psbdf.bus, + &g_com_port.comc_psbdf.slot, + &g_com_port.comc_psbdf.func); + + return g_psbdf_enabled; +} + +bool g_pbbdf_enabled = false; +static bool parse_com_pbbdf(const char **bdf) +{ + g_pbbdf_enabled = parse_pci_bdf(bdf, + &g_com_port.comc_pbbdf.bus, + &g_com_port.comc_pbbdf.slot, + &g_com_port.comc_pbbdf.func); + + return g_pbbdf_enabled; +} +#pragma GCC diagnostic pop + +static bool parse_com_fmt(const char **fmt) +{ + /* fmt: <5|6|7|8><0|1> */ + /* default 8n1 */ + uint8_t data_bits = 8; + uint8_t parity = 'n'; + uint8_t stop_bits = 1; + + + /* must specify all values */ + if ( sk_strlen(*fmt) < 3 ) + return false; + + /* data bits */ + if ( **fmt >= '5' && **fmt <= '8' ) + data_bits = **fmt - '0'; + else + return false; + (*fmt)++; + + /* parity */ + if ( **fmt == 'n' || **fmt == 'o' || **fmt == 'e' || **fmt == 'm' || + **fmt == 's' ) + parity = **fmt; + else + return false; + (*fmt)++; + + /* stop bits */ + if ( **fmt == '0' || **fmt == '1' ) + stop_bits = **fmt - '0'; + else + return false; + (*fmt)++; + + g_com_port.comc_fmt = GET_LCR_VALUE(data_bits, stop_bits, parity); + + return true; +} + +static bool parse_serial_param(const char *com) +{ + /* parse baud */ + g_com_port.comc_curspeed = sk_strtoul(com, (char **)&com, 10); + if ( (g_com_port.comc_curspeed < 1200) || + (g_com_port.comc_curspeed > 115200) ) + return false; + + /* parse clock hz */ + if ( *com == '/' ) { + ++com; + g_com_port.comc_clockhz = sk_strtoul(com, (char **)&com, 0) << 4; + if ( g_com_port.comc_clockhz == 0 ) + return false; + } + + /* parse data_bits/parity/stop_bits */ + if ( *com != ',' ) + goto exit; + ++com; + while ( isspace(*com) ) + com++; + if ( !parse_com_fmt(&com) ) + return false; + + /* parse IO base */ + if ( *com != ',' ) + goto exit; + ++com; + g_com_port.comc_port = sk_strtoul(com, (char **)&com, 0); + if ( g_com_port.comc_port == 0 ) + return false; + + /* parse irq */ + if ( *com != ',' ) + goto exit; + ++com; + g_com_port.comc_irq = sk_strtoul(com, (char **)&com, 10); + if ( g_com_port.comc_irq == 0 ) + return false; + + /* parse PCI serial controller bdf */ + if ( *com != ',' ) + goto exit; + ++com; + if ( !parse_com_psbdf(&com) ) + return false; + + /* parse PCI bridge bdf */ + if ( *com != ',' ) + goto exit; + ++com; + if ( !parse_com_pbbdf(&com) ) + return false; + + exit: + return true; +} + +bool get_skboot_serial(void) +{ + const char *serial = get_option_val(g_skboot_cmdline_options, + g_skboot_param_values, "serial"); + if ( serial == NULL || *serial == '\0' ) + return false; + + return parse_serial_param(serial); +} + +void get_skboot_vga_delay(void) +{ + const char *vga_delay = get_option_val(g_skboot_cmdline_options, + g_skboot_param_values, "vga_delay"); + if ( vga_delay == NULL ) + return; + + g_vga_delay = sk_strtoul(vga_delay, NULL, 0); +} + +extern uint32_t g_min_ram; +void get_skboot_min_ram(void) +{ + const char *min_ram = get_option_val(g_skboot_cmdline_options, + g_skboot_param_values, "min_ram"); + if ( min_ram == NULL ) + return; + + g_min_ram = sk_strtoul(min_ram, NULL, 0); +} + +uint32_t get_error_shutdown(void) +{ + const char *error_shutdown = + get_option_val(g_skboot_cmdline_options, + g_skboot_param_values, + "error_shutdown"); + if ( error_shutdown != NULL ) { + if ( sk_strcmp(error_shutdown, "reboot") == 0 ) + return SK_SHUTDOWN_REBOOT; + if ( sk_strcmp(error_shutdown, "shutdown") == 0 ) + return SK_SHUTDOWN_SHUTDOWN; + if ( sk_strcmp(error_shutdown, "halt") == 0 ) + return SK_SHUTDOWN_HALT; + } + + /* TODO change to shutdown when implemented */ + return SK_SHUTDOWN_HALT; +} + +/* + * linux kernel command line parsing + */ + +bool get_linux_vga(int *vid_mode) +{ + const char *vga = get_option_val(g_linux_cmdline_options, + g_linux_param_values, "vga"); + if ( vga == NULL || vid_mode == NULL ) + return false; + + if ( sk_strcmp(vga, "normal") == 0 ) + *vid_mode = 0xFFFF; + else if ( sk_strcmp(vga, "ext") == 0 ) + *vid_mode = 0xFFFE; + else if ( sk_strcmp(vga, "ask") == 0 ) + *vid_mode = 0xFFFD; + else + *vid_mode = sk_strtoul(vga, NULL, 0); + + return true; +} + +bool get_linux_mem(uint64_t *max_mem) +{ + char *last = NULL; + const char *mem = get_option_val(g_linux_cmdline_options, + g_linux_param_values, "mem"); + if ( mem == NULL || max_mem == NULL ) + return false; + + *max_mem = sk_strtoul(mem, &last, 0); + if ( *max_mem == 0 ) + return false; + + if ( last == NULL ) + return true; + + switch ( *last ) { + case 'G': + case 'g': + *max_mem = *max_mem << 30; + return true; + case 'M': + case 'm': + *max_mem = *max_mem << 20; + return true; + case 'K': + case 'k': + *max_mem = *max_mem << 10; + return true; + default: + return false; + } + + return true; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/common/com.c b/trenchboot/skboot/common/com.c new file mode 100644 index 0000000..b205aeb --- /dev/null +++ b/trenchboot/skboot/common/com.c @@ -0,0 +1,128 @@ +/*- + * Copyright (c) 1998 Michael Smith (msmith@freebsd.org) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Portions copyright (c) 2010, Intel Corporation + */ + +/* + * sys/boot/i386/libi386/comconsole.c + */ + +#include +#include +#include +#include +#include +#include + +#define COMC_TXWAIT 0x40000 /* transmit timeout */ +#define COMC_BPS(x) (115200 / (x)) /* speed to DLAB divisor */ +#define COMC_DIV2BPS(x) (115200 / (x)) /* DLAB divisor to speed */ + +#define OUTB(add, val) outb(g_com_port.comc_port + (add), (val)) +#define INB(add) inb(g_com_port.comc_port + (add)) + +serial_port_t g_com_port = {115200, 0, 0x3, COM1_ADDR}; /* com1,115200,8n1 */ + +extern bool g_psbdf_enabled; +extern bool g_pbbdf_enabled; + +static void comc_putchar(int c) +{ + int wait; + + for ( wait = COMC_TXWAIT; wait > 0; wait-- ) + if ( INB(com_lsr) & LSR_TXRDY ) { + OUTB(com_data, (u_char)c); + break; + } +} + +static void comc_setup(int speed) +{ + OUTB(com_cfcr, CFCR_DLAB | g_com_port.comc_fmt); + OUTB(com_dlbl, COMC_BPS(speed) & 0xff); + OUTB(com_dlbh, COMC_BPS(speed) >> 8); + OUTB(com_cfcr, g_com_port.comc_fmt); + OUTB(com_mcr, MCR_RTS | MCR_DTR); + + for ( int wait = COMC_TXWAIT; wait > 0; wait-- ) { + INB(com_data); + if ( !(INB(com_lsr) & LSR_RXRDY) ) + break; + } +} + +static void comc_pci_setup(void) +{ + if ( g_psbdf_enabled ) { + if ( g_pbbdf_enabled ) { + pcireg_cfgwrite(g_com_port.comc_pbbdf.bus, + g_com_port.comc_pbbdf.slot, + g_com_port.comc_pbbdf.func, + PCIR_IOBASEL_1, + (g_com_port.comc_port & 0xF000) + | ((g_com_port.comc_port & 0xF000) >> 8), + 2); + } + pcireg_cfgwrite(g_com_port.comc_psbdf.bus, + g_com_port.comc_psbdf.slot, + g_com_port.comc_psbdf.func, + PCIR_BARS, + g_com_port.comc_port | 0x1, + 4); + pcireg_cfgwrite(g_com_port.comc_psbdf.bus, + g_com_port.comc_psbdf.slot, + g_com_port.comc_psbdf.func, + PCIR_COMMAND, + 0x1, + 2); + } +} + +void comc_init(void) +{ + comc_pci_setup(); + comc_setup(g_com_port.comc_curspeed); +} + +void comc_puts(const char *s, unsigned int cnt) +{ + while ( *s && cnt-- ) { + if ( *s == '\n' ) + comc_putchar('\r'); + comc_putchar(*s++); + } +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/common/e820.c b/trenchboot/skboot/common/e820.c new file mode 100644 index 0000000..6ba7490 --- /dev/null +++ b/trenchboot/skboot/common/e820.c @@ -0,0 +1,696 @@ +/* + * e820.c: support functions for manipulating the e820 table + * + * Copyright (c) 2006-2012, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* minimum size of RAM (type 1) region that cannot be marked as reserved even + if it comes after a reserved region; 0 for no minimum (i.e. current + behavior) */ +uint32_t g_min_ram = 0; + +/* + * copy of bootloader/BIOS e820 table with adjusted entries + * this version will replace original in mbi + */ +#define MAX_E820_ENTRIES (SKBOOT_E820_COPY_SIZE / sizeof(memory_map_t)) +static unsigned int g_nr_map; +static memory_map_t *g_copy_e820_map = (memory_map_t *)SKBOOT_E820_COPY_ADDR; + +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; +} + +static inline uint64_t e820_base_64(memory_map_t *entry) +{ + return combine64b(entry->base_addr_low, entry->base_addr_high); +} + +static inline uint64_t e820_length_64(memory_map_t *entry) +{ + return combine64b(entry->length_low, entry->length_high); +} + + +/* + * 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) +{ + for ( int i = 0; i < nr_map; i++ ) { + memory_map_t *entry = &e820[i]; + uint64_t base_addr, length; + + base_addr = e820_base_64(entry); + length = e820_length_64(entry); + + printk(SKBOOT_DETA"\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, unsigned int *nr_map, + unsigned int pos, uint64_t addr, uint64_t size, + uint32_t type) +{ + /* no more room */ + if ( *nr_map + 1 > MAX_E820_ENTRIES ) + return false; + + /* shift (copy) everything up one entry */ + for ( unsigned int 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, unsigned int *nr_map, + unsigned int pos) +{ + /* shift (copy) everything down one entry */ + for ( unsigned int i = pos; i < *nr_map - 1; i++) + e820map[i] = e820map[i+1]; + + (*nr_map)--; +} + +static bool protect_region(memory_map_t *e820map, unsigned int *nr_map, + uint64_t new_addr, uint64_t new_size, + uint32_t new_type) +{ + uint64_t addr, tmp_addr, size, tmp_size; + uint32_t type; + unsigned int i; + + if ( new_size == 0 ) + return true; + /* check for wrap */ + if ( new_addr + new_size < new_addr ) + return false; + + /* find where our region belongs in the table and insert it */ + for ( i = 0; i < *nr_map; i++ ) { + addr = e820_base_64(&e820map[i]); + size = e820_length_64(&e820map[i]); + 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 = e820_base_64(&e820map[i]); + 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 = e820_base_64(&e820map[i]); + tmp_size = e820_length_64(&e820map[i]); + + /* 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 = e820_base_64(&e820map[i]); + tmp_size = e820_length_64(&e820map[i]); + } + + /* finally, if our region partially overlaps an existing region, */ + /* then truncate the existing region */ + if ( i < *nr_map ) { + tmp_addr = e820_base_64(&e820map[i]); + tmp_size = e820_length_64(&e820map[i]); + if ( (new_addr + new_size) > tmp_addr ) { + 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; +} + +/* + * is_overlapped + * + * Detect whether two ranges are overlapped. + * + * return: true = overlapped + */ +static bool is_overlapped(uint64_t base, uint64_t end, uint64_t e820_base, + uint64_t e820_end) +{ + uint64_t length = end - base, e820_length = e820_end - e820_base; + uint64_t min, max; + + min = (base < e820_base)?base:e820_base; + max = (end > e820_end)?end:e820_end; + + /* overlapping */ + if ( (max - min) < (length + e820_length) ) + return true; + + if ( (max - min) == (length + e820_length) + && ( ((length == 0) && (base > e820_base) && (base < e820_end)) + || ((e820_length == 0) && (e820_base > base) && + (e820_base < end)) ) ) + return true; + + return false; +} + +/* helper funcs for loader.c */ +memory_map_t *get_e820_copy() +{ + return g_copy_e820_map; +} + +unsigned int get_nr_map() +{ + return g_nr_map; +} + +/* + * 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(loader_ctx *lctx) +{ + get_skboot_min_ram(); + + g_nr_map = 0; + + if (have_loader_memmap(lctx)){ + uint32_t memmap_length = get_loader_memmap_length(lctx); + memory_map_t *memmap = get_loader_memmap(lctx); + printk(SKBOOT_DETA"original e820 map:\n"); + print_map(memmap, memmap_length/sizeof(memory_map_t)); + + uint32_t entry_offset = 0; + + while ( entry_offset < memmap_length && + g_nr_map < MAX_E820_ENTRIES ) { + memory_map_t *entry = (memory_map_t *) + (((uint32_t) memmap) + entry_offset); + + /* we want to support unordered and/or overlapping entries */ + /* so use protect_region() to insert into existing map, since */ + /* it handles these cases */ + if ( !protect_region(g_copy_e820_map, &g_nr_map, + e820_base_64(entry), e820_length_64(entry), + entry->type) ) + return false; + if (lctx->type == 1) + entry_offset += entry->size + sizeof(entry->size); + if (lctx->type == 2) + /* the MB2 memory map entries don't have a size-- + * they have a "zero" with a value of zero. Additionally, + * because they *end* with a size and the MB1 guys *start* + * with a size, we get into trouble if we try to use them, + */ + entry_offset += sizeof(memory_map_t); + + } + if ( g_nr_map == MAX_E820_ENTRIES ) { + printk(SKBOOT_ERR"Too many e820 entries\n"); + return false; + } + } + else if ( have_loader_memlimits(lctx) ) { + printk(SKBOOT_DETA"no e820 map, mem_lower=%x, mem_upper=%x\n", + get_loader_mem_lower(lctx), get_loader_mem_upper(lctx)); + + /* 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 = (get_loader_mem_lower(lctx)) << 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)(get_loader_mem_upper(lctx)) << 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(SKBOOT_ERR"no e820 map nor memory limits provided\n"); + return false; + } + + return true; +} + +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); +} + +/* + * e820_check_region + * + * Given a range, check which kind of range it covers + * + * return: E820_GAP, it covers gap in e820 map; + * E820_MIXED, it covers at least two different kinds of ranges; + * E820_XXX, it covers E820_XXX range only; + * it will not return 0. + */ +uint32_t e820_check_region(uint64_t base, uint64_t length) +{ + memory_map_t* e820_entry; + uint64_t end = base + length, e820_base, e820_end, e820_length; + uint32_t type; + uint32_t ret = 0; + bool gap = true; /* suppose there is always a virtual gap at first */ + + e820_base = 0; + e820_length = 0; + + for ( unsigned int i = 0; i < g_nr_map; i = gap ? i : i+1, gap = !gap ) { + e820_entry = &g_copy_e820_map[i]; + if ( gap ) { + /* deal with the gap in e820 map */ + e820_base = e820_base + e820_length; + e820_length = e820_base_64(e820_entry) - e820_base; + type = E820_GAP; + } + else { + /* deal with the normal item in e820 map */ + e820_base = e820_base_64(e820_entry); + e820_length = e820_length_64(e820_entry); + type = e820_entry->type; + } + + if ( e820_length == 0 ) + continue; /* if the range is zero, then skip */ + + e820_end = e820_base + e820_length; + + if ( !is_overlapped(base, end, e820_base, e820_end) ) + continue; /* if no overlapping, then skip */ + + /* if the value of ret is not assigned before, + then set ret to type directly */ + if ( ret == 0 ) { + ret = type; + continue; + } + + /* if the value of ret is assigned before but ret is equal to type, + then no need to do anything */ + if ( ret == type ) + continue; + + /* if the value of ret is assigned before but it is GAP, + then no need to do anything since any type merged with GAP is GAP */ + if ( ret == E820_GAP ) + continue; + + /* if the value of ret is assigned before but it is not GAP and type + is GAP now this time, then set ret to GAP since any type merged + with GAP is GAP. */ + if ( type == E820_GAP ) { + ret = E820_GAP; + continue; + } + + /* if the value of ret is assigned before but both ret and type are + not GAP and their values are not equal, then set ret to MIXED + since any two non-GAP values are merged into MIXED if they are + not equal. */ + ret = E820_MIXED; + } + + /* deal with the last gap */ + if ( is_overlapped(base, end, e820_base + e820_length, (uint64_t)-1) ) + ret = E820_GAP; + + /* print the result */ + printk(SKBOOT_DETA" (range from %016Lx to %016Lx is in ", base, base + length); + switch (ret) { + case E820_RAM: + printk(SKBOOT_INFO"E820_RAM)\n"); break; + case E820_RESERVED: + printk(SKBOOT_INFO"E820_RESERVED)\n"); break; + case E820_ACPI: + printk(SKBOOT_INFO"E820_ACPI)\n"); break; + case E820_NVS: + printk(SKBOOT_INFO"E820_NVS)\n"); break; + case E820_UNUSABLE: + printk(SKBOOT_INFO"E820_UNUSABLE)\n"); break; + case E820_GAP: + printk(SKBOOT_INFO"E820_GAP)\n"); break; + case E820_MIXED: + printk(SKBOOT_INFO"E820_MIXED)\n"); break; + default: + printk(SKBOOT_INFO"UNKNOWN)\n"); + } + + return ret; +} + +/* + * e820_reserve_ram + * + * Given the range, any ram range in e820 is in it, change type to reserved. + * + * return: false = error + */ +bool e820_reserve_ram(uint64_t base, uint64_t length) +{ + memory_map_t* e820_entry; + uint64_t e820_base, e820_length, e820_end; + uint64_t end; + + if ( length == 0 ) + return true; + + end = base + length; + + /* find where our region should cover the ram in e820 */ + for ( unsigned int i = 0; i < g_nr_map; i++ ) { + e820_entry = &g_copy_e820_map[i]; + e820_base = e820_base_64(e820_entry); + e820_length = e820_length_64(e820_entry); + e820_end = e820_base + e820_length; + + /* if not ram, no need to deal with */ + if ( e820_entry->type != E820_RAM ) + continue; + + /* if the range is before the current ram range, skip the ram range */ + if ( end <= e820_base ) + continue; + /* if the range is after the current ram range, skip the ram range */ + if ( base >= e820_end ) + continue; + + /* case 1: the current ram range is within the range: + base, e820_base, e820_end, end */ + if ( (base <= e820_base) && (e820_end <= end) ) + e820_entry->type = E820_RESERVED; + /* case 2: overlapping: + base, e820_base, end, e820_end */ + else if ( (e820_base >= base) && (end > e820_base) && + (e820_end > end) ) { + /* split the current ram map */ + if ( !insert_after_region(g_copy_e820_map, &g_nr_map, i-1, + e820_base, (end - e820_base), + E820_RESERVED) ) + return false; + /* fixup the current ram map */ + i++; + split64b(end, &(g_copy_e820_map[i].base_addr_low), + &(g_copy_e820_map[i].base_addr_high)); + split64b(e820_end - end, &(g_copy_e820_map[i].length_low), + &(g_copy_e820_map[i].length_high)); + /* no need to check more */ + break; + } + /* case 3: overlapping: + e820_base, base, e820_end, end */ + else if ( (base > e820_base) && (e820_end > base) && + (end >= e820_end) ) { + /* fixup the current ram map */ + split64b((base - e820_base), &(g_copy_e820_map[i].length_low), + &(g_copy_e820_map[i].length_high)); + /* split the current ram map */ + if ( !insert_after_region(g_copy_e820_map, &g_nr_map, i, base, + (e820_end - base), E820_RESERVED) ) + return false; + i++; + } + /* case 4: the range is within the current ram range: + e820_base, base, end, e820_end */ + else if ( (base > e820_base) && (e820_end > end) ) { + /* fixup the current ram map */ + split64b((base - e820_base), &(g_copy_e820_map[i].length_low), + &(g_copy_e820_map[i].length_high)); + /* split the current ram map */ + if ( !insert_after_region(g_copy_e820_map, &g_nr_map, i, base, + length, E820_RESERVED) ) + return false; + i++; + /* fixup the rest of the current ram map */ + if ( !insert_after_region(g_copy_e820_map, &g_nr_map, i, end, + (e820_end - end), e820_entry->type) ) + return false; + i++; + /* no need to check more */ + break; + } + else { + printk(SKBOOT_ERR"we should never get here\n"); + return false; + } + } + + return true; +} + +void print_e820_map(void) +{ + print_map(g_copy_e820_map, g_nr_map); +} + +bool get_ram_ranges(uint64_t *min_lo_ram, uint64_t *max_lo_ram, + uint64_t *min_hi_ram, uint64_t *max_hi_ram) +{ + if ( min_lo_ram == NULL || max_lo_ram == NULL || + min_hi_ram == NULL || max_hi_ram == NULL ) + return false; + + *min_lo_ram = *min_hi_ram = ~0ULL; + *max_lo_ram = *max_hi_ram = 0; + bool found_reserved_region = false; + uint64_t last_min_ram_base = 0, last_min_ram_size = 0; + + /* + * if g_min_ram > 0, we will never mark a region > g_min_ram in size + * as reserved even if it is after a reserved region (effectively + * we ignore reserved regions below the last type 1 region + * > g_min_ram in size) + * so in order to reserve RAM regions above this last region, we need + * to find it first so that we can tell when we have passed it + */ + if ( g_min_ram > 0 ) { + get_highest_sized_ram(g_min_ram, 0x100000000ULL, &last_min_ram_base, + &last_min_ram_size); + printk(SKBOOT_DETA"highest min_ram (0x%x) region found: base=0x%Lx, size=0x%Lx\n", + g_min_ram, last_min_ram_base, last_min_ram_size); + } + + for ( unsigned int i = 0; i < g_nr_map; i++ ) { + memory_map_t *entry = &g_copy_e820_map[i]; + uint64_t base = e820_base_64(entry); + uint64_t limit = base + e820_length_64(entry); + + if ( entry->type == E820_RAM ) { + /* if range straddles 4GB boundary, that is an error */ + if ( base < 0x100000000ULL && limit > 0x100000000ULL ) { + printk(SKBOOT_ERR"e820 memory range straddles 4GB boundary\n"); + return false; + } + + /* + * some BIOSes put legacy USB buffers in reserved regions <4GB, + * which if DMA protected cause SMM to hang, so make sure that + * we don't overlap any of these even if that wastes RAM + * ...unless min_ram was specified + */ + if ( !found_reserved_region || base <= last_min_ram_base ) { + if ( base < 0x100000000ULL && base < *min_lo_ram ) + *min_lo_ram = base; + if ( limit <= 0x100000000ULL && limit > *max_lo_ram ) + *max_lo_ram = limit; + } + else { /* need to reserve low RAM above reserved regions */ + if ( base < 0x100000000ULL ) { + printk(SKBOOT_DETA"discarding RAM above reserved regions: 0x%Lx - 0x%Lx\n", base, limit); + if ( !e820_reserve_ram(base, limit - base) ) + return false; + } + } + + if ( base >= 0x100000000ULL && base < *min_hi_ram ) + *min_hi_ram = base; + if ( limit > 0x100000000ULL && limit > *max_hi_ram ) + *max_hi_ram = limit; + } + else { + /* parts of low memory may be reserved for cseg, ISA hole, + etc. but these seem OK to DMA protect, so ignore reserved + regions <0x100000 */ + if ( *min_lo_ram != ~0ULL && limit > 0x100000ULL ) + found_reserved_region = true; + } + } + + /* no low RAM found */ + if ( *min_lo_ram >= *max_lo_ram ) { + printk(SKBOOT_ERR"no low ram in e820 map\n"); + return false; + } + /* no high RAM found */ + if ( *min_hi_ram >= *max_hi_ram ) + *min_hi_ram = *max_hi_ram = 0; + + return true; +} + +/* find highest (< ) RAM region of at least bytes */ +void get_highest_sized_ram(uint64_t size, uint64_t limit, + uint64_t *ram_base, uint64_t *ram_size) +{ + uint64_t last_fit_base = 0, last_fit_size = 0; + + if ( ram_base == NULL || ram_size == NULL ) + return; + + for ( unsigned int i = 0; i < g_nr_map; i++ ) { + memory_map_t *entry = &g_copy_e820_map[i]; + + if ( entry->type == E820_RAM ) { + uint64_t base = e820_base_64(entry); + uint64_t length = e820_length_64(entry); + + /* over 4GB so use the last region that fit */ + if ( base + length > limit ) + break; + if ( size <= length ) { + last_fit_base = base; + last_fit_size = length; + } + } + } + + *ram_base = last_fit_base; + *ram_size = last_fit_size; +} + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/common/linux.c b/trenchboot/skboot/common/linux.c new file mode 100644 index 0000000..aa1cc96 --- /dev/null +++ b/trenchboot/skboot/common/linux.c @@ -0,0 +1,490 @@ +/* + * linux.c: support functions for manipulating Linux kernel binaries + * + * Copyright (c) 2006-2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern loader_ctx *g_ldr_ctx; +extern uint32_t g_min_ram; + +static boot_params_t *boot_params; + +extern void *get_skboot_mem_end(void); + +il_kernel_setup_t g_il_kernel_setup = {0}; + +static void +printk_long(const char *what) +{ + /* chunk the command line into 70 byte chunks */ +#define CHUNK_SIZE 70 + int cmdlen = sk_strlen(what); + const char *cptr = what; + char cmdchunk[CHUNK_SIZE+1]; + while (cmdlen > 0) { + sk_strncpy(cmdchunk, cptr, CHUNK_SIZE); + cmdchunk[CHUNK_SIZE] = 0; + printk(SKBOOT_INFO"\t%s\n", cmdchunk); + cmdlen -= CHUNK_SIZE; + cptr += CHUNK_SIZE; + } +} + +/* expand linux kernel with kernel image and initrd image */ +bool expand_linux_image(const void *linux_image, size_t linux_size, + const void *initrd_image, size_t initrd_size) +{ + linux_kernel_header_t *hdr; + linux_kernel_header_t temp_hdr; + uint32_t real_mode_base, protected_mode_base; + unsigned long real_mode_size, protected_mode_size; + /* Note: real_mode_size + protected_mode_size = linux_size */ + uint32_t initrd_base; + int vid_mode = 0; + + /* Check param */ + if ( linux_image == NULL ) { + printk(SKBOOT_ERR"Error: Linux kernel image is zero.\n"); + return false; + } + + if ( linux_size == 0 ) { + printk(SKBOOT_ERR"Error: Linux kernel size is zero.\n"); + return false; + } + + if ( linux_size < sizeof(linux_kernel_header_t) ) { + printk(SKBOOT_ERR"Error: Linux kernel size is too small.\n"); + return false; + } + + hdr = (linux_kernel_header_t *)(linux_image + KERNEL_HEADER_OFFSET); + + if ( hdr == NULL ) { + printk(SKBOOT_ERR"Error: Linux kernel header is zero.\n"); + return false; + } + + /* recommended layout + 0x0000 - 0x7FFF Real mode kernel + 0x8000 - 0x8CFF Stack and heap + 0x8D00 - 0x90FF Kernel command line + for details, see linux_defns.h + */ + + /* if setup_sects is zero, set to default value 4 */ + if ( hdr->setup_sects == 0 ) + hdr->setup_sects = DEFAULT_SECTOR_NUM; + if ( hdr->setup_sects > MAX_SECTOR_NUM ) { + printk(SKBOOT_ERR + "Error: Linux setup sectors %d exceed maximum limitation 64.\n", + hdr->setup_sects); + return false; + } + + /* set vid_mode */ + linux_parse_cmdline(get_cmdline(g_ldr_ctx)); + if ( get_linux_vga(&vid_mode) ) + hdr->vid_mode = vid_mode; + + /* compare to the magic number */ + if ( hdr->header != HDRS_MAGIC ) { + /* old kernel */ + printk(SKBOOT_ERR + "Error: Old kernel (< 2.6.20) is not supported by slboot.\n"); + return false; + } + + if ( hdr->version < 0x0205 ) { + printk(SKBOOT_ERR + "Error: Old kernel (<2.6.20) is not supported by slboot.\n"); + return false; + } + + if ( !(hdr->loadflags & FLAG_LOAD_HIGH) ) { + printk(SKBOOT_ERR + "Error: IL kernel must have the FLAG_LOAD_HIGH loadflag set.\n"); + return false; + } + + /* boot loader is grub, set type_of_loader to 0x71 */ + hdr->type_of_loader = LOADER_TYPE_GRUB; + + /* set loadflags and heap_end_ptr */ + hdr->loadflags |= FLAG_CAN_USE_HEAP; /* can use heap */ + hdr->heap_end_ptr = KERNEL_CMDLINE_OFFSET - BOOT_SECTOR_OFFSET; + + if ( initrd_size > 0 ) { + /* load initrd and set ramdisk_image and ramdisk_size */ + /* The initrd should typically be located as high in memory as + possible, as it may otherwise get overwritten by the early + kernel initialization sequence. */ + + /* check if Linux command line explicitly specified a memory limit */ + uint64_t mem_limit; + get_linux_mem(&mem_limit); + if ( mem_limit > 0x100000000ULL || mem_limit == 0 ) + mem_limit = 0x100000000ULL; + + uint64_t max_ram_base, max_ram_size; + get_highest_sized_ram(initrd_size, mem_limit, + &max_ram_base, &max_ram_size); + if ( max_ram_size == 0 ) { + printk(SKBOOT_ERR"not enough RAM for initrd\n"); + return false; + } + if ( initrd_size > max_ram_size ) { + printk(SKBOOT_ERR"initrd_size is too large\n"); + return false; + } + if ( max_ram_base > ((uint64_t)(uint32_t)(~0)) ) { + printk(SKBOOT_ERR"max_ram_base is too high\n"); + return false; + } + if ( plus_overflow_u32((uint32_t)max_ram_base, + (uint32_t)(max_ram_size - initrd_size)) ) { + printk(SKBOOT_ERR"max_ram overflows\n"); + return false; + } + /*initrd_base = (max_ram_base + max_ram_size - initrd_size) & PAGE_MASK;*/ + + /* + * The location, initrd_base, determined above in the commented out + * code causes memory corruption. This value leads to the corruption + * of EFI System Resource Table (ESRT), which is also located in RAM. + */ + initrd_base = 0x20000000; + + /* should not exceed initrd_addr_max */ + if ( initrd_base + initrd_size > hdr->initrd_addr_max ) { + if ( hdr->initrd_addr_max < initrd_size ) { + printk(SKBOOT_ERR"initrd_addr_max is too small\n"); + return false; + } + initrd_base = hdr->initrd_addr_max - initrd_size; + initrd_base = initrd_base & PAGE_MASK; + } + + /* check for overlap with a kernel image placed high in memory */ + if( (initrd_base < ((uint32_t)linux_image + linux_size)) + && ((uint32_t)linux_image < (initrd_base+initrd_size)) ){ + /* set the starting address just below the image */ + initrd_base = (uint32_t)linux_image - initrd_size; + initrd_base = initrd_base & PAGE_MASK; + /* make sure we're still in usable RAM and above skboot end address*/ + if( initrd_base < max_ram_base ){ + printk(SKBOOT_ERR"no available memory for initrd\n"); + return false; + } + } + + sk_memmove((void *)initrd_base, initrd_image, initrd_size); + printk(SKBOOT_DETA"Initrd from 0x%lx to 0x%lx\n", + (unsigned long)initrd_base, + (unsigned long)(initrd_base + initrd_size)); + + hdr->ramdisk_image = initrd_base; + hdr->ramdisk_size = initrd_size; + } + else { + hdr->ramdisk_image = 0; + hdr->ramdisk_size = 0; + } + + /* calc location of real mode part */ + real_mode_base = LEGACY_REAL_START; + if ( have_loader_memlimits(g_ldr_ctx)) + real_mode_base = + ((get_loader_mem_lower(g_ldr_ctx)) << 10) - REAL_MODE_SIZE; + if ( real_mode_base > LEGACY_REAL_START ) + real_mode_base = LEGACY_REAL_START; + + real_mode_size = (hdr->setup_sects + 1) * SECTOR_SIZE; + if ( real_mode_size > KERNEL_CMDLINE_OFFSET ) { + printk(SKBOOT_ERR"realmode data is too large\n"); + return false; + } + + /* calc location of protected mode part */ + protected_mode_size = linux_size - real_mode_size; + + /* if kernel is relocatable then move it above skboot */ + /* else it may expand over top of skboot */ + /* NOTE the IL kernel is not relocatable and shold be loaded at the + * default location */ + if ( hdr->relocatable_kernel ) { + protected_mode_base = (uint32_t)get_skboot_mem_end(); + /* fix possible mbi overwrite in grub2 case */ + /* assuming grub2 only used for relocatable kernel */ + /* assuming mbi & components are contiguous */ + unsigned long ldr_ctx_end = get_loader_ctx_end(g_ldr_ctx); + if ( ldr_ctx_end > protected_mode_base ) + protected_mode_base = ldr_ctx_end; + /* overflow? */ + if ( plus_overflow_u32(protected_mode_base, + hdr->kernel_alignment - 1) ) { + printk(SKBOOT_ERR"protected_mode_base overflows\n"); + return false; + } + /* round it up to kernel alignment */ + protected_mode_base = (protected_mode_base + hdr->kernel_alignment - 1) + & ~(hdr->kernel_alignment-1); + hdr->code32_start = protected_mode_base; + } + else if ( hdr->loadflags & FLAG_LOAD_HIGH ) { + protected_mode_base = BZIMAGE_PROTECTED_START; + /* bzImage:0x100000 */ + /* overflow? */ + if ( plus_overflow_u32(protected_mode_base, protected_mode_size) ) { + printk(SKBOOT_ERR + "protected_mode_base plus protected_mode_size overflows\n"); + return false; + } + /* Check: protected mode part cannot exceed mem_upper */ + if ( have_loader_memlimits(g_ldr_ctx)){ + uint32_t mem_upper = get_loader_mem_upper(g_ldr_ctx); + if ( (protected_mode_base + protected_mode_size) + > ((mem_upper << 10) + 0x100000) ) { + printk(SKBOOT_ERR + "Error: Linux protected mode part (0x%lx ~ 0x%lx) " + "exceeds mem_upper (0x%lx ~ 0x%lx).\n", + (unsigned long)protected_mode_base, + (unsigned long) + (protected_mode_base + protected_mode_size), + (unsigned long)0x100000, + (unsigned long)((mem_upper << 10) + 0x100000)); + return false; + } + } + } + else { + printk(SKBOOT_ERR"Error: Linux protected mode not loaded high\n"); + return false; + } + + /* save linux header struct to temp memory to copy changes to zero page */ + sk_memmove(&temp_hdr, hdr, sizeof(temp_hdr)); + + /* load real-mode part */ + sk_memmove((void *)real_mode_base, linux_image, real_mode_size); + printk(SKBOOT_DETA"Kernel (real mode) from 0x%lx to 0x%lx size: 0x%lx\n", + (unsigned long)linux_image, + (unsigned long)real_mode_base, + (unsigned long)real_mode_size); + + /* load protected-mode part */ + sk_memmove((void *)protected_mode_base, linux_image + real_mode_size, + protected_mode_size); + printk(SKBOOT_DETA"Kernel (protected mode) from 0x%lx to 0x%lx size: 0x%lx\n", + (unsigned long)(linux_image + real_mode_size), + (unsigned long)protected_mode_base, + (unsigned long)protected_mode_size); + + /* reset pointers to point into zero page at real mode base */ + hdr = (linux_kernel_header_t *)(real_mode_base + KERNEL_HEADER_OFFSET); + + /* copy back the updated kernel header */ + sk_memmove(hdr, &temp_hdr, sizeof(temp_hdr)); + + /* set cmd_line_ptr */ + hdr->cmd_line_ptr = real_mode_base + KERNEL_CMDLINE_OFFSET; + + /* copy cmdline */ + const char *kernel_cmdline = get_cmdline(g_ldr_ctx); + if ( kernel_cmdline == NULL ) { + printk(SKBOOT_ERR"Error: kernel cmdline not available\n"); + return false; + } + const size_t kernel_cmdline_size = REAL_END_OFFSET - KERNEL_CMDLINE_OFFSET; + size_t kernel_cmdline_strlen = sk_strlen(kernel_cmdline); + if (kernel_cmdline_strlen > kernel_cmdline_size - 1) + kernel_cmdline_strlen = kernel_cmdline_size - 1; + sk_memset((void *)hdr->cmd_line_ptr, 0, kernel_cmdline_size); + sk_memcpy((void *)hdr->cmd_line_ptr, kernel_cmdline, kernel_cmdline_strlen); + + printk(SKBOOT_INFO"Linux cmdline from 0x%lx to 0x%lx:\n", + (unsigned long)hdr->cmd_line_ptr, + (unsigned long)(hdr->cmd_line_ptr + kernel_cmdline_size)); + printk_long((void *)hdr->cmd_line_ptr); + +#if 0 + /* DEBUG create some dummy setup_data blocks */ + { + struct setup_data *data = (struct setup_data *)(unsigned long)0x6c000; + + data->next = 0x6c400; + data->type = 10; + data->len = 0x40; + + data = (struct setup_data *)(unsigned long)data->next; + data->next = 0; + data->type = 11; + data->len = 0x80; + + hdr->setup_data = 0x6c000; + } +#endif + + /* need to put boot_params in real mode area so it gets mapped */ + boot_params = (boot_params_t *)real_mode_base; + + /* need to handle a few EFI things here if such is our parentage */ + if (is_loader_launch_efi(g_ldr_ctx)){ + struct efi_info *efi = (struct efi_info *)(boot_params->efi_info); + struct screen_info_t *scr = + (struct screen_info_t *)(boot_params->screen_info); + uint32_t address = 0; + uint64_t long_address = 0UL; + uint32_t descr_size = 0, descr_vers = 0, mmap_size = 0, efi_mmap_addr = 0; + + /* loader signature */ + sk_memcpy(&efi->efi_ldr_sig, "EL64", sizeof(uint32_t)); + + /* EFI system table addr */ + { + if (get_loader_efi_ptr(g_ldr_ctx, &address, &long_address)){ + if (long_address){ + efi->efi_systable = (uint32_t) (long_address & 0xffffffff); + efi->efi_systable_hi = long_address >> 32; + } else { + efi->efi_systable = address; + efi->efi_systable_hi = 0; + } + } else { + printk(SKBOOT_INFO"failed to get efi system table ptr\n"); + } + } + + efi_mmap_addr = find_efi_memmap(g_ldr_ctx, &descr_size, + &descr_vers, &mmap_size); + if (!efi_mmap_addr) { + printk(SKBOOT_INFO"failed to get EFI memory map\n"); + efi->efi_memdescr_size = 0x1; // Avoid div by 0 in kernel. + efi->efi_memmap_size = 0; + efi->efi_memmap = 0; + } else { + efi->efi_memdescr_size = descr_size; + efi->efi_memdescr_ver = descr_vers; + efi->efi_memmap_size = mmap_size; + efi->efi_memmap = efi_mmap_addr; + /* From Multiboot2 spec: + * The bootloader must not load any part of the kernel, the modules, + * the Multiboot2 information structure, etc. higher than 4 GiB - 1. + */ + efi->efi_memmap_hi = 0; + + printk(SKBOOT_INFO "EFI memmap: memmap base: 0x%x, memmap size: 0x%x\n", + efi->efi_memmap, efi->efi_memmap_size); + printk(SKBOOT_INFO "EFI memmap: descr size: 0x%x, descr version: 0x%x\n", + efi->efi_memdescr_size, efi->efi_memdescr_ver); + } + + /* if we're here, GRUB2 probably threw a framebuffer tag at us */ + load_framebuffer_info(g_ldr_ctx, (void *)scr); + } + + /* detect e820 table */ + if (have_loader_memmap(g_ldr_ctx)) { + int i; + + memory_map_t *p = get_loader_memmap(g_ldr_ctx); + if ( p == NULL ) { + printk(SKBOOT_ERR"Error: no memory map available\n"); + return false; + } + uint32_t memmap_start = (uint32_t) p; + uint32_t memmap_length = get_loader_memmap_length(g_ldr_ctx); + for ( i = 0; (uint32_t)p < memmap_start + memmap_length; i++ ) + { + boot_params->e820_map[i].addr = ((uint64_t)p->base_addr_high << 32) + | (uint64_t)p->base_addr_low; + boot_params->e820_map[i].size = ((uint64_t)p->length_high << 32) + | (uint64_t)p->length_low; + boot_params->e820_map[i].type = p->type; + p = (void *)p + sizeof(memory_map_t); + } + boot_params->e820_entries = i; + } + + if (0 == is_loader_launch_efi(g_ldr_ctx)){ + screen_info_t *screen = (screen_info_t *)&boot_params->screen_info; + screen->orig_video_mode = 3; /* BIOS 80*25 text mode */ + screen->orig_video_lines = 25; + screen->orig_video_cols = 80; + screen->orig_video_points = 16; /* set font height to 16 pixels */ + screen->orig_video_isVGA = 1; /* use VGA text screen setups */ + screen->orig_y = 24; /* start display text @ screen end*/ + } + + /* Clear out some boot_params we don't want dangling around */ + sk_memset((void *)boot_params->skboot_shared_addr, 0, 8); + sk_memset((void *)boot_params->acpi_rsdp_addr, 0, 8); + + /* Copy all the handoff information about the loaded IL kernel */ + g_il_kernel_setup.real_mode_base = real_mode_base; + g_il_kernel_setup.real_mode_size = real_mode_size; + g_il_kernel_setup.protected_mode_base = protected_mode_base; + g_il_kernel_setup.protected_mode_size = protected_mode_size; + g_il_kernel_setup.boot_params = boot_params; + + printk(SKBOOT_DETA"Intermediate Loader kernel details:\n"); + printk(SKBOOT_DETA"\treal_mode_base: 0x%x\n", real_mode_base); + printk(SKBOOT_DETA"\treal_mode_size: 0x%lx\n", real_mode_size); + printk(SKBOOT_DETA"\tprotected_mode_base: 0x%x\n", protected_mode_base); + printk(SKBOOT_DETA"\tprotected_mode_size: 0x%lx\n", protected_mode_size); + printk(SKBOOT_DETA"\tboot_params: 0x%p\n", boot_params); + + return true; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/common/loader.c b/trenchboot/skboot/common/loader.c new file mode 100644 index 0000000..8b859ed --- /dev/null +++ b/trenchboot/skboot/common/loader.c @@ -0,0 +1,1169 @@ +/* + * loader.c: support functions for manipulating ELF/Linux kernel + * binaries + * + * Copyright (c) 2006-2013, Intel Corporation + * Copyright (c) 2016 Real-Time Systems GmbH + * 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 + +/* multiboot struct saved so that post_launch() can use it (in skboot.c) */ +extern loader_ctx *g_ldr_ctx; +extern bool expand_linux_image(const void *linux_image, size_t linux_size, + const void *initrd_image, size_t initrd_size); +extern void error_action(int error); +static uint32_t g_mb_orig_size; + +#define LOADER_CTX_BAD(xctx) \ + xctx == NULL ? true : \ + xctx->addr == NULL ? true : \ + xctx->type != 1 && xctx->type != 2 ? true : false + +#define MB_NONE 0 +#define MB1_ONLY 1 +#define MB2_ONLY 2 +#define MB_BOTH 3 + +static void +printk_long(char *what) +{ + /* chunk the command line into 70 byte chunks */ +#define CHUNK_SIZE 70 + int cmdlen = sk_strlen(what); + char *cptr = what; + char cmdchunk[CHUNK_SIZE+1]; + while (cmdlen > 0) { + sk_strncpy(cmdchunk, cptr, CHUNK_SIZE); + cmdchunk[CHUNK_SIZE] = 0; + printk(SKBOOT_INFO"\t%s\n", cmdchunk); + cmdlen -= CHUNK_SIZE; + cptr += CHUNK_SIZE; + } +} + +static module_t +*get_module_mb1(const multiboot_info_t *mbi, unsigned int i) +{ + if ( mbi == NULL ) { + printk(SKBOOT_ERR"Error: mbi pointer is zero.\n"); + return NULL; + } + + if ( i >= mbi->mods_count ) { + printk(SKBOOT_ERR"invalid module #\n"); + return NULL; + } + + return (module_t *)(mbi->mods_addr + i * sizeof(module_t)); +} + +static struct mb2_tag +*next_mb2_tag(struct mb2_tag *start) +{ + /* given "start", what's the beginning of the next tag */ + void *addr = (void *) start; + if (start == NULL) + return NULL; + if (start->type == MB2_TAG_TYPE_END) + return NULL; + addr += ((start->size + 7) & ~7); + return (struct mb2_tag *) addr; +} + +static struct mb2_tag +*find_mb2_tag_type(struct mb2_tag *start, uint32_t tag_type) +{ + while (start != NULL){ + if (start->type == tag_type) + return start; + start = next_mb2_tag(start); + } + return start; +} + +static module_t +*get_module_mb2(loader_ctx *lctx, unsigned int i) +{ + struct mb2_tag *start = (struct mb2_tag *)(lctx->addr + 8); + unsigned int ii; + struct mb2_tag_module *tag_mod = NULL; + module_t *mt = NULL; + start = find_mb2_tag_type(start, MB2_TAG_TYPE_MODULE); + if (start != NULL){ + for (ii = 1; ii <= i; ii++){ + if (start == NULL) + return NULL; + else { + /* nudge off this hit */ + start = next_mb2_tag(start); + start = find_mb2_tag_type(start, MB2_TAG_TYPE_MODULE); + } + } + /* if we're here, we have the tag struct for the desired module */ + tag_mod = (struct mb2_tag_module *) start; + mt = (module_t *) &(tag_mod->mod_start); + } + return mt; +} + +#if 0 +void print_mbi(const multiboot_info_t *mbi) +{ + /* print mbi for debug */ + unsigned int i; + + printk(SKBOOT_DETA"print mbi@%p ...\n", mbi); + printk(SKBOOT_DETA"\t flags: 0x%x\n", mbi->flags); + if ( mbi->flags & MBI_MEMLIMITS ) + printk(SKBOOT_DETA"\t mem_lower: %uKB, mem_upper: %uKB\n", + mbi->mem_lower, mbi->mem_upper); + if ( mbi->flags & MBI_BOOTDEV ) { + printk(SKBOOT_DETA"\t boot_device.bios_driver: 0x%x\n", + mbi->boot_device.bios_driver); + printk(SKBOOT_DETA"\t boot_device.top_level_partition: 0x%x\n", + mbi->boot_device.top_level_partition); + printk(SKBOOT_DETA"\t boot_device.sub_partition: 0x%x\n", + mbi->boot_device.sub_partition); + printk(SKBOOT_DETA"\t boot_device.third_partition: 0x%x\n", + mbi->boot_device.third_partition); + } + if ( mbi->flags & MBI_CMDLINE ) { +# define CHUNK_SIZE 72 + /* Break the command line up into 72 byte chunks */ + int cmdlen = sk_strlen(mbi->cmdline); + char *cmdptr = (char *)mbi->cmdline; + char chunk[CHUNK_SIZE+1]; + printk(SKBOOT_DETA"\t cmdline@0x%x: ", mbi->cmdline); + chunk[CHUNK_SIZE] = '\0'; + while (cmdlen > 0) { + sk_strncpy(chunk, cmdptr, CHUNK_SIZE); + printk(SKBOOT_DETA"\n\t\"%s\"", chunk); + cmdptr += CHUNK_SIZE; + cmdlen -= CHUNK_SIZE; + } + printk(SKBOOT_DETA"\n"); + } + + if ( mbi->flags & MBI_MODULES ) { + printk(SKBOOT_DETA"\t mods_count: %u, mods_addr: 0x%x\n", + mbi->mods_count, mbi->mods_addr); + for ( i = 0; i < mbi->mods_count; i++ ) { + module_t *p = (module_t *)(mbi->mods_addr + i*sizeof(module_t)); + printk(SKBOOT_DETA"\t %d : mod_start: 0x%x, mod_end: 0x%x\n", i, + p->mod_start, p->mod_end); + printk(SKBOOT_DETA"\t string (@0x%x): \"%s\"\n", p->string, + (char *)p->string); + } + } + if ( mbi->flags & MBI_AOUT ) { + const aout_t *p = &(mbi->syms.aout_image); + printk(SKBOOT_DETA + "\t aout :: tabsize: 0x%x, strsize: 0x%x, addr: 0x%x\n", + p->tabsize, p->strsize, p->addr); + } + if ( mbi->flags & MBI_ELF ) { + const elf_t *p = &(mbi->syms.elf_image); + printk(SKBOOT_DETA + "\t elf :: num: %u, size: 0x%x, addr: 0x%x, shndx: 0x%x\n", + p->num, p->size, p->addr, p->shndx); + } + if ( mbi->flags & MBI_MEMMAP ) { + memory_map_t *p; + printk(SKBOOT_DETA + "\t mmap_length: 0x%x, mmap_addr: 0x%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(SKBOOT_DETA"\t size: 0x%x, base_addr: 0x%04x%04x, " + "length: 0x%04x%04x, type: %u\n", p->size, + p->base_addr_high, p->base_addr_low, + p->length_high, p->length_low, p->type); + } + } + if ( mbi->flags & MBI_DRIVES ) { + printk(SKBOOT_DETA"\t drives_length: %u, drives_addr: 0x%x\n", + mbi->drives_length, mbi->drives_addr); + } + if ( mbi->flags & MBI_CONFIG ) { + printk(SKBOOT_DETA"\t config_table: 0x%x\n", mbi->config_table); + } + if ( mbi->flags & MBI_BTLDNAME ) { + printk(SKBOOT_DETA"\t boot_loader_name@0x%x: %s\n", + mbi->boot_loader_name, (char *)mbi->boot_loader_name); + } + if ( mbi->flags & MBI_APM ) { + printk(SKBOOT_DETA"\t apm_table: 0x%x\n", mbi->apm_table); + } + if ( mbi->flags & MBI_VBE ) { + printk(SKBOOT_DETA"\t vbe_control_info: 0x%x\n" + "\t vbe_mode_info: 0x%x\n" + "\t vbe_mode: 0x%x\n" + "\t vbe_interface_seg: 0x%x\n" + "\t vbe_interface_off: 0x%x\n" + "\t vbe_interface_len: 0x%x\n", + mbi->vbe_control_info, + mbi->vbe_mode_info, + mbi->vbe_mode, + mbi->vbe_interface_seg, + mbi->vbe_interface_off, + mbi->vbe_interface_len + ); + } +} +#endif + +bool verify_loader_context(loader_ctx *lctx) +{ + unsigned int count; + if (LOADER_CTX_BAD(lctx)) + return false; + count = get_module_count(lctx); + if (count < 1){ + printk(SKBOOT_ERR"Error: no MB%d modules\n", lctx->type); + return false; + } else + return true; +} + +static bool remove_mb2_tag(loader_ctx *lctx, struct mb2_tag *cur) +{ + uint8_t *s, *d, *e; + struct mb2_tag *next, *end; + next = next_mb2_tag(cur); + if (next == NULL){ + printk(SKBOOT_ERR"missing next tag in remove_mb2_tag\n"); + return false; + } + /* where do we stop? */ + end = (struct mb2_tag *)(lctx->addr + 8); + end = find_mb2_tag_type(end, MB2_TAG_TYPE_END); + if (end == NULL){ + printk(SKBOOT_ERR"remove_mb2_tag, no end tag!!!!\n"); + return false; + } + e = (uint8_t *) end + end->size; + /* we'll do this byte-wise */ + s = (uint8_t *) next; d = (uint8_t *) cur; + + while (s <= e) { + *d = *s; d++; s++; + } + /* adjust MB2 length */ + *((unsigned long *) lctx->addr) -= + (uint8_t *)next - (uint8_t *)cur; + /* sanity check */ + /* print_loader_ctx(lctx); */ + return true; +} + +static bool +grow_mb2_tag(loader_ctx *lctx, struct mb2_tag *which, uint32_t how_much) +{ + struct mb2_tag *next, *new_next, *end; + int growth, slack; + uint8_t *s, *d; + // uint32_t old_size = which->size; + + /* we're holding the tag struct to grow, get its successor */ + next = next_mb2_tag(which); + + /* find the end--we will need it */ + end = (struct mb2_tag *)(lctx->addr + 8); + end = find_mb2_tag_type(end, MB2_TAG_TYPE_END); + if ( end == NULL ) + return false; + + /* How much bigger does it need to be? */ + /* NOTE: this breaks the MBI 2 structure for walking + * until we're done copying. + */ + which->size += how_much; + + /* what's the new growth for its successor? */ + new_next = next_mb2_tag(which); + growth = ((void *) new_next) - ((void *) next); + + /* check to make sure there's actually room for the growth */ + slack = g_mb_orig_size - *(uint32_t *) (lctx->addr); + if (growth > slack){ + printk(SKBOOT_ERR"YIKES!!! grow_mb2_tag slack %d < growth %d\n", + slack, growth); + } + + /* now we copy down from the bottom, going up */ + s = ((uint8_t *) end) + end->size; + d = s + growth; + while (s >= (uint8_t *)next){ + *d = *s; + d--; s--; + } + /* adjust MB2 length */ + *((uint32_t *) lctx->addr) += growth; + return true; +} + +static void *remove_module(loader_ctx *lctx, void *mod_start) +{ + module_t *m = NULL; + unsigned int i; + + if ( !verify_loader_context(lctx)) + return NULL; + + for ( i = 0; i < get_module_count(lctx); i++ ) { + m = get_module(lctx, i); + if ( mod_start == NULL || (void *)m->mod_start == mod_start ) + break; + } + + /* not found */ + if ( m == NULL ) { + printk(SKBOOT_ERR"could not find module to remove\n"); + return NULL; + } + + if (lctx->type == MB1_ONLY){ + /* multiboot 1 */ + /* if we're removing the first module (i.e. the "kernel") then */ + /* need to adjust some mbi fields as well */ + multiboot_info_t *mbi = (multiboot_info_t *) lctx->addr; + if ( mod_start == NULL ) { + mbi->cmdline = m->string; + mbi->flags |= MBI_CMDLINE; + mod_start = (void *)m->mod_start; + } + + /* copy remaing mods down by one */ + sk_memmove(m, m + 1, (mbi->mods_count - i - 1)*sizeof(module_t)); + + mbi->mods_count--; + + return mod_start; + } + if (lctx->type == MB2_ONLY){ + /* multiboot 2 */ + /* if we're removing the first module (i.e. the "kernel") then */ + /* need to adjust some mbi fields as well */ + char cmdbuf[SKBOOT_KERNEL_CMDLINE_SIZE]; + cmdbuf[0] = '\0'; + if ( mod_start == NULL ) { + char *cmdline = get_cmdline(lctx); + char *mod_string = get_module_cmd(lctx, m); + if ( cmdline == NULL ) { + printk(SKBOOT_ERR"could not find cmdline\n"); + return NULL; + } + if ( mod_string == NULL ) { + printk(SKBOOT_ERR"could not find module cmdline\n"); + return NULL; + } + if ((sk_strlen(mod_string)) > (sk_strlen(cmdline))){ + if (sk_strlen(mod_string) >= SKBOOT_KERNEL_CMDLINE_SIZE){ + printk(SKBOOT_ERR"No room to copy MB2 cmdline [%d < %d]\n", + (int)(sk_strlen(cmdline)), (int)(sk_strlen(mod_string))); + } else { + char *s = mod_string; + char *d = cmdbuf; + while (*s){ + *d = *s; + d++; s++; + } + *d = *s; + // strcpy(cmdbuf, mod_string); + } + } else { + // strcpy(cmdline,mod_string); + char *s = mod_string; + char *d = cmdline; + while (*s){ + *d = *s; + d++; s++; + } + *d = *s; + /* note: we didn't adjust the "size" field, since it didn't + * grow and this saves us the pain of shuffling everything + * after cmdline (which is usually first) + */ + } + mod_start = (void *)m->mod_start; + } + /* so MB2 is a different beast. The modules aren't necessarily + * adjacent, first, last, anything. What we can do is bulk copy + * everything after the thing we're killing over the top of it, + * and shorten the total length of the MB2 structure. + */ + { + struct mb2_tag *cur; + struct mb2_tag_module *mod = NULL; + module_t *cur_mod = NULL; + cur = (struct mb2_tag *)(lctx->addr + 8); + cur = find_mb2_tag_type(cur, MB2_TAG_TYPE_MODULE); + mod = (struct mb2_tag_module *) cur; + if (mod != NULL) + cur_mod = (module_t *)&(mod->mod_start); + + while (cur_mod != NULL && cur_mod != m){ + /* nudge off current record */ + cur = next_mb2_tag(cur); + cur = find_mb2_tag_type(cur, MB2_TAG_TYPE_MODULE); + mod = (struct mb2_tag_module *) cur; + if (mod != NULL) + cur_mod = (module_t *)&(mod->mod_start); + else + cur_mod = NULL; + } + if (cur_mod == NULL){ + printk(SKBOOT_ERR"remove_module() for MB2 failed\n"); + return NULL; + } + + /* we're here. cur is the MB2 tag we need to overwrite. */ + if (false == remove_mb2_tag(lctx, cur)) + return NULL; + } + if (cmdbuf[0] != '\0'){ + /* we need to grow the mb2_tag_string that holds the cmdline. + * we know there's room, since we've shortened the MB2 by the + * length of the module_tag we've removed, which contained + * the longer string. + */ + struct mb2_tag *cur = (struct mb2_tag *)(lctx->addr + 8); + struct mb2_tag_string *cmd; + + cur = find_mb2_tag_type(cur, MB2_TAG_TYPE_CMDLINE); + cmd = (struct mb2_tag_string *) cur; + if (cmd == NULL){ + printk(SKBOOT_ERR"remove_modules MB2 shuffle NULL cmd\n"); + return NULL; + } + + grow_mb2_tag(lctx, cur, sk_strlen(cmdbuf) - sk_strlen(cmd->string)); + + /* now we're all good, except for fixing up cmd */ + { + char * s = cmdbuf; + char *d = cmd->string; + while (*s){ + *d = *s; + d++; s++; + } + *d = *s; + } + } + return mod_start; + } + return NULL; +} + +bool +find_module_by_pattern(loader_ctx *lctx, void **base, size_t *size, + const void *pattern, size_t len) +{ + if ( lctx == NULL || lctx->addr == NULL) { + printk(SKBOOT_ERR"Error: context pointer is zero.\n"); + return false; + } + + if ( base == NULL ) { + printk(SKBOOT_ERR"Error: base is NULL.\n"); + return false; + } + + *base = NULL; + if ( size != NULL ) + *size = 0; + + if ( 0 == get_module_count(lctx)) { + printk(SKBOOT_ERR"Error: no module.\n"); + return false; + } + + for ( unsigned int i = get_module_count(lctx) - 1; i > 0; i-- ) { + module_t *m = get_module(lctx, i); + /* check size */ + size_t mod_size = m->mod_end - m->mod_start; + if ( len > mod_size ) { + printk(SKBOOT_ERR"Error: image size is smaller than data size.\n"); + return false; + } + + for ( unsigned int j = 0; j < (mod_size + len); j++ ) { + if ( sk_memcmp((void *)(m->mod_start + j), pattern, len) == 0 ) { + *base = (void *)m->mod_start; + if ( size != NULL ) + *size = mod_size; + return true; + } + } + } + + return false; +} + +static unsigned long max(unsigned long a, unsigned long b) +{ + return (a > b) ? a : b; +} + +static +unsigned long get_mbi_mem_end_mb1(const multiboot_info_t *mbi) +{ + unsigned long end = (unsigned long)(mbi + 1); + + if ( mbi->flags & MBI_CMDLINE ) + end = max(end, mbi->cmdline + sk_strlen((char *)mbi->cmdline) + 1); + if ( mbi->flags & MBI_MODULES ) { + end = max(end, mbi->mods_addr + mbi->mods_count * sizeof(module_t)); + unsigned int i; + for ( i = 0; i < mbi->mods_count; i++ ) { + module_t *p = get_module_mb1(mbi, i); + if ( p == NULL ) + break; + end = max(end, p->string + sk_strlen((char *)p->string) + 1); + } + } + if ( mbi->flags & MBI_AOUT ) { + const aout_t *p = &(mbi->syms.aout_image); + end = max(end, p->addr + p->tabsize + + sizeof(unsigned long) + p->strsize); + } + if ( mbi->flags & MBI_ELF ) { + const elf_t *p = &(mbi->syms.elf_image); + end = max(end, p->addr + p->num * p->size); + } + if ( mbi->flags & MBI_MEMMAP ) + end = max(end, mbi->mmap_addr + mbi->mmap_length); + if ( mbi->flags & MBI_DRIVES ) + end = max(end, mbi->drives_addr + mbi->drives_length); + /* mbi->config_table field should contain */ + /* "the address of the rom configuration table returned by the */ + /* GET CONFIGURATION bios call", so skip it */ + if ( mbi->flags & MBI_BTLDNAME ) + end = max(end, mbi->boot_loader_name + + sk_strlen((char *)mbi->boot_loader_name) + 1); + if ( mbi->flags & MBI_APM ) + /* per Grub-multiboot-Main Part2 Rev94-Structures, apm size is 20 */ + end = max(end, mbi->apm_table + 20); + if ( mbi->flags & MBI_VBE ) { + /* VBE2.0, VBE Function 00 return 512 bytes*/ + end = max(end, mbi->vbe_control_info + 512); + /* VBE2.0, VBE Function 01 return 256 bytes*/ + end = max(end, mbi->vbe_mode_info + 256); + } + + return PAGE_UP(end); +} + +module_t *get_module(loader_ctx *lctx, unsigned int i) +{ + if (LOADER_CTX_BAD(lctx)) + return NULL; + if (lctx->type == MB1_ONLY){ + return(get_module_mb1((multiboot_info_t *) lctx->addr, i)); + } else { + /* so currently, must be type 2 */ + return(get_module_mb2(lctx, i)); + } +} + +static void *remove_first_module(loader_ctx *lctx) +{ + if (LOADER_CTX_BAD(lctx)) + return NULL; + return(remove_module(lctx, NULL)); +} + +bool prepare_intermediate_loader(void) +{ + module_t *m; + void *kernel_image; + size_t kernel_size; + void *initrd_image; + size_t initrd_size; + uint64_t base; + uint64_t size; + + //printk(SKBOOT_INFO"reserving SLBOOT AP wake block (%Lx - %Lx) in e820 table\n", base, (base + size - 1)); + + /* if using memory logging, reserve log area */ + if ( g_log_targets & SKBOOT_LOG_TARGET_MEMORY ) { + base = SKBOOT_SERIAL_LOG_ADDR; + size = SKBOOT_SERIAL_LOG_SIZE; + printk(SKBOOT_INFO"reserving SLBOOT memory log (%Lx - %Lx) in e820 table\n", base, (base + size - 1)); + if ( !e820_protect_region(base, size, E820_RESERVED) ) + error_action(SK_ERR_FATAL); + } + + /* replace map in loader context with copy */ + replace_e820_map(g_ldr_ctx); + printk(SKBOOT_DETA"adjusted e820 map:\n"); + print_e820_map(); + + if ( !verify_loader_context(g_ldr_ctx) ) + return false; + + printk(SKBOOT_INFO"Assuming Intermediate Loader kernel is Linux format\n"); + + /* print_mbi(g_mbi); */ + + /* first module is the IL kernel image */ + m = get_module(g_ldr_ctx, 0); + kernel_size = m->mod_end - m->mod_start; + + /* removing the module causes its command line to be set in the MBI */ + kernel_image = remove_first_module(g_ldr_ctx); + if ( kernel_image == NULL ) + return false; + + if ( get_module_count(g_ldr_ctx) == 0 ) { + initrd_size = 0; + initrd_image = 0; + } + else { + m = get_module(g_ldr_ctx, 0); + initrd_image = (void *)m->mod_start; + initrd_size = m->mod_end - m->mod_start; + } + + return expand_linux_image(kernel_image, kernel_size, + initrd_image, initrd_size); +} + +char *get_module_cmd(loader_ctx *lctx, module_t *mod) +{ + if (LOADER_CTX_BAD(lctx) || mod == NULL) + return NULL; + + if (lctx->type == MB1_ONLY) + return (char *) mod->string; + else /* currently must be type 2 */ + return (char *)&(mod->string); +} + +char *get_first_module_cmd(loader_ctx *lctx) +{ + module_t *mod = get_module(lctx, 0); + return get_module_cmd(lctx, mod); +} + +char *get_cmdline(loader_ctx *lctx) +{ + if (LOADER_CTX_BAD(lctx)) + return NULL; + + if (lctx->type == MB1_ONLY){ + /* multiboot 1 */ + if (((multiboot_info_t *)lctx->addr)->flags & MBI_CMDLINE){ + return (char *) ((multiboot_info_t *)lctx->addr)->cmdline; + } else { + return NULL; + } + } else { + /* currently must be type 2 */ + struct mb2_tag *start = (struct mb2_tag *)(lctx->addr + 8); + start = find_mb2_tag_type(start, MB2_TAG_TYPE_CMDLINE); + if (start != NULL){ + struct mb2_tag_string *cmd = (struct mb2_tag_string *) start; + return (char *) &(cmd->string); + } + return NULL; + } +} + +bool have_loader_memlimits(loader_ctx *lctx) +{ + if (LOADER_CTX_BAD(lctx)) + return false; + if (lctx->type == MB1_ONLY){ + return (((multiboot_info_t *)lctx->addr)->flags & MBI_MEMLIMITS) != 0; + } else { + /* currently must be type 2 */ + struct mb2_tag *start = (struct mb2_tag *)(lctx->addr + 8); + start = find_mb2_tag_type(start, MB2_TAG_TYPE_MEMLIMITS); + return (start != NULL); + } +} + +uint32_t get_loader_mem_lower(loader_ctx *lctx) +{ + if (LOADER_CTX_BAD(lctx)) + return 0; + if (lctx->type == MB1_ONLY){ + return ((multiboot_info_t *)lctx->addr)->mem_lower; + } + /* currently must be type 2 */ + struct mb2_tag *start = (struct mb2_tag *)(lctx->addr + 8); + start = find_mb2_tag_type(start, MB2_TAG_TYPE_MEMLIMITS); + if (start != NULL){ + struct mb2_tag_memlimits *lim = (struct mb2_tag_memlimits *) start; + return lim->mem_lower; + } + return 0; +} + +uint32_t get_loader_mem_upper(loader_ctx *lctx) +{ + if (LOADER_CTX_BAD(lctx)) + return 0; + if (lctx->type == MB1_ONLY){ + return ((multiboot_info_t *)lctx->addr)->mem_upper; + } + /* currently must be type 2 */ + struct mb2_tag *start = (struct mb2_tag *)(lctx->addr + 8); + start = find_mb2_tag_type(start, MB2_TAG_TYPE_MEMLIMITS); + if (start != NULL){ + struct mb2_tag_memlimits *lim = (struct mb2_tag_memlimits *) start; + return lim->mem_upper; + } + return 0; +} + +unsigned int get_module_count(loader_ctx *lctx) +{ + if (LOADER_CTX_BAD(lctx)) + return 0; + if (lctx->type == MB1_ONLY){ + return(((multiboot_info_t *) lctx->addr)->mods_count); + } else { + /* currently must be type 2 */ + struct mb2_tag *start = (struct mb2_tag *)(lctx->addr + 8); + unsigned int count = 0; + start = find_mb2_tag_type(start, MB2_TAG_TYPE_MODULE); + while (start != NULL){ + count++; + /* nudge off this guy */ + start = next_mb2_tag(start); + start = find_mb2_tag_type(start, MB2_TAG_TYPE_MODULE); + } + return count; + } +} + +bool have_loader_memmap(loader_ctx *lctx) +{ + if (LOADER_CTX_BAD(lctx)) + return false; + if (lctx->type == MB1_ONLY){ + return (((multiboot_info_t *) lctx->addr)->flags & MBI_MEMMAP) != 0; + } else { + /* currently must be type 2 */ + struct mb2_tag *start = (struct mb2_tag *)(lctx->addr + 8); + start = find_mb2_tag_type(start, MB2_TAG_TYPE_MMAP); + return (start != NULL); + } +} + +memory_map_t *get_loader_memmap(loader_ctx *lctx) +{ + if (LOADER_CTX_BAD(lctx)) + return NULL; + if (lctx->type == MB1_ONLY){ + /* multiboot 1 */ + return (memory_map_t *)((multiboot_info_t *) lctx->addr)->mmap_addr; + } else { + /* currently must be type 2 */ + struct mb2_tag *start = (struct mb2_tag *)(lctx->addr + 8); + start = find_mb2_tag_type(start, MB2_TAG_TYPE_MMAP); + if (start != NULL){ + struct mb2_tag_mmap *mmap = (struct mb2_tag_mmap *) start; + /* note here: the MB2 mem entries start with the 64-bit address. + * the memory_map_t starts with four bytes of dummy "size". + * Pointing to the MB2 mmap "entry_version" instead of the entries + * lines the two tables up. + */ + return (memory_map_t *) &(mmap->entry_version); + } + return NULL; + } +} + +uint32_t get_loader_memmap_length(loader_ctx *lctx) +{ + if (LOADER_CTX_BAD(lctx)) + return 0; + if (lctx->type == MB1_ONLY){ + /* multiboot 1 */ + return (uint32_t)((multiboot_info_t *) lctx->addr)->mmap_length; + } else { + /* currently must be type 2 */ + struct mb2_tag *start = (struct mb2_tag *)(lctx->addr + 8); + start = find_mb2_tag_type(start, MB2_TAG_TYPE_MMAP); + if (start != NULL){ + struct mb2_tag_mmap *mmap = (struct mb2_tag_mmap *) start; + /* mmap->size is the size of the whole tag. We have 16 bytes + * ahead of the entries + */ + return mmap->size - 16; + } + return 0; + } +} + +unsigned long +get_loader_ctx_end(loader_ctx *lctx) +{ + if (LOADER_CTX_BAD(lctx)) + return 0; + if (lctx->type == 1){ + /* multiboot 1 */ + return (get_mbi_mem_end_mb1((multiboot_info_t *) lctx->addr)); + } else { + /* currently must be type 2 */ + unsigned long mb2_size = *((unsigned long *) lctx->addr); + return PAGE_UP(mb2_size + (unsigned long) lctx->addr); + } +} + +/* + * will go through all modules to find a usable SKL module to do an SKINIT + * launch. + */ +bool +find_skl_module(loader_ctx *lctx) +{ + if ( 0 == get_module_count(lctx)) { + printk(SKBOOT_ERR"no module info\n"); + return false; + } + + for ( unsigned int i = get_module_count(lctx) - 1; i > 0; i-- ) { + module_t *m = get_module(lctx, i); + if (lctx->type == 1) + printk(SKBOOT_DETA + "checking if module %s is an SKL module...\n", + (const char *)m->string); + if (lctx->type == 2) + printk(SKBOOT_DETA + "checking if module %s is an SKL module...\n", + (const char *)&(m->string)); + + void *base = (void *)m->mod_start; + uint32_t size = m->mod_end - (unsigned long)(base); + if ( is_skl_module(base, size) ){ + g_skl_module = (sl_header_t *)base; + g_skl_size = size; + printk(SKBOOT_DETA"SKL module found\n"); + return true; + } + } + /* no SKL found, hosed */ + printk(SKBOOT_ERR"no SKL module found\n"); + return false; +} + +void +replace_e820_map(loader_ctx *lctx) +{ + /* replace original with the copy */ + if (LOADER_CTX_BAD(lctx)) + return; + if (lctx->type == MB1_ONLY){ + /* multiboot 1 */ + multiboot_info_t *mbi = (multiboot_info_t *) lctx->addr; + mbi->mmap_addr = (uint32_t)get_e820_copy(); + mbi->mmap_length = (get_nr_map()) * sizeof(memory_map_t); + mbi->flags |= MBI_MEMMAP; /* in case only MBI_MEMLIMITS was set */ + return; + } else { + /* currently must be type 2 */ + memory_map_t *old, *new; + uint32_t i; + uint32_t old_memmap_size = get_loader_memmap_length(lctx); + uint32_t old_memmap_entry_count = + old_memmap_size / sizeof(memory_map_t); + if (old_memmap_entry_count < (get_nr_map())){ + /* we have to grow */ + struct mb2_tag *map = (struct mb2_tag *)(lctx->addr + 8); + map = find_mb2_tag_type(map, MB2_TAG_TYPE_MMAP); + if (map == NULL){ + printk(SKBOOT_ERR"MB2 map not found\n"); + return; + } + if (false == + grow_mb2_tag(lctx, map, + sizeof(memory_map_t) * + ((get_nr_map()) - old_memmap_entry_count))){ + printk(SKBOOT_ERR"MB2 failed to grow e820 map tag\n"); + return; + } + } + /* copy in new data */ + { + /* RLM: for now, we'll leave the entries in MB1 format (with real + * size). That may need revisited. + */ + new = get_e820_copy(); + old = get_loader_memmap(lctx); + if ( old == NULL ) { + printk(SKBOOT_ERR"old memory map not found\n"); + return; + } + for (i = 0; i < (get_nr_map()); i++){ + *old = *new; + old++, new++; + } + } + /* + printk(SKBOOT_INFO"AFTER replace_e820_map, loader context:\n"); + print_loader_ctx(lctx); + */ + printk(SKBOOT_INFO"replaced memory map:\n"); + print_e820_map(); + return; + } + return; +} + +void print_loader_ctx(loader_ctx *lctx) +{ + if (lctx->type != MB2_ONLY){ + printk(SKBOOT_ERR"this routine only prints out multiboot 2\n"); + return; + } else { + struct mb2_tag *start = (struct mb2_tag *)(lctx->addr + 8); + printk(SKBOOT_INFO"MB2 dump, size %d\n", *(uint32_t *)lctx->addr); + while (start != NULL){ + printk(SKBOOT_INFO"MB2 tag found of type %d size %d ", + start->type, start->size); + switch (start->type){ + case MB2_TAG_TYPE_CMDLINE: + case MB2_TAG_TYPE_LOADER_NAME: + { + struct mb2_tag_string *ts = + (struct mb2_tag_string *) start; + printk(SKBOOT_INFO"%s", ts->string); + } + break; + case MB2_TAG_TYPE_MODULE: + { + struct mb2_tag_module *ts = + (struct mb2_tag_module *) start; + printk_long(ts->cmdline); + } + break; + default: + break; + } + printk(SKBOOT_INFO"\n"); + start = next_mb2_tag(start); + } + return; + } +} + +bool +get_loader_efi_ptr(loader_ctx *lctx, uint32_t *address, uint64_t *long_address) +{ + struct mb2_tag *start, *hit; + struct mb2_tag_efi32 *efi32; + struct mb2_tag_efi64 *efi64; + if (LOADER_CTX_BAD(lctx)) + return false; + if (lctx->type != MB2_ONLY) + return false; + start = (struct mb2_tag *)(lctx->addr + 8); + hit = find_mb2_tag_type(start, MB2_TAG_TYPE_EFI32); + if (hit != NULL){ + efi32 = (struct mb2_tag_efi32 *) hit; + *address = (uint32_t) efi32->pointer; + *long_address = 0; + return true; + } + hit = find_mb2_tag_type(start, MB2_TAG_TYPE_EFI64); + if (hit != NULL){ + efi64 = (struct mb2_tag_efi64 *) hit; + *long_address = (uint64_t) efi64->pointer; + *address = 0; + return true; + } + return false; +} + +uint32_t +find_efi_memmap(loader_ctx *lctx, uint32_t *descr_size, + uint32_t *descr_vers, uint32_t *mmap_size) { + struct mb2_tag *start = NULL, *hit = NULL; + struct mb2_tag_efi_mmap *efi_mmap = NULL; + + start = (struct mb2_tag *)(lctx->addr + 8); + hit = find_mb2_tag_type(start, MB2_TAG_TYPE_EFI_MMAP); + if (hit == NULL) { + return 0; + } + + efi_mmap = (struct mb2_tag_efi_mmap *)hit; + *descr_size = efi_mmap->descr_size; + *descr_vers = efi_mmap->descr_vers; + *mmap_size = efi_mmap->size - sizeof(struct mb2_tag_efi_mmap); + if (*mmap_size % *descr_size) { + printk(SKBOOT_WARN "EFI memmmap (0x%x) should be a multiple of descriptor size (0x%x)\n", + *mmap_size, *descr_size); + } + return (uint32_t)(&efi_mmap->efi_mmap); +} + +bool +is_loader_launch_efi(loader_ctx *lctx) +{ + uint32_t addr = 0; uint64_t long_addr = 0; + if (LOADER_CTX_BAD(lctx)) + return false; + return (get_loader_efi_ptr(lctx, &addr, &long_addr)); +} + +void load_framebuffer_info(loader_ctx *lctx, void *vscr) +{ + screen_info_t *scr = (screen_info_t *) vscr; + struct mb2_tag *start; + + if (scr == NULL) + return; + if (LOADER_CTX_BAD(lctx)) + return; + start = (struct mb2_tag *)(lctx->addr + 8); + start = find_mb2_tag_type(start, MB2_TAG_TYPE_FRAMEBUFFER); + if (start != NULL){ + struct mb2_fb *mbf = (struct mb2_fb *) start; + scr->lfb_base = (uint32_t) mbf->common.fb_addr; + scr->lfb_width = mbf->common.fb_width; + scr->lfb_height = mbf->common.fb_height; + scr->lfb_depth = mbf->common.fb_bpp; + scr->lfb_line_len = mbf->common.fb_pitch; + scr->red_mask_size = mbf->fb_red_mask_size; + scr->red_field_pos = mbf->fb_red_field_position; + scr->blue_mask_size = mbf->fb_blue_mask_size; + scr->blue_field_pos = mbf->fb_blue_field_position; + scr->green_mask_size = mbf->fb_green_mask_size; + scr->green_field_pos = mbf->fb_green_field_position; + + scr->lfb_size = scr->lfb_line_len * scr->lfb_height; + /* round up to next 64k */ + scr->lfb_size = (scr->lfb_size + 65535) & 65535; + + scr->orig_video_isVGA = 0x70; /* EFI FB */ + scr->orig_y = 24; + } + +} + +void determine_loader_type(void *addr, uint32_t magic) +{ + if (g_ldr_ctx->addr == NULL){ + /* brave new world */ + g_ldr_ctx->addr = addr; + switch (magic){ + case MB_MAGIC: + g_ldr_ctx->type = MB1_ONLY; + { + /* we may as well do this here--if we received an ELF + * sections tag, we won't use it, and it's useless to + * Xen downstream, since it's OUR ELF sections, not Xen's + */ + multiboot_info_t *mbi = + (multiboot_info_t *) addr; + if (mbi->flags & MBI_AOUT){ + mbi->flags &= ~MBI_AOUT; + } + if (mbi->flags & MBI_ELF){ + mbi->flags &= ~MBI_ELF; + } + } + break; + case MB2_LOADER_MAGIC: + g_ldr_ctx->type = MB2_ONLY; + /* save the original MB2 info size, since we have + * to put updates inline + */ + g_mb_orig_size = *(uint32_t *) addr; + + { + void *mb2_reloc; + + /* Since GRUB is sticking the MB2 structure very close to the + * default location for the kernel, move it just below the SLBOOT + * image. + */ + mb2_reloc = (void*)PAGE_DOWN(SKBOOT_BASE_ADDR - g_mb_orig_size); + sk_memcpy(mb2_reloc, addr, g_mb_orig_size); + g_ldr_ctx->addr = mb2_reloc; + addr = mb2_reloc; + printk(SKBOOT_INFO"MB2 relocated to: %p size: %x\n", + addr, g_mb_orig_size); + + /* we may as well do this here--if we received an ELF + * sections tag, we won't use it, and it's useless to + * Xen downstream, since it's OUR ELF sections, not Xen's + */ + struct mb2_tag *start = + (struct mb2_tag *)(addr + 8); + start = find_mb2_tag_type(start, MB2_TAG_TYPE_ELF_SECTIONS); + if (start != NULL) + (void) remove_mb2_tag(g_ldr_ctx, start); + } + break; + default: + g_ldr_ctx->type = 0; + break; + } + } + /* so at this point, g_ldr_ctx->type has one of three values: + * 0: not a multiboot launch--we're doomed + * 1: MB1 launch + * 2: MB2 launch + */ +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/common/misc.c b/trenchboot/skboot/common/misc.c new file mode 100644 index 0000000..f682325 --- /dev/null +++ b/trenchboot/skboot/common/misc.c @@ -0,0 +1,292 @@ +/* + * misc.c: miscellaneous support fns + * + * Copyright (c) 2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * if 'prefix' != NULL, print it before each line of hex string + */ +void print_hex(const char *prefix, const void *prtptr, size_t size) +{ + for ( size_t i = 0; i < size; i++ ) { + if ( i % 16 == 0 && prefix != NULL ) + printk(SKBOOT_DETA"\n%s", prefix); + printk(SKBOOT_DETA"%02x ", *(uint8_t *)prtptr++); + } + printk(SKBOOT_DETA"\n"); +} + +static bool g_calibrated = false; +static uint64_t g_ticks_per_millisec; + +#define TIMER_FREQ 1193182 +#define TIMER_DIV(hz) ((TIMER_FREQ+(hz)/2)/(hz)) + +static void wait_tsc_uip(void) +{ + do { + outb(0x43, 0xe8); + cpu_relax(); + } while ( !(inb(0x42) & 0x80) ); + do { + outb(0x43, 0xe8); + cpu_relax(); + } while ( inb(0x42) & 0x80 ); +} + +static void calibrate_tsc(void) +{ + if ( g_calibrated ) + return; + + /* disable speeker */ + uint8_t val = inb(0x61); + val = ((val & ~0x2) | 0x1); + outb(0x61, val); + + /* 0xb6 - counter2, low then high byte write */ + /* mode 3, binary */ + outb(0x43, 0xb6); + + /* 0x4a9 - divisor to get 1ms period time */ + /* 1.19318 MHz / 1193 = 1000.15Hz */ + uint16_t latch = TIMER_DIV(1000); + outb(0x42, latch & 0xff); + outb(0x42, latch >> 8); + + /* 0xe8 - read back command, don't get count */ + /* get status, counter2 select */ + do { + outb(0x43, 0xe8); + cpu_relax(); + } while ( inb(0x42) & 0x40 ); + + wait_tsc_uip(); + + /* get starting TSC val */ + uint64_t start = rdtsc(); + + wait_tsc_uip(); + + uint64_t end = rdtsc(); + + /* # ticks in 1 millisecond */ + g_ticks_per_millisec = end - start; + + /* restore timer 1 programming */ + outb(0x43, 0x54); + outb(0x41, 0x12); + + g_calibrated = true; +} + +void delay(int millisecs) +{ + if ( millisecs <= 0 ) + return; + + calibrate_tsc(); + + uint64_t rtc = rdtsc(); + + uint64_t end_ticks = rtc + millisecs * g_ticks_per_millisec; + while ( rtc < end_ticks ) { + cpu_relax(); + rtc = rdtsc(); + } +} + +/* used by isXXX() in ctype.h */ +/* originally from: + * http://fxr.watson.org/fxr/source/dist/acpica/utclib.c?v=NETBSD5 + * re-licensed by Intel Corporation + */ + +const uint8_t _ctype[257] = { + _CN, /* 0x0 0. */ + _CN, /* 0x1 1. */ + _CN, /* 0x2 2. */ + _CN, /* 0x3 3. */ + _CN, /* 0x4 4. */ + _CN, /* 0x5 5. */ + _CN, /* 0x6 6. */ + _CN, /* 0x7 7. */ + _CN, /* 0x8 8. */ + _CN|_SP, /* 0x9 9. */ + _CN|_SP, /* 0xA 10. */ + _CN|_SP, /* 0xB 11. */ + _CN|_SP, /* 0xC 12. */ + _CN|_SP, /* 0xD 13. */ + _CN, /* 0xE 14. */ + _CN, /* 0xF 15. */ + _CN, /* 0x10 16. */ + _CN, /* 0x11 17. */ + _CN, /* 0x12 18. */ + _CN, /* 0x13 19. */ + _CN, /* 0x14 20. */ + _CN, /* 0x15 21. */ + _CN, /* 0x16 22. */ + _CN, /* 0x17 23. */ + _CN, /* 0x18 24. */ + _CN, /* 0x19 25. */ + _CN, /* 0x1A 26. */ + _CN, /* 0x1B 27. */ + _CN, /* 0x1C 28. */ + _CN, /* 0x1D 29. */ + _CN, /* 0x1E 30. */ + _CN, /* 0x1F 31. */ + _XS|_SP, /* 0x20 32. ' ' */ + _PU, /* 0x21 33. '!' */ + _PU, /* 0x22 34. '"' */ + _PU, /* 0x23 35. '#' */ + _PU, /* 0x24 36. '$' */ + _PU, /* 0x25 37. '%' */ + _PU, /* 0x26 38. '&' */ + _PU, /* 0x27 39. ''' */ + _PU, /* 0x28 40. '(' */ + _PU, /* 0x29 41. ')' */ + _PU, /* 0x2A 42. '*' */ + _PU, /* 0x2B 43. '+' */ + _PU, /* 0x2C 44. ',' */ + _PU, /* 0x2D 45. '-' */ + _PU, /* 0x2E 46. '.' */ + _PU, /* 0x2F 47. '/' */ + _XD|_DI, /* 0x30 48. '' */ + _XD|_DI, /* 0x31 49. '1' */ + _XD|_DI, /* 0x32 50. '2' */ + _XD|_DI, /* 0x33 51. '3' */ + _XD|_DI, /* 0x34 52. '4' */ + _XD|_DI, /* 0x35 53. '5' */ + _XD|_DI, /* 0x36 54. '6' */ + _XD|_DI, /* 0x37 55. '7' */ + _XD|_DI, /* 0x38 56. '8' */ + _XD|_DI, /* 0x39 57. '9' */ + _PU, /* 0x3A 58. ':' */ + _PU, /* 0x3B 59. ';' */ + _PU, /* 0x3C 60. '<' */ + _PU, /* 0x3D 61. '=' */ + _PU, /* 0x3E 62. '>' */ + _PU, /* 0x3F 63. '?' */ + _PU, /* 0x40 64. '@' */ + _XD|_UP, /* 0x41 65. 'A' */ + _XD|_UP, /* 0x42 66. 'B' */ + _XD|_UP, /* 0x43 67. 'C' */ + _XD|_UP, /* 0x44 68. 'D' */ + _XD|_UP, /* 0x45 69. 'E' */ + _XD|_UP, /* 0x46 70. 'F' */ + _UP, /* 0x47 71. 'G' */ + _UP, /* 0x48 72. 'H' */ + _UP, /* 0x49 73. 'I' */ + _UP, /* 0x4A 74. 'J' */ + _UP, /* 0x4B 75. 'K' */ + _UP, /* 0x4C 76. 'L' */ + _UP, /* 0x4D 77. 'M' */ + _UP, /* 0x4E 78. 'N' */ + _UP, /* 0x4F 79. 'O' */ + _UP, /* 0x50 80. 'P' */ + _UP, /* 0x51 81. 'Q' */ + _UP, /* 0x52 82. 'R' */ + _UP, /* 0x53 83. 'S' */ + _UP, /* 0x54 84. 'T' */ + _UP, /* 0x55 85. 'U' */ + _UP, /* 0x56 86. 'V' */ + _UP, /* 0x57 87. 'W' */ + _UP, /* 0x58 88. 'X' */ + _UP, /* 0x59 89. 'Y' */ + _UP, /* 0x5A 90. 'Z' */ + _PU, /* 0x5B 91. '[' */ + _PU, /* 0x5C 92. '\' */ + _PU, /* 0x5D 93. ']' */ + _PU, /* 0x5E 94. '^' */ + _PU, /* 0x5F 95. '_' */ + _PU, /* 0x60 96. '`' */ + _XD|_LO, /* 0x61 97. 'a' */ + _XD|_LO, /* 0x62 98. 'b' */ + _XD|_LO, /* 0x63 99. 'c' */ + _XD|_LO, /* 0x64 100. 'd' */ + _XD|_LO, /* 0x65 101. 'e' */ + _XD|_LO, /* 0x66 102. 'f' */ + _LO, /* 0x67 103. 'g' */ + _LO, /* 0x68 104. 'h' */ + _LO, /* 0x69 105. 'i' */ + _LO, /* 0x6A 106. 'j' */ + _LO, /* 0x6B 107. 'k' */ + _LO, /* 0x6C 108. 'l' */ + _LO, /* 0x6D 109. 'm' */ + _LO, /* 0x6E 110. 'n' */ + _LO, /* 0x6F 111. 'o' */ + _LO, /* 0x70 112. 'p' */ + _LO, /* 0x71 113. 'q' */ + _LO, /* 0x72 114. 'r' */ + _LO, /* 0x73 115. 's' */ + _LO, /* 0x74 116. 't' */ + _LO, /* 0x75 117. 'u' */ + _LO, /* 0x76 118. 'v' */ + _LO, /* 0x77 119. 'w' */ + _LO, /* 0x78 120. 'x' */ + _LO, /* 0x79 121. 'y' */ + _LO, /* 0x7A 122. 'z' */ + _PU, /* 0x7B 123. '{' */ + _PU, /* 0x7C 124. '|' */ + _PU, /* 0x7D 125. '}' */ + _PU, /* 0x7E 126. '~' */ + _CN, /* 0x7F 127. */ + + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80 to 0x8F */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x90 to 0x9F */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xA0 to 0xAF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xB0 to 0xBF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xC0 to 0xCF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xD0 to 0xDF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xE0 to 0xEF */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 0xF0 to 0x100 */ +}; + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/common/pci.c b/trenchboot/skboot/common/pci.c new file mode 100644 index 0000000..bbaec59 --- /dev/null +++ b/trenchboot/skboot/common/pci.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 1997, Stefan Esser + * Copyright (c) 2000, Michael Smith + * Copyright (c) 2000, BSDi + * Copyright (c) 2004, Scott Long + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* from: + * $FreeBSD: src/sys/i386/pci/pci_cfgreg.c,v 1.134.2.2.2.1 2010/06/14 02:09:06 kensmith Exp $ + */ +/* + * Portions copyright (c) 2010, Intel Corporation + */ + +#include +#include +#include + +enum { + CFGMECH_NONE = 0, + CFGMECH_1, + CFGMECH_2, + CFGMECH_PCIE, +}; + +static const int cfgmech = CFGMECH_1; + +/* + * Configuration space access using direct register operations + */ + +/* enable configuration space accesses and return data port address */ +static int +pci_cfgenable(unsigned bus, unsigned slot, unsigned func, int reg, int bytes) +{ + int dataport = 0; + + if (bus <= PCI_BUSMAX + && slot <= PCI_SLOTMAX + && func <= PCI_FUNCMAX + && (unsigned)reg <= PCI_REGMAX + && bytes != 3 + && (unsigned)bytes <= 4 + && (reg & (bytes - 1)) == 0) { + switch (cfgmech) { + case CFGMECH_PCIE: + case CFGMECH_1: + outl(CONF1_ADDR_PORT, (1 << 31) + | (bus << 16) | (slot << 11) + | (func << 8) | (reg & ~0x03)); + dataport = CONF1_DATA_PORT + (reg & 0x03); + break; + case CFGMECH_2: + outb(CONF2_ENABLE_PORT, 0xf0 | (func << 1)); + outb(CONF2_FORWARD_PORT, bus); + dataport = 0xc000 | (slot << 8) | reg; + break; + default: + break; + } + } + return (dataport); +} + +/* disable configuration space accesses */ +static void +pci_cfgdisable(void) +{ + switch (cfgmech) { + case CFGMECH_PCIE: + case CFGMECH_1: + /* + * Do nothing for the config mechanism 1 case. + * Writing a 0 to the address port can apparently + * confuse some bridges and cause spurious + * access failures. + */ + break; + case CFGMECH_2: + outb(CONF2_ENABLE_PORT, 0); + break; + default: + break; + } +} + +void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes) +{ + int port; + + port = pci_cfgenable(bus, slot, func, reg, bytes); + if (port != 0) { + switch (bytes) { + case 1: + outb(port, data); + break; + case 2: + outw(port, data); + break; + case 4: + outl(port, data); + break; + default: + break; + } + pci_cfgdisable(); + } +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/common/printk.c b/trenchboot/skboot/common/printk.c new file mode 100644 index 0000000..7427fa7 --- /dev/null +++ b/trenchboot/skboot/common/printk.c @@ -0,0 +1,162 @@ +/* + * printk.c: printk() output fn and helpers + * + * Copyright (c) 2006-2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +uint8_t g_log_level = SKBOOT_LOG_LEVEL_ALL; +uint8_t g_log_targets = SKBOOT_LOG_TARGET_SERIAL | SKBOOT_LOG_TARGET_VGA; + +/* + * memory logging + */ + +/* memory-based serial log (ensure in .data section so that not cleared) */ +__data skboot_log_t *g_log = NULL; + +static void memlog_init(void) +{ + if ( g_log == NULL ) { + g_log = (skboot_log_t *)SKBOOT_SERIAL_LOG_ADDR; + g_log->uuid = (uuid_t)SKBOOT_LOG_UUID; + g_log->curr_pos = 0; + } + + /* initialize these post-launch as well, since bad/malicious values */ + /* could compromise environment */ + g_log = (skboot_log_t *)SKBOOT_SERIAL_LOG_ADDR; + g_log->max_size = SKBOOT_SERIAL_LOG_SIZE - sizeof(*g_log); + + /* if we're calling this post-launch, verify that curr_pos is valid */ + if ( g_log->curr_pos > g_log->max_size ) + g_log->curr_pos = 0; +} + +static void memlog_write(const char *str, unsigned int count) +{ + if ( g_log == NULL || count > g_log->max_size ) + return; + + /* wrap to beginning if too big to fit */ + if ( g_log->curr_pos + count > g_log->max_size ) + g_log->curr_pos = 0; + + sk_memcpy(&g_log->buf[g_log->curr_pos], str, count); + g_log->curr_pos += count; + + /* if the string wasn't NULL-terminated, then NULL-terminate the log */ + if ( str[count-1] != '\0' ) + g_log->buf[g_log->curr_pos] = '\0'; + else { + /* so that curr_pos will point to the NULL and be overwritten */ + /* on next copy */ + g_log->curr_pos--; + } +} + +void printk_init(void) +{ + /* parse loglvl from string to int */ + get_skboot_loglvl(); + + /* parse logging targets */ + get_skboot_log_targets(); + + /* parse serial settings */ + if ( !get_skboot_serial() ) + g_log_targets &= ~SKBOOT_LOG_TARGET_SERIAL; + + if ( g_log_targets & SKBOOT_LOG_TARGET_MEMORY ) + memlog_init(); + if ( g_log_targets & SKBOOT_LOG_TARGET_SERIAL ) + serial_init(); + if ( g_log_targets & SKBOOT_LOG_TARGET_VGA ) { + vga_init(); + get_skboot_vga_delay(); /* parse vga delay time */ + } +} + +#define WRITE_LOGS(s, n) \ + do { \ + if (g_log_targets & SKBOOT_LOG_TARGET_MEMORY) memlog_write(s, n); \ + if (g_log_targets & SKBOOT_LOG_TARGET_SERIAL) serial_write(s, n); \ + if (g_log_targets & SKBOOT_LOG_TARGET_VGA) vga_write(s, n); \ + } while (0) + +void printk(const char *fmt, ...) +{ + char buf[256]; + char *pbuf = buf; + int n; + va_list ap; + uint8_t log_level; + static bool last_line_cr = true; + + sk_memset(buf, '\0', sizeof(buf)); + va_start(ap, fmt); + n = sk_vscnprintf(buf, sizeof(buf), fmt, ap); + + log_level = get_loglvl_prefix(&pbuf, &n); + + if ( !(g_log_level & log_level) ) + goto exit; + + /* prepend "SKBOOT: " if the last line that was printed ended with a '\n' */ + if ( last_line_cr ) + WRITE_LOGS("SLBOOT: ", 8); + + last_line_cr = (n > 0 && (*(pbuf+n-1) == '\n')); + WRITE_LOGS(pbuf, n); + +exit: + va_end(ap); +} + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/common/sha1.c b/trenchboot/skboot/common/sha1.c new file mode 100644 index 0000000..c3067f8 --- /dev/null +++ b/trenchboot/skboot/common/sha1.c @@ -0,0 +1,288 @@ +/*$KAME: sha1.c,v 1.5 2000/11/08 06:13:08 itojun Exp $ */ +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Portions copyright (c) 2010, Intel Corporation + */ + +/* + * From: FreeBSD sys/crypto/sha1.c + */ + +/* + * FIPS pub 180-1: Secure Hash Algorithm (SHA-1) + * based on: http://csrc.nist.gov/fips/fip180-1.txt + * implemented by Jun-ichiro itojun Itoh + */ + +#include +#include +#include + +struct sha1_ctxt { + union { + uint8_t b8[20]; + uint32_t b32[5]; + } h; + union { + uint8_t b8[8]; + uint64_t b64[1]; + } c; + union { + uint8_t b8[64]; + uint32_t b32[16]; + } m; + uint8_t count; +}; + +static void sha1_init(struct sha1_ctxt *); +static void sha1_pad(struct sha1_ctxt *); +static void sha1_loop(struct sha1_ctxt *, const uint8_t *, size_t); +static void sha1_result(struct sha1_ctxt *, unsigned char *); + +/* compatibilty with other SHA1 source codes */ +typedef struct sha1_ctxt SHA_CTX; +#define SHA1_Init(x) sha1_init((x)) +#define SHA1_Update(x, y, z) sha1_loop((x), (y), (z)) +#define SHA1_Final(x, y) sha1_result((y), (x)) + +#define BIG_ENDIAN \ + (!(__x86_64__ || __i386__ || _M_IX86 || _M_X64 || __ARMEL__ || __MIPSEL__)) +#define LITTLE_ENDIAN !BIG_ENDIAN + +/* constant table */ +static uint32_t _K[] = { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 }; +#define K(t) _K[(t) / 20] +#define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d))) +#define F1(b, c, d) (((b) ^ (c)) ^ (d)) +#define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) +#define F3(b, c, d) (((b) ^ (c)) ^ (d)) +#define S(n, x) (((x) << (n)) | ((x) >> (32 - n))) +#define H(n) (ctxt->h.b32[(n)]) +#define COUNT (ctxt->count) +#define BCOUNT (ctxt->c.b64[0] / 8) +#define W(n) (ctxt->m.b32[(n)]) +#define PUTBYTE(x){\ + ctxt->m.b8[(COUNT % 64)] = (x);\ + COUNT++;\ + COUNT %= 64;\ + ctxt->c.b64[0] += 8;\ + if (COUNT % 64 == 0)\ + sha1_step(ctxt);\ + } +#define PUTPAD(x){\ + ctxt->m.b8[(COUNT % 64)] = (x);\ + COUNT++;\ + COUNT %= 64;\ + if (COUNT % 64 == 0)\ + sha1_step(ctxt);\ + } +static void sha1_step(struct sha1_ctxt *ctxt) +{ + uint32_t a, b, c, d, e; + size_t t, s; + uint32_t tmp; + +#if LITTLE_ENDIAN + struct sha1_ctxt tctxt; + sk_memcpy(&tctxt.m.b8[0], &ctxt->m.b8[0], 64); + ctxt->m.b8[0] = tctxt.m.b8[3]; ctxt->m.b8[1] = tctxt.m.b8[2]; + ctxt->m.b8[2] = tctxt.m.b8[1]; ctxt->m.b8[3] = tctxt.m.b8[0]; + ctxt->m.b8[4] = tctxt.m.b8[7]; ctxt->m.b8[5] = tctxt.m.b8[6]; + ctxt->m.b8[6] = tctxt.m.b8[5]; ctxt->m.b8[7] = tctxt.m.b8[4]; + ctxt->m.b8[8] = tctxt.m.b8[11]; ctxt->m.b8[9] = tctxt.m.b8[10]; + ctxt->m.b8[10] = tctxt.m.b8[9]; ctxt->m.b8[11] = tctxt.m.b8[8]; + ctxt->m.b8[12] = tctxt.m.b8[15]; ctxt->m.b8[13] = tctxt.m.b8[14]; + ctxt->m.b8[14] = tctxt.m.b8[13]; ctxt->m.b8[15] = tctxt.m.b8[12]; + ctxt->m.b8[16] = tctxt.m.b8[19]; ctxt->m.b8[17] = tctxt.m.b8[18]; + ctxt->m.b8[18] = tctxt.m.b8[17]; ctxt->m.b8[19] = tctxt.m.b8[16]; + ctxt->m.b8[20] = tctxt.m.b8[23]; ctxt->m.b8[21] = tctxt.m.b8[22]; + ctxt->m.b8[22] = tctxt.m.b8[21]; ctxt->m.b8[23] = tctxt.m.b8[20]; + ctxt->m.b8[24] = tctxt.m.b8[27]; ctxt->m.b8[25] = tctxt.m.b8[26]; + ctxt->m.b8[26] = tctxt.m.b8[25]; ctxt->m.b8[27] = tctxt.m.b8[24]; + ctxt->m.b8[28] = tctxt.m.b8[31]; ctxt->m.b8[29] = tctxt.m.b8[30]; + ctxt->m.b8[30] = tctxt.m.b8[29]; ctxt->m.b8[31] = tctxt.m.b8[28]; + ctxt->m.b8[32] = tctxt.m.b8[35]; ctxt->m.b8[33] = tctxt.m.b8[34]; + ctxt->m.b8[34] = tctxt.m.b8[33]; ctxt->m.b8[35] = tctxt.m.b8[32]; + ctxt->m.b8[36] = tctxt.m.b8[39]; ctxt->m.b8[37] = tctxt.m.b8[38]; + ctxt->m.b8[38] = tctxt.m.b8[37]; ctxt->m.b8[39] = tctxt.m.b8[36]; + ctxt->m.b8[40] = tctxt.m.b8[43]; ctxt->m.b8[41] = tctxt.m.b8[42]; + ctxt->m.b8[42] = tctxt.m.b8[41]; ctxt->m.b8[43] = tctxt.m.b8[40]; + ctxt->m.b8[44] = tctxt.m.b8[47]; ctxt->m.b8[45] = tctxt.m.b8[46]; + ctxt->m.b8[46] = tctxt.m.b8[45]; ctxt->m.b8[47] = tctxt.m.b8[44]; + ctxt->m.b8[48] = tctxt.m.b8[51]; ctxt->m.b8[49] = tctxt.m.b8[50]; + ctxt->m.b8[50] = tctxt.m.b8[49]; ctxt->m.b8[51] = tctxt.m.b8[48]; + ctxt->m.b8[52] = tctxt.m.b8[55]; ctxt->m.b8[53] = tctxt.m.b8[54]; + ctxt->m.b8[54] = tctxt.m.b8[53]; ctxt->m.b8[55] = tctxt.m.b8[52]; + ctxt->m.b8[56] = tctxt.m.b8[59]; ctxt->m.b8[57] = tctxt.m.b8[58]; + ctxt->m.b8[58] = tctxt.m.b8[57]; ctxt->m.b8[59] = tctxt.m.b8[56]; + ctxt->m.b8[60] = tctxt.m.b8[63]; ctxt->m.b8[61] = tctxt.m.b8[62]; + ctxt->m.b8[62] = tctxt.m.b8[61]; ctxt->m.b8[63] = tctxt.m.b8[60]; +#endif + + a = H(0); b = H(1); c = H(2); d = H(3); e = H(4); + + for (t = 0; t < 20; t++) { + s = t & 0x0f; + if (t >= 16){ + W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); + } + tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t); + e = d; d = c; c = S(30, b); b = a; a = tmp; + } + for (t = 20; t < 40; t++) { + s = t & 0x0f; + W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); + tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t); + e = d; d = c; c = S(30, b); b = a; a = tmp; + } + for (t = 40; t < 60; t++) { + s = t & 0x0f; + W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); + tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t); + e = d; d = c; c = S(30, b); b = a; a = tmp; + } + for (t = 60; t < 80; t++) { + s = t & 0x0f; + W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); + tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t); + e = d; d = c; c = S(30, b); b = a; a = tmp; + } + + H(0) = H(0) + a; + H(1) = H(1) + b; + H(2) = H(2) + c; + H(3) = H(3) + d; + H(4) = H(4) + e; + + sk_memset(&ctxt->m.b8[0],0, 64); +} + +/*------------------------------------------------------------*/ + +static void sha1_init(struct sha1_ctxt *ctxt) +{ + sk_memset(ctxt,0, sizeof(struct sha1_ctxt)); + H(0) = 0x67452301; + H(1) = 0xefcdab89; + H(2) = 0x98badcfe; + H(3) = 0x10325476; + H(4) = 0xc3d2e1f0; +} + +static void sha1_pad(struct sha1_ctxt *ctxt) +{ + size_t padlen; /*pad length in bytes*/ + size_t padstart; + + PUTPAD(0x80); + + padstart = COUNT % 64; + padlen = 64 - padstart; + if (padlen < 8) { + sk_memset(&ctxt->m.b8[padstart],0, padlen); + COUNT += padlen; + COUNT %= 64; + sha1_step(ctxt); + padstart = COUNT % 64; /* should be 0 */ + padlen = 64 - padstart; /* should be 64 */ + } + sk_memset(&ctxt->m.b8[padstart],0, padlen - 8); + COUNT += (padlen - 8); + COUNT %= 64; +#if BIG_ENDIAN + PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[1]); + PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[3]); + PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[5]); + PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]); +#else + PUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[6]); + PUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[4]); + PUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[2]); + PUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]); +#endif +} + +static void sha1_loop(struct sha1_ctxt *ctxt,const uint8_t *input,size_t len) +{ + size_t gaplen; + size_t gapstart; + size_t off; + size_t copysiz; + + off = 0; + + while (off < len) { + gapstart = COUNT % 64; + gaplen = 64 - gapstart; + + copysiz = (gaplen < len - off) ? gaplen : len - off; + sk_memcpy(&ctxt->m.b8[gapstart],&input[off], copysiz); + COUNT += copysiz; + COUNT %= 64; + ctxt->c.b64[0] += copysiz * 8; + if (COUNT % 64 == 0) + sha1_step(ctxt); + off += copysiz; + } +} + +static void sha1_result(struct sha1_ctxt *ctxt,unsigned char *digest0) +{ + uint8_t *digest; + digest = (uint8_t *)digest0; + sha1_pad(ctxt); +#if BIG_ENDIAN + sk_memcpy(digest, &ctxt->h.b8[0],20); +#else + digest[0] = ctxt->h.b8[3]; digest[1] = ctxt->h.b8[2]; + digest[2] = ctxt->h.b8[1]; digest[3] = ctxt->h.b8[0]; + digest[4] = ctxt->h.b8[7]; digest[5] = ctxt->h.b8[6]; + digest[6] = ctxt->h.b8[5]; digest[7] = ctxt->h.b8[4]; + digest[8] = ctxt->h.b8[11]; digest[9] = ctxt->h.b8[10]; + digest[10] = ctxt->h.b8[9]; digest[11] = ctxt->h.b8[8]; + digest[12] = ctxt->h.b8[15]; digest[13] = ctxt->h.b8[14]; + digest[14] = ctxt->h.b8[13]; digest[15] = ctxt->h.b8[12]; + digest[16] = ctxt->h.b8[19]; digest[17] = ctxt->h.b8[18]; + digest[18] = ctxt->h.b8[17]; digest[19] = ctxt->h.b8[16]; +#endif +} + +int sha1_buffer(const unsigned char *buffer, size_t len, + unsigned char md[20]) +{ + SHA_CTX c; + + if (md == NULL) + return 1; + SHA1_Init(&c); + SHA1_Update(&c,buffer,len); + SHA1_Final(md,&c); + return 0; +} diff --git a/trenchboot/skboot/common/sha256.c b/trenchboot/skboot/common/sha256.c new file mode 100644 index 0000000..172fa65 --- /dev/null +++ b/trenchboot/skboot/common/sha256.c @@ -0,0 +1,262 @@ +#include +#include +#include +#include + +#define STORE64H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>56)&255); (y)[1] = (unsigned char)(((x)>>48)&255); \ + (y)[2] = (unsigned char)(((x)>>40)&255); (y)[3] = (unsigned char)(((x)>>32)&255); \ + (y)[4] = (unsigned char)(((x)>>24)&255); (y)[5] = (unsigned char)(((x)>>16)&255); \ + (y)[6] = (unsigned char)(((x)>>8)&255); (y)[7] = (unsigned char)((x)&255); } + +#define STORE32H(x, y) \ + { (y)[0] = (unsigned char)(((x)>>24)&255); (y)[1] = (unsigned char)(((x)>>16)&255); \ + (y)[2] = (unsigned char)(((x)>>8)&255); (y)[3] = (unsigned char)((x)&255); } + +#define LOAD32H(x, y) \ + { x = ((unsigned long)((y)[0] & 255)<<24) | \ + ((unsigned long)((y)[1] & 255)<<16) | \ + ((unsigned long)((y)[2] & 255)<<8) | \ + ((unsigned long)((y)[3] & 255)); } + +typedef struct { + u64 length; + u32 state[8], curlen; + unsigned char buf[64]; +} sha256_state; + +/* Various logical functions */ +#define RORc(x, y) ( ((((unsigned long)(x)&0xFFFFFFFFUL)>>(unsigned long)((y)&31)) \ + | ((unsigned long)(x)<<(unsigned long)(32-((y)&31)))) \ + & 0xFFFFFFFFUL) +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) (((x | y) & z) | (x & y)) +#define S(x, n) RORc((x),(n)) +#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) +#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) +#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) +#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) +#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + +/* compress 512-bits */ +static int sha256_compress(sha256_state * md, unsigned char *buf) +{ + u32 S[8], W[64], t0, t1; + int i; + + /* copy state into S */ + for (i = 0; i < 8; i++) { + S[i] = md->state[i]; + } + + /* copy the state into 512-bits into W[0..15] */ + for (i = 0; i < 16; i++) { + LOAD32H(W[i], buf + (4*i)); + } + + /* fill W[16..63] */ + for (i = 16; i < 64; i++) { + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; + } + + /* Compress */ +#define RND(a,b,c,d,e,f,g,h,i,ki) \ + t0 = h + Sigma1(e) + Ch(e, f, g) + ki + W[i]; \ + t1 = Sigma0(a) + Maj(a, b, c); \ + d += t0; \ + h = t0 + t1; + + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],0,0x428a2f98); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],1,0x71374491); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],2,0xb5c0fbcf); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],3,0xe9b5dba5); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],4,0x3956c25b); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],5,0x59f111f1); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],6,0x923f82a4); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],7,0xab1c5ed5); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],8,0xd807aa98); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],9,0x12835b01); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],10,0x243185be); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],11,0x550c7dc3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],12,0x72be5d74); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],13,0x80deb1fe); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],14,0x9bdc06a7); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],15,0xc19bf174); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],16,0xe49b69c1); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],17,0xefbe4786); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],18,0x0fc19dc6); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],19,0x240ca1cc); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],20,0x2de92c6f); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],21,0x4a7484aa); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],22,0x5cb0a9dc); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],23,0x76f988da); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],24,0x983e5152); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],25,0xa831c66d); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],26,0xb00327c8); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],27,0xbf597fc7); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],28,0xc6e00bf3); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],29,0xd5a79147); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],30,0x06ca6351); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],31,0x14292967); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],32,0x27b70a85); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],33,0x2e1b2138); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],34,0x4d2c6dfc); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],35,0x53380d13); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],36,0x650a7354); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],37,0x766a0abb); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],38,0x81c2c92e); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],39,0x92722c85); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],40,0xa2bfe8a1); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],41,0xa81a664b); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],42,0xc24b8b70); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],43,0xc76c51a3); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],44,0xd192e819); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],45,0xd6990624); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],46,0xf40e3585); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],47,0x106aa070); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],48,0x19a4c116); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],49,0x1e376c08); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],50,0x2748774c); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],51,0x34b0bcb5); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],52,0x391c0cb3); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],53,0x4ed8aa4a); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],54,0x5b9cca4f); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],55,0x682e6ff3); + RND(S[0],S[1],S[2],S[3],S[4],S[5],S[6],S[7],56,0x748f82ee); + RND(S[7],S[0],S[1],S[2],S[3],S[4],S[5],S[6],57,0x78a5636f); + RND(S[6],S[7],S[0],S[1],S[2],S[3],S[4],S[5],58,0x84c87814); + RND(S[5],S[6],S[7],S[0],S[1],S[2],S[3],S[4],59,0x8cc70208); + RND(S[4],S[5],S[6],S[7],S[0],S[1],S[2],S[3],60,0x90befffa); + RND(S[3],S[4],S[5],S[6],S[7],S[0],S[1],S[2],61,0xa4506ceb); + RND(S[2],S[3],S[4],S[5],S[6],S[7],S[0],S[1],62,0xbef9a3f7); + RND(S[1],S[2],S[3],S[4],S[5],S[6],S[7],S[0],63,0xc67178f2); + +#undef RND + + /* feedback */ + for (i = 0; i < 8; i++) { + md->state[i] = md->state[i] + S[i]; + } + return 0; +} + +#define SHA256_BLOCK_SIZE 64 +#define MIN(x, y) ( ((x)<(y))?(x):(y) ) +static int sha256_process(sha256_state * md, const unsigned char *in, unsigned long inlen) +{ + unsigned long n; + int err; + + if (md == NULL || in == NULL) + return -1; + if (md->curlen > sizeof(md->buf)) + return -1; + + while (inlen > 0) { + if (md->curlen == 0 && inlen >= SHA256_BLOCK_SIZE) { + if ((err = sha256_compress(md, (unsigned char *)in)) != 0) { + return err; + } + md->length += SHA256_BLOCK_SIZE * 8; + in += SHA256_BLOCK_SIZE; + inlen -= SHA256_BLOCK_SIZE; + } else { + n = MIN(inlen, (SHA256_BLOCK_SIZE - md->curlen)); + sk_memcpy(md->buf + md->curlen, in, (size_t)n); + md->curlen += n; + in += n; + inlen -= n; + if (md->curlen == SHA256_BLOCK_SIZE) { + if ((err = sha256_compress(md, md->buf)) != 0) { + return err; + } + md->length += 8*SHA256_BLOCK_SIZE; + md->curlen = 0; + } + } + } + return 0; +} + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +static void sha256_init(sha256_state * md) +{ + if (md == NULL) + return; + + md->curlen = 0; + md->length = 0; + md->state[0] = 0x6A09E667UL; + md->state[1] = 0xBB67AE85UL; + md->state[2] = 0x3C6EF372UL; + md->state[3] = 0xA54FF53AUL; + md->state[4] = 0x510E527FUL; + md->state[5] = 0x9B05688CUL; + md->state[6] = 0x1F83D9ABUL; + md->state[7] = 0x5BE0CD19UL; +} + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (32 bytes) + @return 0 if successful +*/ +static int sha256_done(sha256_state * md, unsigned char *out) +{ + int i; + + if (md == NULL || out == NULL) + return -1; + + if (md->curlen >= sizeof(md->buf)) + return -1; + + /* increase the length of the message */ + md->length += md->curlen * 8; + + /* append the '1' bit */ + md->buf[md->curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->curlen > 56) { + while (md->curlen < 64) { + md->buf[md->curlen++] = (unsigned char)0; + } + sha256_compress(md, md->buf); + md->curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->curlen < 56) { + md->buf[md->curlen++] = (unsigned char)0; + } + + /* store length */ + STORE64H(md->length, md->buf+56); + sha256_compress(md, md->buf); + + /* copy output */ + for (i = 0; i < 8; i++) { + STORE32H(md->state[i], out+(4*i)); + } + + return 0; +} + +void sha256_buffer(const unsigned char *buffer, size_t len, + unsigned char hash[32]) +{ + sha256_state md; + + sha256_init(&md); + sha256_process(&md, buffer, len); + sha256_done(&md, hash); +} diff --git a/trenchboot/skboot/common/skboot.c b/trenchboot/skboot/common/skboot.c new file mode 100644 index 0000000..7d68ae1 --- /dev/null +++ b/trenchboot/skboot/common/skboot.c @@ -0,0 +1,311 @@ +/* + * skboot.c: main entry point and pre-launch code for Trenchboot + * + * Used to be: + * skboot.c: main entry point and "generic" routines for measured launch + * support + * + * Copyright (c) 2006-2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* loader context struct saved so that post_launch() can use it */ +__data loader_ctx g_loader_ctx = { NULL, 0 }; +__data loader_ctx *g_ldr_ctx = &g_loader_ctx; + +__data sl_header_t *g_skl_module = NULL; +__data uint32_t g_skl_size = 0; + +static uint32_t g_default_error_action = SK_SHUTDOWN_HALT; +static unsigned int g_cpuid_ext_feat_info; +static bool is_powercycle_required = true; + +static void shutdown_system(uint32_t shutdown_type) +{ + static const char *types[] = { "SK_SHUTDOWN_REBOOT", "SK_SHUTDOWN_REBOOT", + "SK_SHUTDOWN_HALT" }; + char type[32]; + + /* NOTE: the TPM close and open current locality is not needed here since */ + /* since that only makes sense if this is called post laucnh which is */ + /* the case in SLBOOT */ + + if ( shutdown_type >= ARRAY_SIZE(types) ) + sk_snprintf(type, sizeof(type), "unknown: %u", shutdown_type); + else { + sk_strncpy(type, types[shutdown_type], sizeof(type)); + type[sizeof(type) - 1] = '\0'; + } + printk(SKBOOT_INFO"shutdown_system() called for shutdown_type: %s\n", type); + + switch( shutdown_type ) { + case SK_SHUTDOWN_REBOOT: + if ( is_powercycle_required ) { + /* powercycle by writing 0x0a+0x0e to port 0xcf9 */ + /* (supported by all TXT-capable chipsets) */ + outb(0xcf9, 0x0a); + outb(0xcf9, 0x0e); + } + else { + /* soft reset by writing 0xfe to keyboard reset vector 0x64 */ + /* BIOSes (that are not performing some special operation, */ + /* such as update) will turn this into a platform reset as */ + /* expected. */ + outb(0x64, 0xfe); + /* fall back to soft reset by writing 0x06 to port 0xcf9 */ + /* (supported by all TXT-capable chipsets) */ + outb(0xcf9, 0x06); + } + break; + case SK_SHUTDOWN_SHUTDOWN: + /* TODO implement S5 */ + break; + /* FALLTHROUGH */ + case SK_SHUTDOWN_HALT: + default: + while ( true ) + halt(); + } +} + +unsigned long get_skboot_mem_end(void) +{ + return PAGE_UP((unsigned long)&_end); +} + +static bool prepare_cpu(void) +{ + unsigned long eflags, cr0; + uint64_t mcg_cap, mcg_stat; + + /* must be running at CPL 0 => this is implicit in even getting this far */ + /* since our bootstrap code loads a GDT, etc. */ + + cr0 = read_cr0(); + + /* must be in protected mode */ + if ( !(cr0 & CR0_PE) ) { + printk(SKBOOT_ERR"ERR: not in protected mode\n"); + return false; + } + + /* cache must be enabled (CR0.CD = CR0.NW = 0) */ + if ( cr0 & CR0_CD ) { + printk(SKBOOT_INFO"CR0.CD set\n"); + cr0 &= ~CR0_CD; + } + if ( cr0 & CR0_NW ) { + printk(SKBOOT_INFO"CR0.NW set\n"); + cr0 &= ~CR0_NW; + } + + /* native FPU error reporting must be enabled for proper */ + /* interaction behavior */ + if ( !(cr0 & CR0_NE) ) { + printk(SKBOOT_INFO"CR0.NE not set\n"); + cr0 |= CR0_NE; + } + + write_cr0(cr0); + + /* cannot be in virtual-8086 mode (EFLAGS.VM=1) */ + eflags = read_eflags(); + if ( eflags & X86_EFLAGS_VM ) { + printk(SKBOOT_INFO"EFLAGS.VM set\n"); + write_eflags(eflags | ~X86_EFLAGS_VM); + } + + printk(SKBOOT_INFO"CR0 and EFLAGS OK\n"); + + /* + * verify all machine check status registers are clear (unless + * support preserving them) + */ + + /* no machine check in progress (IA32_MCG_STATUS.MCIP=1) */ + mcg_stat = rdmsr(MSR_MCG_STATUS); + if ( mcg_stat & 0x04 ) { + printk(SKBOOT_ERR"machine check in progress\n"); + return false; + } + + /* check if all machine check regs are clear */ + mcg_cap = rdmsr(MSR_MCG_CAP); + for ( unsigned int i = 0; i < (mcg_cap & 0xff); i++ ) { + mcg_stat = rdmsr(MSR_MC0_STATUS + 4*i); + if ( mcg_stat & (1ULL << 63) ) { + printk(SKBOOT_ERR"MCG[%u] = %Lx ERROR\n", i, mcg_stat); + return false; + } + } + + printk(SKBOOT_INFO"Machine Check OK\n"); + + return true; +} + +static bool platform_architecture(void) +{ + uint32_t regs[4]; + + do_cpuid(0, regs); + + if ( regs[1] == 0x68747541 /* "Auth" */ + && regs[2] == 0x444d4163 /* "cAMD" */ + && regs[3] == 0x69746e65 ) /* "enti" */ + return true; + + printk(SKBOOT_ERR"Error: platform is neither Intel or AMD\n"); + return false; +} + +static int supports_skinit(void) +{ + g_cpuid_ext_feat_info = cpuid_ecx(0x80000001); + + if (g_cpuid_ext_feat_info & CPUID_X86_FEATURE_SKINIT) { + printk(SKBOOT_INFO"SKINIT CPU and all needed capabilities present\n"); + return SK_ERR_NONE; + } + return SK_ERR_NO_SKINIT; +} + +void error_action(int error) +{ + if ( error == SK_ERR_NONE ) + return; + + printk(SKBOOT_ERR"error action invoked for: %x\n", error); + shutdown_system(g_default_error_action); +} + +void begin_launch(void *addr, uint32_t magic) +{ + const char *cmdline; + int err; + + /* this is the SKBOOT module loader type, either MB1 or MB2 */ + determine_loader_type(addr, magic); + + cmdline = get_cmdline(g_ldr_ctx); + sk_memset(g_cmdline, '\0', sizeof(g_cmdline)); + if ( cmdline ) + sk_strncpy(g_cmdline, cmdline, sizeof(g_cmdline)-1); + + /* always parse cmdline */ + skboot_parse_cmdline(); + + g_default_error_action = get_error_shutdown(); + + /* initialize all logging targets */ + printk_init(); + + printk(SKBOOT_INFO"******************* SKBOOT *******************\n"); + printk(SKBOOT_INFO" %s\n", SKBOOT_CHANGESET); + printk(SKBOOT_INFO"*********************************************\n"); + + printk(SKBOOT_INFO"command line: %s\n", g_cmdline); + + if ( !platform_architecture() ) + error_action(SK_ERR_FATAL); + + /* we should only be executing on the BSP */ + if ( !(rdmsr(MSR_APICBASE) & APICBASE_BSP) ) { + printk(SKBOOT_INFO"entry processor is not BSP\n"); + error_action(SK_ERR_FATAL); + } + printk(SKBOOT_INFO"BSP is cpu %u\n", get_apicid()); + + /* make copy of e820 map that we will use and adjust */ + if ( !copy_e820_map(g_ldr_ctx) ) + error_action(SK_ERR_FATAL); + + /* we need to make sure this is a (SKINIT) capable platform before using */ + /* any of the features, incl. those required to check if the environment */ + /* has already been launched */ + err = supports_skinit(); + error_action(err); + + /* make TPM ready for measured launch */ + if ( !tpm_detect() ) + error_action(SK_ERR_TPM_NOT_READY); + + /* ensure there are modules */ + if ( !verify_loader_context(g_ldr_ctx) ) + error_action(SK_ERR_FATAL); + + /* make the CPU ready for secure launch */ + if ( !prepare_cpu() ) + error_action(SK_ERR_FATAL); + + if ( !prepare_tpm() ) + error_action(SK_ERR_TPM_NOT_READY); + + /* TODO locate and load LZ */ + + if ( !prepare_intermediate_loader() ) + error_action(SK_ERR_FATAL); + + /* launch the secure environment */ + /*err = txt_launch_environment(g_ldr_ctx); + error_action(err);*/ +} + +void handle_exception(void) +{ + printk(SKBOOT_INFO"Received exception; shutting down...\n"); +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/common/skboot.lds b/trenchboot/skboot/common/skboot.lds new file mode 100644 index 0000000..b797ef9 --- /dev/null +++ b/trenchboot/skboot/common/skboot.lds @@ -0,0 +1,37 @@ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(start) +PHDRS +{ + text PT_LOAD ; +} +SECTIONS +{ + . = 0x02C00000; + + .text : { + *(.skboot_multiboot_header) + *(.text) + *(.fixup) + *(.gnu.warning) + } :text = 0x9090 + + .rodata : { *(.rodata) *(.rodata.*) } + . = ALIGN(4096); + + .data : { /* Data */ + *(.data) + CONSTRUCTORS + } + + . = ALIGN(4096); + + __bss_start = .; /* BSS */ + .bss : { + *(.bss.stack_aligned) + *(.bss.page_aligned) + *(.bss) + } + + _end = . ; +} diff --git a/trenchboot/skboot/common/skl.c b/trenchboot/skboot/common/skl.c new file mode 100644 index 0000000..ddcb016 --- /dev/null +++ b/trenchboot/skboot/common/skl.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +lz_info_t lz_info = { + .uuid = { + 0x78, 0xf1, 0x26, 0x8e, 0x04, 0x92, 0x11, 0xe9, + 0x83, 0x2a, 0xc8, 0x5b, 0x76, 0xc4, 0xcc, 0x02, + }, + .version = SKL_VERSION, + .msb_key_algo = 0x14, + .msb_key_hash = { 0 }, +}; + +bool is_skl_module(const void *skl_base, uint32_t skl_size) +{ + sl_header_t *header = (sl_header_t *)skl_base; + lz_info_t *info; + + if (skl_size < (16*PAGE_SIZE)) { + printk(SKBOOT_INFO"Possible SKL module too small\n"); + return false; + } + + info = (lz_info_t *)(header + header->skl_info_offset); + if (info->version != SKL_VERSION) { + printk(SKBOOT_INFO"Possible SKL module incorrect version\n"); + return false; + } + + if (sk_memcmp(info->uuid, lz_info.uuid, 16)) { + printk(SKBOOT_INFO"Possible SKL module incorrect UUID\n"); + return false; + } + + /* Otherwise it looks like the SKL module */ + + return true; +} diff --git a/trenchboot/skboot/common/string.c b/trenchboot/skboot/common/string.c new file mode 100644 index 0000000..241cc8f --- /dev/null +++ b/trenchboot/skboot/common/string.c @@ -0,0 +1,739 @@ +/* + * string.c: provides string formatting fns + * + * Copyright (c) 2010-2011, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include + +static bool div64(uint64_t num, uint32_t base, uint64_t *quot, uint32_t *rem) +{ + /* check exceptions */ + if ( (quot == NULL) || (rem == NULL) || (base == 0) ) + return false; + + uint32_t high = num >> 32; + uint32_t low = (uint32_t)num; + if ( high == 0 ) { + *quot = low / base; + *rem = low % base; + } + else { + uint64_t hquo = high / base; \ + uint32_t hrem = high % base; + uint32_t lquo; + /* + * use "divl" instead of "/" to avoid the link error + * undefined reference to `__udivdi3' + */ + __asm__ __volatile__ ( "divl %4;" + : "=a"(lquo), "=d"(*rem) + : "a"(low), "d"(hrem), "r"(base)); + *quot = (hquo << 32) + lquo; + } + + return true; +} + +/* + * write the character into the buffer + * return the position of the buffer after writting + */ +static unsigned long write_char_to_buffer(char *buf, size_t buf_len, + unsigned long buf_pos, char ch) +{ + /* check buffer overflow? */ + if ( buf_pos >= buf_len ) + return 0; + + *(buf + buf_pos) = ch; + return buf_pos + 1; +} + +/* + * write pad_len pads into the buffer + * return the position of the buffer after writting + */ +static unsigned long write_pads_to_buffer(char *buf, size_t buf_len, + unsigned long buf_pos, char pad, + size_t pad_len) +{ + for ( unsigned int i = 0; i < pad_len; i++ ) + buf_pos = write_char_to_buffer(buf, buf_len, buf_pos, pad); + + return buf_pos; +} + +/* %[flags][width][.precision][length]specifier */ +typedef struct { + /* flag */ +#define LEFT_ALIGNED (1 << 0) /* '-' */ +#define SIGNED (1 << 1) /* '+' */ +#define SPACE (1 << 2) /* ' ' */ +#define PREFIX (1 << 3) /* '#' */ +#define ZERO_PADDED (1 << 4) /* '0' */ + int flag; + /* width & precision */ + unsigned int width, precision; + /* length */ + enum {NORM, LONG, LONGLONG} flag_long; + /* specifier */ + int base; + bool cap; + bool sign; + bool digit; +} modifiers_t; + +/* + * write the string into the buffer regarding flags + * return the position of the buffer after writing + */ +static unsigned long write_string_to_buffer(char *buf, size_t buf_len, + unsigned long buf_pos, + const char* str, size_t strlen, + modifiers_t *mods) +{ + unsigned int i; + if (mods->precision > 0) + strlen = (strlen > mods->precision) ? mods->precision : strlen; + mods->width = ( mods->width > strlen ) ? mods->width - strlen : 0; + if ( mods->flag & LEFT_ALIGNED ) { /* left align */ + for ( i = 0; i < strlen; i++ ) + buf_pos = write_char_to_buffer(buf, buf_len, buf_pos, str[i]); + buf_pos = write_pads_to_buffer(buf, buf_len, buf_pos, ' ', mods->width); + } + else { /* right align */ + /* if not digit, don't considering pad '0' */ + char pad = ( mods->digit && (mods->flag & ZERO_PADDED) ) ? '0' : ' '; + + buf_pos = write_pads_to_buffer(buf, buf_len, buf_pos, pad, mods->width); + for ( i = 0; i < strlen; i++ ) + buf_pos = write_char_to_buffer(buf, buf_len, buf_pos, str[i]); + } + + return buf_pos; +} + +/* convert a integer to a string regarding flags, qualifier, specifier, etc. */ +static size_t int2str(long long val, char *str, size_t strlen, + const modifiers_t *mods) +{ + unsigned int i; + size_t length = 0, number_length = 0; + unsigned long number_start = 0; + const char hexdig_lowercase[] = "0123456789abcdef"; + const char hexdig_uppercase[] = "0123456789ABCDEF"; + unsigned long long nval; + + /* check, we support octal/decimal/hex only */ + if ( (mods->base != 8) && (mods->base != 10) && (mods->base != 16) ) + return 0; + + if ( str == NULL || strlen == 0 ) + return 0; + + if ( mods->flag & PREFIX ) { + if ( mods->base == 8 ) + *(str + length++) = '0'; /* add prefix 0 for octal */ + else if ( mods->base == 16 ) { + if ( strlen < 2 ) + return 0; + + /* add prefix 0x/0X for hex */ + *(str + length++) = '0'; + *(str + length++) = ( mods->cap ) ? 'X' : 'x'; + } + } + + /* + * if it is shown as signed decimal(%d), we consider to add -/+/' ' + * but, if it is an unsigned number, no need to add -/+/' ' + */ + if ( mods->base == 10 && mods->sign ) { + if ( val < 0 ) { /* negative */ + *(str + length++) = '-'; + val = -val; + } + else { /* positive */ + if ( mods->flag & SIGNED ) + *(str + length++) = '+'; + else if ( mods->flag & SPACE ) + *(str + length++) = ' '; + } + } + + /* truncate to unsigned long or unsigned int if type of val is */ + if ( mods->flag_long == LONGLONG ) + nval = (unsigned long long)val; + else if ( mods->flag_long == LONG ) + nval = (unsigned long long)(unsigned long)val; + else + nval = (unsigned long long)(unsigned int)val; + + /* convert */ + number_start = length; + do { + /* overflow? */ + if ( length >= strlen ) + break; + + uint32_t rem = 0; + if ( !div64(nval, mods->base, &nval, &rem) ) + return 0; + *(str + length) = ( mods->cap ) ? + hexdig_uppercase[rem] : hexdig_lowercase[rem]; + length++; + number_length++; + } while ( nval ); + + /* handle precision */ + while ( number_length < mods->precision ) { + /* overflow? */ + if ( length >= strlen ) + break; + + *(str + length) = '0'; + length++; + number_length++; + } + + /* reverse */ + for ( i = 0; i < number_length/2; i++ ) { + char ch; + + ch = *(str + number_start + i); + *(str + number_start + i) + = *(str + number_start + (number_length - i - 1)); + *(str + number_start + (number_length - i - 1)) = ch; + } + + return length; +} + +int sk_vscnprintf(char *buf, size_t size, const char *fmt, va_list ap) +{ + unsigned int buf_pos = 0; /* return value doesn't count the last '\0' */ + const char *fmt_ptr; + modifiers_t mods; + + /* check buf */ + if ( (buf == NULL) || (size == 0) ) + return 0; + + /* check fmt */ + if ( fmt == NULL ) + return 0; + + sk_memset(&mods, 0, sizeof(mods)); + + while ( buf_pos < size ) { + bool success; + + /* handle normal characters */ + while ( *fmt != '%' ) { + buf_pos = write_char_to_buffer(buf, size, buf_pos, *fmt); + if ( *fmt == '\0' ) + return buf_pos - 1; + fmt++; + } + + /* handle %: %[flags][width][.precision][length]specifier */ + /* + * start to parse the syntax of %, save the position of fmt + * in case that append the string to the buffer if % substring + * doesnot match the syntax + */ + fmt_ptr = fmt + 1; /* skip '%' */ + success = true; /* assume parsing % substring would succeed */ + + /* parsing flags */ + while ( true ) { + switch ( *fmt_ptr ) { + case '-': + mods.flag |= LEFT_ALIGNED; + break; + case '+': + mods.flag |= SIGNED ; + break; + case ' ': + mods.flag |= SPACE; + break; + case '#': + mods.flag |= PREFIX; + break; + case '0': + mods.flag |= ZERO_PADDED; + break; + default: + goto handle_width; + } + fmt_ptr++; + } + + /* parsing width */ +handle_width: + if ( *fmt_ptr == '*' ) { + mods.width = va_arg(ap, int); + fmt_ptr++; + } + else + mods.width = sk_strtoul(fmt_ptr, (char **)&fmt_ptr, 10); + + if ( *fmt_ptr == '.' ) { + /* skip . */ + fmt_ptr++; + + /* parsing precision */ + if ( *fmt_ptr == '*' ) { + mods.precision = va_arg(ap, int); + fmt_ptr++; + } + else + mods.precision = sk_strtoul(fmt_ptr, (char **)&fmt_ptr, 10); + } + + /* parsing qualifier: h l L; + * h is ignored here, and 'L' and 'j' are treated as 'll' + */ + mods.flag_long = NORM; + if ( *fmt_ptr == 'L' || *fmt_ptr == 'j' ) { + mods.flag_long = LONGLONG; + fmt_ptr++; + } + else if ( *fmt_ptr == 'l' && *(fmt_ptr + 1) == 'l' ) { + mods.flag_long = LONGLONG; + fmt_ptr += 2; + } + else if ( *fmt_ptr == 'l' ) { + mods.flag_long = LONG; + fmt_ptr++; + } + +#define write_number_to_buffer(__buf, __size, __buf_pos, __mods) \ +({ \ + char __str[32]; \ + size_t __real_strlen; \ + if ( __mods.flag_long == LONGLONG ) { \ + long long __number = 0; \ + __number = va_arg(ap, long long); \ + __real_strlen = int2str(__number, __str, sizeof(__str), &__mods); \ + } \ + else if ( __mods.flag_long == LONG ) { \ + long __number = 0; \ + __number = va_arg(ap, long); \ + __real_strlen = int2str(__number, __str, sizeof(__str), &__mods); \ + } \ + else { \ + int __number = 0; \ + __number = va_arg(ap, int); \ + __real_strlen = int2str(__number, __str, sizeof(__str), &__mods); \ + } \ + __mods.digit = true; \ + write_string_to_buffer( \ + __buf, __size, __buf_pos, __str, __real_strlen, &__mods); \ +}) + + /* parsing specifier */ + mods.base = 10; + mods.cap = mods.sign = false; + switch ( *fmt_ptr ) { + case 'c': + { + char str[1]; + + str[0] = (char)va_arg(ap, int); + mods.digit = false; + buf_pos = write_string_to_buffer( + buf, size, buf_pos, str, sk_strlen(str), &mods); + break; + } + case 's': + { + char *str; + + str = va_arg(ap, char *); + mods.digit = false; + buf_pos = write_string_to_buffer( + buf, size, buf_pos, str, sk_strlen(str), &mods); + break; + } + case 'o': + mods.base = 8; + buf_pos = write_number_to_buffer(buf, size, buf_pos, mods); + break; + + case 'X': + mods.cap = true; + mods.base = 16; + buf_pos = write_number_to_buffer(buf, size, buf_pos, mods); + break; + + case 'p': + mods.flag |= PREFIX; /* print prefix 0x for %p */ + mods.flag_long = LONG; + /* FALLTHROUGH */ + case 'x': + mods.base = 16; + buf_pos = write_number_to_buffer(buf, size, buf_pos, mods); + break; + + case 'i': + case 'd': + mods.sign = true; + buf_pos = write_number_to_buffer(buf, size, buf_pos, mods); + break; + + case 'u': + buf_pos = write_number_to_buffer(buf, size, buf_pos, mods); + break; + case 'e': + case 'E': + /* ignore */ + break; + case '%': + buf_pos = write_char_to_buffer(buf, size, buf_pos, '%'); + break; + default: + success = false; + break; + } /* switch for specifier */ + + fmt_ptr++; /* skip the above character */ + if ( success ) + fmt = fmt_ptr; + else + /* parsing % substring error, treat it as a normal string */ + /* *fmt = '%' */ + buf_pos = write_char_to_buffer(buf, size, buf_pos, *fmt++); + } /* while */ + + buf[buf_pos - 1] = '\0'; /* if the buffer is overflowed. */ + return buf_pos - 1; +} + +int sk_snprintf(char *buf, size_t size, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + int count = sk_vscnprintf(buf, size, fmt, ap); + va_end(ap); + return count; +} + +/* + * index() is also present as the strchr() in the kernel; it does exactly the + * same thing as it's userland equivalent. + */ +char *sk_index(p, ch) + const char *p; + int ch; +{ + union { + const char *cp; + char *p; + } u; + + if (p == NULL) + return(NULL); + u.cp = p; + for (;; ++u.p) { + if (*u.p == ch) + return(u.p); + if (*u.p == '\0') + return(NULL); + } + /* NOTREACHED */ +} + +/* + * Compare memory regions. + */ +int sk_memcmp(const void *s1, const void *s2, size_t n) +{ + if (s1 == NULL || s2 == NULL) + return (-1); + + if (s1 == s2) + return (0); + + if (n != 0) { + const unsigned char *p1 = s1, *p2 = s2; + + do { + if (*p1++ != *p2++) + return (*--p1 - *--p2); + } while (--n != 0); + } + return (0); +} + +/* + * sizeof(word) MUST BE A POWER OF TWO + * SO THAT wmask BELOW IS ALL ONES + */ +typedef int word; /* "word" used for optimal copy speed */ + +#define wsize sizeof(word) +#define wmask (wsize - 1) + +/* + * Copy a block of memory, handling overlap. + * This is the routine that actually implements + * (the portable versions of) bcopy, memcpy, and memmove. + */ +void *sk_memcpy(void *dst0, const void *src0, size_t length) +{ + char *dst; + const char *src; + size_t t; + + dst = dst0; + src = src0; + + if (dst0 == NULL || src0 == NULL) + return NULL; + if (length == 0 || dst == src) { /* nothing to do */ + goto done; + } + + /* + * Macros: loop-t-times; and loop-t-times, t>0 + */ +#define TLOOP(s) if (t) TLOOP1(s) +#define TLOOP1(s) do { s; } while (--t) + + if ((unsigned long)dst < (unsigned long)src) { + /* + * Copy forward. + */ + t = (int)src; /* only need low bits */ + + if ((t | (int)dst) & wmask) { + /* + * Try to align operands. This cannot be done + * unless the low bits match. + */ + if ((t ^ (int)dst) & wmask || length < wsize) { + t = length; + } else { + t = wsize - (t & wmask); + } + + length -= t; + TLOOP1(*dst++ = *src++); + } + /* + * Copy whole words, then mop up any trailing bytes. + */ + t = length / wsize; + TLOOP(*(word *)dst = *(const word *)src; src += wsize; + dst += wsize); + t = length & wmask; + TLOOP(*dst++ = *src++); + } else { + /* + * Copy backwards. Otherwise essentially the same. + * Alignment works as before, except that it takes + * (t&wmask) bytes to align, not wsize-(t&wmask). + */ + src += length; + dst += length; + t = (int)src; + + if ((t | (int)dst) & wmask) { + if ((t ^ (int)dst) & wmask || length <= wsize) { + t = length; + } else { + t &= wmask; + } + + length -= t; + TLOOP1(*--dst = *--src); + } + t = length / wsize; + TLOOP(src -= wsize; dst -= wsize; + *(word *)dst = *(const word *)src); + t = length & wmask; + TLOOP(*--dst = *--src); + } +done: + return (dst0); +} + +/* + * Compare strings. + */ +int sk_strcmp(s1, s2) + register const char *s1, *s2; +{ + if (s1 == NULL || s2 == NULL) + return(-1); + if (s1 == s2) + return(0); + while (*s1 == *s2++) + if (*s1++ == 0) + return (0); + return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1)); +} + +size_t sk_strlen(str) + const char *str; +{ + register const char *s; + + if (str == NULL) + return 0; + for (s = str; *s; ++s); + return(s - str); +} + +int sk_strncmp(s1, s2, n) + register const char *s1, *s2; + register size_t n; +{ + if (s1 == NULL || s2 == NULL) + return(-1); + if (n == 0 || s1 == s2) + return (0); + do { + if (*s1 != *s2++) + return (*(const unsigned char *)s1 - + *(const unsigned char *)(s2 - 1)); + if (*s1++ == 0) + break; + } while (--n != 0); + return (0); +} + +/* + * Copy src to dst, truncating or null-padding to always copy n bytes. + * Return dst. + */ +char *sk_strncpy(char * __restrict dst, const char * __restrict src, size_t n) +{ + if (dst == NULL || src == NULL) + return NULL; + if (n != 0) { + register char *d = dst; + register const char *s = src; + + do { + if ((*d++ = *s++) == 0) { + /* NUL pad the remaining n-1 bytes */ + while (--n != 0) + *d++ = 0; + break; + } + } while (--n != 0); + } + return (dst); +} + +#define ULONG_MAX 0xFFFFFFFFUL + +/* + * Convert a string to an unsigned long integer. + * + * Ignores `locale' stuff. Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long sk_strtoul(const char *nptr, char **endptr, int base) +{ + const char *s = nptr; + unsigned long acc; + unsigned char c; + unsigned long cutoff; + int neg = 0, any, cutlim; + + if (nptr == NULL) + return ULONG_MAX; + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != 0) + *((const char **)endptr) = any ? s - 1 : nptr; + return (acc); +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/common/tpm.c b/trenchboot/skboot/common/tpm.c new file mode 100644 index 0000000..1681d57 --- /dev/null +++ b/trenchboot/skboot/common/tpm.c @@ -0,0 +1,865 @@ +/* + * tpm.c: TPM-related support functions + * + * Copyright (c) 2006-2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +__data uint8_t g_tpm_ver = TPM_VER_UNKNOWN; +__data struct tpm_if g_tpm = { + .cur_loc = 0, + .timeout.timeout_a = TIMEOUT_A, + .timeout.timeout_b = TIMEOUT_B, + .timeout.timeout_c = TIMEOUT_C, + .timeout.timeout_d = TIMEOUT_D, +}; + +u16 skboot_alg_list[] = {HASH_ALG_SHA1, HASH_ALG_SHA256}; + +/* Global variables for TPM status register */ +static tpm20_reg_sts_t g_reg_sts, *g_reg_sts_20 = &g_reg_sts; +static tpm12_reg_sts_t *g_reg_sts_12 = (tpm12_reg_sts_t *)&g_reg_sts; + +uint8_t g_tpm_family = 0; + +/* TPM_DATA_FIFO_x */ +#define TPM_REG_DATA_FIFO 0x24 +typedef union { + uint8_t _raw[1]; /* 1-byte reg */ +} tpm_reg_data_fifo_t; + +typedef union { + uint8_t _raw[1]; +} tpm_reg_data_crb_t; + +#define TPM_ACTIVE_LOCALITY_TIME_OUT \ + (TIMEOUT_UNIT *get_tpm()->timeout.timeout_a) /* according to spec */ +#define TPM_CMD_READY_TIME_OUT \ + (TIMEOUT_UNIT *get_tpm()->timeout.timeout_b) /* according to spec */ +#define TPM_CMD_WRITE_TIME_OUT \ + (TIMEOUT_UNIT *get_tpm()->timeout.timeout_d) /* let it long enough */ +#define TPM_DATA_AVAIL_TIME_OUT \ + (TIMEOUT_UNIT *get_tpm()->timeout.timeout_c) /* let it long enough */ +#define TPM_RSP_READ_TIME_OUT \ + (TIMEOUT_UNIT *get_tpm()->timeout.timeout_d) /* let it long enough */ +#define TPM_VALIDATE_LOCALITY_TIME_OUT 0x100 + +#define read_tpm_sts_reg(locality) { \ +if ( g_tpm_family == 0 ) \ + read_tpm_reg(locality, TPM_REG_STS, g_reg_sts_12); \ +else \ + read_tpm_reg(locality, TPM_REG_STS, g_reg_sts_20); \ +} + +#define write_tpm_sts_reg(locality) { \ +if ( g_tpm_family == 0 ) \ + write_tpm_reg(locality, TPM_REG_STS, g_reg_sts_12); \ +else \ + write_tpm_reg(locality, TPM_REG_STS, g_reg_sts_20); \ +} + +static void tpm_send_cmd_ready_status(uint32_t locality) +{ + /* write 1 to TPM_STS_x.commandReady to let TPM enter ready state */ + sk_memset((void *)&g_reg_sts, 0, sizeof(g_reg_sts)); + g_reg_sts.command_ready = 1; + write_tpm_sts_reg(locality); +} + +static bool tpm_send_cmd_ready_status_crb(uint32_t locality) +{ + tpm_reg_ctrl_request_t reg_ctrl_request; + tpm_reg_ctrl_sts_t reg_ctrl_sts; + uint32_t i = 0; + + read_tpm_reg(locality, TPM_CRB_CTRL_STS, ®_ctrl_sts); + +#ifdef TPM_TRACE + printk(SKBOOT_INFO"1. reg_ctrl_sts.tpmidle: 0x%x\n", reg_ctrl_sts.tpmidle); + printk(SKBOOT_INFO"1. reg_ctrl_sts.tpmsts: 0x%x\n", reg_ctrl_sts.tpmsts); +#endif + + if ( reg_ctrl_sts.tpmidle == 1) { + sk_memset(®_ctrl_request,0,sizeof(reg_ctrl_request)); + reg_ctrl_request.cmdReady = 1; + write_tpm_reg(locality, TPM_CRB_CTRL_REQ, ®_ctrl_request); + + return true; + } + + sk_memset(®_ctrl_request,0,sizeof(reg_ctrl_request)); + reg_ctrl_request.goIdle = 1; + write_tpm_reg(locality, TPM_CRB_CTRL_REQ, ®_ctrl_request); + + do { + read_tpm_reg(locality, TPM_CRB_CTRL_REQ, ®_ctrl_request); + if ( reg_ctrl_request.goIdle == 0) + break; + else { + cpu_relax(); + read_tpm_reg(locality, TPM_CRB_CTRL_REQ, ®_ctrl_request); +#ifdef TPM_TRACE + printk(SKBOOT_INFO"1. reg_ctrl_request.goIdle: 0x%x\n", reg_ctrl_request.goIdle); + printk(SKBOOT_INFO"1. reg_ctrl_request.cmdReady: 0x%x\n", reg_ctrl_request.cmdReady); +#endif + } + i++; + } while ( i <= TPM_DATA_AVAIL_TIME_OUT); + + if ( i > TPM_DATA_AVAIL_TIME_OUT ) { + printk(SKBOOT_ERR"TPM: reg_ctrl_request.goidle timeout!\n"); + return false; + } + + read_tpm_reg(locality, TPM_CRB_CTRL_STS, ®_ctrl_sts); + +#ifdef TPM_TRACE + printk(SKBOOT_INFO"2. reg_ctrl_sts.tpmidle: 0x%x\n", reg_ctrl_sts.tpmidle); + printk(SKBOOT_INFO"2. reg_ctrl_sts.tpmsts: 0x%x\n", reg_ctrl_sts.tpmsts); +#endif + + sk_memset(®_ctrl_request,0,sizeof(reg_ctrl_request)); + reg_ctrl_request.cmdReady = 1; + write_tpm_reg(locality, TPM_CRB_CTRL_REQ, ®_ctrl_request); + +#ifdef TPM_TRACE + printk(SKBOOT_INFO"2. reg_ctrl_request.goIdle: 0x%x\n", reg_ctrl_request.goIdle); + printk(SKBOOT_INFO"2. reg_ctrl_request.cmdReady: 0x%x\n", reg_ctrl_request.cmdReady); +#endif + + read_tpm_reg(locality, TPM_CRB_CTRL_STS, ®_ctrl_sts); + +#ifdef TPM_TRACE + printk(SKBOOT_INFO"2. reg_ctrl_sts.tpmidle: 0x%x\n", reg_ctrl_sts.tpmidle); + printk(SKBOOT_INFO"2. reg_ctrl_sts.tpmsts: 0x%x\n", reg_ctrl_sts.tpmsts); +#endif + + return true; +} + +static bool tpm_check_cmd_ready_status_crb(uint32_t locality) +{ + tpm_reg_ctrl_request_t reg_ctrl_request; + read_tpm_reg(locality, TPM_CRB_CTRL_REQ, ®_ctrl_request); + +#ifdef TPM_TRACE + printk(SKBOOT_INFO"3. reg_ctrl_request.goIdle: 0x%x\n", reg_ctrl_request.goIdle); + printk(SKBOOT_INFO"3. reg_ctrl_request.cmdReady: 0x%x\n", reg_ctrl_request.cmdReady); +#endif + + if ( reg_ctrl_request.cmdReady == 0 ) + return true; + else + return false; +} + +static bool tpm_check_cmd_ready_status(uint32_t locality) +{ + read_tpm_sts_reg(locality); +#ifdef TPM_TRACE + printk(SKBOOT_INFO"."); +#endif + return g_reg_sts.command_ready; +} + +static void tpm_print_status_register(void) +{ + if ( g_tpm_family == 0 ) + { + printk(SKBOOT_DETA"TPM: status reg content: %02x %02x %02x\n", + (uint32_t)g_reg_sts_12->_raw[0], + (uint32_t)g_reg_sts_12->_raw[1], + (uint32_t)g_reg_sts_12->_raw[2]); + } + else + { + printk(SKBOOT_DETA"TPM: status reg content: %02x %02x %02x %02x\n", + (uint32_t)g_reg_sts_20->_raw[0], + (uint32_t)g_reg_sts_20->_raw[1], + (uint32_t)g_reg_sts_20->_raw[2], + (uint32_t)g_reg_sts_20->_raw[3]); + } +} + +static u16 tpm_get_burst_count(uint32_t locality) +{ + read_tpm_sts_reg(locality); + return g_reg_sts.burst_count; +} + +static bool tpm_check_expect_status(uint32_t locality) +{ + read_tpm_sts_reg(locality); +#ifdef TPM_TRACE + printk(SKBOOT_INFO"Wait on Expect = 0, Status register %02x\n", g_reg_sts._raw[0]); +#endif + return g_reg_sts.sts_valid == 1 && g_reg_sts.expect == 0; +} + +static bool tpm_check_da_status(uint32_t locality) +{ + read_tpm_sts_reg(locality); +#ifdef TPM_TRACE + printk(SKBOOT_INFO"Waiting for DA Flag, Status register %02x\n", g_reg_sts._raw[0]); +#endif + return g_reg_sts.sts_valid == 1 && g_reg_sts.data_avail == 1; +} + +static void tpm_execute_cmd(uint32_t locality) +{ + sk_memset((void *)&g_reg_sts, 0, sizeof(g_reg_sts)); + g_reg_sts.tpm_go = 1; + write_tpm_sts_reg(locality); +} + +bool tpm_validate_locality(uint32_t locality) +{ + uint32_t i; + tpm_reg_access_t reg_acc; + + for ( i = TPM_VALIDATE_LOCALITY_TIME_OUT; i > 0; 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(); + } + if ( i <= 0 ) + printk(SKBOOT_ERR"TPM: tpm_validate_locality timeout\n"); + + return false; +} + +bool tpm_validate_locality_crb(uint32_t locality) +{ + uint32_t i; + tpm_reg_loc_state_t reg_loc_state; + + for ( i = TPM_VALIDATE_LOCALITY_TIME_OUT; i > 0; i-- ) { + /* + * Platfrom Tpm Profile for TPM 2.0 SPEC + */ + read_tpm_reg(locality, TPM_REG_LOC_STATE, ®_loc_state); + if ( reg_loc_state.tpm_reg_valid_sts == 1 && reg_loc_state.loc_assigned == 1 && reg_loc_state.active_locality == locality) { + printk(SKBOOT_INFO"TPM: reg_loc_state._raw[0]: 0x%x\n", reg_loc_state._raw[0]); + return true; + } + cpu_relax(); + } + + printk(SKBOOT_ERR"TPM: tpm_validate_locality_crb timeout\n"); + printk(SKBOOT_INFO"TPM: reg_loc_state._raw[0]: 0x%x\n", reg_loc_state._raw[0]); + return false; +} + +bool tpm_wait_cmd_ready(uint32_t locality) +{ + uint32_t i; + tpm_reg_access_t reg_acc; + +#if 0 /* some tpms doesn't always return 1 for reg_acc.tpm_reg_valid_sts */ + /* and this bit was checked in tpm_validate_locality() already, */ + /* so safe to skip the check here */ + /* ensure the contents of the ACCESS register are valid */ + read_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); +#ifdef TPM_TRACE + printk(SKBOOT_INFO"TPM: Access reg content: 0x%02x\n", (uint32_t)reg_acc._raw[0]); +#endif + if ( reg_acc.tpm_reg_valid_sts == 0 ) { + printk(SKBOOT_ERR"TPM: Access reg not valid\n"); + return false; + } +#endif + /* 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); + + i = 0; + do { + read_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); + if ( reg_acc.active_locality == 1 ) + break; + else + cpu_relax(); + i++; + } while ( i <= TPM_ACTIVE_LOCALITY_TIME_OUT); + + if ( i > TPM_ACTIVE_LOCALITY_TIME_OUT ) { + printk(SKBOOT_ERR"TPM: FIFO_INF access reg request use timeout\n"); + return false; + } + + /* ensure the TPM is ready to accept a command */ +#ifdef TPM_TRACE + printk(SKBOOT_INFO"TPM: wait for cmd ready \n"); +#endif + i = 0; + do { + tpm_send_cmd_ready_status(locality); + cpu_relax(); + /* then see if it has */ + + if ( tpm_check_cmd_ready_status(locality) ) + break; + else + cpu_relax(); + i++; + } while ( i <= TPM_CMD_READY_TIME_OUT ); +#ifdef TPM_TRACE + printk(SKBOOT_INFO"\n"); +#endif + + if ( i > TPM_CMD_READY_TIME_OUT ) { + tpm_print_status_register(); + printk(SKBOOT_INFO"TPM: tpm timeout for command_ready\n"); + goto RelinquishControl; + } + + return true; + +RelinquishControl: + /* deactivate current locality */ + reg_acc._raw[0] = 0; + reg_acc.active_locality = 1; + write_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); + + return false; +} + +static bool tpm_wait_cmd_ready_crb(uint32_t locality) +{ + uint32_t i; + + /* ensure the TPM is ready to accept a command */ +#ifdef TPM_TRACE + printk(SKBOOT_INFO"TPM: wait for cmd ready \n"); +#endif + tpm_send_cmd_ready_status_crb(locality); + i = 0; + do { + if ( tpm_check_cmd_ready_status_crb(locality) ) + break; + else + cpu_relax(); + i++; + } while ( i <= TPM_CMD_READY_TIME_OUT ); + + if ( i > TPM_CMD_READY_TIME_OUT ) { + //tpm_print_status_register(); + printk(SKBOOT_INFO"TPM: tpm timeout for command_ready\n"); + goto RelinquishControl; + } + + return true; + +RelinquishControl: + /* deactivate current locality */ + //tpm_reg_loc_ctrl_t reg_loc_ctrl; + //reg_loc_ctrl._raw[0] = 0; + //reg_loc_ctrl.relinquish = 1; + //write_tpm_reg(locality, TPM_REG_LOC_CTRL, ®_loc_ctrl); + + return false; +} + +bool tpm_submit_cmd(u32 locality, u8 *in, u32 in_size, u8 *out, u32 *out_size) +{ + u32 i, rsp_size, offset; + u16 row_size; + tpm_reg_access_t reg_acc; + bool ret = true; + + if ( locality >= TPM_NR_LOCALITIES ) { + printk(SKBOOT_WARN"TPM: Invalid locality for tpm_write_cmd_fifo()\n"); + return false; + } + if ( in == NULL || out == NULL || out_size == NULL ) { + printk(SKBOOT_WARN"TPM: Invalid parameter for tpm_write_cmd_fifo()\n"); + return false; + } + if ( in_size < CMD_HEAD_SIZE || *out_size < RSP_HEAD_SIZE ) { + printk(SKBOOT_WARN"TPM: in/out buf size must be larger than 10 bytes\n"); + return false; + } + + if ( !tpm_validate_locality(locality) ) { + printk(SKBOOT_WARN"TPM: Locality %d is not open\n", locality); + return false; + } + + if ( !tpm_wait_cmd_ready(locality) ) return false; + +#ifdef TPM_TRACE + { + printk(SKBOOT_DETA"TPM: cmd size = 0x%x\nTPM: cmd content: ", in_size); + print_hex("TPM: \t", in, in_size); + } +#endif + + /* write the command to the TPM FIFO */ + offset = 0; + do { + i = 0; + do { + /* find out how many bytes the TPM can accept in a row */ + row_size = tpm_get_burst_count(locality); + if ( row_size > 0 ) break; + else cpu_relax(); + i++; + } while ( i <= TPM_CMD_WRITE_TIME_OUT ); + if ( i > TPM_CMD_WRITE_TIME_OUT ) { + printk(SKBOOT_ERR"TPM: write cmd timeout\n"); + ret = false; + 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 ); + + i = 0; + do { + if ( tpm_check_expect_status(locality) ) break; + else cpu_relax(); + i++; + } while ( i <= TPM_DATA_AVAIL_TIME_OUT ); + if ( i > TPM_DATA_AVAIL_TIME_OUT ) { + printk(SKBOOT_ERR"TPM: wait for expect becoming 0 timeout\n"); + ret = false; + goto RelinquishControl; + } + + /* command has been written to the TPM, it is time to execute it. */ + tpm_execute_cmd(locality); + + /* check for data available */ + i = 0; + do { + if ( tpm_check_da_status(locality) ) break; + else cpu_relax(); + i++; + } while ( i <= TPM_DATA_AVAIL_TIME_OUT ); + if ( i > TPM_DATA_AVAIL_TIME_OUT ) { + printk(SKBOOT_ERR"TPM: wait for data available timeout\n"); + ret = false; + goto RelinquishControl; + } + + rsp_size = 0; + offset = 0; + do { + /* find out how many bytes the TPM returned in a row */ + i = 0; + do { + row_size = tpm_get_burst_count(locality); + if ( row_size > 0 ) break; + else cpu_relax(); + i++; + } while ( i <= TPM_RSP_READ_TIME_OUT ); + if ( i > TPM_RSP_READ_TIME_OUT ) { + printk(SKBOOT_ERR"TPM: read rsp timeout\n"); + ret = false; + 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 - 1 ) { + 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; + +#ifdef TPM_TRACE + { + printk(SKBOOT_INFO"TPM: response size = %d\n", *out_size); + printk(SKBOOT_DETA"TPM: response content: "); + print_hex("TPM: \t", out, *out_size); + } +#endif + + tpm_send_cmd_ready_status(locality); + +RelinquishControl: + /* deactivate current locality */ + reg_acc._raw[0] = 0; + reg_acc.active_locality = 1; + write_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); + + return ret; +} + + +bool tpm_submit_cmd_crb(u32 locality, u8 *in, u32 in_size, u8 *out, u32 *out_size) +{ + uint32_t i; + bool ret = true; + //tpm_reg_loc_ctrl_t reg_loc_ctrl; + tpm_reg_ctrl_start_t start; + tpm_reg_ctrl_cmdsize_t CmdSize; + tpm_reg_ctrl_cmdaddr_t CmdAddr; + tpm_reg_ctrl_rspsize_t RspSize; + tpm_reg_ctrl_rspaddr_t RspAddr; + uint32_t tpm_crb_data_buffer_base; + + if ( locality >= TPM_NR_LOCALITIES ) { + printk(SKBOOT_WARN"TPM: Invalid locality for tpm_submit_cmd_crb()\n"); + return false; + } + if ( in == NULL || out == NULL || out_size == NULL ) { + printk(SKBOOT_WARN"TPM: Invalid parameter for tpm_submit_cmd_crb()\n"); + return false; + } + if ( in_size < CMD_HEAD_SIZE || *out_size < RSP_HEAD_SIZE ) { + printk(SKBOOT_WARN"TPM: in/out buf size must be larger than 10 bytes\n"); + return false; + } + + if ( !tpm_validate_locality_crb(locality) ) { + printk(SKBOOT_WARN"TPM: CRB Interface Locality %d is not open\n", locality); + return false; + } + + if ( !tpm_wait_cmd_ready_crb(locality) ) { + printk(SKBOOT_WARN"TPM: tpm_wait_cmd_read_crb failed\n"); + return false; + } + +#ifdef TPM_TRACE + { + printk(SKBOOT_DETA"TPM: Before submit, cmd size = 0x%x\nTPM: Before submit, cmd content: ", in_size); + print_hex("TPM: \t", in, in_size); + } +#endif + + /* write the command to the TPM CRB buffer 01-04-2016 */ +//copy *in and size to crb buffer + + CmdAddr.cmdladdr = TPM_LOCALITY_CRB_BASE_N(locality) | TPM_CRB_DATA_BUFFER; + CmdAddr.cmdhaddr = 0; + RspAddr.rspaddr = TPM_LOCALITY_CRB_BASE_N(locality) | TPM_CRB_DATA_BUFFER; + CmdSize.cmdsize = TPMCRBBUF_LEN; + RspSize.rspsize = TPMCRBBUF_LEN; + tpm_crb_data_buffer_base = TPM_CRB_DATA_BUFFER; + +#ifdef TPM_TRACE + printk(SKBOOT_INFO"CmdAddr.cmdladdr is 0x%x\n",CmdAddr.cmdladdr); + printk(SKBOOT_INFO"CmdAddr.cmdhaddr is 0x%x\n",CmdAddr.cmdhaddr); + + printk(SKBOOT_INFO"CmdSize.cmdsize is 0x%x\n",CmdSize.cmdsize); + printk(SKBOOT_INFO"RspAddr.rspaddr is 0x%Lx\n",RspAddr.rspaddr); + printk(SKBOOT_INFO"RspSize.rspsize is 0x%x\n",RspSize.rspsize); +#endif + + write_tpm_reg(locality, TPM_CRB_CTRL_CMD_ADDR, &CmdAddr); + write_tpm_reg(locality, TPM_CRB_CTRL_CMD_SIZE, &CmdSize); + write_tpm_reg(locality, TPM_CRB_CTRL_RSP_ADDR, &RspAddr); + write_tpm_reg(locality, TPM_CRB_CTRL_RSP_SIZE, &RspSize); + // write the command to the buffer + for ( i = 0 ; i< in_size; i++ ) { + write_tpm_reg(locality, tpm_crb_data_buffer_base++, (tpm_reg_data_crb_t *)&in[i]); + //tpm_crb_data_buffer_base++; + } + + /* command has been written to the TPM, it is time to execute it. */ + start.start = 1; + write_tpm_reg(locality, TPM_CRB_CTRL_START, &start); + //read_tpm_reg(locality, TPM_CRB_CTRL_START, &start); + printk(SKBOOT_INFO"tpm_ctrl_start.start is 0x%x\n",start.start); + + /* check for data available */ + i = 0; + do { + read_tpm_reg(locality, TPM_CRB_CTRL_START, &start); + //printk(SKBOOT_INFO"tpm_ctrl_start.start is 0x%x\n",start.start); + if ( start.start == 0 ) break; + else cpu_relax(); + i++; + } while ( i <= TPM_DATA_AVAIL_TIME_OUT ); + + if ( i > TPM_DATA_AVAIL_TIME_OUT ) { + printk(SKBOOT_ERR"TPM: wait for data available timeout\n"); + ret = false; + goto RelinquishControl; + } + + tpm_crb_data_buffer_base = TPM_CRB_DATA_BUFFER; + + for ( i = 0 ; i< *out_size; i++ ) { + read_tpm_reg(locality, tpm_crb_data_buffer_base++, (tpm_reg_data_crb_t *)&out[i]); + //tpm_crb_data_buffer_base++; + } + +#ifdef TPM_TRACE + { + printk(SKBOOT_INFO"TPM: After cmd submit, response size = 0x%x\n", *out_size); + printk(SKBOOT_DETA"TPM: After cmd submit, response content: "); + print_hex("TPM: \t", out, *out_size); + } +#endif + + //tpm_send_cmd_ready_status_crb(locality); + +RelinquishControl: + /* deactivate current locality */ + // reg_loc_ctrl._raw[0] = 0; + //reg_loc_ctrl.relinquish = 1; + //write_tpm_reg(locality, TPM_REG_LOC_CTRL, ®_loc_ctrl); + + return ret; +} + +bool release_locality(uint32_t locality) +{ + uint32_t i; +#ifdef TPM_TRACE + printk(SKBOOT_DETA"TPM: releasing locality %u\n", locality); +#endif + + if ( !tpm_validate_locality(locality) ) return true; + + tpm_reg_access_t reg_acc; + read_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); + if ( reg_acc.active_locality == 0 ) return true; + + /* make inactive by writing a 1 */ + reg_acc._raw[0] = 0; + reg_acc.active_locality = 1; + write_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); + + i = 0; + do { + read_tpm_reg(locality, TPM_REG_ACCESS, ®_acc); + if ( reg_acc.active_locality == 0 ) + return true; + else + cpu_relax(); + i++; + } while ( i <= TPM_ACTIVE_LOCALITY_TIME_OUT ); + + printk(SKBOOT_INFO"TPM: access reg release locality timeout\n"); + return false; +} + +bool tpm_relinquish_locality_crb(uint32_t locality) +{ + uint32_t i; + tpm_reg_loc_state_t reg_loc_state; + tpm_reg_loc_ctrl_t reg_loc_ctrl; + +#ifdef TPM_TRACE + printk(SKBOOT_DETA"TPM: releasing CRB_INF locality %u\n", locality); +#endif + + if ( !tpm_validate_locality_crb(locality) ) return true; + read_tpm_reg(locality, TPM_REG_LOC_STATE, ®_loc_state); + if ( reg_loc_state.loc_assigned == 0 ) return true; + + /* make inactive by writing a 1 */ + sk_memset(®_loc_ctrl,0,sizeof(reg_loc_ctrl)); + reg_loc_ctrl.relinquish = 1; + write_tpm_reg(locality, TPM_REG_LOC_CTRL, ®_loc_ctrl); + + i = 0; + do { + read_tpm_reg(locality, TPM_REG_LOC_STATE, ®_loc_state); + if ( reg_loc_state.loc_assigned == 0 ) return true; + else cpu_relax(); + i++; + } while ( i <= TPM_ACTIVE_LOCALITY_TIME_OUT ); + + printk(SKBOOT_INFO"TPM: CRB_INF release locality timeout\n"); + return false; +} + +bool is_tpm_crb(void) +{ + tpm_crb_interface_id_t crb_interface; + read_tpm_reg(0, TPM_INTERFACE_ID, &crb_interface); + if (crb_interface.interface_type == TPM_INTERFACE_ID_CRB ) { + printk(SKBOOT_INFO"TPM: PTP CRB interface is active...\n"); + if (g_tpm_family != TPM_IF_20_CRB ) g_tpm_family = TPM_IF_20_CRB; + return true; + } + if (crb_interface.interface_type == TPM_INTERFACE_ID_FIFO_20) { + printk(SKBOOT_INFO"TPM: TPM 2.0 FIFO interface is active...\n"); + if (g_tpm_family != TPM_IF_20_FIFO) g_tpm_family = TPM_IF_20_FIFO; + } + + return false; +} + +bool prepare_tpm(void) +{ + /* + * must ensure TPM_ACCESS_0.activeLocality bit is clear + * (: locality is not active) + */ + if (is_tpm_crb()) + return tpm_relinquish_locality_crb(0); + else + return release_locality(0); +} + +bool tpm_request_locality_crb(uint32_t locality) +{ + uint32_t i; + tpm_reg_loc_state_t reg_loc_state; + tpm_reg_loc_ctrl_t reg_loc_ctrl; + /* request access to the TPM from locality N */ + sk_memset(®_loc_ctrl,0,sizeof(reg_loc_ctrl)); + reg_loc_ctrl.requestAccess = 1; + write_tpm_reg(locality, TPM_REG_LOC_CTRL, ®_loc_ctrl); + + i = 0; + do { + read_tpm_reg(locality, TPM_REG_LOC_STATE, ®_loc_state); + if ( reg_loc_state.active_locality == locality && reg_loc_state.loc_assigned == 1) + break; + else + cpu_relax(); + i++; + } while ( i <= TPM_ACTIVE_LOCALITY_TIME_OUT); + + if ( i > TPM_ACTIVE_LOCALITY_TIME_OUT ) { + printk(SKBOOT_ERR"TPM: access loc request use timeout\n"); + return false; + } + + return true; +} + +bool tpm_detect(void) +{ + struct tpm_if *tpm = get_tpm(); /* Don't leave tpm as NULL */ + const struct tpm_if_fp *tpm_fp; + + if (is_tpm_crb()) { + printk(SKBOOT_INFO"TPM: This is TPM20, TPM Family 0x%d\n", g_tpm_family); + + if ( tpm_validate_locality_crb(0) ) + printk(SKBOOT_INFO"TPM: CRB_INF Locality 0 is open\n"); + else { + printk(SKBOOT_INFO"TPM: CRB_INF request access to Locality 0...\n"); + if (!tpm_request_locality_crb(0)) { + printk(SKBOOT_ERR"TPM: CRB_INF Locality 0 request failed...\n"); + return false; + } + } + } + else { + g_tpm_ver = TPM_VER_12; + tpm_fp = get_tpm_fp(); /* Don't leave tpm_fp as NULL */ + + if ( tpm_validate_locality(0) ) printk(SKBOOT_INFO"TPM: FIFO_INF Locality 0 is open\n"); + else { + printk(SKBOOT_ERR"TPM: FIFO_INF Locality 0 is not open\n"); + return false; + } + /* determine TPM family from command check */ + if ( tpm_fp->check() ) { + g_tpm_family = TPM_IF_12; + printk(SKBOOT_INFO"TPM: discrete TPM1.2 Family 0x%d\n", g_tpm_family); + } + else { + g_tpm_family = TPM_IF_20_FIFO; + printk(SKBOOT_INFO"TPM: discrete TPM2.0 Family 0x%d\n", g_tpm_family); + } + } + + if (g_tpm_family == TPM_IF_12) g_tpm_ver = TPM_VER_12; + if (g_tpm_family == TPM_IF_20_FIFO) g_tpm_ver = TPM_VER_20; + if (g_tpm_family == TPM_IF_20_CRB) g_tpm_ver = TPM_VER_20; + + tpm_fp = get_tpm_fp(); + return tpm_fp->init(tpm); +} + +void tpm_print(struct tpm_if *ti) +{ + if ( ti == NULL ) + return; + + printk(SKBOOT_INFO"TPM attribute:\n"); + printk(SKBOOT_INFO"\t extend policy: %d\n", ti->extpol); + printk(SKBOOT_INFO"\t current alg id: 0x%x\n", ti->cur_alg); + printk(SKBOOT_INFO"\t timeout values: A: %u, B: %u, C: %u, D: %u\n", + ti->timeout.timeout_a, ti->timeout.timeout_b, ti->timeout.timeout_c, ti->timeout.timeout_d); +} + +struct tpm_if *get_tpm(void) +{ + return &g_tpm; +} + +const struct tpm_if_fp *get_tpm_fp(void) +{ + if ( g_tpm_ver == TPM_VER_12 ) + return &tpm_12_if_fp; + else if ( g_tpm_ver == TPM_VER_20) + return &tpm_20_if_fp; + + return NULL; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/common/tpm_12.c b/trenchboot/skboot/common/tpm_12.c new file mode 100644 index 0000000..ddcfeae --- /dev/null +++ b/trenchboot/skboot/common/tpm_12.c @@ -0,0 +1,562 @@ +/* + * tpm_12.c: TPM1.2-related support functions + * + * Copyright (c) 2006-2013, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * return code: + * The TPM has five types of return code. One indicates successful operation + * and four indicate failure. + * TPM_SUCCESS (00000000) indicates successful execution. + * The failure reports are: + * TPM defined fatal errors (00000001 to 000003FF) + * vendor defined fatal errors (00000400 to 000007FF) + * TPM defined non-fatal errors (00000800 to 00000BFF) + * vendor defined non-fatal errors (00000C00 to 00000FFF). + * Here only give definitions for a few commonly used return code. + */ +#define TPM_BASE 0x00000000 +#define TPM_NON_FATAL 0x00000800 +#define TPM_SUCCESS TPM_BASE +#define TPM_BADINDEX (TPM_BASE + 2) +#define TPM_BAD_PARAMETER (TPM_BASE + 3) +#define TPM_DEACTIVATED (TPM_BASE + 6) +#define TPM_DISABLED (TPM_BASE + 7) +#define TPM_FAIL (TPM_BASE + 9) +#define TPM_BAD_ORDINAL (TPM_BASE + 10) +#define TPM_NOSPACE (TPM_BASE + 17) +#define TPM_NOTRESETABLE (TPM_BASE + 50) +#define TPM_NOTLOCAL (TPM_BASE + 51) +#define TPM_BAD_LOCALITY (TPM_BASE + 61) +#define TPM_READ_ONLY (TPM_BASE + 62) +#define TPM_NOT_FULLWRITE (TPM_BASE + 70) +#define TPM_RETRY (TPM_BASE + TPM_NON_FATAL) + +typedef uint8_t tpm_locality_selection_t; +#define TPM_LOC_ZERO 0x01 +#define TPM_LOC_ONE 0x02 +#define TPM_LOC_TWO 0x04 +#define TPM_LOC_THREE 0x08 +#define TPM_LOC_FOUR 0x10 +#define TPM_LOC_RSVD 0xE0 + +/* ~5 secs are required for Infineon that requires this, so leave some extra */ +#define MAX_SAVESTATE_RETRIES 60 + +#define TPM_TAG_RQU_COMMAND 0x00C1 +#define TPM_TAG_RQU_AUTH1_COMMAND 0x00C2 +#define TPM_TAG_RQU_AUTH2_COMMAND 0x00C3 +#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 TPM_ORD_GET_CAPABILITY 0x00000065 +#define TPM_ORD_SEAL 0x00000017 +#define TPM_ORD_UNSEAL 0x00000018 +#define TPM_ORD_OSAP 0x0000000B +#define TPM_ORD_OIAP 0x0000000A +#define TPM_ORD_SAVE_STATE 0x00000098 +#define TPM_ORD_GET_RANDOM 0x00000046 + +#define TPM_TAG_PCR_INFO_LONG 0x0006 +#define TPM_TAG_STORED_DATA12 0x0016 + +/* + * specified as minimum cmd buffer size should be supported by all 1.2 TPM + * device in the TCG_PCClientTPMSpecification_1-20_1-00_FINAL.pdf + */ +#define TPM_CMD_SIZE_MAX 768 +#define TPM_RSP_SIZE_MAX 768 + +/* + * The _tpm12_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) + * tag : The TPM command tag + * 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]; + +__data tpm_pcr_value_t post_launch_pcr17, post_launch_pcr18; + +#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 _tpm12_submit_cmd(uint32_t locality, uint16_t tag, uint32_t cmd, uint32_t arg_size, uint32_t *out_size) +{ + uint32_t ret; + uint32_t cmd_size, rsp_size = 0; + + if ( out_size == NULL ) { + printk(SKBOOT_WARN"TPM: invalid param for _tpm12_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(SKBOOT_WARN"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_CC_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; + if ( !tpm_submit_cmd(locality, cmd_buf, cmd_size, rsp_buf, &rsp_size) ) return TPM_FAIL; + + /* + * 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; + + reverse_copy(&ret, rsp_buf + RSP_RST_OFFSET, sizeof(uint32_t)); + 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; +} + +static inline uint32_t tpm12_submit_cmd(uint32_t locality, uint32_t cmd, uint32_t arg_size, uint32_t *out_size) +{ + return _tpm12_submit_cmd(locality, TPM_TAG_RQU_COMMAND, cmd, arg_size, out_size); +} + +static inline uint32_t tpm12_submit_cmd_auth1(uint32_t locality, uint32_t cmd, + uint32_t arg_size, uint32_t *out_size) +{ + return _tpm12_submit_cmd(locality, TPM_TAG_RQU_AUTH1_COMMAND, cmd, + arg_size, out_size); +} + +static inline uint32_t tpm12_submit_cmd_auth2(uint32_t locality, uint32_t cmd, + uint32_t arg_size, uint32_t *out_size) +{ + return _tpm12_submit_cmd(locality, TPM_TAG_RQU_AUTH2_COMMAND, cmd, + arg_size, out_size); +} + +typedef struct __packed { + uint8_t digest[SHA1_LENGTH]; +} tpm12_digest_t; + +#define TPM_CAP_VERSION_VAL 0x1A + +typedef uint16_t tpm_structure_tag_t; + +typedef struct __packed { + uint8_t major; + uint8_t minor; + uint8_t rev_major; + uint8_t rev_minor; +} tpm_version_t; + +typedef struct __packed { + tpm_structure_tag_t tag; + tpm_version_t version; + uint16_t specLevel; + uint8_t errataRev; + uint8_t tpmVendorID[4]; + uint16_t vendorSpecificSize; + uint8_t vendorSpecific[]; +} tpm_cap_version_info_t; + +#define HMAC_BLOCK_SIZE 64 +#define HMAC_OUTPUT_SIZE 20 + +#define UNLOAD_INTEGER(buf, offset, var) {\ + reverse_copy(buf + offset, &(var), sizeof(var));\ + offset += sizeof(var);\ +} + +#define UNLOAD_BLOB(buf, offset, blob, size) {\ + sk_memcpy(buf + offset, blob, size);\ + offset += size;\ +} + +#define UNLOAD_BLOB_TYPE(buf, offset, blob) \ + UNLOAD_BLOB(buf, offset, blob, sizeof(*(blob))) + +#define LOAD_INTEGER(buf, offset, var) {\ + reverse_copy(&(var), buf + offset, sizeof(var));\ + offset += sizeof(var);\ +} + +#define LOAD_BLOB(buf, offset, blob, size) {\ + sk_memcpy(blob, buf + offset, size);\ + offset += size;\ +} + +typedef uint32_t tpm_capability_area_t; + +#define TPM_CAP_NV_INDEX 0x00000011 + +static uint32_t tpm12_get_capability(uint32_t locality, tpm_capability_area_t cap_area, + uint32_t sub_cap_size, const uint8_t *sub_cap, + uint32_t *resp_size, uint8_t *resp) +{ + uint32_t ret, offset, out_size, size; + + if ( sub_cap == NULL || resp_size == NULL || resp == NULL ) { + printk(SKBOOT_WARN"TPM: tpm12_get_capability() bad parameter\n"); + return TPM_BAD_PARAMETER; + } + + offset = 0; + UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, cap_area); + UNLOAD_INTEGER(WRAPPER_IN_BUF, offset, sub_cap_size); + UNLOAD_BLOB(WRAPPER_IN_BUF, offset, sub_cap, sub_cap_size); + + out_size = sizeof(*resp_size) + *resp_size; + + ret = tpm12_submit_cmd(locality, TPM_ORD_GET_CAPABILITY, offset, &out_size); + +#ifdef TPM_TRACE + printk(SKBOOT_DETA"TPM: get capability, return value = %08X\n", ret); +#endif + if ( ret != TPM_SUCCESS ) { + printk(SKBOOT_DETA"TPM: get capability, return value = %08X\n", ret); + return ret; + } + + offset = 0; + LOAD_INTEGER(WRAPPER_OUT_BUF, offset, size); + if ( *resp_size < size || + size != out_size - sizeof(*resp_size) ) { + printk(SKBOOT_WARN"TPM: capability response too small\n"); + return TPM_FAIL; + } + *resp_size = size; + LOAD_BLOB(WRAPPER_OUT_BUF, offset, resp, *resp_size); + + return ret; +} + +typedef struct __packed { + tpm_structure_tag_t tag; + uint8_t disable; + uint8_t ownership; + uint8_t deactivated; + uint8_t read_pubek; + uint8_t disable_owner_clear; + uint8_t allow_maintenance; + uint8_t physical_presence_lifetime_lock; + uint8_t physical_presence_hw_enable; + uint8_t physical_presence_cmd_enable; + uint8_t cekp_used; + uint8_t tpm_post; + uint8_t tpm_post_lock; + uint8_t fips; + uint8_t operator; + uint8_t enable_revoke_ek; + uint8_t nv_locked; + uint8_t read_srk_pub; + uint8_t tpm_established; + uint8_t maintenance_done; + uint8_t disable_full_da_logic_info; +} tpm_permanent_flags_t; + +typedef struct __packed { + tpm_structure_tag_t tag; + uint8_t deactivated; + uint8_t disable_force_clear; + uint8_t physical_presence; + uint8_t phycical_presence_lock; + uint8_t b_global_lock; +} tpm_stclear_flags_t; + +#define TPM_CAP_FLAG 0x00000004 +#define TPM_CAP_FLAG_PERMANENT 0x00000108 +#define TPM_CAP_FLAG_VOLATILE 0x00000109 + +static uint32_t tpm12_get_flags(uint32_t locality, uint32_t flag_id, + uint8_t *flags, uint32_t flag_size) +{ + uint32_t ret, offset, resp_size; + uint8_t sub_cap[sizeof(flag_id)]; + tpm_structure_tag_t tag; + + if ( flags == NULL ) { + printk(SKBOOT_WARN"TPM: tpm12_get_flags() bad parameter\n"); + return TPM_BAD_PARAMETER; + } + + offset = 0; + UNLOAD_INTEGER(sub_cap, offset, flag_id); + + resp_size = flag_size; + ret = tpm12_get_capability(locality, TPM_CAP_FLAG, sizeof(sub_cap), + sub_cap, &resp_size, flags); + +#ifdef TPM_TRACE + printk(SKBOOT_DETA"TPM: get flags %08X, return value = %08X\n", flag_id, ret); +#endif + if ( ret != TPM_SUCCESS ) + return ret; + + /* 1.2 spec, main part 2, rev 103 add one more byte to permanent flags, to + be backward compatible, not assume all expected bytes can be gotten */ + if ( resp_size > flag_size ) { + printk(SKBOOT_WARN"TPM: tpm12_get_flags() response size too small\n"); + return TPM_FAIL; + } + + offset = 0; + LOAD_INTEGER(flags, offset, tag); + offset = 0; + UNLOAD_BLOB_TYPE(flags, offset, &tag); + + return ret; +} + +#define TPM_CAP_PROPERTY 0x00000005 +#define TPM_CAP_PROP_TIS_TIMEOUT 0x00000115 + +static uint32_t tpm12_get_timeout(uint32_t locality, + uint8_t *prop, uint32_t prop_size) +{ + uint32_t ret, offset, resp_size, prop_id = TPM_CAP_PROP_TIS_TIMEOUT; + uint8_t sub_cap[sizeof(prop_id)]; + uint32_t resp[4]; + + if ( (prop == NULL) || (prop_size < sizeof(resp)) ) { + printk(SKBOOT_WARN"TPM: tpm12_get_timeout() bad parameter\n"); + return TPM_BAD_PARAMETER; + } + + offset = 0; + UNLOAD_INTEGER(sub_cap, offset, prop_id); + + resp_size = prop_size; + ret = tpm12_get_capability(locality, TPM_CAP_PROPERTY, sizeof(sub_cap), + sub_cap, &resp_size, prop); + +#ifdef TPM_TRACE + printk(SKBOOT_DETA"TPM: get prop %08X, return value = %08X\n", prop_id, ret); +#endif + if ( ret != TPM_SUCCESS ) + return ret; + + if ( resp_size != prop_size ) { + printk(SKBOOT_WARN"TPM: tpm_get_property() response size incorrect\n"); + return TPM_FAIL; + } + + offset = 0; + LOAD_INTEGER(prop, offset, resp); + offset = 0; + UNLOAD_BLOB_TYPE(prop, offset, &resp); + + return ret; +} + +/* ensure TPM is ready to accept commands */ +static bool tpm12_init(struct tpm_if *ti) +{ + tpm_permanent_flags_t pflags; + tpm_stclear_flags_t vflags; + uint32_t timeout[4]; + uint32_t locality; + uint32_t ret; + + if ( ti == NULL ) + return false; + + ti->cur_loc = 0; + + locality = ti->cur_loc; + if ( !tpm_validate_locality(locality) ) { + printk(SKBOOT_WARN"TPM is not available.\n"); + return false; + } + + /* make sure tpm is not disabled/deactivated */ + sk_memset(&pflags, 0, sizeof(pflags)); + ret = tpm12_get_flags(locality, TPM_CAP_FLAG_PERMANENT, + (uint8_t *)&pflags, sizeof(pflags)); + if ( ret != TPM_SUCCESS ) { + printk(SKBOOT_WARN"TPM is disabled or deactivated.\n"); + ti->error = ret; + return false; + } + if ( pflags.disable ) { + printk(SKBOOT_WARN"TPM is disabled.\n"); + return false; + } + + sk_memset(&vflags, 0, sizeof(vflags)); + ret = tpm12_get_flags(locality, TPM_CAP_FLAG_VOLATILE, + (uint8_t *)&vflags, sizeof(vflags)); + if ( ret != TPM_SUCCESS ) { + printk(SKBOOT_WARN"TPM is disabled or deactivated.\n"); + ti->error = ret; + return false; + } + if ( vflags.deactivated ) { + printk(SKBOOT_WARN"TPM is deactivated.\n"); + return false; + } + + printk(SKBOOT_INFO"TPM is ready\n"); + printk(SKBOOT_DETA"TPM nv_locked: %s\n", (pflags.nv_locked != 0) ? "TRUE" : "FALSE"); + + /* get tpm timeout values */ + ret = tpm12_get_timeout(locality, (uint8_t *)&timeout, sizeof(timeout)); + if ( ret != TPM_SUCCESS ) { + printk(SKBOOT_WARN"TPM timeout values are not achieved, " + "default values will be used.\n"); + ti->error = ret; + } else { + /* + * timeout_x represents the number of milliseconds for the timeout + * and timeout[x] represents the number of microseconds. + */ + ti->timeout.timeout_a = timeout[0]/1000; + ti->timeout.timeout_b = timeout[1]/1000; + ti->timeout.timeout_c = timeout[2]/1000; + ti->timeout.timeout_d = timeout[3]/1000; + printk(SKBOOT_DETA"TPM timeout values: A: %u, B: %u, C: %u, D: %u\n", + ti->timeout.timeout_a, ti->timeout.timeout_b, ti->timeout.timeout_c, + ti->timeout.timeout_d); + /* + * if any timeout values are less than default values, set to default + * value (due to bug with some TPMs) + */ + if ( ti->timeout.timeout_a < TIMEOUT_A ) { + ti->timeout.timeout_a = TIMEOUT_A; + printk(SKBOOT_WARN"Wrong timeout A, fallback to %u\n", TIMEOUT_A); + } + if ( ti->timeout.timeout_b < TIMEOUT_B ) { + ti->timeout.timeout_b = TIMEOUT_B; + printk(SKBOOT_WARN"Wrong timeout B, fallback to %u\n", TIMEOUT_B); + } + if ( ti->timeout.timeout_c < TIMEOUT_C ) { + ti->timeout.timeout_c = TIMEOUT_C; + printk(SKBOOT_WARN"Wrong timeout C, fallback to %u\n", TIMEOUT_C); + } + if ( ti->timeout.timeout_d < TIMEOUT_D ) { + ti->timeout.timeout_d = TIMEOUT_D; + printk(SKBOOT_WARN"Wrong timeout D, fallback to %u\n", TIMEOUT_D); + } + } + + /* init version */ + ti->major = TPM12_VER_MAJOR; + ti->minor = TPM12_VER_MINOR; + + /* init supported alg list */ + ti->banks = 1; + ti->alg_count = 1; + ti->algs[0] = HASH_ALG_SHA1; + ti->extpol = SK_EXTPOL_FIXED; + ti->cur_alg = HASH_ALG_SHA1; + + /* init NV index */ + ti->sk_policy_index = 0x20000001; + ti->lcp_own_index = 0x40000001; + ti->sk_err_index = 0x20000002; + ti->sgx_svn_index = 0x50000004; + + return true; +} + +static bool tpm12_check(void) +{ + uint32_t ret, out_size = 0; + + ret = tpm12_submit_cmd(0, 0xFFFFFFFF, 0, &out_size); + + return ( ret == TPM_BAD_ORDINAL ); +} + +const struct tpm_if_fp tpm_12_if_fp = { + .init = tpm12_init, + .check = tpm12_check, +}; + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/common/tpm_20.c b/trenchboot/skboot/common/tpm_20.c new file mode 100644 index 0000000..4f0f16b --- /dev/null +++ b/trenchboot/skboot/common/tpm_20.c @@ -0,0 +1,494 @@ +/* + * tpm_20.c: TPM2.0-related support functions + * + * Copyright (c) 2006-2013, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static u8 cmd_buf[MAX_COMMAND_SIZE]; +static u8 rsp_buf[MAX_RESPONSE_SIZE]; + +#define reverse_copy_in(out, var) {\ + _reverse_copy((uint8_t *)(out), (uint8_t *)&(var), sizeof(var));\ + out += sizeof(var);\ +} + +#define reverse_copy_out(var, out) {\ + _reverse_copy((uint8_t *)&(var), (uint8_t *)(out), sizeof(var));\ + out += sizeof(var);\ +} + +static void reverse_copy_header(u32 cmd_code, TPM_CMD_SESSIONS_IN *sessions_in) +{ + u16 tag; + + if (sessions_in == NULL || sessions_in->num_sessions == 0) + tag = TPM_ST_NO_SESSIONS; + else + tag = TPM_ST_SESSIONS; + + reverse_copy(cmd_buf, &tag, sizeof(tag)); + reverse_copy(cmd_buf + CMD_CC_OFFSET, &cmd_code, sizeof(cmd_code)); +} + +/* + * Copy sized byte buffer from source to destination and + * twiddle the bytes in the size field. + * + * This can be used for the any of the following + * TPM 2.0 data structures, but is not limited to these: + * + * ENCRYPTED_SECRET_2B + * TPM2B_DIGEST + * TPM2B_NONCE + * TPM2B_DATA + * etc. (any structures consisting of UINT16 followed by a + * byte buffer whose size is specified by the UINT16. + * + * Inputs: + * + * dest -- pointer to SIZED_BYTE_BUFFER + * src -- pointer to SIZED_BYTE_BUFFER + * + * Outputs: + * + * number of bytes copied + */ +static u16 reverse_copy_sized_buf_in(TPM2B *dest, TPM2B *src) +{ + int i; + + if (dest == NULL || src == NULL) + return 0; + + reverse_copy(&dest->size, &src->size, sizeof(u16)); + for (i=0; isize; i++) + dest->buffer[i] = src->buffer[i]; + + return sizeof(u16) + src->size; +} + +/* + * Inputs: dest->size should contain the buffer size of dest->buffer[] + * Ouputs: dest->size should contain the final copied data size + * + * Return: 0, failed; 2+, succeed. + */ +static u16 reverse_copy_sized_buf_out(TPM2B *dest, TPM2B *src) +{ + u16 i, size; + + if (dest == NULL || src == NULL) + return 0; + + reverse_copy(&size, &src->size, sizeof(u16)); + if ( size > dest->size ) + return 0; + + dest->size = size; + for (i=0; isize; i++) + dest->buffer[i] = src->buffer[i]; + + return sizeof(u16) + dest->size; +} + +static void reverse_copy_session_data_in(void **other, + TPM_CMD_SESSION_DATA_IN *session_data, + u32 *session_size) +{ + *session_size += sizeof(u32) + sizeof( u16 ) + + session_data->nonce.t.size + sizeof( u8 ) + + sizeof( u16 ) + session_data->hmac.t.size; + + /* copy session handle */ + reverse_copy_in(*other, session_data->session_handle); + + /* Copy nonce */ + *other += reverse_copy_sized_buf_in((TPM2B *)*other, (TPM2B *)&session_data->nonce); + + /* Copy attributes */ + *((u8 *)*other) = *(u8 *)(void *)&(session_data->session_attr); + *other += sizeof(u8); + + /* Copy hmac data */ + *other += reverse_copy_sized_buf_in((TPM2B *)*other, (TPM2B *)&session_data->hmac); +} + +static void reverse_copy_sessions_in(void **other, TPM_CMD_SESSIONS_IN *sessions_in) +{ + int i; + u32 session_size = 0; + void *session_size_ptr = *other; + + if (sessions_in == NULL) + return; + + if (sessions_in->num_sessions != 0) { + *other += sizeof(u32); + for (i=0; inum_sessions; i++) + reverse_copy_session_data_in(other, + &sessions_in->sessions[i], &session_size); + } + + reverse_copy(session_size_ptr, &session_size, sizeof(u32)); +} + +static bool reverse_copy_session_data_out(TPM_CMD_SESSION_DATA_OUT *session_data, + void **other) +{ + u16 size; + + if (session_data == NULL) + return false; + + /* Copy nonce */ + session_data->nonce.t.size = sizeof(session_data->nonce.t.buffer); + size = reverse_copy_sized_buf_out((TPM2B *)&(session_data->nonce), + (TPM2B *)*other); + if ( size == 0 ) + return false; + *other += size; + + /* Copy sessionAttributes */ + *(u8 *)(void *)&(session_data->session_attr) = *((u8 *)*other); + *other += sizeof(u8); + + /* Copy hmac */ + session_data->hmac.t.size = sizeof(session_data->hmac.t.buffer); + size = reverse_copy_sized_buf_out((TPM2B *)&(session_data->hmac), + (TPM2B *)*other); + if ( size == 0 ) + return false; + *other += size; + + return true; +} + +static bool reverse_copy_sessions_out(TPM_CMD_SESSIONS_OUT *sessions_out, + void *other, u16 rsp_tag, + TPM_CMD_SESSIONS_IN *sessions_in) +{ + int i; + + if (sessions_in == NULL || sessions_out == NULL || rsp_tag != TPM_ST_SESSIONS) + return false; + + sessions_out->num_sessions = sessions_in->num_sessions; + for (i=0; inum_sessions; i++) + if ( !reverse_copy_session_data_out(&sessions_out->sessions[i], &other) ) + return false; + + return true; +} + +typedef struct { + u16 alg_id; + u16 size; /* Size of digest */ +} HASH_SIZE_INFO; + +HASH_SIZE_INFO hash_sizes[] = { + {TPM_ALG_SHA1, SHA1_DIGEST_SIZE}, + {TPM_ALG_SHA256, SHA256_DIGEST_SIZE}, + {TPM_ALG_SHA384, SHA384_DIGEST_SIZE}, + {TPM_ALG_SHA512, SHA512_DIGEST_SIZE}, + {TPM_ALG_SM3_256, SM3_256_DIGEST_SIZE}, + {TPM_ALG_NULL,0} +}; + +u16 get_digest_size(u16 id) +{ + unsigned int i; + for(i=0; i<(sizeof(hash_sizes)/sizeof(HASH_SIZE_INFO)); i++) { + if(hash_sizes[i].alg_id == id) + return hash_sizes[i].size; + } + + /* If not found, return 0 size, and let TPM handle the error. */ + return 0 ; +} + +static bool reverse_copy_digest_values_out(TPML_DIGEST_VALUES *tpml_digest, + void **other) +{ + unsigned int i, k, num_bytes; + + if (tpml_digest == NULL) + return false; + + reverse_copy_out(tpml_digest->count, *other); + if ( tpml_digest->count > HASH_COUNT ) + return false; + + for (i=0; icount; i++) { + reverse_copy_out(tpml_digest->digests[i].hash_alg, *other); + + num_bytes = get_digest_size(tpml_digest->digests[i].hash_alg); + + for (k=0; kdigests[i].digest.sha1[k] = *((u8 *)*other); + *other += sizeof(u8); + } + } + + return true; +} + +static uint32_t _tpm20_pcr_event(uint32_t locality, + tpm_pcr_event_in *in, + tpm_pcr_event_out *out) +{ + u32 ret; + u32 cmd_size, rsp_size; + u16 rsp_tag; + void *other; + + reverse_copy_header(TPM_CC_PCR_Event, &in->sessions); + + other = (void *)cmd_buf + CMD_HEAD_SIZE; + reverse_copy_in(other, in->pcr_handle); + + reverse_copy_sessions_in(&other, &in->sessions); + + other += reverse_copy_sized_buf_in((TPM2B *)other, (TPM2B *)&(in->data)); + + /* Now set the command size field, now that we know the size of the whole command */ + cmd_size = (u8 *)other - cmd_buf; + reverse_copy(cmd_buf + CMD_SIZE_OFFSET, &cmd_size, sizeof(cmd_size)); + + rsp_size = sizeof(*out); + + if (g_tpm_family == TPM_IF_20_FIFO) { + if (!tpm_submit_cmd(locality, cmd_buf, cmd_size, rsp_buf, &rsp_size)) + return TPM_RC_FAILURE; + } + if (g_tpm_family == TPM_IF_20_CRB) { + if (!tpm_submit_cmd_crb(locality, cmd_buf, cmd_size, rsp_buf, &rsp_size)) + return TPM_RC_FAILURE; + } + + reverse_copy(&ret, rsp_buf + RSP_RST_OFFSET, sizeof(ret)); + if ( ret != TPM_RC_SUCCESS ) + return ret; + + other = (void *)rsp_buf + RSP_HEAD_SIZE; + reverse_copy(&rsp_tag, rsp_buf, sizeof(rsp_tag)); + if (rsp_tag == TPM_ST_SESSIONS) + other += sizeof(u32); + + if ( !reverse_copy_digest_values_out(&out->digests, &other) ) + return TPM_RC_FAILURE; + + if ( !reverse_copy_sessions_out(&out->sessions, other, rsp_tag, &in->sessions) ) + return TPM_RC_FAILURE; + + return ret; +} + +static uint32_t _tpm20_pcr_reset(uint32_t locality, + tpm_pcr_reset_in *in, + tpm_pcr_reset_out *out) +{ + u32 ret; + u32 cmd_size, rsp_size; + u16 rsp_tag; + void *other; + + reverse_copy_header(TPM_CC_PCR_Reset, &in->sessions); + + other = (void *)cmd_buf + CMD_HEAD_SIZE; + reverse_copy(other, &in->pcr_handle, sizeof(u32)); + + other += sizeof(u32); + reverse_copy_sessions_in(&other, &in->sessions); + + /* Now set the command size field, now that we know the size of the whole command */ + cmd_size = (u8 *)other - cmd_buf; + reverse_copy(cmd_buf + CMD_SIZE_OFFSET, &cmd_size, sizeof(cmd_size)); + + rsp_size = sizeof(*out); + if (g_tpm_family == TPM_IF_20_FIFO) { + if (!tpm_submit_cmd(locality, cmd_buf, cmd_size, rsp_buf, &rsp_size)) + return TPM_RC_FAILURE; + } + if (g_tpm_family == TPM_IF_20_CRB) { + if (!tpm_submit_cmd_crb(locality, cmd_buf, cmd_size, rsp_buf, &rsp_size)) + return TPM_RC_FAILURE; + } + + reverse_copy(&ret, rsp_buf + RSP_RST_OFFSET, sizeof(ret)); + if ( ret != TPM_RC_SUCCESS ) + return ret; + + other = (void *)rsp_buf + RSP_HEAD_SIZE; + reverse_copy(&rsp_tag, rsp_buf, sizeof(rsp_tag)); + if (rsp_tag == TPM_ST_SESSIONS) + other += sizeof(u32); + + if ( !reverse_copy_sessions_out(&out->sessions, other, rsp_tag, &in->sessions) ) + return TPM_RC_FAILURE; + + return ret; +} + +__data u32 handle2048 = 0; + +TPM_CMD_SESSION_DATA_IN pw_session; +static void create_pw_session(TPM_CMD_SESSION_DATA_IN *ses) +{ + ses->session_handle = TPM_RS_PW; + ses->nonce.t.size = 0; + *((u8 *)((void *)&ses->session_attr)) = 0; + ses->hmac.t.size = 0; +} + +static bool tpm20_pcr_reset(struct tpm_if *ti, uint32_t locality, uint32_t pcr) +{ + tpm_pcr_reset_in reset_in; + tpm_pcr_reset_out reset_out; + u32 ret; + + reset_in.pcr_handle = pcr; + reset_in.sessions.num_sessions = 1; + reset_in.sessions.sessions[0] = pw_session; + + ret = _tpm20_pcr_reset(locality, &reset_in, &reset_out); + if (ret != TPM_RC_SUCCESS) { + printk(SKBOOT_WARN"TPM: Pcr %d Reset return value = %08X\n", pcr, ret); + ti->error = ret; + return false; + } + + return true; +} + +static bool alg_is_supported(u16 alg) +{ + for (int i=0; i<2; i++) { + if (alg == skboot_alg_list[i]) + return true; + } + + return false; +} + +static bool tpm20_init(struct tpm_if *ti) +{ + u32 ret; + unsigned int i; + //tpm_info_list_t *info_list = get_tpm_info_list(g_sinit); + + if ( ti == NULL ) + return false; + + ti->cur_loc = 0; + + /* init version */ + ti->major = TPM20_VER_MAJOR; + ti->minor = TPM20_VER_MINOR; + + /* init timeouts value */ + ti->timeout.timeout_a = TIMEOUT_A; + ti->timeout.timeout_b = TIMEOUT_B; + ti->timeout.timeout_c = TIMEOUT_C; + ti->timeout.timeout_d = TIMEOUT_D; + + /* create one common password sesson*/ + create_pw_session(&pw_session); + + /* init supported alg list for banks */ + tpm_pcr_event_in event_in; + tpm_pcr_event_out event_out; + event_in.pcr_handle = 16; + event_in.sessions.num_sessions = 1; + event_in.sessions.sessions[0] = pw_session; + event_in.data.t.size = 4; + event_in.data.t.buffer[0] = 0; + event_in.data.t.buffer[1] = 0xff; + event_in.data.t.buffer[2] = 0x55; + event_in.data.t.buffer[3] = 0xaa; + ret = _tpm20_pcr_event(ti->cur_loc, &event_in, &event_out); + if (ret != TPM_RC_SUCCESS) { + printk(SKBOOT_WARN"TPM: PcrEvent not successful, return value = %08X\n", ret); + ti->error = ret; + return false; + } + ti->banks = event_out.digests.count; + printk(SKBOOT_INFO"TPM: supported bank count = %d\n", ti->banks); + for (i=0; ibanks; i++) { + ti->algs_banks[i] = event_out.digests.digests[i].hash_alg;; + printk(SKBOOT_INFO"TPM: bank alg = %08x\n", ti->algs_banks[i]); + } + + /* init supported alg list */ + ti->alg_count = 0; + for (i=0; ibanks; i++) { + if (alg_is_supported(ti->algs_banks[i])) { + ti->algs[ti->alg_count] = ti->algs_banks[i]; + ti->alg_count++; + } + } + printk(SKBOOT_INFO"skboot: supported alg count = %d\n", ti->alg_count); + for (unsigned int i=0; ialg_count; i++) + printk(SKBOOT_INFO"skboot: hash alg = %08X\n", ti->algs[i]); + + /* reset debug PCR 16 */ + if (!tpm20_pcr_reset(ti, ti->cur_loc, 16)){ + printk(SKBOOT_WARN"TPM: tpm20_pcr_reset failed...\n"); + return false; + } + + return true; +} + +const struct tpm_if_fp tpm_20_if_fp = { + .init = tpm20_init +}; + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/common/vga.c b/trenchboot/skboot/common/vga.c new file mode 100644 index 0000000..34fd900 --- /dev/null +++ b/trenchboot/skboot/common/vga.c @@ -0,0 +1,138 @@ +/* + * vga.c: fns for outputting strings to VGA display + * + * Copyright (c) 2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +static uint16_t * const screen = (uint16_t * const)VGA_BASE; +static __data uint8_t cursor_x, cursor_y; +static __data unsigned int num_lines; +uint8_t g_vga_delay = 0; /* default to no delay */ + +static inline void reset_screen(void) +{ + sk_memset(screen, 0, SCREEN_BUFFER); + cursor_x = 0; + cursor_y = 0; + num_lines = 0; + + outb(CTL_ADDR_REG, START_ADD_HIGH_REG); + outb(CTL_DATA_REG, 0x00); + outb(CTL_ADDR_REG, START_ADD_LOW_REG); + outb(CTL_DATA_REG, 0x00); +} + +static void scroll_screen(void) +{ + for ( int y = 1; y < MAX_LINES; y++ ) { + for ( int x = 0; x < MAX_COLS; x++ ) + writew(VGA_ADDR(x, y-1), readw(VGA_ADDR(x, y))); + } + /* clear last line */ + for ( int x = 0; x < MAX_COLS; x++ ) + writew(VGA_ADDR(x, MAX_LINES-1), 0x720); +} + +static void __putc(uint8_t x, uint8_t y, int c) +{ + screen[(y * MAX_COLS) + x] = (COLOR << 8) | c; +} + +static void vga_putc(int c) +{ + bool new_row = false; + + switch ( c ) { + case '\n': + cursor_y++; + cursor_x = 0; + new_row = true; + break; + case '\r': + cursor_x = 0; + break; + case '\t': + cursor_x += 4; + break; + default: + __putc(cursor_x, cursor_y, c); + cursor_x++; + break; + } + + if ( cursor_x >= MAX_COLS ) { + cursor_x %= MAX_COLS; + cursor_y++; + new_row = true; + } + + if ( new_row ) { + num_lines++; + if ( cursor_y >= MAX_LINES ) { + scroll_screen(); + cursor_y--; + } + + /* (optionally) pause after every screenful */ + if ( (num_lines % (MAX_LINES - 1)) == 0 && g_vga_delay > 0 ) + delay(g_vga_delay * 1000); + } +} + +void vga_init(void) +{ + reset_screen(); +} + +void vga_puts(const char *s, unsigned int cnt) +{ + while ( *s && cnt-- ) { + vga_putc(*s); + s++; + } +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/cmdline.h b/trenchboot/skboot/include/cmdline.h new file mode 100644 index 0000000..7052615 --- /dev/null +++ b/trenchboot/skboot/include/cmdline.h @@ -0,0 +1,70 @@ +/* + * cmdline.h: support functions for command line parsing + * + * Copyright (c) 2006-2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __CMDLINE_H__ +#define __CMDLINE_H__ + +#define CMDLINE_SIZE 512 +extern char g_cmdline[CMDLINE_SIZE]; + + +extern void skboot_parse_cmdline(void); +extern void get_skboot_loglvl(void); +extern void get_skboot_log_targets(void); +extern bool get_skboot_serial(void); +extern void get_skboot_baud(void); +extern void get_skboot_vga_delay(void); +extern void get_skboot_min_ram(void); +extern uint32_t get_error_shutdown(void); + +/* for parse cmdline of linux kernel, say vga and mem */ +extern void linux_parse_cmdline(const char *cmdline); +extern bool get_linux_vga(int *vid_mode); +extern bool get_linux_mem(uint64_t *initrd_max_mem); + +extern uint8_t get_loglvl_prefix(char **pbuf, int *len); + +#endif /* __CMDLINE_H__ */ + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/com.h b/trenchboot/skboot/include/com.h new file mode 100644 index 0000000..da69392 --- /dev/null +++ b/trenchboot/skboot/include/com.h @@ -0,0 +1,311 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)ns16550.h 7.1 (Berkeley) 5/9/91 + * $FreeBSD: src/sys/dev/ic/ns16550.h,v 1.20 2010/01/11 04:13:06 imp Exp $ + */ +/* + * Portions copyright (c) 2010, Intel Corporation + */ + +/* + * NS8250... UART registers. + */ +#ifndef __COM_H__ +#define __COM_H__ + +/* 8250 registers #[0-6]. */ + +#define com_data 0 /* data register (R/W) */ +#define REG_DATA com_data + +#define com_ier 1 /* interrupt enable register (W) */ +#define REG_IER com_ier +#define IER_ERXRDY 0x1 +#define IER_ETXRDY 0x2 +#define IER_ERLS 0x4 +#define IER_EMSC 0x8 + +#define IER_BITS "\20\1ERXRDY\2ETXRDY\3ERLS\4EMSC" + +#define com_iir 2 /* interrupt identification register (R) */ +#define REG_IIR com_iir +#define IIR_IMASK 0xf +#define IIR_RXTOUT 0xc +#define IIR_BUSY 0x7 +#define IIR_RLS 0x6 +#define IIR_RXRDY 0x4 +#define IIR_TXRDY 0x2 +#define IIR_NOPEND 0x1 +#define IIR_MLSC 0x0 +#define IIR_FIFO_MASK 0xc0 /* set if FIFOs are enabled */ + +#define IIR_BITS "\20\1NOPEND\2TXRDY\3RXRDY" + +#define com_lcr 3 /* line control register (R/W) */ +#define com_cfcr com_lcr /* character format control register (R/W) */ +#define REG_LCR com_lcr +#define LCR_DLAB 0x80 +#define CFCR_DLAB LCR_DLAB +#define LCR_EFR_ENABLE 0xbf /* magic to enable EFR on 16650 up */ +#define CFCR_EFR_ENABLE LCR_EFR_ENABLE +#define LCR_SBREAK 0x40 +#define CFCR_SBREAK LCR_SBREAK +#define LCR_PZERO 0x30 +#define CFCR_PZERO LCR_PZERO +#define LCR_PONE 0x20 +#define CFCR_PONE LCR_PONE +#define LCR_PEVEN 0x10 +#define CFCR_PEVEN LCR_PEVEN +#define LCR_PODD 0x00 +#define CFCR_PODD LCR_PODD +#define LCR_PENAB 0x08 +#define CFCR_PENAB LCR_PENAB +#define LCR_STOPB 0x04 +#define CFCR_STOPB LCR_STOPB +#define LCR_8BITS 0x03 +#define CFCR_8BITS LCR_8BITS +#define LCR_7BITS 0x02 +#define CFCR_7BITS LCR_7BITS +#define LCR_6BITS 0x01 +#define CFCR_6BITS LCR_6BITS +#define LCR_5BITS 0x00 +#define CFCR_5BITS LCR_5BITS + +#define LCR_ODD_PARITY (LCR_PENAB | LCR_PODD) +#define LCR_EVEN_PARITY (LCR_PENAB | LCR_PEVEN) +#define LCR_MARK_PARITY (LCR_PENAB | LCR_PONE) +#define LCR_SPACE_PARITY (LCR_PENAB | LCR_PZERO) + +#define com_mcr 4 /* modem control register (R/W) */ +#define REG_MCR com_mcr +#define MCR_PRESCALE 0x80 /* only available on 16650 up */ +#define MCR_LOOPBACK 0x10 +#define MCR_IE 0x08 +#define MCR_IENABLE MCR_IE +#define MCR_DRS 0x04 +#define MCR_RTS 0x02 +#define MCR_DTR 0x01 + +#define MCR_BITS "\20\1DTR\2RTS\3DRS\4IE\5LOOPBACK\10PRESCALE" + +#define com_lsr 5 /* line status register (R/W) */ +#define REG_LSR com_lsr +#define LSR_RCV_FIFO 0x80 +#define LSR_TEMT 0x40 +#define LSR_TSRE LSR_TEMT +#define LSR_THRE 0x20 +#define LSR_TXRDY LSR_THRE +#define LSR_BI 0x10 +#define LSR_FE 0x08 +#define LSR_PE 0x04 +#define LSR_OE 0x02 +#define LSR_RXRDY 0x01 +#define LSR_RCV_MASK 0x1f + +#define LSR_BITS "\20\1RXRDY\2OE\3PE\4FE\5BI\6THRE\7TEMT\10RCV_FIFO" + +#define com_msr 6 /* modem status register (R/W) */ +#define REG_MSR com_msr +#define MSR_DCD 0x80 +#define MSR_RI 0x40 +#define MSR_DSR 0x20 +#define MSR_CTS 0x10 +#define MSR_DDCD 0x08 +#define MSR_TERI 0x04 +#define MSR_DDSR 0x02 +#define MSR_DCTS 0x01 + +#define MSR_BITS "\20\1DCTS\2DDSR\3TERI\4DDCD\5CTS\6DSR\7RI\10DCD" + +/* 8250 multiplexed registers #[0-1]. Access enabled by LCR[7]. */ +#define com_dll 0 /* divisor latch low (R/W) */ +#define com_dlbl com_dll +#define com_dlm 1 /* divisor latch high (R/W) */ +#define com_dlbh com_dlm +#define REG_DLL com_dll +#define REG_DLH com_dlm + +/* 16450 register #7. Not multiplexed. */ +#define com_scr 7 /* scratch register (R/W) */ + +/* 16550 register #2. Not multiplexed. */ +#define com_fcr 2 /* FIFO control register (W) */ +#define com_fifo com_fcr +#define REG_FCR com_fcr +#define FCR_ENABLE 0x01 +#define FIFO_ENABLE FCR_ENABLE +#define FCR_RCV_RST 0x02 +#define FIFO_RCV_RST FCR_RCV_RST +#define FCR_XMT_RST 0x04 +#define FIFO_XMT_RST FCR_XMT_RST +#define FCR_DMA 0x08 +#define FIFO_DMA_MODE FCR_DMA +#define FCR_RX_LOW 0x00 +#define FIFO_RX_LOW FCR_RX_LOW +#define FCR_RX_MEDL 0x40 +#define FIFO_RX_MEDL FCR_RX_MEDL +#define FCR_RX_MEDH 0x80 +#define FIFO_RX_MEDH FCR_RX_MEDH +#define FCR_RX_HIGH 0xc0 +#define FIFO_RX_HIGH FCR_RX_HIGH + +#define FCR_BITS "\20\1ENABLE\2RCV_RST\3XMT_RST\4DMA" + +/* 16650 registers #2,[4-7]. Access enabled by LCR_EFR_ENABLE. */ + +#define com_efr 2 /* enhanced features register (R/W) */ +#define REG_EFR com_efr +#define EFR_CTS 0x80 +#define EFR_AUTOCTS EFR_CTS +#define EFR_RTS 0x40 +#define EFR_AUTORTS EFR_RTS +#define EFR_EFE 0x10 /* enhanced functions enable */ + +#define com_xon1 4 /* XON 1 character (R/W) */ +#define com_xon2 5 /* XON 2 character (R/W) */ +#define com_xoff1 6 /* XOFF 1 character (R/W) */ +#define com_xoff2 7 /* XOFF 2 character (R/W) */ + +#define com_usr 39 /* Octeon 16750/16550 Uart Status Reg */ +#define REG_USR com_usr +#define USR_TXFIFO_NOTFULL 2 /* Uart TX FIFO Not full */ + +/* 16950 register #1. Access enabled by ACR[7]. Also requires !LCR[7]. */ +#define com_asr 1 /* additional status register (R[0-7]/W[0-1]) */ + +/* 16950 register #3. R/W access enabled by ACR[7]. */ +#define com_rfl 3 /* receiver fifo level (R) */ + +/* + * 16950 register #4. Access enabled by ACR[7]. Also requires + * !LCR_EFR_ENABLE. + */ +#define com_tfl 4 /* transmitter fifo level (R) */ + +/* + * 16950 register #5. Accessible if !LCR_EFR_ENABLE. Read access also + * requires ACR[6]. + */ +#define com_icr 5 /* index control register (R/W) */ + +/* + * 16950 register #7. It is the same as com_scr except it has a different + * abbreviation in the manufacturer's data sheet and it also serves as an + * index into the Indexed Control register set. + */ +#define com_spr com_scr /* scratch pad (and index) register (R/W) */ +#define REG_SPR com_scr + +/* + * 16950 indexed control registers #[0-0x13]. Access is via index in SPR, + * data in ICR (if ICR is accessible). + */ + +#define com_acr 0 /* additional control register (R/W) */ +#define ACR_ASE 0x80 /* ASR/RFL/TFL enable */ +#define ACR_ICRE 0x40 /* ICR enable */ +#define ACR_TLE 0x20 /* TTL/RTL enable */ + +#define com_cpr 1 /* clock prescaler register (R/W) */ +#define com_tcr 2 /* times clock register (R/W) */ +#define com_ttl 4 /* transmitter trigger level (R/W) */ +#define com_rtl 5 /* receiver trigger level (R/W) */ +/* ... */ + +/* Hardware extension mode register for RSB-2000/3000. */ +#define com_emr com_msr +#define EMR_EXBUFF 0x04 +#define EMR_CTSFLW 0x08 +#define EMR_DSRFLW 0x10 +#define EMR_RTSFLW 0x20 +#define EMR_DTRFLW 0x40 +#define EMR_EFMODE 0x80 + +/* com port */ +#define COM1_ADDR 0x3f8 +#define COM2_ADDR 0x2f8 +#define COM3_ADDR 0x3e8 +#define COM4_ADDR 0x2e8 + +#define GET_LCR_DATABIT(x) ({ \ + typeof(x) val = 0; \ + val = (((x) == 5) ? LCR_5BITS : (val)); \ + val = (((x) == 6) ? LCR_6BITS : (val)); \ + val = (((x) == 7) ? LCR_7BITS : (val)); \ + val = (((x) == 8) ? LCR_8BITS : (val)); \ + val; }) + +#define GET_LCR_STOPBIT(x) ({ \ + typeof(x) val = 0; \ + val = (((x) > 1) ? LCR_STOPB : val); \ + val; }) + +#define GET_LCR_PARITY(x) ({ \ + typeof(x) val = 0; \ + val = (((x) == 'n') ? (!LCR_PENAB) : val); \ + val = (((x) == 'o') ? LCR_ODD_PARITY : val); \ + val = (((x) == 'e') ? LCR_EVEN_PARITY : val); \ + val = (((x) == 'm') ? LCR_MARK_PARITY : val); \ + val = (((x) == 's') ? LCR_SPACE_PARITY : val); \ + val; }) + +#define GET_LCR_VALUE(data, stop, parity) \ + (GET_LCR_DATABIT(data) | GET_LCR_STOPBIT(stop) | GET_LCR_PARITY(parity)) + +typedef struct __packed { + uint32_t bus; + uint32_t slot; + uint32_t func; +} bdf_t; + +typedef struct __packed { + uint32_t comc_curspeed; /* baud rate */ + uint32_t comc_clockhz; /* clock hz */ + uint8_t comc_fmt; /* lcr value */ + uint32_t comc_port; /* serial port, COM[1|2|3|4] */ + uint32_t comc_irq; /* irq */ + bdf_t comc_psbdf; /* PCI serial controller bdf */ + bdf_t comc_pbbdf; /* PCI bridge bdf */ +} serial_port_t; + +extern void comc_init(void); +extern void comc_puts(const char*, unsigned int); + +#endif /* __COM_H__ */ + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/config.h b/trenchboot/skboot/include/config.h new file mode 100644 index 0000000..6055318 --- /dev/null +++ b/trenchboot/skboot/include/config.h @@ -0,0 +1,118 @@ +/* + * config.h: project-wide definitions + * + * Copyright (c) 2006-2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +/* + * build/support flags + */ + +/* address skboot will load and execute at */ +#define SKBOOT_START 0x02C04000 + +/* the beginning of skboot memory */ +#define SKBOOT_BASE_ADDR 0x02C00000 + +/* these addrs must be in low memory so that they are mapped by the */ +/* kernel at startup */ + +/* address/size for memory-resident serial log (when enabled) */ +#define SKBOOT_SERIAL_LOG_ADDR 0x60000 +#define SKBOOT_SERIAL_LOG_SIZE 0x08000 + +/* address/size for modified e820 table */ +#define SKBOOT_E820_COPY_ADDR (SKBOOT_SERIAL_LOG_ADDR + \ + SKBOOT_SERIAL_LOG_SIZE) +#define SKBOOT_E820_COPY_SIZE 0x02000 + +/* Used as a basic cmdline buffer size for copying cmdlines */ +#define SKBOOT_KERNEL_CMDLINE_SIZE 0x0400 + +#ifndef NR_CPUS +#define NR_CPUS 512 +#endif + +#ifdef __ASSEMBLY__ +#define ENTRY(name) \ + .globl name; \ + .align 16,0x90; \ + name: +#else +extern char _start[]; /* start of skboot */ +extern char _end[]; /* end of skboot */ +#endif + + +#define COMPILE_TIME_ASSERT(e) \ +{ \ + struct tmp { \ + int a : ((e) ? 1 : -1); \ + }; \ +} + + +#define __data __attribute__ ((__section__ (".data"))) +#define __text __attribute__ ((__section__ (".text"))) + +#define __packed __attribute__ ((packed)) + +/* skboot log level */ +#ifdef NO_SKBOOT_LOGLVL +#define SKBOOT_NONE +#define SKBOOT_ERR +#define SKBOOT_WARN +#define SKBOOT_INFO +#define SKBOOT_DETA +#define SKBOOT_ALL +#else /* NO_SKBOOT_LOGLVL */ +#define SKBOOT_NONE "<0>" +#define SKBOOT_ERR "<1>" +#define SKBOOT_WARN "<2>" +#define SKBOOT_INFO "<3>" +#define SKBOOT_DETA "<4>" +#define SKBOOT_ALL "<5>" +#endif /* NO_SKBOOT_LOGLVL */ + +#endif /* __CONFIG_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/ctype.h b/trenchboot/skboot/include/ctype.h new file mode 100644 index 0000000..1747dfc --- /dev/null +++ b/trenchboot/skboot/include/ctype.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __CTYPE_H__ +#define __CTYPE_H__ + +#include +#include + +/* from: + * http://fxr.watson.org/fxr/source/dist/acpica/acutils.h?v=NETBSD5 +*/ + +extern const uint8_t _ctype[]; + +#define _XA 0x00 /* extra alphabetic - not supported */ +#define _XS 0x40 /* extra space */ +#define _BB 0x00 /* BEL, BS, etc. - not supported */ +#define _CN 0x20 /* CR, FF, HT, NL, VT */ +#define _DI 0x04 /* ''-'9' */ +#define _LO 0x02 /* 'a'-'z' */ +#define _PU 0x10 /* punctuation */ +#define _SP 0x08 /* space */ +#define _UP 0x01 /* 'A'-'Z' */ +#define _XD 0x80 /* ''-'9', 'A'-'F', 'a'-'f' */ + +static always_inline bool isdigit(int c) +{ + return (_ctype[(unsigned char)(c)] & (_DI)); +} +static always_inline bool isspace(int c) +{ + return (_ctype[(unsigned char)(c)] & (_SP)); +} +static always_inline bool isxdigit(int c) +{ + return (_ctype[(unsigned char)(c)] & (_XD)); +} +static always_inline bool isupper(int c) +{ + return (_ctype[(unsigned char)(c)] & (_UP)); +} +static always_inline bool islower(int c) +{ + return (_ctype[(unsigned char)(c)] & (_LO)); +} +static always_inline bool isprint(int c) +{ + return (_ctype[(unsigned char)(c)] & (_LO | _UP | _DI | + _SP | _PU)); +} +static always_inline bool isalpha(int c) +{ + return (_ctype[(unsigned char)(c)] & (_LO | _UP)); +} + + +#endif /* __CTYPE_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/e820.h b/trenchboot/skboot/include/e820.h new file mode 100644 index 0000000..efe9a79 --- /dev/null +++ b/trenchboot/skboot/include/e820.h @@ -0,0 +1,137 @@ +/* + * e820.h: support functions for manipulating the e820 table + * + * Copyright (c) 2006-2009, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __E820_H__ +#define __E820_H__ + +#ifndef E820_RAM +#define E820_RAM 1 +#endif + +#ifndef E820_RESERVED +#define E820_RESERVED 2 +#endif + +#ifndef E820_ACPI +#define E820_ACPI 3 +#endif + +#ifndef E820_NVS +#define E820_NVS 4 +#endif + +#ifndef E820_UNUSABLE +#define E820_UNUSABLE 5 +#endif + +/* these are only used by e820_check_region() */ +#define E820_MIXED ((uint32_t)-1 - 1) +#define E820_GAP ((uint32_t)-1) + +#define E820MAX 128 + +typedef struct __packed { + uint64_t addr; /* start of memory segment */ + uint64_t size; /* size of memory segment */ + uint32_t type; /* type of memory segment */ +} e820entry_t; + +typedef struct { + uint32_t type; + uint32_t pad; + uint64_t phys_addr; + uint64_t virt_addr; + uint64_t num_pages; + uint64_t attribute; +} efi_memory_desc_t; + +extern memory_map_t *get_e820_copy(void); +extern unsigned int get_nr_map(void); +extern bool copy_e820_map(loader_ctx *lctx); +extern bool e820_protect_region(uint64_t addr, uint64_t size, uint32_t type); +extern bool e820_reserve_ram(uint64_t base, uint64_t length); +extern void print_e820_map(void); +extern uint32_t e820_check_region(uint64_t base, uint64_t length); +extern bool get_ram_ranges(uint64_t *min_lo_ram, uint64_t *max_lo_ram, + uint64_t *min_hi_ram, uint64_t *max_hi_ram); +extern void get_highest_sized_ram(uint64_t size, uint64_t limit, + uint64_t *ram_base, uint64_t *ram_size); + +/* + * Memory map descriptor: + */ + +/* Memory types: */ +#define EFI_RESERVED_TYPE 0 +#define EFI_LOADER_CODE 1 +#define EFI_LOADER_DATA 2 +#define EFI_BOOT_SERVICES_CODE 3 +#define EFI_BOOT_SERVICES_DATA 4 +#define EFI_RUNTIME_SERVICES_CODE 5 +#define EFI_RUNTIME_SERVICES_DATA 6 +#define EFI_CONVENTIONAL_MEMORY 7 +#define EFI_UNUSABLE_MEMORY 8 +#define EFI_ACPI_RECLAIM_MEMORY 9 +#define EFI_ACPI_MEMORY_NVS 10 +#define EFI_MEMORY_MAPPED_IO 11 +#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12 +#define EFI_PAL_CODE 13 +#define EFI_MAX_MEMORY_TYPE 14 + +/* Attribute values: */ +#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */ +#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */ +#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */ +#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */ +#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */ +#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */ +#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */ +#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */ +#define EFI_MEMORY_DESCRIPTOR_VERSION 1 + +#define EFI_PAGE_SHIFT 12 + +#endif /* __E820_H__ */ + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/elf.h b/trenchboot/skboot/include/elf.h new file mode 100644 index 0000000..442630b --- /dev/null +++ b/trenchboot/skboot/include/elf.h @@ -0,0 +1,181 @@ +/* + * elf_defns.h: ELF file type definitions + * + * Copyright (c) 2006-2007, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __ELF_DEFNS_H__ +#define __ELF_DEFNS_H__ + +/* Elf header */ +typedef struct { + unsigned char e_ident[16]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint32_t e_entry; + uint32_t e_phoff; + uint32_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsz; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +} elf_header_t; + +/* elf64_header_t */ +typedef struct { +unsigned char e_ident[16]; /* ELF identification */ +uint16_t e_type; /* Object file type */ +uint16_t e_machine; /* Machine type */ +uint32_t e_version; /* Object file version */ +uint64_t e_entry; /* Entry point address */ +uint64_t e_phoff; /* Program header offset */ +uint64_t e_shoff; /* Section header offset */ +uint32_t e_flags; /* Processor-specific flags */ +uint16_t e_ehsize; /* ELF header size */ +uint16_t e_phentsize; /* Size of program header entry */ +uint16_t e_phnum; /* Number of program header entries */ +uint16_t e_shentsize; /* Size of section header entry */ +uint16_t e_shnum; /* Number of section header entries */ +uint16_t e_shstrndx; /* Section name string table index */ +} elf64_header_t; + + + + + + +/* e_ident[] Identification Indexes */ +#define EI_MAG0 0 /* File identification */ +#define EI_MAG1 1 /* File identification */ +#define EI_MAG2 2 /* File identification */ +#define EI_MAG3 3 /* File identification */ +#define EI_CLASS 4 /* File class */ +#define EI_DATA 5 /* Data encoding */ +#define EI_VERSION 6 /* File version */ +#define EI_PAD 7 /* Start of padding bytes */ +#define EI_NIDENT 8 /* Size of e_ident[] */ + +/* Magic number */ +#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */ +#define ELFMAG1 'E' /* e_ident[EI_MAG1] */ +#define ELFMAG2 'L' /* e_ident[EI_MAG2] */ +#define ELFMAG3 'F' /* e_ident[EI_MAG3] */ + +/* e_ident[EI_CLASS] */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ + +/* e_ident[EI_DATA] */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* Least significant byte */ +#define ELFDATA2MSB 2 /* Most significant byte */ + +/* e_type */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_LOPROC 0xff00 /* Processor-specific */ +#define ET_HIPROC 0xffff /* Processor-specific */ + +/* e_machine */ +#define ET_NONE 0 /* No machine */ +#define EM_M32 1 /* At&t We 32100 */ +#define EM_SPARC 2 /* SPARC */ +#define EM_386 3 /* Intel architecture */ +#define EM_68K 4 /* Motorola 68000 */ +#define EM_88K 5 /* Motorola 88000 */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS RS3000 Big-Endian */ +#define EM_MIPS_RS4_BE 10 /* MIPS RS4000 Big-Endian */ +#define EM_AMD64 62 /* AMDs x86-64 architecture */ + +/* e_version */ +#define EV_NONE 0 /* Invalid version */ +#define EV_CURRENT 1 /* Current version */ + +/* Program header */ +typedef struct { + uint32_t p_type; + uint32_t p_offset; + uint32_t p_vaddr; + uint32_t p_paddr; + uint32_t p_filesz; + uint32_t p_memsz; + uint32_t p_flags; + uint32_t p_align; +} elf_program_header_t; + +typedef struct{ +uint32_t p_type; /* Type of segment */ +uint32_t p_flags; /* Segment attributes */ +uint64_t p_offset; /* Offset in file */ +uint64_t p_vaddr; /* Virtual address in memory */ +uint64_t p_paddr; /* Reserved */ +uint64_t p_filesz; /* Size of segment in file */ +uint64_t p_memsz; /* Size of segment in memory */ +uint64_t p_align; /* Alignment of segment */ +} elf64_program_header_t; + +/* p_type */ +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +/* multiboot magic */ +#define MB_MAGIC 0x2badb002 + +#endif /* __ELF_DEFNS_H__ */ + + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/linux.h b/trenchboot/skboot/include/linux.h new file mode 100644 index 0000000..2a8fc75 --- /dev/null +++ b/trenchboot/skboot/include/linux.h @@ -0,0 +1,261 @@ +/* + * linux_defns.h: Linux kernel type definitions + * + * Copyright (c) 2006-2009, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __LINUX_DEFNS_H__ +#define __LINUX_DEFNS_H__ + +#define SECTOR_SIZE (1 << 9) /* 0x200 = 512B */ + +#define KERNEL_HEADER_OFFSET 0x1F1 + +/* linux kernel header */ +typedef struct __attribute__ ((packed)) { + uint8_t setup_sects; /* The size of the setup in sectors */ + #define DEFAULT_SECTOR_NUM 4 /* default sector number 4 */ + #define MAX_SECTOR_NUM 64 /* max sector number 64 */ + + uint16_t root_flags; /* If set, the root is mounted readonly */ + uint32_t syssize; /* The size of the 32-bit code in 16-byte paras */ + uint16_t ram_size; /* DO NOT USE - for bootsect.S use only */ + uint16_t vid_mode; /* Video mode control */ + uint16_t root_dev; /* Default root device number */ + uint16_t boot_flag; /* 0xAA55 magic number */ + uint16_t jump; /* Jump instruction */ + + uint32_t header; /* Magic signature "HdrS" */ + #define HDRS_MAGIC 0x53726448 + + uint16_t version; /* Boot protocol version supported */ + uint32_t realmode_swtch; /* Boot loader hook */ + uint16_t start_sys; /* The load-low segment (0x1000) (obsolete) */ + uint16_t kernel_version; /* Points to kernel version string */ + + uint8_t type_of_loader; /* Boot loader identifier */ + #define LOADER_TYPE_LILO 0x01 + #define LOADER_TYPE_LOADLIN 0x10 + #define LOADER_TYPE_BOOTSECT_LOADER 0x20 + #define LOADER_TYPE_SYSLINUX 0x30 + #define LOADER_TYPE_ETHERBOOT 0x40 + #define LOADER_TYPE_ELILO 0x50 + #define LOADER_TYPE_GRUB 0x71 + #define LOADER_TYPE_U_BOOT 0x80 + #define LOADER_TYPE_XEN 0x90 + #define LOADER_TYPE_UNKNOWN 0xFF + + uint8_t loadflags; /* Boot protocol option flags */ + #define FLAG_LOAD_HIGH 0x01 + #define FLAG_CAN_USE_HEAP 0x80 + + uint16_t setup_move_size;/* Move to high memory size (used with hooks) */ + uint32_t code32_start; /* Boot loader hook */ + uint32_t ramdisk_image; /* initrd load address (set by boot loader) */ + uint32_t ramdisk_size; /* initrd size (set by boot loader) */ + uint32_t bootsect_kludge;/* DO NOT USE - for bootsect.S use only */ + uint16_t heap_end_ptr; /* Free memory after setup end */ + uint8_t ext_loader_ver; /* Boot Protocol: 2.02+ */ + uint8_t ext_loader_type;/* Boot Protocol: 2.02+ */ + uint32_t cmd_line_ptr; /* 32-bit pointer to the kernel command line */ + uint32_t initrd_addr_max;/* Highest legal initrd address */ + uint32_t kernel_alignment; /* Physical addr alignment + required for kernel */ + uint8_t relocatable_kernel; /* Whether kernel is relocatable + or not */ + uint8_t min_alignment; /* Boot Protocol: 2.10+ */ + uint16_t xloadflags; /* Boot Protocol: 2.12+ */ + uint32_t cmdline_size; /* Maximum size of the kernel + command line */ + uint32_t hardware_subarch; /* Hardware subarchitecture */ + uint64_t hardware_subarch_data; /* Subarchitecture-specific data */ + uint32_t payload_offset; + uint32_t payload_length; + uint64_t setup_data; + uint64_t pref_address; + uint32_t init_size; + uint32_t handover_offset; + uint32_t slaunch_header; +} linux_kernel_header_t; + +typedef struct __attribute__ ((packed)) { + uint8_t screen_info[0x040-0x000]; /* 0x000 */ + uint8_t apm_bios_info[0x054-0x040]; /* 0x040 */ + uint8_t _pad2[4]; /* 0x054 */ + uint8_t skboot_shared_addr[8]; /* 0x058 */ + uint8_t ist_info[0x070-0x060]; /* 0x060 */ + uint8_t acpi_rsdp_addr[8]; /* 0x070 */ + uint8_t _pad3[8]; /* 0x078 */ + uint8_t hd0_info[16]; /* obsolete! */ /* 0x080 */ + uint8_t hd1_info[16]; /* obsolete! */ /* 0x090 */ + uint8_t sys_desc_table[0x0b0-0x0a0]; /* 0x0a0 */ + uint8_t _pad4[144]; /* 0x0b0 */ + uint8_t edid_info[0x1c0-0x140]; /* 0x140 */ + uint8_t efi_info[0x1e0-0x1c0]; /* 0x1c0 */ + uint8_t alt_mem_k[0x1e4-0x1e0]; /* 0x1e0 */ + uint8_t scratch[0x1e8-0x1e4]; /* 0x1e4 */ + uint8_t e820_entries; /* 0x1e8 */ + uint8_t eddbuf_entries; /* 0x1e9 */ + uint8_t edd_mbr_sig_buf_entries; /* 0x1ea */ + uint8_t _pad6[6]; /* 0x1eb */ + linux_kernel_header_t hdr; /* setup header */ /* 0x1f1 */ + uint8_t _pad7[0x290-0x1f1-sizeof(linux_kernel_header_t)]; + uint8_t edd_mbr_sig_buffer[0x2d0-0x290]; /* 0x290 */ + e820entry_t e820_map[E820MAX]; /* 0x2d0 */ + uint8_t _pad8[48]; /* 0xcd0 */ + uint8_t eddbuf[0xeec-0xd00]; /* 0xd00 */ + uint8_t _pad9[276]; /* 0xeec */ +} boot_params_t; + +typedef struct __attribute__ ((packed)) { + u8 orig_x; /* 0x00 */ + u8 orig_y; /* 0x01 */ + u16 ext_mem_k; /* extended memory size in kb */ /* 0x02 */ + u16 orig_video_page; /* 0x04 */ + u8 orig_video_mode; /* representing the specific mode + that was in effect when booting */ /* 0x06 */ + u8 orig_video_cols; /* 0x07 */ + u16 unused2; /* 0x08 */ + u16 orig_video_ega_bx; /* video state and installed + memory */ /* 0x0a */ + u16 unused3; /* 0x0c */ + u8 orig_video_lines; /* 0x0e */ + u8 orig_video_isVGA; /* distinguish between VGA text + and vesa lfb based screen setups */ /* 0x0f */ + u16 orig_video_points; /* font height */ /* 0x10 */ + + u16 lfb_width; /* 0x12 */ + u16 lfb_height; /* 0x14 */ + u16 lfb_depth; /* 0x16 */ + u32 lfb_base; /* 0x18 */ + u32 lfb_size; /* 0x1c */ + + u16 cl_magic; /* 0x20 */ + u16 cl_offset; /* 0x22 */ + + u16 lfb_line_len; /* 0x24 */ + u8 red_mask_size; /* 0x26 */ + u8 red_field_pos; /* 0x27 */ + u8 green_mask_size; /* 0x28 */ + u8 green_field_pos; /* 0x29 */ + u8 blue_mask_size; /* 0x2a */ + u8 blue_field_pos; /* 0x2b */ + u8 reserved_mask_size; /* 0x2c */ + u8 reserved_field_pos; /* 0x2d */ + u16 vesapm_segment; /* 0x2e */ + u16 vesapm_offset; /* 0x30 */ + u16 lfb_pages; /* 0x32 */ + u16 vesa_attrib; /* 0x34 */ + u32 capabilities; /* 0x36 */ + /* padding out to 0x40 */ +} screen_info_t; + +/* recommended layout + | Protected-mode kernel | The kernel protected-mode code. +100000 +---------------------------+ + | I/O memory hole | +0A0000 +---------------------------+ + | Reserved for BIOS | Do not use. Reserved for BIOS EBDA. +099100 +---------------------------+ + | cmdline | +099000 +---------------------------+ + | Stack/heap | For use by the kernel real-mode code. +098000 +---------------------------+ + | Kernel setup | The kernel real-mode code. +090200 +---------------------------+ + | Kernel boot sector | The kernel legacy boot sector. +090000 +---------------------------+ + | Boot loader | <- Boot sector entry point 0000:7C00 +001000 +---------------------------+ + | Reserved for MBR/BIOS | +000800 +---------------------------+ + | Typically used by MBR | +000600 +---------------------------+ + | BIOS use only | +000000 +---------------------------+ +*/ + +#define BZIMAGE_PROTECTED_START 0x100000 +#define LEGACY_REAL_START 0x90000 + +#define REAL_KERNEL_OFFSET 0x0000 +#define BOOT_SECTOR_OFFSET 0x0200 +#define KERNEL_CMDLINE_OFFSET 0x8D00 +#define REAL_END_OFFSET 0x9100 + +#define REAL_MODE_SIZE REAL_END_OFFSET - REAL_KERNEL_OFFSET + +struct efi_info { + uint32_t efi_ldr_sig; + uint32_t efi_systable; + uint32_t efi_memdescr_size; + uint32_t efi_memdescr_ver; + uint32_t efi_memmap; + uint32_t efi_memmap_size; + uint32_t efi_systable_hi; + uint32_t efi_memmap_hi; +}; + +struct setup_data { + uint64_t next; + uint32_t type; + uint32_t len; + /* data */ +}; + +struct kernel_info { + char magic[4]; + uint32_t size; + uint32_t size_total; + uint32_t setup_type_max; + uint32_t mle_header_offset; +}; + +typedef struct { + uint32_t real_mode_base; + unsigned long real_mode_size; + uint32_t protected_mode_base; + unsigned long protected_mode_size; + boot_params_t *boot_params; +} il_kernel_setup_t; + +#endif /* __LINUX_DEFNS_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/loader.h b/trenchboot/skboot/include/loader.h new file mode 100644 index 0000000..ed039b6 --- /dev/null +++ b/trenchboot/skboot/include/loader.h @@ -0,0 +1,104 @@ +/* + * loader.h: support functions for manipulating ELF and AOUT binaries + * + * Copyright (c) 2006-2013, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __LOADER_H__ +#define __LOADER_H__ + +typedef struct { + void *addr; + uint32_t type; +} loader_ctx; + +extern loader_ctx *g_ldr_ctx; + +#ifndef __MULTIBOOT_H__ +/* a few useful utility types */ +typedef struct { + uint32_t mod_start; + uint32_t mod_end; + uint32_t string; + uint32_t reserved; +} module_t; + +typedef struct { + uint32_t size; + uint32_t base_addr_low; + uint32_t base_addr_high; + uint32_t length_low; + uint32_t length_high; + uint32_t type; +} memory_map_t; +#endif + +extern void print_loader_ctx(loader_ctx *lctx); +extern bool find_module_by_pattern(loader_ctx *lctx, void **base, size_t *size, + const void *pattern, size_t len); +extern uint32_t find_efi_memmap(loader_ctx *lctx, uint32_t *descr_size, + uint32_t *descr_vers, uint32_t *mmap_size); + +extern bool prepare_intermediate_loader(void); +extern bool verify_loader_context(loader_ctx *lctx); +extern module_t *get_module(loader_ctx *lctx, unsigned int i); +extern unsigned int get_module_count(loader_ctx *lctx); + +extern bool have_loader_memlimits(loader_ctx *lctx); +extern bool have_loader_memmap(loader_ctx *lctx); +extern memory_map_t *get_loader_memmap(loader_ctx *lctx); +extern uint32_t get_loader_memmap_length(loader_ctx *lctx); +extern uint32_t get_loader_mem_lower(loader_ctx *lctx); +extern uint32_t get_loader_mem_upper(loader_ctx *lctx); +extern char *get_module_cmd(loader_ctx *lctx, module_t *mod); +extern char *get_cmdline(loader_ctx *lctx); +extern void determine_loader_type(void *addr, uint32_t magic); +extern unsigned long get_loader_ctx_end(loader_ctx *lctx); +extern bool find_skl_module(loader_ctx *lctx); +extern void replace_e820_map(loader_ctx *lctx); +extern bool is_loader_launch_efi(loader_ctx *lctx); +extern bool get_loader_efi_ptr(loader_ctx *lctx, uint32_t *address, + uint64_t *long_address); +extern void load_framebuffer_info(loader_ctx *lctx, void *vscr); +extern char *get_first_module_cmd(loader_ctx *lctx); + +#endif /* __LOADER_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/misc.h b/trenchboot/skboot/include/misc.h new file mode 100644 index 0000000..6c8b05d --- /dev/null +++ b/trenchboot/skboot/include/misc.h @@ -0,0 +1,89 @@ +/* + * misc.h: miscellaneous support fns + * + * Copyright (c) 2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __MISC_H__ +#define __MISC_H__ + +extern void print_hex(const char * buf, const void * prtptr, size_t size); + +extern void delay(int millisecs); + +/* + * These three "plus overflow" functions take a "x" value + * and add the "y" value to it and if the two values are + * greater than the size of the variable type, they will + * overflow the type and end up with a smaller value and + * return TRUE - that they did overflow. i.e. + * x + y <= variable type maximum. + */ +static inline bool plus_overflow_u64(uint64_t x, uint64_t y) +{ + return ((((uint64_t)(~0)) - x) < y); +} + +static inline bool plus_overflow_u32(uint32_t x, uint32_t y) +{ + return ((((uint32_t)(~0)) - x) < y); +} + +/* + * This checks to see if two numbers multiplied together are larger + * than the type that they are. Returns TRUE if OVERFLOWING. + * If the first parameter "x" is greater than zero and + * if that is true, that the largest possible value 0xFFFFFFFF / "x" + * is less than the second parameter "y". If "y" is zero then + * it will also fail because no unsigned number is less than zero. + */ +static inline bool multiply_overflow_u32(uint32_t x, uint32_t y) +{ + return (x > 0) ? ((((uint32_t)(~0))/x) < y) : false; +} + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +#define AP_WAKE_TRIGGER_DEF 0xffffffff + +#endif /* __MISC_H__ */ + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/multiboot.h b/trenchboot/skboot/include/multiboot.h new file mode 100644 index 0000000..ef5c0d6 --- /dev/null +++ b/trenchboot/skboot/include/multiboot.h @@ -0,0 +1,478 @@ +/* + * multiboot.h: definitions for the multiboot bootloader specification + * + * Copyright (c) 2013, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __MULTIBOOT_H__ +#define __MULTIBOOT_H__ + +#include + +/* Multiboot Header Definitions of OS image*/ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 +#define MULTIBOOT_HEADER_SEARCH_LIMIT 8192 + +/* Bit definitions of flags field of multiboot header*/ +#define MULTIBOOT_HEADER_MODS_ALIGNED 0x1 +#define MULTIBOOT_HEADER_WANT_MEMORY 0x2 + +/* bit definitions of flags field of multiboot information */ +#define MBI_MEMLIMITS (1<<0) +#define MBI_BOOTDEV (1<<1) +#define MBI_CMDLINE (1<<2) +#define MBI_MODULES (1<<3) +#define MBI_AOUT (1<<4) +#define MBI_ELF (1<<5) +#define MBI_MEMMAP (1<<6) +#define MBI_DRIVES (1<<7) +#define MBI_CONFIG (1<<8) +#define MBI_BTLDNAME (1<<9) +#define MBI_APM (1<<10) +#define MBI_VBE (1<<11) + +/* multiboot 2 constants */ +#define MB2_HEADER_MAGIC 0xe85250d6 +#define MB2_LOADER_MAGIC 0x36d76289 +#define MB2_HEADER_SEARCH_LIMIT 32768 + +#define MB2_ARCH_X86 0 + +#define MB2_HDR_TAG_END 0 +#define MB2_HDR_TAG_INFO_REQ 1 +#define MB2_HDR_TAG_ADDR 2 +#define MB2_HDR_TAG_ENTRY_ADDR 3 +#define MB2_HDR_TAG_CONSOLE_FLAGS 4 +#define MB2_HDR_TAG_FRAMEBUFFER 5 +#define MB2_HDR_TAG_MOD_ALIGN 6 + +#define MB2_HDR_TAG_OPTIONAL 1 + +#define MB2_CONS_FLAGS_CONS_REQ 1 +#define MB2_CONS_FLAGS_EGA_TEXT_SUP 2 + + +#define MB2_TAG_TYPE_END 0 +#define MB2_TAG_TYPE_CMDLINE 1 +#define MB2_TAG_TYPE_LOADER_NAME 2 +#define MB2_TAG_TYPE_MODULE 3 +#define MB2_TAG_TYPE_MEMLIMITS 4 +#define MB2_TAG_TYPE_BOOTDEV 5 +#define MB2_TAG_TYPE_MMAP 6 +#define MB2_TAG_TYPE_VBE 7 +#define MB2_TAG_TYPE_FRAMEBUFFER 8 +#define MB2_TAG_TYPE_ELF_SECTIONS 9 +#define MB2_TAG_TYPE_APM 10 +#define MB2_TAG_TYPE_EFI32 11 +#define MB2_TAG_TYPE_EFI64 12 +#define MB2_TAG_TYPE_SMBIOS 13 +#define MB2_TAG_TYPE_ACPI_OLD 14 +#define MB2_TAG_TYPE_ACPI_NEW 15 +#define MB2_TAG_TYPE_NETWORK 16 +#define MB2_TAG_TYPE_EFI_MMAP 17 +#define MB2_TAG_TYPE_EFI_BS 18 + +#ifndef __ASSEMBLY__ + +/* mb2 header flags */ +struct mb2_hdr_tag_info_req +{ + uint16_t type; + uint16_t flags; + uint32_t size; + uint32_t requests[0]; +}; + +struct mb2_hdr_tag_addr +{ + uint16_t type; + uint16_t flags; + uint32_t size; + uint32_t header_addr; + uint32_t load_addr; + uint32_t load_end_addr; + uint32_t bss_end_addr; +}; + +struct mb2_hdr_tag_entry_addr +{ + uint16_t type; + uint16_t flags; + uint32_t size; + uint32_t entry_addr; +}; + +struct mb2_hdr_tag_console_flags +{ + uint16_t type; + uint16_t flags; + uint32_t size; + uint32_t console_flags; +}; + +struct mb2_hdr_tag_framebuffer +{ + uint16_t type; + uint16_t flags; + uint32_t size; + uint32_t width; + uint32_t height; + uint32_t depth; +}; + +struct mb2_hdr_tag_mod_align +{ + uint16_t type; + uint16_t flags; + uint32_t size; + uint32_t width; + uint32_t height; + uint32_t depth; +}; + +/* MB2 info tags */ + +struct mb2_tag +{ + uint32_t type; + uint32_t size; +}; + +struct mb2_tag_string +{ + uint32_t type; + uint32_t size; + char string[0]; +}; + +struct mb2_tag_memlimits +{ + uint32_t type; + uint32_t size; + uint32_t mem_lower; + uint32_t mem_upper; +}; + +struct mb2_tag_bootdev +{ + uint32_t type; + uint32_t size; + uint32_t biosdev; + uint32_t slice; + uint32_t part; +}; + +struct mb2_mmap_entry +{ + uint64_t addr; + uint64_t len; +#define MULTIBOOT_MEMORY_AVAILABLE 1 +#define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 +#define MULTIBOOT_MEMORY_BADRAM 5 + uint32_t type; + uint32_t zero; +} __attribute__((packed)); + +struct mb2_tag_mmap +{ + uint32_t type; + uint32_t size; + uint32_t entry_size; + uint32_t entry_version; + struct mb2_mmap_entry entries[0]; +}; + +struct mb2_tag_module +{ + uint32_t type; + uint32_t size; + uint32_t mod_start; + uint32_t mod_end; + char cmdline[0]; +}; + +struct mb2_tag_old_acpi +{ + uint32_t type; + uint32_t size; + uint8_t rsdp[0]; +}; + +struct mb2_tag_new_acpi +{ + uint32_t type; + uint32_t size; + uint8_t rsdp[0]; +}; + +struct mb2_tag_efi32 +{ + uint32_t type; + uint32_t size; + uint32_t pointer; +}; + +struct mb2_tag_efi64 +{ + uint32_t type; + uint32_t size; + uint64_t pointer; +}; + +struct mb2_tag_network +{ + uint32_t type; + uint32_t size; + uint8_t dhcpack[0]; +}; + +struct mb2_tag_smbios +{ + uint32_t type; + uint32_t size; + uint8_t major; + uint8_t minor; + uint8_t reserved[6]; + uint8_t tables[0]; +}; + +struct mb2_tag_elf_sections +{ + uint32_t type; + uint32_t size; + uint32_t num; + uint32_t entsize; + uint32_t shndx; + char sections[0]; +}; + +struct mb2_tag_apm +{ + uint32_t type; + uint32_t size; + uint16_t version; + uint16_t cseg; + uint32_t offset; + uint16_t cseg_16; + uint16_t dseg; + uint16_t flags; + uint16_t cseg_len; + uint16_t cseg_16_len; + uint16_t dseg_len; +}; + +struct mb2_vbe_info_block +{ + uint8_t external_specification[512]; +}; + +struct mb2_vbe_mode_info_block +{ + uint8_t external_specification[256]; +}; + +struct mb2_tag_vbe +{ + uint32_t type; + uint32_t size; + + uint16_t vbe_mode; + uint16_t vbe_interface_seg; + uint16_t vbe_interface_off; + uint16_t vbe_interface_len; + + struct mb2_vbe_info_block vbe_control_info; + struct mb2_vbe_mode_info_block vbe_mode_info; +}; + +struct mb2_tag_efi_mmap +{ + uint32_t type; + uint32_t size; + uint32_t descr_size; + uint32_t descr_vers; + uint8_t efi_mmap[0]; +}; + + + +struct mb2_fb_common +{ + uint32_t type; + uint32_t size; + + uint64_t fb_addr; + uint32_t fb_pitch; + uint32_t fb_width; + uint32_t fb_height; + uint8_t fb_bpp; +#define MB2_FB_TYPE_INDEXED 0 +#define MB2_FB_TYPE_RGB 1 +#define MB2_FB_TYPE_EGA_TEXT 2 + uint8_t fb_type; + uint16_t reserved; +}; + +struct mb2_color +{ + uint8_t red; + uint8_t green; + uint8_t blue; +}; + +struct mb2_fb +{ + struct mb2_fb_common common; + + union + { + struct + { + uint16_t fb_palette_num_colors; + struct mb2_color fb_palette[0]; + }; + struct + { + uint8_t fb_red_field_position; + uint8_t fb_red_mask_size; + uint8_t fb_green_field_position; + uint8_t fb_green_mask_size; + uint8_t fb_blue_field_position; + uint8_t fb_blue_mask_size; + }; + }; +}; + +/* MB1 */ +typedef struct { + uint32_t tabsize; + uint32_t strsize; + uint32_t addr; + uint32_t reserved; +} aout_t; /* a.out kernel image */ + +typedef struct { + uint32_t num; + uint32_t size; + uint32_t addr; + uint32_t shndx; +} elf_t; /* elf kernel */ + +typedef struct { + uint8_t bios_driver; + uint8_t top_level_partition; + uint8_t sub_partition; + uint8_t third_partition; +} boot_device_t; + +typedef struct { + uint32_t flags; + + /* valid if flags[0] (MBI_MEMLIMITS) set */ + uint32_t mem_lower; + uint32_t mem_upper; + + /* valid if flags[1] set */ + boot_device_t boot_device; + + /* valid if flags[2] (MBI_CMDLINE) set */ + uint32_t cmdline; + + /* valid if flags[3] (MBI_MODS) set */ + uint32_t mods_count; + uint32_t mods_addr; + + /* valid if flags[4] or flags[5] set */ + union { + aout_t aout_image; + elf_t elf_image; + } syms; + + /* valid if flags[6] (MBI_MEMMAP) set */ + uint32_t mmap_length; + uint32_t mmap_addr; + + /* valid if flags[7] set */ + uint32_t drives_length; + uint32_t drives_addr; + + /* valid if flags[8] set */ + uint32_t config_table; + + /* valid if flags[9] set */ + uint32_t boot_loader_name; + + /* valid if flags[10] set */ + uint32_t apm_table; + + /* valid if flags[11] set */ + uint32_t vbe_control_info; + uint32_t vbe_mode_info; + uint16_t vbe_mode; + uint16_t vbe_interface_seg; + uint16_t vbe_interface_off; + uint16_t vbe_interface_len; +} multiboot_info_t; + +typedef struct { + uint32_t mod_start; + uint32_t mod_end; + uint32_t string; + uint32_t reserved; +} module_t; + +typedef struct { + uint32_t size; + uint32_t base_addr_low; + uint32_t base_addr_high; + uint32_t length_low; + uint32_t length_high; + uint32_t type; +} memory_map_t; + + +#endif /* __ASSEMBLY__ */ + +#endif /* __MULTIBOOT_H__ */ + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/pci.h b/trenchboot/skboot/include/pci.h new file mode 100644 index 0000000..445aa2f --- /dev/null +++ b/trenchboot/skboot/include/pci.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1997, Stefan Esser + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD: src/sys/i386/include/pci_cfgreg.h,v 1.15.2.1.4.1 2010/06/14 02:09:06 kensmith Exp $ + * $FreeBSD: src/sys/dev/pci/pcireg.h,v 1.72.2.4.2.1 2010/06/14 02:09:06 kensmith Exp $ + */ +/* + * Portions copyright (c) 2010, Intel Corporation + */ + +#ifndef __PCI_CFGREG_H__ +#define __PCI_CFGREG_H__ + +#define PCI_BUSMAX 255 /* highest supported bus number */ +#define PCI_SLOTMAX 31 /* highest supported slot number */ +#define PCI_FUNCMAX 7 /* highest supported function number */ +#define PCI_REGMAX 255 /* highest supported config register addr. */ + +#define CONF1_ADDR_PORT 0x0cf8 +#define CONF1_DATA_PORT 0x0cfc + +#define CONF1_ENABLE 0x80000000ul +#define CONF1_ENABLE_CHK 0x80000000ul +#define CONF1_ENABLE_MSK 0x7f000000ul +#define CONF1_ENABLE_CHK1 0xff000001ul +#define CONF1_ENABLE_MSK1 0x80000001ul +#define CONF1_ENABLE_RES1 0x80000000ul + +#define CONF2_ENABLE_PORT 0x0cf8 +#define CONF2_FORWARD_PORT 0x0cfa + +#define CONF2_ENABLE_CHK 0x0e +#define CONF2_ENABLE_RES 0x0e + +#define PCIR_COMMAND 0x04 +#define PCIR_BARS 0x10 +#define PCIR_IOBASEL_1 0x1c + +void pcireg_cfgwrite(int bus, int slot, int func, int reg, int data, int bytes); + +#endif /* __PCI_CFGREG_H__ */ +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/printk.h b/trenchboot/skboot/include/printk.h new file mode 100644 index 0000000..637e40a --- /dev/null +++ b/trenchboot/skboot/include/printk.h @@ -0,0 +1,67 @@ +/* + * printk.h: printk to serial for very early boot stages + * + * Copyright (c) 2006-2010, Intel Corporation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __PRINTK_H__ +#define __PRINTK_H__ + +#include +#include + +#define SKBOOT_LOG_LEVEL_NONE 0x00 +#define SKBOOT_LOG_LEVEL_ERR 0x01 +#define SKBOOT_LOG_LEVEL_WARN 0x02 +#define SKBOOT_LOG_LEVEL_INFO 0x04 +#define SKBOOT_LOG_LEVEL_DETA 0x08 +#define SKBOOT_LOG_LEVEL_ALL 0xFF + +#define SKBOOT_LOG_TARGET_NONE 0x00 +#define SKBOOT_LOG_TARGET_VGA 0x01 +#define SKBOOT_LOG_TARGET_SERIAL 0x02 +#define SKBOOT_LOG_TARGET_MEMORY 0x04 + +extern uint8_t g_log_level; +extern uint8_t g_log_targets; +extern uint8_t g_vga_delay; +extern serial_port_t g_com_port; + +#define serial_init() comc_init() +#define serial_write(s, n) comc_puts(s, n) + +#define vga_write(s,n) vga_puts(s, n) + +extern void printk_init(void); +extern void printk(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +#endif diff --git a/trenchboot/skboot/include/processor.h b/trenchboot/skboot/include/processor.h new file mode 100644 index 0000000..3b01a22 --- /dev/null +++ b/trenchboot/skboot/include/processor.h @@ -0,0 +1,347 @@ +/* Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/* + * Portions copyright (c) 2010, Intel Corporation + */ + +#ifndef __PROCESSOR_H__ +#define __PROCESSOR_H__ + +/* from: @(#)specialreg.h 7.1 (Berkeley) 5/9/91 + * $FreeBSD: stable/8/sys/i386/include/specialreg.h 198989 2009-11-06 15:24:48Z attilio $ + */ + +/* + * EFLAGS bits + */ +#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */ +#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */ +#define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */ +#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */ +#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */ +#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */ +#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */ +#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */ +#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */ +#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */ +#define X86_EFLAGS_NT 0x00004000 /* Nested Task */ +#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */ +#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */ +#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */ +#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */ +#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ +#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ + +/* + * Bits in 386 special registers: + */ +#define CR0_PE 0x00000001 /* Protected mode Enable */ +#define CR0_MP 0x00000002 /* "Math" (fpu) Present */ +#define CR0_EM 0x00000004 /* EMulate FPU instructions. (trap ESC only) */ +#define CR0_TS 0x00000008 /* Task Switched (if MP, trap ESC and WAIT) */ +#define CR0_PG 0x80000000 /* PaGing enable */ + +/* + * Bits in 486 special registers: + */ +#define CR0_NE 0x00000020 /* Numeric Error enable (EX16 vs IRQ13) */ +#define CR0_WP 0x00010000 /* Write Protect (honor page protect in all modes) */ +#define CR0_AM 0x00040000 /* Alignment Mask (set to enable AC flag) */ +#define CR0_NW 0x20000000 /* Not Write-through */ +#define CR0_CD 0x40000000 /* Cache Disable */ + +/* + * Bits in PPro special registers + */ +#define CR4_VME 0x00000001 /* Virtual 8086 mode extensions */ +#define CR4_PVI 0x00000002 /* Protected-mode virtual interrupts */ +#define CR4_TSD 0x00000004 /* Time stamp disable */ +#define CR4_DE 0x00000008 /* Debugging extensions */ +#define CR4_PSE 0x00000010 /* Page size extensions */ +#define CR4_PAE 0x00000020 /* Physical address extension */ +#define CR4_MCE 0x00000040 /* Machine check enable */ +#define CR4_PGE 0x00000080 /* Page global enable */ +#define CR4_PCE 0x00000100 /* Performance monitoring counter enable */ +#define CR4_FXSR 0x00000200/* Fast FPU save/restore used by OS */ +#define CR4_XMM 0x00000400 /* enable SIMD/MMX2 to use except 16 */ +#define CR4_VMXE 0x00002000/* enable VMX */ +#define CR4_SMXE 0x00004000/* enable SMX */ +#define CR4_PCIDE 0x00020000/* enable PCID */ + +#define LAPIC_ICR_LO 0xFEE00300 +#define ICR_MODE_INIT (5<<8) +#define ICR_DELIVER_EXCL_SELF (3<<18) + +/* From http://fxr.watson.org/fxr/source/i386/include/param.h */ +#define PAGE_SHIFT 12 /* LOG2(PAGE_SIZE) */ +#define PAGE_SIZE (1 << PAGE_SHIFT) /* bytes/page */ +/* PAGE_MASK is used to pass bits 12 and above. */ +#define PAGE_MASK (~(PAGE_SIZE-1)) + +/* This is used to address the L2's 4MB pages */ +/* From figure 4-3 of IA64/IA32 Arch SDM vol 3A */ +#define FOURMB_PAGE_SHIFT 22 + +/* macros to rounds things up/down to a page */ +#define PAGE_UP(p) (((unsigned long)(p) + PAGE_SIZE- 1) & PAGE_MASK) +#define PAGE_DOWN(p) ((unsigned long)(p) & PAGE_MASK) + +#ifndef __ASSEMBLY__ + +/* from: + * $FreeBSD: src/sys/i386/include/cpufunc.h,v 1.158 2010/01/01 20:55:11 obrien Exp $ + */ + +static inline void do_cpuid(unsigned int ax, uint32_t *p) +{ + __asm__ __volatile__ ("cpuid" + : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) + : "0" (ax)); +} + +static inline void do_cpuid1(unsigned int ax, unsigned int cx, uint32_t *p) +{ + __asm__ __volatile__ ("cpuid" + : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) + : "0" (ax), "c" (cx)); +} + +static always_inline uint32_t cpuid_eax(unsigned int op) +{ + /* eax: regs[0], ebx: regs[1], ecx: regs[2], edx: regs[3] */ + uint32_t regs[4]; + + do_cpuid(op, regs); + + return regs[0]; +} + +static always_inline uint32_t cpuid_ebx(unsigned int op) +{ + /* eax: regs[0], ebx: regs[1], ecx: regs[2], edx: regs[3] */ + uint32_t regs[4]; + + do_cpuid(op, regs); + + return regs[1]; +} + +static always_inline uint32_t cpuid_ebx1(unsigned int op1, unsigned int op2) +{ + /* eax: regs[0], ebx: regs[1], ecx: regs[2], edx: regs[3] */ + uint32_t regs[4]; + + do_cpuid1(op1, op2, regs); + + return regs[1]; +} +static always_inline uint32_t cpuid_ecx(unsigned int op) +{ + /* eax: regs[0], ebx: regs[1], ecx: regs[2], edx: regs[3] */ + uint32_t regs[4]; + + do_cpuid(op, regs); + + return regs[2]; +} +static always_inline uint32_t cpuid_edx(unsigned int op) +{ + /* eax: regs[0], ebx: regs[1], ecx: regs[2], edx: regs[3] */ + uint32_t regs[4]; + + do_cpuid(op, regs); + + return regs[3]; +} + +#define CPUID_X86_FEATURE_XMM3 (1<<0) +#define CPUID_X86_FEATURE_VMX (1<<5) +#define CPUID_X86_FEATURE_SMX (1<<6) + +#define CPUID_X86_FEATURE_SKINIT (1<<12) + +static inline unsigned long read_cr0(void) +{ + unsigned long data; + __asm__ __volatile__ ("movl %%cr0,%0" : "=r" (data)); + return (data); +} +static inline void write_ecx(unsigned long data) +{ + __asm__ __volatile__("movl %0,%%ecx" : : "r" (data)); +} +static inline unsigned long read_ecx(void) +{ + unsigned long data; + __asm__ __volatile__ ("movl %%ecx,%0" : "=r" (data)); + return (data); +} +static inline void write_cr0(unsigned long data) +{ + __asm__ __volatile__("movl %0,%%cr0" : : "r" (data)); +} + +static inline unsigned long read_cr4(void) +{ + unsigned long data; + __asm__ __volatile__ ("movl %%cr4,%0" : "=r" (data)); + return (data); +} +static inline void write_cr4(unsigned long data) +{ + __asm__ __volatile__ ("movl %0,%%cr4" : : "r" (data)); +} + +static inline unsigned long read_cr3(void) +{ + unsigned long data; + __asm__ __volatile__ ("movl %%cr3,%0" : "=r" (data)); + return (data); +} +static inline void write_cr3(unsigned long data) +{ + __asm__ __volatile__("movl %0,%%cr3" : : "r" (data) : "memory"); +} + + +static inline uint32_t read_eflags(void) +{ + uint32_t ef; + __asm__ __volatile__ ("pushfl; popl %0" : "=r" (ef)); + return (ef); +} +static inline void write_eflags(uint32_t ef) +{ + __asm__ __volatile__ ("pushl %0; popfl" : : "r" (ef)); +} + + +static inline void disable_intr(void) +{ + __asm__ __volatile__ ("cli" : : : "memory"); +} +static inline void enable_intr(void) +{ + __asm__ __volatile__ ("sti"); +} + + +/* was ia32_pause() */ +static inline void cpu_relax(void) +{ + __asm__ __volatile__ ("pause"); +} + + +static inline void halt(void) +{ + __asm__ __volatile__ ("hlt"); +} + + +static inline unsigned int get_apicid(void) +{ + return cpuid_edx(0xb); +} + + +static inline uint64_t rdtsc(void) +{ + uint64_t rv; + + __asm__ __volatile__ ("rdtsc" : "=A" (rv)); + return (rv); +} + +static inline void wbinvd(void) +{ + __asm__ __volatile__ ("wbinvd"); +} + +static inline uint32_t bsrl(uint32_t mask) +{ + uint32_t result; + + __asm__ __volatile__ ("bsrl %1,%0" : "=r" (result) : "rm" (mask) : "cc"); + return (result); +} + +static inline int fls(int mask) +{ + return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1); +} + +static always_inline void mb(void) +{ + __asm__ __volatile__ ("lock;addl $0,0(%%esp)" : : : "memory"); +} + +static inline void cpu_monitor(const void *addr, int extensions, int hints) +{ + __asm __volatile__ ("monitor;" : :"a" (addr), "c" (extensions), "d"(hints)); +} + +static inline void cpu_mwait(int extensions, int hints) +{ + __asm __volatile__ ("mwait;" : :"a" (hints), "c" (extensions)); +} + +#define MSR_APICBASE 0x01b +#define MSR_MCG_CAP 0x179 +#define MSR_MCG_STATUS 0x17a +#define MSR_MC0_STATUS 0x401 + +#define APICBASE_BSP 0x00000100 + +static inline uint64_t rdmsr(uint32_t msr) +{ + uint64_t rv; + + __asm__ __volatile__ ("rdmsr" : "=A" (rv) : "c" (msr)); + return (rv); +} + +static inline void wrmsr(uint32_t msr, uint64_t newval) +{ + __asm__ __volatile__ ("wrmsr" : : "A" (newval), "c" (msr)); +} + +#endif /* __ASSEMBLY__ */ + +#endif /* __PROCESSOR_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/skboot.h b/trenchboot/skboot/include/skboot.h new file mode 100644 index 0000000..0be7204 --- /dev/null +++ b/trenchboot/skboot/include/skboot.h @@ -0,0 +1,154 @@ +/* + * slboot.h: main header definition file + * + * Used to be: + * skboot.h: shared data structure with MLE and kernel and functions + * used by kernel for runtime support + * + * Copyright (c) 2006-2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __SKBOOT_H__ +#define __SKBOOT_H__ + +#define SK_ERR_NONE 0 +#define SK_ERR_FATAL 1 +#define SK_ERR_NO_SKINIT 2 +#define SK_ERR_TPM_NOT_READY 3 + +#ifndef __packed +#define __packed __attribute__ ((packed)) +#endif + +#define inline __inline__ +#define always_inline __inline__ __attribute__ ((always_inline)) + +#define readb(va) (*(volatile uint8_t *) (va)) +#define readw(va) (*(volatile uint16_t *) (va)) + +#define writeb(va, d) (*(volatile uint8_t *) (va) = (d)) +#define writew(va, d) (*(volatile uint16_t *) (va) = (d)) + +static inline uint8_t inb(uint16_t port) +{ + uint8_t data; + + __asm volatile("inb %w1, %0" : "=a" (data) : "Nd" (port)); + return (data); +} + +static inline void outb(uint16_t port, uint8_t data) +{ + __asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port)); +} + +static inline void outw(uint16_t port, uint16_t data) +{ + __asm volatile("outw %0, %w1" : : "a" (data), "Nd" (port)); +} + +static inline void outl(uint16_t port, uint32_t data) +{ + __asm volatile("outl %0, %w1" : : "a" (data), "Nd" (port)); +} + +typedef struct __packed { + uint32_t data1; + uint16_t data2; + uint16_t data3; + uint16_t data4; + uint8_t data5[6]; +} uuid_t; + +#define HASH_ALG_SHA1_LG 0x0000 /* legacy define for SHA1 */ +#define HASH_ALG_SHA1 0x0004 +#define HASH_ALG_SHA256 0x000B +#define HASH_ALG_SM3 0x0012 +#define HASH_ALG_SHA384 0x000C +#define HASH_ALG_SHA512 0x000D +#define HASH_ALG_NULL 0x0010 + +#define SHA1_LENGTH 20 +#define SHA256_LENGTH 32 +#define SM3_LENGTH 32 +#define SHA384_LENGTH 48 +#define SHA512_LENGTH 64 + +typedef union { + uint8_t sha1[SHA1_LENGTH]; + uint8_t sha256[SHA256_LENGTH]; + uint8_t sm3[SM3_LENGTH]; + uint8_t sha384[SHA384_LENGTH]; + uint8_t sha512[SHA512_LENGTH]; +} sk_hash_t; + +extern int sha1_buffer(const unsigned char *buffer, size_t len, + unsigned char md[20]); + +extern void sha256_buffer(const unsigned char *buffer, size_t len, + unsigned char hash[32]); + +#define SK_SHUTDOWN_REBOOT 0 +#define SK_SHUTDOWN_SHUTDOWN 1 +#define SK_SHUTDOWN_HALT 2 + +/* + * used to log skboot printk output + */ +#define ZIP_COUNT_MAX 10 +typedef struct { + uuid_t uuid; + uint16_t max_size; + uint16_t curr_pos; + uint16_t zip_pos[ZIP_COUNT_MAX]; + uint16_t zip_size[ZIP_COUNT_MAX]; + uint8_t zip_count; + char buf[]; +} skboot_log_t; + +/* {C0192526-6B30-4db4-844C-A3E953B88174} */ +#define SKBOOT_LOG_UUID {0xc0192526, 0x6b30, 0x4db4, 0x844c, \ + {0xa3, 0xe9, 0x53, 0xb8, 0x81, 0x74 }} + +#define SLAUNCH_LZ_UUID {0x78f1268e, 0x0492, 0x11e9, 0x832a, \ + {0xc8, 0x5b, 0x76, 0xc4, 0xcc, 0x03 }} + +#endif /* __SKBOOT_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/skl.h b/trenchboot/skboot/include/skl.h new file mode 100644 index 0000000..659c871 --- /dev/null +++ b/trenchboot/skboot/include/skl.h @@ -0,0 +1,93 @@ +#ifndef _SKL_H +#define _SKL_H + +#define SKL_VERSION 0 + +/* Setup data structs defined in Linux */ +typedef struct __packed { + uint64_t next; + uint32_t type; + uint32_t len; + /* data[] */ +} setup_data_t; + +typedef struct __packed { + uint32_t type; + uint32_t reserved; + uint64_t len; + uint64_t addr; +} setup_indirect_t; + +/* The SL bloc header, first two fields defined by spec */ +typedef struct __packed { + uint16_t skl_entry_point; + uint16_t bootloader_data_offset; + uint16_t skl_info_offset; +} sl_header_t; + +typedef struct __packed { + uint8_t uuid[16]; /* 78 f1 26 8e 04 92 11 e9 83 2a c8 5b 76 c4 cc 02 */ + uint32_t version; + uint16_t msb_key_algo; + uint8_t msb_key_hash[64]; /* Support up to SHA512 */ +} lz_info_t; + +#define SKL_TAG_CLASS_MASK 0xF0 + +/* Tags with no particular class */ +#define SKL_TAG_NO_CLAS 0x00 +#define SKL_TAG_END 0x00 +#define SKL_TAG_SETUP_INDIRECT 0x01 +#define SKL_TAG_TAGS_SIZE 0x0F /* Always first */ + +/* Tags specifying kernel type */ +#define SKL_TAG_BOOT_CLASS 0x10 +#define SKL_TAG_BOOT_LINUX 0x10 +#define SKL_TAG_BOOT_MB2 0x11 + +/* Tags specific to TPM event log */ +#define SKL_TAG_EVENT_LOG_CLASS 0x20 +#define SKL_TAG_EVENT_LOG 0x20 +#define SKL_TAG_SKL_HASH 0x21 + +typedef struct __packed { + uint8_t type; + uint8_t len; +} skl_tag_hdr_t; + +typedef struct __packed { + skl_tag_hdr_t hdr; + uint16_t size; +} skl_tag_tags_size_t; + +typedef struct __packed { + skl_tag_hdr_t hdr; + uint32_t zero_page; +} skl_tag_boot_linux_t; + +typedef struct __packed { + skl_tag_hdr_t hdr; + uint32_t address; + uint32_t size; +} skl_tag_evtlog_t; + +typedef struct __packed { + skl_tag_hdr_t hdr; + uint16_t algo_id; + /* digest[] */ +} skl_tag_hash_t; + +typedef struct __packed { + skl_tag_hdr_t hdr; + /* type = SETUP_INDIRECT */ + setup_data_t data; + /* type = SETUP_INDIRECT | SETUP_SECURE_LAUNCH */ + setup_indirect_t indirect; +} skl_tag_setup_indirect_t; + +extern sl_header_t *g_skl_module; +extern uint32_t g_skl_size; + +extern bool is_skl_module(const void *skl_base, uint32_t skl_size); + +#endif /* _SKL_H */ diff --git a/trenchboot/skboot/include/string.h b/trenchboot/skboot/include/string.h new file mode 100644 index 0000000..43f342f --- /dev/null +++ b/trenchboot/skboot/include/string.h @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)libkern.h 8.1 (Berkeley) 6/10/93 + * $FreeBSD: src/sys/sys/libkern.h,v 1.60 2009/02/14 11:34:57 rrs Exp $ + */ +/* + * Portions copyright (c) 2010-2018, Intel Corporation + */ + +#ifndef __STRING_H__ +#define __STRING_H__ + +#include +#include + +int sk_memcmp(const void *b1, const void *b2, size_t len); +char *sk_index(const char *, int); +int sk_strcmp(const char *, const char *); +size_t sk_strlen(const char *); +int sk_strncmp(const char *, const char *, size_t); +char *sk_strncpy(char * __restrict, const char * __restrict, size_t); +void *sk_memcpy(void *dst, const void *src, size_t len); +int sk_snprintf(char *buf, size_t size, const char *fmt, ...); +int sk_vscnprintf(char *buf, size_t size, const char *fmt, va_list ap); +unsigned long sk_strtoul(const char *nptr, char **endptr, int base); + +static inline void *sk_memset(void *b, int c, size_t len) +{ + char *bb; + + for (bb = (char *)b; len--; ) + *bb++ = c; + + return (b); +} + +static inline void *sk_memmove(void *dest, const void *src, size_t n) +{ + return sk_memcpy(dest, src, n); +} + +static __inline char *sk_strchr(const char *p, int ch) +{ + return sk_index(p, ch); +} + +#endif /* __STRING_H__ */ diff --git a/trenchboot/skboot/include/tpm.h b/trenchboot/skboot/include/tpm.h new file mode 100644 index 0000000..56f69c6 --- /dev/null +++ b/trenchboot/skboot/include/tpm.h @@ -0,0 +1,543 @@ +/* + * tpm.h: TPM-related support functions + * + * Copyright (c) 2006-2009, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __TPM_H__ +#define __TPM_H__ + +#include + +/* un-comment to enable detailed command tracing */ +//#define TPM_TRACE + +#define TPM_IF_12 0 +#define TPM_IF_20_FIFO 1 +#define TPM_IF_20_CRB 2 + +#define TPM_VER_UNKNOWN 0 +#define TPM_VER_12 1 +#define TPM_VER_20 2 + +#define TPM_INTERFACE_ID_FIFO_20 0x0 +#define TPM_INTERFACE_ID_CRB 0x1 +#define TPM_INTERFACE_ID_FIFO_13 0xF + +#define TPM_LOCALITY_BASE 0xfed40000 +#define TPM_LOCALITY_0 TPM_LOCALITY_BASE +#define TPM_LOCALITY_1 (TPM_LOCALITY_BASE | 0x1000) +#define TPM_LOCALITY_2 (TPM_LOCALITY_BASE | 0x2000) +#define TPM_LOCALITY_3 (TPM_LOCALITY_BASE | 0x3000) +#define TPM_LOCALITY_4 (TPM_LOCALITY_BASE | 0x4000) +#define TPM_LOCALITY_BASE_N(n) (TPM_LOCALITY_BASE | ((n) << 12)) +#define TPM_NR_LOCALITIES 5 +#define NR_TPM_LOCALITY_PAGES ((TPM_LOCALITY_1 - TPM_LOCALITY_0) >> PAGE_SHIFT) + +#define TPM_LOCALITY_CRB_BASE 0xfed40000 +#define TPM_LOCALITY_CRB_0 TPM_LOCALITY_CRB_BASE +#define TPM_LOCALITY_CRB_1 (TPM_LOCALITY_CRB_BASE | 0x1000) +#define TPM_LOCALITY_CRB_2 (TPM_LOCALITY_CRB_BASE | 0x2000) +#define TPM_LOCALITY_CRB_3 (TPM_LOCALITY_CRB_BASE | 0x3000) +#define TPM_LOCALITY_CRB_4 (TPM_LOCALITY_CRB_BASE | 0x4000) +#define TPM_LOCALITY_CRB_BASE_N(n) (TPM_LOCALITY_CRB_BASE | ((n) << 12)) +#define TPM_NR_CRB_LOCALITIES 5 +#define NR_TPM_LOCALITY_CRB_PAGES ((TPM_LOCALITY_CRB_1 - TPM_LOCALITY_CRB_0) >> PAGE_SHIFT) +/* + * Command Header Fields: + * 0 1 2 3 4 5 6 7 8 9 10 ... + * ------------------------------------------------------------- + * | TAG | SIZE | COMMAND CODE | other ... + * ------------------------------------------------------------- + * + * Response Header Fields: + * 0 1 2 3 4 5 6 7 8 9 10 ... + * ------------------------------------------------------------- + * | TAG | SIZE | RETURN CODE | other ... + * ------------------------------------------------------------- + */ +#define CMD_HEAD_SIZE 10 +#define RSP_HEAD_SIZE 10 +#define CMD_SIZE_OFFSET 2 +#define CMD_CC_OFFSET 6 +#define RSP_SIZE_OFFSET 2 +#define RSP_RST_OFFSET 6 + +/* + * The term timeout applies to timings between various states + * or transitions within the interface protocol. + */ +#define TIMEOUT_UNIT (0x100000 / 330) /* ~1ms, 1 tpm r/w need > 330ns */ +#define TIMEOUT_A 750 /* 750ms */ +#define TIMEOUT_B 2000 /* 2s */ +#define TIMEOUT_C 75000 /* 750ms */ +#define TIMEOUT_D 750 /* 750ms */ + +typedef struct __packed { + uint32_t timeout_a; + uint32_t timeout_b; + uint32_t timeout_c; + uint32_t timeout_d; +} tpm_timeout_t; + +/* + * The TCG maintains a registry of all algorithms that have an + * assigned algorithm ID. That registry is the definitive list + * of algorithms that may be supported by a TPM. + */ +#define TPM_ALG_ERROR 0x0000 +#define TPM_ALG_FIRST 0x0001 +#define TPM_ALG_RSA 0x0001 +#define TPM_ALG_DES 0x0002 +#define TPM_ALG__3DES 0x0003 +#define TPM_ALG_SHA 0x0004 +#define TPM_ALG_SHA1 0x0004 +#define TPM_ALG_HMAC 0x0005 +#define TPM_ALG_AES 0x0006 +#define TPM_ALG_MGF1 0x0007 +#define TPM_ALG_KEYEDHASH 0x0008 +#define TPM_ALG_XOR 0x000A +#define TPM_ALG_SHA256 0x000B +#define TPM_ALG_SHA384 0x000C +#define TPM_ALG_SHA512 0x000D +#define TPM_ALG_WHIRLPOOL512 0x000E +#define TPM_ALG_NULL 0x0010 +#define TPM_ALG_SM3_256 0x0012 +#define TPM_ALG_SM4 0x0013 +#define TPM_ALG_RSASSA 0x0014 +#define TPM_ALG_RSAES 0x0015 +#define TPM_ALG_RSAPSS 0x0016 +#define TPM_ALG_OAEP 0x0017 +#define TPM_ALG_ECDSA 0x0018 +#define TPM_ALG_ECDH 0x0019 +#define TPM_ALG_ECDAA 0x001A +#define TPM_ALG_SM2 0x001B +#define TPM_ALG_ECSCHNORR 0x001C +#define TPM_ALG_KDF1_SP800_56a 0x0020 +#define TPM_ALG_KDF2 0x0021 +#define TPM_ALG_KDF1_SP800_108 0x0022 +#define TPM_ALG_ECC 0x0023 +#define TPM_ALG_SYMCIPHER 0x0025 +#define TPM_ALG_CTR 0x0040 +#define TPM_ALG_OFB 0x0041 +#define TPM_ALG_CBC 0x0042 +#define TPM_ALG_CFB 0x0043 +#define TPM_ALG_ECB 0x0044 +#define TPM_ALG_LAST 0x0044 +#define TPM_ALG_MAX_NUM (TPM_ALG_LAST - TPM_ALG_ERROR) + +#define MAX_ALG_NUM 5 + +typedef struct { + uint16_t alg; + sk_hash_t hash; +} hash_entry_t; + +typedef struct { + uint32_t count; + hash_entry_t entries[MAX_ALG_NUM]; +} hash_list_t; + + +// move from tpm.c + +/* + * TPM registers and data structures + * + * register values are offsets from each locality base + * see {read,write}_tpm_reg() for data struct format + */ + +/* TPM_ACCESS_x */ +#define TPM_REG_ACCESS 0x00 +#define TPM_REG_STS 0x18 + +typedef union { + u8 _raw[1]; /* 1-byte reg */ + struct __packed { + u8 tpm_establishment : 1; /* RO, 0=T/OS has been established + before */ + u8 request_use : 1; /* RW, 1=locality is requesting TPM use */ + u8 pending_request : 1; /* RO, 1=other locality is requesting + TPM usage */ + u8 seize : 1; /* WO, 1=seize locality */ + u8 been_seized : 1; /* RW, 1=locality seized while active */ + u8 active_locality : 1; /* RW, 1=locality is active */ + u8 reserved : 1; + u8 tpm_reg_valid_sts : 1; /* RO, 1=other bits are valid */ + }; +} tpm_reg_access_t; + +/* TPM_STS_x */ + +typedef union { + u8 _raw[3]; /* 3-byte reg */ + struct __packed { + u8 reserved1 : 1; + u8 response_retry : 1; /* WO, 1=re-send response */ + u8 self_test_done : 1; /* RO, only for version 2 */ + u8 expect : 1; /* RO, 1=more data for command expected */ + u8 data_avail : 1; /* RO, 0=no more data for response */ + u8 tpm_go : 1; /* WO, 1=execute sent command */ + u8 command_ready : 1; /* RW, 1=TPM ready to receive new cmd */ + u8 sts_valid : 1; /* RO, 1=data_avail and expect bits are valid */ + u16 burst_count : 16; /* RO, # read/writes bytes before wait */ + }; +} tpm12_reg_sts_t; + +typedef union { + u8 _raw[4]; /* 4-byte reg */ + struct __packed { + u8 reserved1 : 1; + u8 response_retry : 1; /* WO, 1=re-send response */ + u8 self_test_done : 1; /* RO, only for version 2 */ + u8 expect : 1; /* RO, 1=more data for command expected */ + u8 data_avail : 1; /* RO, 0=no more data for response */ + u8 tpm_go : 1; /* WO, 1=execute sent command */ + u8 command_ready : 1; /* RW, 1=TPM ready to receive new cmd */ + u8 sts_valid : 1; /* RO, 1=data_avail and expect bits are + valid */ + u16 burst_count : 16; /* RO, # read/writes bytes before wait */ + /* version >= 2 */ + u8 command_cancel : 1; + u8 reset_establishment : 1; + u8 tpm_family : 2; + u8 reserved2 : 4; + }; +} tpm20_reg_sts_t; + +//----------------------------------------------------------------------------- +// CRB I/F related definitions, see TCG PC Client Platform TPM Profile (PTP) Specification, Level 00 Revision 00.43 +//----------------------------------------------------------------------------- +#define TPM_REG_LOC_STATE 0x00 +#define TPM_REG_LOC_CTRL 0x8 +#define TPM_LOCALITY_STS 0x0C +#define TPM_INTERFACE_ID 0x30 +#define TPM_CONTROL_AREA 0x40 +#define TPM_CRB_CTRL_REQ 0x40 +#define TPM_CRB_CTRL_STS 0x44 +#define TPM_CRB_CTRL_CANCEL 0x48 +#define TPM_CRB_CTRL_START 0x4C +#define TPM_CRB_CTRL_CMD_SIZE 0x58 +#define TPM_CRB_CTRL_CMD_ADDR 0x5C +#define TPM_CRB_CTRL_CMD_HADDR 0x60 +#define TPM_CRB_CTRL_RSP_SIZE 0x64 +#define TPM_CRB_CTRL_RSP_ADDR 0x68 +#define TPM_CRB_DATA_BUFFER 0x80 +#define TPMCRBBUF_LEN 0xF80 //3968 Bytes + +//#define CTRL_AREA_ADDR (uint32_t) (TPM_CRB_BASE + 0x40) +//#define DATA_BUF_ADDR (uint32_t) (TPM_CRB_BASE + 0x80) + +typedef union { + u8 _raw[4]; /* 4-byte reg */ + struct __packed { + u8 tpm_establishment : 1; + u8 loc_assigned : 1; + u8 active_locality : 3; + u8 reserved : 2; + u8 tpm_reg_valid_sts : 1; /* RO, 1=other bits are valid */ + u8 reserved1 :8; + u16 reserved2 :16; + }; +} tpm_reg_loc_state_t; + +typedef union { + uint8_t _raw[4]; + struct __packed { + uint32_t requestAccess:1; + uint32_t relinquish:1; + uint32_t seize:1; + uint32_t resetEstablishment:1; + uint32_t reserved1:28; + }; +} tpm_reg_loc_ctrl_t; + +typedef union { + uint8_t _raw[4]; + struct __packed{ + uint32_t Granted:1; + uint32_t BeenSeized:1; + uint32_t R:30; + }; +} tpm_reg_loc_sts_t; + +typedef union { + uint8_t _raw[8]; // 8-byte reg + struct __packed { + uint64_t interface_type:4; + uint64_t interface_version:4; + uint64_t cap_locality:1; + uint64_t reserverd1:2; + uint64_t cap_data_xfer_size_support:2; + uint64_t cap_tis:1; + uint64_t cap_crb:1; + uint64_t cap_if_res:2; + uint64_t interface_selector:2; + uint64_t intf_sel_lock:1; + uint64_t reserverd2:4; + uint64_t rid:8; + uint64_t vid:16; + uint64_t did:16; + }; +} tpm_crb_interface_id_t; + +typedef union { + uint8_t _raw[4]; + struct __packed{ + uint32_t cmdReady:1; + uint32_t goIdle:1; + uint32_t Reserved:30; + }; + } tpm_reg_ctrl_request_t; + +typedef union { + uint8_t _raw[4]; + struct __packed{ + uint32_t tpmsts:1; + uint32_t tpmidle:1; + uint32_t reserved:30; + }; +} tpm_reg_ctrl_sts_t; + +typedef union { + uint8_t _raw[4]; + struct __packed{ + uint32_t start; + }; +} tpm_reg_ctrl_start_t; + +typedef union { + uint8_t _raw[4]; + struct __packed{ + uint32_t cancel; + }; +} tpm_reg_ctrl_cancel_t; + +typedef union { + uint8_t _raw[8]; + struct __packed{ + uint32_t cmdladdr; + uint32_t cmdhaddr; + }; +} tpm_reg_ctrl_cmdaddr_t; + +typedef union { + uint8_t _raw[4]; + struct __packed{ + uint32_t cmdsize; + }; +} tpm_reg_ctrl_cmdsize_t; + +typedef union { + uint8_t _raw[8]; + struct __packed{ + uint64_t rspaddr; + }; +} tpm_reg_ctrl_rspaddr_t; + +typedef union { + uint8_t _raw[4]; + struct __packed{ + uint32_t rspsize; + }; +} tpm_reg_ctrl_rspsize_t; + +typedef union { + uint8_t _raw[48]; + struct __packed { + tpm_reg_ctrl_request_t Request; + tpm_reg_ctrl_sts_t Status; + tpm_reg_ctrl_cancel_t Cancel; + tpm_reg_ctrl_start_t Start; + uint64_t R; + tpm_reg_ctrl_cmdsize_t CmdSize; + tpm_reg_ctrl_cmdaddr_t CmdAddr; + tpm_reg_ctrl_rspsize_t RspSize; + tpm_reg_ctrl_rspaddr_t RspAddr; + }; +} tpm_ctrl_area_t; + +// END OF CRB I/F + +/* + * assumes that all reg types follow above format: + * - packed + * - member named '_raw' which is array whose size is that of data to read + */ +#define read_tpm_reg(locality, reg, pdata) _read_tpm_reg(locality, reg, (pdata)->_raw, sizeof(*(pdata))) + +#define write_tpm_reg(locality, reg, pdata) _write_tpm_reg(locality, reg, (pdata)->_raw, sizeof(*(pdata))) + +static inline void _read_tpm_reg(int locality, u32 reg, u8 *_raw, size_t size) +{ + for ( size_t i = 0; i < size; i++ ) _raw[i] = readb((TPM_LOCALITY_BASE_N(locality) | reg) + i); +} + +static inline void _write_tpm_reg(int locality, u32 reg, u8 *_raw, size_t size) +{ + for ( size_t i = 0; i < size; i++ ) writeb((TPM_LOCALITY_BASE_N(locality) | reg) + i, _raw[i]); +} + + +/* + * the following inline function reversely copy the bytes from 'in' to + * 'out', the byte number to copy is given in count. + */ +#define reverse_copy(out, in, count) _reverse_copy((uint8_t *)(out), (uint8_t *)(in), count) + +static inline void _reverse_copy(uint8_t *out, uint8_t *in, uint32_t count) +{ + for ( uint32_t i = 0; i < count; i++ ) + out[i] = in[count - i - 1]; +} + +/* alg id list supported by skboot */ +extern u16 skboot_alg_list[]; + +typedef sk_hash_t tpm_digest_t; +typedef tpm_digest_t tpm_pcr_value_t; + +struct tpm_if; +struct tpm_if_fp; + +struct tpm_if { +#define TPM12_VER_MAJOR 1 +#define TPM12_VER_MINOR 2 +#define TPM20_VER_MAJOR 2 +#define TPM20_VER_MINOR 0 + u8 major; + u8 minor; + u16 family; + + tpm_timeout_t timeout; + + u32 error; /* last reported error */ + u32 cur_loc; + + u16 banks; + u16 algs_banks[TPM_ALG_MAX_NUM]; + u16 alg_count; + u16 algs[TPM_ALG_MAX_NUM]; + + /* + * Only for version>=2. PCR extend policy. + */ +#define SK_EXTPOL_AGILE 0 +#define SK_EXTPOL_EMBEDDED 1 +#define SK_EXTPOL_FIXED 2 + u8 extpol; + u16 cur_alg; + + /* NV index to be used */ + u32 lcp_own_index; + u32 sk_policy_index; + u32 sk_err_index; + u32 sgx_svn_index; +}; + +struct tpm_if_fp { + + bool (*init)(struct tpm_if *ti); + + bool (*pcr_read)(struct tpm_if *ti, u32 locality, u32 pcr, tpm_pcr_value_t *out); + bool (*pcr_extend)(struct tpm_if *ti, u32 locality, u32 pcr, const hash_list_t *in); + bool (*pcr_reset)(struct tpm_if *ti, u32 locality, u32 pcr); + bool (*hash)(struct tpm_if *ti, u32 locality, const u8 *data, u32 data_size, hash_list_t *hl); + + bool (*nv_read)(struct tpm_if *ti, u32 locality, u32 index, u32 offset, u8 *data, u32 *data_size); + bool (*nv_write)(struct tpm_if *ti, u32 locality, u32 index, u32 offset, const u8 *data, u32 data_size); + bool (*get_nvindex_size)(struct tpm_if *ti, u32 locality, u32 index, u32 *size); + +#define TPM_NV_PER_WRITE_STCLEAR (1<<14) +#define TPM_NV_PER_WRITEDEFINE (1<<13) +#define TPM_NV_PER_WRITEALL (1<<12) +#define TPM_NV_PER_AUTHWRITE (1<<2) +#define TPM_NV_PER_OWNERWRITE (1<<1) +#define TPM_NV_PER_PPWRITE (1<<0) + bool (*get_nvindex_permission)(struct tpm_if *ti, u32 locality, u32 index, u32 *attribute); + + bool (*seal)(struct tpm_if *ti, u32 locality, u32 in_data_size, const u8 *in_data, u32 *sealed_data_size, u8 *sealed_data); + bool (*unseal)(struct tpm_if *ti, u32 locality, u32 sealed_data_size, const u8 *sealed_data, u32 *secret_size, u8 *secret); + + bool (*get_random)(struct tpm_if *ti, u32 locality, u8 *random_data, u32 *data_size); + + uint32_t (*save_state)(struct tpm_if *ti, u32 locality); + + bool (*context_save)(struct tpm_if *ti, u32 locality, u32 handle, void *context_saved); + bool (*context_load)(struct tpm_if *ti, u32 locality, void *context_saved, u32 *handle); + bool (*context_flush)(struct tpm_if *ti, u32 locality, u32 handle); + + bool (*check)(void); +}; + +extern struct tpm_if_data tpm_if_data; +extern const struct tpm_if_fp tpm_12_if_fp; +extern const struct tpm_if_fp tpm_20_if_fp; +extern uint8_t g_tpm_ver; +extern uint8_t g_tpm_family; + +extern bool tpm_validate_locality(uint32_t locality); +extern bool tpm_validate_locality_crb(uint32_t locality); +extern bool release_locality(uint32_t locality); +extern bool prepare_tpm(void); +extern bool tpm_detect(void); +extern void tpm_print(struct tpm_if *ti); +extern bool tpm_submit_cmd(u32 locality, u8 *in, u32 in_size, u8 *out, u32 *out_size); +extern bool tpm_submit_cmd_crb(u32 locality, u8 *in, u32 in_size, u8 *out, u32 *out_size); +extern bool tpm_wait_cmd_ready(uint32_t locality); +extern bool tpm_request_locality_crb(uint32_t locality); +extern bool tpm_relinquish_locality_crb(uint32_t locality); +extern struct tpm_if *get_tpm(void); +extern const struct tpm_if_fp *get_tpm_fp(void); + + +//#define TPM_UNIT_TEST 1 + +#ifdef TPM_UNIT_TEST +void tpm_unit_test(void); +#else +#define tpm_unit_test() +#endif /* TPM_UNIT_TEST */ + + +#endif /* __TPM_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/tpm_20.h b/trenchboot/skboot/include/tpm_20.h new file mode 100644 index 0000000..ed6f372 --- /dev/null +++ b/trenchboot/skboot/include/tpm_20.h @@ -0,0 +1,1565 @@ +/* + * tpm_20.h: TPM2.0-related structure + * + * Copyright (c) 2006-2013, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __TPM20_H__ +#define __TPM20_H__ + +/* + * tpm2.0 structure defined in spec. + */ + +typedef struct { + u16 size; + u8 buffer[1]; +} TPM2B; + +// Table 205 -- SHA1 Hash Values +#define SHA1_DIGEST_SIZE 20 +#define SHA1_BLOCK_SIZE 64 +#define SHA1_DER_SIZE 15 +#define SHA1_DER {0x30,0x21,0x30,0x09,0x06, 0x05,0x2B,0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14} + +// Table 206 -- SHA256 Hash Values +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 +#define SHA256_DER_SIZE 19 +#define SHA256_DER {0x30,0x31,0x30,0x0d,0x06, 0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01, 0x05,0x00,0x04,0x20} + +// Table 207 -- SHA384 Hash Values +#define SHA384_DIGEST_SIZE 48 +#define SHA384_BLOCK_SIZE 128 +#define SHA384_DER_SIZE 19 +#define SHA384_DER {0x30,0x41,0x30,0x0d,0x06, 0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02, 0x05,0x00,0x04,0x30} + + +// Table 208 -- SHA512 Hash Values +#define SHA512_DIGEST_SIZE 64 +#define SHA512_BLOCK_SIZE 128 +#define SHA512_DER_SIZE 19 +#define SHA512_DER {0x30,0x51,0x30,0x0d,0x06, \ + 0x09,0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,\ + 0x05,0x00,0x04,0x40} + +// Table 210 -- SM3_256 Hash Values +#define SM3_256_DIGEST_SIZE 32 +#define SM3_256_BLOCK_SIZE 64 +#define SM3_256_DER_SIZE 18 +#define SM3_256_DER {0x30,0x30,0x30,0x0c,0x06, \ + 0x08,0x2A,0x81,0x1C,0x81,0x45,0x01,0x83,0x11,0x05,\ + 0x00,0x04,0x20} + +// Table 213 -- Logic Values +#define YES 1 +#define NO 0 +#define TRUE 1 +#define FALSE 0 +#define SET 1 +#define CLEAR 0 + +// Table 215 -- Implemented Algorithms +#define ALG_RSA YES // 1 +#define ALG_SHA1 YES // 1 +#define ALG_HMAC YES // 1 +#define ALG_AES YES // 1 +#define ALG_MGF1 YES // 1 +#define ALG_XOR YES // 1 +#define ALG_KEYEDHASH YES // 1 +#define ALG_SHA256 YES // 1 +#define ALG_SHA384 YES // 0 +#define ALG_SHA512 YES // 0 +#define ALG_SM3_256 YES // 1 +#define ALG_SM4 YES // 1 +#define ALG_RSASSA YES // 1 +#define ALG_RSAES YES // 1 +#define ALG_RSAPSS YES // 1 +#define ALG_OAEP YES // 1 +#define ALG_ECC YES // 1 +#define ALG_ECDH YES // 1 +#define ALG_ECDSA YES // 1 +#define ALG_ECDAA YES // 1 +#define ALG_SM2 YES // 1 +#define ALG_ECSCHNORR YES // 1 +#define ALG_SYMCIPHER YES // 1 +#define ALG_KDF1_SP800_56a YES // 1 +#define ALG_KDF2 NO // 0 +#define ALG_KDF1_SP800_108 YES // 1 +#define ALG_CTR YES // 1 +#define ALG_OFB YES // 1 +#define ALG_CBC YES // 1 +#define ALG_CFB YES // 1 +#define ALG_ECB YES // 1 + +#define HASH_COUNT (ALG_SHA1+ALG_SHA256+ALG_SM3_256+ALG_SHA384+ALG_SHA512) + +// Table 217 -- RSA Algorithm Constants +#define RSA_KEY_SIZES_BITS {1024, 2048} // {1024,2048} +#define MAX_RSA_KEY_BITS 2048 +#define MAX_RSA_KEY_BYTES ((MAX_RSA_KEY_BITS + 7) / 8) // 256 + +// Table 218 -- ECC Algorithm Constants +#define ECC_CURVES {TPM_ECC_NIST_P256,TPM_ECC_BN_P256,TPM_ECC_SM2_P256} +#define ECC_KEY_SIZES_BITS {256} +#define MAX_ECC_KEY_BITS 256 +#define MAX_ECC_KEY_BYTES ((MAX_ECC_KEY_BITS + 7) / 8) // 32 + +// Table 219 -- AES Algorithm Constants +#define AES_KEY_SIZES_BITS {128} +#define MAX_AES_KEY_BITS 128 +#define MAX_AES_BLOCK_SIZE_BYTES 16 +#define MAX_AES_KEY_BYTES ((MAX_AES_KEY_BITS + 7) / 8) // 16 + +// Table 221 -- Symmetric Algorithm Constants +#define MAX_SYM_KEY_BITS MAX_AES_KEY_BITS // 128 +#define MAX_SYM_KEY_BYTES MAX_AES_KEY_BYTES // 16 +#define MAX_SYM_BLOCK_SIZE MAX_AES_BLOCK_SIZE_BYTES // 16 + +// Table 222 -- Implementation Values +#define FIELD_UPGRADE_IMPLEMENTED NO // 0 +typedef u16 BSIZE; +#define BUFFER_ALIGNMENT 4 +#define IMPLEMENTATION_PCR 24 +#define PLATFORM_PCR 24 +#define DRTM_PCR 17 +#define NUM_LOCALITIES 5 +#define MAX_HANDLE_NUM 3 +#define MAX_ACTIVE_SESSIONS 64 +typedef u16 CONTEXT_SLOT; +typedef u64 CONTEXT_COUNTER; +#define MAX_LOADED_SESSIONS 3 +#define MAX_SESSION_NUM 3 +#define MAX_LOADED_OBJECTS 3 +#define MIN_EVICT_OBJECTS 2 +#define PCR_SELECT_MIN ((PLATFORM_PCR+7)/8) // 3 +#define PCR_SELECT_MAX ((IMPLEMENTATION_PCR+7)/8) // 3 +#define NUM_POLICY_PCR_GROUP 1 +#define NUM_AUTHVALUE_PCR_GROUP 1 +#define MAX_CONTEXT_SIZE 4000 +#define MAX_DIGEST_BUFFER 1024 +#define MAX_NV_INDEX_SIZE 1024 +#define MAX_CAP_BUFFER 1024 +#define NV_MEMORY_SIZE 16384 +#define NUM_STATIC_PCR 16 +#define MAX_ALG_LIST_SIZE 64 +#define TIMER_PRESCALE 100000 +#define PRIMARY_SEED_SIZE 32 +#define CONTEXT_ENCRYPT_ALG TPM_ALG_AES +#define CONTEXT_ENCRYPT_KEY_BITS MAX_SYM_KEY_BITS // 128 +#define CONTEXT_ENCRYPT_KEY_BYTES ((CONTEXT_ENCRYPT_KEY_BITS+7)/8) +#define CONTEXT_INTEGRITY_HASH_ALG TPM_ALG_SHA256 +#define CONTEXT_INTEGRITY_HASH_SIZE SHA256_DIGEST_SIZE // 32 +#define PROOF_SIZE CONTEXT_INTEGRITY_HASH_SIZE // 32 +#define NV_CLOCK_UPDATE_INTERVAL 12 +#define NUM_POLICY_PCR 1 +#define MAX_COMMAND_SIZE 4096 +#define MAX_RESPONSE_SIZE 4096 +#define ORDERLY_BITS 8 +#define MAX_ORDERLY_COUNT ((1 << ORDERLY_BITS) - 1) // 255 +#define ALG_ID_FIRST TPM_ALG_FIRST +#define ALG_ID_LAST TPM_ALG_LAST +#define MAX_SYM_DATA 128 +#define MAX_HASH_STATE_SIZE 512 +#define MAX_RNG_ENTROPY_SIZE 64 +#define RAM_INDEX_SPACE 512 +#define RSA_DEFAULT_PUBLIC_EXPONENT 0x00010001 +#define ENABLE_PCR_NO_INCREMENT YES // 1 + +// Table 11 -- TPM_CC Constants +typedef u32 TPM_CC; + +#define TPM_CC_FIRST (TPM_CC)(0x0000011F) +#define TPM_CC_PP_FIRST (TPM_CC)(0x0000011F) +#define TPM_CC_NV_UndefineSpaceSpecial (TPM_CC)(0x0000011F) +#define TPM_CC_EvictControl (TPM_CC)(0x00000120) +#define TPM_CC_HierarchyControl (TPM_CC)(0x00000121) +#define TPM_CC_NV_UndefineSpace (TPM_CC)(0x00000122) +#define TPM_CC_ChangeEPS (TPM_CC)(0x00000124) +#define TPM_CC_ChangePPS (TPM_CC)(0x00000125) +#define TPM_CC_Clear (TPM_CC)(0x00000126) +#define TPM_CC_ClearControl (TPM_CC)(0x00000127) +#define TPM_CC_ClockSet (TPM_CC)(0x00000128) +#define TPM_CC_HierarchyChangeAuth (TPM_CC)(0x00000129) +#define TPM_CC_NV_DefineSpace (TPM_CC)(0x0000012A) +#define TPM_CC_PCR_Allocate (TPM_CC)(0x0000012B) +#define TPM_CC_PCR_SetAuthPolicy (TPM_CC)(0x0000012C) +#define TPM_CC_PP_Commands (TPM_CC)(0x0000012D) +#define TPM_CC_SetPrimaryPolicy (TPM_CC)(0x0000012E) +#define TPM_CC_FieldUpgradeStart (TPM_CC)(0x0000012F) +#define TPM_CC_ClockRateAdjust (TPM_CC)(0x00000130) +#define TPM_CC_CreatePrimary (TPM_CC)(0x00000131) +#define TPM_CC_NV_GlobalWriteLock (TPM_CC)(0x00000132) +#define TPM_CC_PP_LAST (TPM_CC)(0x00000132) +#define TPM_CC_GetCommandAuditDigest (TPM_CC)(0x00000133) +#define TPM_CC_NV_Increment (TPM_CC)(0x00000134) +#define TPM_CC_NV_SetBits (TPM_CC)(0x00000135) +#define TPM_CC_NV_Extend (TPM_CC)(0x00000136) +#define TPM_CC_NV_Write (TPM_CC)(0x00000137) +#define TPM_CC_NV_WriteLock (TPM_CC)(0x00000138) +#define TPM_CC_DictionaryAttackLockReset (TPM_CC)(0x00000139) +#define TPM_CC_DictionaryAttackParameters (TPM_CC)(0x0000013A) +#define TPM_CC_NV_ChangeAuth (TPM_CC)(0x0000013B) +#define TPM_CC_PCR_Event (TPM_CC)(0x0000013C) +#define TPM_CC_PCR_Reset (TPM_CC)(0x0000013D) +#define TPM_CC_SequenceComplete (TPM_CC)(0x0000013E) +#define TPM_CC_SetAlgorithmSet (TPM_CC)(0x0000013F) +#define TPM_CC_SetCommandCodeAuditStatus (TPM_CC)(0x00000140) +#define TPM_CC_FieldUpgradeData (TPM_CC)(0x00000141) +#define TPM_CC_IncrementalSelfTest (TPM_CC)(0x00000142) +#define TPM_CC_SelfTest (TPM_CC)(0x00000143) +#define TPM_CC_Startup (TPM_CC)(0x00000144) +#define TPM_CC_Shutdown (TPM_CC)(0x00000145) +#define TPM_CC_StirRandom (TPM_CC)(0x00000146) +#define TPM_CC_ActivateCredential (TPM_CC)(0x00000147) +#define TPM_CC_Certify (TPM_CC)(0x00000148) +#define TPM_CC_PolicyNV (TPM_CC)(0x00000149) +#define TPM_CC_CertifyCreation (TPM_CC)(0x0000014A) +#define TPM_CC_Duplicate (TPM_CC)(0x0000014B) +#define TPM_CC_GetTime (TPM_CC)(0x0000014C) +#define TPM_CC_GetSessionAuditDigest (TPM_CC)(0x0000014D) +#define TPM_CC_NV_Read (TPM_CC)(0x0000014E) +#define TPM_CC_NV_ReadLock (TPM_CC)(0x0000014F) +#define TPM_CC_ObjectChangeAuth (TPM_CC)(0x00000150) +#define TPM_CC_PolicySecret (TPM_CC)(0x00000151) +#define TPM_CC_Rewrap (TPM_CC)(0x00000152) +#define TPM_CC_Create (TPM_CC)(0x00000153) +#define TPM_CC_ECDH_ZGen (TPM_CC)(0x00000154) +#define TPM_CC_HMAC (TPM_CC)(0x00000155) +#define TPM_CC_Import (TPM_CC)(0x00000156) +#define TPM_CC_Load (TPM_CC)(0x00000157) +#define TPM_CC_Quote (TPM_CC)(0x00000158) +#define TPM_CC_RSA_Decrypt (TPM_CC)(0x00000159) +#define TPM_CC_HMAC_Start (TPM_CC)(0x0000015B) +#define TPM_CC_SequenceUpdate (TPM_CC)(0x0000015C) +#define TPM_CC_Sign (TPM_CC)(0x0000015D) +#define TPM_CC_Unseal (TPM_CC)(0x0000015E) +#define TPM_CC_PolicySigned (TPM_CC)(0x00000160) +#define TPM_CC_ContextLoad (TPM_CC)(0x00000161) +#define TPM_CC_ContextSave (TPM_CC)(0x00000162) +#define TPM_CC_ECDH_KeyGen (TPM_CC)(0x00000163) +#define TPM_CC_EncryptDecrypt (TPM_CC)(0x00000164) +#define TPM_CC_FlushContext (TPM_CC)(0x00000165) +#define TPM_CC_LoadExternal (TPM_CC)(0x00000167) +#define TPM_CC_MakeCredential (TPM_CC)(0x00000168) +#define TPM_CC_NV_ReadPublic (TPM_CC)(0x00000169) +#define TPM_CC_PolicyAuthorize (TPM_CC)(0x0000016A) +#define TPM_CC_PolicyAuthValue (TPM_CC)(0x0000016B) +#define TPM_CC_PolicyCommandCode (TPM_CC)(0x0000016C) +#define TPM_CC_PolicyCounterTimer (TPM_CC)(0x0000016D) +#define TPM_CC_PolicyCpHash (TPM_CC)(0x0000016E) +#define TPM_CC_PolicyLocality (TPM_CC)(0x0000016F) +#define TPM_CC_PolicyNameHash (TPM_CC)(0x00000170) +#define TPM_CC_PolicyOR (TPM_CC)(0x00000171) +#define TPM_CC_PolicyTicket (TPM_CC)(0x00000172) +#define TPM_CC_ReadPublic (TPM_CC)(0x00000173) +#define TPM_CC_RSA_Encrypt (TPM_CC)(0x00000174) +#define TPM_CC_StartAuthSession (TPM_CC)(0x00000176) +#define TPM_CC_VerifySignature (TPM_CC)(0x00000177) +#define TPM_CC_ECC_Parameters (TPM_CC)(0x00000178) +#define TPM_CC_FirmwareRead (TPM_CC)(0x00000179) +#define TPM_CC_GetCapability (TPM_CC)(0x0000017A) +#define TPM_CC_GetRandom (TPM_CC)(0x0000017B) +#define TPM_CC_GetTestResult (TPM_CC)(0x0000017C) +#define TPM_CC_Hash (TPM_CC)(0x0000017D) +#define TPM_CC_PCR_Read (TPM_CC)(0x0000017E) +#define TPM_CC_PolicyPCR (TPM_CC)(0x0000017F) +#define TPM_CC_PolicyRestart (TPM_CC)(0x00000180) +#define TPM_CC_ReadClock (TPM_CC)(0x00000181) +#define TPM_CC_PCR_Extend (TPM_CC)(0x00000182) +#define TPM_CC_PCR_SetAuthValue (TPM_CC)(0x00000183) +#define TPM_CC_NV_Certify (TPM_CC)(0x00000184) +#define TPM_CC_EventSequenceComplete (TPM_CC)(0x00000185) +#define TPM_CC_HashSequenceStart (TPM_CC)(0x00000186) +#define TPM_CC_PolicyPhysicalPresence (TPM_CC)(0x00000187) +#define TPM_CC_PolicyDuplicationSelect (TPM_CC)(0x00000188) +#define TPM_CC_PolicyGetDigest (TPM_CC)(0x00000189) +#define TPM_CC_TestParms (TPM_CC)(0x0000018A) +#define TPM_CC_Commit (TPM_CC)(0x0000018B) +#define TPM_CC_PolicyPassword (TPM_CC)(0x0000018C) +#define TPM_CC_SM2_ZGen (TPM_CC)(0x0000018D) +#define TPM_CC_LAST (TPM_CC)(0x0000018D) + +// Table 15 -- TPM_RC Constants +typedef u32 TPM_RCS; // The 'safe' error codes +typedef u32 TPM_RC; + +#define TPM_RC_SUCCESS (TPM_RC)(0x000) +#define TPM_RC_BAD_TAG (TPM_RC)(0x030) +#define RC_VER1 (TPM_RC)(0x100) +#define TPM_RC_INITIALIZE (TPM_RC)(RC_VER1 + 0x000) +#define TPM_RC_FAILURE (TPM_RC)(RC_VER1 + 0x001) +#define TPM_RC_SEQUENCE (TPM_RC)(RC_VER1 + 0x003) +#define TPM_RC_PRIVATE (TPM_RC)(RC_VER1 + 0x00B) +#define TPM_RC_HMAC (TPM_RC)(RC_VER1 + 0x019) +#define TPM_RC_DISABLED (TPM_RC)(RC_VER1 + 0x020) +#define TPM_RC_EXCLUSIVE (TPM_RC)(RC_VER1 + 0x021) +#define TPM_RC_AUTH_TYPE (TPM_RC)(RC_VER1 + 0x024) +#define TPM_RC_AUTH_MISSING (TPM_RC)(RC_VER1 + 0x025) +#define TPM_RC_POLICY (TPM_RC)(RC_VER1 + 0x026) +#define TPM_RC_PCR (TPM_RC)(RC_VER1 + 0x027) +#define TPM_RC_PCR_CHANGED (TPM_RC)(RC_VER1 + 0x028) +#define TPM_RC_UPGRADE (TPM_RC)(RC_VER1 + 0x02D) +#define TPM_RC_TOO_MANY_CONTEXTS (TPM_RC)(RC_VER1 + 0x02E) +#define TPM_RC_AUTH_UNAVAILABLE (TPM_RC)(RC_VER1 + 0x02F) +#define TPM_RC_REBOOT (TPM_RC)(RC_VER1 + 0x030) +#define TPM_RC_UNBALANCED (TPM_RC)(RC_VER1 + 0x031) +#define TPM_RC_COMMAND_SIZE (TPM_RC)(RC_VER1 + 0x042) +#define TPM_RC_COMMAND_CODE (TPM_RC)(RC_VER1 + 0x043) +#define TPM_RC_AUTHSIZE (TPM_RC)(RC_VER1 + 0x044) +#define TPM_RC_AUTH_CONTEXT (TPM_RC)(RC_VER1 + 0x045) +#define TPM_RC_NV_RANGE (TPM_RC)(RC_VER1 + 0x046) +#define TPM_RC_NV_SIZE (TPM_RC)(RC_VER1 + 0x047) +#define TPM_RC_NV_LOCKED (TPM_RC)(RC_VER1 + 0x048) +#define TPM_RC_NV_AUTHORIZATION (TPM_RC)(RC_VER1 + 0x049) +#define TPM_RC_NV_UNINITIALIZED (TPM_RC)(RC_VER1 + 0x04A) +#define TPM_RC_NV_SPACE (TPM_RC)(RC_VER1 + 0x04B) +#define TPM_RC_NV_DEFINED (TPM_RC)(RC_VER1 + 0x04C) +#define TPM_RC_BAD_CONTEXT (TPM_RC)(RC_VER1 + 0x050) +#define TPM_RC_CPHASH (TPM_RC)(RC_VER1 + 0x051) +#define TPM_RC_PARENT (TPM_RC)(RC_VER1 + 0x052) +#define TPM_RC_NEEDS_TEST (TPM_RC)(RC_VER1 + 0x053) +#define TPM_RC_NO_RESULT (TPM_RC)(RC_VER1 + 0x054) +#define TPM_RC_SENSITIVE (TPM_RC)(RC_VER1 + 0x055) +#define RC_MAX_FM0 (TPM_RC)(RC_VER1 + 0x07F) +#define RC_FMT1 (TPM_RC)(0x080) +#define TPM_RC_ASYMMETRIC (TPM_RC)(RC_FMT1 + 0x001) +#define TPM_RCS_ASYMMETRIC (TPM_RCS)(RC_FMT1 + 0x001) +#define TPM_RC_ATTRIBUTES (TPM_RC)(RC_FMT1 + 0x002) +#define TPM_RCS_ATTRIBUTES (TPM_RCS)(RC_FMT1 + 0x002) +#define TPM_RC_HASH (TPM_RC)(RC_FMT1 + 0x003) +#define TPM_RCS_HASH (TPM_RCS)(RC_FMT1 + 0x003) +#define TPM_RC_VALUE (TPM_RC)(RC_FMT1 + 0x004) +#define TPM_RCS_VALUE (TPM_RCS)(RC_FMT1 + 0x004) +#define TPM_RC_HIERARCHY (TPM_RC)(RC_FMT1 + 0x005) +#define TPM_RCS_HIERARCHY (TPM_RCS)(RC_FMT1 + 0x005) +#define TPM_RC_KEY_SIZE (TPM_RC)(RC_FMT1 + 0x007) +#define TPM_RCS_KEY_SIZE (TPM_RCS)(RC_FMT1 + 0x007) +#define TPM_RC_MGF (TPM_RC)(RC_FMT1 + 0x008) +#define TPM_RCS_MGF (TPM_RCS)(RC_FMT1 + 0x008) +#define TPM_RC_MODE (TPM_RC)(RC_FMT1 + 0x009) +#define TPM_RCS_MODE (TPM_RCS)(RC_FMT1 + 0x009) +#define TPM_RC_TYPE (TPM_RC)(RC_FMT1 + 0x00A) +#define TPM_RCS_TYPE (TPM_RCS)(RC_FMT1 + 0x00A) +#define TPM_RC_HANDLE (TPM_RC)(RC_FMT1 + 0x00B) +#define TPM_RCS_HANDLE (TPM_RCS)(RC_FMT1 + 0x00B) +#define TPM_RC_KDF (TPM_RC)(RC_FMT1 + 0x00C) +#define TPM_RCS_KDF (TPM_RCS)(RC_FMT1 + 0x00C) +#define TPM_RC_RANGE (TPM_RC)(RC_FMT1 + 0x00D) +#define TPM_RCS_RANGE (TPM_RCS)(RC_FMT1 + 0x00D) +#define TPM_RC_AUTH_FAIL (TPM_RC)(RC_FMT1 + 0x00E) +#define TPM_RCS_AUTH_FAIL (TPM_RCS)(RC_FMT1 + 0x00E) +#define TPM_RC_NONCE (TPM_RC)(RC_FMT1 + 0x00F) +#define TPM_RCS_NONCE (TPM_RCS)(RC_FMT1 + 0x00F) +#define TPM_RC_PP (TPM_RC)(RC_FMT1 + 0x010) +#define TPM_RCS_PP (TPM_RCS)(RC_FMT1 + 0x010) +#define TPM_RC_SCHEME (TPM_RC)(RC_FMT1 + 0x012) +#define TPM_RCS_SCHEME (TPM_RCS)(RC_FMT1 + 0x012) +#define TPM_RC_SIZE (TPM_RC)(RC_FMT1 + 0x015) +#define TPM_RCS_SIZE (TPM_RCS)(RC_FMT1 + 0x015) +#define TPM_RC_SYMMETRIC (TPM_RC)(RC_FMT1 + 0x016) +#define TPM_RCS_SYMMETRIC (TPM_RCS)(RC_FMT1 + 0x016) +#define TPM_RC_TAG (TPM_RC)(RC_FMT1 + 0x017) +#define TPM_RCS_TAG (TPM_RCS)(RC_FMT1 + 0x017) +#define TPM_RC_SELECTOR (TPM_RC)(RC_FMT1 + 0x018) +#define TPM_RCS_SELECTOR (TPM_RCS)(RC_FMT1 + 0x018) +#define TPM_RC_INSUFFICIENT (TPM_RC)(RC_FMT1 + 0x01A) +#define TPM_RCS_INSUFFICIENT (TPM_RCS)(RC_FMT1 + 0x01A) +#define TPM_RC_SIGNATURE (TPM_RC)(RC_FMT1 + 0x01B) +#define TPM_RCS_SIGNATURE (TPM_RCS)(RC_FMT1 + 0x01B) +#define TPM_RC_KEY (TPM_RC)(RC_FMT1 + 0x01C) +#define TPM_RCS_KEY (TPM_RCS)(RC_FMT1 + 0x01C) +#define TPM_RC_POLICY_FAIL (TPM_RC)(RC_FMT1 + 0x01D) +#define TPM_RCS_POLICY_FAIL (TPM_RCS)(RC_FMT1 + 0x01D) +#define TPM_RC_INTEGRITY (TPM_RC)(RC_FMT1 + 0x01F) +#define TPM_RCS_INTEGRITY (TPM_RCS)(RC_FMT1 + 0x01F) +#define TPM_RC_TICKET (TPM_RC)(RC_FMT1 + 0x020) +#define TPM_RCS_TICKET (TPM_RCS)(RC_FMT1 + 0x020) +#define TPM_RC_RESERVED_BITS (TPM_RC)(RC_FMT1 + 0x021) +#define TPM_RCS_RESERVED_BITS (TPM_RCS)(RC_FMT1 + 0x021) +#define TPM_RC_BAD_AUTH (TPM_RC)(RC_FMT1 + 0x022) +#define TPM_RCS_BAD_AUTH (TPM_RCS)(RC_FMT1 + 0x022) +#define TPM_RC_EXPIRED (TPM_RC)(RC_FMT1 + 0x023) +#define TPM_RCS_EXPIRED (TPM_RCS)(RC_FMT1 + 0x023) +#define TPM_RC_POLICY_CC (TPM_RC)(RC_FMT1 + 0x024 ) +#define TPM_RCS_POLICY_CC (TPM_RCS)(RC_FMT1 + 0x024 ) +#define TPM_RC_BINDING (TPM_RC)(RC_FMT1 + 0x025) +#define TPM_RCS_BINDING (TPM_RCS)(RC_FMT1 + 0x025) +#define TPM_RC_CURVE (TPM_RC)(RC_FMT1 + 0x026) +#define TPM_RCS_CURVE (TPM_RCS)(RC_FMT1 + 0x026) +#define TPM_RC_ECC_POINT (TPM_RC)(RC_FMT1 + 0x027) +#define TPM_RCS_ECC_POINT (TPM_RCS)(RC_FMT1 + 0x027) +#define RC_WARN (TPM_RC)(0x900) +#define TPM_RC_CONTEXT_GAP (TPM_RC)(RC_WARN + 0x001) +#define TPM_RC_OBJECT_MEMORY (TPM_RC)(RC_WARN + 0x002) +#define TPM_RC_SESSION_MEMORY (TPM_RC)(RC_WARN + 0x003) +#define TPM_RC_MEMORY (TPM_RC)(RC_WARN + 0x004) +#define TPM_RC_SESSION_HANDLES (TPM_RC)(RC_WARN + 0x005) +#define TPM_RC_OBJECT_HANDLES (TPM_RC)(RC_WARN + 0x006) +#define TPM_RC_LOCALITY (TPM_RC)(RC_WARN + 0x007) +#define TPM_RC_YIELDED (TPM_RC)(RC_WARN + 0x008) +#define TPM_RC_CANCELLED (TPM_RC)(RC_WARN + 0x009) +#define TPM_RC_TESTING (TPM_RC)(RC_WARN + 0x00A) +#define TPM_RC_REFERENCE_H0 (TPM_RC)(RC_WARN + 0x010) +#define TPM_RC_REFERENCE_H1 (TPM_RC)(RC_WARN + 0x011) +#define TPM_RC_REFERENCE_H2 (TPM_RC)(RC_WARN + 0x012) +#define TPM_RC_REFERENCE_H3 (TPM_RC)(RC_WARN + 0x013) +#define TPM_RC_REFERENCE_H4 (TPM_RC)(RC_WARN + 0x014) +#define TPM_RC_REFERENCE_H5 (TPM_RC)(RC_WARN + 0x015) +#define TPM_RC_REFERENCE_H6 (TPM_RC)(RC_WARN + 0x016) +#define TPM_RC_REFERENCE_S0 (TPM_RC)(RC_WARN + 0x018) +#define TPM_RC_REFERENCE_S1 (TPM_RC)(RC_WARN + 0x019) +#define TPM_RC_REFERENCE_S2 (TPM_RC)(RC_WARN + 0x01A) +#define TPM_RC_REFERENCE_S3 (TPM_RC)(RC_WARN + 0x01B) +#define TPM_RC_REFERENCE_S4 (TPM_RC)(RC_WARN + 0x01C) +#define TPM_RC_REFERENCE_S5 (TPM_RC)(RC_WARN + 0x01D) +#define TPM_RC_REFERENCE_S6 (TPM_RC)(RC_WARN + 0x01E) +#define TPM_RC_NV_RATE (TPM_RC)(RC_WARN + 0x020) +#define TPM_RC_LOCKOUT (TPM_RC)(RC_WARN + 0x021) +#define TPM_RC_RETRY (TPM_RC)(RC_WARN + 0x022) +#define TPM_RC_NV_UNAVAILABLE (TPM_RC)(RC_WARN + 0x023) +#define TPM_RC_NOT_USED (TPM_RC)(RC_WARN + 0x7F) +#define TPM_RC_H (TPM_RC)(0x000) +#define TPM_RC_P (TPM_RC)(0x040) +#define TPM_RC_S (TPM_RC)(0x800) +#define TPM_RC_1 (TPM_RC)(0x100) +#define TPM_RC_2 (TPM_RC)(0x200) +#define TPM_RC_3 (TPM_RC)(0x300) +#define TPM_RC_4 (TPM_RC)(0x400) +#define TPM_RC_5 (TPM_RC)(0x500) +#define TPM_RC_6 (TPM_RC)(0x600) +#define TPM_RC_7 (TPM_RC)(0x700) +#define TPM_RC_8 (TPM_RC)(0x800) +#define TPM_RC_9 (TPM_RC)(0x900) +#define TPM_RC_A (TPM_RC)(0xA00) +#define TPM_RC_B (TPM_RC)(0xB00) +#define TPM_RC_C (TPM_RC)(0xC00) +#define TPM_RC_D (TPM_RC)(0xD00) +#define TPM_RC_E (TPM_RC)(0xE00) +#define TPM_RC_F (TPM_RC)(0xF00) +#define TPM_RC_N_MASK (TPM_RC)(0xF00) + +// Table 18 -- TPM_ST Constants +typedef u16 TPM_ST; + +#define TPM_ST_RSP_COMMAND (TPM_ST)(0x00C4) +#define TPM_ST_NULL (TPM_ST)(0X8000) +#define TPM_ST_NO_SESSIONS (TPM_ST)(0x8001) +#define TPM_ST_SESSIONS (TPM_ST)(0x8002) +#define TPM_ST_ATTEST_NV (TPM_ST)(0x8014) +#define TPM_ST_ATTEST_COMMAND_AUDIT (TPM_ST)(0x8015) +#define TPM_ST_ATTEST_SESSION_AUDIT (TPM_ST)(0x8016) +#define TPM_ST_ATTEST_CERTIFY (TPM_ST)(0x8017) +#define TPM_ST_ATTEST_QUOTE (TPM_ST)(0x8018) +#define TPM_ST_ATTEST_TIME (TPM_ST)(0x8019) +#define TPM_ST_ATTEST_CREATION (TPM_ST)(0x801A) +#define TPM_ST_CREATION (TPM_ST)(0x8021) +#define TPM_ST_VERIFIED (TPM_ST)(0x8022) +#define TPM_ST_AUTH_SECRET (TPM_ST)(0x8023) +#define TPM_ST_HASHCHECK (TPM_ST)(0x8024) +#define TPM_ST_AUTH_SIGNED (TPM_ST)(0x8025) +#define TPM_ST_FU_MANIFEST (TPM_ST)(0x8029) + +// Table 19 -- TPM_SU Constants +typedef u16 TPM_SU; + +#define TPM_SU_CLEAR (TPM_SU)(0x0000) +#define TPM_SU_STATE (TPM_SU)(0x0001) + +// Table 21 -- TPM_CAP Constants +typedef u32 TPM_CAP; + +#define TPM_CAP_FIRST (TPM_CAP)(0x00000000) +#define TPM_CAP_ALGS (TPM_CAP)(0x00000000) +#define TPM_CAP_HANDLES (TPM_CAP)(0x00000001) +#define TPM_CAP_COMMANDS (TPM_CAP)(0x00000002) +#define TPM_CAP_PP_COMMANDS (TPM_CAP)(0x00000003) +#define TPM_CAP_AUDIT_COMMANDS (TPM_CAP)(0x00000004) +#define TPM_CAP_PCRS (TPM_CAP)(0x00000005) +#define TPM_CAP_TPM_PROPERTIES (TPM_CAP)(0x00000006) +#define TPM_CAP_PCR_PROPERTIES (TPM_CAP)(0x00000007) +#define TPM_CAP_ECC_CURVES (TPM_CAP)(0x00000008) +#define TPM_CAP_LAST (TPM_CAP)(0x00000008) +#define TPM_CAP_VENDOR_PROPERTY (TPM_CAP)(0x00000100) + +// Table 25 -- Handles Types +typedef u32 TPM_HANDLE; +typedef u8 TPM_HT; + +#define TPM_HT_PCR (TPM_HT)(0x00) +#define TPM_HT_NV_INDEX (TPM_HT)(0x01) +#define TPM_HT_HMAC_SESSION (TPM_HT)(0x02) +#define TPM_HT_LOADED_SESSION (TPM_HT)(0x02) +#define TPM_HT_POLICY_SESSION (TPM_HT)(0x03) +#define TPM_HT_ACTIVE_SESSION (TPM_HT)(0x03) +#define TPM_HT_PERMANENT (TPM_HT)(0x40) +#define TPM_HT_TRANSIENT (TPM_HT)(0x80) +#define TPM_HT_PERSISTENT (TPM_HT)(0x81) + +// Table 27 -- TPM_RH Constants +typedef u32 TPM_RH; + +#define TPM_RH_FIRST (TPM_RH)(0x40000000) +#define TPM_RH_SRK (TPM_RH)(0x40000000) +#define TPM_RH_OWNER (TPM_RH)(0x40000001) +#define TPM_RH_REVOKE (TPM_RH)(0x40000002) +#define TPM_RH_TRANSPORT (TPM_RH)(0x40000003) +#define TPM_RH_OPERATOR (TPM_RH)(0x40000004) +#define TPM_RH_ADMIN (TPM_RH)(0x40000005) +#define TPM_RH_EK (TPM_RH)(0x40000006) +#define TPM_RH_NULL (TPM_RH)(0x40000007) +#define TPM_RH_UNASSIGNED (TPM_RH)(0x40000008) +#define TPM_RS_PW (TPM_RH)(0x40000009) +#define TPM_RH_LOCKOUT (TPM_RH)(0x4000000A) +#define TPM_RH_ENDORSEMENT (TPM_RH)(0x4000000B) +#define TPM_RH_PLATFORM (TPM_RH)(0x4000000C) +#define TPM_RH_LAST (TPM_RH)(0x4000000C) + +#define RC_ContextSave_saveHandle (TPM_RC_P + TPM_RC_1) +#define RC_ContextLoad_context (TPM_RC_P + TPM_RC_1) +#define RC_FlushContext_flushHandle (TPM_RC_P + TPM_RC_1) + + +// Table 29 -- TPMA_ALGORITHM Bits +typedef struct { + unsigned int asymmetric : 1; + unsigned int symmetric : 1; + unsigned int hash : 1; + unsigned int object : 1; + unsigned int reserved5 : 4; + unsigned int signing : 1; + unsigned int encrypting : 1; + unsigned int method : 1; + unsigned int reserved9 : 21; +} TPMA_ALGORITHM ; + +// Table 30 -- TPMA_OBJECT Bits +typedef struct { + unsigned int reserved1 : 1; + unsigned int fixedTPM : 1; + unsigned int stClear : 1; + unsigned int reserved4 : 1; + unsigned int fixedParent : 1; + unsigned int sensitiveDataOrigin : 1; + unsigned int userWithAuth : 1; + unsigned int adminWithPolicy : 1; + unsigned int reserved9 : 2; + unsigned int noDA : 1; + unsigned int encryptedDuplication : 1; + unsigned int reserved12 : 4; + unsigned int restricted : 1; // Start of 2nd dword + unsigned int decrypt : 1; + unsigned int sign : 1; + unsigned int reserved16 : 13; +} TPMA_OBJECT ; + +// Table 31 -- TPMA_SESSION Bits +typedef struct { + unsigned int continueSession : 1; + unsigned int auditExclusive : 1; + unsigned int auditReset : 1; + unsigned int reserved4 : 2; + unsigned int decrypt : 1; + unsigned int encrypt : 1; + unsigned int audit : 1; +} TPMA_SESSION; + +// Table 32 -- TPMA_LOCALITY Bits +typedef struct { + unsigned int TPM_LOC_ZERO : 1; + unsigned int TPM_LOC_ONE : 1; + unsigned int TPM_LOC_TWO : 1; + unsigned int TPM_LOC_THREE : 1; + unsigned int TPM_LOC_FOUR : 1; + unsigned int reserved6 : 3; +} TPMA_LOCALITY; +// Table 47 Definition of TPMI_DH_CONTEXT Type +typedef TPM_HANDLE TPMI_DH_CONTEXT; +// Table 48 Definition of TPMI_RH_HIERARCHY Type +typedef TPM_HANDLE TPMI_RH_HIERARCHY; + +// Table 66 -- TPMU_HA Union +typedef union { +#ifdef TPM_ALG_SHA1 + u8 sha1[SHA1_DIGEST_SIZE]; +#endif +#ifdef TPM_ALG_SHA256 + u8 sha256[SHA256_DIGEST_SIZE]; +#endif +#ifdef TPM_ALG_SM3_256 + u8 sm3_256[SM3_256_DIGEST_SIZE]; +#endif +#ifdef TPM_ALG_SHA384 + u8 sha384[SHA384_DIGEST_SIZE]; +#endif +#ifdef TPM_ALG_SHA512 + u8 sha512[SHA512_DIGEST_SIZE]; +#endif +} TPMU_HA ; + +// Table 67 -- TPMT_HA Structure +typedef struct { + u16 hash_alg; + TPMU_HA digest; +} TPMT_HA; + +// Table 68 -- TPM2B_DIGEST Structure +typedef struct { + u16 size; + u8 buffer[sizeof(TPMU_HA)]; +} DIGEST_2B; + +typedef union { + DIGEST_2B t; + TPM2B b; +} TPM2B_DIGEST; + +// Table 69 -- TPM2B_DATA Structure +typedef struct { + u16 size; + u8 buffer[sizeof(TPMT_HA)]; +} DATA_2B; + +typedef union { + DATA_2B t; + TPM2B b; +} TPM2B_DATA; + +// Table 70 -- TPM2B_NONCE Types +typedef TPM2B_DIGEST TPM2B_NONCE; + +// Table 71 -- TPM2B_AUTH Types +typedef TPM2B_DIGEST TPM2B_AUTH; + +// Table 73 -- TPM2B_EVENT Structure +typedef struct { + u16 size; + u8 buffer[1024]; +} EVENT_2B; + +typedef union { + EVENT_2B t; + TPM2B b; +} TPM2B_EVENT; + +// Table 74 -- TPM2B_MAX_BUFFER Structure +typedef struct { + u16 size; + u8 buffer[MAX_DIGEST_BUFFER]; +} MAX_BUFFER_2B; + +typedef union { + MAX_BUFFER_2B t; + TPM2B b; +} TPM2B_MAX_BUFFER; + +// Table 75 -- TPM2B_MAX_NV_BUFFER Structure +typedef struct { + u16 size; + u8 buffer[MAX_NV_INDEX_SIZE]; +} MAX_NV_BUFFER_2B; + +typedef union { + MAX_NV_BUFFER_2B t; + TPM2B b; +} TPM2B_MAX_NV_BUFFER; + +// Table 79 -- TPMU_NAME Structure +typedef union { + TPMT_HA digest; + u32 handle; +} TPMU_NAME ; + +// Table 79 -- TPM2B_NAME Structure +typedef struct { + u16 size; + u8 name[sizeof(TPMU_NAME)]; +} NAME_2B; + +typedef union { + NAME_2B t; + TPM2B b; +} TPM2B_NAME; + +// Table 80 -- TPMS_PCR_SELECTION Structure +typedef struct { + u16 hash; + u8 size_of_select; + u8 pcr_select[PCR_SELECT_MAX]; +} TPMS_PCR_SELECTION; + +// Table 84 -- TPMT_TK_CREATION Structure +typedef struct { + u16 tag; + u32 hierarchy; + TPM2B_DIGEST digest; +} TPMT_TK_CREATION; + +// Table 86 -- TPMT_TK_HASHCHECK Structure +typedef struct { + u16 tag; + u32 hierarchy; + TPM2B_DIGEST digest; +} TPMT_TK_HASHCHECK; + +// Table 88 -- TPMS_ALG_PROPERTY Structure +typedef struct { + u16 alg; + TPMA_ALGORITHM alg_pro; +} TPMS_ALG_PROPERTY; + +// Table 95 -- TPML_DIGEST Structure +typedef struct { + u32 count; + TPM2B_DIGEST digests[8]; +} TPML_DIGEST; + +// Table 96 -- TPML_DIGEST_VALUES Structure +typedef struct { + u32 count; + TPMT_HA digests[HASH_COUNT]; +} TPML_DIGEST_VALUES; + +// Table 98 -- TPML_PCR_SELECTION Structure +typedef struct { + u32 count; + TPMS_PCR_SELECTION selections[HASH_COUNT]; +} TPML_PCR_SELECTION; + +#define MAX_CAP_DATA (MAX_CAP_BUFFER-sizeof(u32)-sizeof(u32)) +#define MAX_CAP_ALGS (MAX_CAP_DATA/sizeof(TPMS_ALG_PROPERTY)) +// Table 99 -- TPML_ALG_PROPERTY Structure +typedef struct { + u32 count; + TPMS_ALG_PROPERTY alg_pros[MAX_CAP_ALGS]; +} TPML_ALG_PROPERTY; + +// Table 103 -- TPMU_CAPABILITIES Union +typedef union { + TPML_ALG_PROPERTY algs; +} TPMU_CAPABILITIES; + +// Table 104 -- TPMS_CAPABILITY_DATA Structure +typedef struct { + u32 capability; + TPMU_CAPABILITIES data; +} TPMS_CAPABILITY_DATA; + +// Table 122 -- TPMU_SYM_KEY_BITS Union +typedef union { +#ifdef TPM_ALG_AES + u16 aes; +#endif +#ifdef TPM_ALG_SM4 + u16 sm4; +#endif + u16 sym; +#ifdef TPM_ALG_XOR + u16 xor; +#endif +} TPMU_SYM_KEY_BITS ; + +// Table 122 -- TPMU_SYM_MODE Union +typedef union { +#ifdef TPM_ALG_AES + u16 aes; +#endif +#ifdef TPM_ALG_SM4 + u16 sm4; +#endif + u16 sym; +} TPMU_SYM_MODE ; + +// Table 126 -- TPMT_SYM_DEF_OBJECT Structure +typedef struct { + u16 alg; + TPMU_SYM_KEY_BITS key_bits; + TPMU_SYM_MODE mode; +} TPMT_SYM_DEF_OBJECT; + +// Table 126 -- TPM2B_SYM_KEY Structure +typedef struct { + u16 size; + u8 buffer[MAX_SYM_KEY_BYTES]; +} SYM_KEY_2B; + +typedef union { + SYM_KEY_2B t; + TPM2B b; +} TPM2B_SYM_KEY; + +// Table 129 -- TPM2B_SENSITIVE_DATA Structure +typedef struct { + u16 size; + u8 buffer[MAX_SYM_DATA]; +} SENSITIVE_DATA_2B; + +typedef union { + SENSITIVE_DATA_2B t; + TPM2B b; +} TPM2B_SENSITIVE_DATA; + +// Table 130 -- TPMS_SENSITIVE_CREATE Structure +typedef struct { + TPM2B_AUTH user_auth; + TPM2B_SENSITIVE_DATA data; +} TPMS_SENSITIVE_CREATE; + +// Table 131 -- TPM2B_SENSITIVE_CREATE Structure +typedef struct { + u16 size; + TPMS_SENSITIVE_CREATE sensitive; +} SENSITIVE_CREATE_2B; + +typedef union { + SENSITIVE_CREATE_2B t; + TPM2B b; +} TPM2B_SENSITIVE_CREATE; + +// Table 132 -- TPMS_SCHEME_SIGHASH Structure +typedef struct { + u16 hash_alg; +} TPMS_SCHEME_SIGHASH; + +// Table 134 -- HMAC_SIG_SCHEME Types +typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_HMAC; + +// Table 135 -- TPMS_SCHEME_XOR Structure +typedef struct { + u16 hash_alg; + u16 kdf; +} TPMS_SCHEME_XOR; + +// Table 136 -- TPMU_SCHEME_KEYEDHASH Union +typedef union { +#ifdef TPM_ALG_HMAC + TPMS_SCHEME_HMAC hmac; +#endif +#ifdef TPM_ALG_XOR + TPMS_SCHEME_XOR xor; +#endif + +} TPMU_SCHEME_KEYEDHASH; + +// Table 137 -- TPMT_KEYEDHASH_SCHEME Structure +typedef struct { + u16 scheme; + TPMU_SCHEME_KEYEDHASH details; +} TPMT_KEYEDHASH_SCHEME; + +// Table 138 -- RSA_SIG_SCHEMES Types +typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_RSASSA; +typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_RSAPSS; + +// Table 139 -- ECC_SIG_SCHEMES Types +typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_ECDSA; +typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_SM2; +typedef TPMS_SCHEME_SIGHASH TPMS_SCHEME_ECSCHNORR; + +// Table 140 -- TPMS_SCHEME_ECDAA Structure +typedef struct { + u16 hash_alg; + u16 count; +} TPMS_SCHEME_ECDAA; + +// Table 141 -- TPMU_SIG_SCHEME Union +typedef union { +#ifdef TPM_ALG_RSASSA + TPMS_SCHEME_RSASSA rsassa; +#endif +#ifdef TPM_ALG_RSAPSS + TPMS_SCHEME_RSAPSS rsapss; +#endif +#ifdef TPM_ALG_ECDSA + TPMS_SCHEME_ECDSA ecdsa; +#endif +#ifdef TPM_ALG_SM2 + TPMS_SCHEME_SM2 sm2; +#endif +#ifdef TPM_ALG_ECDAA + TPMS_SCHEME_ECDAA ecdaa; +#endif +#ifdef TPM_ALG_ECSCHNORR + TPMS_SCHEME_ECSCHNORR ec_schnorr; +#endif +#ifdef TPM_ALG_HMAC + TPMS_SCHEME_HMAC hmac; +#endif + TPMS_SCHEME_SIGHASH any; + +} TPMU_SIG_SCHEME ; + +// Table 143 -- TPMS_SCHEME_OAEP Structure +typedef struct { + u16 hash_alg; +} TPMS_SCHEME_OAEP; + +// Table 145 -- TPMS_SCHEME_MGF1 Structure +typedef struct { + u16 hash_alg; +} TPMS_SCHEME_MGF1; + +// Table 146 -- TPMS_SCHEME_KDF1_SP800_56a Structure +typedef struct { + u16 hash_alg; +} TPMS_SCHEME_KDF1_SP800_56a; + +// Table 147 -- TPMS_SCHEME_KDF2 Structure +typedef struct { + u16 hash_alg; +} TPMS_SCHEME_KDF2; + +// Table 148 -- TPMS_SCHEME_KDF1_SP800_108 Structure +typedef struct { + u16 hash_alg; +} TPMS_SCHEME_KDF1_SP800_108; + +// Table 149 -- TPMU_KDF_SCHEME Union +typedef union { +#ifdef TPM_ALG_MGF1 + TPMS_SCHEME_MGF1 mgf1; +#endif +#ifdef TPM_ALG_KDF1_SP800_56a + TPMS_SCHEME_KDF1_SP800_56a kdf1_SP800_56a; +#endif +#ifdef TPM_ALG_KDF2 + TPMS_SCHEME_KDF2 kdf2; +#endif +#ifdef TPM_ALG_KDF1_SP800_108 + TPMS_SCHEME_KDF1_SP800_108 kdf1_sp800_108; +#endif +} TPMU_KDF_SCHEME ; + +// Table 150 -- TPMT_KDF_SCHEME Structure +typedef struct { + u16 scheme; + TPMU_KDF_SCHEME details; +} TPMT_KDF_SCHEME; + +// Table 152 -- TPMU_ASYM_SCHEME Union +typedef union { +#ifdef TPM_ALG_RSASSA + TPMS_SCHEME_RSASSA rsassa; +#endif +#ifdef TPM_ALG_RSAPSS + TPMS_SCHEME_RSAPSS rsapss; +#endif +#ifdef TPM_ALG_OAEP + TPMS_SCHEME_OAEP oaep; +#endif +#ifdef TPM_ALG_ECDSA + TPMS_SCHEME_ECDSA ecdsa; +#endif +#ifdef TPM_ALG_SM2 + TPMS_SCHEME_SM2 sm2; +#endif +#ifdef TPM_ALG_ECDAA + TPMS_SCHEME_ECDAA ecdaa; +#endif +#ifdef TPM_ALG_ECSCHNORR + TPMS_SCHEME_ECSCHNORR ec_schnorr; +#endif + TPMS_SCHEME_SIGHASH any; + +} TPMU_ASYM_SCHEME; + +// Table 153 -- TPMT_ASYM_SCHEME Structure <> +typedef struct { + u16 scheme; + TPMU_ASYM_SCHEME details; +} TPMT_ASYM_SCHEME; + +// Table 155 -- TPMT_RSA_SCHEME Structure +typedef struct { + u16 scheme; + TPMU_ASYM_SCHEME details; +} TPMT_RSA_SCHEME; + +// Table 158 -- TPM2B_PUBLIC_KEY_RSA Structure +typedef struct { + u16 size; + u8 buffer[MAX_RSA_KEY_BYTES]; +} PUBLIC_KEY_RSA_2B; + +typedef union { + PUBLIC_KEY_RSA_2B t; + TPM2B b; +} TPM2B_PUBLIC_KEY_RSA; + +// Table 160 -- TPM2B_PRIVATE_KEY_RSA Structure +typedef struct { + u16 size; + u8 buffer[MAX_RSA_KEY_BYTES/2]; +} PRIVATE_KEY_RSA_2B; + +typedef union { + PRIVATE_KEY_RSA_2B t; + TPM2B b; +} TPM2B_PRIVATE_KEY_RSA; + +// Table 161 -- TPM2B_ECC_PARAMETER Structure +typedef struct { + u16 size; + u8 buffer[MAX_ECC_KEY_BYTES]; +} ECC_PARAMETER_2B; + +typedef union { + ECC_PARAMETER_2B t; + TPM2B b; +} TPM2B_ECC_PARAMETER; + +// Table 162 -- TPMS_ECC_POINT Structure +typedef struct { + TPM2B_ECC_PARAMETER x; + TPM2B_ECC_PARAMETER y; +} TPMS_ECC_POINT; + +// Table 166 -- TPMT_ECC_SCHEME Structure +typedef struct { + u16 scheme; + TPMU_SIG_SCHEME details; +} TPMT_ECC_SCHEME; + +// Table 176 -- TPMU_PUBLIC_ID Union +typedef union { +#ifdef TPM_ALG_KEYEDHASH + TPM2B_DIGEST keyed_hash; +#endif +#ifdef TPM_ALG_SYMCIPHER + TPM2B_DIGEST sym; +#endif +#ifdef TPM_ALG_RSA + TPM2B_PUBLIC_KEY_RSA rsa; +#endif +#ifdef TPM_ALG_ECC + TPMS_ECC_POINT ecc; +#endif +} TPMU_PUBLIC_ID; + +// Table 177 -- TPMS_KEYEDHASH_PARMS Structure +typedef struct { + TPMT_KEYEDHASH_SCHEME scheme; +} TPMS_KEYEDHASH_PARMS; + +// Table 178 -- TPMS_ASYM_PARMS Structure +typedef struct { + TPMT_SYM_DEF_OBJECT symmetric; + TPMT_ASYM_SCHEME scheme; +} TPMS_ASYM_PARMS; + +// Table 179 -- TPMS_RSA_PARMS Structure +typedef struct { + TPMT_SYM_DEF_OBJECT symmetric; + TPMT_RSA_SCHEME scheme; + u16 key_bits; + u32 exponent; +} TPMS_RSA_PARMS; + +// Table 180 -- TPMS_ECC_PARMS Structure +typedef struct { + TPMT_SYM_DEF_OBJECT symmetric; + TPMT_ECC_SCHEME scheme; + u16 curve_id; + TPMT_KDF_SCHEME kdf; +} TPMS_ECC_PARMS; + +// Table 181 -- TPMU_PUBLIC_PARMS Union +typedef union { +#ifdef TPM_ALG_KEYEDHASH + TPMS_KEYEDHASH_PARMS keyed_hash; +#endif +#ifdef TPM_ALG_SYMCIPHER + TPMT_SYM_DEF_OBJECT sym; +#endif +#ifdef TPM_ALG_RSA + TPMS_RSA_PARMS rsa; +#endif +#ifdef TPM_ALG_ECC + TPMS_ECC_PARMS ecc; +#endif + TPMS_ASYM_PARMS asym; + +} TPMU_PUBLIC_PARMS; + +// Table 184 -- TPMT_PUBLIC Structure +typedef struct { + u16 type; + u16 name_alg; + TPMA_OBJECT object_attr; + TPM2B_DIGEST auth_policy; + TPMU_PUBLIC_PARMS param; + TPMU_PUBLIC_ID unique; +} TPMT_PUBLIC; + +// Table 185 -- TPM2B_PUBLIC Structure +typedef struct { + u16 size; + TPMT_PUBLIC public_area; +} PUBLIC_2B; + +typedef union { + PUBLIC_2B t; + TPM2B b; +} TPM2B_PUBLIC; + +// Table 186 -- TPMU_SENSITIVE_COMPOSITE Union +typedef union { +#ifdef TPM_ALG_RSA + TPM2B_PRIVATE_KEY_RSA rsa; +#endif +#ifdef TPM_ALG_ECC + TPM2B_ECC_PARAMETER ecc; +#endif +#ifdef TPM_ALG_KEYEDHASH + TPM2B_SENSITIVE_DATA bits; +#endif +#ifdef TPM_ALG_SYMCIPHER + TPM2B_SYM_KEY sym; +#endif + TPM2B_SENSITIVE_DATA any; + +} TPMU_SENSITIVE_COMPOSITE ; + +// Table 187 -- TPMT_SENSITIVE Structure +typedef struct { + u16 type; + TPM2B_AUTH auth_value; + TPM2B_DIGEST seedValue; + TPMU_SENSITIVE_COMPOSITE sensitive; +} TPMT_SENSITIVE; + +// Table 189 -- _PRIVATE Structure <> +typedef struct { + TPM2B_DIGEST integrity_outer; + TPM2B_DIGEST integrity_inner; + TPMT_SENSITIVE sensitive; +} _PRIVATE; + +// Table 190 -- TPM2B_PRIVATE Structure +typedef struct { + u16 size; + u8 buffer[sizeof(_PRIVATE)]; +} PRIVATE_2B; + +typedef union { + PRIVATE_2B t; + TPM2B b; +} TPM2B_PRIVATE; + +// Table 195 -- TPMA_NV Bits +typedef struct { + unsigned int TPMA_NV_PPWRITE : 1; + unsigned int TPMA_NV_OWNERWRITE : 1; + unsigned int TPMA_NV_AUTHWRITE : 1; + unsigned int TPMA_NV_POLICYWRITE : 1; + unsigned int TPMA_NV_COUNTER : 1; + unsigned int TPMA_NV_BITS : 1; + unsigned int TPMA_NV_EXTEND : 1; + unsigned int reserved8 : 3; + unsigned int TPMA_NV_POLICY_DELETE : 1; + unsigned int TPMA_NV_WRITELOCKED : 1; + unsigned int TPMA_NV_WRITEALL : 1; + unsigned int TPMA_NV_WRITEDEFINE : 1; + unsigned int TPMA_NV_WRITE_STCLEAR : 1; + unsigned int TPMA_NV_GLOBALLOCK : 1; + unsigned int TPMA_NV_PPREAD : 1; + unsigned int TPMA_NV_OWNERREAD : 1; + unsigned int TPMA_NV_AUTHREAD : 1; + unsigned int TPMA_NV_POLICYREAD : 1; + unsigned int reserved19 : 5; + unsigned int TPMA_NV_NO_DA : 1; + unsigned int TPMA_NV_ORDERLY : 1; + unsigned int TPMA_NV_CLEAR_STCLEAR : 1; + unsigned int TPMA_NV_READLOCKED : 1; + unsigned int TPMA_NV_WRITTEN : 1; + unsigned int TPMA_NV_PLATFORMCREATE : 1; + unsigned int TPMA_NV_READ_STCLEAR : 1; +} TPMA_NV ; + +// Table 196 -- TPMS_NV_PUBLIC Structure +typedef struct { + u32 index; + u16 name_alg; + TPMA_NV attr; + TPM2B_DIGEST auth_policy; + u16 data_size; +} TPMS_NV_PUBLIC; + +// Table 197 -- TPM2B_NV_PUBLIC Structure +typedef struct { + u16 size; + TPMS_NV_PUBLIC nv_public; +} NV_PUBLIC_2B; + +typedef union { + NV_PUBLIC_2B t; + TPM2B b; +} TPM2B_NV_PUBLIC; + +// Table 198 Definition of TPM2B_CONTEXT_SENSITIVE Structure < IN/OUT> +typedef union { + struct { + u16 size; + u8 buffer[MAX_CONTEXT_SIZE]; + } t; + TPM2B b; +} TPM2B_CONTEXT_SENSITIVE; + +// Table 199 Definition of TPMS_CONTEXT_DATA Structure < IN/OUT, S> +typedef struct { + TPM2B_DIGEST integrity; + TPM2B_CONTEXT_SENSITIVE encrypted; +} TPMS_CONTEXT_DATA; + +// Table 200 Definition of TPM2B_CONTEXT_DATA Structure < IN/OUT> +typedef union { + struct { + u16 size; + u8 buffer[sizeof(TPMS_CONTEXT_DATA)]; + } t; + TPM2B b; +} TPM2B_CONTEXT_DATA; + +// Table 201 Definition of TPMS_CONTEXT Structure +typedef struct { + u64 sequence; + TPMI_DH_CONTEXT savedHandle; + TPMI_RH_HIERARCHY hierarchy; + TPM2B_CONTEXT_DATA contextBlob; +} TPMS_CONTEXT; + +// Table 203 -- TPMS_CREATION_DATA Structure +typedef struct { + TPML_PCR_SELECTION pcr_select; + TPM2B_DIGEST pcr_digest; + TPMA_LOCALITY locality; + u16 parent_name_alg; + TPM2B_NAME parent_name; + TPM2B_NAME parent_qualified_name; + TPM2B_DATA outside_info; +} TPMS_CREATION_DATA; + +// Table 204 -- TPM2B_CREATION_DATA Structure +typedef struct { + u16 size; + TPMS_CREATION_DATA data; +} CREATION_DATA_2B; + +typedef union { + CREATION_DATA_2B t; + TPM2B b; +} TPM2B_CREATION_DATA; + + +#define MAX_SESSIONS 3 + +// Input structure for session data for a single session, +typedef struct { + u32 session_handle; + TPM2B_NONCE nonce; + TPMA_SESSION session_attr; + TPM2B_AUTH hmac; +} TPM_CMD_SESSION_DATA_IN ; + +// Input structure for sessions data. +typedef struct { + u8 num_sessions; + TPM_CMD_SESSION_DATA_IN sessions[MAX_SESSION_NUM]; +} TPM_CMD_SESSIONS_IN; + +// Output structure for session data for a single session. +typedef struct { + TPM2B_NONCE nonce; + TPMA_SESSION session_attr; + TPM2B_AUTH hmac; +} TPM_CMD_SESSION_DATA_OUT; + +// Output structure for sessions data. +typedef struct { + u8 num_sessions; + TPM_CMD_SESSION_DATA_OUT sessions[MAX_SESSION_NUM]; +} TPM_CMD_SESSIONS_OUT; + + +/* + * command parameter related structure + */ + +typedef struct { + TPML_PCR_SELECTION pcr_selection; +} tpm_pcr_read_in; + +typedef struct { + u32 pcr_update_counter; + TPML_PCR_SELECTION pcr_selection; + TPML_DIGEST pcr_values; +} tpm_pcr_read_out; + +typedef struct { + u32 pcr_handle; + TPM_CMD_SESSIONS_IN sessions; + TPML_DIGEST_VALUES digests; +} tpm_pcr_extend_in; + +typedef struct { + TPM_CMD_SESSIONS_OUT sessions; +} tpm_pcr_extend_out; + +typedef struct { + u32 pcr_handle; + TPM_CMD_SESSIONS_IN sessions; + TPM2B_EVENT data; +} tpm_pcr_event_in; + +typedef struct { + TPML_DIGEST_VALUES digests; + TPM_CMD_SESSIONS_OUT sessions; +} tpm_pcr_event_out; + +typedef struct { + u32 pcr_handle; + TPM_CMD_SESSIONS_IN sessions; +} tpm_pcr_reset_in; + +typedef struct { + TPM_CMD_SESSIONS_OUT sessions; +} tpm_pcr_reset_out; + +typedef struct { + TPM2B_AUTH auth; + u16 hash_alg; +} tpm_sequence_start_in; + +typedef struct { + u32 handle; +} tpm_sequence_start_out; + +typedef struct { + u32 handle; + TPM_CMD_SESSIONS_IN sessions; + TPM2B_MAX_BUFFER buf; +} tpm_sequence_update_in; + +typedef struct { + TPM_CMD_SESSIONS_OUT sessions; +} tpm_sequence_update_out; + +typedef struct { + u32 pcr_handle; + u32 seq_handle; + TPM_CMD_SESSIONS_IN sessions; + TPM2B_MAX_BUFFER buf; +} tpm_sequence_complete_in; + +typedef struct { + TPML_DIGEST_VALUES results; + TPM_CMD_SESSIONS_OUT sessions; +} tpm_sequence_complete_out; + +typedef struct { + u32 seq_handle; + TPM_CMD_SESSIONS_IN sessions; + TPM2B_MAX_BUFFER buf; + u32 hierarchy; +} tpm_sequence_complete2_in; + +typedef struct { + TPML_DIGEST_VALUES results; + TPMT_TK_HASHCHECK validation; + TPM_CMD_SESSIONS_OUT sessions; +} tpm_sequence_complete2_out; + +typedef struct { + u32 handle; + u32 index; + TPM_CMD_SESSIONS_IN sessions; + u16 size; + u16 offset; +} tpm_nv_read_in; + +typedef struct { + TPM2B_MAX_NV_BUFFER data; + TPM_CMD_SESSIONS_OUT sessions; +} tpm_nv_read_out; + +typedef struct { + u32 handle; + u32 index; + TPM_CMD_SESSIONS_IN sessions; + TPM2B_MAX_NV_BUFFER data; + u16 offset; +} tpm_nv_write_in; + +typedef struct { + TPM_CMD_SESSIONS_OUT sessions; +} tpm_nv_write_out; + +typedef struct { + u32 handle; + TPM_CMD_SESSIONS_IN sessions; + TPM2B_AUTH auth; + TPM2B_NV_PUBLIC public_info; +} tpm_nv_define_space_in; + +typedef struct { + TPM_CMD_SESSIONS_OUT sessions; +} tpm_nv_define_space_out; + +typedef struct { + u32 handle; + u32 index; + TPM_CMD_SESSIONS_IN sessions; +} tpm_nv_undefine_space_in; + +typedef struct { + TPM_CMD_SESSIONS_OUT sessions; +} tpm_nv_undefine_space_out; + +typedef struct { + u32 index; +} tpm_nv_read_public_in; + +typedef struct { + TPM2B_NV_PUBLIC nv_public; + TPM2B_NAME nv_name; +} tpm_nv_read_public_out; + +typedef struct { + u16 bytes_req; +} tpm_get_random_in; + +typedef struct { + TPM2B_DIGEST random_bytes; +} tpm_get_random_out; + +typedef struct { + u32 capability; + u32 property; + u32 property_count; +} tpm_get_capability_in; + +typedef struct { + u8 more_data; + TPMS_CAPABILITY_DATA data; +} tpm_get_capability_out; + +typedef struct { + u32 primary_handle; + TPM_CMD_SESSIONS_IN sessions; + TPM2B_SENSITIVE_CREATE sensitive; + TPM2B_PUBLIC public; + TPM2B_DATA outside_info; + TPML_PCR_SELECTION creation_pcr; +} tpm_create_primary_in; + +typedef struct { + u32 obj_handle; + TPM2B_PUBLIC public; + TPM2B_CREATION_DATA creation_data; + TPM2B_DIGEST creation_hash; + TPMT_TK_CREATION creation_ticket; + TPM2B_NAME name; + TPM_CMD_SESSIONS_OUT sessions; +} tpm_create_primary_out; + +typedef struct { + u32 parent_handle; + TPM_CMD_SESSIONS_IN sessions; + TPM2B_SENSITIVE_CREATE sensitive; + TPM2B_PUBLIC public; + TPM2B_DATA outside_info; + TPML_PCR_SELECTION creation_pcr; +} tpm_create_in; + +typedef struct { + TPM2B_PRIVATE private; + TPM2B_PUBLIC public; + TPM2B_CREATION_DATA creation_data; + TPM2B_DIGEST creation_hash; + TPMT_TK_CREATION creation_ticket; + TPM_CMD_SESSIONS_OUT sessions; +} tpm_create_out; + +typedef struct { + u32 parent_handle; + TPM_CMD_SESSIONS_IN sessions; + TPM2B_PRIVATE private; + TPM2B_PUBLIC public; +} tpm_load_in; + +typedef struct { + u32 obj_handle; + TPM2B_NAME name; + TPM_CMD_SESSIONS_OUT sessions; +} tpm_load_out; + +typedef struct { + u32 item_handle; + TPM_CMD_SESSIONS_IN sessions; +} tpm_unseal_in; + +typedef struct { + TPM2B_SENSITIVE_DATA data; + TPM_CMD_SESSIONS_OUT sessions; +} tpm_unseal_out; + +typedef struct { + TPMI_DH_CONTEXT saveHandle; +} tpm_contextsave_in; + +typedef struct { + TPMS_CONTEXT context; +} tpm_contextsave_out; + +typedef struct { + TPMS_CONTEXT context; +} tpm_contextload_in; + +typedef struct { + TPMI_DH_CONTEXT loadedHandle; +} tpm_contextload_out; + +typedef struct { + TPMI_DH_CONTEXT flushHandle; +} tpm_flushcontext_in; + +#endif /* __TPM20_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/types.h b/trenchboot/skboot/include/types.h new file mode 100644 index 0000000..ee34cef --- /dev/null +++ b/trenchboot/skboot/include/types.h @@ -0,0 +1,93 @@ +/* + * types.h: defines size-based types for 32b builds + * + * Copyright (c) 2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __TYPES_H__ +#define __TYPES_H__ + +/* Need for other later defines. */ +#include + +#define NULL ((void*)0) + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +typedef signed short s16; + +typedef unsigned char u_char; + +typedef unsigned int u_int; + +typedef unsigned char u_int8_t; +typedef unsigned short u_int16_t; +typedef unsigned int u_int32_t; + +/* + * This should be unsigned int but gets an error in + * policy.c that expects it to be an unsigned long. + */ +typedef unsigned long size_t; + +/* + * This is specifically for IA32. + */ +typedef unsigned int uintptr_t; +typedef unsigned long long u64; +typedef unsigned long long uint64_t; +typedef unsigned long long u_int64_t; +#define BYTES_PER_LONG 4 + +#if __GNUC__ > 3 +#define offsetof(type, field) __builtin_offsetof(type, field) +#else +#define offsetof(type, member) ((size_t) &((type *)0)->member) +#endif + +#endif /* __TYPES_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/skboot/include/vga.h b/trenchboot/skboot/include/vga.h new file mode 100644 index 0000000..7e9914a --- /dev/null +++ b/trenchboot/skboot/include/vga.h @@ -0,0 +1,87 @@ +/* + * vga.h: definitions of and supports functions for VGA + * + * Copyright (c) 2006-2010, Intel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef __VGA_H__ +#define __VGA_H__ + +#define VGA_BASE 0xb8000 + +/* 80*25 text mode*/ +#define MAX_LINES 25 +#define MAX_COLS 80 +#define SCREEN_BUFFER (MAX_LINES*MAX_COLS*2) +#define VGA_ADDR(x, y) (VGA_BASE + 2*(MAX_COLS*(y) + (x))) + +/* registers */ +#define CTL_ADDR_REG 0x3D4 +#define CTL_DATA_REG 0x3D5 +#define START_ADD_HIGH_REG 0x0C +#define START_ADD_LOW_REG 0x0D + +/* colors */ +#define COLOR_BLACK 0x00 +#define COLOR_BLUE 0x01 +#define COLOR_GREEN 0x02 +#define COLOR_CYAN 0x03 +#define COLOR_RED 0x04 +#define COLOR_MAGENTA 0x05 +#define COLOR_BROWN 0x06 +#define COLOR_LTGRAY 0x07 +#define COLOR_DKGRAY 0x08 +#define COLOR_LTBLUE 0x09 +#define COLOR_LTGREEN 0x0A +#define COLOR_LTCYAN 0x0B +#define COLOR_LTRED 0x0C +#define COLOR_LTMAGENTA 0x0D +#define COLOR_LTBROWN 0x0E +#define COLOR_WHITE 0x0F + +#define COLOR ((COLOR_BLACK << 4) | COLOR_LTGRAY) + + +void vga_init(void); +void vga_puts(const char *s, unsigned int cnt); + +#endif /* __VGA_H__ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/trenchboot/slboot/common/tpm.c b/trenchboot/slboot/common/tpm.c index a45a300..21f8730 100644 --- a/trenchboot/slboot/common/tpm.c +++ b/trenchboot/slboot/common/tpm.c @@ -750,8 +750,7 @@ bool prepare_tpm(void) * (: locality is not active) */ if (is_tpm_crb()) -// return release_locality_crb(0); - return true; + return tpm_relinquish_locality_crb(0); else return release_locality(0); }