diff --git a/libstb/Makefile.inc b/libstb/Makefile.inc
index 6d54c5cd..5cd6c2ee 100644
--- a/libstb/Makefile.inc
+++ b/libstb/Makefile.inc
@@ -4,7 +4,7 @@ LIBSTB_DIR = libstb
 
 SUBDIRS += $(LIBSTB_DIR)
 
-LIBSTB_SRCS = container.c tpm_chip.c cvc.c secureboot.c trustedboot.c
+LIBSTB_SRCS = container.c tpm_chip.c cvc.c secureboot.c trustedboot.c secboot_part.c
 LIBSTB_OBJS = $(LIBSTB_SRCS:%.c=%.o)
 LIBSTB = $(LIBSTB_DIR)/built-in.a
 
diff --git a/libstb/secboot_part.c b/libstb/secboot_part.c
new file mode 100644
index 00000000..e6558166
--- /dev/null
+++ b/libstb/secboot_part.c
@@ -0,0 +1,249 @@
+/* Copyright 2013-2018 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef pr_fmt
+#define pr_fmt(fmt) "SECBOOT_PART: " fmt
+#endif
+
+#include <skiboot.h>
+#include "secboot_part.h"
+
+struct secboot_section_item {
+	const char *name;  /* null terminated string */
+	uint32_t size;
+	char data[0];
+} __packed;
+
+struct secboot_section_header {
+	uint8_t version;
+	uint32_t reserved;
+	uint32_t size;
+} __packed;
+
+struct secboot_section {
+	struct secboot_section_header header;
+	struct secboot_section_item item[0]; // section_item place holder
+	// followed by other section items up to section size:
+	//	SECBOOT_BANK_SIZE if it is bank section; or
+	//	SECBOOT_QUEUE_SIZE if it is an update queue section
+} __packed;
+
+struct secboot_header {
+	uint32_t magic_number;
+	uint8_t version;
+} __packed;
+
+struct secboot_part {
+	struct secboot_header header;
+	struct secboot_section bank[0]; // section_header place holder
+	// followed by bank1 section
+	// followed by update queue section
+} __packed;
+
+//#define SECBOOT_SECTION_SIZE(p)  (sizeof(section_header) + p->size)
+/* 0x5053424b = "PSBK" or Power Secure Boot Keystore */
+#define SECBOOT_MAGIC_NUMBER		0x5053424b
+#define SECBOOT_VERSION			1
+#define SECBOOT_MINIMUM_SIZE (sizeof(struct secboot_header) + SECBOOT_BANK_SIZE*2 + SECBOOT_QUEUE_SIZE)
+
+#define SECBOOT_BANK_VERSION		1
+#define SECBOOT_BANK_SIZE		0xb400   // 45 KB
+
+#define SECBOOT_QUEUE_VERSION		1
+#define SECBOOT_QUEUE_SIZE		0x7800   // 30 KB
+
+static struct secboot_part *secboot = NULL;
+static uint32_t secboot_size = 0;
+
+/* Indicates if the secboot partition data can be consumed */
+static bool secboot_valid = false;
+
+static struct secboot_section *active_bank = NULL;
+static struct secboot_section *staging_bank = NULL;
+static struct secboot_section *update_queue = NULL;
+
+static int secboot_part_format(void)
+{
+	struct secboot_section *section;
+	int rc;
+
+	if (!platform.secboot_write)
+		return -1;
+
+	memset(secboot, 0, secboot_size);
+
+	/* INITIALIZE THE HEADERS */
+
+	/* secboot header */
+	secboot->header.magic_number = SECBOOT_MAGIC_NUMBER;
+	secboot->header.version = SECBOOT_VERSION;
+
+	/* bank0 section header */
+	section = secboot->bank;
+	section->header.version = SECBOOT_BANK_VERSION;
+	section->header.reserved = 0;
+	section->header.size = SECBOOT_BANK_SIZE;
+
+	/* bank1 section header */
+	section = (struct secboot_section*)((uint8_t*) section + SECBOOT_BANK_SIZE);
+	section->header.version = SECBOOT_BANK_VERSION;
+	section->header.reserved = 0;
+	section->header.size = SECBOOT_BANK_SIZE;
+
+	/* update queue section header */
+	section = (struct secboot_section*)((uint8_t*) section + SECBOOT_BANK_SIZE);
+	section->header.version = SECBOOT_QUEUE_VERSION;
+	section->header.reserved = 0;
+	section->header.size = SECBOOT_QUEUE_SIZE;
+
+	/* write the whole thing back to PNOR */
+	rc = platform.secboot_write(0, secboot, secboot_size);
+	if (rc)
+		return -1;
+
+	prlog(PR_INFO, "formatted\n");
+	secboot_valid = true;
+
+	return 0;
+}
+
+/*
+ * Check that the keystore layout is sane. If not, we re-format the lot of it
+ */
+static int secboot_part_validate(void)
+{
+	if (secboot->header.magic_number != SECBOOT_MAGIC_NUMBER) {
+		prlog(PR_ERR, "magic number 0x%x mismatch, expected 0x%x\n",
+		      secboot->header.magic_number, SECBOOT_MAGIC_NUMBER);
+		return -1;
+	}
+	if (secboot->header.version != SECBOOT_VERSION) {
+		prlog(PR_ERR, "secboot version %d not supported, expected %d\n",
+		      secboot->header.version, SECBOOT_VERSION);
+		return -1;
+	}
+
+	/*
+	 * No need to check the staging bank version, we may overwrite it at
+	 * runtime but we don't consume it
+	 */
+
+	active_bank = secboot->bank;
+	if (active_bank->header.version != SECBOOT_BANK_VERSION) {
+		prlog(PR_ERR, "active bank version %d not supported, expected %d\n",
+		      active_bank->header.version, SECBOOT_BANK_VERSION);
+		return -1;
+	}
+
+	staging_bank = active_bank;
+	update_queue = (struct secboot_section*)((uint8_t*) secboot->bank +  secboot->bank->header.size);
+	update_queue = (struct secboot_section*)((uint8_t*) update_queue + update_queue->header.size);
+
+	if (update_queue->header.version != SECBOOT_QUEUE_VERSION) {
+		prlog(PR_ERR, "update queue version %d not supported, expected %d\n",
+		      update_queue->header.version, SECBOOT_QUEUE_VERSION);
+		return -1;
+	}
+
+	prlog(PR_INFO, "secboot partition valid\n");
+	secboot_valid = true;
+	return 0;
+}
+
+
+int secboot_part_init()
+{
+	int rc;
+
+	/* Already initialized */
+	if (secboot)
+		return 0;
+
+	if (!platform.secboot_info)
+		return -1;
+	rc = platform.secboot_info(&secboot_size);
+	if (rc) {
+		prlog(PR_ERR, "error %d retrieving keystore info\n", rc);
+		return -1;
+	}
+	if (SECBOOT_MINIMUM_SIZE > secboot_size) {
+		prlog(PR_ERR, "secboot partition %d KB too small. min=%ld\n",
+		      secboot_size >> 10, SECBOOT_MINIMUM_SIZE);
+		return -1;
+	}
+
+	prlog(PR_INFO, "size is %d KB\n", secboot_size >> 10);
+
+	/*
+	 * We allocate the pnor secboot image with 4k alignment to make the
+	 * FSP backend job's easier
+	 */
+	secboot = memalign(0x1000, secboot_size);
+	if (!secboot) {
+		prlog(PR_ERR, "failed to allocate the secboot partition buffer\n");
+		secboot_size = 0;
+		return -1;
+	}
+
+	/* Read it in */
+	rc = platform.secboot_read(secboot, 0, secboot_size);
+	if (rc) {
+		prlog(PR_ERR, "failed to read the secboot partition, rc=%d\n", rc);
+		goto out_free;
+	}
+
+	/*
+	 * TODO:
+	 * 1. Can we assume that the secboot partition is zeroed out in MFG?
+	 */
+	if (secboot->header.magic_number == 0xffffffff ||
+	    secboot->header.version == 0xff ||
+	    secboot->header.magic_number == 0x00000000) {
+		rc = secboot_part_format();
+		if (rc)
+			goto out_free;
+	}
+
+	rc = secboot_part_validate();
+	if (rc)
+		goto out_free;
+
+	/* secboot header */
+	prlog(PR_INFO, "secboot->magic_number 0x%x\n", secboot->header.magic_number);
+	prlog(PR_INFO, "secboot->version %d\n", secboot->header.version);
+	/* active bank header */
+	prlog(PR_INFO, "active->version %d\n", active_bank->header.version);
+	prlog(PR_INFO, "active->reserved 0x%x\n", active_bank->header.reserved);
+	prlog(PR_INFO, "active->size %d KB\n", active_bank->header.size >> 10);
+	/* staging bank header */
+	prlog(PR_INFO, "staging->version %d\n", staging_bank->header.version);
+	prlog(PR_INFO, "staging->reserved 0x%x\n", staging_bank->header.reserved);
+	prlog(PR_INFO, "staging->size %d KB\n", staging_bank->header.size >> 10);
+	/* update queue header */
+	prlog(PR_INFO, "queue->version %d\n", update_queue->header.version);
+	prlog(PR_INFO, "queue->reserved 0x%x\n", update_queue->header.reserved);
+	prlog(PR_INFO, "queue->size %d KB\n", update_queue->header.size >> 10);
+
+	return 0;
+
+out_free:
+	if (secboot) {
+		free(secboot);
+		secboot = NULL;
+		secboot_size = 0;
+	}
+	return -1;
+}
diff --git a/libstb/secboot_part.h b/libstb/secboot_part.h
new file mode 100644
index 00000000..7f29183b
--- /dev/null
+++ b/libstb/secboot_part.h
@@ -0,0 +1,22 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __SECBOOT_PART_H
+#define __SECBOOT_PART_H
+
+int secboot_part_init(void);
+
+#endif /* __SECBOOT_PART_H */
