@ -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 ;