]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Pei/FwVol/FwVol.c
MdeModulePkg PeiCore: Support USED_SIZE FV_EXT_TYPE
[mirror_edk2.git] / MdeModulePkg / Core / Pei / FwVol / FwVol.c
index 3da90f95312d0172dac6721317e173859115a20c..7cb295c2c679d40744d3915c9e9ff9afac563347 100644 (file)
@@ -1294,6 +1294,68 @@ PeiFfsGetVolumeInfo (
   return CoreHandle->FvPpi->GetVolumeInfo (CoreHandle->FvPpi, VolumeHandle, VolumeInfo);\r
 }\r
 \r
+/**\r
+  Find USED_SIZE FV_EXT_TYPE entry in FV extension header and get the FV used size.\r
+\r
+  @param[in]  FvHeader      Pointer to FV header.\r
+  @param[out] FvUsedSize    Pointer to FV used size returned,\r
+                            only valid if USED_SIZE FV_EXT_TYPE entry is found.\r
+  @param[out] EraseByte     Pointer to erase byte returned,\r
+                            only valid if USED_SIZE FV_EXT_TYPE entry is found.\r
+\r
+  @retval TRUE              USED_SIZE FV_EXT_TYPE entry is found,\r
+                            FV used size and erase byte are returned.\r
+  @retval FALSE             No USED_SIZE FV_EXT_TYPE entry found.\r
+\r
+**/\r
+BOOLEAN\r
+GetFvUsedSize (\r
+  IN EFI_FIRMWARE_VOLUME_HEADER     *FvHeader,\r
+  OUT UINT32                        *FvUsedSize,\r
+  OUT UINT8                         *EraseByte\r
+  )\r
+{\r
+  UINT16                                        ExtHeaderOffset;\r
+  EFI_FIRMWARE_VOLUME_EXT_HEADER                *ExtHeader;\r
+  EFI_FIRMWARE_VOLUME_EXT_ENTRY                 *ExtEntryList;\r
+  EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE  *ExtEntryUsedSize;\r
+\r
+  ExtHeaderOffset = ReadUnaligned16 (&FvHeader->ExtHeaderOffset);\r
+  if (ExtHeaderOffset != 0) {\r
+    ExtHeader    = (EFI_FIRMWARE_VOLUME_EXT_HEADER *) ((UINT8 *) FvHeader + ExtHeaderOffset);\r
+    ExtEntryList = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *) (ExtHeader + 1);\r
+    while ((UINTN) ExtEntryList < ((UINTN) ExtHeader + ReadUnaligned32 (&ExtHeader->ExtHeaderSize))) {\r
+      if (ReadUnaligned16 (&ExtEntryList->ExtEntryType) == EFI_FV_EXT_TYPE_USED_SIZE_TYPE) {\r
+        //\r
+        // USED_SIZE FV_EXT_TYPE entry is found.\r
+        //\r
+        ExtEntryUsedSize = (EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *) ExtEntryList;\r
+        *FvUsedSize = ReadUnaligned32 (&ExtEntryUsedSize->UsedSize);\r
+        if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ERASE_POLARITY) != 0) {\r
+          *EraseByte = 0xFF;\r
+        } else {\r
+          *EraseByte = 0;\r
+        }\r
+        DEBUG ((\r
+          DEBUG_INFO,\r
+          "FV at 0x%x has 0x%x used size, and erase byte is 0x%02x\n",\r
+          FvHeader,\r
+          *FvUsedSize,\r
+          *EraseByte\r
+          ));\r
+        return TRUE;\r
+      }\r
+      ExtEntryList = (EFI_FIRMWARE_VOLUME_EXT_ENTRY *)\r
+                     ((UINT8 *) ExtEntryList + ReadUnaligned16 (&ExtEntryList->ExtEntrySize));\r
+    }\r
+  }\r
+\r
+  //\r
+  // No USED_SIZE FV_EXT_TYPE entry found.\r
+  //\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Get Fv image from the FV type file, then install FV INFO(2) ppi, Build FV hob.\r
 \r
@@ -1326,7 +1388,9 @@ ProcessFvFile (
   EFI_FV_FILE_INFO              FileInfo;\r
   UINT64                        FvLength;\r
   UINT32                        AuthenticationStatus;\r
-  \r
+  UINT32                        FvUsedSize;\r
+  UINT8                         EraseByte;\r
+\r
   //\r
   // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already\r
   // been extracted.\r
@@ -1391,8 +1455,16 @@ ProcessFvFile (
       FvAlignment = 8;\r
     }\r
 \r
+    DEBUG ((\r
+      DEBUG_INFO,\r
+      "%a() FV at 0x%x, FvAlignment required is 0x%x\n",\r
+      __FUNCTION__,\r
+      FvHeader,\r
+      FvAlignment\r
+      ));\r
+\r
     //\r
-    // Check FvImage\r
+    // Check FvImage alignment.\r
     //\r
     if ((UINTN) FvHeader % FvAlignment != 0) {\r
       FvLength    = ReadUnaligned64 (&FvHeader->FvLength);\r
@@ -1400,7 +1472,19 @@ ProcessFvFile (
       if (NewFvBuffer == NULL) {\r
         return EFI_OUT_OF_RESOURCES;\r
       }\r
-      CopyMem (NewFvBuffer, FvHeader, (UINTN) FvLength);\r
+      if (GetFvUsedSize (FvHeader, &FvUsedSize, &EraseByte)) {\r
+        //\r
+        // Copy the used bytes and fill the rest with the erase value.\r
+        //\r
+        CopyMem (NewFvBuffer, FvHeader, (UINTN) FvUsedSize);\r
+        SetMem (\r
+          (UINT8 *) NewFvBuffer + FvUsedSize,\r
+          (UINTN) (FvLength - FvUsedSize),\r
+          EraseByte\r
+          );\r
+      } else {\r
+        CopyMem (NewFvBuffer, FvHeader, (UINTN) FvLength);\r
+      }\r
       FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*) NewFvBuffer;\r
     }\r
   }\r