]> 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 5686d94e6a727372003ba6ba177d2103eb310ee1..088cd81063137a269e0d9f2957713bd9cc239fc0 100644 (file)
@@ -773,7 +773,7 @@ FvIsBeingProcesssed (
     for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) {\r
       KnownHandle = CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE);\r
       if (CompareGuid (&FvNameGuid, &KnownHandle->FvNameGuid)) {\r
-        DEBUG ((EFI_D_ERROR, "FvImage on FvHandle %p and %p has the same FvNameGuid %g.\n", FvHandle, KnownHandle->Handle, FvNameGuid));\r
+        DEBUG ((EFI_D_ERROR, "FvImage on FvHandle %p and %p has the same FvNameGuid %g.\n", FvHandle, KnownHandle->Handle, &FvNameGuid));\r
         return NULL;\r
       }\r
     }\r
@@ -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
@@ -1023,32 +1085,58 @@ CoreProcessFvImageFile (
     // can be aligned on any power-of-two boundary. A weakly aligned volume can not be moved from\r
     // its initial linked location and maintain its alignment.\r
     //\r
-    if ((FvHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {\r
+    if ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {\r
       //\r
       // Get FvHeader alignment\r
       //\r
-      FvAlignment = 1 << ((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);\r
+      FvAlignment = 1 << ((ReadUnaligned32 (&FvHeader->Attributes) & EFI_FVB2_ALIGNMENT) >> 16);\r
       //\r
       // FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.\r
       //\r
       if (FvAlignment < 8) {\r
         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
-      // Allocate the aligned buffer for the FvImage.\r
+      // Check FvImage alignment.\r
       //\r
-      AlignedBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment);\r
-      if (AlignedBuffer == NULL) {\r
-        FreePool (Buffer);\r
-        return EFI_OUT_OF_RESOURCES;\r
-      } else {\r
+      if ((UINTN) FvHeader % FvAlignment != 0) {\r
         //\r
-        // Move FvImage into the aligned buffer and release the original buffer.\r
+        // Allocate the aligned buffer for the FvImage.\r
         //\r
-        CopyMem (AlignedBuffer, Buffer, BufferSize);\r
-        FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) AlignedBuffer;\r
-        CoreFreePool (Buffer);\r
-        Buffer = NULL;\r
+        AlignedBuffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (BufferSize), (UINTN) FvAlignment);\r
+        if (AlignedBuffer == NULL) {\r
+          FreePool (Buffer);\r
+          return EFI_OUT_OF_RESOURCES;\r
+        } else {\r
+          //\r
+          // Move FvImage into the aligned buffer and release the original buffer.\r
+          //\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
+        }\r
       }\r
     }\r
     //\r