[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 03:40:12 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 2c849e8cf3b1dc6a8b255521ef132ec7a84209f5
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 | 155 +++++++++++++++++++++++++++++------------
 util/intelmetool/mmap.c        |   4 --
 util/intelmetool/msr.c         |  98 ++++++++++++++++++++++++++
 util/intelmetool/msr.h         |  43 ++++++++++++
 5 files changed, 253 insertions(+), 49 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..2bd03c1 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");
 
@@ -116,20 +122,18 @@ 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);
+				printf(CYEL "Found `%s`. Not sure whether you have ME hardware, exiting\n" RESET);
 				pci_cleanup(pacc);
 				return 1;
 				break;
@@ -138,10 +142,10 @@ static int pci_platform_scan() {
 	}
 
 	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_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" RESET);
 		pci_cleanup(pacc);
 		return 1;
 	}
@@ -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;
@@ -207,6 +211,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 +238,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,6 +278,58 @@ 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);
@@ -289,11 +348,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 +366,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 +381,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 +393,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