3 Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "LightMemoryTest.h"
13 // Since this driver will only ever produce one instance of the memory test
14 // protocol, so we do not need to dynamically allocate the PrivateData.
16 EFI_PHYSICAL_ADDRESS mCurrentAddress
;
17 LIST_ENTRY
*mCurrentLink
;
18 NONTESTED_MEMORY_RANGE
*mCurrentRange
;
19 UINT64 mTestedSystemMemory
;
20 UINT64 mNonTestedSystemMemory
;
22 UINT32 GenericMemoryTestMonoPattern
[GENERIC_CACHELINE_SIZE
/ 4] = {
42 Compares the contents of two buffers.
44 This function compares Length bytes of SourceBuffer to Length bytes of DestinationBuffer.
45 If all Length bytes of the two buffers are identical, then 0 is returned. Otherwise, the
46 value returned is the first mismatched byte in SourceBuffer subtracted from the first
47 mismatched byte in DestinationBuffer.
49 If Length = 0, then ASSERT().
51 @param[in] DestinationBuffer The pointer to the destination buffer to compare.
52 @param[in] SourceBuffer The pointer to the source buffer to compare.
53 @param[in] Length The number of bytes to compare.
55 @return 0 All Length bytes of the two buffers are identical.
56 @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first
57 mismatched byte in DestinationBuffer.
62 CompareMemWithoutCheckArgument (
63 IN CONST VOID
*DestinationBuffer
,
64 IN CONST VOID
*SourceBuffer
,
69 while ((--Length
!= 0) &&
70 (*(INT8
*)DestinationBuffer
== *(INT8
*)SourceBuffer
))
72 DestinationBuffer
= (INT8
*)DestinationBuffer
+ 1;
73 SourceBuffer
= (INT8
*)SourceBuffer
+ 1;
76 return (INTN
)*(UINT8
*)DestinationBuffer
- (INTN
)*(UINT8
*)SourceBuffer
;
80 Construct the system base memory range through GCD service.
82 @param[in] Private Point to generic memory test driver's private data.
84 @retval EFI_SUCCESS Successful construct the base memory range through GCD service.
85 @retval EFI_OUT_OF_RESOURCE Could not allocate needed resource from base memory.
86 @retval Others Failed to construct base memory range through GCD service.
90 ConstructBaseMemoryRange (
91 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
94 UINTN NumberOfDescriptors
;
95 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
99 // Base memory will always below 4G
101 gDS
->GetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
103 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
104 if ((MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) ||
105 (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeMoreReliable
))
107 Private
->BaseMemorySize
+= MemorySpaceMap
[Index
].Length
;
115 Destroy the link list base on the correspond link list type.
117 @param[in] Private Point to generic memory test driver's private data.
122 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
126 NONTESTED_MEMORY_RANGE
*NontestedRange
;
128 Link
= Private
->NonTestedMemRanList
.BackLink
;
130 while (Link
!= &Private
->NonTestedMemRanList
) {
131 RemoveEntryList (Link
);
132 NontestedRange
= NONTESTED_MEMORY_RANGE_FROM_LINK (Link
);
133 gBS
->FreePool (NontestedRange
);
134 Link
= Private
->NonTestedMemRanList
.BackLink
;
139 Convert the memory range to tested.
141 @param BaseAddress Base address of the memory range.
142 @param Length Length of the memory range.
143 @param Capabilities Capabilities of the memory range.
145 @retval EFI_SUCCESS The memory range is converted to tested.
146 @retval others Error happens.
149 ConvertToTestedMemory (
150 IN UINT64 BaseAddress
,
152 IN UINT64 Capabilities
157 Status
= gDS
->RemoveMemorySpace (
161 if (!EFI_ERROR (Status
)) {
162 Status
= gDS
->AddMemorySpace (
163 ((Capabilities
& EFI_MEMORY_MORE_RELIABLE
) == EFI_MEMORY_MORE_RELIABLE
) ?
164 EfiGcdMemoryTypeMoreReliable
: EfiGcdMemoryTypeSystemMemory
,
168 (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
| EFI_MEMORY_RUNTIME
)
176 Add the extened memory to whole system memory map.
178 @param[in] Private Point to generic memory test driver's private data.
180 @retval EFI_SUCCESS Successful add all the extended memory to system memory map.
181 @retval Others Failed to add the tested extended memory.
186 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
190 NONTESTED_MEMORY_RANGE
*Range
;
192 Link
= Private
->NonTestedMemRanList
.ForwardLink
;
194 while (Link
!= &Private
->NonTestedMemRanList
) {
195 Range
= NONTESTED_MEMORY_RANGE_FROM_LINK (Link
);
197 ConvertToTestedMemory (
200 Range
->Capabilities
&~
201 (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
| EFI_MEMORY_RUNTIME
)
203 Link
= Link
->ForwardLink
;
210 Test a range of the memory directly .
212 @param[in] Private Point to generic memory test driver's private data.
213 @param[in] StartAddress Starting address of the memory range to be tested.
214 @param[in] Length Length in bytes of the memory range to be tested.
215 @param[in] Capabilities The bit mask of attributes that the memory range supports.
217 @retval EFI_SUCCESS Successful test the range of memory.
218 @retval Others Failed to test the range of memory.
223 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
,
224 IN EFI_PHYSICAL_ADDRESS StartAddress
,
226 IN UINT64 Capabilities
232 // Perform a dummy memory test, so directly write the pattern to all range
234 WriteMemory (Private
, StartAddress
, Length
);
237 // Verify the memory range
239 Status
= VerifyMemory (Private
, StartAddress
, Length
);
240 if (EFI_ERROR (Status
)) {
245 // Add the tested compatible memory to system memory using GCD service
247 ConvertToTestedMemory (
251 (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
| EFI_MEMORY_RUNTIME
)
258 Construct the system non-tested memory range through GCD service.
260 @param[in] Private Point to generic memory test driver's private data.
262 @retval EFI_SUCCESS Successful construct the non-tested memory range through GCD service.
263 @retval EFI_OUT_OF_RESOURCE Could not allocate needed resource from base memory.
264 @retval Others Failed to construct non-tested memory range through GCD service.
268 ConstructNonTestedMemoryRange (
269 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
272 NONTESTED_MEMORY_RANGE
*Range
;
274 UINTN NumberOfDescriptors
;
275 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
279 // Non tested memory range may be span 4G here
283 gDS
->GetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
285 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
286 if ((MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeReserved
) &&
287 ((MemorySpaceMap
[Index
].Capabilities
& (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
)) ==
288 (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
))
293 // Light version do not need to process >4G memory range
297 sizeof (NONTESTED_MEMORY_RANGE
),
301 Range
->Signature
= EFI_NONTESTED_MEMORY_RANGE_SIGNATURE
;
302 Range
->StartAddress
= MemorySpaceMap
[Index
].BaseAddress
;
303 Range
->Length
= MemorySpaceMap
[Index
].Length
;
304 Range
->Capabilities
= MemorySpaceMap
[Index
].Capabilities
;
306 mNonTestedSystemMemory
+= MemorySpaceMap
[Index
].Length
;
307 InsertTailList (&Private
->NonTestedMemRanList
, &Range
->Link
);
312 return EFI_NOT_FOUND
;
319 Write the memory test pattern into a range of physical memory.
321 @param[in] Private Point to generic memory test driver's private data.
322 @param[in] Start The memory range's start address.
323 @param[in] Size The memory range's size.
325 @retval EFI_SUCCESS Successful write the test pattern into the non-tested memory.
326 @retval Others The test pattern may not really write into the physical memory.
331 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
,
332 IN EFI_PHYSICAL_ADDRESS Start
,
336 EFI_PHYSICAL_ADDRESS Address
;
341 // Add 4G memory address check for IA32 platform
342 // NOTE: Without page table, there is no way to use memory above 4G.
344 if (Start
+ Size
> MAX_ADDRESS
) {
348 while (Address
< (Start
+ Size
)) {
349 CopyMem ((VOID
*)(UINTN
)Address
, Private
->MonoPattern
, Private
->MonoTestSize
);
350 Address
+= Private
->CoverageSpan
;
354 // bug bug: we may need GCD service to make the code cache and data uncache,
355 // if GCD do not support it or return fail, then just flush the whole cache.
357 if (Private
->Cpu
!= NULL
) {
358 Private
->Cpu
->FlushDataCache (Private
->Cpu
, Start
, Size
, EfiCpuFlushTypeWriteBackInvalidate
);
365 Verify the range of physical memory which covered by memory test pattern.
367 This function will also do not return any informatin just cause system reset,
368 because the handle error encount fatal error and disable the bad DIMMs.
370 @param[in] Private Point to generic memory test driver's private data.
371 @param[in] Start The memory range's start address.
372 @param[in] Size The memory range's size.
374 @retval EFI_SUCCESS Successful verify the range of memory, no errors' location found.
375 @retval Others The range of memory have errors contained.
380 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
,
381 IN EFI_PHYSICAL_ADDRESS Start
,
385 EFI_PHYSICAL_ADDRESS Address
;
387 EFI_MEMORY_EXTENDED_ERROR_DATA
*ExtendedErrorData
;
390 ExtendedErrorData
= NULL
;
393 // Add 4G memory address check for IA32 platform
394 // NOTE: Without page table, there is no way to use memory above 4G.
396 if (Start
+ Size
> MAX_ADDRESS
) {
401 // Use the software memory test to check whether have detected miscompare
402 // error here. If there is miscompare error here then check if generic
403 // memory test driver can disable the bad DIMM.
405 while (Address
< (Start
+ Size
)) {
406 ErrorFound
= CompareMemWithoutCheckArgument (
407 (VOID
*)(UINTN
)(Address
),
408 Private
->MonoPattern
,
409 Private
->MonoTestSize
411 if (ErrorFound
!= 0) {
413 // Report uncorrectable errors
415 ExtendedErrorData
= AllocateZeroPool (sizeof (EFI_MEMORY_EXTENDED_ERROR_DATA
));
416 if (ExtendedErrorData
== NULL
) {
417 return EFI_OUT_OF_RESOURCES
;
420 ExtendedErrorData
->DataHeader
.HeaderSize
= (UINT16
)sizeof (EFI_STATUS_CODE_DATA
);
421 ExtendedErrorData
->DataHeader
.Size
= (UINT16
)(sizeof (EFI_MEMORY_EXTENDED_ERROR_DATA
) - sizeof (EFI_STATUS_CODE_DATA
));
422 ExtendedErrorData
->Granularity
= EFI_MEMORY_ERROR_DEVICE
;
423 ExtendedErrorData
->Operation
= EFI_MEMORY_OPERATION_READ
;
424 ExtendedErrorData
->Syndrome
= 0x0;
425 ExtendedErrorData
->Address
= Address
;
426 ExtendedErrorData
->Resolution
= 0x40;
428 REPORT_STATUS_CODE_EX (
430 EFI_COMPUTING_UNIT_MEMORY
| EFI_CU_MEMORY_EC_UNCORRECTABLE
,
432 &gEfiGenericMemTestProtocolGuid
,
434 (UINT8
*)ExtendedErrorData
+ sizeof (EFI_STATUS_CODE_DATA
),
435 ExtendedErrorData
->DataHeader
.Size
438 return EFI_DEVICE_ERROR
;
441 Address
+= Private
->CoverageSpan
;
448 Initialize the generic memory test.
450 @param[in] This The protocol instance pointer.
451 @param[in] Level The coverage level of the memory test.
452 @param[out] RequireSoftECCInit Indicate if the memory need software ECC init.
454 @retval EFI_SUCCESS The generic memory test is initialized correctly.
455 @retval EFI_NO_MEDIA The system had no memory to be tested.
460 InitializeMemoryTest (
461 IN EFI_GENERIC_MEMORY_TEST_PROTOCOL
*This
,
462 IN EXTENDMEM_COVERAGE_LEVEL Level
,
463 OUT BOOLEAN
*RequireSoftECCInit
467 GENERIC_MEMORY_TEST_PRIVATE
*Private
;
468 EFI_CPU_ARCH_PROTOCOL
*Cpu
;
470 Private
= GENERIC_MEMORY_TEST_PRIVATE_FROM_THIS (This
);
471 *RequireSoftECCInit
= FALSE
;
474 // This is initialize for default value, but some value may be reset base on
475 // platform memory test driver.
477 Private
->CoverLevel
= Level
;
478 Private
->BdsBlockSize
= TEST_BLOCK_SIZE
;
479 Private
->MonoPattern
= GenericMemoryTestMonoPattern
;
480 Private
->MonoTestSize
= GENERIC_CACHELINE_SIZE
;
483 // Initialize several internal link list
485 InitializeListHead (&Private
->NonTestedMemRanList
);
488 // Construct base memory range
490 ConstructBaseMemoryRange (Private
);
493 // get the cpu arch protocol to support flash cache
495 Status
= gBS
->LocateProtocol (
496 &gEfiCpuArchProtocolGuid
,
500 if (!EFI_ERROR (Status
)) {
505 // Create the CoverageSpan of the memory test base on the coverage level
507 switch (Private
->CoverLevel
) {
509 Private
->CoverageSpan
= GENERIC_CACHELINE_SIZE
;
513 Private
->CoverageSpan
= SPARSE_SPAN_SIZE
;
517 // Even the BDS do not need to test any memory, but in some case it
518 // still need to init ECC memory.
521 Private
->CoverageSpan
= QUICK_SPAN_SIZE
;
526 // This is the first time we construct the non-tested memory range, if no
527 // extended memory found, we know the system have not any extended memory
530 Status
= ConstructNonTestedMemoryRange (Private
);
531 if (Status
== EFI_NOT_FOUND
) {
536 // ready to perform the R/W/V memory test
538 mTestedSystemMemory
= Private
->BaseMemorySize
;
539 mCurrentLink
= Private
->NonTestedMemRanList
.ForwardLink
;
540 mCurrentRange
= NONTESTED_MEMORY_RANGE_FROM_LINK (mCurrentLink
);
541 mCurrentAddress
= mCurrentRange
->StartAddress
;
547 Perform the memory test.
549 @param[in] This The protocol instance pointer.
550 @param[out] TestedMemorySize Return the tested extended memory size.
551 @param[out] TotalMemorySize Return the whole system physical memory size.
552 The total memory size does not include memory in a slot with a disabled DIMM.
553 @param[out] ErrorOut TRUE if the memory error occurred.
554 @param[in] IfTestAbort Indicates that the user pressed "ESC" to skip the memory test.
556 @retval EFI_SUCCESS One block of memory passed the test.
557 @retval EFI_NOT_FOUND All memory blocks have already been tested.
558 @retval EFI_DEVICE_ERROR Memory device error occurred, and no agent can handle it.
563 GenPerformMemoryTest (
564 IN EFI_GENERIC_MEMORY_TEST_PROTOCOL
*This
,
565 OUT UINT64
*TestedMemorySize
,
566 OUT UINT64
*TotalMemorySize
,
567 OUT BOOLEAN
*ErrorOut
,
572 GENERIC_MEMORY_TEST_PRIVATE
*Private
;
573 EFI_MEMORY_RANGE_EXTENDED_DATA
*RangeData
;
574 UINT64 BlockBoundary
;
576 Private
= GENERIC_MEMORY_TEST_PRIVATE_FROM_THIS (This
);
582 // In extensive mode the boundary of "mCurrentRange->Length" may will lost
583 // some range that is not Private->BdsBlockSize size boundary, so need
584 // the software mechanism to confirm all memory location be covered.
586 if (mCurrentAddress
< (mCurrentRange
->StartAddress
+ mCurrentRange
->Length
)) {
587 if ((mCurrentAddress
+ Private
->BdsBlockSize
) <= (mCurrentRange
->StartAddress
+ mCurrentRange
->Length
)) {
588 BlockBoundary
= Private
->BdsBlockSize
;
590 BlockBoundary
= mCurrentRange
->StartAddress
+ mCurrentRange
->Length
- mCurrentAddress
;
594 // If TestAbort is true, means user cancel the memory test
596 if (!TestAbort
&& (Private
->CoverLevel
!= IGNORE
)) {
598 // Report status code of every memory range
600 RangeData
= AllocateZeroPool (sizeof (EFI_MEMORY_RANGE_EXTENDED_DATA
));
601 if (RangeData
== NULL
) {
602 return EFI_OUT_OF_RESOURCES
;
605 RangeData
->DataHeader
.HeaderSize
= (UINT16
)sizeof (EFI_STATUS_CODE_DATA
);
606 RangeData
->DataHeader
.Size
= (UINT16
)(sizeof (EFI_MEMORY_RANGE_EXTENDED_DATA
) - sizeof (EFI_STATUS_CODE_DATA
));
607 RangeData
->Start
= mCurrentAddress
;
608 RangeData
->Length
= BlockBoundary
;
610 REPORT_STATUS_CODE_EX (
612 EFI_COMPUTING_UNIT_MEMORY
| EFI_CU_MEMORY_PC_TEST
,
614 &gEfiGenericMemTestProtocolGuid
,
616 (UINT8
*)RangeData
+ sizeof (EFI_STATUS_CODE_DATA
),
617 RangeData
->DataHeader
.Size
621 // The software memory test (R/W/V) perform here. It will detect the
622 // memory mis-compare error.
624 WriteMemory (Private
, mCurrentAddress
, BlockBoundary
);
626 Status
= VerifyMemory (Private
, mCurrentAddress
, BlockBoundary
);
627 if (EFI_ERROR (Status
)) {
629 // If perform here, means there is mis-compare error, and no agent can
630 // handle it, so we return to BDS EFI_DEVICE_ERROR.
633 return EFI_DEVICE_ERROR
;
637 mTestedSystemMemory
+= BlockBoundary
;
638 *TestedMemorySize
= mTestedSystemMemory
;
641 // If the memory test restart after the platform driver disable dimms,
642 // the NonTestSystemMemory may be changed, but the base memory size will
643 // not changed, so we can get the current total memory size.
645 *TotalMemorySize
= Private
->BaseMemorySize
+ mNonTestedSystemMemory
;
648 // Update the current test address pointing to next BDS BLOCK
650 mCurrentAddress
+= Private
->BdsBlockSize
;
656 // Change to next non tested memory range
658 mCurrentLink
= mCurrentLink
->ForwardLink
;
659 if (mCurrentLink
!= &Private
->NonTestedMemRanList
) {
660 mCurrentRange
= NONTESTED_MEMORY_RANGE_FROM_LINK (mCurrentLink
);
661 mCurrentAddress
= mCurrentRange
->StartAddress
;
665 // Here means all the memory test have finished
667 *TestedMemorySize
= mTestedSystemMemory
;
668 *TotalMemorySize
= Private
->BaseMemorySize
+ mNonTestedSystemMemory
;
669 return EFI_NOT_FOUND
;
674 Finish the memory test.
676 @param[in] This The protocol instance pointer.
678 @retval EFI_SUCCESS Success. All resources used in the memory test are freed.
683 GenMemoryTestFinished (
684 IN EFI_GENERIC_MEMORY_TEST_PROTOCOL
*This
688 GENERIC_MEMORY_TEST_PRIVATE
*Private
;
690 Private
= GENERIC_MEMORY_TEST_PRIVATE_FROM_THIS (This
);
693 // Perform Data and Address line test only if not ignore memory test
695 if (Private
->CoverLevel
!= IGNORE
) {
696 Status
= PerformAddressDataLineTest (Private
);
697 ASSERT_EFI_ERROR (Status
);
701 // Add the non tested memory range to system memory map through GCD service
703 UpdateMemoryMap (Private
);
706 // we need to free all the memory allocate
708 DestroyLinkList (Private
);
714 Provides the capability to test the compatible range used by some special drivers.
716 @param[in] This The protocol instance pointer.
717 @param[in] StartAddress The start address of the compatible memory range that
719 @param[in] Length The compatible memory range's length.
721 @retval EFI_SUCCESS The compatible memory range pass the memory test.
722 @retval EFI_INVALID_PARAMETER The compatible memory range are not below Low 16M.
727 GenCompatibleRangeTest (
728 IN EFI_GENERIC_MEMORY_TEST_PROTOCOL
*This
,
729 IN EFI_PHYSICAL_ADDRESS StartAddress
,
734 GENERIC_MEMORY_TEST_PRIVATE
*Private
;
735 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
736 EFI_PHYSICAL_ADDRESS CurrentBase
;
737 UINT64 CurrentLength
;
739 Private
= GENERIC_MEMORY_TEST_PRIVATE_FROM_THIS (This
);
742 // Check if the parameter is below 16MB
744 if (StartAddress
+ Length
> 0x1000000) {
745 return EFI_INVALID_PARAMETER
;
748 CurrentBase
= StartAddress
;
751 // Check the required memory range status; if the required memory range span
752 // the different GCD memory descriptor, it may be cause different action.
754 Status
= gDS
->GetMemorySpaceDescriptor (
758 if (EFI_ERROR (Status
)) {
762 if ((Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeReserved
) &&
763 ((Descriptor
.Capabilities
& (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
)) ==
764 (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
))
767 CurrentLength
= Descriptor
.BaseAddress
+ Descriptor
.Length
- CurrentBase
;
768 if (CurrentBase
+ CurrentLength
> StartAddress
+ Length
) {
769 CurrentLength
= StartAddress
+ Length
- CurrentBase
;
772 Status
= DirectRangeTest (
776 Descriptor
.Capabilities
778 if (EFI_ERROR (Status
)) {
783 CurrentBase
= Descriptor
.BaseAddress
+ Descriptor
.Length
;
784 } while (CurrentBase
< StartAddress
+ Length
);
787 // Here means the required range already be tested, so just return success.
793 Perform the address line walking ones test.
795 @param[in] Private Point to generic memory test driver's private data.
797 @retval EFI_SUCCESS Successful finished walking ones test.
798 @retval EFI_OUT_OF_RESOURCE Could not get resource in base memory.
799 @retval EFI_ACCESS_DENIED Code may can not run here because if walking one test
800 failed, system may be already halt.
804 PerformAddressDataLineTest (
805 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
808 LIST_ENTRY
*ExtendedLink
;
809 NONTESTED_MEMORY_RANGE
*ExtendedRange
;
810 BOOLEAN InExtendedRange
;
811 EFI_PHYSICAL_ADDRESS TestAddress
;
814 // Light version no data line test, only perform the address line test
816 TestAddress
= (EFI_PHYSICAL_ADDRESS
)0x1;
817 while (TestAddress
< MAX_ADDRESS
&& TestAddress
> 0) {
819 // only test if the address falls in the enabled range
821 InExtendedRange
= FALSE
;
822 ExtendedLink
= Private
->NonTestedMemRanList
.BackLink
;
823 while (ExtendedLink
!= &Private
->NonTestedMemRanList
) {
824 ExtendedRange
= NONTESTED_MEMORY_RANGE_FROM_LINK (ExtendedLink
);
825 if ((TestAddress
>= ExtendedRange
->StartAddress
) &&
826 (TestAddress
< (ExtendedRange
->StartAddress
+ ExtendedRange
->Length
))
829 InExtendedRange
= TRUE
;
832 ExtendedLink
= ExtendedLink
->BackLink
;
835 if (InExtendedRange
) {
836 *(EFI_PHYSICAL_ADDRESS
*)(UINTN
)TestAddress
= TestAddress
;
837 Private
->Cpu
->FlushDataCache (Private
->Cpu
, TestAddress
, 1, EfiCpuFlushTypeWriteBackInvalidate
);
838 if (*(EFI_PHYSICAL_ADDRESS
*)(UINTN
)TestAddress
!= TestAddress
) {
839 return EFI_ACCESS_DENIED
;
843 TestAddress
= LShiftU64 (TestAddress
, 1);
852 GENERIC_MEMORY_TEST_PRIVATE mGenericMemoryTestPrivate
= {
853 EFI_GENERIC_MEMORY_TEST_PRIVATE_SIGNATURE
,
857 InitializeMemoryTest
,
858 GenPerformMemoryTest
,
859 GenMemoryTestFinished
,
860 GenCompatibleRangeTest
862 (EXTENDMEM_COVERAGE_LEVEL
)0,
875 The generic memory test driver's entry point.
877 It initializes private data to default value.
879 @param[in] ImageHandle The firmware allocated handle for the EFI image.
880 @param[in] SystemTable A pointer to the EFI System Table.
882 @retval EFI_SUCCESS The entry point is executed successfully.
883 @retval EFI_NOT_FOUND Can't find HandOff Hob in HobList.
884 @retval other Some error occurs when executing this entry point.
889 GenericMemoryTestEntryPoint (
890 IN EFI_HANDLE ImageHandle
,
891 IN EFI_SYSTEM_TABLE
*SystemTable
896 EFI_BOOT_MODE BootMode
;
897 EFI_PEI_HOB_POINTERS Hob
;
900 // Use the generic pattern to test compatible memory range
902 mGenericMemoryTestPrivate
.MonoPattern
= GenericMemoryTestMonoPattern
;
903 mGenericMemoryTestPrivate
.MonoTestSize
= GENERIC_CACHELINE_SIZE
;
906 // Get the platform boot mode
908 HobList
= GetHobList ();
911 if (Hob
.Header
->HobType
!= EFI_HOB_TYPE_HANDOFF
) {
912 return EFI_NOT_FOUND
;
915 BootMode
= Hob
.HandoffInformationTable
->BootMode
;
918 // Get the platform boot mode and create the default memory test coverage
919 // level and span size for compatible memory test using
922 case BOOT_WITH_FULL_CONFIGURATION
:
923 case BOOT_WITH_DEFAULT_SETTINGS
:
924 mGenericMemoryTestPrivate
.CoverageSpan
= SPARSE_SPAN_SIZE
;
927 case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS
:
928 mGenericMemoryTestPrivate
.CoverageSpan
= GENERIC_CACHELINE_SIZE
;
932 mGenericMemoryTestPrivate
.CoverageSpan
= QUICK_SPAN_SIZE
;
937 // Install the protocol
939 Status
= gBS
->InstallProtocolInterface (
940 &mGenericMemoryTestPrivate
.Handle
,
941 &gEfiGenericMemTestProtocolGuid
,
942 EFI_NATIVE_INTERFACE
,
943 &mGenericMemoryTestPrivate
.GenericMemoryTest