]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Enhance DXE dispatcher logic to check the duplicated FV image bases on FvHob2 and...
authorlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>
Thu, 15 Dec 2011 06:50:54 +0000 (06:50 +0000)
committerlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>
Thu, 15 Dec 2011 06:50:54 +0000 (06:50 +0000)
Signed-off-by: lgao4
Reviewed-by: rsun3
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12874 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Core/Dxe/Dispatcher/Dispatcher.c
MdeModulePkg/Core/Dxe/DxeMain.h
MdeModulePkg/Core/Dxe/FwVol/FwVol.c
MdeModulePkg/Core/Dxe/FwVol/FwVolDriver.h

index 68f5ef5d6463385c9de692a49db72ebf435dbc3d..5f8e383158eb83e6fbb0a115dc723ac1d2095589 100644 (file)
@@ -708,25 +708,102 @@ FvHasBeenProcessed (
 \r
 /**\r
   Remember that Fv protocol on FvHandle has had it's drivers placed on the\r
-  mDiscoveredList. This fucntion adds entries on the mFvHandleList. Items are\r
-  never removed/freed from the mFvHandleList.\r
+  mDiscoveredList. This fucntion adds entries on the mFvHandleList if new \r
+  entry is different from one in mFvHandleList by checking FvImage Guid.\r
+  Items are never removed/freed from the mFvHandleList.\r
 \r
   @param  FvHandle              The handle of a FV that has been processed\r
 \r
+  @return A point to new added FvHandle entry. If FvHandle with the same FvImage guid\r
+          has been added, NULL will return. \r
+\r
 **/\r
-VOID\r
+KNOWN_HANDLE * \r
 FvIsBeingProcesssed (\r
   IN  EFI_HANDLE    FvHandle\r
   )\r
 {\r
-  KNOWN_HANDLE  *KnownHandle;\r
+  EFI_STATUS                            Status;\r
+  EFI_GUID                              FvNameGuid;\r
+  BOOLEAN                               FvNameGuidIsFound;\r
+  UINT32                                ExtHeaderOffset;\r
+  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL    *Fvb;\r
+  EFI_FIRMWARE_VOLUME_HEADER            *FwVolHeader;\r
+  EFI_FV_BLOCK_MAP_ENTRY                *BlockMap;\r
+  UINTN                                 LbaOffset;\r
+  UINTN                                 Index;\r
+  EFI_LBA                               LbaIndex;\r
+  LIST_ENTRY                            *Link;\r
+  KNOWN_HANDLE                          *KnownHandle;\r
 \r
-  KnownHandle = AllocatePool (sizeof (KNOWN_HANDLE));\r
+  //\r
+  // Get the FirmwareVolumeBlock protocol on that handle\r
+  //\r
+  FvNameGuidIsFound = FALSE;\r
+  Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Get the full FV header based on FVB protocol.\r
+    //\r
+    Status = GetFwVolHeader (Fvb, &FwVolHeader);\r
+    if (EFI_ERROR (Status)) {\r
+      FwVolHeader = NULL;\r
+    } else if (VerifyFvHeaderChecksum (FwVolHeader) && FwVolHeader->ExtHeaderOffset != 0) {\r
+      ExtHeaderOffset = (UINT32) FwVolHeader->ExtHeaderOffset;\r
+      BlockMap  = FwVolHeader->BlockMap;\r
+      LbaIndex  = 0;\r
+      LbaOffset = 0;\r
+      //\r
+      // Find LbaIndex and LbaOffset for FV extension header based on BlockMap.\r
+      //\r
+      while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {\r
+        for (Index = 0; Index < BlockMap->NumBlocks && ExtHeaderOffset >= BlockMap->Length; Index ++) {\r
+          ExtHeaderOffset -= BlockMap->Length;\r
+          LbaIndex ++;\r
+        }\r
+        //\r
+        // Check whether FvExtHeader is crossing the multi block range.\r
+        //\r
+        if (Index < BlockMap->NumBlocks) {\r
+          LbaOffset = ExtHeaderOffset;\r
+          break;\r
+        }\r
+        BlockMap++;\r
+      }\r
+      //\r
+      // Read FvNameGuid from FV extension header.\r
+      //\r
+      Status = ReadFvbData (Fvb, &LbaIndex, &LbaOffset, sizeof (FvNameGuid), (UINT8 *) &FvNameGuid);\r
+      if (!EFI_ERROR (Status)) {\r
+        FvNameGuidIsFound = TRUE;\r
+      }\r
+    }\r
+    CoreFreePool (FwVolHeader);\r
+  }\r
+\r
+  if (FvNameGuidIsFound) {\r
+    //\r
+    // Check whether the FV image with the found FvNameGuid has been processed.\r
+    //\r
+    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
+        return NULL;\r
+      }\r
+    }\r
+  }\r
+\r
+  KnownHandle = AllocateZeroPool (sizeof (KNOWN_HANDLE));\r
   ASSERT (KnownHandle != NULL);\r
 \r
   KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE;\r
   KnownHandle->Handle = FvHandle;\r
