--- /dev/null
+/** @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
--- /dev/null
+/** @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