Home | History | Annotate | Download | only in SecPeiServicesLib
      1 /*++ @file
      2   A simple FV stack so the SEC can extract the SEC Core from an
      3   FV.
      4 
      5 Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include <PiPei.h>
     17 
     18 
     19 #define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
     20   (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1))
     21 
     22 EFI_FFS_FILE_STATE
     23 GetFileState (
     24   IN UINT8                ErasePolarity,
     25   IN EFI_FFS_FILE_HEADER  *FfsHeader
     26   )
     27 /*++
     28 
     29 Routine Description:
     30   Returns the highest bit set of the State field
     31 
     32 Arguments:
     33   ErasePolarity   - Erase Polarity  as defined by EFI_FVB2_ERASE_POLARITY
     34                     in the Attributes field.
     35   FfsHeader       - Pointer to FFS File Header.
     36 
     37 Returns:
     38   Returns the highest bit in the State field
     39 
     40 **/
     41 {
     42   EFI_FFS_FILE_STATE  FileState;
     43   EFI_FFS_FILE_STATE  HighestBit;
     44 
     45   FileState = FfsHeader->State;
     46 
     47   if (ErasePolarity != 0) {
     48     FileState = (EFI_FFS_FILE_STATE)~FileState;
     49   }
     50 
     51   HighestBit = 0x80;
     52   while (HighestBit != 0 && (HighestBit & FileState) == 0) {
     53     HighestBit >>= 1;
     54   }
     55 
     56   return HighestBit;
     57 }
     58 
     59 UINT8
     60 CalculateHeaderChecksum (
     61   IN EFI_FFS_FILE_HEADER  *FileHeader
     62   )
     63 /*++
     64 
     65 Routine Description:
     66   Calculates the checksum of the header of a file.
     67 
     68 Arguments:
     69   FileHeader       - Pointer to FFS File Header.
     70 
     71 Returns:
     72   Checksum of the header.
     73 
     74 **/
     75 {
     76   UINT8 *ptr;
     77   UINTN Index;
     78   UINT8 Sum;
     79 
     80   Sum = 0;
     81   ptr = (UINT8 *) FileHeader;
     82 
     83   for (Index = 0; Index < sizeof (EFI_FFS_FILE_HEADER) - 3; Index += 4) {
     84     Sum = (UINT8) (Sum + ptr[Index]);
     85     Sum = (UINT8) (Sum + ptr[Index + 1]);
     86     Sum = (UINT8) (Sum + ptr[Index + 2]);
     87     Sum = (UINT8) (Sum + ptr[Index + 3]);
     88   }
     89 
     90   for (; Index < sizeof (EFI_FFS_FILE_HEADER); Index++) {
     91     Sum = (UINT8) (Sum + ptr[Index]);
     92   }
     93   //
     94   // State field (since this indicates the different state of file).
     95   //
     96   Sum = (UINT8) (Sum - FileHeader->State);
     97   //
     98   // Checksum field of the file is not part of the header checksum.
     99   //
    100   Sum = (UINT8) (Sum - FileHeader->IntegrityCheck.Checksum.File);
    101 
    102   return Sum;
    103 }
    104 
    105 EFI_STATUS
    106 SecFfsFindNextFile (
    107   IN EFI_FV_FILETYPE             SearchType,
    108   IN EFI_PEI_FV_HANDLE           FvHandle,
    109   IN OUT EFI_PEI_FILE_HANDLE     *FileHandle
    110   )
    111 /*++
    112 
    113 Routine Description:
    114     Given the input file pointer, search for the next matching file in the
    115     FFS volume as defined by SearchType. The search starts from FileHeader inside
    116     the Firmware Volume defined by FwVolHeader.
    117 
    118 Arguments:
    119     SearchType - Filter to find only files of this type.
    120                  Type EFI_FV_FILETYPE_ALL causes no filtering to be done.
    121     FwVolHeader - Pointer to the FV header of the volume to search.
    122                   This parameter must point to a valid FFS volume.
    123     FileHeader  - Pointer to the current file from which to begin searching.
    124                   This pointer will be updated upon return to reflect the file
    125                   found.
    126 
    127 Returns:
    128     EFI_NOT_FOUND - No files matching the search criteria were found
    129     EFI_SUCCESS
    130 
    131 **/
    132 {
    133   EFI_FFS_FILE_HEADER *FfsFileHeader;
    134   UINT32              FileLength;
    135   UINT32              FileOccupiedSize;
    136   UINT32              FileOffset;
    137   UINT64              FvLength;
    138   UINT8               ErasePolarity;
    139   UINT8               FileState;
    140   EFI_FIRMWARE_VOLUME_HEADER  *FwVolHeader;
    141   EFI_FFS_FILE_HEADER         **FileHeader;
    142 
    143   //
    144   // Convert the handle of FV to FV header for memory-mapped firmware volume
    145   //
    146   FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvHandle;
    147   FileHeader  = (EFI_FFS_FILE_HEADER **)FileHandle;
    148 
    149   FvLength = FwVolHeader->FvLength;
    150   if (FwVolHeader->Attributes & EFI_FVB2_ERASE_POLARITY) {
    151     ErasePolarity = 1;
    152   } else {
    153     ErasePolarity = 0;
    154   }
    155   //
    156   // If FileHeader is not specified (NULL) start with the first file in the
    157   // firmware volume.  Otherwise, start from the FileHeader.
    158   //
    159   if (*FileHeader == NULL) {
    160     FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolHeader + FwVolHeader->HeaderLength);
    161   } else {
    162     //
    163     // Length is 24 bits wide so mask upper 8 bits
    164     // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned.
    165     //
    166     FileLength        = *(UINT32 *) (*FileHeader)->Size & 0x00FFFFFF;
    167     FileOccupiedSize  = GET_OCCUPIED_SIZE (FileLength, 8);
    168     FfsFileHeader     = (EFI_FFS_FILE_HEADER *) ((UINT8 *) *FileHeader + FileOccupiedSize);
    169   }
    170 
    171   FileOffset = (UINT32) ((UINT8 *) FfsFileHeader - (UINT8 *) FwVolHeader);
    172 
    173   while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) {
    174     //
    175     // Get FileState which is the highest bit of the State
    176     //
    177     FileState = GetFileState (ErasePolarity, FfsFileHeader);
    178 
    179     switch (FileState) {
    180 
    181     case EFI_FILE_HEADER_INVALID:
    182       FileOffset += sizeof (EFI_FFS_FILE_HEADER);
    183       FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));
    184       break;
    185 
    186     case EFI_FILE_DATA_VALID:
    187     case EFI_FILE_MARKED_FOR_UPDATE:
    188       if (CalculateHeaderChecksum (FfsFileHeader) == 0) {
    189         FileLength        = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF;
    190         FileOccupiedSize  = GET_OCCUPIED_SIZE (FileLength, 8);
    191 
    192         if ((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) {
    193 
    194           *FileHeader = FfsFileHeader;
    195 
    196           return EFI_SUCCESS;
    197         }
    198 
    199         FileOffset += FileOccupiedSize;
    200         FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + FileOccupiedSize);
    201       } else {
    202         return EFI_NOT_FOUND;
    203       }
    204       break;
    205 
    206     case EFI_FILE_DELETED:
    207       FileLength        = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF;
    208       FileOccupiedSize  = GET_OCCUPIED_SIZE (FileLength, 8);
    209       FileOffset += FileOccupiedSize;
    210       FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + FileOccupiedSize);
    211       break;
    212 
    213     default:
    214       return EFI_NOT_FOUND;
    215 
    216     }
    217   }
    218 
    219   return EFI_NOT_FOUND;
    220 }
    221 
    222 EFI_STATUS
    223 SecFfsFindSectionData (
    224   IN EFI_SECTION_TYPE      SectionType,
    225   IN EFI_FFS_FILE_HEADER   *FfsFileHeader,
    226   IN OUT VOID              **SectionData
    227   )
    228 /*++
    229 
    230 Routine Description:
    231     Given the input file pointer, search for the next matching section in the
    232     FFS volume.
    233 
    234 Arguments:
    235     SearchType    - Filter to find only sections of this type.
    236     FfsFileHeader - Pointer to the current file to search.
    237     SectionData   - Pointer to the Section matching SectionType in FfsFileHeader.
    238                      NULL if section not found
    239 
    240 Returns:
    241     EFI_NOT_FOUND - No files matching the search criteria were found
    242     EFI_SUCCESS
    243 
    244 **/
    245 {
    246   UINT32                    FileSize;
    247   EFI_COMMON_SECTION_HEADER *Section;
    248   UINT32                    SectionLength;
    249   UINT32                    ParsedLength;
    250 
    251   //
    252   // Size is 24 bits wide so mask upper 8 bits.
    253   //    Does not include FfsFileHeader header size
    254   // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned.
    255   //
    256   Section   = (EFI_COMMON_SECTION_HEADER *) (FfsFileHeader + 1);
    257   FileSize  = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF;
    258   FileSize -= sizeof (EFI_FFS_FILE_HEADER);
    259 
    260   *SectionData  = NULL;
    261   ParsedLength  = 0;
    262   while (ParsedLength < FileSize) {
    263     if (Section->Type == SectionType) {
    264       *SectionData = (VOID *) (Section + 1);
    265       return EFI_SUCCESS;
    266     }
    267     //
    268     // Size is 24 bits wide so mask upper 8 bits.
    269     // SectionLength is adjusted it is 4 byte aligned.
    270     // Go to the next section
    271     //
    272     SectionLength = *(UINT32 *) Section->Size & 0x00FFFFFF;
    273     SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4);
    274 
    275     ParsedLength += SectionLength;
    276     Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + SectionLength);
    277   }
    278 
    279   return EFI_NOT_FOUND;
    280 }
    281 
    282