summaryrefslogtreecommitdiff
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/std_svc/drtm/drtm_main.c7
-rw-r--r--services/std_svc/drtm/drtm_main.h6
-rw-r--r--services/std_svc/rmmd/trp/trp_entry.S34
-rw-r--r--services/std_svc/rmmd/trp/trp_main.c94
-rw-r--r--services/std_svc/rmmd/trp/trp_private.h4
-rw-r--r--services/std_svc/spm/el3_spmc/spmc.mk2
-rw-r--r--services/std_svc/spm/el3_spmc/spmc_shared_mem.c74
-rw-r--r--services/std_svc/std_svc_setup.c6
-rw-r--r--services/std_svc/trng/trng_entropy_pool.c29
-rw-r--r--services/std_svc/trng/trng_main.c21
10 files changed, 199 insertions, 78 deletions
diff --git a/services/std_svc/drtm/drtm_main.c b/services/std_svc/drtm/drtm_main.c
index e0f5c1784..3acf6838e 100644
--- a/services/std_svc/drtm/drtm_main.c
+++ b/services/std_svc/drtm/drtm_main.c
@@ -366,9 +366,10 @@ static enum drtm_retc drtm_dl_check_args(uint64_t x1,
}
a = &args_buf;
- if (a->version != 1) {
- ERROR("DRTM: parameters structure incompatible with major version %d\n",
- ARM_DRTM_VERSION_MAJOR);
+ if (!((a->version >= ARM_DRTM_PARAMS_MIN_VERSION) &&
+ (a->version <= ARM_DRTM_PARAMS_MAX_VERSION))) {
+ ERROR("DRTM: parameters structure version %u is unsupported\n",
+ a->version);
return NOT_SUPPORTED;
}
diff --git a/services/std_svc/drtm/drtm_main.h b/services/std_svc/drtm/drtm_main.h
index baa37ae7d..60051632e 100644
--- a/services/std_svc/drtm/drtm_main.h
+++ b/services/std_svc/drtm/drtm_main.h
@@ -36,6 +36,12 @@
#define DL_ARGS_GET_DLME_ENTRY_POINT(a) \
(((a)->dlme_paddr + (a)->dlme_img_off + (a)->dlme_img_ep_off))
+/*
+ * Range(Min/Max) of DRTM parameter structure versions supported
+ */
+#define ARM_DRTM_PARAMS_MIN_VERSION U(1)
+#define ARM_DRTM_PARAMS_MAX_VERSION U(1)
+
enum drtm_dlme_el {
DLME_AT_EL1 = MODE_EL1,
DLME_AT_EL2 = MODE_EL2
diff --git a/services/std_svc/rmmd/trp/trp_entry.S b/services/std_svc/rmmd/trp/trp_entry.S
index 47c1df14d..3e1d8c9d4 100644
--- a/services/std_svc/rmmd/trp/trp_entry.S
+++ b/services/std_svc/rmmd/trp/trp_entry.S
@@ -83,7 +83,17 @@ trp_head:
mov x3, x23
bl trp_setup
bl trp_main
+ b 1f
+
warm_boot:
+ mov x0, x20
+ mov x1, x21
+ mov x2, x22
+ mov x3, x23
+ bl trp_validate_warmboot_args
+ cbnz x0, trp_panic /* Failed to validate warmboot args */
+
+1:
mov_imm x0, RMM_BOOT_COMPLETE
mov x1, xzr /* RMM_BOOT_SUCCESS */
smc #0
@@ -115,7 +125,29 @@ endfunc trp_smc
* ---------------------------------------------
*/
func trp_handler
+ /*
+ * Save Link Register and X4, as per SMCCC v1.2 its value
+ * must be preserved unless it contains result, as specified
+ * in the function definition.
+ */
+ stp x4, lr, [sp, #-16]!
+
+ /*
+ * Zero the space for X0-X3 in trp_smc_result structure
+ * and pass its address as the last argument.
+ */
+ stp xzr, xzr, [sp, #-16]!
+ stp xzr, xzr, [sp, #-16]!
+ mov x7, sp
+
bl trp_rmi_handler
- restore_args_call_smc
+
+ ldp x1, x2, [sp], #16
+ ldp x3, x4, [sp], #16
+ ldp x5, lr, [sp], #16
+
+ ldr x0, =RMM_RMI_REQ_COMPLETE
+ smc #0
+
b trp_handler
endfunc trp_handler
diff --git a/services/std_svc/rmmd/trp/trp_main.c b/services/std_svc/rmmd/trp/trp_main.c
index 5a56af043..196bc119e 100644
--- a/services/std_svc/rmmd/trp/trp_main.c
+++ b/services/std_svc/rmmd/trp/trp_main.c
@@ -4,7 +4,6 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
-
#include <common/debug.h>
#include <plat/common/platform.h>
#include <services/rmm_core_manifest.h>
@@ -31,11 +30,11 @@ void trp_setup(uint64_t x0,
uint64_t x3)
{
/*
- * Validate boot parameters.
+ * Validate boot parameters
*
- * According to the Boot Interface ABI v.0.1, the
- * parameters recived from EL3 are:
- * x0: CPUID (verified earlier so not used)
+ * According to the Boot Interface ABI v.0.1,
+ * the parameters received from EL3 are:
+ * x0: CPUID (verified earlier, so not used)
* x1: Boot Interface version
* x2: PLATFORM_CORE_COUNT
* x3: Pointer to the shared memory area.
@@ -66,6 +65,24 @@ void trp_setup(uint64_t x0,
trp_early_platform_setup((rmm_manifest_t *)trp_shared_region_start);
}
+int trp_validate_warmboot_args(uint64_t x0, uint64_t x1,
+ uint64_t x2, uint64_t x3)
+{
+ /*
+ * Validate boot parameters for warm boot
+ *
+ * According to the Boot Interface ABI v.0.1, the parameters
+ * received from EL3 during warm boot are:
+ *
+ * x0: CPUID (verified earlier so not used here)
+ * [x1:x3]: RES0
+ */
+
+ (void)x0;
+
+ return ((x1 | x2 | x3) == 0UL) ? 0 : E_RMM_BOOT_UNKNOWN;
+}
+
/* Main function for TRP */
void trp_main(void)
{
@@ -73,14 +90,14 @@ void trp_main(void)
NOTICE("TRP: %s\n", build_message);
NOTICE("TRP: Supported RMM-EL3 Interface ABI: v.%u.%u\n",
TRP_RMM_EL3_ABI_VERS_MAJOR, TRP_RMM_EL3_ABI_VERS_MINOR);
- NOTICE("TRP: Boot Manifest Version : v.%u.%u\n",
+ NOTICE("TRP: Boot Manifest Version: v.%u.%u\n",
RMMD_GET_MANIFEST_VERSION_MAJOR(trp_boot_manifest_version),
RMMD_GET_MANIFEST_VERSION_MINOR(trp_boot_manifest_version));
- INFO("TRP: Memory base : 0x%lx\n", (unsigned long)RMM_BASE);
- INFO("TRP: Base address for the shared region : 0x%lx\n",
+ INFO("TRP: Memory base: 0x%lx\n", (unsigned long)RMM_BASE);
+ INFO("TRP: Shared region base address: 0x%lx\n",
(unsigned long)trp_shared_region_start);
- INFO("TRP: Total size : 0x%lx bytes\n", (unsigned long)(RMM_END
- - RMM_BASE));
+ INFO("TRP: Total size: 0x%lx bytes\n",
+ (unsigned long)(RMM_END - RMM_BASE));
INFO("TRP: RMM-EL3 Interface ABI reported by EL3: v.%u.%u\n",
TRP_RMM_EL3_VERSION_GET_MAJOR(trp_boot_abi_version),
TRP_RMM_EL3_VERSION_GET_MINOR(trp_boot_abi_version));
@@ -89,62 +106,73 @@ void trp_main(void)
/*******************************************************************************
* Returning RMI version back to Normal World
******************************************************************************/
-static trp_args_t *trp_ret_rmi_version(void)
+static void trp_ret_rmi_version(struct trp_smc_result *smc_ret)
{
VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR,
RMI_ABI_VERSION_MINOR);
- return set_smc_args(RMM_RMI_REQ_COMPLETE, RMI_ABI_VERSION,
- 0, 0, 0, 0, 0, 0);
+ smc_ret->x[0] = RMI_ABI_VERSION;
}
/*******************************************************************************
* Transitioning granule of NON-SECURE type to REALM type
******************************************************************************/
-static trp_args_t *trp_asc_mark_realm(unsigned long long x1)
+static void trp_asc_mark_realm(unsigned long long x1,
+ struct trp_smc_result *smc_ret)
{
- unsigned long long ret;
-
VERBOSE("Delegating granule 0x%llx\n", x1);
- ret = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1, 0, 0, 0, 0, 0, 0));
+ smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_DELEGATE, x1,
+ 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
- if (ret != 0ULL) {
+ if (smc_ret->x[0] != 0ULL) {
ERROR("Granule transition from NON-SECURE type to REALM type "
- "failed 0x%llx\n", ret);
+ "failed 0x%llx\n", smc_ret->x[0]);
}
- return set_smc_args(RMM_RMI_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0);
}
/*******************************************************************************
* Transitioning granule of REALM type to NON-SECURE type
******************************************************************************/
-static trp_args_t *trp_asc_mark_nonsecure(unsigned long long x1)
+static void trp_asc_mark_nonsecure(unsigned long long x1,
+ struct trp_smc_result *smc_ret)
{
- unsigned long long ret;
-
VERBOSE("Undelegating granule 0x%llx\n", x1);
- ret = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1, 0, 0, 0, 0, 0, 0));
+ smc_ret->x[0] = trp_smc(set_smc_args(RMM_GTSI_UNDELEGATE, x1,
+ 0UL, 0UL, 0UL, 0UL, 0UL, 0UL));
- if (ret != 0ULL) {
+ if (smc_ret->x[0] != 0ULL) {
ERROR("Granule transition from REALM type to NON-SECURE type "
- "failed 0x%llx\n", ret);
+ "failed 0x%llx\n", smc_ret->x[0]);
}
- return set_smc_args(RMM_RMI_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0);
}
/*******************************************************************************
* Main RMI SMC handler function
******************************************************************************/
-trp_args_t *trp_rmi_handler(unsigned long fid, unsigned long long x1)
+void trp_rmi_handler(unsigned long fid,
+ unsigned long long x1, unsigned long long x2,
+ unsigned long long x3, unsigned long long x4,
+ unsigned long long x5, unsigned long long x6,
+ struct trp_smc_result *smc_ret)
{
+ /* Not used in the current implementation */
+ (void)x2;
+ (void)x3;
+ (void)x4;
+ (void)x5;
+ (void)x6;
+
switch (fid) {
case RMI_RMM_REQ_VERSION:
- return trp_ret_rmi_version();
+ trp_ret_rmi_version(smc_ret);
+ break;
case RMI_RMM_GRANULE_DELEGATE:
- return trp_asc_mark_realm(x1);
+ trp_asc_mark_realm(x1, smc_ret);
+ break;
case RMI_RMM_GRANULE_UNDELEGATE:
- return trp_asc_mark_nonsecure(x1);
+ trp_asc_mark_nonsecure(x1, smc_ret);
+ break;
default:
- ERROR("Invalid SMC code to %s, FID %lu\n", __func__, fid);
+ ERROR("Invalid SMC code to %s, FID %lx\n", __func__, fid);
+ smc_ret->x[0] = SMC_UNK;
}
- return set_smc_args(SMC_UNK, 0, 0, 0, 0, 0, 0, 0);
}
diff --git a/services/std_svc/rmmd/trp/trp_private.h b/services/std_svc/rmmd/trp/trp_private.h
index 945ae1c89..d8c69603b 100644
--- a/services/std_svc/rmmd/trp/trp_private.h
+++ b/services/std_svc/rmmd/trp/trp_private.h
@@ -53,5 +53,9 @@ void trp_setup(uint64_t x0,
uint64_t x2,
uint64_t x3);
+/* Validate arguments for warm boot only */
+int trp_validate_warmboot_args(uint64_t x0, uint64_t x1,
+ uint64_t x2, uint64_t x3);
+
#endif /* __ASSEMBLER__ */
#endif /* TRP_PRIVATE_H */
diff --git a/services/std_svc/spm/el3_spmc/spmc.mk b/services/std_svc/spm/el3_spmc/spmc.mk
index c674e7161..6442af049 100644
--- a/services/std_svc/spm/el3_spmc/spmc.mk
+++ b/services/std_svc/spm/el3_spmc/spmc.mk
@@ -20,7 +20,9 @@ SPMC_LP_SOURCES := $(addprefix ${PLAT_DIR}/, \
${PLAT}_el3_spmc_logical_sp.c)
+ifneq ($(wildcard $(SPMC_LP_SOURCES)),)
SPMC_SOURCES += $(SPMC_LP_SOURCES)
+endif
# Let the top-level Makefile know that we intend to include a BL32 image
NEED_BL32 := yes
diff --git a/services/std_svc/spm/el3_spmc/spmc_shared_mem.c b/services/std_svc/spm/el3_spmc/spmc_shared_mem.c
index 1da2efc14..c039350a3 100644
--- a/services/std_svc/spm/el3_spmc/spmc_shared_mem.c
+++ b/services/std_svc/spm/el3_spmc/spmc_shared_mem.c
@@ -72,13 +72,23 @@ spmc_shmem_obj_alloc(struct spmc_shmem_obj_state *state, size_t desc_size)
{
struct spmc_shmem_obj *obj;
size_t free = state->data_size - state->allocated;
+ size_t obj_size;
if (state->data == NULL) {
ERROR("Missing shmem datastore!\n");
return NULL;
}
- if (spmc_shmem_obj_size(desc_size) > free) {
+ obj_size = spmc_shmem_obj_size(desc_size);
+
+ /* Ensure the obj size has not overflowed. */
+ if (obj_size < desc_size) {
+ WARN("%s(0x%zx) desc_size overflow\n",
+ __func__, desc_size);
+ return NULL;
+ }
+
+ if (obj_size > free) {
WARN("%s(0x%zx) failed, free 0x%zx\n",
__func__, desc_size, free);
return NULL;
@@ -88,7 +98,7 @@ spmc_shmem_obj_alloc(struct spmc_shmem_obj_state *state, size_t desc_size)
obj->desc_size = desc_size;
obj->desc_filled = 0;
obj->in_use = 0;
- state->allocated += spmc_shmem_obj_size(desc_size);
+ state->allocated += obj_size;
return obj;
}
@@ -264,13 +274,15 @@ spmc_shmem_obj_ffa_constituent_size(struct spmc_shmem_obj *obj,
* spmc_shmem_obj_validate_id - Validate a partition ID is participating in
* a given memory transaction.
* @sp_id: Partition ID to validate.
- * @desc: Descriptor of the memory transaction.
- *
+ * @obj: The shared memory object containing the descriptor
+ * of the memory transaction.
* Return: true if ID is valid, else false.
*/
-bool spmc_shmem_obj_validate_id(const struct ffa_mtd *desc, uint16_t sp_id)
+bool spmc_shmem_obj_validate_id(struct spmc_shmem_obj *obj, uint16_t sp_id)
{
bool found = false;
+ struct ffa_mtd *desc = &obj->desc;
+ size_t desc_size = obj->desc_size;
/* Validate the partition is a valid participant. */
for (unsigned int i = 0U; i < desc->emad_count; i++) {
@@ -280,6 +292,15 @@ bool spmc_shmem_obj_validate_id(const struct ffa_mtd *desc, uint16_t sp_id)
emad = spmc_shmem_obj_get_emad(desc, i,
MAKE_FFA_VERSION(1, 1),
&emad_size);
+ /*
+ * Validate the calculated emad address resides within the
+ * descriptor.
+ */
+ if ((emad == NULL) || (uintptr_t) emad >=
+ (uintptr_t)((uint8_t *) desc + desc_size)) {
+ VERBOSE("Invalid emad.\n");
+ break;
+ }
if (sp_id == emad->mapd.endpoint_id) {
found = true;
break;
@@ -330,10 +351,9 @@ overlapping_memory_regions(struct ffa_comp_mrd *region1,
PAGE_SIZE_4KB;
region2_end = region2_start + region2_size;
- if ((region1_start >= region2_start &&
- region1_start < region2_end) ||
- (region1_end > region2_start
- && region1_end < region2_end)) {
+ /* Check if regions are not overlapping. */
+ if (!((region2_end <= region1_start) ||
+ (region1_end <= region2_start))) {
WARN("Overlapping mem regions 0x%lx-0x%lx & 0x%lx-0x%lx\n",
region1_start, region1_end,
region2_start, region2_end);
@@ -376,7 +396,8 @@ spmc_shm_get_v1_1_descriptor_size(struct ffa_mtd_v1_0 *orig, size_t desc_size)
emad_array[0].comp_mrd_offset);
/* Check the calculated address is within the memory descriptor. */
- if ((uintptr_t) mrd >= (uintptr_t)((uint8_t *) orig + desc_size)) {
+ if (((uintptr_t) mrd + sizeof(struct ffa_comp_mrd)) >
+ (uintptr_t)((uint8_t *) orig + desc_size)) {
return 0;
}
size += mrd->address_range_count * sizeof(struct ffa_cons_mrd);
@@ -415,7 +436,8 @@ spmc_shm_get_v1_0_descriptor_size(struct ffa_mtd *orig, size_t desc_size)
emad_array[0].comp_mrd_offset);
/* Check the calculated address is within the memory descriptor. */
- if ((uintptr_t) mrd >= (uintptr_t)((uint8_t *) orig + desc_size)) {
+ if (((uintptr_t) mrd + sizeof(struct ffa_comp_mrd)) >
+ (uintptr_t)((uint8_t *) orig + desc_size)) {
return 0;
}
size += mrd->address_range_count * sizeof(struct ffa_cons_mrd);
@@ -466,6 +488,12 @@ spmc_shm_convert_shmem_obj_from_v1_0(struct spmc_shmem_obj *out_obj,
/* Copy across the emad structs. */
for (unsigned int i = 0U; i < out->emad_count; i++) {
+ /* Bound check for emad array. */
+ if (((uint8_t *)emad_array_in + sizeof(struct ffa_emad_v1_0)) >
+ ((uint8_t *) mtd_orig + orig->desc_size)) {
+ VERBOSE("%s: Invalid mtd structure.\n", __func__);
+ return false;
+ }
memcpy(&emad_array_out[i], &emad_array_in[i],
sizeof(struct ffa_emad_v1_0));
}
@@ -533,6 +561,7 @@ spmc_shm_convert_mtd_to_v1_0(struct spmc_shmem_obj *out_obj,
size_t mrd_out_offset;
size_t emad_out_array_size;
size_t mrd_size = 0;
+ size_t orig_desc_size = orig->desc_size;
/* Populate the v1.0 descriptor format from the v1.1 struct. */
out->sender_id = mtd_orig->sender_id;
@@ -550,6 +579,12 @@ spmc_shm_convert_mtd_to_v1_0(struct spmc_shmem_obj *out_obj,
/* Copy across the emad structs. */
emad_in = emad_array_in;
for (unsigned int i = 0U; i < out->emad_count; i++) {
+ /* Bound check for emad array. */
+ if (((uint8_t *)emad_in + sizeof(struct ffa_emad_v1_0)) >
+ ((uint8_t *) mtd_orig + orig_desc_size)) {
+ VERBOSE("%s: Invalid mtd structure.\n", __func__);
+ return false;
+ }
memcpy(&emad_array_out[i], emad_in,
sizeof(struct ffa_emad_v1_0));
@@ -886,9 +921,6 @@ static long spmc_ffa_fill_desc(struct mailbox *mbox,
goto err_arg;
}
- memcpy((uint8_t *)&obj->desc + obj->desc_filled,
- (uint8_t *) mbox->tx_buffer, fragment_length);
-
if (fragment_length > obj->desc_size - obj->desc_filled) {
WARN("%s: bad fragment size %u > %zu remaining\n", __func__,
fragment_length, obj->desc_size - obj->desc_filled);
@@ -896,6 +928,9 @@ static long spmc_ffa_fill_desc(struct mailbox *mbox,
goto err_arg;
}
+ memcpy((uint8_t *)&obj->desc + obj->desc_filled,
+ (uint8_t *) mbox->tx_buffer, fragment_length);
+
/* Ensure that the sender ID resides in the normal world. */
if (ffa_is_secure_world_id(obj->desc.sender_id)) {
WARN("%s: Invalid sender ID 0x%x.\n",
@@ -1433,7 +1468,7 @@ spmc_ffa_mem_retrieve_req(uint32_t smc_fid,
}
/* Validate the caller is a valid participant. */
- if (!spmc_shmem_obj_validate_id(&obj->desc, sp_ctx->sp_id)) {
+ if (!spmc_shmem_obj_validate_id(obj, sp_ctx->sp_id)) {
WARN("%s: Invalid endpoint ID (0x%x).\n",
__func__, sp_ctx->sp_id);
ret = FFA_ERROR_INVALID_PARAMETER;
@@ -1752,7 +1787,7 @@ int spmc_ffa_mem_relinquish(uint32_t smc_fid,
}
/* Validate the caller is a valid participant. */
- if (!spmc_shmem_obj_validate_id(&obj->desc, sp_ctx->sp_id)) {
+ if (!spmc_shmem_obj_validate_id(obj, sp_ctx->sp_id)) {
WARN("%s: Invalid endpoint ID (0x%x).\n",
__func__, req->endpoint_array[0]);
ret = FFA_ERROR_INVALID_PARAMETER;
@@ -1828,6 +1863,13 @@ int spmc_ffa_mem_reclaim(uint32_t smc_fid,
goto err_unlock;
}
+ if (obj->desc_filled != obj->desc_size) {
+ WARN("%s: incomplete object desc filled %zu < size %zu\n",
+ __func__, obj->desc_filled, obj->desc_size);
+ ret = FFA_ERROR_INVALID_PARAMETER;
+ goto err_unlock;
+ }
+
/* Allow for platform specific operations to be performed. */
ret = plat_spmc_shmem_reclaim(&obj->desc);
if (ret != 0) {
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
index 08d16e21a..2884a3b9e 100644
--- a/services/std_svc/std_svc_setup.c
+++ b/services/std_svc/std_svc_setup.c
@@ -74,7 +74,10 @@ static int32_t std_svc_setup(void)
sdei_init();
#endif
+#if TRNG_SUPPORT
+ /* TRNG initialisation */
trng_setup();
+#endif /* TRNG_SUPPORT */
#if DRTM_SUPPORT
if (drtm_setup() != 0) {
@@ -172,7 +175,8 @@ static uintptr_t std_svc_smc_handler(uint32_t smc_fid,
return trng_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle,
flags);
}
-#endif
+#endif /* TRNG_SUPPORT */
+
#if ENABLE_RME
if (is_rmmd_el3_fid(smc_fid)) {
diff --git a/services/std_svc/trng/trng_entropy_pool.c b/services/std_svc/trng/trng_entropy_pool.c
index ac13b1d7a..30105b3a3 100644
--- a/services/std_svc/trng/trng_entropy_pool.c
+++ b/services/std_svc/trng/trng_entropy_pool.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, ARM Limited. All rights reserved.
+ * Copyright (c) 2021-2022, ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,7 +18,7 @@
* 192 bits of entropy, we don't have to throw out the leftover 1-63 bits of
* entropy.
*/
-#define WORDS_IN_POOL (4)
+#define WORDS_IN_POOL (4)
static uint64_t entropy[WORDS_IN_POOL];
/* index in bits of the first bit of usable entropy */
static uint32_t entropy_bit_index;
@@ -27,14 +27,14 @@ static uint32_t entropy_bit_size;
static spinlock_t trng_pool_lock;
-#define BITS_PER_WORD (sizeof(entropy[0]) * 8)
-#define BITS_IN_POOL (WORDS_IN_POOL * BITS_PER_WORD)
-#define ENTROPY_MIN_WORD (entropy_bit_index / BITS_PER_WORD)
-#define ENTROPY_FREE_BIT (entropy_bit_size + entropy_bit_index)
-#define _ENTROPY_FREE_WORD (ENTROPY_FREE_BIT / BITS_PER_WORD)
-#define ENTROPY_FREE_INDEX (_ENTROPY_FREE_WORD % WORDS_IN_POOL)
+#define BITS_PER_WORD (sizeof(entropy[0]) * 8)
+#define BITS_IN_POOL (WORDS_IN_POOL * BITS_PER_WORD)
+#define ENTROPY_MIN_WORD (entropy_bit_index / BITS_PER_WORD)
+#define ENTROPY_FREE_BIT (entropy_bit_size + entropy_bit_index)
+#define _ENTROPY_FREE_WORD (ENTROPY_FREE_BIT / BITS_PER_WORD)
+#define ENTROPY_FREE_INDEX (_ENTROPY_FREE_WORD % WORDS_IN_POOL)
/* ENTROPY_WORD_INDEX(0) includes leftover bits in the lower bits */
-#define ENTROPY_WORD_INDEX(i) ((ENTROPY_MIN_WORD + i) % WORDS_IN_POOL)
+#define ENTROPY_WORD_INDEX(i) ((ENTROPY_MIN_WORD + i) % WORDS_IN_POOL)
/*
* Fill the entropy pool until we have at least as many bits as requested.
@@ -65,12 +65,12 @@ static bool trng_fill_entropy(uint32_t nbits)
*/
bool trng_pack_entropy(uint32_t nbits, uint64_t *out)
{
- bool success = true;
+ bool ret = true;
spin_lock(&trng_pool_lock);
if (!trng_fill_entropy(nbits)) {
- success = false;
+ ret = false;
goto out;
}
@@ -82,9 +82,8 @@ bool trng_pack_entropy(uint32_t nbits, uint64_t *out)
for (word_i = 0; word_i < to_fill; word_i++) {
/*
* Repack the entropy from the pool into the passed in out
- * buffer. This takes the lower bits from the valid upper bits
- * of word_i and the upper bits from the lower bits of
- * (word_i + 1).
+ * buffer. This takes lesser bits from the valid upper bits
+ * of word_i and more bits from the lower bits of (word_i + 1).
*
* I found the following diagram useful. note: `e` represents
* valid entropy, ` ` represents invalid bits (not entropy) and
@@ -136,7 +135,7 @@ bool trng_pack_entropy(uint32_t nbits, uint64_t *out)
out:
spin_unlock(&trng_pool_lock);
- return success;
+ return ret;
}
void trng_entropy_pool_setup(void)
diff --git a/services/std_svc/trng/trng_main.c b/services/std_svc/trng/trng_main.c
index 38aa64997..90098a8f2 100644
--- a/services/std_svc/trng/trng_main.c
+++ b/services/std_svc/trng/trng_main.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -23,9 +23,9 @@ static const uuid_t uuid_null;
static uintptr_t trng_rnd32(uint32_t nbits, void *handle)
{
uint32_t mask = ~0U;
- uint64_t ent[2];
+ uint64_t ent[2] = {0};
- if (nbits == 0U || nbits > 96U) {
+ if (nbits == 0U || nbits > TRNG_RND32_ENTROPY_MAXBITS) {
SMC_RET1(handle, TRNG_E_INVALID_PARAMS);
}
@@ -59,9 +59,9 @@ static uintptr_t trng_rnd32(uint32_t nbits, void *handle)
static uintptr_t trng_rnd64(uint32_t nbits, void *handle)
{
uint64_t mask = ~0ULL;
- uint64_t ent[3];
+ uint64_t ent[3] = {0};
- if (nbits == 0U || nbits > 192U) {
+ if (nbits == 0U || nbits > TRNG_RND64_ENTROPY_MAXBITS) {
SMC_RET1(handle, TRNG_E_INVALID_PARAMS);
}
@@ -117,9 +117,9 @@ uintptr_t trng_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
switch (smc_fid) {
case ARM_TRNG_VERSION:
SMC_RET1(handle, MAKE_SMCCC_VERSION(
- TRNG_VERSION_MAJOR, TRNG_VERSION_MINOR
- ));
+ TRNG_VERSION_MAJOR, TRNG_VERSION_MINOR));
break; /* unreachable */
+
case ARM_TRNG_FEATURES:
if (is_trng_fid((uint32_t)x1)) {
SMC_RET1(handle, TRNG_E_SUCCESS);
@@ -127,16 +127,19 @@ uintptr_t trng_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
SMC_RET1(handle, TRNG_E_NOT_SUPPORTED);
}
break; /* unreachable */
+
case ARM_TRNG_GET_UUID:
SMC_UUID_RET(handle, plat_trng_uuid);
break; /* unreachable */
+
case ARM_TRNG_RND32:
return trng_rnd32((uint32_t)x1, handle);
+
case ARM_TRNG_RND64:
return trng_rnd64((uint32_t)x1, handle);
+
default:
- WARN("Unimplemented TRNG Service Call: 0x%x\n",
- smc_fid);
+ WARN("Unimplemented TRNG Service Call: 0x%x\n", smc_fid);
SMC_RET1(handle, TRNG_E_NOT_IMPLEMENTED);
break; /* unreachable */
}