mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-17 01:54:22 +00:00
feat(drtm): check drtm arguments during dynamic launch
Check the sanity of arguments before dynamic launch. Change-Id: Iad68f852b09851b0c55a55df6ba16576e105758a Signed-off-by: Manish Pandey <manish.pandey2@arm.com> Signed-off-by: Lucian Paul-Trifu <lucian.paultrifu@gmail.com>
This commit is contained in:
parent
bd6cc0b238
commit
40e1fad69b
3 changed files with 213 additions and 0 deletions
|
@ -9,6 +9,14 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
struct __packed drtm_dl_dma_prot_args_v1 {
|
||||
uint64_t dma_prot_table_paddr;
|
||||
uint64_t dma_prot_table_size;
|
||||
};
|
||||
|
||||
/* Opaque / encapsulated type. */
|
||||
typedef struct drtm_dl_dma_prot_args_v1 drtm_dl_dma_prot_args_v1_t;
|
||||
|
||||
bool drtm_dma_prot_init(void);
|
||||
|
||||
#endif /* DRTM_DMA_PROT_H */
|
||||
|
|
|
@ -194,9 +194,170 @@ static enum drtm_retc drtm_dl_check_cores(void)
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
static enum drtm_retc drtm_dl_prepare_dlme_data(const struct_drtm_dl_args *args,
|
||||
size_t *dlme_data_size_out)
|
||||
{
|
||||
size_t dlme_data_total_bytes_req = 0;
|
||||
|
||||
*dlme_data_size_out = dlme_data_total_bytes_req;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: accesses to the dynamic launch args, and to the DLME data are
|
||||
* little-endian as required, thanks to TF-A BL31 init requirements.
|
||||
*/
|
||||
static enum drtm_retc drtm_dl_check_args(uint64_t x1,
|
||||
struct_drtm_dl_args *a_out)
|
||||
{
|
||||
uint64_t dlme_start, dlme_end;
|
||||
uint64_t dlme_img_start, dlme_img_ep, dlme_img_end;
|
||||
uint64_t dlme_data_start, dlme_data_end;
|
||||
uintptr_t args_mapping;
|
||||
size_t args_mapping_size;
|
||||
struct_drtm_dl_args *a;
|
||||
struct_drtm_dl_args args_buf;
|
||||
size_t dlme_data_size_req;
|
||||
int rc;
|
||||
|
||||
if (x1 % DRTM_PAGE_SIZE != 0) {
|
||||
ERROR("DRTM: parameters structure is not "
|
||||
DRTM_PAGE_SIZE_STR "-aligned\n");
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
args_mapping_size = ALIGNED_UP(sizeof(struct_drtm_dl_args), DRTM_PAGE_SIZE);
|
||||
rc = mmap_add_dynamic_region_alloc_va(x1, &args_mapping, args_mapping_size,
|
||||
MT_MEMORY | MT_NS | MT_RO |
|
||||
MT_SHAREABILITY_ISH);
|
||||
if (rc != 0) {
|
||||
WARN("DRTM: %s: mmap_add_dynamic_region() failed rc=%d\n",
|
||||
__func__, rc);
|
||||
return INTERNAL_ERROR;
|
||||
}
|
||||
a = (struct_drtm_dl_args *)args_mapping;
|
||||
/*
|
||||
* TODO: invalidate all data cache before reading the data passed by the
|
||||
* DCE Preamble. This is required to avoid / defend against racing with
|
||||
* cache evictions.
|
||||
*/
|
||||
args_buf = *a;
|
||||
|
||||
rc = mmap_remove_dynamic_region(args_mapping, args_mapping_size);
|
||||
if (rc) {
|
||||
ERROR("%s(): mmap_remove_dynamic_region() failed unexpectedly"
|
||||
" rc=%d\n", __func__, rc);
|
||||
panic();
|
||||
}
|
||||
a = &args_buf;
|
||||
|
||||
if (a->version != 1) {
|
||||
ERROR("DRTM: parameters structure incompatible with major version %d\n",
|
||||
ARM_DRTM_VERSION_MAJOR);
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (!(a->dlme_img_off < a->dlme_size &&
|
||||
a->dlme_data_off < a->dlme_size)) {
|
||||
ERROR("DRTM: argument offset is outside of the DLME region\n");
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
dlme_start = a->dlme_paddr;
|
||||
dlme_end = a->dlme_paddr + a->dlme_size;
|
||||
dlme_img_start = a->dlme_paddr + a->dlme_img_off;
|
||||
dlme_img_ep = dlme_img_start + a->dlme_img_ep_off;
|
||||
dlme_img_end = dlme_img_start + a->dlme_img_size;
|
||||
dlme_data_start = a->dlme_paddr + a->dlme_data_off;
|
||||
dlme_data_end = dlme_end;
|
||||
|
||||
/*
|
||||
* TODO: validate that the DLME physical address range is all NS memory,
|
||||
* return INVALID_PARAMETERS if it is not.
|
||||
* Note that this check relies on platform-specific information. For
|
||||
* examples, see psci_plat_pm_ops->validate_ns_entrypoint() or
|
||||
* arm_validate_ns_entrypoint().
|
||||
*/
|
||||
|
||||
/* Check the DLME regions arguments. */
|
||||
if ((dlme_start % DRTM_PAGE_SIZE) != 0) {
|
||||
ERROR("DRTM: argument DLME region is not "
|
||||
DRTM_PAGE_SIZE_STR "-aligned\n");
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
if (!(dlme_start < dlme_end &&
|
||||
dlme_start <= dlme_img_start && dlme_img_start < dlme_img_end &&
|
||||
dlme_start <= dlme_data_start && dlme_data_start < dlme_data_end)) {
|
||||
ERROR("DRTM: argument DLME region is discontiguous\n");
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
if (dlme_img_start < dlme_data_end && dlme_data_start < dlme_img_end) {
|
||||
ERROR("DRTM: argument DLME regions overlap\n");
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
/* Check the DLME image region arguments. */
|
||||
if ((dlme_img_start % DRTM_PAGE_SIZE) != 0) {
|
||||
ERROR("DRTM: argument DLME image region is not "
|
||||
DRTM_PAGE_SIZE_STR "-aligned\n");
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
if (!(dlme_img_start <= dlme_img_ep && dlme_img_ep < dlme_img_end)) {
|
||||
ERROR("DRTM: DLME entry point is outside of the DLME image region\n");
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
if ((dlme_img_ep % 4) != 0) {
|
||||
ERROR("DRTM: DLME image entry point is not 4-byte-aligned\n");
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
/* Check the DLME data region arguments. */
|
||||
if ((dlme_data_start % DRTM_PAGE_SIZE) != 0) {
|
||||
ERROR("DRTM: argument DLME data region is not "
|
||||
DRTM_PAGE_SIZE_STR "-aligned\n");
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
rc = drtm_dl_prepare_dlme_data(NULL, &dlme_data_size_req);
|
||||
if (rc) {
|
||||
ERROR("%s: drtm_dl_prepare_dlme_data() failed unexpectedly rc=%d\n",
|
||||
__func__, rc);
|
||||
panic();
|
||||
}
|
||||
if (dlme_data_end - dlme_data_start < dlme_data_size_req) {
|
||||
ERROR("DRTM: argument DLME data region is short of %lu bytes\n",
|
||||
dlme_data_size_req - (size_t)(dlme_data_end - dlme_data_start));
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
/* Check the Normal World DCE region arguments. */
|
||||
if (a->dce_nwd_paddr != 0) {
|
||||
uint32_t dce_nwd_start = a->dce_nwd_paddr;
|
||||
uint32_t dce_nwd_end = dce_nwd_start + a->dce_nwd_size;
|
||||
|
||||
if (!(dce_nwd_start < dce_nwd_end)) {
|
||||
ERROR("DRTM: argument Normal World DCE region is dicontiguous\n");
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
|
||||
if (dce_nwd_start < dlme_end && dlme_start < dce_nwd_end) {
|
||||
ERROR("DRTM: argument Normal World DCE regions overlap\n");
|
||||
return INVALID_PARAMETERS;
|
||||
}
|
||||
}
|
||||
|
||||
*a_out = *a;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle)
|
||||
{
|
||||
enum drtm_retc ret = SUCCESS;
|
||||
struct_drtm_dl_args args;
|
||||
|
||||
/* Ensure that only boot PE is powered on */
|
||||
ret = drtm_dl_check_cores();
|
||||
|
@ -213,6 +374,11 @@ static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle)
|
|||
SMC_RET1(handle, ret);
|
||||
}
|
||||
|
||||
ret = drtm_dl_check_args(x1, &args);
|
||||
if (ret != SUCCESS) {
|
||||
SMC_RET1(handle, ret);
|
||||
}
|
||||
|
||||
SMC_RET1(handle, ret);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,10 +9,28 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <lib/smccc.h>
|
||||
|
||||
#include "drtm_dma_prot.h"
|
||||
|
||||
#define ALIGNED_UP(x, a) __extension__ ({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(a) _one = 1; \
|
||||
assert(IS_POWER_OF_TWO(_a)); \
|
||||
((x) + (_a - _one)) & ~(_a - _one); \
|
||||
})
|
||||
|
||||
#define ALIGNED_DOWN(x, a) __extension__ ({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(a) _one = 1; \
|
||||
assert(IS_POWER_OF_TWO(_a)); \
|
||||
(x) & ~(_a - _one); \
|
||||
})
|
||||
|
||||
#define DRTM_PAGE_SIZE (4 * (1 << 10))
|
||||
#define DRTM_PAGE_SIZE_STR "4-KiB"
|
||||
|
||||
enum drtm_retc {
|
||||
SUCCESS = SMC_OK,
|
||||
NOT_SUPPORTED = SMC_UNK,
|
||||
|
@ -31,7 +49,28 @@ typedef struct {
|
|||
uint64_t tcb_hash_features;
|
||||
} drtm_features_t;
|
||||
|
||||
struct __packed drtm_dl_args_v1 {
|
||||
uint16_t version; /* Must be 1. */
|
||||
uint8_t __res[2];
|
||||
uint32_t features;
|
||||
uint64_t dlme_paddr;
|
||||
uint64_t dlme_size;
|
||||
uint64_t dlme_img_off;
|
||||
uint64_t dlme_img_ep_off;
|
||||
uint64_t dlme_img_size;
|
||||
uint64_t dlme_data_off;
|
||||
uint64_t dce_nwd_paddr;
|
||||
uint64_t dce_nwd_size;
|
||||
drtm_dl_dma_prot_args_v1_t dma_prot_args;
|
||||
} __aligned(__alignof(uint16_t /* First member's type, `uint16_t version' */));
|
||||
|
||||
drtm_memory_region_descriptor_table_t *drtm_build_address_map(void);
|
||||
uint64_t drtm_get_address_map_size(void);
|
||||
|
||||
/*
|
||||
* Version-independent type. May be used to avoid excessive line of code
|
||||
* changes when migrating to new struct versions.
|
||||
*/
|
||||
typedef struct drtm_dl_args_v1 struct_drtm_dl_args;
|
||||
|
||||
#endif /* DRTM_MAIN_H */
|
||||
|
|
Loading…
Add table
Reference in a new issue