[Skiboot] [RFC 1/6] core/flash.c: add SECBOOT read and write support

Oliver oohall at gmail.com
Fri Mar 29 12:55:43 AEDT 2019


On Fri, Mar 29, 2019 at 9:18 AM Eric Richter <erichte at linux.ibm.com> wrote:
>
> From: Claudio Carvalho <cclaudio at linux.ibm.com>
>
> 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 so
> that OPAL can handle the secure variables.
>
> CC: Jeremy Kerr <jk at ozlabs.org>
> Signed-off-by: Claudio Carvalho <cclaudio at linux.ibm.com>
> ---
>  core/flash.c       | 130 +++++++++++++++++++++++++++++++++++++++++++++
>  include/platform.h |   4 ++
>  2 files changed, 134 insertions(+)
>
> diff --git a/core/flash.c b/core/flash.c
> index 90189dd6..4de52e3f 100644
> --- a/core/flash.c
> +++ b/core/flash.c
> @@ -50,6 +50,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;
> @@ -73,6 +77,91 @@ void flash_release(void)
>         unlock(&flash_lock);
>  }
>
> +static 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;
> +}
> +
> +static 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;
> +}
> +
> +static 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;
> +}

Looks like a lot of this is copy+pasted from the nvram partition
reading code below. It's probably a good idea to factor out the common
bits into a flash_partion_read() or similar to cut down on the amount
of duplication.

> +
>  static int flash_nvram_info(uint32_t *total_size)
>  {
>         int rc;
> @@ -162,6 +251,46 @@ 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_INFO, "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;
> +
> +       platform.secboot_info = flash_secboot_info;
> +       platform.secboot_read = flash_secboot_read;
> +       platform.secboot_write = flash_secboot_write;
> +
> +       return 0;
> +}
> +
>  static int flash_nvram_probe(struct flash *flash, struct ffs_handle *ffs)
>  {
>         uint32_t start, size, part;
> @@ -255,6 +384,7 @@ static void setup_system_flash(struct flash *flash, struct dt_node *node,
>         prlog(PR_INFO, "FLASH: 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/platform.h b/include/platform.h
> index de4638f3..0cc9c234 100644
> --- a/include/platform.h
> +++ b/include/platform.h
> @@ -181,6 +181,10 @@ struct platform {
>                                             uint32_t len);
>         int             (*nvram_write)(uint32_t dst, void *src, uint32_t len);
>
> +       int (*secboot_info)(uint32_t *total_size);
> +       int (*secboot_read)(void *dst, uint32_t src, uint32_t len);
> +       int (*secboot_write)(uint32_t dst, void *src, uint32_t len);
> +
>         /*
>          * OCC timeout. This return how long we should wait for the OCC
>          * before timing out. This lets us use a high value on larger FSP
> --
> 2.17.2
>
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot


More information about the Skiboot mailing list