PrePiLib.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /** @file
  2. Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include <PrePi.h>
  6. //
  7. // Hack to work in NT32
  8. //
  9. EFI_STATUS
  10. EFIAPI
  11. SecWinNtPeiLoadFile (
  12. IN VOID *Pe32Data,
  13. IN EFI_PHYSICAL_ADDRESS *ImageAddress,
  14. IN UINT64 *ImageSize,
  15. IN EFI_PHYSICAL_ADDRESS *EntryPoint
  16. );
  17. STATIC
  18. VOID *
  19. EFIAPI
  20. AllocateCodePages (
  21. IN UINTN Pages
  22. )
  23. {
  24. VOID *Alloc;
  25. EFI_PEI_HOB_POINTERS Hob;
  26. Alloc = AllocatePages (Pages);
  27. if (Alloc == NULL) {
  28. return NULL;
  29. }
  30. // find the HOB we just created, and change the type to EfiBootServicesCode
  31. Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
  32. while (Hob.Raw != NULL) {
  33. if (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == (UINTN)Alloc) {
  34. Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiBootServicesCode;
  35. return Alloc;
  36. }
  37. Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, GET_NEXT_HOB (Hob));
  38. }
  39. ASSERT (FALSE);
  40. FreePages (Alloc, Pages);
  41. return NULL;
  42. }
  43. EFI_STATUS
  44. EFIAPI
  45. LoadPeCoffImage (
  46. IN VOID *PeCoffImage,
  47. OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
  48. OUT UINT64 *ImageSize,
  49. OUT EFI_PHYSICAL_ADDRESS *EntryPoint
  50. )
  51. {
  52. RETURN_STATUS Status;
  53. PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
  54. VOID *Buffer;
  55. ZeroMem (&ImageContext, sizeof (ImageContext));
  56. ImageContext.Handle = PeCoffImage;
  57. ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
  58. Status = PeCoffLoaderGetImageInfo (&ImageContext);
  59. ASSERT_EFI_ERROR (Status);
  60. //
  61. // Allocate Memory for the image
  62. //
  63. Buffer = AllocateCodePages (EFI_SIZE_TO_PAGES ((UINT32)ImageContext.ImageSize));
  64. ASSERT (Buffer != 0);
  65. ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
  66. //
  67. // Load the image to our new buffer
  68. //
  69. Status = PeCoffLoaderLoadImage (&ImageContext);
  70. ASSERT_EFI_ERROR (Status);
  71. //
  72. // Relocate the image in our new buffer
  73. //
  74. Status = PeCoffLoaderRelocateImage (&ImageContext);
  75. ASSERT_EFI_ERROR (Status);
  76. *ImageAddress = ImageContext.ImageAddress;
  77. *ImageSize = ImageContext.ImageSize;
  78. *EntryPoint = ImageContext.EntryPoint;
  79. //
  80. // Flush not needed for all architectures. We could have a processor specific
  81. // function in this library that does the no-op if needed.
  82. //
  83. InvalidateInstructionCacheRange ((VOID *)(UINTN)*ImageAddress, (UINTN)*ImageSize);
  84. return Status;
  85. }
  86. typedef
  87. VOID
  88. (EFIAPI *DXE_CORE_ENTRY_POINT)(
  89. IN VOID *HobStart
  90. );
  91. EFI_STATUS
  92. EFIAPI
  93. LoadDxeCoreFromFfsFile (
  94. IN EFI_PEI_FILE_HANDLE FileHandle,
  95. IN UINTN StackSize
  96. )
  97. {
  98. EFI_STATUS Status;
  99. VOID *PeCoffImage;
  100. EFI_PHYSICAL_ADDRESS ImageAddress;
  101. UINT64 ImageSize;
  102. EFI_PHYSICAL_ADDRESS EntryPoint;
  103. VOID *BaseOfStack;
  104. VOID *TopOfStack;
  105. VOID *Hob;
  106. EFI_FV_FILE_INFO FvFileInfo;
  107. Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &PeCoffImage);
  108. if (EFI_ERROR (Status)) {
  109. return Status;
  110. }
  111. Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint);
  112. // For NT32 Debug Status = SecWinNtPeiLoadFile (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint);
  113. ASSERT_EFI_ERROR (Status);
  114. //
  115. // Extract the DxeCore GUID file name.
  116. //
  117. Status = FfsGetFileInfo (FileHandle, &FvFileInfo);
  118. ASSERT_EFI_ERROR (Status);
  119. BuildModuleHob (&FvFileInfo.FileName, (EFI_PHYSICAL_ADDRESS)(UINTN)ImageAddress, EFI_SIZE_TO_PAGES ((UINT32)ImageSize) * EFI_PAGE_SIZE, EntryPoint);
  120. DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Loading DxeCore at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)EntryPoint));
  121. Hob = GetHobList ();
  122. if (StackSize == 0) {
  123. // User the current stack
  124. ((DXE_CORE_ENTRY_POINT)(UINTN)EntryPoint)(Hob);
  125. } else {
  126. //
  127. // Allocate 128KB for the Stack
  128. //
  129. BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (StackSize));
  130. ASSERT (BaseOfStack != NULL);
  131. //
  132. // Compute the top of the stack we were allocated. Pre-allocate a UINTN
  133. // for safety.
  134. //
  135. TopOfStack = (VOID *)((UINTN)BaseOfStack + EFI_SIZE_TO_PAGES (StackSize) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);
  136. TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
  137. //
  138. // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
  139. //
  140. UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN)BaseOfStack, StackSize);
  141. SwitchStack (
  142. (SWITCH_STACK_ENTRY_POINT)(UINTN)EntryPoint,
  143. Hob,
  144. NULL,
  145. TopOfStack
  146. );
  147. }
  148. // Should never get here as DXE Core does not return
  149. DEBUG ((DEBUG_ERROR, "DxeCore returned\n"));
  150. ASSERT (FALSE);
  151. return EFI_DEVICE_ERROR;
  152. }
  153. EFI_STATUS
  154. EFIAPI
  155. LoadDxeCoreFromFv (
  156. IN UINTN *FvInstance OPTIONAL,
  157. IN UINTN StackSize
  158. )
  159. {
  160. EFI_STATUS Status;
  161. EFI_PEI_FV_HANDLE VolumeHandle;
  162. EFI_PEI_FILE_HANDLE FileHandle = NULL;
  163. if (FvInstance != NULL) {
  164. //
  165. // Caller passed in a specific FV to try, so only try that one
  166. //
  167. Status = FfsFindNextVolume (*FvInstance, &VolumeHandle);
  168. if (!EFI_ERROR (Status)) {
  169. Status = FfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle);
  170. }
  171. } else {
  172. Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, &FileHandle);
  173. }
  174. if (!EFI_ERROR (Status)) {
  175. return LoadDxeCoreFromFfsFile (FileHandle, StackSize);
  176. }
  177. return Status;
  178. }
  179. EFI_STATUS
  180. EFIAPI
  181. DecompressFirstFv (
  182. VOID
  183. )
  184. {
  185. EFI_STATUS Status;
  186. EFI_PEI_FV_HANDLE VolumeHandle;
  187. EFI_PEI_FILE_HANDLE FileHandle;
  188. Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, &VolumeHandle, &FileHandle);
  189. if (!EFI_ERROR (Status)) {
  190. Status = FfsProcessFvFile (FileHandle);
  191. }
  192. return Status;
  193. }