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 boot menu will look like this:
Select boot device:
1. ata0-1: QEMU HARDDISK ATA-7 Hard-Disk (6144 MiBytes) 2. Legacy option rom 3. iPXE (PCI 00:03.0)
T. TPM Menu
Upon pressing T 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
--- src/boot.c | 14 ++++++-- src/tcgbios.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/tcgbios.h | 2 ++ src/util.h | 1 + 4 files changed, 127 insertions(+), 2 deletions(-)
diff --git a/src/boot.c b/src/boot.c index 3044fb0..3c077d0 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,7 +461,7 @@ 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"); + printf("%s", bootmsg ?: "\nPress ESC for boot menu.\n"); free(bootmsg);
u32 menutime = romfile_loadint("etc/boot-menu-wait", DEFAULT_BOOTMENU_WAIT); @@ -474,6 +474,7 @@ interactive_bootmenu(void) while (get_keystroke(0) >= 0) ;
+show_boot_menu: printf("Select boot device:\n\n"); wait_threads();
@@ -486,6 +487,9 @@ interactive_bootmenu(void) printf("%d. %s\n", maxmenu , strtcpy(desc, pos->description, ARRAY_SIZE(desc))); } + if (tpm_is_detected()) { + printf("\nT. TPM menu\n"); + }
// Get key press. If the menu key is ESC, do not restart boot unless // 1.5 seconds have passed. Otherwise users (trained by years of @@ -496,6 +500,12 @@ interactive_bootmenu(void) scan_code = get_keystroke(1000); if (scan_code == 1 && !irqtimer_check(esc_accepted_time)) continue; + if (tpm_is_detected() && scan_code == 20 /* T */) { + printf("\n"); + tpm_menu(); + printf("\n"); + goto show_boot_menu; + } if (scan_code >= 1 && scan_code <= maxmenu+1) break; } diff --git a/src/tcgbios.c b/src/tcgbios.c index 610ed12..2b74775 100644 --- a/src/tcgbios.c +++ b/src/tcgbios.c @@ -26,6 +26,7 @@ #include "std/smbios.h" #include "malloc.h" // malloc_* #include "fw/paravirt.h" // runningOnQEMU +#include "stacks.h" // wait_threads
static const u8 Startup_ST_CLEAR[2] = { 0x00, TPM_ST_CLEAR }; @@ -135,6 +136,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) { @@ -2054,3 +2066,103 @@ tpm_ppi_process(void) } } } + + +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, + }; + + 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 9811827..e71470f 100644 --- a/src/tcgbios.h +++ b/src/tcgbios.h @@ -441,5 +441,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);