From f4bbf435554e87de31c0a70039aa03b19962aaea Mon Sep 17 00:00:00 2001 From: Jeffrey Kardatzke Date: Thu, 9 Feb 2023 10:45:35 -0800 Subject: feat(optee): add device tree for coreboot table This adds creation of a device tree that will be passed to OP-TEE. Currently that device tree only contains the coreboot table per the Linux coreboot device tree specification. This device tree is then passed to OP-TEE so it can extract the CBMEM console information from the coreboot table for logging purposes. Signed-off-by: Jeffrey Kardatzke Change-Id: I6a26d335e16f7226018c56ad571cca77b81b0f6a --- include/lib/coreboot.h | 1 + lib/coreboot/coreboot_table.c | 10 ++++ services/spd/opteed/opteed.mk | 1 + services/spd/opteed/opteed_main.c | 104 +++++++++++++++++++++++++++++++++++++- 4 files changed, 115 insertions(+), 1 deletion(-) diff --git a/include/lib/coreboot.h b/include/lib/coreboot.h index 0aa65791d..42d4149aa 100644 --- a/include/lib/coreboot.h +++ b/include/lib/coreboot.h @@ -41,5 +41,6 @@ typedef enum { coreboot_memory_t coreboot_get_memory_type(uintptr_t start, size_t size); void coreboot_table_setup(void *base); +void coreboot_get_table_location(uint64_t *address, uint32_t *size); #endif /* COREBOOT_H */ diff --git a/lib/coreboot/coreboot_table.c b/lib/coreboot/coreboot_table.c index fb31ef1e0..43e983590 100644 --- a/lib/coreboot/coreboot_table.c +++ b/lib/coreboot/coreboot_table.c @@ -46,6 +46,8 @@ typedef struct { coreboot_memrange_t coreboot_memranges[COREBOOT_MAX_MEMRANGES]; coreboot_serial_t coreboot_serial; +uint64_t coreboot_table_addr; +uint32_t coreboot_table_size; /* * The coreboot table is parsed before the MMU is enabled (i.e. with strongly @@ -108,6 +110,12 @@ coreboot_memory_t coreboot_get_memory_type(uintptr_t start, size_t size) return CB_MEM_NONE; } +void coreboot_get_table_location(uint64_t *address, uint32_t *size) +{ + *address = coreboot_table_addr; + *size = coreboot_table_size; +} + void coreboot_table_setup(void *base) { cb_header_t *header = base; @@ -118,6 +126,8 @@ void coreboot_table_setup(void *base) ERROR("coreboot table signature corrupt!\n"); return; } + coreboot_table_addr = (uint64_t) base; + coreboot_table_size = header->header_bytes + header->table_bytes; ptr = base + header->header_bytes; for (i = 0; i < header->table_entries; i++) { diff --git a/services/spd/opteed/opteed.mk b/services/spd/opteed/opteed.mk index 477b45d98..f394744e9 100644 --- a/services/spd/opteed/opteed.mk +++ b/services/spd/opteed/opteed.mk @@ -31,4 +31,5 @@ $(warning "OPTEE_ALLOW_SMC_LOAD is enabled which may result in an insecure \ platform") $(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC)) $(eval $(call add_define,OPTEE_ALLOW_SMC_LOAD)) +include lib/libfdt/libfdt.mk endif diff --git a/services/spd/opteed/opteed_main.c b/services/spd/opteed/opteed_main.c index f069775d2..4d055db17 100644 --- a/services/spd/opteed/opteed_main.c +++ b/services/spd/opteed/opteed_main.c @@ -24,9 +24,13 @@ #include #include #include +#include #include #include #include +#if OPTEE_ALLOW_SMC_LOAD +#include +#endif /* OPTEE_ALLOW_SMC_LOAD */ #include #include @@ -51,6 +55,10 @@ static bool opteed_allow_load; DEFINE_SVC_UUID2(optee_image_load_uuid, 0xb1eafba3, 0x5d31, 0x4612, 0xb9, 0x06, 0xc4, 0xc7, 0xa4, 0xbe, 0x3c, 0xc0); + +#define OPTEED_FDT_SIZE 256 +static uint8_t fdt_buf[OPTEED_FDT_SIZE] __aligned(CACHE_WRITEBACK_GRANULE); + #else static int32_t opteed_init(void); #endif @@ -209,6 +217,91 @@ static int32_t opteed_init(void) #endif /* !OPTEE_ALLOW_SMC_LOAD */ #if OPTEE_ALLOW_SMC_LOAD +#if COREBOOT +/* + * Adds a firmware/coreboot node with the coreboot table information to a device + * tree. Returns zero on success or if there is no coreboot table information; + * failure code otherwise. + */ +static int add_coreboot_node(void *fdt) +{ + int ret; + uint64_t coreboot_table_addr; + uint32_t coreboot_table_size; + struct { + uint64_t addr; + uint32_t size; + } reg_node; + coreboot_get_table_location(&coreboot_table_addr, &coreboot_table_size); + if (!coreboot_table_addr || !coreboot_table_size) { + WARN("Unable to get coreboot table location for device tree"); + return 0; + } + ret = fdt_begin_node(fdt, "firmware"); + if (ret) + return ret; + + ret = fdt_property(fdt, "ranges", NULL, 0); + if (ret) + return ret; + + ret = fdt_begin_node(fdt, "coreboot"); + if (ret) + return ret; + + ret = fdt_property_string(fdt, "compatible", "coreboot"); + if (ret) + return ret; + + reg_node.addr = cpu_to_fdt64(coreboot_table_addr); + reg_node.size = cpu_to_fdt32(coreboot_table_size); + ret = fdt_property(fdt, "reg", ®_node, + sizeof(uint64_t) + sizeof(uint32_t)); + if (ret) + return ret; + + ret = fdt_end_node(fdt); + if (ret) + return ret; + + return fdt_end_node(fdt); +} +#endif /* COREBOOT */ + +/* + * Creates a device tree for passing into OP-TEE. Currently is populated with + * the coreboot table address. + * Returns 0 on success, error code otherwise. + */ +static int create_opteed_dt(void) +{ + int ret; + + ret = fdt_create(fdt_buf, OPTEED_FDT_SIZE); + if (ret) + return ret; + + ret = fdt_finish_reservemap(fdt_buf); + if (ret) + return ret; + + ret = fdt_begin_node(fdt_buf, ""); + if (ret) + return ret; + +#if COREBOOT + ret = add_coreboot_node(fdt_buf); + if (ret) + return ret; +#endif /* COREBOOT */ + + ret = fdt_end_node(fdt_buf); + if (ret) + return ret; + + return fdt_finish(fdt_buf); +} + /******************************************************************************* * 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 @@ -232,6 +325,7 @@ static int32_t opteed_handle_smc_load(uint64_t data_size, uint32_t data_pa) uint64_t target_size; entry_point_info_t optee_ep_info; uint32_t linear_id = plat_my_core_pos(); + uint64_t dt_addr = 0; mapped_data_pa = page_align(data_pa, DOWN); mapped_data_va = mapped_data_pa; @@ -292,12 +386,20 @@ static int32_t opteed_handle_smc_load(uint64_t data_size, uint32_t data_pa) /* Save the non-secure state */ cm_el1_sysregs_context_save(NON_SECURE); + rc = create_opteed_dt(); + if (rc) { + ERROR("Failed device tree creation %d\n", rc); + return rc; + } + dt_addr = (uint64_t)fdt_buf; + flush_dcache_range(dt_addr, OPTEED_FDT_SIZE); + opteed_init_optee_ep_state(&optee_ep_info, opteed_rw, image_pa, 0, 0, - 0, + dt_addr, &opteed_sp_context[linear_id]); if (opteed_init_with_entry_point(&optee_ep_info) == 0) { rc = -EFAULT; -- cgit v1.2.1