[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 19:05:59 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 8329d98360c26ee559915f2caff560f24395ba28
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 | 208 ++++++++++++++++++++++++++++-------------
util/intelmetool/intelmetool.h | 8 +-
util/intelmetool/mmap.c | 4 -
util/intelmetool/msr.c | 78 ++++++++++++++++
util/intelmetool/msr.h | 43 +++++++++
6 files changed, 271 insertions(+), 72 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..c563efb 100644
--- a/util/intelmetool/intelmetool.c
+++ b/util/intelmetool/intelmetool.c
@@ -16,6 +16,8 @@
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
+#include <string.h>
+#include <cpuid.h>
#ifdef __NetBSD__
#include <machine/sysarch.h>
@@ -23,17 +25,16 @@
#include "me.h"
#include "mmap.h"
+#include "msr.h"
#include "intelmetool.h"
-#define FD2 0x3428
-#define ME_COMMAND_DELAY 10000
-
extern int fd_mem;
int debug = 0;
static uint32_t fd2 = 0;
static const int size = 0x4000;
static volatile uint8_t *rcba;
+static char cpu_id[CPU_ID_SIZE] = { 0 };
static void dumpmem(uint8_t *phys, uint32_t size)
{
@@ -72,6 +73,16 @@ static void rehide_me() {
}
}
+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);
+}
+
/* You need >4GB total ram, in kernel cmdline, use 'mem=1000m'
* then this code will clone to absolute memory address 0xe0000000
* which can be read using a mmap tool at that offset.
@@ -80,10 +91,14 @@ static void rehide_me() {
*/
static void dump_me_memory() {
uint32_t me_clone = 0x60000000;
- uint8_t *dump;
+ void *dump;
dump = map_physical_exact(me_clone, me_clone, 0x2000000);
- zeroit(dump, 0x2000000);
+ if(!dump) {
+ printf("ME physical memory can't be mapped!! Take a look at DMESG log.\n");
+ return;
+ }
+ zeroit((uint8_t*)dump, 0x2000000);
printf("Send magic command for memory clone\n");
mei_reset();
@@ -95,7 +110,7 @@ static void dump_me_memory() {
printf("Wait a second...");
usleep(ME_COMMAND_DELAY);
printf("done\n\nHere are the first bytes:\n");
- dumpmemfile(dump, 0x2000000);
+ dumpmemfile((uint8_t*)dump, 0x2000000);
//printf("Try reading 0x%zx with other mmap tool...\n"
// "Press enter to quit, you only get one chance to run this tool before reboot required for some reason\n", me_clone);
while (getc(stdin) != '\n') {};
@@ -103,10 +118,9 @@ static void dump_me_memory() {
}
}
-static int pci_platform_scan() {
+static int pci_platform_scan(char* msg) {
struct pci_access *pacc;
struct pci_dev *dev;
- char namebuf[1024], *name;
pacc = pci_alloc();
pacc->method = PCI_ACCESS_I386_TYPE1;
@@ -116,38 +130,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 (dev->vendor_id == INTEL_PLATFORM_VENDOR_ID) {
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);
+ snprintf(msg, ME_MESSAGE_LEN, CGRN "Good news, your ME is present but can be disabled, continuing...\n\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);
+ snprintf(msg, ME_MESSAGE_LEN, CRED "Bad news, you have ME hardware on board but you can't control or disable it, continuing...\n\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);
+ snprintf(msg, ME_MESSAGE_LEN, CYEL "Not sure if ME hardware is present, but it is possible to disable it if you do, continuing...\n\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;
+ snprintf(msg, ME_MESSAGE_LEN, CYEL "Not sure whether you have ME hardware, exiting\n\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) {
+ snprintf(msg, ME_MESSAGE_LEN, CCYN "ME is not present on your board or unkown\n\n" RESET);
}
pci_cleanup(pacc);
-
return 0;
}
@@ -166,7 +170,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;
@@ -206,7 +210,12 @@ static int activate_me() {
pci_fill_info(sb, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_SIZES | PCI_FILL_CLASS);
rcba_phys = pci_read_long(sb, 0xf0) & 0xfffffffe;
- rcba = map_physical(rcba_phys, size);
+ void* map = map_physical(rcba_phys, size);
+ if(!rcba) {
+ return 1;
+ } else {
+ rcba = (uint8_t*)map;
+ }
//printf("RCBA at 0x%08" PRIx32 "\n", (uint32_t)rcba_phys);
fd2 = *(uint32_t *)(rcba + FD2);
@@ -225,9 +234,9 @@ static int activate_me() {
static void dump_me_info() {
struct pci_dev *dev;
uint32_t stat, stat2;
- char *name;
+ char *name, msg[ME_MESSAGE_LEN] = { 0 };
- if (pci_platform_scan()) {
+ if (pci_platform_scan(msg)) {
exit(1);
}
@@ -236,10 +245,9 @@ static void dump_me_info() {
exit(1);
}
- if (activate_me()) {
- exit(1);
- }
+ activate_me();
+ printf("%s", msg);
printf("MEI found: [%x:%x] %s\n\n", dev->vendor_id, dev->device_id, name);
stat = pci_read_long(dev, 0x40);
printf("ME Status : 0x%x\n", stat);
@@ -271,10 +279,63 @@ static void dump_me_info() {
munmap((void*)rcba, size);
}
+static void dump_bootguard_info() {
+ struct pci_dev *dev;
+ uint32_t stat = 0;
+ char *name, msg[ME_MESSAGE_LEN] = { 0 };
+ uint64_t bootguard = 0;
+
+ if(msr_bootguard(&bootguard, debug) < 0) {
+ return;
+ }
+
+ pci_platform_scan(msg);
+ 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);
+ bootguard &= ~0xff;
+ }
+
+ if(BOOTGUARD_CAPABILITY(bootguard)) {
+ printf("ME Capability: BootGuard : YES\n");
+ if (dev && (stat & 0x10)) {
+ printf(CYEL "Your southbridge configuration is insecure!! BootGuard keys can be overwritten or wiped or you are in developer mode.\n" RESET);
+ }
+ switch(bootguard) {
+ case BOOTGUARD_DISABLED:
+ printf("ME Capability: 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 Capability: Bootguard Mode : Verified & Measured Boot\n");
+ printf(CRED "You can't flash other firmware. Verified boot is enabled!\n" RESET);
+ break;
+ case BOOTGUARD_ENABLED_MEASUREMENT_MODE:
+ printf("ME Capability: Bootguard Mode : Measured Boot\n");
+ printf(CGRN "Your system is bootguard ready but only running the measured boot mode. You can flash other firmware!\n" RESET);
+ break;
+ case BOOTGUARD_ENABLED_VERIFIED_MODE:
+ printf("ME Capability: Bootguard Mode : Verified Boot\n");
+ printf(CRED "You can't flash other firmware. Verified boot is enabled!\n" RESET);
+ break;
+ }
+ } else {
+ printf("ME Capability: BootGuard : 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"
@@ -287,13 +348,14 @@ static void print_version(void)
static void print_usage(const char *name)
{
- printf("usage: %s [-vh?sd]\n", name);
+ printf("usage: %s [-vh?mdb]\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"
+ " -m | --me dump all me related information on console\n"
+ " -b | --bootguard dump bootguard state of the platform\n"
+ " -d | --debug enable debug output\n"
+ "\n");
exit(1);
}
@@ -305,21 +367,25 @@ int main(int argc, char *argv[])
static struct option long_options[] = {
{"version", 0, 0, 'v'},
{"help", 0, 0, 'h'},
- {"show", 0, 0, 's'},
+ {"me", 0, 0, 'm'},
+ {"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?mdb",
+ long_options, &option_index)) != EOF) {
+ switch (opt) {
case 'v':
print_version();
exit(0);
break;
- case 's':
+ case 'm':
cmd_exec = 1;
break;
+ case 'b':
+ cmd_exec = 2;
+ break;
case 'd':
debug = 1;
break;
@@ -329,42 +395,52 @@ 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);
+ }
+
+ get_cpu_id(cpu_id);
+ if(strncmp(cpu_id, "GenuineIntel", CPU_ID_SIZE-1)) {
+ perror("Error CPU is not from Intel.");
+ 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:
+ dump_me_info();
+ dump_bootguard_info();
+ break;
}
return 0;
diff --git a/util/intelmetool/intelmetool.h b/util/intelmetool/intelmetool.h
index 4b9803b..ab2c0ea 100644
--- a/util/intelmetool/intelmetool.h
+++ b/util/intelmetool/intelmetool.h
@@ -22,7 +22,7 @@
#define ME_PRESENT_CAN_DISABLE 4
#define ME_PRESENT_CANNOT_DISABLE 5
-#define INTELMETOOL_VERSION "1.0"
+#define INTELMETOOL_VERSION "1.1"
#if defined(__GLIBC__)
#include <sys/io.h>
@@ -48,6 +48,12 @@
#define CWHT "\x1B[37m"
#define RESET "\033[0m"
+#define CPU_ID_SIZE 13
+#define FD2 0x3428
+#define ME_COMMAND_DELAY 10000
+#define ME_MESSAGE_LEN 256
+#define INTEL_PLATFORM_VENDOR_ID 0x8086
+
extern int debug;
// Definitely has ME and can be disabled
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..3172d0c
--- /dev/null
+++ b/util/intelmetool/msr.c
@@ -0,0 +1,78 @@
+/* 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 "msr.h"
+
+#ifndef __DARWIN__
+static int fd_msr = 0;
+
+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 == EIO) {
+ close(fd_msr);
+ return -2;
+ } else {
+ perror("Could not read() MSR");
+ close(fd_msr);
+ return -1;
+ }
+
+ return msr;
+}
+#endif
+
+int msr_bootguard(uint64_t *msr, int debug) {
+
+#ifndef __DARWIN__
+ fd_msr = open("/dev/cpu/0/msr", O_RDONLY);
+ if (fd_msr < 0) {
+ perror("Error while opening /dev/cpu/0/msr");
+ printf("Did you run 'modprobe msr'?\n");
+ return -1;
+ }
+
+ *msr = rdmsr(MSR_BOOTGUARD);
+#endif
+
+ if(debug) {
+ *msr &= ~0xff;
+ }
+
+ return 0;
+}
diff --git a/util/intelmetool/msr.h b/util/intelmetool/msr.h
new file mode 100644
index 0000000..b46a8da
--- /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 int msr_bootguard(uint64_t *msr, int debug);
+#endif
More information about the coreboot-gerrit
mailing list