]> git.proxmox.com Git - mirror_edk2.git/blame - Tools/Source/TianoTools/Common/PeiLib/PeCoffLoader.c
Fix capitalization issues.
[mirror_edk2.git] / Tools / Source / TianoTools / Common / PeiLib / PeCoffLoader.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2004 - 2005, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 PeCoffLoader.c\r
15\r
16Abstract:\r
17\r
18 Tiano PE/COFF loader \r
19\r
20Revision History\r
21\r
22--*/\r
23\r
24#include "Tiano.h"\r
25#include "Pei.h"\r
26#include "PeiLib.h"\r
27#include "PeCoffLoaderEx.h"\r
28\r
29#ifdef EFI_NT_EMULATOR\r
30#include "peilib.h"\r
31#include "EfiHobLib.h"\r
32#include EFI_PPI_DEFINITION (NtLoadAsDll)\r
33#endif\r
34\r
35STATIC\r
36EFI_STATUS\r
37PeCoffLoaderGetPeHeader (\r
38 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
39 OUT EFI_IMAGE_NT_HEADERS *PeHdr,\r
40 OUT EFI_TE_IMAGE_HEADER *TeHdr\r
41 );\r
42\r
43STATIC\r
44EFI_STATUS\r
45PeCoffLoaderCheckImageType (\r
46 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
47 IN EFI_IMAGE_NT_HEADERS *PeHdr,\r
48 IN EFI_TE_IMAGE_HEADER *TeHdr\r
49 );\r
50\r
51STATIC\r
52VOID *\r
53PeCoffLoaderImageAddress (\r
54 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
55 IN UINTN Address\r
56 );\r
57\r
58EFI_STATUS\r
59EFIAPI\r
60PeCoffLoaderGetImageInfo (\r
61 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,\r
62 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
63 );\r
64\r
65EFI_STATUS\r
66EFIAPI\r
67PeCoffLoaderRelocateImage (\r
68 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,\r
69 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
70 );\r
71\r
72EFI_STATUS\r
73EFIAPI\r
74PeCoffLoaderLoadImage (\r
75 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,\r
76 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
77 );\r
78\r
79EFI_STATUS\r
80EFIAPI\r
81PeCoffLoaderUnloadImage (\r
82 IN EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
83 );\r
84\r
85EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader = {\r
86 PeCoffLoaderGetImageInfo,\r
87 PeCoffLoaderLoadImage,\r
88 PeCoffLoaderRelocateImage,\r
89 PeCoffLoaderUnloadImage\r
90};\r
91\r
92#ifdef EFI_NT_EMULATOR\r
93EFI_NT_LOAD_AS_DLL_PPI *mPeCoffLoaderWinNtLoadAsDll = NULL;\r
94#endif\r
95\r
96EFI_STATUS\r
97InstallEfiPeiPeCoffLoader (\r
98 IN EFI_PEI_SERVICES **PeiServices,\r
99 IN OUT EFI_PEI_PE_COFF_LOADER_PROTOCOL **This,\r
100 IN EFI_PEI_PPI_DESCRIPTOR *ThisPpi\r
101 )\r
102/*++\r
103\r
104Routine Description:\r
105\r
106 Install PE/COFF loader PPI\r
107 \r
108Arguments:\r
109\r
110 PeiServices - General purpose services available to every PEIM\r
111\r
112 This - Pointer to get Pei PE coff loader protocol as output\r
113 \r
114 ThisPpi - Passed in as EFI_NT_LOAD_AS_DLL_PPI on NT_EMULATOR platform\r
115\r
116Returns:\r
117\r
118 EFI_SUCCESS\r
119\r
120--*/\r
121{\r
122 EFI_STATUS Status;\r
123\r
124 Status = EFI_SUCCESS;\r
125\r
126#ifdef EFI_NT_EMULATOR\r
127 //\r
128 // For use by PEI Core and Modules\r
129 //\r
130 if (NULL != PeiServices) {\r
131 Status = (**PeiServices).LocatePpi (\r
132 PeiServices,\r
133 &gEfiNtLoadAsDllPpiGuid,\r
134 0,\r
135 NULL,\r
136 &mPeCoffLoaderWinNtLoadAsDll\r
137 );\r
138 } else {\r
139 //\r
140 // Now in SecMain or ERM usage, bind appropriately\r
141 //\r
142 PEI_ASSERT (PeiServices, (NULL != ThisPpi));\r
143\r
144 mPeCoffLoaderWinNtLoadAsDll = (EFI_NT_LOAD_AS_DLL_PPI *) ThisPpi;\r
145 PEI_ASSERT (PeiServices, (NULL != mPeCoffLoaderWinNtLoadAsDll));\r
146 }\r
147#endif\r
148\r
149 if (NULL != This) {\r
150 *This = &mPeCoffLoader;\r
151 }\r
152\r
153 return Status;\r
154}\r
155\r
156STATIC\r
157EFI_STATUS\r
158PeCoffLoaderGetPeHeader (\r
159 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
160 OUT EFI_IMAGE_NT_HEADERS *PeHdr,\r
161 OUT EFI_TE_IMAGE_HEADER *TeHdr\r
162 )\r
163/*++\r
164\r
165Routine Description:\r
166\r
167 Retrieves the PE or TE Header from a PE/COFF or TE image\r
168\r
169Arguments:\r
170\r
171 ImageContext - The context of the image being loaded\r
172\r
173 PeHdr - The buffer in which to return the PE header\r
174 \r
175 TeHdr - The buffer in which to return the TE header\r
176\r
177Returns:\r
178\r
179 EFI_SUCCESS if the PE or TE Header is read, \r
180 Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function.\r
181\r
182--*/\r
183{\r
184 EFI_STATUS Status;\r
185 EFI_IMAGE_DOS_HEADER DosHdr;\r
186 UINTN Size;\r
187\r
188 ImageContext->IsTeImage = FALSE;\r
189 //\r
190 // Read the DOS image headers\r
191 //\r
192 Size = sizeof (EFI_IMAGE_DOS_HEADER);\r
193 Status = ImageContext->ImageRead (\r
194 ImageContext->Handle,\r
195 0,\r
196 &Size,\r
197 &DosHdr\r
198 );\r
199 if (EFI_ERROR (Status)) {\r
200 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;\r
201 return Status;\r
202 }\r
203\r
204 ImageContext->PeCoffHeaderOffset = 0;\r
205 if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
206 //\r
207 // DOS image header is present, so read the PE header after the DOS image header\r
208 //\r
209 ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew;\r
210 }\r
211 //\r
212 // Read the PE/COFF Header\r
213 //\r
214 Size = sizeof (EFI_IMAGE_NT_HEADERS);\r
215 Status = ImageContext->ImageRead (\r
216 ImageContext->Handle,\r
217 ImageContext->PeCoffHeaderOffset,\r
218 &Size,\r
219 PeHdr\r
220 );\r
221 if (EFI_ERROR (Status)) {\r
222 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;\r
223 return Status;\r
224 }\r
225 //\r
226 // Check the PE/COFF Header Signature. If not, then try to read a TE header\r
227 //\r
228 if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) {\r
229 Size = sizeof (EFI_TE_IMAGE_HEADER);\r
230 Status = ImageContext->ImageRead (\r
231 ImageContext->Handle,\r
232 0,\r
233 &Size,\r
234 TeHdr\r
235 );\r
236 if (TeHdr->Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
237 return EFI_UNSUPPORTED;\r
238 }\r
239\r
240 ImageContext->IsTeImage = TRUE;\r
241 }\r
242\r
243 return EFI_SUCCESS;\r
244}\r
245\r
246STATIC\r
247EFI_STATUS\r
248PeCoffLoaderCheckImageType (\r
249 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
250 IN EFI_IMAGE_NT_HEADERS *PeHdr,\r
251 IN EFI_TE_IMAGE_HEADER *TeHdr\r
252 )\r
253/*++\r
254\r
255Routine Description:\r
256\r
257 Checks the PE or TE header of a PE/COFF or TE image to determine if it supported\r
258\r
259Arguments:\r
260\r
261 ImageContext - The context of the image being loaded\r
262\r
263 PeHdr - The buffer in which to return the PE header\r
264 \r
265 TeHdr - The buffer in which to return the TE header\r
266\r
267Returns:\r
268\r
269 EFI_SUCCESS if the PE/COFF or TE image is supported\r
270 EFI_UNSUPPORTED of the PE/COFF or TE image is not supported.\r
271\r
272--*/\r
273{\r
274 //\r
275 // See if the machine type is supported. We support a native machine type (IA-32/Itanium-based)\r
276 // and the machine type for the Virtual Machine.\r
277 //\r
278 if (ImageContext->IsTeImage == FALSE) {\r
279 ImageContext->Machine = PeHdr->FileHeader.Machine;\r
280 } else {\r
281 ImageContext->Machine = TeHdr->Machine;\r
282 }\r
283\r
284 if (!(EFI_IMAGE_MACHINE_TYPE_SUPPORTED (ImageContext->Machine))) {\r
285 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_MACHINE_TYPE;\r
286 return EFI_UNSUPPORTED;\r
287 }\r
288\r
289 //\r
290 // See if the image type is supported. We support EFI Applications,\r
291 // EFI Boot Service Drivers, and EFI Runtime Drivers.\r
292 //\r
293 if (ImageContext->IsTeImage == FALSE) {\r
294 ImageContext->ImageType = PeHdr->OptionalHeader.Subsystem;\r
295 } else {\r
296 ImageContext->ImageType = (UINT16) (TeHdr->Subsystem);\r
297 }\r
298\r
299 switch (ImageContext->ImageType) {\r
300\r
301 case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION:\r
302 ImageContext->ImageCodeMemoryType = EfiLoaderCode;\r
303 ImageContext->ImageDataMemoryType = EfiLoaderData;\r
304 break;\r
305\r
306 case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER:\r
307 ImageContext->ImageCodeMemoryType = EfiBootServicesCode;\r
308 ImageContext->ImageDataMemoryType = EfiBootServicesData;\r
309 break;\r
310\r
311 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:\r
312 case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER:\r
313 ImageContext->ImageCodeMemoryType = EfiRuntimeServicesCode;\r
314 ImageContext->ImageDataMemoryType = EfiRuntimeServicesData;\r
315 break;\r
316\r
317 default:\r
318 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_SUBSYSTEM;\r
319 return EFI_UNSUPPORTED;\r
320 }\r
321\r
322 return EFI_SUCCESS;\r
323}\r
324\r
325EFI_STATUS\r
326EFIAPI\r
327PeCoffLoaderGetImageInfo (\r
328 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,\r
329 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
330 )\r
331/*++\r
332\r
333Routine Description:\r
334\r
335 Retrieves information on a PE/COFF image\r
336\r
337Arguments:\r
338\r
339 This - Calling context\r
340 ImageContext - The context of the image being loaded\r
341\r
342Returns:\r
343\r
344 EFI_SUCCESS - The information on the PE/COFF image was collected.\r
345 EFI_INVALID_PARAMETER - ImageContext is NULL.\r
346 EFI_UNSUPPORTED - The PE/COFF image is not supported.\r
347 Otherwise - The error status from reading the PE/COFF image using the\r
348 ImageContext->ImageRead() function\r
349\r
350--*/\r
351{\r
352 EFI_STATUS Status;\r
353 EFI_IMAGE_NT_HEADERS PeHdr;\r
354 EFI_TE_IMAGE_HEADER TeHdr;\r
355 EFI_IMAGE_DATA_DIRECTORY *DebugDirectoryEntry;\r
356 UINTN Size;\r
357 UINTN Index;\r
358 UINTN DebugDirectoryEntryRva;\r
359 UINTN DebugDirectoryEntryFileOffset;\r
360 UINTN SectionHeaderOffset;\r
361 EFI_IMAGE_SECTION_HEADER SectionHeader;\r
362 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry;\r
363\r
364 if (NULL == ImageContext) {\r
365 return EFI_INVALID_PARAMETER;\r
366 }\r
367 //\r
368 // Assume success\r
369 //\r
370 ImageContext->ImageError = EFI_IMAGE_ERROR_SUCCESS;\r
371\r
372 Status = PeCoffLoaderGetPeHeader (ImageContext, &PeHdr, &TeHdr);\r
373 if (EFI_ERROR (Status)) {\r
374 return Status;\r
375 }\r
376 //\r
377 // Verify machine type\r
378 //\r
379 Status = PeCoffLoaderCheckImageType (ImageContext, &PeHdr, &TeHdr);\r
380 if (EFI_ERROR (Status)) {\r
381 return Status;\r
382 }\r
383 //\r
384 // Retrieve the base address of the image\r
385 //\r
386 if (!(ImageContext->IsTeImage)) {\r
387 ImageContext->ImageAddress = PeHdr.OptionalHeader.ImageBase;\r
388 } else {\r
389 ImageContext->ImageAddress = (EFI_PHYSICAL_ADDRESS) (TeHdr.ImageBase);\r
390 }\r
391 //\r
392 // Initialize the alternate destination address to 0 indicating that it\r
393 // should not be used.\r
394 //\r
395 ImageContext->DestinationAddress = 0;\r
396\r
397 //\r
398 // Initialize the codeview pointer.\r
399 //\r
400 ImageContext->CodeView = NULL;\r
401 ImageContext->PdbPointer = NULL;\r
402\r
403 //\r
404 // Three cases with regards to relocations:\r
405 // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable\r
406 // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable\r
407 // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but\r
408 // has no base relocs to apply\r
409 // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.\r
410 //\r
411 // Look at the file header to determine if relocations have been stripped, and\r
412 // save this info in the image context for later use.\r
413 //\r
414 if ((!(ImageContext->IsTeImage)) && ((PeHdr.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {\r
415 ImageContext->RelocationsStripped = TRUE;\r
416 } else {\r
417 ImageContext->RelocationsStripped = FALSE;\r
418 }\r
419\r
420 if (!(ImageContext->IsTeImage)) {\r
421 ImageContext->ImageSize = (UINT64) PeHdr.OptionalHeader.SizeOfImage;\r
422 ImageContext->SectionAlignment = PeHdr.OptionalHeader.SectionAlignment;\r
423 ImageContext->SizeOfHeaders = PeHdr.OptionalHeader.SizeOfHeaders;\r
424\r
425 //\r
426 // Modify ImageSize to contain .PDB file name if required and initialize\r
427 // PdbRVA field...\r
428 //\r
429 if (PeHdr.OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
430 DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
431\r
432 DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;\r
433\r
434 //\r
435 // Determine the file offset of the debug directory... This means we walk\r
436 // the sections to find which section contains the RVA of the debug\r
437 // directory\r
438 //\r
439 DebugDirectoryEntryFileOffset = 0;\r
440\r
441 SectionHeaderOffset = (UINTN)(\r
442 ImageContext->PeCoffHeaderOffset +\r
443 sizeof (UINT32) + \r
444 sizeof (EFI_IMAGE_FILE_HEADER) + \r
445 PeHdr.FileHeader.SizeOfOptionalHeader\r
446 );\r
447\r
448 for (Index = 0; Index < PeHdr.FileHeader.NumberOfSections; Index++) {\r
449 //\r
450 // Read section header from file\r
451 //\r
452 Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
453 Status = ImageContext->ImageRead (\r
454 ImageContext->Handle,\r
455 SectionHeaderOffset,\r
456 &Size,\r
457 &SectionHeader\r
458 );\r
459 if (EFI_ERROR (Status)) {\r
460 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;\r
461 return Status;\r
462 }\r
463\r
464 if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&\r
465 DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {\r
466 DebugDirectoryEntryFileOffset =\r
467 DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData;\r
468 break;\r
469 }\r
470\r
471 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
472 }\r
473\r
474 if (DebugDirectoryEntryFileOffset != 0) {\r
475 for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) {\r
476 //\r
477 // Read next debug directory entry\r
478 //\r
479 Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
480 Status = ImageContext->ImageRead (\r
481 ImageContext->Handle,\r
482 DebugDirectoryEntryFileOffset,\r
483 &Size,\r
484 &DebugEntry\r
485 );\r
486 if (EFI_ERROR (Status)) {\r
487 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;\r
488 return Status;\r
489 }\r
490\r
491 if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
492 ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));\r
493 if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) {\r
494 ImageContext->ImageSize += DebugEntry.SizeOfData;\r
495 }\r
496\r
497 return EFI_SUCCESS;\r
498 }\r
499 }\r
500 }\r
501 }\r
502 } else {\r
503 ImageContext->ImageSize = 0;\r
504 ImageContext->SectionAlignment = 4096;\r
505 ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN) TeHdr.BaseOfCode - (UINTN) TeHdr.StrippedSize;\r
506\r
507 DebugDirectoryEntry = &TeHdr.DataDirectory[1];\r
508 DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;\r
509 SectionHeaderOffset = (UINTN) (sizeof (EFI_TE_IMAGE_HEADER));\r
510\r
511 DebugDirectoryEntryFileOffset = 0;\r
512\r
513 for (Index = 0; Index < TeHdr.NumberOfSections;) {\r
514 //\r
515 // Read section header from file\r
516 //\r
517 Size = sizeof (EFI_IMAGE_SECTION_HEADER);\r
518 Status = ImageContext->ImageRead (\r
519 ImageContext->Handle,\r
520 SectionHeaderOffset,\r
521 &Size,\r
522 &SectionHeader\r
523 );\r
524 if (EFI_ERROR (Status)) {\r
525 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;\r
526 return Status;\r
527 }\r
528\r
529 if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress &&\r
530 DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) {\r
531 DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva -\r
532 SectionHeader.VirtualAddress +\r
533 SectionHeader.PointerToRawData +\r
534 sizeof (EFI_TE_IMAGE_HEADER) -\r
535 TeHdr.StrippedSize;\r
536\r
537 //\r
538 // File offset of the debug directory was found, if this is not the last\r
539 // section, then skip to the last section for calculating the image size.\r
540 //\r
541 if (Index < (UINTN) TeHdr.NumberOfSections - 1) {\r
542 SectionHeaderOffset += (TeHdr.NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER);\r
543 Index = TeHdr.NumberOfSections - 1;\r
544 continue;\r
545 }\r
546 }\r
547\r
548 //\r
549 // In Te image header there is not a field to describe the ImageSize.\r
550 // Actually, the ImageSize equals the RVA plus the VirtualSize of \r
551 // the last section mapped into memory (Must be rounded up to \r
552 // a mulitple of Section Alignment). Per the PE/COFF specification, the\r
553 // section headers in the Section Table must appear in order of the RVA\r
554 // values for the corresponding sections. So the ImageSize can be determined\r
555 // by the RVA and the VirtualSize of the last section header in the\r
556 // Section Table.\r
557 //\r
558 if ((++Index) == (UINTN) TeHdr.NumberOfSections) {\r
559 ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize +\r
560 ImageContext->SectionAlignment - 1) & ~(ImageContext->SectionAlignment - 1);\r
561 }\r
562\r
563 SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
564 }\r
565\r
566 if (DebugDirectoryEntryFileOffset != 0) {\r
567 for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) {\r
568 //\r
569 // Read next debug directory entry\r
570 //\r
571 Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
572 Status = ImageContext->ImageRead (\r
573 ImageContext->Handle,\r
574 DebugDirectoryEntryFileOffset,\r
575 &Size,\r
576 &DebugEntry\r
577 );\r
578 if (EFI_ERROR (Status)) {\r
579 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;\r
580 return Status;\r
581 }\r
582\r
583 if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
584 ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));\r
585 return EFI_SUCCESS;\r
586 }\r
587 }\r
588 }\r
589 }\r
590\r
591 return EFI_SUCCESS;\r
592}\r
593\r
594STATIC\r
595VOID *\r
596PeCoffLoaderImageAddress (\r
597 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,\r
598 IN UINTN Address\r
599 )\r
600/*++\r
601\r
602Routine Description:\r
603\r
604 Converts an image address to the loaded address\r
605\r
606Arguments:\r
607\r
608 ImageContext - The context of the image being loaded\r
609\r
610 Address - The address to be converted to the loaded address\r
611\r
612Returns:\r
613\r
614 NULL if the address can not be converted, otherwise, the converted address\r
615\r
616--*/\r
617{\r
618 if (Address >= ImageContext->ImageSize) {\r
619 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_IMAGE_ADDRESS;\r
620 return NULL;\r
621 }\r
622\r
623 return (CHAR8 *) ((UINTN) ImageContext->ImageAddress + Address);\r
624}\r
625\r
626EFI_STATUS\r
627EFIAPI\r
628PeCoffLoaderRelocateImage (\r
629 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,\r
630 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
631 )\r
632/*++\r
633\r
634Routine Description:\r
635\r
636 Relocates a PE/COFF image in memory\r
637\r
638Arguments:\r
639\r
640 This - Calling context\r
641\r
642 ImageContext - Contains information on the loaded image to relocate\r
643\r
644Returns:\r
645\r
646 EFI_SUCCESS if the PE/COFF image was relocated\r
647 EFI_LOAD_ERROR if the image is not a valid PE/COFF image\r
648 EFI_UNSUPPORTED not support\r
649\r
650--*/\r
651{\r
652 EFI_STATUS Status;\r
653 EFI_IMAGE_NT_HEADERS *PeHdr;\r
654 EFI_TE_IMAGE_HEADER *TeHdr;\r
655 EFI_IMAGE_DATA_DIRECTORY *RelocDir;\r
656 UINT64 Adjust;\r
657 EFI_IMAGE_BASE_RELOCATION *RelocBase;\r
658 EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd;\r
659 UINT16 *Reloc;\r
660 UINT16 *RelocEnd;\r
661 CHAR8 *Fixup;\r
662 CHAR8 *FixupBase;\r
663 UINT16 *F16;\r
664 UINT32 *F32;\r
665 CHAR8 *FixupData;\r
666 EFI_PHYSICAL_ADDRESS BaseAddress;\r
667#ifdef EFI_NT_EMULATOR\r
668 VOID *DllEntryPoint;\r
669 VOID *ModHandle;\r
670 ModHandle = NULL;\r
671#endif\r
672\r
673 PeHdr = NULL;\r
674 TeHdr = NULL;\r
675 //\r
676 // Assume success\r
677 //\r
678 ImageContext->ImageError = EFI_IMAGE_ERROR_SUCCESS;\r
679\r
680 //\r
681 // If there are no relocation entries, then we are done\r
682 //\r
683 if (ImageContext->RelocationsStripped) {\r
684 return EFI_SUCCESS;\r
685 }\r
686\r
687 //\r
688 // If the destination address is not 0, use that rather than the\r
689 // image address as the relocation target.\r
690 //\r
691 if (ImageContext->DestinationAddress) {\r
692 BaseAddress = ImageContext->DestinationAddress;\r
693 } else {\r
694 BaseAddress = ImageContext->ImageAddress;\r
695 }\r
696\r
697 if (!(ImageContext->IsTeImage)) {\r
698 PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext->ImageAddress + \r
699 ImageContext->PeCoffHeaderOffset);\r
700 Adjust = (UINT64) BaseAddress - PeHdr->OptionalHeader.ImageBase;\r
701 PeHdr->OptionalHeader.ImageBase = (UINTN) BaseAddress;\r
702\r
703 //\r
704 // Find the relocation block\r
705 //\r
706 // Per the PE/COFF spec, you can't assume that a given data directory\r
707 // is present in the image. You have to check the NumberOfRvaAndSizes in\r
708 // the optional header to verify a desired directory entry is there.\r
709 //\r
710 if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
711 RelocDir = &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
712 RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);\r
713 RelocBaseEnd = PeCoffLoaderImageAddress (\r
714 ImageContext,\r
715 RelocDir->VirtualAddress + RelocDir->Size - 1\r
716 );\r
717 } else {\r
718 //\r
719 // Set base and end to bypass processing below.\r
720 //\r
721 RelocBase = RelocBaseEnd = 0;\r
722 }\r
723 } else {\r
724 TeHdr = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress);\r
725 Adjust = (UINT64) (BaseAddress - TeHdr->ImageBase);\r
726 TeHdr->ImageBase = (UINT64) (BaseAddress);\r
727\r
728 //\r
729 // Find the relocation block\r
730 //\r
731 RelocDir = &TeHdr->DataDirectory[0];\r
732 RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(\r
733 ImageContext->ImageAddress + \r
734 RelocDir->VirtualAddress +\r
735 sizeof(EFI_TE_IMAGE_HEADER) - \r
736 TeHdr->StrippedSize\r
737 );\r
738 RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);\r
739 }\r
740 \r
741 //\r
742 // Run the relocation information and apply the fixups\r
743 //\r
744 FixupData = ImageContext->FixupData;\r
745 while (RelocBase < RelocBaseEnd) {\r
746\r
747 Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));\r
748 RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);\r
749 if (!(ImageContext->IsTeImage)) {\r
750 FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);\r
751 } else {\r
752 FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress +\r
753 RelocBase->VirtualAddress +\r
754 sizeof(EFI_TE_IMAGE_HEADER) - \r
755 TeHdr->StrippedSize\r
756 );\r
757 }\r
758\r
759 if ((CHAR8 *) RelocEnd < (CHAR8 *) ((UINTN) ImageContext->ImageAddress) ||\r
760 (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress + \r
761 (UINTN)ImageContext->ImageSize)) {\r
762 ImageContext->ImageError = EFI_IMAGE_ERROR_FAILED_RELOCATION;\r
763 return EFI_LOAD_ERROR;\r
764 }\r
765\r
766 //\r
767 // Run this relocation record\r
768 //\r
769 while (Reloc < RelocEnd) {\r
770\r
771 Fixup = FixupBase + (*Reloc & 0xFFF);\r
772 switch ((*Reloc) >> 12) {\r
773 case EFI_IMAGE_REL_BASED_ABSOLUTE:\r
774 break;\r
775\r
776 case EFI_IMAGE_REL_BASED_HIGH:\r
777 F16 = (UINT16 *) Fixup;\r
778 *F16 = (UINT16) ((*F16 << 16) + (UINT16) Adjust);\r
779 if (FixupData != NULL) {\r
780 *(UINT16 *) FixupData = *F16;\r
781 FixupData = FixupData + sizeof (UINT16);\r
782 }\r
783 break;\r
784\r
785 case EFI_IMAGE_REL_BASED_LOW:\r
786 F16 = (UINT16 *) Fixup;\r
787 *F16 = (UINT16) (*F16 + (UINT16) Adjust);\r
788 if (FixupData != NULL) {\r
789 *(UINT16 *) FixupData = *F16;\r
790 FixupData = FixupData + sizeof (UINT16);\r
791 }\r
792 break;\r
793\r
794 case EFI_IMAGE_REL_BASED_HIGHLOW:\r
795 F32 = (UINT32 *) Fixup;\r
796 *F32 = *F32 + (UINT32) Adjust;\r
797 if (FixupData != NULL) {\r
798 FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));\r
799 *(UINT32 *) FixupData = *F32;\r
800 FixupData = FixupData + sizeof (UINT32);\r
801 }\r
802 break;\r
803\r
804 case EFI_IMAGE_REL_BASED_HIGHADJ:\r
805 //\r
806 // Return the same EFI_UNSUPPORTED return code as\r
807 // PeCoffLoaderRelocateImageEx() returns if it does not recognize\r
808 // the relocation type.\r
809 //\r
810 ImageContext->ImageError = EFI_IMAGE_ERROR_FAILED_RELOCATION;\r
811 return EFI_UNSUPPORTED;\r
812\r
813 default:\r
814 Status = PeCoffLoaderRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);\r
815 if (EFI_ERROR (Status)) {\r
816 ImageContext->ImageError = EFI_IMAGE_ERROR_FAILED_RELOCATION;\r
817 return Status;\r
818 }\r
819 }\r
820\r
821 //\r
822 // Next relocation record\r
823 //\r
824 Reloc += 1;\r
825 }\r
826\r
827 //\r
828 // Next reloc block\r
829 //\r
830 RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;\r
831 }\r
832\r
833#ifdef EFI_NT_EMULATOR\r
834 DllEntryPoint = NULL;\r
835 ImageContext->ModHandle = NULL;\r
836 //\r
837 // Load the DLL if it's not an EBC image.\r
838 //\r
839 if ((ImageContext->PdbPointer != NULL) && \r
840 (ImageContext->Machine != EFI_IMAGE_MACHINE_EBC)) {\r
841 Status = mPeCoffLoaderWinNtLoadAsDll->Entry (\r
842 ImageContext->PdbPointer,\r
843 &DllEntryPoint,\r
844 &ModHandle\r
845 );\r
846\r
847 if (!EFI_ERROR (Status) && DllEntryPoint != NULL) {\r
848 ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) DllEntryPoint;\r
849 ImageContext->ModHandle = ModHandle;\r
850 }\r
851 }\r
852#endif\r
853\r
854 return EFI_SUCCESS;\r
855}\r
856\r
857EFI_STATUS\r
858EFIAPI\r
859PeCoffLoaderLoadImage (\r
860 IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This,\r
861 IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
862 )\r
863/*++\r
864\r
865Routine Description:\r
866\r
867 Loads a PE/COFF image into memory\r
868\r
869Arguments:\r
870\r
871 This - Calling context\r
872\r
873 ImageContext - Contains information on image to load into memory\r
874\r
875Returns:\r
876\r
877 EFI_SUCCESS if the PE/COFF image was loaded\r
878 EFI_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer\r
879 EFI_LOAD_ERROR if the image is a runtime driver with no relocations\r
880 EFI_INVALID_PARAMETER if the image address is invalid\r
881\r
882--*/\r
883{\r
884 EFI_STATUS Status;\r
885 EFI_IMAGE_NT_HEADERS *PeHdr;\r
886 EFI_TE_IMAGE_HEADER *TeHdr;\r
887 EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT CheckContext;\r
888 EFI_IMAGE_SECTION_HEADER *FirstSection;\r
889 EFI_IMAGE_SECTION_HEADER *Section;\r
890 UINTN NumberOfSections;\r
891 UINTN Index;\r
892 CHAR8 *Base;\r
893 CHAR8 *End;\r
894 CHAR8 *MaxEnd;\r
895 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;\r
896 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
897 UINTN Size;\r
898 UINT32 TempDebugEntryRva;\r
899\r
900 PeHdr = NULL;\r
901 TeHdr = NULL;\r
902 //\r
903 // Assume success\r
904 //\r
905 ImageContext->ImageError = EFI_IMAGE_ERROR_SUCCESS;\r
906\r
907 //\r
908 // Copy the provided context info into our local version, get what we\r
909 // can from the original image, and then use that to make sure everything\r
910 // is legit.\r
911 //\r
912 CopyMem (&CheckContext, ImageContext, sizeof (EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT));\r
913\r
914 Status = PeCoffLoaderGetImageInfo (\r
915 This,\r
916 &CheckContext\r
917 );\r
918 if (EFI_ERROR (Status)) {\r
919 return Status;\r
920 }\r
921\r
922 //\r
923 // Make sure there is enough allocated space for the image being loaded\r
924 //\r
925 if (ImageContext->ImageSize < CheckContext.ImageSize) {\r
926 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_IMAGE_SIZE;\r
927 return EFI_BUFFER_TOO_SMALL;\r
928 }\r
929\r
930 //\r
931 // If there's no relocations, then make sure it's not a runtime driver,\r
932 // and that it's being loaded at the linked address.\r
933 //\r
934 if (CheckContext.RelocationsStripped) {\r
935 //\r
936 // If the image does not contain relocations and it is a runtime driver\r
937 // then return an error.\r
938 //\r
939 if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {\r
940 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_SUBSYSTEM;\r
941 return EFI_LOAD_ERROR;\r
942 }\r
943 //\r
944 // If the image does not contain relocations, and the requested load address\r
945 // is not the linked address, then return an error.\r
946 //\r
947 if (CheckContext.ImageAddress != ImageContext->ImageAddress) {\r
948 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_IMAGE_ADDRESS;\r
949 return EFI_INVALID_PARAMETER;\r
950 }\r
951 }\r
952 //\r
953 // Make sure the allocated space has the proper section alignment\r
954 //\r
955 if (!(ImageContext->IsTeImage)) {\r
956 if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) {\r
957 ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_SECTION_ALIGNMENT;\r
958 return EFI_INVALID_PARAMETER;\r
959 }\r
960 }\r
961 //\r
962 // Read the entire PE/COFF or TE header into memory\r
963 //\r
964 if (!(ImageContext->IsTeImage)) {\r
965 Status = ImageContext->ImageRead (\r
966 ImageContext->Handle,\r
967 0,\r
968 &ImageContext->SizeOfHeaders,\r
969 (VOID *) (UINTN) ImageContext->ImageAddress\r
970 );\r
971\r
972 PeHdr = (EFI_IMAGE_NT_HEADERS *)\r
973 ((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);\r
974\r
975 FirstSection = (EFI_IMAGE_SECTION_HEADER *) (\r
976 (UINTN)ImageContext->ImageAddress +\r
977 ImageContext->PeCoffHeaderOffset +\r
978 sizeof(UINT32) + \r
979 sizeof(EFI_IMAGE_FILE_HEADER) + \r
980 PeHdr->FileHeader.SizeOfOptionalHeader\r
981 );\r
982 NumberOfSections = (UINTN) (PeHdr->FileHeader.NumberOfSections);\r
983 } else {\r
984 Status = ImageContext->ImageRead (\r
985 ImageContext->Handle,\r
986 0,\r
987 &ImageContext->SizeOfHeaders,\r
988 (void *) (UINTN) ImageContext->ImageAddress\r
989 );\r
990\r
991 TeHdr = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress);\r
992\r
993 FirstSection = (EFI_IMAGE_SECTION_HEADER *) (\r
994 (UINTN)ImageContext->ImageAddress +\r
995 sizeof(EFI_TE_IMAGE_HEADER)\r
996 );\r
997 NumberOfSections = (UINTN) (TeHdr->NumberOfSections);\r
998\r
999 }\r
1000\r
1001 if (EFI_ERROR (Status)) {\r
1002 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;\r
1003 return EFI_LOAD_ERROR;\r
1004 }\r
1005\r
1006 //\r
1007 // Load each section of the image\r
1008 //\r
1009 Section = FirstSection;\r
1010 for (Index = 0, MaxEnd = NULL; Index < NumberOfSections; Index++) {\r
1011\r
1012 //\r
1013 // Compute sections address\r
1014 //\r
1015 Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress);\r
1016 End = PeCoffLoaderImageAddress (\r
1017 ImageContext,\r
1018 Section->VirtualAddress + Section->Misc.VirtualSize - 1\r
1019 );\r
1020 if (ImageContext->IsTeImage) {\r
1021 Base = (CHAR8 *) ((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);\r
1022 End = (CHAR8 *) ((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);\r
1023 }\r
1024\r
1025 if (End > MaxEnd) {\r
1026 MaxEnd = End;\r
1027 }\r
1028 //\r
1029 // If the base start or end address resolved to 0, then fail.\r
1030 //\r
1031 if ((Base == NULL) || (End == NULL)) {\r
1032 ImageContext->ImageError = EFI_IMAGE_ERROR_SECTION_NOT_LOADED;\r
1033 return EFI_LOAD_ERROR;\r
1034 }\r
1035\r
1036 //\r
1037 // Read the section\r
1038 //\r
1039 Size = (UINTN) Section->Misc.VirtualSize;\r
1040 if ((Size == 0) || (Size > Section->SizeOfRawData)) {\r
1041 Size = (UINTN) Section->SizeOfRawData;\r
1042 }\r
1043\r
1044 if (Section->SizeOfRawData) {\r
1045 if (!(ImageContext->IsTeImage)) {\r
1046 Status = ImageContext->ImageRead (\r
1047 ImageContext->Handle,\r
1048 Section->PointerToRawData,\r
1049 &Size,\r
1050 Base\r
1051 );\r
1052 } else {\r
1053 Status = ImageContext->ImageRead (\r
1054 ImageContext->Handle,\r
1055 Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize,\r
1056 &Size,\r
1057 Base\r
1058 );\r
1059 }\r
1060\r
1061 if (EFI_ERROR (Status)) {\r
1062 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;\r
1063 return Status;\r
1064 }\r
1065 }\r
1066\r
1067 //\r
1068 // If raw size is less then virt size, zero fill the remaining\r
1069 //\r
1070\r
1071 if (Size < Section->Misc.VirtualSize) {\r
1072 ZeroMem (Base + Size, Section->Misc.VirtualSize - Size);\r
1073 }\r
1074\r
1075 //\r
1076 // Next Section\r
1077 //\r
1078 Section += 1;\r
1079 }\r
1080\r
1081 //\r
1082 // Get image's entry point\r
1083 //\r
1084 if (!(ImageContext->IsTeImage)) {\r
1085 ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress (\r
1086 ImageContext,\r
1087 PeHdr->OptionalHeader.AddressOfEntryPoint\r
1088 );\r
1089 } else {\r
1090 ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) (\r
1091 (UINTN)ImageContext->ImageAddress +\r
1092 (UINTN)TeHdr->AddressOfEntryPoint +\r
1093 (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -\r
1094 (UINTN) TeHdr->StrippedSize\r
1095 );\r
1096 }\r
1097\r
1098 //\r
1099 // Determine the size of the fixup data\r
1100 //\r
1101 // Per the PE/COFF spec, you can't assume that a given data directory\r
1102 // is present in the image. You have to check the NumberOfRvaAndSizes in\r
1103 // the optional header to verify a desired directory entry is there.\r
1104 //\r
1105 if (!(ImageContext->IsTeImage)) {\r
1106 if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
1107 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)\r
1108 &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
1109 ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);\r
1110 } else {\r
1111 ImageContext->FixupDataSize = 0;\r
1112 }\r
1113 } else {\r
1114 DirectoryEntry = &TeHdr->DataDirectory[0];\r
1115 ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN);\r
1116 }\r
1117 //\r
1118 // Consumer must allocate a buffer for the relocation fixup log.\r
1119 // Only used for runtime drivers.\r
1120 //\r
1121 ImageContext->FixupData = NULL;\r
1122\r
1123 //\r
1124 // Load the Codeview info if present\r
1125 //\r
1126 if (ImageContext->DebugDirectoryEntryRva != 0) {\r
1127 if (!(ImageContext->IsTeImage)) {\r
1128 DebugEntry = PeCoffLoaderImageAddress (\r
1129 ImageContext,\r
1130 ImageContext->DebugDirectoryEntryRva\r
1131 );\r
1132 } else {\r
1133 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(\r
1134 ImageContext->ImageAddress +\r
1135 ImageContext->DebugDirectoryEntryRva +\r
1136 sizeof(EFI_TE_IMAGE_HEADER) -\r
1137 TeHdr->StrippedSize\r
1138 );\r
1139 }\r
1140\r
1141 if (DebugEntry != NULL) {\r
1142 TempDebugEntryRva = DebugEntry->RVA;\r
1143 if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) {\r
1144 Section--;\r
1145 if ((UINTN) Section->SizeOfRawData < Section->Misc.VirtualSize) {\r
1146 TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize;\r
1147 } else {\r
1148 TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData;\r
1149 }\r
1150 }\r
1151\r
1152 if (TempDebugEntryRva != 0) {\r
1153 if (!(ImageContext->IsTeImage)) {\r
1154 ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva);\r
1155 } else {\r
1156 ImageContext->CodeView = (VOID *)(\r
1157 (UINTN)ImageContext->ImageAddress +\r
1158 (UINTN)TempDebugEntryRva +\r
1159 (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -\r
1160 (UINTN) TeHdr->StrippedSize\r
1161 );\r
1162 }\r
1163\r
1164 if (ImageContext->CodeView == NULL) {\r
1165 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;\r
1166 return EFI_LOAD_ERROR;\r
1167 }\r
1168\r
1169 if (DebugEntry->RVA == 0) {\r
1170 Size = DebugEntry->SizeOfData;\r
1171 if (!(ImageContext->IsTeImage)) {\r
1172 Status = ImageContext->ImageRead (\r
1173 ImageContext->Handle,\r
1174 DebugEntry->FileOffset,\r
1175 &Size,\r
1176 ImageContext->CodeView\r
1177 );\r
1178 } else {\r
1179 Status = ImageContext->ImageRead (\r
1180 ImageContext->Handle,\r
1181 DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - TeHdr->StrippedSize,\r
1182 &Size,\r
1183 ImageContext->CodeView\r
1184 );\r
1185 //\r
1186 // Should we apply fix up to this field according to the size difference between PE and TE?\r
1187 // Because now we maintain TE header fields unfixed, this field will also remain as they are\r
1188 // in original PE image.\r
1189 //\r
1190 }\r
1191\r
1192 if (EFI_ERROR (Status)) {\r
1193 ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ;\r
1194 return EFI_LOAD_ERROR;\r
1195 }\r
1196\r
1197 DebugEntry->RVA = TempDebugEntryRva;\r
1198 }\r
1199\r
1200 switch (*(UINT32 *) ImageContext->CodeView) {\r
1201 case CODEVIEW_SIGNATURE_NB10:\r
1202 ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);\r
1203 break;\r
1204\r
1205 case CODEVIEW_SIGNATURE_RSDS:\r
1206 ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);\r
1207 break;\r
1208\r
1209 default:\r
1210 break;\r
1211 }\r
1212 }\r
1213 }\r
1214 }\r
1215\r
1216 return Status;\r
1217}\r
1218\r
1219EFI_STATUS\r
1220EFIAPI\r
1221PeCoffLoaderUnloadImage (\r
1222 IN EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext\r
1223 )\r
1224/*++\r
1225\r
1226Routine Description:\r
1227\r
1228 Unload a PE/COFF image from memory\r
1229\r
1230Arguments:\r
1231\r
1232 ImageContext - Contains information on image to load into memory\r
1233\r
1234Returns:\r
1235\r
1236 EFI_SUCCESS \r
1237\r
1238--*/\r
1239{\r
1240#ifdef EFI_NT_EMULATOR\r
1241 //\r
1242 // Calling Win32 API free library\r
1243 //\r
1244 mPeCoffLoaderWinNtLoadAsDll->FreeLibrary (ImageContext->ModHandle);\r
1245\r
1246#endif\r
1247\r
1248 return EFI_SUCCESS;\r
1249}\r