• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 EFI Firmware Volume routines which work on a Fv image in buffers.
3 
4 Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "FirmwareVolumeBufferLib.h"
16 #include "BinderFuncs.h"
17 
18 //
19 // Local macros
20 //
21 #define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \
22     ( \
23       (BOOLEAN) ( \
24           (FvbAttributes & EFI_FVB2_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \
25         ) \
26     )
27 
28 
29 //
30 // Local prototypes
31 //
32 
33 STATIC
34 UINT32
FvBufGetSecHdrLen(IN EFI_COMMON_SECTION_HEADER * SectionHeader)35 FvBufGetSecHdrLen(
36    IN EFI_COMMON_SECTION_HEADER *SectionHeader
37    )
38 {
39   if (SectionHeader == NULL) {
40     return 0;
41   }
42   if (FvBufExpand3ByteSize(SectionHeader->Size) == 0xffffff) {
43     return sizeof(EFI_COMMON_SECTION_HEADER2);
44   }
45   return sizeof(EFI_COMMON_SECTION_HEADER);
46 }
47 
48 STATIC
49 UINT32
FvBufGetSecFileLen(IN EFI_COMMON_SECTION_HEADER * SectionHeader)50 FvBufGetSecFileLen (
51   IN EFI_COMMON_SECTION_HEADER *SectionHeader
52   )
53 {
54   UINT32 Length;
55   if (SectionHeader == NULL) {
56     return 0;
57   }
58   Length = FvBufExpand3ByteSize(SectionHeader->Size);
59   if (Length == 0xffffff) {
60     Length = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize;
61   }
62   return Length;
63 }
64 
65 //
66 // Local prototypes
67 //
68 
69 STATIC
70 UINT16
71 FvBufCalculateChecksum16 (
72   IN UINT16       *Buffer,
73   IN UINTN        Size
74   );
75 
76 STATIC
77 UINT8
78 FvBufCalculateChecksum8 (
79   IN UINT8        *Buffer,
80   IN UINTN        Size
81   );
82 
83 //
84 // Procedures start
85 //
86 
87 EFI_STATUS
FvBufRemoveFileNew(IN OUT VOID * Fv,IN EFI_GUID * Name)88 FvBufRemoveFileNew (
89   IN OUT VOID *Fv,
90   IN EFI_GUID *Name
91   )
92 /*++
93 
94 Routine Description:
95 
96   Clears out all files from the Fv buffer in memory
97 
98 Arguments:
99 
100   SourceFv - Address of the Fv in memory, this firmware volume volume will
101              be modified, if SourceFfsFile exists
102   SourceFfsFile - Input FFS file to replace
103 
104 Returns:
105 
106   EFI_SUCCESS
107   EFI_NOT_FOUND
108 
109 --*/
110 {
111   EFI_STATUS                  Status;
112   EFI_FFS_FILE_HEADER*        FileToRm;
113   UINTN                       FileToRmLength;
114 
115   Status = FvBufFindFileByName(
116     Fv,
117     Name,
118     (VOID **)&FileToRm
119     );
120   if (EFI_ERROR (Status)) {
121     return Status;
122   }
123 
124   FileToRmLength = FvBufGetFfsFileSize (FileToRm);
125 
126   CommonLibBinderSetMem (
127     FileToRm,
128     FileToRmLength,
129     (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY)
130       ? 0xFF : 0
131     );
132 
133   return EFI_SUCCESS;
134 }
135 
136 
137 EFI_STATUS
FvBufRemoveFile(IN OUT VOID * Fv,IN EFI_GUID * Name)138 FvBufRemoveFile (
139   IN OUT VOID *Fv,
140   IN EFI_GUID *Name
141   )
142 /*++
143 
144 Routine Description:
145 
146   Clears out all files from the Fv buffer in memory
147 
148 Arguments:
149 
150   SourceFv - Address of the Fv in memory, this firmware volume volume will
151              be modified, if SourceFfsFile exists
152   SourceFfsFile - Input FFS file to replace
153 
154 Returns:
155 
156   EFI_SUCCESS
157   EFI_NOT_FOUND
158 
159 --*/
160 {
161   EFI_STATUS                  Status;
162   EFI_FFS_FILE_HEADER        *NextFile;
163   EFI_FIRMWARE_VOLUME_HEADER *TempFv;
164   UINTN                       FileKey;
165   UINTN                       FvLength;
166 
167   Status = FvBufFindFileByName(
168     Fv,
169     Name,
170     NULL
171     );
172   if (EFI_ERROR (Status)) {
173     return Status;
174   }
175 
176   Status = FvBufGetSize (Fv, &FvLength);
177   if (EFI_ERROR (Status)) {
178     return Status;
179   }
180 
181   TempFv = NULL;
182   Status = FvBufDuplicate (Fv, (VOID **)&TempFv);
183   if (EFI_ERROR (Status)) {
184     return Status;
185   }
186 
187   Status = FvBufClearAllFiles (TempFv);
188   if (EFI_ERROR (Status)) {
189     CommonLibBinderFree (TempFv);
190     return Status;
191   }
192 
193   // TempFv has been allocated.  It must now be freed
194   // before returning.
195 
196   FileKey = 0;
197   while (TRUE) {
198 
199     Status = FvBufFindNextFile (Fv, &FileKey, (VOID **)&NextFile);
200     if (Status == EFI_NOT_FOUND) {
201       break;
202     } else if (EFI_ERROR (Status)) {
203       CommonLibBinderFree (TempFv);
204       return Status;
205     }
206 
207     if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) {
208       continue;
209     }
210     else {
211       Status = FvBufAddFile (TempFv, NextFile);
212       if (EFI_ERROR (Status)) {
213         CommonLibBinderFree (TempFv);
214         return Status;
215       }
216     }
217   }
218 
219   CommonLibBinderCopyMem (Fv, TempFv, FvLength);
220   CommonLibBinderFree (TempFv);
221 
222   return EFI_SUCCESS;
223 }
224 
225 
226 EFI_STATUS
FvBufChecksumFile(IN OUT VOID * FfsFile)227 FvBufChecksumFile (
228   IN OUT VOID *FfsFile
229   )
230 /*++
231 
232 Routine Description:
233 
234   Clears out all files from the Fv buffer in memory
235 
236 Arguments:
237 
238   SourceFfsFile - Input FFS file to update the checksum for
239 
240 Returns:
241 
242   EFI_SUCCESS
243   EFI_NOT_FOUND
244 
245 --*/
246 {
247   EFI_FFS_FILE_HEADER* File = (EFI_FFS_FILE_HEADER*)FfsFile;
248   EFI_FFS_FILE_STATE StateBackup;
249   UINT32 FileSize;
250 
251   FileSize = FvBufGetFfsFileSize (File);
252 
253   //
254   // Fill in checksums and state, they must be 0 for checksumming.
255   //
256   File->IntegrityCheck.Checksum.Header = 0;
257   File->IntegrityCheck.Checksum.File = 0;
258   StateBackup = File->State;
259   File->State = 0;
260 
261   File->IntegrityCheck.Checksum.Header =
262     FvBufCalculateChecksum8 (
263       (UINT8 *) File,
264       FvBufGetFfsHeaderSize (File)
265       );
266 
267   if (File->Attributes & FFS_ATTRIB_CHECKSUM) {
268     File->IntegrityCheck.Checksum.File = FvBufCalculateChecksum8 (
269                                                 (VOID*)((UINT8 *)File + FvBufGetFfsHeaderSize (File)),
270                                                 FileSize - FvBufGetFfsHeaderSize (File)
271                                                 );
272   } else {
273     File->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
274   }
275 
276   File->State = StateBackup;
277 
278   return EFI_SUCCESS;
279 }
280 
281 
282 EFI_STATUS
FvBufChecksumHeader(IN OUT VOID * Fv)283 FvBufChecksumHeader (
284   IN OUT VOID *Fv
285   )
286 /*++
287 
288 Routine Description:
289 
290   Clears out all files from the Fv buffer in memory
291 
292 Arguments:
293 
294   SourceFv - Address of the Fv in memory, this firmware volume volume will
295              be modified, if SourceFfsFile exists
296   SourceFfsFile - Input FFS file to replace
297 
298 Returns:
299 
300   EFI_SUCCESS
301   EFI_NOT_FOUND
302 
303 --*/
304 {
305   EFI_FIRMWARE_VOLUME_HEADER* FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
306 
307   FvHeader->Checksum = 0;
308   FvHeader->Checksum =
309     FvBufCalculateChecksum16 (
310       (UINT16*) FvHeader,
311       FvHeader->HeaderLength / sizeof (UINT16)
312       );
313 
314   return EFI_SUCCESS;
315 }
316 
317 
318 EFI_STATUS
FvBufDuplicate(IN VOID * SourceFv,IN OUT VOID ** DestinationFv)319 FvBufDuplicate (
320   IN VOID *SourceFv,
321   IN OUT VOID **DestinationFv
322   )
323 /*++
324 
325 Routine Description:
326 
327   Clears out all files from the Fv buffer in memory
328 
329 Arguments:
330 
331   SourceFv - Address of the Fv in memory
332   DestinationFv - Output for destination Fv
333     DestinationFv == NULL - invalid parameter
334     *DestinationFv == NULL - memory will be allocated
335     *DestinationFv != NULL - this address will be the destination
336 
337 Returns:
338 
339   EFI_SUCCESS
340 
341 --*/
342 {
343   EFI_STATUS Status;
344   UINTN size;
345 
346   if (DestinationFv == NULL) {
347     return EFI_INVALID_PARAMETER;
348   }
349 
350   Status = FvBufGetSize (SourceFv, &size);
351   if (EFI_ERROR (Status)) {
352     return Status;
353   }
354 
355   if (*DestinationFv == NULL) {
356     *DestinationFv = CommonLibBinderAllocate (size);
357     if (*DestinationFv == NULL) {
358       return EFI_OUT_OF_RESOURCES;
359     }
360   }
361 
362   CommonLibBinderCopyMem (*DestinationFv, SourceFv, size);
363 
364   return EFI_SUCCESS;
365 }
366 
367 
368 EFI_STATUS
FvBufExtend(IN VOID ** Fv,IN UINTN Size)369 FvBufExtend (
370   IN VOID **Fv,
371   IN UINTN Size
372   )
373 /*++
374 
375 Routine Description:
376 
377   Extends a firmware volume by the given number of bytes.
378 
379   BUGBUG: Does not handle the case where the firmware volume has a
380           VTF (Volume Top File).  The VTF will not be moved to the
381           end of the extended FV.
382 
383 Arguments:
384 
385   Fv - Source and destination firmware volume.
386        Note: The original firmware volume buffer is freed!
387 
388   Size - The minimum size that the firmware volume is to be extended by.
389          The FV may be extended more than this size.
390 
391 Returns:
392 
393   EFI_SUCCESS
394 
395 --*/
396 {
397   EFI_STATUS Status;
398   UINTN OldSize;
399   UINTN NewSize;
400   UINTN BlockCount;
401   VOID* NewFv;
402 
403   EFI_FIRMWARE_VOLUME_HEADER* hdr;
404   EFI_FV_BLOCK_MAP_ENTRY*     blk;
405 
406   Status = FvBufGetSize (*Fv, &OldSize);
407   if (EFI_ERROR (Status)) {
408     return Status;
409   }
410 
411   //
412   // Locate the block map in the fv header
413   //
414   hdr = (EFI_FIRMWARE_VOLUME_HEADER*)*Fv;
415   blk = hdr->BlockMap;
416 
417   //
418   // Calculate the number of blocks needed to achieve the requested
419   // size extension
420   //
421   BlockCount = ((Size + (blk->Length - 1)) / blk->Length);
422 
423   //
424   // Calculate the new size from the number of blocks that will be added
425   //
426   NewSize = OldSize + (BlockCount * blk->Length);
427 
428   NewFv = CommonLibBinderAllocate (NewSize);
429   if (NewFv == NULL) {
430     return EFI_OUT_OF_RESOURCES;
431   }
432 
433   //
434   // Copy the old data
435   //
436   CommonLibBinderCopyMem (NewFv, *Fv, OldSize);
437 
438   //
439   // Free the old fv buffer
440   //
441   CommonLibBinderFree (*Fv);
442 
443   //
444   // Locate the block map in the new fv header
445   //
446   hdr = (EFI_FIRMWARE_VOLUME_HEADER*)NewFv;
447   hdr->FvLength = NewSize;
448   blk = hdr->BlockMap;
449 
450   //
451   // Update the block map for the new fv
452   //
453   blk->NumBlocks += (UINT32)BlockCount;
454 
455   //
456   // Update the FV header checksum
457   //
458   FvBufChecksumHeader (NewFv);
459 
460   //
461   // Clear out the new area of the FV
462   //
463   CommonLibBinderSetMem (
464     (UINT8*)NewFv + OldSize,
465     (NewSize - OldSize),
466     (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0
467     );
468 
469   //
470   // Set output with new fv that was created
471   //
472   *Fv = NewFv;
473 
474   return EFI_SUCCESS;
475 
476 }
477 
478 
479 EFI_STATUS
FvBufClearAllFiles(IN OUT VOID * Fv)480 FvBufClearAllFiles (
481   IN OUT VOID *Fv
482   )
483 /*++
484 
485 Routine Description:
486 
487   Clears out all files from the Fv buffer in memory
488 
489 Arguments:
490 
491   Fv - Address of the Fv in memory
492 
493 Returns:
494 
495   EFI_SUCCESS
496 
497 --*/
498 
499 {
500   EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
501   EFI_STATUS Status;
502   UINTN size = 0;
503 
504   Status = FvBufGetSize (Fv, &size);
505   if (EFI_ERROR (Status)) {
506     return Status;
507   }
508 
509   CommonLibBinderSetMem(
510     (UINT8*)hdr + hdr->HeaderLength,
511     size - hdr->HeaderLength,
512     (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0
513     );
514 
515   return EFI_SUCCESS;
516 }
517 
518 
519 EFI_STATUS
FvBufGetSize(IN VOID * Fv,OUT UINTN * Size)520 FvBufGetSize (
521   IN VOID *Fv,
522   OUT UINTN *Size
523   )
524 /*++
525 
526 Routine Description:
527 
528   Clears out all files from the Fv buffer in memory
529 
530 Arguments:
531 
532   Fv - Address of the Fv in memory
533 
534 Returns:
535 
536   EFI_SUCCESS
537 
538 --*/
539 
540 {
541   EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
542   EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap;
543 
544   *Size = 0;
545 
546   while (blk->Length != 0 || blk->NumBlocks != 0) {
547     *Size = *Size + (blk->Length * blk->NumBlocks);
548     if (*Size >= 0x40000000) {
549       // If size is greater than 1GB, then assume it is corrupted
550       return EFI_VOLUME_CORRUPTED;
551     }
552     blk++;
553   }
554 
555   if (*Size == 0) {
556     // If size is 0, then assume the volume is corrupted
557     return EFI_VOLUME_CORRUPTED;
558   }
559 
560   return EFI_SUCCESS;
561 }
562 
563 
564 EFI_STATUS
FvBufAddFile(IN OUT VOID * Fv,IN VOID * File)565 FvBufAddFile (
566   IN OUT VOID *Fv,
567   IN VOID *File
568   )
569 /*++
570 
571 Routine Description:
572 
573   Adds a new FFS file
574 
575 Arguments:
576 
577   Fv - Address of the Fv in memory
578   File - FFS file to add to Fv
579 
580 Returns:
581 
582   EFI_SUCCESS
583 
584 --*/
585 {
586   EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
587 
588   EFI_FFS_FILE_HEADER *fhdr = NULL;
589   EFI_FVB_ATTRIBUTES_2 FvbAttributes;
590   UINTN offset;
591   UINTN fsize;
592   UINTN newSize;
593   UINTN clearLoop;
594 
595   EFI_STATUS Status;
596   UINTN fvSize;
597 
598   Status = FvBufGetSize (Fv, &fvSize);
599   if (EFI_ERROR (Status)) {
600     return Status;
601   }
602 
603   FvbAttributes = hdr->Attributes;
604   newSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);
605 
606   for(
607       offset = (UINTN)ALIGN_POINTER (hdr->HeaderLength, 8);
608       offset + newSize <= fvSize;
609       offset = (UINTN)ALIGN_POINTER (offset, 8)
610     ) {
611 
612     fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + offset);
613 
614     if (EFI_TEST_FFS_ATTRIBUTES_BIT(
615           FvbAttributes,
616           fhdr->State,
617           EFI_FILE_HEADER_VALID
618         )
619       ) {
620       // BUGBUG: Need to make sure that the new file does not already
621       // exist.
622 
623       fsize = FvBufGetFfsFileSize (fhdr);
624       if (fsize == 0 || (offset + fsize > fvSize)) {
625         return EFI_VOLUME_CORRUPTED;
626       }
627 
628       offset = offset + fsize;
629       continue;
630     }
631 
632     clearLoop = 0;
633     while ((clearLoop < newSize) &&
634            (((UINT8*)fhdr)[clearLoop] ==
635              (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0)
636            )
637           ) {
638       clearLoop++;
639     }
640 
641     //
642     // We found a place in the FV which is empty and big enough for
643     // the new file
644     //
645     if (clearLoop >= newSize) {
646       break;
647     }
648 
649     offset = offset + 1; // Make some forward progress
650   }
651 
652   if (offset + newSize > fvSize) {
653     return EFI_OUT_OF_RESOURCES;
654   }
655 
656   CommonLibBinderCopyMem (fhdr, File, newSize);
657 
658   return EFI_SUCCESS;
659 }
660 
661 
662 EFI_STATUS
FvBufAddFileWithExtend(IN OUT VOID ** Fv,IN VOID * File)663 FvBufAddFileWithExtend (
664   IN OUT VOID **Fv,
665   IN VOID *File
666   )
667 /*++
668 
669 Routine Description:
670 
671   Adds a new FFS file.  Extends the firmware volume if needed.
672 
673 Arguments:
674 
675   Fv - Source and destination firmware volume.
676        Note: If the FV is extended, then the original firmware volume
677              buffer is freed!
678 
679   Size - The minimum size that the firmware volume is to be extended by.
680          The FV may be extended more than this size.
681 
682 Returns:
683 
684   EFI_SUCCESS
685 
686 --*/
687 {
688   EFI_STATUS Status;
689   EFI_FFS_FILE_HEADER* NewFile;
690 
691   NewFile = (EFI_FFS_FILE_HEADER*)File;
692 
693   //
694   // Try to add to the capsule volume
695   //
696   Status = FvBufAddFile (*Fv, NewFile);
697   if (Status == EFI_OUT_OF_RESOURCES) {
698     //
699     // Try to extend the capsule volume by the size of the file
700     //
701     Status = FvBufExtend (Fv, FvBufExpand3ByteSize (NewFile->Size));
702     if (EFI_ERROR (Status)) {
703       return Status;
704     }
705 
706     //
707     // Now, try to add the file again
708     //
709     Status = FvBufAddFile (*Fv, NewFile);
710   }
711 
712   return Status;
713 }
714 
715 
716 EFI_STATUS
FvBufAddVtfFile(IN OUT VOID * Fv,IN VOID * File)717 FvBufAddVtfFile (
718   IN OUT VOID *Fv,
719   IN VOID *File
720   )
721 /*++
722 
723 Routine Description:
724 
725   Adds a new FFS VFT (Volume Top File) file.  In other words, adds the
726   file to the end of the firmware volume.
727 
728 Arguments:
729 
730   Fv - Address of the Fv in memory
731   File - FFS file to add to Fv
732 
733 Returns:
734 
735   EFI_SUCCESS
736 
737 --*/
738 {
739   EFI_STATUS Status;
740 
741   EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
742 
743   EFI_FFS_FILE_HEADER* NewFile;
744   UINTN                NewFileSize;
745 
746   UINT8 erasedUint8;
747   UINTN clearLoop;
748 
749   EFI_FFS_FILE_HEADER *LastFile;
750   UINTN LastFileSize;
751 
752   UINTN fvSize;
753   UINTN Key;
754 
755   Status = FvBufGetSize (Fv, &fvSize);
756   if (EFI_ERROR (Status)) {
757     return Status;
758   }
759 
760   erasedUint8 = (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0);
761   NewFileSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);
762 
763   if (NewFileSize != (UINTN)ALIGN_POINTER (NewFileSize, 8)) {
764     return EFI_INVALID_PARAMETER;
765   }
766 
767   //
768   // Find the last file in the FV
769   //
770   Key = 0;
771   LastFile = NULL;
772   LastFileSize = 0;
773   do {
774     Status = FvBufFindNextFile (Fv, &Key, (VOID **)&LastFile);
775     LastFileSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File);
776   } while (!EFI_ERROR (Status));
777 
778   //
779   // If no files were found, then we start at the beginning of the FV
780   //
781   if (LastFile == NULL) {
782     LastFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + hdr->HeaderLength);
783   }
784 
785   //
786   // We want to put the new file (VTF) at the end of the FV
787   //
788   NewFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + (fvSize - NewFileSize));
789 
790   //
791   // Check to see if there is enough room for the VTF after the last file
792   // found in the FV
793   //
794   if ((UINT8*)NewFile < ((UINT8*)LastFile + LastFileSize)) {
795     return EFI_OUT_OF_RESOURCES;
796   }
797 
798   //
799   // Loop to determine if the end of the FV is empty
800   //
801   clearLoop = 0;
802   while ((clearLoop < NewFileSize) &&
803          (((UINT8*)NewFile)[clearLoop] == erasedUint8)
804         ) {
805     clearLoop++;
806   }
807 
808   //
809   // Check to see if there was not enough room for the file
810   //
811   if (clearLoop < NewFileSize) {
812     return EFI_OUT_OF_RESOURCES;
813   }
814 
815   CommonLibBinderCopyMem (NewFile, File, NewFileSize);
816 
817   return EFI_SUCCESS;
818 }
819 
820 
821 VOID
FvBufCompact3ByteSize(OUT VOID * SizeDest,IN UINT32 Size)822 FvBufCompact3ByteSize (
823   OUT VOID* SizeDest,
824   IN UINT32 Size
825   )
826 /*++
827 
828 Routine Description:
829 
830   Expands the 3 byte size commonly used in Firmware Volume data structures
831 
832 Arguments:
833 
834   Size - Address of the 3 byte array representing the size
835 
836 Returns:
837 
838   UINT32
839 
840 --*/
841 {
842   ((UINT8*)SizeDest)[0] = (UINT8)Size;
843   ((UINT8*)SizeDest)[1] = (UINT8)(Size >> 8);
844   ((UINT8*)SizeDest)[2] = (UINT8)(Size >> 16);
845 }
846 
847 UINT32
FvBufGetFfsFileSize(IN EFI_FFS_FILE_HEADER * Ffs)848 FvBufGetFfsFileSize (
849   IN EFI_FFS_FILE_HEADER *Ffs
850   )
851 /*++
852 
853 Routine Description:
854 
855   Get the FFS file size.
856 
857 Arguments:
858 
859   Ffs - Pointer to FFS header
860 
861 Returns:
862 
863   UINT32
864 
865 --*/
866 {
867   if (Ffs == NULL) {
868     return 0;
869   }
870   if (Ffs->Attributes & FFS_ATTRIB_LARGE_FILE) {
871     return (UINT32) ((EFI_FFS_FILE_HEADER2 *)Ffs)->ExtendedSize;
872   }
873   return FvBufExpand3ByteSize(Ffs->Size);
874 }
875 
876 UINT32
FvBufGetFfsHeaderSize(IN EFI_FFS_FILE_HEADER * Ffs)877 FvBufGetFfsHeaderSize (
878   IN EFI_FFS_FILE_HEADER *Ffs
879   )
880 /*++
881 
882 Routine Description:
883 
884   Get the FFS header size.
885 
886 Arguments:
887 
888   Ffs - Pointer to FFS header
889 
890 Returns:
891 
892   UINT32
893 
894 --*/
895 {
896   if (Ffs == NULL) {
897     return 0;
898   }
899   if (Ffs->Attributes & FFS_ATTRIB_LARGE_FILE) {
900     return sizeof(EFI_FFS_FILE_HEADER2);
901   }
902   return sizeof(EFI_FFS_FILE_HEADER);
903 }
904 
905 UINT32
FvBufExpand3ByteSize(IN VOID * Size)906 FvBufExpand3ByteSize (
907   IN VOID* Size
908   )
909 /*++
910 
911 Routine Description:
912 
913   Expands the 3 byte size commonly used in Firmware Volume data structures
914 
915 Arguments:
916 
917   Size - Address of the 3 byte array representing the size
918 
919 Returns:
920 
921   UINT32
922 
923 --*/
924 {
925   return (((UINT8*)Size)[2] << 16) +
926          (((UINT8*)Size)[1] << 8) +
927          ((UINT8*)Size)[0];
928 }
929 
930 EFI_STATUS
FvBufFindNextFile(IN VOID * Fv,IN OUT UINTN * Key,OUT VOID ** File)931 FvBufFindNextFile (
932   IN VOID *Fv,
933   IN OUT UINTN *Key,
934   OUT VOID **File
935   )
936 /*++
937 
938 Routine Description:
939 
940   Iterates through the files contained within the firmware volume
941 
942 Arguments:
943 
944   Fv - Address of the Fv in memory
945   Key - Should be 0 to get the first file.  After that, it should be
946         passed back in without modifying it's contents to retrieve
947         subsequent files.
948   File - Output file pointer
949     File == NULL - invalid parameter
950     otherwise - *File will be update to the location of the file
951 
952 Returns:
953 
954   EFI_SUCCESS
955   EFI_NOT_FOUND
956   EFI_VOLUME_CORRUPTED
957 
958 --*/
959 {
960   EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
961 
962   EFI_FFS_FILE_HEADER *fhdr = NULL;
963   EFI_FVB_ATTRIBUTES_2 FvbAttributes;
964   UINTN fsize;
965 
966   EFI_STATUS Status;
967   UINTN fvSize;
968 
969   if (Fv == NULL) {
970     return EFI_INVALID_PARAMETER;
971   }
972 
973   Status = FvBufGetSize (Fv, &fvSize);
974   if (EFI_ERROR (Status)) {
975     return Status;
976   }
977 
978   if (*Key == 0) {
979     *Key = hdr->HeaderLength;
980   }
981 
982   FvbAttributes = hdr->Attributes;
983 
984   for(
985       *Key = (UINTN)ALIGN_POINTER (*Key, 8);
986       (*Key + sizeof (*fhdr)) < fvSize;
987       *Key = (UINTN)ALIGN_POINTER (*Key, 8)
988     ) {
989 
990     fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + *Key);
991     fsize = FvBufGetFfsFileSize (fhdr);
992 
993     if (!EFI_TEST_FFS_ATTRIBUTES_BIT(
994           FvbAttributes,
995           fhdr->State,
996           EFI_FILE_HEADER_VALID
997         ) ||
998         EFI_TEST_FFS_ATTRIBUTES_BIT(
999           FvbAttributes,
1000           fhdr->State,
1001           EFI_FILE_HEADER_INVALID
1002         )
1003       ) {
1004       *Key = *Key + 1; // Make some forward progress
1005       continue;
1006     } else if(
1007         EFI_TEST_FFS_ATTRIBUTES_BIT(
1008           FvbAttributes,
1009           fhdr->State,
1010           EFI_FILE_MARKED_FOR_UPDATE
1011         ) ||
1012         EFI_TEST_FFS_ATTRIBUTES_BIT(
1013           FvbAttributes,
1014           fhdr->State,
1015           EFI_FILE_DELETED
1016         )
1017       ) {
1018       *Key = *Key + fsize;
1019       continue;
1020     } else if (EFI_TEST_FFS_ATTRIBUTES_BIT(
1021           FvbAttributes,
1022           fhdr->State,
1023           EFI_FILE_DATA_VALID
1024         )
1025       ) {
1026       *File = (UINT8*)hdr + *Key;
1027       *Key = *Key + fsize;
1028       return EFI_SUCCESS;
1029     }
1030 
1031     *Key = *Key + 1; // Make some forward progress
1032   }
1033 
1034   return EFI_NOT_FOUND;
1035 }
1036 
1037 
1038 EFI_STATUS
FvBufFindFileByName(IN VOID * Fv,IN EFI_GUID * Name,OUT VOID ** File)1039 FvBufFindFileByName (
1040   IN VOID *Fv,
1041   IN EFI_GUID *Name,
1042   OUT VOID **File
1043   )
1044 /*++
1045 
1046 Routine Description:
1047 
1048   Searches the Fv for a file by its name
1049 
1050 Arguments:
1051 
1052   Fv - Address of the Fv in memory
1053   Name - Guid filename to search for in the firmware volume
1054   File - Output file pointer
1055     File == NULL - Only determine if the file exists, based on return
1056                    value from the function call.
1057     otherwise - *File will be update to the location of the file
1058 
1059 Returns:
1060 
1061   EFI_SUCCESS
1062   EFI_NOT_FOUND
1063   EFI_VOLUME_CORRUPTED
1064 
1065 --*/
1066 {
1067   EFI_STATUS Status;
1068   UINTN Key;
1069   EFI_FFS_FILE_HEADER *NextFile;
1070 
1071   Key = 0;
1072   while (TRUE) {
1073     Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile);
1074     if (EFI_ERROR (Status)) {
1075       return Status;
1076     }
1077 
1078     if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) {
1079       if (File != NULL) {
1080         *File = NextFile;
1081       }
1082       return EFI_SUCCESS;
1083     }
1084   }
1085 
1086   return EFI_NOT_FOUND;
1087 }
1088 
1089 
1090 EFI_STATUS
FvBufFindFileByType(IN VOID * Fv,IN EFI_FV_FILETYPE Type,OUT VOID ** File)1091 FvBufFindFileByType (
1092   IN VOID *Fv,
1093   IN EFI_FV_FILETYPE Type,
1094   OUT VOID **File
1095   )
1096 /*++
1097 
1098 Routine Description:
1099 
1100   Searches the Fv for a file by its type
1101 
1102 Arguments:
1103 
1104   Fv - Address of the Fv in memory
1105   Type - FFS FILE type to search for
1106   File - Output file pointer
1107     (File == NULL) -> Only determine if the file exists, based on return
1108                       value from the function call.
1109     otherwise -> *File will be update to the location of the file
1110 
1111 Returns:
1112 
1113   EFI_SUCCESS
1114   EFI_NOT_FOUND
1115   EFI_VOLUME_CORRUPTED
1116 
1117 --*/
1118 {
1119   EFI_STATUS Status;
1120   UINTN Key;
1121   EFI_FFS_FILE_HEADER *NextFile;
1122 
1123   Key = 0;
1124   while (TRUE) {
1125     Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile);
1126     if (EFI_ERROR (Status)) {
1127       return Status;
1128     }
1129 
1130     if (Type == NextFile->Type) {
1131       if (File != NULL) {
1132         *File = NextFile;
1133       }
1134       return EFI_SUCCESS;
1135     }
1136   }
1137 
1138   return EFI_NOT_FOUND;
1139 }
1140 
1141 
1142 EFI_STATUS
FvBufGetFileRawData(IN VOID * FfsFile,OUT VOID ** RawData,OUT UINTN * RawDataSize)1143 FvBufGetFileRawData (
1144   IN  VOID*     FfsFile,
1145   OUT VOID**    RawData,
1146   OUT UINTN*    RawDataSize
1147   )
1148 /*++
1149 
1150 Routine Description:
1151 
1152   Searches the requested file for raw data.
1153 
1154   This routine either returns all the payload of a EFI_FV_FILETYPE_RAW file,
1155   or finds the EFI_SECTION_RAW section within the file and returns its data.
1156 
1157 Arguments:
1158 
1159   FfsFile - Address of the FFS file in memory
1160   RawData - Pointer to the raw data within the file
1161             (This is NOT allocated.  It is within the file.)
1162   RawDataSize - Size of the raw data within the file
1163 
1164 Returns:
1165 
1166   EFI_STATUS
1167 
1168 --*/
1169 {
1170   EFI_STATUS Status;
1171   EFI_FFS_FILE_HEADER* File;
1172   EFI_RAW_SECTION* Section;
1173 
1174   File = (EFI_FFS_FILE_HEADER*)FfsFile;
1175 
1176   //
1177   // Is the file type == EFI_FV_FILETYPE_RAW?
1178   //
1179   if (File->Type == EFI_FV_FILETYPE_RAW) {
1180     //
1181     // Raw filetypes don't have sections, so we just return the raw data
1182     //
1183     *RawData = (VOID*)((UINT8 *)File + FvBufGetFfsHeaderSize (File));
1184     *RawDataSize = FvBufGetFfsFileSize (File) - FvBufGetFfsHeaderSize (File);
1185     return EFI_SUCCESS;
1186   }
1187 
1188   //
1189   // Within the file, we now need to find the EFI_SECTION_RAW section.
1190   //
1191   Status = FvBufFindSectionByType (File, EFI_SECTION_RAW, (VOID **)&Section);
1192   if (EFI_ERROR (Status)) {
1193     return Status;
1194   }
1195 
1196   *RawData = (VOID*)((UINT8 *)Section + FvBufGetSecHdrLen(Section));
1197   *RawDataSize =
1198     FvBufGetSecFileLen (Section) - FvBufGetSecHdrLen(Section);
1199 
1200   return EFI_SUCCESS;
1201 
1202 }
1203 
1204 
1205 EFI_STATUS
FvBufPackageFreeformRawFile(IN EFI_GUID * Filename,IN VOID * RawData,IN UINTN RawDataSize,OUT VOID ** FfsFile)1206 FvBufPackageFreeformRawFile (
1207   IN EFI_GUID*  Filename,
1208   IN VOID*      RawData,
1209   IN UINTN      RawDataSize,
1210   OUT VOID**    FfsFile
1211   )
1212 /*++
1213 
1214 Routine Description:
1215 
1216   Packages up a FFS file containing the input raw data.
1217 
1218   The file created will have a type of EFI_FV_FILETYPE_FREEFORM, and will
1219   contain one EFI_FV_FILETYPE_RAW section.
1220 
1221 Arguments:
1222 
1223   RawData - Pointer to the raw data to be packed
1224   RawDataSize - Size of the raw data to be packed
1225   FfsFile - Address of the packaged FFS file.
1226             Note: The called must deallocate this memory!
1227 
1228 Returns:
1229 
1230   EFI_STATUS
1231 
1232 --*/
1233 {
1234   EFI_FFS_FILE_HEADER* NewFile;
1235   UINT32 NewFileSize;
1236   EFI_RAW_SECTION* NewSection;
1237   UINT32 NewSectionSize;
1238   UINT32 FfsHdrLen;
1239   UINT32 SecHdrLen;
1240 
1241   //
1242   // The section size is the DataSize + the size of the section header
1243   //
1244   NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION) + (UINT32)RawDataSize;
1245   SecHdrLen = sizeof (EFI_RAW_SECTION);
1246   if (NewSectionSize >= MAX_SECTION_SIZE) {
1247     NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION2) + (UINT32)RawDataSize;
1248     SecHdrLen = sizeof (EFI_RAW_SECTION2);
1249   }
1250 
1251   //
1252   // The file size is the size of the file header + the section size
1253   //
1254   NewFileSize = sizeof (EFI_FFS_FILE_HEADER) + NewSectionSize;
1255   FfsHdrLen = sizeof (EFI_FFS_FILE_HEADER);
1256   if (NewFileSize >= MAX_FFS_SIZE) {
1257     NewFileSize = sizeof (EFI_FFS_FILE_HEADER2) + NewSectionSize;
1258     FfsHdrLen = sizeof (EFI_FFS_FILE_HEADER2);
1259   }
1260 
1261   //
1262   // Try to allocate a buffer to build the new FFS file in
1263   //
1264   NewFile = CommonLibBinderAllocate (NewFileSize);
1265   if (NewFile == NULL) {
1266     return EFI_OUT_OF_RESOURCES;
1267   }
1268   CommonLibBinderSetMem (NewFile, NewFileSize, 0);
1269 
1270   //
1271   // The NewSection follow right after the FFS file header
1272   //
1273   NewSection = (EFI_RAW_SECTION*)((UINT8*)NewFile + FfsHdrLen);
1274   if (NewSectionSize >= MAX_SECTION_SIZE) {
1275     FvBufCompact3ByteSize (NewSection->Size, 0xffffff);
1276     ((EFI_RAW_SECTION2 *)NewSection)->ExtendedSize = NewSectionSize;
1277   } else {
1278     FvBufCompact3ByteSize (NewSection->Size, NewSectionSize);
1279   }
1280   NewSection->Type = EFI_SECTION_RAW;
1281 
1282   //
1283   // Copy the actual file data into the buffer
1284   //
1285   CommonLibBinderCopyMem ((UINT8 *)NewSection + SecHdrLen, RawData, RawDataSize);
1286 
1287   //
1288   // Initialize the FFS file header
1289   //
1290   CommonLibBinderCopyMem (&NewFile->Name, Filename, sizeof (EFI_GUID));
1291   NewFile->Attributes = 0;
1292   if (NewFileSize >= MAX_FFS_SIZE) {
1293     FvBufCompact3ByteSize (NewFile->Size, 0x0);
1294     ((EFI_FFS_FILE_HEADER2 *)NewFile)->ExtendedSize = NewFileSize;
1295     NewFile->Attributes |= FFS_ATTRIB_LARGE_FILE;
1296   } else {
1297     FvBufCompact3ByteSize (NewFile->Size, NewFileSize);
1298   }
1299   NewFile->Type = EFI_FV_FILETYPE_FREEFORM;
1300   NewFile->IntegrityCheck.Checksum.Header =
1301     FvBufCalculateChecksum8 ((UINT8*)NewFile, FfsHdrLen);
1302   NewFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
1303   NewFile->State = (UINT8)~( EFI_FILE_HEADER_CONSTRUCTION |
1304                              EFI_FILE_HEADER_VALID |
1305                              EFI_FILE_DATA_VALID
1306                            );
1307 
1308   *FfsFile = NewFile;
1309 
1310   return EFI_SUCCESS;
1311 }
1312 
1313 
1314 EFI_STATUS
FvBufFindNextSection(IN VOID * SectionsStart,IN UINTN TotalSectionsSize,IN OUT UINTN * Key,OUT VOID ** Section)1315 FvBufFindNextSection (
1316   IN VOID *SectionsStart,
1317   IN UINTN TotalSectionsSize,
1318   IN OUT UINTN *Key,
1319   OUT VOID **Section
1320   )
1321 /*++
1322 
1323 Routine Description:
1324 
1325   Iterates through the sections contained within a given array of sections
1326 
1327 Arguments:
1328 
1329   SectionsStart - Address of the start of the FFS sections array
1330   TotalSectionsSize - Total size of all the sections
1331   Key - Should be 0 to get the first section.  After that, it should be
1332         passed back in without modifying it's contents to retrieve
1333         subsequent files.
1334   Section - Output section pointer
1335     (Section == NULL) -> invalid parameter
1336     otherwise -> *Section will be update to the location of the file
1337 
1338 Returns:
1339 
1340   EFI_SUCCESS
1341   EFI_NOT_FOUND
1342   EFI_VOLUME_CORRUPTED
1343 
1344 --*/
1345 {
1346   EFI_COMMON_SECTION_HEADER *sectionHdr;
1347   UINTN sectionSize;
1348 
1349   *Key = (UINTN)ALIGN_POINTER (*Key, 4); // Sections are DWORD aligned
1350 
1351   if ((*Key + sizeof (*sectionHdr)) > TotalSectionsSize) {
1352     return EFI_NOT_FOUND;
1353   }
1354 
1355   sectionHdr = (EFI_COMMON_SECTION_HEADER*)((UINT8*)SectionsStart + *Key);
1356   sectionSize = FvBufGetSecFileLen (sectionHdr);
1357 
1358   if (sectionSize < sizeof (EFI_COMMON_SECTION_HEADER)) {
1359     return EFI_NOT_FOUND;
1360   }
1361 
1362   if ((*Key + sectionSize) > TotalSectionsSize) {
1363     return EFI_NOT_FOUND;
1364   }
1365 
1366   *Section = (UINT8*)sectionHdr;
1367   *Key = *Key + sectionSize;
1368   return EFI_SUCCESS;
1369 
1370 }
1371 
1372 
1373 EFI_STATUS
FvBufCountSections(IN VOID * FfsFile,IN UINTN * Count)1374 FvBufCountSections (
1375   IN VOID* FfsFile,
1376   IN UINTN* Count
1377   )
1378 /*++
1379 
1380 Routine Description:
1381 
1382   Searches the FFS file and counts the number of sections found.
1383   The sections are NOT recursed.
1384 
1385 Arguments:
1386 
1387   FfsFile - Address of the FFS file in memory
1388   Count - The location to store the section count in
1389 
1390 Returns:
1391 
1392   EFI_SUCCESS
1393   EFI_NOT_FOUND
1394   EFI_VOLUME_CORRUPTED
1395 
1396 --*/
1397 {
1398   EFI_STATUS                 Status;
1399   UINTN                      Key;
1400   VOID*                      SectionStart;
1401   UINTN                      TotalSectionsSize;
1402   EFI_COMMON_SECTION_HEADER* NextSection;
1403 
1404   SectionStart = (VOID*)((UINTN)FfsFile + FvBufGetFfsHeaderSize(FfsFile));
1405   TotalSectionsSize =
1406     FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)FfsFile) -
1407     FvBufGetFfsHeaderSize(FfsFile);
1408   Key = 0;
1409   *Count = 0;
1410   while (TRUE) {
1411     Status = FvBufFindNextSection (
1412                SectionStart,
1413                TotalSectionsSize,
1414                &Key,
1415                (VOID **)&NextSection
1416                );
1417     if (Status == EFI_NOT_FOUND) {
1418       return EFI_SUCCESS;
1419     } else if (EFI_ERROR (Status)) {
1420       return Status;
1421     }
1422 
1423     //
1424     // Increment the section counter
1425     //
1426     *Count += 1;
1427 
1428   }
1429 
1430   return EFI_NOT_FOUND;
1431 }
1432 
1433 
1434 EFI_STATUS
FvBufFindSectionByType(IN VOID * FfsFile,IN UINT8 Type,OUT VOID ** Section)1435 FvBufFindSectionByType (
1436   IN VOID *FfsFile,
1437   IN UINT8 Type,
1438   OUT VOID **Section
1439   )
1440 /*++
1441 
1442 Routine Description:
1443 
1444   Searches the FFS file for a section by its type
1445 
1446 Arguments:
1447 
1448   FfsFile - Address of the FFS file in memory
1449   Type - FFS FILE section type to search for
1450   Section - Output section pointer
1451     (Section == NULL) -> Only determine if the section exists, based on return
1452                          value from the function call.
1453     otherwise -> *Section will be update to the location of the file
1454 
1455 Returns:
1456 
1457   EFI_SUCCESS
1458   EFI_NOT_FOUND
1459   EFI_VOLUME_CORRUPTED
1460 
1461 --*/
1462 {
1463   EFI_STATUS Status;
1464   UINTN Key;
1465   VOID*                      SectionStart;
1466   UINTN                      TotalSectionsSize;
1467   EFI_COMMON_SECTION_HEADER* NextSection;
1468 
1469   SectionStart = (VOID*)((UINTN)FfsFile + FvBufGetFfsHeaderSize(FfsFile));
1470   TotalSectionsSize =
1471     FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)FfsFile) -
1472     FvBufGetFfsHeaderSize(FfsFile);
1473   Key = 0;
1474   while (TRUE) {
1475     Status = FvBufFindNextSection (
1476                SectionStart,
1477                TotalSectionsSize,
1478                &Key,
1479                (VOID **)&NextSection
1480                );
1481     if (EFI_ERROR (Status)) {
1482       return Status;
1483     }
1484 
1485     if (Type == NextSection->Type) {
1486       if (Section != NULL) {
1487         *Section = NextSection;
1488       }
1489       return EFI_SUCCESS;
1490     }
1491   }
1492 
1493   return EFI_NOT_FOUND;
1494 }
1495 
1496 
1497 EFI_STATUS
FvBufShrinkWrap(IN VOID * Fv)1498 FvBufShrinkWrap (
1499   IN VOID *Fv
1500   )
1501 /*++
1502 
1503 Routine Description:
1504 
1505   Shrinks a firmware volume (in place) to provide a minimal FV.
1506 
1507   BUGBUG: Does not handle the case where the firmware volume has a
1508           VTF (Volume Top File).  The VTF will not be moved to the
1509           end of the extended FV.
1510 
1511 Arguments:
1512 
1513   Fv - Firmware volume.
1514 
1515 Returns:
1516 
1517   EFI_SUCCESS
1518 
1519 --*/
1520 {
1521   EFI_STATUS Status;
1522   UINTN OldSize;
1523   UINT32 BlockCount;
1524   UINT32 NewBlockSize = 128;
1525   UINTN Key;
1526   EFI_FFS_FILE_HEADER* FileIt;
1527   VOID* EndOfLastFile;
1528 
1529   EFI_FIRMWARE_VOLUME_HEADER* FvHdr;
1530 
1531   Status = FvBufGetSize (Fv, &OldSize);
1532   if (EFI_ERROR (Status)) {
1533     return Status;
1534   }
1535 
1536   Status = FvBufUnifyBlockSizes (Fv, NewBlockSize);
1537   if (EFI_ERROR (Status)) {
1538     return Status;
1539   }
1540 
1541   //
1542   // Locate the block map in the fv header
1543   //
1544   FvHdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
1545 
1546   //
1547   // Find the end of the last file
1548   //
1549   Key = 0;
1550   EndOfLastFile = (UINT8*)FvHdr + FvHdr->FvLength;
1551   while (!EFI_ERROR (FvBufFindNextFile (Fv, &Key, (VOID **)&FileIt))) {
1552     EndOfLastFile =
1553       (VOID*)((UINT8*)FileIt + FvBufGetFfsFileSize (FileIt));
1554   }
1555 
1556   //
1557   // Set the BlockCount to have the minimal number of blocks for the Fv.
1558   //
1559   BlockCount = (UINT32)((UINTN)EndOfLastFile - (UINTN)Fv);
1560   BlockCount = BlockCount + NewBlockSize - 1;
1561   BlockCount = BlockCount / NewBlockSize;
1562 
1563   //
1564   // Adjust the block count to shrink the Fv in place.
1565   //
1566   FvHdr->BlockMap[0].NumBlocks = BlockCount;
1567   FvHdr->FvLength = BlockCount * NewBlockSize;
1568 
1569   //
1570   // Update the FV header checksum
1571   //
1572   FvBufChecksumHeader (Fv);
1573 
1574   return EFI_SUCCESS;
1575 
1576 }
1577 
1578 
1579 EFI_STATUS
FvBufUnifyBlockSizes(IN OUT VOID * Fv,IN UINTN BlockSize)1580 FvBufUnifyBlockSizes (
1581   IN OUT VOID *Fv,
1582   IN UINTN BlockSize
1583   )
1584 /*++
1585 
1586 Routine Description:
1587 
1588   Searches the FFS file for a section by its type
1589 
1590 Arguments:
1591 
1592   Fv - Address of the Fv in memory
1593   BlockSize - The size of the blocks to convert the Fv to.  If the total size
1594               of the Fv is not evenly divisible by this size, then
1595               EFI_INVALID_PARAMETER will be returned.
1596 
1597 Returns:
1598 
1599   EFI_SUCCESS
1600   EFI_NOT_FOUND
1601   EFI_VOLUME_CORRUPTED
1602 
1603 --*/
1604 {
1605   EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv;
1606   EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap;
1607   UINT32 Size;
1608 
1609   Size = 0;
1610 
1611   //
1612   // Scan through the block map list, performing error checking, and adding
1613   // up the total Fv size.
1614   //
1615   while( blk->Length != 0 ||
1616          blk->NumBlocks != 0
1617        ) {
1618     Size = Size + (blk->Length * blk->NumBlocks);
1619     blk++;
1620     if ((UINT8*)blk > ((UINT8*)hdr + hdr->HeaderLength)) {
1621       return EFI_VOLUME_CORRUPTED;
1622     }
1623   }
1624 
1625   //
1626   // Make sure that the Fv size is a multiple of the new block size.
1627   //
1628   if ((Size % BlockSize) != 0) {
1629     return EFI_INVALID_PARAMETER;
1630   }
1631 
1632   //
1633   // Zero out the entire block map.
1634   //
1635   CommonLibBinderSetMem (
1636     &hdr->BlockMap,
1637     (UINTN)blk - (UINTN)&hdr->BlockMap,
1638     0
1639     );
1640 
1641   //
1642   // Write out the single block map entry.
1643   //
1644   hdr->BlockMap[0].Length = (UINT32)BlockSize;
1645   hdr->BlockMap[0].NumBlocks = Size / (UINT32)BlockSize;
1646 
1647   return EFI_SUCCESS;
1648 }
1649 
1650 STATIC
1651 UINT16
FvBufCalculateSum16(IN UINT16 * Buffer,IN UINTN Size)1652 FvBufCalculateSum16 (
1653   IN UINT16       *Buffer,
1654   IN UINTN        Size
1655   )
1656 /*++
1657 
1658 Routine Description:
1659 
1660   This function calculates the UINT16 sum for the requested region.
1661 
1662 Arguments:
1663 
1664   Buffer      Pointer to buffer containing byte data of component.
1665   Size        Size of the buffer
1666 
1667 Returns:
1668 
1669   The 16 bit checksum
1670 
1671 --*/
1672 {
1673   UINTN   Index;
1674   UINT16  Sum;
1675 
1676   Sum = 0;
1677 
1678   //
1679   // Perform the word sum for buffer
1680   //
1681   for (Index = 0; Index < Size; Index++) {
1682     Sum = (UINT16) (Sum + Buffer[Index]);
1683   }
1684 
1685   return (UINT16) Sum;
1686 }
1687 
1688 
1689 STATIC
1690 UINT16
FvBufCalculateChecksum16(IN UINT16 * Buffer,IN UINTN Size)1691 FvBufCalculateChecksum16 (
1692   IN UINT16       *Buffer,
1693   IN UINTN        Size
1694   )
1695 /*++
1696 
1697 Routine Description::
1698 
1699   This function calculates the value needed for a valid UINT16 checksum
1700 
1701 Arguments:
1702 
1703   Buffer      Pointer to buffer containing byte data of component.
1704   Size        Size of the buffer
1705 
1706 Returns:
1707 
1708   The 16 bit checksum value needed.
1709 
1710 --*/
1711 {
1712   return (UINT16)(0x10000 - FvBufCalculateSum16 (Buffer, Size));
1713 }
1714 
1715 
1716 STATIC
1717 UINT8
FvBufCalculateSum8(IN UINT8 * Buffer,IN UINTN Size)1718 FvBufCalculateSum8 (
1719   IN UINT8  *Buffer,
1720   IN UINTN  Size
1721   )
1722 /*++
1723 
1724 Description:
1725 
1726   This function calculates the UINT8 sum for the requested region.
1727 
1728 Input:
1729 
1730   Buffer      Pointer to buffer containing byte data of component.
1731   Size        Size of the buffer
1732 
1733 Return:
1734 
1735   The 8 bit checksum value needed.
1736 
1737 --*/
1738 {
1739   UINTN   Index;
1740   UINT8   Sum;
1741 
1742   Sum = 0;
1743 
1744   //
1745   // Perform the byte sum for buffer
1746   //
1747   for (Index = 0; Index < Size; Index++) {
1748     Sum = (UINT8) (Sum + Buffer[Index]);
1749   }
1750 
1751   return Sum;
1752 }
1753 
1754 
1755 STATIC
1756 UINT8
FvBufCalculateChecksum8(IN UINT8 * Buffer,IN UINTN Size)1757 FvBufCalculateChecksum8 (
1758   IN UINT8        *Buffer,
1759   IN UINTN        Size
1760   )
1761 /*++
1762 
1763 Description:
1764 
1765   This function calculates the value needed for a valid UINT8 checksum
1766 
1767 Input:
1768 
1769   Buffer      Pointer to buffer containing byte data of component.
1770   Size        Size of the buffer
1771 
1772 Return:
1773 
1774   The 8 bit checksum value needed.
1775 
1776 --*/
1777 {
1778   return (UINT8)(0x100 - FvBufCalculateSum8 (Buffer, Size));
1779 }
1780 
1781 
1782