/ src / drivers / crb / tis.c
tis.c
  1  /* SPDX-License-Identifier: GPL-2.0-only */
  2  
  3  #include <console/console.h>
  4  #include <security/tpm/tis.h>
  5  #include <acpi/acpigen.h>
  6  #include <device/device.h>
  7  #include <drivers/intel/ptt/ptt.h>
  8  #include <drivers/tpm/tpm_ppi.h>
  9  #include <security/tpm/tss.h>
 10  #include <endian.h>
 11  #include <smbios.h>
 12  #include <string.h>
 13  
 14  #include "tpm.h"
 15  #include "chip.h"
 16  
 17  static const struct {
 18  	uint16_t vid;
 19  	uint16_t did;
 20  	const char *device_name;
 21  } dev_map[] = {
 22  	{0x1ae0, 0x0028, "CR50"},
 23  	{0xa13a, 0x8086, "Intel iTPM"}
 24  };
 25  
 26  static const char *tis_get_dev_name(struct crb_tpm_info *info)
 27  {
 28  	int i;
 29  
 30  	for (i = 0; i < ARRAY_SIZE(dev_map); i++)
 31  		if ((dev_map[i].vid == info->vendor_id) && (dev_map[i].did == info->device_id))
 32  			return dev_map[i].device_name;
 33  	return "Unknown";
 34  }
 35  
 36  static tpm_result_t crb_tpm_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, uint8_t *recvbuf,
 37  				     size_t *rbuf_len)
 38  {
 39  	int len = crb_tpm_process_command(sendbuf, sbuf_size, recvbuf, *rbuf_len);
 40  
 41  	if (len == 0)
 42  		return TPM_CB_FAIL;
 43  
 44  	*rbuf_len = len;
 45  
 46  	return TPM_SUCCESS;
 47  }
 48  
 49  tis_sendrecv_fn crb_tis_probe(enum tpm_family *family)
 50  {
 51  	struct crb_tpm_info info;
 52  
 53  	if (CONFIG(HAVE_INTEL_PTT)) {
 54  		if (!ptt_active()) {
 55  			printk(BIOS_ERR, "%s: Intel PTT is not active.\n", __func__);
 56  			return NULL;
 57  		}
 58  		printk(BIOS_DEBUG, "%s: Intel PTT is active.\n", __func__);
 59  	}
 60  
 61  	/* Wake TPM up (if necessary) */
 62  	if (crb_tpm_init())
 63  		return NULL;
 64  
 65  	/* CRB interface exists only in TPM2 */
 66  	if (family != NULL)
 67  		*family = TPM_2;
 68  
 69  	crb_tpm_get_info(&info);
 70  
 71  	printk(BIOS_INFO, "Initialized TPM device %s revision %d\n", tis_get_dev_name(&info),
 72  	       info.revision);
 73  
 74  	return &crb_tpm_sendrecv;
 75  }
 76  
 77  static void crb_tpm_fill_ssdt(const struct device *dev)
 78  {
 79  	const char *path = acpi_device_path(dev);
 80  	if (!path) {
 81  		path = "\\_SB_.TPM";
 82  		printk(BIOS_DEBUG, "Using default TPM2 ACPI path: '%s'\n", path);
 83  	}
 84  
 85  	/* Device */
 86  	acpigen_write_device(path);
 87  
 88  	acpigen_write_name_string("_HID", "MSFT0101");
 89  	acpigen_write_name_string("_CID", "MSFT0101");
 90  
 91  	acpi_device_write_uid(dev);
 92  
 93  	if (CONFIG(HAVE_INTEL_PTT) && ptt_active())
 94  		acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
 95  	else
 96  		acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_OFF);
 97  
 98  	/* Resources */
 99  	acpigen_write_name("_CRS");
