Skip to content

Commit

Permalink
core: load stmm via secure partition
Browse files Browse the repository at this point in the history
Secure variable storage for EFI variables is critical for enabling and
protecting UEFI Secure Boot. Unfortunately due to the fact that SPD and
SPM are mutually exclusive, we can't run StMM from EDK2 and OP-TEE.
An advantage of doing so is that different firmware implementations
can leverage EDK2's StandAloneMM and in cooperation with OP-TEE RPMB
APIs can store UEFI variables in a secure storage.
This makes the variable storage quite generic in any device with an RPMB
partition.

Using a well debugged application is preferable over rewriting the whole
application as a TA. Another advantage is that this inherits the Fault
Tolerant Writes (FTW) functionality built-in on StMM to protect
variables against corruptions during writing. Considering the FFA
changes of the future Arm architectures using an SP that includes
everything seems like a better choice at the moment.
The 'SPM emulation' currently added into OP-TEE only supports
a single SP to be launched. This means that the StMM embedded
application has the RPMB driver built in at the moment. In the future we
can add code (evolving FFA) to launch multiple SPs. So the StMM variable
handling can be decoupled from the RPMB driver, which will reside in a
different SP.

So let's add a user mode secure partition context and support loading
"Standalone MM" of EDK2 into it. A separate syscall handling is added to
serve as different kind of ABI and syscall IDs. The secure partition has
a TA like interface towards normal world, but requests are routed into
the StMM partition instead.

CFG_STMM_PATH is assigned the path of BL32_AP_MM.fd, for instance:
CFG_STMM_PATH=...Build/QemuVirtMmStandalone/DEBUG_GCC5/FV/BL32_AP_MM.fd

Since this is quite tricky to compile and test you can use this [1].
Just clone the repo and run ./build.sh. The script will pick up edk2,
edk2-platforms, op-tee, atf and U-boot and compile all the necessary
binaries for QEMU. A patch (awful hack) has been added to U-boot to
allow RPMB emulation through it's supplicant, since QEMU RPMB emulation
is not yet available.
After compiling and launching QEMU the usual U-boot commands for EFI
variable management will store the variables on an RPMB device.

[1] https://git.linaro.org/people/ilias.apalodimas/efi_optee_variables.git/

Signed-off-by: Jens Wiklander <[email protected]>
Co-developed-by: Ilias Apalodimas <[email protected]>
Signed-off-by: Ilias Apalodimas <[email protected]>
Co-developed-by: Pipat Methavanitpong <[email protected]>
Signed-off-by: Pipat Methavanitpong <[email protected]>
Co-developed-by: Miklos Balint <[email protected]>
Signed-off-by: Miklos Balint <[email protected]>
  • Loading branch information
jenswi-linaro authored and apalos committed Jul 15, 2020
1 parent 93aade0 commit 305a152
Show file tree
Hide file tree
Showing 10 changed files with 1,125 additions and 1 deletion.
90 changes: 90 additions & 0 deletions core/arch/arm/include/ffa.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* SPDX-License-Identifier: BSD-2-Clause
* Copyright (c) 2020, Linaro Limited
* Copyright (c) 2018-2020, Arm Limited. All rights reserved.
*/

#ifndef __FFA_H
#define __FFA_H

/* This is based on the FF-A 1.0 EAC specification */

#include <smccc.h>
#include <stdint.h>

/* Error codes */
#define FFA_NOT_SUPPORTED -1
#define FFA_INVALID_PARAMETER -2
#define FFA_NO_MEMORY -3
#define FFA_BUSY -4
#define FFA_INTERRUPTED -5
#define FFA_DENIED -6
#define FFA_RETRY -7

/* The macros below are used to identify FF-A calls from the SMC function ID */
#define FFA_FID_MASK U(0xffff)
#define FFA_FID_MIN_VALUE U(0x60)
#define FFA_FID_MAX_VALUE U(0x7f)

/* FFA_VERSION helpers */
#define FFA_VERSION_MAJOR U(1)
#define FFA_VERSION_MAJOR_SHIFT 16
#define FFA_VERSION_MAJOR_MASK U(0x7FFF)
#define FFA_VERSION_MINOR U(0)
#define FFA_VERSION_MINOR_SHIFT 0
#define FFA_VERSION_MINOR_MASK U(0xFFFF)
#define MAKE_FFA_VERSION(major, minor) ((((major) & FFA_VERSION_MAJOR_MASK) \
<< FFA_VERSION_MAJOR_SHIFT) | \
((minor) & FFA_VERSION_MINOR_MASK))
#define FFA_VERSION_COMPILED FFA_VERSION_FORM(FFA_VERSION_MAJOR, \
FFA_VERSION_MINOR)

