| /* inteltool - dump all registers on an Intel CPU + chipset based system */ |
| /* SPDX-License-Identifier: GPL-2.0-only */ |
| |
| #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); |
| } |
| |
| static void print_pcr_port(const uint8_t port) |
| { |
| size_t i = 0; |
| uint32_t last_reg = 0; |
| bool last_printed = true; |
| |
| printf("PCR port offset: 0x%06zx\n\n", (size_t)port << 16); |
| |
| for (i = 0; i < PCR_PORT_SIZE; i += 4) { |
| const uint32_t reg = read_pcr32(port, i); |
| const bool rep = i && last_reg == reg; |
| if (!rep) { |
| if (!last_printed) |
| printf("*\n"); |
| printf("0x%04zx: 0x%08"PRIx32"\n", i, reg); |
| } |
| |
| last_reg = reg; |
| last_printed = !rep; |
| } |
| if (!last_printed) |
| printf("*\n"); |
| } |
| |
| void print_pcr_ports(struct pci_dev *const sb, |
| const uint8_t *const ports, const size_t count) |
| { |
| size_t i; |
| |
| pcr_init(sb); |
| |
| for (i = 0; i < count; ++i) { |
| printf("\n========== PCR 0x%02x ==========\n\n", ports[i]); |
| print_pcr_port(ports[i]); |
| } |
| } |
| |
| void pcr_init(struct pci_dev *const sb) |
| { |
| bool error_exit = false; |
| bool p2sb_revealed = false; |
| struct pci_dev *p2sb; |
| bool use_p2sb = true; |
| pciaddr_t sbbar_phys; |
| |
| if (sbbar) |
| return; |
| |
| switch (sb->device_id) { |
| case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_PRE: |
| case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_PRE: |
| case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_SKL: |
| case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_SKL: |
| case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_SKL: |
| case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_KBL: |
| case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_KBL: |
| case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_KBL: |
| case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_BASE: |
| case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_PREM: |
| case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_IHDCP_PREM: |
| case PCI_DEVICE_ID_INTEL_H110: |
| case PCI_DEVICE_ID_INTEL_H170: |
| case PCI_DEVICE_ID_INTEL_Z170: |
| case PCI_DEVICE_ID_INTEL_Q170: |
| case PCI_DEVICE_ID_INTEL_Q150: |
| case PCI_DEVICE_ID_INTEL_B150: |
| case PCI_DEVICE_ID_INTEL_C236: |
| case PCI_DEVICE_ID_INTEL_C232: |
| case PCI_DEVICE_ID_INTEL_QM170: |
| case PCI_DEVICE_ID_INTEL_HM170: |
| case PCI_DEVICE_ID_INTEL_CM236: |
| case PCI_DEVICE_ID_INTEL_HM175: |
| case PCI_DEVICE_ID_INTEL_QM175: |
| case PCI_DEVICE_ID_INTEL_CM238: |
| case PCI_DEVICE_ID_INTEL_H270: |
| case PCI_DEVICE_ID_INTEL_Z270: |
| case PCI_DEVICE_ID_INTEL_Q270: |
| case PCI_DEVICE_ID_INTEL_Q250: |
| case PCI_DEVICE_ID_INTEL_B250: |
| case PCI_DEVICE_ID_INTEL_Z370: |
| case PCI_DEVICE_ID_INTEL_H310C: |
| case PCI_DEVICE_ID_INTEL_X299: |
| case PCI_DEVICE_ID_INTEL_C621: |
| case PCI_DEVICE_ID_INTEL_C621A: |
| case PCI_DEVICE_ID_INTEL_C622: |
| case PCI_DEVICE_ID_INTEL_C624: |
| case PCI_DEVICE_ID_INTEL_C625: |
| case PCI_DEVICE_ID_INTEL_C626: |
| case PCI_DEVICE_ID_INTEL_C627: |
| case PCI_DEVICE_ID_INTEL_C628: |
| case PCI_DEVICE_ID_INTEL_C629: |
| case PCI_DEVICE_ID_INTEL_C624_SUPER: |
| case PCI_DEVICE_ID_INTEL_C627_SUPER_1: |
| case PCI_DEVICE_ID_INTEL_C621_SUPER: |
| case PCI_DEVICE_ID_INTEL_C627_SUPER_2: |
| case PCI_DEVICE_ID_INTEL_C628_SUPER: |
| case PCI_DEVICE_ID_INTEL_DNV_LPC: |
| p2sb = pci_get_dev(sb->access, 0, 0, 0x1f, 1); |
| break; |
| case PCI_DEVICE_ID_INTEL_APL_LPC: |
| case PCI_DEVICE_ID_INTEL_GLK_LPC: |
| p2sb = pci_get_dev(sb->access, 0, 0, 0x0d, 0); |
| break; |
| case PCI_DEVICE_ID_INTEL_H310: |
| case PCI_DEVICE_ID_INTEL_H370: |
| case PCI_DEVICE_ID_INTEL_Z390: |
| case PCI_DEVICE_ID_INTEL_Q370: |
| case PCI_DEVICE_ID_INTEL_B360: |
| case PCI_DEVICE_ID_INTEL_C246: |
| case PCI_DEVICE_ID_INTEL_C242: |
| case PCI_DEVICE_ID_INTEL_QM370: |
| case PCI_DEVICE_ID_INTEL_HM370: |
| case PCI_DEVICE_ID_INTEL_CM246: |
| case PCI_DEVICE_ID_INTEL_Q570: |
| case PCI_DEVICE_ID_INTEL_Z590: |
| case PCI_DEVICE_ID_INTEL_H570: |
| case PCI_DEVICE_ID_INTEL_B560: |
| case PCI_DEVICE_ID_INTEL_H510: |
| case PCI_DEVICE_ID_INTEL_WM590: |
| case PCI_DEVICE_ID_INTEL_QM580: |
| case PCI_DEVICE_ID_INTEL_HM570: |
| case PCI_DEVICE_ID_INTEL_C252: |
| case PCI_DEVICE_ID_INTEL_C256: |
| case PCI_DEVICE_ID_INTEL_W580: |
| case PCI_DEVICE_ID_INTEL_CANNONPOINT_LP_U_PREM: |
| case PCI_DEVICE_ID_INTEL_COMETPOINT_LP_U_PREM: |
| case PCI_DEVICE_ID_INTEL_COMETPOINT_LP_U_BASE: |
| case PCI_DEVICE_ID_INTEL_ICELAKE_LP_U: |
| case PCI_DEVICE_ID_INTEL_TIGERPOINT_U_SUPER: |
| case PCI_DEVICE_ID_INTEL_TIGERPOINT_U_PREM: |
| case PCI_DEVICE_ID_INTEL_TIGERPOINT_U_BASE: |
| case PCI_DEVICE_ID_INTEL_TIGERPOINT_Y_SUPER: |
| case PCI_DEVICE_ID_INTEL_TIGERPOINT_Y_PREM: |
| case PCI_DEVICE_ID_INTEL_ADL_P: |
| case PCI_DEVICE_ID_INTEL_ADL_M: |
| case PCI_DEVICE_ID_INTEL_RPL_P: |
| case PCI_DEVICE_ID_INTEL_EHL: |
| case PCI_DEVICE_ID_INTEL_JSL: |
| case PCI_DEVICE_ID_INTEL_EBG: |
| sbbar_phys = 0xfd000000; |
| use_p2sb = false; |
| break; |
| case PCI_DEVICE_ID_INTEL_H610E: |
| case PCI_DEVICE_ID_INTEL_Q670E: |
| case PCI_DEVICE_ID_INTEL_R680E: |
| case PCI_DEVICE_ID_INTEL_H610: |
| case PCI_DEVICE_ID_INTEL_B660: |
| case PCI_DEVICE_ID_INTEL_H670: |
| case PCI_DEVICE_ID_INTEL_Q670: |
| case PCI_DEVICE_ID_INTEL_Z690: |
| case PCI_DEVICE_ID_INTEL_W680: |
| case PCI_DEVICE_ID_INTEL_W685: |
| case PCI_DEVICE_ID_INTEL_WM690: |
| case PCI_DEVICE_ID_INTEL_HM670: |
| case PCI_DEVICE_ID_INTEL_WM790: |
| case PCI_DEVICE_ID_INTEL_HM770: |
| sbbar_phys = 0xe0000000; |
| use_p2sb = false; |
| break; |
| default: |
| perror("Unknown LPC device."); |
| exit(1); |
| } |
| |
| if (use_p2sb) { |
| 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(). Bytes |
| surrounding 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); |
| |
| 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 (use_p2sb) { |
| 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); |
| } |