Index: seabios/src/tcgbios.c
===================================================================
--- seabios.orig/src/tcgbios.c
+++ seabios/src/tcgbios.c
@@ -82,6 +82,10 @@ static tcpa_state_t tcpa_state = {
     .tpm_driver_to_use = TPM_INVALID_DRIVER,
 };
 
+typedef struct {
+    u8  op;
+} tpm_bios_cfg_t;
+
 
 /********************************************************
   Extensions for TCG-enabled BIOS
@@ -1448,3 +1452,503 @@ tcpa_ipl(enum ipltype bootcd, const u8 *
 
 
 
+static u32
+assert_physical_presence(void)
+{
+    u32 rc = 0;
+    u32 returnCode;
+
+    rc = build_and_send_cmd(TPM_ORD_PhysicalPresence,
+                            PhysicalPresence_CMD_ENABLE,
+                            sizeof(PhysicalPresence_CMD_ENABLE),
+                            NULL, 10, &returnCode, TPM_DURATION_TYPE_SHORT);
+
+    dprintf(DEBUG_tcg,
+           "Return code from TSC_PhysicalPresence(CMD_ENABLE) = 0x%08x\n",
+           returnCode);
+
+    if (rc || returnCode)
+        goto err_exit;
+
+    rc = build_and_send_cmd(TPM_ORD_PhysicalPresence,
+                            PhysicalPresence_PRESENT,
+                            sizeof(PhysicalPresence_PRESENT),
+                            NULL, 10, &returnCode, TPM_DURATION_TYPE_SHORT);
+
+    dprintf(DEBUG_tcg,
+           "Return code from TSC_PhysicalPresence(PRESENT) = 0x%08x\n",
+           returnCode);
+
+    if (rc || returnCode)
+        goto err_exit;
+
+    return 0;
+
+err_exit:
+    dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
+
+    tcpa_state.tpm_working = 0;
+    if (rc)
+        return rc;
+    return TCG_TCG_COMMAND_ERROR;
+}
+
+
+static u32
+read_permanent_flags(char *buf, int buf_len)
+{
+    u32 rc;
+    u32 returnCode;
+    struct tpm_res_getcap_perm_flags pf;
+
+    memset(buf, 0x0, buf_len);
+
+    rc = build_and_send_cmd(TPM_ORD_GetCapability,
+                            GetCapability_Permanent_Flags,
+                            sizeof(GetCapability_Permanent_Flags),
+                            (u8 *)&pf,
+                            sizeof(struct tpm_res_getcap_perm_flags),
+                            &returnCode, TPM_DURATION_TYPE_SHORT);
+
+    dprintf(DEBUG_tcg, "TCGBIOS: Return code from TPM_GetCapability() "
+            "= 0x%08x\n", returnCode);
+
+    if (rc || returnCode)
+        goto err_exit;
+
+    memcpy(buf, &pf.perm_flags, buf_len);
+
+    return 0;
+
+err_exit:
+    dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
+
+    tcpa_state.tpm_working = 0;
+    if (rc)
+        return rc;
+    return TCG_TCG_COMMAND_ERROR;
+}
+
+
+static u32
+read_has_owner(u8 *has_owner)
+{
+    u32 rc;
+    u32 returnCode;
+    struct tpm_res_getcap_ownerauth oauth;
+
+    rc = build_and_send_cmd(TPM_ORD_GetCapability,
+                            GetCapability_OwnerAuth,
+                            sizeof(GetCapability_OwnerAuth),
+                            (u8 *)&oauth,
+                            sizeof(struct tpm_res_getcap_ownerauth),
+                            &returnCode, TPM_DURATION_TYPE_SHORT);
+
+    dprintf(DEBUG_tcg, "TCGBIOS: Return code from TPM_GetCapability() "
+            "= 0x%08x\n", returnCode);
+
+    if (rc || returnCode)
+        goto err_exit;
+
+    *has_owner = oauth.flag;
+
+    return 0;
+
+err_exit:
+    dprintf(DEBUG_tcg,"TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
+
+    tcpa_state.tpm_working = 0;
+    if (rc)
+        return rc;
+    return TCG_TCG_COMMAND_ERROR;
+}
+
+
+static u32
+disable_tpm(int disable, int verbose)
+{
+    u32 rc;
+    u32 returnCode;
+    struct tpm_permanent_flags pf;
+
+    rc = read_permanent_flags((char *)&pf, sizeof(pf));
+    if (rc)
+        return rc;
+
+    if (!!pf.flags[PERM_FLAG_IDX_DISABLE] == !!disable) {
+        if (verbose)
+            printf("TPM is already %s.\n,",
+                   disable ? "disabled" : "enabled");
+        return 0;
+    }
+
+    rc = assert_physical_presence();
+    if (rc) {
+        dprintf(DEBUG_tcg, "TCGBIOS: Asserting physical presence failed.\n");
+        return rc;
+    }
+
+    rc = build_and_send_cmd(disable ? TPM_ORD_PhysicalDisable
+                                    : TPM_ORD_PhysicalEnable,
+                            NULL, 0, NULL, 10, &returnCode,
+                            TPM_DURATION_TYPE_SHORT);
+    dprintf(DEBUG_tcg, "Return code from TPM_Physical%sable = 0x%08x\n",
+            disable ? "Dis" : "En", returnCode);
+
+    if (rc || returnCode)
+        goto err_exit;
+
+
+    return 0;
+
+err_exit:
+    dprintf(DEBUG_tcg, "TCGBIOS: %sabling the TPM failed.\n",
+            disable ? "Dis" : "En");
+    dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
+
+    tcpa_state.tpm_working = 0;
+    if (rc)
+        return rc;
+    return TCG_TCG_COMMAND_ERROR;
+}
+
+
+static u32
+deactivate_tpm(int deactivate, int allow_reset, int verbose)
+{
+    u32 rc;
+    u32 returnCode;
+    struct tpm_permanent_flags pf;
+
+    rc = read_permanent_flags((char *)&pf, sizeof(pf));
+    if (rc)
+        return rc;
+
+    if (!!pf.flags[PERM_FLAG_IDX_DEACTIVATED] == !!deactivate) {
+        if (verbose)
+            printf("TPM is already %s.\n",
+                   deactivate ? "deactivated" : "activated");
+        return 0;
+    }
+
+    if (pf.flags[PERM_FLAG_IDX_DISABLE]) {
+        if (verbose)
+            printf("TPM must first be enabled.\n");
+        return 0;
+    }
+
+    rc = assert_physical_presence();
+    if (rc) {
+        dprintf(DEBUG_tcg, "TCGBIOS: Asserting physical presence failed.\n");
+        return rc;
+    }
+
+    rc = build_and_send_cmd(TPM_ORD_PhysicalSetDeactivated,
+                            deactivate ? CommandFlag_TRUE
+                                       : CommandFlag_FALSE,
+                            deactivate ? sizeof(CommandFlag_TRUE)
+                                       : sizeof(CommandFlag_FALSE),
+                            NULL, 10, &returnCode, TPM_DURATION_TYPE_SHORT);
+
+    dprintf(DEBUG_tcg,
+            "Return code from PhysicalSetDeactivated(%d) = 0x%08x\n",
+            deactivate ? 1 : 0, returnCode);
+
+    if (rc || returnCode)
+        goto err_exit;
+
+    if (!deactivate && allow_reset) {
+        if (verbose) {
+            printf("Requiring a reboot to activate the TPM.\n");
+
+            msleep(2000);
+        }
+        reset_vector();
+    }
+
+    return 0;
+
+err_exit:
+    dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
+
+    tcpa_state.tpm_working = 0;
+    if (rc)
+        return rc;
+    return TCG_TCG_COMMAND_ERROR;
+}
+
+
+static u32
+enable_activate(int allow_reset, int verbose)
+{
+    u32 rc;
+
+    rc = disable_tpm(0, verbose);
+    if (rc)
+        return rc;
+
+    rc = deactivate_tpm(0, allow_reset, verbose);
+
+    return rc;
+}
+
+
+static u32
+force_clear(int enable_activate_before, int enable_activate_after, int verbose)
+{
+    u32 rc;
+    u32 returnCode;
+    u8 has_owner;
+
+    rc = read_has_owner(&has_owner);
+    if (rc)
+        return rc;
+    if (!has_owner) {
+        if (verbose)
+            printf("TPM does not have an owner.\n");
+        return 0;
+    }
+
+    if (enable_activate_before) {
+        rc = enable_activate(0, verbose);
+        if (rc) {
+            dprintf(DEBUG_tcg,
+                    "TCGBIOS: Enabling/activating the TPM failed.\n");
+            return rc;
+        }
+    }
+
+    rc = assert_physical_presence();
+    if (rc) {
+        dprintf(DEBUG_tcg, "TCGBIOS: Asserting physical presence failed.\n");
+        return rc;
+    }
+
+    rc = build_and_send_cmd(TPM_ORD_ForceClear,
+                            NULL, 0, NULL, 10, &returnCode,
+                            TPM_DURATION_TYPE_SHORT);
+
+    dprintf(DEBUG_tcg, "Return code from TPM_ForceClear() = 0x%08x\n",
+            returnCode);
+
+    if (rc || returnCode)
+        goto err_exit;
+
+    if (!enable_activate_after) {
+        if (verbose)
+            printf("Owner successfully cleared.\n"
+                   "You will need to enable/activate the TPM again.\n\n");
+        return 0;
+    }
+
+    enable_activate(1, verbose);
+
+    return 0;
+
+err_exit:
+    dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
+
+    tcpa_state.tpm_working = 0;
+    if (rc)
+        return rc;
+    return TCG_TCG_COMMAND_ERROR;
+}
+
+
+static u32
+set_owner_install(int allow, int verbose)
+{
+    u32 rc, returnCode;
+    u8 has_owner;
+    struct tpm_permanent_flags pf;
+
+    rc = read_has_owner(&has_owner);
+    if (rc)
+        return rc;
+    if (has_owner) {
+        if (verbose)
+            printf("Must first remove owner.\n");
+        return 0;
+    }
+
+    rc = read_permanent_flags((char *)&pf, sizeof(pf));
+    if (rc)
+        return rc;
+
+    if (pf.flags[PERM_FLAG_IDX_DISABLE]) {
+        if (verbose)
+            printf("TPM must first be enable.\n");
+        return 0;
+    }
+
+    rc = assert_physical_presence();
+    if (rc) {
+        dprintf(DEBUG_tcg, "TCGBIOS: Asserting physical presence failed.\n");
+        return rc;
+    }
+
+    rc = build_and_send_cmd(TPM_ORD_SetOwnerInstall,
+                            (allow) ? CommandFlag_TRUE :
+                                      CommandFlag_FALSE,
+                            sizeof(CommandFlag_TRUE),
+                            NULL, 10, &returnCode, TPM_DURATION_TYPE_SHORT);
+
+    dprintf(DEBUG_tcg, "Return code from TPM_SetOwnerInstall() = 0x%08x\n",
+           returnCode);
+
+    if (rc || returnCode)
+        goto err_exit;
+
+    if (verbose)
+        printf("Installation of owner %s.\n", allow ? "enabled" : "disabled");
+
+    return 0;
+
+err_exit:
+    dprintf(DEBUG_tcg, "TCGBIOS: TPM malfunctioning (line %d).\n", __LINE__);
+    tcpa_state.tpm_working = 0;
+    if (rc)
+        return rc;
+    return TCG_TCG_COMMAND_ERROR;
+}
+
+
+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");
+    }
+
+}
+
+
+static u32
+tcpa_process_cfg(const tpm_bios_cfg_t *cfg, int verbose)
+{
+    u32 rc = 0;
+
+    switch (cfg->op) {
+        case 0: /* no-op */
+            break;
+
+        case 1:
+            rc = disable_tpm(0, verbose);
+            break;
+
+        case 2:
+            rc = disable_tpm(1, verbose);
+            break;
+
+        case 3:
+            rc = deactivate_tpm(0, 1, verbose);
+            break;
+
+        case 4:
+            rc = deactivate_tpm(1, 1, verbose);
+            break;
+
+        case 5:
+            rc = force_clear(1, 0, verbose);
+            break;
+
+        case 6:
+            rc = set_owner_install(1, verbose);
+            break;
+
+        case 7:
+            rc = set_owner_install(0, verbose);
+            break;
+
+        default:
+            break;
+    }
+
+    if (rc)
+        printf("Op %d: An error occurred: 0x%x\n", cfg->op, rc);
+
+    return rc;
+}
+
+
+void
+tcpa_menu(void)
+{
+    if (!CONFIG_TCGBIOS)
+        return;
+
+    int show_menu = 1;
+    int scan_code;
+    u32 rc;
+    tpm_bios_cfg_t cfg = {
+        .op  = 0,
+    };
+
+    while (get_keystroke(0) >= 0)
+        ;
+    wait_threads();
+
+    for (;;) {
+        if (show_menu) {
+            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"
+                   "Escape for previous menu.\n");
+            show_menu = 0;
+            show_tpm_state();
+        }
+
+        cfg.op = 0;
+
+        scan_code = get_keystroke(1000);
+
+        switch (scan_code) {
+        case 1:
+            // ESC
+            return;
+        case 2 ... 8:
+            cfg.op = scan_code - 1;
+            break;
+        default:
+            continue;
+        }
+
+        rc = tcpa_process_cfg(&cfg, 1);
+
+        if (rc)
+            printf("An error occurred: 0x%x\n", rc);
+
+        show_menu = 1;
+    }
+}
+
+
Index: seabios/src/tcgbios.h
===================================================================
--- seabios.orig/src/tcgbios.h
+++ seabios/src/tcgbios.h
@@ -390,6 +390,7 @@ u32 tcpa_ipl(enum ipltype bootcd, const 
 u32 tcpa_start_option_rom_scan(void);
 u32 tcpa_option_rom(const void *addr, u32 len);
 u32 tcpa_smbios_measure(void);
+void tcpa_menu(void);
 
 
 #endif /* TCGBIOS_H */
Index: seabios/src/boot.c
===================================================================
--- seabios.orig/src/boot.c
+++ seabios/src/boot.c
@@ -377,12 +377,20 @@ interactive_bootmenu(void)
     while (get_keystroke(0) >= 0)
         ;
 
-    printf("Press F12 for boot menu.\n\n");
+again:
+    printf("Press F12 for boot menu.\n");
+    if (has_working_tpm())
+        printf("Press F11 to 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 (has_working_tpm() && scan_code == 0x85) {
+         tcpa_menu();
+         goto again;
+    }
     if (scan_code != 0x86)
         /* not F12 */
         return;
