mirror of
https://github.com/linuxboot/heads.git
synced 2024-12-24 07:06:42 +00:00
686 lines
20 KiB
Diff
686 lines
20 KiB
Diff
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 <stdint.h>
|
|
+#include <commonlib/helpers.h>
|
|
+
|
|
+#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 <reset.h>
|
|
#include <boot/tables.h>
|
|
#include <program_loading.h>
|
|
+#include <tpm_lite/tlcl.h>
|
|
#include <lib.h>
|
|
#if IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)
|
|
#include <arch/acpi.h>
|
|
@@ -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 <string.h>
|
|
+
|
|
+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 <string.h>
|
|
#include <tpm_lite/tlcl.h>
|
|
#include <tpm.h>
|
|
+#include <sha1.h>
|
|
#include <vb2_api.h>
|
|
#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 <southbridge/amd/common/acpi/sleepstates.asl>
|
|
|
|
/* 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 <device/device.h>
|
|
#include <halt.h>
|
|
#include <tpm.h>
|
|
+#include <tpm_lite/tlcl.h>
|
|
+#include <program_loading.h>
|
|
#include <northbridge/intel/sandybridge/chip.h>
|
|
#include "southbridge/intel/bd82x6x/pch.h"
|
|
#include <southbridge/intel/common/gpio.h>
|
|
@@ -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);
|
|
+ }
|
|
+}
|
|
+
|