BasePeCoff.c 51 KB

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