]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c
MdeModulePkg DxeCore: Support USED_SIZE FV_EXT_TYPE
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Dispatcher / Dispatcher.c
index c7b9224c0e33301e111d48f9b9407c03ac5b8572..088cd81063137a269e0d9f2957713bd9cc239fc0 100644 (file)
@@ -938,7 +938,67 @@ FvFoundInHobFv2 (
   return FALSE;\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 the driver from the FV through driver name, and produce a FVB protocol on FvHandle.\r
@@ -968,6 +1028,8 @@ CoreProcessFvImageFile (
   EFI_FIRMWARE_VOLUME_HEADER          *FvHeader;\r
   UINT32                              FvAlignment;\r
   EFI_DEVICE_PATH_PROTOCOL            *FvFileDevicePath;\r
+  UINT32                              FvUsedSize;\r
+  UINT8                               EraseByte;\r
 \r
   //\r
   // Read the first (and only the first) firmware volume section\r
@@ -1035,6 +1097,14 @@ CoreProcessFvImageFile (
         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 alignment.\r
       //\r
@@ -1050,7 +1120,19 @@ CoreProcessFvImageFile (
           //\r
           // Move FvImage into the aligned buffer and release the original buffer.\r
           //\r
-          CopyMem (AlignedBuffer, Buffer, BufferSize);\r
+          if (GetFvUsedSize (FvHeader, &FvUsedSize, &EraseByte)) {\r
+            //\r
+            // Copy the used bytes and fill the rest with the erase value.\r
+            //\r
+            CopyMem (AlignedBuffer, FvHeader, (UINTN) FvUsedSize);\r
+            SetMem (\r
+              (UINT8 *) AlignedBuffer + FvUsedSize,\r
+              (UINTN) (BufferSize - FvUsedSize),\r
+              EraseByte\r
+              );\r
+          } else {\r
+            CopyMem (AlignedBuffer, Buffer, BufferSize);\r
+          }\r
           FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) AlignedBuffer;\r
           CoreFreePool (Buffer);\r
           Buffer = NULL;\r