]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg: Add GenericMemoryTestDxe driver
authorjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 1 Jul 2011 00:40:26 +0000 (00:40 +0000)
committerjljusten <jljusten@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 1 Jul 2011 00:40:26 +0000 (00:40 +0000)
Signed-off-by: jljusten
Reviewed-by: mdkinney
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11937 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/MdeModulePkg.dsc
MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/GenericMemoryTestDxe.inf [new file with mode: 0644]
MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.c [new file with mode: 0644]
MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.h [new file with mode: 0644]

index a273c2726349dbff7d71022788c6d33e959e1e6d..8ebab615606bb35811aa06d2341448702d1eb47c 100644 (file)
   MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf\r
   MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf\r
   MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf\r
+  MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/GenericMemoryTestDxe.inf\r
   MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf\r
   MdeModulePkg/Universal/Metronome/Metronome.inf\r
   MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf\r
diff --git a/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/GenericMemoryTestDxe.inf b/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/GenericMemoryTestDxe.inf
new file mode 100644 (file)
index 0000000..5158a8c
--- /dev/null
@@ -0,0 +1,59 @@
+## @file\r
+# Component description file for Generic memory test.\r
+#\r
+# This driver first constructs the non-tested memory range,\r
+# then performs the R/W/V memory test.\r
+#\r
+# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+#\r
+# This program and the accompanying materials are\r
+# 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
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+##\r
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = GenericMemoryTestDxe\r
+  FILE_GUID                      = 9C1080EE-D02E-487f-9432-F3BF086EC180\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+\r
+  ENTRY_POINT                    = GenericMemoryTestEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources]\r
+  LightMemoryTest.h\r
+  LightMemoryTest.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  UefiBootServicesTableLib\r
+  MemoryAllocationLib\r
+  BaseMemoryLib\r
+  BaseLib\r
+  ReportStatusCodeLib\r
+  DxeServicesTableLib\r
+  HobLib\r
+  UefiDriverEntryPoint\r
+  DebugLib\r
+\r
+[Protocols]\r
+  gEfiCpuArchProtocolGuid                       # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiGenericMemTestProtocolGuid                # PROTOCOL ALWAYS_PRODUCED\r
+\r
+[Depex]\r
+  gEfiCpuArchProtocolGuid\r
+\r
diff --git a/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.c b/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.c
new file mode 100644 (file)
index 0000000..6161274
--- /dev/null
@@ -0,0 +1,906 @@
+/** @file\r
+\r
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions\r
+  of the BSD License which accompanies this distribution.  The\r
+  full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "LightMemoryTest.h"\r
+\r
+//\r
+// Global:\r
+// Since this driver will only ever produce one instance of the memory test\r
+// protocol, so we do not need to dynamically allocate the PrivateData.\r
+//\r
+EFI_PHYSICAL_ADDRESS    mCurrentAddress;\r
+LIST_ENTRY          *mCurrentLink;\r
+NONTESTED_MEMORY_RANGE  *mCurrentRange;\r
+UINT64                  mTestedSystemMemory;\r
+UINT64                  mNonTestedSystemMemory;\r
+\r
+UINT32                  GenericMemoryTestMonoPattern[GENERIC_CACHELINE_SIZE / 4] = {\r
+  0x5a5a5a5a,\r
+  0xa5a5a5a5,\r
+  0x5a5a5a5a,\r
+  0xa5a5a5a5,\r
+  0x5a5a5a5a,\r
+  0xa5a5a5a5,\r
+  0x5a5a5a5a,\r
+  0xa5a5a5a5,\r
+  0x5a5a5a5a,\r
+  0xa5a5a5a5,\r
+  0x5a5a5a5a,\r
+  0xa5a5a5a5,\r
+  0x5a5a5a5a,\r
+  0xa5a5a5a5,\r
+  0x5a5a5a5a,\r
+  0xa5a5a5a5\r
+};\r
+\r
+/**\r
+  Compares the contents of two buffers.\r
+\r
+  This function compares Length bytes of SourceBuffer to Length bytes of DestinationBuffer.\r
+  If all Length bytes of the two buffers are identical, then 0 is returned.  Otherwise, the\r
+  value returned is the first mismatched byte in SourceBuffer subtracted from the first\r
+  mismatched byte in DestinationBuffer.\r
+  \r
+  If Length = 0, then ASSERT().\r
+\r
+  @param[in] DestinationBuffer The pointer to the destination buffer to compare.\r
+  @param[in] SourceBuffer      The pointer to the source buffer to compare.\r
+  @param[in] Length            The number of bytes to compare.\r
+\r
+  @return 0                 All Length bytes of the two buffers are identical.\r
+  @retval Non-zero          The first mismatched byte in SourceBuffer subtracted from the first\r
+                            mismatched byte in DestinationBuffer.\r
+                            \r
+**/\r
+INTN\r
+EFIAPI\r
+CompareMemWithoutCheckArgument (\r
+  IN      CONST VOID                *DestinationBuffer,\r
+  IN      CONST VOID                *SourceBuffer,\r
+  IN      UINTN                     Length\r
+  )\r
+{\r
+  ASSERT (Length > 0);\r
+  while ((--Length != 0) &&\r
+         (*(INT8*)DestinationBuffer == *(INT8*)SourceBuffer)) {\r
+    DestinationBuffer = (INT8*)DestinationBuffer + 1;\r
+    SourceBuffer = (INT8*)SourceBuffer + 1;\r
+  }\r
+  return (INTN)*(UINT8*)DestinationBuffer - (INTN)*(UINT8*)SourceBuffer;\r
+}\r
+\r
+/**\r
+  Construct the system base memory range through GCD service.\r
+\r
+  @param[in] Private  Point to generic memory test driver's private data.\r
+\r
+  @retval EFI_SUCCESS          Successful construct the base memory range through GCD service.\r
+  @retval EFI_OUT_OF_RESOURCE  Could not allocate needed resource from base memory.\r
+  @retval Others               Failed to construct base memory range through GCD service.\r
+                            \r
+**/\r
+EFI_STATUS\r
+ConstructBaseMemoryRange (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE  *Private\r
+  )\r
+{\r
+  UINTN                           NumberOfDescriptors;\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
+  UINTN                           Index;\r
+\r
+  //\r
+  // Base memory will always below 4G\r
+  //\r
+  gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
+\r
+  for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
+    if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) {\r
+      Private->BaseMemorySize += MemorySpaceMap[Index].Length;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Destroy the link list base on the correspond link list type.\r
+\r
+  @param[in] Private  Point to generic memory test driver's private data.\r
+                            \r
+**/\r
+VOID\r
+DestroyLinkList (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE  *Private\r
+  )\r
+{\r
+  LIST_ENTRY          *Link;\r
+  NONTESTED_MEMORY_RANGE  *NontestedRange;\r
+\r
+  Link = Private->NonTestedMemRanList.BackLink;\r
+\r
+  while (Link != &Private->NonTestedMemRanList) {\r
+    RemoveEntryList (Link);\r
+    NontestedRange = NONTESTED_MEMORY_RANGE_FROM_LINK (Link);\r
+    gBS->FreePool (NontestedRange);\r
+    Link = Private->NonTestedMemRanList.BackLink;;\r
+  }\r
+}\r
+\r
+/**\r
+  Add the extened memory to whole system memory map.\r
+\r
+  @param[in] Private  Point to generic memory test driver's private data.\r
+\r
+  @retval EFI_SUCCESS Successful add all the extended memory to system memory map.\r
+  @retval Others      Failed to add the tested extended memory.\r
+                            \r
+**/\r
+EFI_STATUS\r
+UpdateMemoryMap (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE  *Private\r
+  )\r
+{\r
+  LIST_ENTRY          *Link;\r
+  NONTESTED_MEMORY_RANGE  *Range;\r
+\r
+  Link = Private->NonTestedMemRanList.ForwardLink;\r
+\r
+  while (Link != &Private->NonTestedMemRanList) {\r
+    Range = NONTESTED_MEMORY_RANGE_FROM_LINK (Link);\r
+\r
+    gDS->RemoveMemorySpace (\r
+          Range->StartAddress,\r
+          Range->Length\r
+          );\r
+\r
+    gDS->AddMemorySpace (\r
+          EfiGcdMemoryTypeSystemMemory,\r
+          Range->StartAddress,\r
+          Range->Length,\r
+          Range->Capabilities &~(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME)\r
+          );\r
+\r
+    Link = Link->ForwardLink;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Test a range of the memory directly .\r
+\r
+  @param[in] Private       Point to generic memory test driver's private data.\r
+  @param[in] StartAddress  Starting address of the memory range to be tested.\r
+  @param[in] Length        Length in bytes of the memory range to be tested.\r
+  @param[in] Capabilities  The bit mask of attributes that the memory range supports.\r
+\r
+  @retval EFI_SUCCESS      Successful test the range of memory.\r
+  @retval Others           Failed to test the range of memory.\r
+                            \r
+**/\r
+EFI_STATUS\r
+DirectRangeTest (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE  *Private,\r
+  IN  EFI_PHYSICAL_ADDRESS         StartAddress,\r
+  IN  UINT64                       Length,\r
+  IN  UINT64                       Capabilities\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Perform a dummy memory test, so directly write the pattern to all range\r
+  //\r
+  WriteMemory (Private, StartAddress, Length);\r
+\r
+  //\r
+  // Verify the memory range\r
+  //\r
+  Status = VerifyMemory (Private, StartAddress, Length);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+  //\r
+  // Add the tested compatible memory to system memory using GCD service\r
+  //\r
+  gDS->RemoveMemorySpace (\r
+        StartAddress,\r
+        Length\r
+        );\r
+\r
+  gDS->AddMemorySpace (\r
+        EfiGcdMemoryTypeSystemMemory,\r
+        StartAddress,\r
+        Length,\r
+        Capabilities &~(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME)\r
+        );\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Construct the system non-tested memory range through GCD service.\r
+\r
+  @param[in] Private  Point to generic memory test driver's private data.\r
+\r
+  @retval EFI_SUCCESS          Successful construct the non-tested memory range through GCD service.\r
+  @retval EFI_OUT_OF_RESOURCE  Could not allocate needed resource from base memory.\r
+  @retval Others               Failed to construct non-tested memory range through GCD service.\r
+                            \r
+**/\r
+EFI_STATUS\r
+ConstructNonTestedMemoryRange (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE  *Private\r
+  )\r
+{\r
+  NONTESTED_MEMORY_RANGE          *Range;\r
+  BOOLEAN                         NoFound;\r
+  UINTN                           NumberOfDescriptors;\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;\r
+  UINTN                           Index;\r
+\r
+  //\r
+  // Non tested memory range may be span 4G here\r
+  //\r
+  NoFound = TRUE;\r
+\r
+  gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);\r
+\r
+  for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
+    if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeReserved &&\r
+        (MemorySpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==\r
+          (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)\r
+          ) {\r
+      NoFound = FALSE;\r
+      //\r
+      // Light version do not need to process >4G memory range\r
+      //\r
+      gBS->AllocatePool (\r
+            EfiBootServicesData,\r
+            sizeof (NONTESTED_MEMORY_RANGE),\r
+            (VOID **) &Range\r
+            );\r
+\r
+      Range->Signature    = EFI_NONTESTED_MEMORY_RANGE_SIGNATURE;\r
+      Range->StartAddress = MemorySpaceMap[Index].BaseAddress;\r
+      Range->Length       = MemorySpaceMap[Index].Length;\r
+      Range->Capabilities = MemorySpaceMap[Index].Capabilities;\r
+\r
+      mNonTestedSystemMemory += MemorySpaceMap[Index].Length;\r
+      InsertTailList (&Private->NonTestedMemRanList, &Range->Link);\r
+    }\r
+  }\r
+\r
+  if (NoFound) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Write the memory test pattern into a range of physical memory.\r
+\r
+  @param[in] Private  Point to generic memory test driver's private data.\r
+  @param[in] Start    The memory range's start address.\r
+  @param[in] Size     The memory range's size.\r
+\r
+  @retval EFI_SUCCESS Successful write the test pattern into the non-tested memory.\r
+  @retval Others      The test pattern may not really write into the physical memory.\r
+                            \r
+**/\r
+EFI_STATUS\r
+WriteMemory (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE  *Private,\r
+  IN  EFI_PHYSICAL_ADDRESS         Start,\r
+  IN  UINT64                       Size\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS  Address;\r
+\r
+  Address = Start;\r
+\r
+  //\r
+  // Add 4G memory address check for IA32 platform\r
+  // NOTE: Without page table, there is no way to use memory above 4G.\r
+  //\r
+  if (Start + Size > MAX_ADDRESS) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  while (Address < (Start + Size)) {\r
+    CopyMem ((VOID *) (UINTN) Address, Private->MonoPattern, Private->MonoTestSize);\r
+    Address += Private->CoverageSpan;\r
+  }\r
+  //\r
+  // bug bug: we may need GCD service to make the code cache and data uncache,\r
+  // if GCD do not support it or return fail, then just flush the whole cache.\r
+  //\r
+  if (Private->Cpu != NULL) {\r
+    Private->Cpu->FlushDataCache (Private->Cpu, Start, Size, EfiCpuFlushTypeWriteBackInvalidate);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Verify the range of physical memory which covered by memory test pattern.\r
+\r
+  This function will also do not return any informatin just cause system reset,\r
+  because the handle error encount fatal error and disable the bad DIMMs.\r
+\r
+  @param[in] Private  Point to generic memory test driver's private data.\r
+  @param[in] Start    The memory range's start address.\r
+  @param[in] Size     The memory range's size.\r
+\r
+  @retval EFI_SUCCESS Successful verify the range of memory, no errors' location found.\r
+  @retval Others      The range of memory have errors contained.\r
+                            \r
+**/\r
+EFI_STATUS\r
+VerifyMemory (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE  *Private,\r
+  IN  EFI_PHYSICAL_ADDRESS         Start,\r
+  IN  UINT64                       Size\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS            Address;\r
+  INTN                            ErrorFound;\r
+  EFI_MEMORY_EXTENDED_ERROR_DATA  *ExtendedErrorData;\r
+\r
+  Address           = Start;\r
+  ExtendedErrorData = NULL;\r
+\r
+  //\r
+  // Add 4G memory address check for IA32 platform\r
+  // NOTE: Without page table, there is no way to use memory above 4G.\r
+  //\r
+  if (Start + Size > MAX_ADDRESS) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Use the software memory test to check whether have detected miscompare\r
+  // error here. If there is miscompare error here then check if generic\r
+  // memory test driver can disable the bad DIMM.\r
+  //\r
+  while (Address < (Start + Size)) {\r
+    ErrorFound = CompareMemWithoutCheckArgument (\r
+                  (VOID *) (UINTN) (Address),\r
+                  Private->MonoPattern,\r
+                  Private->MonoTestSize\r
+                  );\r
+    if (ErrorFound != 0) {\r
+      //\r
+      // Report uncorrectable errors\r
+      //\r
+      ExtendedErrorData = AllocateZeroPool (sizeof (EFI_MEMORY_EXTENDED_ERROR_DATA));\r
+      if (ExtendedErrorData == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+\r
+      ExtendedErrorData->DataHeader.HeaderSize  = (UINT16) sizeof (EFI_STATUS_CODE_DATA);\r
+      ExtendedErrorData->DataHeader.Size        = (UINT16) (sizeof (EFI_MEMORY_EXTENDED_ERROR_DATA) - sizeof (EFI_STATUS_CODE_DATA));\r
+      ExtendedErrorData->Granularity            = EFI_MEMORY_ERROR_DEVICE;\r
+      ExtendedErrorData->Operation              = EFI_MEMORY_OPERATION_READ;\r
+      ExtendedErrorData->Syndrome               = 0x0;\r
+      ExtendedErrorData->Address                = Address;\r
+      ExtendedErrorData->Resolution             = 0x40;\r
+\r
+      REPORT_STATUS_CODE_EX (\r
+          EFI_ERROR_CODE,\r
+          EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_EC_UNCORRECTABLE,\r
+          0,\r
+          &gEfiGenericMemTestProtocolGuid,\r
+          NULL,\r
+          (UINT8 *) ExtendedErrorData + sizeof (EFI_STATUS_CODE_DATA),\r
+          ExtendedErrorData->DataHeader.Size\r
+          ); \r
+\r
+      return EFI_DEVICE_ERROR;\r
+    }\r
+\r
+    Address += Private->CoverageSpan;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Initialize the generic memory test.\r
+\r
+  @param[in]  This                The protocol instance pointer. \r
+  @param[in]  Level               The coverage level of the memory test. \r
+  @param[out] RequireSoftECCInit  Indicate if the memory need software ECC init. \r
+\r
+  @retval EFI_SUCCESS         The generic memory test is initialized correctly. \r
+  @retval EFI_NO_MEDIA        The system had no memory to be tested. \r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeMemoryTest (\r
+  IN EFI_GENERIC_MEMORY_TEST_PROTOCOL          *This,\r
+  IN  EXTENDMEM_COVERAGE_LEVEL                 Level,\r
+  OUT BOOLEAN                                  *RequireSoftECCInit\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  GENERIC_MEMORY_TEST_PRIVATE *Private;\r
+  EFI_CPU_ARCH_PROTOCOL       *Cpu;\r
+\r
+  Private             = GENERIC_MEMORY_TEST_PRIVATE_FROM_THIS (This);\r
+  *RequireSoftECCInit = FALSE;\r
+\r
+  //\r
+  // This is initialize for default value, but some value may be reset base on\r
+  // platform memory test driver.\r
+  //\r
+  Private->CoverLevel   = Level;\r
+  Private->BdsBlockSize = TEST_BLOCK_SIZE;\r
+  Private->MonoPattern  = GenericMemoryTestMonoPattern;\r
+  Private->MonoTestSize = GENERIC_CACHELINE_SIZE;\r
+\r
+  //\r
+  // Initialize several internal link list\r
+  //\r
+  InitializeListHead (&Private->NonTestedMemRanList);\r
+\r
+  //\r
+  // Construct base memory range\r
+  //\r
+  ConstructBaseMemoryRange (Private);\r
+\r
+  //\r
+  // get the cpu arch protocol to support flash cache\r
+  //\r
+  Status = gBS->LocateProtocol (\r
+                  &gEfiCpuArchProtocolGuid,\r
+                  NULL,\r
+                  (VOID **) &Cpu\r
+                  );\r
+  if (!EFI_ERROR (Status)) {\r
+    Private->Cpu = Cpu;\r
+  }\r
+  //\r
+  // Create the CoverageSpan of the memory test base on the coverage level\r
+  //\r
+  switch (Private->CoverLevel) {\r
+  case EXTENSIVE:\r
+    Private->CoverageSpan = GENERIC_CACHELINE_SIZE;\r
+    break;\r
+\r
+  case SPARSE:\r
+    Private->CoverageSpan = SPARSE_SPAN_SIZE;\r
+    break;\r
+\r
+  //\r
+  // Even the BDS do not need to test any memory, but in some case it\r
+  // still need to init ECC memory.\r
+  //\r
+  default:\r
+    Private->CoverageSpan = QUICK_SPAN_SIZE;\r
+    break;\r
+  }\r
+  //\r
+  // This is the first time we construct the non-tested memory range, if no\r
+  // extended memory found, we know the system have not any extended memory\r
+  // need to be test\r
+  //\r
+  Status = ConstructNonTestedMemoryRange (Private);\r
+  if (Status == EFI_NOT_FOUND) {\r
+    return EFI_NO_MEDIA;\r
+  }\r
+  //\r
+  // ready to perform the R/W/V memory test\r
+  //\r
+  mTestedSystemMemory = Private->BaseMemorySize;\r
+  mCurrentLink        = Private->NonTestedMemRanList.ForwardLink;\r
+  mCurrentRange       = NONTESTED_MEMORY_RANGE_FROM_LINK (mCurrentLink);\r
+  mCurrentAddress     = mCurrentRange->StartAddress;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Perform the memory test.\r
+\r
+  @param[in]  This              The protocol instance pointer. \r
+  @param[out] TestedMemorySize  Return the tested extended memory size. \r
+  @param[out] TotalMemorySize   Return the whole system physical memory size. \r
+                                The total memory size does not include memory in a slot with a disabled DIMM.  \r
+  @param[out] ErrorOut          TRUE if the memory error occured.\r
+  @param[in]  IfTestAbort       Indicates that the user pressed "ESC" to skip the memory test. \r
+\r
+  @retval EFI_SUCCESS         One block of memory passed the test.\r
+  @retval EFI_NOT_FOUND       All memory blocks have already been tested.\r
+  @retval EFI_DEVICE_ERROR    Memory device error occured, and no agent can handle it.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GenPerformMemoryTest (\r
+  IN EFI_GENERIC_MEMORY_TEST_PROTOCOL          *This,\r
+  OUT UINT64                                   *TestedMemorySize,\r
+  OUT UINT64                                   *TotalMemorySize,\r
+  OUT BOOLEAN                                  *ErrorOut,\r
+  IN BOOLEAN                                   TestAbort\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  GENERIC_MEMORY_TEST_PRIVATE     *Private;\r
+  EFI_MEMORY_RANGE_EXTENDED_DATA  *RangeData;\r
+  UINT64                          BlockBoundary;\r
+\r
+  Private       = GENERIC_MEMORY_TEST_PRIVATE_FROM_THIS (This);\r
+  *ErrorOut     = FALSE;\r
+  RangeData     = NULL;\r
+  BlockBoundary = 0;\r
+\r
+  //\r
+  // In extensive mode the boundary of "mCurrentRange->Length" may will lost\r
+  // some range that is not Private->BdsBlockSize size boundry, so need\r
+  // the software mechanism to confirm all memory location be covered.\r
+  //\r
+  if (mCurrentAddress < (mCurrentRange->StartAddress + mCurrentRange->Length)) {\r
+    if ((mCurrentAddress + Private->BdsBlockSize) <= (mCurrentRange->StartAddress + mCurrentRange->Length)) {\r
+      BlockBoundary = Private->BdsBlockSize;\r
+    } else {\r
+      BlockBoundary = mCurrentRange->StartAddress + mCurrentRange->Length - mCurrentAddress;\r
+    }\r
+    //\r
+    // If TestAbort is true, means user cancel the memory test\r
+    //\r
+    if (!TestAbort && Private->CoverLevel != IGNORE) {\r
+      //\r
+      // Report status code of every memory range\r
+      //\r
+      RangeData                         = AllocateZeroPool (sizeof (EFI_MEMORY_RANGE_EXTENDED_DATA));\r
+      if (RangeData == NULL) {\r
+        return EFI_OUT_OF_RESOURCES;\r
+      }\r
+      RangeData->DataHeader.HeaderSize  = (UINT16) sizeof (EFI_STATUS_CODE_DATA);\r
+      RangeData->DataHeader.Size        = (UINT16) (sizeof (EFI_MEMORY_RANGE_EXTENDED_DATA) - sizeof (EFI_STATUS_CODE_DATA));\r
+      RangeData->Start                  = mCurrentAddress;\r
+      RangeData->Length                 = BlockBoundary;\r
+\r
+      REPORT_STATUS_CODE_EX (\r
+          EFI_PROGRESS_CODE,\r
+          EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_PC_TEST,\r
+          0,\r
+          &gEfiGenericMemTestProtocolGuid,\r
+          NULL,\r
+          (UINT8 *) RangeData + sizeof (EFI_STATUS_CODE_DATA),\r
+          RangeData->DataHeader.Size\r
+          );\r
+\r
+      //\r
+      // The software memory test (R/W/V) perform here. It will detect the\r
+      // memory mis-compare error.\r
+      //\r
+      WriteMemory (Private, mCurrentAddress, BlockBoundary);\r
+\r
+      Status = VerifyMemory (Private, mCurrentAddress, BlockBoundary);\r
+      if (EFI_ERROR (Status)) {\r
+        //\r
+        // If perform here, means there is mis-compare error, and no agent can\r
+        // handle it, so we return to BDS EFI_DEVICE_ERROR.\r
+        //\r
+        *ErrorOut = TRUE;\r
+        return EFI_DEVICE_ERROR;\r
+      }\r
+    }\r
+\r
+    mTestedSystemMemory += BlockBoundary;\r
+    *TestedMemorySize = mTestedSystemMemory;\r
+\r
+    //\r
+    // If the memory test restart after the platform driver disable dimms,\r
+    // the NonTestSystemMemory may be changed, but the base memory size will\r
+    // not changed, so we can get the current total memory size.\r
+    //\r
+    *TotalMemorySize = Private->BaseMemorySize + mNonTestedSystemMemory;\r
+\r
+    //\r
+    // Update the current test address pointing to next BDS BLOCK\r
+    //\r
+    mCurrentAddress += Private->BdsBlockSize;\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+  //\r
+  // Change to next non tested memory range\r
+  //\r
+  mCurrentLink = mCurrentLink->ForwardLink;\r
+  if (mCurrentLink != &Private->NonTestedMemRanList) {\r
+    mCurrentRange   = NONTESTED_MEMORY_RANGE_FROM_LINK (mCurrentLink);\r
+    mCurrentAddress = mCurrentRange->StartAddress;\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    //\r
+    // Here means all the memory test have finished\r
+    //\r
+    *TestedMemorySize = mTestedSystemMemory;\r
+    *TotalMemorySize  = Private->BaseMemorySize + mNonTestedSystemMemory;\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+}\r
+\r
+/**\r
+  Finish the memory test.\r
+\r
+  @param[in] This             The protocol instance pointer. \r
+\r
+  @retval EFI_SUCCESS         Success. All resources used in the memory test are freed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GenMemoryTestFinished (\r
+  IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  GENERIC_MEMORY_TEST_PRIVATE *Private;\r
+\r
+  Private = GENERIC_MEMORY_TEST_PRIVATE_FROM_THIS (This);\r
+\r
+  //\r
+  // Perform Data and Address line test\r
+  //\r
+  Status = PerformAddressDataLineTest (Private);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Add the non tested memory range to system memory map through GCD service\r
+  //\r
+  UpdateMemoryMap (Private);\r
+\r
+  //\r
+  // we need to free all the memory allocate\r
+  //\r
+  DestroyLinkList (Private);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Provides the capability to test the compatible range used by some special drivers.\r
+\r
+  @param[in]  This              The protocol instance pointer. \r
+  @param[in]  StartAddress      The start address of the compatible memory range that\r
+                                must be below 16M.\r
+  @param[in]  Length            The compatible 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 are not below Low 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
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  GENERIC_MEMORY_TEST_PRIVATE     *Private;\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;\r
+  EFI_PHYSICAL_ADDRESS            CurrentBase;\r
+  UINT64                          CurrentLength;\r
+\r
+  Private = GENERIC_MEMORY_TEST_PRIVATE_FROM_THIS (This);\r
+\r
+  //\r
+  // Check if the parameter is below 16MB\r
+  //\r
+  if (StartAddress + Length > 0x1000000) {\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 = DirectRangeTest (\r
+                 Private,\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
+/**\r
+  Perform the address line walking ones test.\r
+\r
+  @param[in] Private  Point to generic memory test driver's private data.\r
+  \r
+  @retval EFI_SUCCESS          Successful finished walking ones test. \r
+  @retval EFI_OUT_OF_RESOURCE  Could not get resource in base memory. \r
+  @retval EFI_ACCESS_DENIED    Code may can not run here because if walking one test\r
+                               failed, system may be already halt.\r
+\r
+**/\r
+EFI_STATUS\r
+PerformAddressDataLineTest (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE      *Private\r
+  )\r
+{\r
+  LIST_ENTRY              *ExtendedLink;\r
+  NONTESTED_MEMORY_RANGE  *ExtendedRange;\r
+  BOOLEAN                 InExtendedRange;\r
+  EFI_PHYSICAL_ADDRESS    TestAddress;\r
+\r
+  //\r
+  // Light version no data line test, only perform the address line test\r
+  //\r
+  TestAddress = (EFI_PHYSICAL_ADDRESS) 0x1;\r
+  while (TestAddress < MAX_ADDRESS && TestAddress > 0) {\r
+    //\r
+    // only test if the address falls in the enabled range\r
+    //\r
+    InExtendedRange = FALSE;\r
+    ExtendedLink    = Private->NonTestedMemRanList.BackLink;\r
+    while (ExtendedLink != &Private->NonTestedMemRanList) {\r
+      ExtendedRange = NONTESTED_MEMORY_RANGE_FROM_LINK (ExtendedLink);\r
+      if ((TestAddress >= ExtendedRange->StartAddress) &&\r
+          (TestAddress < (ExtendedRange->StartAddress + ExtendedRange->Length))\r
+          ) {\r
+        InExtendedRange = TRUE;\r
+      }\r
+\r
+      ExtendedLink = ExtendedLink->BackLink;\r
+    }\r
+\r
+    if (InExtendedRange) {\r
+      *(EFI_PHYSICAL_ADDRESS *) (UINTN) TestAddress = TestAddress;\r
+      Private->Cpu->FlushDataCache (Private->Cpu, TestAddress, 1, EfiCpuFlushTypeWriteBackInvalidate);\r
+      if (*(EFI_PHYSICAL_ADDRESS *) (UINTN) TestAddress != TestAddress) {\r
+        return EFI_ACCESS_DENIED;\r
+      }\r
+    }\r
+\r
+    TestAddress = LShiftU64 (TestAddress, 1);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+//\r
+// Driver entry here\r
+//\r
+GENERIC_MEMORY_TEST_PRIVATE mGenericMemoryTestPrivate = {\r
+  EFI_GENERIC_MEMORY_TEST_PRIVATE_SIGNATURE,\r
+  NULL,\r
+  NULL,\r
+  {\r
+    InitializeMemoryTest,\r
+    GenPerformMemoryTest,\r
+    GenMemoryTestFinished,\r
+    GenCompatibleRangeTest\r
+  },\r
+  (EXTENDMEM_COVERAGE_LEVEL) 0,\r
+  0,\r
+  0,\r
+  NULL,\r
+  0,\r
+  0,\r
+  {\r
+    NULL,\r
+    NULL\r
+  }\r
+};\r
+\r
+/**\r
+  The generic memory test driver's entry point.\r
+\r
+  It initializes private data to default value.\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 entry point is executed successfully.\r
+  @retval EFI_NOT_FOUND   Can't find HandOff Hob in HobList.\r
+  @retval other           Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GenericMemoryTestEntryPoint (\r
+  IN  EFI_HANDLE           ImageHandle,\r
+  IN  EFI_SYSTEM_TABLE     *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS            Status;\r
+  VOID                  *HobList;\r
+  EFI_BOOT_MODE         BootMode;\r
+  EFI_PEI_HOB_POINTERS  Hob;\r
+\r
+  //\r
+  // Use the generic pattern to test compatible memory range\r
+  //\r
+  mGenericMemoryTestPrivate.MonoPattern   = GenericMemoryTestMonoPattern;\r
+  mGenericMemoryTestPrivate.MonoTestSize  = GENERIC_CACHELINE_SIZE;\r
+\r
+  //\r
+  // Get the platform boot mode\r
+  //\r
+  HobList = GetHobList ();\r
+\r
+  Hob.Raw = HobList;\r
+  if (Hob.Header->HobType != EFI_HOB_TYPE_HANDOFF) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  BootMode = Hob.HandoffInformationTable->BootMode;\r
+\r
+  //\r
+  // Get the platform boot mode and create the default memory test coverage\r
+  // level and span size for compatible memory test using\r
+  //\r
+  switch (BootMode) {\r
+  case BOOT_WITH_FULL_CONFIGURATION:\r
+  case BOOT_WITH_DEFAULT_SETTINGS:\r
+    mGenericMemoryTestPrivate.CoverageSpan = SPARSE_SPAN_SIZE;\r
+    break;\r
+\r
+  case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS:\r
+    mGenericMemoryTestPrivate.CoverageSpan = GENERIC_CACHELINE_SIZE;\r
+    break;\r
+\r
+  default:\r
+    mGenericMemoryTestPrivate.CoverageSpan = QUICK_SPAN_SIZE;\r
+    break;\r
+  }\r
+  //\r
+  // Install the protocol\r
+  //\r
+  Status = gBS->InstallProtocolInterface (\r
+                  &mGenericMemoryTestPrivate.Handle,\r
+                  &gEfiGenericMemTestProtocolGuid,\r
+                  EFI_NATIVE_INTERFACE,\r
+                  &mGenericMemoryTestPrivate.GenericMemoryTest\r
+                  );\r
+\r
+  return Status;\r
+}\r
diff --git a/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.h b/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.h
new file mode 100644 (file)
index 0000000..391c8a4
--- /dev/null
@@ -0,0 +1,342 @@
+/** @file\r
+  The generic memory test driver definition\r
+\r
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions\r
+  of the BSD License which accompanies this distribution.  The\r
+  full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _GENERIC_MEMORY_TEST_H_\r
+#define _GENERIC_MEMORY_TEST_H_\r
+\r
+#include <Guid/StatusCodeDataTypeId.h>\r
+#include <Protocol/GenericMemoryTest.h>\r
+#include <Protocol/Cpu.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/HobLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
+#include <Library/ReportStatusCodeLib.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+\r
+//\r
+// Some global define\r
+//\r
+#define GENERIC_CACHELINE_SIZE  0x40\r
+\r
+//\r
+// attributes for reserved memory before it is promoted to system memory\r
+//\r
+#define EFI_MEMORY_PRESENT      0x0100000000000000ULL\r
+#define EFI_MEMORY_INITIALIZED  0x0200000000000000ULL\r
+#define EFI_MEMORY_TESTED       0x0400000000000000ULL\r
+\r
+//\r
+// The SPARSE_SPAN_SIZE size can not small then the MonoTestSize\r
+//\r
+#define TEST_BLOCK_SIZE   0x2000000\r
+#define QUICK_SPAN_SIZE   (TEST_BLOCK_SIZE >> 2)\r
+#define SPARSE_SPAN_SIZE  (TEST_BLOCK_SIZE >> 4)\r
+\r
+//\r
+// This structure records every nontested memory range parsed through GCD\r
+// service.\r
+//\r
+#define EFI_NONTESTED_MEMORY_RANGE_SIGNATURE  SIGNATURE_32 ('N', 'T', 'M', 'E')\r
+\r
+typedef struct {\r
+  UINTN                 Signature;\r
+  LIST_ENTRY        Link;\r
+  EFI_PHYSICAL_ADDRESS  StartAddress;\r
+  UINT64                Length;\r
+  UINT64                Capabilities;\r
+  BOOLEAN               Above4G;\r
+  BOOLEAN               AlreadyMapped;\r
+} NONTESTED_MEMORY_RANGE;\r
+\r
+#define NONTESTED_MEMORY_RANGE_FROM_LINK(link) \\r
+  CR ( \\r
+  link, \\r
+  NONTESTED_MEMORY_RANGE, \\r
+  Link, \\r
+  EFI_NONTESTED_MEMORY_RANGE_SIGNATURE \\r
+  )\r
+\r
+//\r
+// This is the memory test driver's structure definition\r
+//\r
+#define EFI_GENERIC_MEMORY_TEST_PRIVATE_SIGNATURE SIGNATURE_32 ('G', 'E', 'M', 'T')\r
+\r
+typedef struct {\r
+\r
+  UINTN                             Signature;\r
+  EFI_HANDLE                        Handle;\r
+\r
+  //\r
+  // Cpu arch protocol's pointer\r
+  //\r
+  EFI_CPU_ARCH_PROTOCOL             *Cpu;\r
+\r
+  //\r
+  // generic memory test driver's protocol\r
+  //\r
+  EFI_GENERIC_MEMORY_TEST_PROTOCOL  GenericMemoryTest;\r
+\r
+  //\r
+  // memory test covered spans\r
+  //\r
+  EXTENDMEM_COVERAGE_LEVEL          CoverLevel;\r
+  UINTN                             CoverageSpan;\r
+  UINT64                            BdsBlockSize;\r
+\r
+  //\r
+  // the memory test pattern and size every time R/W/V memory\r
+  //\r
+  VOID                              *MonoPattern;\r
+  UINTN                             MonoTestSize;\r
+\r
+  //\r
+  // base memory's size which tested in PEI phase\r
+  //\r
+  UINT64                            BaseMemorySize;\r
+\r
+  //\r
+  // memory range list\r
+  //\r
+  LIST_ENTRY                    NonTestedMemRanList;\r
+\r
+} GENERIC_MEMORY_TEST_PRIVATE;\r
+\r
+#define GENERIC_MEMORY_TEST_PRIVATE_FROM_THIS(a) \\r
+  CR ( \\r
+  a, \\r
+  GENERIC_MEMORY_TEST_PRIVATE, \\r
+  GenericMemoryTest, \\r
+  EFI_GENERIC_MEMORY_TEST_PRIVATE_SIGNATURE \\r
+  )\r
+\r
+//\r
+// Function Prototypes\r
+//\r
+\r
+/**\r
+  Construct the system base memory range through GCD service.\r
+\r
+  @param[in] Private  Point to generic memory test driver's private data.\r
+\r
+  @retval EFI_SUCCESS          Successful construct the base memory range through GCD service.\r
+  @retval EFI_OUT_OF_RESOURCE  Could not allocate needed resource from base memory.\r
+  @retval Others               Failed to construct base memory range through GCD service.\r
+                            \r
+**/\r
+EFI_STATUS\r
+ConstructBaseMemoryRange (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE  *Private\r
+  );\r
+\r
+/**\r
+  Construct the system non-tested memory range through GCD service.\r
+\r
+  @param[in] Private  Point to generic memory test driver's private data.\r
+\r
+  @retval EFI_SUCCESS          Successful construct the non-tested memory range through GCD service.\r
+  @retval EFI_OUT_OF_RESOURCE  Could not allocate needed resource from base memory.\r
+  @retval Others               Failed to construct non-tested memory range through GCD service.\r
+                            \r
+**/\r
+EFI_STATUS\r
+ConstructNonTestedMemoryRange (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE  *Private\r
+  );\r
+\r
+/**\r
+  Perform the address line walking ones test.\r
+\r
+  @param[in] Private  Point to generic memory test driver's private data.\r
+  \r
+  @retval EFI_SUCCESS          Successful finished walking ones test. \r
+  @retval EFI_OUT_OF_RESOURCE  Could not get resource in base memory. \r
+  @retval EFI_ACCESS_DENIED    Code may can not run here because if walking one test\r
+                               failed, system may be already halt.\r
+\r
+**/\r
+EFI_STATUS\r
+PerformAddressDataLineTest (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE      *Private\r
+  );\r
+\r
+/**\r
+  Destroy the link list base on the correspond link list type.\r
+\r
+  @param[in] Private  Point to generic memory test driver's private data.\r
+                            \r
+**/\r
+VOID\r
+DestroyLinkList (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE  *Private\r
+  );\r
+\r
+/**\r
+  Add the extened memory to whole system memory map.\r
+\r
+  @param[in] Private  Point to generic memory test driver's private data.\r
+\r
+  @retval EFI_SUCCESS Successful add all the extended memory to system memory map.\r
+  @retval Others      Failed to add the tested extended memory.\r
+                            \r
+**/\r
+EFI_STATUS\r
+UpdateMemoryMap (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE  *Private\r
+  );\r
+\r
+/**\r
+  Write the memory test pattern into a range of physical memory.\r
+\r
+  @param[in] Private  Point to generic memory test driver's private data.\r
+  @param[in] Start    The memory range's start address.\r
+  @param[in] Size     The memory range's size.\r
+\r
+  @retval EFI_SUCCESS Successful write the test pattern into the non-tested memory.\r
+  @retval Others      The test pattern may not really write into the physical memory.\r
+                            \r
+**/\r
+EFI_STATUS\r
+WriteMemory (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE  *Private,\r
+  IN  EFI_PHYSICAL_ADDRESS         Start,\r
+  IN  UINT64                       Size\r
+  );\r
+\r
+/**\r
+  Verify the range of physical memory which covered by memory test pattern.\r
+\r
+  This function will also do not return any informatin just cause system reset,\r
+  because the handle error encount fatal error and disable the bad DIMMs.\r
+\r
+  @param[in] Private  Point to generic memory test driver's private data.\r
+  @param[in] Start    The memory range's start address.\r
+  @param[in] Size     The memory range's size.\r
+\r
+  @retval EFI_SUCCESS Successful verify the range of memory, no errors' location found.\r
+  @retval Others      The range of memory have errors contained.\r
+                            \r
+**/\r
+EFI_STATUS\r
+VerifyMemory (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE  *Private,\r
+  IN  EFI_PHYSICAL_ADDRESS         Start,\r
+  IN  UINT64                       Size\r
+  );\r
+\r
+/**\r
+  Test a range of the memory directly .\r
+\r
+  @param[in] Private       Point to generic memory test driver's private data.\r
+  @param[in] StartAddress  Starting address of the memory range to be tested.\r
+  @param[in] Length        Length in bytes of the memory range to be tested.\r
+  @param[in] Capabilities  The bit mask of attributes that the memory range supports.\r
+\r
+  @retval EFI_SUCCESS      Successful test the range of memory.\r
+  @retval Others           Failed to test the range of memory.\r
+                            \r
+**/\r
+EFI_STATUS\r
+DirectRangeTest (\r
+  IN  GENERIC_MEMORY_TEST_PRIVATE  *Private,\r
+  IN  EFI_PHYSICAL_ADDRESS         StartAddress,\r
+  IN  UINT64                       Length,\r
+  IN  UINT64                       Capabilities\r
+  );\r
+\r
+/**\r
+  Initialize the generic memory test.\r
+\r
+  @param[in]  This                The protocol instance pointer. \r
+  @param[in]  Level               The coverage level of the memory test. \r
+  @param[out] RequireSoftECCInit  Indicate if the memory need software ECC init. \r
+\r
+  @retval EFI_SUCCESS         The generic memory test is initialized correctly. \r
+  @retval EFI_NO_MEDIA        The system had no memory to be tested. \r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InitializeMemoryTest (\r
+  IN EFI_GENERIC_MEMORY_TEST_PROTOCOL          *This,\r
+  IN  EXTENDMEM_COVERAGE_LEVEL                 Level,\r
+  OUT BOOLEAN                                  *RequireSoftECCInit\r
+  );\r
+\r
+/**\r
+  Perform the memory test.\r
+\r
+  @param[in]  This              The protocol instance pointer. \r
+  @param[out] TestedMemorySize  Return the tested extended memory size. \r
+  @param[out] TotalMemorySize   Return the whole system physical memory size. \r
+                                The total memory size does not include memory in a slot with a disabled DIMM.  \r
+  @param[out] ErrorOut          TRUE if the memory error occured.\r
+  @param[in]  IfTestAbort       Indicates that the user pressed "ESC" to skip the memory test. \r
+\r
+  @retval EFI_SUCCESS         One block of memory passed the test.\r
+  @retval EFI_NOT_FOUND       All memory blocks have already been tested.\r
+  @retval EFI_DEVICE_ERROR    Memory device error occured, and no agent can handle it.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GenPerformMemoryTest (\r
+  IN EFI_GENERIC_MEMORY_TEST_PROTOCOL          *This,\r
+  OUT UINT64                                   *TestedMemorySize,\r
+  OUT UINT64                                   *TotalMemorySize,\r
+  OUT BOOLEAN                                  *ErrorOut,\r
+  IN BOOLEAN                                   TestAbort\r
+  );\r
+\r
+/**\r
+  Finish the memory test.\r
+\r
+  @param[in] This             The protocol instance pointer. \r
+\r
+  @retval EFI_SUCCESS         Success. All resources used in the memory test are freed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GenMemoryTestFinished (\r
+  IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This\r
+  );\r
+\r
+/**\r
+  Provides the capability to test the compatible range used by some special drivers.\r
+\r
+  @param[in]  This              The protocol instance pointer. \r
+  @param[in]  StartAddress      The start address of the compatible memory range that\r
+                                must be below 16M.\r
+  @param[in]  Length            The compatible 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 are not below Low 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
+  );\r
+\r
+#endif\r