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@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 3044fb0..3be0395 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 1d93d77..9dcd316 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -25,6 +25,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 }; @@ -134,6 +135,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) { @@ -2068,3 +2080,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 bf5b19b..38b673f 100644 --- a/src/tcgbios.h +++ b/src/tcgbios.h @@ -448,5 +448,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);