100  	acpigen_write_resourcetemplate_header();
101  	acpigen_write_mem32fixed(1, TPM_CRB_BASE_ADDRESS, 0x5000);
102  
103  	acpigen_write_resourcetemplate_footer();
104  
105  	if (!CONFIG(CHROMEOS) && CONFIG(TPM_PPI))
106  		tpm_ppi_acpi_fill_ssdt(dev);
107  
108  	acpigen_pop_len(); /* Device */
109  }
110  
111  static const char *crb_tpm_acpi_name(const struct device *dev)
112  {
113  	return "TPM";
114  }
115  
116  #if CONFIG(GENERATE_SMBIOS_TABLES) && CONFIG(TPM2)
117  static tpm_result_t tpm_get_cap(uint32_t property, uint32_t *value)
118  {
119  	TPMS_CAPABILITY_DATA cap_data;
120  	int i;
121  	tpm_result_t rc;
122  
123  	if (!value)
124  		return TPM_CB_INVALID_ARG;
125  
126  	rc = tlcl2_get_capability(TPM_CAP_TPM_PROPERTIES, property, 1, &cap_data);
127  
128  	if (rc)
129  		return rc;
130  
131  	for (i = 0 ; i < cap_data.data.tpmProperties.count; i++) {
132  		if (cap_data.data.tpmProperties.tpmProperty[i].property == property) {
133  			*value = cap_data.data.tpmProperties.tpmProperty[i].value;
134  			return TPM_SUCCESS;
135  		}
136  	}
137  
138  	return TPM_CB_FAIL;
139  }
140  
141  static int smbios_write_type43_tpm(struct device *dev, int *handle, unsigned long *current)
142  {
143  	struct crb_tpm_info info;
144  	uint32_t tpm_manuf, tpm_family;
145  	uint32_t fw_ver1, fw_ver2;
146  	uint8_t major_spec_ver, minor_spec_ver;
147  
148  	if (tlcl_get_family() == TPM_1)
149  		return 0;
150  
151  	crb_tpm_get_info(&info);
152  
153  	/* If any of these have invalid values, assume TPM not present or disabled */
154  	if (info.vendor_id == 0 || info.vendor_id == 0xFFFF ||
155  	    info.device_id == 0 || info.device_id == 0xFFFF) {
156  		printk(BIOS_DEBUG, "%s: Invalid Vendor ID/Device ID\n", __func__);
157  		return 0;
158  	}
159  
160  	/* Vendor ID is the value returned by TPM2_GetCapabiltiy TPM_PT_MANUFACTURER */
161  	if (tpm_get_cap(TPM_PT_MANUFACTURER, &tpm_manuf)) {
162  		printk(BIOS_DEBUG, "TPM2_GetCap TPM_PT_MANUFACTURER failed\n");
163  		return 0;
164  	}
165  
166  	tpm_manuf = be32toh(tpm_manuf);
167  
168  	if (tpm_get_cap(TPM_PT_FIRMWARE_VERSION_1, &fw_ver1)) {
169  		printk(BIOS_DEBUG, "TPM2_GetCap TPM_PT_FIRMWARE_VERSION_1 failed\n");
170  		return 0;
171  	}
172  
173  	if (tpm_get_cap(TPM_PT_FIRMWARE_VERSION_2, &fw_ver2)) {
174  		printk(BIOS_DEBUG, "TPM2_GetCap TPM_PT_FIRMWARE_VERSION_2 failed\n");
175  		return 0;
176  	}
177  
178  	if (tpm_get_cap(TPM_PT_FAMILY_INDICATOR, &tpm_family)) {
179  		printk(BIOS_DEBUG, "TPM2_GetCap TPM_PT_FAMILY_INDICATOR failed\n");
180  		return 0;
181  	}
182  
183  	tpm_family = be32toh(tpm_family);
184  
185  	if (!strncmp((char *)&tpm_family, "2.0", 4)) {
186  		major_spec_ver = 2;
187  		minor_spec_ver = 0;
188  	} else {
189  		printk(BIOS_ERR, "%s: Invalid TPM family\n", __func__);
190  		return 0;
191  	}
192  
193  	return smbios_write_type43(current, handle, tpm_manuf, major_spec_ver, minor_spec_ver,
194  				   fw_ver1, fw_ver2, tis_get_dev_name(&info),
195  				   SMBIOS_TPM_DEVICE_CHARACTERISTICS_NOT_SUPPORTED, 0);
196  }
197  #endif
198  
199  static struct device_operations __maybe_unused crb_ops = {
200  	.read_resources = noop_read_resources,
201  	.set_resources = noop_set_resources,
202  #if CONFIG(HAVE_ACPI_TABLES)
203  	.acpi_name = crb_tpm_acpi_name,
204  	.acpi_fill_ssdt = crb_tpm_fill_ssdt,
205  #endif
206  #if CONFIG(GENERATE_SMBIOS_TABLES) && CONFIG(TPM2)
207  	.get_smbios_data	= smbios_write_type43_tpm,
208  #endif
209  };
210  
211  static void enable_dev(struct device *dev)
212  {
213  	if (crb_tis_probe(NULL) == NULL) {
214  		dev->enabled = 0;
215  		return;
216  	}
217  
218  #if !DEVTREE_EARLY
219  	dev->ops = &crb_ops;
220  #endif
221  }
222  
223  struct chip_operations drivers_crb_ops = {
224  	.name = "CRB TPM",
225  	.enable_dev = enable_dev
226  };