]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Core/Pei/Image/Image.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Core / Pei / Image / Image.c
CommitLineData
615c6dd0 1/** @file\r
b1f6a7c6 2 Pei Core Load Image Support\r
54ea99a7 3\r
ab2b389e 4Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
192f6d4c 6\r
615c6dd0 7**/\r
192f6d4c 8\r
0d516397 9#include "PeiMain.h"\r
192f6d4c 10\r
1436aea4 11EFI_PEI_LOAD_FILE_PPI mPeiLoadImagePpi = {\r
b0d803fe 12 PeiLoadImageLoadImageWrapper\r
13};\r
14\r
1436aea4 15EFI_PEI_PPI_DESCRIPTOR gPpiLoadFilePpiList = {\r
b0d803fe 16 (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
17 &gEfiPeiLoadFilePpiGuid,\r
18 &mPeiLoadImagePpi\r
19};\r
20\r
b1f6a7c6 21/**\r
22\r
25973fc3 23 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file.\r
24 The function is used for XIP code to have optimized memory copy.\r
b1f6a7c6 25\r
26 @param FileHandle - The handle to the PE/COFF file\r
27 @param FileOffset - The offset, in bytes, into the file to read\r
28 @param ReadSize - The number of bytes to read from the file starting at FileOffset\r
29 @param Buffer - A pointer to the buffer to read the data into.\r
30\r
31 @return EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
32\r
33**/\r
b0d803fe 34EFI_STATUS\r
35EFIAPI\r
36PeiImageRead (\r
1436aea4
MK
37 IN VOID *FileHandle,\r
38 IN UINTN FileOffset,\r
39 IN UINTN *ReadSize,\r
40 OUT VOID *Buffer\r
b0d803fe 41 )\r
b0d803fe 42{\r
1436aea4
MK
43 CHAR8 *Destination8;\r
44 CHAR8 *Source8;\r
d1102dba 45\r
1436aea4
MK
46 Destination8 = Buffer;\r
47 Source8 = (CHAR8 *)((UINTN)FileHandle + FileOffset);\r
25973fc3 48 if (Destination8 != Source8) {\r
49 CopyMem (Destination8, Source8, *ReadSize);\r
50 }\r
51\r
52 return EFI_SUCCESS;\r
53}\r
54\r
54ea99a7 55/**\r
2048c585
GM
56 To check memory usage bit map array to figure out if the memory range the image will be loaded in is available or not. If\r
57 memory range is available, the function will mark the corresponding bits to 1 which indicates the memory range is used.\r
d1102dba
LG
58 The function is only invoked when load modules at fixed address feature is enabled.\r
59\r
54ea99a7 60 @param Private Pointer to the private data passed in from caller\r
2048c585 61 @param ImageBase The base address the image will be loaded at.\r
54ea99a7 62 @param ImageSize The size of the image\r
d1102dba 63\r
54ea99a7 64 @retval EFI_SUCCESS The memory range the image will be loaded in is available\r
65 @retval EFI_NOT_FOUND The memory range the image will be loaded in is not available\r
66**/\r
67EFI_STATUS\r
68CheckAndMarkFixLoadingMemoryUsageBitMap (\r
1436aea4
MK
69 IN PEI_CORE_INSTANCE *Private,\r
70 IN EFI_PHYSICAL_ADDRESS ImageBase,\r
71 IN UINT32 ImageSize\r
54ea99a7 72 )\r
73{\r
1436aea4
MK
74 UINT32 DxeCodePageNumber;\r
75 UINT64 ReservedCodeSize;\r
76 EFI_PHYSICAL_ADDRESS PeiCodeBase;\r
77 UINT32 BaseOffsetPageNumber;\r
78 UINT32 TopOffsetPageNumber;\r
79 UINT32 Index;\r
80 UINT64 *MemoryUsageBitMap;\r
81\r
82 //\r
83 // The reserved code range includes RuntimeCodePage range, Boot time code range and PEI code range.\r
84 //\r
85 DxeCodePageNumber = PcdGet32 (PcdLoadFixAddressBootTimeCodePageNumber);\r
86 DxeCodePageNumber += PcdGet32 (PcdLoadFixAddressRuntimeCodePageNumber);\r
87 ReservedCodeSize = EFI_PAGES_TO_SIZE (DxeCodePageNumber + PcdGet32 (PcdLoadFixAddressPeiCodePageNumber));\r
88 PeiCodeBase = Private->LoadModuleAtFixAddressTopAddress - ReservedCodeSize;\r
89\r
90 //\r
91 // Test the memory range for loading the image in the PEI code range.\r
92 //\r
93 if (((Private->LoadModuleAtFixAddressTopAddress - EFI_PAGES_TO_SIZE (DxeCodePageNumber)) < (ImageBase + ImageSize)) ||\r
94 (PeiCodeBase > ImageBase))\r
95 {\r
96 return EFI_NOT_FOUND;\r
97 }\r
98\r
99 //\r
100 // Test if the memory is available or not.\r
101 //\r
102 MemoryUsageBitMap = Private->PeiCodeMemoryRangeUsageBitMap;\r
103 BaseOffsetPageNumber = EFI_SIZE_TO_PAGES ((UINT32)(ImageBase - PeiCodeBase));\r
104 TopOffsetPageNumber = EFI_SIZE_TO_PAGES ((UINT32)(ImageBase + ImageSize - PeiCodeBase));\r
105 for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index++) {\r
106 if ((MemoryUsageBitMap[Index / 64] & LShiftU64 (1, (Index % 64))) != 0) {\r
107 //\r
108 // This page is already used.\r
109 //\r
110 return EFI_NOT_FOUND;\r
111 }\r
112 }\r
113\r
114 //\r
115 // Being here means the memory range is available. So mark the bits for the memory range\r
116 //\r
117 for (Index = BaseOffsetPageNumber; Index < TopOffsetPageNumber; Index++) {\r
118 MemoryUsageBitMap[Index / 64] |= LShiftU64 (1, (Index % 64));\r
119 }\r
120\r
121 return EFI_SUCCESS;\r
54ea99a7 122}\r
1436aea4 123\r
54ea99a7 124/**\r
125\r
2048c585 126 Get the fixed loading address from image header assigned by build tool. This function only be called\r
54ea99a7 127 when Loading module at Fixed address feature enabled.\r
128\r
129 @param ImageContext Pointer to the image context structure that describes the PE/COFF\r
130 image that needs to be examined by this function.\r
131 @param Private Pointer to the private data passed in from caller\r
132\r
133 @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools .\r
2048c585 134 @retval EFI_NOT_FOUND The image has no assigned fixed loading address.\r
b0d803fe 135\r
54ea99a7 136**/\r
137EFI_STATUS\r
1436aea4 138GetPeCoffImageFixLoadingAssignedAddress (\r
54ea99a7 139 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
140 IN PEI_CORE_INSTANCE *Private\r
141 )\r
142{\r
1436aea4
MK
143 UINTN SectionHeaderOffset;\r
144 EFI_STATUS Status;\r
145 EFI_IMAGE_SECTION_HEADER SectionHeader;\r
146 EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;\r
147 EFI_PHYSICAL_ADDRESS FixLoadingAddress;\r
148 UINT16 Index;\r
149 UINTN Size;\r
150 UINT16 NumberOfSections;\r
151 UINT64 ValueInSectionHeader;\r
152\r
153 FixLoadingAddress = 0;\r
154 Status = EFI_NOT_FOUND;\r
155\r
156 //\r
157 // Get PeHeader pointer\r
158 //\r
159 ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8 *)ImageContext->Handle + ImageContext->PeCoffHeaderOffset);\r
160 if (ImageContext->IsTeImage) {\r
161 //\r
162 // for TE image, the fix loading address is saved in first section header that doesn't point\r
163 // to code section.\r
164 //\r
165 SectionHeaderOffset = sizeof (EFI_TE_IMAGE_HEADER);\r
166 NumberOfSections = ImgHdr->Te.NumberOfSections;\r
167 } else {\r
168 SectionHeaderOffset = ImageContext->PeCoffHeaderOffset +\r
169 sizeof (UINT32) +\r
170 sizeof (EFI_IMAGE_FILE_HEADER) +\r
171 ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader;\r
172 NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections;\r
173 }\r
174\r
175 //\r
176 // Get base address from the first section header that doesn't point to code section.\r
177 //\r
178 for (Index = 0; Index < NumberOfSections; Index++) {\r
179 //\r
180 // Read section header from file\r
181 //\r
182 Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
183 Status = ImageContext->ImageRead (\r
184 ImageContext->Handle,\r
185 SectionHeaderOffset,\r
186 &Size,\r
187 &SectionHeader\r
188 );\r
189 if (EFI_ERROR (Status)) {\r
190 return Status;\r
191 }\r
192\r
193 Status = EFI_NOT_FOUND;\r
194\r
195 if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {\r
196 //\r
197 // Build tool will save the address in PointerToRelocations & PointerToLineNumbers fields in the first section header\r
198 // that doesn't point to code section in image header, as well as ImageBase field of image header. A notable thing is\r
199 // that for PEIM, the value in ImageBase field may not be equal to the value in PointerToRelocations & PointerToLineNumbers because\r
200 // for XIP PEIM, ImageBase field holds the image base address running on the Flash. And PointerToRelocations & PointerToLineNumbers\r
201 // hold the image base address when it is shadow to the memory. And there is an assumption that when the feature is enabled, if a\r
202 // module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers fields should NOT be Zero, or\r
203 // else, these 2 fields should be set to Zero\r
204 //\r
205 ValueInSectionHeader = ReadUnaligned64 ((UINT64 *)&SectionHeader.PointerToRelocations);\r
206 if (ValueInSectionHeader != 0) {\r
207 //\r
208 // Found first section header that doesn't point to code section.\r
209 //\r
210 if ((INT64)PcdGet64 (PcdLoadModuleAtFixAddressEnable) > 0) {\r
211 //\r
212 // When LMFA feature is configured as Load Module at Fixed Absolute Address mode, PointerToRelocations & PointerToLineNumbers field\r
213 // hold the absolute address of image base running in memory\r
214 //\r
215 FixLoadingAddress = ValueInSectionHeader;\r
216 } else {\r
217 //\r
218 // When LMFA feature is configured as Load Module at Fixed offset mode, PointerToRelocations & PointerToLineNumbers field\r
219 // hold the offset relative to a platform-specific top address.\r
220 //\r
221 FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(Private->LoadModuleAtFixAddressTopAddress + (INT64)ValueInSectionHeader);\r
222 }\r
223\r
224 //\r
225 // Check if the memory range is available.\r
226 //\r
227 Status = CheckAndMarkFixLoadingMemoryUsageBitMap (Private, FixLoadingAddress, (UINT32)ImageContext->ImageSize);\r
228 if (!EFI_ERROR (Status)) {\r
229 //\r
230 // The assigned address is valid. Return the specified loading address\r
231 //\r
232 ImageContext->ImageAddress = FixLoadingAddress;\r
233 }\r
234 }\r
235\r
236 break;\r
237 }\r
238\r
239 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
240 }\r
241\r
242 DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address 0x%11p. Status= %r \n", (VOID *)(UINTN)FixLoadingAddress, Status));\r
243 return Status;\r
54ea99a7 244}\r
1436aea4 245\r
b1f6a7c6 246/**\r
247\r
248 Loads and relocates a PE/COFF image into memory.\r
341a658f 249 If the image is not relocatable, it will not be loaded into memory and be loaded as XIP image.\r
b1f6a7c6 250\r
3d44658c 251 @param FileHandle - Pointer to the FFS file header of the image.\r
b1f6a7c6 252 @param Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated\r
253 @param ImageAddress - The base address of the relocated PE/COFF image\r
254 @param ImageSize - The size of the relocated PE/COFF image\r
255 @param EntryPoint - The entry point of the relocated PE/COFF image\r
256\r
257 @retval EFI_SUCCESS The file was loaded and relocated\r
258 @retval EFI_OUT_OF_RESOURCES There was not enough memory to load and relocate the PE/COFF file\r
d1102dba 259 @retval EFI_WARN_BUFFER_TOO_SMALL\r
5d7f3126
LG
260 There is not enough heap to allocate the requested size.\r
261 This will not prevent the XIP image from being invoked.\r
b1f6a7c6 262\r
263**/\r
b0d803fe 264EFI_STATUS\r
265LoadAndRelocatePeCoffImage (\r
1436aea4
MK
266 IN EFI_PEI_FILE_HANDLE FileHandle,\r
267 IN VOID *Pe32Data,\r
268 OUT EFI_PHYSICAL_ADDRESS *ImageAddress,\r
269 OUT UINT64 *ImageSize,\r
270 OUT EFI_PHYSICAL_ADDRESS *EntryPoint\r
b0d803fe 271 )\r
b0d803fe 272{\r
1436aea4
MK
273 EFI_STATUS Status;\r
274 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
275 PEI_CORE_INSTANCE *Private;\r
276 UINT64 AlignImageSize;\r
277 BOOLEAN IsXipImage;\r
278 EFI_STATUS ReturnStatus;\r
279 BOOLEAN IsS3Boot;\r
280 BOOLEAN IsPeiModule;\r
281 BOOLEAN IsRegisterForShadow;\r
282 EFI_FV_FILE_INFO FileInfo;\r
43ada17c 283\r
284 Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
b0d803fe 285\r
5d7f3126
LG
286 ReturnStatus = EFI_SUCCESS;\r
287 IsXipImage = FALSE;\r
b0d803fe 288 ZeroMem (&ImageContext, sizeof (ImageContext));\r
1436aea4 289 ImageContext.Handle = Pe32Data;\r
40a7b235 290 ImageContext.ImageRead = PeiImageRead;\r
b0d803fe 291\r
3d7b0992 292 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
b0d803fe 293 if (EFI_ERROR (Status)) {\r
294 return Status;\r
295 }\r
d1102dba 296\r
3d44658c 297 //\r
d39d1260 298 // Initialize local IsS3Boot and IsRegisterForShadow variable\r
3d44658c
LG
299 //\r
300 IsS3Boot = FALSE;\r
301 if (Private->HobList.HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME) {\r
302 IsS3Boot = TRUE;\r
303 }\r
1436aea4 304\r
3d44658c 305 IsRegisterForShadow = FALSE;\r
1436aea4
MK
306 if ( (Private->CurrentFileHandle == FileHandle)\r
307 && (Private->Fv[Private->CurrentPeimFvCount].PeimState[Private->CurrentPeimCount] == PEIM_STATE_REGISTER_FOR_SHADOW))\r
308 {\r
3d44658c
LG
309 IsRegisterForShadow = TRUE;\r
310 }\r
311\r
5d7f3126
LG
312 //\r
313 // XIP image that ImageAddress is same to Image handle.\r
314 //\r
1436aea4 315 if (ImageContext.ImageAddress == (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data) {\r
5d7f3126
LG
316 IsXipImage = TRUE;\r
317 }\r
318\r
609730ef
LG
319 //\r
320 // Get file type first\r
321 //\r
322 Status = PeiServicesFfsGetFileInfo (FileHandle, &FileInfo);\r
323 ASSERT_EFI_ERROR (Status);\r
d1102dba 324\r
609730ef
LG
325 //\r
326 // Check whether the file type is PEI module.\r
327 //\r
328 IsPeiModule = FALSE;\r
1436aea4
MK
329 if ((FileInfo.FileType == EFI_FV_FILETYPE_PEI_CORE) ||\r
330 (FileInfo.FileType == EFI_FV_FILETYPE_PEIM) ||\r
331 (FileInfo.FileType == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER))\r
332 {\r
609730ef
LG
333 IsPeiModule = TRUE;\r
334 }\r
335\r
b0d803fe 336 //\r
9626a87e
LG
337 // When Image has no reloc section, it can't be relocated into memory.\r
338 //\r
9bedaec0
MK
339 if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) &&\r
340 ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||\r
341 (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) ||\r
342 (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))\r
1436aea4
MK
343 )\r
344 {\r
345 DEBUG ((DEBUG_INFO|DEBUG_LOAD, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN)Pe32Data));\r
9626a87e 346 }\r
414bdfb6 347\r
341a658f
LG
348 //\r
349 // Set default base address to current image address.\r
350 //\r
1436aea4 351 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data;\r
54ea99a7 352\r
9626a87e 353 //\r
3d44658c
LG
354 // Allocate Memory for the image when memory is ready, and image is relocatable.\r
355 // On normal boot, PcdShadowPeimOnBoot decides whether load PEIM or PeiCore into memory.\r
356 // On S3 boot, PcdShadowPeimOnS3Boot decides whether load PEIM or PeiCore into memory.\r
b0d803fe 357 //\r
9bedaec0
MK
358 if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) &&\r
359 ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||\r
360 (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) ||\r
361 (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))\r
1436aea4
MK
362 )\r
363 {\r
935efc21
ED
364 //\r
365 // Allocate more buffer to avoid buffer overflow.\r
366 //\r
367 if (ImageContext.IsTeImage) {\r
1436aea4 368 AlignImageSize = ImageContext.ImageSize + ((EFI_TE_IMAGE_HEADER *)Pe32Data)->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);\r
935efc21
ED
369 } else {\r
370 AlignImageSize = ImageContext.ImageSize;\r
371 }\r
372\r
373 if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {\r
374 AlignImageSize += ImageContext.SectionAlignment;\r
375 }\r
376\r
1436aea4
MK
377 if ((PcdGet64 (PcdLoadModuleAtFixAddressEnable) != 0) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
378 Status = GetPeCoffImageFixLoadingAssignedAddress (&ImageContext, Private);\r
379 if (EFI_ERROR (Status)) {\r
87000d77 380 DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED ERROR: Failed to load module at fixed address. \n"));\r
54ea99a7 381 //\r
d39d1260 382 // The PEIM is not assigned valid address, try to allocate page to load it.\r
54ea99a7 383 //\r
1436aea4
MK
384 Status = PeiServicesAllocatePages (\r
385 EfiBootServicesCode,\r
386 EFI_SIZE_TO_PAGES ((UINT32)AlignImageSize),\r
387 &ImageContext.ImageAddress\r
388 );\r
54ea99a7 389 }\r
390 } else {\r
1436aea4
MK
391 Status = PeiServicesAllocatePages (\r
392 EfiBootServicesCode,\r
393 EFI_SIZE_TO_PAGES ((UINT32)AlignImageSize),\r
394 &ImageContext.ImageAddress\r
395 );\r
54ea99a7 396 }\r
1436aea4 397\r
a0ffd7a9 398 if (!EFI_ERROR (Status)) {\r
5d7f3126
LG
399 //\r
400 // Adjust the Image Address to make sure it is section alignment.\r
401 //\r
402 if (ImageContext.SectionAlignment > EFI_PAGE_SIZE) {\r
403 ImageContext.ImageAddress =\r
1436aea4
MK
404 (ImageContext.ImageAddress + ImageContext.SectionAlignment - 1) &\r
405 ~((UINTN)ImageContext.SectionAlignment - 1);\r
5d7f3126 406 }\r
1436aea4 407\r
5d7f3126
LG
408 //\r
409 // Fix alignment requirement when Load IPF TeImage into memory.\r
410 // Skip the reserved space for the stripped PeHeader when load TeImage into memory.\r
411 //\r
412 if (ImageContext.IsTeImage) {\r
413 ImageContext.ImageAddress = ImageContext.ImageAddress +\r
1436aea4 414 ((EFI_TE_IMAGE_HEADER *)Pe32Data)->StrippedSize -\r
5d7f3126
LG
415 sizeof (EFI_TE_IMAGE_HEADER);\r
416 }\r
417 } else {\r
418 //\r
419 // No enough memory resource.\r
420 //\r
421 if (IsXipImage) {\r
422 //\r
423 // XIP image can still be invoked.\r
424 //\r
1436aea4
MK
425 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data;\r
426 ReturnStatus = EFI_WARN_BUFFER_TOO_SMALL;\r
5d7f3126
LG
427 } else {\r
428 //\r
429 // Non XIP image can't be loaded because no enough memory is allocated.\r
430 //\r
431 ASSERT (FALSE);\r
432 return EFI_OUT_OF_RESOURCES;\r
433 }\r
43ada17c 434 }\r
4e844595 435 }\r
b0d803fe 436\r
437 //\r
438 // Load the image to our new buffer\r
439 //\r
3d7b0992 440 Status = PeCoffLoaderLoadImage (&ImageContext);\r
b0d803fe 441 if (EFI_ERROR (Status)) {\r
63c677e2 442 if (ImageContext.ImageError == IMAGE_ERROR_INVALID_SECTION_ALIGNMENT) {\r
1436aea4 443 DEBUG ((DEBUG_ERROR, "PEIM Image Address 0x%11p doesn't meet with section alignment 0x%x.\n", (VOID *)(UINTN)ImageContext.ImageAddress, ImageContext.SectionAlignment));\r
63c677e2 444 }\r
1436aea4 445\r
b0d803fe 446 return Status;\r
447 }\r
1436aea4 448\r
b0d803fe 449 //\r
450 // Relocate the image in our new buffer\r
451 //\r
3d7b0992 452 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
b0d803fe 453 if (EFI_ERROR (Status)) {\r
454 return Status;\r
455 }\r
456\r
457 //\r
458 // Flush the instruction cache so the image data is written before we execute it\r
459 //\r
1436aea4 460 if (ImageContext.ImageAddress != (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data) {\r
43ada17c 461 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
462 }\r
b0d803fe 463\r
464 *ImageAddress = ImageContext.ImageAddress;\r
465 *ImageSize = ImageContext.ImageSize;\r
466 *EntryPoint = ImageContext.EntryPoint;\r
467\r
5d7f3126 468 return ReturnStatus;\r
b0d803fe 469}\r
470\r
9bedaec0
MK
471/**\r
472 Loads and relocates a PE/COFF image in place.\r
473\r
474 @param Pe32Data The base address of the PE/COFF file that is to be loaded and relocated\r
475 @param ImageAddress The base address of the relocated PE/COFF image\r
476\r
477 @retval EFI_SUCCESS The file was loaded and relocated.\r
478 @retval Others The file not be loaded and error occurred.\r
479\r
480**/\r
481EFI_STATUS\r
482LoadAndRelocatePeCoffImageInPlace (\r
1436aea4
MK
483 IN VOID *Pe32Data,\r
484 IN VOID *ImageAddress\r
9bedaec0
MK
485 )\r
486{\r
1436aea4
MK
487 EFI_STATUS Status;\r
488 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
9bedaec0
MK
489\r
490 ZeroMem (&ImageContext, sizeof (ImageContext));\r
1436aea4 491 ImageContext.Handle = Pe32Data;\r
9bedaec0
MK
492 ImageContext.ImageRead = PeiImageRead;\r
493\r
494 Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
495 if (EFI_ERROR (Status)) {\r
496 ASSERT_EFI_ERROR (Status);\r
497 return Status;\r
498 }\r
499\r
1436aea4 500 ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN)ImageAddress;\r
9bedaec0
MK
501\r
502 //\r
503 // Load the image in place\r
504 //\r
505 Status = PeCoffLoaderLoadImage (&ImageContext);\r
506 if (EFI_ERROR (Status)) {\r
507 ASSERT_EFI_ERROR (Status);\r
508 return Status;\r
509 }\r
510\r
511 //\r
512 // Relocate the image in place\r
513 //\r
514 Status = PeCoffLoaderRelocateImage (&ImageContext);\r
515 if (EFI_ERROR (Status)) {\r
516 ASSERT_EFI_ERROR (Status);\r
517 return Status;\r
518 }\r
519\r
520 //\r
521 // Flush the instruction cache so the image data is written before we execute it\r
522 //\r
1436aea4 523 if (ImageContext.ImageAddress != (EFI_PHYSICAL_ADDRESS)(UINTN)Pe32Data) {\r
9bedaec0
MK
524 InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
525 }\r
526\r
527 return Status;\r
528}\r
529\r
530/**\r
531 Find the PE32 Data for an FFS file.\r
532\r
533 @param FileHandle Pointer to the FFS file header of the image.\r
534 @param Pe32Data Pointer to a (VOID *) PE32 Data pointer.\r
535\r
536 @retval EFI_SUCCESS Image is successfully loaded.\r
537 @retval EFI_NOT_FOUND Fail to locate PE32 Data.\r
538\r
539**/\r
540EFI_STATUS\r
541PeiGetPe32Data (\r
542 IN EFI_PEI_FILE_HANDLE FileHandle,\r
543 OUT VOID **Pe32Data\r
544 )\r
545{\r
1436aea4
MK
546 EFI_STATUS Status;\r
547 EFI_SECTION_TYPE SearchType1;\r
548 EFI_SECTION_TYPE SearchType2;\r
549 UINT32 AuthenticationState;\r
9bedaec0
MK
550\r
551 *Pe32Data = NULL;\r
552\r
553 if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {\r
554 SearchType1 = EFI_SECTION_TE;\r
555 SearchType2 = EFI_SECTION_PE32;\r
556 } else {\r
557 SearchType1 = EFI_SECTION_PE32;\r
558 SearchType2 = EFI_SECTION_TE;\r
559 }\r
560\r
561 //\r
562 // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst\r
563 // is true, TE will be searched first).\r
564 //\r
565 Status = PeiServicesFfsFindSectionData3 (\r
566 SearchType1,\r
567 0,\r
568 FileHandle,\r
569 Pe32Data,\r
570 &AuthenticationState\r
571 );\r
572 //\r
573 // If we didn't find a first exe section, try to find the second exe section.\r
574 //\r
575 if (EFI_ERROR (Status)) {\r
576 Status = PeiServicesFfsFindSectionData3 (\r
577 SearchType2,\r
578 0,\r
579 FileHandle,\r
580 Pe32Data,\r
581 &AuthenticationState\r
582 );\r
583 }\r
1436aea4 584\r
9bedaec0
MK
585 return Status;\r
586}\r
587\r
b1f6a7c6 588/**\r
54ea99a7 589 Loads a PEIM into memory for subsequent execution. If there are compressed\r
590 images or images that need to be relocated into memory for performance reasons,\r
ed299e3c 591 this service performs that transformation.\r
b1f6a7c6 592\r
ed299e3c 593 @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
b1f6a7c6 594 @param FileHandle Pointer to the FFS file header of the image.\r
595 @param ImageAddressArg Pointer to PE/TE image.\r
596 @param ImageSizeArg Size of PE/TE image.\r
597 @param EntryPoint Pointer to entry point of specified image file for output.\r
598 @param AuthenticationState - Pointer to attestation authentication state of image.\r
599\r
ed299e3c
LG
600 @retval EFI_SUCCESS Image is successfully loaded.\r
601 @retval EFI_NOT_FOUND Fail to locate necessary PPI.\r
602 @retval EFI_UNSUPPORTED Image Machine Type is not supported.\r
d1102dba 603 @retval EFI_WARN_BUFFER_TOO_SMALL\r
5d7f3126
LG
604 There is not enough heap to allocate the requested size.\r
605 This will not prevent the XIP image from being invoked.\r
b1f6a7c6 606\r
607**/\r
b0d803fe 608EFI_STATUS\r
609PeiLoadImageLoadImage (\r
1436aea4
MK
610 IN CONST EFI_PEI_SERVICES **PeiServices,\r
611 IN EFI_PEI_FILE_HANDLE FileHandle,\r
612 OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL,\r
613 OUT UINT64 *ImageSizeArg OPTIONAL,\r
614 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,\r
615 OUT UINT32 *AuthenticationState\r
b0d803fe 616 )\r
192f6d4c 617{\r
1436aea4
MK
618 EFI_STATUS Status;\r
619 VOID *Pe32Data;\r
620 EFI_PHYSICAL_ADDRESS ImageAddress;\r
621 UINT64 ImageSize;\r
622 EFI_PHYSICAL_ADDRESS ImageEntryPoint;\r
623 UINT16 Machine;\r
624 EFI_SECTION_TYPE SearchType1;\r
625 EFI_SECTION_TYPE SearchType2;\r
192f6d4c 626\r
3d7b0992
LG
627 *EntryPoint = 0;\r
628 ImageSize = 0;\r
b0d803fe 629 *AuthenticationState = 0;\r
192f6d4c 630\r
3076397e 631 if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {\r
632 SearchType1 = EFI_SECTION_TE;\r
633 SearchType2 = EFI_SECTION_PE32;\r
634 } else {\r
635 SearchType1 = EFI_SECTION_PE32;\r
636 SearchType2 = EFI_SECTION_TE;\r
637 }\r
1b620adb 638\r
192f6d4c 639 //\r
54ea99a7 640 // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst\r
3076397e 641 // is true, TE will be searched first).\r
192f6d4c 642 //\r
c7935105 643 Status = PeiServicesFfsFindSectionData3 (\r
3076397e 644 SearchType1,\r
c7935105 645 0,\r
b0d803fe 646 FileHandle,\r
c7935105
SZ
647 &Pe32Data,\r
648 AuthenticationState\r
192f6d4c 649 );\r
650 //\r
3076397e 651 // If we didn't find a first exe section, try to find the second exe section.\r
192f6d4c 652 //\r
653 if (EFI_ERROR (Status)) {\r
c7935105 654 Status = PeiServicesFfsFindSectionData3 (\r
3076397e 655 SearchType2,\r
c7935105 656 0,\r
b0d803fe 657 FileHandle,\r
c7935105
SZ
658 &Pe32Data,\r
659 AuthenticationState\r
192f6d4c 660 );\r
b0d803fe 661 if (EFI_ERROR (Status)) {\r
192f6d4c 662 //\r
c7935105 663 // PEI core only carry the loader function for TE and PE32 executables\r
b0d803fe 664 // If this two section does not exist, just return.\r
192f6d4c 665 //\r
b0d803fe 666 return Status;\r
667 }\r
668 }\r
54ea99a7 669\r
63c677e2
LG
670 DEBUG ((DEBUG_INFO, "Loading PEIM %g\n", FileHandle));\r
671\r
43ada17c 672 //\r
673 // If memory is installed, perform the shadow operations\r
674 //\r
675 Status = LoadAndRelocatePeCoffImage (\r
1436aea4
MK
676 FileHandle,\r
677 Pe32Data,\r
678 &ImageAddress,\r
679 &ImageSize,\r
680 &ImageEntryPoint\r
681 );\r
192f6d4c 682\r
43ada17c 683 if (EFI_ERROR (Status)) {\r
684 return Status;\r
192f6d4c 685 }\r
43ada17c 686\r
687 //\r
688 // Got the entry point from the loaded Pe32Data\r
689 //\r
1436aea4 690 Pe32Data = (VOID *)((UINTN)ImageAddress);\r
43ada17c 691 *EntryPoint = ImageEntryPoint;\r
54ea99a7 692\r
3d7b0992 693 Machine = PeCoffLoaderGetMachineType (Pe32Data);\r
54ea99a7 694\r
192f6d4c 695 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {\r
8c519a56 696 if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine)) {\r
697 return EFI_UNSUPPORTED;\r
698 }\r
192f6d4c 699 }\r
700\r
b0d803fe 701 if (ImageAddressArg != NULL) {\r
702 *ImageAddressArg = ImageAddress;\r
703 }\r
704\r
705 if (ImageSizeArg != NULL) {\r
706 *ImageSizeArg = ImageSize;\r
707 }\r
54ea99a7 708\r
192f6d4c 709 DEBUG_CODE_BEGIN ();\r
1436aea4
MK
710 CHAR8 *AsciiString;\r
711 CHAR8 EfiFileName[512];\r
712 INT32 Index;\r
713 INT32 StartIndex;\r
e98cd821 714\r
1436aea4
MK
715 //\r
716 // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi\r
717 //\r
718 if (Machine != EFI_IMAGE_MACHINE_IA64) {\r
719 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint));\r
720 } else {\r
e98cd821 721 //\r
1436aea4 722 // For IPF Image, the real entry point should be print.\r
e98cd821 723 //\r
1436aea4
MK
724 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));\r
725 }\r
54ea99a7 726\r
1436aea4
MK
727 //\r
728 // Print Module Name by PeImage PDB file name.\r
729 //\r
730 AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data);\r
54ea99a7 731\r
1436aea4
MK
732 if (AsciiString != NULL) {\r
733 StartIndex = 0;\r
734 for (Index = 0; AsciiString[Index] != 0; Index++) {\r
735 if ((AsciiString[Index] == '\\') || (AsciiString[Index] == '/')) {\r
736 StartIndex = Index + 1;\r
192f6d4c 737 }\r
1436aea4 738 }\r
192f6d4c 739\r
1436aea4
MK
740 //\r
741 // Copy the PDB file name to our temporary string, and replace .pdb with .efi\r
742 // The PDB file name is limited in the range of 0~511.\r
743 // If the length is bigger than 511, trim the redundant characters to avoid overflow in array boundary.\r
744 //\r
745 for (Index = 0; Index < sizeof (EfiFileName) - 4; Index++) {\r
746 EfiFileName[Index] = AsciiString[Index + StartIndex];\r
747 if (EfiFileName[Index] == 0) {\r
748 EfiFileName[Index] = '.';\r
192f6d4c 749 }\r
77a750a5 750\r
1436aea4
MK
751 if (EfiFileName[Index] == '.') {\r
752 EfiFileName[Index + 1] = 'e';\r
753 EfiFileName[Index + 2] = 'f';\r
754 EfiFileName[Index + 3] = 'i';\r
755 EfiFileName[Index + 4] = 0;\r
756 break;\r
77a750a5 757 }\r
1436aea4 758 }\r
77a750a5 759\r
1436aea4
MK
760 if (Index == sizeof (EfiFileName) - 4) {\r
761 EfiFileName[Index] = 0;\r
192f6d4c 762 }\r
3d7b0992 763\r
1436aea4
MK
764 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "%a", EfiFileName));\r
765 }\r
766\r
192f6d4c 767 DEBUG_CODE_END ();\r
768\r
87000d77 769 DEBUG ((DEBUG_INFO | DEBUG_LOAD, "\n"));\r
192f6d4c 770\r
771 return EFI_SUCCESS;\r
b0d803fe 772}\r
773\r
b1f6a7c6 774/**\r
775 The wrapper function of PeiLoadImageLoadImage().\r
776\r
777 @param This - Pointer to EFI_PEI_LOAD_FILE_PPI.\r
778 @param FileHandle - Pointer to the FFS file header of the image.\r
779 @param ImageAddressArg - Pointer to PE/TE image.\r
780 @param ImageSizeArg - Size of PE/TE image.\r
781 @param EntryPoint - Pointer to entry point of specified image file for output.\r
782 @param AuthenticationState - Pointer to attestation authentication state of image.\r
783\r
784 @return Status of PeiLoadImageLoadImage().\r
785\r
786**/\r
b0d803fe 787EFI_STATUS\r
788EFIAPI\r
789PeiLoadImageLoadImageWrapper (\r
790 IN CONST EFI_PEI_LOAD_FILE_PPI *This,\r
791 IN EFI_PEI_FILE_HANDLE FileHandle,\r
e3917e22
MK
792 OUT EFI_PHYSICAL_ADDRESS *ImageAddressArg OPTIONAL,\r
793 OUT UINT64 *ImageSizeArg OPTIONAL,\r
b0d803fe 794 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,\r
795 OUT UINT32 *AuthenticationState\r
796 )\r
b0d803fe 797{\r
798 return PeiLoadImageLoadImage (\r
799 GetPeiServicesTablePointer (),\r
800 FileHandle,\r
801 ImageAddressArg,\r
802 ImageSizeArg,\r
803 EntryPoint,\r
804 AuthenticationState\r
805 );\r
192f6d4c 806}\r
b0d803fe 807\r
341a658f
LG
808/**\r
809 Check whether the input image has the relocation.\r
810\r
811 @param Pe32Data Pointer to the PE/COFF or TE image.\r
812\r
813 @retval TRUE Relocation is stripped.\r
814 @retval FALSE Relocation is not stripped.\r
815\r
816**/\r
817BOOLEAN\r
818RelocationIsStrip (\r
819 IN VOID *Pe32Data\r
820 )\r
821{\r
822 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
823 EFI_IMAGE_DOS_HEADER *DosHdr;\r
824\r
825 ASSERT (Pe32Data != NULL);\r
826\r
827 DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
828 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
829 //\r
830 // DOS image header is present, so read the PE header after the DOS image header.\r
831 //\r
1436aea4 832 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));\r
341a658f
LG
833 } else {\r
834 //\r
835 // DOS image header is not present, so PE header is at the image base.\r
836 //\r
837 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
838 }\r
839\r
840 //\r
841 // Three cases with regards to relocations:\r
842 // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable\r
843 // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable\r
844 // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but\r
845 // has no base relocs to apply\r
846 // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.\r
847 //\r
848 // Look at the file header to determine if relocations have been stripped, and\r
849 // save this info in the image context for later use.\r
850 //\r
851 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
852 if ((Hdr.Te->DataDirectory[0].Size == 0) && (Hdr.Te->DataDirectory[0].VirtualAddress == 0)) {\r
853 return TRUE;\r
854 } else {\r
855 return FALSE;\r
856 }\r
1436aea4 857 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
341a658f
LG
858 if ((Hdr.Pe32->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0) {\r
859 return TRUE;\r
860 } else {\r
861 return FALSE;\r
862 }\r
863 }\r
864\r
865 return FALSE;\r
866}\r
867\r
b1f6a7c6 868/**\r
ed299e3c 869 Routine to load image file for subsequent execution by LoadFile Ppi.\r
54ea99a7 870 If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE\r
ed299e3c 871 XIP image format is used.\r
b1f6a7c6 872\r
ed299e3c
LG
873 @param PeiServices - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
874 @param FileHandle - Pointer to the FFS file header of the image.\r
341a658f 875 @param PeimState - The dispatch state of the input PEIM handle.\r
ed299e3c
LG
876 @param EntryPoint - Pointer to entry point of specified image file for output.\r
877 @param AuthenticationState - Pointer to attestation authentication state of image.\r
b1f6a7c6 878\r
ed299e3c
LG
879 @retval EFI_SUCCESS - Image is successfully loaded.\r
880 @retval EFI_NOT_FOUND - Fail to locate necessary PPI\r
881 @retval Others - Fail to load file.\r
b1f6a7c6 882\r
883**/\r
b0d803fe 884EFI_STATUS\r
885PeiLoadImage (\r
1436aea4
MK
886 IN CONST EFI_PEI_SERVICES **PeiServices,\r
887 IN EFI_PEI_FILE_HANDLE FileHandle,\r
888 IN UINT8 PeimState,\r
889 OUT EFI_PHYSICAL_ADDRESS *EntryPoint,\r
890 OUT UINT32 *AuthenticationState\r
b0d803fe 891 )\r
b0d803fe 892{\r
1436aea4
MK
893 EFI_STATUS PpiStatus;\r
894 EFI_STATUS Status;\r
895 UINTN Index;\r
896 EFI_PEI_LOAD_FILE_PPI *LoadFile;\r
897 EFI_PHYSICAL_ADDRESS ImageAddress;\r
898 UINT64 ImageSize;\r
899 BOOLEAN IsStrip;\r
b0d803fe 900\r
341a658f 901 IsStrip = FALSE;\r
b0d803fe 902 //\r
903 // If any instances of PEI_LOAD_FILE_PPI are installed, they are called.\r
904 // one at a time, until one reports EFI_SUCCESS.\r
905 //\r
906 Index = 0;\r
907 do {\r
908 PpiStatus = PeiServicesLocatePpi (\r
909 &gEfiPeiLoadFilePpiGuid,\r
910 Index,\r
911 NULL,\r
912 (VOID **)&LoadFile\r
913 );\r
914 if (!EFI_ERROR (PpiStatus)) {\r
915 Status = LoadFile->LoadFile (\r
1436aea4
MK
916 LoadFile,\r
917 FileHandle,\r
918 &ImageAddress,\r
919 &ImageSize,\r
920 EntryPoint,\r
921 AuthenticationState\r
922 );\r
923 if (!EFI_ERROR (Status) || (Status == EFI_WARN_BUFFER_TOO_SMALL)) {\r
341a658f
LG
924 //\r
925 // The shadowed PEIM must be relocatable.\r
926 //\r
c2c4199b 927 if (PeimState == PEIM_STATE_REGISTER_FOR_SHADOW) {\r
1436aea4 928 IsStrip = RelocationIsStrip ((VOID *)(UINTN)ImageAddress);\r
341a658f
LG
929 ASSERT (!IsStrip);\r
930 if (IsStrip) {\r
931 return EFI_UNSUPPORTED;\r
932 }\r
933 }\r
934\r
db0b7ad5
LG
935 //\r
936 // The image to be started must have the machine type supported by PeiCore.\r
937 //\r
1436aea4
MK
938 ASSERT (EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID *)(UINTN)ImageAddress)));\r
939 if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID *)(UINTN)ImageAddress))) {\r
919df8e6
LG
940 return EFI_UNSUPPORTED;\r
941 }\r
1436aea4 942\r
5d7f3126 943 return EFI_SUCCESS;\r
b0d803fe 944 }\r
945 }\r
1436aea4 946\r
b0d803fe 947 Index++;\r
948 } while (!EFI_ERROR (PpiStatus));\r
949\r
8c519a56 950 return PpiStatus;\r
b0d803fe 951}\r
952\r
b1f6a7c6 953/**\r
b0d803fe 954\r
ed299e3c
LG
955 Install Pei Load File PPI.\r
956\r
957\r
958 @param PrivateData - Pointer to PEI_CORE_INSTANCE.\r
959 @param OldCoreData - Pointer to PEI_CORE_INSTANCE.\r
b0d803fe 960\r
b1f6a7c6 961**/\r
962VOID\r
963InitializeImageServices (\r
1436aea4
MK
964 IN PEI_CORE_INSTANCE *PrivateData,\r
965 IN PEI_CORE_INSTANCE *OldCoreData\r
b1f6a7c6 966 )\r
b0d803fe 967{\r
b0d803fe 968 if (OldCoreData == NULL) {\r
969 //\r
970 // The first time we are XIP (running from FLASH). We need to remember the\r
971 // FLASH address so we can reinstall the memory version that runs faster\r
972 //\r
973 PrivateData->XipLoadFile = &gPpiLoadFilePpiList;\r
974 PeiServicesInstallPpi (PrivateData->XipLoadFile);\r
975 } else {\r
976 //\r
54ea99a7 977 // 2nd time we are running from memory so replace the XIP version with the\r
978 // new memory version.\r
b0d803fe 979 //\r
54ea99a7 980 PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList);\r
b0d803fe 981 }\r
982}\r