diff options
author | Nico Huber <nico.huber@secunet.com> | 2017-04-05 17:39:57 +0200 |
---|---|---|
committer | Stefan Reinauer <stefan.reinauer@coreboot.org> | 2018-01-15 01:18:05 +0000 |
commit | 99b02a1d7c486d0b4083cbfdafe2a92de4975362 (patch) | |
tree | d4221e5772446d5158f642bec6cfbc20fe351aa6 | |
parent | 76a4f71e89722fd579daa559a1d24b3d710dbed6 (diff) | |
download | coreboot-99b02a1d7c486d0b4083cbfdafe2a92de4975362.tar.xz |
inteltool: Support for nasty Primary to Sideband Bridge (P2SB)
The Primary to Sideband Bridge (P2SB) is the interface to Private Con-
figuration Registers (PCR) including GPIO configuration. Of course,
access is restricted to Intel partners and criminals, so the PCI device
is hidden from the OS. Probably we only need to fetch the SBREG_BAR
address and can hide the PCI device again after that.
Change-Id: Ic121a09f021708aab82ae4b9d76d6c3c6fb884fa
Signed-off-by: Nico Huber <nico.huber@secunet.com>
Reviewed-on: https://review.coreboot.org/19588
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
-rw-r--r-- | util/inteltool/Makefile | 3 | ||||
-rw-r--r-- | util/inteltool/inteltool.c | 3 | ||||
-rw-r--r-- | util/inteltool/inteltool.h | 6 | ||||
-rw-r--r-- | util/inteltool/pcr.c | 90 | ||||
-rw-r--r-- | util/inteltool/pcr.h | 30 |
5 files changed, 131 insertions, 1 deletions
diff --git a/util/inteltool/Makefile b/util/inteltool/Makefile index 179bea9f85..d0f04899f0 100644 --- a/util/inteltool/Makefile +++ b/util/inteltool/Makefile @@ -27,7 +27,8 @@ LDFLAGS += -lpci -lz CPPFLAGS += -I$(top)/src/commonlib/include -OBJS = inteltool.o cpu.o gpio.o rootcmplx.o powermgt.o memory.o pcie.o amb.o ivy_memory.o spi.o gfx.o ahci.o +OBJS = inteltool.o pcr.o cpu.o gpio.o rootcmplx.o powermgt.o \ + memory.o pcie.o amb.o ivy_memory.o spi.o gfx.o ahci.o \ OS_ARCH = $(shell uname) ifeq ($(OS_ARCH), Darwin) diff --git a/util/inteltool/inteltool.c b/util/inteltool/inteltool.c index 688e74342f..7cd4363129 100644 --- a/util/inteltool/inteltool.c +++ b/util/inteltool/inteltool.c @@ -24,6 +24,7 @@ #include <sys/mman.h> #include <unistd.h> #include "inteltool.h" +#include "pcr.h" #ifdef __NetBSD__ #include <machine/sysarch.h> @@ -511,6 +512,7 @@ int main(int argc, char *argv[]) #endif pacc = pci_alloc(); + pacc->method = PCI_ACCESS_I386_TYPE1; pci_init(pacc); pci_scan_bus(pacc); @@ -681,6 +683,7 @@ int main(int argc, char *argv[]) print_sgx(); /* Clean up */ + pcr_cleanup(); if (ahci) pci_free_dev(ahci); if (gfx) diff --git a/util/inteltool/inteltool.h b/util/inteltool/inteltool.h index 512bdbaee3..22eda6ead8 100644 --- a/util/inteltool/inteltool.h +++ b/util/inteltool/inteltool.h @@ -14,6 +14,9 @@ * GNU General Public License for more details. */ +#ifndef INTELTOOL_H +#define INTELTOOL_H 1 + #include <commonlib/helpers.h> #include <stdint.h> @@ -139,6 +142,7 @@ static inline uint32_t inl(unsigned port) #define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_PREM 0x9cc3 #define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP 0x9cc5 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_SATA 0xa102 +#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_P2SB 0xa120 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_PRE 0xa141 #define PCI_DEVICE_ID_INTEL_H110 0xa143 #define PCI_DEVICE_ID_INTEL_H170 0xa144 @@ -307,3 +311,5 @@ int print_gfx(struct pci_dev *gfx); int print_ahci(struct pci_dev *ahci); int print_sgx(void); void ivybridge_dump_timings(const char *dump_spd_file); + +#endif diff --git a/util/inteltool/pcr.c b/util/inteltool/pcr.c new file mode 100644 index 0000000000..0310e2eba1 --- /dev/null +++ b/util/inteltool/pcr.c @@ -0,0 +1,90 @@ +/* + * inteltool - dump all registers on an Intel CPU + chipset based system. + * + * Copyright (C) 2017 secunet Security Networks AG + * + * 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; version 2 of the License. + * + * 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 <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <inttypes.h> +#include <assert.h> +#include "pcr.h" + +const uint8_t *sbbar = NULL; + +uint32_t read_pcr32(const uint8_t port, const uint16_t offset) +{ + assert(sbbar); + return *(const uint32_t *)(sbbar + (port << 16) + offset); +} + +void pcr_init(struct pci_dev *const sb) +{ + bool error_exit = false; + bool p2sb_revealed = false; + + if (sbbar) + return; + + struct pci_dev *const p2sb = pci_get_dev(sb->access, 0, 0, 0x1f, 1); + + if (!p2sb) { + perror("Can't allocate device node for P2SB."); + exit(1); + } + + /* do not fill bases here, libpci refuses to refill later */ + pci_fill_info(p2sb, PCI_FILL_IDENT); + if (p2sb->vendor_id == 0xffff && p2sb->device_id == 0xffff) { + printf("Trying to reveal Primary to Sideband Bridge " + "(P2SB),\nlet's hope the OS doesn't mind... "); + /* Do not use pci_write_long(). Surrounding + bytes 0xe0 must be maintained. */ + pci_write_byte(p2sb, 0xe0 + 1, 0); + + pci_fill_info(p2sb, PCI_FILL_IDENT | PCI_FILL_RESCAN); + if (p2sb->vendor_id != 0xffff || + p2sb->device_id != 0xffff) { + printf("done.\n"); + p2sb_revealed = true; + } else { + printf("failed.\n"); + exit(1); + } + } + pci_fill_info(p2sb, PCI_FILL_BASES | PCI_FILL_CLASS); + + const pciaddr_t sbbar_phys = p2sb->base_addr[0] & ~0xfULL; + printf("SBREG_BAR = 0x%08"PRIx64" (MEM)\n\n", (uint64_t)sbbar_phys); + sbbar = map_physical(sbbar_phys, SBBAR_SIZE); + if (sbbar == NULL) { + perror("Error mapping SBREG_BAR"); + error_exit = true; + } + + if (p2sb_revealed) { + printf("Hiding Primary to Sideband Bridge (P2SB).\n"); + pci_write_byte(p2sb, 0xe0 + 1, 1); + } + pci_free_dev(p2sb); + + if (error_exit) + exit(1); +} + +void pcr_cleanup(void) +{ + if (sbbar) + unmap_physical((void *)sbbar, SBBAR_SIZE); +} diff --git a/util/inteltool/pcr.h b/util/inteltool/pcr.h new file mode 100644 index 0000000000..601cfb6874 --- /dev/null +++ b/util/inteltool/pcr.h @@ -0,0 +1,30 @@ +/* + * inteltool - dump all registers on an Intel CPU + chipset based system. + * + * Copyright (C) 2017 secunet Security Networks AG + * + * 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; version 2 of the License. + * + * 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. + */ + +#ifndef INTELTOOL_PCR_H +#define INTELTOOL_PCR_H 1 + +#include <stdint.h> +#include "inteltool.h" + +#define SBBAR_SIZE (16 * MiB) +#define PCR_PORT_SIZE (64 * KiB) + +uint32_t read_pcr32(uint8_t port, uint16_t offset); + +void pcr_init(struct pci_dev *sb); +void pcr_cleanup(void); + +#endif |