[SeaBIOS] [PATCH v9 6/6] Add a menu for TPM control

Stefan Berger stefanb at linux.vnet.ibm.com
Fri Mar 20 19:00:41 CET 2015


From: Stefan Berger <stefann at linux.vnet.ibm.com>

This patch provides an addtional menu entry that enables the user to control
certain aspects of the TPM's state.

If a working TPM has been detected, the top level BIOS menu
will look like this:

Press F12 for boot menu.
Press F11 to TPM menu.

Upon pressing F11 the TPM menu will be shown:

1. Enable TPM
2. Disable TPM
3. Activate TPM
4. Deactivate TPM
5. Clear ownership
6. Allow installation of owner
7. Prevent installation of owner
Escape for previous menu.
TPM is enabled, active, does not have an owner but one can be installed.

Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>

---

v9:
  - to enter TPM menu, use Tab key by default

v6:
  - passing durations of commands to the transmission function

v5:
  - fixed an indentation

v2:
  - use if (!CONFIG_TCGBIOS) ... in all non-static functions
  - use dprintf(DEBUG_tcg, ...) for printing of debugging info
  - removing some code used for a future patch
---
 src/boot.c    |  15 ++++++--
 src/tcgbios.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/tcgbios.h |   2 +
 src/util.h    |   1 +
 4 files changed, 131 insertions(+), 3 deletions(-)

diff --git a/src/boot.c b/src/boot.c
index 014b8fd..b167a32 100644
--- a/src/boot.c
+++ b/src/boot.c
@@ -427,7 +427,7 @@ get_raw_keystroke(void)
 }
 
 // Read a keystroke - waiting up to 'msec' milliseconds.
-static int
+int
 get_keystroke(int msec)
 {
     u32 end = irqtimer_calc(msec);
@@ -461,13 +461,22 @@ interactive_bootmenu(void)
 
     char *bootmsg = romfile_loadfile("etc/boot-menu-message", NULL);
     int menukey = romfile_loadint("etc/boot-menu-key", 1);
-    printf("%s", bootmsg ?: "\nPress ESC for boot menu.\n\n");
-    free(bootmsg);
+    int menukey_tpm = romfile_loadint("etc/boot-menu-key-tpm", 0xf);
+again:
+    printf("%s", bootmsg ?: "\nPress ESC for boot menu.\n");
+    if (tpm_is_detected())
+        printf("Press Tab for TPM menu.\n");
+    printf("\n");
 
     u32 menutime = romfile_loadint("etc/boot-menu-wait", DEFAULT_BOOTMENU_WAIT);
     enable_bootsplash();
     int scan_code = get_keystroke(menutime);
     disable_bootsplash();
+    if (tpm_is_detected() && scan_code == menukey_tpm) {
+         tpm_menu();
+         goto again;
+    }
+    free(bootmsg);
     if (scan_code != menukey)
         return;
 
diff --git a/src/tcgbios.c b/src/tcgbios.c
index 3e6d9bf..6ffa841 100644
--- a/src/tcgbios.c
+++ b/src/tcgbios.c
@@ -24,6 +24,7 @@
 #include "sha1.h" // sha1
 #include "std/smbios.h"
 #include "malloc.h" // malloc_*
+#include "stacks.h" // wait_threads
 
 
 static const u8 Startup_ST_CLEAR[2] = { 0x00, TPM_ST_CLEAR };
@@ -133,6 +134,17 @@ probe_tpm(void)
     }
 }
 
+int
+tpm_is_detected(void)
+{
+    if (!CONFIG_TCGBIOS)
+        return 0;
+
+    probe_tpm();
+
+    return tpm_state.tpm_found;
+}
+
 static int
 has_working_tpm(void)
 {
@@ -2063,3 +2075,107 @@ tpm_ppi_dump(void)
     printf("tpm_ppi_found_high = %d\n", tpm_ppi_found_high);
     printf("tp  = %lx\n", (long)tp);
 }
+
+
+static void
+show_tpm_state(void)
+{
+    struct tpm_permanent_flags pf;
+    u8 has_owner;
+
+    if (read_permanent_flags((char *)&pf, sizeof(pf)) ||
+        read_has_owner(&has_owner))
+        return;
+
+    printf("TPM is ");
+
+    if (pf.flags[PERM_FLAG_IDX_DISABLE])
+        printf("disabled");
+    else
+        printf("enabled");
+
+    if (pf.flags[PERM_FLAG_IDX_DEACTIVATED])
+        printf(", deactivated");
+    else
+        printf(", active");
+
+    if (has_owner)
+        printf(" and has an owner.\n");
+    else {
+        printf(", does not have an owner ");
+        if (pf.flags[PERM_FLAG_IDX_OWNERSHIP])
+            printf("but one can be installed.\n");
+        else
+            printf("and an owner cannot be installed.\n");
+    }
+
+}
+
+
+void
+tpm_menu(void)
+{
+    if (!CONFIG_TCGBIOS)
+        return;
+
+    int scan_code;
+    u32 rc, returnCode;
+    u8 next_step;
+    tpm_bios_cfg_t cfg = {
+        .op  = 0,
+    };
+
+    //tpm_ppi_dump();
+
+    while (get_keystroke(0) >= 0)
+        ;
+    wait_threads();
+
+    for (;;) {
+        if (has_working_tpm()) {
+            printf("1. Enable TPM\n"
+                   "2. Disable TPM\n"
+                   "3. Activate TPM\n"
+                   "4. Deactivate TPM\n"
+                   "5. Clear ownership\n"
+                   "6. Allow installation of owner\n"
+                   "7. Prevent installation of owner\n");
+        } else {
+            printf("TPM is not working correctly.\n");
+        }
+
+        printf("Escape for previous menu.\n");
+
+        if (has_working_tpm()) {
+            show_tpm_state();
+        }
+
+        cfg.op = 0;
+
+        while ((scan_code = get_keystroke(1000)) == ~0)
+            ;
+
+        switch (scan_code) {
+        case 1:
+            // ESC
+            return;
+        case 2 ... 6:
+            cfg.op = scan_code - 1;
+            break;
+        case 7 ... 8:
+            cfg.op = scan_code + 1;
+            break;
+        default:
+            continue;
+        }
+
+        if (has_working_tpm()) {
+            rc = tpm_process_cfg(&cfg, 1, &returnCode, &next_step);
+
+            if (rc)
+                printf("An error occurred: 0x%x\n", rc);
+        }
+    }
+}
+
+
diff --git a/src/tcgbios.h b/src/tcgbios.h
index e940637..da8190b 100644
--- a/src/tcgbios.h
+++ b/src/tcgbios.h
@@ -450,5 +450,7 @@ u32 tpm_ipl(enum ipltype bootcd, const u8 *addr, u32 count);
 u32 tpm_start_option_rom_scan(void);
 u32 tpm_option_rom(const void *addr, u32 len);
 u32 tpm_smbios_measure(void);
+int tpm_is_detected(void);
+void tpm_menu(void);
 
 #endif /* TCGBIOS_H */
diff --git a/src/util.h b/src/util.h
index 2244090..bb24744 100644
--- a/src/util.h
+++ b/src/util.h
@@ -36,6 +36,7 @@ int bootprio_find_pci_rom(struct pci_device *pci, int instance);
 int bootprio_find_named_rom(const char *name, int instance);
 struct usbdevice_s;
 int bootprio_find_usb(struct usbdevice_s *usbdev, int lun);
+int get_keystroke(int msec);
 
 // bootsplash.c
 void enable_vga_console(void);
-- 
1.9.3




More information about the SeaBIOS mailing list