+  if (FvNameGuidIsFound) {\r
+    CopyGuid (&KnownHandle->FvNameGuid, &FvNameGuid);\r
+  }\r
   InsertTailList (&mFvHandleList, &KnownHandle->Link);\r
+  return KnownHandle;\r
 }\r
 \r
 \r
@@ -844,7 +921,7 @@ CoreAddToDriverList (
   Check if a FV Image type file (EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) is\r
   described by a EFI_HOB_FIRMWARE_VOLUME2 Hob.\r
 \r
-  @param  FvHandle              The handle which FVB protocol installed on.\r
+  @param  FvNameGuid            The FV image guid specified.\r
   @param  DriverName            The driver guid specified.\r
 \r
   @retval TRUE                  This file is found in a EFI_HOB_FIRMWARE_VOLUME2\r
@@ -854,7 +931,7 @@ CoreAddToDriverList (
 **/\r
 BOOLEAN\r
 FvFoundInHobFv2 (\r
-  IN  EFI_HANDLE                      FvHandle,\r
+  IN  CONST EFI_GUID                  *FvNameGuid,\r
   IN  CONST EFI_GUID                  *DriverName\r
   )\r
 {\r
@@ -863,7 +940,11 @@ FvFoundInHobFv2 (
   HobFv2.Raw = GetHobList ();\r
 \r
   while ((HobFv2.Raw = GetNextHob (EFI_HOB_TYPE_FV2, HobFv2.Raw)) != NULL) {\r
-    if (CompareGuid (DriverName, &HobFv2.FirmwareVolume2->FileName)) {\r
+    //\r
+    // Compare parent FvNameGuid and FileGuid both.\r
+    //\r
+    if (CompareGuid (DriverName, &HobFv2.FirmwareVolume2->FileName) &&\r
+        CompareGuid (FvNameGuid, &HobFv2.FirmwareVolume2->FvName)) {\r
       return TRUE;\r
     }\r
     HobFv2.Raw = GET_NEXT_HOB (HobFv2);\r
@@ -1021,6 +1102,7 @@ CoreFwVolEventProtocolNotify (
   UINT32                        AuthenticationStatus;\r
   UINTN                         SizeOfBuffer;\r
   VOID                          *DepexBuffer;\r
+  KNOWN_HANDLE                  *KnownHandle;\r
 \r
   while (TRUE) {\r
     BufferSize = sizeof (EFI_HANDLE);\r
@@ -1048,7 +1130,14 @@ CoreFwVolEventProtocolNotify (
     //\r
     // Since we are about to process this Fv mark it as processed.\r
     //\r
-    FvIsBeingProcesssed (FvHandle);\r
+    KnownHandle = FvIsBeingProcesssed (FvHandle);\r
+    if (KnownHandle == NULL) {\r
+      //\r
+      // The FV with the same FV name guid has already been processed. \r
+      // So lets skip it!\r
+      //\r
+      continue;\r
+    }\r
 \r
     Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);\r
     if (EFI_ERROR (Status) || Fv == NULL) {\r
@@ -1131,7 +1220,7 @@ CoreFwVolEventProtocolNotify (
             // Check if this EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE file has already\r
             // been extracted.\r
             //\r
-            if (FvFoundInHobFv2 (FvHandle, &NameGuid)) {\r
+            if (FvFoundInHobFv2 (&KnownHandle->FvNameGuid, &NameGuid)) {\r
               continue;\r
             }\r
 \r
index 8cdfe0605432a879e3b30aebf2558a6468cbd65a..cf65c1526b642158b0c1882d8f4d42698a6611fd 100644 (file)
@@ -134,6 +134,7 @@ typedef struct {
   UINTN           Signature;\r
   LIST_ENTRY      Link;         // mFvHandleList\r
   EFI_HANDLE      Handle;\r
+  EFI_GUID        FvNameGuid;\r
 } KNOWN_HANDLE;\r
 \r
 \r
@@ -2489,4 +2490,64 @@ CoreEmptyCallbackFunction (
   IN VOID                     *Context\r
   );\r
 \r
+/**\r
+  Read data from Firmware Block by FVB protocol Read. \r
+  The data may cross the multi block ranges.\r
+\r
+  @param  Fvb                   The FW_VOL_BLOCK_PROTOCOL instance from which to read data.\r
+  @param  StartLba              Pointer to StartLba.\r
+                                On input, the start logical block index from which to read.\r
+                                On output,the end logical block index after reading.\r
+  @param  Offset                Pointer to Offset\r
+                                On input, offset into the block at which to begin reading.\r
+                                On output, offset into the end block after reading.\r
+  @param  DataSize              Size of data to be read.\r
+  @param  Data                  Pointer to Buffer that the data will be read into.\r
+\r
+  @retval EFI_SUCCESS           Successfully read data from firmware block.\r
+  @retval others\r
+**/\r
+EFI_STATUS\r
+ReadFvbData (\r
+  IN     EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *Fvb,\r
+  IN OUT EFI_LBA                                *StartLba,\r
+  IN OUT UINTN                                  *Offset,\r
+  IN     UINTN                                  DataSize,\r
+  OUT    UINT8                                  *Data\r
+  );\r
+\r
+/**\r
+  Given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and\r
+  copy the real length volume header into it.\r
+\r
+  @param  Fvb                   The FW_VOL_BLOCK_PROTOCOL instance from which to\r
+                                read the volume header\r
+  @param  FwVolHeader           Pointer to pointer to allocated buffer in which\r
+                                the volume header is returned.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES  No enough buffer could be allocated.\r
+  @retval EFI_SUCCESS           Successfully read volume header to the allocated\r
+                                buffer.\r
+\r
+**/\r
+EFI_STATUS\r
+GetFwVolHeader (\r
+  IN     EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL     *Fvb,\r
+  OUT    EFI_FIRMWARE_VOLUME_HEADER             **FwVolHeader\r
+  );\r
+\r
+/**\r
+  Verify checksum of the firmware volume header.\r
+\r
+  @param  FvHeader       Points to the firmware volume header to be checked\r
+\r
+  @retval TRUE           Checksum verification passed\r
+  @retval FALSE          Checksum verification failed\r
+\r
+**/\r
+BOOLEAN\r
+VerifyFvHeaderChecksum (\r
+  IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader\r
+  );\r
+\r
 #endif\r
index 1e1cbae368f1817553a56d3e409213ab6f0656c8..07cbbb94df56f33ff5b7b861b987e03dcb8a3cc2 100644 (file)
@@ -357,7 +357,7 @@ FvCheck (
       //\r
       // Check whether FvHeader is crossing the multi block range.\r
       //\r
-      if (HeaderSize > BlockMap->Length) {\r
+      if (Index >= BlockMap->NumBlocks) {\r
         BlockMap++;\r
         continue;\r
       } else if (HeaderSize > 0) {\r
index 7cc775f69b664ba4aabd146ca573fa960d7c7b82..a614b93d1bd9f87b55d48d1390c8d1e15620db94 100644 (file)
@@ -366,22 +366,6 @@ SetFileState (
   IN EFI_FFS_FILE_HEADER  *FfsHeader\r
   );\r
 \r
-\r
-/**\r
-  Verify checksum of the firmware volume header.\r
-\r
-  @param  FvHeader       Points to the firmware volume header to be checked\r
-\r
-  @retval TRUE           Checksum verification passed\r
-  @retval FALSE          Checksum verification failed\r
-\r
-**/\r
-BOOLEAN\r
-VerifyFvHeaderChecksum (\r
-  IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader\r
-  );\r
-\r
-\r
 /**\r
   Check if it's a valid FFS file header.\r
 \r