diff options
Diffstat (limited to 'util/inteltool/pcr.c')
-rw-r--r-- | util/inteltool/pcr.c | 90 |
1 files changed, 90 insertions, 0 deletions
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); +} |