Beispiel #1
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 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;
}
Beispiel #3
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;
}
Beispiel #6
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;
}