diff --git a/include/services/ffa_svc.h b/include/services/ffa_svc.h index fe32175..7285077 100644 --- a/include/services/ffa_svc.h +++ b/include/services/ffa_svc.h @@ -12,13 +12,13 @@ #include /* FFA error codes. */ -#define FFA_ERROR_NOT_SUPPORTED -1 +#define FFA_ERROR_NOT_SUPPORTED -1 #define FFA_ERROR_INVALID_PARAMETER -2 #define FFA_ERROR_NO_MEMORY -3 #define FFA_ERROR_BUSY -4 #define FFA_ERROR_INTERRUPTED -5 #define FFA_ERROR_DENIED -6 -#define FFA_ERROR_RETRY -7 +#define FFA_ERROR_RETRY -7 /* The macros below are used to identify FFA calls from the SMC function ID */ #define FFA_FNUM_MIN_VALUE U(0x60) @@ -30,13 +30,15 @@ /* FFA_VERSION helpers */ #define FFA_VERSION_MAJOR U(1) -#define FFA_VERSION_MAJOR_SHIFT 16 +#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_SHIFT 0 #define FFA_VERSION_MINOR_MASK U(0xFFFF) +#define FFA_VERSION_BIT31_MASK U(0x1u << 31) -#define MAKE_FFA_VERSION(major, minor) \ + +#define MAKE_FFA_VERSION(major, minor) \ ((((major) & FFA_VERSION_MAJOR_MASK) << FFA_VERSION_MAJOR_SHIFT) | \ (((minor) & FFA_VERSION_MINOR_MASK) << FFA_VERSION_MINOR_SHIFT)) #define FFA_VERSION_COMPILED MAKE_FFA_VERSION(FFA_VERSION_MAJOR, \ diff --git a/services/std_svc/spmd/spmd_main.c b/services/std_svc/spmd/spmd_main.c index a818037..4c2b58d 100644 --- a/services/std_svc/spmd/spmd_main.c +++ b/services/std_svc/spmd/spmd_main.c @@ -350,6 +350,7 @@ spmd_spm_core_context_t *ctx = spmd_get_context(); bool secure_origin; int32_t ret; + uint32_t input_version; /* Determine which security state this SMC originated from */ secure_origin = is_caller_secure(flags); @@ -375,15 +376,24 @@ break; /* not reached */ case FFA_VERSION: + input_version = (uint32_t)(0xFFFFFFFF & x1); /* - * TODO: This is an optimization that the version information - * provided by the SPM Core manifest is returned by the SPM - * dispatcher. It might be a better idea to simply forward this - * call to the SPM Core and wash our hands completely. + * If caller is secure and SPMC was initialized, + * return FFA_VERSION of SPMD. + * If caller is non secure and SPMC was initialized, + * return SPMC's version. + * Sanity check to "input_version". */ - ret = MAKE_FFA_VERSION(spmc_attrs.major_version, - spmc_attrs.minor_version); - SMC_RET8(handle, FFA_SUCCESS_SMC32, FFA_TARGET_INFO_MBZ, ret, + if ((input_version & FFA_VERSION_BIT31_MASK) || + (ctx->state == SPMC_STATE_RESET)) { + ret = FFA_ERROR_NOT_SUPPORTED; + } else if (!secure_origin) { + ret = MAKE_FFA_VERSION(spmc_attrs.major_version, spmc_attrs.minor_version); + } else { + ret = MAKE_FFA_VERSION(FFA_VERSION_MAJOR, FFA_VERSION_MINOR); + } + + SMC_RET8(handle, ret, FFA_TARGET_INFO_MBZ, FFA_TARGET_INFO_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); break; /* not reached */