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