[U-Boot] [PATCHV5 3/6] ARMv8/layerscape: Add FSL PPA support

Zhiqiang Hou zhiqiang.hou at nxp.com
Sun Jun 12 05:53:50 CEST 2016


Hi York,

Thanks for your comments!

> -----Original Message-----
> From: York Sun [mailto:york.sun at nxp.com]
> Sent: 2016年6月8日 8:51
> To: Zhiqiang Hou <zhiqiang.hou at nxp.com>; u-boot at lists.denx.de;
> albert.u.boot at aribaud.net; scottwood at freescale.com;
> Mingkai.hu at freescale.com; yorksun at freescale.com; leoli at freescale.com;
> prabhakar at freescale.com; bhupesh.sharma at freescale.com
> Subject: Re: [PATCHV5 3/6] ARMv8/layerscape: Add FSL PPA support
> 
> On 06/04/2016 11:40 PM, Zhiqiang Hou wrote:
> > From: Hou Zhiqiang <Zhiqiang.Hou at nxp.com>
> >
> > The FSL Primary Protected Application (PPA) is a software component
> > loaded during boot which runs in TrustZone and remains resident after
> > boot.
> >
> > Signed-off-by: Hou Zhiqiang <Zhiqiang.Hou at nxp.com>
> > ---
> > V5:
> >  - Added API sec_firmware_init() implementation.
> >
> > V4:
> >  - Moved secure firmware validation API to this patch.
> >  - Moved secure firmware getting supported PSCI version API to this patch.
> >
> > V3:
> >  - Refactor the code.
> >  - Add PPA firmware version info output.
> >
> >  arch/arm/cpu/armv8/fsl-layerscape/Makefile     |   1 +
> >  arch/arm/cpu/armv8/fsl-layerscape/ppa.c        | 311
> +++++++++++++++++++++++++
> >  arch/arm/cpu/armv8/fsl-layerscape/ppa_entry.S  |  53 +++++
> > arch/arm/include/asm/arch-fsl-layerscape/ppa.h |  14 ++
> >  arch/arm/include/asm/armv8/sec_firmware.h      |   4 +
> >  5 files changed, 383 insertions(+)
> >  create mode 100644 arch/arm/cpu/armv8/fsl-layerscape/ppa.c
> >  create mode 100644 arch/arm/cpu/armv8/fsl-layerscape/ppa_entry.S
> >  create mode 100644 arch/arm/include/asm/arch-fsl-layerscape/ppa.h
> >
> > diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Makefile
> > b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
> > index 5f86ef9..1535fee 100644
> > --- a/arch/arm/cpu/armv8/fsl-layerscape/Makefile
> > +++ b/arch/arm/cpu/armv8/fsl-layerscape/Makefile
> > @@ -10,6 +10,7 @@ obj-y += soc.o
> >  obj-$(CONFIG_MP) += mp.o
> >  obj-$(CONFIG_OF_LIBFDT) += fdt.o
> >  obj-$(CONFIG_SPL) += spl.o
> > +obj-$(CONFIG_FSL_LS_PPA) += ppa.o ppa_entry.o
> >
> >  ifneq ($(CONFIG_FSL_LSCH3),)
> >  obj-y += fsl_lsch3_speed.o
> > diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
> > b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
> > new file mode 100644
> > index 0000000..6a75960
> > --- /dev/null
> > +++ b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
> > @@ -0,0 +1,311 @@
> > +/*
> > + * Copyright 2016 NXP Semiconductor, Inc.
> > + *
> > + * SPDX-License-Identifier:	GPL-2.0+
> > + */
> > +#include <common.h>
> > +#include <config.h>
> > +#include <errno.h>
> > +#include <malloc.h>
> > +#include <asm/system.h>
> > +#include <asm/io.h>
> > +#include <asm/types.h>
> > +#include <asm/macro.h>
> > +#include <asm/arch/soc.h>
> > +#ifdef CONFIG_FSL_LSCH3
> > +#include <asm/arch/immap_lsch3.h>
> > +#elif defined(CONFIG_FSL_LSCH2)
> > +#include <asm/arch/immap_lsch2.h>
> > +#endif
> > +#ifdef CONFIG_ARMV8_SEC_FIRMWARE_SUPPORT #include
> > +<asm/armv8/sec_firmware.h> #endif
> > +
> > +DECLARE_GLOBAL_DATA_PTR;
> > +
> > +extern void c_runtime_cpu_setup(void);
> > +
> > +#define LS_PPA_FIT_FIRMWARE_IMAGE	"firmware"
> > +#define LS_PPA_FIT_CNF_NAME		"config at 1"
> > +#define PPA_MEM_SIZE_ENV_VAR		"ppamemsize"
> > +
> > +/*
> > + * Return the actual size of the PPA private DRAM block.
> > + */
> > +unsigned long ppa_get_dram_block_size(void) {
> > +	unsigned long dram_block_size =
> > +CONFIG_SYS_LS_PPA_DRAM_BLOCK_MIN_SIZE;
> > +
> > +	char *dram_block_size_env_var = getenv(PPA_MEM_SIZE_ENV_VAR);
> > +
> > +	if (dram_block_size_env_var) {
> > +		dram_block_size = simple_strtoul(dram_block_size_env_var,
> NULL,
> > +						 10);
> > +
> > +		if (dram_block_size <
> CONFIG_SYS_LS_PPA_DRAM_BLOCK_MIN_SIZE) {
> > +			printf("fsl-ppa: WARNING: Invalid value for \'"
> > +			       PPA_MEM_SIZE_ENV_VAR
> > +			       "\' environment variable: %lu\n",
> > +			       dram_block_size);
> > +
> > +			dram_block_size =
> CONFIG_SYS_LS_PPA_DRAM_BLOCK_MIN_SIZE;
> > +		}
> > +	}
> > +
> > +	return dram_block_size;
> > +}
> > +
> > +static bool ppa_firmware_is_valid(void *ppa_addr) {
> > +	void *fit_hdr;
> > +
> > +	fit_hdr = ppa_addr;
> > +
> > +	if (fdt_check_header(fit_hdr)) {
> > +		printf("fsl-ppa: Bad firmware image (not a FIT image)\n");
> > +		return false;
> > +	}
> > +
> > +	if (!fit_check_format(fit_hdr)) {
> > +		printf("fsl-ppa: Bad firmware image (bad FIT header)\n");
> > +		return false;
> > +	}
> > +
> > +	return true;
> > +}
> > +
> > +static int ppa_firmware_get_data(void *ppa_addr,
> > +				const void **data, size_t *size)
> > +{
> > +	void *fit_hdr;
> > +	int conf_node_off, fw_node_off;
> > +	char *conf_node_name = NULL;
> > +	char *desc;
> > +	int ret;
> > +
> > +	fit_hdr = ppa_addr;
> > +	conf_node_name = LS_PPA_FIT_CNF_NAME;
> > +
> > +	conf_node_off = fit_conf_get_node(fit_hdr, conf_node_name);
> > +	if (conf_node_off < 0) {
> > +		printf("fsl-ppa: %s: no such config\n", conf_node_name);
> > +		return -ENOENT;
> > +	}
> > +
> > +	fw_node_off = fit_conf_get_prop_node(fit_hdr, conf_node_off,
> > +			LS_PPA_FIT_FIRMWARE_IMAGE);
> > +	if (fw_node_off < 0) {
> > +		printf("fsl-ppa: No '%s' in config\n",
> > +				LS_PPA_FIT_FIRMWARE_IMAGE);
> > +		return -ENOLINK;
> > +	}
> > +
> > +	/* Verify PPA firmware image */
> > +	if (!(fit_image_verify(fit_hdr, fw_node_off))) {
> > +		printf("fsl-ppa: Bad firmware image (bad CRC)\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (fit_image_get_data(fit_hdr, fw_node_off, data, size)) {
> > +		printf("fsl-ppa: Can't get %s subimage data/size",
> > +				LS_PPA_FIT_FIRMWARE_IMAGE);
> > +		return -ENOENT;
> > +	}
> > +
> > +	ret = fit_get_desc(fit_hdr, fw_node_off, &desc);
> > +	if (ret)
> > +		printf("PPA Firmware unavailable\n");
> > +	else
> > +		printf("%s\n", desc);
> > +
> > +	return 0;
> > +}
> > +
> > +/*
> > + * PPA firmware FIT image parser checks if the image is in FIT
> > + * format, verifies integrity of the image and calculates raw
> > + * image address and size values.
> > + *
> > + * Returns 0 on success and a negative errno on error task fail.
> > + */
> > +static int ppa_parse_firmware_fit_image(const void **raw_image_addr,
> > +				size_t *raw_image_size)
> > +{
> > +	void *ppa_addr;
> > +	int ret;
> > +
> > +#ifdef CONFIG_SYS_LS_PPA_FW_IN_NOR
> > +	ppa_addr = (void *)CONFIG_SYS_LS_PPA_FW_ADDR; #else #error "No
> > +CONFIG_SYS_LS_PPA_FW_IN_xxx defined"
> > +#endif
> > +
> > +	if (!ppa_firmware_is_valid(ppa_addr))
> > +		return -1;
> > +
> > +	ret = ppa_firmware_get_data(ppa_addr, raw_image_addr,
> raw_image_size);
> > +	if (ret)
> > +		return ret;
> > +
> > +	debug("fsl-ppa: raw_image_addr = 0x%p, raw_image_size = 0x%lx\n",
> > +			*raw_image_addr, *raw_image_size);
> > +
> > +	return 0;
> > +}
> > +
> > +static int ppa_copy_image(const char *title,
> > +			 u64 image_addr, u32 image_size, u64 ppa_ram_addr) {
> > +	debug("%s copied to address 0x%p\n", title, (void *)ppa_ram_addr);
> > +	memcpy((void *)ppa_ram_addr, (void *)image_addr, image_size);
> > +	flush_dcache_range(ppa_ram_addr, ppa_ram_addr + image_size);
> > +
> > +	return 0;
> > +}
> > +
> > +static int ppa_init_pre(u64 *entry)
> > +{
> > +	u64 ppa_ram_addr;
> > +	const void *raw_image_addr;
> > +	size_t raw_image_size = 0;
> > +	size_t ppa_ram_size = ppa_get_dram_block_size();
> > +	int ret;
> > +
> > +	debug("fsl-ppa: ppa size(0x%lx)\n", ppa_ram_size);
> > +
> > +	/*
> > +	 * The Excetpion Level must be EL3 to prepare and initialize the PPA.
> > +	 */
> > +	if (current_el() != 3) {
> > +		ret = -EACCES;
> > +		goto out;
> > +	}
> > +
> > +#ifdef CONFIG_SYS_MEM_RESERVE_SECURE
> > +	/*
> > +	 * The PPA must be stored in secure memory.
> > +	 * Append PPA to secure mmu table.
> > +	 */
> > +	if (!(gd->secure_ram & MEM_RESERVE_SECURE_MAINTAINED)) {
> > +		ret = -ENXIO;
> > +		goto out;
> > +	}
> > +
> > +	ppa_ram_addr = (gd->secure_ram &
> MEM_RESERVE_SECURE_ADDR_MASK) +
> > +			gd->arch.tlb_size;
> > +#else
> > +#error "The CONFIG_SYS_MEM_RESERVE_SECURE must be defined when
> enabled PPA"
> > +#endif
> > +
> > +	/* Align PPA base address to 4K */
> > +	ppa_ram_addr = (ppa_ram_addr + 0xfff) & ~0xfff;
> > +	debug("fsl-ppa: PPA load address (0x%llx)\n", ppa_ram_addr);
> > +
> > +	ret = ppa_parse_firmware_fit_image(&raw_image_addr,
> &raw_image_size);
> > +	if (ret < 0)
> > +		goto out;
> > +
> > +	if (ppa_ram_size < raw_image_size) {
> > +		ret = -ENOSPC;
> > +		goto out;
> > +	}
> > +
> > +	/* TODO:
> > +	 * Check if the end addr of PPA has been extend the secure memory.
> > +	 */
> > +
> > +	ppa_copy_image("PPA firmware", (u64)raw_image_addr,
> > +			raw_image_size, ppa_ram_addr);
> > +
> > +	debug("fsl-ppa: PPA entry: 0x%llx\n", ppa_ram_addr);
> > +	*entry = ppa_ram_addr;
> > +
> > +	return 0;
> > +
> > +out:
> > +	printf("fsl-ppa: error (%d)\n", ret);
> > +	*entry = 0;
> > +
> > +	return ret;
> > +}
> > +
> > +static int ppa_init_entry(void *ppa_entry) {
> > +	int ret;
> > +	u32 *boot_loc_ptr_l, *boot_loc_ptr_h;
> > +
> > +#ifdef CONFIG_FSL_LSCH3
> > +	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
> > +	boot_loc_ptr_l = &gur->bootlocptrl;
> > +	boot_loc_ptr_h = &gur->bootlocptrh;
> > +#elif defined(CONFIG_FSL_LSCH2)
> > +	struct ccsr_scfg __iomem *scfg = (void *)(CONFIG_SYS_FSL_SCFG_ADDR);
> > +	boot_loc_ptr_l = &scfg->scratchrw[1];
> > +	boot_loc_ptr_h = &scfg->scratchrw[0]; #endif
> > +
> > +	debug("fsl-ppa: boot_loc_ptr_l = 0x%p, boot_loc_ptr_h =0x%p\n",
> > +			boot_loc_ptr_l, boot_loc_ptr_h);
> > +	ret = ppa_init(ppa_entry, boot_loc_ptr_l, boot_loc_ptr_h);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	debug("fsl-ppa: Return from PPA: current_el = %d\n", current_el());
> > +
> > +	/* The PE will be turned into EL2 when run out of PPA. */
> > +	if (current_el() != 2)
> > +		return -EACCES;
> > +
> > +	/*
> > +	 * First, set vector for EL2.
> > +	 */
> > +	c_runtime_cpu_setup();
> > +
> > +	/* Enable caches and MMU for EL2. */
> > +	enable_caches();
> > +
> > +	return 0;
> > +}
> > +
> > +bool sec_firmware_is_valid(void)
> > +{
> > +	void *ppa_addr;
> > +
> > +#ifdef CONFIG_SYS_LS_PPA_FW_IN_NOR
> > +	ppa_addr = (void *)CONFIG_SYS_LS_PPA_FW_ADDR; #else #error "No
> > +CONFIG_SYS_LS_PPA_FW_IN_xxx defined"
> > +#endif
> > +
> > +	return ppa_firmware_is_valid(ppa_addr); }
> > +
> > +#ifdef CONFIG_ARMV8_PSCI
> > +unsigned int sec_firmware_support_psci_version(void)
> > +{
> > +	unsigned int psci_ver = 0;
> > +
> > +	if (sec_firmware_is_valid())
> > +		psci_ver = ppa_support_psci_version();
> > +
> > +	return psci_ver;
> > +}
> > +#endif
> 
> 
> Zhiqiang,
> 
> I am not convinced this function can be used to prove ppa is up and running, as you
> used in your 4th patch in this set. See more comment there.
> 
> This function can return a psci version number based on the image. Is it possible to
> make a PSCI call to return the version of running image?

The psci version isn't based on the image but psci_version call, see my feedback for the
4th patch comments.

Thanks,
Zhiqiang


More information about the U-Boot mailing list