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