1 /*++ 2 3 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR> 4 This program and the accompanying materials 5 are licensed and made available under the terms and conditions of the BSD License 6 which accompanies this distribution. The full text of the license may be found at 7 http://opensource.org/licenses/bsd-license.php 8 9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11 12 Module Name: 13 EfiLoader.c 14 15 Abstract: 16 17 Revision History: 18 19 --*/ 20 21 #include "EfiLdr.h" 22 #include "Support.h" 23 #include "Debug.h" 24 #include "PeLoader.h" 25 #include "LzmaDecompress.h" 26 27 EFILDR_LOADED_IMAGE DxeCoreImage; 28 EFILDR_LOADED_IMAGE DxeIplImage; 29 30 VOID 31 SystemHang ( 32 CHAR8 *Message 33 ) 34 { 35 PrintString ( 36 "%s## FATAL ERROR ##: Fail to load DUET images! System hang!\n", 37 Message 38 ); 39 CpuDeadLoop(); 40 } 41 42 VOID 43 EfiLoader ( 44 UINT32 BiosMemoryMapBaseAddress 45 ) 46 { 47 BIOS_MEMORY_MAP *BiosMemoryMap; 48 EFILDR_IMAGE *EFILDRImage; 49 EFI_MEMORY_DESCRIPTOR EfiMemoryDescriptor[EFI_MAX_MEMORY_DESCRIPTORS]; 50 EFI_STATUS Status; 51 UINTN NumberOfMemoryMapEntries; 52 UINT32 DestinationSize; 53 UINT32 ScratchSize; 54 UINTN BfvPageNumber; 55 UINTN BfvBase; 56 EFI_MAIN_ENTRYPOINT EfiMainEntrypoint; 57 EFILDRHANDOFF Handoff; 58 UINTN Index; 59 60 ClearScreen(); 61 62 PrintHeader ('A'); 63 64 PrintString ("Enter DUET Loader...\n"); 65 PrintString ("BiosMemoryMapBaseAddress = %x\n", (UINTN) BiosMemoryMapBaseAddress); 66 67 // 68 // Add all EfiConventionalMemory descriptors to the table. If there are partial pages, then 69 // round the start address up to the next page, and round the length down to a page boundry. 70 // 71 BiosMemoryMap = (BIOS_MEMORY_MAP *) (UINTN) BiosMemoryMapBaseAddress; 72 NumberOfMemoryMapEntries = 0; 73 GenMemoryMap (&NumberOfMemoryMapEntries, EfiMemoryDescriptor, BiosMemoryMap); 74 75 PrintString ("Get %d entries of memory map!\n", NumberOfMemoryMapEntries); 76 77 // 78 // Get information on where the image is in memory 79 // 80 EFILDRImage = (EFILDR_IMAGE *)(UINTN)(EFILDR_HEADER_ADDRESS + sizeof(EFILDR_HEADER)); 81 82 83 // 84 // Point to the 4th image (Bfv) 85 // 86 EFILDRImage += 3; 87 88 // 89 // Decompress the image 90 // 91 PrintString ( 92 "Decompress BFV image, Image Address = %x Offset = %x\n", 93 (UINTN) (EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), 94 (UINTN) EFILDRImage->Offset 95 ); 96 Status = LzmaUefiDecompressGetInfo ( 97 (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), 98 EFILDRImage->Length, 99 &DestinationSize, 100 &ScratchSize 101 ); 102 103 if (EFI_ERROR (Status)) { 104 SystemHang ("Failed to get decompress information for BFV!\n"); 105 } 106 107 PrintString ("BFV decompress: DestinationSize = %x, ScratchSize = %x\n", (UINTN) DestinationSize, (UINTN) ScratchSize); 108 Status = LzmaUefiDecompress ( 109 (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), 110 EFILDRImage->Length, 111 (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, 112 (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000) 113 ); 114 115 116 if (EFI_ERROR (Status)) { 117 SystemHang ("Failed to decompress BFV!\n"); 118 } 119 120 BfvPageNumber = EFI_SIZE_TO_PAGES (DestinationSize); 121 BfvBase = (UINTN) FindSpace (BfvPageNumber, &NumberOfMemoryMapEntries, EfiMemoryDescriptor, EfiRuntimeServicesData, EFI_MEMORY_WB); 122 if (BfvBase == 0) { 123 SystemHang ("Failed to find free space to hold decompressed BFV\n"); 124 } 125 ZeroMem ((VOID *)(UINTN)BfvBase, BfvPageNumber * EFI_PAGE_SIZE); 126 CopyMem ((VOID *)(UINTN)BfvBase, (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, DestinationSize); 127 128 PrintHeader ('B'); 129 130 // 131 // Point to the 2nd image (DxeIpl) 132 // 133 134 EFILDRImage -= 2; 135 136 // 137 // Decompress the image 138 // 139 PrintString ( 140 "Decompress DxeIpl image, Image Address = %x Offset = %x\n", 141 (UINTN) (EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), 142 (UINTN) EFILDRImage->Offset 143 ); 144 145 Status = LzmaUefiDecompressGetInfo ( 146 (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), 147 EFILDRImage->Length, 148 &DestinationSize, 149 &ScratchSize 150 ); 151 if (EFI_ERROR (Status)) { 152 SystemHang ("Failed to get decompress information for DxeIpl!\n"); 153 } 154 155 Status = LzmaUefiDecompress ( 156 (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), 157 EFILDRImage->Length, 158 (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, 159 (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000) 160 ); 161 if (EFI_ERROR (Status)) { 162 SystemHang ("Failed to decompress DxeIpl image\n"); 163 } 164 165 PrintString ("Start load DxeIpl PE image\n"); 166 167 // 168 // Load and relocate the EFI PE/COFF Firmware Image 169 // 170 Status = EfiLdrPeCoffLoadPeImage ( 171 (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS), 172 &DxeIplImage, 173 &NumberOfMemoryMapEntries, 174 EfiMemoryDescriptor 175 ); 176 if (EFI_ERROR (Status)) { 177 SystemHang ("Failed to load and relocate DxeIpl PE image!\n"); 178 } 179 PrintString ( 180 "DxeIpl PE image is successed loaded at %lx, entry=%p\n", 181 DxeIplImage.ImageBasePage, 182 DxeIplImage.EntryPoint 183 ); 184 185 PrintHeader ('C'); 186 187 // 188 // Point to the 3rd image (DxeMain) 189 // 190 EFILDRImage++; 191 192 // 193 // Decompress the image 194 // 195 PrintString ( 196 "Decompress DxeMain FV image, Image Address = %x Offset = %x\n", 197 (UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), 198 (UINTN) EFILDRImage->Offset 199 ); 200 201 Status = LzmaUefiDecompressGetInfo ( 202 (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), 203 EFILDRImage->Length, 204 &DestinationSize, 205 &ScratchSize 206 ); 207 if (EFI_ERROR (Status)) { 208 SystemHang ("Failed to get decompress information for DxeMain FV image!\n"); 209 } 210 211 Status = LzmaUefiDecompress ( 212 (VOID *)(UINTN)(EFILDR_HEADER_ADDRESS + EFILDRImage->Offset), 213 EFILDRImage->Length, 214 (VOID *)(UINTN)EFI_DECOMPRESSED_BUFFER_ADDRESS, 215 (VOID *)(UINTN)((EFI_DECOMPRESSED_BUFFER_ADDRESS + DestinationSize + 0x1000) & 0xfffff000) 216 ); 217 if (EFI_ERROR (Status)) { 218 SystemHang ("Failed to decompress DxeMain FV image!\n"); 219 } 220 221 // 222 // Load and relocate the EFI PE/COFF Firmware Image 223 // 224 Status = EfiLdrPeCoffLoadPeImage ( 225 (VOID *)(UINTN)(EFI_DECOMPRESSED_BUFFER_ADDRESS), 226 &DxeCoreImage, 227 &NumberOfMemoryMapEntries, 228 EfiMemoryDescriptor 229 ); 230 if (EFI_ERROR (Status)) { 231 SystemHang ("Failed to load/relocate DxeMain!\n"); 232 } 233 PrintString ( 234 "DxeCore PE image is successed loaded at %lx, entry=%p\n", 235 DxeCoreImage.ImageBasePage, 236 DxeCoreImage.EntryPoint 237 ); 238 239 PrintHeader ('E'); 240 241 // 242 // Display the table of memory descriptors. 243 // 244 PrintString ("\nEFI Memory Descriptors\n"); 245 for (Index = 0; Index < NumberOfMemoryMapEntries; Index++) { 246 PrintString ( 247 "Type = %x Start = %08lx NumberOfPages = %08lx\n", 248 EfiMemoryDescriptor[Index].Type, EfiMemoryDescriptor[Index].PhysicalStart, EfiMemoryDescriptor[Index].NumberOfPages 249 ); 250 } 251 252 // 253 // Jump to EFI Firmware 254 // 255 256 if (DxeIplImage.EntryPoint != NULL) { 257 258 Handoff.MemDescCount = NumberOfMemoryMapEntries; 259 Handoff.MemDesc = EfiMemoryDescriptor; 260 Handoff.BfvBase = (VOID *)(UINTN)BfvBase; 261 Handoff.BfvSize = BfvPageNumber * EFI_PAGE_SIZE; 262 Handoff.DxeIplImageBase = (VOID *)(UINTN)DxeIplImage.ImageBasePage; 263 Handoff.DxeIplImageSize = DxeIplImage.NoPages * EFI_PAGE_SIZE; 264 Handoff.DxeCoreImageBase = (VOID *)(UINTN)DxeCoreImage.ImageBasePage; 265 Handoff.DxeCoreImageSize = DxeCoreImage.NoPages * EFI_PAGE_SIZE; 266 Handoff.DxeCoreEntryPoint = (VOID *)(UINTN)DxeCoreImage.EntryPoint; 267 268 PrintString ("Transfer to DxeIpl ...EntryPoint = %p\n", DxeIplImage.EntryPoint); 269 270 EfiMainEntrypoint = (EFI_MAIN_ENTRYPOINT) DxeIplImage.EntryPoint; 271 EfiMainEntrypoint (&Handoff); 272 } 273 274 PrintHeader ('F'); 275 276 // 277 // There was a problem loading the image, so HALT the system. 278 // 279 280 SystemHang ("Failed to jump to DxeIpl!\n"); 281 } 282 283 EFI_STATUS 284 EFIAPI 285 _ModuleEntryPoint ( 286 UINT32 BiosMemoryMapBaseAddress 287 ) 288 { 289 SerialPortInitialize (); 290 EfiLoader(BiosMemoryMapBaseAddress); 291 return EFI_SUCCESS; 292 } 293 294 295