]> 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 61e2d21d09692fe7fdb06bba610e7d83e576eb13..a9bd1015013104d99e63d9f609452f6fe67e4bba 100644 (file)
@@ -1,8 +1,8 @@
 /** @file\r
-  Intall memory test protocol and bypass the real memory test procedure.\r
+  Implementation of Generic Memory Test Protocol which does not perform real memory test.\r
 \r
-Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
-All rights reserved. This program and the accompanying materials\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
 http://opensource.org/licenses/bsd-license.php\r
@@ -15,16 +15,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "NullMemoryTest.h"\r
 \r
-//\r
-// Module global members\r
-//\r
 UINT64                            mTestedSystemMemory = 0;\r
 UINT64                            mTotalSystemMemory  = 0;\r
 EFI_HANDLE                        mGenericMemoryTestHandle;\r
 \r
-//\r
-// Driver entry here\r
-//\r
 EFI_GENERIC_MEMORY_TEST_PROTOCOL  mGenericMemoryTest = {\r
   InitializeMemoryTest,\r
   GenPerformMemoryTest,\r
@@ -32,51 +26,90 @@ EFI_GENERIC_MEMORY_TEST_PROTOCOL  mGenericMemoryTest = {
   GenCompatibleRangeTest\r
 };\r
 \r
+/**\r
+  Entry point of the NULL memory test driver.\r
+  \r
+  This function is the entry point of the NULL memory test driver.\r
+  It simply installs the Generic Memory Test Protocol.\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    Generic Memory Test Protocol is successfully installed.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 GenericMemoryTestEntryPoint (\r
   IN  EFI_HANDLE           ImageHandle,\r
   IN  EFI_SYSTEM_TABLE     *SystemTable\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  The generic memory test driver's entry point, it can initialize private data\r
-  to default value\r
-\r
-Arguments:\r
-\r
-  ImageHandle of the loaded driver\r
-  Pointer to the System Table\r
-\r
-Returns:\r
-\r
-  Status\r
-\r
-  EFI_SUCCESS           - Protocol successfully installed\r
-  EFI_OUT_OF_RESOURCES  - Can not allocate protocol data structure in base\r
-                          memory\r
-\r
---*/\r
 {\r
   EFI_STATUS  Status;\r
 \r
-  //\r
-  // Install the protocol\r
-  //\r
   Status = gBS->InstallProtocolInterface (\r
                   &mGenericMemoryTestHandle,\r
                   &gEfiGenericMemTestProtocolGuid,\r
                   EFI_NATIVE_INTERFACE,\r
                   &mGenericMemoryTest\r
                   );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  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
-// EFI_GENERIC_MEMORY_TEST_PROTOCOL implementation\r
-//\r
+\r
+/**\r
+  Initialize the generic memory test.\r
+\r
+  This function implements EFI_GENERIC_MEMORY_TEST_PROTOCOL.MemoryTestInit.\r
+  It simply promotes untested reserved memory to system memory without real test.\r
+\r
+  @param  This                Protocol instance pointer. \r
+  @param  Level               The coverage level of the memory test. \r
+  @param  RequireSoftECCInit  Indicate if the memory need software ECC init. \r
+\r
+  @retval EFI_SUCCESS         The generic memory test initialized correctly. \r
+  @retval EFI_NO_MEDIA        There is not any non-tested memory found, in this \r
+                              function if not any non-tesed memory found means  \r
+                              that the memory test driver have not detect any \r
+                              non-tested extended memory of current system. \r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 InitializeMemoryTest (\r
@@ -84,16 +117,8 @@ InitializeMemoryTest (
   IN  EXTENDMEM_COVERAGE_LEVEL                 Level,\r
   OUT BOOLEAN                                  *RequireSoftECCInit\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
---*/\r
 {\r
+  EFI_STATUS                      Status;\r
   UINTN                           NumberOfDescriptors;\r
   EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
   UINTN                           Index;\r
@@ -104,22 +129,19 @@ Returns:
         (MemorySpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==\r
           (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)\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
+      //\r
+      // For those reserved memory that have not been tested, simply promote to system memory.\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
@@ -130,6 +152,29 @@ Returns:
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Perform the memory test.\r
+\r
+  This function implements EFI_GENERIC_MEMORY_TEST_PROTOCOL.PerformMemoryTest.\r
+  It simply returns EFI_NOT_FOUND.\r
+\r
+  @param  This                Protocol instance pointer. \r
+  @param  TestedMemorySize    Return the tested extended memory size. \r
+  @param  TotalMemorySize     Return the whole system physical memory size, this  \r
+                              value may be changed if in some case some error  \r
+                              DIMMs be disabled. \r
+  @param  ErrorOut            Any time the memory error occurs, this will be \r
+                              TRUE. \r
+  @param  IfTestAbort         Indicate if the user press "ESC" to skip the memory \r
+                              test. \r
+\r
+  @retval EFI_SUCCESS         One block of memory test ok, the block size is hide \r
+                              internally. \r
+  @retval EFI_NOT_FOUND       Indicate all the non-tested memory blocks have  \r
+                              already go through. \r
+  @retval EFI_DEVICE_ERROR    Mis-compare error, and no agent can handle it\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 GenPerformMemoryTest (\r
@@ -139,15 +184,6 @@ GenPerformMemoryTest (
   OUT BOOLEAN                                  *ErrorOut,\r
   IN BOOLEAN                                   TestAbort\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
---*/\r
 {\r
   *ErrorOut         = FALSE;\r
   *TestedMemorySize = mTestedSystemMemory;\r
@@ -157,53 +193,98 @@ Returns:
 \r
 }\r
 \r
+/**\r
+  The memory test finished.\r
+\r
+  This function implements EFI_GENERIC_MEMORY_TEST_PROTOCOL.Finished.\r
+  It simply returns EFI_SUCCESS.\r
+\r
+  @param  This                Protocol instance pointer. \r
+\r
+  @retval EFI_SUCCESS         Successful free all the generic memory test driver \r
+                              allocated resource and notify to platform memory \r
+                              test driver that memory test finished. \r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 GenMemoryTestFinished (\r
   IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
---*/\r
 {\r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Provide capability to test compatible range which used by some special\r
+  driver required using memory range before BDS perform memory test.\r
+\r
+  This function implements EFI_GENERIC_MEMORY_TEST_PROTOCOL.CompatibleRangeTest.\r
+  It simply sets the memory range to system memory.\r
+\r
+  @param  This                Protocol instance pointer. \r
+  @param  StartAddress        The start address of the memory range. \r
+  @param  Length              The memory range's length. \r
+  \r
+  @retval EFI_SUCCESS           The compatible memory range pass the memory test. \r
+  @retval EFI_INVALID_PARAMETER The compatible memory range must be below 16M.\r
+\r
+**/\r
 EFI_STATUS\r
 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
-\r
-Routine Description:\r
-\r
-Arguments:\r
-\r
-Returns:\r
-\r
---*/\r
 {\r
-  EFI_GCD_MEMORY_SPACE_DESCRIPTOR descriptor;\r
-\r
-  gDS->GetMemorySpaceDescriptor (StartAddress, &descriptor);\r
+  EFI_STATUS                      Status;\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
+  EFI_PHYSICAL_ADDRESS            CurrentBase;\r
+  UINT64                          CurrentLength;\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
+  // 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
+    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