| /* |
| * 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); |
| } |