coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
tpm.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*
3  * This is a driver for a CRB Interface.
4  *
5  * The general flow looks like this:
6  *
7  * TPM starts in IDLE Mode
8  *
9  * IDLE --> READY --> Command Reception
10  * ^ |
11  * | v
12  -- Cmd Complete <-- Command Execution
13  */
14 
15 #include <timer.h>
16 #include <console/console.h>
17 #include <device/mmio.h>
18 #include <string.h>
19 #include <soc/pci_devs.h>
20 #include <device/pci_ops.h>
21 
22 #include "tpm.h"
23 
24 static struct control_area {
31  void *command_bfr;
33  void *response_bfr;
35 
36 static uint8_t cur_loc = 0;
37 
38 /* Read Control Area Structure back */
39 static void crb_readControlArea(void)
40 {
51 }
52 
53 /* Wait for Reg to be expected Value */
54 static int crb_wait_for_reg32(const void *addr, uint32_t timeoutMs, uint32_t mask,
55  uint32_t expectedValue)
56 {
57  uint32_t regValue;
58  struct stopwatch sw;
59 
60  // Set up a timer which breaks the loop after timeout
61  stopwatch_init_msecs_expire(&sw, timeoutMs);
62 
63  while (1) {
64  // Now check if the TPM is in IDLE mode
65  regValue = read32(addr);
66 
67  if ((regValue & mask) == expectedValue)
68  return 0;
69 
70  if (stopwatch_expired(&sw)) {
72  "CRB_WAIT: Error - Returning Zero with RegValue: %08x, Mask: %08x, Expected: %08x\n",
73  regValue, mask, expectedValue);
74  return -1;
75  }
76  }
77 }
78 
79 /* CRB PROBE
80  *
81  * Checks if the CRB Interface is ready
82  */
83 static int crb_probe(void)
84 {
86  printk(BIOS_SPEW, "Interface ID Reg. %llx\n", tpmStatus);
87 
88  if ((tpmStatus & CRB_INTF_REG_CAP_CRB) == 0) {
89  printk(BIOS_DEBUG, "TPM: CRB Interface is not supported.\n");
90  return -1;
91  }
92 
93  if ((tpmStatus & (0xf)) != 1) {
95  "TPM: CRB Interface is not active. System needs reboot in order to active TPM.\n");
97  return -1;
98  }
99 
102 
103  return 0;
104 }
105 
106 /*
107  * Get active Locality
108  *
109  * Get the active locality
110  */
112 {
113 
114  uint8_t locality = (read8(CRB_REG(0, CRB_REG_LOC_STATE)) >> 2) & 0x07;
115  printk(BIOS_SPEW, "Active locality: %i\n", locality);
116 
117  int rc = crb_wait_for_reg32(CRB_REG(locality, CRB_REG_LOC_STATE), 750,
119  if (!rc && (locality == 0))
120  return locality;
121 
122  if (rc)
124 
127  if (rc) {
128  printk(BIOS_ERR, "TPM: Error - No Locality has been assigned TPM-wise.\n");
129  return 0;
130  }
131 
132  rc = crb_wait_for_reg32(CRB_REG(locality, CRB_REG_LOC_STATE), 1500,
134  if (rc) {
135  printk(BIOS_ERR, "TPM: Error - LOC_STATE Register %u contains errors.\n",
136  locality);
137  return 0;
138  }
139 
140  return locality;
141 }
142 
143 /* Switch Device into a Ready State */
144 static int crb_switch_to_ready(void)
145 {
146  /* Transition into ready state */
150  if (rc) {
152  "TPM: Error - TPM did not transition into ready state in time.\n");
153  return -1;
154  }
155 
156  /* Check TPM_CRB_CTRL_STS[0] to be "0" - no unrecoverable error */
158  0x0);
159  if (rc) {
160  printk(BIOS_ERR, "TPM: Fatal Error - Could not recover.\n");
161  return -1;
162  }
163 
164  return 0;
165 }
166 
167 /*
168  * tpm2_init
169  *
170  * Even though the TPM does not need an initialization we check
171  * if the TPM responds and is in IDLE mode, which should be the
172  * normal bring up mode.
173  *
174  */
175 int tpm2_init(void)
176 {
177 
178  if (crb_probe()) {
179  printk(BIOS_ERR, "TPM: Probe failed.\n");
180  return -1;
181  }
182 
183  /* Read back control area structure */
185 
186  /* Good to go. */
187  printk(BIOS_SPEW, "TPM: CRB TPM initialized successfully\n");
188 
189  return 0;
190 }
191 
192 /*
193  * tpm2_process_command
194  */
195 size_t tpm2_process_command(const void *tpm2_command, size_t command_size, void *tpm2_response,
196  size_t max_response)
197 {
198  int rc;
199 
200  if (command_size > control_area.command_size) {
201  printk(BIOS_ERR, "TPM: Command size is too big.\n");
202  return -1;
203  }
204 
205  if (control_area.response_size < max_response) {
206  printk(BIOS_ERR, "TPM: Response size could be too big.\n");
207  return -1;
208  }
209 
211 
212  // Check if CMD bit is cleared.
214  if (rc) {
215  printk(BIOS_ERR, "TPM: Error - Cmd Bit not cleared.\n");
216  return -1;
217  }
218 
219  if (crb_switch_to_ready())
220  return -1;
221 
222  // Write to Command Buffer
223  memcpy(control_area.command_bfr, tpm2_command, command_size);
224 
225  // Write Start Bit
227 
228  // Poll for Response
230  if (rc) {
231  printk(BIOS_DEBUG, "TPM: Command Timed out.\n");
232  return -1;
233  }
234 
235  // Check for errors
237  if (rc) {
238  printk(BIOS_DEBUG, "TPM: Command errored.\n");
239  return -1;
240  }
241 
242  // Get Response Length
243  uint32_t length = be32_to_cpu(read32(control_area.response_bfr + 2));
244 
245  /* Response has to have at least 6 bytes */
246  if (length < 6)
247  return 1;
248 
249  // Copy Response
251 
252  if (crb_switch_to_ready()) {
253  printk(BIOS_DEBUG, "TPM: Can not transition into ready state again.\n");
254  return -1;
255  }
256 
257  return length;
258 }
259 
260 /*
261  * tp2_get_info
262  *
263  * Returns information about the TPM
264  *
265  */
267 {
268  uint64_t interfaceReg = read64(CRB_REG(cur_loc, CRB_REG_INTF_ID));
269 
270  tpm2_info->vendor_id = (interfaceReg >> 48) & 0xFFFF;
271  tpm2_info->device_id = (interfaceReg >> 32) & 0xFFFF;
272  tpm2_info->revision = (interfaceReg >> 24) & 0xFF;
273 }
static void write8(void *addr, uint8_t val)
Definition: mmio.h:30
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
uint64_t read64(const void *addr)
static uint8_t read8(const void *addr)
Definition: mmio.h:12
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
static u32 addr
Definition: cirrus.c:14
#define printk(level,...)
Definition: stdlib.h:16
static void crb_readControlArea(void)
Definition: tpm.c:39
static struct control_area control_area
static uint8_t cur_loc
Definition: tpm.c:36
int tpm2_init(void)
Definition: tpm.c:175
static int crb_probe(void)
Definition: tpm.c:83
static uint8_t crb_activate_locality(void)
Definition: tpm.c:111
static int crb_switch_to_ready(void)
Definition: tpm.c:144
size_t tpm2_process_command(const void *tpm2_command, size_t command_size, void *tpm2_response, size_t max_response)
Definition: tpm.c:195
void tpm2_get_info(struct tpm2_info *tpm2_info)
Definition: tpm.c:266
static int crb_wait_for_reg32(const void *addr, uint32_t timeoutMs, uint32_t mask, uint32_t expectedValue)
Definition: tpm.c:54
#define CRB_REG_REQUEST
Definition: tpm.h:27
#define CRB_REG_CMD_ADDR
Definition: tpm.h:33
#define CRB_REG_STATUS
Definition: tpm.h:28
#define CRB_REG_LOC_STATE
Definition: tpm.h:12
#define CRB_INTF_REG_INTF_SEL
Definition: tpm.h:39
#define LOC_STATE_REG_VALID_STS
Definition: tpm.h:21
#define CRB_REG_RESP_SIZE
Definition: tpm.h:34
#define LOC_STATE_LOC_ASSIGN
Definition: tpm.h:20
#define CRB_REG_REQUEST_CMD_RDY
Definition: tpm.h:43
#define CRB_REG_INT_CTRL
Definition: tpm.h:31
#define LOC_CTRL_REQ_ACCESS
Definition: tpm.h:17
#define CRB_REG_INTF_ID
Definition: tpm.h:26
#define CRB_REG_LOC_CTRL
Definition: tpm.h:13
#define CRB_REG(LOCTY, REG)
Definition: tpm.h:8
#define CRB_REG_START
Definition: tpm.h:30
#define CRB_INTF_REG_INTF_LOCK
Definition: tpm.h:40
#define CRB_REG_CANCEL
Definition: tpm.h:29
#define CRB_REG_STATUS_ERROR
Definition: tpm.h:47
#define CRB_REG_START_START
Definition: tpm.h:51
#define CRB_REG_RESP_ADDR
Definition: tpm.h:35
#define CRB_INTF_REG_CAP_CRB
Definition: tpm.h:38
#define CRB_REG_CMD_SIZE
Definition: tpm.h:32
uint64_t length
Definition: fw_cfg_if.h:1
static int stopwatch_expired(struct stopwatch *sw)
Definition: timer.h:152
static void stopwatch_init_msecs_expire(struct stopwatch *sw, long ms)
Definition: timer.h:133
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_SPEW
BIOS_SPEW - Excessively verbose output.
Definition: loglevel.h:142
static const int mask[4]
Definition: gpio.c:308
unsigned int uint32_t
Definition: stdint.h:14
unsigned long uintptr_t
Definition: stdint.h:21
unsigned long long uint64_t
Definition: stdint.h:17
unsigned char uint8_t
Definition: stdint.h:8
uint32_t start
Definition: tpm.c:28
uint32_t response_size
Definition: tpm.c:32
uint32_t request
Definition: tpm.c:25
uint32_t cancel
Definition: tpm.c:27
void * command_bfr
Definition: tpm.c:31
void * response_bfr
Definition: tpm.c:33
uint32_t status
Definition: tpm.c:26
uint32_t command_size
Definition: tpm.c:30
uint64_t interrupt_control
Definition: tpm.c:29
Definition: tpm.h:54
uint16_t device_id
Definition: tpm.h:56
uint16_t revision
Definition: tpm.h:57
uint16_t vendor_id
Definition: tpm.h:55