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