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