[SeaBIOS] [PATCH v2 2/3] tcgbios: Add TPM Physical Presence interface support

Stefan Berger stefanb at linux.vnet.ibm.com
Tue Jan 16 17:41:02 CET 2018


Add support for TPM 1.2 and TPM 2 Physical Presence interface (PPI).
A shared memory structure is located at 0xfffe f000 - 0xfffe f3ff
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-specification/

Version 1.30 is implemented.

Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
---
 src/post.c     |  4 +++
 src/std/acpi.h | 10 ++++++
 src/std/tcg.h  | 31 ++++++++++++++++++
 src/tcgbios.c  | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/tcgbios.h  |  3 ++
 5 files changed, 147 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/acpi.h b/src/std/acpi.h
index c01fa7b..5f2e8b7 100644
--- a/src/std/acpi.h
+++ b/src/std/acpi.h
@@ -320,4 +320,14 @@ struct tpm2_descriptor_rev2
     u64  log_area_start_address;
 } PACKED;
 
+#define QEMU_SIGNATURE 0x554d4551
+struct qemu_descriptor
+{
+    ACPI_TABLE_HEADER_DEF
+    u32 tpmppi_address;
+    u8 tpm_version; /* 1 = 1.2, 2 = 2 */
+    u8 tpmppi_version;
+#define TPM_PPI_VERSION_1_30   1
+} PACKED;
+
 #endif // acpi.h
diff --git a/src/std/tcg.h b/src/std/tcg.h
index 09a92d8..22353a9 100644
--- a/src/std/tcg.h
+++ b/src/std/tcg.h
@@ -551,4 +551,35 @@ struct pcctes_romex
 #define TPM_PPI_OP_SET_OWNERINSTALL_TRUE 8
 #define TPM_PPI_OP_SET_OWNERINSTALL_FALSE 9
 
+struct tpm_ppi {
+    u8 ppin;            /*  0: 1 = initialized */
+    u32 ppip;           /*  1: not used */
+    u32 pprp;           /*  5: response from TPM; set by BIOS */
+    u32 pprq;           /*  9: opcode; set by ACPI */
+    u32 pprm;           /* 13: parameter for opcode; set by ACPI */
+    u32 lppr;           /* 17: last opcode; set by BIOS */
+    u32 fret;           /* 21: not used */
+    u8 res1;            /* 25: reserved */
+    u32 res2[4];        /* 26: reserved */
+    u8 res3[214];       /* 42: reserved */
+    u8 func[256];       /* 256: per function implementation flags; set by BIOS */
+/* indication whether function is implemented; bit 0 */
+#define TPM_PPI_FUNC_IMPLEMENTED       (1 << 0)
+/* actions OS should take to transition to the pre-OS env.; bits 1, 2 */
+#define TPM_PPI_FUNC_ACTION_SHUTDOWN   (1 << 1)
+#define TPM_PPI_FUNC_ACTION_REBOOT     (2 << 1)
+#define TPM_PPI_FUNC_ACTION_VENDOR     (3 << 1)
+#define TPM_PPI_FUNC_ACTION_MASK       (3 << 1)
+/* whether function is blocked by BIOS settings; bits 3,4,5 */
+#define TPM_PPI_FUNC_NOT_IMPLEMENTED     (0 << 3)
+#define TPM_PPI_FUNC_BIOS_ONLY           (1 << 3)
+#define TPM_PPI_FUNC_BLOCKED             (2 << 3)
+#define TPM_PPI_FUNC_ALLOWED_USR_REQ     (3 << 3)
+#define TPM_PPI_FUNC_ALLOWED_USR_NOT_REQ (4 << 3)
+#define TPM_PPI_FUNC_MASK                (7 << 3)
+} 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 730b5e7..c8e6ca2 100644
--- a/src/tcgbios.c
+++ b/src/tcgbios.c
@@ -1783,6 +1783,18 @@ tpm20_process_cfg(tpm_ppi_code msgCode, int verbose, u32 *returnCode)
 }
 
 static int
