diff options
Diffstat (limited to 'board')
-rw-r--r-- | board/st/u8500/itp.c | 159 | ||||
-rw-r--r-- | board/st/u8500/itp.h | 4 | ||||
-rw-r--r-- | board/st/u8500/mmc_host.c | 2 |
3 files changed, 151 insertions, 14 deletions
diff --git a/board/st/u8500/itp.c b/board/st/u8500/itp.c index e7ef4fa7e..033d3d03c 100644 --- a/board/st/u8500/itp.c +++ b/board/st/u8500/itp.c @@ -13,7 +13,116 @@ #include "itp.h" #include "cspsa_fp.h" +#define SEC_ROM_FORCE_CLEAN_MASK 0x0020 +#define SEC_ROM_RET_OK 0x01 +#define ISSWAPI_SECURE_LOAD 0x10000002 +#define ISSWAPI_FLUSH_BOOT_CODE 0x11000003 +#define IPL_ITEM_ID 0x02 +typedef u32 (*boot_rom_bridge_func_t)(const u32 , const u32, const va_list); + +static boot_rom_bridge_func_t hw_sec_rom_pub_bridge; + +struct sec_rom_cut_desc { + u32 cutid_addr; + u32 cutid; + u32 bridge_func; +}; + +static const struct sec_rom_cut_desc cuttable[] = { + { 0x9001FFF4, 0x008500A0, 0x90018300 }, + { 0x9001FFF4, 0x008500A1, 0x90018300 }, + { 0x9001FFF4, 0x005500A0, 0x90018300 }, + { 0x9001DBF4, 0x008500B0, 0x90017300 }, +}; + +static u32 itp_call_secure_service(const u32 serviceid, + const u32 secureconfig, + ...) +{ + va_list ap; + u32 returnvalue; + + va_start(ap, secureconfig); + + returnvalue = hw_sec_rom_pub_bridge(serviceid, + secureconfig, + ap); + + va_end(ap); + return returnvalue; +} + +static int itp_init_bridge(void) +{ + u8 cutnb = 0; + + hw_sec_rom_pub_bridge = NULL; + + while ((cutnb < ARRAY_SIZE(cuttable)) && + (cuttable[cutnb].cutid != *(u32 *)(cuttable[cutnb].cutid_addr))) + cutnb++; + + if (cutnb < ARRAY_SIZE(cuttable)) { + hw_sec_rom_pub_bridge = + (boot_rom_bridge_func_t)cuttable[cutnb].bridge_func; + return 0; + } + + printf("itp_init_bridge: cutid not found\n"); + return 1; +} + +static int itp_flush_issw(void) +{ + u32 ret; + + ret = itp_call_secure_service(ISSWAPI_FLUSH_BOOT_CODE, + SEC_ROM_FORCE_CLEAN_MASK, + 0, + 0); + + if (ret != SEC_ROM_RET_OK) { + printf("itp_flush_issw: ISSWAPI_FLUSH_BOOT_CODE failed: %d\n", + ret); + return 1; + } + + return 0; +} + +static int itp_load_ipl(block_dev_desc_t *block_dev) +{ + u32 offset; + u32 size; + u32 loadaddr; + u32 returnvalue; + int ab8500_cutid; + + debug("loadipl\n"); + + /* Check if IPL partition is present */ + if (get_entry_info_toc(block_dev, ITP_TOC_IPL_NAME, &offset, + &size, &loadaddr)) { + printf("itp_load_ipl: get_entry_info_toc failed\n"); + return 1; + } + + /* Get CutID */ + ab8500_cutid = ab8500_read(AB8500_MISC, AB8500_REV_REG); + + returnvalue = itp_call_secure_service((u32)ISSWAPI_SECURE_LOAD, + SEC_ROM_FORCE_CLEAN_MASK, + IPL_ITEM_ID, + ab8500_cutid); + if (returnvalue != SEC_ROM_RET_OK) { + printf("itp_load_ipl: ISSWAPI_SECURE_LOAD failed: %d\n", + returnvalue); + return 1; + } + + return 0; +} static int itp_load_toc_entry(block_dev_desc_t *block_dev, const char *partname, u32 *loadaddress) @@ -47,36 +156,62 @@ static int itp_load_toc_entry(block_dev_desc_t *block_dev, } /* - * itp_load_itp - Loads itp depending on config. + * itp_load_itp_and_modem - Loads itp and modem depending on config. * If itp is loaded ok it will be executed and u-boot execution will stop */ -int itp_load_itp(block_dev_desc_t *block_dev) +int itp_load_itp_and_modem(block_dev_desc_t *block_dev) { + int retval = 0; u32 cspsa_key; void (*loadaddress)(void) = NULL; - debug("\nitp_load_itp\n"); + debug("\nitp_load_itp_and_modem\n"); + + if (itp_init_bridge()) { + retval = 1; + goto exit; + } if (cspsa_fp_read(block_dev, ITP_CSPSA_KEY, &cspsa_key)) { - printf("itp_load_itp: cspsa_fp_read failed\n"); - return 1; + printf("itp_load_itp_and_modem: cspsa_fp_read failed\n"); + retval = 1; + goto exit; + } + + if (cspsa_key & ITP_LOAD_MODEM) { + if (itp_load_toc_entry(block_dev, + ITP_TOC_MODEM_NAME, + (u32 *)loadaddress)) { + retval = 1; + goto exit; + } + + if (itp_load_ipl(block_dev)) { + retval = 1; + goto exit; + } } if (cspsa_key & ITP_LOAD_ITP) { if (itp_load_toc_entry(block_dev, ITP_TOC_ITP_NAME, (u32 *)loadaddress)) { - printf("itp_load_itp: itp_load_partition failed\n"); - return 1; + retval = 1; + goto exit; } - loadaddress(); /* U-boot execution will end here*/ - - printf("itp_load_itp: itp execution failed\n"); - return 1; } - return 0; +exit: + /* Always Flush */ + if (hw_sec_rom_pub_bridge != NULL) + itp_flush_issw(); + + if ((cspsa_key & ITP_LOAD_ITP) && !retval) + loadaddress(); /* U-boot execution will end here*/ + + /* Return on error */ + return retval; } diff --git a/board/st/u8500/itp.h b/board/st/u8500/itp.h index 74dc6b65b..13d039eed 100644 --- a/board/st/u8500/itp.h +++ b/board/st/u8500/itp.h @@ -16,9 +16,11 @@ #define ITP_LOAD_ITP 0x04 #define ITP_TOC_ITP_NAME "ITP" +#define ITP_TOC_MODEM_NAME "MODEM" +#define ITP_TOC_IPL_NAME "IPL" #define ITP_CSPSA_KEY 0 -int itp_load_itp(block_dev_desc_t *block_dev); +int itp_load_itp_and_modem(block_dev_desc_t *block_dev); #endif /* __ITP_H__ */ diff --git a/board/st/u8500/mmc_host.c b/board/st/u8500/mmc_host.c index a77793620..79be58acd 100644 --- a/board/st/u8500/mmc_host.c +++ b/board/st/u8500/mmc_host.c @@ -625,7 +625,7 @@ int board_mmc_init(bd_t *bis) */ #ifdef CONFIG_ITP_LOAD - itp_load_itp(&dev->block_dev); + itp_load_itp_and_modem(&dev->block_dev); #endif dev = alloc_mmc_struct(); |