diff --git a/include/secvar.h b/include/secvar.h
index 413d7997..259b9b63 100644
--- a/include/secvar.h
+++ b/include/secvar.h
@@ -5,6 +5,7 @@
 #define _SECVAR_DRIVER_
 
 #include <stdint.h>
+#include <ccan/list/list.h>
 
 struct secvar;
 
@@ -37,6 +38,7 @@ struct secvar_backend_driver {
 };
 
 extern struct secvar_storage_driver secboot_tpm_driver;
+extern struct secvar_storage_driver secboot_tpm_switchable_driver;
 extern struct secvar_backend_driver edk2_compatible_v1;
 
 int secvar_main(struct secvar_storage_driver, struct secvar_backend_driver);
diff --git a/libstb/secvar/storage/Makefile.inc b/libstb/secvar/storage/Makefile.inc
index 50156fe2..dbddd6e5 100644
--- a/libstb/secvar/storage/Makefile.inc
+++ b/libstb/secvar/storage/Makefile.inc
@@ -7,7 +7,7 @@ SUBDIRS += $(SECVAR_STORAGE_DIR)
 
 # Swap the comment on these two lines to use the fake TPM NV
 # implementation hardware without a TPM
-SECVAR_STORAGE_OBJS = secboot_tpm.o tpmnv_ops.o
+SECVAR_STORAGE_OBJS = secboot_tpm.o tpmnv_ops.o secboot_tpm_switchable.o
 #SECVAR_STORAGE_OBJS = secboot_tpm.o fakenv_ops.o
 
 SECVAR_STORAGE = $(SECVAR_STORAGE_DIR)/built-in.a
