/******************************************************************************* * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type * (aarch32/aarch64) if not already known and initialises the context for entry * into the SP for its initialisation. ******************************************************************************/ int32_t tspd_setup(void) { entry_point_info_t *tsp_ep_info; uint32_t linear_id; linear_id = plat_my_core_pos(); /* * Get information about the Secure Payload (BL32) image. Its * absence is a critical failure. TODO: Add support to * conditionally include the SPD service */ tsp_ep_info = bl31_plat_get_next_image_ep_info(SECURE); if (!tsp_ep_info) { WARN("No TSP provided by BL2 boot loader, Booting device" " without TSP initialization. SMC`s destined for TSP" " will return SMC_UNK\n"); return 1; } /* * If there's no valid entry point for SP, we return a non-zero value * signalling failure initializing the service. We bail out without * registering any handlers */ if (!tsp_ep_info->pc) return 1; /* * We could inspect the SP image and determine it's execution * state i.e whether AArch32 or AArch64. Assuming it's AArch64 * for the time being. */ tspd_init_tsp_ep_state(tsp_ep_info, TSP_AARCH64, tsp_ep_info->pc, &tspd_sp_context[linear_id]); #if TSP_INIT_ASYNC bl31_set_next_image_type(SECURE); #else /* * All TSPD initialization done. Now register our init function with * BL31 for deferred invocation */ bl31_register_bl32_init(&tspd_init); #endif return 0; }
/******************************************************************************* * This cpu has been turned on. Enter the TSP to initialise S-EL1 and other bits * before passing control back to the Secure Monitor. Entry in S-El1 is done * after initialising minimal architectural state that guarantees safe * execution. ******************************************************************************/ static void tspd_cpu_on_finish_handler(uint64_t unused) { int32_t rc = 0; uint32_t linear_id = plat_my_core_pos(); tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; entry_point_info_t tsp_on_entrypoint; assert(tsp_vectors); assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_OFF); tspd_init_tsp_ep_state(&tsp_on_entrypoint, TSP_AARCH64, (uint64_t) &tsp_vectors->cpu_on_entry, tsp_ctx); /* Initialise this cpu's secure context */ cm_init_my_context(&tsp_on_entrypoint); #if TSP_NS_INTR_ASYNC_PREEMPT /* * Disable the NS interrupt locally since it will be enabled globally * within cm_init_my_context. */ disable_intr_rm_local(INTR_TYPE_NS, SECURE); #endif /* Enter the TSP */ rc = tspd_synchronous_sp_entry(tsp_ctx); /* * Read the response from the TSP. A non-zero return means that * something went wrong while communicating with the SP. */ if (rc != 0) panic(); /* Update its context to reflect the state the SP is in */ set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON); }