diff mbox

[U-Boot,PATCHv4,3/7] ARMv8/layerscape: Add FSL PPA support

Message ID 1464003511-19262-3-git-send-email-Zhiqiang.Hou@nxp.com
State Superseded
Delegated to: York Sun
Headers show

Commit Message

Z.Q. Hou May 23, 2016, 11:38 a.m. UTC
From: Hou Zhiqiang <Zhiqiang.Hou@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 <Zhiqiag.Hou@nxp.com>
---
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        | 268 +++++++++++++++++++++++++
 arch/arm/cpu/armv8/fsl-layerscape/ppa_entry.S  |  53 +++++
 arch/arm/include/asm/arch-fsl-layerscape/ppa.h |  16 ++
 arch/arm/include/asm/armv8/sec_firmware.h      |   4 +
 5 files changed, 341 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

Comments

York Sun May 27, 2016, 6:06 p.m. UTC | #1
On 05/23/2016 04:48 AM, Zhiqiang Hou wrote:
> From: Hou Zhiqiang <Zhiqiang.Hou@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 <Zhiqiag.Hou@nxp.com>
> ---
> 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.
> 
<snip>

> +int sec_firmware_validate(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_validate(ppa_addr);
> +}

You are returning 0 when the image is valid. This function name is confusing.
How about declare it as bool, and change the name to is_sec_firmware_valid()?

> +
> +#ifdef CONFIG_ARMV8_PSCI
> +unsigned int sec_firmware_support_psci_version(void)
> +{
> +	unsigned int psci_ver = 0;
> +
> +	if (!sec_firmware_validate())
> +		psci_ver = ppa_support_psci_version();
> +
> +	return psci_ver;
> +}
> +#endif
> +
> +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 PPA must be stored in secure memory.
> +	 * Append PPA to secure mmu table.
> +	 */
> +	ppa_ram_addr = (gd->secure_ram & MEM_RESERVE_SECURE_ADDR_MASK) +
> +			gd->arch.tlb_size;
> +

Should we check "if (gd->secure_ram & MEM_RESERVE_SECURE_SECURED)" before using
the secure memory?

York
York Sun May 27, 2016, 7:58 p.m. UTC | #2
Resend to fix address error in CC box

On 05/23/2016 04:48 AM, Zhiqiang Hou wrote:
> From: Hou Zhiqiang <Zhiqiang.Hou@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 <Zhiqiag.Hou@nxp.com>
> ---
> 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.
> 
<snip>

> +int sec_firmware_validate(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_validate(ppa_addr);
> +}

You are returning 0 when the image is valid. This function name is confusing.
How about declare it as bool, and change the name to is_sec_firmware_valid()?

> +
> +#ifdef CONFIG_ARMV8_PSCI
> +unsigned int sec_firmware_support_psci_version(void)
> +{
> +	unsigned int psci_ver = 0;
> +
> +	if (!sec_firmware_validate())
> +		psci_ver = ppa_support_psci_version();
> +
> +	return psci_ver;
> +}
> +#endif
> +
> +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 PPA must be stored in secure memory.
> +	 * Append PPA to secure mmu table.
> +	 */
> +	ppa_ram_addr = (gd->secure_ram & MEM_RESERVE_SECURE_ADDR_MASK) +
> +			gd->arch.tlb_size;
> +

Should we check "if (gd->secure_ram & MEM_RESERVE_SECURE_SECURED)" before using
the secure memory?

York
Z.Q. Hou May 30, 2016, 2:56 a.m. UTC | #3
Hi York,

Thanks for your comments and suggestion!

> -----Original Message-----

> From: York Sun [mailto:york.sun@nxp.com]

> Sent: 2016年5月28日 2:06

> To: Zhiqiang Hou <zhiqiang.hou@nxp.com>; u-boot@lists.denx.de;

> albert.u.boot@aribaud.net; scottwood@freescale.com;

> Mingkai.hu@freescale.com; yorksun@freescale.com; leoli@freescale.com;

> prabhakar@freescale.com; bhupesh.sharma@freescale.com

> Cc: Hou Zhiqiang <Zhiqiag.Hou@nxp.com>

> Subject: Re: [PATCHv4 3/7] ARMv8/layerscape: Add FSL PPA support

> 

> On 05/23/2016 04:48 AM, Zhiqiang Hou wrote:

> > From: Hou Zhiqiang <Zhiqiang.Hou@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 <Zhiqiag.Hou@nxp.com>

> > ---

> > 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.

> >

> <snip>

> 

> > +int sec_firmware_validate(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_validate(ppa_addr); }

> 

> You are returning 0 when the image is valid. This function name is confusing.

> How about declare it as bool, and change the name to is_sec_firmware_valid()?


Yes, will correct the confusing name next version.

> > +

> > +#ifdef CONFIG_ARMV8_PSCI

> > +unsigned int sec_firmware_support_psci_version(void)

> > +{

> > +	unsigned int psci_ver = 0;

> > +

> > +	if (!sec_firmware_validate())

> > +		psci_ver = ppa_support_psci_version();

> > +

> > +	return psci_ver;

> > +}

> > +#endif

> > +

> > +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 PPA must be stored in secure memory.

> > +	 * Append PPA to secure mmu table.

> > +	 */

> > +	ppa_ram_addr = (gd->secure_ram &

> MEM_RESERVE_SECURE_ADDR_MASK) +

> > +			gd->arch.tlb_size;

> > +

> 

> Should we check "if (gd->secure_ram & MEM_RESERVE_SECURE_SECURED)"

