]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg DxeCore: Don't cache memory mapped IO FV.
authorStar Zeng <star.zeng@intel.com>
Wed, 27 Aug 2014 08:31:44 +0000 (08:31 +0000)
committerlzeng14 <lzeng14@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 27 Aug 2014 08:31:44 +0000 (08:31 +0000)
Previous DxeCore FwVol code will cache whole FvMain FV from flash that may be
uncached if platform reports FvMain FVB, it will impact DXE performance.

The code already has file level cache, so don’t need to cache memory mapped IO FV.
It can also reduce memory consumption of caching memory mapped IO FVs.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Star Zeng <star.zeng@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15916 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Core/Dxe/DxeMain.h
MdeModulePkg/Core/Dxe/FwVol/FwVol.c
MdeModulePkg/Core/Dxe/FwVol/FwVolDriver.h
MdeModulePkg/Core/Dxe/FwVol/FwVolRead.c
MdeModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c

index 3b2b11d2760f456bfecd93a9a5f8c289b522611e..f4db06d43e9a3f34aa21e7cbbef3cea613d70992 100644 (file)
@@ -2,7 +2,7 @@
   The internal header file includes the common header files, defines\r
   internal structure and functions used by DxeCore module.\r
 \r
   The internal header file includes the common header files, defines\r
   internal structure and functions used by DxeCore module.\r
 \r
-Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\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
 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
