1 /** @file 2 3 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> 4 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include <PrePi.h> 16 17 // 18 // Hack to work in NT32 19 // 20 EFI_STATUS 21 22 EFIAPI 23 24 SecWinNtPeiLoadFile ( 25 IN VOID *Pe32Data, 26 IN EFI_PHYSICAL_ADDRESS *ImageAddress, 27 IN UINT64 *ImageSize, 28 IN EFI_PHYSICAL_ADDRESS *EntryPoint 29 ); 30 31 32 EFI_STATUS 33 EFIAPI 34 LoadPeCoffImage ( 35 IN VOID *PeCoffImage, 36 OUT EFI_PHYSICAL_ADDRESS *ImageAddress, 37 OUT UINT64 *ImageSize, 38 OUT EFI_PHYSICAL_ADDRESS *EntryPoint 39 ) 40 { 41 RETURN_STATUS Status; 42 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; 43 VOID *Buffer; 44 45 ZeroMem (&ImageContext, sizeof (ImageContext)); 46 47 ImageContext.Handle = PeCoffImage; 48 ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory; 49 50 Status = PeCoffLoaderGetImageInfo (&ImageContext); 51 ASSERT_EFI_ERROR (Status); 52 53 54 // 55 // Allocate Memory for the image 56 // 57 Buffer = AllocatePages (EFI_SIZE_TO_PAGES((UINT32)ImageContext.ImageSize)); 58 ASSERT (Buffer != 0); 59 60 61 ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer; 62 63 // 64 // Load the image to our new buffer 65 // 66 Status = PeCoffLoaderLoadImage (&ImageContext); 67 ASSERT_EFI_ERROR (Status); 68 69 // 70 // Relocate the image in our new buffer 71 // 72 Status = PeCoffLoaderRelocateImage (&ImageContext); 73 ASSERT_EFI_ERROR (Status); 74 75 76 *ImageAddress = ImageContext.ImageAddress; 77 *ImageSize = ImageContext.ImageSize; 78 *EntryPoint = ImageContext.EntryPoint; 79 80 // 81 // Flush not needed for all architectures. We could have a processor specific 82 // function in this library that does the no-op if needed. 83 // 84 InvalidateInstructionCacheRange ((VOID *)(UINTN)*ImageAddress, (UINTN)*ImageSize); 85 86 return Status; 87 } 88 89 90 91 typedef 92 VOID 93 (EFIAPI *DXE_CORE_ENTRY_POINT) ( 94 IN VOID *HobStart 95 ); 96 97 EFI_STATUS 98 EFIAPI 99 LoadDxeCoreFromFfsFile ( 100 IN EFI_PEI_FILE_HANDLE FileHandle, 101 IN UINTN StackSize 102 ) 103 { 104 EFI_STATUS Status; 105 VOID *PeCoffImage; 106 EFI_PHYSICAL_ADDRESS ImageAddress; 107 UINT64 ImageSize; 108 EFI_PHYSICAL_ADDRESS EntryPoint; 109 VOID *BaseOfStack; 110 VOID *TopOfStack; 111 VOID *Hob; 112 EFI_FV_FILE_INFO FvFileInfo; 113 114 Status = FfsFindSectionData (EFI_SECTION_PE32, FileHandle, &PeCoffImage); 115 if (EFI_ERROR (Status)) { 116 return Status; 117 } 118 119 120 Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint); 121 // For NT32 Debug Status = SecWinNtPeiLoadFile (PeCoffImage, &ImageAddress, &ImageSize, &EntryPoint); 122 ASSERT_EFI_ERROR (Status); 123 124 // 125 // Extract the DxeCore GUID file name. 126 // 127 Status = FfsGetFileInfo (FileHandle, &FvFileInfo); 128 ASSERT_EFI_ERROR (Status); 129 130 BuildModuleHob (&FvFileInfo.FileName, (EFI_PHYSICAL_ADDRESS)(UINTN)ImageAddress, EFI_SIZE_TO_PAGES ((UINT32) ImageSize) * EFI_PAGE_SIZE, EntryPoint); 131 132 DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading DxeCore at 0x%10p EntryPoint=0x%10p\n", (VOID *)(UINTN)ImageAddress, (VOID *)(UINTN)EntryPoint)); 133 134 Hob = GetHobList (); 135 if (StackSize == 0) { 136 // User the current stack 137 138 ((DXE_CORE_ENTRY_POINT)(UINTN)EntryPoint) (Hob); 139 } else { 140 141 // 142 // Allocate 128KB for the Stack 143 // 144 BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (StackSize)); 145 ASSERT (BaseOfStack != NULL); 146 147 // 148 // Compute the top of the stack we were allocated. Pre-allocate a UINTN 149 // for safety. 150 // 151 TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (StackSize) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT); 152 TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT); 153 154 // 155 // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore. 156 // 157 UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, StackSize); 158 159 SwitchStack ( 160 (SWITCH_STACK_ENTRY_POINT)(UINTN)EntryPoint, 161 Hob, 162 NULL, 163 TopOfStack 164 ); 165 166 } 167 168 // Should never get here as DXE Core does not return 169 DEBUG ((EFI_D_ERROR, "DxeCore returned\n")); 170 ASSERT (FALSE); 171 172 return EFI_DEVICE_ERROR; 173 } 174 175 176 177 EFI_STATUS 178 EFIAPI 179 LoadDxeCoreFromFv ( 180 IN UINTN *FvInstance, OPTIONAL 181 IN UINTN StackSize 182 ) 183 { 184 EFI_STATUS Status; 185 EFI_PEI_FV_HANDLE VolumeHandle; 186 EFI_PEI_FILE_HANDLE FileHandle = NULL; 187 188 if (FvInstance != NULL) { 189 // 190 // Caller passed in a specific FV to try, so only try that one 191 // 192 Status = FfsFindNextVolume (*FvInstance, &VolumeHandle); 193 if (!EFI_ERROR (Status)) { 194 Status = FfsFindNextFile (EFI_FV_FILETYPE_DXE_CORE, VolumeHandle, &FileHandle); 195 } 196 } else { 197 Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_DXE_CORE, &VolumeHandle, &FileHandle); 198 } 199 200 if (!EFI_ERROR (Status)) { 201 return LoadDxeCoreFromFfsFile (FileHandle, StackSize); 202 } 203 204 return Status; 205 } 206 207 208 EFI_STATUS 209 EFIAPI 210 DecompressFirstFv ( 211 VOID 212 ) 213 { 214 EFI_STATUS Status; 215 EFI_PEI_FV_HANDLE VolumeHandle; 216 EFI_PEI_FILE_HANDLE FileHandle; 217 218 Status = FfsAnyFvFindFirstFile (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, &VolumeHandle, &FileHandle); 219 if (!EFI_ERROR (Status)) { 220 Status = FfsProcessFvFile (FileHandle); 221 } 222 223 return Status; 224 } 225 226 227