Karthik Ramasubramanian has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/44277 )
Change subject: drivers/spi/tpm: Add support to cache the TPM firmware version ......................................................................
drivers/spi/tpm: Add support to cache the TPM firmware version
TPM firmware version is required for couple of use-cases during ramstage - GPIO PM configuration for Intel SoCs, Board specific reset when CSE Lite jumps from RO to RW. This change adds support to read the TPM firmware version and cache it.
BUG=b:154333137, b:162290856 TEST=Ensure that the DUT boots to OS. Ensure that the firmware version is cached and matches with the firmware version logged in the bootup logs.
Change-Id: I2c894d619f6b986be196a9da6ee4556bc440424e --- M src/drivers/spi/tpm/tpm.c M src/drivers/spi/tpm/tpm.h 2 files changed, 148 insertions(+), 6 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/77/44277/1
diff --git a/src/drivers/spi/tpm/tpm.c b/src/drivers/spi/tpm/tpm.c index b44c87e..dac405a 100644 --- a/src/drivers/spi/tpm/tpm.c +++ b/src/drivers/spi/tpm/tpm.c @@ -35,6 +35,7 @@ #define CR50_TIMEOUT_INIT_MS 30000 /* Very long timeout for TPM init */
#define TPM_FW_VER_STRLEN 301 +#define TPM_FW_VER_COUNT 2 /* One for RO and one for RW */
/* SPI slave structure for TPM device. */ static struct spi_slave spi_slave; @@ -42,6 +43,9 @@ /* Cached TPM device identification. */ static struct tpm2_info tpm_info;
+/* Cached TPM FW Version. */ +static struct tpm2_fw_ver tpm_fw_ver[TPM_FW_VER_COUNT]; + /* * TODO(vbendeb): make CONFIG(DEBUG_TPM) an int to allow different level of * debug traces. Right now it is either 0 or 1. @@ -423,20 +427,96 @@ return 0; }
+/** + * Extract the TPM firmware version from the tokenized firmware version string. + * @fw_ver : Tokenized firmware version string. + * @cache : Buffer to cache the firmware version. + * + * @return: 0 on success, -1 on error. + * + * The RO/RW tokenized firmware version string is of the below format: + * "<region_type>_<region_label>:<epoch>.<major_ver>.<minor_ver>/<hash>" + * where region_type : "RO" or "RW" + * region_label : "A" or "B" + */ +static int cache_tpm_fw_version(char *fw_ver, struct tpm2_fw_ver *cache) +{ + /* + */ + char *str = fw_ver + 5; /* Skip past the colon. */ + enum tpm2_fw_ver_type type = TPM2_FW_VER_TYPE_INIT; + + if (!strncmp(fw_ver, "RO_", strlen("RO_"))) + type = TPM2_FW_VER_TYPE_RO; + else if (!strncmp(fw_ver, "RW_", strlen("RW_"))) + type = TPM2_FW_VER_TYPE_RW; + + if (type == TPM2_FW_VER_TYPE_INIT) + return -1; + + cache->epoch = skip_atoi(&str); + if (*str++ != '.') { + printk(BIOS_ERR, "Error parsing after epoch\n"); + return -1; + } + cache->major_ver = skip_atoi(&str); + if (*str++ != '.') { + printk(BIOS_ERR, "Error parsing after major version\n"); + return -1; + } + cache->minor_ver = skip_atoi(&str); + if (*str != '/') { + printk(BIOS_ERR, "Error parsing after minor version\n"); + return -1; + } + + /* Caching the type marks successful caching of firmware version. */ + cache->type = type; + return 0; +} + +/** + * Helper to parse the firmware version string read from TPM. + * @vstr : Firmware version string read from TPM. + * + * The firmware version string read from TPM is of the following format: + * "<chip_info> <RO_firmware_info> <RW_firmware_info>". + * Use the space delimiter to tokenize the TPM firmware version string + * and extract the firmware version. + */ +static void parse_tpm_fw_version(char *vstr) +{ + char *str = vstr; + char *fw_ver, *ctx; + uint32_t count = 0; + + do { + fw_ver = strtok_r(str, " ", &ctx); + if (fw_ver && !cache_tpm_fw_version(fw_ver, &tpm_fw_ver[count])) + count++; + str = NULL; + } while (fw_ver && count < TPM_FW_VER_COUNT); +} + static void read_tpm_fw_version(void) { char vstr[TPM_FW_VER_STRLEN]; - int chunk_count = 0; - /* - * let's read 50 bytes at a time; leave room for the trailing - * zero. - */ + int chunk_count = 0, i; + /* Read 50 bytes at a time; leave room for the trailing zero. */ size_t chunk_size = 50;
/* Only cr50 reports device FW version */ if (tpm_info.vendor_id != 0x1ae0) return;
+ /* If all the FW entries are cached, no need to read again */ + for (i = 0; i < TPM_FW_VER_COUNT; i++) { + if (tpm_fw_ver[i].type == TPM2_FW_VER_TYPE_INIT) + break; + } + if (i == TPM_FW_VER_COUNT) + return; + /* * Does not really matter what's written, this just makes sure * the version is reported from the beginning. @@ -451,6 +531,7 @@ (chunk_count + 1) * chunk_size < sizeof(vstr)); vstr[chunk_count * chunk_size] = 0; printk(BIOS_INFO, "Firmware version: %s\n", vstr); + parse_tpm_fw_version(vstr); }
/* Device/vendor ID values of the TPM devices this driver supports. */ @@ -502,7 +583,15 @@ uint32_t did_vid, status; uint8_t cmd;
- memcpy(&spi_slave, spi_if, sizeof(*spi_if)); + /* + * Ensure SPI controller is set up - either already or passed as the + * paramter. + */ + if (!spi_if && !spi_slave.ctrlr) + return -1; + + if (spi_if) + memcpy(&spi_slave, spi_if, sizeof(*spi_if));
/* clear any pending IRQs */ tis_plat_irq_status(); @@ -749,3 +838,34 @@
return payload_size; } + +bool is_tpm2_fw_version(struct tpm2_fw_ver *match) +{ + int i; + + /* + * Setup the SPI controller if it is not already set up. Also initialize + * TPM so that firmware version is read and cached if not done already. + * If SPI controller is already set up, then the firmware version is + * already read and cached. + */ + if (!spi_slave.ctrlr) { + if (spi_setup_slave(CONFIG_DRIVER_TPM_SPI_BUS, + CONFIG_DRIVER_TPM_SPI_CHIP, &spi_slave)) { + printk(BIOS_ERR, "Failed to setup TPM SPI slave\n"); + return false; + } + + if (tpm2_init(NULL)) + return false; + } + + for (i = 0; i < TPM_FW_VER_COUNT; i++) { + if (tpm_fw_ver[i].type == match->type && + tpm_fw_ver[i].epoch == match->epoch && + tpm_fw_ver[i].major_ver == match->major_ver && + tpm_fw_ver[i].minor_ver == match->minor_ver) + return true; + } + return false; +} diff --git a/src/drivers/spi/tpm/tpm.h b/src/drivers/spi/tpm/tpm.h index be98ed0..3baceab 100644 --- a/src/drivers/spi/tpm/tpm.h +++ b/src/drivers/spi/tpm/tpm.h @@ -16,6 +16,20 @@ uint16_t revision; };
+enum tpm2_fw_ver_type { + TPM2_FW_VER_TYPE_INIT, + TPM2_FW_VER_TYPE_RO, + TPM2_FW_VER_TYPE_RW, +}; + +/* Data structure defining the indivdual elements of TPM firmware version. */ +struct tpm2_fw_ver { + enum tpm2_fw_ver_type type; + uint32_t epoch; + uint32_t major_ver; + uint32_t minor_ver; +}; + /* * Initialize a TPM2 device: read its id, claim locality of zero, verify that * this indeed is a TPM2 device. Use the passed in handle to access the right @@ -41,4 +55,12 @@ /* Get information about previously initialized TPM device. */ void tpm2_get_info(struct tpm2_info *info);
+/** + * is_tpm2_fw_version() - Check if the TPM is running a firmware version. + * @match : Firmware version to be matched against. + * + * @return: true if TPM is running the concerned firmware version, else false. + */ +bool is_tpm2_fw_version(struct tpm2_fw_ver *match); + #endif /* ! __COREBOOT_SRC_DRIVERS_SPI_TPM_TPM_H */
build bot (Jenkins) has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44277 )
Change subject: drivers/spi/tpm: Add support to cache the TPM firmware version ......................................................................
Patch Set 1:
(2 comments)
https://review.coreboot.org/c/coreboot/+/44277/1/src/drivers/spi/tpm/tpm.h File src/drivers/spi/tpm/tpm.h:
https://review.coreboot.org/c/coreboot/+/44277/1/src/drivers/spi/tpm/tpm.h@2... PS1, Line 25: /* Data structure defining the indivdual elements of TPM firmware version. */ 'indivdual' may be misspelled - perhaps 'individual'?
https://review.coreboot.org/c/coreboot/+/44277/1/src/drivers/spi/tpm/tpm.c File src/drivers/spi/tpm/tpm.c:
https://review.coreboot.org/c/coreboot/+/44277/1/src/drivers/spi/tpm/tpm.c@5... PS1, Line 588: * paramter. 'paramter' may be misspelled - perhaps 'parameter'?
Hello build bot (Jenkins), Christian Walter,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/44277
to look at the new patch set (#2).
Change subject: drivers/spi/tpm: Add support to cache the TPM firmware version ......................................................................
drivers/spi/tpm: Add support to cache the TPM firmware version
TPM firmware version is required for couple of use-cases during ramstage - GPIO PM configuration for Intel SoCs, Board specific reset when CSE Lite jumps from RO to RW. This change adds support to read the TPM firmware version and cache it.
BUG=b:154333137, b:162290856 TEST=Ensure that the DUT boots to OS. Ensure that the firmware version is cached and matches with the firmware version logged in the bootup logs.
Change-Id: I2c894d619f6b986be196a9da6ee4556bc440424e Signed-off-by: Karthikeyan Ramasubramanian kramasub@google.com --- M src/drivers/spi/tpm/tpm.c M src/drivers/spi/tpm/tpm.h 2 files changed, 148 insertions(+), 6 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/77/44277/2
Paul Menzel has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44277 )
Change subject: drivers/spi/tpm: Add support to cache the TPM firmware version ......................................................................
Patch Set 2:
(15 comments)
https://review.coreboot.org/c/coreboot/+/44277/2//COMMIT_MSG Commit Message:
https://review.coreboot.org/c/coreboot/+/44277/2//COMMIT_MSG@15 PS2, Line 15: DUT Which one?
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.h File src/drivers/spi/tpm/tpm.h:
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.h@5... PS2, Line 58: /** /*
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.h@5... PS2, Line 59: a firmware version Maybe:
… a specific firmware version.
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.h@6... PS2, Line 60: * @match : Firmware version to be matched against. Remove tab?
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.h@6... PS2, Line 64: is_tpm2_fw_version
is_same_tpm2_fw_version
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.c File src/drivers/spi/tpm/tpm.c:
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.c@4... PS2, Line 430: /** /*
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.c@4... PS2, Line 432: * @fw_ver : Tokenized firmware version string. I’d use exactly one space before the colon, and maybe the tab afterward.
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.c@4... PS2, Line 435: * @return: 0 on success, -1 on error. Please use `CB_SUCCESS` and friends.
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.c@4... PS2, Line 445: */ Remove?
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.c@4... PS2, Line 447: enum tpm2_fw_ver_type type = TPM2_FW_VER_TYPE_INIT; Why not use null?
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.c@4... PS2, Line 454: if (type == TPM2_FW_VER_TYPE_INIT) Could also be just an `else` branch above.
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.c@4... PS2, Line 459: printk(BIOS_ERR, "Error parsing after epoch\n"); Prefix with TPM, and also note the effect: TPM firmware can’t be cached.
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.c@4... PS2, Line 491: uint32_t size_t
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.c@8... PS2, Line 847: Setup Set up
https://review.coreboot.org/c/coreboot/+/44277/2/src/drivers/spi/tpm/tpm.c@8... PS2, Line 855: setup set up
Karthik Ramasubramanian has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/44277 )
Change subject: drivers/spi/tpm: Add support to cache the TPM firmware version ......................................................................
Patch Set 2: Code-Review-2
As pointed out in the parent CL, CB:43741 CL stack is chosen as the candidate to cache and re-use the TPM Firmware version.
I have to abandon this CL in favor of that one. So please post any comments regarding the TPM firmware version in that CL stack. Sorry for the inconvenience.
Karthik Ramasubramanian has abandoned this change. ( https://review.coreboot.org/c/coreboot/+/44277 )
Change subject: drivers/spi/tpm: Add support to cache the TPM firmware version ......................................................................
Abandoned
Abandoning since the required support landed as part of CB:43741