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