Browse Source

feat(optee): enable transfer list in opteed

Enable handoff to OP-TEE using transfer list.
Create transfer list when loading OP-TEE image via non-secure SMC call.
Fallback to default handoff args when transfer list is disabled or
transfer list signature does not exist.

Change-Id: I94bb5b7fdfbb8829016a9d5d9ef5aff993d7cc99
Signed-off-by: Raymond Mao <raymond.mao@linaro.org>
pull/1999/merge
Raymond Mao 1 year ago
parent
commit
0e8def996e
  1. 15
      services/spd/opteed/opteed_common.c
  2. 111
      services/spd/opteed/opteed_main.c
  3. 4
      services/spd/opteed/opteed_pm.c
  4. 9
      services/spd/opteed/opteed_private.h

15
services/spd/opteed/opteed_common.c

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -20,9 +20,9 @@
* initialize OPTEE context and entry point info for OPTEE. * initialize OPTEE context and entry point info for OPTEE.
******************************************************************************/ ******************************************************************************/
void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point, void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point,
uint32_t rw, uint64_t pc, uint32_t rw, uint64_t pc, uint64_t arg0,
uint64_t pageable_part, uint64_t mem_limit, uint64_t arg1, uint64_t arg2, uint64_t arg3,
uint64_t dt_addr, optee_context_t *optee_ctx) optee_context_t *optee_ctx)
{ {
uint32_t ep_attr; uint32_t ep_attr;
@ -54,9 +54,10 @@ void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point,
DAIF_IRQ_BIT | DAIF_IRQ_BIT |
DAIF_ABT_BIT); DAIF_ABT_BIT);
zeromem(&optee_entry_point->args, sizeof(optee_entry_point->args)); zeromem(&optee_entry_point->args, sizeof(optee_entry_point->args));
optee_entry_point->args.arg0 = pageable_part; optee_entry_point->args.arg0 = arg0;
optee_entry_point->args.arg1 = mem_limit; optee_entry_point->args.arg1 = arg1;
optee_entry_point->args.arg2 = dt_addr; optee_entry_point->args.arg2 = arg2;
optee_entry_point->args.arg3 = arg3;
} }
/******************************************************************************* /*******************************************************************************

111
services/spd/opteed/opteed_main.c

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -27,6 +27,7 @@
#include <lib/coreboot.h> #include <lib/coreboot.h>
#include <lib/el3_runtime/context_mgmt.h> #include <lib/el3_runtime/context_mgmt.h>
#include <lib/optee_utils.h> #include <lib/optee_utils.h>
#include <lib/transfer_list.h>
#include <lib/xlat_tables/xlat_tables_v2.h> #include <lib/xlat_tables/xlat_tables_v2.h>
#if OPTEE_ALLOW_SMC_LOAD #if OPTEE_ALLOW_SMC_LOAD
#include <libfdt.h> #include <libfdt.h>
@ -37,6 +38,10 @@
#include "opteed_private.h" #include "opteed_private.h"
#include "teesmc_opteed.h" #include "teesmc_opteed.h"
#if OPTEE_ALLOW_SMC_LOAD
static struct transfer_list_header *bl31_tl;
#endif
/******************************************************************************* /*******************************************************************************
* Address of the entrypoint vector table in OPTEE. It is * Address of the entrypoint vector table in OPTEE. It is
* initialised once on the primary core after a cold boot. * initialised once on the primary core after a cold boot.
@ -123,9 +128,13 @@ static int32_t opteed_setup(void)
#else #else
entry_point_info_t *optee_ep_info; entry_point_info_t *optee_ep_info;
uint32_t linear_id; uint32_t linear_id;
uint64_t opteed_pageable_part; uint64_t arg0;
uint64_t opteed_mem_limit; uint64_t arg1;
uint64_t dt_addr; uint64_t arg2;
uint64_t arg3;
struct transfer_list_header *tl = NULL;
struct transfer_list_entry *te = NULL;
void *dt = NULL;
linear_id = plat_my_core_pos(); linear_id = plat_my_core_pos();
@ -150,17 +159,39 @@ static int32_t opteed_setup(void)
if (!optee_ep_info->pc) if (!optee_ep_info->pc)
return 1; return 1;
if (TRANSFER_LIST &&
optee_ep_info->args.arg1 == (TRANSFER_LIST_SIGNATURE |
REGISTER_CONVENTION_VERSION_MASK)) {
tl = (void *)optee_ep_info->args.arg3;
if (transfer_list_check_header(tl) == TL_OPS_NON) {
return 1;
}
opteed_rw = GET_RW(optee_ep_info->spsr);
te = transfer_list_find(tl, TL_TAG_FDT);
dt = transfer_list_entry_data(te);
if (opteed_rw == OPTEE_AARCH64) {
arg0 = (uint64_t)dt;
arg2 = 0;
} else {
arg2 = (uint64_t)dt;
arg0 = 0;
}
arg1 = optee_ep_info->args.arg1;
arg3 = optee_ep_info->args.arg3;
} else {
/* Default handoff arguments */
opteed_rw = optee_ep_info->args.arg0; opteed_rw = optee_ep_info->args.arg0;
opteed_pageable_part = optee_ep_info->args.arg1; arg0 = optee_ep_info->args.arg1; /* opteed_pageable_part */
opteed_mem_limit = optee_ep_info->args.arg2; arg1 = optee_ep_info->args.arg2; /* opteed_mem_limit */
dt_addr = optee_ep_info->args.arg3; arg2 = optee_ep_info->args.arg3; /* dt_addr */
arg3 = 0;
}
opteed_init_optee_ep_state(optee_ep_info, opteed_init_optee_ep_state(optee_ep_info, opteed_rw, optee_ep_info->pc,
opteed_rw, arg0, arg1, arg2, arg3,
optee_ep_info->pc,
opteed_pageable_part,
opteed_mem_limit,
dt_addr,
&opteed_sp_context[linear_id]); &opteed_sp_context[linear_id]);
/* /*
@ -302,6 +333,26 @@ static int create_opteed_dt(void)
return fdt_finish(fdt_buf); return fdt_finish(fdt_buf);
} }
static int32_t create_smc_tl(const void *fdt, uint32_t fdt_sz)
{
#if TRANSFER_LIST
bl31_tl = transfer_list_init((void *)(uintptr_t)FW_HANDOFF_BASE,
FW_HANDOFF_SIZE);
if (!bl31_tl) {
ERROR("Failed to initialize Transfer List at 0x%lx\n",
(unsigned long)FW_HANDOFF_BASE);
return -1;
}
if (!transfer_list_add(bl31_tl, TL_TAG_FDT, fdt_sz, fdt)) {
return -1;
}
return 0;
#else
return -1;
#endif
}
/******************************************************************************* /*******************************************************************************
* This function is responsible for handling the SMC that loads the OP-TEE * This function is responsible for handling the SMC that loads the OP-TEE
* binary image via a non-secure SMC call. It takes the size and physical * binary image via a non-secure SMC call. It takes the size and physical
@ -326,6 +377,10 @@ static int32_t opteed_handle_smc_load(uint64_t data_size, uint32_t data_pa)
entry_point_info_t optee_ep_info; entry_point_info_t optee_ep_info;
uint32_t linear_id = plat_my_core_pos(); uint32_t linear_id = plat_my_core_pos();
uint64_t dt_addr = 0; uint64_t dt_addr = 0;
uint64_t arg0 = 0;
uint64_t arg1 = 0;
uint64_t arg2 = 0;
uint64_t arg3 = 0;
mapped_data_pa = page_align(data_pa, DOWN); mapped_data_pa = page_align(data_pa, DOWN);
mapped_data_va = mapped_data_pa; mapped_data_va = mapped_data_pa;
@ -394,12 +449,36 @@ static int32_t opteed_handle_smc_load(uint64_t data_size, uint32_t data_pa)
dt_addr = (uint64_t)fdt_buf; dt_addr = (uint64_t)fdt_buf;
flush_dcache_range(dt_addr, OPTEED_FDT_SIZE); flush_dcache_range(dt_addr, OPTEED_FDT_SIZE);
if (TRANSFER_LIST &&
!create_smc_tl((void *)dt_addr, OPTEED_FDT_SIZE)) {
struct transfer_list_entry *te = NULL;
void *dt = NULL;
te = transfer_list_find(bl31_tl, TL_TAG_FDT);
dt = transfer_list_entry_data(te);
if (opteed_rw == OPTEE_AARCH64) {
arg0 = (uint64_t)dt;
arg2 = 0;
} else {
arg2 = (uint64_t)dt;
arg0 = 0;
}
arg1 = TRANSFER_LIST_SIGNATURE |
REGISTER_CONVENTION_VERSION_MASK;
arg3 = (uint64_t)bl31_tl;
} else {
/* Default handoff arguments */
arg2 = dt_addr;
}
opteed_init_optee_ep_state(&optee_ep_info, opteed_init_optee_ep_state(&optee_ep_info,
opteed_rw, opteed_rw,
image_pa, image_pa,
0, arg0,
0, arg1,
dt_addr, arg2,
arg3,
&opteed_sp_context[linear_id]); &opteed_sp_context[linear_id]);
if (opteed_init_with_entry_point(&optee_ep_info) == 0) { if (opteed_init_with_entry_point(&optee_ep_info) == 0) {
rc = -EFAULT; rc = -EFAULT;

4
services/spd/opteed/opteed_pm.c

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -113,7 +113,7 @@ void opteed_cpu_on_finish_handler(u_register_t unused)
opteed_init_optee_ep_state(&optee_on_entrypoint, opteed_rw, opteed_init_optee_ep_state(&optee_on_entrypoint, opteed_rw,
(uint64_t)&optee_vector_table->cpu_on_entry, (uint64_t)&optee_vector_table->cpu_on_entry,
0, 0, 0, optee_ctx); 0, 0, 0, 0, optee_ctx);
/* Initialise this cpu's secure context */ /* Initialise this cpu's secure context */
cm_init_my_context(&optee_on_entrypoint); cm_init_my_context(&optee_on_entrypoint);

9
services/spd/opteed/opteed_private.h

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -148,11 +148,8 @@ void __dead2 opteed_exit_sp(uint64_t c_rt_ctx, uint64_t ret);
uint64_t opteed_synchronous_sp_entry(optee_context_t *optee_ctx); uint64_t opteed_synchronous_sp_entry(optee_context_t *optee_ctx);
void __dead2 opteed_synchronous_sp_exit(optee_context_t *optee_ctx, uint64_t ret); void __dead2 opteed_synchronous_sp_exit(optee_context_t *optee_ctx, uint64_t ret);
void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point, void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point,
uint32_t rw, uint32_t rw, uint64_t pc, uint64_t arg0,
uint64_t pc, uint64_t arg1, uint64_t arg2, uint64_t arg3,
uint64_t pageable_part,
uint64_t mem_limit,
uint64_t dt_addr,
optee_context_t *optee_ctx); optee_context_t *optee_ctx);
void opteed_cpu_on_finish_handler(u_register_t unused); void opteed_cpu_on_finish_handler(u_register_t unused);

Loading…
Cancel
Save