basepe.c 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. basepe.c
  9. Abstract:
  10. This module implements basic PE/COFF file loader support.
  11. Author:
  12. Evan Green 13-Mar-2014
  13. Environment:
  14. Firmware
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "ueficore.h"
  20. #include "imagep.h"
  21. //
  22. // ---------------------------------------------------------------- Definitions
  23. //
  24. //
  25. // ------------------------------------------------------ Data Type Definitions
  26. //
  27. //
  28. // ----------------------------------------------- Internal Function Prototypes
  29. //
  30. VOID *
  31. EfipPeLoaderGetAddress (
  32. PEFI_PE_LOADER_CONTEXT Context,
  33. UINTN Address,
  34. UINTN TeStrippedOffset
  35. );
  36. //
  37. // -------------------------------------------------------------------- Globals
  38. //
  39. //
  40. // ------------------------------------------------------------------ Functions
  41. //
  42. EFIAPI
  43. RETURN_STATUS
  44. EfiPeLoaderLoadImage (
  45. PEFI_PE_LOADER_CONTEXT Context
  46. )
  47. /*++
  48. Routine Description:
  49. This routine loads a PE/COFF image.
  50. Arguments:
  51. Context - Supplies a pointer to the image context. Before calling this
  52. function the caller must have allocated the load buffer and filled in
  53. the image address and size fields.
  54. Return Value:
  55. RETURN_SUCCESS on success.
  56. RETURN_INVALID_PARAMETER if the image address is invalid.
  57. RETURN_LOAD_ERROR if the image is a PE/COFF runtime image with no
  58. relocations.
  59. RETURN_BUFFER_TOO_SMALL if the caller provided buffer was not large enough.
  60. --*/
  61. {
  62. CHAR8 *Base;
  63. EFI_PE_LOADER_CONTEXT CheckContext;
  64. EFI_IMAGE_DATA_DIRECTORY *Directories;
  65. EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
  66. CHAR8 *End;
  67. UINTN EntryPoint;
  68. EFI_IMAGE_SECTION_HEADER *FirstSection;
  69. UINTN FirstSectionOffset;
  70. EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Header;
  71. UINTN Index;
  72. UINT16 Magic;
  73. UINT32 NumberOfRvaAndSizes;
  74. UINT32 Offset;
  75. EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry;
  76. EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory;
  77. EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *ResourceDirectoryEntry;
  78. EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;
  79. EFI_IMAGE_SECTION_HEADER *Section;
  80. UINTN SectionCount;
  81. UINTN Size;
  82. RETURN_STATUS Status;
  83. CHAR16 *String;
  84. UINT32 TeStrippedOffset;
  85. ASSERT(Context != NULL);
  86. Context->ImageError = IMAGE_ERROR_SUCCESS;
  87. NumberOfRvaAndSizes = 0;
  88. Directories = NULL;
  89. //
  90. // Copy the provided context information into the local version.
  91. //
  92. EfiCoreCopyMemory(&CheckContext, Context, sizeof(EFI_PE_LOADER_CONTEXT));
  93. Status = EfiPeLoaderGetImageInfo(&CheckContext);
  94. if (RETURN_ERROR(Status)) {
  95. return Status;
  96. }
  97. //
  98. // Make sure there is enough allocated space for the image being loaded.
  99. //
  100. if (Context->ImageSize < CheckContext.ImageSize) {
  101. Context->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE;
  102. return RETURN_BUFFER_TOO_SMALL;
  103. }
  104. if (Context->ImageAddress == 0) {
  105. Context->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
  106. return RETURN_INVALID_PARAMETER;
  107. }
  108. //
  109. // If there are no relocations, it had better be loaded at its linked
  110. // address and not be a runtime driver.
  111. //
  112. if (CheckContext.RelocationsStripped != FALSE) {
  113. if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) {
  114. Context->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM;
  115. return RETURN_LOAD_ERROR;
  116. }
  117. if (CheckContext.ImageAddress != Context->ImageAddress) {
  118. Context->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
  119. return RETURN_INVALID_PARAMETER;
  120. }
  121. }
  122. //
  123. // Make sure the allocated space has the proper alignment.
  124. //
  125. if (Context->IsTeImage == FALSE) {
  126. if (Context->ImageAddress !=
  127. ALIGN_VALUE(Context->ImageAddress, CheckContext.SectionAlignment)) {
  128. Context->ImageError = IMAGE_ERROR_INVALID_SECTION_ALIGNMENT;
  129. return RETURN_INVALID_PARAMETER;
  130. }
  131. }
  132. //
  133. // Read the entire PE or TE header into memory.
  134. //
  135. Status = Context->ImageRead(Context->Handle,
  136. 0,
  137. &(Context->SizeOfHeaders),
  138. (VOID *)(UINTN)(Context->ImageAddress));
  139. if (Context->IsTeImage == FALSE) {
  140. Header.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Context->ImageAddress +
  141. Context->PeCoffHeaderOffset);
  142. FirstSectionOffset = Context->PeCoffHeaderOffset + sizeof(UINT32) +
  143. sizeof(EFI_IMAGE_FILE_HEADER) +
  144. Header.Pe32->FileHeader.SizeOfOptionalHeader;
  145. FirstSection =
  146. (EFI_IMAGE_SECTION_HEADER *)((UINTN)Context->ImageAddress +
  147. FirstSectionOffset);
  148. SectionCount = (UINTN)(Header.Pe32->FileHeader.NumberOfSections);
  149. TeStrippedOffset = 0;
  150. } else {
  151. Header.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(Context->ImageAddress);
  152. FirstSection =
  153. (EFI_IMAGE_SECTION_HEADER *)((UINTN)Context->ImageAddress +
  154. sizeof(EFI_TE_IMAGE_HEADER));
  155. SectionCount = (UINTN)(Header.Te->NumberOfSections);
  156. TeStrippedOffset = (UINT32)(Header.Te->StrippedSize) -
  157. sizeof(EFI_TE_IMAGE_HEADER);
  158. }
  159. if (RETURN_ERROR(Status)) {
  160. Context->ImageError = IMAGE_ERROR_IMAGE_READ;
  161. return RETURN_LOAD_ERROR;
  162. }
  163. //
  164. // Load each section of the image.
  165. //
  166. Section = FirstSection;
  167. for (Index = 0; Index < SectionCount; Index += 1) {
  168. Size = (UINTN)(Section->Misc.VirtualSize);
  169. if ((Size == 0) || (Size > Section->SizeOfRawData)) {
  170. Size = (UINTN)Section->SizeOfRawData;
  171. }
  172. //
  173. // Compute the section addresses.
  174. //
  175. Base = EfipPeLoaderGetAddress(Context,
  176. Section->VirtualAddress,
  177. TeStrippedOffset);
  178. End = EfipPeLoaderGetAddress(
  179. Context,
  180. Section->VirtualAddress + Section->Misc.VirtualSize - 1,
  181. TeStrippedOffset);
  182. if ((Size > 0) && ((Base == NULL) || (End == NULL))) {
  183. Context->ImageError = IMAGE_ERROR_SECTION_NOT_LOADED;
  184. return RETURN_LOAD_ERROR;
  185. }
  186. if (Section->SizeOfRawData > 0) {
  187. Status = Context->ImageRead(
  188. Context->Handle,
  189. Section->PointerToRawData - TeStrippedOffset,
  190. &Size,
  191. Base);
  192. if (RETURN_ERROR(Status)) {
  193. Context->ImageError = IMAGE_ERROR_IMAGE_READ;
  194. return RETURN_LOAD_ERROR;
  195. }
  196. }
  197. //
  198. // If the raw size is less than the virtual size, zero fill the
  199. // remainder.
  200. //
  201. if (Size < Section->Misc.VirtualSize) {
  202. EfiSetMem(Base + Size, Section->Misc.VirtualSize - Size, 0);
  203. }
  204. Section += 1;
  205. }
  206. //
  207. // Get the image entry point.
  208. //
  209. Magic = EfiPeLoaderGetPeHeaderMagicValue(Header);
  210. if (Context->IsTeImage == FALSE) {
  211. if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  212. EntryPoint =
  213. (UINTN)(Header.Pe32->OptionalHeader.AddressOfEntryPoint);
  214. } else {
  215. EntryPoint =
  216. (UINTN)(Header.Pe32Plus->OptionalHeader.AddressOfEntryPoint);
  217. }
  218. } else {
  219. EntryPoint = (UINTN)(Header.Te->AddressOfEntryPoint);
  220. }
  221. Context->EntryPoint = (PHYSICAL_ADDRESS)(UINTN)EfipPeLoaderGetAddress(
  222. Context,
  223. EntryPoint,
  224. TeStrippedOffset);
  225. //
  226. // Determine the size of the fixup data.
  227. //
  228. if (Context->IsTeImage == FALSE) {
  229. if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  230. NumberOfRvaAndSizes =
  231. Header.Pe32->OptionalHeader.NumberOfRvaAndSizes;
  232. Directories = &(Header.Pe32->OptionalHeader.DataDirectory[0]);
  233. DirectoryEntry =
  234. &(Directories[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]);
  235. } else {
  236. NumberOfRvaAndSizes =
  237. Header.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
  238. Directories = &(Header.Pe32Plus->OptionalHeader.DataDirectory[0]);
  239. DirectoryEntry =
  240. &(Directories[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]);
  241. }
  242. Context->FixupDataSize = 0;
  243. if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
  244. Context->FixupDataSize =
  245. DirectoryEntry->Size / sizeof(UINT16) * sizeof(UINTN);
  246. }
  247. } else {
  248. DirectoryEntry = &(Header.Te->DataDirectory[0]);
  249. Context->FixupDataSize =
  250. DirectoryEntry->Size / sizeof(UINT16) * sizeof(UINTN);
  251. }
  252. //
  253. // The consumer must allocate a buffer for the relocation fixup log.
  254. // This is used by the runtime relocation code.
  255. //
  256. Context->FixupData = NULL;
  257. //
  258. // Get the image's HII resource section.
  259. //
  260. Context->HiiResourceData = 0;
  261. if (Context->IsTeImage == FALSE) {
  262. DirectoryEntry = &(Directories[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE]);
  263. if ((NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE) &&
  264. (DirectoryEntry->Size != 0)) {
  265. ASSERT(Directories != NULL);
  266. Base = EfipPeLoaderGetAddress(Context,
  267. DirectoryEntry->VirtualAddress,
  268. 0);
  269. if (Base != NULL) {
  270. ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *)Base;
  271. Offset = sizeof(EFI_IMAGE_RESOURCE_DIRECTORY) +
  272. (sizeof(EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY) *
  273. (ResourceDirectory->NumberOfNamedEntries +
  274. ResourceDirectory->NumberOfIdEntries));
  275. if (Offset > DirectoryEntry->Size) {
  276. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  277. return RETURN_UNSUPPORTED;
  278. }
  279. //
  280. // Loop through every directory entry.
  281. //
  282. ResourceDirectoryEntry =
  283. (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *)(ResourceDirectory +
  284. 1);
  285. for (Index = 0;
  286. Index < ResourceDirectory->NumberOfNamedEntries;
  287. Index += 1) {
  288. //
  289. // Skip entries whose names are not strings.
  290. //
  291. if (ResourceDirectoryEntry->u1.s.NameIsString == 0) {
  292. ResourceDirectoryEntry += 1;
  293. continue;
  294. }
  295. if (ResourceDirectoryEntry->u1.s.NameOffset >=
  296. DirectoryEntry->Size) {
  297. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  298. return RETURN_UNSUPPORTED;
  299. }
  300. //
  301. // Skip entries not named "HII".
  302. //
  303. Offset = ResourceDirectoryEntry->u1.s.NameOffset;
  304. ResourceDirectoryString =
  305. (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *)(Base + Offset);
  306. String = &(ResourceDirectoryString->String[0]);
  307. if ((ResourceDirectoryString->Length != 3) ||
  308. (String[0] != L'H') ||
  309. (String[1] != L'I') ||
  310. (String[2] != L'I')) {
  311. ResourceDirectoryEntry += 1;
  312. continue;
  313. }
  314. //
  315. // A HII resource was found.
  316. //
  317. if (ResourceDirectoryEntry->u2.s.DataIsDirectory != 0) {
  318. //
  319. // Move to the next level - Resource Name.
  320. //
  321. if (ResourceDirectoryEntry->u2.s.OffsetToDirectory >=
  322. DirectoryEntry->Size) {
  323. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  324. return RETURN_UNSUPPORTED;
  325. }
  326. Offset = ResourceDirectoryEntry->u2.s.OffsetToDirectory;
  327. ResourceDirectory =
  328. (EFI_IMAGE_RESOURCE_DIRECTORY *)(Base + Offset);
  329. Offset += sizeof(EFI_IMAGE_RESOURCE_DIRECTORY) +
  330. (sizeof(EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY) *
  331. (ResourceDirectory->NumberOfNamedEntries +
  332. ResourceDirectory->NumberOfIdEntries));
  333. if (Offset > DirectoryEntry->Size) {
  334. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  335. return RETURN_UNSUPPORTED;
  336. }
  337. ResourceDirectoryEntry =
  338. (VOID *)(ResourceDirectory + 1);
  339. if (ResourceDirectoryEntry->u2.s.DataIsDirectory != 0) {
  340. //
  341. // Move to the next level - Resource Language.
  342. //
  343. Offset =
  344. ResourceDirectoryEntry->u2.s.OffsetToDirectory;
  345. if (Offset >= DirectoryEntry->Size) {
  346. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  347. return RETURN_UNSUPPORTED;
  348. }
  349. ResourceDirectory = (VOID *)(Base + Offset);
  350. Offset +=
  351. sizeof(EFI_IMAGE_RESOURCE_DIRECTORY) +
  352. (sizeof(EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY) *
  353. (ResourceDirectory->NumberOfNamedEntries +
  354. ResourceDirectory->NumberOfIdEntries));
  355. if (Offset > DirectoryEntry->Size) {
  356. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  357. return RETURN_UNSUPPORTED;
  358. }
  359. ResourceDirectoryEntry =
  360. (VOID *)(ResourceDirectory + 1);
  361. }
  362. }
  363. //
  364. // Now it ought to be resource data.
  365. //
  366. if (ResourceDirectoryEntry->u2.s.DataIsDirectory != 0) {
  367. if (ResourceDirectoryEntry->u2.OffsetToData >=
  368. DirectoryEntry->Size) {
  369. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  370. return RETURN_UNSUPPORTED;
  371. }
  372. Offset = ResourceDirectoryEntry->u2.OffsetToData;
  373. ResourceDataEntry =
  374. (EFI_IMAGE_RESOURCE_DATA_ENTRY *)(Base + Offset);
  375. Offset = ResourceDataEntry->OffsetToData;
  376. Context->HiiResourceData =
  377. (PHYSICAL_ADDRESS)(UINTN)EfipPeLoaderGetAddress(
  378. Context,
  379. Offset,
  380. 0);
  381. break;
  382. }
  383. ResourceDirectoryEntry += 1;
  384. }
  385. }
  386. }
  387. }
  388. return Status;
  389. }
  390. EFIAPI
  391. RETURN_STATUS
  392. EfiPeLoaderRelocateImage (
  393. PEFI_PE_LOADER_CONTEXT Context
  394. )
  395. /*++
  396. Routine Description:
  397. This routine relocates a loaded PE image.
  398. Arguments:
  399. Context - Supplies a pointer to the image context.
  400. Return Value:
  401. RETURN_SUCCESS on success.
  402. RETURN_LOAD_ERROR if the image is not valid.
  403. RETURN_UNSUPPORTED if an unsupported relocation type was encountered.
  404. --*/
  405. {
  406. UINT64 Adjust;
  407. PHYSICAL_ADDRESS BaseAddress;
  408. EFI_IMAGE_DATA_DIRECTORY *Directories;
  409. UINTN EndOffset;
  410. CHAR8 *Fixup;
  411. UINT16 *Fixup16;
  412. UINT32 *Fixup32;
  413. UINT64 *Fixup64;
  414. CHAR8 *FixupBase;
  415. CHAR8 *FixupData;
  416. EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Header;
  417. UINT16 Magic;
  418. UINT32 NumberOfRvaAndSizes;
  419. UINT16 *Relocation;
  420. EFI_IMAGE_BASE_RELOCATION *RelocationBase;
  421. EFI_IMAGE_BASE_RELOCATION *RelocationBaseEnd;
  422. EFI_IMAGE_DATA_DIRECTORY *RelocationDirectory;
  423. UINT16 *RelocationEnd;
  424. UINT32 TeStrippedOffset;
  425. ASSERT(Context != NULL);
  426. Context->ImageError = IMAGE_ERROR_SUCCESS;
  427. if (Context->RelocationsStripped != FALSE) {
  428. return RETURN_SUCCESS;
  429. }
  430. //
  431. // If the destination address is not zero, use that rather than the image
  432. // address.
  433. //
  434. BaseAddress = Context->ImageAddress;
  435. if (Context->DestinationAddress != 0) {
  436. BaseAddress = Context->DestinationAddress;
  437. }
  438. if (Context->IsTeImage == FALSE) {
  439. Header.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Context->ImageAddress +
  440. Context->PeCoffHeaderOffset);
  441. TeStrippedOffset = 0;
  442. Magic = EfiPeLoaderGetPeHeaderMagicValue(Header);
  443. if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  444. Adjust = (UINT64)BaseAddress -
  445. Header.Pe32->OptionalHeader.ImageBase;
  446. if (Adjust != 0) {
  447. Header.Pe32->OptionalHeader.ImageBase = (UINT32)BaseAddress;
  448. }
  449. NumberOfRvaAndSizes =
  450. Header.Pe32->OptionalHeader.NumberOfRvaAndSizes;
  451. Directories = &(Header.Pe32->OptionalHeader.DataDirectory[0]);
  452. RelocationDirectory =
  453. &(Directories[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]);
  454. } else {
  455. Adjust = (UINT64)BaseAddress -
  456. Header.Pe32Plus->OptionalHeader.ImageBase;
  457. if (Adjust != 0) {
  458. Header.Pe32Plus->OptionalHeader.ImageBase = (UINT64)BaseAddress;
  459. }
  460. NumberOfRvaAndSizes =
  461. Header.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
  462. Directories = &(Header.Pe32Plus->OptionalHeader.DataDirectory[0]);
  463. RelocationDirectory =
  464. &(Directories[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]);
  465. }
  466. if (NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
  467. RelocationDirectory = NULL;
  468. }
  469. } else {
  470. Header.Te = (EFI_TE_IMAGE_HEADER *)(UINTN)(Context->ImageAddress);
  471. TeStrippedOffset = (UINT32)(Header.Te->StrippedSize) -
  472. sizeof(EFI_TE_IMAGE_HEADER);
  473. Adjust = (UINT64)(BaseAddress -
  474. (Header.Te->ImageBase + TeStrippedOffset));
  475. if (Adjust != 0) {
  476. Header.Te->ImageBase = (UINT64)(BaseAddress - TeStrippedOffset);
  477. }
  478. RelocationDirectory = &(Header.Te->DataDirectory[0]);
  479. }
  480. if ((RelocationDirectory != NULL) && (RelocationDirectory->Size != 0)) {
  481. RelocationBase = (EFI_IMAGE_BASE_RELOCATION *)EfipPeLoaderGetAddress(
  482. Context,
  483. RelocationDirectory->VirtualAddress,
  484. TeStrippedOffset);
  485. EndOffset = RelocationDirectory->VirtualAddress +
  486. RelocationDirectory->Size - 1;
  487. RelocationBaseEnd = (EFI_IMAGE_BASE_RELOCATION *)EfipPeLoaderGetAddress(
  488. Context,
  489. EndOffset,
  490. TeStrippedOffset);
  491. if ((RelocationBase == NULL) || (RelocationBaseEnd == NULL)) {
  492. Context->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
  493. return RETURN_LOAD_ERROR;
  494. }
  495. } else {
  496. RelocationBase = NULL;
  497. RelocationBaseEnd = NULL;
  498. }
  499. //
  500. // If there are adjustments to be made, relocate the image.
  501. //
  502. if (Adjust != 0) {
  503. FixupData = Context->FixupData;
  504. //
  505. // Loop across every relocation page.
  506. //
  507. while (RelocationBase < RelocationBaseEnd) {
  508. Relocation = (UINT16 *)((CHAR8 *)RelocationBase +
  509. sizeof(EFI_IMAGE_BASE_RELOCATION));
  510. if ((RelocationBase->SizeOfBlock == 0) ||
  511. (RelocationBase->SizeOfBlock > RelocationDirectory->Size)) {
  512. Context->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
  513. return RETURN_LOAD_ERROR;
  514. }
  515. RelocationEnd = (UINT16 *)((CHAR8 *)RelocationBase +
  516. RelocationBase->SizeOfBlock);
  517. FixupBase = EfipPeLoaderGetAddress(Context,
  518. RelocationBase->VirtualAddress,
  519. TeStrippedOffset);
  520. if (FixupBase == NULL) {
  521. Context->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
  522. return RETURN_LOAD_ERROR;
  523. }
  524. //
  525. // Run every relocation in the page.
  526. //
  527. while (Relocation < RelocationEnd) {
  528. Fixup = FixupBase + (*Relocation & 0xFFF);
  529. switch ((*Relocation) >> 12) {
  530. case EFI_IMAGE_REL_BASED_ABSOLUTE:
  531. break;
  532. case EFI_IMAGE_REL_BASED_HIGH:
  533. Fixup16 = (UINT16 *)Fixup;
  534. *Fixup16 =
  535. (UINT16)(*Fixup + ((UINT16)((UINT32)Adjust >> 16)));
  536. if (FixupData != NULL) {
  537. *(UINT16 *)FixupData = *Fixup16;
  538. FixupData = FixupData + sizeof(UINT16);
  539. }
  540. break;
  541. case EFI_IMAGE_REL_BASED_LOW:
  542. Fixup16 = (UINT16 *)Fixup;
  543. *Fixup16 = (UINT16)(*Fixup + (UINT16)Adjust);
  544. if (FixupData != NULL) {
  545. *(UINT16 *)FixupData = *Fixup16;
  546. FixupData = FixupData + sizeof(UINT16);
  547. }
  548. break;
  549. case EFI_IMAGE_REL_BASED_HIGHLOW:
  550. Fixup32 = (UINT32 *)Fixup;
  551. *Fixup32 = *Fixup32 + (UINT32)Adjust;
  552. if (FixupData != NULL) {
  553. FixupData = ALIGN_POINTER(FixupData, sizeof(UINT32));
  554. *(UINT32 *)FixupData = *Fixup32;
  555. FixupData = FixupData + sizeof(UINT32);
  556. }
  557. break;
  558. case EFI_IMAGE_REL_BASED_DIR64:
  559. Fixup64 = (UINT64 *)Fixup;
  560. *Fixup64 = *Fixup64 + (UINT64)Adjust;
  561. if (FixupData != NULL) {
  562. FixupData = ALIGN_POINTER(FixupData, sizeof(UINT64));
  563. *(UINT64 *)FixupData = *Fixup64;
  564. FixupData = FixupData + sizeof(UINT64);
  565. }
  566. break;
  567. default:
  568. RtlDebugPrint("Error: Unknown relocation type.\n");
  569. Context->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
  570. return RETURN_LOAD_ERROR;
  571. }
  572. //
  573. // Move to the next relocation record.
  574. //
  575. Relocation += 1;
  576. }
  577. //
  578. // Move to the next relocation page.
  579. //
  580. RelocationBase = (EFI_IMAGE_BASE_RELOCATION *)RelocationEnd;
  581. }
  582. //
  583. // Adjust the entry point.
  584. //
  585. if (Context->DestinationAddress != 0) {
  586. Context->EntryPoint -= (UINT64)Context->ImageAddress;
  587. Context->EntryPoint += (UINT64)Context->DestinationAddress;
  588. }
  589. }
  590. return RETURN_SUCCESS;
  591. }
  592. EFIAPI
  593. RETURN_STATUS
  594. EfiPeLoaderGetImageInfo (
  595. PEFI_PE_LOADER_CONTEXT Context
  596. )
  597. /*++
  598. Routine Description:
  599. This routine extracts information about the given PE/COFF image.
  600. Arguments:
  601. Context - Supplies a pointer to the image context.
  602. Return Value:
  603. RETURN_SUCCESS on success.
  604. RETURN_INVALID_PARAMETER if the image context is NULL.
  605. RETURN_UNSUPPORTED if the image format is not supported.
  606. --*/
  607. {
  608. EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Header;
  609. EFI_IMAGE_OPTIONAL_HEADER_UNION HeaderData;
  610. UINT16 Magic;
  611. RETURN_STATUS Status;
  612. UINT32 TeStrippedOffset;
  613. if (Context == NULL) {
  614. return EFI_INVALID_PARAMETER;
  615. }
  616. Context->ImageError = IMAGE_ERROR_SUCCESS;
  617. Header.Union = &HeaderData;
  618. Status = EfiPeLoaderGetPeHeader(Context, Header);
  619. if (RETURN_ERROR(Status)) {
  620. return Status;
  621. }
  622. Magic = EfiPeLoaderGetPeHeaderMagicValue(Header);
  623. //
  624. // Get the base address of the image.
  625. //
  626. if (Context->IsTeImage == FALSE) {
  627. TeStrippedOffset = 0;
  628. if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  629. Context->ImageAddress = Header.Pe32->OptionalHeader.ImageBase;
  630. } else {
  631. Context->ImageAddress = Header.Pe32Plus->OptionalHeader.ImageBase;
  632. }
  633. } else {
  634. TeStrippedOffset = (UINT32)(Header.Te->StrippedSize -
  635. sizeof(EFI_TE_IMAGE_HEADER));
  636. Context->ImageAddress = (EFI_PHYSICAL_ADDRESS)(Header.Te->ImageBase +
  637. TeStrippedOffset);
  638. }
  639. Context->DestinationAddress = 0;
  640. Context->DebugDirectoryEntryRva = 0;
  641. Context->CodeView = NULL;
  642. Context->PdbPointer = NULL;
  643. //
  644. // Look at the file header to determine if relocations have been stripped.
  645. //
  646. if ((Context->IsTeImage == FALSE) &&
  647. ((Header.Pe32->FileHeader.Characteristics &
  648. EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {
  649. Context->RelocationsStripped = TRUE;
  650. } else if ((Context->IsTeImage != FALSE) &&
  651. (Header.Te->DataDirectory[0].Size == 0) &&
  652. (Header.Te->DataDirectory[0].VirtualAddress == 0)) {
  653. Context->RelocationsStripped = TRUE;
  654. } else {
  655. Context->RelocationsStripped = FALSE;
  656. }
  657. return EFI_SUCCESS;
  658. }
  659. EFIAPI
  660. RETURN_STATUS
  661. EfiPeLoaderUnloadImage (
  662. PEFI_PE_LOADER_CONTEXT Context
  663. )
  664. /*++
  665. Routine Description:
  666. This routine unloads the PE/COFF image.
  667. Arguments:
  668. Context - Supplies a pointer to the image context.
  669. Return Value:
  670. RETURN_* status code.
  671. --*/
  672. {
  673. return RETURN_SUCCESS;
  674. }
  675. UINT16
  676. EfiPeLoaderGetPeHeaderMagicValue (
  677. EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Header
  678. )
  679. /*++
  680. Routine Description:
  681. This routine returns the magic value out of the PE/COFF header.
  682. Arguments:
  683. Header - Supplies a pointer to the header.
  684. Return Value:
  685. Returns the magic value from the header.
  686. --*/
  687. {
  688. return Header.Pe32->OptionalHeader.Magic;
  689. }
  690. RETURN_STATUS
  691. EfiPeLoaderGetPeHeader (
  692. PEFI_PE_LOADER_CONTEXT Context,
  693. EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Header
  694. )
  695. /*++
  696. Routine Description:
  697. This routine retrieves the PE or TE header from a PE/COFF or TE image.
  698. Arguments:
  699. Context - Supplies a pointer to the loader context.
  700. Header - Supplies a pointer to the header.
  701. Return Value:
  702. RETURN_* error code.
  703. --*/
  704. {
  705. CHAR8 BufferData;
  706. EFI_IMAGE_DOS_HEADER DosHeader;
  707. UINT32 HeaderWithoutDataDirectory;
  708. UINT32 Index;
  709. UINTN LastByteOffset;
  710. UINT16 Magic;
  711. UINTN ReadSize;
  712. UINTN SectionCount;
  713. EFI_IMAGE_SECTION_HEADER SectionHeader;
  714. UINT32 SectionHeaderOffset;
  715. UINTN Size;
  716. RETURN_STATUS Status;
  717. UINT32 TeStrippedOffset;
  718. //
  719. // Read the DOS image header to check for its existence.
  720. //
  721. ASSERT(Context->ImageRead != NULL);
  722. Size = sizeof(EFI_IMAGE_DOS_HEADER);
  723. ReadSize = Size;
  724. Status = Context->ImageRead(Context->Handle,
  725. 0,
  726. &Size,
  727. &DosHeader);
  728. if ((RETURN_ERROR(Status)) || (Size != ReadSize)) {
  729. Context->ImageError = IMAGE_ERROR_IMAGE_READ;
  730. if (Size != ReadSize) {
  731. Status = RETURN_UNSUPPORTED;
  732. }
  733. return Status;
  734. }
  735. //
  736. // Assume the PE header is at the beginning of the image. If the DOS
  737. // header is valid, then the PE header comes at some point after the DOS
  738. // header.
  739. //
  740. Context->PeCoffHeaderOffset = 0;
  741. if (DosHeader.e_magic == EFI_IMAGE_DOS_SIGNATURE) {
  742. Context->PeCoffHeaderOffset = DosHeader.e_lfanew;
  743. }
  744. //
  745. // Read the PE/COFF header. This may read too much, but that's alright.
  746. //
  747. Size = sizeof(EFI_IMAGE_OPTIONAL_HEADER_UNION);
  748. ReadSize = Size;
  749. Status = Context->ImageRead(Context->Handle,
  750. Context->PeCoffHeaderOffset,
  751. &Size,
  752. Header.Pe32);
  753. if ((RETURN_ERROR(Status)) || (Size != ReadSize)) {
  754. Context->ImageError = IMAGE_ERROR_IMAGE_READ;
  755. if (Size != ReadSize) {
  756. Status = RETURN_UNSUPPORTED;
  757. }
  758. return Status;
  759. }
  760. //
  761. // Use the signature to figure out the image offset. Start with TE images.
  762. //
  763. if (Header.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
  764. Context->IsTeImage = TRUE;
  765. Context->Machine = Header.Te->Machine;
  766. Context->ImageType = (UINT16)(Header.Te->Subsystem);
  767. Context->ImageSize = 0;
  768. Context->SectionAlignment = 0;
  769. Context->SizeOfHeaders = sizeof(EFI_TE_IMAGE_HEADER) +
  770. (UINTN)(Header.Te->BaseOfCode) -
  771. (UINTN)(Header.Te->StrippedSize);
  772. if ((sizeof(EFI_TE_IMAGE_HEADER) >= (UINT32)Header.Te->StrippedSize) ||
  773. (Header.Te->BaseOfCode <= Header.Te->StrippedSize)) {
  774. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  775. return RETURN_UNSUPPORTED;
  776. }
  777. //
  778. // Read the last byte of the header from the file.
  779. //
  780. Size = 1;
  781. ReadSize = Size;
  782. Status = Context->ImageRead(Context->Handle,
  783. Context->SizeOfHeaders - 1,
  784. &Size,
  785. &BufferData);
  786. if ((RETURN_ERROR(Status)) || (Size != ReadSize)) {
  787. Context->ImageError = IMAGE_ERROR_IMAGE_READ;
  788. if (Size != ReadSize) {
  789. Status = RETURN_UNSUPPORTED;
  790. }
  791. return Status;
  792. }
  793. //
  794. // If the TE image data directory entry size is non-zero, but the data
  795. // directory VA is zero, then that's not valid.
  796. //
  797. if (((Header.Te->DataDirectory[0].Size != 0) &&
  798. (Header.Te->DataDirectory[0].VirtualAddress == 0)) ||
  799. ((Header.Te->DataDirectory[1].Size != 0) &&
  800. (Header.Te->DataDirectory[1].VirtualAddress == 0))) {
  801. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  802. return RETURN_UNSUPPORTED;
  803. }
  804. //
  805. // It's not a TE image, handle it being a PE image.
  806. //
  807. } else if (Header.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
  808. Context->IsTeImage = FALSE;
  809. Context->Machine = Header.Pe32->FileHeader.Machine;
  810. Magic = EfiPeLoaderGetPeHeaderMagicValue(Header);
  811. //
  812. // Handle a 32-bit image.
  813. //
  814. if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  815. //
  816. // Check the number of RVA and sizes.
  817. //
  818. if (Header.Pe32->OptionalHeader.NumberOfRvaAndSizes >
  819. EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES) {
  820. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  821. return RETURN_UNSUPPORTED;
  822. }
  823. //
  824. // Check the size of the optional header.
  825. //
  826. HeaderWithoutDataDirectory =
  827. sizeof(EFI_IMAGE_OPTIONAL_HEADER32) -
  828. (sizeof(EFI_IMAGE_DATA_DIRECTORY) *
  829. EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES);
  830. if ((UINT32)(Header.Pe32->FileHeader.SizeOfOptionalHeader) -
  831. HeaderWithoutDataDirectory !=
  832. Header.Pe32->OptionalHeader.NumberOfRvaAndSizes *
  833. sizeof(EFI_IMAGE_DATA_DIRECTORY)) {
  834. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  835. return RETURN_UNSUPPORTED;
  836. }
  837. //
  838. // Check the number of sections.
  839. //
  840. SectionHeaderOffset = Context->PeCoffHeaderOffset +
  841. sizeof(UINT32) +
  842. sizeof(EFI_IMAGE_FILE_HEADER) +
  843. Header.Pe32->FileHeader.SizeOfOptionalHeader;
  844. if (Header.Pe32->OptionalHeader.SizeOfImage < SectionHeaderOffset) {
  845. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  846. return RETURN_UNSUPPORTED;
  847. }
  848. if ((Header.Pe32->OptionalHeader.SizeOfImage -
  849. SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER <=
  850. Header.Pe32->FileHeader.NumberOfSections) {
  851. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  852. return RETURN_UNSUPPORTED;
  853. }
  854. //
  855. // Check the size of headers field.
  856. //
  857. if ((Header.Pe32->OptionalHeader.SizeOfHeaders <
  858. SectionHeaderOffset) ||
  859. (Header.Pe32->OptionalHeader.SizeOfHeaders >=
  860. Header.Pe32->OptionalHeader.SizeOfImage) ||
  861. ((Header.Pe32->OptionalHeader.SizeOfHeaders -
  862. SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER <
  863. (UINT32)(Header.Pe32->FileHeader.NumberOfSections))) {
  864. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  865. return RETURN_UNSUPPORTED;
  866. }
  867. //
  868. // Read the last byte of the headers from the file.
  869. //
  870. Size = 1;
  871. ReadSize = Size;
  872. Status = Context->ImageRead(
  873. Context->Handle,
  874. Header.Pe32->OptionalHeader.SizeOfHeaders - 1,
  875. &Size,
  876. &BufferData);
  877. if ((RETURN_ERROR(Status)) || (Size != ReadSize)) {
  878. Context->ImageError = IMAGE_ERROR_IMAGE_READ;
  879. if (Size != ReadSize) {
  880. Status = RETURN_UNSUPPORTED;
  881. }
  882. return Status;
  883. }
  884. Context->ImageType = Header.Pe32->OptionalHeader.Subsystem;
  885. Context->ImageSize =
  886. (UINT64)(Header.Pe32->OptionalHeader.SizeOfImage);
  887. Context->SectionAlignment =
  888. Header.Pe32->OptionalHeader.SectionAlignment;
  889. Context->SizeOfHeaders = Header.Pe32->OptionalHeader.SizeOfHeaders;
  890. //
  891. // Handle a 64-bit image.
  892. //
  893. } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  894. //
  895. // Check the number of RVA and sizes.
  896. //
  897. if (Header.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes >
  898. EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES) {
  899. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  900. return RETURN_UNSUPPORTED;
  901. }
  902. //
  903. // Check the size of the optional header.
  904. //
  905. HeaderWithoutDataDirectory =
  906. sizeof(EFI_IMAGE_OPTIONAL_HEADER64) -
  907. (sizeof(EFI_IMAGE_DATA_DIRECTORY) *
  908. EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES);
  909. if ((UINT32)(Header.Pe32Plus->FileHeader.SizeOfOptionalHeader) -
  910. HeaderWithoutDataDirectory !=
  911. Header.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes *
  912. sizeof(EFI_IMAGE_DATA_DIRECTORY)) {
  913. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  914. return RETURN_UNSUPPORTED;
  915. }
  916. //
  917. // Check the number of sections.
  918. //
  919. SectionHeaderOffset =
  920. Context->PeCoffHeaderOffset +
  921. sizeof(UINT32) +
  922. sizeof(EFI_IMAGE_FILE_HEADER) +
  923. Header.Pe32Plus->FileHeader.SizeOfOptionalHeader;
  924. if (Header.Pe32Plus->OptionalHeader.SizeOfImage <
  925. SectionHeaderOffset) {
  926. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  927. return RETURN_UNSUPPORTED;
  928. }
  929. if ((Header.Pe32Plus->OptionalHeader.SizeOfImage -
  930. SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER <=
  931. Header.Pe32Plus->FileHeader.NumberOfSections) {
  932. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  933. return RETURN_UNSUPPORTED;
  934. }
  935. //
  936. // Check the size of headers field.
  937. //
  938. if ((Header.Pe32Plus->OptionalHeader.SizeOfHeaders <
  939. SectionHeaderOffset) ||
  940. (Header.Pe32Plus->OptionalHeader.SizeOfHeaders >=
  941. Header.Pe32Plus->OptionalHeader.SizeOfImage) ||
  942. ((Header.Pe32Plus->OptionalHeader.SizeOfHeaders -
  943. SectionHeaderOffset) / EFI_IMAGE_SIZEOF_SECTION_HEADER <
  944. (UINT32)(Header.Pe32Plus->FileHeader.NumberOfSections))) {
  945. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  946. return RETURN_UNSUPPORTED;
  947. }
  948. //
  949. // Read the last byte of the headers from the file.
  950. //
  951. Size = 1;
  952. ReadSize = Size;
  953. Status = Context->ImageRead(
  954. Context->Handle,
  955. Header.Pe32Plus->OptionalHeader.SizeOfHeaders - 1,
  956. &Size,
  957. &BufferData);
  958. if ((RETURN_ERROR(Status)) || (Size != ReadSize)) {
  959. Context->ImageError = IMAGE_ERROR_IMAGE_READ;
  960. if (Size != ReadSize) {
  961. Status = RETURN_UNSUPPORTED;
  962. }
  963. return Status;
  964. }
  965. Context->ImageType = Header.Pe32Plus->OptionalHeader.Subsystem;
  966. Context->ImageSize =
  967. (UINT64)(Header.Pe32Plus->OptionalHeader.SizeOfImage);
  968. Context->SectionAlignment =
  969. Header.Pe32Plus->OptionalHeader.SectionAlignment;
  970. Context->SizeOfHeaders =
  971. Header.Pe32Plus->OptionalHeader.SizeOfHeaders;
  972. //
  973. // The magic isn't known.
  974. //
  975. } else {
  976. Context->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE;
  977. return RETURN_UNSUPPORTED;
  978. }
  979. //
  980. // This header signature is not recognized.
  981. //
  982. } else {
  983. Context->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE;
  984. return RETURN_UNSUPPORTED;
  985. }
  986. if (!EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Context->Machine)) {
  987. return RETURN_UNSUPPORTED;
  988. }
  989. //
  990. // Check each section field.
  991. //
  992. if (Context->IsTeImage != FALSE) {
  993. SectionHeaderOffset = sizeof(EFI_TE_IMAGE_HEADER);
  994. SectionCount = (UINTN)(Header.Te->NumberOfSections);
  995. } else {
  996. SectionHeaderOffset = Context->PeCoffHeaderOffset + sizeof(UINT32) +
  997. sizeof(EFI_IMAGE_FILE_HEADER) +
  998. Header.Pe32->FileHeader.SizeOfOptionalHeader;
  999. SectionCount = (UINTN)(Header.Pe32->FileHeader.NumberOfSections);
  1000. }
  1001. for (Index = 0; Index < SectionCount; Index += 1) {
  1002. //
  1003. // Read the section header from the file.
  1004. //
  1005. Size = sizeof(EFI_IMAGE_SECTION_HEADER);
  1006. ReadSize = Size;
  1007. Status = Context->ImageRead(Context->Handle,
  1008. SectionHeaderOffset,
  1009. &Size,
  1010. &SectionHeader);
  1011. if ((RETURN_ERROR(Status)) || (Size != ReadSize)) {
  1012. Context->ImageError = IMAGE_ERROR_IMAGE_READ;
  1013. if (Size != ReadSize) {
  1014. Status = RETURN_UNSUPPORTED;
  1015. }
  1016. return Status;
  1017. }
  1018. //
  1019. // Adjust the offsets in the section header for TE images.
  1020. //
  1021. if (Context->IsTeImage != FALSE) {
  1022. TeStrippedOffset = (UINT32)Header.Te->StrippedSize -
  1023. sizeof(EFI_TE_IMAGE_HEADER);
  1024. SectionHeader.VirtualAddress -= TeStrippedOffset;
  1025. SectionHeader.PointerToRawData -= TeStrippedOffset;
  1026. }
  1027. if (SectionHeader.SizeOfRawData != 0) {
  1028. //
  1029. // Section data should be beyond the PE header, and shouldn't
  1030. // overflow.
  1031. //
  1032. if ((SectionHeader.VirtualAddress < Context->SizeOfHeaders) ||
  1033. (SectionHeader.PointerToRawData < Context->SizeOfHeaders) ||
  1034. ((UINT32)(~0) - SectionHeader.PointerToRawData <
  1035. SectionHeader.SizeOfRawData)) {
  1036. Context->ImageError = IMAGE_ERROR_UNSUPPORTED;
  1037. return RETURN_UNSUPPORTED;
  1038. }
  1039. //
  1040. // Read the last byte of the section data.
  1041. //
  1042. Size = 1;
  1043. ReadSize = Size;
  1044. LastByteOffset = SectionHeader.PointerToRawData +
  1045. SectionHeader.SizeOfRawData - 1;
  1046. Status = Context->ImageRead(Context->Handle,
  1047. LastByteOffset,
  1048. &Size,
  1049. &BufferData);
  1050. if ((RETURN_ERROR(Status)) || (Size != ReadSize)) {
  1051. Context->ImageError = IMAGE_ERROR_IMAGE_READ;
  1052. if (Size != ReadSize) {
  1053. Status = RETURN_UNSUPPORTED;
  1054. }
  1055. return Status;
  1056. }
  1057. }
  1058. //
  1059. // Move to the next section.
  1060. //
  1061. SectionHeaderOffset += sizeof(EFI_IMAGE_SECTION_HEADER);
  1062. }
  1063. return RETURN_SUCCESS;
  1064. }
  1065. //
  1066. // --------------------------------------------------------- Internal Functions
  1067. //
  1068. VOID *
  1069. EfipPeLoaderGetAddress (
  1070. PEFI_PE_LOADER_CONTEXT Context,
  1071. UINTN Address,
  1072. UINTN TeStrippedOffset
  1073. )
  1074. /*++
  1075. Routine Description:
  1076. This routine converts an image address into a loaded in-memory address.
  1077. Arguments:
  1078. Context - Supplies a pointer to the loader context.
  1079. Address - Supplies the address to translate.
  1080. TeStrippedOffset - Supplies the stripped offset for TE images.
  1081. Return Value:
  1082. Returns the in memory address.
  1083. NULL on failure.
  1084. --*/
  1085. {
  1086. if (Address >= Context->ImageSize + TeStrippedOffset) {
  1087. Context->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS;
  1088. return NULL;
  1089. }
  1090. return (CHAR8 *)((UINTN)Context->ImageAddress + Address - TeStrippedOffset);
  1091. }