Print the warning information for the image without relocation only when load it...
[efi/edk2/.git] / edk2 / MdeModulePkg / Core / Pei / Image / Image.c
1 /** @file\r
2   Pei Core Load Image Support\r
3   \r
4 Copyright (c) 2006 - 2010, Intel Corporation                                                         \r
5 All rights reserved. This program and the accompanying materials                          \r
6 are licensed and made available under the terms and conditions of the BSD License         \r
7 which accompanies this distribution.  The full text of the license may be found at        \r
8 http://opensource.org/licenses/bsd-license.php                                            \r
9                                                                                           \r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
12 \r
13 **/\r
14 \r
15 #include "PeiMain.h"\r
16 \r
17 \r
18 EFI_PEI_LOAD_FILE_PPI   mPeiLoadImagePpi = {\r
19   PeiLoadImageLoadImageWrapper\r
20 };\r
21 \r
22 \r
23 EFI_PEI_PPI_DESCRIPTOR     gPpiLoadFilePpiList = {\r
24   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
25   &gEfiPeiLoadFilePpiGuid,\r
26   &mPeiLoadImagePpi\r
27 };\r
28 \r
29 /**\r
30 \r
31   Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
32 \r
33 \r
34   @param FileHandle      - The handle to the PE/COFF file\r
35   @param FileOffset      - The offset, in bytes, into the file to read\r
36   @param ReadSize        - The number of bytes to read from the file starting at FileOffset\r
37   @param Buffer          - A pointer to the buffer to read the data into.\r
38 \r
39   @return EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
40 \r
41 **/\r
42 EFI_STATUS\r
43 EFIAPI\r
44 PeiImageRead (\r
45   IN     VOID    *FileHandle,\r
46   IN     UINTN   FileOffset,\r
47   IN     UINTN   *ReadSize,\r
48   OUT    VOID    *Buffer\r
49   )\r
50 {\r
51   CHAR8 *Destination8;\r
52   CHAR8 *Source8;\r
53   UINTN Length;\r
54 \r
55   Destination8  = Buffer;\r
56   Source8       = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
57   if (Destination8 != Source8) {\r
58     Length        = *ReadSize;\r
59     while ((Length--) > 0) {\r
60       *(Destination8++) = *(Source8++);\r
61     }\r
62   }\r
63 \r
64   return EFI_SUCCESS;\r
65 }\r
66 \r
67 /**\r
68 \r
69   Support routine to get the Image read file function.\r
70 \r
71   @param ImageContext    - The context of the image being loaded\r
72 \r
73   @retval EFI_SUCCESS - If Image function location is found\r
74 \r
75 **/\r
76 EFI_STATUS\r
77 GetImageReadFunction (\r
78   IN      PE_COFF_LOADER_IMAGE_CONTEXT  *ImageContext\r
79   )\r
80 {\r
81   PEI_CORE_INSTANCE  *Private;\r
82   VOID*  MemoryBuffer;\r
83 \r
84   Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
85 \r
86   if (!Private->PeiMemoryInstalled || (Private->HobList.HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME)) {\r
87     ImageContext->ImageRead = PeiImageRead;\r
88   } else {\r
89     MemoryBuffer = AllocatePages (0x400 / EFI_PAGE_SIZE + 1);\r
90     ASSERT (MemoryBuffer != NULL);\r
91 \r
92     CopyMem (MemoryBuffer, (CONST VOID *) (UINTN) PeiImageRead, 0x400);\r
93 \r
94     ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer;\r
95   }\r
96 \r
97   return EFI_SUCCESS;\r
98 }\r
99 \r
100 /**\r
101 \r
102   Loads and relocates a PE/COFF image into memory.\r
103   If the image is not relocatable, it will not be loaded into memory and be loaded as XIP image.\r
104 \r
105   @param Pe32Data        - The base address of the PE/COFF file that is to be loaded and relocated\r
106   @param ImageAddress    - The base address of the relocated PE/COFF image\r
107   @param ImageSize       - The size of the relocated PE/COFF image\r
108   @param EntryPoint      - The entry point of the relocated PE/COFF image\r
109 \r
110   @retval EFI_SUCCESS           The file was loaded and relocated\r
111   @retval EFI_OUT_OF_RESOURCES  There was not enough memory to load and relocate the PE/COFF file\r
112 \r
113 **/\r
114 EFI_STATUS\r
115 LoadAndRelocatePeCoffImage (\r
116   IN  VOID                                      *Pe32Data,\r
117   OUT EFI_PHYSICAL_ADDRESS                      *ImageAddress,\r
118   OUT UINT64                                    *ImageSize,\r
119   OUT EFI_PHYSICAL_ADDRESS                      *EntryPoint\r
120   )\r
121 {\r
122   EFI_STATUS                            Status;\r
123   PE_COFF_LOADER_IMAGE_CONTEXT          ImageContext;\r
124   PEI_CORE_INSTANCE                     *Private;\r
125 \r
126   Private = PEI_CORE_INSTANCE_FROM_PS_THIS (GetPeiServicesTablePointer ());\r
127 \r
128   ZeroMem (&ImageContext, sizeof (ImageContext));\r
129   ImageContext.Handle = Pe32Data;\r
130   Status              = GetImageReadFunction (&ImageContext);\r
131 \r
132   ASSERT_EFI_ERROR (Status);\r
133 \r
134   Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
135   if (EFI_ERROR (Status)) {\r
136     return Status;\r
137   }\r
138   //\r
139   // When Image has no reloc section, it can't be relocated into memory.\r
140   //\r
141   if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
142     DEBUG ((EFI_D_INFO, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data));\r
143   }\r
144 \r
145   //\r
146   // Set default base address to current image address.\r
147   //\r
148   ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) Pe32Data;\r
149   \r
150   //\r
151   // Allocate Memory for the image when memory is ready, boot mode is not S3, and image is relocatable.\r
152   //\r
153   if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
154     ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize));\r
155     ASSERT (ImageContext.ImageAddress != 0);\r
156     if (ImageContext.ImageAddress == 0) {\r
157       return EFI_OUT_OF_RESOURCES;\r
158     }\r
159     \r
160     //\r
161     // Skip the reserved space for the stripped PeHeader when load TeImage into memory.\r
162     //\r
163     if (ImageContext.IsTeImage) {\r
164       ImageContext.ImageAddress = ImageContext.ImageAddress + \r
165                                   ((EFI_TE_IMAGE_HEADER *) Pe32Data)->StrippedSize -\r
166                                   sizeof (EFI_TE_IMAGE_HEADER);\r
167     }\r
168   }\r
169 \r
170   //\r
171   // Load the image to our new buffer\r
172   //\r
173   Status = PeCoffLoaderLoadImage (&ImageContext);\r
174   if (EFI_ERROR (Status)) {\r
175     return Status;\r
176   }\r
177   //\r
178   // Relocate the image in our new buffer\r
179   //\r
180   Status = PeCoffLoaderRelocateImage (&ImageContext);\r
181   if (EFI_ERROR (Status)) {\r
182     return Status;\r
183   }\r
184 \r
185   //\r
186   // Flush the instruction cache so the image data is written before we execute it\r
187   //\r
188   if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME)) {\r
189     InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);\r
190   }\r
191 \r
192   *ImageAddress = ImageContext.ImageAddress;\r
193   *ImageSize    = ImageContext.ImageSize;\r
194   *EntryPoint   = ImageContext.EntryPoint;\r
195 \r
196   return EFI_SUCCESS;\r
197 }\r
198 \r
199 /**\r
200   Loads a PEIM into memory for subsequent execution. If there are compressed \r
201   images or images that need to be relocated into memory for performance reasons, \r
202   this service performs that transformation.\r
203 \r
204   @param PeiServices      An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
205   @param FileHandle       Pointer to the FFS file header of the image.\r
206   @param ImageAddressArg  Pointer to PE/TE image.\r
207   @param ImageSizeArg     Size of PE/TE image.\r
208   @param EntryPoint       Pointer to entry point of specified image file for output.\r
209   @param AuthenticationState - Pointer to attestation authentication state of image.\r
210 \r
211   @retval EFI_SUCCESS      Image is successfully loaded.\r
212   @retval EFI_NOT_FOUND    Fail to locate necessary PPI.\r
213   @retval EFI_UNSUPPORTED  Image Machine Type is not supported.\r
214 \r
215 **/\r
216 EFI_STATUS\r
217 PeiLoadImageLoadImage (\r
218   IN     CONST EFI_PEI_SERVICES       **PeiServices,\r
219   IN     EFI_PEI_FILE_HANDLE          FileHandle,\r
220   OUT    EFI_PHYSICAL_ADDRESS         *ImageAddressArg,  OPTIONAL\r
221   OUT    UINT64                       *ImageSizeArg,     OPTIONAL\r
222   OUT    EFI_PHYSICAL_ADDRESS         *EntryPoint,\r
223   OUT    UINT32                       *AuthenticationState\r
224   )\r
225 {\r
226   EFI_STATUS                  Status;\r
227   VOID                        *Pe32Data;\r
228   EFI_PHYSICAL_ADDRESS        ImageAddress;\r
229   UINT64                      ImageSize;\r
230   EFI_PHYSICAL_ADDRESS        ImageEntryPoint;\r
231   UINT16                      Machine;\r
232   EFI_SECTION_TYPE            SearchType1;\r
233   EFI_SECTION_TYPE            SearchType2;\r
234 \r
235   *EntryPoint          = 0;\r
236   ImageSize            = 0;\r
237   *AuthenticationState = 0;\r
238 \r
239   if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {\r
240     SearchType1 = EFI_SECTION_TE;\r
241     SearchType2 = EFI_SECTION_PE32;\r
242   } else {\r
243     SearchType1 = EFI_SECTION_PE32;\r
244     SearchType2 = EFI_SECTION_TE;\r
245   }\r
246 \r
247   //\r
248   // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst \r
249   // is true, TE will be searched first).\r
250   //\r
251   Status = PeiServicesFfsFindSectionData (\r
252              SearchType1,\r
253              FileHandle,\r
254              &Pe32Data\r
255              );\r
256   //\r
257   // If we didn't find a first exe section, try to find the second exe section.\r
258   //\r
259   if (EFI_ERROR (Status)) {\r
260     Status = PeiServicesFfsFindSectionData (\r
261                SearchType2,\r
262                FileHandle,\r
263                &Pe32Data\r
264                );\r
265     if (EFI_ERROR (Status)) {\r
266       //\r
267       // PEI core only carry the loader function fro TE and PE32 executables\r
268       // If this two section does not exist, just return.\r
269       //\r
270       return Status;\r
271     }\r
272   }\r
273   \r
274   //\r
275   // If memory is installed, perform the shadow operations\r
276   //\r
277   Status = LoadAndRelocatePeCoffImage (\r
278     Pe32Data,\r
279     &ImageAddress,\r
280     &ImageSize,\r
281     &ImageEntryPoint\r
282   );\r
283 \r
284   ASSERT_EFI_ERROR (Status);\r
285 \r
286 \r
287   if (EFI_ERROR (Status)) {\r
288     return Status;\r
289   }\r
290 \r
291   //\r
292   // Got the entry point from the loaded Pe32Data\r
293   //\r
294   Pe32Data    = (VOID *) ((UINTN) ImageAddress);\r
295   *EntryPoint = ImageEntryPoint;\r
296   \r
297   Machine = PeCoffLoaderGetMachineType (Pe32Data);\r
298   \r
299   if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (Machine)) {\r
300     if (!EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED (Machine)) {\r
301       return EFI_UNSUPPORTED;\r
302     }\r
303   }\r
304 \r
305   if (ImageAddressArg != NULL) {\r
306     *ImageAddressArg = ImageAddress;\r
307   }\r
308 \r
309   if (ImageSizeArg != NULL) {\r
310     *ImageSizeArg = ImageSize;\r
311   }\r
312   \r
313   DEBUG_CODE_BEGIN ();\r
314     CHAR8                              *AsciiString;\r
315     CHAR8                              AsciiBuffer[512];\r
316     INT32                              Index;\r
317     INT32                              Index1;\r
318 \r
319     //\r
320     // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi\r
321     //\r
322     if (Machine != EFI_IMAGE_MACHINE_IA64) {\r
323       DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)*EntryPoint));\r
324     } else {\r
325       //\r
326       // For IPF Image, the real entry point should be print.\r
327       //\r
328       DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%11p EntryPoint=0x%11p ", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)(*(UINT64 *)(UINTN)*EntryPoint)));\r
329     }\r
330     \r
331     //\r
332     // Print Module Name by PeImage PDB file name.\r
333     //\r
334     AsciiString = PeCoffLoaderGetPdbPointer (Pe32Data);\r
335     \r
336     if (AsciiString != NULL) {\r
337       for (Index = (INT32) AsciiStrLen (AsciiString) - 1; Index >= 0; Index --) {\r
338         if (AsciiString[Index] == '\\') {\r
339           break;\r
340         }\r
341       }\r
342 \r
343       if (Index != 0) {\r
344         for (Index1 = 0; AsciiString[Index + 1 + Index1] != '.'; Index1 ++) {\r
345           AsciiBuffer [Index1] = AsciiString[Index + 1 + Index1];\r
346         }\r
347         AsciiBuffer [Index1] = '\0';\r
348         DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer));\r
349       }\r
350     }\r
351 \r
352   DEBUG_CODE_END ();\r
353 \r
354   DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n"));\r
355 \r
356   return EFI_SUCCESS;\r
357 \r
358 }\r
359 \r
360 \r
361 /**\r
362   The wrapper function of PeiLoadImageLoadImage().\r
363 \r
364   @param This            - Pointer to EFI_PEI_LOAD_FILE_PPI.\r
365   @param FileHandle      - Pointer to the FFS file header of the image.\r
366   @param ImageAddressArg - Pointer to PE/TE image.\r
367   @param ImageSizeArg    - Size of PE/TE image.\r
368   @param EntryPoint      - Pointer to entry point of specified image file for output.\r
369   @param AuthenticationState - Pointer to attestation authentication state of image.\r
370 \r
371   @return Status of PeiLoadImageLoadImage().\r
372 \r
373 **/\r
374 EFI_STATUS\r
375 EFIAPI\r
376 PeiLoadImageLoadImageWrapper (\r
377   IN     CONST EFI_PEI_LOAD_FILE_PPI  *This,\r
378   IN     EFI_PEI_FILE_HANDLE          FileHandle,\r
379   OUT    EFI_PHYSICAL_ADDRESS         *ImageAddressArg,  OPTIONAL\r
380   OUT    UINT64                       *ImageSizeArg,     OPTIONAL\r
381   OUT    EFI_PHYSICAL_ADDRESS         *EntryPoint,\r
382   OUT    UINT32                       *AuthenticationState\r
383   )\r
384 {\r
385   return PeiLoadImageLoadImage (\r
386            GetPeiServicesTablePointer (),\r
387            FileHandle,\r
388            ImageAddressArg,\r
389            ImageSizeArg,\r
390            EntryPoint,\r
391            AuthenticationState\r
392            );\r
393 }\r
394 \r
395 /**\r
396   Check whether the input image has the relocation.\r
397 \r
398   @param  Pe32Data   Pointer to the PE/COFF or TE image.\r
399 \r
400   @retval TRUE       Relocation is stripped.\r
401   @retval FALSE      Relocation is not stripped.\r
402 \r
403 **/\r
404 BOOLEAN\r
405 RelocationIsStrip (\r
406   IN VOID  *Pe32Data\r
407   )\r
408 {\r
409   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;\r
410   EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
411 \r
412   ASSERT (Pe32Data != NULL);\r
413 \r
414   DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
415   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
416     //\r
417     // DOS image header is present, so read the PE header after the DOS image header.\r
418     //\r
419     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
420   } else {\r
421     //\r
422     // DOS image header is not present, so PE header is at the image base.\r
423     //\r
424     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
425   }\r
426 \r
427   //\r
428   // Three cases with regards to relocations:\r
429   // - Image has base relocs, RELOCS_STRIPPED==0    => image is relocatable\r
430   // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable\r
431   // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but\r
432   //   has no base relocs to apply\r
433   // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.\r
434   //\r
435   // Look at the file header to determine if relocations have been stripped, and\r
436   // save this info in the image context for later use.\r
437   //\r
438   if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
439     if ((Hdr.Te->DataDirectory[0].Size == 0) && (Hdr.Te->DataDirectory[0].VirtualAddress == 0)) {\r
440       return TRUE;\r
441     } else {\r
442       return FALSE;\r
443     }\r
444   } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)  {\r
445     if ((Hdr.Pe32->FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0) {\r
446       return TRUE;\r
447     } else {\r
448       return FALSE;\r
449     }\r
450   }\r
451 \r
452   return FALSE;\r
453 }\r
454 \r
455 /**\r
456   Routine to load image file for subsequent execution by LoadFile Ppi.\r
457   If any LoadFile Ppi is not found, the build-in support function for the PE32+/TE \r
458   XIP image format is used.\r
459 \r
460   @param PeiServices     - An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation\r
461   @param FileHandle      - Pointer to the FFS file header of the image.\r
462   @param PeimState       - The dispatch state of the input PEIM handle.\r
463   @param EntryPoint      - Pointer to entry point of specified image file for output.\r
464   @param AuthenticationState - Pointer to attestation authentication state of image.\r
465 \r
466   @retval EFI_SUCCESS    - Image is successfully loaded.\r
467   @retval EFI_NOT_FOUND  - Fail to locate necessary PPI\r
468   @retval Others         - Fail to load file.\r
469 \r
470 **/\r
471 EFI_STATUS\r
472 PeiLoadImage (\r
473   IN     CONST EFI_PEI_SERVICES       **PeiServices,\r
474   IN     EFI_PEI_FILE_HANDLE          FileHandle,\r
475   IN     UINT8                        PeimState,\r
476   OUT    EFI_PHYSICAL_ADDRESS         *EntryPoint,\r
477   OUT    UINT32                       *AuthenticationState\r
478   )\r
479 {\r
480   EFI_STATUS              PpiStatus;\r
481   EFI_STATUS              Status;\r
482   UINTN                   Index;\r
483   EFI_PEI_LOAD_FILE_PPI   *LoadFile;\r
484   EFI_PHYSICAL_ADDRESS    ImageAddress;\r
485   UINT64                  ImageSize;\r
486   BOOLEAN                 IsStrip;\r
487 \r
488   IsStrip = FALSE;\r
489   //\r
490   // If any instances of PEI_LOAD_FILE_PPI are installed, they are called.\r
491   // one at a time, until one reports EFI_SUCCESS.\r
492   //\r
493   Index = 0;\r
494   do {\r
495     PpiStatus = PeiServicesLocatePpi (\r
496                   &gEfiPeiLoadFilePpiGuid,\r
497                   Index,\r
498                   NULL,\r
499                   (VOID **)&LoadFile\r
500                   );\r
501     if (!EFI_ERROR (PpiStatus)) {\r
502       Status = LoadFile->LoadFile (\r
503                           LoadFile, \r
504                           FileHandle, \r
505                           &ImageAddress, \r
506                           &ImageSize,\r
507                           EntryPoint,\r
508                           AuthenticationState\r
509                           );\r
510       if (!EFI_ERROR (Status)) {\r
511         //\r
512         // The shadowed PEIM must be relocatable.\r
513         //\r
514         if (PeimState == PEIM_STATE_REGISITER_FOR_SHADOW) {\r
515           IsStrip = RelocationIsStrip ((VOID *) (UINTN) ImageAddress);\r
516           ASSERT (!IsStrip);\r
517           if (IsStrip) {\r
518             return EFI_UNSUPPORTED;\r
519           }\r
520         }\r
521 \r
522         //\r
523         // The image to be started must have the machine type supported by PeiCore.\r
524         //\r
525         ASSERT (EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID *) (UINTN) ImageAddress)));\r
526         if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED (PeCoffLoaderGetMachineType ((VOID *) (UINTN) ImageAddress))) {\r
527           return EFI_UNSUPPORTED;\r
528         }\r
529         return Status;\r
530       }\r
531     }\r
532     Index++;\r
533   } while (!EFI_ERROR (PpiStatus));\r
534 \r
535   return PpiStatus;\r
536 }\r
537 \r
538 \r
539 /**\r
540 \r
541   Install Pei Load File PPI.\r
542 \r
543 \r
544   @param PrivateData     - Pointer to PEI_CORE_INSTANCE.\r
545   @param OldCoreData     - Pointer to PEI_CORE_INSTANCE.\r
546 \r
547 **/\r
548 VOID\r
549 InitializeImageServices (\r
550   IN  PEI_CORE_INSTANCE   *PrivateData,\r
551   IN  PEI_CORE_INSTANCE   *OldCoreData\r
552   )\r
553 {\r
554   if (OldCoreData == NULL) {\r
555     //\r
556     // The first time we are XIP (running from FLASH). We need to remember the\r
557     // FLASH address so we can reinstall the memory version that runs faster\r
558     //\r
559     PrivateData->XipLoadFile = &gPpiLoadFilePpiList;\r
560     PeiServicesInstallPpi (PrivateData->XipLoadFile);\r
561   } else {\r
562     //\r
563     // 2nd time we are running from memory so replace the XIP version with the \r
564     // new memory version. \r
565     //\r
566     PeiServicesReInstallPpi (PrivateData->XipLoadFile, &gPpiLoadFilePpiList); \r
567   }\r
568 }\r
569 \r
570 \r
571 \r
572 \r