3 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions
7 of the BSD License which accompanies this distribution. The
8 full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "LightMemoryTest.h"
20 // Since this driver will only ever produce one instance of the memory test
21 // protocol, so we do not need to dynamically allocate the PrivateData.
23 EFI_PHYSICAL_ADDRESS mCurrentAddress
;
24 LIST_ENTRY
*mCurrentLink
;
25 NONTESTED_MEMORY_RANGE
*mCurrentRange
;
26 UINT64 mTestedSystemMemory
;
27 UINT64 mNonTestedSystemMemory
;
29 UINT32 GenericMemoryTestMonoPattern
[GENERIC_CACHELINE_SIZE
/ 4] = {
49 Compares the contents of two buffers.
51 This function compares Length bytes of SourceBuffer to Length bytes of DestinationBuffer.
52 If all Length bytes of the two buffers are identical, then 0 is returned. Otherwise, the
53 value returned is the first mismatched byte in SourceBuffer subtracted from the first
54 mismatched byte in DestinationBuffer.
56 If Length = 0, then ASSERT().
58 @param[in] DestinationBuffer The pointer to the destination buffer to compare.
59 @param[in] SourceBuffer The pointer to the source buffer to compare.
60 @param[in] Length The number of bytes to compare.
62 @return 0 All Length bytes of the two buffers are identical.
63 @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first
64 mismatched byte in DestinationBuffer.
69 CompareMemWithoutCheckArgument (
70 IN CONST VOID
*DestinationBuffer
,
71 IN CONST VOID
*SourceBuffer
,
76 while ((--Length
!= 0) &&
77 (*(INT8
*)DestinationBuffer
== *(INT8
*)SourceBuffer
)) {
78 DestinationBuffer
= (INT8
*)DestinationBuffer
+ 1;
79 SourceBuffer
= (INT8
*)SourceBuffer
+ 1;
81 return (INTN
)*(UINT8
*)DestinationBuffer
- (INTN
)*(UINT8
*)SourceBuffer
;
85 Construct the system base memory range through GCD service.
87 @param[in] Private Point to generic memory test driver's private data.
89 @retval EFI_SUCCESS Successful construct the base memory range through GCD service.
90 @retval EFI_OUT_OF_RESOURCE Could not allocate needed resource from base memory.
91 @retval Others Failed to construct base memory range through GCD service.
95 ConstructBaseMemoryRange (
96 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
99 UINTN NumberOfDescriptors
;
100 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
104 // Base memory will always below 4G
106 gDS
->GetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
108 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
109 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeSystemMemory
) {
110 Private
->BaseMemorySize
+= MemorySpaceMap
[Index
].Length
;
118 Destroy the link list base on the correspond link list type.
120 @param[in] Private Point to generic memory test driver's private data.
125 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
129 NONTESTED_MEMORY_RANGE
*NontestedRange
;
131 Link
= Private
->NonTestedMemRanList
.BackLink
;
133 while (Link
!= &Private
->NonTestedMemRanList
) {
134 RemoveEntryList (Link
);
135 NontestedRange
= NONTESTED_MEMORY_RANGE_FROM_LINK (Link
);
136 gBS
->FreePool (NontestedRange
);
137 Link
= Private
->NonTestedMemRanList
.BackLink
;;
142 Add the extened memory to whole system memory map.
144 @param[in] Private Point to generic memory test driver's private data.
146 @retval EFI_SUCCESS Successful add all the extended memory to system memory map.
147 @retval Others Failed to add the tested extended memory.
152 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
156 NONTESTED_MEMORY_RANGE
*Range
;
158 Link
= Private
->NonTestedMemRanList
.ForwardLink
;
160 while (Link
!= &Private
->NonTestedMemRanList
) {
161 Range
= NONTESTED_MEMORY_RANGE_FROM_LINK (Link
);
163 gDS
->RemoveMemorySpace (
168 gDS
->AddMemorySpace (
169 EfiGcdMemoryTypeSystemMemory
,
172 Range
->Capabilities
&~(EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
| EFI_MEMORY_RUNTIME
)
175 Link
= Link
->ForwardLink
;
182 Test a range of the memory directly .
184 @param[in] Private Point to generic memory test driver's private data.
185 @param[in] StartAddress Starting address of the memory range to be tested.
186 @param[in] Length Length in bytes of the memory range to be tested.
187 @param[in] Capabilities The bit mask of attributes that the memory range supports.
189 @retval EFI_SUCCESS Successful test the range of memory.
190 @retval Others Failed to test the range of memory.
195 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
,
196 IN EFI_PHYSICAL_ADDRESS StartAddress
,
198 IN UINT64 Capabilities
204 // Perform a dummy memory test, so directly write the pattern to all range
206 WriteMemory (Private
, StartAddress
, Length
);
209 // Verify the memory range
211 Status
= VerifyMemory (Private
, StartAddress
, Length
);
212 if (EFI_ERROR (Status
)) {
216 // Add the tested compatible memory to system memory using GCD service
218 gDS
->RemoveMemorySpace (
223 gDS
->AddMemorySpace (
224 EfiGcdMemoryTypeSystemMemory
,
227 Capabilities
&~(EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
| EFI_MEMORY_RUNTIME
)
234 Construct the system non-tested memory range through GCD service.
236 @param[in] Private Point to generic memory test driver's private data.
238 @retval EFI_SUCCESS Successful construct the non-tested memory range through GCD service.
239 @retval EFI_OUT_OF_RESOURCE Could not allocate needed resource from base memory.
240 @retval Others Failed to construct non-tested memory range through GCD service.
244 ConstructNonTestedMemoryRange (
245 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
248 NONTESTED_MEMORY_RANGE
*Range
;
250 UINTN NumberOfDescriptors
;
251 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
255 // Non tested memory range may be span 4G here
259 gDS
->GetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
261 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
262 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeReserved
&&
263 (MemorySpaceMap
[Index
].Capabilities
& (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
)) ==
264 (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
)
268 // Light version do not need to process >4G memory range
272 sizeof (NONTESTED_MEMORY_RANGE
),
276 Range
->Signature
= EFI_NONTESTED_MEMORY_RANGE_SIGNATURE
;
277 Range
->StartAddress
= MemorySpaceMap
[Index
].BaseAddress
;
278 Range
->Length
= MemorySpaceMap
[Index
].Length
;
279 Range
->Capabilities
= MemorySpaceMap
[Index
].Capabilities
;
281 mNonTestedSystemMemory
+= MemorySpaceMap
[Index
].Length
;
282 InsertTailList (&Private
->NonTestedMemRanList
, &Range
->Link
);
287 return EFI_NOT_FOUND
;
294 Write the memory test pattern into a range of physical memory.
296 @param[in] Private Point to generic memory test driver's private data.
297 @param[in] Start The memory range's start address.
298 @param[in] Size The memory range's size.
300 @retval EFI_SUCCESS Successful write the test pattern into the non-tested memory.
301 @retval Others The test pattern may not really write into the physical memory.
306 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
,
307 IN EFI_PHYSICAL_ADDRESS Start
,
311 EFI_PHYSICAL_ADDRESS Address
;
316 // Add 4G memory address check for IA32 platform
317 // NOTE: Without page table, there is no way to use memory above 4G.
319 if (Start
+ Size
> MAX_ADDRESS
) {
323 while (Address
< (Start
+ Size
)) {
324 CopyMem ((VOID
*) (UINTN
) Address
, Private
->MonoPattern
, Private
->MonoTestSize
);
325 Address
+= Private
->CoverageSpan
;
328 // bug bug: we may need GCD service to make the code cache and data uncache,
329 // if GCD do not support it or return fail, then just flush the whole cache.
331 if (Private
->Cpu
!= NULL
) {
332 Private
->Cpu
->FlushDataCache (Private
->Cpu
, Start
, Size
, EfiCpuFlushTypeWriteBackInvalidate
);
339 Verify the range of physical memory which covered by memory test pattern.
341 This function will also do not return any informatin just cause system reset,
342 because the handle error encount fatal error and disable the bad DIMMs.
344 @param[in] Private Point to generic memory test driver's private data.
345 @param[in] Start The memory range's start address.
346 @param[in] Size The memory range's size.
348 @retval EFI_SUCCESS Successful verify the range of memory, no errors' location found.
349 @retval Others The range of memory have errors contained.
354 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
,
355 IN EFI_PHYSICAL_ADDRESS Start
,
359 EFI_PHYSICAL_ADDRESS Address
;
361 EFI_MEMORY_EXTENDED_ERROR_DATA
*ExtendedErrorData
;
364 ExtendedErrorData
= NULL
;
367 // Add 4G memory address check for IA32 platform
368 // NOTE: Without page table, there is no way to use memory above 4G.
370 if (Start
+ Size
> MAX_ADDRESS
) {
375 // Use the software memory test to check whether have detected miscompare
376 // error here. If there is miscompare error here then check if generic
377 // memory test driver can disable the bad DIMM.
379 while (Address
< (Start
+ Size
)) {
380 ErrorFound
= CompareMemWithoutCheckArgument (
381 (VOID
*) (UINTN
) (Address
),
382 Private
->MonoPattern
,
383 Private
->MonoTestSize
385 if (ErrorFound
!= 0) {
387 // Report uncorrectable errors
389 ExtendedErrorData
= AllocateZeroPool (sizeof (EFI_MEMORY_EXTENDED_ERROR_DATA
));
390 if (ExtendedErrorData
== NULL
) {
391 return EFI_OUT_OF_RESOURCES
;
394 ExtendedErrorData
->DataHeader
.HeaderSize
= (UINT16
) sizeof (EFI_STATUS_CODE_DATA
);
395 ExtendedErrorData
->DataHeader
.Size
= (UINT16
) (sizeof (EFI_MEMORY_EXTENDED_ERROR_DATA
) - sizeof (EFI_STATUS_CODE_DATA
));
396 ExtendedErrorData
->Granularity
= EFI_MEMORY_ERROR_DEVICE
;
397 ExtendedErrorData
->Operation
= EFI_MEMORY_OPERATION_READ
;
398 ExtendedErrorData
->Syndrome
= 0x0;
399 ExtendedErrorData
->Address
= Address
;
400 ExtendedErrorData
->Resolution
= 0x40;
402 REPORT_STATUS_CODE_EX (
404 EFI_COMPUTING_UNIT_MEMORY
| EFI_CU_MEMORY_EC_UNCORRECTABLE
,
406 &gEfiGenericMemTestProtocolGuid
,
408 (UINT8
*) ExtendedErrorData
+ sizeof (EFI_STATUS_CODE_DATA
),
409 ExtendedErrorData
->DataHeader
.Size
412 return EFI_DEVICE_ERROR
;
415 Address
+= Private
->CoverageSpan
;
422 Initialize the generic memory test.
424 @param[in] This The protocol instance pointer.
425 @param[in] Level The coverage level of the memory test.
426 @param[out] RequireSoftECCInit Indicate if the memory need software ECC init.
428 @retval EFI_SUCCESS The generic memory test is initialized correctly.
429 @retval EFI_NO_MEDIA The system had no memory to be tested.
434 InitializeMemoryTest (
435 IN EFI_GENERIC_MEMORY_TEST_PROTOCOL
*This
,
436 IN EXTENDMEM_COVERAGE_LEVEL Level
,
437 OUT BOOLEAN
*RequireSoftECCInit
441 GENERIC_MEMORY_TEST_PRIVATE
*Private
;
442 EFI_CPU_ARCH_PROTOCOL
*Cpu
;
444 Private
= GENERIC_MEMORY_TEST_PRIVATE_FROM_THIS (This
);
445 *RequireSoftECCInit
= FALSE
;
448 // This is initialize for default value, but some value may be reset base on
449 // platform memory test driver.
451 Private
->CoverLevel
= Level
;
452 Private
->BdsBlockSize
= TEST_BLOCK_SIZE
;
453 Private
->MonoPattern
= GenericMemoryTestMonoPattern
;
454 Private
->MonoTestSize
= GENERIC_CACHELINE_SIZE
;
457 // Initialize several internal link list
459 InitializeListHead (&Private
->NonTestedMemRanList
);
462 // Construct base memory range
464 ConstructBaseMemoryRange (Private
);
467 // get the cpu arch protocol to support flash cache
469 Status
= gBS
->LocateProtocol (
470 &gEfiCpuArchProtocolGuid
,
474 if (!EFI_ERROR (Status
)) {
478 // Create the CoverageSpan of the memory test base on the coverage level
480 switch (Private
->CoverLevel
) {
482 Private
->CoverageSpan
= GENERIC_CACHELINE_SIZE
;
486 Private
->CoverageSpan
= SPARSE_SPAN_SIZE
;
490 // Even the BDS do not need to test any memory, but in some case it
491 // still need to init ECC memory.
494 Private
->CoverageSpan
= QUICK_SPAN_SIZE
;
498 // This is the first time we construct the non-tested memory range, if no
499 // extended memory found, we know the system have not any extended memory
502 Status
= ConstructNonTestedMemoryRange (Private
);
503 if (Status
== EFI_NOT_FOUND
) {
507 // ready to perform the R/W/V memory test
509 mTestedSystemMemory
= Private
->BaseMemorySize
;
510 mCurrentLink
= Private
->NonTestedMemRanList
.ForwardLink
;
511 mCurrentRange
= NONTESTED_MEMORY_RANGE_FROM_LINK (mCurrentLink
);
512 mCurrentAddress
= mCurrentRange
->StartAddress
;
518 Perform the memory test.
520 @param[in] This The protocol instance pointer.
521 @param[out] TestedMemorySize Return the tested extended memory size.
522 @param[out] TotalMemorySize Return the whole system physical memory size.
523 The total memory size does not include memory in a slot with a disabled DIMM.
524 @param[out] ErrorOut TRUE if the memory error occured.
525 @param[in] IfTestAbort Indicates that the user pressed "ESC" to skip the memory test.
527 @retval EFI_SUCCESS One block of memory passed the test.
528 @retval EFI_NOT_FOUND All memory blocks have already been tested.
529 @retval EFI_DEVICE_ERROR Memory device error occured, and no agent can handle it.
534 GenPerformMemoryTest (
535 IN EFI_GENERIC_MEMORY_TEST_PROTOCOL
*This
,
536 OUT UINT64
*TestedMemorySize
,
537 OUT UINT64
*TotalMemorySize
,
538 OUT BOOLEAN
*ErrorOut
,
543 GENERIC_MEMORY_TEST_PRIVATE
*Private
;
544 EFI_MEMORY_RANGE_EXTENDED_DATA
*RangeData
;
545 UINT64 BlockBoundary
;
547 Private
= GENERIC_MEMORY_TEST_PRIVATE_FROM_THIS (This
);
553 // In extensive mode the boundary of "mCurrentRange->Length" may will lost
554 // some range that is not Private->BdsBlockSize size boundry, so need
555 // the software mechanism to confirm all memory location be covered.
557 if (mCurrentAddress
< (mCurrentRange
->StartAddress
+ mCurrentRange
->Length
)) {
558 if ((mCurrentAddress
+ Private
->BdsBlockSize
) <= (mCurrentRange
->StartAddress
+ mCurrentRange
->Length
)) {
559 BlockBoundary
= Private
->BdsBlockSize
;
561 BlockBoundary
= mCurrentRange
->StartAddress
+ mCurrentRange
->Length
- mCurrentAddress
;
564 // If TestAbort is true, means user cancel the memory test
566 if (!TestAbort
&& Private
->CoverLevel
!= IGNORE
) {
568 // Report status code of every memory range
570 RangeData
= AllocateZeroPool (sizeof (EFI_MEMORY_RANGE_EXTENDED_DATA
));
571 if (RangeData
== NULL
) {
572 return EFI_OUT_OF_RESOURCES
;
574 RangeData
->DataHeader
.HeaderSize
= (UINT16
) sizeof (EFI_STATUS_CODE_DATA
);
575 RangeData
->DataHeader
.Size
= (UINT16
) (sizeof (EFI_MEMORY_RANGE_EXTENDED_DATA
) - sizeof (EFI_STATUS_CODE_DATA
));
576 RangeData
->Start
= mCurrentAddress
;
577 RangeData
->Length
= BlockBoundary
;
579 REPORT_STATUS_CODE_EX (
581 EFI_COMPUTING_UNIT_MEMORY
| EFI_CU_MEMORY_PC_TEST
,
583 &gEfiGenericMemTestProtocolGuid
,
585 (UINT8
*) RangeData
+ sizeof (EFI_STATUS_CODE_DATA
),
586 RangeData
->DataHeader
.Size
590 // The software memory test (R/W/V) perform here. It will detect the
591 // memory mis-compare error.
593 WriteMemory (Private
, mCurrentAddress
, BlockBoundary
);
595 Status
= VerifyMemory (Private
, mCurrentAddress
, BlockBoundary
);
596 if (EFI_ERROR (Status
)) {
598 // If perform here, means there is mis-compare error, and no agent can
599 // handle it, so we return to BDS EFI_DEVICE_ERROR.
602 return EFI_DEVICE_ERROR
;
606 mTestedSystemMemory
+= BlockBoundary
;
607 *TestedMemorySize
= mTestedSystemMemory
;
610 // If the memory test restart after the platform driver disable dimms,
611 // the NonTestSystemMemory may be changed, but the base memory size will
612 // not changed, so we can get the current total memory size.
614 *TotalMemorySize
= Private
->BaseMemorySize
+ mNonTestedSystemMemory
;
617 // Update the current test address pointing to next BDS BLOCK
619 mCurrentAddress
+= Private
->BdsBlockSize
;
624 // Change to next non tested memory range
626 mCurrentLink
= mCurrentLink
->ForwardLink
;
627 if (mCurrentLink
!= &Private
->NonTestedMemRanList
) {
628 mCurrentRange
= NONTESTED_MEMORY_RANGE_FROM_LINK (mCurrentLink
);
629 mCurrentAddress
= mCurrentRange
->StartAddress
;
633 // Here means all the memory test have finished
635 *TestedMemorySize
= mTestedSystemMemory
;
636 *TotalMemorySize
= Private
->BaseMemorySize
+ mNonTestedSystemMemory
;
637 return EFI_NOT_FOUND
;
643 Finish the memory test.
645 @param[in] This The protocol instance pointer.
647 @retval EFI_SUCCESS Success. All resources used in the memory test are freed.
652 GenMemoryTestFinished (
653 IN EFI_GENERIC_MEMORY_TEST_PROTOCOL
*This
657 GENERIC_MEMORY_TEST_PRIVATE
*Private
;
659 Private
= GENERIC_MEMORY_TEST_PRIVATE_FROM_THIS (This
);
662 // Perform Data and Address line test
664 Status
= PerformAddressDataLineTest (Private
);
665 ASSERT_EFI_ERROR (Status
);
668 // Add the non tested memory range to system memory map through GCD service
670 UpdateMemoryMap (Private
);
673 // we need to free all the memory allocate
675 DestroyLinkList (Private
);
681 Provides the capability to test the compatible range used by some special drivers.
683 @param[in] This The protocol instance pointer.
684 @param[in] StartAddress The start address of the compatible memory range that
686 @param[in] Length The compatible memory range's length.
688 @retval EFI_SUCCESS The compatible memory range pass the memory test.
689 @retval EFI_INVALID_PARAMETER The compatible memory range are not below Low 16M.
694 GenCompatibleRangeTest (
695 IN EFI_GENERIC_MEMORY_TEST_PROTOCOL
*This
,
696 IN EFI_PHYSICAL_ADDRESS StartAddress
,
701 GENERIC_MEMORY_TEST_PRIVATE
*Private
;
702 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
703 EFI_PHYSICAL_ADDRESS CurrentBase
;
704 UINT64 CurrentLength
;
706 Private
= GENERIC_MEMORY_TEST_PRIVATE_FROM_THIS (This
);
709 // Check if the parameter is below 16MB
711 if (StartAddress
+ Length
> 0x1000000) {
712 return EFI_INVALID_PARAMETER
;
714 CurrentBase
= StartAddress
;
717 // Check the required memory range status; if the required memory range span
718 // the different GCD memory descriptor, it may be cause different action.
720 Status
= gDS
->GetMemorySpaceDescriptor (
724 if (EFI_ERROR (Status
)) {
728 if (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeReserved
&&
729 (Descriptor
.Capabilities
& (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
)) ==
730 (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
)
732 CurrentLength
= Descriptor
.BaseAddress
+ Descriptor
.Length
- CurrentBase
;
733 if (CurrentBase
+ CurrentLength
> StartAddress
+ Length
) {
734 CurrentLength
= StartAddress
+ Length
- CurrentBase
;
736 Status
= DirectRangeTest (
740 Descriptor
.Capabilities
742 if (EFI_ERROR (Status
)) {
746 CurrentBase
= Descriptor
.BaseAddress
+ Descriptor
.Length
;
747 } while (CurrentBase
< StartAddress
+ Length
);
749 // Here means the required range already be tested, so just return success.
755 Perform the address line walking ones test.
757 @param[in] Private Point to generic memory test driver's private data.
759 @retval EFI_SUCCESS Successful finished walking ones test.
760 @retval EFI_OUT_OF_RESOURCE Could not get resource in base memory.
761 @retval EFI_ACCESS_DENIED Code may can not run here because if walking one test
762 failed, system may be already halt.
766 PerformAddressDataLineTest (
767 IN GENERIC_MEMORY_TEST_PRIVATE
*Private
770 LIST_ENTRY
*ExtendedLink
;
771 NONTESTED_MEMORY_RANGE
*ExtendedRange
;
772 BOOLEAN InExtendedRange
;
773 EFI_PHYSICAL_ADDRESS TestAddress
;
776 // Light version no data line test, only perform the address line test
778 TestAddress
= (EFI_PHYSICAL_ADDRESS
) 0x1;
779 while (TestAddress
< MAX_ADDRESS
&& TestAddress
> 0) {
781 // only test if the address falls in the enabled range
783 InExtendedRange
= FALSE
;
784 ExtendedLink
= Private
->NonTestedMemRanList
.BackLink
;
785 while (ExtendedLink
!= &Private
->NonTestedMemRanList
) {
786 ExtendedRange
= NONTESTED_MEMORY_RANGE_FROM_LINK (ExtendedLink
);
787 if ((TestAddress
>= ExtendedRange
->StartAddress
) &&
788 (TestAddress
< (ExtendedRange
->StartAddress
+ ExtendedRange
->Length
))
790 InExtendedRange
= TRUE
;
793 ExtendedLink
= ExtendedLink
->BackLink
;
796 if (InExtendedRange
) {
797 *(EFI_PHYSICAL_ADDRESS
*) (UINTN
) TestAddress
= TestAddress
;
798 Private
->Cpu
->FlushDataCache (Private
->Cpu
, TestAddress
, 1, EfiCpuFlushTypeWriteBackInvalidate
);
799 if (*(EFI_PHYSICAL_ADDRESS
*) (UINTN
) TestAddress
!= TestAddress
) {
800 return EFI_ACCESS_DENIED
;
804 TestAddress
= LShiftU64 (TestAddress
, 1);
812 GENERIC_MEMORY_TEST_PRIVATE mGenericMemoryTestPrivate
= {
813 EFI_GENERIC_MEMORY_TEST_PRIVATE_SIGNATURE
,
817 InitializeMemoryTest
,
818 GenPerformMemoryTest
,
819 GenMemoryTestFinished
,
820 GenCompatibleRangeTest
822 (EXTENDMEM_COVERAGE_LEVEL
) 0,
835 The generic memory test driver's entry point.
837 It initializes private data to default value.
839 @param[in] ImageHandle The firmware allocated handle for the EFI image.
840 @param[in] SystemTable A pointer to the EFI System Table.
842 @retval EFI_SUCCESS The entry point is executed successfully.
843 @retval EFI_NOT_FOUND Can't find HandOff Hob in HobList.
844 @retval other Some error occurs when executing this entry point.
849 GenericMemoryTestEntryPoint (
850 IN EFI_HANDLE ImageHandle
,
851 IN EFI_SYSTEM_TABLE
*SystemTable
856 EFI_BOOT_MODE BootMode
;
857 EFI_PEI_HOB_POINTERS Hob
;
860 // Use the generic pattern to test compatible memory range
862 mGenericMemoryTestPrivate
.MonoPattern
= GenericMemoryTestMonoPattern
;
863 mGenericMemoryTestPrivate
.MonoTestSize
= GENERIC_CACHELINE_SIZE
;
866 // Get the platform boot mode
868 HobList
= GetHobList ();
871 if (Hob
.Header
->HobType
!= EFI_HOB_TYPE_HANDOFF
) {
872 return EFI_NOT_FOUND
;
875 BootMode
= Hob
.HandoffInformationTable
->BootMode
;
878 // Get the platform boot mode and create the default memory test coverage
879 // level and span size for compatible memory test using
882 case BOOT_WITH_FULL_CONFIGURATION
:
883 case BOOT_WITH_DEFAULT_SETTINGS
:
884 mGenericMemoryTestPrivate
.CoverageSpan
= SPARSE_SPAN_SIZE
;
887 case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS
:
888 mGenericMemoryTestPrivate
.CoverageSpan
= GENERIC_CACHELINE_SIZE
;
892 mGenericMemoryTestPrivate
.CoverageSpan
= QUICK_SPAN_SIZE
;
896 // Install the protocol
898 Status
= gBS
->InstallProtocolInterface (
899 &mGenericMemoryTestPrivate
.Handle
,
900 &gEfiGenericMemTestProtocolGuid
,
901 EFI_NATIVE_INTERFACE
,
902 &mGenericMemoryTestPrivate
.GenericMemoryTest