Add support for TPM 1.2 and TPM 2 physical presence interface (PPI). A shared memory structure is located at 0xffff 0000 - 0xffff 00ff that SeaBIOS initializes unless it has already been intialized and then searches for a code it is supposed to act upon. A code typically requires that one or more TPM commands are being sent.
The underlying spec can be accessed from this page here:
https://trustedcomputinggroup.org/tcg-physical-presence-interface-specificat...
Version 1.20 is implemented.
Signed-off-by: Stefan Berger stefanb@linux.vnet.ibm.com --- src/post.c | 4 ++++ src/std/tcg.h | 18 ++++++++++++++++++ src/tcgbios.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/tcgbios.h | 3 +++ 4 files changed, 86 insertions(+)
diff --git a/src/post.c b/src/post.c index f93106a..f451013 100644 --- a/src/post.c +++ b/src/post.c @@ -201,6 +201,7 @@ maininit(void)
// Setup platform devices. platform_hardware_setup(); + tpm_ppi_init();
// Start hardware initialization (if threads allowed during optionroms) if (threads_during_optionroms()) @@ -220,6 +221,9 @@ maininit(void) // Run option roms optionrom_setup();
+ // Process user-requested TPM state change + tpm_ppi_process(); + // Allow user to modify overall boot order. interactive_bootmenu(); wait_threads(); diff --git a/src/std/tcg.h b/src/std/tcg.h index 09a92d8..0aeafe8 100644 --- a/src/std/tcg.h +++ b/src/std/tcg.h @@ -551,4 +551,22 @@ struct pcctes_romex #define TPM_PPI_OP_SET_OWNERINSTALL_TRUE 8 #define TPM_PPI_OP_SET_OWNERINSTALL_FALSE 9
+#define TPM_PPI_ADDR_BASE 0xffff0000 + +struct tpm_ppi { + u8 ppin; // 1 = initialized + u32 ppip; // not used + u32 pprp; // response from TPM; set by BIOS + u32 pprq; // opcode; set by ACPI + u32 pprm; // parameter for opcode; set by ACPI + u32 lppr; // last opcode; set by BIOS + u32 fret; // not used + u8 res1; // reserved + u32 res[4]; // reserved + u32 fail; // set by BIOS (0 = success) +} PACKED; + +void tpm_ppi_init(void); +void tpm_ppi_process(void); + #endif // tcg.h diff --git a/src/tcgbios.c b/src/tcgbios.c index 40b3028..2adca71 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -1774,6 +1774,18 @@ tpm20_process_cfg(tpm_ppi_code msgCode, int verbose) }
static int +tpm_process_cfg(tpm_ppi_code msgCode, int verbose) +{ + switch (TPM_version) { + case TPM_VERSION_1_2: + return tpm12_process_cfg(msgCode, verbose); + case TPM_VERSION_2: + return tpm20_process_cfg(msgCode, verbose); + } + return -1; +} + +static int tpm12_get_tpm_state(void) { int state = 0; @@ -2012,3 +2024,52 @@ tpm_can_show_menu(void) } return 0; } + +static struct tpm_ppi *tp; +static u8 next_step; /* next opcode to execute after reboot */ + +void +tpm_ppi_init(void) +{ + tp = (struct tpm_ppi *)TPM_PPI_ADDR_BASE; + + dprintf(DEBUG_tcg, "TCGBIOS: TPM PPI struct at %p\n", tp); + + if (!tp->ppin) { + tp->ppin = 1; + tp->pprq = 0; + tp->lppr = 0; + tp->fail = 0; + } +} + +void +tpm_ppi_process(void) +{ + tpm_ppi_code op; + + if (tp) { + op = tp->pprq; + if (!op) { + /* intermediate step after a reboot? */ + op = next_step; + } else { + /* last full opcode */ + tp->lppr = op; + } + if (op) { + /* + * Reset the opcode so we don't permanently reboot upon + * code 3 (Activate). + */ + tp->pprq = 0; + + printf("Processing TPM PPI opcode %d\n", op); + tp->fail = (tpm_process_cfg(op, 0) != 0); + if (tp->fail) + tp->pprp = 0x0badc0de; + else + tp->pprp = 0; + } + } +} diff --git a/src/tcgbios.h b/src/tcgbios.h index 32fb941..52b86f2 100644 --- a/src/tcgbios.h +++ b/src/tcgbios.h @@ -16,4 +16,7 @@ void tpm_option_rom(const void *addr, u32 len); int tpm_can_show_menu(void); void tpm_menu(void);
+void tpm_ppi_init(void); +void tpm_ppi_process(void); + #endif /* TCGBIOS_H */