#define SPM_MAJOR_VERSION_FFA 1\r
#define SPM_MINOR_VERSION_FFA 0\r
\r
+#define ARM_FFA_SPM_RET_SUCCESS 0\r
+#define ARM_FFA_SPM_RET_NOT_SUPPORTED -1\r
+#define ARM_FFA_SPM_RET_INVALID_PARAMETERS -2\r
+#define ARM_FFA_SPM_RET_NO_MEMORY -3\r
+#define ARM_FFA_SPM_RET_BUSY -4\r
+#define ARM_FFA_SPM_RET_INTERRUPTED -5\r
+#define ARM_FFA_SPM_RET_DENIED -6\r
+#define ARM_FFA_SPM_RET_RETRY -7\r
+#define ARM_FFA_SPM_RET_ABORTED -8\r
+\r
+// For now, the destination id to be used in the FF-A calls\r
+// is being hard-coded. Subsequently, support will be added\r
+// to get the endpoint id's dynamically\r
+// This is the endpoint id used by the optee os's implementation\r
+// of the spmc.\r
+// https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/stmm_sp.c#L66\r
+#define ARM_FFA_DESTINATION_ENDPOINT_ID 3\r
+\r
#endif // ARM_FFA_SVC_H_\r
#include <Library/BaseLib.h>\r
#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
+#include <Library/PcdLib.h>\r
\r
STATIC\r
EFI_STATUS\r
OUT UINT32 *MemoryAttributes\r
)\r
{\r
+ INT32 Ret;\r
ARM_SVC_ARGS GetMemoryPermissionsSvcArgs;\r
+ BOOLEAN FfaEnabled;\r
\r
ZeroMem (&GetMemoryPermissionsSvcArgs, sizeof (ARM_SVC_ARGS));\r
\r
- GetMemoryPermissionsSvcArgs.Arg0 = ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH64;\r
- GetMemoryPermissionsSvcArgs.Arg1 = BaseAddress;\r
+ FfaEnabled = FeaturePcdGet (PcdFfaEnable);\r
+ if (FfaEnabled) {\r
+ GetMemoryPermissionsSvcArgs.Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH64;\r
+ GetMemoryPermissionsSvcArgs.Arg1 = ARM_FFA_DESTINATION_ENDPOINT_ID;\r
+ GetMemoryPermissionsSvcArgs.Arg2 = 0;\r
+ GetMemoryPermissionsSvcArgs.Arg3 = ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH64;\r
+ GetMemoryPermissionsSvcArgs.Arg4 = BaseAddress;\r
+ } else {\r
+ GetMemoryPermissionsSvcArgs.Arg0 = ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH64;\r
+ GetMemoryPermissionsSvcArgs.Arg1 = BaseAddress;\r
+ GetMemoryPermissionsSvcArgs.Arg2 = 0;\r
+ GetMemoryPermissionsSvcArgs.Arg3 = 0;\r
+ }\r
\r
+ *MemoryAttributes = 0;\r
ArmCallSvc (&GetMemoryPermissionsSvcArgs);\r
- if (GetMemoryPermissionsSvcArgs.Arg0 == ARM_SVC_SPM_RET_INVALID_PARAMS) {\r
- *MemoryAttributes = 0;\r
- return EFI_INVALID_PARAMETER;\r
+ if (FfaEnabled) {\r
+ // Getting memory attributes is an atomic call, with\r
+ // StandaloneMm at S-EL0 being the caller and the SPM\r
+ // core being the callee. Thus there won't be a\r
+ // FFA_INTERRUPT or FFA_SUCCESS response to the Direct\r
+ // Request sent above. This will have to be considered\r
+ // for other Direct Request calls which are not atomic\r
+ // We therefore check only for Direct Response by the\r
+ // callee.\r
+ if (GetMemoryPermissionsSvcArgs.Arg0 !=\r
+ ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64) {\r
+ // If Arg0 is not a Direct Response, that means we\r
+ // have an FF-A error. We need to check Arg2 for the\r
+ // FF-A error code.\r
+ Ret = GetMemoryPermissionsSvcArgs.Arg2;\r
+ switch (Ret) {\r
+ case ARM_FFA_SPM_RET_INVALID_PARAMETERS:\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+\r
+ case ARM_FFA_SPM_RET_DENIED:\r
+ return EFI_NOT_READY;\r
+\r
+ case ARM_FFA_SPM_RET_NOT_SUPPORTED:\r
+ return EFI_UNSUPPORTED;\r
+\r
+ case ARM_FFA_SPM_RET_BUSY:\r
+ return EFI_NOT_READY;\r
+\r
+ case ARM_FFA_SPM_RET_ABORTED:\r
+ return EFI_ABORTED;\r
+ }\r
+ } else if (GetMemoryPermissionsSvcArgs.Arg0 ==\r
+ ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64) {\r
+ // A Direct Response means FF-A success\r
+ // Now check the payload for errors\r
+ // The callee sends back the return value\r
+ // in Arg3\r
+ Ret = GetMemoryPermissionsSvcArgs.Arg3;\r
+ }\r
+ } else {\r
+ Ret = GetMemoryPermissionsSvcArgs.Arg0;\r
+ }\r
+\r
+ if (Ret & BIT31) {\r
+ // Bit 31 set means there is an error retured\r
+ switch (Ret) {\r
+ case ARM_SVC_SPM_RET_INVALID_PARAMS:\r
+ return EFI_INVALID_PARAMETER;\r
+\r
+ case ARM_SVC_SPM_RET_NOT_SUPPORTED:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ } else {\r
+ *MemoryAttributes = Ret;\r
}\r
\r
- *MemoryAttributes = GetMemoryPermissionsSvcArgs.Arg0;\r
return EFI_SUCCESS;\r
}\r
\r