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