blob: ef6bb39d1637b9dfe9e94bc7d693f83c02300b28 [file] [log] [blame]
Nico Huber99b02a12017-04-05 17:39:57 +02001/*
2 * inteltool - dump all registers on an Intel CPU + chipset based system.
3 *
4 * Copyright (C) 2017 secunet Security Networks AG
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <stdint.h>
19#include <stdbool.h>
20#include <inttypes.h>
21#include <assert.h>
22#include "pcr.h"
23
24const uint8_t *sbbar = NULL;
25
26uint32_t read_pcr32(const uint8_t port, const uint16_t offset)
27{
28 assert(sbbar);
29 return *(const uint32_t *)(sbbar + (port << 16) + offset);
30}
31
Youness Alaouid8214d7e2018-03-13 16:58:52 -040032static void print_pcr_port(const uint8_t port)
33{
34 size_t i = 0;
35 uint32_t last_reg = 0;
36 bool last_printed = true;
37
38 printf("PCR port offset: 0x%06zx\n\n", (size_t)port << 16);
39
40 for (i = 0; i < PCR_PORT_SIZE; i += 4) {
41 const uint32_t reg = read_pcr32(port, i);
42 const bool rep = i && last_reg == reg;
43 if (!rep) {
44 if (!last_printed)
45 printf("*\n");
46 printf("0x%04zx: 0x%08"PRIx32"\n", i, reg);
47 }
48
49 last_reg = reg;
50 last_printed = !rep;
51 }
52 if (!last_printed)
53 printf("*\n");
54}
55
56void print_pcr_ports(struct pci_dev *const sb,
57 const uint8_t *const ports, const size_t count)
58{
59 size_t i;
60
61 pcr_init(sb);
62
63 for (i = 0; i < count; ++i) {
64 printf("\n========== PCR 0x%02x ==========\n\n", ports[i]);
65 print_pcr_port(ports[i]);
66 }
67}
68
Nico Huber99b02a12017-04-05 17:39:57 +020069void pcr_init(struct pci_dev *const sb)
70{
71 bool error_exit = false;
72 bool p2sb_revealed = false;
Nico Huber94473af2018-11-20 12:10:29 +010073 struct pci_dev *p2sb;
Thomas Heijligen725369f2019-02-19 10:51:34 +000074 bool use_p2sb = true;
75 pciaddr_t sbbar_phys;
Nico Huber99b02a12017-04-05 17:39:57 +020076
77 if (sbbar)
78 return;
79
Nico Huber94473af2018-11-20 12:10:29 +010080 switch (sb->device_id) {
81 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_PRE:
Felix Singer0a7543d2019-02-19 23:49:11 +010082 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_PRE:
83 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_SKL:
84 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_SKL:
85 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_SKL:
86 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_BASE_KBL:
87 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_PREM_KBL:
88 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_PREM_KBL:
Shaleen Jain2822d662019-01-02 11:15:16 +053089 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_BASE:
90 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_U_IHDCP_PREM:
91 case PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_Y_IHDCP_PREM:
Nico Huber94473af2018-11-20 12:10:29 +010092 case PCI_DEVICE_ID_INTEL_H110:
93 case PCI_DEVICE_ID_INTEL_H170:
94 case PCI_DEVICE_ID_INTEL_Z170:
95 case PCI_DEVICE_ID_INTEL_Q170:
96 case PCI_DEVICE_ID_INTEL_Q150:
97 case PCI_DEVICE_ID_INTEL_B150:
98 case PCI_DEVICE_ID_INTEL_C236:
99 case PCI_DEVICE_ID_INTEL_C232:
100 case PCI_DEVICE_ID_INTEL_QM170:
101 case PCI_DEVICE_ID_INTEL_HM170:
102 case PCI_DEVICE_ID_INTEL_CM236:
103 case PCI_DEVICE_ID_INTEL_HM175:
104 case PCI_DEVICE_ID_INTEL_QM175:
105 case PCI_DEVICE_ID_INTEL_CM238:
Maxim Polyakovb89ce2e2019-08-17 14:54:02 +0300106 case PCI_DEVICE_ID_INTEL_C621:
107 case PCI_DEVICE_ID_INTEL_C622:
108 case PCI_DEVICE_ID_INTEL_C624:
109 case PCI_DEVICE_ID_INTEL_C625:
110 case PCI_DEVICE_ID_INTEL_C626:
111 case PCI_DEVICE_ID_INTEL_C627:
112 case PCI_DEVICE_ID_INTEL_C628:
113 case PCI_DEVICE_ID_INTEL_C629:
114 case PCI_DEVICE_ID_INTEL_C624_SUPER:
115 case PCI_DEVICE_ID_INTEL_C627_SUPER_1:
116 case PCI_DEVICE_ID_INTEL_C621_SUPER:
117 case PCI_DEVICE_ID_INTEL_C627_SUPER_2:
118 case PCI_DEVICE_ID_INTEL_C628_SUPER:
Thomas Heijligenda027192019-01-12 19:20:50 +0100119 case PCI_DEVICE_ID_INTEL_DNV_LPC:
Nico Huber94473af2018-11-20 12:10:29 +0100120 p2sb = pci_get_dev(sb->access, 0, 0, 0x1f, 1);
121 break;
122 case PCI_DEVICE_ID_INTEL_APL_LPC:
123 p2sb = pci_get_dev(sb->access, 0, 0, 0x0d, 0);
124 break;
Thomas Heijligen725369f2019-02-19 10:51:34 +0000125 case PCI_DEVICE_ID_INTEL_H310:
126 case PCI_DEVICE_ID_INTEL_H370:
127 case PCI_DEVICE_ID_INTEL_Z390:
128 case PCI_DEVICE_ID_INTEL_Q370:
129 case PCI_DEVICE_ID_INTEL_B360:
130 case PCI_DEVICE_ID_INTEL_C246:
131 case PCI_DEVICE_ID_INTEL_C242:
132 case PCI_DEVICE_ID_INTEL_QM370:
133 case PCI_DEVICE_ID_INTEL_HM370:
134 case PCI_DEVICE_ID_INTEL_CM246:
135 sbbar_phys = 0xfd000000;
136 use_p2sb = false;
137 break;
Nico Huber94473af2018-11-20 12:10:29 +0100138 default:
139 perror("Unknown LPC device.");
140 exit(1);
141 }
Nico Huber99b02a12017-04-05 17:39:57 +0200142
Thomas Heijligen725369f2019-02-19 10:51:34 +0000143 if (use_p2sb) {
144 if (!p2sb) {
145 perror("Can't allocate device node for P2SB.");
Nico Huber99b02a12017-04-05 17:39:57 +0200146 exit(1);
147 }
Nico Huber99b02a12017-04-05 17:39:57 +0200148
Thomas Heijligen725369f2019-02-19 10:51:34 +0000149 /* do not fill bases here, libpci refuses to refill later */
150 pci_fill_info(p2sb, PCI_FILL_IDENT);
151 if (p2sb->vendor_id == 0xffff && p2sb->device_id == 0xffff) {
152 printf("Trying to reveal Primary to Sideband Bridge "
153 "(P2SB),\nlet's hope the OS doesn't mind... ");
154 /* Do not use pci_write_long(). Bytes
155 surrounding 0xe0 must be maintained. */
156 pci_write_byte(p2sb, 0xe0 + 1, 0);
157
158 pci_fill_info(p2sb, PCI_FILL_IDENT | PCI_FILL_RESCAN);
159 if (p2sb->vendor_id != 0xffff ||
160 p2sb->device_id != 0xffff) {
161 printf("done.\n");
162 p2sb_revealed = true;
163 } else {
164 printf("failed.\n");
165 exit(1);
166 }
167 }
168 pci_fill_info(p2sb, PCI_FILL_BASES | PCI_FILL_CLASS);
169
170 sbbar_phys = p2sb->base_addr[0] & ~0xfULL;
171 }
172
Nico Huber99b02a12017-04-05 17:39:57 +0200173 printf("SBREG_BAR = 0x%08"PRIx64" (MEM)\n\n", (uint64_t)sbbar_phys);
174 sbbar = map_physical(sbbar_phys, SBBAR_SIZE);
175 if (sbbar == NULL) {
176 perror("Error mapping SBREG_BAR");
177 error_exit = true;
178 }
179
Thomas Heijligen725369f2019-02-19 10:51:34 +0000180 if (use_p2sb) {
181 if (p2sb_revealed) {
182 printf("Hiding Primary to Sideband Bridge (P2SB).\n");
183 pci_write_byte(p2sb, 0xe0 + 1, 1);
184 }
185 pci_free_dev(p2sb);
Nico Huber99b02a12017-04-05 17:39:57 +0200186 }
Nico Huber99b02a12017-04-05 17:39:57 +0200187
188 if (error_exit)
189 exit(1);
190}
191
192void pcr_cleanup(void)
193{
194 if (sbbar)
195 unmap_physical((void *)sbbar, SBBAR_SIZE);
196}