[Skiboot] [RFC PATCH RESEND 02/10] core/flash.c: add SECBOOT read and write support

Stewart Smith stewart at linux.ibm.com
Mon Mar 4 16:44:44 AEDT 2019


Eric Richter <erichte at linux.ibm.com> writes:

> From: Claudio Carvalho <cclaudio at linux.ibm.com>
>
> The SECBOOT partition is used to store secure boot variables and variable
> updates. A variable/update can store several data types, including a x509
> certificate, but for skiboot the variable/update data is a blob that can be
> handled by the linux kernel via secure boot runtime services (added by
> other patches in this series).

It would be good to detail here why it's different to NVRAM and what the
semantic differences are.

>
> This implements the SECBOOT API required to provide the aforementioned
> runtime services. This implementation is based on the NVRAM API
> implementation.

What are things going to look like for FSP based systems? Are we going
to get similar calls to the NVRAM ones?

> NOTE: There are other ways to implement the SECBOOT API, for example
> extending the current resource load framework (flash API). Issues:
> (1) Looking at the NVRAM code, it seems that the flash API should be used
> only for boot services. (2) The flash API spend some space with partition
> and subpartition headers, but the SECBOOT space is very limited for the
> purpose. (3) The flash API doesn't support partial writes to a partition or
> subpartition. The SECBOOT API can also be implemented extending the NVRAM
> API. The same platform hooks could be used if a new parameter is added to
> determine the partition.

The resource framework is only for boot time, yes. It's designed to only
be used when OPAL has control, as it fundamentally does things
asynchronously in a way that only works when skiboot has complete
control.


> CC: Jeremy Kerr <jk at ozlabs.org>
> Signed-off-by: Claudio Carvalho <cclaudio at linux.ibm.com>
> ---
>  core/flash.c       | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/platform.h |   4 ++
>  2 files changed, 122 insertions(+)
>
> diff --git a/core/flash.c b/core/flash.c
> index 8f00d85e..4e952cb0 100644
> --- a/core/flash.c
> +++ b/core/flash.c
> @@ -49,6 +49,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;
> +
>  /* ibm,firmware-versions support */
>  static char *version_buf;
>  static size_t version_buf_size = 0x2000;
> @@ -76,6 +80,80 @@ 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;
> +	}
> +
> +	rc = blocklevel_read(secboot_flash->bl, secboot_offset + src, dst, len);
> +
> +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;
> +	}
> +	rc = blocklevel_write(secboot_flash->bl, secboot_offset + dst, src, len);
> +
> +out:
> +	unlock(&flash_lock);
> +	return rc;
> +}
> +
>  static int flash_nvram_info(uint32_t *total_size)
>  {
>  	int rc;
> @@ -283,6 +361,45 @@ void flash_fw_version_preload(void)
>  	}
>  }
>  
> +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");

PR_DEBUG or PR_TRACE, we probably don't need this printed to the console.

> +
> +	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;
> +	}

Should we enforce secure boot here? As in, if booting securely, do we
erase everything?

What is the behaviour of the system in the event of corruption? Should
there be a golden image that's signed and immutable?

> +	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;
> @@ -376,6 +493,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 1a35a86a..1ecafe74 100644
> --- a/include/platform.h
> +++ b/include/platform.h
> @@ -161,6 +161,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.14.4
>
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot
>

-- 
Stewart Smith
OPAL Architect, IBM.



More information about the Skiboot mailing list