@@ -2356,6 +2356,8 @@ GetSection (
   SEP member function.  Deletes an existing section stream\r
 \r
   @param  StreamHandleToClose    Indicates the stream to close\r
   SEP member function.  Deletes an existing section stream\r
 \r
   @param  StreamHandleToClose    Indicates the stream to close\r
+  @param  FreeStreamBuffer       TRUE - Need to free stream buffer;\r
+                                 FALSE - No need to free stream buffer.\r
 \r
   @retval EFI_SUCCESS            The section stream is closed sucessfully.\r
   @retval EFI_OUT_OF_RESOURCES   Memory allocation failed.\r
 \r
   @retval EFI_SUCCESS            The section stream is closed sucessfully.\r
   @retval EFI_OUT_OF_RESOURCES   Memory allocation failed.\r
@@ -2366,7 +2368,8 @@ GetSection (
 EFI_STATUS\r
 EFIAPI\r
 CloseSectionStream (\r
 EFI_STATUS\r
 EFIAPI\r
 CloseSectionStream (\r
-  IN  UINTN                                     StreamHandleToClose\r
+  IN  UINTN                                     StreamHandleToClose,\r
+  IN  BOOLEAN                                   FreeStreamBuffer\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
index 9355e52ab068179760e6e19bcbc2ec6b7564cb8e..d3447a57ac2eb3c8486872947896e1646858c1ca 100644 (file)
@@ -3,7 +3,7 @@
   Layers on top of Firmware Block protocol to produce a file abstraction\r
   of FV based files.\r
 \r
   Layers on top of Firmware Block protocol to produce a file abstraction\r
   of FV based files.\r
 \r
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\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
 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
@@ -46,8 +46,9 @@ FV_DEVICE mFvDevice = {
   NULL,\r
   { NULL, NULL },\r
   0,\r
   NULL,\r
   { NULL, NULL },\r
   0,\r
+  0,\r
   FALSE,\r
   FALSE,\r
-  0\r
+  FALSE\r
 };\r
 \r
 \r
 };\r
 \r
 \r
@@ -254,7 +255,14 @@ FreeFvDeviceResource (
       //\r
       // Close stream and free resources from SEP\r
       //\r
       //\r
       // Close stream and free resources from SEP\r
       //\r
-      CloseSectionStream (FfsFileEntry->StreamHandle);\r
+      CloseSectionStream (FfsFileEntry->StreamHandle, FALSE);\r
+    }\r
+\r
+    if (FfsFileEntry->FileCached) {\r
+      //\r
+      // Free the cached file buffer.\r
+      //\r
+      CoreFreePool (FfsFileEntry->FfsHeader);\r
     }\r
 \r
     CoreFreePool (FfsFileEntry);\r
     }\r
 \r
     CoreFreePool (FfsFileEntry);\r
@@ -262,11 +270,12 @@ FreeFvDeviceResource (
     FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry;\r
   }\r
 \r
     FfsFileEntry = (FFS_FILE_LIST_ENTRY *) NextEntry;\r
   }\r
 \r
-\r
-  //\r
-  // Free the cache\r
-  //\r
-  CoreFreePool (FvDevice->CachedFv);\r
+  if (!FvDevice->IsMemoryMapped) {\r
+    //\r
+    // Free the cached FV buffer.\r
+    //\r
+    CoreFreePool (FvDevice->CachedFv);\r
+  }\r
 \r
   //\r
   // Free Volume Header\r
 \r
   //\r
   // Free Volume Header\r
@@ -310,7 +319,7 @@ FvCheck (
   EFI_FFS_FILE_STATE                    FileState;\r
   UINT8                                 *TopFvAddress;\r
   UINTN                                 TestLength;\r
   EFI_FFS_FILE_STATE                    FileState;\r
   UINT8                                 *TopFvAddress;\r
   UINTN                                 TestLength;\r
-\r
+  EFI_PHYSICAL_ADDRESS                  PhysicalAddress;\r
 \r
   Fvb = FvDevice->Fvb;\r
   FwVolHeader = FvDevice->FwVolHeader;\r
 \r
   Fvb = FvDevice->Fvb;\r
   FwVolHeader = FvDevice->FwVolHeader;\r
@@ -325,10 +334,25 @@ FvCheck (
   // the header to check to make sure the volume is valid\r
   //\r
   Size = (UINTN)(FwVolHeader->FvLength - FwVolHeader->HeaderLength);\r
   // the header to check to make sure the volume is valid\r
   //\r
   Size = (UINTN)(FwVolHeader->FvLength - FwVolHeader->HeaderLength);\r
-  FvDevice->CachedFv = AllocatePool (Size);\r
+  if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {\r
+    FvDevice->IsMemoryMapped = TRUE;\r
 \r
 \r
-  if (FvDevice->CachedFv == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+    Status = Fvb->GetPhysicalAddress (Fvb, &PhysicalAddress);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Don't cache memory mapped FV really.\r
+    //\r
+    FvDevice->CachedFv = (UINT8 *) (UINTN) (PhysicalAddress + FwVolHeader->HeaderLength);\r
+  } else {\r
+    FvDevice->IsMemoryMapped = FALSE;\r
+    FvDevice->CachedFv = AllocatePool (Size);\r
+\r
+    if (FvDevice->CachedFv == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
@@ -336,69 +360,71 @@ FvCheck (
   //\r
   FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size;\r
 \r
   //\r
   FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size;\r
 \r
-  //\r
-  // Copy FV minus header into memory using the block map we have all ready\r
-  // read into memory.\r
-  //\r
-  BlockMap = FwVolHeader->BlockMap;\r
-  CacheLocation = FvDevice->CachedFv;\r
-  LbaIndex = 0;\r
-  LbaOffset = 0;\r
-  HeaderSize = FwVolHeader->HeaderLength;\r
-  while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {\r
-    Index = 0;\r
-    Size  = BlockMap->Length;\r
-    if (HeaderSize > 0) {\r
-      //\r
-      // Skip header size\r
-      //\r
-      for (; Index < BlockMap->NumBlocks && HeaderSize >= BlockMap->Length; Index ++) {\r
-        HeaderSize -= BlockMap->Length;\r
-        LbaIndex ++;\r
-      }\r
-\r
-      //\r
-      // Check whether FvHeader is crossing the multi block range.\r
-      //\r
-      if (Index >= BlockMap->NumBlocks) {\r
-        BlockMap++;\r
-        continue;\r
-      } else if (HeaderSize > 0) {\r
-        LbaOffset = HeaderSize;\r
-        Size = BlockMap->Length - HeaderSize;\r
-        HeaderSize = 0;\r
-      }\r
-    }\r
-    \r
+  if (!FvDevice->IsMemoryMapped) {\r
     //\r
     //\r
-    // read the FV data  \r
+    // Copy FV minus header into memory using the block map we have all ready\r
+    // read into memory.\r
     //\r
     //\r
-    for (; Index < BlockMap->NumBlocks; Index ++) {\r
-      Status = Fvb->Read (Fvb,\r
-                      LbaIndex,\r
-                      LbaOffset,\r
-                      &Size,\r
-                      CacheLocation\r
-                      );\r
+    BlockMap = FwVolHeader->BlockMap;\r
+    CacheLocation = FvDevice->CachedFv;\r
+    LbaIndex = 0;\r
+    LbaOffset = 0;\r
+    HeaderSize = FwVolHeader->HeaderLength;\r
+    while ((BlockMap->NumBlocks != 0) || (BlockMap->Length != 0)) {\r
+      Index = 0;\r
+      Size  = BlockMap->Length;\r
+      if (HeaderSize > 0) {\r
+        //\r
+        // Skip header size\r
+        //\r
+        for (; Index < BlockMap->NumBlocks && HeaderSize >= BlockMap->Length; Index ++) {\r
+          HeaderSize -= BlockMap->Length;\r
+          LbaIndex ++;\r
+        }\r
 \r
 \r
+        //\r
+        // Check whether FvHeader is crossing the multi block range.\r
+        //\r
+        if (Index >= BlockMap->NumBlocks) {\r
+          BlockMap++;\r
+          continue;\r
+        } else if (HeaderSize > 0) {\r
+          LbaOffset = HeaderSize;\r
+          Size = BlockMap->Length - HeaderSize;\r
+          HeaderSize = 0;\r
+        }\r
+      }\r
+    \r
       //\r
       //\r
-      // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length\r
+      // read the FV data  \r
       //\r
       //\r
-      if (EFI_ERROR (Status)) {\r
-        goto Done;\r
-      }\r
+      for (; Index < BlockMap->NumBlocks; Index ++) {\r
+        Status = Fvb->Read (Fvb,\r
+                        LbaIndex,\r
+                        LbaOffset,\r
+                        &Size,\r
+                        CacheLocation\r
+                        );\r
 \r
 \r
-      LbaIndex++;\r
-      CacheLocation += Size;\r
+        //\r
+        // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length\r
+        //\r
+        if (EFI_ERROR (Status)) {\r
+          goto Done;\r
+        }\r
 \r
 \r
-      //\r
-      // After we skip Fv Header always read from start of block\r
-      //\r
-      LbaOffset = 0;\r
-      Size  = BlockMap->Length;\r
-    }\r
+        LbaIndex++;\r
+        CacheLocation += Size;\r
 \r
 \r
-    BlockMap++;\r
+        //\r
+        // After we skip Fv Header always read from start of block\r
+        //\r
+        LbaOffset = 0;\r
+        Size  = BlockMap->Length;\r
+      }\r
+\r
+      BlockMap++;\r
+    }\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
index 4986792edd443db8aa26f4117518761da471b1c9..514c6ed211ad3108c3a7a7123306733e8102a94d 100644 (file)
@@ -2,7 +2,7 @@
   Firmware File System protocol. Layers on top of Firmware\r
   Block protocol to produce a file abstraction of FV based files.\r
 \r
   Firmware File System protocol. Layers on top of Firmware\r
   Block protocol to produce a file abstraction of FV based files.\r
 \r
-Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\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
 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
@@ -26,6 +26,7 @@ typedef struct {
   LIST_ENTRY                      Link;\r
   EFI_FFS_FILE_HEADER             *FfsHeader;\r
   UINTN                           StreamHandle;\r
   LIST_ENTRY                      Link;\r
   EFI_FFS_FILE_HEADER             *FfsHeader;\r
   UINTN                           StreamHandle;\r
+  BOOLEAN                         FileCached;\r
 } FFS_FILE_LIST_ENTRY;\r
 \r
 typedef struct {\r
 } FFS_FILE_LIST_ENTRY;\r
 \r
 typedef struct {\r
@@ -42,9 +43,10 @@ typedef struct {
 \r
   LIST_ENTRY                              FfsFileListHeader;\r
 \r
 \r
   LIST_ENTRY                              FfsFileListHeader;\r
 \r
+  UINT32                                  AuthenticationStatus;\r
   UINT8                                   ErasePolarity;\r
   BOOLEAN                                 IsFfs3Fv;\r
   UINT8                                   ErasePolarity;\r
   BOOLEAN                                 IsFfs3Fv;\r
-  UINT32                                  AuthenticationStatus;\r
+  BOOLEAN                                 IsMemoryMapped;\r
 } FV_DEVICE;\r
 \r
 #define FV_DEVICE_FROM_THIS(a) CR(a, FV_DEVICE, Fv, FV2_DEVICE_SIGNATURE)\r
 } FV_DEVICE;\r
 \r
 #define FV_DEVICE_FROM_THIS(a) CR(a, FV_DEVICE, Fv, FV2_DEVICE_SIGNATURE)\r
index f2c0dd5de42e0593211750d299de93d39f17d680..1acac5d8fd79ff30e31f1b937865578e6f8c5f9e 100644 (file)
@@ -280,6 +280,7 @@ FvReadFile (
   UINT8                             *SrcPtr;\r
   EFI_FFS_FILE_HEADER               *FfsHeader;\r
   UINTN                             InputBufferSize;\r
   UINT8                             *SrcPtr;\r
   EFI_FFS_FILE_HEADER               *FfsHeader;\r
   UINTN                             InputBufferSize;\r
+  UINTN                             WholeFileSize;\r
 \r
   if (NameGuid == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
 \r
   if (NameGuid == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -290,7 +291,7 @@ FvReadFile (
 \r
   //\r
   // Keep looking until we find the matching NameGuid.\r
 \r
   //\r
   // Keep looking until we find the matching NameGuid.\r
-  // The Key is really an FfsFileEntry\r
+  // The Key is really a FfsFileEntry\r
   //\r
   FvDevice->LastKey = 0;\r
   do {\r
   //\r
   FvDevice->LastKey = 0;\r
   do {\r
@@ -312,6 +313,26 @@ FvReadFile (
   // Get a pointer to the header\r
   //\r
   FfsHeader = FvDevice->LastKey->FfsHeader;\r
   // Get a pointer to the header\r
   //\r
   FfsHeader = FvDevice->LastKey->FfsHeader;\r
+  if (FvDevice->IsMemoryMapped) {\r
+    //\r
+    // Memory mapped FV has not been cached, so here is to cache by file.\r
+    //\r
+    if (!FvDevice->LastKey->FileCached) {\r
+      //\r
+      // Cache FFS file to memory buffer.\r
+      //\r
+      WholeFileSize = IS_FFS_FILE2 (FfsHeader) ? FFS_FILE2_SIZE (FfsHeader): FFS_FILE_SIZE (FfsHeader);\r
+      FfsHeader = AllocateCopyPool (WholeFileSize, FfsHeader);\r
+      if (FfsHeader == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      //\r
+      // Let FfsHeader in FfsFileEntry point to the cached file buffer.\r
+      //\r
+      FvDevice->LastKey->FfsHeader = FfsHeader;\r
+      FvDevice->LastKey->FileCached = TRUE;\r
+    }\r
+  }\r
 \r
   //\r
   // Remember callers buffer size\r
 \r
   //\r
   // Remember callers buffer size\r
@@ -427,13 +448,12 @@ FvReadFileSection (
   FvDevice = FV_DEVICE_FROM_THIS (This);\r
 \r
   //\r
   FvDevice = FV_DEVICE_FROM_THIS (This);\r
 \r
   //\r
-  // Read the whole file into buffer\r
+  // Read the file\r
   //\r
   //\r
-  FileBuffer = NULL;\r
   Status = FvReadFile (\r
             This,\r
             NameGuid,\r
   Status = FvReadFile (\r
             This,\r
             NameGuid,\r
-            (VOID **)&FileBuffer,\r
+            NULL,\r
             &FileSize,\r
             &FileType,\r
             &FileAttributes,\r
             &FileSize,\r
             &FileType,\r
             &FileAttributes,\r
@@ -447,8 +467,11 @@ FvReadFileSection (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
-  ASSERT (FileBuffer != NULL);\r
-\r
+  if (IS_FFS_FILE2 (FfsEntry->FfsHeader)) {\r
+    FileBuffer = ((UINT8 *) FfsEntry->FfsHeader) + sizeof (EFI_FFS_FILE_HEADER2);\r
+  } else {\r
+    FileBuffer = ((UINT8 *) FfsEntry->FfsHeader) + sizeof (EFI_FFS_FILE_HEADER);\r
+  }\r
   //\r
   // Check to see that the file actually HAS sections before we go any further.\r
   //\r
   //\r
   // Check to see that the file actually HAS sections before we go any further.\r
   //\r
@@ -497,8 +520,6 @@ FvReadFileSection (
   //\r
 \r
 Done:\r
   //\r
 \r
 Done:\r
-  CoreFreePool (FileBuffer);\r
-\r
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
 \r
index 981744c4d33151f1f00009ab20a6cbcc19e02439..3c4f3f58dbc1b8587ffff02e228d155c0d05131b 100644 (file)
@@ -440,7 +440,7 @@ OpenSectionStream (
   return OpenSectionStreamEx (\r
            SectionStreamLength,\r
            SectionStream,\r
   return OpenSectionStreamEx (\r
            SectionStreamLength,\r
            SectionStream,\r
-           TRUE,\r
+           FALSE,\r
            0,\r
            SectionStreamHandle\r
            );\r
            0,\r
            SectionStreamHandle\r
            );\r
@@ -1344,7 +1344,7 @@ FreeChildNode (
     // If it's an encapsulating section, we close the resulting section stream.\r
     // CloseSectionStream will free all memory associated with the stream.\r
     //\r
     // If it's an encapsulating section, we close the resulting section stream.\r
     // CloseSectionStream will free all memory associated with the stream.\r
     //\r
-    CloseSectionStream (ChildNode->EncapsulatedStreamHandle);\r
+    CloseSectionStream (ChildNode->EncapsulatedStreamHandle, TRUE);\r
   }\r
 \r
   if (ChildNode->Event != NULL) {\r
   }\r
 \r
   if (ChildNode->Event != NULL) {\r
@@ -1362,6 +1362,8 @@ FreeChildNode (
   SEP member function.  Deletes an existing section stream\r
 \r
   @param  StreamHandleToClose    Indicates the stream to close\r
   SEP member function.  Deletes an existing section stream\r
 \r
   @param  StreamHandleToClose    Indicates the stream to close\r
+  @param  FreeStreamBuffer       TRUE - Need to free stream buffer;\r
+                                 FALSE - No need to free stream buffer.\r
 \r
   @retval EFI_SUCCESS            The section stream is closed sucessfully.\r
   @retval EFI_OUT_OF_RESOURCES   Memory allocation failed.\r
 \r
   @retval EFI_SUCCESS            The section stream is closed sucessfully.\r
   @retval EFI_OUT_OF_RESOURCES   Memory allocation failed.\r
@@ -1372,7 +1374,8 @@ FreeChildNode (
 EFI_STATUS\r
 EFIAPI\r
 CloseSectionStream (\r
 EFI_STATUS\r
 EFIAPI\r
 CloseSectionStream (\r
-  IN  UINTN                                     StreamHandleToClose\r
+  IN  UINTN                                     StreamHandleToClose,\r
+  IN  BOOLEAN                                   FreeStreamBuffer\r
   )\r
 {\r
   CORE_SECTION_STREAM_NODE                      *StreamNode;\r
   )\r
 {\r
   CORE_SECTION_STREAM_NODE                      *StreamNode;\r
@@ -1397,7 +1400,9 @@ CloseSectionStream (
       ChildNode = CHILD_SECTION_NODE_FROM_LINK (Link);\r
       FreeChildNode (ChildNode);\r
     }\r
       ChildNode = CHILD_SECTION_NODE_FROM_LINK (Link);\r
       FreeChildNode (ChildNode);\r
     }\r
-    CoreFreePool (StreamNode->StreamBuffer);\r
+    if (FreeStreamBuffer) {\r
+      CoreFreePool (StreamNode->StreamBuffer);\r
+    }\r
     CoreFreePool (StreamNode);\r
     Status = EFI_SUCCESS;\r
   } else {\r
     CoreFreePool (StreamNode);\r
     Status = EFI_SUCCESS;\r
   } else {\r