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