]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
MdeModulePkg/Core: Fix typos in comments
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / FwVolBlock / FwVolBlock.c
index bc234aa0d01080276286375ae3850782e6949fd7..f031ef110c19b78680235837541bf6d1566731fc 100644 (file)
@@ -1,12 +1,11 @@
 /** @file\r
-  Firmware Volume Block protocol.  Consumes FV hobs and creates\r
-  appropriate block protocols.\r
+  Implementations for Firmware Volume Block protocol.\r
 \r
-  Also consumes NT_NON_MM_FV envinronment variable and produces appropriate\r
-  block protocols fro them also... (this is TBD)\r
+  It consumes FV HOBs and creates read-only Firmare Volume Block protocol\r
+  instances for each of them.\r
 \r
-Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2006 - 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
@@ -16,29 +15,59 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 **/\r
 \r
-#include <DxeMain.h>\r
+#include "DxeMain.h"\r
+#include "FwVolBlock.h"\r
 \r
-\r
-EFI_FW_VOL_BLOCK_DEVICE  mFwVolBlock = {\r
-  FVB_DEVICE_SIGNATURE,\r
-  NULL,\r
+FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = {\r
   {\r
     {\r
+      HARDWARE_DEVICE_PATH,\r
+      HW_MEMMAP_DP,\r
       {\r
-        HARDWARE_DEVICE_PATH,\r
-        HW_MEMMAP_DP,\r
-        { (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) }\r
-      },\r
-      EfiMemoryMappedIO,\r
-      (EFI_PHYSICAL_ADDRESS)0,\r
-      (EFI_PHYSICAL_ADDRESS)0,\r
+        (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),\r
+        (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8)\r
+      }\r
     },\r
+    EfiMemoryMappedIO,\r
+    (EFI_PHYSICAL_ADDRESS) 0,\r
+    (EFI_PHYSICAL_ADDRESS) 0,\r
+  },\r
+  {\r
+    END_DEVICE_PATH_TYPE,\r
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+    {\r
+      END_DEVICE_PATH_LENGTH,\r
+      0\r
+    }\r
+  }\r
+};\r
+\r
+FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = {\r
+  {\r
     {\r
-      END_DEVICE_PATH_TYPE,\r
-      END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
-      { END_DEVICE_PATH_LENGTH, 0 }      \r
+      MEDIA_DEVICE_PATH,\r
+      MEDIA_PIWG_FW_VOL_DP,\r
+      {\r
+        (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)),\r
+        (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8)\r
+      }\r
     },\r
+    { 0 }\r
   },\r
