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