+tpm_process_cfg(tpm_ppi_code msgCode, int verbose, u32 *returnCode)
+{
+    switch (TPM_version) {
+    case TPM_VERSION_1_2:
+        return tpm12_process_cfg(msgCode, verbose, returnCode);
+    case TPM_VERSION_2:
+        return tpm20_process_cfg(msgCode, verbose, returnCode);
+    }
+    return -1;
+}
+
+static int
 tpm12_get_tpm_state(void)
 {
     int state = 0;
@@ -2021,3 +2033,90 @@ tpm_can_show_menu(void)
     }
     return 0;
 }
+
+static struct tpm_ppi *tp;
+static u8 nextStep = TPM_PPI_OP_NOOP; /* opcode to execute after reboot */
+
+#define FLAGS (TPM_PPI_FUNC_IMPLEMENTED | \
+               TPM_PPI_FUNC_ACTION_REBOOT | \
+               TPM_PPI_FUNC_ALLOWED_USR_NOT_REQ)
+
+static const u8 tpm12_ppi_funcs[] = {
+    [TPM_PPI_OP_NOOP] = TPM_PPI_FUNC_IMPLEMENTED |
+                        TPM_PPI_FUNC_ALLOWED_USR_NOT_REQ,
+    [TPM_PPI_OP_ENABLE]  = FLAGS,
+    [TPM_PPI_OP_DISABLE] = FLAGS,
+    [TPM_PPI_OP_ACTIVATE] = FLAGS,
+    [TPM_PPI_OP_DEACTIVATE] = FLAGS,
+    [TPM_PPI_OP_CLEAR] = FLAGS,
+    [TPM_PPI_OP_SET_OWNERINSTALL_TRUE] = FLAGS,
+    [TPM_PPI_OP_SET_OWNERINSTALL_FALSE] = FLAGS,
+};
+
+static const u8 tpm2_ppi_funcs[] = {
+    [TPM_PPI_OP_CLEAR] = FLAGS,
+};
+
+void
+tpm_ppi_init(void)
+{
+    struct qemu_descriptor *qemu = NULL;
+
+    while (1) {
+        qemu  = find_acpi_table_iter(QEMU_SIGNATURE, qemu);
+        if (!qemu)
+            return;
+        if (!memcmp("QEMU", qemu->oem_id, 5) && !memcmp("CONF", qemu->oem_table_id, 5))
+            break;
+    }
+
+    tp = (struct tpm_ppi *)(u32)qemu->tpmppi_address;
+    dprintf(DEBUG_tcg, "TCGBIOS: TPM PPI struct at %p\n", tp);
+
+    memset(&tp->func, 0, sizeof(tp->func));
+    switch (qemu->tpmppi_version) {
+    case TPM_PPI_VERSION_1_30:
+        switch (qemu->tpm_version) {
+        case TPM_VERSION_1_2:
+            memcpy(&tp->func, tpm12_ppi_funcs, sizeof(tpm12_ppi_funcs));
+            break;
+        case TPM_VERSION_2:
+            memcpy(&tp->func, tpm2_ppi_funcs, sizeof(tpm2_ppi_funcs));
+            break;
+        }
+        break;
+    }
+
+    if (!tp->ppin) {
+        tp->ppin = 1;
+        tp->pprq = 0;
+        tp->lppr = 0;
+    }
+}
+
+void
+tpm_ppi_process(void)
+{
+   tpm_ppi_code op;
+
+   if (tp) {
+        op = tp->pprq;
+        if (!op) {
+            /* intermediate step after a reboot? */
+            op = nextStep;
+        } 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);
+            tpm_process_cfg(op, 0, &tp->pprp);
+        }
+   }
+}
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 */
-- 
2.5.5




More information about the SeaBIOS mailing list