diff --git a/board-qemu/slof/OF.fs b/board-qemu/slof/OF.fs
index 3e117ad..7bdd6ea 100644
--- a/board-qemu/slof/OF.fs
+++ b/board-qemu/slof/OF.fs
@@ -175,6 +175,9 @@ CREATE version-str 10 ALLOT
     version-str 8 + @               \ end
     over - dump-display-write
     " Press 's' to enter Open Firmware." dump-display-write
+    s" /ibm,vtpm" find-node IF
+        "  Press 't' to enter TPM menu." terminal-write drop
+    THEN
     cr cr
     temp-ptr disp-size > IF
         temp-ptr disp-size MOD
diff --git a/board-qemu/slof/vtpm-sml.fs b/board-qemu/slof/vtpm-sml.fs
index b4a0fc1..60bd03c 100644
--- a/board-qemu/slof/vtpm-sml.fs
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -120,6 +120,195 @@ log-base LOG-SIZE tpm-set-log-parameters
     THEN
 ;
 
+\
+\  TPM menu
+\
+
+1 CONSTANT TPM_ST_ENABLED
+2 CONSTANT TPM_ST_ACTIVE
+4 CONSTANT TPM_ST_OWNED
+8 CONSTANT TPM_ST_OWNERINSTALL
+
+\ helper to test whether the TPM is enabled and active
+: is-enabled-active? ( state -- ok? )
+    TPM_ST_ENABLED TPM_ST_ACTIVE OR dup rot AND =
+;
+
+\ display the menu for manipulating TPM state; we get
+\ the state of the TPM in form of flags from the C-driver
+\
+\ Some info about the TPM's states:
+\ - enabling/disabling can be done at any time
+\ - activating/deactivating the TPM requires an enabled TPM
+\ - clearing ownership can be done even if the TPM is deactivated and disabled
+\ - allowing/preventing owner installation requires an enabled and active TPM
+\
+: tpm12-menu-show ( -- )
+    tpm-is-working IF
+        ." The TPM is "
+
+        tpm-get-state                   ( flags )
+
+        dup TPM_ST_ENABLED AND TPM_ST_ENABLED <> IF
+            ." disabled"
+        ELSE
+            ." enabled"
+        THEN
+
+        dup TPM_ST_ACTIVE AND TPM_ST_ACTIVE <> IF
+            ." , deactivated"
+        ELSE
+            ." , active"
+        THEN
+
+        dup TPM_ST_OWNED AND TPM_ST_OWNED <> IF
+            ." , does not have an owner "
+            dup TPM_ST_OWNERINSTALL AND TPM_ST_OWNERINSTALL <> IF
+                ." and an owner cannot be installed."
+            ELSE
+                ." but one can be installed."
+            THEN
+        ELSE
+            ." , and has an owner."
+        THEN
+
+        cr cr
+        ." To configure the TPM, choose one of the following actions:"
+        cr cr
+
+        dup TPM_ST_ENABLED AND TPM_ST_ENABLED <> IF
+            ." e. Enable the TPM" cr
+        ELSE
+            ." d. Disable the TPM" cr
+
+            dup TPM_ST_ACTIVE AND TPM_ST_ACTIVE <> IF
+                ." a. Activate the TPM" cr
+            ELSE
+                ." v. Deactivate the TPM" cr
+
+                dup TPM_ST_OWNERINSTALL AND TPM_ST_OWNERINSTALL <> IF
+                    ." s. Allow installation of an owner" cr
+                ELSE
+                    ." p. Prevent installation of an owner" cr
+                THEN
+            THEN
+
+        THEN
+
+        dup TPM_ST_OWNED AND TPM_ST_OWNED = IF
+           ." c. Clear ownership" cr
+        THEN
+
+        cr
+        \ If the TPM is either disabled or deactivated, show message
+        is-enabled-active? 0= IF
+            ." Note: To be able to use all features of the TPM, it must be enabled and active."
+            cr cr
+        THEN
+
+    ELSE
+       ." The TPM is not working correctly." cr
+    THEN
+
+    ." Press escape to continue boot." cr cr
+;
+
+\ Send a code to the C-driver to change the state of the vTPM
+: process-opcode ( verbose? opcode -- )
+    tpm-process-opcode
+    dup 0<> IF
+        ." VTPM: Error code from tpm-process-opcode: " . cr
+    ELSE
+        drop
+    THEN
+;
+
+1  CONSTANT PPI_OP_ENABLE
+2  CONSTANT PPI_OP_DISABLE
+3  CONSTANT PPI_OP_ACTIVATE
+4  CONSTANT PPI_OP_DEACTIVATE
+5  CONSTANT PPI_OP_CLEAR
+8  CONSTANT PPI_OP_SETOWNERINSTALL_TRUE
+9  CONSTANT PPI_OP_SETOWNERINSTALL_FALSE
+
+\ if there's a vtpm available, display the menu
+\ wait for keyboard input and have the C-driver
+\ process opcodes we derive from the chosen menu
+\ item
+: vtpm12-menu
+    tpm-is-working IF
+        \ vtpm-empty-keybuffer
+        tpm12-menu-show
+        BEGIN
+            0 \ loop end-flag                                           ( 0 )
+            key CASE
+            [char] e OF  tpm-get-state                                  ( 0 flags )
+                         TPM_ST_ENABLED AND TPM_ST_ENABLED <> IF
+                             0 PPI_OP_ENABLE     process-opcode
+                             tpm12-menu-show
+                         THEN
+                     ENDOF
+            [char] d OF  tpm-get-state                                  ( 0 flags )
+                         TPM_ST_ENABLED AND TPM_ST_ENABLED = IF
+                             0 PPI_OP_DISABLE    process-opcode
+                             tpm12-menu-show
+                         THEN
+                     ENDOF
+            [char] a OF  tpm-get-state                                  ( 0 flags )
+                         TPM_ST_ACTIVE AND TPM_ST_ACTIVE <> IF
+                             0 PPI_OP_ACTIVATE   process-opcode
+                             tpm-get-state
+                             TPM_ST_ACTIVE AND TPM_ST_ACTIVE = IF
+                                 ." The system needs to reboot to activate the TPM."
+                                 100 MS \ so the message shows
+                                 reset-all
+                             THEN
+                         THEN
+                     ENDOF
+            [char] v OF  tpm-get-state                                  ( 0 flags )
+                         TPM_ST_ACTIVE AND TPM_ST_ACTIVE = IF
+                             0 PPI_OP_DEACTIVATE process-opcode
+                             tpm12-menu-show
+                         THEN
+                     ENDOF
+            [char] c OF  tpm-get-state                                  ( 0 flags )
+                         TPM_ST_OWNED AND TPM_ST_OWNED = IF
+                             0 PPI_OP_CLEAR      process-opcode
+                             tpm12-menu-show
+                         THEN
+                     ENDOF
+            [char] s OF  tpm-get-state                                  ( 0 flags )
+                         \ The TPM must be enabled and active to allow
+                         \ owner installation mods
+                         dup is-enabled-active? IF
+                             TPM_ST_OWNERINSTALL AND TPM_ST_OWNERINSTALL <> IF
+                                 0 PPI_OP_SETOWNERINSTALL_TRUE  process-opcode
+                                 tpm12-menu-show
+                             THEN
+                         THEN
+                     ENDOF
+            [char] p OF  tpm-get-state                                  ( 0 flags )
+                         \ The TPM must be enabled and active to allow
+                         \ owner installation mods
+                         dup is-enabled-active? IF
+                             TPM_ST_OWNERINSTALL AND TPM_ST_OWNERINSTALL = IF
+                                 0 PPI_OP_SETOWNERINSTALL_FALSE process-opcode
+                                 tpm12-menu-show
+                             THEN
+                         THEN
+                     ENDOF
+            1b       OF                                                ( 0 )
+                         drop 1                                        ( 1 )
+                     ENDOF
+            ENDCASE
+        UNTIL
+    THEN
+;
+
+: vtpm-menu
+    vtpm12-menu
+;
+
 : open  true ;
 : close ;
 
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index 8bd684c..3c9d2d7 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -206,7 +206,7 @@ static int tpm_extend(uint8_t *hash, uint32_t pcrindex)
  * Setup and Measurements
  ****************************************************************/
 
