diff options
author | Philipp Deppenwiese <zaolin@das-labor.org> | 2016-08-26 02:10:51 +0200 |
---|---|---|
committer | Patrick Rudolph <siro@das-labor.org> | 2017-11-25 12:59:54 +0000 |
commit | 73add175cd866a5acd2bddb662080d6b03179d8b (patch) | |
tree | 55dbfd0fb2986ea4874d13c7459a4ff04e5aad3c | |
parent | 5e9dc37818a017fd5cccba65b9268d715e414380 (diff) |
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>
-rw-r--r-- | util/intelmetool/Makefile | 2 | ||||
-rw-r--r-- | util/intelmetool/intelmetool.c | 144 | ||||
-rw-r--r-- | util/intelmetool/intelmetool.h | 22 | ||||
-rw-r--r-- | util/intelmetool/me.c | 14 | ||||
-rw-r--r-- | util/intelmetool/me.h | 2 | ||||
-rw-r--r-- | util/intelmetool/msr.c | 78 | ||||
-rw-r--r-- | util/intelmetool/msr.h | 30 |
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, ®s.ebx, ®s.ecx, ®s.edx); + + return !strncmp((char *)®s, "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 |