+  {\r
+    END_DEVICE_PATH_TYPE,\r
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
+    {\r
+      END_DEVICE_PATH_LENGTH,\r
+      0\r
+    }\r
+  }\r
+};\r
+\r
+EFI_FW_VOL_BLOCK_DEVICE  mFwVolBlock = {\r
+  FVB_DEVICE_SIGNATURE,\r
+  NULL,\r
+  NULL,\r
   {\r
     FwVolBlockGetAttributes,\r
     (EFI_FVB_SET_ATTRIBUTES)FwVolBlockSetAttributes,\r
@@ -47,23 +76,22 @@ EFI_FW_VOL_BLOCK_DEVICE  mFwVolBlock = {
     FwVolBlockReadBlock,\r
     (EFI_FVB_WRITE)FwVolBlockWriteBlock,\r
     (EFI_FVB_ERASE_BLOCKS)FwVolBlockEraseBlock,\r
-    NULL      \r
+    NULL\r
   },\r
   0,\r
   NULL,\r
   0,\r
+  0,\r
   0\r
 };\r
 \r
 \r
 \r
-\r
-\r
 /**\r
   Retrieves Volume attributes.  No polarity translations are done.\r
 \r
-  @param  This                   Calling context \r
-  @param  Attributes             output buffer which contains attributes \r
+  @param  This                   Calling context\r
+  @param  Attributes             output buffer which contains attributes\r
 \r
   @retval EFI_SUCCESS            The firmware volume attributes were returned.\r
 \r
@@ -72,17 +100,17 @@ EFI_STATUS
 EFIAPI\r
 FwVolBlockGetAttributes (\r
   IN CONST  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,\r
-  OUT       EFI_FVB_ATTRIBUTES                  *Attributes\r
+  OUT       EFI_FVB_ATTRIBUTES_2                *Attributes\r
   )\r
 {\r
   EFI_FW_VOL_BLOCK_DEVICE               *FvbDevice;\r
-  \r
+\r
   FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
 \r
   //\r
   // Since we are read only, it's safe to get attributes data from our in-memory copy.\r
   //\r
-  *Attributes = FvbDevice->FvbAttributes;\r
+  *Attributes = FvbDevice->FvbAttributes & ~EFI_FVB2_WRITE_STATUS;\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -92,13 +120,13 @@ FwVolBlockGetAttributes (
 /**\r
   Modifies the current settings of the firmware volume according to the input parameter.\r
 \r
-  @param  This                   Calling context \r
-  @param  Attributes             input buffer which contains attributes \r
+  @param  This                   Calling context\r
+  @param  Attributes             input buffer which contains attributes\r
 \r
-  @retval EFI_SUCCESS            The firmware volume attributes were returned. \r
-  @retval EFI_INVALID_PARAMETER  The attributes requested are in conflict with \r
-                                 the capabilities as declared in the firmware \r
-                                 volume header. \r
+  @retval EFI_SUCCESS            The firmware volume attributes were returned.\r
+  @retval EFI_INVALID_PARAMETER  The attributes requested are in conflict with\r
+                                 the capabilities as declared in the firmware\r
+                                 volume header.\r
   @retval EFI_UNSUPPORTED        Not supported.\r
 \r
 **/\r
@@ -106,7 +134,7 @@ EFI_STATUS
 EFIAPI\r
 FwVolBlockSetAttributes (\r
   IN CONST  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,\r
-  IN CONST  EFI_FVB_ATTRIBUTES                  *Attributes\r
+  IN CONST  EFI_FVB_ATTRIBUTES_2                *Attributes\r
   )\r
 {\r
   return EFI_UNSUPPORTED;\r
@@ -122,18 +150,18 @@ FwVolBlockSetAttributes (
   block of the firmware volume), the EraseBlock() function must return\r
   EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.\r
 \r
-  @param  This                   Calling context \r
-  @param  ...                    Starting LBA followed by Number of Lba to erase. \r
-                                 a -1 to terminate the list. \r
-\r
-  @retval EFI_SUCCESS            The erase request was successfully completed. \r
-  @retval EFI_ACCESS_DENIED      The firmware volume is in the WriteDisabled \r
-                                 state. \r
-  @retval EFI_DEVICE_ERROR       The block device is not functioning correctly \r
-                                 and could not be written. The firmware device \r
-                                 may have been partially erased. \r
-  @retval EFI_INVALID_PARAMETER  One or more of the LBAs listed in the variable \r
-                                 argument list do \r
+  @param  This                   Calling context\r
+  @param  ...                    Starting LBA followed by Number of Lba to erase.\r
+                                 a -1 to terminate the list.\r
+\r
+  @retval EFI_SUCCESS            The erase request was successfully completed.\r
+  @retval EFI_ACCESS_DENIED      The firmware volume is in the WriteDisabled\r
+                                 state.\r
+  @retval EFI_DEVICE_ERROR       The block device is not functioning correctly\r
+                                 and could not be written. The firmware device\r
+                                 may have been partially erased.\r
+  @retval EFI_INVALID_PARAMETER  One or more of the LBAs listed in the variable\r
+                                 argument list do\r
   @retval EFI_UNSUPPORTED        Not supported.\r
 \r
 **/\r
@@ -152,20 +180,20 @@ FwVolBlockEraseBlock (
 /**\r
   Read the specified number of bytes from the block to the input buffer.\r
 \r
-  @param  This                   Indicates the calling context. \r
-  @param  Lba                    The starting logical block index to read. \r
-  @param  Offset                 Offset into the block at which to begin reading. \r
-  @param  NumBytes               Pointer to a UINT32. At entry, *NumBytes \r
-                                 contains the total size of the buffer. At exit, \r
-                                 *NumBytes contains the total number of bytes \r
-                                 actually read. \r
-  @param  Buffer                 Pinter to a caller-allocated buffer that \r
-                                 contains the destine for the read. \r
-\r
-  @retval EFI_SUCCESS            The firmware volume was read successfully. \r
-  @retval EFI_BAD_BUFFER_SIZE    The read was attempted across an LBA boundary. \r
-  @retval EFI_ACCESS_DENIED      Access denied. \r
-  @retval EFI_DEVICE_ERROR       The block device is malfunctioning and could not \r
+  @param  This                   Indicates the calling context.\r
+  @param  Lba                    The starting logical block index to read.\r
+  @param  Offset                 Offset into the block at which to begin reading.\r
+  @param  NumBytes               Pointer to a UINT32. At entry, *NumBytes\r
+                                 contains the total size of the buffer. At exit,\r
+                                 *NumBytes contains the total number of bytes\r
+                                 actually read.\r
+  @param  Buffer                 Pinter to a caller-allocated buffer that\r
+                                 contains the destine for the read.\r
+\r
+  @retval EFI_SUCCESS            The firmware volume was read successfully.\r
+  @retval EFI_BAD_BUFFER_SIZE    The read was attempted across an LBA boundary.\r
+  @retval EFI_ACCESS_DENIED      Access denied.\r
+  @retval EFI_DEVICE_ERROR       The block device is malfunctioning and could not\r
                                  be read.\r
 \r
 **/\r
@@ -185,7 +213,7 @@ FwVolBlockReadBlock (
   UINTN                                 LbaStart;\r
   UINTN                                 NumOfBytesRead;\r
   UINTN                                 LbaIndex;\r
-  \r
+\r
   FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
 \r
   //\r
@@ -194,8 +222,8 @@ FwVolBlockReadBlock (
   if ((FvbDevice->FvbAttributes & EFI_FVB2_READ_STATUS) == 0) {\r
     return EFI_ACCESS_DENIED;\r
   }\r
-  \r
-  LbaIndex = (UINTN)Lba;\r
+\r
+  LbaIndex = (UINTN) Lba;\r
   if (LbaIndex >= FvbDevice->NumBlocks) {\r
     //\r
     // Invalid Lba, read nothing.\r
@@ -203,63 +231,63 @@ FwVolBlockReadBlock (
     *NumBytes = 0;\r
     return EFI_BAD_BUFFER_SIZE;\r
   }\r
-  \r
+\r
   if (Offset > FvbDevice->LbaCache[LbaIndex].Length) {\r
     //\r
-    // all exceed boundry, read nothing.\r
+    // all exceed boundary, read nothing.\r
     //\r
     *NumBytes = 0;\r
     return EFI_BAD_BUFFER_SIZE;\r
   }\r
-  \r
+\r
   NumOfBytesRead = *NumBytes;\r
   if (Offset + NumOfBytesRead > FvbDevice->LbaCache[LbaIndex].Length) {\r
     //\r
-    // partial exceed boundry, read data from current postion to end.\r
+    // partial exceed boundary, read data from current postion to end.\r
     //\r
     NumOfBytesRead = FvbDevice->LbaCache[LbaIndex].Length - Offset;\r
   }\r
-  \r
+\r
   LbaStart = FvbDevice->LbaCache[LbaIndex].Base;\r
-  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress);\r
-  LbaOffset = (UINT8 *)FwVolHeader + LbaStart + Offset;\r
+  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN) FvbDevice->BaseAddress);\r
+  LbaOffset = (UINT8 *) FwVolHeader + LbaStart + Offset;\r
 \r
   //\r
   // Perform read operation\r
   //\r
   CopyMem (Buffer, LbaOffset, NumOfBytesRead);\r
-  \r
+\r
   if (NumOfBytesRead == *NumBytes) {\r
     return EFI_SUCCESS;\r
   }\r
-    \r
+\r
   *NumBytes = NumOfBytesRead;\r
   return EFI_BAD_BUFFER_SIZE;\r
 }\r
-  \r
+\r
 \r
 \r
 /**\r
   Writes the specified number of bytes from the input buffer to the block.\r
 \r
-  @param  This                   Indicates the calling context. \r
-  @param  Lba                    The starting logical block index to write to. \r
-  @param  Offset                 Offset into the block at which to begin writing. \r
-  @param  NumBytes               Pointer to a UINT32. At entry, *NumBytes \r
-                                 contains the total size of the buffer. At exit, \r
-                                 *NumBytes contains the total number of bytes \r
-                                 actually written. \r
-  @param  Buffer                 Pinter to a caller-allocated buffer that \r
-                                 contains the source for the write. \r
-\r
-  @retval EFI_SUCCESS            The firmware volume was written successfully. \r
-  @retval EFI_BAD_BUFFER_SIZE    The write was attempted across an LBA boundary. \r
-                                 On output, NumBytes contains the total number of \r
-                                 bytes actually written. \r
-  @retval EFI_ACCESS_DENIED      The firmware volume is in the WriteDisabled \r
-                                 state. \r
-  @retval EFI_DEVICE_ERROR       The block device is malfunctioning and could not \r
-                                 be written. \r
+  @param  This                   Indicates the calling context.\r
+  @param  Lba                    The starting logical block index to write to.\r
+  @param  Offset                 Offset into the block at which to begin writing.\r
+  @param  NumBytes               Pointer to a UINT32. At entry, *NumBytes\r
+                                 contains the total size of the buffer. At exit,\r
+                                 *NumBytes contains the total number of bytes\r
+                                 actually written.\r
+  @param  Buffer                 Pinter to a caller-allocated buffer that\r
+                                 contains the source for the write.\r
+\r
+  @retval EFI_SUCCESS            The firmware volume was written successfully.\r
+  @retval EFI_BAD_BUFFER_SIZE    The write was attempted across an LBA boundary.\r
+                                 On output, NumBytes contains the total number of\r
+                                 bytes actually written.\r
+  @retval EFI_ACCESS_DENIED      The firmware volume is in the WriteDisabled\r
+                                 state.\r
+  @retval EFI_DEVICE_ERROR       The block device is malfunctioning and could not\r
+                                 be written.\r
   @retval EFI_UNSUPPORTED        Not supported.\r
 \r
 **/\r
@@ -275,16 +303,16 @@ FwVolBlockWriteBlock (
 {\r
   return EFI_UNSUPPORTED;\r
 }\r
\r
+\r
 \r
 \r
 /**\r
   Get Fvb's base address.\r
 \r
-  @param  This                   Indicates the calling context. \r
-  @param  Address                Fvb device base address. \r
+  @param  This                   Indicates the calling context.\r
+  @param  Address                Fvb device base address.\r
 \r
-  @retval EFI_SUCCESS            Successfully got Fvb's base address. \r
+  @retval EFI_SUCCESS            Successfully got Fvb's base address.\r
   @retval EFI_UNSUPPORTED        Not supported.\r
 \r
 **/\r
@@ -296,14 +324,14 @@ FwVolBlockGetPhysicalAddress (
   )\r
 {\r
   EFI_FW_VOL_BLOCK_DEVICE               *FvbDevice;\r
-  \r
+\r
   FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
-  \r
-  if (FvbDevice->FvbAttributes & EFI_FVB2_MEMORY_MAPPED) {\r
+\r
+  if ((FvbDevice->FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {\r
     *Address = FvbDevice->BaseAddress;\r
     return EFI_SUCCESS;\r
   }\r
-  \r
+\r
   return EFI_UNSUPPORTED;\r
 }\r
 \r
@@ -312,17 +340,17 @@ FwVolBlockGetPhysicalAddress (
 /**\r
   Retrieves the size in bytes of a specific block within a firmware volume.\r
 \r
-  @param  This                   Indicates the calling context. \r
-  @param  Lba                    Indicates the block for which to return the \r
-                                 size. \r
-  @param  BlockSize              Pointer to a caller-allocated UINTN in which the \r
-                                 size of the block is returned. \r
-  @param  NumberOfBlocks         Pointer to a caller-allocated UINTN in which the \r
-                                 number of consecutive blocks starting with Lba \r
-                                 is returned. All blocks in this range have a \r
-                                 size of BlockSize. \r
-\r
-  @retval EFI_SUCCESS            The firmware volume base address is returned. \r
+  @param  This                   Indicates the calling context.\r
+  @param  Lba                    Indicates the block for which to return the\r
+                                 size.\r
+  @param  BlockSize              Pointer to a caller-allocated UINTN in which the\r
+                                 size of the block is returned.\r
+  @param  NumberOfBlocks         Pointer to a caller-allocated UINTN in which the\r
+                                 number of consecutive blocks starting with Lba\r
+                                 is returned. All blocks in this range have a\r
+                                 size of BlockSize.\r
+\r
+  @retval EFI_SUCCESS            The firmware volume base address is returned.\r
   @retval EFI_INVALID_PARAMETER  The requested LBA is out of range.\r
 \r
 **/\r
@@ -339,20 +367,20 @@ FwVolBlockGetBlockSize (
   EFI_FW_VOL_BLOCK_DEVICE               *FvbDevice;\r
   EFI_FV_BLOCK_MAP_ENTRY                *PtrBlockMapEntry;\r
   EFI_FIRMWARE_VOLUME_HEADER            *FwVolHeader;\r
-  \r
+\r
   FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
-  \r
+\r
   //\r
   // Do parameter checking\r
   //\r
   if (Lba >= FvbDevice->NumBlocks) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
-  \r
+\r
   FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress);\r
-  \r
+\r
   PtrBlockMapEntry = FwVolHeader->BlockMap;\r
-  \r
+\r
   //\r
   // Search the block map for the given block\r
   //\r
@@ -365,32 +393,58 @@ FwVolBlockGetBlockSize (
       //\r
       break;\r
     }\r
-    \r
+\r
     PtrBlockMapEntry++;\r
   }\r
-  \r
+\r
   *BlockSize = PtrBlockMapEntry->Length;\r
   *NumberOfBlocks = TotalBlocks - (UINTN)Lba;\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+\r
+  Get FVB authentication status\r
+\r
+  @param FvbProtocol    FVB protocol.\r
 \r
+  @return Authentication status.\r
+\r
+**/\r
+UINT32\r
+GetFvbAuthenticationStatus (\r
+  IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *FvbProtocol\r
+  )\r
+{\r
+  EFI_FW_VOL_BLOCK_DEVICE   *FvbDevice;\r
+  UINT32                    AuthenticationStatus;\r
+\r
+  AuthenticationStatus = 0;\r
+  FvbDevice = BASE_CR (FvbProtocol, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance);\r
+  if (FvbDevice->Signature == FVB_DEVICE_SIGNATURE) {\r
+    AuthenticationStatus = FvbDevice->AuthenticationStatus;\r
+  }\r
+\r
+  return AuthenticationStatus;\r
+}\r
 \r
 /**\r
   This routine produces a firmware volume block protocol on a given\r
   buffer.\r
 \r
-  @param  BaseAddress            base address of the firmware volume image \r
-  @param  Length                 length of the firmware volume image \r
-  @param  ParentHandle           handle of parent firmware volume, if this image \r
-                                 came from an FV image file in another firmware \r
-                                 volume (ala capsules) \r
-  @param  FvProtocol             Firmware volume block protocol produced. \r
-\r
-  @retval EFI_VOLUME_CORRUPTED   Volume corrupted. \r
-  @retval EFI_OUT_OF_RESOURCES   No enough buffer to be allocated. \r
-  @retval EFI_SUCCESS            Successfully produced a FVB protocol on given \r
+  @param  BaseAddress            base address of the firmware volume image\r
+  @param  Length                 length of the firmware volume image\r
+  @param  ParentHandle           handle of parent firmware volume, if this image\r
+                                 came from an FV image file and section in another firmware\r
+                                 volume (ala capsules)\r
+  @param  AuthenticationStatus   Authentication status inherited, if this image\r
+                                 came from an FV image file and section in another firmware volume.\r
+  @param  FvProtocol             Firmware volume block protocol produced.\r
+\r
+  @retval EFI_VOLUME_CORRUPTED   Volume corrupted.\r
+  @retval EFI_OUT_OF_RESOURCES   No enough buffer to be allocated.\r
+  @retval EFI_SUCCESS            Successfully produced a FVB protocol on given\r
                                  buffer.\r
 \r
 **/\r
@@ -399,6 +453,7 @@ ProduceFVBProtocolOnBuffer (
   IN EFI_PHYSICAL_ADDRESS   BaseAddress,\r
   IN UINT64                 Length,\r
   IN EFI_HANDLE             ParentHandle,\r
+  IN UINT32                 AuthenticationStatus,\r
   OUT EFI_HANDLE            *FvProtocol  OPTIONAL\r
   )\r
 {\r
@@ -410,32 +465,44 @@ ProduceFVBProtocolOnBuffer (
   UINTN                         LinearOffset;\r
   UINT32                        FvAlignment;\r
   EFI_FV_BLOCK_MAP_ENTRY        *PtrBlockMapEntry;\r
-  \r
+\r
   FvAlignment = 0;\r
-  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;\r
+  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN) BaseAddress;\r
   //\r
   // Validate FV Header, if not as expected, return\r
   //\r
   if (FwVolHeader->Signature != EFI_FVH_SIGNATURE) {\r
     return EFI_VOLUME_CORRUPTED;\r
   }\r
+\r
   //\r
-  // Get FvHeader alignment\r
+  // If EFI_FVB2_WEAK_ALIGNMENT is set in the volume header then the first byte of the volume\r
+  // 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
-  FvAlignment = 1 << ((FwVolHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);\r
-  if (FvAlignment < 8) {\r
-    FvAlignment = 8;\r
-  }\r
-  if ((UINTN)BaseAddress % FvAlignment != 0) {\r
+  if ((FwVolHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {\r
     //\r
-    // FvImage buffer is not at its required alignment.\r
+    // Get FvHeader alignment\r
     //\r
-    return EFI_VOLUME_CORRUPTED;\r
+    FvAlignment = 1 << ((FwVolHeader->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
+    if ((UINTN)BaseAddress % FvAlignment != 0) {\r
+      //\r
+      // FvImage buffer is not at its required alignment.\r
+      //\r
+      return EFI_VOLUME_CORRUPTED;\r
+    }\r
   }\r
+\r
   //\r
-  // Allocate EFI_FW_VOL_BLOCK_DEVICE \r
+  // Allocate EFI_FW_VOL_BLOCK_DEVICE\r
   //\r
-  FvbDev = CoreAllocateCopyPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE), &mFwVolBlock);\r
+  FvbDev = AllocateCopyPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE), &mFwVolBlock);\r
   if (FvbDev == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
@@ -443,6 +510,9 @@ ProduceFVBProtocolOnBuffer (
   FvbDev->BaseAddress   = BaseAddress;\r
   FvbDev->FvbAttributes = FwVolHeader->Attributes;\r
   FvbDev->FwVolBlockInstance.ParentHandle = ParentHandle;\r
+  if (ParentHandle != NULL) {\r
+    FvbDev->AuthenticationStatus = AuthenticationStatus;\r
+  }\r
 \r
   //\r
   // Init the block caching fields of the device\r
@@ -450,25 +520,31 @@ ProduceFVBProtocolOnBuffer (
   //\r
   FvbDev->NumBlocks = 0;\r
   for (PtrBlockMapEntry = FwVolHeader->BlockMap;\r
-        PtrBlockMapEntry->NumBlocks != 0;\r
-        PtrBlockMapEntry++) {\r
+       PtrBlockMapEntry->NumBlocks != 0;\r
+       PtrBlockMapEntry++) {\r
     FvbDev->NumBlocks += PtrBlockMapEntry->NumBlocks;\r
   }\r
+\r
   //\r
   // Second, allocate the cache\r
   //\r
-  FvbDev->LbaCache = CoreAllocateBootServicesPool (FvbDev->NumBlocks * sizeof (LBA_CACHE));\r
+  if (FvbDev->NumBlocks >= (MAX_ADDRESS / sizeof (LBA_CACHE))) {\r
+    CoreFreePool (FvbDev);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  FvbDev->LbaCache = AllocatePool (FvbDev->NumBlocks * sizeof (LBA_CACHE));\r
   if (FvbDev->LbaCache == NULL) {\r
     CoreFreePool (FvbDev);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
+  \r
   //\r
   // Last, fill in the cache with the linear address of the blocks\r
   //\r
   BlockIndex = 0;\r
   LinearOffset = 0;\r
   for (PtrBlockMapEntry = FwVolHeader->BlockMap;\r
-        PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {\r
+       PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {\r
     for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) {\r
       FvbDev->LbaCache[BlockIndex].Base = LinearOffset;\r
       FvbDev->LbaCache[BlockIndex].Length = PtrBlockMapEntry->Length;\r
@@ -478,22 +554,44 @@ ProduceFVBProtocolOnBuffer (
   }\r
 \r
   //\r
-  // Set up the devicepath\r
+  // Judget whether FV name guid is produced in Fv extension header\r
   //\r
-  FvbDev->DevicePath.MemMapDevPath.StartingAddress = BaseAddress;\r
-  FvbDev->DevicePath.MemMapDevPath.EndingAddress = BaseAddress + FwVolHeader->FvLength - 1;\r
-\r
+  if (FwVolHeader->ExtHeaderOffset == 0) {\r
+    //\r
+    // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH\r
+    //\r
+    FvbDev->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateCopyPool (sizeof (FV_MEMMAP_DEVICE_PATH), &mFvMemmapDevicePathTemplate);\r
+    if (FvbDev->DevicePath == NULL) {\r
+      FreePool (FvbDev);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    ((FV_MEMMAP_DEVICE_PATH *) FvbDev->DevicePath)->MemMapDevPath.StartingAddress = BaseAddress;\r
+    ((FV_MEMMAP_DEVICE_PATH *) FvbDev->DevicePath)->MemMapDevPath.EndingAddress   = BaseAddress + FwVolHeader->FvLength - 1;\r
+  } else {\r
+    //\r
+    // FV contains extension header, then produce MEDIA_FW_VOL_DEVICE_PATH\r
+    //\r
+    FvbDev->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocateCopyPool (sizeof (FV_PIWG_DEVICE_PATH), &mFvPIWGDevicePathTemplate);\r
+    if (FvbDev->DevicePath == NULL) {\r
+      FreePool (FvbDev);\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    CopyGuid (\r
+      &((FV_PIWG_DEVICE_PATH *)FvbDev->DevicePath)->FvDevPath.FvName, \r
+      (GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset)\r
+      );\r
+  }\r
+  \r
   //\r
   //\r
   // Attach FvVolBlock Protocol to new handle\r
   //\r
   Status = CoreInstallMultipleProtocolInterfaces (\r
-            &FvbDev->Handle,\r
-            &gEfiFirmwareVolumeBlockProtocolGuid,     &FvbDev->FwVolBlockInstance,\r
-            &gEfiDevicePathProtocolGuid,              &FvbDev->DevicePath,\r
-            &gEfiFirmwareVolumeDispatchProtocolGuid,  NULL,\r
-            NULL\r
-            );\r
+             &FvbDev->Handle,\r
+             &gEfiFirmwareVolumeBlockProtocolGuid,     &FvbDev->FwVolBlockInstance,\r
+             &gEfiDevicePathProtocolGuid,              FvbDev->DevicePath,\r
+             NULL\r
+             );\r
 \r
   //\r
   // If they want the handle back, set it.\r
@@ -508,14 +606,12 @@ ProduceFVBProtocolOnBuffer (
 \r
 \r
 /**\r
-  This routine is the driver initialization entry point.  It initializes the\r
-  libraries, consumes FV hobs and NT_NON_MM_FV environment variable and\r
-  produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate.\r
+  This routine consumes FV hobs and produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate.\r
 \r
-  @param  ImageHandle            The image handle. \r
-  @param  SystemTable            The system table. \r
+  @param  ImageHandle            The image handle.\r
+  @param  SystemTable            The system table.\r
 \r
-  @retval EFI_SUCCESS            Successfully initialized firmware volume block \r
+  @retval EFI_SUCCESS            Successfully initialized firmware volume block\r
                                  driver.\r
 \r
 **/\r
@@ -527,6 +623,7 @@ FwVolBlockDriverInit (
   )\r
 {\r
   EFI_PEI_HOB_POINTERS          FvHob;\r
+\r
   //\r
   // Core Needs Firmware Volumes to function\r
   //\r
@@ -535,9 +632,10 @@ FwVolBlockDriverInit (
     //\r
     // Produce an FVB protocol for it\r
     //\r
-    ProduceFVBProtocolOnBuffer (FvHob.FirmwareVolume->BaseAddress, FvHob.FirmwareVolume->Length, NULL, NULL);    \r
+    ProduceFVBProtocolOnBuffer (FvHob.FirmwareVolume->BaseAddress, FvHob.FirmwareVolume->Length, NULL, 0, NULL);\r
     FvHob.Raw = GET_NEXT_HOB (FvHob);\r
   }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -548,22 +646,27 @@ FwVolBlockDriverInit (
   particular, it can be called by BDS to process a single firmware\r
   volume found in a capsule.\r
 \r
-  @param  FvHeader               pointer to a firmware volume header \r
-  @param  Size                   the size of the buffer pointed to by FvHeader \r
-  @param  FVProtocolHandle       the handle on which a firmware volume protocol \r
-                                 was produced for the firmware volume passed in. \r
+  Caution: The caller need validate the input firmware volume to follow\r
+  PI specification.\r
+  DxeCore will trust the input data and process firmware volume directly.\r
+\r
+  @param  FvHeader               pointer to a firmware volume header\r
+  @param  Size                   the size of the buffer pointed to by FvHeader\r
+  @param  FVProtocolHandle       the handle on which a firmware volume protocol\r
+                                 was produced for the firmware volume passed in.\r
 \r
-  @retval EFI_OUT_OF_RESOURCES   if an FVB could not be produced due to lack of  \r
-                                 system resources \r
-  @retval EFI_VOLUME_CORRUPTED   if the volume was corrupted \r
-  @retval EFI_SUCCESS            a firmware volume protocol was produced for the \r
+  @retval EFI_OUT_OF_RESOURCES   if an FVB could not be produced due to lack of\r
+                                 system resources\r
+  @retval EFI_VOLUME_CORRUPTED   if the volume was corrupted\r
+  @retval EFI_SUCCESS            a firmware volume protocol was produced for the\r
                                  firmware volume\r
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 CoreProcessFirmwareVolume (\r
   IN VOID                             *FvHeader,\r
-  IN UINTN                            Size, \r
+  IN UINTN                            Size,\r
   OUT EFI_HANDLE                      *FVProtocolHandle\r
   )\r
 {\r
@@ -571,23 +674,25 @@ CoreProcessFirmwareVolume (
   EFI_STATUS  Status;\r
 \r
   *FVProtocolHandle = NULL;\r
-  Status = ProduceFVBProtocolOnBuffer ( \r
-            (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, \r
-            (UINT64)Size, \r
-            NULL, \r
+  Status = ProduceFVBProtocolOnBuffer (\r
+            (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader,\r
+            (UINT64)Size,\r
+            NULL,\r
+            0,\r
             FVProtocolHandle\r
             );\r
   //\r
   // Since in our implementation we use register-protocol-notify to put a\r
   // FV protocol on the FVB protocol handle, we can't directly verify that\r
   // the FV protocol was produced. Therefore here we will check the handle\r
-  // and make sure an FV protocol is on it. This indicates that all went \r
-  // well. Otherwise we have to assume that the volume was corrupted \r
+  // and make sure an FV protocol is on it. This indicates that all went\r
+  // well. Otherwise we have to assume that the volume was corrupted\r
   // somehow.\r
   //\r
   if (!EFI_ERROR(Status)) {\r
+    ASSERT (*FVProtocolHandle != NULL);\r
     Ptr = NULL;\r
-    Status = CoreHandleProtocol (*FVProtocolHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Ptr);\r
+    Status = CoreHandleProtocol (*FVProtocolHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **) &Ptr);\r
     if (EFI_ERROR(Status) || (Ptr == NULL)) {\r
       return EFI_VOLUME_CORRUPTED;\r
     }\r