GenFw.c 121 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240
  1. /** @file
  2. Converts a pe32+ image to an FW, Te image type, or other specific image.
  3. Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
  4. This program and the accompanying materials
  5. are licensed and made available under the terms and conditions of the BSD License
  6. which accompanies this distribution. The full text of the license may be found at
  7. http://opensource.org/licenses/bsd-license.php
  8. THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
  10. **/
  11. #include "WinNtInclude.h"
  12. #ifndef __GNUC__
  13. #include <windows.h>
  14. #include <io.h>
  15. #include <sys/types.h>
  16. #include <sys/stat.h>
  17. #endif
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <time.h>
  22. #include <ctype.h>
  23. #include <Common/UefiBaseTypes.h>
  24. #include <IndustryStandard/PeImage.h>
  25. #include <Common/UefiInternalFormRepresentation.h>
  26. //
  27. // Acpi Table definition
  28. //
  29. #include <IndustryStandard/Acpi.h>
  30. #include <IndustryStandard/Acpi1_0.h>
  31. #include <IndustryStandard/Acpi2_0.h>
  32. #include <IndustryStandard/Acpi3_0.h>
  33. #include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
  34. #include "CommonLib.h"
  35. #include "PeCoffLib.h"
  36. #include "ParseInf.h"
  37. #include "EfiUtilityMsgs.h"
  38. #include "GenFw.h"
  39. //
  40. // Version of this utility
  41. //
  42. #define UTILITY_NAME "GenFw"
  43. #define UTILITY_MAJOR_VERSION 0
  44. #define UTILITY_MINOR_VERSION 2
  45. #define HII_RESOURCE_SECTION_INDEX 1
  46. #define HII_RESOURCE_SECTION_NAME "HII"
  47. #define DEFAULT_MC_PAD_BYTE_VALUE 0xFF
  48. #define DEFAULT_MC_ALIGNMENT 16
  49. #define STATUS_IGNORE 0xA
  50. //
  51. // Structure definition for a microcode header
  52. //
  53. typedef struct {
  54. UINT32 HeaderVersion;
  55. UINT32 PatchId;
  56. UINT32 Date;
  57. UINT32 CpuId;
  58. UINT32 Checksum;
  59. UINT32 LoaderVersion;
  60. UINT32 PlatformId;
  61. UINT32 DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid
  62. UINT32 TotalSize; // number of bytes
  63. UINT32 Reserved[3];
  64. } MICROCODE_IMAGE_HEADER;
  65. static EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
  66. static const char *gHiiPackageRCFileHeader[] = {
  67. "//",
  68. "// DO NOT EDIT -- auto-generated file",
  69. "//",
  70. NULL
  71. };
  72. //
  73. // Module image information
  74. //
  75. CHAR8 *mInImageName;
  76. UINT32 mImageTimeStamp = 0;
  77. UINT32 mImageSize = 0;
  78. UINT32 mOutImageType = FW_DUMMY_IMAGE;
  79. BOOLEAN mIsConvertXip = FALSE;
  80. STATIC
  81. EFI_STATUS
  82. ZeroDebugData (
  83. IN OUT UINT8 *FileBuffer,
  84. BOOLEAN ZeroDebug
  85. );
  86. STATIC
  87. EFI_STATUS
  88. SetStamp (
  89. IN OUT UINT8 *FileBuffer,
  90. IN CHAR8 *TimeStamp
  91. );
  92. STATIC
  93. STATUS
  94. MicrocodeReadData (
  95. FILE *InFptr,
  96. UINT32 *Data
  97. );
  98. STATIC
  99. VOID
  100. Version (
  101. VOID
  102. )
  103. /*++
  104. Routine Description:
  105. Print out version information for this utility.
  106. Arguments:
  107. None
  108. Returns:
  109. None
  110. --*/
  111. {
  112. fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
  113. }
  114. STATIC
  115. VOID
  116. Usage (
  117. VOID
  118. )
  119. /*++
  120. Routine Description:
  121. Print Help message.
  122. Arguments:
  123. VOID
  124. Returns:
  125. None
  126. --*/
  127. {
  128. //
  129. // Summary usage
  130. //
  131. fprintf (stdout, "\nUsage: %s [options] <input_file>\n\n", UTILITY_NAME);
  132. //
  133. // Copyright declaration
  134. //
  135. fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
  136. //
  137. // Details Option
  138. //
  139. fprintf (stdout, "Options:\n");
  140. fprintf (stdout, " -o FileName, --outputfile FileName\n\
  141. File will be created to store the output content.\n");
  142. fprintf (stdout, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\
  143. Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\
  144. PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\
  145. SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\
  146. DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\
  147. MM_STANDALONE, MM_CORE_STANDALONE,\n\
  148. PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\
  149. APPLICATION, SAL_RT_DRIVER to support all module types\n\
  150. It can only be used together with --keepexceptiontable,\n\
  151. --keepzeropending, --keepoptionalheader, -r, -o option.\n\
  152. It is a action option. If it is combined with other action options,\n\
  153. the later input action option will override the previous one.\n");
  154. fprintf (stdout, " -c, --acpi Create Acpi table.\n\
  155. It can't be combined with other action options\n\
  156. except for -o, -r option. It is a action option.\n\
  157. If it is combined with other action options, the later\n\
  158. input action option will override the previous one.\n");
  159. fprintf (stdout, " -t, --terse Create Te Image.\n\
  160. It can only be used together with --keepexceptiontable,\n\
  161. --keepzeropending, --keepoptionalheader, -r, -o option.\n\
  162. It is a action option. If it is combined with other action options,\n\
  163. the later input action option will override the previous one.\n");
  164. fprintf (stdout, " -u, --dump Dump TeImage Header.\n\
  165. It can't be combined with other action options\n\
  166. except for -o, -r option. It is a action option.\n\
  167. If it is combined with other action options, the later\n\
  168. input action option will override the previous one.\n");
  169. fprintf (stdout, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\
  170. It also zeros the time stamp fields.\n\
  171. This option can be used to compare the binary efi image.\n\
  172. It can't be combined with other action options\n\
  173. except for -o, -r option. It is a action option.\n\
  174. If it is combined with other action options, the later\n\
  175. input action option will override the previous one.\n");
  176. fprintf (stdout, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\
  177. It can't be combined with other action options\n\
  178. except for -o, -r option. It is a action option.\n\
  179. If it is combined with other action options, the later\n\
  180. input action option will override the previous one.\n");;
  181. fprintf (stdout, " -l, --stripped Strip off the relocation info from PE or TE image.\n\
  182. It can't be combined with other action options\n\
  183. except for -o, -r option. It is a action option.\n\
  184. If it is combined with other action options, the later\n\
  185. input action option will override the previous one.\n");
  186. fprintf (stdout, " -s timedate, --stamp timedate\n\
  187. timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\
  188. is set to NOW, current system time is used. The support\n\
  189. date scope is 1970-01-01 00+timezone:00:00\n\
  190. ~ 2038-01-19 03+timezone:14:07\n\
  191. The scope is adjusted according to the different zones.\n\
  192. It can't be combined with other action options\n\
  193. except for -o, -r option. It is a action option.\n\
  194. If it is combined with other action options, the later\n\
  195. input action option will override the previous one.\n");
  196. fprintf (stdout, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\
  197. It can't be combined with other action options\n\
  198. except for -o option. It is a action option.\n\
  199. If it is combined with other action options, the later\n\
  200. input action option will override the previous one.\n");
  201. fprintf (stdout, " -j, --join Combine multi microcode bin files to one file.\n\
  202. It can be specified with -a, -p, -o option.\n\
  203. No other options can be combined with it.\n\
  204. If it is combined with other action options, the later\n\
  205. input action option will override the previous one.\n");
  206. fprintf (stdout, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\
  207. This option is only used together with -j option.\n");
  208. fprintf (stdout, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\
  209. This option is only used together with -j option.\n");
  210. fprintf (stdout, " --keepexceptiontable Don't clear exception table.\n\
  211. This option can be used together with -e or -t.\n\
  212. It doesn't work for other options.\n");
  213. fprintf (stdout, " --keepoptionalheader Don't zero PE/COFF optional header fields.\n\
  214. This option can be used together with -e or -t.\n\
  215. It doesn't work for other options.\n");
  216. fprintf (stdout, " --keepzeropending Don't strip zero pending of .reloc.\n\
  217. This option can be used together with -e or -t.\n\
  218. It doesn't work for other options.\n");
  219. fprintf (stdout, " -r, --replace Overwrite the input file with the output content.\n\
  220. If more input files are specified,\n\
  221. the last input file will be as the output file.\n");
  222. fprintf (stdout, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\
  223. Guid is used to specify hii package list guid.\n\
  224. Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\
  225. If not specified, the first Form FormSet guid is used.\n");
  226. fprintf (stdout, " --hiipackage Combine all input binary hii packages into \n\
  227. a single package list as the text resource data(RC).\n\
  228. It can't be combined with other action options\n\
  229. except for -o option. It is a action option.\n\
  230. If it is combined with other action options, the later\n\
  231. input action option will override the previous one.\n");
  232. fprintf (stdout, " --hiibinpackage Combine all input binary hii packages into \n\
  233. a single package list as the binary resource section.\n\
  234. It can't be combined with other action options\n\
  235. except for -o option. It is a action option.\n\
  236. If it is combined with other action options, the later\n\
  237. input action option will override the previous one.\n");
  238. fprintf (stdout, " --rebase NewAddress Rebase image to new base address. New address \n\
  239. is also set to the first none code section header.\n\
  240. It can't be combined with other action options\n\
  241. except for -o or -r option. It is a action option.\n\
  242. If it is combined with other action options, the later\n\
  243. input action option will override the previous one.\n");
  244. fprintf (stdout, " --address NewAddress Set new address into the first none code \n\
  245. section header of the input image.\n\
  246. It can't be combined with other action options\n\
  247. except for -o or -r option. It is a action option.\n\
  248. If it is combined with other action options, the later\n\
  249. input action option will override the previous one.\n");
  250. fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");
  251. fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");
  252. fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");
  253. fprintf (stdout, " --version Show program's version number and exit\n");
  254. fprintf (stdout, " -h, --help Show this help message and exit\n");
  255. }
  256. STATIC
  257. STATUS
  258. CheckAcpiTable (
  259. VOID *AcpiTable,
  260. UINT32 Length
  261. )
  262. /*++
  263. Routine Description:
  264. Check Acpi Table
  265. Arguments:
  266. AcpiTable Buffer for AcpiSection
  267. Length AcpiSection Length
  268. Returns:
  269. 0 success
  270. non-zero otherwise
  271. --*/
  272. {
  273. EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader;
  274. EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs;
  275. UINT32 ExpectedLength;
  276. AcpiHeader = (EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable;
  277. //
  278. // Generic check for AcpiTable length.
  279. //
  280. if (AcpiHeader->Length > Length) {
  281. Error (NULL, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL);
  282. return STATUS_ERROR;
  283. }
  284. //
  285. // Currently, we only check must-have tables: FADT, FACS, DSDT,
  286. // and some important tables: MADT, MCFG.
  287. //
  288. switch (AcpiHeader->Signature) {
  289. //
  290. // "FACP" Fixed ACPI Description Table
  291. //
  292. case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE:
  293. switch (AcpiHeader->Revision) {
  294. case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
  295. ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE);
  296. break;
  297. case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
  298. ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE);
  299. break;
  300. case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION:
  301. ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE);
  302. break;
  303. default:
  304. if (AcpiHeader->Revision > EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) {
  305. ExpectedLength = AcpiHeader->Length;
  306. break;
  307. }
  308. Error (NULL, 0, 3000, "Invalid", "FACP revision check failed.");
  309. return STATUS_ERROR;
  310. }
  311. if (ExpectedLength != AcpiHeader->Length) {
  312. Error (NULL, 0, 3000, "Invalid", "FACP length check failed.");
  313. return STATUS_ERROR;
  314. }
  315. break;
  316. //
  317. // "FACS" Firmware ACPI Control Structure
  318. //
  319. case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE:
  320. Facs = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable;
  321. if (Facs->Version > EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) {
  322. break;
  323. }
  324. if ((Facs->Version != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
  325. (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) &&
  326. (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)){
  327. Error (NULL, 0, 3000, "Invalid", "FACS version check failed.");
  328. return STATUS_ERROR;
  329. }
  330. if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&
  331. (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) &&
  332. (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) {
  333. Error (NULL, 0, 3000, "Invalid", "FACS length check failed.");
  334. return STATUS_ERROR;
  335. }
  336. break;
  337. //
  338. // "DSDT" Differentiated System Description Table
  339. //
  340. case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE:
  341. if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) {
  342. break;
  343. }
  344. if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) {
  345. Error (NULL, 0, 3000, "Invalid", "DSDT length check failed.");
  346. return STATUS_ERROR;
  347. }
  348. break;
  349. //
  350. // "APIC" Multiple APIC Description Table
  351. //
  352. case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE:
  353. if (AcpiHeader->Revision > EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) {
  354. break;
  355. }
  356. if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&
  357. (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) &&
  358. (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) {
  359. Error (NULL, 0, 3000, "Invalid", "APIC revision check failed.");
  360. return STATUS_ERROR;
  361. }
  362. if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32)) {
  363. Error (NULL, 0, 3000, "Invalid", "APIC length check failed.");
  364. return STATUS_ERROR;
  365. }
  366. break;
  367. //
  368. // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table
  369. //
  370. case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE:
  371. if (AcpiHeader->Revision > EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {
  372. break;
  373. }
  374. if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) {
  375. Error (NULL, 0, 3000, "Invalid", "MCFG revision check failed.");
  376. return STATUS_ERROR;
  377. }
  378. if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)) {
  379. Error (NULL, 0, 3000, "Invalid", "MCFG length check failed.");
  380. return STATUS_ERROR;
  381. }
  382. break;
  383. //
  384. // Other table pass check
  385. //
  386. default:
  387. break;
  388. }
  389. return STATUS_SUCCESS;
  390. }
  391. VOID
  392. SetHiiResourceHeader (
  393. UINT8 *HiiBinData,
  394. UINT32 OffsetToFile
  395. )
  396. {
  397. UINT32 Index;
  398. EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory;
  399. EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *ResourceDirectoryEntry;
  400. EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;
  401. EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry;
  402. //
  403. // Fill Resource section entry
  404. //
  405. ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData);
  406. ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
  407. for (Index = 0; Index < ResourceDirectory->NumberOfNamedEntries; Index ++) {
  408. if (ResourceDirectoryEntry->u1.s.NameIsString) {
  409. ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiBinData + ResourceDirectoryEntry->u1.s.NameOffset);
  410. if (ResourceDirectoryString->Length == 3 &&
  411. ResourceDirectoryString->String[0] == L'H' &&
  412. ResourceDirectoryString->String[1] == L'I' &&
  413. ResourceDirectoryString->String[2] == L'I') {
  414. //
  415. // Resource Type "HII" found
  416. //
  417. if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {
  418. //
  419. // Move to next level - resource Name
  420. //
  421. ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + ResourceDirectoryEntry->u2.s.OffsetToDirectory);
  422. ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
  423. if (ResourceDirectoryEntry->u2.s.DataIsDirectory) {
  424. //
  425. // Move to next level - resource Language
  426. //
  427. ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + ResourceDirectoryEntry->u2.s.OffsetToDirectory);
  428. ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1);
  429. }
  430. }
  431. //
  432. // Now it ought to be resource Data and update its OffsetToData value
  433. //
  434. if (!ResourceDirectoryEntry->u2.s.DataIsDirectory) {
  435. ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiBinData + ResourceDirectoryEntry->u2.OffsetToData);
  436. ResourceDataEntry->OffsetToData = ResourceDataEntry->OffsetToData + OffsetToFile;
  437. break;
  438. }
  439. }
  440. }
  441. ResourceDirectoryEntry++;
  442. }
  443. return;
  444. }
  445. EFI_IMAGE_OPTIONAL_HEADER_UNION *
  446. GetPeCoffHeader (
  447. void *Data
  448. )
  449. {
  450. EFI_IMAGE_DOS_HEADER *DosHdr;
  451. EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr;
  452. //
  453. // Read the dos & pe hdrs of the image
  454. //
  455. DosHdr = (EFI_IMAGE_DOS_HEADER *)Data;
  456. if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
  457. // NO DOS header, check for PE/COFF header
  458. PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(Data);
  459. if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
  460. return NULL;
  461. }
  462. } else {
  463. PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(((UINT8 *)Data) + DosHdr->e_lfanew);
  464. if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
  465. return NULL;
  466. }
  467. }
  468. return PeHdr;
  469. }
  470. void
  471. PeCoffConvertImageToXip (
  472. UINT8 **FileBuffer,
  473. UINT32 *FileLength
  474. )
  475. {
  476. EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr;
  477. EFI_IMAGE_OPTIONAL_HEADER_UNION *NewPeHdr;
  478. EFI_IMAGE_SECTION_HEADER *SectionHeader;
  479. UINTN TotalNecessaryFileSize;
  480. UINTN SectionSize;
  481. UINT8 *XipFile;
  482. UINT32 XipLength;
  483. UINTN Index;
  484. UINTN FirstSectionOffset;
  485. BOOLEAN ConversionNeeded;
  486. PeHdr = GetPeCoffHeader ((void *) *FileBuffer);
  487. if (PeHdr == NULL) {
  488. return;
  489. }
  490. if (PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment) {
  491. //
  492. // The only reason to expand zero fill sections is to make them compatible with XIP images.
  493. // If SectionAlignment is not equal to FileAlignment then it is not an XIP type image.
  494. //
  495. return;
  496. }
  497. //
  498. // Calculate size of XIP file, and determine if the conversion is needed.
  499. //
  500. ConversionNeeded = FALSE;
  501. XipLength = 0;
  502. FirstSectionOffset = *FileLength;
  503. TotalNecessaryFileSize = 0;
  504. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
  505. for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
  506. SectionSize = MAX (SectionHeader->Misc.VirtualSize, SectionHeader->SizeOfRawData);
  507. TotalNecessaryFileSize += SectionSize;
  508. if (SectionSize > 0) {
  509. FirstSectionOffset = MIN (FirstSectionOffset, SectionHeader->VirtualAddress);
  510. XipLength = MAX (XipLength, SectionHeader->VirtualAddress + SectionSize);
  511. if (SectionHeader->VirtualAddress != SectionHeader->PointerToRawData) {
  512. ConversionNeeded = TRUE;
  513. }
  514. }
  515. if (SectionHeader->Misc.VirtualSize > SectionHeader->SizeOfRawData) {
  516. ConversionNeeded = TRUE;
  517. }
  518. }
  519. if (FirstSectionOffset < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) {
  520. //
  521. // If one of the sections should be loaded to an offset overlapping with
  522. // the executable header, then it cannot be made into an XIP image.
  523. //
  524. VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap");
  525. VerboseMsg ("of section data with the executable header.");
  526. return;
  527. }
  528. if (FirstSectionOffset == *FileLength) {
  529. //
  530. // If we never found a section with a non-zero size, then we
  531. // skip the conversion.
  532. //
  533. return;
  534. }
  535. TotalNecessaryFileSize += FirstSectionOffset;
  536. if (!ConversionNeeded) {
  537. return;
  538. }
  539. if (XipLength > (2 * TotalNecessaryFileSize)) {
  540. VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary.");
  541. VerboseMsg ("The image linking process may have left unused memory ranges.");
  542. }
  543. if (PeHdr->Pe32.FileHeader.PointerToSymbolTable != 0) {
  544. //
  545. // This field is obsolete and should be zero
  546. //
  547. PeHdr->Pe32.FileHeader.PointerToSymbolTable = 0;
  548. }
  549. //
  550. // Allocate the extra space that we need to grow the image
  551. //
  552. XipFile = malloc (XipLength);
  553. if (XipFile == NULL) {
  554. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  555. return;
  556. }
  557. memset (XipFile, 0, XipLength);
  558. //
  559. // Copy the file headers
  560. //
  561. memcpy (XipFile, *FileBuffer, PeHdr->Pe32.OptionalHeader.SizeOfHeaders);
  562. NewPeHdr = GetPeCoffHeader ((void *)XipFile);
  563. if (NewPeHdr == NULL) {
  564. free (XipFile);
  565. return;
  566. }
  567. //
  568. // Copy the section data over to the appropriate XIP offsets
  569. //
  570. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(NewPeHdr->Pe32.OptionalHeader) + NewPeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
  571. for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
  572. if (SectionHeader->SizeOfRawData > 0) {
  573. memcpy (
  574. XipFile + SectionHeader->VirtualAddress,
  575. *FileBuffer + SectionHeader->PointerToRawData,
  576. SectionHeader->SizeOfRawData
  577. );
  578. }
  579. //
  580. // Make the size of raw data in section header alignment.
  581. //
  582. SectionHeader->SizeOfRawData = (SectionHeader->Misc.VirtualSize + PeHdr->Pe32.OptionalHeader.FileAlignment - 1) & (~(PeHdr->Pe32.OptionalHeader.FileAlignment - 1));
  583. SectionHeader->PointerToRawData = SectionHeader->VirtualAddress;
  584. }
  585. free (*FileBuffer);
  586. *FileLength = XipLength;
  587. *FileBuffer = XipFile;
  588. mIsConvertXip = TRUE;
  589. }
  590. UINT8 *
  591. CreateHiiResouceSectionHeader (
  592. UINT32 *pSectionHeaderSize,
  593. UINT32 HiiDataSize
  594. )
  595. /*++
  596. Routine Description:
  597. Create COFF resource section header
  598. Arguments:
  599. pSectionHeaderSize - Pointer to section header size.
  600. HiiDataSize - Size of the total HII data in section.
  601. Returns:
  602. The created section header buffer.
  603. --*/
  604. {
  605. UINT32 HiiSectionHeaderSize;
  606. UINT32 HiiSectionOffset;
  607. UINT8 *HiiSectionHeader;
  608. EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory;
  609. EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *TypeResourceDirectoryEntry;
  610. EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *NameResourceDirectoryEntry;
  611. EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *LanguageResourceDirectoryEntry;
  612. EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString;
  613. EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry;
  614. //
  615. // Calculate the total size for the resource header (include Type, Name and Language)
  616. // then allocate memory for the resource header.
  617. //
  618. HiiSectionHeaderSize = 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY))
  619. + 3 * (sizeof (UINT16) + 3 * sizeof (CHAR16))
  620. + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);
  621. HiiSectionHeader = malloc (HiiSectionHeaderSize);
  622. if (HiiSectionHeader == NULL) {
  623. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  624. return NULL;
  625. }
  626. memset (HiiSectionHeader, 0, HiiSectionHeaderSize);
  627. HiiSectionOffset = 0;
  628. //
  629. // Create Type entry
  630. //
  631. ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);
  632. HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);
  633. ResourceDirectory->NumberOfNamedEntries = 1;
  634. TypeResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);
  635. HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);
  636. TypeResourceDirectoryEntry->u1.s.NameIsString = 1;
  637. TypeResourceDirectoryEntry->u2.s.DataIsDirectory = 1;
  638. TypeResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset;
  639. //
  640. // Create Name entry
  641. //
  642. ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);
  643. HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);
  644. ResourceDirectory->NumberOfNamedEntries = 1;
  645. NameResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);
  646. HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);
  647. NameResourceDirectoryEntry->u1.s.NameIsString = 1;
  648. NameResourceDirectoryEntry->u2.s.DataIsDirectory = 1;
  649. NameResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset;
  650. //
  651. // Create Language entry
  652. //
  653. ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset);
  654. HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY);
  655. ResourceDirectory->NumberOfNamedEntries = 1;
  656. LanguageResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset);
  657. HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY);
  658. LanguageResourceDirectoryEntry->u1.s.NameIsString = 1;
  659. //
  660. // Create string entry for Type
  661. //
  662. TypeResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;
  663. ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);
  664. ResourceDirectoryString->Length = 3;
  665. ResourceDirectoryString->String[0] = L'H';
  666. ResourceDirectoryString->String[1] = L'I';
  667. ResourceDirectoryString->String[2] = L'I';
  668. HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);
  669. //
  670. // Create string entry for Name
  671. //
  672. NameResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;
  673. ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);
  674. ResourceDirectoryString->Length = 3;
  675. ResourceDirectoryString->String[0] = L'E';
  676. ResourceDirectoryString->String[1] = L'F';
  677. ResourceDirectoryString->String[2] = L'I';
  678. HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);
  679. //
  680. // Create string entry for Language
  681. //
  682. LanguageResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset;
  683. ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset);
  684. ResourceDirectoryString->Length = 3;
  685. ResourceDirectoryString->String[0] = L'B';
  686. ResourceDirectoryString->String[1] = L'I';
  687. ResourceDirectoryString->String[2] = L'N';
  688. HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]);
  689. //
  690. // Create Leaf data
  691. //
  692. LanguageResourceDirectoryEntry->u2.OffsetToData = HiiSectionOffset;
  693. ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiSectionHeader + HiiSectionOffset);
  694. HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY);
  695. ResourceDataEntry->OffsetToData = HiiSectionOffset;
  696. ResourceDataEntry->Size = HiiDataSize;
  697. *pSectionHeaderSize = HiiSectionHeaderSize;
  698. return HiiSectionHeader;
  699. }
  700. EFI_STATUS
  701. RebaseImageRead (
  702. IN VOID *FileHandle,
  703. IN UINTN FileOffset,
  704. IN OUT UINT32 *ReadSize,
  705. OUT VOID *Buffer
  706. )
  707. /*++
  708. Routine Description:
  709. Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
  710. Arguments:
  711. FileHandle - The handle to the PE/COFF file
  712. FileOffset - The offset, in bytes, into the file to read
  713. ReadSize - The number of bytes to read from the file starting at FileOffset
  714. Buffer - A pointer to the buffer to read the data into.
  715. Returns:
  716. EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
  717. --*/
  718. {
  719. CHAR8 *Destination8;
  720. CHAR8 *Source8;
  721. UINT32 Length;
  722. Destination8 = Buffer;
  723. Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
  724. Length = *ReadSize;
  725. while (Length--) {
  726. *(Destination8++) = *(Source8++);
  727. }
  728. return EFI_SUCCESS;
  729. }
  730. EFI_STATUS
  731. SetAddressToSectionHeader (
  732. IN CHAR8 *FileName,
  733. IN OUT UINT8 *FileBuffer,
  734. IN UINT64 NewPe32BaseAddress
  735. )
  736. /*++
  737. Routine Description:
  738. Set new base address into the section header of PeImage
  739. Arguments:
  740. FileName - Name of file
  741. FileBuffer - Pointer to PeImage.
  742. NewPe32BaseAddress - New Base Address for PE image.
  743. Returns:
  744. EFI_SUCCESS Set new base address into this image successfully.
  745. --*/
  746. {
  747. EFI_STATUS Status;
  748. PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
  749. UINTN Index;
  750. EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
  751. EFI_IMAGE_SECTION_HEADER *SectionHeader;
  752. //
  753. // Initialize context
  754. //
  755. memset (&ImageContext, 0, sizeof (ImageContext));
  756. ImageContext.Handle = (VOID *) FileBuffer;
  757. ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;
  758. Status = PeCoffLoaderGetImageInfo (&ImageContext);
  759. if (EFI_ERROR (Status)) {
  760. Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);
  761. return Status;
  762. }
  763. if (ImageContext.RelocationsStripped) {
  764. Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);
  765. return Status;
  766. }
  767. //
  768. // Get PeHeader pointer
  769. //
  770. ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);
  771. //
  772. // Get section header list
  773. //
  774. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
  775. (UINTN) ImgHdr +
  776. sizeof (UINT32) +
  777. sizeof (EFI_IMAGE_FILE_HEADER) +
  778. ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
  779. );
  780. //
  781. // Set base address into the first section header that doesn't point to code section.
  782. //
  783. for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
  784. if ((SectionHeader->Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) {
  785. *(UINT64 *) &SectionHeader->PointerToRelocations = NewPe32BaseAddress;
  786. break;
  787. }
  788. }
  789. //
  790. // BaseAddress is set to section header.
  791. //
  792. return EFI_SUCCESS;
  793. }
  794. EFI_STATUS
  795. RebaseImage (
  796. IN CHAR8 *FileName,
  797. IN OUT UINT8 *FileBuffer,
  798. IN UINT64 NewPe32BaseAddress
  799. )
  800. /*++
  801. Routine Description:
  802. Set new base address into PeImage, and fix up PeImage based on new address.
  803. Arguments:
  804. FileName - Name of file
  805. FileBuffer - Pointer to PeImage.
  806. NewPe32BaseAddress - New Base Address for PE image.
  807. Returns:
  808. EFI_INVALID_PARAMETER - BaseAddress is not valid.
  809. EFI_SUCCESS - Update PeImage is correctly.
  810. --*/
  811. {
  812. EFI_STATUS Status;
  813. PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
  814. UINTN Index;
  815. EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
  816. UINT8 *MemoryImagePointer;
  817. EFI_IMAGE_SECTION_HEADER *SectionHeader;
  818. //
  819. // Initialize context
  820. //
  821. memset (&ImageContext, 0, sizeof (ImageContext));
  822. ImageContext.Handle = (VOID *) FileBuffer;
  823. ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead;
  824. Status = PeCoffLoaderGetImageInfo (&ImageContext);
  825. if (EFI_ERROR (Status)) {
  826. Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName);
  827. return Status;
  828. }
  829. if (ImageContext.RelocationsStripped) {
  830. Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName);
  831. return Status;
  832. }
  833. //
  834. // Get PeHeader pointer
  835. //
  836. ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset);
  837. //
  838. // Load and Relocate Image Data
  839. //
  840. MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
  841. if (MemoryImagePointer == NULL) {
  842. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
  843. return EFI_OUT_OF_RESOURCES;
  844. }
  845. memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
  846. ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1));
  847. Status = PeCoffLoaderLoadImage (&ImageContext);
  848. if (EFI_ERROR (Status)) {
  849. Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
  850. free ((VOID *) MemoryImagePointer);
  851. return Status;
  852. }
  853. ImageContext.DestinationAddress = NewPe32BaseAddress;
  854. Status = PeCoffLoaderRelocateImage (&ImageContext);
  855. if (EFI_ERROR (Status)) {
  856. Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName);
  857. free ((VOID *) MemoryImagePointer);
  858. return Status;
  859. }
  860. //
  861. // Copy Relocated data to raw image file.
  862. //
  863. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
  864. (UINTN) ImgHdr +
  865. sizeof (UINT32) +
  866. sizeof (EFI_IMAGE_FILE_HEADER) +
  867. ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
  868. );
  869. for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
  870. CopyMem (
  871. FileBuffer + SectionHeader->PointerToRawData,
  872. (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),
  873. SectionHeader->SizeOfRawData
  874. );
  875. }
  876. free ((VOID *) MemoryImagePointer);
  877. //
  878. // Update Image Base Address
  879. //
  880. if (ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  881. ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;
  882. } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  883. ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;
  884. } else {
  885. Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
  886. ImgHdr->Pe32.OptionalHeader.Magic,
  887. FileName
  888. );
  889. return EFI_ABORTED;
  890. }
  891. //
  892. // Set new base address into section header
  893. //
  894. Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress);
  895. return Status;
  896. }
  897. int
  898. main (
  899. int argc,
  900. char *argv[]
  901. )
  902. /*++
  903. Routine Description:
  904. Main function.
  905. Arguments:
  906. argc - Number of command line parameters.
  907. argv - Array of pointers to command line parameter strings.
  908. Returns:
  909. STATUS_SUCCESS - Utility exits successfully.
  910. STATUS_ERROR - Some error occurred during execution.
  911. --*/
  912. {
  913. UINT32 Type;
  914. UINT32 InputFileNum;
  915. CHAR8 **InputFileName;
  916. char *OutImageName;
  917. char *ModuleType;
  918. CHAR8 *TimeStamp;
  919. FILE *fpIn;
  920. FILE *fpOut;
  921. FILE *fpInOut;
  922. UINT32 Data;
  923. UINT32 *DataPointer;
  924. UINT32 *OldDataPointer;
  925. UINT32 CheckSum;
  926. UINT32 Index;
  927. UINT32 Index1;
  928. UINT32 Index2;
  929. UINT64 Temp64;
  930. UINT32 MciAlignment;
  931. UINT8 MciPadValue;
  932. UINT32 AllignedRelocSize;
  933. UINT8 *FileBuffer;
  934. UINT32 FileLength;
  935. UINT8 *OutputFileBuffer;
  936. UINT32 OutputFileLength;
  937. UINT8 *InputFileBuffer;
  938. UINT32 InputFileLength;
  939. RUNTIME_FUNCTION *RuntimeFunction;
  940. UNWIND_INFO *UnwindInfo;
  941. STATUS Status;
  942. BOOLEAN ReplaceFlag;
  943. BOOLEAN KeepExceptionTableFlag;
  944. BOOLEAN KeepOptionalHeaderFlag;
  945. BOOLEAN KeepZeroPendingFlag;
  946. UINT64 LogLevel;
  947. EFI_TE_IMAGE_HEADER TEImageHeader;
  948. EFI_TE_IMAGE_HEADER *TeHdr;
  949. EFI_IMAGE_SECTION_HEADER *SectionHeader;
  950. EFI_IMAGE_DOS_HEADER *DosHdr;
  951. EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr;
  952. EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;
  953. EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;
  954. EFI_IMAGE_DOS_HEADER BackupDosHdr;
  955. MICROCODE_IMAGE_HEADER *MciHeader;
  956. UINT8 *HiiPackageListBuffer;
  957. UINT8 *HiiPackageDataPointer;
  958. EFI_GUID HiiPackageListGuid;
  959. EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader;
  960. EFI_HII_PACKAGE_HEADER HiiPackageHeader;
  961. EFI_IFR_FORM_SET IfrFormSet;
  962. UINT8 NumberOfFormPackage;
  963. EFI_HII_PACKAGE_HEADER EndPackage;
  964. UINT32 HiiSectionHeaderSize;
  965. UINT8 *HiiSectionHeader;
  966. UINT64 NewBaseAddress;
  967. BOOLEAN NegativeAddr;
  968. FILE *ReportFile;
  969. CHAR8 *ReportFileName;
  970. UINTN FileLen;
  971. time_t InputFileTime;
  972. time_t OutputFileTime;
  973. struct stat Stat_Buf;
  974. SetUtilityName (UTILITY_NAME);
  975. //
  976. // Assign to fix compile warning
  977. //
  978. FileLen = 0;
  979. InputFileNum = 0;
  980. InputFileName = NULL;
  981. mInImageName = NULL;
  982. OutImageName = NULL;
  983. ModuleType = NULL;
  984. Type = 0;
  985. Status = STATUS_SUCCESS;
  986. FileBuffer = NULL;
  987. fpIn = NULL;
  988. fpOut = NULL;
  989. fpInOut = NULL;
  990. TimeStamp = NULL;
  991. MciAlignment = DEFAULT_MC_ALIGNMENT;
  992. MciPadValue = DEFAULT_MC_PAD_BYTE_VALUE;
  993. FileLength = 0;
  994. MciHeader = NULL;
  995. CheckSum = 0;
  996. ReplaceFlag = FALSE;
  997. LogLevel = 0;
  998. OutputFileBuffer = NULL;
  999. OutputFileLength = 0;
  1000. InputFileBuffer = NULL;
  1001. InputFileLength = 0;
  1002. Optional32 = NULL;
  1003. Optional64 = NULL;
  1004. KeepExceptionTableFlag = FALSE;
  1005. KeepOptionalHeaderFlag = FALSE;
  1006. KeepZeroPendingFlag = FALSE;
  1007. NumberOfFormPackage = 0;
  1008. HiiPackageListBuffer = NULL;
  1009. HiiPackageDataPointer = NULL;
  1010. EndPackage.Length = sizeof (EFI_HII_PACKAGE_HEADER);
  1011. EndPackage.Type = EFI_HII_PACKAGE_END;
  1012. memset (&HiiPackageListGuid, 0, sizeof (HiiPackageListGuid));
  1013. HiiSectionHeaderSize = 0;
  1014. HiiSectionHeader = NULL;
  1015. NewBaseAddress = 0;
  1016. NegativeAddr = FALSE;
  1017. InputFileTime = 0;
  1018. OutputFileTime = 0;
  1019. if (argc == 1) {
  1020. Error (NULL, 0, 1001, "Missing options", "No input options.");
  1021. Usage ();
  1022. return STATUS_ERROR;
  1023. }
  1024. argc --;
  1025. argv ++;
  1026. if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
  1027. Version ();
  1028. Usage ();
  1029. return STATUS_SUCCESS;
  1030. }
  1031. if (stricmp (argv[0], "--version") == 0) {
  1032. Version ();
  1033. return STATUS_SUCCESS;
  1034. }
  1035. while (argc > 0) {
  1036. if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
  1037. if (argv[1] == NULL || argv[1][0] == '-') {
  1038. Error (NULL, 0, 1003, "Invalid option value", "Output file name is missing for -o option");
  1039. goto Finish;
  1040. }
  1041. OutImageName = argv[1];
  1042. argc -= 2;
  1043. argv += 2;
  1044. continue;
  1045. }
  1046. if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--efiImage") == 0)) {
  1047. if (argv[1] == NULL || argv[1][0] == '-') {
  1048. Error (NULL, 0, 1003, "Invalid option value", "Module Type is missing for -o option");
  1049. goto Finish;
  1050. }
  1051. ModuleType = argv[1];
  1052. if (mOutImageType != FW_TE_IMAGE) {
  1053. mOutImageType = FW_EFI_IMAGE;
  1054. }
  1055. argc -= 2;
  1056. argv += 2;
  1057. continue;
  1058. }
  1059. if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--stripped") == 0)) {
  1060. mOutImageType = FW_RELOC_STRIPEED_IMAGE;
  1061. argc --;
  1062. argv ++;
  1063. continue;
  1064. }
  1065. if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) {
  1066. mOutImageType = FW_ACPI_IMAGE;
  1067. argc --;
  1068. argv ++;
  1069. continue;
  1070. }
  1071. if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) {
  1072. mOutImageType = FW_TE_IMAGE;
  1073. argc --;
  1074. argv ++;
  1075. continue;
  1076. }
  1077. if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) {
  1078. mOutImageType = DUMP_TE_HEADER;
  1079. argc --;
  1080. argv ++;
  1081. continue;
  1082. }
  1083. if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) {
  1084. mOutImageType = FW_BIN_IMAGE;
  1085. argc --;
  1086. argv ++;
  1087. continue;
  1088. }
  1089. if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) {
  1090. mOutImageType = FW_ZERO_DEBUG_IMAGE;
  1091. argc --;
  1092. argv ++;
  1093. continue;
  1094. }
  1095. if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) {
  1096. mOutImageType = FW_SET_STAMP_IMAGE;
  1097. if (argv[1] == NULL || argv[1][0] == '-') {
  1098. Error (NULL, 0, 1003, "Invalid option value", "time stamp is missing for -s option");
  1099. goto Finish;
  1100. }
  1101. TimeStamp = argv[1];
  1102. argc -= 2;
  1103. argv += 2;
  1104. continue;
  1105. }
  1106. if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--replace") == 0)) {
  1107. ReplaceFlag = TRUE;
  1108. argc --;
  1109. argv ++;
  1110. continue;
  1111. }
  1112. if (stricmp (argv[0], "--keepexceptiontable") == 0) {
  1113. KeepExceptionTableFlag = TRUE;
  1114. argc --;
  1115. argv ++;
  1116. continue;
  1117. }
  1118. if (stricmp(argv[0], "--keepoptionalheader") == 0) {
  1119. KeepOptionalHeaderFlag = TRUE;
  1120. argc--;
  1121. argv++;
  1122. continue;
  1123. }
  1124. if (stricmp (argv[0], "--keepzeropending") == 0) {
  1125. KeepZeroPendingFlag = TRUE;
  1126. argc --;
  1127. argv ++;
  1128. continue;
  1129. }
  1130. if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) {
  1131. mOutImageType = FW_MCI_IMAGE;
  1132. argc --;
  1133. argv ++;
  1134. continue;
  1135. }
  1136. if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--join") == 0)) {
  1137. mOutImageType = FW_MERGE_IMAGE;
  1138. argc --;
  1139. argv ++;
  1140. continue;
  1141. }
  1142. if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) {
  1143. if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {
  1144. Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
  1145. goto Finish;
  1146. }
  1147. MciAlignment = (UINT32) Temp64;
  1148. argc -= 2;
  1149. argv += 2;
  1150. continue;
  1151. }
  1152. if ((stricmp (argv[0], "--rebase") == 0)) {
  1153. if (argv[1][0] == '-') {
  1154. NegativeAddr = TRUE;
  1155. Status = AsciiStringToUint64 (argv[1] + 1, FALSE, &Temp64);
  1156. } else {
  1157. NegativeAddr = FALSE;
  1158. Status = AsciiStringToUint64 (argv[1], FALSE, &Temp64);
  1159. }
  1160. if (Status != EFI_SUCCESS) {
  1161. Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
  1162. goto Finish;
  1163. }
  1164. mOutImageType = FW_REBASE_IMAGE;
  1165. NewBaseAddress = (UINT64) Temp64;
  1166. argc -= 2;
  1167. argv += 2;
  1168. continue;
  1169. }
  1170. if ((stricmp (argv[0], "--address") == 0)) {
  1171. if (argv[1][0] == '-') {
  1172. NegativeAddr = TRUE;
  1173. Status = AsciiStringToUint64 (argv[1] + 1, FALSE, &Temp64);
  1174. } else {
  1175. NegativeAddr = FALSE;
  1176. Status = AsciiStringToUint64 (argv[1], FALSE, &Temp64);
  1177. }
  1178. if (Status != EFI_SUCCESS) {
  1179. Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
  1180. goto Finish;
  1181. }
  1182. mOutImageType = FW_SET_ADDRESS_IMAGE;
  1183. NewBaseAddress = (UINT64) Temp64;
  1184. argc -= 2;
  1185. argv += 2;
  1186. continue;
  1187. }
  1188. if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--pad") == 0)) {
  1189. if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) {
  1190. Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
  1191. goto Finish;
  1192. }
  1193. MciPadValue = (UINT8) Temp64;
  1194. argc -= 2;
  1195. argv += 2;
  1196. continue;
  1197. }
  1198. if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
  1199. SetPrintLevel (VERBOSE_LOG_LEVEL);
  1200. VerboseMsg ("Verbose output Mode Set!");
  1201. argc --;
  1202. argv ++;
  1203. continue;
  1204. }
  1205. if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
  1206. SetPrintLevel (KEY_LOG_LEVEL);
  1207. KeyMsg ("Quiet output Mode Set!");
  1208. argc --;
  1209. argv ++;
  1210. continue;
  1211. }
  1212. if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
  1213. Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
  1214. if (EFI_ERROR (Status)) {
  1215. Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
  1216. goto Finish;
  1217. }
  1218. if (LogLevel > 9) {
  1219. Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel);
  1220. goto Finish;
  1221. }
  1222. SetPrintLevel (LogLevel);
  1223. DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
  1224. argc -= 2;
  1225. argv += 2;
  1226. continue;
  1227. }
  1228. if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--hiiguid") == 0)) {
  1229. Status = StringToGuid (argv[1], &HiiPackageListGuid);
  1230. if (EFI_ERROR (Status)) {
  1231. Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
  1232. goto Finish;
  1233. }
  1234. argc -= 2;
  1235. argv += 2;
  1236. continue;
  1237. }
  1238. if (stricmp (argv[0], "--hiipackage") == 0) {
  1239. mOutImageType = FW_HII_PACKAGE_LIST_RCIMAGE;
  1240. argc --;
  1241. argv ++;
  1242. continue;
  1243. }
  1244. if (stricmp (argv[0], "--hiibinpackage") == 0) {
  1245. mOutImageType = FW_HII_PACKAGE_LIST_BINIMAGE;
  1246. argc --;
  1247. argv ++;
  1248. continue;
  1249. }
  1250. if (argv[0][0] == '-') {
  1251. Error (NULL, 0, 1000, "Unknown option", argv[0]);
  1252. goto Finish;
  1253. }
  1254. //
  1255. // Get Input file name
  1256. //
  1257. if ((InputFileNum == 0) && (InputFileName == NULL)) {
  1258. InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
  1259. if (InputFileName == NULL) {
  1260. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  1261. goto Finish;
  1262. }
  1263. memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
  1264. } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
  1265. //
  1266. // InputFileName buffer too small, need to realloc
  1267. //
  1268. InputFileName = (CHAR8 **) realloc (
  1269. InputFileName,
  1270. (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
  1271. );
  1272. if (InputFileName == NULL) {
  1273. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  1274. goto Finish;
  1275. }
  1276. memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
  1277. }
  1278. InputFileName [InputFileNum ++] = argv[0];
  1279. argc --;
  1280. argv ++;
  1281. }
  1282. VerboseMsg ("%s tool start.", UTILITY_NAME);
  1283. if (mOutImageType == FW_DUMMY_IMAGE) {
  1284. Error (NULL, 0, 1001, "Missing option", "No create file action specified; pls specify -e, -c or -t option to create efi image, or acpi table or TeImage!");
  1285. if (ReplaceFlag) {
  1286. Error (NULL, 0, 1001, "Missing option", "-r option is not supported as the independent option. It can be used together with other create file option specified at the above.");
  1287. }
  1288. goto Finish;
  1289. }
  1290. //
  1291. // check input files
  1292. //
  1293. if (InputFileNum == 0) {
  1294. Error (NULL, 0, 1001, "Missing option", "Input files");
  1295. goto Finish;
  1296. }
  1297. //
  1298. // Combine MciBinary files to one file
  1299. //
  1300. if ((mOutImageType == FW_MERGE_IMAGE) && ReplaceFlag) {
  1301. Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option.");
  1302. goto Finish;
  1303. }
  1304. //
  1305. // Combine HiiBinary packages to a single package list
  1306. //
  1307. if ((mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) && ReplaceFlag) {
  1308. Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option.");
  1309. goto Finish;
  1310. }
  1311. if ((mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) && ReplaceFlag) {
  1312. Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option.");
  1313. goto Finish;
  1314. }
  1315. //
  1316. // Input image file
  1317. //
  1318. mInImageName = InputFileName [InputFileNum - 1];
  1319. VerboseMsg ("the input file name is %s", mInImageName);
  1320. //
  1321. // Action will be taken for the input file.
  1322. //
  1323. switch (mOutImageType) {
  1324. case FW_EFI_IMAGE:
  1325. VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType);
  1326. break;
  1327. case FW_TE_IMAGE:
  1328. VerboseMsg ("Create Te Image based on the input PE image.");
  1329. break;
  1330. case FW_ACPI_IMAGE:
  1331. VerboseMsg ("Get acpi table data from the input PE image.");
  1332. break;
  1333. case FW_RELOC_STRIPEED_IMAGE:
  1334. VerboseMsg ("Remove relocation section from Pe or Te image.");
  1335. break;
  1336. case FW_BIN_IMAGE:
  1337. VerboseMsg ("Convert the input EXE to the output BIN file.");
  1338. break;
  1339. case FW_ZERO_DEBUG_IMAGE:
  1340. VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image.");
  1341. break;
  1342. case FW_SET_STAMP_IMAGE:
  1343. VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp);
  1344. break;
  1345. case DUMP_TE_HEADER:
  1346. VerboseMsg ("Dump the TE header information of the input TE image.");
  1347. break;
  1348. case FW_MCI_IMAGE:
  1349. VerboseMsg ("Convert input MicroCode.txt file to MicroCode.bin file.");
  1350. break;
  1351. case FW_MERGE_IMAGE:
  1352. VerboseMsg ("Combine the input multi microcode bin files to one bin file.");
  1353. break;
  1354. case FW_HII_PACKAGE_LIST_RCIMAGE:
  1355. VerboseMsg ("Combine the input multi hii bin packages to one text package list RC file.");
  1356. break;
  1357. case FW_HII_PACKAGE_LIST_BINIMAGE:
  1358. VerboseMsg ("Combine the input multi hii bin packages to one binary package list file.");
  1359. break;
  1360. case FW_REBASE_IMAGE:
  1361. VerboseMsg ("Rebase the input image to new base address.");
  1362. break;
  1363. case FW_SET_ADDRESS_IMAGE:
  1364. VerboseMsg ("Set the preferred address into the section header of the input image");
  1365. break;
  1366. default:
  1367. break;
  1368. }
  1369. if (ReplaceFlag) {
  1370. VerboseMsg ("Overwrite the input file with the output content.");
  1371. }
  1372. //
  1373. // Open output file and Write image into the output file.
  1374. //
  1375. if (OutImageName != NULL) {
  1376. fpOut = fopen (LongFilePath (OutImageName), "rb");
  1377. if (fpOut != NULL) {
  1378. //
  1379. // Get Output file time stamp
  1380. //
  1381. fstat(fileno (fpOut), &Stat_Buf);
  1382. OutputFileTime = Stat_Buf.st_mtime;
  1383. //
  1384. // Get Output file data
  1385. //
  1386. OutputFileLength = _filelength (fileno (fpOut));
  1387. OutputFileBuffer = malloc (OutputFileLength);
  1388. if (OutputFileBuffer == NULL) {
  1389. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  1390. fclose (fpOut);
  1391. fpOut = NULL;
  1392. goto Finish;
  1393. }
  1394. fread (OutputFileBuffer, 1, OutputFileLength, fpOut);
  1395. fclose (fpOut);
  1396. fpOut = NULL;
  1397. }
  1398. VerboseMsg ("Output file name is %s", OutImageName);
  1399. } else if (!ReplaceFlag && mOutImageType != DUMP_TE_HEADER) {
  1400. Error (NULL, 0, 1001, "Missing option", "output file");
  1401. goto Finish;
  1402. }
  1403. //
  1404. // Open input file and read file data into file buffer.
  1405. //
  1406. fpIn = fopen (LongFilePath (mInImageName), "rb");
  1407. if (fpIn == NULL) {
  1408. Error (NULL, 0, 0001, "Error opening file", mInImageName);
  1409. goto Finish;
  1410. }
  1411. //
  1412. // Get Iutput file time stamp
  1413. //
  1414. fstat(fileno (fpIn), &Stat_Buf);
  1415. InputFileTime = Stat_Buf.st_mtime;
  1416. //
  1417. // Get Input file data
  1418. //
  1419. InputFileLength = _filelength (fileno (fpIn));
  1420. InputFileBuffer = malloc (InputFileLength);
  1421. if (InputFileBuffer == NULL) {
  1422. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  1423. fclose (fpIn);
  1424. goto Finish;
  1425. }
  1426. fread (InputFileBuffer, 1, InputFileLength, fpIn);
  1427. fclose (fpIn);
  1428. DebugMsg (NULL, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) InputFileLength);
  1429. //
  1430. // Combine multi binary HII package files.
  1431. //
  1432. if (mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE || mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) {
  1433. //
  1434. // Open output file handle.
  1435. //
  1436. fpOut = fopen (LongFilePath (OutImageName), "wb");
  1437. if (!fpOut) {
  1438. Error (NULL, 0, 0001, "Error opening output file", OutImageName);
  1439. goto Finish;
  1440. }
  1441. //
  1442. // Get hii package list length
  1443. //
  1444. HiiPackageListHeader.PackageLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER);
  1445. for (Index = 0; Index < InputFileNum; Index ++) {
  1446. fpIn = fopen (LongFilePath (InputFileName [Index]), "rb");
  1447. if (fpIn == NULL) {
  1448. Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);
  1449. goto Finish;
  1450. }
  1451. FileLength = _filelength (fileno (fpIn));
  1452. fread (&HiiPackageHeader, 1, sizeof (HiiPackageHeader), fpIn);
  1453. if (HiiPackageHeader.Type == EFI_HII_PACKAGE_FORM) {
  1454. if (HiiPackageHeader.Length != FileLength) {
  1455. Error (NULL, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName [Index]);
  1456. fclose (fpIn);
  1457. goto Finish;
  1458. }
  1459. if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) {
  1460. fread (&IfrFormSet, 1, sizeof (IfrFormSet), fpIn);
  1461. memcpy (&HiiPackageListGuid, &IfrFormSet.Guid, sizeof (EFI_GUID));
  1462. }
  1463. NumberOfFormPackage ++;
  1464. }
  1465. HiiPackageListHeader.PackageLength += FileLength;
  1466. fclose (fpIn);
  1467. }
  1468. HiiPackageListHeader.PackageLength += sizeof (EndPackage);
  1469. //
  1470. // Check whether hii packages are valid
  1471. //
  1472. if (NumberOfFormPackage > 1) {
  1473. Error (NULL, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package");
  1474. goto Finish;
  1475. }
  1476. if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) {
  1477. Error (NULL, 0, 3000, "Invalid", "HII package list guid is not specified!");
  1478. goto Finish;
  1479. }
  1480. memcpy (&HiiPackageListHeader.PackageListGuid, &HiiPackageListGuid, sizeof (EFI_GUID));
  1481. //
  1482. // read hii packages
  1483. //
  1484. HiiPackageListBuffer = malloc (HiiPackageListHeader.PackageLength);
  1485. if (HiiPackageListBuffer == NULL) {
  1486. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  1487. goto Finish;
  1488. }
  1489. memcpy (HiiPackageListBuffer, &HiiPackageListHeader, sizeof (HiiPackageListHeader));
  1490. HiiPackageDataPointer = HiiPackageListBuffer + sizeof (HiiPackageListHeader);
  1491. for (Index = 0; Index < InputFileNum; Index ++) {
  1492. fpIn = fopen (LongFilePath (InputFileName [Index]), "rb");
  1493. if (fpIn == NULL) {
  1494. Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);
  1495. free (HiiPackageListBuffer);
  1496. goto Finish;
  1497. }
  1498. FileLength = _filelength (fileno (fpIn));
  1499. fread (HiiPackageDataPointer, 1, FileLength, fpIn);
  1500. fclose (fpIn);
  1501. HiiPackageDataPointer = HiiPackageDataPointer + FileLength;
  1502. }
  1503. memcpy (HiiPackageDataPointer, &EndPackage, sizeof (EndPackage));
  1504. //
  1505. // write the hii package into the binary package list file with the resource section header
  1506. //
  1507. if (mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) {
  1508. //
  1509. // Create the resource section header
  1510. //
  1511. HiiSectionHeader = CreateHiiResouceSectionHeader (&HiiSectionHeaderSize, HiiPackageListHeader.PackageLength);
  1512. if (HiiSectionHeader == NULL) {
  1513. free (HiiPackageListBuffer);
  1514. goto Finish;
  1515. }
  1516. //
  1517. // Wrtie section header and HiiData into File.
  1518. //
  1519. fwrite (HiiSectionHeader, 1, HiiSectionHeaderSize, fpOut);
  1520. fwrite (HiiPackageListBuffer, 1, HiiPackageListHeader.PackageLength, fpOut);
  1521. //
  1522. // Free allocated resources.
  1523. //
  1524. free (HiiSectionHeader);
  1525. free (HiiPackageListBuffer);
  1526. //
  1527. // Done successfully
  1528. //
  1529. goto Finish;
  1530. }
  1531. //
  1532. // write the hii package into the text package list rc file.
  1533. //
  1534. if (mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) {
  1535. for (Index = 0; gHiiPackageRCFileHeader[Index] != NULL; Index++) {
  1536. fprintf (fpOut, "%s\n", gHiiPackageRCFileHeader[Index]);
  1537. }
  1538. fprintf (fpOut, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX, HII_RESOURCE_SECTION_NAME);
  1539. HiiPackageDataPointer = HiiPackageListBuffer;
  1540. for (Index = 0; Index + 2 < HiiPackageListHeader.PackageLength; Index += 2) {
  1541. if (Index % 16 == 0) {
  1542. fprintf (fpOut, "\n ");
  1543. }
  1544. fprintf (fpOut, " 0x%04X,", *(UINT16 *) HiiPackageDataPointer);
  1545. HiiPackageDataPointer += 2;
  1546. }
  1547. if (Index % 16 == 0) {
  1548. fprintf (fpOut, "\n ");
  1549. }
  1550. if ((Index + 2) == HiiPackageListHeader.PackageLength) {
  1551. fprintf (fpOut, " 0x%04X\n}\n", *(UINT16 *) HiiPackageDataPointer);
  1552. }
  1553. if ((Index + 1) == HiiPackageListHeader.PackageLength) {
  1554. fprintf (fpOut, " 0x%04X\n}\n", *(UINT8 *) HiiPackageDataPointer);
  1555. }
  1556. free (HiiPackageListBuffer);
  1557. //
  1558. // Done successfully
  1559. //
  1560. goto Finish;
  1561. }
  1562. }
  1563. //
  1564. // Combine MciBinary files to one file
  1565. //
  1566. if (mOutImageType == FW_MERGE_IMAGE) {
  1567. //
  1568. // Open output file handle.
  1569. //
  1570. fpOut = fopen (LongFilePath (OutImageName), "wb");
  1571. if (!fpOut) {
  1572. Error (NULL, 0, 0001, "Error opening output file", OutImageName);
  1573. goto Finish;
  1574. }
  1575. for (Index = 0; Index < InputFileNum; Index ++) {
  1576. fpIn = fopen (LongFilePath (InputFileName [Index]), "rb");
  1577. if (!fpIn) {
  1578. Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]);
  1579. goto Finish;
  1580. }
  1581. FileLength = _filelength (fileno (fpIn));
  1582. FileBuffer = malloc (FileLength);
  1583. if (FileBuffer == NULL) {
  1584. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  1585. fclose (fpIn);
  1586. goto Finish;
  1587. }
  1588. fread (FileBuffer, 1, FileLength, fpIn);
  1589. fclose (fpIn);
  1590. //
  1591. // write input file to out file
  1592. //
  1593. fwrite (FileBuffer, 1, FileLength, fpOut);
  1594. //
  1595. // write pad value to out file.
  1596. //
  1597. while (FileLength ++ % MciAlignment != 0) {
  1598. fwrite (&MciPadValue, 1, 1, fpOut);
  1599. }
  1600. //
  1601. // free allocated memory space
  1602. //
  1603. free (FileBuffer);
  1604. FileBuffer = NULL;
  1605. }
  1606. //
  1607. // Done successfully
  1608. //
  1609. goto Finish;
  1610. }
  1611. //
  1612. // Convert MicroCode.txt file to MicroCode.bin file
  1613. //
  1614. if (mOutImageType == FW_MCI_IMAGE) {
  1615. fpIn = fopen (LongFilePath (mInImageName), "r");
  1616. if (fpIn == NULL) {
  1617. Error (NULL, 0, 0001, "Error opening file", mInImageName);
  1618. goto Finish;
  1619. }
  1620. //
  1621. // The first pass is to determine
  1622. // how much data is in the file so we can allocate a working buffer.
  1623. //
  1624. FileLength = 0;
  1625. do {
  1626. Status = MicrocodeReadData (fpIn, &Data);
  1627. if (Status == STATUS_SUCCESS) {
  1628. FileLength += sizeof (Data);
  1629. }
  1630. if (Status == STATUS_IGNORE) {
  1631. Status = STATUS_SUCCESS;
  1632. }
  1633. } while (Status == STATUS_SUCCESS);
  1634. //
  1635. // Error if no data.
  1636. //
  1637. if (FileLength == 0) {
  1638. Error (NULL, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName);
  1639. goto Finish;
  1640. }
  1641. if (FileLength < sizeof (MICROCODE_IMAGE_HEADER)) {
  1642. Error (NULL, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName);
  1643. goto Finish;
  1644. }
  1645. //
  1646. // Allocate a buffer for the data
  1647. //
  1648. FileBuffer = malloc (FileLength);
  1649. if (FileBuffer == NULL) {
  1650. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  1651. goto Finish;
  1652. }
  1653. //
  1654. // Re-read the file, storing the data into our buffer
  1655. //
  1656. fseek (fpIn, 0, SEEK_SET);
  1657. DataPointer = (UINT32 *) FileBuffer;
  1658. OldDataPointer = DataPointer;
  1659. do {
  1660. OldDataPointer = DataPointer;
  1661. Status = MicrocodeReadData (fpIn, DataPointer++);
  1662. if (Status == STATUS_IGNORE) {
  1663. DataPointer = OldDataPointer;
  1664. Status = STATUS_SUCCESS;
  1665. }
  1666. } while (Status == STATUS_SUCCESS);
  1667. //
  1668. // close input file after read data
  1669. //
  1670. fclose (fpIn);
  1671. //
  1672. // Can't do much checking on the header because, per the spec, the
  1673. // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K,
  1674. // and the TotalSize field is invalid (actually missing). Thus we can't
  1675. // even verify the Reserved fields are 0.
  1676. //
  1677. MciHeader = (MICROCODE_IMAGE_HEADER *) FileBuffer;
  1678. if (MciHeader->DataSize == 0) {
  1679. Index = 2048;
  1680. } else {
  1681. Index = MciHeader->TotalSize;
  1682. }
  1683. if (Index != FileLength) {
  1684. Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, (unsigned) FileLength, (unsigned) Index);
  1685. goto Finish;
  1686. }
  1687. //
  1688. // Checksum the contents
  1689. //
  1690. DataPointer = (UINT32 *) FileBuffer;
  1691. CheckSum = 0;
  1692. Index = 0;
  1693. while (Index < FileLength) {
  1694. CheckSum += *DataPointer;
  1695. DataPointer ++;
  1696. Index += sizeof (*DataPointer);
  1697. }
  1698. if (CheckSum != 0) {
  1699. Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum, mInImageName);
  1700. goto Finish;
  1701. }
  1702. //
  1703. // Open the output file and write the buffer contents
  1704. //
  1705. VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
  1706. goto WriteFile;
  1707. }
  1708. //
  1709. // Open input file and read file data into file buffer.
  1710. //
  1711. FileLength = InputFileLength;
  1712. FileBuffer = malloc (FileLength);
  1713. if (FileBuffer == NULL) {
  1714. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  1715. goto Finish;
  1716. }
  1717. memcpy (FileBuffer, InputFileBuffer, InputFileLength);
  1718. //
  1719. // Dump TeImage Header into output file.
  1720. //
  1721. if (mOutImageType == DUMP_TE_HEADER) {
  1722. memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader));
  1723. if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {
  1724. Error (NULL, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName);
  1725. goto Finish;
  1726. }
  1727. //
  1728. // Open the output file handle.
  1729. //
  1730. if (ReplaceFlag) {
  1731. fpInOut = fopen (LongFilePath (mInImageName), "wb");
  1732. if (fpInOut == NULL) {
  1733. Error (NULL, 0, 0001, "Error opening file", mInImageName);
  1734. goto Finish;
  1735. }
  1736. } else {
  1737. if (OutImageName != NULL) {
  1738. fpOut = fopen (LongFilePath (OutImageName), "wb");
  1739. } else {
  1740. fpOut = stdout;
  1741. }
  1742. if (fpOut == NULL) {
  1743. Error (NULL, 0, 0001, "Error opening output file", OutImageName);
  1744. goto Finish;
  1745. }
  1746. }
  1747. if (fpInOut != NULL) {
  1748. fprintf (fpInOut, "Dump of file %s\n\n", mInImageName);
  1749. fprintf (fpInOut, "TE IMAGE HEADER VALUES\n");
  1750. fprintf (fpInOut, "%17X machine\n", TEImageHeader.Machine);
  1751. fprintf (fpInOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);
  1752. fprintf (fpInOut, "%17X subsystems\n", TEImageHeader.Subsystem);
  1753. fprintf (fpInOut, "%17X stripped size\n", TEImageHeader.StrippedSize);
  1754. fprintf (fpInOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint);
  1755. fprintf (fpInOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode);
  1756. fprintf (fpInOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase);
  1757. fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size);
  1758. fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size);
  1759. }
  1760. if (fpOut != NULL) {
  1761. fprintf (fpOut, "Dump of file %s\n\n", mInImageName);
  1762. fprintf (fpOut, "TE IMAGE HEADER VALUES\n");
  1763. fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine);
  1764. fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections);
  1765. fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem);
  1766. fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize);
  1767. fprintf (fpOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint);
  1768. fprintf (fpOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode);
  1769. fprintf (fpOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase);
  1770. fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size);
  1771. fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size);
  1772. }
  1773. goto Finish;
  1774. }
  1775. //
  1776. // Following code to convert dll to efi image or te image.
  1777. // Get new image type
  1778. //
  1779. if ((mOutImageType == FW_EFI_IMAGE) || (mOutImageType == FW_TE_IMAGE)) {
  1780. if (ModuleType == NULL) {
  1781. if (mOutImageType == FW_EFI_IMAGE) {
  1782. Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE");
  1783. goto Finish;
  1784. } else if (mOutImageType == FW_TE_IMAGE) {
  1785. //
  1786. // Default TE Image Type is Boot service driver
  1787. //
  1788. Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
  1789. VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
  1790. }
  1791. } else {
  1792. if (stricmp (ModuleType, "BASE") == 0 ||
  1793. stricmp (ModuleType, "SEC") == 0 ||
  1794. stricmp (ModuleType, "SECURITY_CORE") == 0 ||
  1795. stricmp (ModuleType, "PEI_CORE") == 0 ||
  1796. stricmp (ModuleType, "PEIM") == 0 ||
  1797. stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 ||
  1798. stricmp (ModuleType, "PIC_PEIM") == 0 ||
  1799. stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 ||
  1800. stricmp (ModuleType, "DXE_CORE") == 0 ||
  1801. stricmp (ModuleType, "BS_DRIVER") == 0 ||
  1802. stricmp (ModuleType, "DXE_DRIVER") == 0 ||
  1803. stricmp (ModuleType, "DXE_SMM_DRIVER") == 0 ||
  1804. stricmp (ModuleType, "UEFI_DRIVER") == 0 ||
  1805. stricmp (ModuleType, "SMM_CORE") == 0 ||
  1806. stricmp (ModuleType, "MM_STANDALONE") == 0 ||
  1807. stricmp (ModuleType, "MM_CORE_STANDALONE") == 0) {
  1808. Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER;
  1809. VerboseMsg ("Efi Image subsystem type is efi boot service driver.");
  1810. } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 ||
  1811. stricmp (ModuleType, "APPLICATION") == 0) {
  1812. Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION;
  1813. VerboseMsg ("Efi Image subsystem type is efi application.");
  1814. } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 ||
  1815. stricmp (ModuleType, "RT_DRIVER") == 0) {
  1816. Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER;
  1817. VerboseMsg ("Efi Image subsystem type is efi runtime driver.");
  1818. } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 ||
  1819. stricmp (ModuleType, "SAL_RT_DRIVER") == 0) {
  1820. Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER;
  1821. VerboseMsg ("Efi Image subsystem type is efi sal runtime driver.");
  1822. } else {
  1823. Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType);
  1824. goto Finish;
  1825. }
  1826. }
  1827. }
  1828. //
  1829. // Convert ELF image to PeImage
  1830. //
  1831. if (IsElfHeader(FileBuffer)) {
  1832. VerboseMsg ("Convert %s from ELF to PE/COFF.", mInImageName);
  1833. if (!ConvertElf(&FileBuffer, &FileLength)) {
  1834. Error (NULL, 0, 3000, "Invalid", "Unable to convert %s from ELF to PE/COFF.", mInImageName);
  1835. goto Finish;
  1836. }
  1837. }
  1838. //
  1839. // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP
  1840. // XIP == eXecute In Place
  1841. //
  1842. PeCoffConvertImageToXip (&FileBuffer, &FileLength);
  1843. //
  1844. // Remove reloc section from PE or TE image
  1845. //
  1846. if (mOutImageType == FW_RELOC_STRIPEED_IMAGE) {
  1847. //
  1848. // Check TeImage
  1849. //
  1850. TeHdr = (EFI_TE_IMAGE_HEADER *) FileBuffer;
  1851. if (TeHdr->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
  1852. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TeHdr + 1);
  1853. for (Index = 0; Index < TeHdr->NumberOfSections; Index ++, SectionHeader ++) {
  1854. if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) {
  1855. //
  1856. // Check the reloc section is in the end of image.
  1857. //
  1858. if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) ==
  1859. (FileLength + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER))) {
  1860. //
  1861. // Remove .reloc section and update TeImage Header
  1862. //
  1863. FileLength = FileLength - SectionHeader->SizeOfRawData;
  1864. SectionHeader->SizeOfRawData = 0;
  1865. SectionHeader->Misc.VirtualSize = 0;
  1866. TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
  1867. TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
  1868. break;
  1869. }
  1870. }
  1871. }
  1872. } else {
  1873. //
  1874. // Check PE Image
  1875. //
  1876. DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;
  1877. if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
  1878. PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer);
  1879. if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
  1880. Error (NULL, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName);
  1881. goto Finish;
  1882. }
  1883. DosHdr = NULL;
  1884. } else {
  1885. PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew);
  1886. if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
  1887. Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);
  1888. goto Finish;
  1889. }
  1890. }
  1891. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
  1892. for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
  1893. if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) {
  1894. //
  1895. // Check the reloc section is in the end of image.
  1896. //
  1897. if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == FileLength) {
  1898. //
  1899. // Remove .reloc section and update PeImage Header
  1900. //
  1901. FileLength = FileLength - SectionHeader->SizeOfRawData;
  1902. PeHdr->Pe32.FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED;
  1903. if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  1904. Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
  1905. Optional32->SizeOfImage -= SectionHeader->SizeOfRawData;
  1906. Optional32->SizeOfInitializedData -= SectionHeader->SizeOfRawData;
  1907. if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
  1908. Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
  1909. Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
  1910. }
  1911. }
  1912. if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  1913. Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
  1914. Optional64->SizeOfImage -= SectionHeader->SizeOfRawData;
  1915. Optional64->SizeOfInitializedData -= SectionHeader->SizeOfRawData;
  1916. if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
  1917. Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0;
  1918. Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
  1919. }
  1920. }
  1921. SectionHeader->Misc.VirtualSize = 0;
  1922. SectionHeader->SizeOfRawData = 0;
  1923. break;
  1924. }
  1925. }
  1926. }
  1927. }
  1928. //
  1929. // Write file
  1930. //
  1931. goto WriteFile;
  1932. }
  1933. //
  1934. // Read the dos & pe hdrs of the image
  1935. //
  1936. DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
  1937. if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
  1938. // NO DOS header, check for PE/COFF header
  1939. PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer);
  1940. if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
  1941. Error (NULL, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName);
  1942. goto Finish;
  1943. }
  1944. DosHdr = NULL;
  1945. } else {
  1946. PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew);
  1947. if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
  1948. Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName);
  1949. goto Finish;
  1950. }
  1951. }
  1952. if (PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) {
  1953. // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2)
  1954. // so patch back to the official UEFI value.
  1955. PeHdr->Pe32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMT;
  1956. }
  1957. //
  1958. // Set new base address into image
  1959. //
  1960. if (mOutImageType == FW_REBASE_IMAGE || mOutImageType == FW_SET_ADDRESS_IMAGE) {
  1961. if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  1962. if (NewBaseAddress >= 0x100000000ULL) {
  1963. Error (NULL, 0, 3000, "Invalid", "New base address is larger than 4G for 32bit PE image");
  1964. goto Finish;
  1965. }
  1966. }
  1967. if (NegativeAddr) {
  1968. //
  1969. // Set Base Address to a negative value.
  1970. //
  1971. NewBaseAddress = (UINT64) (0 - NewBaseAddress);
  1972. }
  1973. if (mOutImageType == FW_REBASE_IMAGE) {
  1974. Status = RebaseImage (mInImageName, FileBuffer, NewBaseAddress);
  1975. } else {
  1976. Status = SetAddressToSectionHeader (mInImageName, FileBuffer, NewBaseAddress);
  1977. }
  1978. if (EFI_ERROR (Status)) {
  1979. if (NegativeAddr) {
  1980. Error (NULL, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address -0x%llx can't success", mInImageName, 0 - NewBaseAddress);
  1981. } else {
  1982. Error (NULL, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address 0x%llx can't success", mInImageName, NewBaseAddress);
  1983. }
  1984. goto Finish;
  1985. }
  1986. //
  1987. // Write file
  1988. //
  1989. goto WriteFile;
  1990. }
  1991. //
  1992. // Extract bin data from Pe image.
  1993. //
  1994. if (mOutImageType == FW_BIN_IMAGE) {
  1995. if (FileLength < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) {
  1996. Error (NULL, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName);
  1997. goto Finish;
  1998. }
  1999. //
  2000. // Output bin data from exe file
  2001. //
  2002. FileLength = FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders;
  2003. memmove (FileBuffer, FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, FileLength);
  2004. VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
  2005. goto WriteFile;
  2006. }
  2007. //
  2008. // Zero Debug Information of Pe Image
  2009. //
  2010. if (mOutImageType == FW_ZERO_DEBUG_IMAGE) {
  2011. Status = ZeroDebugData (FileBuffer, TRUE);
  2012. if (EFI_ERROR (Status)) {
  2013. Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status);
  2014. goto Finish;
  2015. }
  2016. //
  2017. // Write the updated Image
  2018. //
  2019. VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
  2020. goto WriteFile;
  2021. }
  2022. //
  2023. // Set Time Stamp of Pe Image
  2024. //
  2025. if (mOutImageType == FW_SET_STAMP_IMAGE) {
  2026. Status = SetStamp (FileBuffer, TimeStamp);
  2027. if (EFI_ERROR (Status)) {
  2028. goto Finish;
  2029. }
  2030. //
  2031. // Write the updated Image
  2032. //
  2033. VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
  2034. goto WriteFile;
  2035. }
  2036. //
  2037. // Extract acpi data from pe image.
  2038. //
  2039. if (mOutImageType == FW_ACPI_IMAGE) {
  2040. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
  2041. for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
  2042. if (strcmp ((char *)SectionHeader->Name, ".data") == 0 || strcmp ((char *)SectionHeader->Name, ".sdata") == 0) {
  2043. //
  2044. // Check Acpi Table
  2045. //
  2046. if (SectionHeader->Misc.VirtualSize < SectionHeader->SizeOfRawData) {
  2047. FileLength = SectionHeader->Misc.VirtualSize;
  2048. } else {
  2049. FileLength = SectionHeader->SizeOfRawData;
  2050. }
  2051. if (CheckAcpiTable (FileBuffer + SectionHeader->PointerToRawData, FileLength) != STATUS_SUCCESS) {
  2052. Error (NULL, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName);
  2053. goto Finish;
  2054. }
  2055. //
  2056. // Output Apci data to file
  2057. //
  2058. memmove (FileBuffer, FileBuffer + SectionHeader->PointerToRawData, FileLength);
  2059. VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
  2060. goto WriteFile;
  2061. }
  2062. }
  2063. Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName);
  2064. goto Finish;
  2065. }
  2066. //
  2067. // Zero all unused fields of the DOS header
  2068. //
  2069. if (DosHdr != NULL) {
  2070. memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER));
  2071. memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER));
  2072. DosHdr->e_magic = BackupDosHdr.e_magic;
  2073. DosHdr->e_lfanew = BackupDosHdr.e_lfanew;
  2074. for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (UINT32 ) DosHdr->e_lfanew; Index++) {
  2075. FileBuffer[Index] = (UINT8) DosHdr->e_cp;
  2076. }
  2077. }
  2078. //
  2079. // Initialize TeImage Header
  2080. //
  2081. memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER));
  2082. TEImageHeader.Signature = EFI_TE_IMAGE_HEADER_SIGNATURE;
  2083. TEImageHeader.Machine = PeHdr->Pe32.FileHeader.Machine;
  2084. TEImageHeader.NumberOfSections = (UINT8) PeHdr->Pe32.FileHeader.NumberOfSections;
  2085. TEImageHeader.StrippedSize = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer);
  2086. TEImageHeader.Subsystem = (UINT8) Type;
  2087. //
  2088. // Patch the PE header
  2089. //
  2090. PeHdr->Pe32.OptionalHeader.Subsystem = (UINT16) Type;
  2091. if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  2092. Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
  2093. if (!KeepOptionalHeaderFlag) {
  2094. Optional32->MajorOperatingSystemVersion = 0;
  2095. Optional32->MinorOperatingSystemVersion = 0;
  2096. Optional32->MajorImageVersion = 0;
  2097. Optional32->MinorImageVersion = 0;
  2098. Optional32->MajorSubsystemVersion = 0;
  2099. Optional32->MinorSubsystemVersion = 0;
  2100. Optional32->Win32VersionValue = 0;
  2101. Optional32->CheckSum = 0;
  2102. Optional32->SizeOfStackReserve = 0;
  2103. Optional32->SizeOfStackCommit = 0;
  2104. Optional32->SizeOfHeapReserve = 0;
  2105. Optional32->SizeOfHeapCommit = 0;
  2106. }
  2107. TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint;
  2108. TEImageHeader.BaseOfCode = Optional32->BaseOfCode;
  2109. TEImageHeader.ImageBase = (UINT64) (Optional32->ImageBase);
  2110. if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
  2111. TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
  2112. TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
  2113. }
  2114. if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
  2115. TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  2116. TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
  2117. }
  2118. //
  2119. // Zero .pdata section data.
  2120. //
  2121. if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&
  2122. Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&
  2123. Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {
  2124. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
  2125. for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
  2126. if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {
  2127. //
  2128. // Zero .pdata Section data
  2129. //
  2130. memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData);
  2131. //
  2132. // Zero .pdata Section header name
  2133. //
  2134. memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));
  2135. //
  2136. // Zero Exception Table
  2137. //
  2138. Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;
  2139. Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;
  2140. DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL);
  2141. break;
  2142. }
  2143. }
  2144. }
  2145. //
  2146. // Strip zero padding at the end of the .reloc section
  2147. //
  2148. if (!KeepZeroPendingFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
  2149. if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {
  2150. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
  2151. for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
  2152. //
  2153. // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
  2154. //
  2155. if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {
  2156. SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
  2157. AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1));
  2158. //
  2159. // Check to see if there is zero padding at the end of the base relocations
  2160. //
  2161. if (AllignedRelocSize < SectionHeader->SizeOfRawData) {
  2162. //
  2163. // Check to see if the base relocations are at the end of the file
  2164. //
  2165. if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) {
  2166. //
  2167. // All the required conditions are met to strip the zero padding of the end of the base relocations section
  2168. //
  2169. Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
  2170. Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
  2171. SectionHeader->SizeOfRawData = AllignedRelocSize;
  2172. FileLength = Optional32->SizeOfImage;
  2173. DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader->SizeOfRawData - AllignedRelocSize));
  2174. }
  2175. }
  2176. }
  2177. }
  2178. }
  2179. }
  2180. } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  2181. Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
  2182. if (!KeepOptionalHeaderFlag) {
  2183. Optional64->MajorOperatingSystemVersion = 0;
  2184. Optional64->MinorOperatingSystemVersion = 0;
  2185. Optional64->MajorImageVersion = 0;
  2186. Optional64->MinorImageVersion = 0;
  2187. Optional64->MajorSubsystemVersion = 0;
  2188. Optional64->MinorSubsystemVersion = 0;
  2189. Optional64->Win32VersionValue = 0;
  2190. Optional64->CheckSum = 0;
  2191. Optional64->SizeOfStackReserve = 0;
  2192. Optional64->SizeOfStackCommit = 0;
  2193. Optional64->SizeOfHeapReserve = 0;
  2194. Optional64->SizeOfHeapCommit = 0;
  2195. }
  2196. TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint;
  2197. TEImageHeader.BaseOfCode = Optional64->BaseOfCode;
  2198. TEImageHeader.ImageBase = (UINT64) (Optional64->ImageBase);
  2199. if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
  2200. TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
  2201. TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
  2202. }
  2203. if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
  2204. TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  2205. TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
  2206. }
  2207. //
  2208. // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty
  2209. // For Itaninum and X64 Image, remove .pdata section.
  2210. //
  2211. if ((!KeepExceptionTableFlag && PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64)) {
  2212. if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION &&
  2213. Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 &&
  2214. Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) {
  2215. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
  2216. for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
  2217. if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) {
  2218. //
  2219. // Zero .pdata Section header name
  2220. //
  2221. memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name));
  2222. RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData);
  2223. for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) {
  2224. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
  2225. for (Index2 = 0; Index2 < PeHdr->Pe32.FileHeader.NumberOfSections; Index2++, SectionHeader++) {
  2226. if (RuntimeFunction->UnwindInfoAddress >= SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) {
  2227. UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress));
  2228. if (UnwindInfo->Version == 1) {
  2229. memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16));
  2230. memset (UnwindInfo, 0, sizeof (UNWIND_INFO));
  2231. }
  2232. break;
  2233. }
  2234. }
  2235. memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION));
  2236. }
  2237. //
  2238. // Zero Exception Table
  2239. //
  2240. Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0;
  2241. Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0;
  2242. DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL);
  2243. break;
  2244. }
  2245. }
  2246. }
  2247. }
  2248. //
  2249. // Strip zero padding at the end of the .reloc section
  2250. //
  2251. if (!KeepZeroPendingFlag && Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
  2252. if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) {
  2253. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
  2254. for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) {
  2255. //
  2256. // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory
  2257. //
  2258. if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) {
  2259. SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
  2260. AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1));
  2261. //
  2262. // Check to see if there is zero padding at the end of the base relocations
  2263. //
  2264. if (AllignedRelocSize < SectionHeader->SizeOfRawData) {
  2265. //
  2266. // Check to see if the base relocations are at the end of the file
  2267. //
  2268. if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) {
  2269. //
  2270. // All the required conditions are met to strip the zero padding of the end of the base relocations section
  2271. //
  2272. Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
  2273. Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize);
  2274. SectionHeader->SizeOfRawData = AllignedRelocSize;
  2275. FileLength = Optional64->SizeOfImage;
  2276. DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader->SizeOfRawData - AllignedRelocSize));
  2277. }
  2278. }
  2279. }
  2280. }
  2281. }
  2282. }
  2283. } else {
  2284. Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->Pe32.OptionalHeader.Magic, mInImageName);
  2285. goto Finish;
  2286. }
  2287. if (((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) == 0) && \
  2288. (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == 0) && \
  2289. (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0)) {
  2290. //
  2291. // PeImage can be loaded into memory, but it has no relocation section.
  2292. // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero.
  2293. //
  2294. if (Optional32 != NULL) {
  2295. TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);
  2296. } else if (Optional64 != NULL) {
  2297. TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION);
  2298. }
  2299. }
  2300. //
  2301. // Fill HII section data
  2302. //
  2303. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
  2304. for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {
  2305. if (stricmp ((char *)SectionHeader[Index].Name, ".hii") == 0) {
  2306. //
  2307. // Update resource section header offset
  2308. //
  2309. SetHiiResourceHeader ((UINT8*) FileBuffer + SectionHeader[Index].PointerToRawData, SectionHeader[Index].VirtualAddress);
  2310. //
  2311. // Update resource section name
  2312. //
  2313. strcpy((char *) SectionHeader[Index].Name, ".rsrc");
  2314. //
  2315. // Update resource data directory.
  2316. //
  2317. if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  2318. Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
  2319. Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress;
  2320. Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize;
  2321. } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  2322. Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
  2323. Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress;
  2324. Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize;
  2325. }
  2326. break;
  2327. }
  2328. }
  2329. //
  2330. // Zero ExceptionTable Xdata
  2331. //
  2332. if (!KeepExceptionTableFlag) {
  2333. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader);
  2334. for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) {
  2335. if (stricmp ((char *)SectionHeader[Index].Name, ".xdata") == 0) {
  2336. //
  2337. // zero .xdata section
  2338. //
  2339. memset (FileBuffer + SectionHeader[Index].PointerToRawData, 0, SectionHeader[Index].SizeOfRawData);
  2340. DebugMsg (NULL, 0, 9, NULL, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", (unsigned) SectionHeader[Index].PointerToRawData, (unsigned) SectionHeader[Index].SizeOfRawData);
  2341. break;
  2342. }
  2343. }
  2344. }
  2345. //
  2346. // Zero Time/Data field
  2347. //
  2348. ZeroDebugData (FileBuffer, FALSE);
  2349. if (mOutImageType == FW_TE_IMAGE) {
  2350. if ((PeHdr->Pe32.FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) {
  2351. //
  2352. // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both.
  2353. //
  2354. Error (NULL, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName);
  2355. goto Finish;
  2356. }
  2357. if ((PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment)) {
  2358. //
  2359. // TeImage has the same section alignment and file alignment.
  2360. //
  2361. Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName);
  2362. goto Finish;
  2363. }
  2364. DebugMsg (NULL, 0, 9, "TeImage Header Info", "Machine type is %X, Number of sections is %X, Stripped size is %X, EntryPoint is %X, BaseOfCode is %X, ImageBase is %llX",
  2365. TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, (unsigned) TEImageHeader.AddressOfEntryPoint, (unsigned) TEImageHeader.BaseOfCode, (unsigned long long) TEImageHeader.ImageBase);
  2366. //
  2367. // Update Image to TeImage
  2368. //
  2369. FileLength = FileLength - TEImageHeader.StrippedSize;
  2370. memmove (FileBuffer + sizeof (EFI_TE_IMAGE_HEADER), FileBuffer + TEImageHeader.StrippedSize, FileLength);
  2371. FileLength = FileLength + sizeof (EFI_TE_IMAGE_HEADER);
  2372. memcpy (FileBuffer, &TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER));
  2373. VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength));
  2374. } else {
  2375. //
  2376. // Following codes are to fix the objcopy's issue:
  2377. // objcopy in binutil 2.50.18 will set PE image's charactices to "RELOC_STRIPPED" if image has no ".reloc" section
  2378. // It cause issue for EFI image which has no ".reloc" sections.
  2379. // Following codes will be removed when objcopy in binutil fix this problem for PE image.
  2380. //
  2381. if ((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0) {
  2382. if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  2383. Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader;
  2384. if (Optional32->ImageBase == 0) {
  2385. PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED;
  2386. }
  2387. } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  2388. Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader;
  2389. if (Optional64->ImageBase == 0) {
  2390. PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED;
  2391. }
  2392. }
  2393. }
  2394. }
  2395. WriteFile:
  2396. //
  2397. // Update Image to EfiImage or TE image
  2398. //
  2399. if (ReplaceFlag) {
  2400. if ((FileLength != InputFileLength) || (memcmp (FileBuffer, InputFileBuffer, FileLength) != 0)) {
  2401. //
  2402. // Update File when File is changed.
  2403. //
  2404. fpInOut = fopen (LongFilePath (mInImageName), "wb");
  2405. if (fpInOut == NULL) {
  2406. Error (NULL, 0, 0001, "Error opening file", mInImageName);
  2407. goto Finish;
  2408. }
  2409. fwrite (FileBuffer, 1, FileLength, fpInOut);
  2410. VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
  2411. }
  2412. } else {
  2413. if ((OutputFileTime < InputFileTime) || (FileLength != OutputFileLength) || (memcmp (FileBuffer, OutputFileBuffer, FileLength) != 0)) {
  2414. //
  2415. // Update File when File is changed or File is old.
  2416. //
  2417. fpOut = fopen (LongFilePath (OutImageName), "wb");
  2418. if (fpOut == NULL) {
  2419. Error (NULL, 0, 0001, "Error opening output file", OutImageName);
  2420. goto Finish;
  2421. }
  2422. fwrite (FileBuffer, 1, FileLength, fpOut);
  2423. VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength);
  2424. }
  2425. }
  2426. mImageSize = FileLength;
  2427. Finish:
  2428. if (fpInOut != NULL) {
  2429. if (GetUtilityStatus () != STATUS_SUCCESS) {
  2430. //
  2431. // when file updates failed, original file is still recovered.
  2432. //
  2433. fwrite (InputFileBuffer, 1, InputFileLength, fpInOut);
  2434. }
  2435. //
  2436. // Write converted data into fpInOut file and close input file.
  2437. //
  2438. fclose (fpInOut);
  2439. }
  2440. if (FileBuffer != NULL) {
  2441. free (FileBuffer);
  2442. }
  2443. if (InputFileName != NULL) {
  2444. free (InputFileName);
  2445. }
  2446. if (fpOut != NULL) {
  2447. //
  2448. // Write converted data into fpOut file and close output file.
  2449. //
  2450. fclose (fpOut);
  2451. if (GetUtilityStatus () != STATUS_SUCCESS) {
  2452. if (OutputFileBuffer == NULL) {
  2453. remove (OutImageName);
  2454. } else {
  2455. fpOut = fopen (LongFilePath (OutImageName), "wb");
  2456. fwrite (OutputFileBuffer, 1, OutputFileLength, fpOut);
  2457. fclose (fpOut);
  2458. }
  2459. }
  2460. }
  2461. if (InputFileBuffer != NULL) {
  2462. free (InputFileBuffer);
  2463. }
  2464. if (OutputFileBuffer != NULL) {
  2465. free (OutputFileBuffer);
  2466. }
  2467. //
  2468. // Write module size and time stamp to report file.
  2469. //
  2470. if (OutImageName != NULL) {
  2471. FileLen = strlen (OutImageName);
  2472. }
  2473. if (FileLen >= 4 && strcmp (OutImageName + (FileLen - 4), ".efi") == 0) {
  2474. ReportFileName = (CHAR8 *) malloc (FileLen + 1);
  2475. if (ReportFileName != NULL) {
  2476. strcpy (ReportFileName, OutImageName);
  2477. strcpy (ReportFileName + (FileLen - 4), ".txt");
  2478. ReportFile = fopen (LongFilePath (ReportFileName), "w+");
  2479. if (ReportFile != NULL) {
  2480. fprintf (ReportFile, "MODULE_SIZE = %u\n", (unsigned) mImageSize);
  2481. fprintf (ReportFile, "TIME_STAMP = %u\n", (unsigned) mImageTimeStamp);
  2482. fclose(ReportFile);
  2483. }
  2484. free (ReportFileName);
  2485. }
  2486. }
  2487. VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
  2488. return GetUtilityStatus ();
  2489. }
  2490. STATIC
  2491. EFI_STATUS
  2492. ZeroDebugData (
  2493. IN OUT UINT8 *FileBuffer,
  2494. BOOLEAN ZeroDebugFlag
  2495. )
  2496. /*++
  2497. Routine Description:
  2498. Zero debug information in PeImage.
  2499. Arguments:
  2500. FileBuffer - Pointer to PeImage.
  2501. ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp
  2502. Returns:
  2503. EFI_ABORTED - PeImage is invalid.
  2504. EFI_SUCCESS - Zero debug data successfully.
  2505. --*/
  2506. {
  2507. UINT32 Index;
  2508. UINT32 DebugDirectoryEntryRva;
  2509. UINT32 DebugDirectoryEntrySize;
  2510. UINT32 DebugDirectoryEntryFileOffset;
  2511. UINT32 ExportDirectoryEntryRva;
  2512. UINT32 ExportDirectoryEntryFileOffset;
  2513. UINT32 ResourceDirectoryEntryRva;
  2514. UINT32 ResourceDirectoryEntryFileOffset;
  2515. EFI_IMAGE_DOS_HEADER *DosHdr;
  2516. EFI_IMAGE_FILE_HEADER *FileHdr;
  2517. EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr;
  2518. EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr;
  2519. EFI_IMAGE_SECTION_HEADER *SectionHeader;
  2520. EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
  2521. EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY *RsdsEntry;
  2522. UINT32 *NewTimeStamp;
  2523. //
  2524. // Init variable.
  2525. //
  2526. DebugDirectoryEntryRva = 0;
  2527. DebugDirectoryEntrySize = 0;
  2528. ExportDirectoryEntryRva = 0;
  2529. ResourceDirectoryEntryRva = 0;
  2530. DebugDirectoryEntryFileOffset = 0;
  2531. ExportDirectoryEntryFileOffset = 0;
  2532. ResourceDirectoryEntryFileOffset = 0;
  2533. DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer;
  2534. FileHdr = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
  2535. DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
  2536. if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
  2537. // NO DOS header, must start with PE/COFF header
  2538. FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));
  2539. } else {
  2540. FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
  2541. }
  2542. //
  2543. // Get Debug, Export and Resource EntryTable RVA address.
  2544. // Resource Directory entry need to review.
  2545. //
  2546. Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
  2547. Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
  2548. if (Optional32Hdr->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  2549. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader);
  2550. if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
  2551. Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
  2552. ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  2553. }
  2554. if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
  2555. Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
  2556. ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
  2557. }
  2558. if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
  2559. Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
  2560. DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  2561. DebugDirectoryEntrySize = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
  2562. if (ZeroDebugFlag) {
  2563. Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;
  2564. Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;
  2565. }
  2566. }
  2567. } else {
  2568. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader);
  2569. if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
  2570. Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
  2571. ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  2572. }
  2573. if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
  2574. Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
  2575. ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
  2576. }
  2577. if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
  2578. Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
  2579. DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  2580. DebugDirectoryEntrySize = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
  2581. if (ZeroDebugFlag) {
  2582. Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0;
  2583. Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0;
  2584. }
  2585. }
  2586. }
  2587. //
  2588. // Get DirectoryEntryTable file offset.
  2589. //
  2590. for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {
  2591. if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&
  2592. DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
  2593. DebugDirectoryEntryFileOffset =
  2594. DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
  2595. }
  2596. if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&
  2597. ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
  2598. ExportDirectoryEntryFileOffset =
  2599. ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
  2600. }
  2601. if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&
  2602. ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
  2603. ResourceDirectoryEntryFileOffset =
  2604. ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
  2605. }
  2606. }
  2607. //
  2608. //Zero Debug Data and TimeStamp
  2609. //
  2610. FileHdr->TimeDateStamp = 0;
  2611. mImageTimeStamp = 0;
  2612. if (ExportDirectoryEntryFileOffset != 0) {
  2613. NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));
  2614. *NewTimeStamp = 0;
  2615. }
  2616. if (ResourceDirectoryEntryFileOffset != 0) {
  2617. NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));
  2618. *NewTimeStamp = 0;
  2619. }
  2620. if (DebugDirectoryEntryFileOffset != 0) {
  2621. DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset);
  2622. Index = 0;
  2623. for (Index=0; Index < DebugDirectoryEntrySize / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); Index ++, DebugEntry ++) {
  2624. DebugEntry->TimeDateStamp = 0;
  2625. if (mIsConvertXip) {
  2626. DebugEntry->FileOffset = DebugEntry->RVA;
  2627. }
  2628. if (ZeroDebugFlag || DebugEntry->Type != EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
  2629. memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData);
  2630. memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
  2631. }
  2632. if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
  2633. RsdsEntry = (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY *) (FileBuffer + DebugEntry->FileOffset);
  2634. if (RsdsEntry->Signature == CODEVIEW_SIGNATURE_MTOC) {
  2635. // MTOC sets DebugDirectoryEntrySize to size of the .debug section, so fix it.
  2636. if (!ZeroDebugFlag) {
  2637. if (Optional32Hdr->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  2638. Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
  2639. } else {
  2640. Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
  2641. }
  2642. }
  2643. break;
  2644. }
  2645. }
  2646. }
  2647. }
  2648. return EFI_SUCCESS;
  2649. }
  2650. STATIC
  2651. EFI_STATUS
  2652. SetStamp (
  2653. IN OUT UINT8 *FileBuffer,
  2654. IN CHAR8 *TimeStamp
  2655. )
  2656. /*++
  2657. Routine Description:
  2658. Set new time stamp into PeImage FileHdr and Directory table:
  2659. Debug, Export and Resource.
  2660. Arguments:
  2661. FileBuffer - Pointer to PeImage.
  2662. TimeStamp - Time stamp string.
  2663. Returns:
  2664. EFI_INVALID_PARAMETER - TimeStamp format is not recognized.
  2665. EFI_SUCCESS - Set new time stamp in this image successfully.
  2666. --*/
  2667. {
  2668. struct tm stime;
  2669. struct tm *ptime;
  2670. time_t newtime;
  2671. UINT32 Index;
  2672. UINT32 DebugDirectoryEntryRva;
  2673. UINT32 DebugDirectoryEntryFileOffset;
  2674. UINT32 ExportDirectoryEntryRva;
  2675. UINT32 ExportDirectoryEntryFileOffset;
  2676. UINT32 ResourceDirectoryEntryRva;
  2677. UINT32 ResourceDirectoryEntryFileOffset;
  2678. EFI_IMAGE_DOS_HEADER *DosHdr;
  2679. EFI_IMAGE_FILE_HEADER *FileHdr;
  2680. EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr;
  2681. EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr;
  2682. EFI_IMAGE_SECTION_HEADER *SectionHeader;
  2683. UINT32 *NewTimeStamp;
  2684. //
  2685. // Init variable.
  2686. //
  2687. DebugDirectoryEntryRva = 0;
  2688. DebugDirectoryEntryFileOffset = 0;
  2689. ExportDirectoryEntryRva = 0;
  2690. ExportDirectoryEntryFileOffset = 0;
  2691. ResourceDirectoryEntryRva = 0;
  2692. ResourceDirectoryEntryFileOffset = 0;
  2693. //
  2694. // Get time and date that will be set.
  2695. //
  2696. if (TimeStamp == NULL) {
  2697. Error (NULL, 0, 3000, "Invalid", "TimeStamp cannot be NULL.");
  2698. return EFI_INVALID_PARAMETER;
  2699. }
  2700. //
  2701. // compare the value with "NOW", if yes, current system time is set.
  2702. //
  2703. if (stricmp (TimeStamp, "NOW") == 0) {
  2704. //
  2705. // get system current time and date
  2706. //
  2707. time (&newtime);
  2708. } else {
  2709. //
  2710. // Check Time Format strictly yyyy-mm-dd 00:00:00
  2711. //
  2712. for (Index = 0; TimeStamp[Index] != '\0' && Index < 20; Index ++) {
  2713. if (Index == 4 || Index == 7) {
  2714. if (TimeStamp[Index] == '-') {
  2715. continue;
  2716. }
  2717. } else if (Index == 13 || Index == 16) {
  2718. if (TimeStamp[Index] == ':') {
  2719. continue;
  2720. }
  2721. } else if (Index == 10 && TimeStamp[Index] == ' ') {
  2722. continue;
  2723. } else if ((TimeStamp[Index] < '0') || (TimeStamp[Index] > '9')) {
  2724. break;
  2725. }
  2726. }
  2727. if (Index < 19 || TimeStamp[19] != '\0') {
  2728. Error (NULL, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp);
  2729. return EFI_INVALID_PARAMETER;
  2730. }
  2731. //
  2732. // get the date and time from TimeStamp
  2733. //
  2734. if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d",
  2735. &stime.tm_year,
  2736. &stime.tm_mon,
  2737. &stime.tm_mday,
  2738. &stime.tm_hour,
  2739. &stime.tm_min,
  2740. &stime.tm_sec
  2741. ) != 6) {
  2742. Error (NULL, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp);
  2743. return EFI_INVALID_PARAMETER;
  2744. }
  2745. //
  2746. // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it
  2747. //
  2748. if (stime.tm_mon <= 0 || stime.tm_mday <=0) {
  2749. Error (NULL, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp);
  2750. return EFI_INVALID_PARAMETER;
  2751. }
  2752. stime.tm_mon -= 1;
  2753. //
  2754. // in struct, Year (current year minus 1900)
  2755. // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038
  2756. //
  2757. //
  2758. // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038)
  2759. //
  2760. if (stime.tm_year >= 1970 && stime.tm_year <= 2038) {
  2761. //
  2762. // convert 1970 -> 70, 2000 -> 100, ...
  2763. //
  2764. stime.tm_year -= 1900;
  2765. } else {
  2766. Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);
  2767. return EFI_INVALID_PARAMETER;
  2768. }
  2769. //
  2770. // convert the date and time to time_t format
  2771. //
  2772. newtime = mktime (&stime);
  2773. if (newtime == (time_t) - 1) {
  2774. Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp);
  2775. return EFI_INVALID_PARAMETER;
  2776. }
  2777. }
  2778. ptime = localtime (&newtime);
  2779. if (ptime != NULL) {
  2780. DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d",
  2781. ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec);
  2782. }
  2783. //
  2784. // Set new time and data into PeImage.
  2785. //
  2786. DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer;
  2787. if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
  2788. // NO DOS header, must start with PE/COFF header
  2789. FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32));
  2790. } else {
  2791. FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32));
  2792. }
  2793. //
  2794. // Get Debug, Export and Resource EntryTable RVA address.
  2795. // Resource Directory entry need to review.
  2796. //
  2797. if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) {
  2798. Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
  2799. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader);
  2800. if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
  2801. Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
  2802. ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  2803. }
  2804. if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
  2805. Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
  2806. ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
  2807. }
  2808. if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
  2809. Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
  2810. DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  2811. }
  2812. } else {
  2813. Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER));
  2814. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader);
  2815. if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \
  2816. Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) {
  2817. ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  2818. }
  2819. if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \
  2820. Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) {
  2821. ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress;
  2822. }
  2823. if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \
  2824. Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) {
  2825. DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  2826. }
  2827. }
  2828. //
  2829. // Get DirectoryEntryTable file offset.
  2830. //
  2831. for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) {
  2832. if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress &&
  2833. DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
  2834. DebugDirectoryEntryFileOffset =
  2835. DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
  2836. }
  2837. if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress &&
  2838. ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
  2839. ExportDirectoryEntryFileOffset =
  2840. ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
  2841. }
  2842. if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress &&
  2843. ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) {
  2844. ResourceDirectoryEntryFileOffset =
  2845. ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData;
  2846. }
  2847. }
  2848. //
  2849. // Set new stamp
  2850. //
  2851. FileHdr->TimeDateStamp = (UINT32) newtime;
  2852. mImageTimeStamp = (UINT32) newtime;
  2853. if (ExportDirectoryEntryRva != 0) {
  2854. NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32));
  2855. *NewTimeStamp = (UINT32) newtime;
  2856. }
  2857. if (ResourceDirectoryEntryRva != 0) {
  2858. NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32));
  2859. *NewTimeStamp = (UINT32) newtime;
  2860. }
  2861. if (DebugDirectoryEntryRva != 0) {
  2862. NewTimeStamp = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32));
  2863. *NewTimeStamp = (UINT32) newtime;
  2864. }
  2865. return EFI_SUCCESS;
  2866. }
  2867. STATIC
  2868. STATUS
  2869. MicrocodeReadData (
  2870. FILE *InFptr,
  2871. UINT32 *Data
  2872. )
  2873. /*++
  2874. Routine Description:
  2875. Read a 32-bit microcode data value from a text file and convert to raw binary form.
  2876. Arguments:
  2877. InFptr - file pointer to input text file
  2878. Data - pointer to where to return the data parsed
  2879. Returns:
  2880. STATUS_SUCCESS - no errors or warnings, Data contains valid information
  2881. STATUS_ERROR - errors were encountered
  2882. --*/
  2883. {
  2884. CHAR8 Line[MAX_LINE_LEN];
  2885. CHAR8 *cptr;
  2886. int ScannedData = 0;
  2887. Line[MAX_LINE_LEN - 1] = 0;
  2888. while (1) {
  2889. if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) {
  2890. return STATUS_ERROR;
  2891. }
  2892. //
  2893. // If it was a binary file, then it may have overwritten our null terminator
  2894. //
  2895. if (Line[MAX_LINE_LEN - 1] != 0) {
  2896. return STATUS_ERROR;
  2897. }
  2898. //
  2899. // strip space
  2900. //
  2901. for (cptr = Line; *cptr && isspace((int)*cptr); cptr++) {
  2902. }
  2903. // Skip Blank Lines and Comment Lines
  2904. if ((strlen(cptr) != 0) && (*cptr != ';')) {
  2905. break;
  2906. }
  2907. }
  2908. // Look for
  2909. // dd 000000001h ; comment
  2910. // dd XXXXXXXX
  2911. // DD XXXXXXXXX
  2912. // DD XXXXXXXXX
  2913. //
  2914. if ((tolower((int)cptr[0]) == 'd') && (tolower((int)cptr[1]) == 'd') && isspace ((int)cptr[2])) {
  2915. //
  2916. // Skip blanks and look for a hex digit
  2917. //
  2918. cptr += 3;
  2919. for (; *cptr && isspace((int)*cptr); cptr++) {
  2920. }
  2921. if (isxdigit ((int)*cptr)) {
  2922. if (sscanf (cptr, "%X", &ScannedData) != 1) {
  2923. return STATUS_ERROR;
  2924. }
  2925. }
  2926. *Data = (UINT32) ScannedData;
  2927. return STATUS_SUCCESS;
  2928. }
  2929. return STATUS_ERROR;
  2930. }