diff --git a/libstb/secvar/storage/secboot_tpm_switchable.c b/libstb/secvar/storage/secboot_tpm_switchable.c
new file mode 100644
index 00000000..0790ed68
--- /dev/null
+++ b/libstb/secvar/storage/secboot_tpm_switchable.c
@@ -0,0 +1,251 @@
+#include <stdlib.h>
+#include <skiboot.h>
+#include <opal.h>
+#include "../secvar.h"
+#include "../secvar_devtree.h"
+#include "secboot_tpm.h"
+#include <tssskiboot.h>
+#include <ibmtss/TPM_Types.h>
+#include "secboot_tpm_switchable.h"
+
+/* POTENTIAL ITEMS TO MOVE TO secboot_tpm.h */
+#define SECBOOT_TPM_MAX_VAR_SIZE	8192
+
+extern const uint8_t tpmnv_vars_name[34];
+extern const uint8_t tpmnv_vars_prov_name[34];
+extern const uint8_t tpmnv_control_name[34];
+extern const uint8_t tpmnv_control_prov_name[34];
+
+/* END POTENTIALLY HEADER STUFF */
+
+// TODO: actually get the correct mode name hash here.
+const uint8_t tpmnv_mode_name[] = {
+	0x00, 0x0b,
+	0x7a, 0xe8, 0x16, 0xe0, 0x15, 0xab, 0xdc, 0xd8, 0xc6, 0xe6, 0xa1, 0x6f, 0x26, 0x71, 0x65, 0x96,
+	0x69, 0x15, 0x04, 0xd1, 0x05, 0x14, 0xfc, 0xf0, 0x82, 0x17, 0x99, 0x22, 0x4e, 0x06, 0xe5, 0x76,
+};
+
+const uint8_t tpmnv_mode_prov_name[] = {
+	0x00, 0x0b,
+	0x7a, 0xe8, 0x16, 0xe0, 0x15, 0xab, 0xdc, 0xd8, 0xc6, 0xe6, 0xa1, 0x6f, 0x26, 0x71, 0x65, 0x96,
+	0x69, 0x15, 0x04, 0xd1, 0x05, 0x14, 0xfc, 0xf0, 0x82, 0x17, 0x99, 0x22, 0x4e, 0x06, 0xe5, 0x76,
+};
+
+uint64_t mode_value = 0;
+
+
+// TODO: break down into reusable functions w/ the functions in secboot_tpm_store_init
+static int pre_switchable_init(void)
+{
+	TPMI_RH_NV_INDEX *indices = NULL;
+	char nv_vars_name[sizeof(tpmnv_vars_name)];
+	char nv_control_name[sizeof(tpmnv_control_name)];
+	char nv_mode_name[sizeof(tpmnv_mode_name)];
+	size_t count = 0;
+	bool control_defined = false;
+	bool vars_defined = false;
+	bool mode_defined = false;
+	int i, rc;
+
+	/* Check if the NV indices have been defined already */
+	rc = tpmnv_ops.getindices(&indices, &count);
+	if (rc) {
+		prlog(PR_ERR, "Could not load defined indicies from TPM, rc=%d\n", rc);
+		goto error;
+	}
+
+	for (i = 0; i < count; i++) {
+		if (indices[i] == SECBOOT_TPMNV_VARS_INDEX)
+			vars_defined = true;
+		else if (indices[i] == SECBOOT_TPMNV_CONTROL_INDEX)
+			control_defined = true;
+		else if (indices[i] == SECBOOT_TPMNV_MODE_INDEX)
+			mode_defined = true;
+	}
+	free(indices);
+
+        if (secvar_check_clear_keys() || secvar_check_set_default_keys()) {
+                /* TODO: undefine *ALL THREE* indices */
+                mode_defined = control_defined = vars_defined = false;
+        }
+
+	if (mode_defined) {
+                // TODO: Probably break a lot of the following up into a reusable function between
+                //  this driver and secboot_tpm
+		TPMS_NV_PUBLIC nv_public;
+		TPM2B_NAME vars_tmp;
+
+		rc = tpmnv_ops.readpublic(SECBOOT_TPMNV_MODE_INDEX,
+					  &nv_public,
+					  &vars_tmp);
+		if (rc) {
+			prlog(PR_ERR, "Failed to readpublic from the MODE index, rc=%d\n", rc);
+			return rc;
+		}
+
+		memcpy(nv_mode_name, vars_tmp.t.name, MIN(sizeof(tpmnv_vars_name), vars_tmp.t.size));
+
+
+		// TODO: perhaps rework this function too, or just drop that extra function
+		if (!memcmp(tpmnv_mode_prov_name, nv_mode_name, sizeof(tpmnv_mode_prov_name))) {
+			/* Detected a provisioned mode index, claim it here and set the mode to system mode */
+			// TODO: perhaps not hardcode the space
+			rc = tpmnv_ops.definespace(SECBOOT_TPMNV_MODE_INDEX, sizeof(uint64_t));
+			if (rc) {
+				prlog(PR_ERR, "Failed to define the MODE index, rc=%d\n", rc);
+				return rc;
+			}
+
+			/* Write TPMNV variables to actual NV */
+			mode_value = 1;
+			rc = tpmnv_ops.write(SECBOOT_TPMNV_MODE_INDEX, &mode_value, sizeof(mode_value), 0);
+			if (rc)
+				return rc;
+
+			return OPAL_SUCCESS;
+		}
+
+		if (!memcmp(tpmnv_mode_name, nv_mode_name, sizeof(tpmnv_mode_name))) {
+			/* Detected an improperly defined mode index, give up? */
+			abort(); // TODO: don't actually abort, this should be in an init function
+		}
+
+
+		rc = tpmnv_ops.read(SECBOOT_TPMNV_VARS_INDEX,
+				    &mode_value,
+				    sizeof(mode_value), 0);
+		if (rc) {
+			prlog(PR_ERR, "Failed to read from the VARS index\n");
+			goto error;
+		}
+
+		return OPAL_SUCCESS;
+	}
+
+	/* Mode index was not defined, so we need to check the other indices first */
+
+	/* Determine if we need to define the indices. These should BOTH be false or true */
+	if (!vars_defined && !control_defined) {
+                // TODO: Define *ALL THREE* indices here, perhaps let the other init handle the formatting?
+                //  or do we format here as well in secboot_tpm format?
+
+                if (secvar_check_clear_keys()) {
+                        /* clear-os-keys was issued, continue in user mode (OS secure boot disabled) */
+                        mode_value = USER_MODE;
+                }
+
+                /* reset-default-keys likely undefined the indices, either way default to system mode */
+                mode_value = SYSTEM_MODE;
+
+                goto define;
+	}
+	if (vars_defined ^ control_defined) {
+		/* This should never happen. Both indices should be defined at the same
+		 * time. Otherwise something seriously went wrong. */
+		prlog(PR_ERR, "NV indices defined with unexpected attributes. Assert physical presence to clear\n");
+		goto error;
+	}
+
+	rc = secboot_tpm_get_tpmnv_names(nv_vars_name, nv_control_name);
+	if (rc)
+		goto error;
+
+	if (secboot_tpm_check_provisioned_indices(nv_vars_name, nv_control_name)) {
+                // TODO: Reclaim the NV indices here, we default to system mode (noop),
+                //  so that driver will not handle it.
+
+		mode_value = SYSTEM_MODE;
+                goto define;
+	}
+
+	/* Otherwise, ensure the NV indices were defined with the correct set of attributes */
+	rc = secboot_tpm_check_tpmnv_attrs(nv_vars_name, nv_control_name);
+	if (rc)
+		goto error;
+
+        /* Reaching here, mode index was not defined, and the other NV indices were.
+         * This is (likely) a firmware update case, where we should preserve the previous
+         *  secure boot state. */
+        mode_value = SYSTEM_MODE;
+
+define:
+        rc = tpmnv_ops.definespace(SECBOOT_TPMNV_MODE_INDEX, sizeof(mode_value));
+	if (rc) {
+		prlog(PR_ERR, "Failed to define the MODE index, rc=%d\n", rc);
+		return rc;
+	}
+
+        rc = tpmnv_ops.write(SECBOOT_TPMNV_MODE_INDEX,
+			     &mode_value,
+			     sizeof(mode_value), 0);
+        if (rc) {
+                prlog(PR_ERR, "Could not write to the MODE index, rc=%d\n", rc);
+                goto error;
+        }
+
+	return OPAL_SUCCESS;
+
+error:
+	// TODO: error handle better here
+	return rc;
+}
+
+static int switchable_store_init(void)
+{
+        int rc;
+
+        rc = pre_switchable_init();
+        if (rc) {
+                prlog(PR_ERR, "Failed to initialize/detect secure boot mode\n");
+        }
+
+        if (mode_value == USER_MODE)
+                return secboot_tpm_driver.store_init();
+        return OPAL_SUCCESS;
+}
+
+static int switchable_load_bank(struct list_head *bank, int section)
+{
+        if (mode_value == USER_MODE)
+                return secboot_tpm_driver.load_bank(bank, section);
+        return OPAL_SUCCESS;
+}
+
+static int switchable_write_bank(struct list_head *bank, int section)
+{
+        if (mode_value == USER_MODE)
+                return secboot_tpm_driver.write_bank(bank, section);
+        return OPAL_SUCCESS;
+}
+
+static void switchable_lockdown(void)
+{
+	/* Note: While write lock is called here on the two NV indices,
+	 * both indices are also defined on the platform hierarchy.
+	 * The platform hierarchy auth is set later in the skiboot
+	 * initialization process, and not by any secvar-related code.
+	 */
+	int rc;
+
+        rc = tpmnv_ops.writelock(SECBOOT_TPMNV_MODE_INDEX);
+	if (rc) {
+		prlog(PR_EMERG, "TSS Write Lock failed on CONTROL index, halting.\n");
+		abort();
+	}
+
+        /* Unconditionally call the secboot_tpm lockdown as well to lock the other
+         *  two indices we care about. */
+        secboot_tpm_driver.lockdown();
+}
+
+
+struct secvar_storage_driver secboot_tpm_switchable_driver = {
+	.store_init = switchable_store_init,
+
+	/* These two hooks are no-ops, no storage actually needed  */
+	.load_bank = switchable_load_bank,
+	.write_bank = switchable_write_bank,
+
+	.lockdown = switchable_lockdown,
+	.max_var_size = SECBOOT_TPM_MAX_VAR_SIZE,
+};
diff --git a/libstb/secvar/storage/secboot_tpm_switchable.h b/libstb/secvar/storage/secboot_tpm_switchable.h
new file mode 100644
index 00000000..2c95b387
--- /dev/null
+++ b/libstb/secvar/storage/secboot_tpm_switchable.h
@@ -0,0 +1,15 @@
+#ifndef _SECBOOT_TPM_SWITCHABLE_H_
+#define _SECBOOT_TPM_SWITCHABLE_H_
+
+#include <stdint.h>
+
+#define SECBOOT_TPMNV_MODE_INDEX 0x01c10192
+
+extern uint64_t mode_value;
+
+enum switchable_modes {
+        USER_MODE,
+        SYSTEM_MODE,
+};
+
+#endif
\ No newline at end of file