-static bool tpm_is_working(void)
+bool tpm_is_working(void)
 {
 	if (!tpm_state.tpm_probed)
 		probe_tpm();
@@ -749,3 +749,31 @@ uint32_t tpm_process_opcode(uint8_t op, bool verbose)
 {
 	return tpm12_process_cfg(op, verbose);
 }
+
+int tpm_get_state(void)
+{
+	int state = 0;
+	struct tpm_permanent_flags pf;
+	bool has_owner;
+
+	if (tpm12_read_permanent_flags((char *)&pf, sizeof(pf)) ||
+	    tpm12_read_has_owner(&has_owner))
+		return ~0;
+
+	if (!pf.flags[PERM_FLAG_IDX_DISABLE])
+		state |= TPM_STATE_ENABLED; /* enabled */
+
+	if (!pf.flags[PERM_FLAG_IDX_DEACTIVATED])
+		state |= TPM_STATE_ACTIVE; /* active */
+
+	if (has_owner) {
+		state |= TPM_STATE_OWNED; /* has owner */
+	} else {
+		if (pf.flags[PERM_FLAG_IDX_OWNERSHIP])
+			state |= TPM_STATE_OWNERINSTALL; /* owner can be installed */
+	}
+
+	dprintf("TPM state flags = 0x%x\n", state);
+
+	return state;
+}
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index b288778..956df43 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -34,4 +34,13 @@ uint32_t tpm_measure_bcv_mbr(uint32_t bootdrv, const uint8_t *addr,
 uint32_t tpm_add_event_separators(uint32_t start_pcr, uint32_t end_pcr);
 uint32_t tpm_process_opcode(uint8_t op, bool verbose);
 
+/* flags returned by tpm_get_state */
+#define TPM_STATE_ENABLED        1
+#define TPM_STATE_ACTIVE         2
+#define TPM_STATE_OWNED          4
+#define TPM_STATE_OWNERINSTALL   8
+
+int tpm_get_state(void);
+bool tpm_is_working(void);
+
 #endif /* TCGBIOS_H */
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index 1a5273f..3957028 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -132,3 +132,23 @@ PRIM(tpm_X2d_process_X2d_opcode)
 	bool verbose = TOS.u;
 	TOS.n = tpm_process_opcode(opcode, verbose);
 MIRP
+
+/************************************************/
+/* Get state of the TPM in form of flags        */
+/* SLOF:   tpm-get-state  ( -- flags )          */
+/* LIBTPM: state = tpm_get_state()              */
+/************************************************/
+PRIM(tpm_X2d_get_X2d_state)
+	PUSH;
+	TOS.n = tpm_get_state();
+MIRP
+
+/************************************************/
+/* Check whether the TPM is working             */
+/* SLOF:   tpm-is-working  ( -- true | false )  */
+/* LIBTPM: bool = tpm_is_working()              */
+/************************************************/
+PRIM(tpm_X2d_is_X2d_working)
+	PUSH;
+	TOS.n = tpm_is_working();
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index 9fb30bb..0e942bc 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -24,3 +24,5 @@ cod(tpm-hash-all)
 cod(tpm-add-event-separators)
 cod(tpm-measure-bcv-mbr)
 cod(tpm-process-opcode)
+cod(tpm-get-state)
+cod(tpm-is-working)
diff --git a/slof/fs/start-up.fs b/slof/fs/start-up.fs
index 0715357..d72579b 100644
--- a/slof/fs/start-up.fs
+++ b/slof/fs/start-up.fs
@@ -55,6 +55,14 @@
    nvramlog-write-string-cr
 ;
 
+: (t-pressed) ( -- )
+   s" /ibm,vtpm" find-node dup IF
+      s" vtpm-menu" rot $call-static
+   ELSE
+      drop
+   THEN
+;
+
 : (boot?) ( -- )
    \ last step before we boot we give up physical presence on the TPM
    s" /ibm,vtpm" find-node dup IF
@@ -107,6 +115,7 @@ TRUE VALUE use-load-watchdog?
    key? IF
       key CASE
 	 [char] s  OF (s-pressed) ENDOF
+	 [char] t  OF (t-pressed) (boot?) ENDOF
 	 1b        OF
 	     (esc-sequence) CASE
 		 1   OF