/* FFA_MSG_SEND helpers */
#define FFA_MSG_SEND_ATTRS_BLK_SHIFT U(0)
#define FFA_MSG_SEND_ATTRS_BLK_MASK U(0x1)
#define FFA_MSG_SEND_ATTRS_BLK U(0)
#define FFA_MSG_SEND_ATTRS_BLK_NOT U(1)
#define FFA_MSG_SEND_ATTRS(blk) (((blk) & FFA_MSG_SEND_ATTRS_BLK_MASK) \
<< FFA_MSG_SEND_ATTRS_BLK_SHIFT)

/* Function IDs */
#define FFA_ERROR U(0x84000060)
#define FFA_SUCCESS_SMC32 U(0x84000061)
#define FFA_SUCCESS_SMC64 U(0xC4000061)
#define FFA_INTERRUPT U(0x84000062)
#define FFA_VERSION U(0x84000063)
#define FFA_FEATURES U(0x84000064)
#define FFA_RX_RELEASE U(0x84000065)
#define FFA_RXTX_MAP_SMC32 U(0x84000066)
#define FFA_RXTX_MAP_SMC64 U(0xC4000066)
#define FFA_RXTX_UNMAP U(0x84000067)
#define FFA_PARTITION_INFO_GET U(0x84000068)
#define FFA_ID_GET U(0x84000069)
#define FFA_MSG_WAIT U(0x8400006B)
#define FFA_MSG_YIELD U(0x8400006C)
#define FFA_MSG_RUN U(0x8400006D)
#define FFA_NORMAL_WORLD_RESUME U(0x8400007A)
#define FFA_MSG_SEND U(0x8400006E)
#define FFA_MSG_SEND_DIRECT_REQ_SMC32 U(0x8400006F)
#define FFA_MSG_SEND_DIRECT_REQ_SMC64 U(0xC400006F)
#define FFA_MSG_SEND_DIRECT_RESP_SMC32 U(0x84000070)
#define FFA_MSG_SEND_DIRECT_RESP_SMC64 U(0xC4000070)
#define FFA_MSG_POLL U(0x8400006A)
#define FFA_MEM_DONATE_SMC32 U(0x84000071)
#define FFA_MEM_DONATE_SMC64 U(0xC4000071)
#define FFA_MEM_LEND_SMC32 U(0x84000072)
#define FFA_MEM_LEND_SMC64 U(0xC4000072)
#define FFA_MEM_SHARE_SMC32 U(0x84000073)
#define FFA_MEM_SHARE_SMC64 U(0xC4000073)
#define FFA_MEM_RETRIEVE_REQ_SMC32 U(0x84000074)
#define FFA_MEM_RETRIEVE_REQ_SMC64 U(0xC4000074)
#define FFA_MEM_RETRIEVE_RESP U(0x84000075)
#define FFA_MEM_RELINQUISH U(0x84000076)
#define FFA_MEM_RECLAIM U(0x84000077)

/* Special value for traffic targeted to the Hypervisor or SPM */
#define FFA_TARGET_INFO_MBZ U(0x0)

/* Special value for MBZ parameters */
#define FFA_PARAM_MBZ U(0x0)

#endif /* __FFA_H */
152 changes: 152 additions & 0 deletions core/arch/arm/include/kernel/secure_partition.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2019, Linaro Limited
*/

#ifndef __KERNEL_SECURE_PARTITION_H
#define __KERNEL_SECURE_PARTITION_H

#include <assert.h>
#include <kernel/tee_ta_manager.h>
#include <kernel/thread.h>
#include <kernel/user_mode_ctx_struct.h>
#include <types_ext.h>
#include <util.h>

#define SP_RET_SUCCESS 0
#define SP_RET_NOT_SUPPORTED -1
#define SP_RET_INVALID_PARAM -2
#define SP_RET_DENIED -3
#define SP_RET_NO_MEM -4

#define SP_VER_MAJOR_MASK 0x7FFF
#define SP_VER_MINOR_MASK 0xFFFF
#define SP_VER_MAJOR (0 & SP_VER_MAJOR_MASK)
#define SP_VER_MINOR (1 & SP_VER_MINOR_MASK)
#define SP_VERSION ((SP_VER_MAJOR << 16) | (SP_VER_MINOR))

#define SP_MEM_ATTR_ACCESS_MASK 3
#define SP_MEM_ATTR_ACCESS_NONE 0
#define SP_MEM_ATTR_ACCESS_RW 1
#define SP_MEM_ATTR_ACCESS_RO 3
#define SP_MEM_ATTR_EXEC_MASK BIT(2)
#define SP_MEM_ATTR_EXEC 0

/* FFA ids */
#define FFA_MSG_SEND_DIRECT_REQ_64 0xC400006F
#define FFA_MSG_SEND_DIRECT_RESP_64 0xC4000070
/* FIXME randomly defined, switch to proper ids */
#define FFA_SVC_EVENT_COMPLETE_64 0xC4000061
#define FFA_SVC_MEMORY_ATTRIBUTES_GET_64 0xC4000064
#define FFA_SVC_MEMORY_ATTRIBUTES_SET_64 0xC4000065
#define FFA_SVC_RPMB_READ 0xC4000066
#define FFA_SVC_RPMB_WRITE 0xC4000067

