EventHandle.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /** @file
  2. Copyright (c) 2016 HP Development Company, L.P.
  3. Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.
  4. Copyright (c) 2021, Linaro Limited
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include <Base.h>
  8. #include <Pi/PiMmCis.h>
  9. #include <Library/ArmSvcLib.h>
  10. #include <Library/ArmLib.h>
  11. #include <Library/BaseMemoryLib.h>
  12. #include <Library/DebugLib.h>
  13. #include <Library/HobLib.h>
  14. #include <Protocol/DebugSupport.h> // for EFI_SYSTEM_CONTEXT
  15. #include <Guid/ZeroGuid.h>
  16. #include <Guid/MmramMemoryReserve.h>
  17. #include <IndustryStandard/ArmFfaSvc.h>
  18. #include <IndustryStandard/ArmStdSmc.h>
  19. #include "StandaloneMmCpu.h"
  20. EFI_STATUS
  21. EFIAPI
  22. MmFoundationEntryRegister (
  23. IN CONST EFI_MM_CONFIGURATION_PROTOCOL *This,
  24. IN EFI_MM_ENTRY_POINT MmEntryPoint
  25. );
  26. //
  27. // On ARM platforms every event is expected to have a GUID associated with
  28. // it. It will be used by the MM Entry point to find the handler for the
  29. // event. It will either be populated in a EFI_MM_COMMUNICATE_HEADER by the
  30. // caller of the event (e.g. MM_COMMUNICATE SMC) or by the CPU driver
  31. // (e.g. during an asynchronous event). In either case, this context is
  32. // maintained in an array which has an entry for each CPU. The pointer to this
  33. // array is held in PerCpuGuidedEventContext. Memory is allocated once the
  34. // number of CPUs in the system are made known through the
  35. // MP_INFORMATION_HOB_DATA.
  36. //
  37. EFI_MM_COMMUNICATE_HEADER **PerCpuGuidedEventContext = NULL;
  38. // Descriptor with whereabouts of memory used for communication with the normal world
  39. EFI_MMRAM_DESCRIPTOR mNsCommBuffer;
  40. MP_INFORMATION_HOB_DATA *mMpInformationHobData;
  41. EFI_MM_CONFIGURATION_PROTOCOL mMmConfig = {
  42. 0,
  43. MmFoundationEntryRegister
  44. };
  45. STATIC EFI_MM_ENTRY_POINT mMmEntryPoint = NULL;
  46. /**
  47. The PI Standalone MM entry point for the TF-A CPU driver.
  48. @param [in] EventId The event Id.
  49. @param [in] CpuNumber The CPU number.
  50. @param [in] NsCommBufferAddr Address of the NS common buffer.
  51. @retval EFI_SUCCESS Success.
  52. @retval EFI_INVALID_PARAMETER A parameter was invalid.
  53. @retval EFI_ACCESS_DENIED Access not permitted.
  54. @retval EFI_OUT_OF_RESOURCES Out of resources.
  55. @retval EFI_UNSUPPORTED Operation not supported.
  56. **/
  57. EFI_STATUS
  58. PiMmStandaloneArmTfCpuDriverEntry (
  59. IN UINTN EventId,
  60. IN UINTN CpuNumber,
  61. IN UINTN NsCommBufferAddr
  62. )
  63. {
  64. EFI_MM_COMMUNICATE_HEADER *GuidedEventContext;
  65. EFI_MM_ENTRY_CONTEXT MmEntryPointContext;
  66. EFI_STATUS Status;
  67. UINTN NsCommBufferSize;
  68. DEBUG ((DEBUG_INFO, "Received event - 0x%x on cpu %d\n", EventId, CpuNumber));
  69. Status = EFI_SUCCESS;
  70. //
  71. // ARM TF passes SMC FID of the MM_COMMUNICATE interface as the Event ID upon
  72. // receipt of a synchronous MM request. Use the Event ID to distinguish
  73. // between synchronous and asynchronous events.
  74. //
  75. if ((ARM_SMC_ID_MM_COMMUNICATE != EventId) &&
  76. (ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ != EventId)) {
  77. DEBUG ((DEBUG_INFO, "UnRecognized Event - 0x%x\n", EventId));
  78. return EFI_INVALID_PARAMETER;
  79. }
  80. // Perform parameter validation of NsCommBufferAddr
  81. if (NsCommBufferAddr == (UINTN)NULL) {
  82. return EFI_INVALID_PARAMETER;
  83. }
  84. if (NsCommBufferAddr < mNsCommBuffer.PhysicalStart) {
  85. return EFI_ACCESS_DENIED;
  86. }
  87. if ((NsCommBufferAddr + sizeof (EFI_MM_COMMUNICATE_HEADER)) >=
  88. (mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize)) {
  89. return EFI_INVALID_PARAMETER;
  90. }
  91. // Find out the size of the buffer passed
  92. NsCommBufferSize = ((EFI_MM_COMMUNICATE_HEADER *) NsCommBufferAddr)->MessageLength +
  93. sizeof (EFI_MM_COMMUNICATE_HEADER);
  94. // perform bounds check.
  95. if (NsCommBufferAddr + NsCommBufferSize >=
  96. mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize) {
  97. return EFI_ACCESS_DENIED;
  98. }
  99. GuidedEventContext = NULL;
  100. // Now that the secure world can see the normal world buffer, allocate
  101. // memory to copy the communication buffer to the secure world.
  102. Status = mMmst->MmAllocatePool (
  103. EfiRuntimeServicesData,
  104. NsCommBufferSize,
  105. (VOID **) &GuidedEventContext
  106. );
  107. if (Status != EFI_SUCCESS) {
  108. DEBUG ((DEBUG_INFO, "Mem alloc failed - 0x%x\n", EventId));
  109. return EFI_OUT_OF_RESOURCES;
  110. }
  111. // X1 contains the VA of the normal world memory accessible from
  112. // S-EL0
  113. CopyMem (GuidedEventContext, (CONST VOID *) NsCommBufferAddr, NsCommBufferSize);
  114. // Stash the pointer to the allocated Event Context for this CPU
  115. PerCpuGuidedEventContext[CpuNumber] = GuidedEventContext;
  116. ZeroMem (&MmEntryPointContext, sizeof (EFI_MM_ENTRY_CONTEXT));
  117. MmEntryPointContext.CurrentlyExecutingCpu = CpuNumber;
  118. MmEntryPointContext.NumberOfCpus = mMpInformationHobData->NumberOfProcessors;
  119. // Populate the MM system table with MP and state information
  120. mMmst->CurrentlyExecutingCpu = CpuNumber;
  121. mMmst->NumberOfCpus = mMpInformationHobData->NumberOfProcessors;
  122. mMmst->CpuSaveStateSize = 0;
  123. mMmst->CpuSaveState = NULL;
  124. if (mMmEntryPoint == NULL) {
  125. DEBUG ((DEBUG_INFO, "Mm Entry point Not Found\n"));
  126. return EFI_UNSUPPORTED;
  127. }
  128. mMmEntryPoint (&MmEntryPointContext);
  129. // Free the memory allocation done earlier and reset the per-cpu context
  130. ASSERT (GuidedEventContext);
  131. CopyMem ((VOID *)NsCommBufferAddr, (CONST VOID *) GuidedEventContext, NsCommBufferSize);
  132. Status = mMmst->MmFreePool ((VOID *) GuidedEventContext);
  133. if (Status != EFI_SUCCESS) {
  134. return EFI_OUT_OF_RESOURCES;
  135. }
  136. PerCpuGuidedEventContext[CpuNumber] = NULL;
  137. return Status;
  138. }
  139. /**
  140. Registers the MM foundation entry point.
  141. @param [in] This Pointer to the MM Configuration protocol.
  142. @param [in] MmEntryPoint Function pointer to the MM Entry point.
  143. @retval EFI_SUCCESS Success.
  144. **/
  145. EFI_STATUS
  146. EFIAPI
  147. MmFoundationEntryRegister (
  148. IN CONST EFI_MM_CONFIGURATION_PROTOCOL *This,
  149. IN EFI_MM_ENTRY_POINT MmEntryPoint
  150. )
  151. {
  152. // store the entry point in a global
  153. mMmEntryPoint = MmEntryPoint;
  154. return EFI_SUCCESS;
  155. }
  156. /**
  157. This function is the main entry point for an MM handler dispatch
  158. or communicate-based callback.
  159. @param DispatchHandle The unique handle assigned to this handler by
  160. MmiHandlerRegister().
  161. @param Context Points to an optional handler context which was
  162. specified when the handler was registered.
  163. @param CommBuffer A pointer to a collection of data in memory that will
  164. be conveyed from a non-MM environment into an
  165. MM environment.
  166. @param CommBufferSize The size of the CommBuffer.
  167. @return Status Code
  168. **/
  169. EFI_STATUS
  170. EFIAPI
  171. PiMmCpuTpFwRootMmiHandler (
  172. IN EFI_HANDLE DispatchHandle,
  173. IN CONST VOID *Context, OPTIONAL
  174. IN OUT VOID *CommBuffer, OPTIONAL
  175. IN OUT UINTN *CommBufferSize OPTIONAL
  176. )
  177. {
  178. EFI_STATUS Status;
  179. UINTN CpuNumber;
  180. ASSERT (Context == NULL);
  181. ASSERT (CommBuffer == NULL);
  182. ASSERT (CommBufferSize == NULL);
  183. CpuNumber = mMmst->CurrentlyExecutingCpu;
  184. if (PerCpuGuidedEventContext[CpuNumber] == NULL) {
  185. return EFI_NOT_FOUND;
  186. }
  187. DEBUG ((DEBUG_INFO, "CommBuffer - 0x%x, CommBufferSize - 0x%x\n",
  188. PerCpuGuidedEventContext[CpuNumber],
  189. PerCpuGuidedEventContext[CpuNumber]->MessageLength));
  190. Status = mMmst->MmiManage (
  191. &PerCpuGuidedEventContext[CpuNumber]->HeaderGuid,
  192. NULL,
  193. PerCpuGuidedEventContext[CpuNumber]->Data,
  194. &PerCpuGuidedEventContext[CpuNumber]->MessageLength
  195. );
  196. if (Status != EFI_SUCCESS) {
  197. DEBUG ((DEBUG_WARN, "Unable to manage Guided Event - %d\n", Status));
  198. }
  199. return Status;
  200. }