[coreboot-gerrit] Patch set updated for coreboot: util/intelmetool: Add bootguard information dump support
Philipp Deppenwiese (zaolin.daisuki@googlemail.com)
gerrit at coreboot.org
Fri Aug 26 11:14:19 CEST 2016
Philipp Deppenwiese (zaolin.daisuki at googlemail.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16328
-gerrit
commit 465be12cccf53c7d1ceeded2c9e1e24c4f93e491
Author: Philipp Deppenwiese <zaolin at das-labor.org>
Date: Fri Aug 26 02:10:51 2016 +0200
util/intelmetool: Add bootguard information dump support
With this implementation it's possible to detect the state
of bootguard in intel based systems. Currently it's WIP and
in a testphase. Handle it with care!
Change-Id: Ifeec8e20fa8efc35d7db4c6a84be1f118dccfc4a
Signed-off-by: Philipp Deppenwiese <zaolin at das-labor.org>
---
util/intelmetool/Makefile | 2 +-
util/intelmetool/intelmetool.c | 162 ++++++++++++++++++++++++++++-------------
util/intelmetool/mmap.c | 4 -
util/intelmetool/msr.c | 98 +++++++++++++++++++++++++
util/intelmetool/msr.h | 43 +++++++++++
5 files changed, 252 insertions(+), 57 deletions(-)
diff --git a/util/intelmetool/Makefile b/util/intelmetool/Makefile
index 4461f86..4ea5c0f 100644
--- a/util/intelmetool/Makefile
+++ b/util/intelmetool/Makefile
@@ -20,7 +20,7 @@ PREFIX ?= /usr/local
CFLAGS ?= -O0 -g -Wall -W -Wno-unused-parameter -Wno-unused-but-set-variable -Wno-sign-compare -Wno-unused-function
LDFLAGS += -lpci -lz
-OBJS = intelmetool.o me.o me_status.o mmap.o
+OBJS = intelmetool.o me.o me_status.o mmap.o msr.o
OS_ARCH = $(shell uname)
ifeq ($(OS_ARCH), Darwin)
diff --git a/util/intelmetool/intelmetool.c b/util/intelmetool/intelmetool.c
index aec0715..6c56310 100644
--- a/util/intelmetool/intelmetool.c
+++ b/util/intelmetool/intelmetool.c
@@ -16,6 +16,7 @@
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
+#include <string.h>
#ifdef __NetBSD__
#include <machine/sysarch.h>
@@ -23,6 +24,7 @@
#include "me.h"
#include "mmap.h"
+#include "msr.h"
#include "intelmetool.h"
#define FD2 0x3428
@@ -83,6 +85,10 @@ static void dump_me_memory() {
uint8_t *dump;
dump = map_physical_exact(me_clone, me_clone, 0x2000000);
+ if(!dump) {
+ printf("ME physical memory can't be mapped!! Take a look at DMESG log.\n");
+ return;
+ }
zeroit(dump, 0x2000000);
printf("Send magic command for memory clone\n");
@@ -106,7 +112,6 @@ static void dump_me_memory() {
static int pci_platform_scan() {
struct pci_access *pacc;
struct pci_dev *dev;
- char namebuf[1024], *name;
pacc = pci_alloc();
pacc->method = PCI_ACCESS_I386_TYPE1;
@@ -116,38 +121,28 @@ static int pci_platform_scan() {
for (dev=pacc->devices; dev; dev=dev->next) {
pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_CLASS);
- name = pci_lookup_name(pacc, namebuf, sizeof(namebuf),
- PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
if (dev->vendor_id == 0x8086) {
if (PCI_DEV_HAS_ME_DISABLE(dev->device_id)) {
- printf(CGRN "Good news, you have a `%s` so ME is present but can be disabled, continuing...\n\n" RESET, name);
+ printf(CGRN "Good news, your ME is present but can be disabled, continuing...\n" RESET);
break;
} else if (PCI_DEV_HAS_ME_DIFFICULT(dev->device_id)) {
- printf(CRED "Bad news, you have a `%s` so you have ME hardware on board and you can't control or disable it, continuing...\n\n" RESET, name);
+ printf(CRED "Bad news, you have a ME hardware on board and you can't control or disable it, continuing...\n" RESET);
break;
} else if (PCI_DEV_CAN_DISABLE_ME_IF_PRESENT(dev->device_id)) {
- printf(CYEL "Not sure if ME hardware is present because you have a `%s`, but it is possible to disable it if you do, continuing...\n\n" RESET, name);
+ printf(CYEL "Not sure if ME hardware is present, but it is possible to disable it if you do, continuing...\n" RESET);
break;
} else if (PCI_DEV_ME_NOT_SURE(dev->device_id)) {
- printf(CYEL "Found `%s`. Not sure whether you have ME hardware, exiting\n\n" RESET, name);
- pci_cleanup(pacc);
- return 1;
+ printf(CYEL "Not sure whether you have ME hardware, exiting\n" RESET);
break;
}
}
}
- if (!PCI_DEV_HAS_ME_DISABLE(dev->device_id) &&
- !PCI_DEV_HAS_ME_DIFFICULT(dev->device_id) &&
- !PCI_DEV_CAN_DISABLE_ME_IF_PRESENT(dev->device_id) &&
- !PCI_DEV_ME_NOT_SURE(dev->device_id)) {
- printf(CCYN "ME is not present on your board or unkown\n\n" RESET);
- pci_cleanup(pacc);
- return 1;
+ if(!dev) {
+ printf(CCYN "ME is not present on your board or unkown\n" RESET);
}
pci_cleanup(pacc);
-
return 0;
}
@@ -166,7 +161,7 @@ static struct pci_dev *pci_me_interface_scan(char **name) {
for (dev=pacc->devices; dev; dev=dev->next) {
pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_CLASS);
*name = pci_lookup_name(pacc, namebuf, sizeof(namebuf),
- PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
+ PCI_LOOKUP_DEVICE, dev->vendor_id, dev->device_id);
if (dev->vendor_id == 0x8086) {
if (PCI_DEV_HAS_SUPPORTED_ME(dev->device_id)) {
me = 1;
@@ -207,6 +202,9 @@ static int activate_me() {
rcba_phys = pci_read_long(sb, 0xf0) & 0xfffffffe;
rcba = map_physical(rcba_phys, size);
+ if(!rcba) {
+ return 1;
+ }
//printf("RCBA at 0x%08" PRIx32 "\n", (uint32_t)rcba_phys);
fd2 = *(uint32_t *)(rcba + FD2);
@@ -231,14 +229,14 @@ static void dump_me_info() {
exit(1);
}
+ printf("\n");
+
dev = pci_me_interface_scan(&name);
if (!dev) {
exit(1);
}
- if (activate_me()) {
- exit(1);
- }
+ activate_me();
printf("MEI found: [%x:%x] %s\n\n", dev->vendor_id, dev->device_id, name);
stat = pci_read_long(dev, 0x40);
@@ -271,10 +269,62 @@ static void dump_me_info() {
munmap((void*)rcba, size);
}
+static void dump_bootguard_info() {
+ int result = 0;
+ struct pci_dev *dev;
+ uint32_t stat = 0;
+ char *name;
+ uint64_t bootguard;
+
+ bootguard = msr_bootguard(&result);
+
+ if(result < 0) {
+ return;
+ }
+
+ pci_platform_scan();
+ dev = pci_me_interface_scan(&name);
+ activate_me();
+
+ if(dev) {
+ stat = pci_read_long(dev, 0x40);
+ }
+
+ printf(CYEL "Beware this feature is WIP and not stable!\n\n" RESET);
+ if(debug) {
+ printf("BootGuard MSR Output: 0x%" PRIx64 "\n", bootguard);
+ }
+
+ if(BOOTGUARD_CAPABILITY(bootguard)) {
+ printf("ME BootGuard Capability: YES\n");
+ if (dev && (stat & 0x10) >> 4) {
+ printf(CRED "Your southbridge configuration is insecure!! BootGuard keys can be overwritten or wiped.\n" RESET);
+ }
+ switch(bootguard) {
+ case BOOTGUARD_DISABLED:
+ printf("ME BootGuard Mode: Disabled\n");
+ printf(CGRN "Your system is bootguard ready but your vendor disabled it. You can flash other firmware!\n" RESET);
+ break;
+ case BOOTGUARD_ENABLED_COMBI_MODE:
+ printf("ME BootGuard Mode: Verified & Measured Boot\n");
+ break;
+ case BOOTGUARD_ENABLED_MEASUREMENT_MODE:
+ printf("ME BootGuard Mode: Measured Boot\n");
+ break;
+ case BOOTGUARD_ENABLED_VERIFIED_MODE:
+ printf("ME BootGuard Mode: Verified Boot\n");
+ break;
+ }
+ } else {
+ printf("ME BootGuard Capability: NO\n");
+ printf(CGRN "Your system isn't bootguard ready. You can flash other firmware!\n" RESET);
+ }
+}
+
static void print_version(void)
{
printf("intelmetool v%s -- ", INTELMETOOL_VERSION);
- printf("Copyright (C) 2015 Damien Zammit\n\n");
+ printf("Copyright (C) 2016 Damien Zammit, Philipp Deppenwiese\n\n");
printf(
"This program is free software: you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License as published by\n"
@@ -289,11 +339,12 @@ static void print_usage(const char *name)
{
printf("usage: %s [-vh?sd]\n", name);
printf("\n"
- " -v | --version: print the version\n"
- " -h | --help: print this help\n\n"
- " -s | --show: dump all me information on console\n"
- " -d | --debug: enable debug output\n"
- "\n");
+ " -v | --version: print the version\n"
+ " -h | --help: print this help\n\n"
+ " -s | --show: dump all me information on console\n"
+ " -b | --bootguard dump bootguard state of platform\n"
+ " -d | --debug: enable debug output\n"
+ "\n");
exit(1);
}
@@ -306,13 +357,14 @@ int main(int argc, char *argv[])
{"version", 0, 0, 'v'},
{"help", 0, 0, 'h'},
{"show", 0, 0, 's'},
+ {"bootguard", 0, 0, 'b'},
{"debug", 0, 0, 'd'},
{0, 0, 0, 0}
};
- while ((opt = getopt_long(argc, argv, "vh?sd",
- long_options, &option_index)) != EOF) {
- switch (opt) {
+ while ((opt = getopt_long(argc, argv, "vh?sdb",
+ long_options, &option_index)) != EOF) {
+ switch (opt) {
case 'v':
print_version();
exit(0);
@@ -320,6 +372,9 @@ int main(int argc, char *argv[])
case 's':
cmd_exec = 1;
break;
+ case 'b':
+ cmd_exec = 2;
+ break;
case 'd':
debug = 1;
break;
@@ -329,42 +384,45 @@ int main(int argc, char *argv[])
print_usage(argv[0]);
exit(0);
break;
- }
}
+ }
#if defined(__FreeBSD__)
- if (open("/dev/io", O_RDWR) < 0) {
- perror("/dev/io");
+ if (open("/dev/io", O_RDWR) < 0) {
+ perror("/dev/io");
#elif defined(__NetBSD__)
# ifdef __i386__
- if (i386_iopl(3)) {
- perror("iopl");
+ if (i386_iopl(3)) {
+ perror("iopl");
# else
- if (x86_64_iopl(3)) {
- perror("iopl");
+ if (x86_64_iopl(3)) {
+ perror("iopl");
# endif
#else
- if (iopl(3)) {
- perror("iopl");
+ if (iopl(3)) {
+ perror("iopl");
#endif
- printf("You need to be root.\n");
- exit(1);
- }
+ printf("You need to be root.\n");
+ exit(1);
+ }
#ifndef __DARWIN__
- if ((fd_mem = open("/dev/mem", O_RDWR)) < 0) {
- perror("Can not open /dev/mem");
- exit(1);
- }
+ if ((fd_mem = open("/dev/mem", O_RDWR)) < 0) {
+ perror("Can not open /dev/mem");
+ exit(1);
+ }
#endif
switch(cmd_exec) {
- case 1:
- dump_me_info();
- break;
- default:
- print_usage(argv[0]);
- break;
+ case 1:
+ dump_me_info();
+ break;
+ case 2:
+ dump_bootguard_info();
+ break;
+ default:
+ print_usage(argv[0]);
+ break;
}
return 0;
diff --git a/util/intelmetool/mmap.c b/util/intelmetool/mmap.c
index da36eaa..bf3c378 100644
--- a/util/intelmetool/mmap.c
+++ b/util/intelmetool/mmap.c
@@ -28,8 +28,6 @@ void *map_physical_exact(uint64_t phys_addr, uint64_t mapto, size_t len) {
if (virt_addr == MAP_FAILED) {
err = errno;
- printf("Error mapping physical memory 0x%016" PRIx64 "[0x%zx] ERRNO=%d\n",
- phys_addr, len, err);
return NULL;
}
@@ -44,8 +42,6 @@ void *map_physical(uint64_t phys_addr, size_t len) {
if (virt_addr == MAP_FAILED) {
err = errno;
- printf("Error mapping physical memory 0x%016" PRIx64 "[0x%zx] ERRNO=%d\n",
- phys_addr, len, err);
return NULL;
}
diff --git a/util/intelmetool/msr.c b/util/intelmetool/msr.c
new file mode 100644
index 0000000..3314fb4
--- /dev/null
+++ b/util/intelmetool/msr.c
@@ -0,0 +1,98 @@
+/* intelmetool
+ *
+ * Copyright (C) 2013-2016 Philipp Deppenwiese <zaolin at das-labor.org>, Alexander Couzens <lynxis at fe80.eu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <cpuid.h>
+
+#include "msr.h"
+
+#define CPU_ID_SIZE 13
+
+#ifndef __DARWIN__
+int fd_msr = 0;
+
+static void get_cpu_id(char *id) {
+ cpu_t cpu;
+ unsigned int level = 0;
+ unsigned int eax = 0;
+
+ __get_cpuid(level, &eax, &cpu.ebx, &cpu.ecx, &cpu.edx);
+
+ memcpy(id, (char*)&cpu, CPU_ID_SIZE);
+}
+
+static uint64_t rdmsr(int addr)
+{
+ uint32_t buf[2];
+ uint64_t msr = 0;
+
+ if (lseek(fd_msr, (off_t) addr, SEEK_SET) == -1) {
+ perror("Could not lseek() to MSR");
+ close(fd_msr);
+ return -1;
+ }
+
+ if (read(fd_msr, buf, 8) == 8) {
+ msr = buf[1];
+ msr <<= 32;
+ msr |= buf[0];
+ close(fd_msr);
+ return msr;
+ }
+
+ if (errno == 5) {
+ close(fd_msr);
+ return -2;
+ } else {
+ perror("Could not read() MSR");
+ close(fd_msr);
+ return -1;
+ }
+
+ return msr;
+}
+#endif
+
+uint64_t msr_bootguard(int *result) {
+ uint64_t msr = 0;
+ char cpu_id[CPU_ID_SIZE] = { 0 };
+
+#ifndef __DARWIN__
+ get_cpu_id(cpu_id);
+ if(strncmp(cpu_id, "GenuineIntel", CPU_ID_SIZE-1)) {
+ perror("Error CPU is not from Intel.");
+ *result = -1;
+ return 0;
+ }
+
+ fd_msr = open("/dev/cpu/0/msr", O_RDWR);
+ if (fd_msr < 0) {
+ perror("Error while opening /dev/cpu/0/msr");
+ printf("Did you run 'modprobe msr'?\n");
+ *result = -2;
+ return 0;
+ }
+#endif
+
+ msr = rdmsr(MSR_BOOTGUARD);
+ msr &= ~0xff;
+
+ return msr;
+}
diff --git a/util/intelmetool/msr.h b/util/intelmetool/msr.h
new file mode 100644
index 0000000..c76206b
--- /dev/null
+++ b/util/intelmetool/msr.h
@@ -0,0 +1,43 @@
+/* intelmetool
+ *
+ * Copyright (C) 2013-2016 Philipp Deppenwiese <zaolin at das-labor.org>, Alexander Couzens <lynxis at fe80.eu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <stdio.h>
+
+#define MSR_BOOTGUARD 0x13A
+
+#define BOOTGUARD_DISABLED 0x400000000
+#define BOOTGUARD_ENABLED_VERIFIED_MODE 0x100000000
+#define BOOTGUARD_ENABLED_MEASUREMENT_MODE 0x200000000
+#define BOOTGUARD_ENABLED_COMBI_MODE 0x300000000
+#define BOOTGUARD_CAPABILITY(x) ( \
+ ( (x) == BOOTGUARD_DISABLED ) || \
+ ( (x) == BOOTGUARD_ENABLED_VERIFIED_MODE ) || \
+ ( (x) == BOOTGUARD_ENABLED_MEASUREMENT_MODE ) || \
+ ( (x) == BOOTGUARD_ENABLED_COMBI_MODE ))
+
+#ifndef __DARWIN__
+
+typedef struct {
+ unsigned int ebx;
+ unsigned int edx;
+ unsigned int ecx;
+} cpu_t;
+
+extern uint64_t msr_bootguard(int *result);
+#endif
More information about the coreboot-gerrit
mailing list