]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/PeiCrc32GuidedSectionExtractLib/PeiCrc32GuidedSectionExtractLib.c
Contributed-under: TianoCore Contribution Agreement 1.0
[mirror_edk2.git] / MdeModulePkg / Library / PeiCrc32GuidedSectionExtractLib / PeiCrc32GuidedSectionExtractLib.c
diff --git a/MdeModulePkg/Library/PeiCrc32GuidedSectionExtractLib/PeiCrc32GuidedSectionExtractLib.c b/MdeModulePkg/Library/PeiCrc32GuidedSectionExtractLib/PeiCrc32GuidedSectionExtractLib.c
new file mode 100644 (file)
index 0000000..6e3dcdd
--- /dev/null
@@ -0,0 +1,312 @@
+/** @file\r
+\r
+  This library registers CRC32 guided section handler \r
+  to parse CRC32 encapsulation section and extract raw data.\r
+\r
+Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Guid/Crc32GuidedSectionExtraction.h>\r
+#include <Library/ExtractGuidedSectionLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+///\r
+/// CRC32 Guided Section header\r
+///\r
+typedef struct {\r
+  EFI_GUID_DEFINED_SECTION  GuidedSectionHeader; ///< EFI guided section header\r
+  UINT32                    CRC32Checksum;       ///< 32bit CRC check sum\r
+} CRC32_SECTION_HEADER;\r
+\r
+typedef struct {\r
+  EFI_GUID_DEFINED_SECTION2 GuidedSectionHeader; ///< EFI guided section header\r
+  UINT32                    CRC32Checksum;       ///< 32bit CRC check sum\r
+} CRC32_SECTION2_HEADER;\r
+\r
+/**\r
+  This internal function reverses bits for 32bit data.\r
+\r
+  @param  Value                 The data to be reversed.\r
+\r
+  @return                       Data reversed.\r
+\r
+**/\r
+UINT32\r
+PeiCrc32GuidedSectionExtractLibReverseBits (\r
+  UINT32  Value\r
+  )\r
+{\r
+  UINTN   Index;\r
+  UINT32  NewValue;\r
+\r
+  NewValue = 0;\r
+  for (Index = 0; Index < 32; Index++) {\r
+    if ((Value & (1 << Index)) != 0) {\r
+      NewValue = NewValue | (1 << (31 - Index));\r
+    }\r
+  }\r
+\r
+  return NewValue;\r
+}\r
+\r
+/**\r
+  Calculate CRC32 for target data.\r
+\r
+  @param  Data                  The target data.\r
+  @param  DataSize              The target data size.\r
+  @param  CrcOut                The CRC32 for target data.\r
+\r
+  @retval EFI_SUCCESS           The CRC32 for target data is calculated successfully.\r
+  @retval EFI_INVALID_PARAMETER Some parameter is not valid, so the CRC32 is not\r
+                                calculated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiCrc32GuidedSectionExtractLibCalculateCrc32 (\r
+  IN  VOID    *Data,\r
+  IN  UINTN   DataSize,\r
+  OUT UINT32  *CrcOut\r
+  )\r
+{\r
+  UINT32  CrcTable[256];\r
+  UINTN   TableEntry;\r
+  UINTN   Index;\r
+  UINT32  Value;\r
+  UINT32  Crc;\r
+  UINT8   *Ptr;\r
+\r
+  if (Data == NULL || DataSize == 0 || CrcOut == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  //\r
+  // Initialize CRC32 table.\r
+  //\r
+  for (TableEntry = 0; TableEntry < 256; TableEntry++) {\r
+    Value = PeiCrc32GuidedSectionExtractLibReverseBits ((UINT32) TableEntry);\r
+    for (Index = 0; Index < 8; Index++) {\r
+      if ((Value & 0x80000000) != 0) {\r
+        Value = (Value << 1) ^ 0x04c11db7;\r
+      } else {\r
+        Value = Value << 1;\r
+      }\r
+    }\r
+    CrcTable[TableEntry] = PeiCrc32GuidedSectionExtractLibReverseBits (Value);\r
+  }\r
+\r
+  //\r
+  // Compute CRC\r
+  //\r
+  Crc = 0xffffffff;\r
+  for (Index = 0, Ptr = Data; Index < DataSize; Index++, Ptr++) {\r
+    Crc = (Crc >> 8) ^ CrcTable[(UINT8) Crc ^ *Ptr];\r
+  }\r
+\r
+  *CrcOut = Crc ^ 0xffffffff;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  GetInfo gets raw data size and attribute of the input guided section.\r
+  It first checks whether the input guid section is supported. \r
+  If not, EFI_INVALID_PARAMETER will return.\r
+\r
+  @param InputSection       Buffer containing the input GUIDed section to be processed.\r
+  @param OutputBufferSize   The size of OutputBuffer.\r
+  @param ScratchBufferSize  The size of ScratchBuffer.\r
+  @param SectionAttribute   The attribute of the input guided section.\r
+\r
+  @retval EFI_SUCCESS            The size of destination buffer, the size of scratch buffer and \r
+                                 the attribute of the input section are successull retrieved.\r
+  @retval EFI_INVALID_PARAMETER  The GUID in InputSection does not match this instance guid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Crc32GuidedSectionGetInfo (\r
+  IN  CONST VOID  *InputSection,\r
+  OUT UINT32      *OutputBufferSize,\r
+  OUT UINT32      *ScratchBufferSize,\r
+  OUT UINT16      *SectionAttribute\r
+  )\r
+{\r
+  if (IS_SECTION2 (InputSection)) {\r
+    //\r
+    // Check whether the input guid section is recognized.\r
+    //\r
+    if (!CompareGuid (\r
+        &gEfiCrc32GuidedSectionExtractionGuid,\r
+        &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    //\r
+    // Retrieve the size and attribute of the input section data.\r
+    //\r
+    *SectionAttribute  = ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes;\r
+    *ScratchBufferSize = 0;\r
+    *OutputBufferSize  = SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset;\r
+  } else {\r
+    //\r
+    // Check whether the input guid section is recognized.\r
+    //\r
+    if (!CompareGuid (\r
+        &gEfiCrc32GuidedSectionExtractionGuid,\r
+        &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    //\r
+    // Retrieve the size and attribute of the input section data.\r
+    //\r
+    *SectionAttribute  = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes;\r
+    *ScratchBufferSize = 0;\r
+    *OutputBufferSize  = SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+\r
+  Extraction handler tries to extract raw data from the input guided section.\r
+  It also does authentication check for 32bit CRC value in the input guided section.\r
+  It first checks whether the input guid section is supported. \r
+  If not, EFI_INVALID_PARAMETER will return.\r
+\r
+  @param InputSection    Buffer containing the input GUIDed section to be processed.\r
+  @param OutputBuffer    Buffer to contain the output raw data allocated by the caller.\r
+  @param ScratchBuffer   A pointer to a caller-allocated buffer for function internal use.\r
+  @param AuthenticationStatus A pointer to a caller-allocated UINT32 that indicates the\r
+                              authentication status of the output buffer.\r
+\r
+  @retval EFI_SUCCESS            Section Data and Auth Status is extracted successfully.\r
+  @retval EFI_INVALID_PARAMETER  The GUID in InputSection does not match this instance guid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Crc32GuidedSectionHandler (\r
+  IN CONST  VOID    *InputSection,\r
+  OUT       VOID    **OutputBuffer,\r
+  IN        VOID    *ScratchBuffer,        OPTIONAL\r
+  OUT       UINT32  *AuthenticationStatus\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      SectionCrc32Checksum;\r
+  UINT32      Crc32Checksum;\r
+  UINT32      OutputBufferSize;\r
+\r
+  if (IS_SECTION2 (InputSection)) {\r
+    //\r
+    // Check whether the input guid section is recognized.\r
+    //\r
+    if (!CompareGuid (\r
+        &gEfiCrc32GuidedSectionExtractionGuid,\r
+        &(((EFI_GUID_DEFINED_SECTION2 *) InputSection)->SectionDefinitionGuid))) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  \r
+    //\r
+    // Get section Crc32 checksum.\r
+    //\r
+    SectionCrc32Checksum = ((CRC32_SECTION2_HEADER *) InputSection)->CRC32Checksum;\r
+    *OutputBuffer      = (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset;\r
+    OutputBufferSize   = SECTION2_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION2 *) InputSection)->DataOffset;\r
+\r
+    //\r
+    // Implicitly CRC32 GUIDed section should have STATUS_VALID bit set\r
+    //\r
+    ASSERT (((EFI_GUID_DEFINED_SECTION2 *) InputSection)->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID);\r
+    *AuthenticationStatus = EFI_AUTH_STATUS_IMAGE_SIGNED;\r
+  } else {\r
+    //\r
+    // Check whether the input guid section is recognized.\r
+    //\r
+    if (!CompareGuid (\r
+        &gEfiCrc32GuidedSectionExtractionGuid,\r
+        &(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+  \r
+    //\r
+    // Get section Crc32 checksum.\r
+    //\r
+    SectionCrc32Checksum = ((CRC32_SECTION_HEADER *) InputSection)->CRC32Checksum;\r
+    *OutputBuffer      = (UINT8 *) InputSection + ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset;\r
+    OutputBufferSize   = SECTION_SIZE (InputSection) - ((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset;\r
+\r
+    //\r
+    // Implicitly CRC32 GUIDed section should have STATUS_VALID bit set\r
+    //\r
+    ASSERT (((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID);\r
+    *AuthenticationStatus = EFI_AUTH_STATUS_IMAGE_SIGNED;\r
+  }\r
+\r
+  //\r
+  // Init Checksum value to Zero.\r
+  //\r
+  Crc32Checksum = 0;\r
+\r
+  //\r
+  // Calculate CRC32 Checksum of Image\r
+  //\r
+  Status = PeiCrc32GuidedSectionExtractLibCalculateCrc32 (*OutputBuffer, OutputBufferSize, &Crc32Checksum);\r
+  if (Status == EFI_SUCCESS) {\r
+    if (Crc32Checksum != SectionCrc32Checksum) {\r
+      //\r
+      // If Crc32 checksum is not matched, AUTH tested failed bit is set.\r
+      //\r
+      *AuthenticationStatus |= EFI_AUTH_STATUS_TEST_FAILED;\r
+    }\r
+  } else {\r
+    //\r
+    // If Crc32 checksum is not calculated, AUTH not tested bit is set.\r
+    //\r
+    *AuthenticationStatus |= EFI_AUTH_STATUS_NOT_TESTED;\r
+  }\r
+\r
+  //\r
+  // Temp solution until PeiCore checks AUTH Status.\r
+  //\r
+  if ((*AuthenticationStatus & (EFI_AUTH_STATUS_TEST_FAILED | EFI_AUTH_STATUS_NOT_TESTED)) != 0) {\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Register the handler to extract CRC32 guided section.\r
+\r
+  @param  FileHandle   The handle of FFS header the loaded driver.\r
+  @param  PeiServices  The pointer to the PEI services.\r
+\r
+  @retval  EFI_SUCCESS           Register successfully.\r
+  @retval  EFI_OUT_OF_RESOURCES  Not enough memory to register this handler.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PeiCrc32GuidedSectionExtractLibConstructor (\r
+  IN EFI_PEI_FILE_HANDLE        FileHandle,\r
+  IN CONST EFI_PEI_SERVICES     **PeiServices\r
+  )\r
+{\r
+  return ExtractGuidedSectionRegisterHandlers (\r
+          &gEfiCrc32GuidedSectionExtractionGuid,\r
+          Crc32GuidedSectionGetInfo,\r
+          Crc32GuidedSectionHandler\r
+          );\r
+}\r