EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

Nt32Pkg/Library/Nt32PeiPeCoffGetEntryPointLib/PeCoffGetEntryPoint.c

Go to the documentation of this file.
00001 
00024 #include <PiPei.h>
00025 #include <IndustryStandard/PeImage.h>
00026 #include <WinNtPeim.h>
00027 #include <Ppi/NtPeiLoadFile.h>
00028 #include <Library/PeCoffGetEntryPointLib.h>
00029 #include <Library/PeiServicesLib.h>
00030 #include <Library/DebugLib.h>
00031 
00032 
00033 RETURN_STATUS
00034 EFIAPI
00035 PeCoffLoaderGetEntryPoint (
00036   IN     VOID  *Pe32Data,
00037   IN OUT VOID  **EntryPoint
00038   )
00039 /*++
00040 
00041 Routine Description:
00042 
00043   Loads a PE/COFF image into memory, this is not follow the original purpose of 
00044   PeCoffGetEntryPoint library class.  But it's ok that Unix package not run on a real 
00045   platform and this is for source level debug.
00046 
00047 Arguments:
00048 
00049   Pe32Data   - Pointer to a PE/COFF Image
00050 
00051   EntryPoint - Pointer to the entry point of the PE/COFF image
00052 
00053 Returns:
00054 
00055   EFI_SUCCESS            if the EntryPoint was returned
00056   EFI_INVALID_PARAMETER  if the EntryPoint could not be found from Pe32Data
00057 
00058 --*/
00059 {
00060   EFI_STATUS              Status;
00061   EFI_PEI_PPI_DESCRIPTOR  *PpiDescriptor;
00062   NT_PEI_LOAD_FILE_PPI    *PeiNtService;
00063   EFI_PHYSICAL_ADDRESS    ImageAddress;
00064   UINT64                  ImageSize;
00065   EFI_PHYSICAL_ADDRESS    ImageEntryPoint;
00066 
00067   ASSERT (Pe32Data   != NULL);
00068   ASSERT (EntryPoint != NULL);
00069 
00070   Status = PeiServicesLocatePpi (
00071              &gNtPeiLoadFilePpiGuid,
00072              0,
00073              &PpiDescriptor,
00074              (VOID**)&PeiNtService
00075              );
00076   ASSERT_EFI_ERROR (Status);
00077 
00078   Status = PeiNtService->PeiLoadFileService (
00079                            Pe32Data,
00080                            &ImageAddress,
00081                            &ImageSize,
00082                            &ImageEntryPoint
00083                            );
00084   if (EFI_ERROR (Status)) {
00085     return Status;
00086   }
00087 
00088   *EntryPoint = (VOID*)(UINTN)ImageEntryPoint;
00089   return Status;
00090 }
00091 
00104 UINT16
00105 EFIAPI
00106 PeCoffLoaderGetMachineType (
00107   IN  VOID  *Pe32Data
00108   )
00109 {  
00110   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
00111   EFI_IMAGE_DOS_HEADER                 *DosHdr;
00112 
00113   ASSERT (Pe32Data   != NULL);
00114 
00115   DosHdr = (EFI_IMAGE_DOS_HEADER  *)Pe32Data;
00116   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
00117     //
00118     // DOS image header is present, so read the PE header after the DOS image header.
00119     //
00120     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
00121   } else {
00122     //
00123     // DOS image header is not present, so PE header is at the image base.
00124     //
00125     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
00126   }
00127 
00128   if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
00129     return Hdr.Te->Machine;
00130   } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)  {
00131     return Hdr.Pe32->FileHeader.Machine;
00132   }
00133 
00134   return 0x0000;
00135 }
00136 
00156 VOID *
00157 EFIAPI
00158 PeCoffLoaderGetPdbPointer (
00159   IN VOID  *Pe32Data
00160   )
00161 {
00162   EFI_IMAGE_DOS_HEADER                  *DosHdr;
00163   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;
00164   EFI_IMAGE_DATA_DIRECTORY              *DirectoryEntry;
00165   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY       *DebugEntry;
00166   UINTN                                 DirCount;
00167   VOID                                  *CodeViewEntryPointer;
00168   INTN                                  TEImageAdjust;
00169   UINT32                                NumberOfRvaAndSizes;
00170   UINT16                                Magic;
00171 
00172   ASSERT (Pe32Data   != NULL);
00173 
00174   TEImageAdjust       = 0;
00175   DirectoryEntry      = NULL;
00176   DebugEntry          = NULL;
00177   NumberOfRvaAndSizes = 0;
00178 
00179   DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
00180   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
00181     //
00182     // DOS image header is present, so read the PE header after the DOS image header.
00183     //
00184     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
00185   } else {
00186     //
00187     // DOS image header is not present, so PE header is at the image base.
00188     //
00189     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
00190   }
00191 
00192   if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
00193     if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {
00194       DirectoryEntry  = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];
00195       TEImageAdjust   = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;
00196       DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te +
00197                     Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +
00198                     TEImageAdjust);
00199     }
00200   } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
00201     //
00202     // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.
00203     //       It is due to backward-compatibility, for some system might
00204     //       generate PE32+ image with PE32 Magic.
00205     //
00206     switch (Hdr.Pe32->FileHeader.Machine) {
00207     case IMAGE_FILE_MACHINE_I386:
00208       //
00209       // Assume PE32 image with IA32 Machine field.
00210       //
00211       Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
00212       break;
00213     case IMAGE_FILE_MACHINE_X64:
00214     case IMAGE_FILE_MACHINE_IA64:
00215       //
00216       // Assume PE32+ image with X64 or IA64 Machine field
00217       //
00218       Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
00219       break;
00220     default:
00221       //
00222       // For unknow Machine field, use Magic in optional Header
00223       //
00224       Magic = Hdr.Pe32->OptionalHeader.Magic;
00225     }
00226 
00227     if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
00228       //
00229       // Use PE32 offset get Debug Directory Entry
00230       //
00231       NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
00232       DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
00233       DebugEntry     = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);
00234     } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
00235       //
00236       // Use PE32+ offset get Debug Directory Entry
00237       //
00238       NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
00239       DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
00240       DebugEntry     = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);
00241     }
00242 
00243     if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
00244       DirectoryEntry = NULL;
00245       DebugEntry = NULL;
00246     }
00247   } else {
00248     return NULL;
00249   }
00250 
00251   if (DebugEntry == NULL || DirectoryEntry == NULL) {
00252     return NULL;
00253   }
00254 
00255   for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {
00256     if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
00257       if (DebugEntry->SizeOfData > 0) {
00258         CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust);
00259         switch (* (UINT32 *) CodeViewEntryPointer) {
00260         case CODEVIEW_SIGNATURE_NB10:
00261           return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY));
00262         case CODEVIEW_SIGNATURE_RSDS:
00263           return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY));
00264         case CODEVIEW_SIGNATURE_MTOC:              
00265           return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY));
00266           break;
00267         default:
00268           break;
00269         }
00270       }
00271     }
00272   }
00273 
00274   return NULL;
00275 }
00276 
00289 UINT32
00290 EFIAPI
00291 PeCoffGetSizeOfHeaders (
00292   IN VOID     *Pe32Data
00293   )
00294 {
00295   EFI_IMAGE_DOS_HEADER                  *DosHdr;
00296   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;
00297   UINTN                                 SizeOfHeaders;
00298 
00299   ASSERT (Pe32Data   != NULL);
00300  
00301   DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
00302   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
00303     //
00304     // DOS image header is present, so read the PE header after the DOS image header.
00305     //
00306     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
00307   } else {
00308     //
00309     // DOS image header is not present, so PE header is at the image base.
00310     //
00311     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
00312   }
00313 
00314   if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
00315     SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;
00316   } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
00317     SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
00318   } else {
00319     SizeOfHeaders = 0;
00320   }
00321 
00322   return SizeOfHeaders;
00323 }
00324 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines