FirmwareVolumeBuffer.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775
  1. /** @file
  2. EFI Firmware Volume routines which work on a Fv image in buffers.
  3. Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "FirmwareVolumeBufferLib.h"
  7. #include "BinderFuncs.h"
  8. //
  9. // Local macros
  10. //
  11. #define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \
  12. ( \
  13. (BOOLEAN) ( \
  14. (FvbAttributes & EFI_FVB2_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \
  15. ) \
  16. )
  17. //
  18. // Local prototypes
  19. //
  20. STATIC
  21. UINT32
  22. FvBufGetSecHdrLen(
  23. IN EFI_COMMON_SECTION_HEADER *SectionHeader
  24. )
  25. {
  26. if (SectionHeader == NULL) {
  27. return 0;
  28. }
  29. if (FvBufExpand3ByteSize(SectionHeader->Size) == 0xffffff) {
  30. return sizeof(EFI_COMMON_SECTION_HEADER2);
  31. }
  32. return sizeof(EFI_COMMON_SECTION_HEADER);
  33. }
  34. STATIC
  35. UINT32
  36. FvBufGetSecFileLen (
  37. IN EFI_COMMON_SECTION_HEADER *SectionHeader
  38. )
  39. {
  40. UINT32 Length;
  41. if (SectionHeader == NULL) {
  42. return 0;
  43. }
  44. Length = FvBufExpand3ByteSize(SectionHeader->Size);
  45. if (Length == 0xffffff) {
  46. Length = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;
  47. }
  48. return Length;
  49. }
  50. //
  51. // Local prototypes
  52. //
  53. STATIC
  54. UINT16
  55. FvBufCalculateChecksum16 (
  56. IN UINT16 *Buffer,
  57. IN UINTN Size
  58. );
  59. STATIC
  60. UINT8
  61. FvBufCalculateChecksum8 (
  62. IN UINT8 *Buffer,
  63. IN UINTN Size
  64. );
  65. //
  66. // Procedures start
  67. //
  68. EFI_STATUS
  69. FvBufRemoveFileNew (
  70. IN OUT VOID *Fv,
  71. IN EFI_GUID *Name
  72. )
  73. /*++
  74. Routine Description:
  75. Clears out all files from the Fv buffer in memory
  76. Arguments:
  77. SourceFv - Address of the Fv in memory, this firmware volume volume will
  78. be modified, if SourceFfsFile exists
  79. SourceFfsFile - Input FFS file to replace
  80. Returns:
  81. EFI_SUCCESS
  82. EFI_NOT_FOUND
  83. --*/
  84. {
  85. EFI_STATUS Status;
  86. EFI_FFS_FILE_HEADER* FileToRm;
  87. UINTN FileToRmLength;
  88. Status = FvBufFindFileByName(
  89. Fv,
  90. Name,
  91. (VOID **)&FileToRm
  92. );
  93. if (EFI_ERROR (Status)) {
  94. return Status;
  95. }
  96. FileToRmLength = FvBufGetFfsFileSize (FileToRm);
  97. CommonLibBinderSetMem (
  98. FileToRm,
  99. FileToRmLength,
  100. (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY)
  101. ? 0xFF : 0
  102. );
  103. return EFI_SUCCESS;
  104. }
  105. EFI_STATUS
  106. FvBufRemoveFile (
  107. IN OUT VOID *Fv,
  108. IN EFI_GUID *Name
  109. )
  110. /*++
  111. Routine Description:
  112. Clears out all files from the Fv buffer in memory
  113. Arguments:
  114. SourceFv - Address of the Fv in memory, this firmware volume volume will
  115. be modified, if SourceFfsFile exists
  116. SourceFfsFile - Input FFS file to replace
  117. Returns:
  118. EFI_SUCCESS
  119. EFI_NOT_FOUND
  120. --*/
  121. {
  122. EFI_STATUS Status;
  123. EFI_FFS_FILE_HEADER *NextFile;
  124. EFI_FIRMWARE_VOLUME_HEADER *TempFv;
  125. UINTN FileKey;
  126. UINTN FvLength;
  127. Status = FvBufFindFileByName(
  128. Fv,
  129. Name,
  130. NULL
  131. );
  132. if (EFI_ERROR (Status)) {
  133. return Status;
  134. }
  135. Status = FvBufGetSize (Fv, &FvLength);
  136. if (EFI_ERROR (Status)) {
  137. return Status;
  138. }
  139. TempFv = NULL;
  140. Status = FvBufDuplicate (Fv, (VOID **)&TempFv);
  141. if (EFI_ERROR (Status)) {
  142. return Status;
  143. }
  144. Status = FvBufClearAllFiles (TempFv);
  145. if (EFI_ERROR (Status)) {
  146. CommonLibBinderFree (TempFv);
  147. return Status;
  148. }
  149. // TempFv has been allocated. It must now be freed
  150. // before returning.
  151. FileKey = 0;
  152. while (TRUE) {
  153. Status = FvBufFindNextFile (Fv, &FileKey, (VOID **)&NextFile);
  154. if (Status == EFI_NOT_FOUND) {
  155. break;
  156. } else if (EFI_ERROR (Status)) {
  157. CommonLibBinderFree (TempFv);
  158. return Status;
  159. }
  160. if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) {
  161. continue;
  162. }
  163. else {
  164. Status = FvBufAddFile (TempFv, NextFile);
  165. if (EFI_ERROR (Status)) {
  166. CommonLibBinderFree (TempFv);
  167. return Status;
  168. }
  169. }
  170. }
  171. CommonLibBinderCopyMem (Fv, TempFv, FvLength);
  172. CommonLibBinderFree (TempFv);
  173. return EFI_SUCCESS;
  174. }
  175. EFI_STATUS
  176. FvBufChecksumFile (
  177. IN OUT VOID *FfsFile
  178. )
  179. /*++
  180. Routine Description:
  181. Clears out all files from the Fv buffer in memory
  182. Arguments:
  183. SourceFfsFile - Input FFS file to update the checksum for
  184. Returns:
  185. EFI_SUCCESS
  186. EFI_NOT_FOUND
  187. --*/
  188. {
  189. EFI_FFS_FILE_HEADER* File = (EFI_FFS_FILE_HEADER*)FfsFile;
  190. EFI_FFS_FILE_STATE StateBackup;
  191. UINT32 FileSize;
  192. FileSize = FvBufGetFfsFileSize (File);
  193. //
  194. // Fill in checksums and state, they must be 0 for checksumming.
  195. //
  196. File->IntegrityCheck.Checksum.Header = 0;
  197. File->IntegrityCheck.Checksum.File = 0;
  198. StateBackup = File->State;
  199. File->State = 0;
  200. File->IntegrityCheck.Checksum.Header =
  201. FvBufCalculateChecksum8 (
  202. (UINT8 *) File,
  203. FvBufGetFfsHeaderSize (File)
  204. );
  205. if (File->Attributes & FFS_ATTRIB_CHECKSUM) {
  206. File->IntegrityCheck.Checksum.File = FvBufCalculateChecksum8 (
  207. (VOID*)((UINT8 *)File + FvBufGetFfsHeaderSize (File)),
  208. FileSize - FvBufGetFfsHeaderSize (File)
  209. );
  210. } else {
  211. File->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
  212. }
  213. File->State = StateBackup;
  214. return EFI_SUCCESS;
  215. }
  216. EFI_STATUS
  217. FvBufChecksumHeader (
  218. IN OUT VOID *Fv
  219. )
  220. /*++
  221. Routine Description:
  222. Clears out all files from the Fv buffer in memory
  223. Arguments:
  224. SourceFv - Address of the Fv in memory, this firmware volume volume will
  225. be modified, if SourceFfsFile exists
  226. SourceFfsFile - Input FFS file to replace
  227. Returns:
  228. EFI_SUCCESS
  229. EFI_NOT_FOUND
  230. --*/
  231. {
  232. EFI_FIRMWARE_VOLUME_HEADER* FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
  233. FvHeader->Checksum = 0;
  234. FvHeader->Checksum =
  235. FvBufCalculateChecksum16 (
  236. (UINT16*) FvHeader,
  237. FvHeader->HeaderLength / sizeof (UINT16)
  238. );
  239. return EFI_SUCCESS;
  240. }
  241. EFI_STATUS
  242. FvBufDuplicate (
  243. IN VOID *SourceFv,
  244. IN OUT VOID **DestinationFv
  245. )
  246. /*++
  247. Routine Description:
  248. Clears out all files from the Fv buffer in memory
  249. Arguments:
  250. SourceFv - Address of the Fv in memory
  251. DestinationFv - Output for destination Fv
  252. DestinationFv == NULL - invalid parameter
  253. *DestinationFv == NULL - memory will be allocated
  254. *DestinationFv != NULL - this address will be the destination
  255. Returns:
  256. EFI_SUCCESS
  257. --*/
  258. {
  259. EFI_STATUS Status;
  260. UINTN size;
  261. if (DestinationFv == NULL) {
  262. return EFI_INVALID_PARAMETER;
  263. }
  264. Status = FvBufGetSize (SourceFv, &size);
  265. if (EFI_ERROR (Status)) {
  266. return Status;
  267. }
  268. if (*DestinationFv == NULL) {
  269. *DestinationFv = CommonLibBinderAllocate (size);
  270. if (*DestinationFv == NULL) {
  271. return EFI_OUT_OF_RESOURCES;
  272. }
  273. }
  274. CommonLibBinderCopyMem (*DestinationFv, SourceFv, size);
  275. return EFI_SUCCESS;
  276. }
  277. EFI_STATUS
  278. FvBufExtend (
  279. IN VOID **Fv,
  280. IN UINTN Size
  281. )
  282. /*++
  283. Routine Description:
  284. Extends a firmware volume by the given number of bytes.
  285. BUGBUG: Does not handle the case where the firmware volume has a
  286. VTF (Volume Top File). The VTF will not be moved to the
  287. end of the extended FV.
  288. Arguments:
  289. Fv - Source and destination firmware volume.
  290. Note: The original firmware volume buffer is freed!
  291. Size - The minimum size that the firmware volume is to be extended by.
  292. The FV may be extended more than this size.
  293. Returns:
  294. EFI_SUCCESS
  295. --*/
  296. {
  297. EFI_STATUS Status;
  298. UINTN OldSize;
  299. UINTN NewSize;
  300. UINTN BlockCount;
  301. VOID* NewFv;
  302. EFI_FIRMWARE_VOLUME_HEADER* hdr;
  303. EFI_FV_BLOCK_MAP_ENTRY* blk;
  304. Status = FvBufGetSize (*Fv, &OldSize);
  305. if (EFI_ERROR (Status)) {
  306. return Status;
  307. }
  308. //
  309. // Locate the block map in the fv header
  310. //
  311. hdr = (EFI_FIRMWARE_VOLUME_HEADER*)*Fv;
  312. blk = hdr->BlockMap;
  313. //
  314. // Calculate the number of blocks needed to achieve the requested
  315. // size extension
  316. //
  317. BlockCount = ((Size + (blk->Length - 1)) / blk->Length);
  318. //
  319. // Calculate the new size from the number of blocks that will be added
  320. //
  321. NewSize = OldSize + (BlockCount * blk->Length);
  322. NewFv = CommonLibBinderAllocate (NewSize);
  323. if (NewFv == NULL) {
  324. return EFI_OUT_OF_RESOURCES;
  325. }
  326. //
  327. // Copy the old data
  328. //
  329. CommonLibBinderCopyMem (NewFv, *Fv, OldSize);
  330. //
  331. // Free the old fv buffer
  332. //
  333. CommonLibBinderFree (*Fv);
  334. //
  335. // Locate the block map in the new fv header
  336. //
  337. hdr = (EFI_FIRMWARE_VOLUME_HEADER*)NewFv;
  338. hdr->FvLength = NewSize;
  339. blk = hdr->BlockMap;
  340. //
  341. // Update the block map for the new fv
  342. //
  343. blk->NumBlocks += (UINT32)BlockCount;
  344. //
  345. // Update the FV header checksum
  346. //
  347. FvBufChecksumHeader (NewFv);
  348. //
  349. // Clear out the new area of the FV
  350. //
  351. CommonLibBinderSetMem (
  352. (UINT8*)NewFv + OldSize,
  353. (NewSize - OldSize),
  354. (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0
  355. );
  356. //
  357. // Set output with new fv that was created
  358. //
  359. *Fv = NewFv;
  360. return EFI_SUCCESS;
  361. }
  362. EFI_STATUS
  363. FvBufClearAllFiles (
  364. IN OUT VOID *Fv
  365. )
  366. /*++
  367. Routine Description:
  368. Clears out all files from the Fv buffer in memory
  369. Arguments:
  370. Fv - Address of the Fv in memory
  371. Returns:
  372. EFI_SUCCESS
  373. --*/
  374. {
  375. EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
  376. EFI_STATUS Status;
  377. UINTN size = 0;
  378. Status = FvBufGetSize (Fv, &size);
  379. if (EFI_ERROR (Status)) {
  380. return Status;
  381. }
  382. CommonLibBinderSetMem(
  383. (UINT8*)hdr + hdr->HeaderLength,
  384. size - hdr->HeaderLength,
  385. (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0
  386. );
  387. return EFI_SUCCESS;
  388. }
  389. EFI_STATUS
  390. FvBufGetSize (
  391. IN VOID *Fv,
  392. OUT UINTN *Size
  393. )
  394. /*++
  395. Routine Description:
  396. Clears out all files from the Fv buffer in memory
  397. Arguments:
  398. Fv - Address of the Fv in memory
  399. Returns:
  400. EFI_SUCCESS
  401. --*/
  402. {
  403. EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
  404. EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap;
  405. *Size = 0;
  406. while (blk->Length != 0 || blk->NumBlocks != 0) {
  407. *Size = *Size + (blk->Length * blk->NumBlocks);
  408. if (*Size >= 0x40000000) {
  409. // If size is greater than 1GB, then assume it is corrupted
  410. return EFI_VOLUME_CORRUPTED;
  411. }
  412. blk++;
  413. }
  414. if (*Size == 0) {
  415. // If size is 0, then assume the volume is corrupted
  416. return EFI_VOLUME_CORRUPTED;
  417. }
  418. return EFI_SUCCESS;
  419. }
  420. EFI_STATUS
  421. FvBufAddFile (
  422. IN OUT VOID *Fv,
  423. IN VOID *File
  424. )
  425. /*++
  426. Routine Description:
  427. Adds a new FFS file
  428. Arguments:
  429. Fv - Address of the Fv in memory
  430. File - FFS file to add to Fv
  431. Returns:
  432. EFI_SUCCESS
  433. --*/
  434. {
  435. EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
  436. EFI_FFS_FILE_HEADER *fhdr = NULL;
  437. EFI_FVB_ATTRIBUTES_2 FvbAttributes;
  438. UINTN offset;
  439. UINTN fsize;
  440. UINTN newSize;
  441. UINTN clearLoop;
  442. EFI_STATUS Status;
  443. UINTN fvSize;
  444. Status = FvBufGetSize (Fv, &fvSize);
  445. if (EFI_ERROR (Status)) {
  446. return Status;
  447. }
  448. FvbAttributes = hdr->Attributes;
  449. newSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);
  450. for(
  451. offset = (UINTN)ALIGN_POINTER (hdr->HeaderLength, 8);
  452. offset + newSize <= fvSize;
  453. offset = (UINTN)ALIGN_POINTER (offset, 8)
  454. ) {
  455. fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + offset);
  456. if (EFI_TEST_FFS_ATTRIBUTES_BIT(
  457. FvbAttributes,
  458. fhdr->State,
  459. EFI_FILE_HEADER_VALID
  460. )
  461. ) {
  462. // BUGBUG: Need to make sure that the new file does not already
  463. // exist.
  464. fsize = FvBufGetFfsFileSize (fhdr);
  465. if (fsize == 0 || (offset + fsize > fvSize)) {
  466. return EFI_VOLUME_CORRUPTED;
  467. }
  468. offset = offset + fsize;
  469. continue;
  470. }
  471. clearLoop = 0;
  472. while ((clearLoop < newSize) &&
  473. (((UINT8*)fhdr)[clearLoop] ==
  474. (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0)
  475. )
  476. ) {
  477. clearLoop++;
  478. }
  479. //
  480. // We found a place in the FV which is empty and big enough for
  481. // the new file
  482. //
  483. if (clearLoop >= newSize) {
  484. break;
  485. }
  486. offset = offset + 1; // Make some forward progress
  487. }
  488. if (offset + newSize > fvSize) {
  489. return EFI_OUT_OF_RESOURCES;
  490. }
  491. CommonLibBinderCopyMem (fhdr, File, newSize);
  492. return EFI_SUCCESS;
  493. }
  494. EFI_STATUS
  495. FvBufAddFileWithExtend (
  496. IN OUT VOID **Fv,
  497. IN VOID *File
  498. )
  499. /*++
  500. Routine Description:
  501. Adds a new FFS file. Extends the firmware volume if needed.
  502. Arguments:
  503. Fv - Source and destination firmware volume.
  504. Note: If the FV is extended, then the original firmware volume
  505. buffer is freed!
  506. Size - The minimum size that the firmware volume is to be extended by.
  507. The FV may be extended more than this size.
  508. Returns:
  509. EFI_SUCCESS
  510. --*/
  511. {
  512. EFI_STATUS Status;
  513. EFI_FFS_FILE_HEADER* NewFile;
  514. NewFile = (EFI_FFS_FILE_HEADER*)File;
  515. //
  516. // Try to add to the capsule volume
  517. //
  518. Status = FvBufAddFile (*Fv, NewFile);
  519. if (Status == EFI_OUT_OF_RESOURCES) {
  520. //
  521. // Try to extend the capsule volume by the size of the file
  522. //
  523. Status = FvBufExtend (Fv, FvBufExpand3ByteSize (NewFile->Size));
  524. if (EFI_ERROR (Status)) {
  525. return Status;
  526. }
  527. //
  528. // Now, try to add the file again
  529. //
  530. Status = FvBufAddFile (*Fv, NewFile);
  531. }
  532. return Status;
  533. }
  534. EFI_STATUS
  535. FvBufAddVtfFile (
  536. IN OUT VOID *Fv,
  537. IN VOID *File
  538. )
  539. /*++
  540. Routine Description:
  541. Adds a new FFS VFT (Volume Top File) file. In other words, adds the
  542. file to the end of the firmware volume.
  543. Arguments:
  544. Fv - Address of the Fv in memory
  545. File - FFS file to add to Fv
  546. Returns:
  547. EFI_SUCCESS
  548. --*/
  549. {
  550. EFI_STATUS Status;
  551. EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
  552. EFI_FFS_FILE_HEADER* NewFile;
  553. UINTN NewFileSize;
  554. UINT8 erasedUint8;
  555. UINTN clearLoop;
  556. EFI_FFS_FILE_HEADER *LastFile;
  557. UINTN LastFileSize;
  558. UINTN fvSize;
  559. UINTN Key;
  560. Status = FvBufGetSize (Fv, &fvSize);
  561. if (EFI_ERROR (Status)) {
  562. return Status;
  563. }
  564. erasedUint8 = (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0);
  565. NewFileSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);
  566. if (NewFileSize != (UINTN)ALIGN_POINTER (NewFileSize, 8)) {
  567. return EFI_INVALID_PARAMETER;
  568. }
  569. //
  570. // Find the last file in the FV
  571. //
  572. Key = 0;
  573. LastFile = NULL;
  574. LastFileSize = 0;
  575. do {
  576. Status = FvBufFindNextFile (Fv, &Key, (VOID **)&LastFile);
  577. LastFileSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);
  578. } while (!EFI_ERROR (Status));
  579. //
  580. // If no files were found, then we start at the beginning of the FV
  581. //
  582. if (LastFile == NULL) {
  583. LastFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + hdr->HeaderLength);
  584. }
  585. //
  586. // We want to put the new file (VTF) at the end of the FV
  587. //
  588. NewFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + (fvSize - NewFileSize));
  589. //
  590. // Check to see if there is enough room for the VTF after the last file
  591. // found in the FV
  592. //
  593. if ((UINT8*)NewFile < ((UINT8*)LastFile + LastFileSize)) {
  594. return EFI_OUT_OF_RESOURCES;
  595. }
  596. //
  597. // Loop to determine if the end of the FV is empty
  598. //
  599. clearLoop = 0;
  600. while ((clearLoop < NewFileSize) &&
  601. (((UINT8*)NewFile)[clearLoop] == erasedUint8)
  602. ) {
  603. clearLoop++;
  604. }
  605. //
  606. // Check to see if there was not enough room for the file
  607. //
  608. if (clearLoop < NewFileSize) {
  609. return EFI_OUT_OF_RESOURCES;
  610. }
  611. CommonLibBinderCopyMem (NewFile, File, NewFileSize);
  612. return EFI_SUCCESS;
  613. }
  614. VOID
  615. FvBufCompact3ByteSize (
  616. OUT VOID* SizeDest,
  617. IN UINT32 Size
  618. )
  619. /*++
  620. Routine Description:
  621. Expands the 3 byte size commonly used in Firmware Volume data structures
  622. Arguments:
  623. Size - Address of the 3 byte array representing the size
  624. Returns:
  625. UINT32
  626. --*/
  627. {
  628. ((UINT8*)SizeDest)[0] = (UINT8)Size;
  629. ((UINT8*)SizeDest)[1] = (UINT8)(Size >> 8);
  630. ((UINT8*)SizeDest)[2] = (UINT8)(Size >> 16);
  631. }
  632. UINT32
  633. FvBufGetFfsFileSize (
  634. IN EFI_FFS_FILE_HEADER *Ffs
  635. )
  636. /*++
  637. Routine Description:
  638. Get the FFS file size.
  639. Arguments:
  640. Ffs - Pointer to FFS header
  641. Returns:
  642. UINT32
  643. --*/
  644. {
  645. if (Ffs == NULL) {
  646. return 0;
  647. }
  648. if (Ffs->Attributes & FFS_ATTRIB_LARGE_FILE) {
  649. return (UINT32) ((EFI_FFS_FILE_HEADER2 *)Ffs)->ExtendedSize;
  650. }
  651. return FvBufExpand3ByteSize(Ffs->Size);
  652. }
  653. UINT32
  654. FvBufGetFfsHeaderSize (
  655. IN EFI_FFS_FILE_HEADER *Ffs
  656. )
  657. /*++
  658. Routine Description:
  659. Get the FFS header size.
  660. Arguments:
  661. Ffs - Pointer to FFS header
  662. Returns:
  663. UINT32
  664. --*/
  665. {
  666. if (Ffs == NULL) {
  667. return 0;
  668. }
  669. if (Ffs->Attributes & FFS_ATTRIB_LARGE_FILE) {
  670. return sizeof(EFI_FFS_FILE_HEADER2);
  671. }
  672. return sizeof(EFI_FFS_FILE_HEADER);
  673. }
  674. UINT32
  675. FvBufExpand3ByteSize (
  676. IN VOID* Size
  677. )
  678. /*++
  679. Routine Description:
  680. Expands the 3 byte size commonly used in Firmware Volume data structures
  681. Arguments:
  682. Size - Address of the 3 byte array representing the size
  683. Returns:
  684. UINT32
  685. --*/
  686. {
  687. return (((UINT8*)Size)[2] << 16) +
  688. (((UINT8*)Size)[1] << 8) +
  689. ((UINT8*)Size)[0];
  690. }
  691. EFI_STATUS
  692. FvBufFindNextFile (
  693. IN VOID *Fv,
  694. IN OUT UINTN *Key,
  695. OUT VOID **File
  696. )
  697. /*++
  698. Routine Description:
  699. Iterates through the files contained within the firmware volume
  700. Arguments:
  701. Fv - Address of the Fv in memory
  702. Key - Should be 0 to get the first file. After that, it should be
  703. passed back in without modifying it's contents to retrieve
  704. subsequent files.
  705. File - Output file pointer
  706. File == NULL - invalid parameter
  707. otherwise - *File will be update to the location of the file
  708. Returns:
  709. EFI_SUCCESS
  710. EFI_NOT_FOUND
  711. EFI_VOLUME_CORRUPTED
  712. --*/
  713. {
  714. EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
  715. EFI_FFS_FILE_HEADER *fhdr = NULL;
  716. EFI_FVB_ATTRIBUTES_2 FvbAttributes;
  717. UINTN fsize;
  718. EFI_STATUS Status;
  719. UINTN fvSize;
  720. if (Fv == NULL) {
  721. return EFI_INVALID_PARAMETER;
  722. }
  723. Status = FvBufGetSize (Fv, &fvSize);
  724. if (EFI_ERROR (Status)) {
  725. return Status;
  726. }
  727. if (*Key == 0) {
  728. *Key = hdr->HeaderLength;
  729. }
  730. FvbAttributes = hdr->Attributes;
  731. for(
  732. *Key = (UINTN)ALIGN_POINTER (*Key, 8);
  733. (*Key + sizeof (*fhdr)) < fvSize;
  734. *Key = (UINTN)ALIGN_POINTER (*Key, 8)
  735. ) {
  736. fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + *Key);
  737. fsize = FvBufGetFfsFileSize (fhdr);
  738. if (!EFI_TEST_FFS_ATTRIBUTES_BIT(
  739. FvbAttributes,
  740. fhdr->State,
  741. EFI_FILE_HEADER_VALID
  742. ) ||
  743. EFI_TEST_FFS_ATTRIBUTES_BIT(
  744. FvbAttributes,
  745. fhdr->State,
  746. EFI_FILE_HEADER_INVALID
  747. )
  748. ) {
  749. *Key = *Key + 1; // Make some forward progress
  750. continue;
  751. } else if(
  752. EFI_TEST_FFS_ATTRIBUTES_BIT(
  753. FvbAttributes,
  754. fhdr->State,
  755. EFI_FILE_MARKED_FOR_UPDATE
  756. ) ||
  757. EFI_TEST_FFS_ATTRIBUTES_BIT(
  758. FvbAttributes,
  759. fhdr->State,
  760. EFI_FILE_DELETED
  761. )
  762. ) {
  763. *Key = *Key + fsize;
  764. continue;
  765. } else if (EFI_TEST_FFS_ATTRIBUTES_BIT(
  766. FvbAttributes,
  767. fhdr->State,
  768. EFI_FILE_DATA_VALID
  769. )
  770. ) {
  771. *File = (UINT8*)hdr + *Key;
  772. *Key = *Key + fsize;
  773. return EFI_SUCCESS;
  774. }
  775. *Key = *Key + 1; // Make some forward progress
  776. }
  777. return EFI_NOT_FOUND;
  778. }
  779. EFI_STATUS
  780. FvBufFindFileByName (
  781. IN VOID *Fv,
  782. IN EFI_GUID *Name,
  783. OUT VOID **File
  784. )
  785. /*++
  786. Routine Description:
  787. Searches the Fv for a file by its name
  788. Arguments:
  789. Fv - Address of the Fv in memory
  790. Name - Guid filename to search for in the firmware volume
  791. File - Output file pointer
  792. File == NULL - Only determine if the file exists, based on return
  793. value from the function call.
  794. otherwise - *File will be update to the location of the file
  795. Returns:
  796. EFI_SUCCESS
  797. EFI_NOT_FOUND
  798. EFI_VOLUME_CORRUPTED
  799. --*/
  800. {
  801. EFI_STATUS Status;
  802. UINTN Key;
  803. EFI_FFS_FILE_HEADER *NextFile;
  804. Key = 0;
  805. while (TRUE) {
  806. Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile);
  807. if (EFI_ERROR (Status)) {
  808. return Status;
  809. }
  810. if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) {
  811. if (File != NULL) {
  812. *File = NextFile;
  813. }
  814. return EFI_SUCCESS;
  815. }
  816. }
  817. return EFI_NOT_FOUND;
  818. }
  819. EFI_STATUS
  820. FvBufFindFileByType (
  821. IN VOID *Fv,
  822. IN EFI_FV_FILETYPE Type,
  823. OUT VOID **File
  824. )
  825. /*++
  826. Routine Description:
  827. Searches the Fv for a file by its type
  828. Arguments:
  829. Fv - Address of the Fv in memory
  830. Type - FFS FILE type to search for
  831. File - Output file pointer
  832. (File == NULL) -> Only determine if the file exists, based on return
  833. value from the function call.
  834. otherwise -> *File will be update to the location of the file
  835. Returns:
  836. EFI_SUCCESS
  837. EFI_NOT_FOUND
  838. EFI_VOLUME_CORRUPTED
  839. --*/
  840. {
  841. EFI_STATUS Status;
  842. UINTN Key;
  843. EFI_FFS_FILE_HEADER *NextFile;
  844. Key = 0;
  845. while (TRUE) {
  846. Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile);
  847. if (EFI_ERROR (Status)) {
  848. return Status;
  849. }
  850. if (Type == NextFile->Type) {
  851. if (File != NULL) {
  852. *File = NextFile;
  853. }
  854. return EFI_SUCCESS;
  855. }
  856. }
  857. return EFI_NOT_FOUND;
  858. }
  859. EFI_STATUS
  860. FvBufGetFileRawData (
  861. IN VOID* FfsFile,
  862. OUT VOID** RawData,
  863. OUT UINTN* RawDataSize
  864. )
  865. /*++
  866. Routine Description:
  867. Searches the requested file for raw data.
  868. This routine either returns all the payload of a EFI_FV_FILETYPE_RAW file,
  869. or finds the EFI_SECTION_RAW section within the file and returns its data.
  870. Arguments:
  871. FfsFile - Address of the FFS file in memory
  872. RawData - Pointer to the raw data within the file
  873. (This is NOT allocated. It is within the file.)
  874. RawDataSize - Size of the raw data within the file
  875. Returns:
  876. EFI_STATUS
  877. --*/
  878. {
  879. EFI_STATUS Status;
  880. EFI_FFS_FILE_HEADER* File;
  881. EFI_RAW_SECTION* Section;
  882. File = (EFI_FFS_FILE_HEADER*)FfsFile;
  883. //
  884. // Is the file type == EFI_FV_FILETYPE_RAW?
  885. //
  886. if (File->Type == EFI_FV_FILETYPE_RAW) {
  887. //
  888. // Raw filetypes don't have sections, so we just return the raw data
  889. //
  890. *RawData = (VOID*)((UINT8 *)File + FvBufGetFfsHeaderSize (File));
  891. *RawDataSize = FvBufGetFfsFileSize (File) - FvBufGetFfsHeaderSize (File);
  892. return EFI_SUCCESS;
  893. }
  894. //
  895. // Within the file, we now need to find the EFI_SECTION_RAW section.
  896. //
  897. Status = FvBufFindSectionByType (File, EFI_SECTION_RAW, (VOID **)&Section);
  898. if (EFI_ERROR (Status)) {
  899. return Status;
  900. }
  901. *RawData = (VOID*)((UINT8 *)Section + FvBufGetSecHdrLen(Section));
  902. *RawDataSize =
  903. FvBufGetSecFileLen (Section) - FvBufGetSecHdrLen(Section);
  904. return EFI_SUCCESS;
  905. }
  906. EFI_STATUS
  907. FvBufPackageFreeformRawFile (
  908. IN EFI_GUID* Filename,
  909. IN VOID* RawData,
  910. IN UINTN RawDataSize,
  911. OUT VOID** FfsFile
  912. )
  913. /*++
  914. Routine Description:
  915. Packages up a FFS file containing the input raw data.
  916. The file created will have a type of EFI_FV_FILETYPE_FREEFORM, and will
  917. contain one EFI_FV_FILETYPE_RAW section.
  918. Arguments:
  919. RawData - Pointer to the raw data to be packed
  920. RawDataSize - Size of the raw data to be packed
  921. FfsFile - Address of the packaged FFS file.
  922. Note: The called must deallocate this memory!
  923. Returns:
  924. EFI_STATUS
  925. --*/
  926. {
  927. EFI_FFS_FILE_HEADER* NewFile;
  928. UINT32 NewFileSize;
  929. EFI_RAW_SECTION* NewSection;
  930. UINT32 NewSectionSize;
  931. UINT32 FfsHdrLen;
  932. UINT32 SecHdrLen;
  933. //
  934. // The section size is the DataSize + the size of the section header
  935. //
  936. NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION) + (UINT32)RawDataSize;
  937. SecHdrLen = sizeof (EFI_RAW_SECTION);
  938. if (NewSectionSize >= MAX_SECTION_SIZE) {
  939. NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION2) + (UINT32)RawDataSize;
  940. SecHdrLen = sizeof (EFI_RAW_SECTION2);
  941. }
  942. //
  943. // The file size is the size of the file header + the section size
  944. //
  945. NewFileSize = sizeof (EFI_FFS_FILE_HEADER) + NewSectionSize;
  946. FfsHdrLen = sizeof (EFI_FFS_FILE_HEADER);
  947. if (NewFileSize >= MAX_FFS_SIZE) {
  948. NewFileSize = sizeof (EFI_FFS_FILE_HEADER2) + NewSectionSize;
  949. FfsHdrLen = sizeof (EFI_FFS_FILE_HEADER2);
  950. }
  951. //
  952. // Try to allocate a buffer to build the new FFS file in
  953. //
  954. NewFile = CommonLibBinderAllocate (NewFileSize);
  955. if (NewFile == NULL) {
  956. return EFI_OUT_OF_RESOURCES;
  957. }
  958. CommonLibBinderSetMem (NewFile, NewFileSize, 0);
  959. //
  960. // The NewSection follow right after the FFS file header
  961. //
  962. NewSection = (EFI_RAW_SECTION*)((UINT8*)NewFile + FfsHdrLen);
  963. if (NewSectionSize >= MAX_SECTION_SIZE) {
  964. FvBufCompact3ByteSize (NewSection->Size, 0xffffff);
  965. ((EFI_RAW_SECTION2 *)NewSection)->ExtendedSize = NewSectionSize;
  966. } else {
  967. FvBufCompact3ByteSize (NewSection->Size, NewSectionSize);
  968. }
  969. NewSection->Type = EFI_SECTION_RAW;
  970. //
  971. // Copy the actual file data into the buffer
  972. //
  973. CommonLibBinderCopyMem ((UINT8 *)NewSection + SecHdrLen, RawData, RawDataSize);
  974. //
  975. // Initialize the FFS file header
  976. //
  977. CommonLibBinderCopyMem (&NewFile->Name, Filename, sizeof (EFI_GUID));
  978. NewFile->Attributes = 0;
  979. if (NewFileSize >= MAX_FFS_SIZE) {
  980. FvBufCompact3ByteSize (NewFile->Size, 0x0);
  981. ((EFI_FFS_FILE_HEADER2 *)NewFile)->ExtendedSize = NewFileSize;
  982. NewFile->Attributes |= FFS_ATTRIB_LARGE_FILE;
  983. } else {
  984. FvBufCompact3ByteSize (NewFile->Size, NewFileSize);
  985. }
  986. NewFile->Type = EFI_FV_FILETYPE_FREEFORM;
  987. NewFile->IntegrityCheck.Checksum.Header =
  988. FvBufCalculateChecksum8 ((UINT8*)NewFile, FfsHdrLen);
  989. NewFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
  990. NewFile->State = (UINT8)~( EFI_FILE_HEADER_CONSTRUCTION |
  991. EFI_FILE_HEADER_VALID |
  992. EFI_FILE_DATA_VALID
  993. );
  994. *FfsFile = NewFile;
  995. return EFI_SUCCESS;
  996. }
  997. EFI_STATUS
  998. FvBufFindNextSection (
  999. IN VOID *SectionsStart,
  1000. IN UINTN TotalSectionsSize,
  1001. IN OUT UINTN *Key,
  1002. OUT VOID **Section
  1003. )
  1004. /*++
  1005. Routine Description:
  1006. Iterates through the sections contained within a given array of sections
  1007. Arguments:
  1008. SectionsStart - Address of the start of the FFS sections array
  1009. TotalSectionsSize - Total size of all the sections
  1010. Key - Should be 0 to get the first section. After that, it should be
  1011. passed back in without modifying it's contents to retrieve
  1012. subsequent files.
  1013. Section - Output section pointer
  1014. (Section == NULL) -> invalid parameter
  1015. otherwise -> *Section will be update to the location of the file
  1016. Returns:
  1017. EFI_SUCCESS
  1018. EFI_NOT_FOUND
  1019. EFI_VOLUME_CORRUPTED
  1020. --*/
  1021. {
  1022. EFI_COMMON_SECTION_HEADER *sectionHdr;
  1023. UINTN sectionSize;
  1024. *Key = (UINTN)ALIGN_POINTER (*Key, 4); // Sections are DWORD aligned
  1025. if ((*Key + sizeof (*sectionHdr)) > TotalSectionsSize) {
  1026. return EFI_NOT_FOUND;
  1027. }
  1028. sectionHdr = (EFI_COMMON_SECTION_HEADER*)((UINT8*)SectionsStart + *Key);
  1029. sectionSize = FvBufGetSecFileLen (sectionHdr);
  1030. if (sectionSize < sizeof (EFI_COMMON_SECTION_HEADER)) {
  1031. return EFI_NOT_FOUND;
  1032. }
  1033. if ((*Key + sectionSize) > TotalSectionsSize) {
  1034. return EFI_NOT_FOUND;
  1035. }
  1036. *Section = (UINT8*)sectionHdr;
  1037. *Key = *Key + sectionSize;
  1038. return EFI_SUCCESS;
  1039. }
  1040. EFI_STATUS
  1041. FvBufCountSections (
  1042. IN VOID* FfsFile,
  1043. IN UINTN* Count
  1044. )
  1045. /*++
  1046. Routine Description:
  1047. Searches the FFS file and counts the number of sections found.
  1048. The sections are NOT recursed.
  1049. Arguments:
  1050. FfsFile - Address of the FFS file in memory
  1051. Count - The location to store the section count in
  1052. Returns:
  1053. EFI_SUCCESS
  1054. EFI_NOT_FOUND
  1055. EFI_VOLUME_CORRUPTED
  1056. --*/
  1057. {
  1058. EFI_STATUS Status;
  1059. UINTN Key;
  1060. VOID* SectionStart;
  1061. UINTN TotalSectionsSize;
  1062. EFI_COMMON_SECTION_HEADER* NextSection;
  1063. SectionStart = (VOID*)((UINTN)FfsFile + FvBufGetFfsHeaderSize(FfsFile));
  1064. TotalSectionsSize =
  1065. FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)FfsFile) -
  1066. FvBufGetFfsHeaderSize(FfsFile);
  1067. Key = 0;
  1068. *Count = 0;
  1069. while (TRUE) {
  1070. Status = FvBufFindNextSection (
  1071. SectionStart,
  1072. TotalSectionsSize,
  1073. &Key,
  1074. (VOID **)&NextSection
  1075. );
  1076. if (Status == EFI_NOT_FOUND) {
  1077. return EFI_SUCCESS;
  1078. } else if (EFI_ERROR (Status)) {
  1079. return Status;
  1080. }
  1081. //
  1082. // Increment the section counter
  1083. //
  1084. *Count += 1;
  1085. }
  1086. return EFI_NOT_FOUND;
  1087. }
  1088. EFI_STATUS
  1089. FvBufFindSectionByType (
  1090. IN VOID *FfsFile,
  1091. IN UINT8 Type,
  1092. OUT VOID **Section
  1093. )
  1094. /*++
  1095. Routine Description:
  1096. Searches the FFS file for a section by its type
  1097. Arguments:
  1098. FfsFile - Address of the FFS file in memory
  1099. Type - FFS FILE section type to search for
  1100. Section - Output section pointer
  1101. (Section == NULL) -> Only determine if the section exists, based on return
  1102. value from the function call.
  1103. otherwise -> *Section will be update to the location of the file
  1104. Returns:
  1105. EFI_SUCCESS
  1106. EFI_NOT_FOUND
  1107. EFI_VOLUME_CORRUPTED
  1108. --*/
  1109. {
  1110. EFI_STATUS Status;
  1111. UINTN Key;
  1112. VOID* SectionStart;
  1113. UINTN TotalSectionsSize;
  1114. EFI_COMMON_SECTION_HEADER* NextSection;
  1115. SectionStart = (VOID*)((UINTN)FfsFile + FvBufGetFfsHeaderSize(FfsFile));
  1116. TotalSectionsSize =
  1117. FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)FfsFile) -
  1118. FvBufGetFfsHeaderSize(FfsFile);
  1119. Key = 0;
  1120. while (TRUE) {
  1121. Status = FvBufFindNextSection (
  1122. SectionStart,
  1123. TotalSectionsSize,
  1124. &Key,
  1125. (VOID **)&NextSection
  1126. );
  1127. if (EFI_ERROR (Status)) {
  1128. return Status;
  1129. }
  1130. if (Type == NextSection->Type) {
  1131. if (Section != NULL) {
  1132. *Section = NextSection;
  1133. }
  1134. return EFI_SUCCESS;
  1135. }
  1136. }
  1137. return EFI_NOT_FOUND;
  1138. }
  1139. EFI_STATUS
  1140. FvBufShrinkWrap (
  1141. IN VOID *Fv
  1142. )
  1143. /*++
  1144. Routine Description:
  1145. Shrinks a firmware volume (in place) to provide a minimal FV.
  1146. BUGBUG: Does not handle the case where the firmware volume has a
  1147. VTF (Volume Top File). The VTF will not be moved to the
  1148. end of the extended FV.
  1149. Arguments:
  1150. Fv - Firmware volume.
  1151. Returns:
  1152. EFI_SUCCESS
  1153. --*/
  1154. {
  1155. EFI_STATUS Status;
  1156. UINTN OldSize;
  1157. UINT32 BlockCount;
  1158. UINT32 NewBlockSize = 128;
  1159. UINTN Key;
  1160. EFI_FFS_FILE_HEADER* FileIt;
  1161. VOID* EndOfLastFile;
  1162. EFI_FIRMWARE_VOLUME_HEADER* FvHdr;
  1163. Status = FvBufGetSize (Fv, &OldSize);
  1164. if (EFI_ERROR (Status)) {
  1165. return Status;
  1166. }
  1167. Status = FvBufUnifyBlockSizes (Fv, NewBlockSize);
  1168. if (EFI_ERROR (Status)) {
  1169. return Status;
  1170. }
  1171. //
  1172. // Locate the block map in the fv header
  1173. //
  1174. FvHdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
  1175. //
  1176. // Find the end of the last file
  1177. //
  1178. Key = 0;
  1179. EndOfLastFile = (UINT8*)FvHdr + FvHdr->FvLength;
  1180. while (!EFI_ERROR (FvBufFindNextFile (Fv, &Key, (VOID **)&FileIt))) {
  1181. EndOfLastFile =
  1182. (VOID*)((UINT8*)FileIt + FvBufGetFfsFileSize (FileIt));
  1183. }
  1184. //
  1185. // Set the BlockCount to have the minimal number of blocks for the Fv.
  1186. //
  1187. BlockCount = (UINT32)((UINTN)EndOfLastFile - (UINTN)Fv);
  1188. BlockCount = BlockCount + NewBlockSize - 1;
  1189. BlockCount = BlockCount / NewBlockSize;
  1190. //
  1191. // Adjust the block count to shrink the Fv in place.
  1192. //
  1193. FvHdr->BlockMap[0].NumBlocks = BlockCount;
  1194. FvHdr->FvLength = BlockCount * NewBlockSize;
  1195. //
  1196. // Update the FV header checksum
  1197. //
  1198. FvBufChecksumHeader (Fv);
  1199. return EFI_SUCCESS;
  1200. }
  1201. EFI_STATUS
  1202. FvBufUnifyBlockSizes (
  1203. IN OUT VOID *Fv,
  1204. IN UINTN BlockSize
  1205. )
  1206. /*++
  1207. Routine Description:
  1208. Searches the FFS file for a section by its type
  1209. Arguments:
  1210. Fv - Address of the Fv in memory
  1211. BlockSize - The size of the blocks to convert the Fv to. If the total size
  1212. of the Fv is not evenly divisible by this size, then
  1213. EFI_INVALID_PARAMETER will be returned.
  1214. Returns:
  1215. EFI_SUCCESS
  1216. EFI_NOT_FOUND
  1217. EFI_VOLUME_CORRUPTED
  1218. --*/
  1219. {
  1220. EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
  1221. EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap;
  1222. UINT32 Size;
  1223. Size = 0;
  1224. //
  1225. // Scan through the block map list, performing error checking, and adding
  1226. // up the total Fv size.
  1227. //
  1228. while( blk->Length != 0 ||
  1229. blk->NumBlocks != 0
  1230. ) {
  1231. Size = Size + (blk->Length * blk->NumBlocks);
  1232. blk++;
  1233. if ((UINT8*)blk > ((UINT8*)hdr + hdr->HeaderLength)) {
  1234. return EFI_VOLUME_CORRUPTED;
  1235. }
  1236. }
  1237. //
  1238. // Make sure that the Fv size is a multiple of the new block size.
  1239. //
  1240. if ((Size % BlockSize) != 0) {
  1241. return EFI_INVALID_PARAMETER;
  1242. }
  1243. //
  1244. // Zero out the entire block map.
  1245. //
  1246. CommonLibBinderSetMem (
  1247. &hdr->BlockMap,
  1248. (UINTN)blk - (UINTN)&hdr->BlockMap,
  1249. 0
  1250. );
  1251. //
  1252. // Write out the single block map entry.
  1253. //
  1254. hdr->BlockMap[0].Length = (UINT32)BlockSize;
  1255. hdr->BlockMap[0].NumBlocks = Size / (UINT32)BlockSize;
  1256. return EFI_SUCCESS;
  1257. }
  1258. STATIC
  1259. UINT16
  1260. FvBufCalculateSum16 (
  1261. IN UINT16 *Buffer,
  1262. IN UINTN Size
  1263. )
  1264. /*++
  1265. Routine Description:
  1266. This function calculates the UINT16 sum for the requested region.
  1267. Arguments:
  1268. Buffer Pointer to buffer containing byte data of component.
  1269. Size Size of the buffer
  1270. Returns:
  1271. The 16 bit checksum
  1272. --*/
  1273. {
  1274. UINTN Index;
  1275. UINT16 Sum;
  1276. Sum = 0;
  1277. //
  1278. // Perform the word sum for buffer
  1279. //
  1280. for (Index = 0; Index < Size; Index++) {
  1281. Sum = (UINT16) (Sum + Buffer[Index]);
  1282. }
  1283. return (UINT16) Sum;
  1284. }
  1285. STATIC
  1286. UINT16
  1287. FvBufCalculateChecksum16 (
  1288. IN UINT16 *Buffer,
  1289. IN UINTN Size
  1290. )
  1291. /*++
  1292. Routine Description::
  1293. This function calculates the value needed for a valid UINT16 checksum
  1294. Arguments:
  1295. Buffer Pointer to buffer containing byte data of component.
  1296. Size Size of the buffer
  1297. Returns:
  1298. The 16 bit checksum value needed.
  1299. --*/
  1300. {
  1301. return (UINT16)(0x10000 - FvBufCalculateSum16 (Buffer, Size));
  1302. }
  1303. STATIC
  1304. UINT8
  1305. FvBufCalculateSum8 (
  1306. IN UINT8 *Buffer,
  1307. IN UINTN Size
  1308. )
  1309. /*++
  1310. Description:
  1311. This function calculates the UINT8 sum for the requested region.
  1312. Input:
  1313. Buffer Pointer to buffer containing byte data of component.
  1314. Size Size of the buffer
  1315. Return:
  1316. The 8 bit checksum value needed.
  1317. --*/
  1318. {
  1319. UINTN Index;
  1320. UINT8 Sum;
  1321. Sum = 0;
  1322. //
  1323. // Perform the byte sum for buffer
  1324. //
  1325. for (Index = 0; Index < Size; Index++) {
  1326. Sum = (UINT8) (Sum + Buffer[Index]);
  1327. }
  1328. return Sum;
  1329. }
  1330. STATIC
  1331. UINT8
  1332. FvBufCalculateChecksum8 (
  1333. IN UINT8 *Buffer,
  1334. IN UINTN Size
  1335. )
  1336. /*++
  1337. Description:
  1338. This function calculates the value needed for a valid UINT8 checksum
  1339. Input:
  1340. Buffer Pointer to buffer containing byte data of component.
  1341. Size Size of the buffer
  1342. Return:
  1343. The 8 bit checksum value needed.
  1344. --*/
  1345. {
  1346. return (UINT8)(0x100 - FvBufCalculateSum8 (Buffer, Size));
  1347. }