blob: b11316457fc52bc172ac49a5a287474713ccc005 [file]
/*
* Copyright (c) 2026, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <common/smc_validation_framework.h>
#include <context.h>
#include <lib/el3_runtime/context_mgmt.h>
#include <lib/smccc.h>
#include <lib/utils_def.h>
#include <smccc_helpers.h>
int smc_get_arg(void *handle, unsigned int arg_idx, u_register_t *val)
{
#ifdef __aarch64__
static const uint16_t x_offsets[] = {
CTX_GPREG_X0, CTX_GPREG_X1, CTX_GPREG_X2, CTX_GPREG_X3,
CTX_GPREG_X4, CTX_GPREG_X5, CTX_GPREG_X6, CTX_GPREG_X7,
CTX_GPREG_X8, CTX_GPREG_X9, CTX_GPREG_X10, CTX_GPREG_X11,
CTX_GPREG_X12, CTX_GPREG_X13, CTX_GPREG_X14, CTX_GPREG_X15,
CTX_GPREG_X16, CTX_GPREG_X17
};
#else
static const uint16_t x_offsets[] = { CTX_GPREG_R0, CTX_GPREG_R1,
CTX_GPREG_R2, CTX_GPREG_R3 };
#endif
/* SMCCC registers are x1 to x17 (AArch64) or r1 to r7 (AArch32). */
if (arg_idx >= ARRAY_SIZE(x_offsets)) {
return SMC_INVALID_PARAM;
}
#ifdef __aarch64__
*val = (u_register_t)read_ctx_reg(get_gpregs_ctx(handle),
x_offsets[arg_idx]);
#else
*val = (u_register_t)read_ctx_reg(get_regs_ctx(handle),
x_offsets[arg_idx]);
#endif
return SMC_OK;
}
int smc_validate_mem_range(uintptr_t base, size_t size)
{
/* Reject if base + size overflows. */
if ((size > 0U) && check_uptr_overflow(base, (uintptr_t)size)) {
return SMC_INVALID_PARAM;
}
/* Reject if the range is not in Non-Secure memory. */
if (!plat_is_valid_ns_address_range(base, size)) {
return SMC_INVALID_PARAM;
}
return SMC_OK;
}
int smc_get_mem_range(void *handle, unsigned int base_reg,
unsigned int size_reg, uintptr_t *base, size_t *size)
{
u_register_t base_reg_val;
u_register_t size_reg_val;
if (smc_get_arg(handle, base_reg, &base_reg_val) != SMC_OK) {
return SMC_INVALID_PARAM;
}
if (smc_get_arg(handle, size_reg, &size_reg_val) != SMC_OK) {
return SMC_INVALID_PARAM;
}
uintptr_t base_local = (uintptr_t)base_reg_val;
size_t size_local = (size_t)size_reg_val;
if (smc_validate_mem_range(base_local, size_local) != SMC_OK) {
return SMC_INVALID_PARAM;
}
*base = base_local;
*size = size_local;
return SMC_OK;
}