summaryrefslogtreecommitdiff
path: root/util/intelmetool
diff options
context:
space:
mode:
authorPhilipp Deppenwiese <zaolin@das-labor.org>2016-08-26 02:10:51 +0200
committerPatrick Rudolph <siro@das-labor.org>2017-11-25 12:59:54 +0000
commit73add175cd866a5acd2bddb662080d6b03179d8b (patch)
tree55dbfd0fb2986ea4874d13c7459a4ff04e5aad3c /util/intelmetool
parent5e9dc37818a017fd5cccba65b9268d715e414380 (diff)
downloadcoreboot-73add175cd866a5acd2bddb662080d6b03179d8b.tar.xz
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! Changes done: * Add support for reading msr * Read ME firmware version * Print bootguard state for ME > 9.1 * Make argument -s legacy * Add argument -b for bootguard (and ME) dumping * Add argument -m for ME dumping * Opt out early if CPU is non Intel Change-Id: Ifeec8e20fa8efc35d7db4c6a84be1f118dccfc4a Signed-off-by: Philipp Deppenwiese <zaolin@das-labor.org> Signed-off-by: Patrick Rudolph <siro@das-labor.org> Reviewed-on: https://review.coreboot.org/16328 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Diffstat (limited to 'util/intelmetool')
-rw-r--r--util/intelmetool/Makefile2
-rw-r--r--util/intelmetool/intelmetool.c144
-rw-r--r--util/intelmetool/intelmetool.h22
-rw-r--r--util/intelmetool/me.c14
-rw-r--r--util/intelmetool/me.h2
-rw-r--r--util/intelmetool/msr.c78
-rw-r--r--util/intelmetool/msr.h30
7 files changed, 259 insertions, 33 deletions
diff --git a/util/intelmetool/Makefile b/util/intelmetool/Makefile
index 5862dcac11..b455a0ea86 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-sign-compare -Wno-unused-function
LDFLAGS += -lpci -lz
-OBJS = intelmetool.o me.o me_status.o mmap.o rcba.o
+OBJS = intelmetool.o me.o me_status.o mmap.o rcba.o msr.o
OS_ARCH = $(shell uname)
ifeq ($(OS_ARCH), Darwin)
diff --git a/util/intelmetool/intelmetool.c b/util/intelmetool/intelmetool.c
index 930aa03d0f..2e22899335 100644
--- a/util/intelmetool/intelmetool.c
+++ b/util/intelmetool/intelmetool.c
@@ -16,23 +16,25 @@
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
+#include <string.h>
+#include <cpuid.h>
#ifdef __NetBSD__
#include <machine/sysarch.h>
#endif
+#include "intelmetool.h"
#include "me.h"
#include "mmap.h"
-#include "intelmetool.h"
+#include "msr.h"
#include "rcba.h"
-#define FD2 0x3428
-#define ME_COMMAND_DELAY 10000
-
extern int fd_mem;
int debug = 0;
static uint32_t fd2 = 0;
+static int ME_major_ver = 0;
+static int ME_minor_ver = 0;
static void dumpmem(uint8_t *phys, uint32_t size)
{
@@ -62,6 +64,17 @@ static void dumpmemfile(uint8_t *phys, uint32_t size)
fclose(fp);
}
+static int isCPUGenuineIntel(void)
+{
+ regs_t regs;
+ unsigned int level = 0;
+ unsigned int eax = 0;
+
+ __get_cpuid(level, &eax, &regs.ebx, &regs.ecx, &regs.edx);
+
+ return !strncmp((char *)&regs, "GenuineIntel", CPU_ID_SIZE-1);
+}
+
/* 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.
@@ -278,7 +291,7 @@ static void dump_me_info(void)
usleep(ME_COMMAND_DELAY);
mei_reset();
usleep(ME_COMMAND_DELAY);
- mkhi_get_fw_version();
+ mkhi_get_fw_version(&ME_major_ver, &ME_minor_ver);
usleep(ME_COMMAND_DELAY);
mei_reset();
usleep(ME_COMMAND_DELAY);
@@ -288,21 +301,98 @@ static void dump_me_info(void)
rehide_me();
}
+static void dump_bootguard_info(void)
+{
+ struct pci_dev *dev;
+ char namebuf[1024];
+ const char *name;
+ uint64_t bootguard = 0;
+
+ if (msr_bootguard(&bootguard, debug) < 0)
+ return;
+
+ if (pci_platform_scan())
+ exit(1);
+
+ if (activate_me())
+ exit(1);
+
+ dev = pci_me_interface_scan(&name, namebuf, sizeof(namebuf));
+ if (!dev) {
+ printf("Can't access ME PCI device\n");
+ return;
+ }
+
+ if (debug) {
+ printf("BootGuard MSR Output: 0x%" PRIx64 "\n", bootguard);
+ bootguard &= ~0xff;
+ }
+
+ if (ME_major_ver < 9 ||
+ (ME_major_ver == 9 && ME_minor_ver < 5) ||
+ !BOOTGUARD_CAPABILITY(bootguard)) {
+ print_cap("BootGuard ", 0);
+ printf(CGRN "\nYour system isn't bootguard ready. You can "
+ "flash other firmware!\n" RESET);
+ rehide_me();
+ return;
+ }
+
+ print_cap("BootGuard ", 1);
+ if (pci_read_long(dev, 0x40) & 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: %-43s: " CGRN "%s\n" RESET,
+ "BootGuard Mode", "Disabled");
+ printf(CGRN "\nYour 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: %-43s: " CGRN "%s\n" RESET,
+ "BootGuard Mode", "Verified & Measured Boot");
+ printf(CRED "\nVerified boot is enabled. You can't flash other "
+ "firmware. !\n" RESET);
+ break;
+ case BOOTGUARD_ENABLED_MEASUREMENT_MODE:
+ printf("ME Capability: %-43s: " CGRN "%s\n" RESET,
+ "BootGuard Mode", "Measured Boot");
+ printf(CGRN "\nYour 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: %-43s: " CGRN "%s\n" RESET,
+ "BootGuard Mode", "Verified Boot");
+ printf(CRED "\nVerified boot is enabled! You can't flash other "
+ "firmware.\n" RESET);
+ break;
+ }
+ rehide_me();
+}
+
static void print_version(void)
{
printf("intelmetool v%s -- ", INTELMETOOL_VERSION);
- printf("Copyright (C) 2015 Damien Zammit\n\n");
+ printf("Copyright (C) 2015 Damien Zammit\n");
+ printf("Copyright (C) 2017 Philipp Deppenwiese\n");
+ printf("Copyright (C) 2017 Patrick Rudolph\n\n");
printf(GPLV2COPYRIGHT);
}
static void print_usage(const char *name)
{
- printf("usage: %s [-vh?sd]\n", name);
+ printf("usage: %s [-vh?smdb]\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"
+ " -v | --version: print the version\n"
+ " -h | --help: print this help\n\n"
+ " -d | --debug: enable debug output\n"
+ " -m | --me dump all me information on console\n"
+ " -b | --bootguard dump bootguard state of the platform\n"
"\n");
exit(1);
}
@@ -315,21 +405,27 @@ 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) {
+ while ((opt = getopt_long(argc, argv, "vh?smdb",
+ long_options, &option_index)) != EOF) {
switch (opt) {
case 'v':
print_version();
exit(0);
break;
- case 's':
+ case 's': /* Legacy fallthrough */
+ case 'm':
cmd_exec = 1;
break;
+ case 'b':
+ cmd_exec = 2;
+ break;
+ break;
case 'd':
debug = 1;
break;
@@ -342,6 +438,9 @@ int main(int argc, char *argv[])
}
}
+ if (!cmd_exec)
+ print_usage(argv[0]);
+
#if defined(__FreeBSD__)
if (open("/dev/io", O_RDWR) < 0) {
perror("/dev/io");
@@ -367,16 +466,17 @@ int main(int argc, char *argv[])
perror("Can not open /dev/mem");
exit(1);
}
+
+ if (!isCPUGenuineIntel()) {
+ perror("Error CPU is not from Intel.");
+ exit(1);
+ }
#endif
- switch(cmd_exec) {
- case 1:
+ if (cmd_exec & 3)
dump_me_info();
- break;
- default:
- print_usage(argv[0]);
- break;
- }
+ if (cmd_exec & 2)
+ dump_bootguard_info();
return 0;
}
diff --git a/util/intelmetool/intelmetool.h b/util/intelmetool/intelmetool.h
index 874df16a0f..49f053717d 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"
#define GPLV2COPYRIGHT \
"This program is free software: you can redistribute it and/or modify\n" \
@@ -57,7 +57,17 @@
#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
+
extern int debug;
+static inline void print_cap(const char *name, int state)
+{
+ printf("ME Capability: %-30s : %s\n",
+ name, state ? CRED "ON" RESET : CGRN "OFF" RESET);
+}
#define PCI_VENDOR_ID_INTEL 0x8086
@@ -295,3 +305,13 @@ extern int debug;
((x) == PCI_DEVICE_ID_INTEL_SUNRISE_H1) || \
((x) == PCI_DEVICE_ID_INTEL_SUNRISE_H2) || \
((x) == PCI_DEVICE_ID_INTEL_SUNRISE_LP))
+
+#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))
diff --git a/util/intelmetool/me.c b/util/intelmetool/me.c
index ff73aee2d6..6517022c64 100644
--- a/util/intelmetool/me.c
+++ b/util/intelmetool/me.c
@@ -22,9 +22,9 @@
#include <assert.h>
#include <unistd.h>
+#include "intelmetool.h"
#include "me.h"
#include "mmap.h"
-#include "intelmetool.h"
#define read32(addr, off) ( *((uint32_t *) (addr + off)) )
#define write32(addr, off, val) ( *((uint32_t *) (addr + off)) = val)
@@ -378,7 +378,7 @@ static int mkhi_end_of_post(void)
*/
/* Get ME firmware version */
-int mkhi_get_fw_version(void)
+int mkhi_get_fw_version(int *major, int *minor)
{
uint32_t data = 0;
struct me_fw_version version = {0};
@@ -420,15 +420,13 @@ int mkhi_get_fw_version(void)
printf("ME: Firmware Version %u.%u (code)\n\n"
version.code_major, version.code_minor);
#endif
+ if (major)
+ *major = version.code_major;
+ if (minor)
+ *minor = version.code_minor;
return 0;
}
-static inline void print_cap(const char *name, int state)
-{
- printf("ME Capability: %-30s : %s\n",
- name, state ? CRED "ON" RESET : CGRN "OFF" RESET);
-}
-
/* Get ME Firmware Capabilities */
int mkhi_get_fwcaps(void)
{
diff --git a/util/intelmetool/me.h b/util/intelmetool/me.h
index 76ee245753..ff69d7e7a5 100644
--- a/util/intelmetool/me.h
+++ b/util/intelmetool/me.h
@@ -400,7 +400,7 @@ void mkhi_thermal(void);
uint32_t intel_mei_setup(struct pci_dev *dev);
void intel_mei_unmap(void);
int mkhi_get_fwcaps(void);
-int mkhi_get_fw_version(void);
+int mkhi_get_fw_version(int *major, int *minor);
int mkhi_debug_me_memory(void *addr);
void mei_reset(void);
int intel_me_extend_valid(struct pci_dev *dev);
diff --git a/util/intelmetool/msr.c b/util/intelmetool/msr.c
new file mode 100644
index 0000000000..1010c0e324
--- /dev/null
+++ b/util/intelmetool/msr.c
@@ -0,0 +1,78 @@
+/* intelmetool
+ *
+ * Copyright (C) 2013-2016 Philipp Deppenwiese <zaolin@das-labor.org>,
+ * Copyright (C) 2013-2016 Alexander Couzens <lynxis@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) {
+ perror("IO error couldn't read MSR.");
+ close(fd_msr);
+ return -2;
+ }
+
+ perror("Couldn't read() MSR");
+ close(fd_msr);
+ return -1;
+}
+#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 0000000000..60e07b2409
--- /dev/null
+++ b/util/intelmetool/msr.h
@@ -0,0 +1,30 @@
+/* intelmetool
+ *
+ * Copyright (C) 2013-2016 Philipp Deppenwiese <zaolin@das-labor.org>
+ * Copyright (C) 2013-2016 Alexander Couzens <lynxis@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>
+
+#ifndef __DARWIN__
+
+#define MSR_BOOTGUARD 0x13A
+
+typedef struct {
+ unsigned int ebx;
+ unsigned int edx;
+ unsigned int ecx;
+} regs_t;
+
+extern int msr_bootguard(uint64_t *msr, int debug);
+#endif