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