diff --git ./src/Kconfig ./src/Kconfig index 6896d0e..577bd52 100644 --- ./src/Kconfig +++ ./src/Kconfig @@ -253,6 +253,21 @@ config BOOTSPLASH_FILE The path and filename of the file to use as graphical bootsplash screen. The file format has to be jpg. +config MEASURED_BOOT + bool "Enable TPM measured boot" + default n + select TPM + depends on MAINBOARD_HAS_LPC_TPM + depends on !VBOOT + help + Enable this option to measure the bootblock, romstage and + CBFS files into TPM PCRs. This does not verify these values + (that is the job of something like vboot), but makes it possible + for the payload to validate the boot path and allow something + like Heads to attest to the user that the system is likely safe. + + You probably want to say N. + endmenu menu "Mainboard" diff --git ./src/drivers/pc80/tpm/romstage.c ./src/drivers/pc80/tpm/romstage.c index 5531458..95e65f2 100644 --- ./src/drivers/pc80/tpm/romstage.c +++ ./src/drivers/pc80/tpm/romstage.c @@ -48,6 +48,12 @@ static const struct { static const struct { u8 buffer[12]; +} tpm2_startup_cmd = { + {0x80, 0x01, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x01, 0x44, 0x0, 0x0 } +}; + +static const struct { + u8 buffer[12]; } tpm_deactivate_cmd = { {0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x3 } }; @@ -229,9 +235,15 @@ void init_tpm(int s3resume) return; } } else { - printk(BIOS_SPEW, "TPM: Startup\n"); - result = TlclSendReceive(tpm_startup_cmd.buffer, - response, sizeof(response)); + if (IS_ENABLED(CONFIG_TPM2)) { + printk(BIOS_SPEW, "TPM2: Startup\n"); + result = TlclSendReceive(tpm2_startup_cmd.buffer, + response, sizeof(response)); + } else { + printk(BIOS_SPEW, "TPM: Startup\n"); + result = TlclSendReceive(tpm_startup_cmd.buffer, + response, sizeof(response)); + } } tis_close(); diff --git ./src/drivers/pc80/tpm/tpm.c ./src/drivers/pc80/tpm/tpm.c index 574d3af..9bdc73f 100644 --- ./src/drivers/pc80/tpm/tpm.c +++ ./src/drivers/pc80/tpm/tpm.c @@ -125,10 +125,11 @@ static const struct device_name atmel_devices[] = { static const struct device_name infineon_devices[] = { {0x000b, "SLB9635 TT 1.2"}, - {0x001a, "SLB9660 TT 1.2"}, #if IS_ENABLED(CONFIG_TPM2) + {0x001a, "SLB9665 TT 2.0"}, {0x001b, "SLB9670 TT 2.0"}, #else + {0x001a, "SLB9660 TT 1.2"}, {0x001b, "SLB9670 TT 1.2"}, #endif {0xffff} diff --git ./src/include/program_loading.h ./src/include/program_loading.h index 416e2e9..40486cd 100644 --- ./src/include/program_loading.h +++ ./src/include/program_loading.h @@ -24,6 +24,8 @@ enum { /* Last segment of program. Can be used to take different actions for * cache maintenance of a program load. */ SEG_FINAL = 1 << 0, + /* Indicate that the program segment should not be measured */ + SEG_NO_MEASURE = 1 << 1, }; enum prog_type { diff --git ./src/include/sha1.h ./src/include/sha1.h new file mode 100644 index 0000000..e7e28e6 --- /dev/null +++ ./src/include/sha1.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* SHA-1 functions */ + +#ifndef _sha1_h_ +#define _sha1_h_ + +#include +#include + +#define SHA1_DIGEST_SIZE 20 +#define SHA1_BLOCK_SIZE 64 + +/* SHA-1 context */ +struct sha1_ctx { + uint32_t count; + uint32_t state[5]; + union { + uint8_t b[SHA1_BLOCK_SIZE]; + uint32_t w[DIV_ROUND_UP(SHA1_BLOCK_SIZE, sizeof(uint32_t))]; + } buf; +}; + +void sha1_init(struct sha1_ctx *ctx); +void sha1_update(struct sha1_ctx *ctx, const uint8_t *data, uint32_t len); +uint8_t *sha1_final(struct sha1_ctx *ctx); + +#endif /* _sha1_h_ */ diff --git ./src/include/tpm_lite/tlcl.h ./src/include/tpm_lite/tlcl.h index 8dd5d80..15fbebf 100644 --- ./src/include/tpm_lite/tlcl.h +++ ./src/include/tpm_lite/tlcl.h @@ -147,6 +147,11 @@ uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest, uint8_t *out_digest); /** + * Perform a SHA1 hash on a region and extend a PCR with the hash. + */ +uint32_t tlcl_measure(int pcr_num, const void * start, size_t len); + +/** * Get the entire set of permanent flags. */ uint32_t tlcl_get_permanent_flags(TPM_PERMANENT_FLAGS *pflags); diff --git ./src/lib/Makefile.inc ./src/lib/Makefile.inc index 25537d2..5248483 100644 --- ./src/lib/Makefile.inc +++ ./src/lib/Makefile.inc @@ -57,8 +57,13 @@ verstage-$(CONFIG_TPM) += tlcl.c verstage-$(CONFIG_TPM2) += tpm2_marshaling.c verstage-$(CONFIG_TPM2) += tpm2_tlcl.c -ifeq ($(CONFIG_VBOOT_SEPARATE_VERSTAGE),y) +# Add the TPM support into the ROM stage for measuring the bootblock romstage-$(CONFIG_TPM) += tlcl.c +romstage-$(CONFIG_TPM) += sha1.c +ramstage-$(CONFIG_TPM) += tlcl.c +ramstage-$(CONFIG_TPM) += sha1.c + +ifeq ($(CONFIG_VBOOT_SEPARATE_VERSTAGE),y) romstage-$(CONFIG_TPM2) += tpm2_marshaling.c romstage-$(CONFIG_TPM2) += tpm2_tlcl.c endif # CONFIG_VBOOT_SEPARATE_VERSTAGE diff --git ./src/lib/cbfs.c ./src/lib/cbfs.c index 596abc5..f1928ce 100644 --- ./src/lib/cbfs.c +++ ./src/lib/cbfs.c @@ -69,7 +69,13 @@ void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size) if (size != NULL) *size = fsize; - return rdev_mmap(&fh.data, 0, fsize); + void * buffer = rdev_mmap(&fh.data, 0, fsize); + +#ifndef __SMM__ + prog_segment_loaded((uintptr_t)buffer, fsize, 0); +#endif + + return buffer; } int cbfs_locate_file_in_region(struct cbfsf *fh, const char *region_name, @@ -97,7 +101,8 @@ size_t cbfs_load_and_decompress(const struct region_device *rdev, size_t offset, return 0; if (rdev_readat(rdev, buffer, offset, in_size) != in_size) return 0; - return in_size; + out_size = in_size; + break; case CBFS_COMPRESS_LZ4: if ((ENV_BOOTBLOCK || ENV_VERSTAGE) && @@ -115,7 +120,7 @@ size_t cbfs_load_and_decompress(const struct region_device *rdev, size_t offset, timestamp_add_now(TS_START_ULZ4F); out_size = ulz4fn(compr_start, in_size, buffer, buffer_size); timestamp_add_now(TS_END_ULZ4F); - return out_size; + break; case CBFS_COMPRESS_LZMA: if (ENV_BOOTBLOCK || ENV_VERSTAGE) @@ -134,11 +139,15 @@ size_t cbfs_load_and_decompress(const struct region_device *rdev, size_t offset, rdev_munmap(rdev, map); - return out_size; + break; default: return 0; } + + prog_segment_loaded((uintptr_t)buffer, out_size, 0); + + return out_size; } static inline int tohex4(unsigned int c) diff --git ./src/lib/hardwaremain.c ./src/lib/hardwaremain.c index 0deab4b..eee5415 100644 --- ./src/lib/hardwaremain.c +++ ./src/lib/hardwaremain.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME) #include @@ -544,3 +545,13 @@ void boot_state_current_unblock(void) { boot_state_unblock(current_phase.state_id, current_phase.seq); } + +// ramstage measurements go into PCR3 if we are doing measured boot +void platform_segment_loaded(uintptr_t start, size_t size, int flags) +{ + if (IS_ENABLED(CONFIG_MEASURED_BOOT) && !(flags & SEG_NO_MEASURE)) + { + tlcl_measure(3, (const void*) start, size); + } +} + diff --git ./src/lib/rmodule.c ./src/lib/rmodule.c index 66d5120..b50afe7 100644 --- ./src/lib/rmodule.c +++ ./src/lib/rmodule.c @@ -198,7 +198,7 @@ int rmodule_load(void *base, struct rmodule *module) rmodule_clear_bss(module); prog_segment_loaded((uintptr_t)module->location, - rmodule_memory_size(module), SEG_FINAL); + rmodule_memory_size(module), SEG_FINAL | SEG_NO_MEASURE); return 0; } diff --git ./src/lib/sha1.c ./src/lib/sha1.c new file mode 100644 index 0000000..506907f --- /dev/null +++ ./src/lib/sha1.c @@ -0,0 +1,175 @@ +/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * SHA-1 implementation largely based on libmincrypt in the the Android + * Open Source Project (platorm/system/core.git/libmincrypt/sha.c + */ + +#include "sha1.h" +#include + +static uint32_t ror27(uint32_t val) +{ + return (val >> 27) | (val << 5); +} +static uint32_t ror2(uint32_t val) +{ + return (val >> 2) | (val << 30); +} +static uint32_t ror31(uint32_t val) +{ + return (val >> 31) | (val << 1); +} + +static void sha1_transform(struct sha1_ctx *ctx) +{ + uint32_t W[80]; + register uint32_t A, B, C, D, E; + int t; + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define SHA_F1(A, B, C, D, E, t) \ + E += ror27(A) + \ + (W[t] = __builtin_bswap32(ctx->buf.w[t])) + \ + (D^(B&(C^D))) + 0x5A827999; \ + B = ror2(B); + + for (t = 0; t < 15; t += 5) { + SHA_F1(A, B, C, D, E, t + 0); + SHA_F1(E, A, B, C, D, t + 1); + SHA_F1(D, E, A, B, C, t + 2); + SHA_F1(C, D, E, A, B, t + 3); + SHA_F1(B, C, D, E, A, t + 4); + } + SHA_F1(A, B, C, D, E, t + 0); /* 16th one, t == 15 */ + +#undef SHA_F1 + +#define SHA_F1(A, B, C, D, E, t) \ + E += ror27(A) + \ + (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ + (D^(B&(C^D))) + 0x5A827999; \ + B = ror2(B); + + SHA_F1(E, A, B, C, D, t + 1); + SHA_F1(D, E, A, B, C, t + 2); + SHA_F1(C, D, E, A, B, t + 3); + SHA_F1(B, C, D, E, A, t + 4); + +#undef SHA_F1 + +#define SHA_F2(A, B, C, D, E, t) \ + E += ror27(A) + \ + (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ + (B^C^D) + 0x6ED9EBA1; \ + B = ror2(B); + + for (t = 20; t < 40; t += 5) { + SHA_F2(A, B, C, D, E, t + 0); + SHA_F2(E, A, B, C, D, t + 1); + SHA_F2(D, E, A, B, C, t + 2); + SHA_F2(C, D, E, A, B, t + 3); + SHA_F2(B, C, D, E, A, t + 4); + } + +#undef SHA_F2 + +#define SHA_F3(A, B, C, D, E, t) \ + E += ror27(A) + \ + (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ + ((B&C)|(D&(B|C))) + 0x8F1BBCDC; \ + B = ror2(B); + + for (; t < 60; t += 5) { + SHA_F3(A, B, C, D, E, t + 0); + SHA_F3(E, A, B, C, D, t + 1); + SHA_F3(D, E, A, B, C, t + 2); + SHA_F3(C, D, E, A, B, t + 3); + SHA_F3(B, C, D, E, A, t + 4); + } + +#undef SHA_F3 + +#define SHA_F4(A, B, C, D, E, t) \ + E += ror27(A) + \ + (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \ + (B^C^D) + 0xCA62C1D6; \ + B = ror2(B); + + for (; t < 80; t += 5) { + SHA_F4(A, B, C, D, E, t + 0); + SHA_F4(E, A, B, C, D, t + 1); + SHA_F4(D, E, A, B, C, t + 2); + SHA_F4(C, D, E, A, B, t + 3); + SHA_F4(B, C, D, E, A, t + 4); + } + +#undef SHA_F4 + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + +void sha1_update(struct sha1_ctx *ctx, const uint8_t *data, uint32_t len) +{ + int i = ctx->count % sizeof(ctx->buf); + const uint8_t *p = (const uint8_t *)data; + + ctx->count += len; + + while (len > sizeof(ctx->buf) - i) { + memcpy(&ctx->buf.b[i], p, sizeof(ctx->buf) - i); + len -= sizeof(ctx->buf) - i; + p += sizeof(ctx->buf) - i; + sha1_transform(ctx); + i = 0; + } + + while (len--) { + ctx->buf.b[i++] = *p++; + if (i == sizeof(ctx->buf)) { + sha1_transform(ctx); + i = 0; + } + } +} + + +uint8_t *sha1_final(struct sha1_ctx *ctx) +{ + uint32_t cnt = ctx->count * 8; + int i; + + sha1_update(ctx, (uint8_t *)"\x80", 1); + while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) + sha1_update(ctx, (uint8_t *)"\0", 1); + + for (i = 0; i < 8; ++i) { + uint8_t tmp = cnt >> ((7 - i) * 8); + sha1_update(ctx, &tmp, 1); + } + + for (i = 0; i < 5; i++) + ctx->buf.w[i] = __builtin_bswap32(ctx->state[i]); + + return ctx->buf.b; +} + +void sha1_init(struct sha1_ctx *ctx) +{ + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + ctx->count = 0; +} diff --git ./src/lib/tlcl.c ./src/lib/tlcl.c index 49854cb..32eb128 100644 --- ./src/lib/tlcl.c +++ ./src/lib/tlcl.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "tlcl_internal.h" #include "tlcl_structures.h" @@ -351,3 +352,23 @@ uint32_t tlcl_extend(int pcr_num, const uint8_t *in_digest, kPcrDigestLength); return result; } + + +uint32_t tlcl_measure(int pcr_num, const void * start, size_t len) +{ + VBDEBUG("TPM: pcr %d measure %p @ %zu: ", pcr_num, start, len); + + struct sha1_ctx sha; + sha1_init(&sha); + sha1_update(&sha, start, len); + + const uint8_t * hash = sha1_final(&sha); + for(unsigned i = 0 ; i < SHA1_DIGEST_SIZE ; i++) + VBDEBUG("%02x", hash[i]); + VBDEBUG("\n"); + + //hexdump(start, 128); + + return tlcl_extend(pcr_num, hash, NULL); +} + diff --git ./src/mainboard/asus/kgpe-d16/Kconfig ./src/mainboard/asus/kgpe-d16/Kconfig index 531ba4f..5227d28 100644 --- ./src/mainboard/asus/kgpe-d16/Kconfig +++ ./src/mainboard/asus/kgpe-d16/Kconfig @@ -28,6 +28,7 @@ config BOARD_SPECIFIC_OPTIONS # dummy select BOARD_ROMSIZE_KB_2048 select ENABLE_APIC_EXT_ID select SPI_FLASH + select TPM2 select MAINBOARD_HAS_LPC_TPM select HAVE_ACPI_RESUME select DRIVERS_I2C_W83795 diff --git ./src/mainboard/asus/kgpe-d16/devicetree.cb ./src/mainboard/asus/kgpe-d16/devicetree.cb index 9039f6d..0ea4216 100644 --- ./src/mainboard/asus/kgpe-d16/devicetree.cb +++ ./src/mainboard/asus/kgpe-d16/devicetree.cb @@ -217,6 +217,9 @@ chip northbridge/amd/amdfam10/root_complex # Root complex chip drivers/pc80/tpm device pnp 4e.0 on end # TPM module end + chip drivers/generic/generic # BMC KCS + device pnp ca2.0 on end + end end device pci 14.4 on # Bridge device pci 1.0 on end # VGA diff --git ./src/mainboard/asus/kgpe-d16/dsdt.asl ./src/mainboard/asus/kgpe-d16/dsdt.asl index 6a25b4d..cfcbc98 100644 --- ./src/mainboard/asus/kgpe-d16/dsdt.asl +++ ./src/mainboard/asus/kgpe-d16/dsdt.asl @@ -50,6 +50,9 @@ DefinitionBlock ( /* HPET enable */ Name (HPTE, 0x1) + /* IPMI KCS enable */ + Name (KCSE, 0x1) + #include /* The _PIC method is called by the OS to choose between interrupt @@ -485,6 +488,13 @@ DefinitionBlock ( Name (_HID, EisaId ("PNP0A05")) Name (_ADR, 0x00140003) + OperationRegion(BMRG, SystemIO, 0xca2, 0x02) /* BMC KCS registers */ + Field(BMRG, AnyAcc, NoLock, Preserve) + { + BMRI, 8, /* Index */ + BMRD, 8, /* Data */ + } + /* Real Time Clock Device */ Device(RTC0) { Name(_HID, EISAID("PNP0B00")) /* AT Real Time Clock (not PIIX4 compatible) */ @@ -606,6 +616,27 @@ DefinitionBlock ( }) } } + + Device(KCS1) { /* IPMI KCS */ + Name(_HID,EISAID("IPI0001")) /* ASpeed BMC */ + Method (_STA, 0, NotSerialized) { + If(KCSE) { /* Detection enabled */ + If(LNotEqual(BMRD, 0xff)) { + Return(0x0f) /* Device present */ + } + Return(Zero) + } + Return(Zero) + } + Method(_CRS, 0) { + Return(ResourceTemplate() { + IO(Decode16, 0x0ca2, 0x0ca2, 0x01, 0x02) + }) + } + Method (_IFT, 0, NotSerialized) { /* Interface type */ + Return(One) /* KCS interface */ + } + } } /* High Precision Event Timer */ diff --git ./src/mainboard/asus/kgpe-d16/mainboard.c ./src/mainboard/asus/kgpe-d16/mainboard.c index 65029d4..8ee3a5e 100644 --- ./src/mainboard/asus/kgpe-d16/mainboard.c +++ ./src/mainboard/asus/kgpe-d16/mainboard.c @@ -70,6 +70,13 @@ static void mainboard_enable(device_t dev) set_pcie_dereset(); /* get_ide_dma66(); */ + + /* Enable access to the BMC IPMI via KCS */ + device_t lpc_sio_dev = dev_find_slot_pnp(0xca2, 0); + struct resource *res = new_resource(lpc_sio_dev, 0xca2); + res->base = 0xca2; + res->size = 1; + res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED; } /* override the default SATA PHY setup */ diff --git ./src/mainboard/asus/kgpe-d16/romstage.c ./src/mainboard/asus/kgpe-d16/romstage.c index 63b93c1..bb4f181 100644 --- ./src/mainboard/asus/kgpe-d16/romstage.c +++ ./src/mainboard/asus/kgpe-d16/romstage.c @@ -88,6 +88,47 @@ static void switch_spd_mux(uint8_t channel) byte &= ~0xc0; /* Enable SPD mux GPIO output drivers */ byte |= (channel << 2) & 0xc; /* Set SPD mux GPIOs */ pci_write_config8(PCI_DEV(0, 0x14, 0), 0x54, byte); + + /* Temporary AST PCI mapping */ + uint32_t base_memory = 0xfc000000; + uint32_t memory_limit = 0xfc800000; + + /* Temporarily enable the SP5100 PCI bridge */ + uint16_t prev_sec_cfg = pci_read_config16(PCI_DEV(0, 0x14, 4), 0x04); + uint8_t prev_sec_bus = pci_read_config8(PCI_DEV(0, 0x14, 4), 0x19); + uint8_t prev_sec_sub_bus = pci_read_config8(PCI_DEV(0, 0x14, 4), 0x1a); + uint16_t prev_sec_mem_base = pci_read_config16(PCI_DEV(0, 0x14, 4), 0x20); + uint16_t prev_sec_mem_limit = pci_read_config16(PCI_DEV(0, 0x14, 4), 0x22); + pci_write_config8(PCI_DEV(0, 0x14, 4), 0x19, 0x01); + pci_write_config8(PCI_DEV(0, 0x14, 4), 0x1a, 0xff); + pci_write_config16(PCI_DEV(0, 0x14, 4), 0x20, (base_memory >> 20)); + pci_write_config16(PCI_DEV(0, 0x14, 4), 0x22, (memory_limit >> 20)); + pci_write_config16(PCI_DEV(0, 0x14, 4), 0x04, 0x2); + + /* Temporarily enable AST BAR1 */ + uint32_t prev_ast_cfg = pci_read_config32(PCI_DEV(1, 0x1, 0), 0x04); + uint32_t prev_ast_bar1 = pci_read_config32(PCI_DEV(1, 0x1, 0), 0x14); + pci_write_config32(PCI_DEV(1, 0x1, 0), 0x14, base_memory); + pci_write_config32(PCI_DEV(1, 0x1, 0), 0x04, 0x02100002); + + /* Use the P2A bridge to set ASpeed SPD mux GPIOs to the same values as the SP5100 */ + void* ast_bar1 = (void*)base_memory; + write32(ast_bar1 + 0xf004, 0x1e780000); /* Enable access to GPIO controller */ + write32(ast_bar1 + 0xf000, 0x1); + write32(ast_bar1 + 0x10024, read32(ast_bar1 + 0x10024) | 0x3000); /* Enable SPD mux GPIO output drivers */ + write32(ast_bar1 + 0x10020, (read32(ast_bar1 + 0x10020) & ~0x3000) | ((channel & 0x3) << 12)); /* Set SPD mux GPIOs */ + write32(ast_bar1 + 0xf000, 0x0); + + /* Deconfigure AST BAR1 */ + pci_write_config32(PCI_DEV(1, 0x1, 0), 0x04, prev_ast_cfg); + pci_write_config32(PCI_DEV(1, 0x1, 0), 0x14, prev_ast_bar1); + + /* Deconfigure SP5100 PCI bridge */ + pci_write_config16(PCI_DEV(0, 0x14, 4), 0x04, prev_sec_cfg); + pci_write_config16(PCI_DEV(0, 0x14, 4), 0x22, prev_sec_mem_limit); + pci_write_config16(PCI_DEV(0, 0x14, 4), 0x20, prev_sec_mem_base); + pci_write_config8(PCI_DEV(0, 0x14, 4), 0x1a, prev_sec_sub_bus); + pci_write_config8(PCI_DEV(0, 0x14, 4), 0x19, prev_sec_bus); } static const uint8_t spd_addr_fam15[] = { diff --git ./src/northbridge/intel/sandybridge/romstage.c ./src/northbridge/intel/sandybridge/romstage.c index 8608d5a..dac90ee 100644 --- ./src/northbridge/intel/sandybridge/romstage.c +++ ./src/northbridge/intel/sandybridge/romstage.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include "southbridge/intel/bd82x6x/pch.h" #include @@ -72,6 +74,19 @@ void mainboard_romstage_entry(unsigned long bist) /* Initialize superio */ mainboard_config_superio(); + if (IS_ENABLED(CONFIG_MEASURED_BOOT) && IS_ENABLED(CONFIG_LPC_TPM)) { + // we don't know if we are coming out of a resume + // at this point, but want to setup the tpm ASAP + init_tpm(0); + tlcl_lib_init(); + const void * const bootblock = (const void*) 0xFFFFF800; + const unsigned bootblock_size = 0x800; + tlcl_measure(0, bootblock, bootblock_size); + + extern char _romstage, _eromstage; + tlcl_measure(1, &_romstage, &_eromstage - &_romstage); + } + /* USB is initialized in MRC if MRC is used. */ if (CONFIG_USE_NATIVE_RAMINIT) { early_usb_init(mainboard_usb_ports); @@ -116,9 +131,23 @@ void mainboard_romstage_entry(unsigned long bist) northbridge_romstage_finalize(s3resume); - if (IS_ENABLED(CONFIG_LPC_TPM)) { + // the normal TPM init happens here, if we haven't already + // set it up as part of the measured boot. + if (!IS_ENABLED(CONFIG_MEASURED_BOOT) && IS_ENABLED(CONFIG_LPC_TPM)) { init_tpm(s3resume); } + printk(BIOS_DEBUG, "%s: romstage complete\n", __FILE__); + post_code(0x3f); } + + +void platform_segment_loaded(uintptr_t start, size_t size, int flags) +{ + if (IS_ENABLED(CONFIG_MEASURED_BOOT) && !(flags & SEG_NO_MEASURE)) + { + tlcl_measure(2, (const void*) start, size); + } +} +