/******************************************************************************* * 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 fiqd_setup(void) { entry_point_info_t *tsp_ep_info; uint64_t mpidr = read_mpidr(); uint32_t linear_id; linear_id = platform_get_core_pos(mpidr); /* * 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 0 /* * 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; #endif /* * 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. */ fiqd_init_tsp_ep_state(tsp_ep_info, TSP_AARCH64, tsp_ep_info->pc, &fiqd_sp_context[linear_id]); #if TSP_INIT_ASYNC bl31_set_next_image_type(SECURE); #else /* * All FIQD initialization done. Now register our init function with * BL31 for deferred invocation */ bl31_register_bl32_init(&fiqd_init); #endif return 0; }
/******************************************************************************* * OPTEE Dispatcher setup. The OPTEED finds out the OPTEE entrypoint and type * (aarch32/aarch64) if not already known and initialises the context for entry * into OPTEE for its initialization. ******************************************************************************/ int32_t opteed_setup(void) { entry_point_info_t *optee_ep_info; uint64_t mpidr = read_mpidr(); uint32_t linear_id; linear_id = platform_get_core_pos(mpidr); /* * Get information about the Secure Payload (BL32) image. Its * absence is a critical failure. TODO: Add support to * conditionally include the SPD service */ optee_ep_info = bl31_plat_get_next_image_ep_info(SECURE); if (!optee_ep_info) { WARN("No OPTEE provided by BL2 boot loader, Booting device" " without OPTEE initialization. SMC`s destined for OPTEE" " 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 (!optee_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 AArch32 * for the time being. */ opteed_rw = OPTEE_AARCH32; opteed_init_optee_ep_state(optee_ep_info, opteed_rw, optee_ep_info->pc, &opteed_sp_context[linear_id]); /* * All OPTEED initialization done. Now register our init function with * BL31 for deferred invocation */ bl31_register_bl32_init(&opteed_init); return 0; }
int32_t tbase_fastcall_setup(void) { entry_point_info_t *image_info; image_info = bl31_plat_get_next_image_ep_info(SECURE); assert(image_info); uint32_t linear_id = platform_get_core_pos(read_mpidr()); // TODO: We do not need this anymore, if PM is in use tbase_init_secure_context(&secure_context[linear_id]); tbase_init_eret(image_info->pc,TBASE_AARCH32); bl31_register_bl32_init(&tbase_init_entry); return 0; }
/******************************************************************************* * 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 tlkd_setup(void) { entry_point_info_t *tlk_ep_info; /* * Get information about the Secure Payload (BL32) image. Its * absence is a critical failure. */ tlk_ep_info = bl31_plat_get_next_image_ep_info(SECURE); if (!tlk_ep_info) { WARN("No SP provided. Booting device without SP" " initialization. SMC`s destined for SP" " 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 (!tlk_ep_info->pc) return 1; /* * Inspect the SP image's SPSR and determine it's execution state * i.e whether AArch32 or AArch64. */ tlkd_init_tlk_ep_state(tlk_ep_info, (tlk_ep_info->spsr >> MODE_RW_SHIFT) & MODE_RW_MASK, tlk_ep_info->pc, &tlk_ctx); /* * All TLK SPD initialization done. Now register our init function * with BL31 for deferred invocation */ bl31_register_bl32_init(&tlkd_init); return 0; }
/******************************************************************************* * 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 xilspd_setup(void) { entry_point_info_t *xilsp_ep_info; uint32_t linear_id; linear_id = plat_my_core_pos(); /* * Get information about the XILSP (BL32) image. Its absence is a * critical failure. TODO: Add support to conditionally include * the SPD service */ xilsp_ep_info = bl31_plat_get_next_image_ep_info(SECURE); if (!xilsp_ep_info) { WARN("No XILSP provided by BL2 boot loader, Booting device without XILSP initialization. SMC's destined for XILSP 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 (!xilsp_ep_info->pc) return 1; xilspd_init_xilsp_ep_state(xilsp_ep_info, (xilsp_ep_info->spsr >> MODE_RW_SHIFT) & MODE_RW_MASK, xilsp_ep_info->pc, &xilspd_sp_context[linear_id]); /* * All XILSPD initialization done. Now register our init function with * BL31 for deferred invocation */ bl31_register_bl32_init(&xilspd_init); return 0; }
/******************************************************************************* * OPTEE Dispatcher setup. The OPTEED finds out the OPTEE entrypoint and type * (aarch32/aarch64) if not already known and initialises the context for entry * into OPTEE for its initialization. ******************************************************************************/ int32_t opteed_setup(void) { entry_point_info_t *ep_info; struct optee_header *header; uint64_t mpidr = read_mpidr(); uint32_t linear_id; uintptr_t init_load_addr; size_t init_size; size_t init_mem_usage; uintptr_t payload_addr; uintptr_t mem_limit; uintptr_t paged_part; uintptr_t paged_size; linear_id = platform_get_core_pos(mpidr); /* * Get information about the Secure Payload (BL32) image. Its * absence is a critical failure. TODO: Add support to * conditionally include the SPD service */ ep_info = bl31_plat_get_next_image_ep_info(SECURE); if (!ep_info) { WARN("No OPTEE provided by BL2 boot loader.\n"); goto err; } header = (struct optee_header *)ep_info->pc; if (header->magic != OPTEE_MAGIC || header->version != OPTEE_VERSION) { WARN("Invalid OPTEE header.\n"); goto err; } if (header->arch == OPTEE_ARCH_ARM32) opteed_rw = OPTEE_AARCH32; else if (header->arch == OPTEE_ARCH_ARM64) opteed_rw = OPTEE_AARCH64; else { WARN("Invalid OPTEE architecture (%d)\n", header->arch); goto err; } init_load_addr = ((uint64_t)header->init_load_addr_hi << 32) | header->init_load_addr_lo; init_size = header->init_size; init_mem_usage = header->init_mem_usage; payload_addr = (uintptr_t)(header + 1); paged_size = header->paged_size; /* * Move OPTEE binary to the required location in memory. * * There's two ways OPTEE can be running in memory: * 1. A memory large enough to keep the entire OPTEE binary * (DRAM currently) * 2. A part of OPTEE in a smaller (and more secure) memory * (SRAM currently). This is achieved with demand paging * of read-only data/code against a backing store in some * larger memory (DRAM currently). * * In either case dictates init_load_addr in the OPTEE * header the address where what's after the header * (payload) should be residing when started. init_size in * the header tells how much of the payload that need to be * copied. init_mem_usage tells how much runtime memory in * total is needed by OPTEE. * * In alternative 2 there's additional data after * init_size, this is the rest of OPTEE which is demand * paged into memory. A pointer to that data is supplied * to OPTEE when initializing. * * Alternative 1 only uses DRAM when executing OPTEE while * alternative 2 uses both SRAM and DRAM to execute. * * All data written which is later read by OPTEE must be flushed * out to memory since OPTEE starts with MMU turned off and caches * disabled. */ if (is_mem_free(BL32_SRAM_BASE, BL32_SRAM_LIMIT - BL32_SRAM_BASE, init_load_addr, init_mem_usage)) { /* Running in SRAM, paging some code against DRAM */ memcpy((void *)init_load_addr, (void *)payload_addr, init_size); flush_dcache_range(init_load_addr, init_size); paged_part = payload_addr + init_size; mem_limit = BL32_SRAM_LIMIT; } else if (is_mem_free(BL32_DRAM_BASE, BL32_DRAM_LIMIT - BL32_DRAM_BASE, init_load_addr, init_mem_usage)) { /* * Running in DRAM. * * The paged part normally empty, but if it isn't, * move it to the end of DRAM before moving the * init part in place. */ paged_part = BL32_DRAM_LIMIT - paged_size; if (paged_size) { if (!is_mem_free(BL32_DRAM_BASE, BL32_DRAM_LIMIT - BL32_DRAM_BASE, init_load_addr, init_mem_usage + paged_size)) { WARN("Failed to reserve memory 0x%lx - 0x%lx\n", init_load_addr, init_load_addr + init_mem_usage + paged_size); goto err; } memcpy((void *)paged_part, (void *)(payload_addr + init_size), paged_size); flush_dcache_range(paged_part, paged_size); } memmove((void *)init_load_addr, (void *)payload_addr, init_size); flush_dcache_range(init_load_addr, init_size); mem_limit = BL32_DRAM_LIMIT; } else { WARN("Failed to reserve memory 0x%lx - 0x%lx\n", init_load_addr, init_load_addr + init_mem_usage); goto err; } opteed_init_optee_ep_state(ep_info, opteed_rw, init_load_addr, paged_part, mem_limit, &opteed_sp_context[linear_id]); /* * All OPTEED initialization done. Now register our init function with * BL31 for deferred invocation */ bl31_register_bl32_init(&opteed_init); return 0; err: WARN("Booting device without OPTEE initialization.\n"); WARN("SMC`s destined for OPTEE will return SMC_UNK\n"); return 1; }
/******************************************************************************* * Initialize contexts of all Secure Partitions. ******************************************************************************/ int32_t spm_setup(void) { int rc; sp_context_t *ctx; void *sp_base, *rd_base; size_t sp_size, rd_size; uint64_t flags = 0U; /* Disable MMU at EL1 (initialized by BL2) */ disable_mmu_icache_el1(); /* * Non-blocking services can be interrupted by Non-secure interrupts. * Register an interrupt handler for NS interrupts when generated while * the CPU is in secure state. They are routed to EL3. */ set_interrupt_rm_flag(flags, SECURE); uint64_t rc_int = register_interrupt_type_handler(INTR_TYPE_NS, spm_ns_interrupt_handler, flags); if (rc_int) { ERROR("SPM: Failed to register NS interrupt handler with rc = %llx\n", rc_int); panic(); } /* Setup shim layer */ spm_exceptions_xlat_init_context(); /* * Setup all Secure Partitions. */ unsigned int i = 0U; while (1) { rc = plat_spm_sp_get_next_address(&sp_base, &sp_size, &rd_base, &rd_size); if (rc < 0) { /* Reached the end of the package. */ break; } if (i >= PLAT_SPM_MAX_PARTITIONS) { ERROR("Too many partitions in the package.\n"); panic(); } ctx = &sp_ctx_array[i]; assert(ctx->is_present == 0); /* Initialize context of the SP */ INFO("Secure Partition %u context setup start...\n", i); /* Save location of the image in physical memory */ ctx->image_base = (uintptr_t)sp_base; ctx->image_size = sp_size; rc = plat_spm_sp_rd_load(&ctx->rd, rd_base, rd_size); if (rc < 0) { ERROR("Error while loading RD blob.\n"); panic(); } spm_sp_setup(ctx); ctx->is_present = 1; INFO("Secure Partition %u setup done.\n", i); i++; } if (i == 0U) { ERROR("No present partitions in the package.\n"); panic(); } /* Register init function for deferred init. */ bl31_register_bl32_init(&spm_init); return 0; }