TianoCore EDK2 master
Loading...
Searching...
No Matches
DxePrmModuleDiscoveryLib.c
Go to the documentation of this file.
1
11#include <PiMm.h>
12#include <Protocol/MmAccess.h>
13#include <Library/BaseLib.h>
15#include <Library/DebugLib.h>
21
22#include "PrmModuleDiscovery.h"
23
24#define _DBGMSGID_ "[PRMMODULEDISCOVERYLIB]"
25
26LIST_ENTRY mPrmModuleList;
27
41EFIAPI
43 IN OUT PRM_MODULE_IMAGE_CONTEXT **ModuleImageContext
44 )
45{
46 LIST_ENTRY *CurrentLink;
47 LIST_ENTRY *ForwardLink;
50
51 DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __func__));
52
53 if (ModuleImageContext == NULL) {
54 return EFI_INVALID_PARAMETER;
55 }
56
57 if (*ModuleImageContext == NULL) {
58 ForwardLink = GetFirstNode (&mPrmModuleList);
59 } else {
60 CurrentListEntry = NULL;
61 CurrentListEntry = CR (*ModuleImageContext, PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY, Context, PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE);
62 if ((CurrentListEntry == NULL) || (CurrentListEntry->Signature != PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE)) {
63 return EFI_INVALID_PARAMETER;
64 }
65
66 CurrentLink = &CurrentListEntry->Link;
67 ForwardLink = GetNextNode (&mPrmModuleList, CurrentLink);
68
69 if (ForwardLink == &mPrmModuleList) {
70 return EFI_NOT_FOUND;
71 }
72 }
73
74 ForwardListEntry = BASE_CR (ForwardLink, PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY, Link);
75 if (ForwardListEntry->Signature == PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE) {
76 *ModuleImageContext = &ForwardListEntry->Context;
77 return EFI_SUCCESS;
78 }
79
80 return EFI_NOT_FOUND;
81}
82
92 VOID
93 )
94{
95 PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY *PrmModuleImageContextListEntry;
96
97 DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __func__));
98
99 PrmModuleImageContextListEntry = AllocateZeroPool (sizeof (*PrmModuleImageContextListEntry));
100 if (PrmModuleImageContextListEntry == NULL) {
101 return NULL;
102 }
103
104 DEBUG ((
105 DEBUG_INFO,
106 " %a %a: Allocated PrmModuleImageContextListEntry at 0x%x of size 0x%x bytes.\n",
107 _DBGMSGID_,
108 __func__,
109 (UINTN)PrmModuleImageContextListEntry,
110 sizeof (*PrmModuleImageContextListEntry)
111 ));
112
113 PrmModuleImageContextListEntry->Signature = PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE;
114
115 return PrmModuleImageContextListEntry;
116}
117
128BOOLEAN
129EFIAPI
131 IN EFI_PHYSICAL_ADDRESS Address,
132 IN EFI_MMRAM_DESCRIPTOR *MmramRanges,
133 IN UINTN MmramRangeCount
134 )
135{
136 UINTN Index;
137
138 for (Index = 0; Index < MmramRangeCount; Index++) {
139 if ((Address >= MmramRanges[Index].CpuStart) &&
140 (Address < (MmramRanges[Index].CpuStart + MmramRanges[Index].PhysicalSize)))
141 {
142 return TRUE;
143 }
144 }
145
146 return FALSE;
147}
148
169EFIAPI
171 OUT UINTN *ModuleCount OPTIONAL,
172 OUT UINTN *HandlerCount OPTIONAL
173 )
174{
175 EFI_STATUS Status;
176 PRM_MODULE_IMAGE_CONTEXT TempPrmModuleImageContext;
177 PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY *PrmModuleImageContextListEntry;
178 EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocol;
179 EFI_HANDLE *HandleBuffer;
180 UINTN HandleCount;
181 UINTN Index;
182 UINTN PrmHandlerCount;
183 UINTN PrmModuleCount;
184 EFI_MM_ACCESS_PROTOCOL *MmAccess;
185 UINTN Size;
186 EFI_MMRAM_DESCRIPTOR *MmramRanges;
187 UINTN MmramRangeCount;
188
189 DEBUG ((DEBUG_INFO, "%a %a - Entry.\n", _DBGMSGID_, __func__));
190
191 PrmHandlerCount = 0;
192 PrmModuleCount = 0;
193
194 if (!IsListEmpty (&mPrmModuleList)) {
195 return EFI_ALREADY_STARTED;
196 }
197
198 Status = gBS->LocateHandleBuffer (
200 &gEfiLoadedImageProtocolGuid,
201 NULL,
202 &HandleCount,
203 &HandleBuffer
204 );
205 if (EFI_ERROR (Status) && (HandleCount == 0)) {
206 DEBUG ((DEBUG_ERROR, "%a %a: No LoadedImageProtocol instances found!\n", _DBGMSGID_, __func__));
207 return EFI_NOT_FOUND;
208 }
209
210 MmramRanges = NULL;
211 MmramRangeCount = 0;
212 Status = gBS->LocateProtocol (
213 &gEfiMmAccessProtocolGuid,
214 NULL,
215 (VOID **)&MmAccess
216 );
217 if (Status == EFI_SUCCESS) {
218 //
219 // Get MMRAM range information
220 //
221 Size = 0;
222 Status = MmAccess->GetCapabilities (MmAccess, &Size, NULL);
223 if ((Status == EFI_BUFFER_TOO_SMALL) && (Size != 0)) {
224 MmramRanges = (EFI_MMRAM_DESCRIPTOR *)AllocatePool (Size);
225 if (MmramRanges != NULL) {
226 Status = MmAccess->GetCapabilities (MmAccess, &Size, MmramRanges);
227 if (Status == EFI_SUCCESS) {
228 MmramRangeCount = Size / sizeof (EFI_MMRAM_DESCRIPTOR);
229 }
230 }
231 }
232 }
233
234 for (Index = 0; Index < HandleCount; Index++) {
235 Status = gBS->HandleProtocol (
236 HandleBuffer[Index],
237 &gEfiLoadedImageProtocolGuid,
238 (VOID **)&LoadedImageProtocol
239 );
240 if (EFI_ERROR (Status)) {
241 continue;
242 }
243
244 if (IsAddressInMmram ((EFI_PHYSICAL_ADDRESS)(UINTN)(LoadedImageProtocol->ImageBase), MmramRanges, MmramRangeCount)) {
245 continue;
246 }
247
248 ZeroMem (&TempPrmModuleImageContext, sizeof (TempPrmModuleImageContext));
249 TempPrmModuleImageContext.PeCoffImageContext.Handle = LoadedImageProtocol->ImageBase;
250 TempPrmModuleImageContext.PeCoffImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
251
252 Status = PeCoffLoaderGetImageInfo (&TempPrmModuleImageContext.PeCoffImageContext);
253 if (EFI_ERROR (Status) || (TempPrmModuleImageContext.PeCoffImageContext.ImageError != IMAGE_ERROR_SUCCESS)) {
254 DEBUG ((
255 DEBUG_WARN,
256 "%a %a: ImageHandle 0x%016lx is not a valid PE/COFF image. It cannot be considered a PRM module.\n",
257 _DBGMSGID_,
258 __func__,
259 (EFI_PHYSICAL_ADDRESS)(UINTN)LoadedImageProtocol->ImageBase
260 ));
261 continue;
262 }
263
264 if (TempPrmModuleImageContext.PeCoffImageContext.IsTeImage) {
265 // A PRM Module is not allowed to be a TE image
266 continue;
267 }
268
269 // Attempt to find an export table in this image
271 LoadedImageProtocol->ImageBase,
272 &TempPrmModuleImageContext.PeCoffImageContext,
273 &TempPrmModuleImageContext.ExportDirectory
274 );
275 if (EFI_ERROR (Status)) {
276 continue;
277 }
278
279 // Attempt to find the PRM Module Export Descriptor in the export table
281 TempPrmModuleImageContext.ExportDirectory,
282 &TempPrmModuleImageContext.PeCoffImageContext,
283 &TempPrmModuleImageContext.ExportDescriptor
284 );
285 if (EFI_ERROR (Status) || (TempPrmModuleImageContext.ExportDescriptor == NULL)) {
286 continue;
287 }
288
289 // A PRM Module Export Descriptor was successfully found, this is considered a PRM Module.
290
291 //
292 // Create a new PRM Module image context node
293 //
294 PrmModuleImageContextListEntry = CreateNewPrmModuleImageContextListEntry ();
295 if (PrmModuleImageContextListEntry == NULL) {
296 return EFI_OUT_OF_RESOURCES;
297 }
298
299 CopyMem (
300 &PrmModuleImageContextListEntry->Context,
301 &TempPrmModuleImageContext,
302 sizeof (PrmModuleImageContextListEntry->Context)
303 );
304 InsertTailList (&mPrmModuleList, &PrmModuleImageContextListEntry->Link);
305 PrmHandlerCount += TempPrmModuleImageContext.ExportDescriptor->Header.NumberPrmHandlers;
306 PrmModuleCount++;
307 DEBUG ((DEBUG_INFO, "%a %a: New PRM Module inserted into list to be processed.\n", _DBGMSGID_, __func__));
308 }
309
310 if (HandlerCount != NULL) {
311 *HandlerCount = PrmHandlerCount;
312 }
313
314 if (ModuleCount != NULL) {
315 *ModuleCount = PrmModuleCount;
316 }
317
318 if (MmramRanges != NULL) {
319 FreePool (MmramRanges);
320 }
321
322 return EFI_SUCCESS;
323}
324
337EFIAPI
339 IN EFI_HANDLE ImageHandle,
340 IN EFI_SYSTEM_TABLE *SystemTable
341 )
342{
343 LIST_ENTRY *Link;
344 LIST_ENTRY *NextLink;
346
347 if (IsListEmpty (&mPrmModuleList)) {
348 return EFI_SUCCESS;
349 }
350
351 Link = GetFirstNode (&mPrmModuleList);
352 while (!IsNull (&mPrmModuleList, Link)) {
353 ListEntry = CR (Link, PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY, Link, PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY_SIGNATURE);
354 NextLink = GetNextNode (&mPrmModuleList, Link);
355
356 RemoveEntryList (Link);
357 FreePool (ListEntry);
358
359 Link = NextLink;
360 }
361
362 return EFI_SUCCESS;
363}
364
377EFIAPI
379 IN EFI_HANDLE ImageHandle,
380 IN EFI_SYSTEM_TABLE *SystemTable
381 )
382{
383 InitializeListHead (&mPrmModuleList);
384
385 return EFI_SUCCESS;
386}
UINT64 UINTN
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
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 GetNextPrmModuleEntry(IN OUT PRM_MODULE_IMAGE_CONTEXT **ModuleImageContext)
PRM_MODULE_IMAGE_CONTEXT_LIST_ENTRY * CreateNewPrmModuleImageContextListEntry(VOID)
BOOLEAN EFIAPI IsAddressInMmram(IN EFI_PHYSICAL_ADDRESS Address, IN EFI_MMRAM_DESCRIPTOR *MmramRanges, IN UINTN MmramRangeCount)
EFI_STATUS EFIAPI DiscoverPrmModules(OUT UINTN *ModuleCount OPTIONAL, OUT UINTN *HandlerCount OPTIONAL)
EFI_STATUS EFIAPI PrmModuleDiscoveryLibConstructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
EFI_STATUS EFIAPI PrmModuleDiscoveryLibDestructor(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define BASE_CR(Record, TYPE, Field)
Definition: Base.h:891
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define CR(Record, TYPE, Field, TestSignature)
Definition: DebugLib.h:659
RETURN_STATUS EFIAPI PeCoffLoaderGetImageInfo(IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext)
Definition: BasePeCoff.c:577
RETURN_STATUS EFIAPI PeCoffLoaderImageReadFromMemory(IN VOID *FileHandle, IN UINTN FileOffset, IN OUT UINTN *ReadSize, OUT VOID *Buffer)
Definition: BasePeCoff.c:1992
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
EFI_STATUS GetExportDirectoryInPeCoffImage(IN VOID *Image, IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext, OUT EFI_IMAGE_EXPORT_DIRECTORY **ImageExportDirectory)
EFI_STATUS GetPrmModuleExportDescriptorTable(IN EFI_IMAGE_EXPORT_DIRECTORY *ImageExportDirectory, IN PE_COFF_LOADER_IMAGE_CONTEXT *PeCoffLoaderImageContext, OUT PRM_MODULE_EXPORT_DESCRIPTOR_STRUCT **ExportDescriptor)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
@ ByProtocol
Definition: UefiSpec.h:1518
VOID * ImageBase
The base address at which the image was loaded.
Definition: LoadedImage.h:67
PE_COFF_LOADER_READ_FILE ImageRead
Definition: PeCoffLib.h:100