]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c
MdeModulePkg DxeCore: Fix issue to print GUID value %g without pointer
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / FwVolBlock / FwVolBlock.c
index e90a10bfdc1bb3aee228e2b3df9d75812a942ea4..bc7b34140f841547e9458eafb2a787ddb6c8ae80 100644 (file)
@@ -1,51 +1,73 @@
-/*++\r
+/** @file\r
+  Implementations for Firmware Volume Block protocol.\r
 \r
-Copyright (c) 2006, Intel Corporation                                                         \r
-All rights reserved. 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
+  It consumes FV HOBs and creates read-only Firmare Volume Block protocol\r
+  instances for each of them.\r
 \r
-Module Name:\r
+Copyright (c) 2006 - 2016, 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
-  FwVolBlock.c\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
-Abstract:\r
+**/\r
 \r
-  Firmware Volume Block protocol..  Consumes FV hobs and creates\r
-  appropriate block protocols.\r
+#include "DxeMain.h"\r
+#include "FwVolBlock.h"\r
 \r
-  Also consumes NT_NON_MM_FV envinronment variable and produces appropriate\r
-  block protocols fro them also... (this is TBD)\r
-\r
---*/\r
-\r
-#include <DxeMain.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_TYPE,\r
-      END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
-      { END_DEVICE_PATH_LENGTH, 0 }      \r
+      END_DEVICE_PATH_LENGTH,\r
+      0\r
+    }\r
+  }\r
+};\r
+\r
+FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = {\r
+  {\r
+    {\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
@@ -54,111 +76,127 @@ 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
+  Retrieves Volume attributes.  No polarity translations are done.\r
 \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
+**/\r
 EFI_STATUS\r
 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
-\r
-Routine Description:\r
-    Retrieves Volume attributes.  No polarity translations are done.\r
-\r
-Arguments:\r
-    This - Calling context\r
-    Attributes - output buffer which contains attributes\r
-\r
-Returns:\r
-    EFI_SUCCESS - The firmware volume attributes were returned.\r
-\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
 \r
 \r
+\r
+/**\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
+\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
 EFI_STATUS\r
 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
-\r
-Routine Description:\r
-  Modifies the current settings of the firmware volume according to the input parameter.\r
-\r
-Arguments:\r
-  This - Calling context\r
-  Attributes - input buffer which contains attributes\r
-\r
-Returns:\r
-  EFI_SUCCESS -  The firmware volume attributes were returned.\r
-  EFI_INVALID_PARAMETER  -  The attributes requested are in conflict with the capabilities as\r
-                             declared in the firmware volume header.\r
-  EFI_UNSUPPORTED        -  Not supported.\r
---*/\r
 {\r
   return EFI_UNSUPPORTED;\r
 }\r
 \r
 \r
+\r
+/**\r
+  The EraseBlock() function erases one or more blocks as denoted by the\r
+  variable argument list. The entire parameter list of blocks must be verified\r
+  prior to erasing any blocks.  If a block is requested that does not exist\r
+  within the associated firmware volume (it has a larger index than the last\r
+  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
+  @retval EFI_UNSUPPORTED        Not supported.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 FwVolBlockEraseBlock (\r
   IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    *This,\r
   ...\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-  The EraseBlock() function erases one or more blocks as denoted by the \r
-variable argument list. The entire parameter list of blocks must be verified\r
-prior to erasing any blocks.  If a block is requested that does not exist \r
-within the associated firmware volume (it has a larger index than the last \r
-block of the firmware volume), the EraseBlock() function must return\r
-EFI_INVALID_PARAMETER without modifying the contents of the firmware volume.\r
-\r
-Arguments:\r
-  This - Calling context\r
-  ...  - Starting LBA followed by Number of Lba to erase. a -1 to terminate\r
-           the list.\r
-    \r
-Returns:\r
-  EFI_SUCCESS   -  The erase request was successfully completed.\r
-  EFI_ACCESS_DENIED   -  The firmware volume is in the WriteDisabled state.\r
-  EFI_DEVICE_ERROR    -  The block device is not functioning correctly and could not be\r
-                         written. The firmware device may have been partially erased.\r
-  EFI_INVALID_PARAMETER  -  One or more of the LBAs listed in the variable argument list do\r
-  EFI_UNSUPPORTED        -  Not supported.\r
-    \r
---*/\r
 {\r
   return EFI_UNSUPPORTED;\r
 }\r
 \r
 \r
+\r
+/**\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
+                                 be read.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 FwVolBlockReadBlock (\r
@@ -168,27 +206,6 @@ FwVolBlockReadBlock (
   IN OUT    UINTN                                *NumBytes,\r
   IN OUT    UINT8                                *Buffer\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-  Read the specified number of bytes from the block to the input buffer.\r
-\r
-Arguments:\r
-  This          -  Indicates the calling context.\r
-  Lba           -  The starting logical block index to read.\r
-  Offset        -  Offset into the block at which to begin reading.\r
-  NumBytes      -  Pointer to a UINT32. At entry, *NumBytes contains the\r
-                   total size of the buffer. At exit, *NumBytes contains the\r
-                   total number of bytes actually read.\r
-  Buffer        -  Pinter to a caller-allocated buffer that contains the destine\r
-                   for the read.    \r
-\r
-Returns:      \r
-  EFI_SUCCESS  -  The firmware volume was read successfully.\r
-  EFI_BAD_BUFFER_SIZE -  The read was attempted across an LBA boundary.\r
-  EFI_ACCESS_DENIED  -  Access denied.\r
-  EFI_DEVICE_ERROR   -  The block device is malfunctioning and could not be read.\r
---*/\r
 {\r
   EFI_FW_VOL_BLOCK_DEVICE               *FvbDevice;\r
   EFI_FIRMWARE_VOLUME_HEADER            *FwVolHeader;\r
@@ -196,17 +213,17 @@ Returns:
   UINTN                                 LbaStart;\r
   UINTN                                 NumOfBytesRead;\r
   UINTN                                 LbaIndex;\r
-  \r
+\r
   FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
 \r
   //\r
   // Check if This FW can be read\r
   //\r
-  if ((FvbDevice->FvbAttributes & EFI_FVB_READ_STATUS) == 0) {\r
+  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
@@ -214,41 +231,66 @@ Returns:
     *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
+  @retval EFI_UNSUPPORTED        Not supported.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 FwVolBlockWriteBlock (\r
@@ -258,67 +300,60 @@ FwVolBlockWriteBlock (
   IN OUT UINTN                                *NumBytes,\r
   IN     UINT8                                *Buffer\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-  Writes the specified number of bytes from the input buffer to the block.\r
-\r
-Arguments:\r
-  This          -  Indicates the calling context.\r
-  Lba           -  The starting logical block index to write to.\r
-  Offset        -  Offset into the block at which to begin writing.\r
-  NumBytes      -  Pointer to a UINT32. At entry, *NumBytes contains the\r
-                   total size of the buffer. At exit, *NumBytes contains the\r
-                   total number of bytes actually written.\r
-  Buffer        -  Pinter to a caller-allocated buffer that contains the source\r
-                   for the write.    \r
-\r
-Returns:     \r
-  EFI_SUCCESS  -  The firmware volume was written successfully.\r
-  EFI_BAD_BUFFER_SIZE -  The write was attempted across an LBA boundary. On output,\r
-                         NumBytes contains the total number of bytes actually written.\r
-  EFI_ACCESS_DENIED  -  The firmware volume is in the WriteDisabled state.\r
-  EFI_DEVICE_ERROR   -  The block device is malfunctioning and could not be written.\r
-  EFI_UNSUPPORTED    -  Not supported.\r
---*/\r
 {\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
+\r
+  @retval EFI_SUCCESS            Successfully got Fvb's base address.\r
+  @retval EFI_UNSUPPORTED        Not supported.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 FwVolBlockGetPhysicalAddress (\r
   IN CONST  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *This,\r
   OUT       EFI_PHYSICAL_ADDRESS                *Address\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-  Get Fvb's base address.\r
-\r
-Arguments:\r
-  This          -  Indicates the calling context.\r
-  Address       -  Fvb device base address.\r
-\r
-Returns:     \r
-  EFI_SUCCESS  -  Successfully got Fvb's base address.\r
-  EFI_UNSUPPORTED -  Not supported.\r
---*/\r
 {\r
   EFI_FW_VOL_BLOCK_DEVICE               *FvbDevice;\r
-  \r
+\r
   FvbDevice = FVB_DEVICE_FROM_THIS (This);\r
-  \r
-  if (FvbDevice->FvbAttributes & EFI_FVB_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
 \r
+\r
+/**\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
+  @retval EFI_INVALID_PARAMETER  The requested LBA is out of range.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 FwVolBlockGetBlockSize (\r
@@ -327,42 +362,25 @@ FwVolBlockGetBlockSize (
   IN OUT    UINTN                               *BlockSize,\r
   IN OUT    UINTN                               *NumberOfBlocks\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-  Retrieves the size in bytes of a specific block within a firmware volume.\r
-\r
-Arguments:\r
-  This            -  Indicates the calling context.\r
-  Lba             -  Indicates the block for which to return the size.\r
-  BlockSize       -  Pointer to a caller-allocated UINTN in which the size of the\r
-                     block is returned.\r
-  NumberOfBlocks  -  Pointer to a caller-allocated UINTN in which the number of\r
-                     consecutive blocks starting with Lba is returned. All blocks\r
-                     in this range have a size of BlockSize.   \r
-Returns:\r
-  EFI_SUCCESS  -  The firmware volume base address is returned.\r
-  EFI_INVALID_PARAMETER  -  The requested LBA is out of range.\r
---*/\r
 {\r
   UINTN                                 TotalBlocks;\r
   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
@@ -375,44 +393,69 @@ Returns:
       //\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 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
 EFI_STATUS\r
 ProduceFVBProtocolOnBuffer (\r
   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
-\r
-Routine Description:\r
-    This routine produces a firmware volume block protocol on a given\r
-    buffer. \r
-\r
-Arguments:\r
-    BaseAddress     - base address of the firmware volume image\r
-    Length          - length of the firmware volume image\r
-    ParentHandle    - handle of parent firmware volume, if this\r
-                      image came from an FV image file in another\r
-                      firmware volume (ala capsules)\r
-    FvProtocol      - Firmware volume block protocol produced.\r
-    \r
-Returns:\r
-    EFI_VOLUME_CORRUPTED    - Volume corrupted.\r
-    EFI_OUT_OF_RESOURCES    - No enough buffer to be allocated.\r
-    EFI_SUCCESS             - Successfully produced a FVB protocol on given buffer.\r
-                     \r
---*/\r
 {\r
   EFI_STATUS                    Status;\r
   EFI_FW_VOL_BLOCK_DEVICE       *FvbDev;\r
@@ -420,19 +463,53 @@ Returns:
   UINTN                         BlockIndex;\r
   UINTN                         BlockIndex2;\r
   UINTN                         LinearOffset;\r
+  UINT32                        FvAlignment;\r
   EFI_FV_BLOCK_MAP_ENTRY        *PtrBlockMapEntry;\r
 \r
-  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;\r
+  FvAlignment = 0;\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
+  // 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
+  if ((FwVolHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) {\r
+    //\r
+    // Get FvHeader alignment\r
+    //\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
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "Unaligned FvImage found at 0x%lx:0x%lx, the required alignment is 0x%x\n",\r
+        BaseAddress,\r
+        Length,\r
+        FvAlignment\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
@@ -440,6 +517,9 @@ Returns:
   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
@@ -447,25 +527,31 @@ Returns:
   //\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
@@ -475,22 +561,44 @@ Returns:
   }\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
@@ -503,26 +611,26 @@ Returns:
 }\r
 \r
 \r
+\r
+/**\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
+\r
+  @retval EFI_SUCCESS            Successfully initialized firmware volume block\r
+                                 driver.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 FwVolBlockDriverInit (\r
   IN EFI_HANDLE                 ImageHandle,\r
   IN EFI_SYSTEM_TABLE           *SystemTable\r
   )\r
-/*++\r
-\r
-Routine Description:\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
-Arguments:\r
-    ImageHandle   - The image handle.\r
-    SystemTable   - The system table.\r
-Returns:\r
-    EFI_SUCCESS   - Successfully initialized firmware volume block driver.\r
---*/\r
 {\r
   EFI_PEI_HOB_POINTERS          FvHob;\r
+\r
   //\r
   // Core Needs Firmware Volumes to function\r
   //\r
@@ -531,62 +639,67 @@ Returns:
     //\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
 \r
+\r
+/**\r
+  This DXE service routine is used to process a firmware volume. In\r
+  particular, it can be called by BDS to process a single firmware\r
+  volume found in a capsule.\r
+\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
+                                 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
-\r
-Routine Description:\r
-    This DXE service routine is used to process a firmware volume. In\r
-    particular, it can be called by BDS to process a single firmware\r
-    volume found in a capsule. \r
-\r
-Arguments:\r
-    FvHeader              - pointer to a firmware volume header\r
-    Size                  - the size of the buffer pointed to by FvHeader\r
-    FVProtocolHandle      - the handle on which a firmware volume protocol\r
-                            was produced for the firmware volume passed in.\r
-\r
-Returns:\r
-    EFI_OUT_OF_RESOURCES  - if an FVB could not be produced due to lack of \r
-                            system resources\r
-    EFI_VOLUME_CORRUPTED  - if the volume was corrupted\r
-    EFI_SUCCESS           - a firmware volume protocol was produced for the\r
-                            firmware volume\r
-\r
---*/\r
 {\r
   VOID        *Ptr;\r
   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
@@ -596,3 +709,4 @@ Returns:
 }\r
 \r
 \r
+\r