1 /*++ 2 3 Copyright (c) 2004 - 2010, 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 FvLib.c 15 16 Abstract: 17 18 These functions assist in parsing and manipulating a Firmware Volume. 19 20 --*/ 21 22 // 23 // Include files 24 // 25 #include "FvLib.h" 26 #include "CommonLib.h" 27 #include "EfiUtilityMsgs.h" 28 29 // 30 // Module global variables 31 // 32 EFI_FIRMWARE_VOLUME_HEADER *mFvHeader = NULL; 33 UINT32 mFvLength = 0; 34 35 // 36 // External function implementations 37 // 38 EFI_STATUS 39 InitializeFvLib ( 40 IN VOID *Fv, 41 IN UINT32 FvLength 42 ) 43 /*++ 44 45 Routine Description: 46 47 This initializes the FV lib with a pointer to the FV and length. It does not 48 verify the FV in any way. 49 50 Arguments: 51 52 Fv Buffer containing the FV. 53 FvLength Length of the FV 54 55 Returns: 56 57 EFI_SUCCESS Function Completed successfully. 58 EFI_INVALID_PARAMETER A required parameter was NULL. 59 60 --*/ 61 { 62 // 63 // Verify input arguments 64 // 65 if (Fv == NULL) { 66 return EFI_INVALID_PARAMETER; 67 } 68 69 mFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Fv; 70 mFvLength = FvLength; 71 72 return EFI_SUCCESS; 73 } 74 75 EFI_STATUS 76 GetFvHeader ( 77 OUT EFI_FIRMWARE_VOLUME_HEADER **FvHeader, 78 OUT UINT32 *FvLength 79 ) 80 /*++ 81 82 Routine Description: 83 84 This function returns a pointer to the current FV and the size. 85 86 Arguments: 87 88 FvHeader Pointer to the FV buffer. 89 FvLength Length of the FV 90 91 Returns: 92 93 EFI_SUCCESS Function Completed successfully. 94 EFI_INVALID_PARAMETER A required parameter was NULL. 95 EFI_ABORTED The library needs to be initialized. 96 97 --*/ 98 { 99 // 100 // Verify library has been initialized. 101 // 102 if (mFvHeader == NULL || mFvLength == 0) { 103 return EFI_ABORTED; 104 } 105 // 106 // Verify input arguments 107 // 108 if (FvHeader == NULL) { 109 return EFI_INVALID_PARAMETER; 110 } 111 112 *FvHeader = mFvHeader; 113 return EFI_SUCCESS; 114 } 115 116 EFI_STATUS 117 GetNextFile ( 118 IN EFI_FFS_FILE_HEADER *CurrentFile, 119 OUT EFI_FFS_FILE_HEADER **NextFile 120 ) 121 /*++ 122 123 Routine Description: 124 125 This function returns the next file. If the current file is NULL, it returns 126 the first file in the FV. If the function returns EFI_SUCCESS and the file 127 pointer is NULL, then there are no more files in the FV. 128 129 Arguments: 130 131 CurrentFile Pointer to the current file, must be within the current FV. 132 NextFile Pointer to the next file in the FV. 133 134 Returns: 135 136 EFI_SUCCESS Function completed successfully. 137 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range. 138 EFI_ABORTED The library needs to be initialized. 139 140 --*/ 141 { 142 EFI_STATUS Status; 143 144 // 145 // Verify library has been initialized. 146 // 147 if (mFvHeader == NULL || mFvLength == 0) { 148 return EFI_ABORTED; 149 } 150 // 151 // Verify input arguments 152 // 153 if (NextFile == NULL) { 154 return EFI_INVALID_PARAMETER; 155 } 156 // 157 // Verify FV header 158 // 159 Status = VerifyFv (mFvHeader); 160 if (EFI_ERROR (Status)) { 161 return EFI_ABORTED; 162 } 163 // 164 // Get first file 165 // 166 if (CurrentFile == NULL) { 167 CurrentFile = (EFI_FFS_FILE_HEADER *) ((UINTN) mFvHeader + mFvHeader->HeaderLength); 168 169 // 170 // Verify file is valid 171 // 172 Status = VerifyFfsFile (CurrentFile); 173 if (EFI_ERROR (Status)) { 174 // 175 // no files in this FV 176 // 177 *NextFile = NULL; 178 return EFI_SUCCESS; 179 } else { 180 // 181 // Verify file is in this FV. 182 // 183 if ((UINTN) CurrentFile + GetLength (CurrentFile->Size) > (UINTN) mFvHeader + mFvLength) { 184 *NextFile = NULL; 185 return EFI_SUCCESS; 186 } 187 188 *NextFile = CurrentFile; 189 return EFI_SUCCESS; 190 } 191 } 192 // 193 // Verify current file is in range 194 // 195 if (((UINTN) CurrentFile < (UINTN) mFvHeader + mFvHeader->HeaderLength) || 196 ((UINTN) CurrentFile + GetLength (CurrentFile->Size) > (UINTN) mFvHeader + mFvLength) 197 ) { 198 return EFI_INVALID_PARAMETER; 199 } 200 // 201 // Get next file, compensate for 8 byte alignment if necessary. 202 // 203 *NextFile = (EFI_FFS_FILE_HEADER *) (((UINTN) CurrentFile + GetLength (CurrentFile->Size) + 0x07) & (-1 << 3)); 204 205 // 206 // Verify file is in this FV. 207 // 208 if (((UINTN) *NextFile + sizeof (EFI_FFS_FILE_HEADER) >= (UINTN) mFvHeader + mFvLength) || 209 ((UINTN) *NextFile + GetLength ((*NextFile)->Size) > (UINTN) mFvHeader + mFvLength) 210 ) { 211 *NextFile = NULL; 212 return EFI_SUCCESS; 213 } 214 // 215 // Verify file is valid 216 // 217 Status = VerifyFfsFile (*NextFile); 218 if (EFI_ERROR (Status)) { 219 // 220 // no more files in this FV 221 // 222 *NextFile = NULL; 223 return EFI_SUCCESS; 224 } 225 226 return EFI_SUCCESS; 227 } 228 229 EFI_STATUS 230 GetFileByName ( 231 IN EFI_GUID *FileName, 232 OUT EFI_FFS_FILE_HEADER **File 233 ) 234 /*++ 235 236 Routine Description: 237 238 Find a file by name. The function will return NULL if the file is not found. 239 240 Arguments: 241 242 FileName The GUID file name of the file to search for. 243 File Return pointer. In the case of an error, contents are undefined. 244 245 Returns: 246 247 EFI_SUCCESS The function completed successfully. 248 EFI_ABORTED An error was encountered. 249 EFI_INVALID_PARAMETER One of the parameters was NULL. 250 251 --*/ 252 { 253 EFI_FFS_FILE_HEADER *CurrentFile; 254 EFI_STATUS Status; 255 256 // 257 // Verify library has been initialized. 258 // 259 if (mFvHeader == NULL || mFvLength == 0) { 260 return EFI_ABORTED; 261 } 262 // 263 // Verify input parameters 264 // 265 if (FileName == NULL || File == NULL) { 266 return EFI_INVALID_PARAMETER; 267 } 268 // 269 // Verify FV header 270 // 271 Status = VerifyFv (mFvHeader); 272 if (EFI_ERROR (Status)) { 273 return EFI_ABORTED; 274 } 275 // 276 // Get the first file 277 // 278 Status = GetNextFile (NULL, &CurrentFile); 279 if (EFI_ERROR (Status)) { 280 Error (NULL, 0, 0, "error parsing the FV", NULL); 281 return EFI_ABORTED; 282 } 283 // 284 // Loop as long as we have a valid file 285 // 286 while (CurrentFile) { 287 if (!CompareGuid (&CurrentFile->Name, FileName)) { 288 *File = CurrentFile; 289 return EFI_SUCCESS; 290 } 291 292 Status = GetNextFile (CurrentFile, &CurrentFile); 293 if (EFI_ERROR (Status)) { 294 Error (NULL, 0, 0, "error parsing the FV", NULL); 295 return EFI_ABORTED; 296 } 297 } 298 // 299 // File not found in this FV. 300 // 301 *File = NULL; 302 return EFI_SUCCESS; 303 } 304 305 EFI_STATUS 306 GetFileByType ( 307 IN EFI_FV_FILETYPE FileType, 308 IN UINTN Instance, 309 OUT EFI_FFS_FILE_HEADER **File 310 ) 311 /*++ 312 313 Routine Description: 314 315 Find a file by type and instance. An instance of 1 is the first instance. 316 The function will return NULL if a matching file cannot be found. 317 File type EFI_FV_FILETYPE_ALL means any file type is valid. 318 319 Arguments: 320 321 FileType Type of file to search for. 322 Instance Instace of the file type to return. 323 File Return pointer. In the case of an error, contents are undefined. 324 325 Returns: 326 327 EFI_SUCCESS The function completed successfully. 328 EFI_ABORTED An error was encountered. 329 EFI_INVALID_PARAMETER One of the parameters was NULL. 330 331 --*/ 332 { 333 EFI_FFS_FILE_HEADER *CurrentFile; 334 EFI_STATUS Status; 335 UINTN FileCount; 336 337 // 338 // Verify library has been initialized. 339 // 340 if (mFvHeader == NULL || mFvLength == 0) { 341 return EFI_ABORTED; 342 } 343 // 344 // Verify input parameters 345 // 346 if (File == NULL) { 347 return EFI_INVALID_PARAMETER; 348 } 349 // 350 // Verify FV header 351 // 352 Status = VerifyFv (mFvHeader); 353 if (EFI_ERROR (Status)) { 354 return EFI_ABORTED; 355 } 356 // 357 // Initialize the number of matching files found. 358 // 359 FileCount = 0; 360 361 // 362 // Get the first file 363 // 364 Status = GetNextFile (NULL, &CurrentFile); 365 if (EFI_ERROR (Status)) { 366 Error (NULL, 0, 0, "error parsing FV", NULL); 367 return EFI_ABORTED; 368 } 369 // 370 // Loop as long as we have a valid file 371 // 372 while (CurrentFile) { 373 if (FileType == EFI_FV_FILETYPE_ALL || CurrentFile->Type == FileType) { 374 FileCount++; 375 } 376 377 if (FileCount == Instance) { 378 *File = CurrentFile; 379 return EFI_SUCCESS; 380 } 381 382 Status = GetNextFile (CurrentFile, &CurrentFile); 383 if (EFI_ERROR (Status)) { 384 Error (NULL, 0, 0, "error parsing the FV", NULL); 385 return EFI_ABORTED; 386 } 387 } 388 389 *File = NULL; 390 return EFI_SUCCESS; 391 } 392 393 EFI_STATUS 394 SearchSectionByType ( 395 IN EFI_FILE_SECTION_POINTER FirstSection, 396 IN UINT8 *SearchEnd, 397 IN EFI_SECTION_TYPE SectionType, 398 IN OUT UINTN *StartIndex, 399 IN UINTN Instance, 400 OUT EFI_FILE_SECTION_POINTER *Section 401 ) 402 /*++ 403 404 Routine Description: 405 406 Helper function to search a sequence of sections from the section pointed 407 by FirstSection to SearchEnd for the Instance-th section of type SectionType. 408 The current counter is saved in StartIndex and when the section is found, it's 409 saved in Section. GUID-defined sections, if special processing is not required, 410 are searched recursively in a depth-first manner. 411 412 Arguments: 413 414 FirstSection The first section to start searching from. 415 SearchEnd The end address to stop search. 416 SectionType The type of section to search. 417 StartIndex The current counter is saved. 418 Instance The requested n-th section number. 419 Section The found section returned. 420 421 Returns: 422 423 EFI_SUCCESS The function completed successfully. 424 EFI_NOT_FOUND The section is not found. 425 --*/ 426 { 427 EFI_FILE_SECTION_POINTER CurrentSection; 428 EFI_FILE_SECTION_POINTER InnerSection; 429 EFI_STATUS Status; 430 UINTN SectionSize; 431 432 CurrentSection = FirstSection; 433 434 while ((UINTN) CurrentSection.CommonHeader < (UINTN) SearchEnd) { 435 if (CurrentSection.CommonHeader->Type == SectionType) { 436 (*StartIndex)++; 437 } 438 439 if (*StartIndex == Instance) { 440 *Section = CurrentSection; 441 return EFI_SUCCESS; 442 } 443 // 444 // If the requesting section is not GUID-defined and 445 // we find a GUID-defined section that doesn't need 446 // special processing, go ahead to search the requesting 447 // section inside the GUID-defined section. 448 // 449 if (SectionType != EFI_SECTION_GUID_DEFINED && 450 CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED && 451 !(CurrentSection.GuidDefinedSection->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED)) { 452 InnerSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) 453 ((UINTN) CurrentSection.CommonHeader + CurrentSection.GuidDefinedSection->DataOffset); 454 SectionSize = CurrentSection.CommonHeader->Size[0] + 455 (CurrentSection.CommonHeader->Size[1] << 8) + 456 (CurrentSection.CommonHeader->Size[2] << 16); 457 Status = SearchSectionByType ( 458 InnerSection, 459 (UINT8 *) ((UINTN) CurrentSection.CommonHeader + SectionSize), 460 SectionType, 461 StartIndex, 462 Instance, 463 Section 464 ); 465 if (!EFI_ERROR (Status)) { 466 return EFI_SUCCESS; 467 } 468 } 469 // 470 // Find next section (including compensating for alignment issues. 471 // 472 CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetLength (CurrentSection.CommonHeader->Size) + 0x03) & (-1 << 2)); 473 } 474 475 return EFI_NOT_FOUND; 476 } 477 478 EFI_STATUS 479 GetSectionByType ( 480 IN EFI_FFS_FILE_HEADER *File, 481 IN EFI_SECTION_TYPE SectionType, 482 IN UINTN Instance, 483 OUT EFI_FILE_SECTION_POINTER *Section 484 ) 485 /*++ 486 487 Routine Description: 488 489 Find a section in a file by type and instance. An instance of 1 is the first 490 instance. The function will return NULL if a matching section cannot be found. 491 GUID-defined sections, if special processing is not needed, are handled in a 492 depth-first manner. 493 494 Arguments: 495 496 File The file to search. 497 SectionType Type of file to search for. 498 Instance Instace of the section to return. 499 Section Return pointer. In the case of an error, contents are undefined. 500 501 Returns: 502 503 EFI_SUCCESS The function completed successfully. 504 EFI_ABORTED An error was encountered. 505 EFI_INVALID_PARAMETER One of the parameters was NULL. 506 EFI_NOT_FOUND No found. 507 --*/ 508 { 509 EFI_FILE_SECTION_POINTER CurrentSection; 510 EFI_STATUS Status; 511 UINTN SectionCount; 512 513 // 514 // Verify input parameters 515 // 516 if (File == NULL || Instance == 0) { 517 return EFI_INVALID_PARAMETER; 518 } 519 // 520 // Verify FFS header 521 // 522 Status = VerifyFfsFile (File); 523 if (EFI_ERROR (Status)) { 524 Error (NULL, 0, 0, "invalid FFS file", NULL); 525 return EFI_ABORTED; 526 } 527 // 528 // Initialize the number of matching sections found. 529 // 530 SectionCount = 0; 531 532 // 533 // Get the first section 534 // 535 CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + sizeof (EFI_FFS_FILE_HEADER)); 536 537 Status = SearchSectionByType ( 538 CurrentSection, 539 (UINT8 *) ((UINTN) File + GetLength (File->Size)), 540 SectionType, 541 &SectionCount, 542 Instance, 543 Section 544 ); 545 546 if (!EFI_ERROR (Status)) { 547 return EFI_SUCCESS; 548 } else { 549 // 550 // Section not found 551 // 552 (*Section).Code16Section = NULL; 553 return EFI_NOT_FOUND; 554 } 555 } 556 // 557 // will not parse compressed sections 558 // 559 EFI_STATUS 560 VerifyFv ( 561 IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader 562 ) 563 /*++ 564 565 Routine Description: 566 567 Verify the current pointer points to a valid FV header. 568 569 Arguments: 570 571 FvHeader Pointer to an alleged FV file. 572 573 Returns: 574 575 EFI_SUCCESS The FV header is valid. 576 EFI_VOLUME_CORRUPTED The FV header is not valid. 577 EFI_INVALID_PARAMETER A required parameter was NULL. 578 EFI_ABORTED Operation aborted. 579 580 --*/ 581 { 582 UINT16 Checksum; 583 584 // 585 // Verify input parameters 586 // 587 if (FvHeader == NULL) { 588 return EFI_INVALID_PARAMETER; 589 } 590 591 if (FvHeader->Signature != EFI_FVH_SIGNATURE) { 592 Error (NULL, 0, 0, "invalid FV header signature", NULL); 593 return EFI_VOLUME_CORRUPTED; 594 } 595 // 596 // Verify header checksum 597 // 598 Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); 599 600 if (Checksum != 0) { 601 Error (NULL, 0, 0, "invalid FV header checksum", NULL); 602 return EFI_ABORTED; 603 } 604 605 return EFI_SUCCESS; 606 } 607 608 EFI_STATUS 609 VerifyFfsFile ( 610 IN EFI_FFS_FILE_HEADER *FfsHeader 611 ) 612 /*++ 613 614 Routine Description: 615 616 Verify the current pointer points to a FFS file header. 617 618 Arguments: 619 620 FfsHeader Pointer to an alleged FFS file. 621 622 Returns: 623 624 EFI_SUCCESS The Ffs header is valid. 625 EFI_NOT_FOUND This "file" is the beginning of free space. 626 EFI_VOLUME_CORRUPTED The Ffs header is not valid. 627 EFI_ABORTED The erase polarity is not known. 628 629 --*/ 630 { 631 BOOLEAN ErasePolarity; 632 EFI_STATUS Status; 633 EFI_FFS_FILE_HEADER BlankHeader; 634 UINT8 Checksum; 635 UINT32 FileLength; 636 UINT32 OccupiedFileLength; 637 UINT8 SavedChecksum; 638 UINT8 SavedState; 639 UINT8 FileGuidString[80]; 640 UINT32 TailSize; 641 #if (PI_SPECIFICATION_VERSION < 0x00010000) 642 EFI_FFS_FILE_TAIL *Tail; 643 #endif 644 645 // 646 // Verify library has been initialized. 647 // 648 if (mFvHeader == NULL || mFvLength == 0) { 649 return EFI_ABORTED; 650 } 651 // 652 // Verify FV header 653 // 654 Status = VerifyFv (mFvHeader); 655 if (EFI_ERROR (Status)) { 656 return EFI_ABORTED; 657 } 658 // 659 // Get the erase polarity. 660 // 661 Status = GetErasePolarity (&ErasePolarity); 662 if (EFI_ERROR (Status)) { 663 return EFI_ABORTED; 664 } 665 // 666 // Check if we have free space 667 // 668 if (ErasePolarity) { 669 memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER)); 670 } else { 671 memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER)); 672 } 673 674 if (memcmp (&BlankHeader, FfsHeader, sizeof (EFI_FFS_FILE_HEADER)) == 0) { 675 return EFI_NOT_FOUND; 676 } 677 // 678 // Convert the GUID to a string so we can at least report which file 679 // if we find an error. 680 // 681 PrintGuidToBuffer (&FfsHeader->Name, FileGuidString, sizeof (FileGuidString), TRUE); 682 if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { 683 TailSize = sizeof (EFI_FFS_FILE_TAIL); 684 } else { 685 TailSize = 0; 686 } 687 // 688 // Verify file header checksum 689 // 690 SavedState = FfsHeader->State; 691 FfsHeader->State = 0; 692 SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File; 693 FfsHeader->IntegrityCheck.Checksum.File = 0; 694 Checksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER)); 695 FfsHeader->State = SavedState; 696 FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum; 697 if (Checksum != 0) { 698 Error (NULL, 0, 0, FileGuidString, "invalid FFS file header checksum"); 699 return EFI_ABORTED; 700 } 701 // 702 // Verify file checksum 703 // 704 if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) { 705 // 706 // Verify file data checksum 707 // 708 FileLength = GetLength (FfsHeader->Size); 709 OccupiedFileLength = (FileLength + 0x07) & (-1 << 3); 710 #if (PI_SPECIFICATION_VERSION < 0x00010000) 711 Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FileLength - TailSize); 712 Checksum = (UINT8) (Checksum - FfsHeader->State); 713 #else 714 Checksum = CalculateSum8 ((UINT8 *) ((UINTN)FfsHeader + sizeof (EFI_FFS_FILE_HEADER)), FileLength - TailSize - sizeof (EFI_FFS_FILE_HEADER)); 715 Checksum = Checksum + (UINT8)FfsHeader->IntegrityCheck.Checksum.File; 716 #endif 717 if (Checksum != 0) { 718 Error (NULL, 0, 0, FileGuidString, "invalid FFS file checksum"); 719 return EFI_ABORTED; 720 } 721 } else { 722 // 723 // File does not have a checksum 724 // Verify contents are 0x5A(Framework) and 0xAA(PI 1.0) as spec'd 725 // 726 if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { 727 Error (NULL, 0, 0, FileGuidString, "invalid fixed file checksum"); 728 return EFI_ABORTED; 729 } 730 } 731 #if (PI_SPECIFICATION_VERSION < 0x00010000) 732 // 733 // Check if the tail is present and verify it if it is. 734 // 735 if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { 736 // 737 // Verify tail is complement of integrity check field in the header. 738 // 739 Tail = (EFI_FFS_FILE_TAIL *) ((UINTN) FfsHeader + GetLength (FfsHeader->Size) - sizeof (EFI_FFS_FILE_TAIL)); 740 if (FfsHeader->IntegrityCheck.TailReference != (EFI_FFS_FILE_TAIL)~(*Tail)) { 741 Error (NULL, 0, 0, FileGuidString, "invalid FFS file tail"); 742 return EFI_ABORTED; 743 } 744 } 745 #endif 746 return EFI_SUCCESS; 747 } 748 749 UINT32 750 GetLength ( 751 UINT8 *ThreeByteLength 752 ) 753 /*++ 754 755 Routine Description: 756 757 Converts a three byte length value into a UINT32. 758 759 Arguments: 760 761 ThreeByteLength Pointer to the first of the 3 byte length. 762 763 Returns: 764 765 UINT32 Size of the section 766 767 --*/ 768 { 769 UINT32 Length; 770 771 if (ThreeByteLength == NULL) { 772 return 0; 773 } 774 775 Length = *((UINT32 *) ThreeByteLength); 776 Length = Length & 0x00FFFFFF; 777 778 return Length; 779 } 780 781 EFI_STATUS 782 GetErasePolarity ( 783 OUT BOOLEAN *ErasePolarity 784 ) 785 /*++ 786 787 Routine Description: 788 789 This function returns with the FV erase polarity. If the erase polarity 790 for a bit is 1, the function return TRUE. 791 792 Arguments: 793 794 ErasePolarity A pointer to the erase polarity. 795 796 Returns: 797 798 EFI_SUCCESS The function completed successfully. 799 EFI_INVALID_PARAMETER One of the input parameters was invalid. 800 EFI_ABORTED Operation aborted. 801 802 --*/ 803 { 804 EFI_STATUS Status; 805 806 // 807 // Verify library has been initialized. 808 // 809 if (mFvHeader == NULL || mFvLength == 0) { 810 return EFI_ABORTED; 811 } 812 // 813 // Verify FV header 814 // 815 Status = VerifyFv (mFvHeader); 816 if (EFI_ERROR (Status)) { 817 return EFI_ABORTED; 818 } 819 // 820 // Verify input parameters. 821 // 822 if (ErasePolarity == NULL) { 823 return EFI_INVALID_PARAMETER; 824 } 825 826 if (mFvHeader->Attributes & EFI_FVB_ERASE_POLARITY) { 827 *ErasePolarity = TRUE; 828 } else { 829 *ErasePolarity = FALSE; 830 } 831 832 return EFI_SUCCESS; 833 } 834 835 UINT8 836 GetFileState ( 837 IN BOOLEAN ErasePolarity, 838 IN EFI_FFS_FILE_HEADER *FfsHeader 839 ) 840 /*++ 841 842 Routine Description: 843 844 This function returns a the highest state bit in the FFS that is set. 845 It in no way validate the FFS file. 846 847 Arguments: 848 849 ErasePolarity The erase polarity for the file state bits. 850 FfsHeader Pointer to a FFS file. 851 852 Returns: 853 854 UINT8 The hightest set state of the file. 855 856 --*/ 857 { 858 UINT8 FileState; 859 UINT8 HighestBit; 860 861 FileState = FfsHeader->State; 862 863 if (ErasePolarity) { 864 FileState = (UINT8)~FileState; 865 } 866 867 HighestBit = 0x80; 868 while (HighestBit != 0 && (HighestBit & FileState) == 0) { 869 HighestBit >>= 1; 870 } 871 872 return HighestBit; 873 } 874