]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTest.c
MdeModulePkg/NullMemoryTest: Fix bug in CompatibleRangeTest
[mirror_edk2.git] / MdeModulePkg / Universal / MemoryTest / NullMemoryTestDxe / NullMemoryTest.c
index 9c9849c776b799448e9fe93b8db4e92dff9debf8..a9bd1015013104d99e63d9f609452f6fe67e4bba 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Implementation of Generic Memory Test Protocol which does not perform real memory test.\r
 \r
-Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2006 - 2018, 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
@@ -58,6 +58,41 @@ GenericMemoryTestEntryPoint (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Convert the memory range to tested.\r
+\r
+  @param BaseAddress  Base address of the memory range.\r
+  @param Length       Length of the memory range.\r
+  @param Capabilities Capabilities of the memory range.\r
+\r
+  @retval EFI_SUCCESS The memory range is converted to tested.\r
+  @retval others      Error happens.\r
+**/\r
+EFI_STATUS\r
+ConvertToTestedMemory (\r
+  IN UINT64           BaseAddress,\r
+  IN UINT64           Length,\r
+  IN UINT64           Capabilities\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  Status = gDS->RemoveMemorySpace (\r
+                  BaseAddress,\r
+                  Length\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gDS->AddMemorySpace (\r
+                    ((Capabilities & EFI_MEMORY_MORE_RELIABLE) == EFI_MEMORY_MORE_RELIABLE) ?\r
+                    EfiGcdMemoryTypeMoreReliable : EfiGcdMemoryTypeSystemMemory,\r
+                    BaseAddress,\r
+                    Length,\r
+                    Capabilities &~\r
+                    (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME)\r
+                    );\r
+  }\r
+  return Status;\r
+}\r
+\r
 /**\r
   Initialize the generic memory test.\r
 \r
@@ -83,6 +118,7 @@ InitializeMemoryTest (
   OUT BOOLEAN                                  *RequireSoftECCInit\r
   )\r
 {\r
+  EFI_STATUS                      Status;\r
   UINTN                           NumberOfDescriptors;\r
   EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
   UINTN                           Index;\r
@@ -96,22 +132,16 @@ InitializeMemoryTest (
       //\r
       // For those reserved memory that have not been tested, simply promote to system memory.\r
       //\r
-      gDS->RemoveMemorySpace (\r
-            MemorySpaceMap[Index].BaseAddress,\r
-            MemorySpaceMap[Index].Length\r
-            );\r
-\r
-      gDS->AddMemorySpace (\r
-            EfiGcdMemoryTypeSystemMemory,\r
-            MemorySpaceMap[Index].BaseAddress,\r
-            MemorySpaceMap[Index].Length,\r
-            MemorySpaceMap[Index].Capabilities &~\r
-            (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME)\r
-            );\r
-\r
+      Status = ConvertToTestedMemory (\r
+                 MemorySpaceMap[Index].BaseAddress,\r
+                 MemorySpaceMap[Index].Length,\r
+                 MemorySpaceMap[Index].Capabilities\r
+                 );\r
+      ASSERT_EFI_ERROR (Status);\r
       mTestedSystemMemory += MemorySpaceMap[Index].Length;\r
       mTotalSystemMemory += MemorySpaceMap[Index].Length;\r
-    } else if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {\r
+    } else if ((MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) ||\r
+               (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMoreReliable)) {\r
       mTotalSystemMemory += MemorySpaceMap[Index].Length;\r
     }\r
   }\r
@@ -204,22 +234,57 @@ EFI_STATUS
 EFIAPI\r
 GenCompatibleRangeTest (\r
   IN EFI_GENERIC_MEMORY_TEST_PROTOCOL          *This,\r
-  IN  EFI_PHYSICAL_ADDRESS                     StartAddress,\r
-  IN  UINT64                                   Length\r
+  IN EFI_PHYSICAL_ADDRESS                      StartAddress,\r
+  IN UINT64                                    Length\r
   )\r
 {\r
+  EFI_STATUS                      Status;\r
   EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
+  EFI_PHYSICAL_ADDRESS            CurrentBase;\r
+  UINT64                          CurrentLength;\r
+\r
+  //\r
+  // Check if the parameter is below 16MB\r
+  //\r
+  if (StartAddress + Length > SIZE_16MB) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  CurrentBase = StartAddress;\r
+  do {\r
+    //\r
+    // Check the required memory range status; if the required memory range span\r
+    // the different GCD memory descriptor, it may be cause different action.\r
+    //\r
+    Status = gDS->GetMemorySpaceDescriptor (\r
+                    CurrentBase,\r
+                    &Descriptor\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
 \r
-  gDS->GetMemorySpaceDescriptor (StartAddress, &Descriptor);\r
-\r
-  gDS->RemoveMemorySpace (StartAddress, Length);\r
-\r
-  gDS->AddMemorySpace (\r
-        EfiGcdMemoryTypeSystemMemory,\r
-        StartAddress,\r
-        Length,\r
-        Descriptor.Capabilities &~(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME)\r
-        );\r
-\r
+    if (Descriptor.GcdMemoryType == EfiGcdMemoryTypeReserved &&\r
+        (Descriptor.Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==\r
+          (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)\r
+          ) {\r
+      CurrentLength = Descriptor.BaseAddress + Descriptor.Length - CurrentBase;\r
+      if (CurrentBase + CurrentLength > StartAddress + Length) {\r
+        CurrentLength = StartAddress + Length - CurrentBase;\r
+      }\r
+      Status = ConvertToTestedMemory (\r
+                 CurrentBase,\r
+                 CurrentLength,\r
+                 Descriptor.Capabilities\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+    }\r
+    CurrentBase = Descriptor.BaseAddress + Descriptor.Length;\r
+  } while (CurrentBase < StartAddress + Length);\r
+  //\r
+  // Here means the required range already be tested, so just return success.\r
+  //\r
   return EFI_SUCCESS;\r
 }\r
+\r