> before using the secure memory?


Yes, will add the check next version.

Thanks,
Zhiqiang
Z.Q. Hou May 30, 2016, 2:58 a.m. UTC | #4
Hi York,

Thanks for your comments!

> -----Original Message-----

> From: York Sun [mailto:york.sun@nxp.com]

> Sent: 2016年5月28日 3:59

> To: Zhiqiang Hou <zhiqiang.hou@nxp.com>; u-boot@lists.denx.de;

> albert.u.boot@aribaud.net; scottwood@freescale.com;

> Mingkai.hu@freescale.com; yorksun@freescale.com; leoli@freescale.com;

> prabhakar@freescale.com; bhupesh.sharma@freescale.com

> Subject: Re: [PATCHv4 3/7] ARMv8/layerscape: Add FSL PPA support

> 

> Resend to fix address error in CC box


Yes, will fix.

Thanks,
Zhiqiang
diff mbox

Patch

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..3cd4d00
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c
@@ -0,0 +1,268 @@ 
+/*
+ * 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
+#include <asm/armv8/sec_firmware.h>
+
+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@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 int ppa_firmware_validate(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 -EINVAL;
+	}
+
+	if (!fit_check_format(fit_hdr)) {
+		printf("fsl-ppa: Bad firmware image (bad FIT header)\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+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
+
+	ret = ppa_firmware_validate(ppa_addr);
+	if (ret)
+		return ret;
+
+	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;
+}
+
+int sec_firmware_validate(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_validate(ppa_addr);
+}
+
+#ifdef CONFIG_ARMV8_PSCI
+unsigned int sec_firmware_support_psci_version(void)
+{
+	unsigned int psci_ver = 0;
+
+	if (!sec_firmware_validate())
+		psci_ver = ppa_support_psci_version();
+
+	return psci_ver;
+}
+#endif
+
+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 PPA must be stored in secure memory.
+	 * Append PPA to secure mmu table.
+	 */
+	ppa_ram_addr = (gd->secure_ram & MEM_RESERVE_SECURE_ADDR_MASK) +
+			gd->arch.tlb_size;
+
+	/* 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;
+	}
+
+	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;
+}
+
+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.
+	 * First, set vector for EL2.
+	 */
+	c_runtime_cpu_setup();
+
+	/* Enable caches and MMU for EL2. */
+	enable_caches();
+
+	return 0;
+}
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ppa_entry.S b/arch/arm/cpu/armv8/fsl-layerscape/ppa_entry.S
new file mode 100644
index 0000000..1f5577b
--- /dev/null
+++ b/arch/arm/cpu/armv8/fsl-layerscape/ppa_entry.S
@@ -0,0 +1,53 @@ 
+/*
+ * Copyright 2016 NXP Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <linux/linkage.h>
+#include <asm/system.h>
+#include <asm/macro.h>
+
+ENTRY(ppa_init)
+	/*
+	 * x0: PPA entry point
+	 * x1: Boot Location Pointer Low
+	 * x2: Boot Location Pointer High
+	 */
+
+	/* Save stack pointer for EL2 */
+	mov	x3, sp
+	msr	sp_el2, x3
+
+	/* Set boot loc pointer */
+        adr	x4, 1f
+        mov	x3, x4
+#if defined(CONFIG_FSL_LSCH2)
+        rev	w3, w3
+#endif
+        str	w3, [x1]
+        lsr	x3, x4, #32
+#if defined(CONFIG_FSL_LSCH2)
+        rev	w3, w3
+#endif
+        str	w3, [x2]
+
+/* Call PPA monitor */
+        br	x0
+
+1:
+        mov	x0, #0
+        ret
+ENDPROC(ppa_init)
+
+#ifdef CONFIG_ARMV8_PSCI
+ENTRY(ppa_support_psci_version)
+	mov	x0, 0x84000000
+	mov	x1, 0x0
+	mov	x2, 0x0
+	mov	x3, 0x0
+	smc	#0
+	ret
+ENDPROC(ppa_support_psci_version)
+#endif
diff --git a/arch/arm/include/asm/arch-fsl-layerscape/ppa.h b/arch/arm/include/asm/arch-fsl-layerscape/ppa.h
new file mode 100644
index 0000000..7b13d56
--- /dev/null
+++ b/arch/arm/include/asm/arch-fsl-layerscape/ppa.h
@@ -0,0 +1,16 @@ 
+/*
+ * Copyright 2016 NXP Semiconductor, Inc.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __FSL_PPA_H_
+#define __FSL_PPA_H_
+
+int ppa_init_pre(u64 *);
+int ppa_init_entry(void *);
+int ppa_init(void *, u32*, u32*);
+unsigned long ppa_get_dram_block_size(void);
+unsigned int ppa_support_psci_version(void);
+
+#endif
diff --git a/arch/arm/include/asm/armv8/sec_firmware.h b/arch/arm/include/asm/armv8/sec_firmware.h
index a39e141..d887922 100644
--- a/arch/arm/include/asm/armv8/sec_firmware.h
+++ b/arch/arm/include/asm/armv8/sec_firmware.h
@@ -7,6 +7,10 @@ 
 #ifndef __SEC_FIRMWARE_H_
 #define __SEC_FIRMWARE_H_
 
+#ifdef CONFIG_FSL_LS_PPA
+#include <asm/arch/ppa.h>
+#endif
+
 #ifdef CONFIG_ARMV8_PSCI
 unsigned int sec_firmware_support_psci_version(void);
 #endif