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