]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/FwVol/FwVol.c
MdeModulePkg DxeCore: Don't cache memory mapped IO FV.
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / FwVol / FwVol.c
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
-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
@@ -46,8 +46,9 @@ FV_DEVICE mFvDevice = {
   NULL,\r
   { NULL, NULL },\r
   0,\r
+  0,\r
   FALSE,\r
-  0\r
+  FALSE\r
 };\r
 \r
 \r
@@ -254,7 +255,14 @@ FreeFvDeviceResource (
       //\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
@@ -262,11 +270,12 @@ FreeFvDeviceResource (
     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
@@ -310,7 +319,7 @@ FvCheck (
   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
@@ -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
-  FvDevice->CachedFv = AllocatePool (Size);\r
+  if ((FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) {\r
+    FvDevice->IsMemoryMapped = TRUE;\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
@@ -336,69 +360,71 @@ FvCheck (
   //\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
-    // 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
-    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
+        // 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
-      // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->Length\r
+      // read the FV data  \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
-      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
-      // 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
-    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