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