diff --git a/include/bl31/services/psci.h b/include/bl31/services/psci.h index c9b3f8d..f6fd487 100644 --- a/include/bl31/services/psci.h +++ b/include/bl31/services/psci.h @@ -165,6 +165,7 @@ #define PSCI_E_INTERN_FAIL -6 #define PSCI_E_NOT_PRESENT -7 #define PSCI_E_DISABLED -8 +#define PSCI_E_INVALID_ADDRESS -9 #define PSCI_INVALID_MPIDR ~(0ULL) diff --git a/services/std_svc/psci/psci_common.c b/services/std_svc/psci/psci_common.c index 7f1a5fd..f810ddf 100644 --- a/services/std_svc/psci/psci_common.c +++ b/services/std_svc/psci/psci_common.c @@ -589,7 +589,7 @@ * This function determines the full entrypoint information for the requested * PSCI entrypoint on power on/resume and returns it. ******************************************************************************/ -int psci_get_ns_ep_info(entry_point_info_t *ep, +static int psci_get_ns_ep_info(entry_point_info_t *ep, uint64_t entrypoint, uint64_t context_id) { uint32_t ep_attr, mode, sctlr, daif, ee; @@ -621,7 +621,7 @@ * aarch64 EL */ if (entrypoint & 0x1) - return PSCI_E_INVALID_PARAMS; + return PSCI_E_INVALID_ADDRESS; mode = ns_scr_el3 & SCR_HCE_BIT ? MODE_EL2 : MODE_EL1; @@ -643,6 +643,32 @@ } /******************************************************************************* + * This function validates the entrypoint with the platform layer if the + * appropriate pm_ops hook is exported by the platform and returns the + * 'entry_point_info'. + ******************************************************************************/ +int psci_validate_entry_point(entry_point_info_t *ep, + uint64_t entrypoint, uint64_t context_id) +{ + int rc; + + /* Validate the entrypoint using platform psci_ops */ + if (psci_plat_pm_ops->validate_ns_entrypoint) { + rc = psci_plat_pm_ops->validate_ns_entrypoint(entrypoint); + if (rc != PSCI_E_SUCCESS) + return PSCI_E_INVALID_ADDRESS; + } + + /* + * Verify and derive the re-entry information for + * the non-secure world from the non-secure state from + * where this call originated. + */ + rc = psci_get_ns_ep_info(ep, entrypoint, context_id); + return rc; +} + +/******************************************************************************* * Generic handler which is called when a cpu is physically powered on. It * traverses the node information and finds the highest power level powered * off and performs generic, architectural, platform setup and state management diff --git a/services/std_svc/psci/psci_main.c b/services/std_svc/psci/psci_main.c index f024291..6d3af20 100644 --- a/services/std_svc/psci/psci_main.c +++ b/services/std_svc/psci/psci_main.c @@ -55,21 +55,8 @@ if (rc != PSCI_E_SUCCESS) return PSCI_E_INVALID_PARAMS; - /* Validate the entrypoint using platform pm_ops */ - if (psci_plat_pm_ops->validate_ns_entrypoint) { - rc = psci_plat_pm_ops->validate_ns_entrypoint(entrypoint); - if (rc != PSCI_E_SUCCESS) { - assert(rc == PSCI_E_INVALID_PARAMS); - return PSCI_E_INVALID_PARAMS; - } - } - - /* - * Verify and derive the re-entry information for - * the non-secure world from the non-secure state from - * where this call originated. - */ - rc = psci_get_ns_ep_info(&ep, entrypoint, context_id); + /* Validate the entry point and get the entry_point_info */ + rc = psci_validate_entry_point(&ep, entrypoint, context_id); if (rc != PSCI_E_SUCCESS) return rc; @@ -141,20 +128,7 @@ * point and program entry information. */ if (is_power_down_state) { - if (psci_plat_pm_ops->validate_ns_entrypoint) { - rc = psci_plat_pm_ops->validate_ns_entrypoint(entrypoint); - if (rc != PSCI_E_SUCCESS) { - assert(rc == PSCI_E_INVALID_PARAMS); - return rc; - } - } - - /* - * Verify and derive the re-entry information for - * the non-secure world from the non-secure state from - * where this call originated. - */ - rc = psci_get_ns_ep_info(&ep, entrypoint, context_id); + rc = psci_validate_entry_point(&ep, entrypoint, context_id); if (rc != PSCI_E_SUCCESS) return rc; } @@ -180,25 +154,12 @@ psci_power_state_t state_info; entry_point_info_t ep; - /* Validate the entrypoint using platform pm_ops */ - if (psci_plat_pm_ops->validate_ns_entrypoint) { - rc = psci_plat_pm_ops->validate_ns_entrypoint(entrypoint); - if (rc != PSCI_E_SUCCESS) { - assert(rc == PSCI_E_INVALID_PARAMS); - return rc; - } - } - /* Check if the current CPU is the last ON CPU in the system */ if (!psci_is_last_on_cpu()) return PSCI_E_DENIED; - /* - * Verify and derive the re-entry information for - * the non-secure world from the non-secure state from - * where this call originated. - */ - rc = psci_get_ns_ep_info(&ep, entrypoint, context_id); + /* Validate the entry point and get the entry_point_info */ + rc = psci_validate_entry_point(&ep, entrypoint, context_id); if (rc != PSCI_E_SUCCESS) return rc; diff --git a/services/std_svc/psci/psci_private.h b/services/std_svc/psci/psci_private.h index e2e32c7..5345ee3 100644 --- a/services/std_svc/psci/psci_private.h +++ b/services/std_svc/psci/psci_private.h @@ -189,7 +189,7 @@ int psci_validate_mpidr(unsigned long mpidr); void psci_init_req_local_pwr_states(void); void psci_power_up_finish(void); -int psci_get_ns_ep_info(entry_point_info_t *ep, +int psci_validate_entry_point(entry_point_info_t *ep, uint64_t entrypoint, uint64_t context_id); void psci_get_parent_pwr_domain_nodes(unsigned int cpu_idx, int end_lvl,