/* Param header types */
#define SP_PARAM_EP UINT8_C(0x01)
#define SP_PARAM_IMAGE_BINARY UINT8_C(0x02)
#define SP_PARAM_BL31 UINT8_C(0x03)
#define SP_PARAM_BL_LOAD_INFO UINT8_C(0x04)
#define SP_PARAM_BL_PARAMS UINT8_C(0x05)
#define SP_PARAM_PSCI_LIB_ARGS UINT8_C(0x06)
#define SP_PARAM_SP_IMAGE_BOOT_INFO UINT8_C(0x07)

/* Param header version */
#define SP_PARAM_VERSION_1 UINT8_C(0x01)
#define SP_PARAM_VERSION_2 UINT8_C(0x02)

/* void syscall_sys_return(uint32_t ret) __noreturn; */
#define SP_SYSCALL_RETURN UINT32_C(0)
/* void syscall_log(const void *buf, size_t len); */
#define SP_SYSCALL_LOG UINT32_C(1)
/* void syscall_panic(uint32_t code) __noreturn; */
#define SP_SYSCALL_PANIC UINT32_C(2)

/***************************************************************************
* This structure provides version information and the size of the
* structure, attributes for the structure it represents
***************************************************************************/
struct sp_param_header {
uint8_t type; /* type of the structure */
uint8_t version; /* version of this structure */
uint16_t size; /* size of this structure in bytes */
uint32_t attr; /* attributes: unused bits SBZ */
};

/*
* Flags used by the secure_partition_mp_info structure to describe the
* characteristics of a cpu. Only a single flag is defined at the moment to
* indicate the primary cpu.
*/
#define MP_INFO_FLAG_PRIMARY_CPU UINT32_C(0x00000001)

/*
* This structure is used to provide information required to initialise a S-EL0
* partition.
*/
struct secure_partition_mp_info {
uint64_t mpidr;
uint32_t linear_id;
uint32_t flags;
};

struct secure_partition_boot_info {
struct sp_param_header h;
uint64_t sp_mem_base;
uint64_t sp_mem_limit;
uint64_t sp_image_base;
uint64_t sp_stack_base;
uint64_t sp_heap_base;
uint64_t sp_ns_comm_buf_base;
uint64_t sp_shared_buf_base;
uint64_t sp_image_size;
uint64_t sp_pcpu_stack_size;
uint64_t sp_heap_size;
uint64_t sp_ns_comm_buf_size;
uint64_t sp_shared_buf_size;
uint32_t num_sp_mem_regions;
uint32_t num_cpus;
struct secure_partition_mp_info *mp_info;
};

struct sec_part_ctx {
struct user_mode_ctx uctx;
struct thread_ctx_regs regs;
vaddr_t ns_comm_buf_addr;
unsigned int ns_comm_buf_size;
bool is_initializing;
};

extern const struct tee_ta_ops secure_partition_ops;

static inline bool is_sp_ctx(struct tee_ta_ctx *ctx __maybe_unused)
{
#ifdef CFG_WITH_SECURE_PARTITION
return ctx && ctx->ops == &secure_partition_ops;
#else
return false;
#endif
}

static inline struct sec_part_ctx *to_sec_part_ctx(struct tee_ta_ctx *ctx)
{
assert(is_sp_ctx(ctx));
return container_of(ctx, struct sec_part_ctx, uctx.ctx);
}

void sec_part_save_return_state(struct thread_ctx_regs *ctx_regs,
struct thread_svc_regs *svc_regs);

#ifdef CFG_WITH_SECURE_PARTITION
TEE_Result sec_part_init_session(const TEE_UUID *uuid,
struct tee_ta_session *s);
#else
static inline TEE_Result
sec_part_init_session(const TEE_UUID *uuid __unused,
struct tee_ta_session *s __unused)
{
return TEE_ERROR_ITEM_NOT_FOUND;
}
#endif

#endif /*__KERNEL_SECURE_PARTITION_H*/
25 changes: 25 additions & 0 deletions core/arch/arm/include/pta_stmm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (c) 2018-2019, Linaro Limited
*/
#ifndef __PTA_STMM_H
#define __PTA_STMM_H

/*
* Interface to the pseudo TA, which provides a communication channel with
* the Standalone MM SP (StMM) running at S-EL0.
*/

#define PTA_STMM_UUID { 0xed32d533, 0x99e6, 0x4209, {\
0x9c, 0xc0, 0x2d, 0x72, 0xcd, 0xd9, 0x98, 0xa7 } }

/*
* Pass a buffer to Standalone MM SP
*
* [in/out] memref[0]: EFI Communication buffer
* [out] value[1].a: EFI return code
*/
#define PTA_STMM_COMMUNICATE 0

#endif /* __PTA_STMM_H */

Loading

0 comments on commit 305a152

Please sign in to comment.