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