]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Enhance SmmMemoryAllocationLib Free function implementation to call gSmst or gBS...
authorlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 28 Jul 2010 01:07:43 +0000 (01:07 +0000)
committerlgao4 <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>
Wed, 28 Jul 2010 01:07:43 +0000 (01:07 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10700 6f19259b-4bc3-4df7-8a09-765794883524

MdePkg/Library/SmmMemoryAllocationLib/MemoryAllocationLib.c
MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf

index f8ab33a44ac28536f0d8181e29ac04f0e1832d77..d68c1a1b653077440645f3391a100dc58fa74907 100644 (file)
 \r
 #include <PiSmm.h>\r
 \r
+#include <Protocol/SmmAccess2.h>\r
 #include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/SmmServicesTableLib.h>\r
 #include <Library/BaseMemoryLib.h>\r
 #include <Library/DebugLib.h>\r
 \r
+EFI_SMRAM_DESCRIPTOR  *mSmramRanges;\r
+UINTN                 mSmramRangeCount;\r
+\r
+/**\r
+  The constructor function caches SMRAM ranges that are present in the system.\r
+    \r
+  It will ASSERT() if SMM Access2 Protocol doesn't exist.\r
+  It will ASSERT() if SMRAM ranges can't be got.\r
+  It will ASSERT() if Resource can't be allocated for cache SMRAM range. \r
+  It will always return EFI_SUCCESS.\r
+\r
+  @param  ImageHandle   The firmware allocated handle for the EFI image.\r
+  @param  SystemTable   A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS   The constructor always returns EFI_SUCCESS.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmMemoryAllocationLibConstructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_SMM_ACCESS2_PROTOCOL  *SmmAccess;\r
+  UINTN                     Size;\r
+\r
+  //\r
+  // Locate SMM Access2 Protocol\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiSmmAccess2ProtocolGuid, \r
+                  NULL, \r
+                  (VOID **)&SmmAccess\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Get SMRAM range information\r
+  //\r
+  Size = 0;\r
+  Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);\r
+  ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
+\r
+  mSmramRanges = (EFI_SMRAM_DESCRIPTOR *) AllocatePool (Size);\r
+  ASSERT (mSmramRanges != NULL);\r
+\r
+  Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  If SMM driver exits with an error, it must call this routine \r
+  to free the allocated resource before the exiting.\r
+\r
+  @param[in]  ImageHandle   The firmware allocated handle for the EFI image.\r
+  @param[in]  SystemTable   A pointer to the EFI System Table.\r
+\r
+  @retval     EFI_SUCCESS   The deconstructor always returns EFI_SUCCESS.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+SmmMemoryAllocationLibDestructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  FreePool (mSmramRanges);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Check whether the start address of buffer is within any of the SMRAM ranges.\r
+\r
+  @param[in]  Buffer   The pointer to the buffer to be checked.\r
+\r
+  @retval     TURE     The buffer is in SMRAM ranges.\r
+  @retval     FALSE    The buffer is out of SMRAM ranges.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+BufferInSmram (\r
+  IN VOID *Buffer\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; Index < mSmramRangeCount; Index ++) {\r
+    if (((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer >= mSmramRanges[Index].CpuStart) && \r
+        ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer < (mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize))) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Allocates one or more 4KB pages of a certain memory type.\r
 \r
@@ -156,7 +261,19 @@ FreePages (
   EFI_STATUS  Status;\r
 \r
   ASSERT (Pages != 0);\r
-  Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
+  if (BufferInSmram (Buffer)) {\r
+    //\r
+    // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service.\r
+    // So, gSmst->SmmFreePages() service is used to free it.\r
+    //\r
+    Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
+  } else {\r
+    //\r
+    // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service.\r
+    // So, gBS->FreePages() service is used to free it.\r
+    //\r
+    Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
+  }\r
   ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
@@ -357,7 +474,19 @@ FreeAlignedPages (
   EFI_STATUS  Status;\r
 \r
   ASSERT (Pages != 0);\r
-  Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
+  if (BufferInSmram (Buffer)) {\r
+    //\r
+    // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePages() service.\r
+    // So, gSmst->SmmFreePages() service is used to free it.\r
+    //\r
+    Status = gSmst->SmmFreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
+  } else {\r
+    //\r
+    // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePages() service.\r
+    // So, gBS->FreePages() service is used to free it.\r
+    //\r
+    Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages);\r
+  }\r
   ASSERT_EFI_ERROR (Status);\r
 }\r
 \r
@@ -831,6 +960,18 @@ FreePool (
 {\r
   EFI_STATUS    Status;\r
 \r
-  Status = gSmst->SmmFreePool (Buffer);\r
+  if (BufferInSmram (Buffer)) {\r
+    //\r
+    // When Buffer is in SMRAM range, it should be allocated by gSmst->SmmAllocatePool() service.\r
+    // So, gSmst->SmmFreePool() service is used to free it.\r
+    //\r
+    Status = gSmst->SmmFreePool (Buffer);\r
+  } else {\r
+    //\r
+    // When Buffer is out of SMRAM range, it should be allocated by gBS->AllocatePool() service.\r
+    // So, gBS->FreePool() service is used to free it.\r
+    //\r
+    Status = gBS->FreePool (Buffer);\r
+  }\r
   ASSERT_EFI_ERROR (Status);\r
 }\r
index 8413da0932d7112996243035406b8e0cc57121e2..f6c11d2e4fc927f120c7eb4a8a5a19807bf78827 100644 (file)
@@ -22,6 +22,8 @@
   VERSION_STRING                 = 1.0\r
   PI_SPECIFICATION_VERSION       = 0x0001000A\r
   LIBRARY_CLASS                  = MemoryAllocationLib|DXE_SMM_DRIVER \r
+  CONSTRUCTOR                    = SmmMemoryAllocationLibConstructor\r
+  DESTRUCTOR                     = SmmMemoryAllocationLibDestructor\r
 \r
 #\r
 #  VALID_ARCHITECTURES           = IA32 X64\r
   DebugLib\r
   BaseMemoryLib\r
   SmmServicesTableLib\r
+  UefiBootServicesTableLib\r
+\r
+[Protocols]\r
+  gEfiSmmAccess2ProtocolGuid    ## CONSUMES  \r
+\r
+[Depex]\r
+  gEfiSmmAccess2ProtocolGuid\r