Home | History | Annotate | Download | only in PeiCrc32GuidedSectionExtractLib
      1 /** @file
      2 
      3   This library registers CRC32 guided section handler
      4   to parse CRC32 encapsulation section and extract raw data.
      5 
      6 Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
      7 This program and the accompanying materials
      8 are licensed and made available under the terms and conditions of the BSD License
      9 which accompanies this distribution.  The full text of the license may be found at
     10 http://opensource.org/licenses/bsd-license.php
     11 
     12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include <PiPei.h>
     18 #include <Guid/Crc32GuidedSectionExtraction.h>
     19 #include <Library/ExtractGuidedSectionLib.h>
     20 #include <Library/DebugLib.h>
     21 #include <Library/BaseMemoryLib.h>
     22 
     23 ///
     24 /// CRC32 Guided Section header
     25 ///
     26 typedef struct {
     27   EFI_GUID_DEFINED_SECTION  GuidedSectionHeader; ///< EFI guided section header
     28   UINT32                    CRC32Checksum;       ///< 32bit CRC check sum
     29 } CRC32_SECTION_HEADER;
     30 
     31 typedef struct {
     32   EFI_GUID_DEFINED_SECTION2 GuidedSectionHeader; ///< EFI guided section header
     33   UINT32                    CRC32Checksum;       ///< 32bit CRC check sum
     34 } CRC32_SECTION2_HEADER;
     35 
     36 /**
     37   This internal function reverses bits for 32bit data.
     38 
     39   @param  Value                 The data to be reversed.
     40 
     41   @return                       Data reversed.
     42 
     43 **/
     44 UINT32
     45 PeiCrc32GuidedSectionExtractLibReverseBits (
     46   UINT32  Value
     47   )
     48 {
     49   UINTN   Index;
     50   UINT32  NewValue;
     51 
     52   NewValue = 0;
     53   for (Index = 0; Index < 32; Index++) {
     54     if ((Value & (1 << Index)) != 0) {
     55       NewValue = NewValue | (1 << (31 - Index));
     56     }
     57   }
     58 
     59   return NewValue;
     60 }
     61 
     62 /**
     63   Calculate CRC32 for target data.
     64 
     65   @param  Data                  The target data.
     66   @param  DataSize              The target data size.
     67   @param  CrcOut                The CRC32 for target data.
     68 
     69   @retval EFI_SUCCESS           The CRC32 for target data is calculated successfully.
     70   @retval EFI_INVALID_PARAMETER Some parameter is not valid, so the CRC32 is not
     71                                 calculated.
     72 
     73 **/
     74 EFI_STATUS
     75 EFIAPI
     76 PeiCrc32GuidedSectionExtractLibCalculateCrc32 (
     77   IN  VOID    *Data,
     78   IN  UINTN   DataSize,
     79   OUT UINT32  *CrcOut
     80   )
     81 {
     82   UINT32  CrcTable[256];
     83   UINTN   TableEntry;
     84   UINTN   Index;
     85   UINT32  Value;
     86   UINT32  Crc;
     87   UINT8   *Ptr;
     88 
     89   if (Data == NULL || DataSize == 0 || CrcOut == NULL) {
     90     return EFI_INVALID_PARAMETER;
     91   }
     92 
     93   //
     94   // Initialize CRC32 table.
     95   //
     96   for (TableEntry = 0; TableEntry < 256; TableEntry++) {
     97     Value = PeiCrc32GuidedSectionExtractLibReverseBits ((UINT32) TableEntry);
     98     for (Index = 0; Index < 8; Index++) {
     99       if ((Value & 0x80000000) != 0) {
    100         Value = (Value << 1) ^ 0x04c11db7;
    101       } else {
    102         Value = Value << 1;
    103       }
    104     }
    105     CrcTable[TableEntry] = PeiCrc32GuidedSectionExtractLibReverseBits (Value);
    106   }
    107 
    108   //
    109   // Compute CRC
    110   //
    111   Crc = 0xffffffff;
    112   for (Index = 0, Ptr = Data; Index < DataSize; Index++, Ptr++) {
    113     Crc = (Crc >> 8) ^ CrcTable[(UINT8) Crc ^ *Ptr];
    114   }
    115 
    116   *CrcOut = Crc ^ 0xffffffff;
    117   return EFI_SUCCESS;
    118 }
    119 
    120 /**
    121 
    122   GetInfo gets raw data size and attribute of the input guided section.
    123   It first checks whether the input guid section is supported.
    124   If not, EFI_INVALID_PARAMETER will return.
    125 
    126   @param InputSection       Buffer containing the input GUIDed section to be processed.
    127   @param OutputBufferSize   The size of OutputBuffer.
    128   @param ScratchBufferSize  The size of ScratchBuffer.
    129   @param SectionAttribute   The attribute of the input guided section.
    130 
    131   @retval EFI_SUCCESS            The size of destination buffer, the size of scratch buffer and
    132                                  the attribute of the input section are successull retrieved.
    133   @retval EFI_INVALID_PARAMETER  The GUID in InputSection does not match this instance guid.
    134 
    135 **/
    136 EFI_STATUS
    137 EFIAPI
    138 Crc32GuidedSectionGetInfo (
    139   IN  CONST VOID  *InputSection,
    140   OUT UINT32      *OutputBufferSize,
    141   OUT UINT32      *ScratchBufferSize,
    142   OUT UINT16      *SectionAttribute
    143   )
    144 {
    145   if (IS_SECTION2 (InputSection)) {
    146     //
    147     // Check whether the input guid section is recognized.
    148     //
    149     if (!CompareGuid (
    150         &gEfiCrc32GuidedSectionExtractionGuid,
    151         &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) {
    152       return EFI_INVALID_PARAMETER;
    153     }
    154     //
    155     // Retrieve the size and attribute of the input section data.
    156     //
    157     *SectionAttribute  = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes;
    158     *ScratchBufferSize = 0;
    159     *OutputBufferSize  = SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset;
    160   } else {
    161     //
    162     // Check whether the input guid section is recognized.
    163     //
    164     if (!CompareGuid (
    165         &gEfiCrc32GuidedSectionExtractionGuid,
    166         &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {
    167       return EFI_INVALID_PARAMETER;
    168     }
    169     //
    170     // Retrieve the size and attribute of the input section data.
    171     //
    172     *SectionAttribute  = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes;
    173     *ScratchBufferSize = 0;
    174     *OutputBufferSize  = SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset;
    175   }
    176 
    177   return EFI_SUCCESS;
    178 }
    179 
    180 /**
    181 
    182   Extraction handler tries to extract raw data from the input guided section.
    183   It also does authentication check for 32bit CRC value in the input guided section.
    184   It first checks whether the input guid section is supported.
    185   If not, EFI_INVALID_PARAMETER will return.
    186 
    187   @param InputSection    Buffer containing the input GUIDed section to be processed.
    188   @param OutputBuffer    Buffer to contain the output raw data allocated by the caller.
    189   @param ScratchBuffer   A pointer to a caller-allocated buffer for function internal use.
    190   @param AuthenticationStatus A pointer to a caller-allocated UINT32 that indicates the
    191                               authentication status of the output buffer.
    192 
    193   @retval EFI_SUCCESS            Section Data and Auth Status is extracted successfully.
    194   @retval EFI_INVALID_PARAMETER  The GUID in InputSection does not match this instance guid.
    195 
    196 **/
    197 EFI_STATUS
    198 EFIAPI
    199 Crc32GuidedSectionHandler (
    200   IN CONST  VOID    *InputSection,
    201   OUT       VOID    **OutputBuffer,
    202   IN        VOID    *ScratchBuffer,        OPTIONAL
    203   OUT       UINT32  *AuthenticationStatus
    204   )
    205 {
    206   EFI_STATUS  Status;
    207   UINT32      SectionCrc32Checksum;
    208   UINT32      Crc32Checksum;
    209   UINT32      OutputBufferSize;
    210 
    211   if (IS_SECTION2 (InputSection)) {
    212     //
    213     // Check whether the input guid section is recognized.
    214     //
    215     if (!CompareGuid (
    216         &gEfiCrc32GuidedSectionExtractionGuid,
    217         &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) {
    218       return EFI_INVALID_PARAMETER;
    219     }
    220 
    221     //
    222     // Get section Crc32 checksum.
    223     //
    224     SectionCrc32Checksum = ((CRC32_SECTION2_HEADER *) InputSection)->CRC32Checksum;
    225     *OutputBuffer      = (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset;
    226     OutputBufferSize   = SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset;
    227 
    228     //
    229     // Implicitly CRC32 GUIDed section should have STATUS_VALID bit set
    230     //
    231     ASSERT (((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID);
    232     *AuthenticationStatus = EFI_AUTH_STATUS_IMAGE_SIGNED;
    233   } else {
    234     //
    235     // Check whether the input guid section is recognized.
    236     //
    237     if (!CompareGuid (
    238         &gEfiCrc32GuidedSectionExtractionGuid,
    239         &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {
    240       return EFI_INVALID_PARAMETER;
    241     }
    242 
    243     //
    244     // Get section Crc32 checksum.
    245     //
    246     SectionCrc32Checksum = ((CRC32_SECTION_HEADER *) InputSection)->CRC32Checksum;
    247     *OutputBuffer      = (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset;
    248     OutputBufferSize   = SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset;
    249 
    250     //
    251     // Implicitly CRC32 GUIDed section should have STATUS_VALID bit set
    252     //
    253     ASSERT (((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID);
    254     *AuthenticationStatus = EFI_AUTH_STATUS_IMAGE_SIGNED;
    255   }
    256 
    257   //
    258   // Init Checksum value to Zero.
    259   //
    260   Crc32Checksum = 0;
    261 
    262   //
    263   // Calculate CRC32 Checksum of Image
    264   //
    265   Status = PeiCrc32GuidedSectionExtractLibCalculateCrc32 (*OutputBuffer, OutputBufferSize, &Crc32Checksum);
    266   if (Status == EFI_SUCCESS) {
    267     if (Crc32Checksum != SectionCrc32Checksum) {
    268       //
    269       // If Crc32 checksum is not matched, AUTH tested failed bit is set.
    270       //
    271       *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;
    272     }
    273   } else {
    274     //
    275     // If Crc32 checksum is not calculated, AUTH not tested bit is set.
    276     //
    277     *AuthenticationStatus |= EFI_AUTH_STATUS_NOT_TESTED;
    278   }
    279 
    280   //
    281   // Temp solution until PeiCore checks AUTH Status.
    282   //
    283   if ((*AuthenticationStatus & (EFI_AUTH_STATUS_TEST_FAILED | EFI_AUTH_STATUS_NOT_TESTED)) != 0) {
    284     return EFI_ACCESS_DENIED;
    285   }
    286 
    287   return EFI_SUCCESS;
    288 }
    289 
    290 /**
    291   Register the handler to extract CRC32 guided section.
    292 
    293   @param  FileHandle   The handle of FFS header the loaded driver.
    294   @param  PeiServices  The pointer to the PEI services.
    295 
    296   @retval  EFI_SUCCESS           Register successfully.
    297   @retval  EFI_OUT_OF_RESOURCES  Not enough memory to register this handler.
    298 
    299 **/
    300 EFI_STATUS
    301 EFIAPI
    302 PeiCrc32GuidedSectionExtractLibConstructor (
    303   IN EFI_PEI_FILE_HANDLE        FileHandle,
    304   IN CONST EFI_PEI_SERVICES     **PeiServices
    305   )
    306 {
    307   return ExtractGuidedSectionRegisterHandlers (
    308           &gEfiCrc32GuidedSectionExtractionGuid,
    309           Crc32GuidedSectionGetInfo,
    310           Crc32GuidedSectionHandler
    311           );
    312 }
    313