aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudio Carvalho <cclaudio@linux.ibm.com>2020-09-16 11:21:23 -0500
committerOliver O'Halloran <oohall@gmail.com>2020-10-01 13:44:06 +1000
commited8436b276f26e9706ac20d11e5a8ab1314a65cb (patch)
tree6db15abf7ccd06cd92f35c3456d0561465576172
parentedafe7532b9c0e5372e784c18bd500d23b8257a0 (diff)
downloadskiboot-ed8436b276f26e9706ac20d11e5a8ab1314a65cb.zip
skiboot-ed8436b276f26e9706ac20d11e5a8ab1314a65cb.tar.gz
skiboot-ed8436b276f26e9706ac20d11e5a8ab1314a65cb.tar.bz2
core/flash.c: add SECBOOT read and write support
In secure boot enabled systems, the petitboot linux kernel verifies the OS kernel against x509 certificates that are wrapped in secure variables controlled by OPAL. These secure variables are stored in the PNOR SECBOOT partition, as well as the updates submitted for them using userspace tools. This patch adds read and write support to the PNOR SECBOOT partition in a similar fashion to that of NVRAM, so that OPAL can handle the secure variables. Signed-off-by: Claudio Carvalho <cclaudio@linux.ibm.com> Signed-off-by: Eric Richter <erichte@linux.ibm.com> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
-rw-r--r--core/flash.c126
-rw-r--r--include/skiboot.h3
2 files changed, 129 insertions, 0 deletions
diff --git a/core/flash.c b/core/flash.c
index de74864..8c1e788 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -59,6 +59,10 @@ static struct lock flash_lock;
static struct flash *nvram_flash;
static u32 nvram_offset, nvram_size;
+/* secboot-on-flash support */
+static struct flash *secboot_flash;
+static u32 secboot_offset, secboot_size;
+
bool flash_reserve(void)
{
bool rc = false;
@@ -93,6 +97,91 @@ bool flash_unregister(void)
return true;
}
+int flash_secboot_info(uint32_t *total_size)
+{
+ int rc;
+
+ lock(&flash_lock);
+ if (!secboot_flash) {
+ rc = OPAL_HARDWARE;
+ } else if (secboot_flash->busy) {
+ rc = OPAL_BUSY;
+ } else {
+ *total_size = secboot_size;
+ rc = OPAL_SUCCESS;
+ }
+ unlock(&flash_lock);
+
+ return rc;
+}
+
+int flash_secboot_read(void *dst, uint32_t src, uint32_t len)
+{
+ int rc;
+
+ if (!try_lock(&flash_lock))
+ return OPAL_BUSY;
+
+ if (!secboot_flash) {
+ rc = OPAL_HARDWARE;
+ goto out;
+ }
+
+ if (secboot_flash->busy) {
+ rc = OPAL_BUSY;
+ goto out;
+ }
+
+ if ((src + len) > secboot_size) {
+ prerror("FLASH_SECBOOT: read out of bound (0x%x,0x%x)\n",
+ src, len);
+ rc = OPAL_PARAMETER;
+ goto out;
+ }
+
+ secboot_flash->busy = true;
+ unlock(&flash_lock);
+
+ rc = blocklevel_read(secboot_flash->bl, secboot_offset + src, dst, len);
+
+ lock(&flash_lock);
+ secboot_flash->busy = false;
+out:
+ unlock(&flash_lock);
+ return rc;
+}
+
+int flash_secboot_write(uint32_t dst, void *src, uint32_t len)
+{
+ int rc;
+
+ if (!try_lock(&flash_lock))
+ return OPAL_BUSY;
+
+ if (secboot_flash->busy) {
+ rc = OPAL_BUSY;
+ goto out;
+ }
+
+ if ((dst + len) > secboot_size) {
+ prerror("FLASH_SECBOOT: write out of bound (0x%x,0x%x)\n",
+ dst, len);
+ rc = OPAL_PARAMETER;
+ goto out;
+ }
+
+ secboot_flash->busy = true;
+ unlock(&flash_lock);
+
+ rc = blocklevel_write(secboot_flash->bl, secboot_offset + dst, src, len);
+
+ lock(&flash_lock);
+ secboot_flash->busy = false;
+out:
+ unlock(&flash_lock);
+ return rc;
+}
+
static int flash_nvram_info(uint32_t *total_size)
{
int rc;
@@ -182,6 +271,42 @@ out:
return rc;
}
+
+static int flash_secboot_probe(struct flash *flash, struct ffs_handle *ffs)
+{
+ uint32_t start, size, part;
+ bool ecc;
+ int rc;
+
+ prlog(PR_DEBUG, "FLASH: probing for SECBOOT\n");
+
+ rc = ffs_lookup_part(ffs, "SECBOOT", &part);
+ if (rc) {
+ prlog(PR_WARNING, "FLASH: no SECBOOT partition found\n");
+ return OPAL_HARDWARE;
+ }
+
+ rc = ffs_part_info(ffs, part, NULL,
+ &start, &size, NULL, &ecc);
+ if (rc) {
+ /**
+ * @fwts-label SECBOOTNoPartition
+ * @fwts-advice OPAL could not find an SECBOOT partition
+ * on the system flash. Check that the system flash
+ * has a valid partition table, and that the firmware
+ * build process has added a SECBOOT partition.
+ */
+ prlog(PR_ERR, "FLASH: Can't parse ffs info for SECBOOT\n");
+ return OPAL_HARDWARE;
+ }
+
+ secboot_flash = flash;
+ secboot_offset = start;
+ secboot_size = ecc ? ecc_buffer_size_minus_ecc(size) : size;
+
+ return 0;
+}
+
static int flash_nvram_probe(struct flash *flash, struct ffs_handle *ffs)
{
uint32_t start, size, part;
@@ -332,6 +457,7 @@ static void setup_system_flash(struct flash *flash, struct dt_node *node,
prlog(PR_INFO, "registered system flash device %s\n", name);
flash_nvram_probe(flash, ffs);
+ flash_secboot_probe(flash, ffs);
}
static int num_flashes(void)
diff --git a/include/skiboot.h b/include/skiboot.h
index 30ff500..7b71ebd 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -229,6 +229,9 @@ extern int flash_subpart_info(void *part_header, uint32_t header_len,
extern void flash_fw_version_preload(void);
extern void flash_dt_add_fw_version(void);
extern const char *flash_map_resource_name(enum resource_id id);
+extern int flash_secboot_info(uint32_t *total_size);
+extern int flash_secboot_read(void *dst, uint32_t src, uint32_t len);
+extern int flash_secboot_write(uint32_t dst, void *src, uint32_t len);
/*
* Decompression routines