diff --git a/plat/imx/common/imx_sip_handler.c b/plat/imx/common/imx_sip_handler.c index ec8631a4f..f830b6409 100644 --- a/plat/imx/common/imx_sip_handler.c +++ b/plat/imx/common/imx_sip_handler.c @@ -17,6 +17,15 @@ #include #include +#if defined(PLAT_imx8mn) || defined(PLAT_imx8mp) +/* + * Defined in + * table 11. ROM event log buffer address location + * AN12853 "i.MX ROMs Log Events" + */ +#define ROM_LOG_BUFFER_ADDR 0x9E0 +#endif + #if defined(PLAT_imx8qm) || defined(PLAT_imx8qx) #ifdef PLAT_imx8qm @@ -177,6 +186,76 @@ int imx_src_handler(uint32_t smc_fid, } #endif /* defined(PLAT_imx8mm) || defined(PLAT_imx8mq) */ +#if defined(PLAT_imx8mn) || defined(PLAT_imx8mp) +static bool is_secondary_boot(void) +{ + uint32_t *rom_log_addr = (uint32_t *)ROM_LOG_BUFFER_ADDR; + bool is_secondary = false; + uint32_t *rom_log; + uint8_t event_id; + + /* If the ROM event log pointer is not valid. */ + if (*rom_log_addr < 0x900000 || *rom_log_addr >= 0xB00000 || + *rom_log_addr & 0x3) { + return false; + } + + /* Parse the ROM event ID version 2 log */ + rom_log = (uint32_t *)(uintptr_t)(*rom_log_addr); + for (size_t i = 0; i < 128; i++) { + event_id = rom_log[i] >> 24; + switch (event_id) { + case 0x00: /* End of list */ + return is_secondary; + /* Log entries with 1 parameter, skip 1 */ + case 0x80: /* Perform the device initialization */ + case 0x81: /* The boot device initialization completes */ + case 0x82: /* Execute boot device driver pre-config */ + case 0x8F: /* The boot device initialization fails */ + case 0x90: /* Start to read data from boot device */ + case 0x91: /* Reading data from boot device completes */ + case 0x9F: /* Reading data from boot device fails */ + i += 1; + continue; + /* Log entries with 2 parameters, skip 2 */ + case 0xA0: /* Image authentication result */ + case 0xC0: /* Jump to the boot image soon */ + i += 2; + continue; + /* Booted the primary boot image */ + case 0x50: + is_secondary = false; + continue; + /* Booted the secondary boot image */ + case 0x51: + is_secondary = true; + continue; + } + } + + return is_secondary; +} + +int imx_src_handler(uint32_t smc_fid, + u_register_t x1, + u_register_t x2, + u_register_t x3, + void *handle) +{ + switch (x1) { + case IMX_SIP_SRC_SET_SECONDARY_BOOT: + /* we do support that on these SoCs */ + break; + case IMX_SIP_SRC_IS_SECONDARY_BOOT: + return is_secondary_boot(); + default: + return SMC_UNK; + }; + + return 0; +} +#endif /* defined(PLAT_imx8mn) || defined(PLAT_imx8mp) */ + static uint64_t imx_get_commit_hash(u_register_t x2, u_register_t x3, u_register_t x4) diff --git a/plat/imx/common/imx_sip_svc.c b/plat/imx/common/imx_sip_svc.c index 6d6633cfc..69d4f053a 100644 --- a/plat/imx/common/imx_sip_svc.c +++ b/plat/imx/common/imx_sip_svc.c @@ -60,7 +60,8 @@ static uintptr_t imx_sip_handler(unsigned int smc_fid, case IMX_SIP_MISC_SET_TEMP: SMC_RET1(handle, imx_misc_set_temp_handler(smc_fid, x1, x2, x3, x4)); #endif -#if defined(PLAT_imx8mm) || defined(PLAT_imx8mq) +#if defined(PLAT_imx8mm) || defined(PLAT_imx8mq) || defined(PLAT_imx8mn) || \ + defined(PLAT_imx8mp) case IMX_SIP_SRC: SMC_RET1(handle, imx_src_handler(smc_fid, x1, x2, x3, handle)); break; diff --git a/plat/imx/common/include/imx_sip_svc.h b/plat/imx/common/include/imx_sip_svc.h index 0e91c7174..35a9f47ec 100644 --- a/plat/imx/common/include/imx_sip_svc.h +++ b/plat/imx/common/include/imx_sip_svc.h @@ -68,7 +68,9 @@ int imx_gpc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, u_register_t x3); #endif -#if defined(PLAT_imx8mm) || defined(PLAT_imx8mq) +#if defined(PLAT_imx8mm) || defined(PLAT_imx8mq) || defined(PLAT_imx8mn) || \ + defined(PLAT_imx8mp) + int imx_src_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, u_register_t x3, void *handle); #endif