TianoCore EDK2 master
Loading...
Searching...
No Matches
PrmConfigDxe.c
Go to the documentation of this file.
1
11#include <Library/BaseLib.h>
13#include <Library/DebugLib.h>
18#include <Library/UefiLib.h>
19
20#include <PiDxe.h>
21#include <PrmContextBuffer.h>
22#include <PrmDataBuffer.h>
23#include <PrmMmio.h>
24#include <Protocol/PrmConfig.h>
25
26#define _DBGMSGID_ "[PRMCONFIG]"
27
28STATIC UINTN mMaxRuntimeMmioRangeCount;
29
31
38VOID
40 IN PRM_RUNTIME_MMIO_RANGES *RuntimeMmioRanges
41 )
42{
43 UINTN Index;
44
45 if ((RuntimeMmioRanges == NULL) || (RuntimeMmioRanges->Count == 0)) {
46 return;
47 }
48
49 for (Index = 0; Index < (UINTN)RuntimeMmioRanges->Count; Index++) {
50 RuntimeMmioRanges->Range[Index].VirtualBaseAddress = RuntimeMmioRanges->Range[Index].PhysicalBaseAddress;
51 gRT->ConvertPointer (0x0, (VOID **)&(RuntimeMmioRanges->Range[Index].VirtualBaseAddress));
52 }
53}
54
64VOID
66 IN PRM_RUNTIME_MMIO_RANGES *RuntimeMmioRanges
67 )
68{
69 EFI_STATUS Status;
70 EFI_STATUS Status2;
71 UINTN Index;
73
74 DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __func__));
75
76 if ((RuntimeMmioRanges == NULL) || (RuntimeMmioRanges->Count == 0)) {
77 return;
78 }
79
80 for (Index = 0; Index < (UINTN)RuntimeMmioRanges->Count; Index++) {
81 DEBUG ((
82 DEBUG_INFO,
83 " %a %a: Runtime MMIO Range [%d].\n",
84 _DBGMSGID_,
85 __func__,
86 Index
87 ));
88 DEBUG ((
89 DEBUG_INFO,
90 " %a %a: Physical address = 0x%016x. Length = 0x%x.\n",
91 _DBGMSGID_,
92 __func__,
93 RuntimeMmioRanges->Range[Index].PhysicalBaseAddress,
94 RuntimeMmioRanges->Range[Index].Length
95 ));
96
97 // Runtime memory ranges should cover ranges on a page boundary
98 ASSERT ((RuntimeMmioRanges->Range[Index].PhysicalBaseAddress & EFI_PAGE_MASK) == 0);
99 ASSERT ((RuntimeMmioRanges->Range[Index].Length & EFI_PAGE_MASK) == 0);
100
101 Status2 = EFI_NOT_FOUND;
102 Status = gDS->GetMemorySpaceDescriptor (RuntimeMmioRanges->Range[Index].PhysicalBaseAddress, &Descriptor);
103 if (!EFI_ERROR (Status) &&
104 (
106 ((Descriptor.Length & EFI_PAGE_MASK) != 0)
107 )
108 )
109 {
110 Status2 = gDS->RemoveMemorySpace (
111 RuntimeMmioRanges->Range[Index].PhysicalBaseAddress,
112 Descriptor.Length
113 );
114 }
115
116 if ((Status == EFI_NOT_FOUND) || !EFI_ERROR (Status2)) {
117 Status = gDS->AddMemorySpace (
119 RuntimeMmioRanges->Range[Index].PhysicalBaseAddress,
120 (UINT64)RuntimeMmioRanges->Range[Index].Length,
121 EFI_MEMORY_UC | EFI_MEMORY_RUNTIME
122 );
123 ASSERT_EFI_ERROR (Status);
124
125 Status = gDS->AllocateMemorySpace (
128 0,
129 (UINT64)RuntimeMmioRanges->Range[Index].Length,
130 &RuntimeMmioRanges->Range[Index].PhysicalBaseAddress,
132 NULL
133 );
134 ASSERT_EFI_ERROR (Status);
135 }
136
137 Status = gDS->GetMemorySpaceDescriptor (RuntimeMmioRanges->Range[Index].PhysicalBaseAddress, &Descriptor);
138 ASSERT_EFI_ERROR (Status);
139 if (EFI_ERROR (Status)) {
140 DEBUG ((
141 DEBUG_ERROR,
142 " %a %a: Error [%r] finding descriptor for runtime memory range 0x%016x.\n",
143 _DBGMSGID_,
144 __func__,
145 Status,
146 RuntimeMmioRanges->Range[Index].PhysicalBaseAddress
147 ));
148 continue;
149 }
150
151 if ((Descriptor.Attributes & EFI_MEMORY_RUNTIME) != 0) {
152 continue;
153 }
154
155 // The memory space descriptor access attributes are not accurate. Don't pass
156 // in access attributes so SetMemorySpaceAttributes() doesn't update them.
157 // EFI_MEMORY_RUNTIME is not a CPU arch attribute, so calling
158 // SetMemorySpaceAttributes() with only it set will not clear existing page table
159 // attributes for this region, such as EFI_MEMORY_XP
160 Status = gDS->SetMemorySpaceAttributes (
161 RuntimeMmioRanges->Range[Index].PhysicalBaseAddress,
162 (UINT64)RuntimeMmioRanges->Range[Index].Length,
163 EFI_MEMORY_RUNTIME
164 );
165 ASSERT_EFI_ERROR (Status);
166 if (EFI_ERROR (Status)) {
167 DEBUG ((
168 DEBUG_ERROR,
169 " %a %a: Error [%r] setting descriptor for runtime memory range 0x%016x.\n",
170 _DBGMSGID_,
171 __func__,
172 Status,
173 RuntimeMmioRanges->Range[Index].PhysicalBaseAddress
174 ));
175 } else {
176 DEBUG ((DEBUG_INFO, " %a %a: Successfully set runtime attribute for the MMIO range.\n", _DBGMSGID_, __func__));
177 }
178 }
179}
180
185VOID
187 VOID
188 )
189{
190 EFI_STATUS Status;
191 UINTN HandleCount;
192 UINTN HandleIndex;
193 UINTN RangeIndex;
194 EFI_HANDLE *HandleBuffer;
195 PRM_CONFIG_PROTOCOL *PrmConfigProtocol;
196
197 DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __func__));
198
199 RangeIndex = 0;
200
201 mRuntimeMmioRanges = AllocateRuntimeZeroPool (sizeof (*mRuntimeMmioRanges) * mMaxRuntimeMmioRangeCount);
202 if ((mRuntimeMmioRanges == NULL) && (mMaxRuntimeMmioRangeCount > 0)) {
203 DEBUG ((
204 DEBUG_ERROR,
205 " %a %a: Memory allocation for runtime MMIO pointer array failed.\n",
206 _DBGMSGID_,
207 __func__
208 ));
209 ASSERT (FALSE);
210 return;
211 }
212
213 HandleBuffer = NULL;
214 Status = gBS->LocateHandleBuffer (
216 &gPrmConfigProtocolGuid,
217 NULL,
218 &HandleCount,
219 &HandleBuffer
220 );
221 if (!EFI_ERROR (Status)) {
222 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
223 Status = gBS->HandleProtocol (
224 HandleBuffer[HandleIndex],
225 &gPrmConfigProtocolGuid,
226 (VOID **)&PrmConfigProtocol
227 );
228 ASSERT_EFI_ERROR (Status);
229 if (EFI_ERROR (Status) || (PrmConfigProtocol == NULL)) {
230 continue;
231 }
232
233 if (PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges != NULL) {
234 if (RangeIndex >= mMaxRuntimeMmioRangeCount) {
235 Status = EFI_BUFFER_TOO_SMALL;
236 DEBUG ((
237 DEBUG_ERROR,
238 " %a %a: Index out of bounds - Actual count (%d) of runtime MMIO ranges exceeds maximum count (%d).\n",
239 _DBGMSGID_,
240 __func__,
241 RangeIndex + 1,
242 mMaxRuntimeMmioRangeCount
243 ));
244 ASSERT_EFI_ERROR (Status);
245 return;
246 }
247
248 mRuntimeMmioRanges[RangeIndex++] = PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges;
249 }
250 }
251
252 DEBUG ((
253 DEBUG_INFO,
254 " %a %a: %d MMIO ranges buffers saved for future virtual memory conversion.\n",
255 _DBGMSGID_,
256 __func__,
257 RangeIndex
258 ));
259 }
260}
261
277 IN CONST PRM_DATA_BUFFER *PrmDataBuffer
278 )
279{
280 if (PrmDataBuffer == NULL) {
281 return EFI_INVALID_PARAMETER;
282 }
283
284 if (PrmDataBuffer->Header.Signature != PRM_DATA_BUFFER_HEADER_SIGNATURE) {
285 DEBUG ((DEBUG_ERROR, " %a %a: The PRM data buffer signature is invalid. PRM module.\n", _DBGMSGID_, __func__));
286 return EFI_NOT_FOUND;
287 }
288
289 if (PrmDataBuffer->Header.Length < sizeof (PRM_DATA_BUFFER_HEADER)) {
290 DEBUG ((DEBUG_ERROR, " %a %a: The PRM data buffer length is invalid.\n", _DBGMSGID_, __func__));
291 return EFI_BUFFER_TOO_SMALL;
292 }
293
294 return EFI_SUCCESS;
295}
296
311 IN CONST PRM_CONTEXT_BUFFER *PrmContextBuffer
312 )
313{
314 if (PrmContextBuffer == NULL) {
315 return EFI_INVALID_PARAMETER;
316 }
317
318 if (PrmContextBuffer->Signature != PRM_CONTEXT_BUFFER_SIGNATURE) {
319 DEBUG ((DEBUG_ERROR, " %a %a: The PRM context buffer signature is invalid.\n", _DBGMSGID_, __func__));
320 return EFI_NOT_FOUND;
321 }
322
323 if (IsZeroGuid (&PrmContextBuffer->HandlerGuid)) {
324 DEBUG ((DEBUG_ERROR, " %a %a: The PRM context buffer GUID is zero.\n", _DBGMSGID_, __func__));
325 return EFI_NOT_FOUND;
326 }
327
328 if ((PrmContextBuffer->StaticDataBuffer != NULL) && EFI_ERROR (ValidatePrmDataBuffer (PrmContextBuffer->StaticDataBuffer))) {
329 DEBUG ((
330 DEBUG_ERROR,
331 " %a %a: Error in static buffer for PRM handler %g.\n",
332 _DBGMSGID_,
333 __func__,
334 &PrmContextBuffer->HandlerGuid
335 ));
336 return EFI_NOT_FOUND;
337 }
338
339 return EFI_SUCCESS;
340}
341
352VOID
353EFIAPI
355 IN EFI_EVENT Event,
356 IN VOID *Context
357 )
358{
359 UINTN Index;
360
361 //
362 // Convert runtime MMIO ranges
363 //
364 for (Index = 0; Index < mMaxRuntimeMmioRangeCount; Index++) {
365 ConvertRuntimeMemoryRangeAddresses (mRuntimeMmioRanges[Index]);
366 }
367}
368
380VOID
381EFIAPI
383 IN EFI_EVENT Event,
384 IN VOID *Context
385 )
386{
387 EFI_STATUS Status;
388 UINTN HandleCount;
389 UINTN BufferIndex;
390 UINTN HandleIndex;
391 EFI_HANDLE *HandleBuffer;
392 PRM_CONTEXT_BUFFER *CurrentContextBuffer;
393 PRM_CONFIG_PROTOCOL *PrmConfigProtocol;
394
395 DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __func__));
396
397 HandleBuffer = NULL;
398 Status = gBS->LocateHandleBuffer (
400 &gPrmConfigProtocolGuid,
401 NULL,
402 &HandleCount,
403 &HandleBuffer
404 );
405 if (!EFI_ERROR (Status)) {
406 for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
407 Status = gBS->HandleProtocol (
408 HandleBuffer[HandleIndex],
409 &gPrmConfigProtocolGuid,
410 (VOID **)&PrmConfigProtocol
411 );
412 ASSERT_EFI_ERROR (Status);
413 if (EFI_ERROR (Status) || (PrmConfigProtocol == NULL)) {
414 continue;
415 }
416
417 DEBUG ((
418 DEBUG_INFO,
419 " %a %a: Found PRM configuration protocol for PRM module %g.\n",
420 _DBGMSGID_,
421 __func__,
422 &PrmConfigProtocol->ModuleContextBuffers.ModuleGuid
423 ));
424
425 DEBUG ((DEBUG_INFO, " %a %a: Validating module context buffers...\n", _DBGMSGID_, __func__));
426 for (BufferIndex = 0; BufferIndex < PrmConfigProtocol->ModuleContextBuffers.BufferCount; BufferIndex++) {
427 CurrentContextBuffer = &(PrmConfigProtocol->ModuleContextBuffers.Buffer[BufferIndex]);
428
429 Status = ValidatePrmContextBuffer (CurrentContextBuffer);
430 if (EFI_ERROR (Status)) {
431 DEBUG ((
432 DEBUG_ERROR,
433 " %a %a: Context buffer validation failed for PRM handler %g.\n",
434 _DBGMSGID_,
435 __func__,
436 CurrentContextBuffer->HandlerGuid
437 ));
438 }
439 }
440
441 DEBUG ((DEBUG_INFO, " %a %a: Module context buffer validation complete.\n", _DBGMSGID_, __func__));
442
443 if (PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges != NULL) {
444 DEBUG ((
445 DEBUG_INFO,
446 " %a %a: Found %d PRM runtime MMIO ranges.\n",
447 _DBGMSGID_,
448 __func__,
449 PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges->Count
450 ));
451 SetRuntimeMemoryRangeAttributes (PrmConfigProtocol->ModuleContextBuffers.RuntimeMmioRanges);
452 mMaxRuntimeMmioRangeCount++;
453 }
454 }
455
457 }
458
459 if (HandleBuffer != NULL) {
460 gBS->FreePool (HandleBuffer);
461 }
462
463 gBS->CloseEvent (Event);
464}
465
477EFIAPI
479 IN EFI_HANDLE ImageHandle,
480 IN EFI_SYSTEM_TABLE *SystemTable
481 )
482{
483 EFI_STATUS Status;
484 EFI_EVENT Event;
485
486 DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __func__));
487
488 //
489 // Register a notification function to change memory attributes at end of DXE
490 //
491 Event = NULL;
492 Status = gBS->CreateEventEx (
493 EVT_NOTIFY_SIGNAL,
494 TPL_CALLBACK,
496 NULL,
497 &gEfiEndOfDxeEventGroupGuid,
498 &Event
499 );
500 ASSERT_EFI_ERROR (Status);
501
502 //
503 // Register a notification function for virtual address change
504 //
505 Event = NULL;
506 Status = gBS->CreateEventEx (
507 EVT_NOTIFY_SIGNAL,
508 TPL_NOTIFY,
510 NULL,
511 &gEfiEventVirtualAddressChangeGuid,
512 &Event
513 );
514 ASSERT_EFI_ERROR (Status);
515
516 return EFI_SUCCESS;
517}
UINT64 UINTN
BOOLEAN EFIAPI IsZeroGuid(IN CONST GUID *Guid)
Definition: MemLibGuid.c:156
EFI_DXE_SERVICES * gDS
VOID *EFIAPI AllocateRuntimeZeroPool(IN UINTN AllocationSize)
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define GLOBAL_REMOVE_IF_UNREFERENCED
Definition: Base.h:48
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
@ EfiGcdMemoryTypeReserved
Definition: PiDxeCis.h:32
@ EfiGcdMemoryTypeMemoryMappedIo
Definition: PiDxeCis.h:44
@ EfiGcdAllocateAddress
Definition: PiDxeCis.h:107
EFI_STATUS ValidatePrmContextBuffer(IN CONST PRM_CONTEXT_BUFFER *PrmContextBuffer)
Definition: PrmConfigDxe.c:310
VOID EFIAPI PrmConfigVirtualAddressChangeEvent(IN EFI_EVENT Event, IN VOID *Context)
Definition: PrmConfigDxe.c:354
VOID StoreVirtualMemoryAddressChangePointers(VOID)
Definition: PrmConfigDxe.c:186
VOID ConvertRuntimeMemoryRangeAddresses(IN PRM_RUNTIME_MMIO_RANGES *RuntimeMmioRanges)
Definition: PrmConfigDxe.c:39
VOID EFIAPI PrmConfigEndOfDxeNotification(IN EFI_EVENT Event, IN VOID *Context)
Definition: PrmConfigDxe.c:382
VOID SetRuntimeMemoryRangeAttributes(IN PRM_RUNTIME_MMIO_RANGES *RuntimeMmioRanges)
Definition: PrmConfigDxe.c:65
EFI_STATUS EFIAPI PrmConfigEntryPoint(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: PrmConfigDxe.c:478
EFI_STATUS ValidatePrmDataBuffer(IN CONST PRM_DATA_BUFFER *PrmDataBuffer)
Definition: PrmConfigDxe.c:276
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
@ ByProtocol
Definition: UefiSpec.h:1518
EFI_GCD_MEMORY_TYPE GcdMemoryType
Definition: PiDxeCis.h:152