]> git.proxmox.com Git - mirror_edk2.git/blame - UnixPkg/Library/EdkUnixPeiPeCoffGetEntryPointLib/PeCoffGetEntryPoint.c
Fix lib to use standard #defines for PE/COFF machine types
[mirror_edk2.git] / UnixPkg / Library / EdkUnixPeiPeCoffGetEntryPointLib / PeCoffGetEntryPoint.c
CommitLineData
804405e7 1/*++\r
2\r
3Copyright (c) 2006 - 2008, 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 PeCoffGetEntryPoint.c\r
15\r
16Abstract:\r
17\r
18 Tiano PE/COFF loader\r
19\r
20Revision History\r
21\r
22--*/\r
23#include "PiPei.h"\r
24#include <Library/PeCoffGetEntryPointLib.h>\r
25#include <Library/PeiServicesLib.h>\r
26#include <Ppi/UnixPeiLoadFile.h>\r
27#include <IndustryStandard/PeImage.h>\r
28#include <Library/DebugLib.h>\r
29\r
30RETURN_STATUS\r
31EFIAPI\r
32PeCoffLoaderGetEntryPoint (\r
33 IN VOID *Pe32Data,\r
34 IN OUT VOID **EntryPoint\r
35 )\r
36/*++\r
37\r
38Routine Description:\r
39\r
40 Loads a PE/COFF image into memory, this is not follow the original purpose of \r
41 PeCoffGetEntryPoint library class. But it's ok that Unix package not run on a real \r
42 platform and this is for source level debug.\r
43\r
44Arguments:\r
45\r
46 Pe32Data - Pointer to a PE/COFF Image\r
47\r
48 EntryPoint - Pointer to the entry point of the PE/COFF image\r
49\r
50Returns:\r
51\r
52 EFI_SUCCESS if the EntryPoint was returned\r
53 EFI_INVALID_PARAMETER if the EntryPoint could not be found from Pe32Data\r
54\r
55--*/\r
56{\r
57 EFI_STATUS Status;\r
58 EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor;\r
59 UNIX_PEI_LOAD_FILE_PPI *PeiUnixService;\r
60 EFI_PHYSICAL_ADDRESS ImageAddress;\r
61 UINT64 ImageSize;\r
62 EFI_PHYSICAL_ADDRESS ImageEntryPoint;\r
63\r
64 ASSERT (Pe32Data != NULL);\r
65 ASSERT (EntryPoint != NULL);\r
66\r
67 Status = PeiServicesLocatePpi (\r
68 &gUnixPeiLoadFilePpiGuid,\r
69 0,\r
70 &PpiDescriptor,\r
71 (void **)&PeiUnixService\r
72 );\r
73\r
74 ASSERT_EFI_ERROR (Status);\r
75\r
76 Status = PeiUnixService->PeiLoadFileService (\r
77 Pe32Data,\r
78 &ImageAddress,\r
79 &ImageSize,\r
80 &ImageEntryPoint\r
81 );\r
82\r
83 if (EFI_ERROR (Status)) {\r
84 return Status;\r
85 }\r
86\r
87 *EntryPoint = (VOID*)(UINTN)ImageEntryPoint;\r
88 return Status;\r
89}\r
90\r
91/**\r
92 Returns the machine type of PE/COFF image. \r
93 This is copied from MDE BasePeCoffGetEntryPointLib, the code should be sync with it.\r
94 The reason is Unix package needs to load the image to memory to support source\r
95 level debug.\r
96 \r
97\r
98 @param Pe32Data Pointer to a PE/COFF header\r
99\r
100 @return Machine type or zero if not a valid iamge\r
101\r
102**/\r
103UINT16\r
104EFIAPI\r
105PeCoffLoaderGetMachineType (\r
106 IN VOID *Pe32Data\r
107 )\r
108{ \r
109 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
110 EFI_IMAGE_DOS_HEADER *DosHdr;\r
111\r
112 ASSERT (Pe32Data != NULL);\r
113\r
114 DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
115 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
116 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
117\r
118 } else {\r
119 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data);\r
120 }\r
121\r
122 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
123 return Hdr.Te->Machine;\r
124 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
125 return Hdr.Pe32->FileHeader.Machine;\r
126 }\r
127\r
128 return 0x0000;\r
129}\r
130\r
131/**\r
132 Returns a pointer to the PDB file name for a PE/COFF image that has been\r
133 loaded into system memory with the PE/COFF Loader Library functions.\r
134\r
135 Returns the PDB file name for the PE/COFF image specified by Pe32Data. If\r
136 the PE/COFF image specified by Pe32Data is not a valid, then NULL is\r
137 returned. If the PE/COFF image specified by Pe32Data does not contain a\r
138 debug directory entry, then NULL is returned. If the debug directory entry\r
139 in the PE/COFF image specified by Pe32Data does not contain a PDB file name,\r
140 then NULL is returned.\r
141 If Pe32Data is NULL, then ASSERT().\r
142\r
143 @param Pe32Data Pointer to the PE/COFF image that is loaded in system\r
144 memory.\r
145\r
146 @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL\r
147 if it cannot be retrieved.\r
148\r
149**/\r
150VOID *\r
151EFIAPI\r
152PeCoffLoaderGetPdbPointer (\r
153 IN VOID *Pe32Data\r
154 )\r
155{\r
156 EFI_IMAGE_DOS_HEADER *DosHdr;\r
157 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
158 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;\r
159 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
160 UINTN DirCount;\r
161 VOID *CodeViewEntryPointer;\r
162 INTN TEImageAdjust;\r
163 UINT32 NumberOfRvaAndSizes;\r
164 UINT16 Magic;\r
165\r
166 ASSERT (Pe32Data != NULL);\r
167\r
168 TEImageAdjust = 0;\r
169 DirectoryEntry = NULL;\r
170 DebugEntry = NULL;\r
171 NumberOfRvaAndSizes = 0;\r
172\r
173 DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
174 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
175 //\r
176 // DOS image header is present, so read the PE header after the DOS image header.\r
177 //\r
178 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
179 } else {\r
180 //\r
181 // DOS image header is not present, so PE header is at the image base.\r
182 //\r
183 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
184 }\r
185\r
186 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
187 if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {\r
188 DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
189 TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;\r
190 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te +\r
191 Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +\r
192 TEImageAdjust);\r
193 }\r
194 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
195 //\r
196 // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.\r
197 // It is due to backward-compatibility, for some system might\r
198 // generate PE32+ image with PE32 Magic.\r
199 //\r
200 switch (Hdr.Pe32->FileHeader.Machine) {\r
201 case EFI_IMAGE_MACHINE_IA32:\r
202 //\r
203 // Assume PE32 image with IA32 Machine field.\r
204 //\r
205 Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
206 break;\r
207 case EFI_IMAGE_MACHINE_X64:\r
e54ce904 208 case EFI_IMAGE_MACHINE_IA64:\r
804405e7 209 //\r
e54ce904 210 // Assume PE32+ image with X64 or IA64 Machine field\r
804405e7 211 //\r
212 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
213 break;\r
214 default:\r
215 //\r
216 // For unknow Machine field, use Magic in optional Header\r
217 //\r
218 Magic = Hdr.Pe32->OptionalHeader.Magic;\r
219 }\r
220\r
221 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
222 //\r
223 // Use PE32 offset get Debug Directory Entry\r
224 //\r
225 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
226 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
227 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
228 } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
229 //\r
230 // Use PE32+ offset get Debug Directory Entry\r
231 //\r
232 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
233 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
234 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
235 }\r
236\r
237 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
238 DirectoryEntry = NULL;\r
239 DebugEntry = NULL;\r
240 }\r
241 } else {\r
242 return NULL;\r
243 }\r
244\r
245 if (DebugEntry == NULL || DirectoryEntry == NULL) {\r
246 return NULL;\r
247 }\r
248\r
249 for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {\r
250 if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
251 if (DebugEntry->SizeOfData > 0) {\r
252 CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust);\r
253 switch (* (UINT32 *) CodeViewEntryPointer) {\r
254 case CODEVIEW_SIGNATURE_NB10:\r
255 return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY));\r
256 case CODEVIEW_SIGNATURE_RSDS:\r
257 return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY));\r
258 default:\r
259 break;\r
260 }\r
261 }\r
262 }\r
263 }\r
264\r
265 return NULL;\r
266}\r