GenFvInternalLib.c 142 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568
  1. /** @file
  2. This file contains the internal functions required to generate a Firmware Volume.
  3. Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
  4. Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
  5. Portions Copyright (c) 2016 HP Development Company, L.P.<BR>
  6. Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
  7. Portions Copyright (c) 2022, Loongson Technology Corporation Limited. All rights reserved.<BR>
  8. SPDX-License-Identifier: BSD-2-Clause-Patent
  9. **/
  10. //
  11. // Include files
  12. //
  13. #ifdef __GNUC__
  14. #include <sys/stat.h>
  15. #endif
  16. #include <string.h>
  17. #ifndef __GNUC__
  18. #include <io.h>
  19. #endif
  20. #include <assert.h>
  21. #include <Guid/FfsSectionAlignmentPadding.h>
  22. #include "WinNtInclude.h"
  23. #include "GenFvInternalLib.h"
  24. #include "FvLib.h"
  25. #include "PeCoffLib.h"
  26. #define ARM64_UNCONDITIONAL_JUMP_INSTRUCTION 0x14000000
  27. /*
  28. * Arm instruction to jump to Fv entry instruction in Arm or Thumb mode.
  29. * From ARM Arch Ref Manual versions b/c/d, section A8.8.25 BL, BLX (immediate)
  30. * BLX (encoding A2) branches to offset in Thumb instruction set mode.
  31. * BL (encoding A1) branches to offset in Arm instruction set mode.
  32. */
  33. #define ARM_JUMP_OFFSET_MAX 0xffffff
  34. #define ARM_JUMP_TO_ARM(Offset) (0xeb000000 | ((Offset - 8) >> 2))
  35. #define _ARM_JUMP_TO_THUMB(Imm32) (0xfa000000 | \
  36. (((Imm32) & (1 << 1)) << (24 - 1)) | \
  37. (((Imm32) >> 2) & 0x7fffff))
  38. #define ARM_JUMP_TO_THUMB(Offset) _ARM_JUMP_TO_THUMB((Offset) - 8)
  39. /*
  40. * Arm instruction to return from exception (MOVS PC, LR)
  41. */
  42. #define ARM_RETURN_FROM_EXCEPTION 0xE1B0F07E
  43. BOOLEAN mArm = FALSE;
  44. BOOLEAN mRiscV = FALSE;
  45. BOOLEAN mLoongArch = FALSE;
  46. STATIC UINT32 MaxFfsAlignment = 0;
  47. BOOLEAN VtfFileFlag = FALSE;
  48. EFI_GUID mEfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID;
  49. EFI_GUID mFileGuidArray [MAX_NUMBER_OF_FILES_IN_FV];
  50. EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
  51. EFI_GUID mDefaultCapsuleGuid = {0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }};
  52. EFI_GUID mEfiFfsSectionAlignmentPaddingGuid = EFI_FFS_SECTION_ALIGNMENT_PADDING_GUID;
  53. CHAR8 *mFvbAttributeName[] = {
  54. EFI_FVB2_READ_DISABLED_CAP_STRING,
  55. EFI_FVB2_READ_ENABLED_CAP_STRING,
  56. EFI_FVB2_READ_STATUS_STRING,
  57. EFI_FVB2_WRITE_DISABLED_CAP_STRING,
  58. EFI_FVB2_WRITE_ENABLED_CAP_STRING,
  59. EFI_FVB2_WRITE_STATUS_STRING,
  60. EFI_FVB2_LOCK_CAP_STRING,
  61. EFI_FVB2_LOCK_STATUS_STRING,
  62. NULL,
  63. EFI_FVB2_STICKY_WRITE_STRING,
  64. EFI_FVB2_MEMORY_MAPPED_STRING,
  65. EFI_FVB2_ERASE_POLARITY_STRING,
  66. EFI_FVB2_READ_LOCK_CAP_STRING,
  67. EFI_FVB2_READ_LOCK_STATUS_STRING,
  68. EFI_FVB2_WRITE_LOCK_CAP_STRING,
  69. EFI_FVB2_WRITE_LOCK_STATUS_STRING
  70. };
  71. CHAR8 *mFvbAlignmentName[] = {
  72. EFI_FVB2_ALIGNMENT_1_STRING,
  73. EFI_FVB2_ALIGNMENT_2_STRING,
  74. EFI_FVB2_ALIGNMENT_4_STRING,
  75. EFI_FVB2_ALIGNMENT_8_STRING,
  76. EFI_FVB2_ALIGNMENT_16_STRING,
  77. EFI_FVB2_ALIGNMENT_32_STRING,
  78. EFI_FVB2_ALIGNMENT_64_STRING,
  79. EFI_FVB2_ALIGNMENT_128_STRING,
  80. EFI_FVB2_ALIGNMENT_256_STRING,
  81. EFI_FVB2_ALIGNMENT_512_STRING,
  82. EFI_FVB2_ALIGNMENT_1K_STRING,
  83. EFI_FVB2_ALIGNMENT_2K_STRING,
  84. EFI_FVB2_ALIGNMENT_4K_STRING,
  85. EFI_FVB2_ALIGNMENT_8K_STRING,
  86. EFI_FVB2_ALIGNMENT_16K_STRING,
  87. EFI_FVB2_ALIGNMENT_32K_STRING,
  88. EFI_FVB2_ALIGNMENT_64K_STRING,
  89. EFI_FVB2_ALIGNMENT_128K_STRING,
  90. EFI_FVB2_ALIGNMENT_256K_STRING,
  91. EFI_FVB2_ALIGNMENT_512K_STRING,
  92. EFI_FVB2_ALIGNMENT_1M_STRING,
  93. EFI_FVB2_ALIGNMENT_2M_STRING,
  94. EFI_FVB2_ALIGNMENT_4M_STRING,
  95. EFI_FVB2_ALIGNMENT_8M_STRING,
  96. EFI_FVB2_ALIGNMENT_16M_STRING,
  97. EFI_FVB2_ALIGNMENT_32M_STRING,
  98. EFI_FVB2_ALIGNMENT_64M_STRING,
  99. EFI_FVB2_ALIGNMENT_128M_STRING,
  100. EFI_FVB2_ALIGNMENT_256M_STRING,
  101. EFI_FVB2_ALIGNMENT_512M_STRING,
  102. EFI_FVB2_ALIGNMENT_1G_STRING,
  103. EFI_FVB2_ALIGNMENT_2G_STRING
  104. };
  105. //
  106. // This data array will be located at the base of the Firmware Volume Header (FVH)
  107. // in the boot block. It must not exceed 14 bytes of code. The last 2 bytes
  108. // will be used to keep the FVH checksum consistent.
  109. // This code will be run in response to a startup IPI for HT-enabled systems.
  110. //
  111. #define SIZEOF_STARTUP_DATA_ARRAY 0x10
  112. UINT8 m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
  113. //
  114. // EA D0 FF 00 F0 ; far jmp F000:FFD0
  115. // 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
  116. // 0, 0 ; Checksum Padding
  117. //
  118. 0xEA,
  119. 0xD0,
  120. 0xFF,
  121. 0x0,
  122. 0xF0,
  123. 0x00,
  124. 0x00,
  125. 0x00,
  126. 0x00,
  127. 0x00,
  128. 0x00,
  129. 0x00,
  130. 0x00,
  131. 0x00,
  132. 0x00,
  133. 0x00
  134. };
  135. UINT8 m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = {
  136. //
  137. // EB CE ; jmp short ($-0x30)
  138. // ; (from offset 0x0 to offset 0xFFD0)
  139. // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes
  140. // 0, 0 ; Checksum Padding
  141. //
  142. 0xEB,
  143. 0xCE,
  144. 0x00,
  145. 0x00,
  146. 0x00,
  147. 0x00,
  148. 0x00,
  149. 0x00,
  150. 0x00,
  151. 0x00,
  152. 0x00,
  153. 0x00,
  154. 0x00,
  155. 0x00,
  156. 0x00,
  157. 0x00
  158. };
  159. FV_INFO mFvDataInfo;
  160. CAP_INFO mCapDataInfo;
  161. BOOLEAN mIsLargeFfs = FALSE;
  162. EFI_PHYSICAL_ADDRESS mFvBaseAddress[0x10];
  163. UINT32 mFvBaseAddressNumber = 0;
  164. EFI_STATUS
  165. ParseFvInf (
  166. IN MEMORY_FILE *InfFile,
  167. OUT FV_INFO *FvInfo
  168. )
  169. /*++
  170. Routine Description:
  171. This function parses a FV.INF file and copies info into a FV_INFO structure.
  172. Arguments:
  173. InfFile Memory file image.
  174. FvInfo Information read from INF file.
  175. Returns:
  176. EFI_SUCCESS INF file information successfully retrieved.
  177. EFI_ABORTED INF file has an invalid format.
  178. EFI_NOT_FOUND A required string was not found in the INF file.
  179. --*/
  180. {
  181. CHAR8 Value[MAX_LONG_FILE_PATH];
  182. UINT64 Value64;
  183. UINTN Index;
  184. UINTN Number;
  185. EFI_STATUS Status;
  186. EFI_GUID GuidValue;
  187. //
  188. // Read the FV base address
  189. //
  190. if (!mFvDataInfo.BaseAddressSet) {
  191. Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_BASE_ADDRESS_STRING, 0, Value);
  192. if (Status == EFI_SUCCESS) {
  193. //
  194. // Get the base address
  195. //
  196. Status = AsciiStringToUint64 (Value, FALSE, &Value64);
  197. if (EFI_ERROR (Status)) {
  198. Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_BASE_ADDRESS_STRING, Value);
  199. return EFI_ABORTED;
  200. }
  201. DebugMsg (NULL, 0, 9, "rebase address", "%s = %s", EFI_FV_BASE_ADDRESS_STRING, Value);
  202. FvInfo->BaseAddress = Value64;
  203. FvInfo->BaseAddressSet = TRUE;
  204. }
  205. }
  206. //
  207. // Read the FV File System Guid
  208. //
  209. if (!FvInfo->FvFileSystemGuidSet) {
  210. Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILESYSTEMGUID_STRING, 0, Value);
  211. if (Status == EFI_SUCCESS) {
  212. //
  213. // Get the guid value
  214. //
  215. Status = StringToGuid (Value, &GuidValue);
  216. if (EFI_ERROR (Status)) {
  217. Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_FILESYSTEMGUID_STRING, Value);
  218. return EFI_ABORTED;
  219. }
  220. memcpy (&FvInfo->FvFileSystemGuid, &GuidValue, sizeof (EFI_GUID));
  221. FvInfo->FvFileSystemGuidSet = TRUE;
  222. }
  223. }
  224. //
  225. // Read the FV Extension Header File Name
  226. //
  227. Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FV_EXT_HEADER_FILE_NAME, 0, Value);
  228. if (Status == EFI_SUCCESS) {
  229. strcpy (FvInfo->FvExtHeaderFile, Value);
  230. }
  231. //
  232. // Read the FV file name
  233. //
  234. Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILE_NAME_STRING, 0, Value);
  235. if (Status == EFI_SUCCESS) {
  236. //
  237. // copy the file name
  238. //
  239. strcpy (FvInfo->FvName, Value);
  240. }
  241. //
  242. // Read Fv Attribute
  243. //
  244. for (Index = 0; Index < sizeof (mFvbAttributeName)/sizeof (CHAR8 *); Index ++) {
  245. if ((mFvbAttributeName [Index] != NULL) && \
  246. (FindToken (InfFile, ATTRIBUTES_SECTION_STRING, mFvbAttributeName [Index], 0, Value) == EFI_SUCCESS)) {
  247. if ((strcmp (Value, TRUE_STRING) == 0) || (strcmp (Value, ONE_STRING) == 0)) {
  248. FvInfo->FvAttributes |= 1 << Index;
  249. } else if ((strcmp (Value, FALSE_STRING) != 0) && (strcmp (Value, ZERO_STRING) != 0)) {
  250. Error (NULL, 0, 2000, "Invalid parameter", "%s expected %s | %s", mFvbAttributeName [Index], TRUE_STRING, FALSE_STRING);
  251. return EFI_ABORTED;
  252. }
  253. }
  254. }
  255. //
  256. // Read Fv Alignment
  257. //
  258. for (Index = 0; Index < sizeof (mFvbAlignmentName)/sizeof (CHAR8 *); Index ++) {
  259. if (FindToken (InfFile, ATTRIBUTES_SECTION_STRING, mFvbAlignmentName [Index], 0, Value) == EFI_SUCCESS) {
  260. if (strcmp (Value, TRUE_STRING) == 0) {
  261. FvInfo->FvAttributes |= Index << 16;
  262. DebugMsg (NULL, 0, 9, "FV file alignment", "Align = %s", mFvbAlignmentName [Index]);
  263. break;
  264. }
  265. }
  266. }
  267. //
  268. // Read weak alignment flag
  269. //
  270. Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FV_WEAK_ALIGNMENT_STRING, 0, Value);
  271. if (Status == EFI_SUCCESS) {
  272. if ((strcmp (Value, TRUE_STRING) == 0) || (strcmp (Value, ONE_STRING) == 0)) {
  273. FvInfo->FvAttributes |= EFI_FVB2_WEAK_ALIGNMENT;
  274. } else if ((strcmp (Value, FALSE_STRING) != 0) && (strcmp (Value, ZERO_STRING) != 0)) {
  275. Error (NULL, 0, 2000, "Invalid parameter", "Weak alignment value expected one of TRUE, FALSE, 1 or 0.");
  276. return EFI_ABORTED;
  277. }
  278. }
  279. //
  280. // Read block maps
  281. //
  282. for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) {
  283. if (FvInfo->FvBlocks[Index].Length == 0) {
  284. //
  285. // Read block size
  286. //
  287. Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value);
  288. if (Status == EFI_SUCCESS) {
  289. //
  290. // Update the size of block
  291. //
  292. Status = AsciiStringToUint64 (Value, FALSE, &Value64);
  293. if (EFI_ERROR (Status)) {
  294. Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_BLOCK_SIZE_STRING, Value);
  295. return EFI_ABORTED;
  296. }
  297. FvInfo->FvBlocks[Index].Length = (UINT32) Value64;
  298. DebugMsg (NULL, 0, 9, "FV Block Size", "%s = %s", EFI_BLOCK_SIZE_STRING, Value);
  299. } else {
  300. //
  301. // If there is no blocks size, but there is the number of block, then we have a mismatched pair
  302. // and should return an error.
  303. //
  304. Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value);
  305. if (!EFI_ERROR (Status)) {
  306. Error (NULL, 0, 2000, "Invalid parameter", "both %s and %s must be specified.", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING);
  307. return EFI_ABORTED;
  308. } else {
  309. //
  310. // We are done
  311. //
  312. break;
  313. }
  314. }
  315. //
  316. // Read blocks number
  317. //
  318. Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value);
  319. if (Status == EFI_SUCCESS) {
  320. //
  321. // Update the number of blocks
  322. //
  323. Status = AsciiStringToUint64 (Value, FALSE, &Value64);
  324. if (EFI_ERROR (Status)) {
  325. Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_NUM_BLOCKS_STRING, Value);
  326. return EFI_ABORTED;
  327. }
  328. FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64;
  329. DebugMsg (NULL, 0, 9, "FV Block Number", "%s = %s", EFI_NUM_BLOCKS_STRING, Value);
  330. }
  331. }
  332. }
  333. if (Index == 0) {
  334. Error (NULL, 0, 2001, "Missing required argument", "block size.");
  335. return EFI_ABORTED;
  336. }
  337. //
  338. // Read files
  339. //
  340. Number = 0;
  341. for (Number = 0; Number < MAX_NUMBER_OF_FILES_IN_FV; Number ++) {
  342. if (FvInfo->FvFiles[Number][0] == '\0') {
  343. break;
  344. }
  345. }
  346. for (Index = 0; Number + Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) {
  347. //
  348. // Read the FFS file list
  349. //
  350. Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value);
  351. if (Status == EFI_SUCCESS) {
  352. //
  353. // Add the file
  354. //
  355. strcpy (FvInfo->FvFiles[Number + Index], Value);
  356. DebugMsg (NULL, 0, 9, "FV component file", "the %uth name is %s", (unsigned) Index, Value);
  357. } else {
  358. break;
  359. }
  360. }
  361. if ((Index + Number) == 0) {
  362. Warning (NULL, 0, 0, "FV components are not specified.", NULL);
  363. }
  364. return EFI_SUCCESS;
  365. }
  366. VOID
  367. UpdateFfsFileState (
  368. IN EFI_FFS_FILE_HEADER *FfsFile,
  369. IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader
  370. )
  371. /*++
  372. Routine Description:
  373. This function changes the FFS file attributes based on the erase polarity
  374. of the FV. Update the reserved bits of State to EFI_FVB2_ERASE_POLARITY.
  375. Arguments:
  376. FfsFile File header.
  377. FvHeader FV header.
  378. Returns:
  379. None
  380. --*/
  381. {
  382. if (FvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {
  383. FfsFile->State = (UINT8)~(FfsFile->State);
  384. // FfsFile->State |= ~(UINT8) EFI_FILE_ALL_STATE_BITS;
  385. }
  386. }
  387. EFI_STATUS
  388. ReadFfsAlignment (
  389. IN EFI_FFS_FILE_HEADER *FfsFile,
  390. IN OUT UINT32 *Alignment
  391. )
  392. /*++
  393. Routine Description:
  394. This function determines the alignment of the FFS input file from the file
  395. attributes.
  396. Arguments:
  397. FfsFile FFS file to parse
  398. Alignment The minimum required alignment offset of the FFS file
  399. Returns:
  400. EFI_SUCCESS The function completed successfully.
  401. EFI_INVALID_PARAMETER One of the input parameters was invalid.
  402. EFI_ABORTED An error occurred.
  403. --*/
  404. {
  405. //
  406. // Verify input parameters.
  407. //
  408. if (FfsFile == NULL || Alignment == NULL) {
  409. return EFI_INVALID_PARAMETER;
  410. }
  411. switch ((FfsFile->Attributes >> 3) & 0x07) {
  412. case 0:
  413. //
  414. // 1 byte alignment
  415. //if bit 1 have set, 128K byte alignment
  416. //
  417. if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
  418. *Alignment = 17;
  419. } else {
  420. *Alignment = 0;
  421. }
  422. break;
  423. case 1:
  424. //
  425. // 16 byte alignment
  426. //if bit 1 have set, 256K byte alignment
  427. //
  428. if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
  429. *Alignment = 18;
  430. } else {
  431. *Alignment = 4;
  432. }
  433. break;
  434. case 2:
  435. //
  436. // 128 byte alignment
  437. //if bit 1 have set, 512K byte alignment
  438. //
  439. if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
  440. *Alignment = 19;
  441. } else {
  442. *Alignment = 7;
  443. }
  444. break;
  445. case 3:
  446. //
  447. // 512 byte alignment
  448. //if bit 1 have set, 1M byte alignment
  449. //
  450. if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
  451. *Alignment = 20;
  452. } else {
  453. *Alignment = 9;
  454. }
  455. break;
  456. case 4:
  457. //
  458. // 1K byte alignment
  459. //if bit 1 have set, 2M byte alignment
  460. //
  461. if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
  462. *Alignment = 21;
  463. } else {
  464. *Alignment = 10;
  465. }
  466. break;
  467. case 5:
  468. //
  469. // 4K byte alignment
  470. //if bit 1 have set, 4M byte alignment
  471. //
  472. if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
  473. *Alignment = 22;
  474. } else {
  475. *Alignment = 12;
  476. }
  477. break;
  478. case 6:
  479. //
  480. // 32K byte alignment
  481. //if bit 1 have set , 8M byte alignment
  482. //
  483. if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
  484. *Alignment = 23;
  485. } else {
  486. *Alignment = 15;
  487. }
  488. break;
  489. case 7:
  490. //
  491. // 64K byte alignment
  492. //if bit 1 have set, 16M alignment
  493. //
  494. if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) {
  495. *Alignment = 24;
  496. } else {
  497. *Alignment = 16;
  498. }
  499. break;
  500. default:
  501. break;
  502. }
  503. return EFI_SUCCESS;
  504. }
  505. EFI_STATUS
  506. AddPadFile (
  507. IN OUT MEMORY_FILE *FvImage,
  508. IN UINT32 DataAlignment,
  509. IN VOID *FvEnd,
  510. IN EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHeader,
  511. IN UINT32 NextFfsSize
  512. )
  513. /*++
  514. Routine Description:
  515. This function adds a pad file to the FV image if it required to align the
  516. data of the next file.
  517. Arguments:
  518. FvImage The memory image of the FV to add it to.
  519. The current offset must be valid.
  520. DataAlignment The data alignment of the next FFS file.
  521. FvEnd End of the empty data in FvImage.
  522. ExtHeader PI FvExtHeader Optional
  523. Returns:
  524. EFI_SUCCESS The function completed successfully.
  525. EFI_INVALID_PARAMETER One of the input parameters was invalid.
  526. EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete
  527. the pad file add.
  528. --*/
  529. {
  530. EFI_FFS_FILE_HEADER *PadFile;
  531. UINTN PadFileSize;
  532. UINT32 NextFfsHeaderSize;
  533. UINT32 CurFfsHeaderSize;
  534. UINT32 Index;
  535. Index = 0;
  536. CurFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER);
  537. //
  538. // Verify input parameters.
  539. //
  540. if (FvImage == NULL) {
  541. return EFI_INVALID_PARAMETER;
  542. }
  543. //
  544. // Calculate the pad file size
  545. //
  546. //
  547. // Append extension header size
  548. //
  549. if (ExtHeader != NULL) {
  550. PadFileSize = ExtHeader->ExtHeaderSize;
  551. if (PadFileSize + sizeof (EFI_FFS_FILE_HEADER) >= MAX_FFS_SIZE) {
  552. CurFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER2);
  553. }
  554. PadFileSize += CurFfsHeaderSize;
  555. } else {
  556. NextFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER);
  557. if (NextFfsSize >= MAX_FFS_SIZE) {
  558. NextFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER2);
  559. }
  560. //
  561. // Check if a pad file is necessary
  562. //
  563. if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + NextFfsHeaderSize) % DataAlignment == 0) {
  564. return EFI_SUCCESS;
  565. }
  566. PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER) + NextFfsHeaderSize;
  567. //
  568. // Add whatever it takes to get to the next aligned address
  569. //
  570. while ((PadFileSize % DataAlignment) != 0) {
  571. PadFileSize++;
  572. }
  573. //
  574. // Subtract the next file header size
  575. //
  576. PadFileSize -= NextFfsHeaderSize;
  577. //
  578. // Subtract the starting offset to get size
  579. //
  580. PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage;
  581. }
  582. //
  583. // Verify that we have enough space for the file header
  584. //
  585. if (((UINTN) FvImage->CurrentFilePointer + PadFileSize) > (UINTN) FvEnd) {
  586. return EFI_OUT_OF_RESOURCES;
  587. }
  588. //
  589. // Write pad file header
  590. //
  591. PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
  592. //
  593. // Write PadFile FFS header with PadType, don't need to set PAD file guid in its header.
  594. //
  595. PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;
  596. PadFile->Attributes = 0;
  597. //
  598. // Write pad file size (calculated size minus next file header size)
  599. //
  600. if (PadFileSize >= MAX_FFS_SIZE) {
  601. memset(PadFile->Size, 0, sizeof(UINT8) * 3);
  602. ((EFI_FFS_FILE_HEADER2 *)PadFile)->ExtendedSize = PadFileSize;
  603. PadFile->Attributes |= FFS_ATTRIB_LARGE_FILE;
  604. } else {
  605. PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF);
  606. PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF);
  607. PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF);
  608. }
  609. //
  610. // Fill in checksums and state, they must be 0 for checksumming.
  611. //
  612. PadFile->IntegrityCheck.Checksum.Header = 0;
  613. PadFile->IntegrityCheck.Checksum.File = 0;
  614. PadFile->State = 0;
  615. PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, CurFfsHeaderSize);
  616. PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
  617. PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
  618. UpdateFfsFileState (
  619. (EFI_FFS_FILE_HEADER *) PadFile,
  620. (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
  621. );
  622. //
  623. // Update the current FV pointer
  624. //
  625. FvImage->CurrentFilePointer += PadFileSize;
  626. if (ExtHeader != NULL) {
  627. //
  628. // Copy Fv Extension Header and Set Fv Extension header offset
  629. //
  630. if (ExtHeader->ExtHeaderSize > sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER)) {
  631. for (Index = sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER); Index < ExtHeader->ExtHeaderSize;) {
  632. if (((EFI_FIRMWARE_VOLUME_EXT_ENTRY *)((UINT8 *)ExtHeader + Index))-> ExtEntryType == EFI_FV_EXT_TYPE_USED_SIZE_TYPE) {
  633. if (VtfFileFlag) {
  634. ((EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *)((UINT8 *)ExtHeader + Index))->UsedSize = mFvTotalSize;
  635. } else {
  636. ((EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *)((UINT8 *)ExtHeader + Index))->UsedSize = mFvTakenSize;
  637. }
  638. break;
  639. }
  640. Index += ((EFI_FIRMWARE_VOLUME_EXT_ENTRY *)((UINT8 *)ExtHeader + Index))-> ExtEntrySize;
  641. }
  642. }
  643. memcpy ((UINT8 *)PadFile + CurFfsHeaderSize, ExtHeader, ExtHeader->ExtHeaderSize);
  644. ((EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage)->ExtHeaderOffset = (UINT16) ((UINTN) ((UINT8 *)PadFile + CurFfsHeaderSize) - (UINTN) FvImage->FileImage);
  645. //
  646. // Make next file start at QWord Boundary
  647. //
  648. while (((UINTN) FvImage->CurrentFilePointer & (EFI_FFS_FILE_HEADER_ALIGNMENT - 1)) != 0) {
  649. FvImage->CurrentFilePointer++;
  650. }
  651. }
  652. return EFI_SUCCESS;
  653. }
  654. BOOLEAN
  655. IsVtfFile (
  656. IN EFI_FFS_FILE_HEADER *FileBuffer
  657. )
  658. /*++
  659. Routine Description:
  660. This function checks the header to validate if it is a VTF file
  661. Arguments:
  662. FileBuffer Buffer in which content of a file has been read.
  663. Returns:
  664. TRUE If this is a VTF file
  665. FALSE If this is not a VTF file
  666. --*/
  667. {
  668. if (!memcmp (&FileBuffer->Name, &mEfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID))) {
  669. return TRUE;
  670. } else {
  671. return FALSE;
  672. }
  673. }
  674. EFI_STATUS
  675. WriteMapFile (
  676. IN OUT FILE *FvMapFile,
  677. IN CHAR8 *FileName,
  678. IN EFI_FFS_FILE_HEADER *FfsFile,
  679. IN EFI_PHYSICAL_ADDRESS ImageBaseAddress,
  680. IN PE_COFF_LOADER_IMAGE_CONTEXT *pImageContext
  681. )
  682. /*++
  683. Routine Description:
  684. This function gets the basic debug information (entrypoint, baseaddress, .text, .data section base address)
  685. from PE/COFF image and abstracts Pe Map file information and add them into FvMap file for Debug.
  686. Arguments:
  687. FvMapFile A pointer to FvMap File
  688. FileName Ffs File PathName
  689. FfsFile A pointer to Ffs file image.
  690. ImageBaseAddress PeImage Base Address.
  691. pImageContext Image Context Information.
  692. Returns:
  693. EFI_SUCCESS Added required map information.
  694. --*/
  695. {
  696. CHAR8 PeMapFileName [MAX_LONG_FILE_PATH];
  697. CHAR8 *Cptr, *Cptr2;
  698. CHAR8 FileGuidName [MAX_LINE_LEN];
  699. FILE *PeMapFile;
  700. CHAR8 Line [MAX_LINE_LEN];
  701. CHAR8 KeyWord [MAX_LINE_LEN];
  702. CHAR8 KeyWord2 [MAX_LINE_LEN];
  703. CHAR8 FunctionName [MAX_LINE_LEN];
  704. EFI_PHYSICAL_ADDRESS FunctionAddress;
  705. UINT32 FunctionType;
  706. CHAR8 FunctionTypeName [MAX_LINE_LEN];
  707. UINT32 Index;
  708. UINT32 AddressOfEntryPoint;
  709. UINT32 Offset;
  710. EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
  711. EFI_TE_IMAGE_HEADER *TEImageHeader;
  712. EFI_IMAGE_SECTION_HEADER *SectionHeader;
  713. long long TempLongAddress;
  714. UINT32 TextVirtualAddress;
  715. UINT32 DataVirtualAddress;
  716. EFI_PHYSICAL_ADDRESS LinkTimeBaseAddress;
  717. BOOLEAN IsUseClang;
  718. //
  719. // Init local variable
  720. //
  721. FunctionType = 0;
  722. //
  723. // Print FileGuid to string buffer.
  724. //
  725. PrintGuidToBuffer (&FfsFile->Name, (UINT8 *)FileGuidName, MAX_LINE_LEN, TRUE);
  726. //
  727. // Construct Map file Name
  728. //
  729. if (strlen (FileName) >= MAX_LONG_FILE_PATH) {
  730. return EFI_ABORTED;
  731. }
  732. strncpy (PeMapFileName, FileName, MAX_LONG_FILE_PATH - 1);
  733. PeMapFileName[MAX_LONG_FILE_PATH - 1] = 0;
  734. //
  735. // Change '\\' to '/', unified path format.
  736. //
  737. Cptr = PeMapFileName;
  738. while (*Cptr != '\0') {
  739. if (*Cptr == '\\') {
  740. *Cptr = FILE_SEP_CHAR;
  741. }
  742. Cptr ++;
  743. }
  744. //
  745. // Get Map file
  746. //
  747. Cptr = PeMapFileName + strlen (PeMapFileName);
  748. while ((*Cptr != '.') && (Cptr >= PeMapFileName)) {
  749. Cptr --;
  750. }
  751. if (Cptr < PeMapFileName) {
  752. return EFI_NOT_FOUND;
  753. } else {
  754. *(Cptr + 1) = 'm';
  755. *(Cptr + 2) = 'a';
  756. *(Cptr + 3) = 'p';
  757. *(Cptr + 4) = '\0';
  758. }
  759. //
  760. // Get module Name
  761. //
  762. Cptr2 = Cptr;
  763. while ((*Cptr != FILE_SEP_CHAR) && (Cptr >= PeMapFileName)) {
  764. Cptr --;
  765. }
  766. *Cptr2 = '\0';
  767. if (strlen (Cptr + 1) >= MAX_LINE_LEN) {
  768. return EFI_ABORTED;
  769. }
  770. strncpy (KeyWord, Cptr + 1, MAX_LINE_LEN - 1);
  771. KeyWord[MAX_LINE_LEN - 1] = 0;
  772. *Cptr2 = '.';
  773. //
  774. // AddressOfEntryPoint and Offset in Image
  775. //
  776. if (!pImageContext->IsTeImage) {
  777. ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) pImageContext->Handle + pImageContext->PeCoffHeaderOffset);
  778. AddressOfEntryPoint = ImgHdr->Pe32.OptionalHeader.AddressOfEntryPoint;
  779. Offset = 0;
  780. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
  781. (UINT8 *) ImgHdr +
  782. sizeof (UINT32) +
  783. sizeof (EFI_IMAGE_FILE_HEADER) +
  784. ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
  785. );
  786. Index = ImgHdr->Pe32.FileHeader.NumberOfSections;
  787. } else {
  788. TEImageHeader = (EFI_TE_IMAGE_HEADER *) pImageContext->Handle;
  789. AddressOfEntryPoint = TEImageHeader->AddressOfEntryPoint;
  790. Offset = TEImageHeader->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
  791. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1);
  792. Index = TEImageHeader->NumberOfSections;
  793. }
  794. //
  795. // module information output
  796. //
  797. if (ImageBaseAddress == 0) {
  798. fprintf (FvMapFile, "%s (dummy) (", KeyWord);
  799. fprintf (FvMapFile, "BaseAddress=%010llx, ", (unsigned long long) ImageBaseAddress);
  800. } else {
  801. fprintf (FvMapFile, "%s (Fixed Flash Address, ", KeyWord);
  802. fprintf (FvMapFile, "BaseAddress=0x%010llx, ", (unsigned long long) (ImageBaseAddress + Offset));
  803. }
  804. fprintf (FvMapFile, "EntryPoint=0x%010llx, ", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint));
  805. if (!pImageContext->IsTeImage) {
  806. fprintf (FvMapFile, "Type=PE");
  807. } else {
  808. fprintf (FvMapFile, "Type=TE");
  809. }
  810. fprintf (FvMapFile, ")\n");
  811. fprintf (FvMapFile, "(GUID=%s", FileGuidName);
  812. TextVirtualAddress = 0;
  813. DataVirtualAddress = 0;
  814. for (; Index > 0; Index --, SectionHeader ++) {
  815. if (stricmp ((CHAR8 *)SectionHeader->Name, ".text") == 0) {
  816. TextVirtualAddress = SectionHeader->VirtualAddress;
  817. } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".data") == 0) {
  818. DataVirtualAddress = SectionHeader->VirtualAddress;
  819. } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".sdata") == 0) {
  820. DataVirtualAddress = SectionHeader->VirtualAddress;
  821. }
  822. }
  823. fprintf (FvMapFile, " .textbaseaddress=0x%010llx", (unsigned long long) (ImageBaseAddress + TextVirtualAddress));
  824. fprintf (FvMapFile, " .databaseaddress=0x%010llx", (unsigned long long) (ImageBaseAddress + DataVirtualAddress));
  825. fprintf (FvMapFile, ")\n\n");
  826. //
  827. // Open PeMapFile
  828. //
  829. PeMapFile = fopen (LongFilePath (PeMapFileName), "r");
  830. if (PeMapFile == NULL) {
  831. // fprintf (stdout, "can't open %s file to reading\n", PeMapFileName);
  832. return EFI_ABORTED;
  833. }
  834. VerboseMsg ("The map file is %s", PeMapFileName);
  835. //
  836. // Output Functions information into Fv Map file
  837. //
  838. LinkTimeBaseAddress = 0;
  839. IsUseClang = FALSE;
  840. while (fgets (Line, MAX_LINE_LEN, PeMapFile) != NULL) {
  841. //
  842. // Skip blank line
  843. //
  844. if (Line[0] == 0x0a) {
  845. FunctionType = 0;
  846. continue;
  847. }
  848. //
  849. // By Address and Static keyword
  850. //
  851. if (FunctionType == 0) {
  852. sscanf (Line, "%s", KeyWord);
  853. if (stricmp (KeyWord, "Address") == 0) {
  854. sscanf (Line, "%s %s", KeyWord, KeyWord2);
  855. if (stricmp (KeyWord2, "Size") == 0) {
  856. IsUseClang = TRUE;
  857. FunctionType = 1;
  858. continue;
  859. }
  860. //
  861. // function list
  862. //
  863. FunctionType = 1;
  864. fgets (Line, MAX_LINE_LEN, PeMapFile);
  865. } else if (stricmp (KeyWord, "Static") == 0) {
  866. //
  867. // static function list
  868. //
  869. FunctionType = 2;
  870. fgets (Line, MAX_LINE_LEN, PeMapFile);
  871. } else if (stricmp (KeyWord, "Preferred") ==0) {
  872. sscanf (Line + strlen (" Preferred load address is"), "%llx", &TempLongAddress);
  873. LinkTimeBaseAddress = (UINT64) TempLongAddress;
  874. }
  875. continue;
  876. }
  877. //
  878. // Printf Function Information
  879. //
  880. if (FunctionType == 1) {
  881. if (IsUseClang) {
  882. sscanf (Line, "%llx %s %s %s", &TempLongAddress, KeyWord, KeyWord2, FunctionTypeName);
  883. FunctionAddress = (UINT64) TempLongAddress;
  884. if (FunctionTypeName [0] != '/' && FunctionTypeName [0] != '.' && FunctionTypeName [1] != ':') {
  885. fprintf (FvMapFile, " 0x%010llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress));
  886. fprintf (FvMapFile, "%s\n", FunctionTypeName);
  887. }
  888. } else {
  889. sscanf (Line, "%s %s %llx %s", KeyWord, FunctionName, &TempLongAddress, FunctionTypeName);
  890. FunctionAddress = (UINT64) TempLongAddress;
  891. if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) {
  892. fprintf (FvMapFile, " 0x%010llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress));
  893. fprintf (FvMapFile, "%s\n", FunctionName);
  894. }
  895. }
  896. } else if (FunctionType == 2) {
  897. sscanf (Line, "%s %s %llx %s", KeyWord, FunctionName, &TempLongAddress, FunctionTypeName);
  898. FunctionAddress = (UINT64) TempLongAddress;
  899. if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) {
  900. fprintf (FvMapFile, " 0x%010llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress));
  901. fprintf (FvMapFile, "%s\n", FunctionName);
  902. }
  903. }
  904. }
  905. //
  906. // Close PeMap file
  907. //
  908. fprintf (FvMapFile, "\n\n");
  909. fclose (PeMapFile);
  910. return EFI_SUCCESS;
  911. }
  912. STATIC
  913. BOOLEAN
  914. AdjustInternalFfsPadding (
  915. IN OUT EFI_FFS_FILE_HEADER *FfsFile,
  916. IN OUT MEMORY_FILE *FvImage,
  917. IN UINTN Alignment,
  918. IN OUT UINTN *FileSize
  919. )
  920. /*++
  921. Routine Description:
  922. This function looks for a dedicated alignment padding section in the FFS, and
  923. shrinks it to the size required to line up subsequent sections correctly.
  924. Arguments:
  925. FfsFile A pointer to Ffs file image.
  926. FvImage The memory image of the FV to adjust it to.
  927. Alignment Current file alignment
  928. FileSize Reference to a variable holding the size of the FFS file
  929. Returns:
  930. TRUE Padding section was found and updated successfully
  931. FALSE Otherwise
  932. --*/
  933. {
  934. EFI_FILE_SECTION_POINTER PadSection;
  935. UINT8 *Remainder;
  936. EFI_STATUS Status;
  937. UINT32 FfsHeaderLength;
  938. UINT32 FfsFileLength;
  939. UINT32 PadSize;
  940. UINTN Misalignment;
  941. EFI_FFS_INTEGRITY_CHECK *IntegrityCheck;
  942. //
  943. // Figure out the misalignment: all FFS sections are aligned relative to the
  944. // start of the FFS payload, so use that as the base of the misalignment
  945. // computation.
  946. //
  947. FfsHeaderLength = GetFfsHeaderLength(FfsFile);
  948. Misalignment = (UINTN) FvImage->CurrentFilePointer -
  949. (UINTN) FvImage->FileImage + FfsHeaderLength;
  950. Misalignment &= Alignment - 1;
  951. if (Misalignment == 0) {
  952. // Nothing to do, return success
  953. return TRUE;
  954. }
  955. //
  956. // We only apply this optimization to FFS files with the FIXED attribute set,
  957. // since the FFS will not be loadable at arbitrary offsets anymore after
  958. // we adjust the size of the padding section.
  959. //
  960. if ((FfsFile->Attributes & FFS_ATTRIB_FIXED) == 0) {
  961. return FALSE;
  962. }
  963. //
  964. // Look for a dedicated padding section that we can adjust to compensate
  965. // for the misalignment. If such a padding section exists, it precedes all
  966. // sections with alignment requirements, and so the adjustment will correct
  967. // all of them.
  968. //
  969. Status = GetSectionByType (FfsFile, EFI_SECTION_FREEFORM_SUBTYPE_GUID, 1,
  970. &PadSection);
  971. if (EFI_ERROR (Status) ||
  972. CompareGuid (&PadSection.FreeformSubtypeSection->SubTypeGuid,
  973. &mEfiFfsSectionAlignmentPaddingGuid) != 0) {
  974. return FALSE;
  975. }
  976. //
  977. // Find out if the size of the padding section is sufficient to compensate
  978. // for the misalignment.
  979. //
  980. PadSize = GetSectionFileLength (PadSection.CommonHeader);
  981. if (Misalignment > PadSize - sizeof (EFI_FREEFORM_SUBTYPE_GUID_SECTION)) {
  982. return FALSE;
  983. }
  984. //
  985. // Move the remainder of the FFS file towards the front, and adjust the
  986. // file size output parameter.
  987. //
  988. Remainder = (UINT8 *) PadSection.CommonHeader + PadSize;
  989. memmove (Remainder - Misalignment, Remainder,
  990. *FileSize - (UINTN) (Remainder - (UINTN) FfsFile));
  991. *FileSize -= Misalignment;
  992. //
  993. // Update the padding section's length with the new values. Note that the
  994. // padding is always < 64 KB, so we can ignore EFI_COMMON_SECTION_HEADER2
  995. // ExtendedSize.
  996. //
  997. PadSize -= Misalignment;
  998. PadSection.CommonHeader->Size[0] = (UINT8) (PadSize & 0xff);
  999. PadSection.CommonHeader->Size[1] = (UINT8) ((PadSize & 0xff00) >> 8);
  1000. PadSection.CommonHeader->Size[2] = (UINT8) ((PadSize & 0xff0000) >> 16);
  1001. //
  1002. // Update the FFS header with the new overall length
  1003. //
  1004. FfsFileLength = GetFfsFileLength (FfsFile) - Misalignment;
  1005. if (FfsHeaderLength > sizeof(EFI_FFS_FILE_HEADER)) {
  1006. ((EFI_FFS_FILE_HEADER2 *)FfsFile)->ExtendedSize = FfsFileLength;
  1007. } else {
  1008. FfsFile->Size[0] = (UINT8) (FfsFileLength & 0x000000FF);
  1009. FfsFile->Size[1] = (UINT8) ((FfsFileLength & 0x0000FF00) >> 8);
  1010. FfsFile->Size[2] = (UINT8) ((FfsFileLength & 0x00FF0000) >> 16);
  1011. }
  1012. //
  1013. // Clear the alignment bits: these have become meaningless now that we have
  1014. // adjusted the padding section.
  1015. //
  1016. FfsFile->Attributes &= ~(FFS_ATTRIB_DATA_ALIGNMENT | FFS_ATTRIB_DATA_ALIGNMENT2);
  1017. //
  1018. // Recalculate the FFS header checksum. Instead of setting Header and State
  1019. // both to zero, set Header to (UINT8)(-State) so State preserves its original
  1020. // value
  1021. //
  1022. IntegrityCheck = &FfsFile->IntegrityCheck;
  1023. IntegrityCheck->Checksum.Header = (UINT8) (0x100 - FfsFile->State);
  1024. IntegrityCheck->Checksum.File = 0;
  1025. IntegrityCheck->Checksum.Header = CalculateChecksum8 (
  1026. (UINT8 *) FfsFile, FfsHeaderLength);
  1027. if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
  1028. //
  1029. // Ffs header checksum = zero, so only need to calculate ffs body.
  1030. //
  1031. IntegrityCheck->Checksum.File = CalculateChecksum8 (
  1032. (UINT8 *) FfsFile + FfsHeaderLength,
  1033. FfsFileLength - FfsHeaderLength);
  1034. } else {
  1035. IntegrityCheck->Checksum.File = FFS_FIXED_CHECKSUM;
  1036. }
  1037. return TRUE;
  1038. }
  1039. EFI_STATUS
  1040. AddFile (
  1041. IN OUT MEMORY_FILE *FvImage,
  1042. IN FV_INFO *FvInfo,
  1043. IN UINTN Index,
  1044. IN OUT EFI_FFS_FILE_HEADER **VtfFileImage,
  1045. IN FILE *FvMapFile,
  1046. IN FILE *FvReportFile
  1047. )
  1048. /*++
  1049. Routine Description:
  1050. This function adds a file to the FV image. The file will pad to the
  1051. appropriate alignment if required.
  1052. Arguments:
  1053. FvImage The memory image of the FV to add it to. The current offset
  1054. must be valid.
  1055. FvInfo Pointer to information about the FV.
  1056. Index The file in the FvInfo file list to add.
  1057. VtfFileImage A pointer to the VTF file within the FvImage. If this is equal
  1058. to the end of the FvImage then no VTF previously found.
  1059. FvMapFile Pointer to FvMap File
  1060. FvReportFile Pointer to FvReport File
  1061. Returns:
  1062. EFI_SUCCESS The function completed successfully.
  1063. EFI_INVALID_PARAMETER One of the input parameters was invalid.
  1064. EFI_ABORTED An error occurred.
  1065. EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add.
  1066. --*/
  1067. {
  1068. FILE *NewFile;
  1069. UINTN FileSize;
  1070. UINT8 *FileBuffer;
  1071. UINTN NumBytesRead;
  1072. UINT32 CurrentFileAlignment;
  1073. EFI_STATUS Status;
  1074. UINTN Index1;
  1075. UINT8 FileGuidString[PRINTED_GUID_BUFFER_SIZE];
  1076. Index1 = 0;
  1077. //
  1078. // Verify input parameters.
  1079. //
  1080. if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL) {
  1081. return EFI_INVALID_PARAMETER;
  1082. }
  1083. //
  1084. // Read the file to add
  1085. //
  1086. NewFile = fopen (LongFilePath (FvInfo->FvFiles[Index]), "rb");
  1087. if (NewFile == NULL) {
  1088. Error (NULL, 0, 0001, "Error opening file", FvInfo->FvFiles[Index]);
  1089. return EFI_ABORTED;
  1090. }
  1091. //
  1092. // Get the file size
  1093. //
  1094. FileSize = _filelength (fileno (NewFile));
  1095. //
  1096. // Read the file into a buffer
  1097. //
  1098. FileBuffer = malloc (FileSize);
  1099. if (FileBuffer == NULL) {
  1100. fclose (NewFile);
  1101. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  1102. return EFI_OUT_OF_RESOURCES;
  1103. }
  1104. NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile);
  1105. //
  1106. // Done with the file, from this point on we will just use the buffer read.
  1107. //
  1108. fclose (NewFile);
  1109. //
  1110. // Verify read successful
  1111. //
  1112. if (NumBytesRead != sizeof (UINT8) * FileSize) {
  1113. free (FileBuffer);
  1114. Error (NULL, 0, 0004, "Error reading file", FvInfo->FvFiles[Index]);
  1115. return EFI_ABORTED;
  1116. }
  1117. //
  1118. // For None PI Ffs file, directly add them into FvImage.
  1119. //
  1120. if (!FvInfo->IsPiFvImage) {
  1121. memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);
  1122. if (FvInfo->SizeofFvFiles[Index] > FileSize) {
  1123. FvImage->CurrentFilePointer += FvInfo->SizeofFvFiles[Index];
  1124. } else {
  1125. FvImage->CurrentFilePointer += FileSize;
  1126. }
  1127. goto Done;
  1128. }
  1129. //
  1130. // Verify Ffs file
  1131. //
  1132. Status = VerifyFfsFile ((EFI_FFS_FILE_HEADER *)FileBuffer);
  1133. if (EFI_ERROR (Status)) {
  1134. free (FileBuffer);
  1135. Error (NULL, 0, 3000, "Invalid", "%s is not a valid FFS file.", FvInfo->FvFiles[Index]);
  1136. return EFI_INVALID_PARAMETER;
  1137. }
  1138. //
  1139. // Verify space exists to add the file
  1140. //
  1141. if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) {
  1142. free (FileBuffer);
  1143. Error (NULL, 0, 4002, "Resource", "FV space is full, not enough room to add file %s.", FvInfo->FvFiles[Index]);
  1144. return EFI_OUT_OF_RESOURCES;
  1145. }
  1146. //
  1147. // Verify the input file is the duplicated file in this Fv image
  1148. //
  1149. for (Index1 = 0; Index1 < Index; Index1 ++) {
  1150. if (CompareGuid ((EFI_GUID *) FileBuffer, &mFileGuidArray [Index1]) == 0) {
  1151. Error (NULL, 0, 2000, "Invalid parameter", "the %dth file and %uth file have the same file GUID.", (unsigned) Index1 + 1, (unsigned) Index + 1);
  1152. PrintGuid ((EFI_GUID *) FileBuffer);
  1153. free (FileBuffer);
  1154. return EFI_INVALID_PARAMETER;
  1155. }
  1156. }
  1157. CopyMem (&mFileGuidArray [Index], FileBuffer, sizeof (EFI_GUID));
  1158. //
  1159. // Update the file state based on polarity of the FV.
  1160. //
  1161. UpdateFfsFileState (
  1162. (EFI_FFS_FILE_HEADER *) FileBuffer,
  1163. (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
  1164. );
  1165. //
  1166. // Check if alignment is required
  1167. //
  1168. ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment);
  1169. //
  1170. // Find the largest alignment of all the FFS files in the FV
  1171. //
  1172. if (CurrentFileAlignment > MaxFfsAlignment) {
  1173. MaxFfsAlignment = CurrentFileAlignment;
  1174. }
  1175. //
  1176. // If we have a VTF file, add it at the top.
  1177. //
  1178. if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) {
  1179. if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) {
  1180. //
  1181. // No previous VTF, add this one.
  1182. //
  1183. *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize);
  1184. //
  1185. // Sanity check. The file MUST align appropriately
  1186. //
  1187. if (((UINTN) *VtfFileImage + GetFfsHeaderLength((EFI_FFS_FILE_HEADER *)FileBuffer) - (UINTN) FvImage->FileImage) % (1 << CurrentFileAlignment)) {
  1188. Error (NULL, 0, 3000, "Invalid", "VTF file cannot be aligned on a %u-byte boundary.", (unsigned) (1 << CurrentFileAlignment));
  1189. free (FileBuffer);
  1190. return EFI_ABORTED;
  1191. }
  1192. //
  1193. // Rebase the PE or TE image in FileBuffer of FFS file for XIP
  1194. // Rebase for the debug genfvmap tool
  1195. //
  1196. Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile);
  1197. if (EFI_ERROR (Status)) {
  1198. Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]);
  1199. return Status;
  1200. }
  1201. //
  1202. // copy VTF File
  1203. //
  1204. memcpy (*VtfFileImage, FileBuffer, FileSize);
  1205. PrintGuidToBuffer ((EFI_GUID *) FileBuffer, FileGuidString, sizeof (FileGuidString), TRUE);
  1206. fprintf (FvReportFile, "0x%08X %s\n", (unsigned)(UINTN) (((UINT8 *)*VtfFileImage) - (UINTN)FvImage->FileImage), FileGuidString);
  1207. free (FileBuffer);
  1208. DebugMsg (NULL, 0, 9, "Add VTF FFS file in FV image", NULL);
  1209. return EFI_SUCCESS;
  1210. } else {
  1211. //
  1212. // Already found a VTF file.
  1213. //
  1214. Error (NULL, 0, 3000, "Invalid", "multiple VTF files are not permitted within a single FV.");
  1215. free (FileBuffer);
  1216. return EFI_ABORTED;
  1217. }
  1218. }
  1219. //
  1220. // Add pad file if necessary
  1221. //
  1222. if (!AdjustInternalFfsPadding ((EFI_FFS_FILE_HEADER *) FileBuffer, FvImage,
  1223. 1 << CurrentFileAlignment, &FileSize)) {
  1224. Status = AddPadFile (FvImage, 1 << CurrentFileAlignment, *VtfFileImage, NULL, FileSize);
  1225. if (EFI_ERROR (Status)) {
  1226. Error (NULL, 0, 4002, "Resource", "FV space is full, could not add pad file for data alignment property.");
  1227. free (FileBuffer);
  1228. return EFI_ABORTED;
  1229. }
  1230. }
  1231. //
  1232. // Add file
  1233. //
  1234. if ((UINTN) (FvImage->CurrentFilePointer + FileSize) <= (UINTN) (*VtfFileImage)) {
  1235. //
  1236. // Rebase the PE or TE image in FileBuffer of FFS file for XIP.
  1237. // Rebase Bs and Rt drivers for the debug genfvmap tool.
  1238. //
  1239. Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile);
  1240. if (EFI_ERROR (Status)) {
  1241. Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]);
  1242. return Status;
  1243. }
  1244. //
  1245. // Copy the file
  1246. //
  1247. memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize);
  1248. PrintGuidToBuffer ((EFI_GUID *) FileBuffer, FileGuidString, sizeof (FileGuidString), TRUE);
  1249. fprintf (FvReportFile, "0x%08X %s\n", (unsigned) (FvImage->CurrentFilePointer - FvImage->FileImage), FileGuidString);
  1250. FvImage->CurrentFilePointer += FileSize;
  1251. } else {
  1252. Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add file %s.", FvInfo->FvFiles[Index]);
  1253. free (FileBuffer);
  1254. return EFI_ABORTED;
  1255. }
  1256. //
  1257. // Make next file start at QWord Boundary
  1258. //
  1259. while (((UINTN) FvImage->CurrentFilePointer & (EFI_FFS_FILE_HEADER_ALIGNMENT - 1)) != 0) {
  1260. FvImage->CurrentFilePointer++;
  1261. }
  1262. Done:
  1263. //
  1264. // Free allocated memory.
  1265. //
  1266. free (FileBuffer);
  1267. return EFI_SUCCESS;
  1268. }
  1269. EFI_STATUS
  1270. PadFvImage (
  1271. IN MEMORY_FILE *FvImage,
  1272. IN EFI_FFS_FILE_HEADER *VtfFileImage
  1273. )
  1274. /*++
  1275. Routine Description:
  1276. This function places a pad file between the last file in the FV and the VTF
  1277. file if the VTF file exists.
  1278. Arguments:
  1279. FvImage Memory file for the FV memory image
  1280. VtfFileImage The address of the VTF file. If this is the end of the FV
  1281. image, no VTF exists and no pad file is needed.
  1282. Returns:
  1283. EFI_SUCCESS Completed successfully.
  1284. EFI_INVALID_PARAMETER One of the input parameters was NULL.
  1285. --*/
  1286. {
  1287. EFI_FFS_FILE_HEADER *PadFile;
  1288. UINTN FileSize;
  1289. UINT32 FfsHeaderSize;
  1290. //
  1291. // If there is no VTF or the VTF naturally follows the previous file without a
  1292. // pad file, then there's nothing to do
  1293. //
  1294. if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || \
  1295. ((UINTN) VtfFileImage == (UINTN) FvImage->CurrentFilePointer)) {
  1296. return EFI_SUCCESS;
  1297. }
  1298. if ((UINTN) VtfFileImage < (UINTN) FvImage->CurrentFilePointer) {
  1299. return EFI_INVALID_PARAMETER;
  1300. }
  1301. //
  1302. // Pad file starts at beginning of free space
  1303. //
  1304. PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer;
  1305. //
  1306. // write PadFile FFS header with PadType, don't need to set PAD file guid in its header.
  1307. //
  1308. PadFile->Type = EFI_FV_FILETYPE_FFS_PAD;
  1309. PadFile->Attributes = 0;
  1310. //
  1311. // FileSize includes the EFI_FFS_FILE_HEADER
  1312. //
  1313. FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer;
  1314. if (FileSize >= MAX_FFS_SIZE) {
  1315. PadFile->Attributes |= FFS_ATTRIB_LARGE_FILE;
  1316. memset(PadFile->Size, 0, sizeof(UINT8) * 3);
  1317. ((EFI_FFS_FILE_HEADER2 *)PadFile)->ExtendedSize = FileSize;
  1318. FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
  1319. mIsLargeFfs = TRUE;
  1320. } else {
  1321. PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF);
  1322. PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8);
  1323. PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16);
  1324. FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
  1325. }
  1326. //
  1327. // Fill in checksums and state, must be zero during checksum calculation.
  1328. //
  1329. PadFile->IntegrityCheck.Checksum.Header = 0;
  1330. PadFile->IntegrityCheck.Checksum.File = 0;
  1331. PadFile->State = 0;
  1332. PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, FfsHeaderSize);
  1333. PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
  1334. PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
  1335. UpdateFfsFileState (
  1336. (EFI_FFS_FILE_HEADER *) PadFile,
  1337. (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage
  1338. );
  1339. //
  1340. // Update the current FV pointer
  1341. //
  1342. FvImage->CurrentFilePointer = FvImage->Eof;
  1343. return EFI_SUCCESS;
  1344. }
  1345. EFI_STATUS
  1346. UpdateResetVector (
  1347. IN MEMORY_FILE *FvImage,
  1348. IN FV_INFO *FvInfo,
  1349. IN EFI_FFS_FILE_HEADER *VtfFile
  1350. )
  1351. /*++
  1352. Routine Description:
  1353. This parses the FV looking for the PEI core and then plugs the address into
  1354. the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to
  1355. complete an IA32 Bootstrap FV.
  1356. Arguments:
  1357. FvImage Memory file for the FV memory image
  1358. FvInfo Information read from INF file.
  1359. VtfFile Pointer to the VTF file in the FV image.
  1360. Returns:
  1361. EFI_SUCCESS Function Completed successfully.
  1362. EFI_ABORTED Error encountered.
  1363. EFI_INVALID_PARAMETER A required parameter was NULL.
  1364. EFI_NOT_FOUND PEI Core file not found.
  1365. --*/
  1366. {
  1367. EFI_FFS_FILE_HEADER *PeiCoreFile;
  1368. EFI_FFS_FILE_HEADER *SecCoreFile;
  1369. EFI_STATUS Status;
  1370. EFI_FILE_SECTION_POINTER Pe32Section;
  1371. UINT32 EntryPoint;
  1372. UINT32 BaseOfCode;
  1373. UINT16 MachineType;
  1374. EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress;
  1375. EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress;
  1376. INT32 Ia32SecEntryOffset;
  1377. UINT32 *Ia32ResetAddressPtr;
  1378. UINT8 *BytePointer;
  1379. UINT8 *BytePointer2;
  1380. UINT16 *WordPointer;
  1381. UINT16 CheckSum;
  1382. UINT32 IpiVector;
  1383. UINTN Index;
  1384. EFI_FFS_FILE_STATE SavedState;
  1385. BOOLEAN Vtf0Detected;
  1386. UINT32 FfsHeaderSize;
  1387. UINT32 SecHeaderSize;
  1388. //
  1389. // Verify input parameters
  1390. //
  1391. if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) {
  1392. return EFI_INVALID_PARAMETER;
  1393. }
  1394. //
  1395. // Initialize FV library
  1396. //
  1397. InitializeFvLib (FvImage->FileImage, FvInfo->Size);
  1398. //
  1399. // Verify VTF file
  1400. //
  1401. Status = VerifyFfsFile (VtfFile);
  1402. if (EFI_ERROR (Status)) {
  1403. return EFI_INVALID_PARAMETER;
  1404. }
  1405. if (
  1406. (((UINTN)FvImage->Eof - (UINTN)FvImage->FileImage) >=
  1407. IA32_X64_VTF_SIGNATURE_OFFSET) &&
  1408. (*(UINT32 *)(VOID*)((UINTN) FvImage->Eof -
  1409. IA32_X64_VTF_SIGNATURE_OFFSET) ==
  1410. IA32_X64_VTF0_SIGNATURE)
  1411. ) {
  1412. Vtf0Detected = TRUE;
  1413. } else {
  1414. Vtf0Detected = FALSE;
  1415. }
  1416. //
  1417. // Find the Sec Core
  1418. //
  1419. Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile);
  1420. if (EFI_ERROR (Status) || SecCoreFile == NULL) {
  1421. if (Vtf0Detected) {
  1422. //
  1423. // If the SEC core file is not found, but the VTF-0 signature
  1424. // is found, we'll treat it as a VTF-0 'Volume Top File'.
  1425. // This means no modifications are required to the VTF.
  1426. //
  1427. return EFI_SUCCESS;
  1428. }
  1429. Error (NULL, 0, 3000, "Invalid", "could not find the SEC core file in the FV.");
  1430. return EFI_ABORTED;
  1431. }
  1432. //
  1433. // Sec Core found, now find PE32 section
  1434. //
  1435. Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
  1436. if (Status == EFI_NOT_FOUND) {
  1437. Status = GetSectionByType (SecCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
  1438. }
  1439. if (EFI_ERROR (Status)) {
  1440. Error (NULL, 0, 3000, "Invalid", "could not find a PE32 section in the SEC core file.");
  1441. return EFI_ABORTED;
  1442. }
  1443. SecHeaderSize = GetSectionHeaderLength(Pe32Section.CommonHeader);
  1444. Status = GetPe32Info (
  1445. (VOID *) ((UINTN) Pe32Section.Pe32Section + SecHeaderSize),
  1446. &EntryPoint,
  1447. &BaseOfCode,
  1448. &MachineType
  1449. );
  1450. if (EFI_ERROR (Status)) {
  1451. Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the SEC core.");
  1452. return EFI_ABORTED;
  1453. }
  1454. if (
  1455. Vtf0Detected &&
  1456. (MachineType == EFI_IMAGE_MACHINE_IA32 ||
  1457. MachineType == EFI_IMAGE_MACHINE_X64)
  1458. ) {
  1459. //
  1460. // If the SEC core code is IA32 or X64 and the VTF-0 signature
  1461. // is found, we'll treat it as a VTF-0 'Volume Top File'.
  1462. // This means no modifications are required to the VTF.
  1463. //
  1464. return EFI_SUCCESS;
  1465. }
  1466. //
  1467. // Physical address is FV base + offset of PE32 + offset of the entry point
  1468. //
  1469. SecCorePhysicalAddress = FvInfo->BaseAddress;
  1470. SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + SecHeaderSize - (UINTN) FvImage->FileImage;
  1471. SecCorePhysicalAddress += EntryPoint;
  1472. DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%llX", (unsigned long long) SecCorePhysicalAddress);
  1473. //
  1474. // Find the PEI Core
  1475. //
  1476. PeiCorePhysicalAddress = 0;
  1477. Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile);
  1478. if (!EFI_ERROR (Status) && (PeiCoreFile != NULL)) {
  1479. //
  1480. // PEI Core found, now find PE32 or TE section
  1481. //
  1482. Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section);
  1483. if (Status == EFI_NOT_FOUND) {
  1484. Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section);
  1485. }
  1486. if (EFI_ERROR (Status)) {
  1487. Error (NULL, 0, 3000, "Invalid", "could not find either a PE32 or a TE section in PEI core file.");
  1488. return EFI_ABORTED;
  1489. }
  1490. SecHeaderSize = GetSectionHeaderLength(Pe32Section.CommonHeader);
  1491. Status = GetPe32Info (
  1492. (VOID *) ((UINTN) Pe32Section.Pe32Section + SecHeaderSize),
  1493. &EntryPoint,
  1494. &BaseOfCode,
  1495. &MachineType
  1496. );
  1497. if (EFI_ERROR (Status)) {
  1498. Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the PEI core.");
  1499. return EFI_ABORTED;
  1500. }
  1501. //
  1502. // Physical address is FV base + offset of PE32 + offset of the entry point
  1503. //
  1504. PeiCorePhysicalAddress = FvInfo->BaseAddress;
  1505. PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + SecHeaderSize - (UINTN) FvImage->FileImage;
  1506. PeiCorePhysicalAddress += EntryPoint;
  1507. DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress);
  1508. }
  1509. if (MachineType == EFI_IMAGE_MACHINE_IA32 || MachineType == EFI_IMAGE_MACHINE_X64) {
  1510. if (PeiCorePhysicalAddress != 0) {
  1511. //
  1512. // Get the location to update
  1513. //
  1514. Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET);
  1515. //
  1516. // Write lower 32 bits of physical address for Pei Core entry
  1517. //
  1518. *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress;
  1519. }
  1520. //
  1521. // Write SecCore Entry point relative address into the jmp instruction in reset vector.
  1522. //
  1523. Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_SEC_CORE_ENTRY_OFFSET);
  1524. Ia32SecEntryOffset = (INT32) (SecCorePhysicalAddress - (FV_IMAGES_TOP_ADDRESS - IA32_SEC_CORE_ENTRY_OFFSET + 2));
  1525. if (Ia32SecEntryOffset <= -65536) {
  1526. Error (NULL, 0, 3000, "Invalid", "The SEC EXE file size is too large, it must be less than 64K.");
  1527. return STATUS_ERROR;
  1528. }
  1529. *(UINT16 *) Ia32ResetAddressPtr = (UINT16) Ia32SecEntryOffset;
  1530. //
  1531. // Update the BFV base address
  1532. //
  1533. Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4);
  1534. *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress);
  1535. DebugMsg (NULL, 0, 9, "update BFV base address in the top FV image", "BFV base address = 0x%llX.", (unsigned long long) FvInfo->BaseAddress);
  1536. //
  1537. // Update the Startup AP in the FVH header block ZeroVector region.
  1538. //
  1539. BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage);
  1540. if (FvInfo->Size <= 0x10000) {
  1541. BytePointer2 = m64kRecoveryStartupApDataArray;
  1542. } else if (FvInfo->Size <= 0x20000) {
  1543. BytePointer2 = m128kRecoveryStartupApDataArray;
  1544. } else {
  1545. BytePointer2 = m128kRecoveryStartupApDataArray;
  1546. //
  1547. // Find the position to place Ap reset vector, the offset
  1548. // between the position and the end of Fvrecovery.fv file
  1549. // should not exceed 128kB to prevent Ap reset vector from
  1550. // outside legacy E and F segment
  1551. //
  1552. Status = FindApResetVectorPosition (FvImage, &BytePointer);
  1553. if (EFI_ERROR (Status)) {
  1554. Error (NULL, 0, 3000, "Invalid", "FV image does not have enough space to place AP reset vector. The FV image needs to reserve at least 4KB of unused space.");
  1555. return EFI_ABORTED;
  1556. }
  1557. }
  1558. for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) {
  1559. BytePointer[Index] = BytePointer2[Index];
  1560. }
  1561. //
  1562. // Calculate the checksum
  1563. //
  1564. CheckSum = 0x0000;
  1565. WordPointer = (UINT16 *) (BytePointer);
  1566. for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) {
  1567. CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer));
  1568. WordPointer++;
  1569. }
  1570. //
  1571. // Update the checksum field
  1572. //
  1573. WordPointer = (UINT16 *) (BytePointer + SIZEOF_STARTUP_DATA_ARRAY - 2);
  1574. *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum);
  1575. //
  1576. // IpiVector at the 4k aligned address in the top 2 blocks in the PEI FV.
  1577. //
  1578. IpiVector = (UINT32) (FV_IMAGES_TOP_ADDRESS - ((UINTN) FvImage->Eof - (UINTN) BytePointer));
  1579. DebugMsg (NULL, 0, 9, "Startup AP Vector address", "IpiVector at 0x%X", (unsigned) IpiVector);
  1580. if ((IpiVector & 0xFFF) != 0) {
  1581. Error (NULL, 0, 3000, "Invalid", "Startup AP Vector address are not 4K aligned, because the FV size is not 4K aligned");
  1582. return EFI_ABORTED;
  1583. }
  1584. IpiVector = IpiVector >> 12;
  1585. IpiVector = IpiVector & 0xFF;
  1586. //
  1587. // Write IPI Vector at Offset FvrecoveryFileSize - 8
  1588. //
  1589. Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 8);
  1590. *Ia32ResetAddressPtr = IpiVector;
  1591. } else if (MachineType == EFI_IMAGE_MACHINE_ARMT) {
  1592. //
  1593. // Since the ARM reset vector is in the FV Header you really don't need a
  1594. // Volume Top File, but if you have one for some reason don't crash...
  1595. //
  1596. } else if (MachineType == EFI_IMAGE_MACHINE_AARCH64) {
  1597. //
  1598. // Since the AArch64 reset vector is in the FV Header you really don't need a
  1599. // Volume Top File, but if you have one for some reason don't crash...
  1600. //
  1601. } else {
  1602. Error (NULL, 0, 3000, "Invalid", "machine type=0x%X in PEI core.", MachineType);
  1603. return EFI_ABORTED;
  1604. }
  1605. //
  1606. // Now update file checksum
  1607. //
  1608. SavedState = VtfFile->State;
  1609. VtfFile->IntegrityCheck.Checksum.File = 0;
  1610. VtfFile->State = 0;
  1611. if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) {
  1612. FfsHeaderSize = GetFfsHeaderLength(VtfFile);
  1613. VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
  1614. (UINT8 *) ((UINT8 *)VtfFile + FfsHeaderSize),
  1615. GetFfsFileLength (VtfFile) - FfsHeaderSize
  1616. );
  1617. } else {
  1618. VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
  1619. }
  1620. VtfFile->State = SavedState;
  1621. return EFI_SUCCESS;
  1622. }
  1623. EFI_STATUS
  1624. FindCorePeSection(
  1625. IN VOID *FvImageBuffer,
  1626. IN UINT64 FvSize,
  1627. IN EFI_FV_FILETYPE FileType,
  1628. OUT EFI_FILE_SECTION_POINTER *Pe32Section
  1629. )
  1630. /*++
  1631. Routine Description:
  1632. Recursively searches the FV for the FFS file of specified type (typically
  1633. SEC or PEI core) and extracts the PE32 section for further processing.
  1634. Arguments:
  1635. FvImageBuffer Buffer containing FV data
  1636. FvSize Size of the FV
  1637. FileType Type of FFS file to search for
  1638. Pe32Section PE32 section pointer when FFS file is found.
  1639. Returns:
  1640. EFI_SUCCESS Function Completed successfully.
  1641. EFI_ABORTED Error encountered.
  1642. EFI_INVALID_PARAMETER A required parameter was NULL.
  1643. EFI_NOT_FOUND Core file not found.
  1644. --*/
  1645. {
  1646. EFI_STATUS Status;
  1647. EFI_FIRMWARE_VOLUME_HEADER *OrigFvHeader;
  1648. UINT32 OrigFvLength;
  1649. EFI_FFS_FILE_HEADER *CoreFfsFile;
  1650. UINTN FvImageFileCount;
  1651. EFI_FFS_FILE_HEADER *FvImageFile;
  1652. UINTN EncapFvSectionCount;
  1653. EFI_FILE_SECTION_POINTER EncapFvSection;
  1654. EFI_FIRMWARE_VOLUME_HEADER *EncapsulatedFvHeader;
  1655. if (Pe32Section == NULL) {
  1656. return EFI_INVALID_PARAMETER;
  1657. }
  1658. //
  1659. // Initialize FV library, saving previous values
  1660. //
  1661. OrigFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)NULL;
  1662. GetFvHeader (&OrigFvHeader, &OrigFvLength);
  1663. InitializeFvLib(FvImageBuffer, (UINT32)FvSize);
  1664. //
  1665. // First see if we can obtain the file directly in outer FV
  1666. //
  1667. Status = GetFileByType(FileType, 1, &CoreFfsFile);
  1668. if (!EFI_ERROR(Status) && (CoreFfsFile != NULL) ) {
  1669. //
  1670. // Core found, now find PE32 or TE section
  1671. //
  1672. Status = GetSectionByType(CoreFfsFile, EFI_SECTION_PE32, 1, Pe32Section);
  1673. if (EFI_ERROR(Status)) {
  1674. Status = GetSectionByType(CoreFfsFile, EFI_SECTION_TE, 1, Pe32Section);
  1675. }
  1676. if (EFI_ERROR(Status)) {
  1677. Error(NULL, 0, 3000, "Invalid", "could not find a PE32 section in the core file.");
  1678. return EFI_ABORTED;
  1679. }
  1680. //
  1681. // Core PE/TE section, found, return
  1682. //
  1683. Status = EFI_SUCCESS;
  1684. goto EarlyExit;
  1685. }
  1686. //
  1687. // File was not found, look for FV Image file
  1688. //
  1689. // iterate through all FV image files in outer FV
  1690. for (FvImageFileCount = 1;; FvImageFileCount++) {
  1691. Status = GetFileByType(EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, FvImageFileCount, &FvImageFile);
  1692. if (EFI_ERROR(Status) || (FvImageFile == NULL) ) {
  1693. // exit FV image file loop, no more found
  1694. break;
  1695. }
  1696. // Found an fv image file, look for an FV image section. The PI spec does not
  1697. // preclude multiple FV image sections so we loop accordingly.
  1698. for (EncapFvSectionCount = 1;; EncapFvSectionCount++) {
  1699. // Look for the next FV image section. The section search code will
  1700. // iterate into encapsulation sections. For example, it will iterate
  1701. // into an EFI_SECTION_GUID_DEFINED encapsulation section to find the
  1702. // EFI_SECTION_FIRMWARE_VOLUME_IMAGE sections contained therein.
  1703. Status = GetSectionByType(FvImageFile, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EncapFvSectionCount, &EncapFvSection);
  1704. if (EFI_ERROR(Status)) {
  1705. // exit section inner loop, no more found
  1706. break;
  1707. }
  1708. EncapsulatedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINT8 *)EncapFvSection.FVImageSection + GetSectionHeaderLength(EncapFvSection.FVImageSection));
  1709. // recurse to search the encapsulated FV for this core file type
  1710. Status = FindCorePeSection(EncapsulatedFvHeader, EncapsulatedFvHeader->FvLength, FileType, Pe32Section);
  1711. if (!EFI_ERROR(Status)) {
  1712. // we found the core in the capsulated image, success
  1713. goto EarlyExit;
  1714. }
  1715. } // end encapsulated fv image section loop
  1716. } // end fv image file loop
  1717. // core was not found
  1718. Status = EFI_NOT_FOUND;
  1719. EarlyExit:
  1720. // restore FV lib values
  1721. if(OrigFvHeader != NULL) {
  1722. InitializeFvLib(OrigFvHeader, OrigFvLength);
  1723. }
  1724. return Status;
  1725. }
  1726. EFI_STATUS
  1727. GetCoreMachineType(
  1728. IN EFI_FILE_SECTION_POINTER Pe32Section,
  1729. OUT UINT16 *CoreMachineType
  1730. )
  1731. /*++
  1732. Routine Description:
  1733. Returns the machine type of a P32 image, typically SEC or PEI core.
  1734. Arguments:
  1735. Pe32Section PE32 section data
  1736. CoreMachineType The extracted machine type
  1737. Returns:
  1738. EFI_SUCCESS Function Completed successfully.
  1739. EFI_ABORTED Error encountered.
  1740. EFI_INVALID_PARAMETER A required parameter was NULL.
  1741. --*/
  1742. {
  1743. EFI_STATUS Status;
  1744. UINT32 EntryPoint;
  1745. UINT32 BaseOfCode;
  1746. if (CoreMachineType == NULL) {
  1747. return EFI_INVALID_PARAMETER;
  1748. }
  1749. Status = GetPe32Info(
  1750. (VOID *)((UINTN)Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader)),
  1751. &EntryPoint,
  1752. &BaseOfCode,
  1753. CoreMachineType
  1754. );
  1755. if (EFI_ERROR(Status)) {
  1756. Error(NULL, 0, 3000, "Invalid", "could not get the PE32 machine type for the core.");
  1757. return EFI_ABORTED;
  1758. }
  1759. return EFI_SUCCESS;
  1760. }
  1761. EFI_STATUS
  1762. GetCoreEntryPointAddress(
  1763. IN VOID *FvImageBuffer,
  1764. IN FV_INFO *FvInfo,
  1765. IN EFI_FILE_SECTION_POINTER Pe32Section,
  1766. OUT EFI_PHYSICAL_ADDRESS *CoreEntryAddress
  1767. )
  1768. /*++
  1769. Routine Description:
  1770. Returns the physical address of the core (SEC or PEI) entry point.
  1771. Arguments:
  1772. FvImageBuffer Pointer to buffer containing FV data
  1773. FvInfo Info for the parent FV
  1774. Pe32Section PE32 section data
  1775. CoreEntryAddress The extracted core entry physical address
  1776. Returns:
  1777. EFI_SUCCESS Function Completed successfully.
  1778. EFI_ABORTED Error encountered.
  1779. EFI_INVALID_PARAMETER A required parameter was NULL.
  1780. --*/
  1781. {
  1782. EFI_STATUS Status;
  1783. UINT32 EntryPoint;
  1784. UINT32 BaseOfCode;
  1785. UINT16 MachineType;
  1786. EFI_PHYSICAL_ADDRESS EntryPhysicalAddress;
  1787. if (CoreEntryAddress == NULL) {
  1788. return EFI_INVALID_PARAMETER;
  1789. }
  1790. Status = GetPe32Info(
  1791. (VOID *)((UINTN)Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader)),
  1792. &EntryPoint,
  1793. &BaseOfCode,
  1794. &MachineType
  1795. );
  1796. if (EFI_ERROR(Status)) {
  1797. Error(NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the core.");
  1798. return EFI_ABORTED;
  1799. }
  1800. //
  1801. // Physical address is FV base + offset of PE32 + offset of the entry point
  1802. //
  1803. EntryPhysicalAddress = FvInfo->BaseAddress;
  1804. EntryPhysicalAddress += (UINTN)Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader) - (UINTN)FvImageBuffer;
  1805. EntryPhysicalAddress += EntryPoint;
  1806. *CoreEntryAddress = EntryPhysicalAddress;
  1807. return EFI_SUCCESS;
  1808. }
  1809. EFI_STATUS
  1810. UpdateArmResetVectorIfNeeded (
  1811. IN MEMORY_FILE *FvImage,
  1812. IN FV_INFO *FvInfo
  1813. )
  1814. /*++
  1815. Routine Description:
  1816. This parses the FV looking for SEC and patches that address into the
  1817. beginning of the FV header.
  1818. For ARM32 the reset vector is at 0x00000000 or 0xFFFF0000.
  1819. For AArch64 the reset vector is at 0x00000000.
  1820. This would commonly map to the first entry in the ROM.
  1821. ARM32 Exceptions:
  1822. Reset +0
  1823. Undefined +4
  1824. SWI +8
  1825. Prefetch Abort +12
  1826. Data Abort +16
  1827. IRQ +20
  1828. FIQ +24
  1829. We support two schemes on ARM.
  1830. 1) Beginning of the FV is the reset vector
  1831. 2) Reset vector is data bytes FDF file and that code branches to reset vector
  1832. in the beginning of the FV (fixed size offset).
  1833. Need to have the jump for the reset vector at location zero.
  1834. We also need to store the address or PEI (if it exists).
  1835. We stub out a return from interrupt in case the debugger
  1836. is using SWI (not done for AArch64, not enough space in struct).
  1837. The optional entry to the common exception handler is
  1838. to support full featured exception handling from ROM and is currently
  1839. not support by this tool.
  1840. Arguments:
  1841. FvImage Memory file for the FV memory image
  1842. FvInfo Information read from INF file.
  1843. Returns:
  1844. EFI_SUCCESS Function Completed successfully.
  1845. EFI_ABORTED Error encountered.
  1846. EFI_INVALID_PARAMETER A required parameter was NULL.
  1847. EFI_NOT_FOUND PEI Core file not found.
  1848. --*/
  1849. {
  1850. EFI_STATUS Status;
  1851. EFI_FILE_SECTION_POINTER SecPe32;
  1852. EFI_FILE_SECTION_POINTER PeiPe32;
  1853. BOOLEAN UpdateVectorSec = FALSE;
  1854. BOOLEAN UpdateVectorPei = FALSE;
  1855. UINT16 MachineType = 0;
  1856. EFI_PHYSICAL_ADDRESS SecCoreEntryAddress = 0;
  1857. UINT16 PeiMachineType = 0;
  1858. EFI_PHYSICAL_ADDRESS PeiCoreEntryAddress = 0;
  1859. //
  1860. // Verify input parameters
  1861. //
  1862. if (FvImage == NULL || FvInfo == NULL) {
  1863. return EFI_INVALID_PARAMETER;
  1864. }
  1865. //
  1866. // Locate an SEC Core instance and if found extract the machine type and entry point address
  1867. //
  1868. Status = FindCorePeSection(FvImage->FileImage, FvInfo->Size, EFI_FV_FILETYPE_SECURITY_CORE, &SecPe32);
  1869. if (!EFI_ERROR(Status)) {
  1870. Status = GetCoreMachineType(SecPe32, &MachineType);
  1871. if (EFI_ERROR(Status)) {
  1872. Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for SEC Core.");
  1873. return EFI_ABORTED;
  1874. }
  1875. Status = GetCoreEntryPointAddress(FvImage->FileImage, FvInfo, SecPe32, &SecCoreEntryAddress);
  1876. if (EFI_ERROR(Status)) {
  1877. Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 entry point address for SEC Core.");
  1878. return EFI_ABORTED;
  1879. }
  1880. VerboseMsg("UpdateArmResetVectorIfNeeded found SEC core entry at 0x%llx", (unsigned long long)SecCoreEntryAddress);
  1881. UpdateVectorSec = TRUE;
  1882. }
  1883. //
  1884. // Locate a PEI Core instance and if found extract the machine type and entry point address
  1885. //
  1886. Status = FindCorePeSection(FvImage->FileImage, FvInfo->Size, EFI_FV_FILETYPE_PEI_CORE, &PeiPe32);
  1887. if (!EFI_ERROR(Status)) {
  1888. Status = GetCoreMachineType(PeiPe32, &PeiMachineType);
  1889. if (EFI_ERROR(Status)) {
  1890. Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for PEI Core.");
  1891. return EFI_ABORTED;
  1892. }
  1893. Status = GetCoreEntryPointAddress(FvImage->FileImage, FvInfo, PeiPe32, &PeiCoreEntryAddress);
  1894. if (EFI_ERROR(Status)) {
  1895. Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 entry point address for PEI Core.");
  1896. return EFI_ABORTED;
  1897. }
  1898. VerboseMsg("UpdateArmResetVectorIfNeeded found PEI core entry at 0x%llx", (unsigned long long)PeiCoreEntryAddress);
  1899. // if we previously found an SEC Core make sure machine types match
  1900. if (UpdateVectorSec && (MachineType != PeiMachineType)) {
  1901. Error(NULL, 0, 3000, "Invalid", "SEC and PEI machine types do not match, can't update reset vector");
  1902. return EFI_ABORTED;
  1903. }
  1904. else {
  1905. MachineType = PeiMachineType;
  1906. }
  1907. UpdateVectorPei = TRUE;
  1908. }
  1909. if (!UpdateVectorSec && !UpdateVectorPei) {
  1910. return EFI_SUCCESS;
  1911. }
  1912. if (MachineType == EFI_IMAGE_MACHINE_ARMT) {
  1913. // ARM: Array of 4 UINT32s:
  1914. // 0 - is branch relative to SEC entry point
  1915. // 1 - PEI Entry Point
  1916. // 2 - movs pc,lr for a SWI handler
  1917. // 3 - Place holder for Common Exception Handler
  1918. UINT32 ResetVector[4];
  1919. memset(ResetVector, 0, sizeof (ResetVector));
  1920. // if we found an SEC core entry point then generate a branch instruction
  1921. // to it and populate a debugger SWI entry as well
  1922. if (UpdateVectorSec) {
  1923. UINT32 EntryOffset;
  1924. VerboseMsg("UpdateArmResetVectorIfNeeded updating ARM SEC vector");
  1925. EntryOffset = (INT32)(SecCoreEntryAddress - FvInfo->BaseAddress);
  1926. if (EntryOffset > ARM_JUMP_OFFSET_MAX) {
  1927. Error(NULL, 0, 3000, "Invalid", "SEC Entry point offset above 1MB of the start of the FV");
  1928. return EFI_ABORTED;
  1929. }
  1930. if ((SecCoreEntryAddress & 1) != 0) {
  1931. ResetVector[0] = ARM_JUMP_TO_THUMB(EntryOffset);
  1932. } else {
  1933. ResetVector[0] = ARM_JUMP_TO_ARM(EntryOffset);
  1934. }
  1935. // SWI handler movs pc,lr. Just in case a debugger uses SWI
  1936. ResetVector[2] = ARM_RETURN_FROM_EXCEPTION;
  1937. // Place holder to support a common interrupt handler from ROM.
  1938. // Currently not supported. For this to be used the reset vector would not be in this FV
  1939. // and the exception vectors would be hard coded in the ROM and just through this address
  1940. // to find a common handler in the a module in the FV.
  1941. ResetVector[3] = 0;
  1942. }
  1943. // if a PEI core entry was found place its address in the vector area
  1944. if (UpdateVectorPei) {
  1945. VerboseMsg("UpdateArmResetVectorIfNeeded updating ARM PEI address");
  1946. // Address of PEI Core, if we have one
  1947. ResetVector[1] = (UINT32)PeiCoreEntryAddress;
  1948. }
  1949. //
  1950. // Copy to the beginning of the FV
  1951. //
  1952. memcpy(FvImage->FileImage, ResetVector, sizeof (ResetVector));
  1953. } else if (MachineType == EFI_IMAGE_MACHINE_AARCH64) {
  1954. // AArch64: Used as UINT64 ResetVector[2]
  1955. // 0 - is branch relative to SEC entry point
  1956. // 1 - PEI Entry Point
  1957. UINT64 ResetVector[2];
  1958. memset(ResetVector, 0, sizeof (ResetVector));
  1959. /* NOTE:
  1960. ARMT above has an entry in ResetVector[2] for SWI. The way we are using the ResetVector
  1961. array at the moment, for AArch64, does not allow us space for this as the header only
  1962. allows for a fixed amount of bytes at the start. If we are sure that UEFI will live
  1963. within the first 4GB of addressable RAM we could potentially adopt the same ResetVector
  1964. layout as above. But for the moment we replace the four 32bit vectors with two 64bit
  1965. vectors in the same area of the Image heasder. This allows UEFI to start from a 64bit
  1966. base.
  1967. */
  1968. // if we found an SEC core entry point then generate a branch instruction to it
  1969. if (UpdateVectorSec) {
  1970. VerboseMsg("UpdateArmResetVectorIfNeeded updating AArch64 SEC vector");
  1971. ResetVector[0] = (UINT64)(SecCoreEntryAddress - FvInfo->BaseAddress) >> 2;
  1972. // B SecEntryPoint - signed_immed_26 part +/-128MB offset
  1973. if (ResetVector[0] > 0x03FFFFFF) {
  1974. Error(NULL, 0, 3000, "Invalid", "SEC Entry point must be within 128MB of the start of the FV");
  1975. return EFI_ABORTED;
  1976. }
  1977. // Add opcode for an unconditional branch with no link. i.e.: " B SecEntryPoint"
  1978. ResetVector[0] |= ARM64_UNCONDITIONAL_JUMP_INSTRUCTION;
  1979. }
  1980. // if a PEI core entry was found place its address in the vector area
  1981. if (UpdateVectorPei) {
  1982. VerboseMsg("UpdateArmResetVectorIfNeeded updating AArch64 PEI address");
  1983. // Address of PEI Core, if we have one
  1984. ResetVector[1] = (UINT64)PeiCoreEntryAddress;
  1985. }
  1986. //
  1987. // Copy to the beginning of the FV
  1988. //
  1989. memcpy(FvImage->FileImage, ResetVector, sizeof (ResetVector));
  1990. } else {
  1991. Error(NULL, 0, 3000, "Invalid", "Unknown machine type");
  1992. return EFI_ABORTED;
  1993. }
  1994. return EFI_SUCCESS;
  1995. }
  1996. EFI_STATUS
  1997. UpdateRiscvResetVectorIfNeeded (
  1998. MEMORY_FILE *FvImage,
  1999. FV_INFO *FvInfo
  2000. )
  2001. /*++
  2002. Routine Description:
  2003. This parses the FV looking for SEC and patches that address into the
  2004. beginning of the FV header.
  2005. For RISC-V ISA, the reset vector is at 0xfff~ff00h or 200h
  2006. Arguments:
  2007. FvImage Memory file for the FV memory image/
  2008. FvInfo Information read from INF file.
  2009. Returns:
  2010. EFI_SUCCESS Function Completed successfully.
  2011. EFI_ABORTED Error encountered.
  2012. EFI_INVALID_PARAMETER A required parameter was NULL.
  2013. EFI_NOT_FOUND PEI Core file not found.
  2014. --*/
  2015. {
  2016. EFI_STATUS Status;
  2017. UINT16 MachineType;
  2018. EFI_FILE_SECTION_POINTER SecPe32;
  2019. EFI_PHYSICAL_ADDRESS SecCoreEntryAddress;
  2020. UINT32 bSecCore;
  2021. UINT32 tmp;
  2022. //
  2023. // Verify input parameters
  2024. //
  2025. if (FvImage == NULL || FvInfo == NULL) {
  2026. return EFI_INVALID_PARAMETER;
  2027. }
  2028. //
  2029. // Initialize FV library
  2030. //
  2031. InitializeFvLib (FvImage->FileImage, FvInfo->Size);
  2032. //
  2033. // Find the Sec Core
  2034. //
  2035. Status = FindCorePeSection(FvImage->FileImage, FvInfo->Size, EFI_FV_FILETYPE_SECURITY_CORE, &SecPe32);
  2036. if(EFI_ERROR(Status)) {
  2037. printf("skip because Secutiry Core not found\n");
  2038. return EFI_SUCCESS;
  2039. }
  2040. DebugMsg (NULL, 0, 9, "Update SEC core in FV Header", NULL);
  2041. Status = GetCoreMachineType(SecPe32, &MachineType);
  2042. if(EFI_ERROR(Status)) {
  2043. Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for SEC core.");
  2044. return EFI_ABORTED;
  2045. }
  2046. if (MachineType != EFI_IMAGE_MACHINE_RISCV64) {
  2047. Error(NULL, 0, 3000, "Invalid", "Could not update SEC core because Machine type is not RiscV.");
  2048. return EFI_ABORTED;
  2049. }
  2050. Status = GetCoreEntryPointAddress(FvImage->FileImage, FvInfo, SecPe32, &SecCoreEntryAddress);
  2051. if(EFI_ERROR(Status)) {
  2052. Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 entry point address for SEC Core.");
  2053. return EFI_ABORTED;
  2054. }
  2055. VerboseMsg("SecCore entry point Address = 0x%llX", (unsigned long long) SecCoreEntryAddress);
  2056. VerboseMsg("BaseAddress = 0x%llX", (unsigned long long) FvInfo->BaseAddress);
  2057. bSecCore = (UINT32)(SecCoreEntryAddress - FvInfo->BaseAddress);
  2058. VerboseMsg("offset = 0x%X", bSecCore);
  2059. if(bSecCore > 0x0fffff) {
  2060. Error(NULL, 0, 3000, "Invalid", "SEC Entry point must be within 1MB of start of the FV");
  2061. return EFI_ABORTED;
  2062. }
  2063. tmp = bSecCore;
  2064. bSecCore = 0;
  2065. //J-type
  2066. bSecCore = (tmp&0x100000)<<11; //imm[20] at bit[31]
  2067. bSecCore |= (tmp&0x0007FE)<<20; //imm[10:1] at bit[30:21]
  2068. bSecCore |= (tmp&0x000800)<<9; //imm[11] at bit[20]
  2069. bSecCore |= (tmp&0x0FF000); //imm[19:12] at bit[19:12]
  2070. bSecCore |= 0x6F; //JAL opcode
  2071. memcpy(FvImage->FileImage, &bSecCore, sizeof(bSecCore));
  2072. return EFI_SUCCESS;
  2073. }
  2074. EFI_STATUS
  2075. UpdateLoongArchResetVectorIfNeeded (
  2076. IN MEMORY_FILE *FvImage,
  2077. IN FV_INFO *FvInfo
  2078. )
  2079. /*++
  2080. Routine Description:
  2081. This parses the FV looking for SEC and patches that address into the
  2082. beginning of the FV header.
  2083. For LoongArch ISA, the reset vector is at 0x1c000000.
  2084. We relocate it to SecCoreEntry and copy the ResetVector code to the
  2085. beginning of the FV.
  2086. Arguments:
  2087. FvImage Memory file for the FV memory image
  2088. FvInfo Information read from INF file.
  2089. Returns:
  2090. EFI_SUCCESS Function Completed successfully.
  2091. EFI_ABORTED Error encountered.
  2092. EFI_INVALID_PARAMETER A required parameter was NULL.
  2093. EFI_NOT_FOUND PEI Core file not found.
  2094. --*/
  2095. {
  2096. EFI_STATUS Status;
  2097. EFI_FILE_SECTION_POINTER SecPe32;
  2098. BOOLEAN UpdateVectorSec = FALSE;
  2099. UINT16 MachineType = 0;
  2100. EFI_PHYSICAL_ADDRESS SecCoreEntryAddress = 0;
  2101. //
  2102. // Verify input parameters
  2103. //
  2104. if (FvImage == NULL || FvInfo == NULL) {
  2105. return EFI_INVALID_PARAMETER;
  2106. }
  2107. //
  2108. // Locate an SEC Core instance and if found extract the machine type and entry point address
  2109. //
  2110. Status = FindCorePeSection(FvImage->FileImage, FvInfo->Size, EFI_FV_FILETYPE_SECURITY_CORE, &SecPe32);
  2111. if (!EFI_ERROR(Status)) {
  2112. Status = GetCoreMachineType(SecPe32, &MachineType);
  2113. if (EFI_ERROR(Status)) {
  2114. Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for SEC Core.");
  2115. return EFI_ABORTED;
  2116. }
  2117. Status = GetCoreEntryPointAddress(FvImage->FileImage, FvInfo, SecPe32, &SecCoreEntryAddress);
  2118. if (EFI_ERROR(Status)) {
  2119. Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 entry point address for SEC Core.");
  2120. return EFI_ABORTED;
  2121. }
  2122. UpdateVectorSec = TRUE;
  2123. }
  2124. if (!UpdateVectorSec)
  2125. return EFI_SUCCESS;
  2126. if (MachineType == EFI_IMAGE_MACHINE_LOONGARCH64) {
  2127. UINT32 ResetVector[1];
  2128. memset(ResetVector, 0, sizeof (ResetVector));
  2129. /* if we found an SEC core entry point then generate a branch instruction */
  2130. if (UpdateVectorSec) {
  2131. VerboseMsg("UpdateLoongArchResetVectorIfNeeded updating LOONGARCH64 SEC vector");
  2132. ResetVector[0] = ((SecCoreEntryAddress - FvInfo->BaseAddress) & 0x3FFFFFF) >> 2;
  2133. ResetVector[0] = ((ResetVector[0] & 0x0FFFF) << 10) | ((ResetVector[0] >> 16) & 0x3FF);
  2134. ResetVector[0] |= 0x50000000; /* b offset */
  2135. }
  2136. //
  2137. // Copy to the beginning of the FV
  2138. //
  2139. memcpy(FvImage->FileImage, ResetVector, sizeof (ResetVector));
  2140. } else {
  2141. Error(NULL, 0, 3000, "Invalid", "Unknown machine type");
  2142. return EFI_ABORTED;
  2143. }
  2144. return EFI_SUCCESS;
  2145. }
  2146. EFI_STATUS
  2147. GetPe32Info (
  2148. IN UINT8 *Pe32,
  2149. OUT UINT32 *EntryPoint,
  2150. OUT UINT32 *BaseOfCode,
  2151. OUT UINT16 *MachineType
  2152. )
  2153. /*++
  2154. Routine Description:
  2155. Retrieves the PE32 entry point offset and machine type from PE image or TeImage.
  2156. See EfiImage.h for machine types. The entry point offset is from the beginning
  2157. of the PE32 buffer passed in.
  2158. Arguments:
  2159. Pe32 Beginning of the PE32.
  2160. EntryPoint Offset from the beginning of the PE32 to the image entry point.
  2161. BaseOfCode Base address of code.
  2162. MachineType Magic number for the machine type.
  2163. Returns:
  2164. EFI_SUCCESS Function completed successfully.
  2165. EFI_ABORTED Error encountered.
  2166. EFI_INVALID_PARAMETER A required parameter was NULL.
  2167. EFI_UNSUPPORTED The operation is unsupported.
  2168. --*/
  2169. {
  2170. EFI_IMAGE_DOS_HEADER *DosHeader;
  2171. EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
  2172. EFI_TE_IMAGE_HEADER *TeHeader;
  2173. //
  2174. // Verify input parameters
  2175. //
  2176. if (Pe32 == NULL) {
  2177. return EFI_INVALID_PARAMETER;
  2178. }
  2179. //
  2180. // First check whether it is one TE Image.
  2181. //
  2182. TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32;
  2183. if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
  2184. //
  2185. // By TeImage Header to get output
  2186. //
  2187. *EntryPoint = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
  2188. *BaseOfCode = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize;
  2189. *MachineType = TeHeader->Machine;
  2190. } else {
  2191. //
  2192. // Then check whether
  2193. // First is the DOS header
  2194. //
  2195. DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32;
  2196. //
  2197. // Verify DOS header is expected
  2198. //
  2199. if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
  2200. Error (NULL, 0, 3000, "Invalid", "Unknown magic number in the DOS header, 0x%04X.", DosHeader->e_magic);
  2201. return EFI_UNSUPPORTED;
  2202. }
  2203. //
  2204. // Immediately following is the NT header.
  2205. //
  2206. ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINTN) Pe32 + DosHeader->e_lfanew);
  2207. //
  2208. // Verify NT header is expected
  2209. //
  2210. if (ImgHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
  2211. Error (NULL, 0, 3000, "Invalid", "Unrecognized image signature 0x%08X.", (unsigned) ImgHdr->Pe32.Signature);
  2212. return EFI_UNSUPPORTED;
  2213. }
  2214. //
  2215. // Get output
  2216. //
  2217. *EntryPoint = ImgHdr->Pe32.OptionalHeader.AddressOfEntryPoint;
  2218. *BaseOfCode = ImgHdr->Pe32.OptionalHeader.BaseOfCode;
  2219. *MachineType = ImgHdr->Pe32.FileHeader.Machine;
  2220. }
  2221. //
  2222. // Verify machine type is supported
  2223. //
  2224. if ((*MachineType != EFI_IMAGE_MACHINE_IA32) && (*MachineType != EFI_IMAGE_MACHINE_X64) && (*MachineType != EFI_IMAGE_MACHINE_EBC) &&
  2225. (*MachineType != EFI_IMAGE_MACHINE_ARMT) && (*MachineType != EFI_IMAGE_MACHINE_AARCH64) &&
  2226. (*MachineType != EFI_IMAGE_MACHINE_RISCV64) && (*MachineType != EFI_IMAGE_MACHINE_LOONGARCH64)) {
  2227. Error (NULL, 0, 3000, "Invalid", "Unrecognized machine type in the PE32 file.");
  2228. return EFI_UNSUPPORTED;
  2229. }
  2230. return EFI_SUCCESS;
  2231. }
  2232. EFI_STATUS
  2233. GenerateFvImage (
  2234. IN CHAR8 *InfFileImage,
  2235. IN UINTN InfFileSize,
  2236. IN CHAR8 *FvFileName,
  2237. IN CHAR8 *MapFileName
  2238. )
  2239. /*++
  2240. Routine Description:
  2241. This is the main function which will be called from application.
  2242. Arguments:
  2243. InfFileImage Buffer containing the INF file contents.
  2244. InfFileSize Size of the contents of the InfFileImage buffer.
  2245. FvFileName Requested name for the FV file.
  2246. MapFileName Fv map file to log fv driver information.
  2247. Returns:
  2248. EFI_SUCCESS Function completed successfully.
  2249. EFI_OUT_OF_RESOURCES Could not allocate required resources.
  2250. EFI_ABORTED Error encountered.
  2251. EFI_INVALID_PARAMETER A required parameter was NULL.
  2252. --*/
  2253. {
  2254. EFI_STATUS Status;
  2255. MEMORY_FILE InfMemoryFile;
  2256. MEMORY_FILE FvImageMemoryFile;
  2257. UINTN Index;
  2258. EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
  2259. EFI_FFS_FILE_HEADER *VtfFileImage;
  2260. UINT8 *FvBufferHeader; // to make sure fvimage header 8 type alignment.
  2261. UINT8 *FvImage;
  2262. UINTN FvImageSize;
  2263. FILE *FvFile;
  2264. CHAR8 *FvMapName;
  2265. FILE *FvMapFile;
  2266. EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader;
  2267. FILE *FvExtHeaderFile;
  2268. UINTN FileSize;
  2269. CHAR8 *FvReportName;
  2270. FILE *FvReportFile;
  2271. FvBufferHeader = NULL;
  2272. FvFile = NULL;
  2273. FvMapName = NULL;
  2274. FvMapFile = NULL;
  2275. FvReportName = NULL;
  2276. FvReportFile = NULL;
  2277. if (InfFileImage != NULL) {
  2278. //
  2279. // Initialize file structures
  2280. //
  2281. InfMemoryFile.FileImage = InfFileImage;
  2282. InfMemoryFile.CurrentFilePointer = InfFileImage;
  2283. InfMemoryFile.Eof = InfFileImage + InfFileSize;
  2284. //
  2285. // Parse the FV inf file for header information
  2286. //
  2287. Status = ParseFvInf (&InfMemoryFile, &mFvDataInfo);
  2288. if (EFI_ERROR (Status)) {
  2289. Error (NULL, 0, 0003, "Error parsing file", "the input FV INF file.");
  2290. return Status;
  2291. }
  2292. }
  2293. //
  2294. // Update the file name return values
  2295. //
  2296. if (FvFileName == NULL && mFvDataInfo.FvName[0] != '\0') {
  2297. FvFileName = mFvDataInfo.FvName;
  2298. }
  2299. if (FvFileName == NULL) {
  2300. Error (NULL, 0, 1001, "Missing option", "Output file name");
  2301. return EFI_ABORTED;
  2302. }
  2303. if (mFvDataInfo.FvBlocks[0].Length == 0) {
  2304. Error (NULL, 0, 1001, "Missing required argument", "Block Size");
  2305. return EFI_ABORTED;
  2306. }
  2307. //
  2308. // Debug message Fv File System Guid
  2309. //
  2310. if (mFvDataInfo.FvFileSystemGuidSet) {
  2311. DebugMsg (NULL, 0, 9, "FV File System Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
  2312. (unsigned) mFvDataInfo.FvFileSystemGuid.Data1,
  2313. mFvDataInfo.FvFileSystemGuid.Data2,
  2314. mFvDataInfo.FvFileSystemGuid.Data3,
  2315. mFvDataInfo.FvFileSystemGuid.Data4[0],
  2316. mFvDataInfo.FvFileSystemGuid.Data4[1],
  2317. mFvDataInfo.FvFileSystemGuid.Data4[2],
  2318. mFvDataInfo.FvFileSystemGuid.Data4[3],
  2319. mFvDataInfo.FvFileSystemGuid.Data4[4],
  2320. mFvDataInfo.FvFileSystemGuid.Data4[5],
  2321. mFvDataInfo.FvFileSystemGuid.Data4[6],
  2322. mFvDataInfo.FvFileSystemGuid.Data4[7]);
  2323. }
  2324. //
  2325. // Add PI FV extension header
  2326. //
  2327. FvExtHeader = NULL;
  2328. FvExtHeaderFile = NULL;
  2329. if (mFvDataInfo.FvExtHeaderFile[0] != 0) {
  2330. //
  2331. // Open the FV Extension Header file
  2332. //
  2333. FvExtHeaderFile = fopen (LongFilePath (mFvDataInfo.FvExtHeaderFile), "rb");
  2334. if (FvExtHeaderFile == NULL) {
  2335. Error (NULL, 0, 0001, "Error opening file", mFvDataInfo.FvExtHeaderFile);
  2336. return EFI_ABORTED;
  2337. }
  2338. //
  2339. // Get the file size
  2340. //
  2341. FileSize = _filelength (fileno (FvExtHeaderFile));
  2342. //
  2343. // Allocate a buffer for the FV Extension Header
  2344. //
  2345. FvExtHeader = malloc(FileSize);
  2346. if (FvExtHeader == NULL) {
  2347. fclose (FvExtHeaderFile);
  2348. return EFI_OUT_OF_RESOURCES;
  2349. }
  2350. //
  2351. // Read the FV Extension Header
  2352. //
  2353. fread (FvExtHeader, sizeof (UINT8), FileSize, FvExtHeaderFile);
  2354. fclose (FvExtHeaderFile);
  2355. //
  2356. // See if there is an override for the FV Name GUID
  2357. //
  2358. if (mFvDataInfo.FvNameGuidSet) {
  2359. memcpy (&FvExtHeader->FvName, &mFvDataInfo.FvNameGuid, sizeof (EFI_GUID));
  2360. }
  2361. memcpy (&mFvDataInfo.FvNameGuid, &FvExtHeader->FvName, sizeof (EFI_GUID));
  2362. mFvDataInfo.FvNameGuidSet = TRUE;
  2363. } else if (mFvDataInfo.FvNameGuidSet) {
  2364. //
  2365. // Allocate a buffer for the FV Extension Header
  2366. //
  2367. FvExtHeader = malloc(sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER));
  2368. if (FvExtHeader == NULL) {
  2369. return EFI_OUT_OF_RESOURCES;
  2370. }
  2371. memcpy (&FvExtHeader->FvName, &mFvDataInfo.FvNameGuid, sizeof (EFI_GUID));
  2372. FvExtHeader->ExtHeaderSize = sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER);
  2373. }
  2374. //
  2375. // Debug message Fv Name Guid
  2376. //
  2377. if (mFvDataInfo.FvNameGuidSet) {
  2378. DebugMsg (NULL, 0, 9, "FV Name Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
  2379. (unsigned) mFvDataInfo.FvNameGuid.Data1,
  2380. mFvDataInfo.FvNameGuid.Data2,
  2381. mFvDataInfo.FvNameGuid.Data3,
  2382. mFvDataInfo.FvNameGuid.Data4[0],
  2383. mFvDataInfo.FvNameGuid.Data4[1],
  2384. mFvDataInfo.FvNameGuid.Data4[2],
  2385. mFvDataInfo.FvNameGuid.Data4[3],
  2386. mFvDataInfo.FvNameGuid.Data4[4],
  2387. mFvDataInfo.FvNameGuid.Data4[5],
  2388. mFvDataInfo.FvNameGuid.Data4[6],
  2389. mFvDataInfo.FvNameGuid.Data4[7]);
  2390. }
  2391. if (CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0 ||
  2392. CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem3Guid) == 0) {
  2393. mFvDataInfo.IsPiFvImage = TRUE;
  2394. }
  2395. //
  2396. // FvMap file to log the function address of all modules in one Fvimage
  2397. //
  2398. if (MapFileName != NULL) {
  2399. if (strlen (MapFileName) > MAX_LONG_FILE_PATH - 1) {
  2400. Error (NULL, 0, 1003, "Invalid option value", "MapFileName %s is too long!", MapFileName);
  2401. Status = EFI_ABORTED;
  2402. goto Finish;
  2403. }
  2404. FvMapName = malloc (strlen (MapFileName) + 1);
  2405. if (FvMapName == NULL) {
  2406. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  2407. Status = EFI_OUT_OF_RESOURCES;
  2408. goto Finish;
  2409. }
  2410. strcpy (FvMapName, MapFileName);
  2411. } else {
  2412. if (strlen (FvFileName) + strlen (".map") > MAX_LONG_FILE_PATH - 1) {
  2413. Error (NULL, 0, 1003, "Invalid option value", "FvFileName %s is too long!", FvFileName);
  2414. Status = EFI_ABORTED;
  2415. goto Finish;
  2416. }
  2417. FvMapName = malloc (strlen (FvFileName) + strlen (".map") + 1);
  2418. if (FvMapName == NULL) {
  2419. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  2420. Status = EFI_OUT_OF_RESOURCES;
  2421. goto Finish;
  2422. }
  2423. strcpy (FvMapName, FvFileName);
  2424. strcat (FvMapName, ".map");
  2425. }
  2426. VerboseMsg ("FV Map file name is %s", FvMapName);
  2427. //
  2428. // FvReport file to log the FV information in one Fvimage
  2429. //
  2430. if (strlen (FvFileName) + strlen (".txt") > MAX_LONG_FILE_PATH - 1) {
  2431. Error (NULL, 0, 1003, "Invalid option value", "FvFileName %s is too long!", FvFileName);
  2432. Status = EFI_ABORTED;
  2433. goto Finish;
  2434. }
  2435. FvReportName = malloc (strlen (FvFileName) + strlen (".txt") + 1);
  2436. if (FvReportName == NULL) {
  2437. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
  2438. Status = EFI_OUT_OF_RESOURCES;
  2439. goto Finish;
  2440. }
  2441. strcpy (FvReportName, FvFileName);
  2442. strcat (FvReportName, ".txt");
  2443. //
  2444. // Calculate the FV size and Update Fv Size based on the actual FFS files.
  2445. // And Update mFvDataInfo data.
  2446. //
  2447. Status = CalculateFvSize (&mFvDataInfo);
  2448. if (EFI_ERROR (Status)) {
  2449. goto Finish;
  2450. }
  2451. VerboseMsg ("the generated FV image size is %u bytes", (unsigned) mFvDataInfo.Size);
  2452. //
  2453. // support fv image and empty fv image
  2454. //
  2455. FvImageSize = mFvDataInfo.Size;
  2456. //
  2457. // Allocate the FV, assure FvImage Header 8 byte alignment
  2458. //
  2459. FvBufferHeader = malloc (FvImageSize + sizeof (UINT64));
  2460. if (FvBufferHeader == NULL) {
  2461. Status = EFI_OUT_OF_RESOURCES;
  2462. goto Finish;
  2463. }
  2464. FvImage = (UINT8 *) (((UINTN) FvBufferHeader + 7) & ~7);
  2465. //
  2466. // Initialize the FV to the erase polarity
  2467. //
  2468. if (mFvDataInfo.FvAttributes == 0) {
  2469. //
  2470. // Set Default Fv Attribute
  2471. //
  2472. mFvDataInfo.FvAttributes = FV_DEFAULT_ATTRIBUTE;
  2473. }
  2474. if (mFvDataInfo.FvAttributes & EFI_FVB2_ERASE_POLARITY) {
  2475. memset (FvImage, -1, FvImageSize);
  2476. } else {
  2477. memset (FvImage, 0, FvImageSize);
  2478. }
  2479. //
  2480. // Initialize FV header
  2481. //
  2482. FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage;
  2483. //
  2484. // Initialize the zero vector to all zeros.
  2485. //
  2486. memset (FvHeader->ZeroVector, 0, 16);
  2487. //
  2488. // Copy the Fv file system GUID
  2489. //
  2490. memcpy (&FvHeader->FileSystemGuid, &mFvDataInfo.FvFileSystemGuid, sizeof (EFI_GUID));
  2491. FvHeader->FvLength = FvImageSize;
  2492. FvHeader->Signature = EFI_FVH_SIGNATURE;
  2493. FvHeader->Attributes = mFvDataInfo.FvAttributes;
  2494. FvHeader->Revision = EFI_FVH_REVISION;
  2495. FvHeader->ExtHeaderOffset = 0;
  2496. FvHeader->Reserved[0] = 0;
  2497. //
  2498. // Copy firmware block map
  2499. //
  2500. for (Index = 0; mFvDataInfo.FvBlocks[Index].Length != 0; Index++) {
  2501. FvHeader->BlockMap[Index].NumBlocks = mFvDataInfo.FvBlocks[Index].NumBlocks;
  2502. FvHeader->BlockMap[Index].Length = mFvDataInfo.FvBlocks[Index].Length;
  2503. }
  2504. //
  2505. // Add block map terminator
  2506. //
  2507. FvHeader->BlockMap[Index].NumBlocks = 0;
  2508. FvHeader->BlockMap[Index].Length = 0;
  2509. //
  2510. // Complete the header
  2511. //
  2512. FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->BlockMap[Index + 1])) - (UINTN) FvImage);
  2513. FvHeader->Checksum = 0;
  2514. FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
  2515. //
  2516. // If there is no FFS file, generate one empty FV
  2517. //
  2518. if (mFvDataInfo.FvFiles[0][0] == 0 && !mFvDataInfo.FvNameGuidSet) {
  2519. goto WriteFile;
  2520. }
  2521. //
  2522. // Initialize our "file" view of the buffer
  2523. //
  2524. FvImageMemoryFile.FileImage = (CHAR8 *)FvImage;
  2525. FvImageMemoryFile.CurrentFilePointer = (CHAR8 *)FvImage + FvHeader->HeaderLength;
  2526. FvImageMemoryFile.Eof = (CHAR8 *)FvImage + FvImageSize;
  2527. //
  2528. // Initialize the FV library.
  2529. //
  2530. InitializeFvLib (FvImageMemoryFile.FileImage, FvImageSize);
  2531. //
  2532. // Initialize the VTF file address.
  2533. //
  2534. VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof;
  2535. //
  2536. // Open FvMap file
  2537. //
  2538. FvMapFile = fopen (LongFilePath (FvMapName), "w");
  2539. if (FvMapFile == NULL) {
  2540. Error (NULL, 0, 0001, "Error opening file", FvMapName);
  2541. Status = EFI_ABORTED;
  2542. goto Finish;
  2543. }
  2544. //
  2545. // Open FvReport file
  2546. //
  2547. FvReportFile = fopen (LongFilePath (FvReportName), "w");
  2548. if (FvReportFile == NULL) {
  2549. Error (NULL, 0, 0001, "Error opening file", FvReportName);
  2550. Status = EFI_ABORTED;
  2551. goto Finish;
  2552. }
  2553. //
  2554. // record FV size information into FvMap file.
  2555. //
  2556. if (mFvTotalSize != 0) {
  2557. fprintf (FvMapFile, EFI_FV_TOTAL_SIZE_STRING);
  2558. fprintf (FvMapFile, " = 0x%x\n", (unsigned) mFvTotalSize);
  2559. }
  2560. if (mFvTakenSize != 0) {
  2561. fprintf (FvMapFile, EFI_FV_TAKEN_SIZE_STRING);
  2562. fprintf (FvMapFile, " = 0x%x\n", (unsigned) mFvTakenSize);
  2563. }
  2564. if (mFvTotalSize != 0 && mFvTakenSize != 0) {
  2565. fprintf (FvMapFile, EFI_FV_SPACE_SIZE_STRING);
  2566. fprintf (FvMapFile, " = 0x%x\n\n", (unsigned) (mFvTotalSize - mFvTakenSize));
  2567. }
  2568. //
  2569. // record FV size information to FvReportFile.
  2570. //
  2571. fprintf (FvReportFile, "%s = 0x%x\n", EFI_FV_TOTAL_SIZE_STRING, (unsigned) mFvTotalSize);
  2572. fprintf (FvReportFile, "%s = 0x%x\n", EFI_FV_TAKEN_SIZE_STRING, (unsigned) mFvTakenSize);
  2573. //
  2574. // Add PI FV extension header
  2575. //
  2576. if (FvExtHeader != NULL) {
  2577. //
  2578. // Add FV Extended Header contents to the FV as a PAD file
  2579. //
  2580. AddPadFile (&FvImageMemoryFile, 4, VtfFileImage, FvExtHeader, 0);
  2581. //
  2582. // Fv Extension header change update Fv Header Check sum
  2583. //
  2584. FvHeader->Checksum = 0;
  2585. FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
  2586. }
  2587. //
  2588. // Add files to FV
  2589. //
  2590. for (Index = 0; mFvDataInfo.FvFiles[Index][0] != 0; Index++) {
  2591. //
  2592. // Add the file
  2593. //
  2594. Status = AddFile (&FvImageMemoryFile, &mFvDataInfo, Index, &VtfFileImage, FvMapFile, FvReportFile);
  2595. //
  2596. // Exit if error detected while adding the file
  2597. //
  2598. if (EFI_ERROR (Status)) {
  2599. goto Finish;
  2600. }
  2601. }
  2602. //
  2603. // If there is a VTF file, some special actions need to occur.
  2604. //
  2605. if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) {
  2606. //
  2607. // Pad from the end of the last file to the beginning of the VTF file.
  2608. // If the left space is less than sizeof (EFI_FFS_FILE_HEADER)?
  2609. //
  2610. Status = PadFvImage (&FvImageMemoryFile, VtfFileImage);
  2611. if (EFI_ERROR (Status)) {
  2612. Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add pad file between the last file and the VTF file.");
  2613. goto Finish;
  2614. }
  2615. if (!mArm && !mRiscV && !mLoongArch) {
  2616. //
  2617. // Update reset vector (SALE_ENTRY for IPF)
  2618. // Now for IA32 and IA64 platform, the fv which has bsf file must have the
  2619. // EndAddress of 0xFFFFFFFF (unless the section was rebased).
  2620. // Thus, only this type fv needs to update the reset vector.
  2621. // If the PEI Core is found, the VTF file will probably get
  2622. // corrupted by updating the entry point.
  2623. //
  2624. if (mFvDataInfo.ForceRebase == 1 ||
  2625. (mFvDataInfo.BaseAddress + mFvDataInfo.Size) == FV_IMAGES_TOP_ADDRESS) {
  2626. Status = UpdateResetVector (&FvImageMemoryFile, &mFvDataInfo, VtfFileImage);
  2627. if (EFI_ERROR(Status)) {
  2628. Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector.");
  2629. goto Finish;
  2630. }
  2631. DebugMsg (NULL, 0, 9, "Update Reset vector in VTF file", NULL);
  2632. }
  2633. }
  2634. }
  2635. if (mArm) {
  2636. Status = UpdateArmResetVectorIfNeeded (&FvImageMemoryFile, &mFvDataInfo);
  2637. if (EFI_ERROR (Status)) {
  2638. Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector.");
  2639. goto Finish;
  2640. }
  2641. //
  2642. // Update Checksum for FvHeader
  2643. //
  2644. FvHeader->Checksum = 0;
  2645. FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
  2646. }
  2647. if (mRiscV) {
  2648. //
  2649. // Update RISCV reset vector.
  2650. //
  2651. Status = UpdateRiscvResetVectorIfNeeded (&FvImageMemoryFile, &mFvDataInfo);
  2652. if (EFI_ERROR (Status)) {
  2653. Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector for RISC-V.");
  2654. goto Finish;
  2655. }
  2656. //
  2657. // Update Checksum for FvHeader
  2658. //
  2659. FvHeader->Checksum = 0;
  2660. FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
  2661. }
  2662. if (mLoongArch) {
  2663. Status = UpdateLoongArchResetVectorIfNeeded (&FvImageMemoryFile, &mFvDataInfo);
  2664. if (EFI_ERROR (Status)) {
  2665. Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector.");
  2666. goto Finish;
  2667. }
  2668. //
  2669. // Update Checksum for FvHeader
  2670. //
  2671. FvHeader->Checksum = 0;
  2672. FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
  2673. }
  2674. //
  2675. // Update FV Alignment attribute to the largest alignment of all the FFS files in the FV
  2676. //
  2677. if (((FvHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) &&
  2678. (((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16)) < MaxFfsAlignment) {
  2679. FvHeader->Attributes = ((MaxFfsAlignment << 16) | (FvHeader->Attributes & 0xFFFF));
  2680. //
  2681. // Update Checksum for FvHeader
  2682. //
  2683. FvHeader->Checksum = 0;
  2684. FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
  2685. }
  2686. //
  2687. // If there are large FFS in FV, the file system GUID should set to system 3 GUID.
  2688. //
  2689. if (mIsLargeFfs && CompareGuid (&FvHeader->FileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0) {
  2690. memcpy (&FvHeader->FileSystemGuid, &mEfiFirmwareFileSystem3Guid, sizeof (EFI_GUID));
  2691. FvHeader->Checksum = 0;
  2692. FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16));
  2693. }
  2694. WriteFile:
  2695. //
  2696. // Write fv file
  2697. //
  2698. FvFile = fopen (LongFilePath (FvFileName), "wb");
  2699. if (FvFile == NULL) {
  2700. Error (NULL, 0, 0001, "Error opening file", FvFileName);
  2701. Status = EFI_ABORTED;
  2702. goto Finish;
  2703. }
  2704. if (fwrite (FvImage, 1, FvImageSize, FvFile) != FvImageSize) {
  2705. Error (NULL, 0, 0002, "Error writing file", FvFileName);
  2706. Status = EFI_ABORTED;
  2707. goto Finish;
  2708. }
  2709. Finish:
  2710. if (FvBufferHeader != NULL) {
  2711. free (FvBufferHeader);
  2712. }
  2713. if (FvExtHeader != NULL) {
  2714. free (FvExtHeader);
  2715. }
  2716. if (FvMapName != NULL) {
  2717. free (FvMapName);
  2718. }
  2719. if (FvReportName != NULL) {
  2720. free (FvReportName);
  2721. }
  2722. if (FvFile != NULL) {
  2723. fflush (FvFile);
  2724. fclose (FvFile);
  2725. }
  2726. if (FvMapFile != NULL) {
  2727. fflush (FvMapFile);
  2728. fclose (FvMapFile);
  2729. }
  2730. if (FvReportFile != NULL) {
  2731. fflush (FvReportFile);
  2732. fclose (FvReportFile);
  2733. }
  2734. return Status;
  2735. }
  2736. EFI_STATUS
  2737. UpdatePeiCoreEntryInFit (
  2738. IN FIT_TABLE *FitTablePtr,
  2739. IN UINT64 PeiCorePhysicalAddress
  2740. )
  2741. /*++
  2742. Routine Description:
  2743. This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from
  2744. Sec to Pei Core
  2745. Arguments:
  2746. FitTablePtr - The pointer of FIT_TABLE.
  2747. PeiCorePhysicalAddress - The address of Pei Core entry.
  2748. Returns:
  2749. EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully.
  2750. EFI_NOT_FOUND - Not found the PEI_CORE FIT entry.
  2751. --*/
  2752. {
  2753. FIT_TABLE *TmpFitPtr;
  2754. UINTN Index;
  2755. UINTN NumFitComponents;
  2756. TmpFitPtr = FitTablePtr;
  2757. NumFitComponents = TmpFitPtr->CompSize;
  2758. for (Index = 0; Index < NumFitComponents; Index++) {
  2759. if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) {
  2760. TmpFitPtr->CompAddress = PeiCorePhysicalAddress;
  2761. return EFI_SUCCESS;
  2762. }
  2763. TmpFitPtr++;
  2764. }
  2765. return EFI_NOT_FOUND;
  2766. }
  2767. VOID
  2768. UpdateFitCheckSum (
  2769. IN FIT_TABLE *FitTablePtr
  2770. )
  2771. /*++
  2772. Routine Description:
  2773. This function is used to update the checksum for FIT.
  2774. Arguments:
  2775. FitTablePtr - The pointer of FIT_TABLE.
  2776. Returns:
  2777. None.
  2778. --*/
  2779. {
  2780. if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) {
  2781. FitTablePtr->CheckSum = 0;
  2782. FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16);
  2783. }
  2784. }
  2785. EFI_STATUS
  2786. CalculateFvSize (
  2787. FV_INFO *FvInfoPtr
  2788. )
  2789. /*++
  2790. Routine Description:
  2791. Calculate the FV size and Update Fv Size based on the actual FFS files.
  2792. And Update FvInfo data.
  2793. Arguments:
  2794. FvInfoPtr - The pointer to FV_INFO structure.
  2795. Returns:
  2796. EFI_ABORTED - Ffs Image Error
  2797. EFI_SUCCESS - Successfully update FvSize
  2798. --*/
  2799. {
  2800. UINTN CurrentOffset;
  2801. UINTN OrigOffset;
  2802. UINTN Index;
  2803. FILE *fpin;
  2804. UINTN FfsFileSize;
  2805. UINTN FvExtendHeaderSize;
  2806. UINT32 FfsAlignment;
  2807. UINT32 FfsHeaderSize;
  2808. EFI_FFS_FILE_HEADER FfsHeader;
  2809. UINTN VtfFileSize;
  2810. UINTN MaxPadFileSize;
  2811. FvExtendHeaderSize = 0;
  2812. MaxPadFileSize = 0;
  2813. VtfFileSize = 0;
  2814. fpin = NULL;
  2815. Index = 0;
  2816. //
  2817. // Compute size for easy access later
  2818. //
  2819. FvInfoPtr->Size = 0;
  2820. for (Index = 0; FvInfoPtr->FvBlocks[Index].NumBlocks > 0 && FvInfoPtr->FvBlocks[Index].Length > 0; Index++) {
  2821. FvInfoPtr->Size += FvInfoPtr->FvBlocks[Index].NumBlocks * FvInfoPtr->FvBlocks[Index].Length;
  2822. }
  2823. //
  2824. // Calculate the required sizes for all FFS files.
  2825. //
  2826. CurrentOffset = sizeof (EFI_FIRMWARE_VOLUME_HEADER);
  2827. for (Index = 1;; Index ++) {
  2828. CurrentOffset += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
  2829. if (FvInfoPtr->FvBlocks[Index].NumBlocks == 0 || FvInfoPtr->FvBlocks[Index].Length == 0) {
  2830. break;
  2831. }
  2832. }
  2833. //
  2834. // Calculate PI extension header
  2835. //
  2836. if (mFvDataInfo.FvExtHeaderFile[0] != '\0') {
  2837. fpin = fopen (LongFilePath (mFvDataInfo.FvExtHeaderFile), "rb");
  2838. if (fpin == NULL) {
  2839. Error (NULL, 0, 0001, "Error opening file", mFvDataInfo.FvExtHeaderFile);
  2840. return EFI_ABORTED;
  2841. }
  2842. FvExtendHeaderSize = _filelength (fileno (fpin));
  2843. fclose (fpin);
  2844. if (sizeof (EFI_FFS_FILE_HEADER) + FvExtendHeaderSize >= MAX_FFS_SIZE) {
  2845. CurrentOffset += sizeof (EFI_FFS_FILE_HEADER2) + FvExtendHeaderSize;
  2846. mIsLargeFfs = TRUE;
  2847. } else {
  2848. CurrentOffset += sizeof (EFI_FFS_FILE_HEADER) + FvExtendHeaderSize;
  2849. }
  2850. CurrentOffset = (CurrentOffset + 7) & (~7);
  2851. } else if (mFvDataInfo.FvNameGuidSet) {
  2852. CurrentOffset += sizeof (EFI_FFS_FILE_HEADER) + sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER);
  2853. CurrentOffset = (CurrentOffset + 7) & (~7);
  2854. }
  2855. //
  2856. // Accumulate every FFS file size.
  2857. //
  2858. for (Index = 0; FvInfoPtr->FvFiles[Index][0] != 0; Index++) {
  2859. //
  2860. // Open FFS file
  2861. //
  2862. fpin = NULL;
  2863. fpin = fopen (LongFilePath (FvInfoPtr->FvFiles[Index]), "rb");
  2864. if (fpin == NULL) {
  2865. Error (NULL, 0, 0001, "Error opening file", FvInfoPtr->FvFiles[Index]);
  2866. return EFI_ABORTED;
  2867. }
  2868. //
  2869. // Get the file size
  2870. //
  2871. FfsFileSize = _filelength (fileno (fpin));
  2872. if (FfsFileSize >= MAX_FFS_SIZE) {
  2873. FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER2);
  2874. mIsLargeFfs = TRUE;
  2875. } else {
  2876. FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER);
  2877. }
  2878. //
  2879. // Read Ffs File header
  2880. //
  2881. fread (&FfsHeader, sizeof (UINT8), sizeof (EFI_FFS_FILE_HEADER), fpin);
  2882. //
  2883. // close file
  2884. //
  2885. fclose (fpin);
  2886. if (FvInfoPtr->IsPiFvImage) {
  2887. //
  2888. // Check whether this ffs file is vtf file
  2889. //
  2890. if (IsVtfFile (&FfsHeader)) {
  2891. if (VtfFileFlag) {
  2892. //
  2893. // One Fv image can't have two vtf files.
  2894. //
  2895. Error (NULL, 0, 3000,"Invalid", "One Fv image can't have two vtf files.");
  2896. return EFI_ABORTED;
  2897. }
  2898. VtfFileFlag = TRUE;
  2899. VtfFileSize = FfsFileSize;
  2900. continue;
  2901. }
  2902. //
  2903. // Get the alignment of FFS file
  2904. //
  2905. ReadFfsAlignment (&FfsHeader, &FfsAlignment);
  2906. FfsAlignment = 1 << FfsAlignment;
  2907. //
  2908. // Add Pad file
  2909. //
  2910. if (((CurrentOffset + FfsHeaderSize) % FfsAlignment) != 0) {
  2911. //
  2912. // Only EFI_FFS_FILE_HEADER is needed for a pad section.
  2913. //
  2914. OrigOffset = CurrentOffset;
  2915. CurrentOffset = (CurrentOffset + FfsHeaderSize + sizeof(EFI_FFS_FILE_HEADER) + FfsAlignment - 1) & ~(FfsAlignment - 1);
  2916. CurrentOffset -= FfsHeaderSize;
  2917. if ((CurrentOffset - OrigOffset) > MaxPadFileSize) {
  2918. MaxPadFileSize = CurrentOffset - OrigOffset;
  2919. }
  2920. }
  2921. }
  2922. //
  2923. // Add ffs file size
  2924. //
  2925. if (FvInfoPtr->SizeofFvFiles[Index] > FfsFileSize) {
  2926. CurrentOffset += FvInfoPtr->SizeofFvFiles[Index];
  2927. } else {
  2928. CurrentOffset += FfsFileSize;
  2929. }
  2930. //
  2931. // Make next ffs file start at QWord Boundary
  2932. //
  2933. if (FvInfoPtr->IsPiFvImage) {
  2934. CurrentOffset = (CurrentOffset + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1);
  2935. }
  2936. }
  2937. CurrentOffset += VtfFileSize;
  2938. DebugMsg (NULL, 0, 9, "FvImage size", "The calculated fv image size is 0x%x and the current set fv image size is 0x%x", (unsigned) CurrentOffset, (unsigned) FvInfoPtr->Size);
  2939. if (FvInfoPtr->Size == 0) {
  2940. //
  2941. // Update FvInfo data
  2942. //
  2943. FvInfoPtr->FvBlocks[0].NumBlocks = CurrentOffset / FvInfoPtr->FvBlocks[0].Length + ((CurrentOffset % FvInfoPtr->FvBlocks[0].Length)?1:0);
  2944. FvInfoPtr->Size = FvInfoPtr->FvBlocks[0].NumBlocks * FvInfoPtr->FvBlocks[0].Length;
  2945. FvInfoPtr->FvBlocks[1].NumBlocks = 0;
  2946. FvInfoPtr->FvBlocks[1].Length = 0;
  2947. } else if (FvInfoPtr->Size < CurrentOffset) {
  2948. //
  2949. // Not invalid
  2950. //
  2951. Error (NULL, 0, 3000, "Invalid", "the required fv image size 0x%x exceeds the set fv image size 0x%x", (unsigned) CurrentOffset, (unsigned) FvInfoPtr->Size);
  2952. return EFI_INVALID_PARAMETER;
  2953. }
  2954. //
  2955. // Set Fv Size Information
  2956. //
  2957. mFvTotalSize = FvInfoPtr->Size;
  2958. mFvTakenSize = CurrentOffset;
  2959. if ((mFvTakenSize == mFvTotalSize) && (MaxPadFileSize > 0)) {
  2960. //
  2961. // This FV means TOP FFS has been taken. Then, check whether there is padding data for use.
  2962. //
  2963. mFvTakenSize = mFvTakenSize - MaxPadFileSize;
  2964. }
  2965. return EFI_SUCCESS;
  2966. }
  2967. EFI_STATUS
  2968. FfsRebaseImageRead (
  2969. IN VOID *FileHandle,
  2970. IN UINTN FileOffset,
  2971. IN OUT UINT32 *ReadSize,
  2972. OUT VOID *Buffer
  2973. )
  2974. /*++
  2975. Routine Description:
  2976. Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
  2977. Arguments:
  2978. FileHandle - The handle to the PE/COFF file
  2979. FileOffset - The offset, in bytes, into the file to read
  2980. ReadSize - The number of bytes to read from the file starting at FileOffset
  2981. Buffer - A pointer to the buffer to read the data into.
  2982. Returns:
  2983. EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
  2984. --*/
  2985. {
  2986. CHAR8 *Destination8;
  2987. CHAR8 *Source8;
  2988. UINT32 Length;
  2989. Destination8 = Buffer;
  2990. Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
  2991. Length = *ReadSize;
  2992. while (Length--) {
  2993. *(Destination8++) = *(Source8++);
  2994. }
  2995. return EFI_SUCCESS;
  2996. }
  2997. EFI_STATUS
  2998. GetChildFvFromFfs (
  2999. IN FV_INFO *FvInfo,
  3000. IN EFI_FFS_FILE_HEADER *FfsFile,
  3001. IN UINTN XipOffset
  3002. )
  3003. /*++
  3004. Routine Description:
  3005. This function gets all child FvImages in the input FfsFile, and records
  3006. their base address to the parent image.
  3007. Arguments:
  3008. FvInfo A pointer to FV_INFO structure.
  3009. FfsFile A pointer to Ffs file image that may contain FvImage.
  3010. XipOffset The offset address to the parent FvImage base.
  3011. Returns:
  3012. EFI_SUCCESS Base address of child Fv image is recorded.
  3013. --*/
  3014. {
  3015. EFI_STATUS Status;
  3016. UINTN Index;
  3017. EFI_FILE_SECTION_POINTER SubFvSection;
  3018. EFI_FIRMWARE_VOLUME_HEADER *SubFvImageHeader;
  3019. EFI_PHYSICAL_ADDRESS SubFvBaseAddress;
  3020. EFI_FILE_SECTION_POINTER CorePe32;
  3021. UINT16 MachineType;
  3022. for (Index = 1;; Index++) {
  3023. //
  3024. // Find FV section
  3025. //
  3026. Status = GetSectionByType (FfsFile, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, Index, &SubFvSection);
  3027. if (EFI_ERROR (Status)) {
  3028. break;
  3029. }
  3030. SubFvImageHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) SubFvSection.FVImageSection + GetSectionHeaderLength(SubFvSection.FVImageSection));
  3031. //
  3032. // See if there's an SEC core in the child FV
  3033. Status = FindCorePeSection(SubFvImageHeader, SubFvImageHeader->FvLength, EFI_FV_FILETYPE_SECURITY_CORE, &CorePe32);
  3034. // if we couldn't find the SEC core, look for a PEI core
  3035. if (EFI_ERROR(Status)) {
  3036. Status = FindCorePeSection(SubFvImageHeader, SubFvImageHeader->FvLength, EFI_FV_FILETYPE_PEI_CORE, &CorePe32);
  3037. }
  3038. if (!EFI_ERROR(Status)) {
  3039. Status = GetCoreMachineType(CorePe32, &MachineType);
  3040. if (EFI_ERROR(Status)) {
  3041. Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for SEC/PEI Core.");
  3042. return EFI_ABORTED;
  3043. }
  3044. // machine type is ARM, set a flag so ARM reset vector processing occurs
  3045. if ((MachineType == EFI_IMAGE_MACHINE_ARMT) || (MachineType == EFI_IMAGE_MACHINE_AARCH64)) {
  3046. VerboseMsg("Located ARM/AArch64 SEC/PEI core in child FV");
  3047. mArm = TRUE;
  3048. }
  3049. // Machine type is LOONGARCH64, set a flag so LoongArch64 reset vector processed.
  3050. if (MachineType == EFI_IMAGE_MACHINE_LOONGARCH64) {
  3051. VerboseMsg("Located LoongArch64 SEC core in child FV");
  3052. mLoongArch = TRUE;
  3053. }
  3054. }
  3055. //
  3056. // Rebase on Flash
  3057. //
  3058. SubFvBaseAddress = FvInfo->BaseAddress + (UINTN) SubFvImageHeader - (UINTN) FfsFile + XipOffset;
  3059. mFvBaseAddress[mFvBaseAddressNumber ++ ] = SubFvBaseAddress;
  3060. }
  3061. return EFI_SUCCESS;
  3062. }
  3063. EFI_STATUS
  3064. FfsRebase (
  3065. IN OUT FV_INFO *FvInfo,
  3066. IN CHAR8 *FileName,
  3067. IN OUT EFI_FFS_FILE_HEADER *FfsFile,
  3068. IN UINTN XipOffset,
  3069. IN FILE *FvMapFile
  3070. )
  3071. /*++
  3072. Routine Description:
  3073. This function determines if a file is XIP and should be rebased. It will
  3074. rebase any PE32 sections found in the file using the base address.
  3075. Arguments:
  3076. FvInfo A pointer to FV_INFO structure.
  3077. FileName Ffs File PathName
  3078. FfsFile A pointer to Ffs file image.
  3079. XipOffset The offset address to use for rebasing the XIP file image.
  3080. FvMapFile FvMapFile to record the function address in one Fvimage
  3081. Returns:
  3082. EFI_SUCCESS The image was properly rebased.
  3083. EFI_INVALID_PARAMETER An input parameter is invalid.
  3084. EFI_ABORTED An error occurred while rebasing the input file image.
  3085. EFI_OUT_OF_RESOURCES Could not allocate a required resource.
  3086. EFI_NOT_FOUND No compressed sections could be found.
  3087. --*/
  3088. {
  3089. EFI_STATUS Status;
  3090. PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
  3091. PE_COFF_LOADER_IMAGE_CONTEXT OrigImageContext;
  3092. EFI_PHYSICAL_ADDRESS XipBase;
  3093. EFI_PHYSICAL_ADDRESS NewPe32BaseAddress;
  3094. UINTN Index;
  3095. EFI_FILE_SECTION_POINTER CurrentPe32Section;
  3096. EFI_FFS_FILE_STATE SavedState;
  3097. EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr;
  3098. EFI_TE_IMAGE_HEADER *TEImageHeader;
  3099. UINT8 *MemoryImagePointer;
  3100. EFI_IMAGE_SECTION_HEADER *SectionHeader;
  3101. CHAR8 PeFileName [MAX_LONG_FILE_PATH];
  3102. CHAR8 *Cptr;
  3103. FILE *PeFile;
  3104. UINT8 *PeFileBuffer;
  3105. UINT32 PeFileSize;
  3106. CHAR8 *PdbPointer;
  3107. UINT32 FfsHeaderSize;
  3108. UINT32 CurSecHdrSize;
  3109. Index = 0;
  3110. MemoryImagePointer = NULL;
  3111. TEImageHeader = NULL;
  3112. ImgHdr = NULL;
  3113. SectionHeader = NULL;
  3114. Cptr = NULL;
  3115. PeFile = NULL;
  3116. PeFileBuffer = NULL;
  3117. //
  3118. // Don't need to relocate image when BaseAddress is zero and no ForceRebase Flag specified.
  3119. //
  3120. if ((FvInfo->BaseAddress == 0) && (FvInfo->ForceRebase == -1)) {
  3121. return EFI_SUCCESS;
  3122. }
  3123. //
  3124. // If ForceRebase Flag specified to FALSE, will always not take rebase action.
  3125. //
  3126. if (FvInfo->ForceRebase == 0) {
  3127. return EFI_SUCCESS;
  3128. }
  3129. XipBase = FvInfo->BaseAddress + XipOffset;
  3130. //
  3131. // We only process files potentially containing PE32 sections.
  3132. //
  3133. switch (FfsFile->Type) {
  3134. case EFI_FV_FILETYPE_SECURITY_CORE:
  3135. case EFI_FV_FILETYPE_PEI_CORE:
  3136. case EFI_FV_FILETYPE_PEIM:
  3137. case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
  3138. case EFI_FV_FILETYPE_DRIVER:
  3139. case EFI_FV_FILETYPE_DXE_CORE:
  3140. break;
  3141. case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE:
  3142. //
  3143. // Rebase the inside FvImage.
  3144. //
  3145. GetChildFvFromFfs (FvInfo, FfsFile, XipOffset);
  3146. //
  3147. // Search PE/TE section in FV sectin.
  3148. //
  3149. break;
  3150. default:
  3151. return EFI_SUCCESS;
  3152. }
  3153. FfsHeaderSize = GetFfsHeaderLength(FfsFile);
  3154. //
  3155. // Rebase each PE32 section
  3156. //
  3157. Status = EFI_SUCCESS;
  3158. for (Index = 1;; Index++) {
  3159. //
  3160. // Init Value
  3161. //
  3162. NewPe32BaseAddress = 0;
  3163. //
  3164. // Find Pe Image
  3165. //
  3166. Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
  3167. if (EFI_ERROR (Status)) {
  3168. break;
  3169. }
  3170. CurSecHdrSize = GetSectionHeaderLength(CurrentPe32Section.CommonHeader);
  3171. //
  3172. // Initialize context
  3173. //
  3174. memset (&ImageContext, 0, sizeof (ImageContext));
  3175. ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize);
  3176. ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
  3177. Status = PeCoffLoaderGetImageInfo (&ImageContext);
  3178. if (EFI_ERROR (Status)) {
  3179. Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName, (int) Status);
  3180. return Status;
  3181. }
  3182. if ( (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) ||
  3183. (ImageContext.Machine == EFI_IMAGE_MACHINE_AARCH64) ) {
  3184. mArm = TRUE;
  3185. }
  3186. if (ImageContext.Machine == EFI_IMAGE_MACHINE_RISCV64) {
  3187. mRiscV = TRUE;
  3188. }
  3189. if (ImageContext.Machine == EFI_IMAGE_MACHINE_LOONGARCH64) {
  3190. mLoongArch = TRUE;
  3191. }
  3192. //
  3193. // Keep Image Context for PE image in FV
  3194. //
  3195. memcpy (&OrigImageContext, &ImageContext, sizeof (ImageContext));
  3196. //
  3197. // Get File PdbPointer
  3198. //
  3199. PdbPointer = PeCoffLoaderGetPdbPointer (ImageContext.Handle);
  3200. //
  3201. // Get PeHeader pointer
  3202. //
  3203. ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize + ImageContext.PeCoffHeaderOffset);
  3204. //
  3205. // Calculate the PE32 base address, based on file type
  3206. //
  3207. switch (FfsFile->Type) {
  3208. case EFI_FV_FILETYPE_SECURITY_CORE:
  3209. case EFI_FV_FILETYPE_PEI_CORE:
  3210. case EFI_FV_FILETYPE_PEIM:
  3211. case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
  3212. //
  3213. // Check if section-alignment and file-alignment match or not
  3214. //
  3215. if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) {
  3216. //
  3217. // Xip module has the same section alignment and file alignment.
  3218. //
  3219. Error (NULL, 0, 3000, "Invalid", "PE image Section-Alignment and File-Alignment do not match : %s.", FileName);
  3220. return EFI_ABORTED;
  3221. }
  3222. //
  3223. // PeImage has no reloc section. It will try to get reloc data from the original EFI image.
  3224. //
  3225. if (ImageContext.RelocationsStripped) {
  3226. //
  3227. // Construct the original efi file Name
  3228. //
  3229. if (strlen (FileName) >= MAX_LONG_FILE_PATH) {
  3230. Error (NULL, 0, 2000, "Invalid", "The file name %s is too long.", FileName);
  3231. return EFI_ABORTED;
  3232. }
  3233. strncpy (PeFileName, FileName, MAX_LONG_FILE_PATH - 1);
  3234. PeFileName[MAX_LONG_FILE_PATH - 1] = 0;
  3235. Cptr = PeFileName + strlen (PeFileName);
  3236. while (*Cptr != '.') {
  3237. Cptr --;
  3238. }
  3239. if (*Cptr != '.') {
  3240. Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);
  3241. return EFI_ABORTED;
  3242. } else {
  3243. *(Cptr + 1) = 'e';
  3244. *(Cptr + 2) = 'f';
  3245. *(Cptr + 3) = 'i';
  3246. *(Cptr + 4) = '\0';
  3247. }
  3248. PeFile = fopen (LongFilePath (PeFileName), "rb");
  3249. if (PeFile == NULL) {
  3250. Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);
  3251. //Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);
  3252. //return EFI_ABORTED;
  3253. break;
  3254. }
  3255. //
  3256. // Get the file size
  3257. //
  3258. PeFileSize = _filelength (fileno (PeFile));
  3259. PeFileBuffer = (UINT8 *) malloc (PeFileSize);
  3260. if (PeFileBuffer == NULL) {
  3261. fclose (PeFile);
  3262. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
  3263. return EFI_OUT_OF_RESOURCES;
  3264. }
  3265. //
  3266. // Read Pe File
  3267. //
  3268. fread (PeFileBuffer, sizeof (UINT8), PeFileSize, PeFile);
  3269. //
  3270. // close file
  3271. //
  3272. fclose (PeFile);
  3273. //
  3274. // Handle pointer to the original efi image.
  3275. //
  3276. ImageContext.Handle = PeFileBuffer;
  3277. Status = PeCoffLoaderGetImageInfo (&ImageContext);
  3278. if (EFI_ERROR (Status)) {
  3279. Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName, (int) Status);
  3280. return Status;
  3281. }
  3282. ImageContext.RelocationsStripped = FALSE;
  3283. }
  3284. NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)FfsFile;
  3285. break;
  3286. case EFI_FV_FILETYPE_DRIVER:
  3287. case EFI_FV_FILETYPE_DXE_CORE:
  3288. //
  3289. // Check if section-alignment and file-alignment match or not
  3290. //
  3291. if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) {
  3292. //
  3293. // Xip module has the same section alignment and file alignment.
  3294. //
  3295. Error (NULL, 0, 3000, "Invalid", "PE image Section-Alignment and File-Alignment do not match : %s.", FileName);
  3296. return EFI_ABORTED;
  3297. }
  3298. NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)FfsFile;
  3299. break;
  3300. default:
  3301. //
  3302. // Not supported file type
  3303. //
  3304. return EFI_SUCCESS;
  3305. }
  3306. //
  3307. // Relocation doesn't exist
  3308. //
  3309. if (ImageContext.RelocationsStripped) {
  3310. Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);
  3311. continue;
  3312. }
  3313. //
  3314. // Relocation exist and rebase
  3315. //
  3316. //
  3317. // Load and Relocate Image Data
  3318. //
  3319. MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
  3320. if (MemoryImagePointer == NULL) {
  3321. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
  3322. return EFI_OUT_OF_RESOURCES;
  3323. }
  3324. memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
  3325. ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((UINTN) ImageContext.SectionAlignment - 1));
  3326. Status = PeCoffLoaderLoadImage (&ImageContext);
  3327. if (EFI_ERROR (Status)) {
  3328. Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
  3329. free ((VOID *) MemoryImagePointer);
  3330. return Status;
  3331. }
  3332. ImageContext.DestinationAddress = NewPe32BaseAddress;
  3333. Status = PeCoffLoaderRelocateImage (&ImageContext);
  3334. if (EFI_ERROR (Status)) {
  3335. Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s Status=%d", FileName, Status);
  3336. free ((VOID *) MemoryImagePointer);
  3337. return Status;
  3338. }
  3339. //
  3340. // Copy Relocated data to raw image file.
  3341. //
  3342. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
  3343. (UINTN) ImgHdr +
  3344. sizeof (UINT32) +
  3345. sizeof (EFI_IMAGE_FILE_HEADER) +
  3346. ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader
  3347. );
  3348. for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) {
  3349. CopyMem (
  3350. (UINT8 *) CurrentPe32Section.Pe32Section + CurSecHdrSize + SectionHeader->PointerToRawData,
  3351. (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),
  3352. SectionHeader->SizeOfRawData
  3353. );
  3354. }
  3355. free ((VOID *) MemoryImagePointer);
  3356. MemoryImagePointer = NULL;
  3357. if (PeFileBuffer != NULL) {
  3358. free (PeFileBuffer);
  3359. PeFileBuffer = NULL;
  3360. }
  3361. //
  3362. // Update Image Base Address
  3363. //
  3364. if (ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
  3365. ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress;
  3366. } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
  3367. ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress;
  3368. } else {
  3369. Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s",
  3370. ImgHdr->Pe32.OptionalHeader.Magic,
  3371. FileName
  3372. );
  3373. return EFI_ABORTED;
  3374. }
  3375. //
  3376. // Now update file checksum
  3377. //
  3378. if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
  3379. SavedState = FfsFile->State;
  3380. FfsFile->IntegrityCheck.Checksum.File = 0;
  3381. FfsFile->State = 0;
  3382. FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
  3383. (UINT8 *) ((UINT8 *)FfsFile + FfsHeaderSize),
  3384. GetFfsFileLength (FfsFile) - FfsHeaderSize
  3385. );
  3386. FfsFile->State = SavedState;
  3387. }
  3388. //
  3389. // Get this module function address from ModulePeMapFile and add them into FvMap file
  3390. //
  3391. //
  3392. // Default use FileName as map file path
  3393. //
  3394. if (PdbPointer == NULL) {
  3395. PdbPointer = FileName;
  3396. }
  3397. WriteMapFile (FvMapFile, PdbPointer, FfsFile, NewPe32BaseAddress, &OrigImageContext);
  3398. }
  3399. if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
  3400. FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
  3401. FfsFile->Type != EFI_FV_FILETYPE_PEIM &&
  3402. FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER &&
  3403. FfsFile->Type != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE
  3404. ) {
  3405. //
  3406. // Only Peim code may have a TE section
  3407. //
  3408. return EFI_SUCCESS;
  3409. }
  3410. //
  3411. // Now process TE sections
  3412. //
  3413. for (Index = 1;; Index++) {
  3414. NewPe32BaseAddress = 0;
  3415. //
  3416. // Find Te Image
  3417. //
  3418. Status = GetSectionByType (FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section);
  3419. if (EFI_ERROR (Status)) {
  3420. break;
  3421. }
  3422. CurSecHdrSize = GetSectionHeaderLength(CurrentPe32Section.CommonHeader);
  3423. //
  3424. // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off
  3425. // by GenTEImage
  3426. //
  3427. TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + CurSecHdrSize);
  3428. //
  3429. // Initialize context, load image info.
  3430. //
  3431. memset (&ImageContext, 0, sizeof (ImageContext));
  3432. ImageContext.Handle = (VOID *) TEImageHeader;
  3433. ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
  3434. Status = PeCoffLoaderGetImageInfo (&ImageContext);
  3435. if (EFI_ERROR (Status)) {
  3436. Error (NULL, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName, (int) Status);
  3437. return Status;
  3438. }
  3439. if ( (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) ||
  3440. (ImageContext.Machine == EFI_IMAGE_MACHINE_AARCH64) ) {
  3441. mArm = TRUE;
  3442. }
  3443. if (ImageContext.Machine == EFI_IMAGE_MACHINE_LOONGARCH64) {
  3444. mLoongArch = TRUE;
  3445. }
  3446. //
  3447. // Keep Image Context for TE image in FV
  3448. //
  3449. memcpy (&OrigImageContext, &ImageContext, sizeof (ImageContext));
  3450. //
  3451. // Get File PdbPointer
  3452. //
  3453. PdbPointer = PeCoffLoaderGetPdbPointer (ImageContext.Handle);
  3454. //
  3455. // Set new rebased address.
  3456. //
  3457. NewPe32BaseAddress = XipBase + (UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) \
  3458. - TEImageHeader->StrippedSize - (UINTN) FfsFile;
  3459. //
  3460. // if reloc is stripped, try to get the original efi image to get reloc info.
  3461. //
  3462. if (ImageContext.RelocationsStripped) {
  3463. //
  3464. // Construct the original efi file name
  3465. //
  3466. if (strlen (FileName) >= MAX_LONG_FILE_PATH) {
  3467. Error (NULL, 0, 2000, "Invalid", "The file name %s is too long.", FileName);
  3468. return EFI_ABORTED;
  3469. }
  3470. strncpy (PeFileName, FileName, MAX_LONG_FILE_PATH - 1);
  3471. PeFileName[MAX_LONG_FILE_PATH - 1] = 0;
  3472. Cptr = PeFileName + strlen (PeFileName);
  3473. while (*Cptr != '.') {
  3474. Cptr --;
  3475. }
  3476. if (*Cptr != '.') {
  3477. Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);
  3478. return EFI_ABORTED;
  3479. } else {
  3480. *(Cptr + 1) = 'e';
  3481. *(Cptr + 2) = 'f';
  3482. *(Cptr + 3) = 'i';
  3483. *(Cptr + 4) = '\0';
  3484. }
  3485. PeFile = fopen (LongFilePath (PeFileName), "rb");
  3486. if (PeFile == NULL) {
  3487. Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);
  3488. //Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName);
  3489. //return EFI_ABORTED;
  3490. } else {
  3491. //
  3492. // Get the file size
  3493. //
  3494. PeFileSize = _filelength (fileno (PeFile));
  3495. PeFileBuffer = (UINT8 *) malloc (PeFileSize);
  3496. if (PeFileBuffer == NULL) {
  3497. fclose (PeFile);
  3498. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
  3499. return EFI_OUT_OF_RESOURCES;
  3500. }
  3501. //
  3502. // Read Pe File
  3503. //
  3504. fread (PeFileBuffer, sizeof (UINT8), PeFileSize, PeFile);
  3505. //
  3506. // close file
  3507. //
  3508. fclose (PeFile);
  3509. //
  3510. // Append reloc section into TeImage
  3511. //
  3512. ImageContext.Handle = PeFileBuffer;
  3513. Status = PeCoffLoaderGetImageInfo (&ImageContext);
  3514. if (EFI_ERROR (Status)) {
  3515. Error (NULL, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName, (int) Status);
  3516. return Status;
  3517. }
  3518. ImageContext.RelocationsStripped = FALSE;
  3519. }
  3520. }
  3521. //
  3522. // Relocation doesn't exist
  3523. //
  3524. if (ImageContext.RelocationsStripped) {
  3525. Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName);
  3526. continue;
  3527. }
  3528. //
  3529. // Relocation exist and rebase
  3530. //
  3531. //
  3532. // Load and Relocate Image Data
  3533. //
  3534. MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
  3535. if (MemoryImagePointer == NULL) {
  3536. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName);
  3537. return EFI_OUT_OF_RESOURCES;
  3538. }
  3539. memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment);
  3540. ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((UINTN) ImageContext.SectionAlignment - 1));
  3541. Status = PeCoffLoaderLoadImage (&ImageContext);
  3542. if (EFI_ERROR (Status)) {
  3543. Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName);
  3544. free ((VOID *) MemoryImagePointer);
  3545. return Status;
  3546. }
  3547. //
  3548. // Reloacate TeImage
  3549. //
  3550. ImageContext.DestinationAddress = NewPe32BaseAddress;
  3551. Status = PeCoffLoaderRelocateImage (&ImageContext);
  3552. if (EFI_ERROR (Status)) {
  3553. Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of TE image %s", FileName);
  3554. free ((VOID *) MemoryImagePointer);
  3555. return Status;
  3556. }
  3557. //
  3558. // Copy the relocated image into raw image file.
  3559. //
  3560. SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1);
  3561. for (Index = 0; Index < TEImageHeader->NumberOfSections; Index ++, SectionHeader ++) {
  3562. if (!ImageContext.IsTeImage) {
  3563. CopyMem (
  3564. (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData,
  3565. (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress),
  3566. SectionHeader->SizeOfRawData
  3567. );
  3568. } else {
  3569. CopyMem (
  3570. (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData,
  3571. (VOID*) (UINTN) (ImageContext.ImageAddress + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->VirtualAddress),
  3572. SectionHeader->SizeOfRawData
  3573. );
  3574. }
  3575. }
  3576. //
  3577. // Free the allocated memory resource
  3578. //
  3579. free ((VOID *) MemoryImagePointer);
  3580. MemoryImagePointer = NULL;
  3581. if (PeFileBuffer != NULL) {
  3582. free (PeFileBuffer);
  3583. PeFileBuffer = NULL;
  3584. }
  3585. //
  3586. // Update Image Base Address
  3587. //
  3588. TEImageHeader->ImageBase = NewPe32BaseAddress;
  3589. //
  3590. // Now update file checksum
  3591. //
  3592. if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
  3593. SavedState = FfsFile->State;
  3594. FfsFile->IntegrityCheck.Checksum.File = 0;
  3595. FfsFile->State = 0;
  3596. FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
  3597. (UINT8 *)((UINT8 *)FfsFile + FfsHeaderSize),
  3598. GetFfsFileLength (FfsFile) - FfsHeaderSize
  3599. );
  3600. FfsFile->State = SavedState;
  3601. }
  3602. //
  3603. // Get this module function address from ModulePeMapFile and add them into FvMap file
  3604. //
  3605. //
  3606. // Default use FileName as map file path
  3607. //
  3608. if (PdbPointer == NULL) {
  3609. PdbPointer = FileName;
  3610. }
  3611. WriteMapFile (
  3612. FvMapFile,
  3613. PdbPointer,
  3614. FfsFile,
  3615. NewPe32BaseAddress,
  3616. &OrigImageContext
  3617. );
  3618. }
  3619. return EFI_SUCCESS;
  3620. }
  3621. EFI_STATUS
  3622. FindApResetVectorPosition (
  3623. IN MEMORY_FILE *FvImage,
  3624. OUT UINT8 **Pointer
  3625. )
  3626. /*++
  3627. Routine Description:
  3628. Find the position in this FvImage to place Ap reset vector.
  3629. Arguments:
  3630. FvImage Memory file for the FV memory image.
  3631. Pointer Pointer to pointer to position.
  3632. Returns:
  3633. EFI_NOT_FOUND - No satisfied position is found.
  3634. EFI_SUCCESS - The suitable position is return.
  3635. --*/
  3636. {
  3637. EFI_FFS_FILE_HEADER *PadFile;
  3638. UINT32 Index;
  3639. EFI_STATUS Status;
  3640. UINT8 *FixPoint;
  3641. UINT32 FileLength;
  3642. for (Index = 1; ;Index ++) {
  3643. //
  3644. // Find Pad File to add ApResetVector info
  3645. //
  3646. Status = GetFileByType (EFI_FV_FILETYPE_FFS_PAD, Index, &PadFile);
  3647. if (EFI_ERROR (Status) || (PadFile == NULL)) {
  3648. //
  3649. // No Pad file to be found.
  3650. //
  3651. break;
  3652. }
  3653. //
  3654. // Get Pad file size.
  3655. //
  3656. FileLength = GetFfsFileLength(PadFile);
  3657. FileLength = (FileLength + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1);
  3658. //
  3659. // FixPoint must be align on 0x1000 relative to FvImage Header
  3660. //
  3661. FixPoint = (UINT8*) PadFile + GetFfsHeaderLength(PadFile);
  3662. FixPoint = FixPoint + 0x1000 - (((UINTN) FixPoint - (UINTN) FvImage->FileImage) & 0xFFF);
  3663. //
  3664. // FixPoint be larger at the last place of one fv image.
  3665. //
  3666. while (((UINTN) FixPoint + SIZEOF_STARTUP_DATA_ARRAY - (UINTN) PadFile) <= FileLength) {
  3667. FixPoint += 0x1000;
  3668. }
  3669. FixPoint -= 0x1000;
  3670. if ((UINTN) FixPoint < ((UINTN) PadFile + GetFfsHeaderLength(PadFile))) {
  3671. //
  3672. // No alignment FixPoint in this Pad File.
  3673. //
  3674. continue;
  3675. }
  3676. if ((UINTN) FvImage->Eof - (UINTN)FixPoint <= 0x20000) {
  3677. //
  3678. // Find the position to place ApResetVector
  3679. //
  3680. *Pointer = FixPoint;
  3681. return EFI_SUCCESS;
  3682. }
  3683. }
  3684. return EFI_NOT_FOUND;
  3685. }
  3686. EFI_STATUS
  3687. ParseCapInf (
  3688. IN MEMORY_FILE *InfFile,
  3689. OUT CAP_INFO *CapInfo
  3690. )
  3691. /*++
  3692. Routine Description:
  3693. This function parses a Cap.INF file and copies info into a CAP_INFO structure.
  3694. Arguments:
  3695. InfFile Memory file image.
  3696. CapInfo Information read from INF file.
  3697. Returns:
  3698. EFI_SUCCESS INF file information successfully retrieved.
  3699. EFI_ABORTED INF file has an invalid format.
  3700. EFI_NOT_FOUND A required string was not found in the INF file.
  3701. --*/
  3702. {
  3703. CHAR8 Value[MAX_LONG_FILE_PATH];
  3704. UINT64 Value64;
  3705. UINTN Index, Number;
  3706. EFI_STATUS Status;
  3707. //
  3708. // Initialize Cap info
  3709. //
  3710. // memset (CapInfo, 0, sizeof (CAP_INFO));
  3711. //
  3712. //
  3713. // Read the Capsule Guid
  3714. //
  3715. Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_GUID_STRING, 0, Value);
  3716. if (Status == EFI_SUCCESS) {
  3717. //
  3718. // Get the Capsule Guid
  3719. //
  3720. Status = StringToGuid (Value, &CapInfo->CapGuid);
  3721. if (EFI_ERROR (Status)) {
  3722. Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_CAPSULE_GUID_STRING, Value);
  3723. return EFI_ABORTED;
  3724. }
  3725. DebugMsg (NULL, 0, 9, "Capsule Guid", "%s = %s", EFI_CAPSULE_GUID_STRING, Value);
  3726. }
  3727. //
  3728. // Read the Capsule Header Size
  3729. //
  3730. Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_HEADER_SIZE_STRING, 0, Value);
  3731. if (Status == EFI_SUCCESS) {
  3732. Status = AsciiStringToUint64 (Value, FALSE, &Value64);
  3733. if (EFI_ERROR (Status)) {
  3734. Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_CAPSULE_HEADER_SIZE_STRING, Value);
  3735. return EFI_ABORTED;
  3736. }
  3737. CapInfo->HeaderSize = (UINT32) Value64;
  3738. DebugMsg (NULL, 0, 9, "Capsule Header size", "%s = %s", EFI_CAPSULE_HEADER_SIZE_STRING, Value);
  3739. }
  3740. //
  3741. // Read the Capsule Flag
  3742. //
  3743. Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_FLAGS_STRING, 0, Value);
  3744. if (Status == EFI_SUCCESS) {
  3745. if (strstr (Value, "PopulateSystemTable") != NULL) {
  3746. CapInfo->Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE;
  3747. if (strstr (Value, "InitiateReset") != NULL) {
  3748. CapInfo->Flags |= CAPSULE_FLAGS_INITIATE_RESET;
  3749. }
  3750. } else if (strstr (Value, "PersistAcrossReset") != NULL) {
  3751. CapInfo->Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
  3752. if (strstr (Value, "InitiateReset") != NULL) {
  3753. CapInfo->Flags |= CAPSULE_FLAGS_INITIATE_RESET;
  3754. }
  3755. } else {
  3756. Error (NULL, 0, 2000, "Invalid parameter", "invalid Flag setting for %s.", EFI_CAPSULE_FLAGS_STRING);
  3757. return EFI_ABORTED;
  3758. }
  3759. DebugMsg (NULL, 0, 9, "Capsule Flag", Value);
  3760. }
  3761. Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_OEM_CAPSULE_FLAGS_STRING, 0, Value);
  3762. if (Status == EFI_SUCCESS) {
  3763. Status = AsciiStringToUint64 (Value, FALSE, &Value64);
  3764. if (EFI_ERROR (Status) || Value64 > 0xffff) {
  3765. Error (NULL, 0, 2000, "Invalid parameter",
  3766. "invalid Flag setting for %s. Must be integer value between 0x0000 and 0xffff.",
  3767. EFI_OEM_CAPSULE_FLAGS_STRING);
  3768. return EFI_ABORTED;
  3769. }
  3770. CapInfo->Flags |= Value64;
  3771. DebugMsg (NULL, 0, 9, "Capsule Extend Flag", Value);
  3772. }
  3773. //
  3774. // Read Capsule File name
  3775. //
  3776. Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FILE_NAME_STRING, 0, Value);
  3777. if (Status == EFI_SUCCESS) {
  3778. //
  3779. // Get output file name
  3780. //
  3781. strcpy (CapInfo->CapName, Value);
  3782. }
  3783. //
  3784. // Read the Capsule FileImage
  3785. //
  3786. Number = 0;
  3787. for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_CAP; Index++) {
  3788. if (CapInfo->CapFiles[Index][0] != '\0') {
  3789. continue;
  3790. }
  3791. //
  3792. // Read the capsule file name
  3793. //
  3794. Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Number++, Value);
  3795. if (Status == EFI_SUCCESS) {
  3796. //
  3797. // Add the file
  3798. //
  3799. strcpy (CapInfo->CapFiles[Index], Value);
  3800. DebugMsg (NULL, 0, 9, "Capsule component file", "the %uth file name is %s", (unsigned) Index, CapInfo->CapFiles[Index]);
  3801. } else {
  3802. break;
  3803. }
  3804. }
  3805. if (Index == 0) {
  3806. Warning (NULL, 0, 0, "Capsule components are not specified.", NULL);
  3807. }
  3808. return EFI_SUCCESS;
  3809. }
  3810. EFI_STATUS
  3811. GenerateCapImage (
  3812. IN CHAR8 *InfFileImage,
  3813. IN UINTN InfFileSize,
  3814. IN CHAR8 *CapFileName
  3815. )
  3816. /*++
  3817. Routine Description:
  3818. This is the main function which will be called from application to create UEFI Capsule image.
  3819. Arguments:
  3820. InfFileImage Buffer containing the INF file contents.
  3821. InfFileSize Size of the contents of the InfFileImage buffer.
  3822. CapFileName Requested name for the Cap file.
  3823. Returns:
  3824. EFI_SUCCESS Function completed successfully.
  3825. EFI_OUT_OF_RESOURCES Could not allocate required resources.
  3826. EFI_ABORTED Error encountered.
  3827. EFI_INVALID_PARAMETER A required parameter was NULL.
  3828. --*/
  3829. {
  3830. UINT32 CapSize;
  3831. UINT8 *CapBuffer;
  3832. EFI_CAPSULE_HEADER *CapsuleHeader;
  3833. MEMORY_FILE InfMemoryFile;
  3834. UINT32 FileSize;
  3835. UINT32 Index;
  3836. FILE *fpin, *fpout;
  3837. EFI_STATUS Status;
  3838. if (InfFileImage != NULL) {
  3839. //
  3840. // Initialize file structures
  3841. //
  3842. InfMemoryFile.FileImage = InfFileImage;
  3843. InfMemoryFile.CurrentFilePointer = InfFileImage;
  3844. InfMemoryFile.Eof = InfFileImage + InfFileSize;
  3845. //
  3846. // Parse the Cap inf file for header information
  3847. //
  3848. Status = ParseCapInf (&InfMemoryFile, &mCapDataInfo);
  3849. if (Status != EFI_SUCCESS) {
  3850. return Status;
  3851. }
  3852. }
  3853. if (mCapDataInfo.HeaderSize == 0) {
  3854. //
  3855. // make header size align 16 bytes.
  3856. //
  3857. mCapDataInfo.HeaderSize = sizeof (EFI_CAPSULE_HEADER);
  3858. mCapDataInfo.HeaderSize = (mCapDataInfo.HeaderSize + 0xF) & ~0xF;
  3859. }
  3860. if (mCapDataInfo.HeaderSize < sizeof (EFI_CAPSULE_HEADER)) {
  3861. Error (NULL, 0, 2000, "Invalid parameter", "The specified HeaderSize cannot be less than the size of EFI_CAPSULE_HEADER.");
  3862. return EFI_INVALID_PARAMETER;
  3863. }
  3864. if (CapFileName == NULL && mCapDataInfo.CapName[0] != '\0') {
  3865. CapFileName = mCapDataInfo.CapName;
  3866. }
  3867. if (CapFileName == NULL) {
  3868. Error (NULL, 0, 2001, "Missing required argument", "Output Capsule file name");
  3869. return EFI_INVALID_PARAMETER;
  3870. }
  3871. //
  3872. // Set Default Capsule Guid value
  3873. //
  3874. if (CompareGuid (&mCapDataInfo.CapGuid, &mZeroGuid) == 0) {
  3875. memcpy (&mCapDataInfo.CapGuid, &mDefaultCapsuleGuid, sizeof (EFI_GUID));
  3876. }
  3877. //
  3878. // Calculate the size of capsule image.
  3879. //
  3880. Index = 0;
  3881. FileSize = 0;
  3882. CapSize = mCapDataInfo.HeaderSize;
  3883. while (mCapDataInfo.CapFiles [Index][0] != '\0') {
  3884. fpin = fopen (LongFilePath (mCapDataInfo.CapFiles[Index]), "rb");
  3885. if (fpin == NULL) {
  3886. Error (NULL, 0, 0001, "Error opening file", mCapDataInfo.CapFiles[Index]);
  3887. return EFI_ABORTED;
  3888. }
  3889. FileSize = _filelength (fileno (fpin));
  3890. CapSize += FileSize;
  3891. fclose (fpin);
  3892. Index ++;
  3893. }
  3894. //
  3895. // Allocate buffer for capsule image.
  3896. //
  3897. CapBuffer = (UINT8 *) malloc (CapSize);
  3898. if (CapBuffer == NULL) {
  3899. Error (NULL, 0, 4001, "Resource", "memory cannot be allocated for creating the capsule.");
  3900. return EFI_OUT_OF_RESOURCES;
  3901. }
  3902. //
  3903. // Initialize the capsule header to zero
  3904. //
  3905. memset (CapBuffer, 0, mCapDataInfo.HeaderSize);
  3906. //
  3907. // create capsule header and get capsule body
  3908. //
  3909. CapsuleHeader = (EFI_CAPSULE_HEADER *) CapBuffer;
  3910. memcpy (&CapsuleHeader->CapsuleGuid, &mCapDataInfo.CapGuid, sizeof (EFI_GUID));
  3911. CapsuleHeader->HeaderSize = mCapDataInfo.HeaderSize;
  3912. CapsuleHeader->Flags = mCapDataInfo.Flags;
  3913. CapsuleHeader->CapsuleImageSize = CapSize;
  3914. Index = 0;
  3915. FileSize = 0;
  3916. CapSize = CapsuleHeader->HeaderSize;
  3917. while (mCapDataInfo.CapFiles [Index][0] != '\0') {
  3918. fpin = fopen (LongFilePath (mCapDataInfo.CapFiles[Index]), "rb");
  3919. if (fpin == NULL) {
  3920. Error (NULL, 0, 0001, "Error opening file", mCapDataInfo.CapFiles[Index]);
  3921. free (CapBuffer);
  3922. return EFI_ABORTED;
  3923. }
  3924. FileSize = _filelength (fileno (fpin));
  3925. fread (CapBuffer + CapSize, 1, FileSize, fpin);
  3926. fclose (fpin);
  3927. Index ++;
  3928. CapSize += FileSize;
  3929. }
  3930. //
  3931. // write capsule data into the output file
  3932. //
  3933. fpout = fopen (LongFilePath (CapFileName), "wb");
  3934. if (fpout == NULL) {
  3935. Error (NULL, 0, 0001, "Error opening file", CapFileName);
  3936. free (CapBuffer);
  3937. return EFI_ABORTED;
  3938. }
  3939. fwrite (CapBuffer, 1, CapSize, fpout);
  3940. fclose (fpout);
  3941. free (CapBuffer);
  3942. VerboseMsg ("The size of the generated capsule image is %u bytes", (unsigned) CapSize);
  3943. return EFI_SUCCESS;
  3944. }