drivers/crb: Add CRB driver for TPM2 support
Add the Command Response Buffer which is defined in the TPM 2.0 Specs. CRB can be specified with MAINBOARD_HAS_CRB_TPM, even though it is actually SoC/SB specific. Change-Id: I477e45963fe3cdbc02cda9ae99c19142747e4b46 Signed-off-by: Christian Walter <christian.walter@9elements.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/34106 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
This commit is contained in:
parent
c703814e95
commit
7706a04c60
|
@ -0,0 +1,17 @@
|
|||
config CRB_TPM
|
||||
bool
|
||||
help
|
||||
CRB TPM driver is enabled!
|
||||
|
||||
config CRB_TPM_BASE_ADDRESS
|
||||
hex
|
||||
default 0xfed40000
|
||||
help
|
||||
Base Address of the CRB TPM Command Structure
|
||||
|
||||
config MAINBOARD_HAS_CRB_TPM
|
||||
bool
|
||||
default n
|
||||
select CRB_TPM
|
||||
help
|
||||
Mainboard has Command Response Buffer support
|
|
@ -0,0 +1,5 @@
|
|||
bootblock-$(CONFIG_CRB_TPM) += tis.c tpm.c
|
||||
verstage-$(CONFIG_CRB_TPM) += tis.c tpm.c
|
||||
romstage-$(CONFIG_CRB_TPM) += tis.c tpm.c
|
||||
ramstage-$(CONFIG_CRB_TPM) += tis.c tpm.c
|
||||
postcar-$(CONFIG_CRB_TPM) += tis.c tpm.c
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2014 Google Inc. All Rights Reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef DRIVERS_CRB_CHIP_H
|
||||
#define DRIVERS_CRB_CHIP_H
|
||||
|
||||
typedef struct drivers_crb_config {
|
||||
} tpm_config_t;
|
||||
|
||||
#endif /* DRIVERS_CRB_CHIP_H */
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* 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 <arch/early_variables.h>
|
||||
#include <console/console.h>
|
||||
#include <security/tpm/tis.h>
|
||||
#include <arch/acpigen.h>
|
||||
#include <device/device.h>
|
||||
|
||||
#include "tpm.h"
|
||||
#include "chip.h"
|
||||
|
||||
static unsigned tpm_is_open CAR_GLOBAL;
|
||||
|
||||
static const struct {
|
||||
uint16_t vid;
|
||||
uint16_t did;
|
||||
const char *device_name;
|
||||
} dev_map[] = {
|
||||
{0x1ae0, 0x0028, "CR50"},
|
||||
{0xa13a, 0x8086, "Intel iTPM"}
|
||||
};
|
||||
|
||||
static const char *tis_get_dev_name(struct tpm2_info *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dev_map); i++)
|
||||
if ((dev_map[i].vid == info->vendor_id) && (dev_map[i].did == info->device_id))
|
||||
return dev_map[i].device_name;
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
|
||||
int tis_open(void)
|
||||
{
|
||||
if (car_get_var(tpm_is_open)) {
|
||||
printk(BIOS_ERR, "%s called twice.\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tis_close(void)
|
||||
{
|
||||
if (car_get_var(tpm_is_open)) {
|
||||
|
||||
/*
|
||||
* Do we need to do something here, like waiting for a
|
||||
* transaction to stop?
|
||||
*/
|
||||
car_set_var(tpm_is_open, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tis_init(void)
|
||||
{
|
||||
struct tpm2_info info;
|
||||
|
||||
// Wake TPM up (if necessary)
|
||||
if (tpm2_init() != 0)
|
||||
return -1;
|
||||
|
||||
tpm2_get_info(&info);
|
||||
|
||||
printk(BIOS_INFO, "Initialized TPM device %s revision %d\n", tis_get_dev_name(&info),
|
||||
info.revision);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, uint8_t *recvbuf, size_t *rbuf_len)
|
||||
{
|
||||
int len = tpm2_process_command(sendbuf, sbuf_size, recvbuf, *rbuf_len);
|
||||
|
||||
if (len == 0)
|
||||
return -1;
|
||||
|
||||
*rbuf_len = len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __RAMSTAGE__
|
||||
|
||||
static void crb_tpm_fill_ssdt(struct device *dev)
|
||||
{
|
||||
const char *path = acpi_device_path(dev);
|
||||
if (!path) {
|
||||
path = "\\_SB_.TPM";
|
||||
printk(BIOS_DEBUG, "Using default TPM2 ACPI path: '%s'\n", path);
|
||||
}
|
||||
|
||||
/* Device */
|
||||
acpigen_write_device(path);
|
||||
|
||||
acpigen_write_name_string("_HID", "MSFT0101");
|
||||
acpigen_write_name_string("_CID", "MSFT0101");
|
||||
|
||||
acpigen_write_name_integer("_UID", 1);
|
||||
|
||||
acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
|
||||
|
||||
/* Resources */
|
||||
acpigen_write_name("_CRS");
|
||||
acpigen_write_resourcetemplate_header();
|
||||
acpigen_write_mem32fixed(1, TPM_CRB_BASE_ADDRESS, 0x5000);
|
||||
|
||||
acpigen_write_resourcetemplate_footer();
|
||||
|
||||
acpigen_pop_len(); /* Device */
|
||||
}
|
||||
|
||||
static const char *crb_tpm_acpi_name(const struct device *dev)
|
||||
{
|
||||
return "TPM";
|
||||
}
|
||||
|
||||
static struct device_operations crb_ops = {
|
||||
.read_resources = DEVICE_NOOP,
|
||||
.set_resources = DEVICE_NOOP,
|
||||
#if CONFIG(HAVE_ACPI_TABLES)
|
||||
.acpi_name = crb_tpm_acpi_name,
|
||||
.acpi_fill_ssdt_generator = crb_tpm_fill_ssdt,
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
static void enable_dev(struct device *dev)
|
||||
{
|
||||
dev->ops = &crb_ops;
|
||||
}
|
||||
|
||||
struct chip_operations drivers_crb_ops = {CHIP_NAME("CRB TPM").enable_dev = enable_dev};
|
||||
|
||||
#endif /* __RAMSTAGE__ */
|
|
@ -0,0 +1,280 @@
|
|||
/*.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*
|
||||
* This is a driver for a CRB Interface.
|
||||
*
|
||||
* The general flow looks like this:
|
||||
*
|
||||
* TPM starts in IDLE Mode
|
||||
*
|
||||
* IDLE --> READY --> Command Receiption
|
||||
* ^ |
|
||||
* | v
|
||||
-- Cmd Complete <-- Command Execution
|
||||
*/
|
||||
|
||||
#include <timer.h>
|
||||
#include <arch/early_variables.h>
|
||||
#include <console/console.h>
|
||||
#include <arch/mmio.h>
|
||||
#include <delay.h>
|
||||
#include <string.h>
|
||||
#include <endian.h>
|
||||
#include <soc/pci_devs.h>
|
||||
#include <device/pci_ops.h>
|
||||
|
||||
#include "tpm.h"
|
||||
|
||||
static struct control_area {
|
||||
uint32_t request;
|
||||
uint32_t status;
|
||||
uint32_t cancel;
|
||||
uint32_t start;
|
||||
uint64_t interrupt_control;
|
||||
uint32_t command_size;
|
||||
void *command_bfr;
|
||||
uint32_t response_size;
|
||||
void *response_bfr;
|
||||
} control_area;
|
||||
|
||||
static uint8_t cur_loc = 0;
|
||||
|
||||
/* Read Control Area Structure back */
|
||||
static void crb_readControlArea(void)
|
||||
{
|
||||
control_area.request = read32(CRB_REG(cur_loc, CRB_REG_REQUEST));
|
||||
control_area.status = read32(CRB_REG(cur_loc, CRB_REG_STATUS));
|
||||
control_area.cancel = read32(CRB_REG(cur_loc, CRB_REG_CANCEL));
|
||||
control_area.interrupt_control = read64(CRB_REG(cur_loc, CRB_REG_INT_CTRL));
|
||||
control_area.command_size = read32(CRB_REG(cur_loc, CRB_REG_CMD_SIZE));
|
||||
control_area.command_bfr = (void *)(uint32_t)read64(CRB_REG(cur_loc, CRB_REG_CMD_ADDR));
|
||||
control_area.response_size = read32(CRB_REG(cur_loc, CRB_REG_RESP_SIZE));
|
||||
control_area.response_bfr =
|
||||
(void *)(uint32_t)read64(CRB_REG(cur_loc, CRB_REG_RESP_ADDR));
|
||||
}
|
||||
|
||||
/* Wait for Reg to be expected Value */
|
||||
static int crb_wait_for_reg32(const void *addr, uint32_t timeoutMs, uint32_t mask,
|
||||
uint32_t expectedValue)
|
||||
{
|
||||
uint32_t regValue;
|
||||
struct stopwatch sw;
|
||||
|
||||
// Set up a timer which breaks the loop after timeout
|
||||
stopwatch_init_msecs_expire(&sw, timeoutMs);
|
||||
|
||||
while (1) {
|
||||
// Now check if the TPM is in IDLE mode
|
||||
regValue = read32(addr);
|
||||
|
||||
if ((regValue & mask) == expectedValue)
|
||||
return 0;
|
||||
|
||||
if (stopwatch_expired(&sw)) {
|
||||
printk(BIOS_ERR,
|
||||
"CRB_WAIT: Error - Returning Zero with RegValue: %08x, Mask: %08x, Expected: %08x\n",
|
||||
regValue, mask, expectedValue);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* CRB PROBE
|
||||
*
|
||||
* Checks if the CRB Interface is ready
|
||||
*/
|
||||
static int crb_probe(void)
|
||||
{
|
||||
uint64_t tpmStatus = read64(CRB_REG(cur_loc, CRB_REG_INTF_ID));
|
||||
printk(BIOS_SPEW, "Interface ID Reg. %llx\n", tpmStatus);
|
||||
|
||||
if ((tpmStatus & CRB_INTF_REG_CAP_CRB) == 0) {
|
||||
printk(BIOS_DEBUG, "TPM: CRB Interface is not supported.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((tpmStatus & (0xf)) != 1) {
|
||||
printk(BIOS_DEBUG,
|
||||
"TPM: CRB Interface is not active. System needs reboot in order to active TPM.\n");
|
||||
write32(CRB_REG(cur_loc, CRB_REG_INTF_ID), CRB_INTF_REG_INTF_SEL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
write32(CRB_REG(cur_loc, CRB_REG_INTF_ID), CRB_INTF_REG_INTF_SEL);
|
||||
write32(CRB_REG(cur_loc, CRB_REG_INTF_ID), CRB_INTF_REG_INTF_LOCK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get active Locality
|
||||
*
|
||||
* Get the active locality
|
||||
*/
|
||||
static uint8_t crb_activate_locality(void)
|
||||
{
|
||||
|
||||
uint8_t locality = (read8(CRB_REG(0, CRB_REG_LOC_STATE)) >> 2) & 0x07;
|
||||
printk(BIOS_SPEW, "Active locality: %i\n", locality);
|
||||
|
||||
int rc = crb_wait_for_reg32(CRB_REG(locality, CRB_REG_LOC_STATE), 750,
|
||||
LOC_STATE_LOC_ASSIGN, LOC_STATE_LOC_ASSIGN);
|
||||
if (!rc && (locality == 0))
|
||||
return locality;
|
||||
|
||||
if (rc)
|
||||
write8(CRB_REG(locality, CRB_REG_LOC_CTRL), LOC_CTRL_REQ_ACCESS);
|
||||
|
||||
|
||||
rc = crb_wait_for_reg32(CRB_REG(locality, CRB_REG_LOC_STATE), 750, LOC_STATE_LOC_ASSIGN,
|
||||
LOC_STATE_LOC_ASSIGN);
|
||||
if (rc) {
|
||||
printk(BIOS_ERR, "TPM: Error - No Locality has been assigned TPM-wise.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = crb_wait_for_reg32(CRB_REG(locality, CRB_REG_LOC_STATE), 1500,
|
||||
LOC_STATE_REG_VALID_STS, LOC_STATE_REG_VALID_STS);
|
||||
if (rc) {
|
||||
printk(BIOS_ERR, "TPM: Error - LOC_STATE Register %u contains errors.\n",
|
||||
locality);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return locality;
|
||||
}
|
||||
|
||||
/* Switch Device into a Ready State */
|
||||
static int crb_switch_to_ready(void)
|
||||
{
|
||||
/* Transition into ready state */
|
||||
write8(CRB_REG(cur_loc, CRB_REG_REQUEST), 0x1);
|
||||
int rc = crb_wait_for_reg32(CRB_REG(cur_loc, CRB_REG_REQUEST), 200,
|
||||
CRB_REG_REQUEST_CMD_RDY, 0x0);
|
||||
if (rc) {
|
||||
printk(BIOS_ERR,
|
||||
"TPM: Error - TPM did not transition into ready state in time.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check TPM_CRB_CTRL_STS[0] to be "0" - no unrecoverable error */
|
||||
rc = crb_wait_for_reg32(CRB_REG(cur_loc, CRB_REG_STATUS), 500, CRB_REG_STATUS_ERROR,
|
||||
0x0);
|
||||
if (rc) {
|
||||
printk(BIOS_ERR, "TPM: Fatal Error - Could not recover.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* tpm2_init
|
||||
*
|
||||
* Even though the TPM does not need an initialization we check
|
||||
* if the TPM responds and is in IDLE mode, which should be the
|
||||
* normal bring up mode.
|
||||
*
|
||||
*/
|
||||
int tpm2_init(void)
|
||||
{
|
||||
|
||||
|
||||
if (crb_probe()) {
|
||||
printk(BIOS_ERR, "TPM: Probe failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read back control area structure */
|
||||
crb_readControlArea();
|
||||
|
||||
/* Good to go. */
|
||||
printk(BIOS_SPEW, "TPM: CRB TPM initialized successfully\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* tpm2_process_command
|
||||
*/
|
||||
size_t tpm2_process_command(const void *tpm2_command, size_t command_size, void *tpm2_response,
|
||||
size_t max_response)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (command_size > control_area.command_size) {
|
||||
printk(BIOS_ERR, "TPM: Command size is too big.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (control_area.response_size < max_response) {
|
||||
printk(BIOS_ERR, "TPM: Response size could be too big.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
cur_loc = crb_activate_locality();
|
||||
|
||||
// Check if CMD bit is cleared.
|
||||
rc = crb_wait_for_reg32(CRB_REG(0, CRB_REG_START), 250, CRB_REG_START_START, 0x0);
|
||||
if (rc) {
|
||||
printk(BIOS_ERR, "TPM: Error - Cmd Bit not cleared.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (crb_switch_to_ready())
|
||||
return -1;
|
||||
|
||||
// Write to Command Buffer
|
||||
memcpy(control_area.command_bfr, tpm2_command, command_size);
|
||||
|
||||
// Write Start Bit
|
||||
write8(CRB_REG(cur_loc, CRB_REG_START), 0x1);
|
||||
|
||||
// Poll for Response
|
||||
rc = crb_wait_for_reg32(CRB_REG(cur_loc, CRB_REG_START), 3500, CRB_REG_START_START, 0);
|
||||
if (rc) {
|
||||
printk(BIOS_DEBUG, "TPM: Command Timed out.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check for errors
|
||||
rc = crb_wait_for_reg32(CRB_REG(cur_loc, CRB_REG_STATUS), 200, CRB_REG_STATUS_ERROR, 0);
|
||||
if (rc) {
|
||||
printk(BIOS_DEBUG, "TPM: Command errored.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get Response Length
|
||||
uint32_t length = be32_to_cpu(read32(control_area.response_bfr + 2));
|
||||
|
||||
/* Response has to have at least 6 bytes */
|
||||
if (length < 6)
|
||||
return 1;
|
||||
|
||||
// Copy Response
|
||||
memcpy(tpm2_response, control_area.response_bfr, length);
|
||||
|
||||
if (crb_switch_to_ready()) {
|
||||
printk(BIOS_DEBUG, "TPM: Can not transition into ready state again.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
/*
|
||||
* tp2_get_info
|
||||
*
|
||||
* Returns information about the TPM
|
||||
*
|
||||
*/
|
||||
void tpm2_get_info(struct tpm2_info *tpm2_info)
|
||||
{
|
||||
uint64_t interfaceReg = read64(CRB_REG(cur_loc, CRB_REG_INTF_ID));
|
||||
|
||||
tpm2_info->vendor_id = (interfaceReg >> 48) & 0xFFFF;
|
||||
tpm2_info->device_id = (interfaceReg >> 32) & 0xFFFF;
|
||||
tpm2_info->revision = (interfaceReg >> 24) & 0xFF;
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright 2016 The Chromium OS Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*
|
||||
* This is a driver for a Command Response Buffer Interface
|
||||
*/
|
||||
|
||||
/* CRB driver */
|
||||
/* address of locality 0 (CRB) */
|
||||
#define TPM_CRB_BASE_ADDRESS CONFIG_CRB_TPM_BASE_ADDRESS
|
||||
|
||||
#define CRB_REG(LOCTY, REG) \
|
||||
(void *)(CONFIG_CRB_TPM_BASE_ADDRESS + (LOCTY << 12) + REG)
|
||||
|
||||
/* hardware registers */
|
||||
#define CRB_REG_LOC_STATE 0x00
|
||||
#define CRB_REG_LOC_CTRL 0x08
|
||||
#define CRB_REG_LOC_STS 0x0C
|
||||
|
||||
/* LOC_CTRL BIT MASKS */
|
||||
#define LOC_CTRL_REQ_ACCESS 0x01
|
||||
|
||||
/* LOC STATE BIT MASKS */
|
||||
#define LOC_STATE_LOC_ASSIGN 0x02
|
||||
#define LOC_STATE_REG_VALID_STS 0x80
|
||||
|
||||
/* LOC STS BIT MASKS */
|
||||
#define LOC_STS_GRANTED 0x01
|
||||
|
||||
#define CRB_REG_INTF_ID 0x30
|
||||
#define CRB_REG_REQUEST 0x40
|
||||
#define CRB_REG_STATUS 0x44
|
||||
#define CRB_REG_CANCEL 0x48
|
||||
#define CRB_REG_START 0x4C
|
||||
#define CRB_REG_INT_CTRL 0x50
|
||||
#define CRB_REG_CMD_SIZE 0x58
|
||||
#define CRB_REG_CMD_ADDR 0x5C
|
||||
#define CRB_REG_RESP_SIZE 0x64
|
||||
#define CRB_REG_RESP_ADDR 0x68
|
||||
|
||||
/* CRB INTF BIT MASK */
|
||||
#define CRB_INTF_REG_CAP_CRB (1<<14)
|
||||
#define CRB_INTF_REG_INTF_SEL (1<<17)
|
||||
#define CRB_INTF_REG_INTF_LOCK (1<<19)
|
||||
|
||||
|
||||
/*REQUEST Register related */
|
||||
#define CRB_REG_REQUEST_CMD_RDY 0x01
|
||||
#define CRB_REG_REQUEST_GO_IDLE 0x02
|
||||
|
||||
/* STATUS Register related */
|
||||
#define CRB_REG_STATUS_ERROR 0x01
|
||||
#define CRB_REG_STATUS_IDLE 0x02
|
||||
|
||||
/* START Register related */
|
||||
#define CRB_REG_START_START 0x01
|
||||
|
||||
/* TPM Info Struct */
|
||||
struct tpm2_info {
|
||||
uint16_t vendor_id;
|
||||
uint16_t device_id;
|
||||
uint16_t revision;
|
||||
};
|
||||
|
||||
|
||||
int tpm2_init(void);
|
||||
void tpm2_get_info(struct tpm2_info *tpm2_info);
|
||||
size_t tpm2_process_command(const void *tpm2_command, size_t command_size,
|
||||
void *tpm2_response, size_t max_response);
|
|
@ -28,7 +28,7 @@ config TPM2
|
|||
default y if MAINBOARD_HAS_TPM2 || USER_TPM2
|
||||
depends on MAINBOARD_HAS_I2C_TPM_GENERIC || MAINBOARD_HAS_LPC_TPM \
|
||||
|| MAINBOARD_HAS_I2C_TPM_ATMEL || MAINBOARD_HAS_I2C_TPM_CR50 \
|
||||
|| MAINBOARD_HAS_SPI_TPM_CR50
|
||||
|| MAINBOARD_HAS_SPI_TPM_CR50 || MAINBOARD_HAS_CRB_TPM
|
||||
|
||||
config MAINBOARD_HAS_TPM1
|
||||
bool
|
||||
|
@ -58,7 +58,7 @@ config USER_TPM2
|
|||
bool "2.0"
|
||||
depends on MAINBOARD_HAS_I2C_TPM_GENERIC || MAINBOARD_HAS_LPC_TPM \
|
||||
|| MAINBOARD_HAS_I2C_TPM_ATMEL || MAINBOARD_HAS_I2C_TPM_CR50 \
|
||||
|| MAINBOARD_HAS_SPI_TPM_CR50
|
||||
|| MAINBOARD_HAS_SPI_TPM_CR50 || MAINBOARD_HAS_CRB_TPM
|
||||
help
|
||||
Enable this option to enable TPM 2.0 support in coreboot.
|
||||
|
||||
|
|
Loading…
Reference in New Issue