TianoCore EDK2 master
Loading...
Searching...
No Matches
PrmLoaderDxe.c
Go to the documentation of this file.
1
12#include "PrmAcpiTable.h"
13
14#include <Guid/ZeroGuid.h>
16#include <Library/BaseLib.h>
18#include <Library/DebugLib.h>
24#include <Library/UefiLib.h>
25#include <Protocol/AcpiTable.h>
26#include <Protocol/PrmConfig.h>
27
28#include <PrmContextBuffer.h>
29#include <PrmMmio.h>
30
31#define _DBGMSGID_ "[PRMLOADER]"
32
33UINTN mPrmHandlerCount;
34UINTN mPrmModuleCount;
35
53 OUT PRM_ACPI_DESCRIPTION_TABLE **PrmAcpiDescriptionTable
54 )
55{
56 EFI_IMAGE_EXPORT_DIRECTORY *CurrentImageExportDirectory;
57 PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT *CurrentExportDescriptorStruct;
58 PRM_ACPI_DESCRIPTION_TABLE *PrmAcpiTable;
59 PRM_MODULE_IMAGE_CONTEXT *CurrentPrmModuleImageContext;
60 CONST CHAR8 *CurrentExportDescriptorHandlerName;
61
62 ACPI_PARAMETER_BUFFER_DESCRIPTOR *CurrentModuleAcpiParamDescriptors;
63 PRM_CONTEXT_BUFFER *CurrentContextBuffer;
64 PRM_MODULE_CONTEXT_BUFFERS *CurrentModuleContextBuffers;
65 PRM_MODULE_INFORMATION_STRUCT *CurrentModuleInfoStruct;
66 PRM_HANDLER_INFORMATION_STRUCT *CurrentHandlerInfoStruct;
67
68 EFI_STATUS Status;
69 EFI_PHYSICAL_ADDRESS CurrentImageAddress;
70 UINTN AcpiParamIndex;
71 UINTN HandlerIndex;
72 UINT32 PrmAcpiDescriptionTableBufferSize;
73
74 UINT64 HandlerPhysicalAddress;
75
76 DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __func__));
77
78 if (PrmAcpiDescriptionTable == NULL) {
79 return EFI_INVALID_PARAMETER;
80 }
81
82 *PrmAcpiDescriptionTable = NULL;
83
84 //
85 // The platform DSC GUID must be set to a non-zero value
86 //
87 if (CompareGuid (&gEdkiiDscPlatformGuid, &gZeroGuid)) {
88 DEBUG ((
89 DEBUG_ERROR,
90 " %a %a: The Platform GUID in the DSC file must be set to a unique non-zero value.\n",
91 _DBGMSGID_,
92 __func__
93 ));
94 ASSERT (!CompareGuid (&gEdkiiDscPlatformGuid, &gZeroGuid));
95 }
96
97 DEBUG ((DEBUG_INFO, " %a %a: %d total PRM modules to process.\n", _DBGMSGID_, __func__, mPrmModuleCount));
98 DEBUG ((DEBUG_INFO, " %a %a: %d total PRM handlers to process.\n", _DBGMSGID_, __func__, mPrmHandlerCount));
99
100 PrmAcpiDescriptionTableBufferSize = (UINT32)(OFFSET_OF (PRM_ACPI_DESCRIPTION_TABLE, PrmModuleInfoStructure) +
101 (OFFSET_OF (PRM_MODULE_INFORMATION_STRUCT, HandlerInfoStructure) * mPrmModuleCount) +
102 (sizeof (PRM_HANDLER_INFORMATION_STRUCT) * mPrmHandlerCount)
103 );
104 DEBUG ((DEBUG_INFO, " %a %a: Total PRM ACPI table size: 0x%x.\n", _DBGMSGID_, __func__, PrmAcpiDescriptionTableBufferSize));
105
106 PrmAcpiTable = AllocateZeroPool ((UINTN)PrmAcpiDescriptionTableBufferSize);
107 if (PrmAcpiTable == NULL) {
108 return EFI_OUT_OF_RESOURCES;
109 }
110
111 PrmAcpiTable->Header.Signature = PRM_TABLE_SIGNATURE;
112 PrmAcpiTable->Header.Length = PrmAcpiDescriptionTableBufferSize;
113 PrmAcpiTable->Header.Revision = PRM_TABLE_REVISION;
114 PrmAcpiTable->Header.Checksum = 0x0;
115 CopyMem (&PrmAcpiTable->Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (PrmAcpiTable->Header.OemId));
116 PrmAcpiTable->Header.OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
117 PrmAcpiTable->Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);
118 PrmAcpiTable->Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
119 PrmAcpiTable->Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
120 CopyGuid (&PrmAcpiTable->PrmPlatformGuid, &gEdkiiDscPlatformGuid);
121 PrmAcpiTable->PrmModuleInfoOffset = OFFSET_OF (PRM_ACPI_DESCRIPTION_TABLE, PrmModuleInfoStructure);
122 PrmAcpiTable->PrmModuleInfoCount = (UINT32)mPrmModuleCount;
123
124 //
125 // Iterate across all PRM Modules on the list
126 //
127 CurrentModuleInfoStruct = &PrmAcpiTable->PrmModuleInfoStructure[0];
128 for (
129 CurrentPrmModuleImageContext = NULL, Status = GetNextPrmModuleEntry (&CurrentPrmModuleImageContext);
130 !EFI_ERROR (Status);
131 Status = GetNextPrmModuleEntry (&CurrentPrmModuleImageContext))
132 {
133 CurrentImageAddress = CurrentPrmModuleImageContext->PeCoffImageContext.ImageAddress;
134 CurrentImageExportDirectory = CurrentPrmModuleImageContext->ExportDirectory;
135 CurrentExportDescriptorStruct = CurrentPrmModuleImageContext->ExportDescriptor;
136 CurrentModuleAcpiParamDescriptors = NULL;
137
138 DEBUG ((
139 DEBUG_INFO,
140 " %a %a: PRM Module - %a with %d handlers.\n",
141 _DBGMSGID_,
142 __func__,
143 (CHAR8 *)((UINTN)CurrentImageAddress + CurrentImageExportDirectory->Name),
144 CurrentExportDescriptorStruct->Header.NumberPrmHandlers
145 ));
146
147 CurrentModuleInfoStruct->StructureRevision = PRM_MODULE_INFORMATION_STRUCT_REVISION;
148 CurrentModuleInfoStruct->StructureLength = (
149 OFFSET_OF (PRM_MODULE_INFORMATION_STRUCT, HandlerInfoStructure) +
150 (CurrentExportDescriptorStruct->Header.NumberPrmHandlers * sizeof (PRM_HANDLER_INFORMATION_STRUCT))
151 );
152 CopyGuid (&CurrentModuleInfoStruct->Identifier, &CurrentExportDescriptorStruct->Header.ModuleGuid);
153 CurrentModuleInfoStruct->HandlerCount = (UINT32)CurrentExportDescriptorStruct->Header.NumberPrmHandlers;
154 CurrentModuleInfoStruct->HandlerInfoOffset = OFFSET_OF (PRM_MODULE_INFORMATION_STRUCT, HandlerInfoStructure);
155
156 CurrentModuleInfoStruct->MajorRevision = 0;
157 CurrentModuleInfoStruct->MinorRevision = 0;
159 (VOID *)(UINTN)CurrentImageAddress,
160 &CurrentPrmModuleImageContext->PeCoffImageContext,
161 &CurrentModuleInfoStruct->MajorRevision,
162 &CurrentModuleInfoStruct->MinorRevision
163 );
164 ASSERT_EFI_ERROR (Status);
165
166 // It is currently valid for a PRM module not to use a context buffer
167 Status = GetModuleContextBuffers (
169 &CurrentModuleInfoStruct->Identifier,
170 (CONST PRM_MODULE_CONTEXT_BUFFERS **)&CurrentModuleContextBuffers
171 );
172 ASSERT (!EFI_ERROR (Status) || Status == EFI_NOT_FOUND);
173 if (!EFI_ERROR (Status) && (CurrentModuleContextBuffers != NULL)) {
174 CurrentModuleInfoStruct->RuntimeMmioRanges = (UINT64)(UINTN)CurrentModuleContextBuffers->RuntimeMmioRanges;
175 CurrentModuleAcpiParamDescriptors = CurrentModuleContextBuffers->AcpiParameterBufferDescriptors;
176 }
177
178 //
179 // Iterate across all PRM handlers in the PRM Module
180 //
181 for (HandlerIndex = 0; HandlerIndex < CurrentExportDescriptorStruct->Header.NumberPrmHandlers; HandlerIndex++) {
182 CurrentHandlerInfoStruct = &(CurrentModuleInfoStruct->HandlerInfoStructure[HandlerIndex]);
183
184 CurrentHandlerInfoStruct->StructureRevision = PRM_HANDLER_INFORMATION_STRUCT_REVISION;
185 CurrentHandlerInfoStruct->StructureLength = sizeof (PRM_HANDLER_INFORMATION_STRUCT);
186 CopyGuid (
187 &CurrentHandlerInfoStruct->Identifier,
188 &CurrentExportDescriptorStruct->PrmHandlerExportDescriptors[HandlerIndex].PrmHandlerGuid
189 );
190
191 CurrentExportDescriptorHandlerName = (CONST CHAR8 *)CurrentExportDescriptorStruct->PrmHandlerExportDescriptors[HandlerIndex].PrmHandlerName;
192
193 Status = GetContextBuffer (
194 &CurrentHandlerInfoStruct->Identifier,
195 CurrentModuleContextBuffers,
196 (CONST PRM_CONTEXT_BUFFER **)&CurrentContextBuffer
197 );
198 if (!EFI_ERROR (Status)) {
199 CurrentHandlerInfoStruct->StaticDataBuffer = (UINT64)(UINTN)CurrentContextBuffer->StaticDataBuffer;
200 }
201
202 Status = GetExportEntryAddress (
203 CurrentExportDescriptorHandlerName,
204 CurrentImageAddress,
205 CurrentImageExportDirectory,
206 &HandlerPhysicalAddress
207 );
208 ASSERT_EFI_ERROR (Status);
209 if (!EFI_ERROR (Status)) {
210 CurrentHandlerInfoStruct->PhysicalAddress = HandlerPhysicalAddress;
211 DEBUG ((
212 DEBUG_INFO,
213 " %a %a: Found %a handler physical address at 0x%016x.\n",
214 _DBGMSGID_,
215 __func__,
216 CurrentExportDescriptorHandlerName,
217 CurrentHandlerInfoStruct->PhysicalAddress
218 ));
219 }
220
221 //
222 // Update the handler ACPI parameter buffer address if applicable
223 //
224 if (CurrentModuleAcpiParamDescriptors != NULL) {
225 for (AcpiParamIndex = 0; AcpiParamIndex < CurrentModuleContextBuffers->AcpiParameterBufferDescriptorCount; AcpiParamIndex++) {
226 if (CompareGuid (&CurrentModuleAcpiParamDescriptors[AcpiParamIndex].HandlerGuid, &CurrentHandlerInfoStruct->Identifier)) {
227 CurrentHandlerInfoStruct->AcpiParameterBuffer = (UINT64)(UINTN)(
228 CurrentModuleAcpiParamDescriptors[AcpiParamIndex].AcpiParameterBufferAddress
229 );
230 }
231 }
232 }
233 }
234
235 CurrentModuleInfoStruct = (PRM_MODULE_INFORMATION_STRUCT *)((UINTN)CurrentModuleInfoStruct + CurrentModuleInfoStruct->StructureLength);
236 }
237
238 *PrmAcpiDescriptionTable = PrmAcpiTable;
239
240 return EFI_SUCCESS;
241}
242
258 IN PRM_ACPI_DESCRIPTION_TABLE *PrmAcpiDescriptionTable
259 )
260{
261 EFI_STATUS Status;
262 EFI_ACPI_TABLE_PROTOCOL *AcpiTableProtocol;
263 UINTN TableKey;
264
265 if ((PrmAcpiDescriptionTable == NULL) || (PrmAcpiDescriptionTable->Header.Signature != PRM_TABLE_SIGNATURE)) {
266 return EFI_INVALID_PARAMETER;
267 }
268
269 Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **)&AcpiTableProtocol);
270 if (!EFI_ERROR (Status)) {
271 TableKey = 0;
272 //
273 // Publish the PRM ACPI table. The table checksum will be computed during installation.
274 //
275 Status = AcpiTableProtocol->InstallAcpiTable (
276 AcpiTableProtocol,
277 PrmAcpiDescriptionTable,
278 PrmAcpiDescriptionTable->Header.Length,
279 &TableKey
280 );
281 if (!EFI_ERROR (Status)) {
282 DEBUG ((DEBUG_INFO, "%a %a: The PRMT ACPI table was installed successfully.\n", _DBGMSGID_, __func__));
283 }
284 }
285
286 ASSERT_EFI_ERROR (Status);
287
288 return Status;
289}
290
309VOID
310EFIAPI
312 IN EFI_EVENT Event,
313 IN VOID *Context
314 )
315{
316 EFI_STATUS Status;
317 PRM_ACPI_DESCRIPTION_TABLE *PrmAcpiDescriptionTable;
318
319 DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __func__));
320
321 Status = DiscoverPrmModules (&mPrmModuleCount, &mPrmHandlerCount);
322 ASSERT_EFI_ERROR (Status);
323
324 Status = ProcessPrmModules (&PrmAcpiDescriptionTable);
325 ASSERT_EFI_ERROR (Status);
326
327 Status = PublishPrmAcpiTable (PrmAcpiDescriptionTable);
328 ASSERT_EFI_ERROR (Status);
329
330 if (PrmAcpiDescriptionTable != NULL) {
331 FreePool (PrmAcpiDescriptionTable);
332 }
333
334 gBS->CloseEvent (Event);
335}
336
348EFIAPI
350 IN EFI_HANDLE ImageHandle,
351 IN EFI_SYSTEM_TABLE *SystemTable
352 )
353{
354 EFI_STATUS Status;
355 EFI_EVENT EndOfDxeEvent;
356
357 DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __func__));
358
359 //
360 // Discover and process installed PRM modules at the End of DXE
361 // The PRM ACPI table is published if one or PRM modules are discovered
362 //
363 Status = gBS->CreateEventEx (
364 EVT_NOTIFY_SIGNAL,
365 TPL_CALLBACK,
367 NULL,
368 &gEfiEndOfDxeEventGroupGuid,
369 &EndOfDxeEvent
370 );
371 if (EFI_ERROR (Status)) {
372 DEBUG ((DEBUG_ERROR, "%a %a: EndOfDxe callback registration failed! %r.\n", _DBGMSGID_, __func__, Status));
373 ASSERT_EFI_ERROR (Status);
374 }
375
376 return EFI_SUCCESS;
377}
UINT64 UINTN
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define IN
Definition: Base.h:279
#define OFFSET_OF(TYPE, Field)
Definition: Base.h:758
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define PcdGet64(TokenName)
Definition: PcdLib.h:375
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
#define PcdGetPtr(TokenName)
Definition: PcdLib.h:388
EFI_STATUS GetContextBuffer(IN CONST EFI_GUID *PrmHandlerGuid, IN CONST PRM_MODULE_CONTEXT_BUFFERS *PrmModuleContextBuffers OPTIONAL, OUT CONST PRM_CONTEXT_BUFFER **PrmContextBuffer)
@ ByModuleGuid
EFI_STATUS GetModuleContextBuffers(IN PRM_GUID_SEARCH_TYPE GuidSearchType, IN CONST EFI_GUID *Guid, OUT CONST PRM_MODULE_CONTEXT_BUFFERS **PrmModuleContextBuffers)
EFI_STATUS EFIAPI PrmLoaderEntryPoint(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: PrmLoaderDxe.c:349
EFI_STATUS ProcessPrmModules(OUT PRM_ACPI_DESCRIPTION_TABLE **PrmAcpiDescriptionTable)
Definition: PrmLoaderDxe.c:52
VOID EFIAPI PrmLoaderEndOfDxeNotification(IN EFI_EVENT Event, IN VOID *Context)
Definition: PrmLoaderDxe.c:311
EFI_STATUS PublishPrmAcpiTable(IN PRM_ACPI_DESCRIPTION_TABLE *PrmAcpiDescriptionTable)
Definition: PrmLoaderDxe.c:257
EFI_STATUS EFIAPI GetNextPrmModuleEntry(IN OUT PRM_MODULE_IMAGE_CONTEXT **ModuleImageContext)
EFI_STATUS EFIAPI DiscoverPrmModules(OUT UINTN *ModuleCount OPTIONAL, OUT UINTN *HandlerCount OPTIONAL)
EFI_STATUS GetImageVersionInPeCoffImage(IN VOID *Image, IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext, OUT UINT16 *ImageMajorVersion, OUT UINT16 *ImageMinorVersion)
EFI_STATUS GetExportEntryAddress(IN CONST CHAR8 *ExportName, IN EFI_PHYSICAL_ADDRESS ImageBaseAddress, IN EFI_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory, OUT EFI_PHYSICAL_ADDRESS *ExportPhysicalAddress)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
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_BOOT_SERVICES * gBS
PHYSICAL_ADDRESS ImageAddress
Definition: PeCoffLib.h:79
UINT32 PrmModuleInfoCount
Number of entries in the PRM Module Info array.
Definition: PrmAcpiTable.h:64
EFI_ACPI_DESCRIPTION_HEADER Header
Standard ACPI description header.
Definition: PrmAcpiTable.h:58
PRM_DATA_BUFFER * StaticDataBuffer
UINT16 StructureRevision
Revision of this structure.
Definition: PrmAcpiTable.h:29
UINT16 StructureLength
Length in bytes of this structure.
Definition: PrmAcpiTable.h:30
GUID Identifier
GUID of the PRM handler for this structure.
Definition: PrmAcpiTable.h:31
UINT64 PhysicalAddress
Physical address of this PRM handler.
Definition: PrmAcpiTable.h:32
ACPI_PARAMETER_BUFFER_DESCRIPTOR * AcpiParameterBufferDescriptors
PRM_RUNTIME_MMIO_RANGES * RuntimeMmioRanges
UINT16 HandlerCount
Number of entries in the Handler Info array.
Definition: PrmAcpiTable.h:49
UINT16 StructureRevision
Revision of this structure.
Definition: PrmAcpiTable.h:43
UINT16 MinorRevision
PRM module minor revision.
Definition: PrmAcpiTable.h:48
GUID Identifier
GUID of the PRM module for this structure.
Definition: PrmAcpiTable.h:46
UINT16 MajorRevision
PRM module major revision.
Definition: PrmAcpiTable.h:47