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