TianoCore EDK2 master
Loading...
Searching...
No Matches
EventHandle.c
Go to the documentation of this file.
1
12#include <Base.h>
13#include <Pi/PiMmCis.h>
14
16#include <Library/DebugLib.h>
17#include <Library/HobLib.h>
18
19#include <Protocol/DebugSupport.h> // for EFI_SYSTEM_CONTEXT
20
21#include <Guid/ZeroGuid.h>
23
24#include <StandaloneMmCpu.h>
25
27EFIAPI
31 );
32
33//
34// On ARM platforms every event is expected to have a GUID associated with
35// it. It will be used by the MM Entry point to find the handler for the
36// event. It will either be populated in a EFI_MM_COMMUNICATE_HEADER by the
37// caller of the event (e.g. MM_COMMUNICATE SMC) or by the CPU driver
38// (e.g. during an asynchronous event). In either case, this context is
39// maintained in an array which has an entry for each CPU. The pointer to this
40// array is held in PerCpuGuidedEventContext. Memory is allocated once the
41// number of CPUs in the system are made known through the
42// MP_INFORMATION_HOB_DATA.
43//
44EFI_MM_COMMUNICATE_HEADER **PerCpuGuidedEventContext = NULL;
45
46// Descriptor with whereabouts of memory used for communication with the normal world
47EFI_MMRAM_DESCRIPTOR mNsCommBuffer;
48EFI_MMRAM_DESCRIPTOR mSCommBuffer;
49
50MP_INFORMATION_HOB_DATA *mMpInformationHobData;
51
53 0,
55};
56
57STATIC EFI_MM_ENTRY_POINT mMmEntryPoint = NULL;
58
70 IN UINTN BufferAddr
71 )
72{
73 UINT64 NsCommBufferEnd;
74 UINT64 SCommBufferEnd;
75 UINT64 CommBufferEnd;
76
77 NsCommBufferEnd = mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize;
78 SCommBufferEnd = mSCommBuffer.PhysicalStart + mSCommBuffer.PhysicalSize;
79
80 if ((BufferAddr >= mNsCommBuffer.PhysicalStart) &&
81 (BufferAddr < NsCommBufferEnd))
82 {
83 CommBufferEnd = NsCommBufferEnd;
84 } else if ((BufferAddr >= mSCommBuffer.PhysicalStart) &&
85 (BufferAddr < SCommBufferEnd))
86 {
87 CommBufferEnd = SCommBufferEnd;
88 } else {
89 return EFI_ACCESS_DENIED;
90 }
91
92 if ((CommBufferEnd - BufferAddr) < sizeof (EFI_MM_COMMUNICATE_HEADER)) {
93 return EFI_ACCESS_DENIED;
94 }
95
96 // perform bounds check.
97 if ((CommBufferEnd - BufferAddr - sizeof (EFI_MM_COMMUNICATE_HEADER)) <
98 ((EFI_MM_COMMUNICATE_HEADER *)BufferAddr)->MessageLength)
99 {
100 return EFI_ACCESS_DENIED;
101 }
102
103 return EFI_SUCCESS;
104}
105
121 IN UINTN EventId,
122 IN UINTN CpuNumber,
123 IN UINTN NsCommBufferAddr
124 )
125{
126 EFI_MM_COMMUNICATE_HEADER *GuidedEventContext;
127 EFI_MM_ENTRY_CONTEXT MmEntryPointContext;
128 EFI_STATUS Status;
129 UINTN NsCommBufferSize;
130
131 DEBUG ((DEBUG_INFO, "Received event - 0x%x on cpu %d\n", EventId, CpuNumber));
132
133 Status = EFI_SUCCESS;
134
135 // Perform parameter validation of NsCommBufferAddr
136 if (NsCommBufferAddr == (UINTN)NULL) {
137 return EFI_INVALID_PARAMETER;
138 }
139
140 Status = CheckBufferAddr (NsCommBufferAddr);
141 if (EFI_ERROR (Status)) {
142 DEBUG ((DEBUG_ERROR, "Check Buffer failed: %r\n", Status));
143 return Status;
144 }
145
146 // Find out the size of the buffer passed
147 NsCommBufferSize = ((EFI_MM_COMMUNICATE_HEADER *)NsCommBufferAddr)->MessageLength +
149
150 GuidedEventContext = NULL;
151 // Now that the secure world can see the normal world buffer, allocate
152 // memory to copy the communication buffer to the secure world.
153 Status = mMmst->MmAllocatePool (
155 NsCommBufferSize,
156 (VOID **)&GuidedEventContext
157 );
158
159 if (Status != EFI_SUCCESS) {
160 DEBUG ((DEBUG_ERROR, "Mem alloc failed - 0x%x\n", EventId));
161 return EFI_OUT_OF_RESOURCES;
162 }
163
164 // X1 contains the VA of the normal world memory accessible from
165 // secure world.
166 CopyMem (GuidedEventContext, (CONST VOID *)NsCommBufferAddr, NsCommBufferSize);
167
168 // Stash the pointer to the allocated Event Context for this CPU
169 PerCpuGuidedEventContext[CpuNumber] = GuidedEventContext;
170
171 ZeroMem (&MmEntryPointContext, sizeof (EFI_MM_ENTRY_CONTEXT));
172
173 MmEntryPointContext.CurrentlyExecutingCpu = CpuNumber;
174 MmEntryPointContext.NumberOfCpus = mMpInformationHobData->NumberOfProcessors;
175
176 // Populate the MM system table with MP and state information
177 mMmst->CurrentlyExecutingCpu = CpuNumber;
178 mMmst->NumberOfCpus = mMpInformationHobData->NumberOfProcessors;
179 mMmst->CpuSaveStateSize = 0;
180 mMmst->CpuSaveState = NULL;
181
182 if (mMmEntryPoint == NULL) {
183 DEBUG ((DEBUG_ERROR, "Mm Entry point Not Found\n"));
184 return EFI_UNSUPPORTED;
185 }
186
187 mMmEntryPoint (&MmEntryPointContext);
188
189 // Free the memory allocation done earlier and reset the per-cpu context
190 ASSERT (GuidedEventContext);
191 CopyMem ((VOID *)NsCommBufferAddr, (CONST VOID *)GuidedEventContext, NsCommBufferSize);
192
193 Status = mMmst->MmFreePool ((VOID *)GuidedEventContext);
194 if (Status != EFI_SUCCESS) {
195 return EFI_OUT_OF_RESOURCES;
196 }
197
198 PerCpuGuidedEventContext[CpuNumber] = NULL;
199
200 return Status;
201}
202
212EFIAPI
216 )
217{
218 // store the entry point in a global
219 mMmEntryPoint = MmEntryPoint;
220 return EFI_SUCCESS;
221}
222
240EFIAPI
242 IN EFI_HANDLE DispatchHandle,
243 IN CONST VOID *Context OPTIONAL,
244 IN OUT VOID *CommBuffer OPTIONAL,
245 IN OUT UINTN *CommBufferSize OPTIONAL
246 )
247{
248 EFI_STATUS Status;
249 UINTN CpuNumber;
250
251 ASSERT (Context == NULL);
252 ASSERT (CommBuffer == NULL);
253 ASSERT (CommBufferSize == NULL);
254
255 CpuNumber = mMmst->CurrentlyExecutingCpu;
256 if (PerCpuGuidedEventContext[CpuNumber] == NULL) {
257 return EFI_NOT_FOUND;
258 }
259
260 DEBUG ((
261 DEBUG_INFO,
262 "CommBuffer - 0x%x, CommBufferSize - 0x%x\n",
263 PerCpuGuidedEventContext[CpuNumber],
264 PerCpuGuidedEventContext[CpuNumber]->MessageLength
265 ));
266
267 Status = mMmst->MmiManage (
268 &PerCpuGuidedEventContext[CpuNumber]->HeaderGuid,
269 NULL,
270 PerCpuGuidedEventContext[CpuNumber]->Data,
271 &PerCpuGuidedEventContext[CpuNumber]->MessageLength
272 );
273
274 if (Status != EFI_SUCCESS) {
275 DEBUG ((DEBUG_WARN, "Unable to manage Guided Event - %d\n", Status));
276 }
277
278 return Status;
279}
UINT64 UINTN
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS EFIAPI PiMmCpuTpFwRootMmiHandler(IN EFI_HANDLE DispatchHandle, IN CONST VOID *Context OPTIONAL, IN OUT VOID *CommBuffer OPTIONAL, IN OUT UINTN *CommBufferSize OPTIONAL)
Definition: EventHandle.c:241
STATIC EFI_STATUS CheckBufferAddr(IN UINTN BufferAddr)
Definition: EventHandle.c:69
EFI_STATUS PiMmStandaloneMmCpuDriverEntry(IN UINTN EventId, IN UINTN CpuNumber, IN UINTN NsCommBufferAddr)
Definition: EventHandle.c:120
EFI_STATUS EFIAPI MmFoundationEntryRegister(IN CONST EFI_MM_CONFIGURATION_PROTOCOL *This, IN EFI_MM_ENTRY_POINT MmEntryPoint)
Definition: EventHandle.c:213
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
VOID(EFIAPI * EFI_MM_ENTRY_POINT)(IN CONST EFI_MM_ENTRY_CONTEXT *MmEntryContext)
Definition: PiMmCis.h:238
VOID EFIAPI MmEntryPoint(IN CONST EFI_MM_ENTRY_CONTEXT *MmEntryContext)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
@ EfiRuntimeServicesData
UINTN CurrentlyExecutingCpu
Definition: PiMmCis.h:211
UINTN CurrentlyExecutingCpu
Definition: PiMmCis.h:292
EFI_MM_INTERRUPT_MANAGE MmiManage
Definition: PiMmCis.h:337
VOID ** CpuSaveState
Definition: PiMmCis.h:308
UINTN * CpuSaveStateSize
Definition: PiMmCis.h:302
EFI_ALLOCATE_POOL MmAllocatePool
Definition: PiMmCis.h:274
EFI_PHYSICAL_ADDRESS PhysicalStart
Definition: PiMultiPhase.h:122