Message ID | 1504254301-7970-2-git-send-email-sumit.garg@nxp.com |
---|---|
State | Accepted |
Commit | 9b3f40ad092ff2633eefa7e8a4a713f71c9cb8cb |
Delegated to: | York Sun |
Headers | show |
Series | [U-Boot,1/2] armv8: layerscape: Allocate 66 MB DDR for secure memory | expand |
On 09/01/2017 01:25 AM, Sumit Garg wrote: > Enable support for loadables in SEC firmware FIT image. Currently support > is added for single loadable image. > > Brief description of implementation: > - Add two more address pointers (loadable_h, loadable_l) as arguments to > sec_firmware_init() api. > - Create new api: sec_firmware_checks_copy_loadable() to check if loadables > node is present in SEC firmware FIT image. If present, verify loadable > image and copies it to secure DDR memory. > - Populate address pointers with secure DDR memory addresses where loadable > is copied. > > Example use-case could be trusted OS (tee.bin) as loadables node in SEC > firmware FIT image. > > Signed-off-by: Sumit Garg <sumit.garg@nxp.com> > --- > arch/arm/cpu/armv8/fsl-layerscape/ppa.c | 16 +++++- > arch/arm/cpu/armv8/sec_firmware.c | 92 +++++++++++++++++++++++++++++-- > arch/arm/include/asm/armv8/sec_firmware.h | 4 +- > 3 files changed, 104 insertions(+), 8 deletions(-) > > diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c > index 35c612d..87a0885 100644 > --- a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c > +++ b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c > @@ -35,6 +35,7 @@ int ppa_init(void) > unsigned int el = current_el(); > void *ppa_fit_addr; > u32 *boot_loc_ptr_l, *boot_loc_ptr_h; > + u32 *loadable_l, *loadable_h; > int ret; > > #ifdef CONFIG_CHAIN_OF_TRUST > @@ -252,9 +253,9 @@ int ppa_init(void) > PPA_KEY_HASH, > &ppa_img_addr); > if (ret != 0) > - printf("PPA validation failed\n"); > + printf("SEC firmware(s) validation failed\n"); > else > - printf("PPA validation Successful\n"); > + printf("SEC firmware(s) validation Successful\n"); > } > #if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \ > defined(CONFIG_SYS_LS_PPA_FW_IN_NAND) > @@ -266,15 +267,24 @@ int ppa_init(void) > struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); > boot_loc_ptr_l = &gur->bootlocptrl; > boot_loc_ptr_h = &gur->bootlocptrh; > + > + /* Assign addresses to loadable ptrs */ > + loadable_l = &gur->scratchrw[4]; > + loadable_h = &gur->scratchrw[5]; > #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]; > + > + /* Assign addresses to loadable ptrs */ > + loadable_l = &scfg->scratchrw[2]; > + loadable_h = &scfg->scratchrw[3]; > #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 = sec_firmware_init(ppa_fit_addr, boot_loc_ptr_l, boot_loc_ptr_h); > + ret = sec_firmware_init(ppa_fit_addr, boot_loc_ptr_l, boot_loc_ptr_h, > + loadable_l, loadable_h); > > #if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \ > defined(CONFIG_SYS_LS_PPA_FW_IN_NAND) > diff --git a/arch/arm/cpu/armv8/sec_firmware.c b/arch/arm/cpu/armv8/sec_firmware.c > index 0e74834..927eae4 100644 > --- a/arch/arm/cpu/armv8/sec_firmware.c > +++ b/arch/arm/cpu/armv8/sec_firmware.c > @@ -105,6 +105,74 @@ static int sec_firmware_parse_image(const void *sec_firmware_img, > return 0; > } > > +/* > + * SEC Firmware FIT image parser to check if any loadable is > + * present. If present, verify integrity of the loadable and > + * copy loadable to address provided in (loadable_h, loadable_l). > + * > + * Returns 0 on success and a negative errno on error task fail. > + */ > +static int sec_firmware_check_copy_loadable(const void *sec_firmware_img, > + u32 *loadable_l, u32 *loadable_h) > +{ > + phys_addr_t sec_firmware_loadable_addr = 0; > + int conf_node_off, ld_node_off; > + char *conf_node_name = NULL; > + const void *data; > + size_t size; > + ulong load; > + > + conf_node_name = SEC_FIRMEWARE_FIT_CNF_NAME; > + > + conf_node_off = fit_conf_get_node(sec_firmware_img, conf_node_name); > + if (conf_node_off < 0) { > + printf("SEC Firmware: %s: no such config\n", conf_node_name); > + return -ENOENT; > + } > + > + ld_node_off = fit_conf_get_prop_node(sec_firmware_img, conf_node_off, > + FIT_LOADABLE_PROP); > + if (ld_node_off >= 0) { > + printf("SEC Firmware: '%s' present in config\n", > + FIT_LOADABLE_PROP); > + > + /* Verify secure firmware image */ > + if (!(fit_image_verify(sec_firmware_img, ld_node_off))) { > + printf("SEC Loadable: Bad loadable image (bad CRC)\n"); > + return -EINVAL; > + } > + > + if (fit_image_get_data(sec_firmware_img, ld_node_off, > + &data, &size)) { > + printf("SEC Loadable: Can't get subimage data/size"); > + return -ENOENT; > + } > + > + /* Get load address, treated as load offset to secure memory */ > + if (fit_image_get_load(sec_firmware_img, ld_node_off, &load)) { > + printf("SEC Loadable: Can't get subimage load"); > + return -ENOENT; > + } > + > + /* Compute load address for loadable in secure memory */ > + sec_firmware_loadable_addr = (sec_firmware_addr - > + gd->arch.tlb_size) + load; > + > + /* Copy loadable to secure memory and flush dcache */ > + debug("%s copied to address 0x%p\n", > + FIT_LOADABLE_PROP, (void *)sec_firmware_loadable_addr); > + memcpy((void *)sec_firmware_loadable_addr, data, size); > + flush_dcache_range(sec_firmware_loadable_addr, > + sec_firmware_loadable_addr + size); > + } > + > + /* Populate address ptrs for loadable image with loadbale addr */ > + out_le32(loadable_l, (sec_firmware_loadable_addr & WORD_MASK)); > + out_le32(loadable_h, (sec_firmware_loadable_addr >> WORD_SHIFT)); > + > + return 0; > +} > + > static int sec_firmware_copy_image(const char *title, > u64 image_addr, u32 image_size, u64 sec_firmware) > { > @@ -117,9 +185,11 @@ static int sec_firmware_copy_image(const char *title, > > /* > * This function will parse the SEC Firmware image, and then load it > - * to secure memory. > + * to secure memory. Also load any loadable if present along with SEC > + * Firmware image. > */ > -static int sec_firmware_load_image(const void *sec_firmware_img) > +static int sec_firmware_load_image(const void *sec_firmware_img, > + u32 *loadable_l, u32 *loadable_h) > { > const void *raw_image_addr; > size_t raw_image_size = 0; > @@ -172,6 +242,15 @@ static int sec_firmware_load_image(const void *sec_firmware_img) > if (ret) > goto out; > > + /* > + * Check if any loadable are present along with firmware image, if > + * present load them. > + */ > + ret = sec_firmware_check_copy_loadable(sec_firmware_img, loadable_l, > + loadable_h); > + if (ret) > + goto out; > + > sec_firmware_addr |= SEC_FIRMWARE_LOADED; > debug("SEC Firmware: Entry point: 0x%llx\n", > sec_firmware_addr & SEC_FIRMWARE_ADDR_MASK); > @@ -289,17 +368,22 @@ int sec_firmware_get_random(uint8_t *rand, int bytes) > * @sec_firmware_img: the SEC Firmware image address > * @eret_hold_l: the address to hold exception return address low > * @eret_hold_h: the address to hold exception return address high > + * @loadable_l: the address to hold loadable address low > + * @loadable_h: the address to hold loadable address high > */ > int sec_firmware_init(const void *sec_firmware_img, > u32 *eret_hold_l, > - u32 *eret_hold_h) > + u32 *eret_hold_h, > + u32 *loadable_l, > + u32 *loadable_h) > { > int ret; > > if (!sec_firmware_is_valid(sec_firmware_img)) > return -EINVAL; > > - ret = sec_firmware_load_image(sec_firmware_img); > + ret = sec_firmware_load_image(sec_firmware_img, loadable_l, > + loadable_h); > if (ret) { > printf("SEC Firmware: Failed to load image\n"); > return ret; > diff --git a/arch/arm/include/asm/armv8/sec_firmware.h b/arch/arm/include/asm/armv8/sec_firmware.h > index 6d42a71..2ba1847 100644 > --- a/arch/arm/include/asm/armv8/sec_firmware.h > +++ b/arch/arm/include/asm/armv8/sec_firmware.h > @@ -9,8 +9,10 @@ > > #define PSCI_INVALID_VER 0xffffffff > #define SEC_JR3_OFFSET 0x40000 > +#define WORD_MASK 0xffffffff > +#define WORD_SHIFT 32 > > -int sec_firmware_init(const void *, u32 *, u32 *); > +int sec_firmware_init(const void *, u32 *, u32 *, u32 *, u32 *); > int _sec_firmware_entry(const void *, u32 *, u32 *); > bool sec_firmware_is_valid(const void *); > bool sec_firmware_support_hwrng(void); > Sumit, If I understand you correctly, you are parsing the secure firmware FIT image to find the loadable node and store the 64-bit load address in the scratch registers. How do you determine which scratch registers to use? York
> -----Original Message----- > From: York Sun > Sent: Tuesday, October 24, 2017 2:51 AM > To: Sumit Garg <sumit.garg@nxp.com>; u-boot@lists.denx.de > Cc: Ruchika Gupta <ruchika.gupta@nxp.com>; Prabhakar Kushwaha > <prabhakar.kushwaha@nxp.com>; Z.q. Hou <zhiqiang.hou@nxp.com>; Pankaj > Gupta <pankaj.gupta@nxp.com>; Arun Pathak <arun.pathak@nxp.com>; Sahil > Malhotra <sahil.malhotra@nxp.com> > Subject: Re: [PATCH 2/2] armv8: sec_firmware: Add support for loadables in FIT > > On 09/01/2017 01:25 AM, Sumit Garg wrote: > > Enable support for loadables in SEC firmware FIT image. Currently > > support is added for single loadable image. > > > > Brief description of implementation: > > - Add two more address pointers (loadable_h, loadable_l) as arguments to > > sec_firmware_init() api. > > - Create new api: sec_firmware_checks_copy_loadable() to check if > loadables > > node is present in SEC firmware FIT image. If present, verify loadable > > image and copies it to secure DDR memory. > > - Populate address pointers with secure DDR memory addresses where > loadable > > is copied. > > > > Example use-case could be trusted OS (tee.bin) as loadables node in > > SEC firmware FIT image. > > > > Signed-off-by: Sumit Garg <sumit.garg@nxp.com> > > --- > > arch/arm/cpu/armv8/fsl-layerscape/ppa.c | 16 +++++- > > arch/arm/cpu/armv8/sec_firmware.c | 92 > +++++++++++++++++++++++++++++-- > > arch/arm/include/asm/armv8/sec_firmware.h | 4 +- > > 3 files changed, 104 insertions(+), 8 deletions(-) > > > > diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c > > b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c > > index 35c612d..87a0885 100644 > > --- a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c > > +++ b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c > > @@ -35,6 +35,7 @@ int ppa_init(void) > > unsigned int el = current_el(); > > void *ppa_fit_addr; > > u32 *boot_loc_ptr_l, *boot_loc_ptr_h; > > + u32 *loadable_l, *loadable_h; > > int ret; > > > > #ifdef CONFIG_CHAIN_OF_TRUST > > @@ -252,9 +253,9 @@ int ppa_init(void) > > PPA_KEY_HASH, > > &ppa_img_addr); > > if (ret != 0) > > - printf("PPA validation failed\n"); > > + printf("SEC firmware(s) validation failed\n"); > > else > > - printf("PPA validation Successful\n"); > > + printf("SEC firmware(s) validation Successful\n"); > > } > > #if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \ > > defined(CONFIG_SYS_LS_PPA_FW_IN_NAND) > > @@ -266,15 +267,24 @@ int ppa_init(void) > > struct ccsr_gur __iomem *gur = (void > *)(CONFIG_SYS_FSL_GUTS_ADDR); > > boot_loc_ptr_l = &gur->bootlocptrl; > > boot_loc_ptr_h = &gur->bootlocptrh; > > + > > + /* Assign addresses to loadable ptrs */ > > + loadable_l = &gur->scratchrw[4]; > > + loadable_h = &gur->scratchrw[5]; > > #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]; > > + > > + /* Assign addresses to loadable ptrs */ > > + loadable_l = &scfg->scratchrw[2]; > > + loadable_h = &scfg->scratchrw[3]; > > #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 = sec_firmware_init(ppa_fit_addr, boot_loc_ptr_l, > boot_loc_ptr_h); > > + ret = sec_firmware_init(ppa_fit_addr, boot_loc_ptr_l, boot_loc_ptr_h, > > + loadable_l, loadable_h); > > > > #if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \ > > defined(CONFIG_SYS_LS_PPA_FW_IN_NAND) > > diff --git a/arch/arm/cpu/armv8/sec_firmware.c > > b/arch/arm/cpu/armv8/sec_firmware.c > > index 0e74834..927eae4 100644 > > --- a/arch/arm/cpu/armv8/sec_firmware.c > > +++ b/arch/arm/cpu/armv8/sec_firmware.c > > @@ -105,6 +105,74 @@ static int sec_firmware_parse_image(const void > *sec_firmware_img, > > return 0; > > } > > > > +/* > > + * SEC Firmware FIT image parser to check if any loadable is > > + * present. If present, verify integrity of the loadable and > > + * copy loadable to address provided in (loadable_h, loadable_l). > > + * > > + * Returns 0 on success and a negative errno on error task fail. > > + */ > > +static int sec_firmware_check_copy_loadable(const void > *sec_firmware_img, > > + u32 *loadable_l, u32 *loadable_h) { > > + phys_addr_t sec_firmware_loadable_addr = 0; > > + int conf_node_off, ld_node_off; > > + char *conf_node_name = NULL; > > + const void *data; > > + size_t size; > > + ulong load; > > + > > + conf_node_name = SEC_FIRMEWARE_FIT_CNF_NAME; > > + > > + conf_node_off = fit_conf_get_node(sec_firmware_img, > conf_node_name); > > + if (conf_node_off < 0) { > > + printf("SEC Firmware: %s: no such config\n", > conf_node_name); > > + return -ENOENT; > > + } > > + > > + ld_node_off = fit_conf_get_prop_node(sec_firmware_img, > conf_node_off, > > + FIT_LOADABLE_PROP); > > + if (ld_node_off >= 0) { > > + printf("SEC Firmware: '%s' present in config\n", > > + FIT_LOADABLE_PROP); > > + > > + /* Verify secure firmware image */ > > + if (!(fit_image_verify(sec_firmware_img, ld_node_off))) { > > + printf("SEC Loadable: Bad loadable image (bad > CRC)\n"); > > + return -EINVAL; > > + } > > + > > + if (fit_image_get_data(sec_firmware_img, ld_node_off, > > + &data, &size)) { > > + printf("SEC Loadable: Can't get subimage data/size"); > > + return -ENOENT; > > + } > > + > > + /* Get load address, treated as load offset to secure memory > */ > > + if (fit_image_get_load(sec_firmware_img, ld_node_off, > &load)) { > > + printf("SEC Loadable: Can't get subimage load"); > > + return -ENOENT; > > + } > > + > > + /* Compute load address for loadable in secure memory */ > > + sec_firmware_loadable_addr = (sec_firmware_addr - > > + gd->arch.tlb_size) + load; > > + > > + /* Copy loadable to secure memory and flush dcache */ > > + debug("%s copied to address 0x%p\n", > > + FIT_LOADABLE_PROP, (void > *)sec_firmware_loadable_addr); > > + memcpy((void *)sec_firmware_loadable_addr, data, size); > > + flush_dcache_range(sec_firmware_loadable_addr, > > + sec_firmware_loadable_addr + size); > > + } > > + > > + /* Populate address ptrs for loadable image with loadbale addr */ > > + out_le32(loadable_l, (sec_firmware_loadable_addr & WORD_MASK)); > > + out_le32(loadable_h, (sec_firmware_loadable_addr >> > WORD_SHIFT)); > > + > > + return 0; > > +} > > + > > static int sec_firmware_copy_image(const char *title, > > u64 image_addr, u32 image_size, u64 sec_firmware) { > @@ -117,9 > > +185,11 @@ static int sec_firmware_copy_image(const char *title, > > > > /* > > * This function will parse the SEC Firmware image, and then load it > > - * to secure memory. > > + * to secure memory. Also load any loadable if present along with SEC > > + * Firmware image. > > */ > > -static int sec_firmware_load_image(const void *sec_firmware_img) > > +static int sec_firmware_load_image(const void *sec_firmware_img, > > + u32 *loadable_l, u32 *loadable_h) > > { > > const void *raw_image_addr; > > size_t raw_image_size = 0; > > @@ -172,6 +242,15 @@ static int sec_firmware_load_image(const void > *sec_firmware_img) > > if (ret) > > goto out; > > > > + /* > > + * Check if any loadable are present along with firmware image, if > > + * present load them. > > + */ > > + ret = sec_firmware_check_copy_loadable(sec_firmware_img, > loadable_l, > > + loadable_h); > > + if (ret) > > + goto out; > > + > > sec_firmware_addr |= SEC_FIRMWARE_LOADED; > > debug("SEC Firmware: Entry point: 0x%llx\n", > > sec_firmware_addr & SEC_FIRMWARE_ADDR_MASK); @@ -289,17 > > +368,22 @@ int sec_firmware_get_random(uint8_t *rand, int bytes) > > * @sec_firmware_img: the SEC Firmware image address > > * @eret_hold_l: the address to hold exception return address low > > * @eret_hold_h: the address to hold exception return address high > > + * @loadable_l: the address to hold loadable address low > > + * @loadable_h: the address to hold loadable address high > > */ > > int sec_firmware_init(const void *sec_firmware_img, > > u32 *eret_hold_l, > > - u32 *eret_hold_h) > > + u32 *eret_hold_h, > > + u32 *loadable_l, > > + u32 *loadable_h) > > { > > int ret; > > > > if (!sec_firmware_is_valid(sec_firmware_img)) > > return -EINVAL; > > > > - ret = sec_firmware_load_image(sec_firmware_img); > > + ret = sec_firmware_load_image(sec_firmware_img, loadable_l, > > + loadable_h); > > if (ret) { > > printf("SEC Firmware: Failed to load image\n"); > > return ret; > > diff --git a/arch/arm/include/asm/armv8/sec_firmware.h > > b/arch/arm/include/asm/armv8/sec_firmware.h > > index 6d42a71..2ba1847 100644 > > --- a/arch/arm/include/asm/armv8/sec_firmware.h > > +++ b/arch/arm/include/asm/armv8/sec_firmware.h > > @@ -9,8 +9,10 @@ > > > > #define PSCI_INVALID_VER 0xffffffff > > #define SEC_JR3_OFFSET 0x40000 > > +#define WORD_MASK 0xffffffff > > +#define WORD_SHIFT 32 > > > > -int sec_firmware_init(const void *, u32 *, u32 *); > > +int sec_firmware_init(const void *, u32 *, u32 *, u32 *, u32 *); > > int _sec_firmware_entry(const void *, u32 *, u32 *); bool > > sec_firmware_is_valid(const void *); bool > > sec_firmware_support_hwrng(void); > > > > Sumit, > > If I understand you correctly, you are parsing the secure firmware FIT image to > find the loadable node and store the 64-bit load address in the scratch > registers. How do you determine which scratch registers to use? > > York Yes your understanding is correct. The scratch registers which I used are as follows: For Chassis gen 3 platforms: /* Assign addresses to loadable ptrs */ loadable_l = &gur->scratchrw[4]; loadable_h = &gur->scratchrw[5]; For Chassis gen 2 platforms: /* Assign addresses to loadable ptrs */ loadable_l = &scfg->scratchrw[2]; loadable_h = &scfg->scratchrw[3]; I choose above scratch registers to avoid any conflict with usage of scratch registers in Boot-ROM, u-boot and PPA. Sumit
On 10/23/2017 09:21 PM, Sumit Garg wrote: <snip> >> >> Sumit, >> >> If I understand you correctly, you are parsing the secure firmware FIT image to >> find the loadable node and store the 64-bit load address in the scratch >> registers. How do you determine which scratch registers to use? >> >> York > > Yes your understanding is correct. The scratch registers which I used are as follows: > > For Chassis gen 3 platforms: > /* Assign addresses to loadable ptrs */ > loadable_l = &gur->scratchrw[4]; > loadable_h = &gur->scratchrw[5]; > > For Chassis gen 2 platforms: > /* Assign addresses to loadable ptrs */ > loadable_l = &scfg->scratchrw[2]; > loadable_h = &scfg->scratchrw[3]; > > I choose above scratch registers to avoid any conflict with usage of scratch registers > in Boot-ROM, u-boot and PPA. I see you write to these scratch registers but never read from them. What's the purpose to store the address in them? York
> -----Original Message----- > From: York Sun > Sent: Tuesday, October 24, 2017 8:00 PM > To: Sumit Garg <sumit.garg@nxp.com>; u-boot@lists.denx.de > Cc: Ruchika Gupta <ruchika.gupta@nxp.com>; Prabhakar Kushwaha > <prabhakar.kushwaha@nxp.com>; Z.q. Hou <zhiqiang.hou@nxp.com>; Pankaj > Gupta <pankaj.gupta@nxp.com>; Arun Pathak <arun.pathak@nxp.com>; Sahil > Malhotra <sahil.malhotra@nxp.com> > Subject: Re: [PATCH 2/2] armv8: sec_firmware: Add support for loadables in FIT > > On 10/23/2017 09:21 PM, Sumit Garg wrote: > <snip> > >> > >> Sumit, > >> > >> If I understand you correctly, you are parsing the secure firmware > >> FIT image to find the loadable node and store the 64-bit load address > >> in the scratch registers. How do you determine which scratch registers to > use? > >> > >> York > > > > Yes your understanding is correct. The scratch registers which I used are as > follows: > > > > For Chassis gen 3 platforms: > > /* Assign addresses to loadable ptrs */ > > loadable_l = &gur->scratchrw[4]; > > loadable_h = &gur->scratchrw[5]; > > > > For Chassis gen 2 platforms: > > /* Assign addresses to loadable ptrs */ > > loadable_l = &scfg->scratchrw[2]; > > loadable_h = &scfg->scratchrw[3]; > > > > I choose above scratch registers to avoid any conflict with usage of > > scratch registers in Boot-ROM, u-boot and PPA. > > I see you write to these scratch registers but never read from them. > What's the purpose to store the address in them? > > York These scratch registers are used to communicate loadable address to PPA similar to how return address is communicated in boot-location pointer registers to PPA. PPA uses this loadable address (Trusted OS address) to initialize Trusted OS. Sumit
On 10/24/2017 09:00 PM, Sumit Garg wrote: >> -----Original Message----- >> From: York Sun >> Sent: Tuesday, October 24, 2017 8:00 PM >> To: Sumit Garg <sumit.garg@nxp.com>; u-boot@lists.denx.de >> Cc: Ruchika Gupta <ruchika.gupta@nxp.com>; Prabhakar Kushwaha >> <prabhakar.kushwaha@nxp.com>; Z.q. Hou <zhiqiang.hou@nxp.com>; Pankaj >> Gupta <pankaj.gupta@nxp.com>; Arun Pathak <arun.pathak@nxp.com>; Sahil >> Malhotra <sahil.malhotra@nxp.com> >> Subject: Re: [PATCH 2/2] armv8: sec_firmware: Add support for loadables in FIT >> >> On 10/23/2017 09:21 PM, Sumit Garg wrote: >> <snip> >>>> >>>> Sumit, >>>> >>>> If I understand you correctly, you are parsing the secure firmware >>>> FIT image to find the loadable node and store the 64-bit load address >>>> in the scratch registers. How do you determine which scratch registers to >> use? >>>> >>>> York >>> >>> Yes your understanding is correct. The scratch registers which I used are as >> follows: >>> >>> For Chassis gen 3 platforms: >>> /* Assign addresses to loadable ptrs */ >>> loadable_l = &gur->scratchrw[4]; >>> loadable_h = &gur->scratchrw[5]; >>> >>> For Chassis gen 2 platforms: >>> /* Assign addresses to loadable ptrs */ >>> loadable_l = &scfg->scratchrw[2]; >>> loadable_h = &scfg->scratchrw[3]; >>> >>> I choose above scratch registers to avoid any conflict with usage of >>> scratch registers in Boot-ROM, u-boot and PPA. >> >> I see you write to these scratch registers but never read from them. >> What's the purpose to store the address in them? >> >> York > > These scratch registers are used to communicate loadable address to PPA similar > to how return address is communicated in boot-location pointer registers to PPA. > > PPA uses this loadable address (Trusted OS address) to initialize Trusted OS. OK. So these registers are actually consumed by PPA image. That makes more sense. York
On 09/01/2017 01:25 AM, Sumit Garg wrote: > Enable support for loadables in SEC firmware FIT image. Currently support > is added for single loadable image. > > Brief description of implementation: > - Add two more address pointers (loadable_h, loadable_l) as arguments to > sec_firmware_init() api. > - Create new api: sec_firmware_checks_copy_loadable() to check if loadables > node is present in SEC firmware FIT image. If present, verify loadable > image and copies it to secure DDR memory. > - Populate address pointers with secure DDR memory addresses where loadable > is copied. > > Example use-case could be trusted OS (tee.bin) as loadables node in SEC > firmware FIT image. > > Signed-off-by: Sumit Garg <sumit.garg@nxp.com> > --- Reformatted commit message get rid of the bulletin style. Applied to fsl-qoriq master. Thanks. York
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c index 35c612d..87a0885 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/ppa.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/ppa.c @@ -35,6 +35,7 @@ int ppa_init(void) unsigned int el = current_el(); void *ppa_fit_addr; u32 *boot_loc_ptr_l, *boot_loc_ptr_h; + u32 *loadable_l, *loadable_h; int ret; #ifdef CONFIG_CHAIN_OF_TRUST @@ -252,9 +253,9 @@ int ppa_init(void) PPA_KEY_HASH, &ppa_img_addr); if (ret != 0) - printf("PPA validation failed\n"); + printf("SEC firmware(s) validation failed\n"); else - printf("PPA validation Successful\n"); + printf("SEC firmware(s) validation Successful\n"); } #if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \ defined(CONFIG_SYS_LS_PPA_FW_IN_NAND) @@ -266,15 +267,24 @@ int ppa_init(void) struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); boot_loc_ptr_l = &gur->bootlocptrl; boot_loc_ptr_h = &gur->bootlocptrh; + + /* Assign addresses to loadable ptrs */ + loadable_l = &gur->scratchrw[4]; + loadable_h = &gur->scratchrw[5]; #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]; + + /* Assign addresses to loadable ptrs */ + loadable_l = &scfg->scratchrw[2]; + loadable_h = &scfg->scratchrw[3]; #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 = sec_firmware_init(ppa_fit_addr, boot_loc_ptr_l, boot_loc_ptr_h); + ret = sec_firmware_init(ppa_fit_addr, boot_loc_ptr_l, boot_loc_ptr_h, + loadable_l, loadable_h); #if defined(CONFIG_SYS_LS_PPA_FW_IN_MMC) || \ defined(CONFIG_SYS_LS_PPA_FW_IN_NAND) diff --git a/arch/arm/cpu/armv8/sec_firmware.c b/arch/arm/cpu/armv8/sec_firmware.c index 0e74834..927eae4 100644 --- a/arch/arm/cpu/armv8/sec_firmware.c +++ b/arch/arm/cpu/armv8/sec_firmware.c @@ -105,6 +105,74 @@ static int sec_firmware_parse_image(const void *sec_firmware_img, return 0; } +/* + * SEC Firmware FIT image parser to check if any loadable is + * present. If present, verify integrity of the loadable and + * copy loadable to address provided in (loadable_h, loadable_l). + * + * Returns 0 on success and a negative errno on error task fail. + */ +static int sec_firmware_check_copy_loadable(const void *sec_firmware_img, + u32 *loadable_l, u32 *loadable_h) +{ + phys_addr_t sec_firmware_loadable_addr = 0; + int conf_node_off, ld_node_off; + char *conf_node_name = NULL; + const void *data; + size_t size; + ulong load; + + conf_node_name = SEC_FIRMEWARE_FIT_CNF_NAME; + + conf_node_off = fit_conf_get_node(sec_firmware_img, conf_node_name); + if (conf_node_off < 0) { + printf("SEC Firmware: %s: no such config\n", conf_node_name); + return -ENOENT; + } + + ld_node_off = fit_conf_get_prop_node(sec_firmware_img, conf_node_off, + FIT_LOADABLE_PROP); + if (ld_node_off >= 0) { + printf("SEC Firmware: '%s' present in config\n", + FIT_LOADABLE_PROP); + + /* Verify secure firmware image */ + if (!(fit_image_verify(sec_firmware_img, ld_node_off))) { + printf("SEC Loadable: Bad loadable image (bad CRC)\n"); + return -EINVAL; + } + + if (fit_image_get_data(sec_firmware_img, ld_node_off, + &data, &size)) { + printf("SEC Loadable: Can't get subimage data/size"); + return -ENOENT; + } + + /* Get load address, treated as load offset to secure memory */ + if (fit_image_get_load(sec_firmware_img, ld_node_off, &load)) { + printf("SEC Loadable: Can't get subimage load"); + return -ENOENT; + } + + /* Compute load address for loadable in secure memory */ + sec_firmware_loadable_addr = (sec_firmware_addr - + gd->arch.tlb_size) + load; + + /* Copy loadable to secure memory and flush dcache */ + debug("%s copied to address 0x%p\n", + FIT_LOADABLE_PROP, (void *)sec_firmware_loadable_addr); + memcpy((void *)sec_firmware_loadable_addr, data, size); + flush_dcache_range(sec_firmware_loadable_addr, + sec_firmware_loadable_addr + size); + } + + /* Populate address ptrs for loadable image with loadbale addr */ + out_le32(loadable_l, (sec_firmware_loadable_addr & WORD_MASK)); + out_le32(loadable_h, (sec_firmware_loadable_addr >> WORD_SHIFT)); + + return 0; +} + static int sec_firmware_copy_image(const char *title, u64 image_addr, u32 image_size, u64 sec_firmware) { @@ -117,9 +185,11 @@ static int sec_firmware_copy_image(const char *title, /* * This function will parse the SEC Firmware image, and then load it - * to secure memory. + * to secure memory. Also load any loadable if present along with SEC + * Firmware image. */ -static int sec_firmware_load_image(const void *sec_firmware_img) +static int sec_firmware_load_image(const void *sec_firmware_img, + u32 *loadable_l, u32 *loadable_h) { const void *raw_image_addr; size_t raw_image_size = 0; @@ -172,6 +242,15 @@ static int sec_firmware_load_image(const void *sec_firmware_img) if (ret) goto out; + /* + * Check if any loadable are present along with firmware image, if + * present load them. + */ + ret = sec_firmware_check_copy_loadable(sec_firmware_img, loadable_l, + loadable_h); + if (ret) + goto out; + sec_firmware_addr |= SEC_FIRMWARE_LOADED; debug("SEC Firmware: Entry point: 0x%llx\n", sec_firmware_addr & SEC_FIRMWARE_ADDR_MASK); @@ -289,17 +368,22 @@ int sec_firmware_get_random(uint8_t *rand, int bytes) * @sec_firmware_img: the SEC Firmware image address * @eret_hold_l: the address to hold exception return address low * @eret_hold_h: the address to hold exception return address high + * @loadable_l: the address to hold loadable address low + * @loadable_h: the address to hold loadable address high */ int sec_firmware_init(const void *sec_firmware_img, u32 *eret_hold_l, - u32 *eret_hold_h) + u32 *eret_hold_h, + u32 *loadable_l, + u32 *loadable_h) { int ret; if (!sec_firmware_is_valid(sec_firmware_img)) return -EINVAL; - ret = sec_firmware_load_image(sec_firmware_img); + ret = sec_firmware_load_image(sec_firmware_img, loadable_l, + loadable_h); if (ret) { printf("SEC Firmware: Failed to load image\n"); return ret; diff --git a/arch/arm/include/asm/armv8/sec_firmware.h b/arch/arm/include/asm/armv8/sec_firmware.h index 6d42a71..2ba1847 100644 --- a/arch/arm/include/asm/armv8/sec_firmware.h +++ b/arch/arm/include/asm/armv8/sec_firmware.h @@ -9,8 +9,10 @@ #define PSCI_INVALID_VER 0xffffffff #define SEC_JR3_OFFSET 0x40000 +#define WORD_MASK 0xffffffff +#define WORD_SHIFT 32 -int sec_firmware_init(const void *, u32 *, u32 *); +int sec_firmware_init(const void *, u32 *, u32 *, u32 *, u32 *); int _sec_firmware_entry(const void *, u32 *, u32 *); bool sec_firmware_is_valid(const void *); bool sec_firmware_support_hwrng(void);
Enable support for loadables in SEC firmware FIT image. Currently support is added for single loadable image. Brief description of implementation: - Add two more address pointers (loadable_h, loadable_l) as arguments to sec_firmware_init() api. - Create new api: sec_firmware_checks_copy_loadable() to check if loadables node is present in SEC firmware FIT image. If present, verify loadable image and copies it to secure DDR memory. - Populate address pointers with secure DDR memory addresses where loadable is copied. Example use-case could be trusted OS (tee.bin) as loadables node in SEC firmware FIT image. Signed-off-by: Sumit Garg <sumit.garg@nxp.com> --- arch/arm/cpu/armv8/fsl-layerscape/ppa.c | 16 +++++- arch/arm/cpu/armv8/sec_firmware.c | 92 +++++++++++++++++++++++++++++-- arch/arm/include/asm/armv8/sec_firmware.h | 4 +- 3 files changed, 104 insertions(+), 8 deletions(-)