]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Library/BaseMemoryTestLib/BaseMemoryTestLib.c
This checkin addresses the compatibility issue of passing arguments of type VA_LIST...
[mirror_edk2.git] / MdeModulePkg / Library / BaseMemoryTestLib / BaseMemoryTestLib.c
1 /** @file
2 Null instance of Memory Test Library.
3
4 Copyright (c) 2009, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 **/
13
14 #include <Base.h>
15 #include <Library/MemoryTestLib.h>
16 #include <Library/BaseMemoryLib.h>
17 #include <Library/CacheMaintenanceLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/PcdLib.h>
20 #include <Library/ReportStatusCodeLib.h>
21
22
23 UINT32 TestPattern[] = {
24 0x5a5a5a5a,
25 0xa5a5a5a5,
26 0x5a5a5a5a,
27 0xa5a5a5a5,
28 0x5a5a5a5a,
29 0xa5a5a5a5,
30 0x5a5a5a5a,
31 0xa5a5a5a5,
32 0x5a5a5a5a,
33 0xa5a5a5a5,
34 0x5a5a5a5a,
35 0xa5a5a5a5,
36 0x5a5a5a5a,
37 0xa5a5a5a5,
38 0x5a5a5a5a,
39 0xa5a5a5a5
40 };
41
42 /**
43 Internal function to compare two memory buffers of a given length.
44
45 This is the internal function to compare two memory buffers. We cannot
46 use CompareMem() in BaseLib, for that function ASSERT when buffer address
47 is zero.
48
49 @param DestinationBuffer First memory buffer
50 @param SourceBuffer Second memory buffer
51 @param Length Length of DestinationBuffer and SourceBuffer memory
52 regions to compare.
53
54 @return 0 All Length bytes of the two buffers are identical.
55 @retval Non-zero The first mismatched byte in SourceBuffer subtracted from the first
56 mismatched byte in DestinationBuffer.
57
58 **/
59 INTN
60 CompareMemoryWorker (
61 IN CONST VOID *DestinationBuffer,
62 IN CONST VOID *SourceBuffer,
63 IN UINTN Length
64 )
65 {
66 while ((--Length != 0) &&
67 (*(INT8*)DestinationBuffer == *(INT8*)SourceBuffer)) {
68 DestinationBuffer = (INT8*)DestinationBuffer + 1;
69 SourceBuffer = (INT8*)SourceBuffer + 1;
70 }
71 return (INTN)*(UINT8*)DestinationBuffer - (INTN)*(UINT8*)SourceBuffer;
72 }
73
74 /**
75 Internal worker function for system memory range test.
76
77 This function is the internal worker function for system memory range test.
78 It writes test pattern to memory range and then reads back to check if memory
79 works well.
80
81 @param StartAddress Start address of the memory range to test.
82 @param Length Length of the memory range to test.
83 @param ErrorAddress Address of the memory where error is encountered.
84
85 @retval RETURN_SUCCESS The memory range passes test.
86 @retval RETURN_DEVICE_ERROR The memory range does not pass test.
87
88 **/
89 RETURN_STATUS
90 MemoryTestWorker (
91 IN VOID *StartAddress,
92 IN UINT64 Length,
93 IN UINTN SpanSize,
94 OUT VOID **ErrorAddress
95 )
96 {
97 VOID *TempAddress;
98
99 //
100 // Make sure we don't try and test anything above the max physical address range
101 //
102 ASSERT ((UINTN) StartAddress + Length < MAX_ADDRESS);
103
104 REPORT_STATUS_CODE (EFI_PROGRESS_CODE, PcdGet32 (PcdStatusCodeValueMemoryTestStarted));
105
106 //
107 // Write the test pattern into memory range
108 //
109 TempAddress = StartAddress;
110 while ((UINTN) TempAddress < (UINTN) StartAddress + Length) {
111 CopyMem (TempAddress, TestPattern, sizeof (TestPattern));
112 TempAddress = (VOID *) ((UINTN) TempAddress + SpanSize);
113 }
114
115 //
116 // Write back and invalidate cache to make sure data is in memory
117 //
118 WriteBackInvalidateDataCacheRange (StartAddress, (UINTN) Length);
119
120 //
121 // Read pattern from memory and compare it
122 //
123 TempAddress = StartAddress;
124 while ((UINTN) TempAddress < (UINTN) StartAddress + Length) {
125 if (CompareMemoryWorker (TempAddress, TestPattern, sizeof (TestPattern)) != 0) {
126 //
127 // Value read back does not equal to the value written, so error is detected.
128 //
129 *ErrorAddress = TempAddress;
130 REPORT_STATUS_CODE (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED, PcdGet32 (PcdStatusCodeValueUncorrectableMemoryError));
131
132 return RETURN_DEVICE_ERROR;
133 }
134
135 TempAddress = (VOID *) ((UINTN) TempAddress + SpanSize);
136 }
137
138 return RETURN_SUCCESS;
139 }
140
141 /**
142 Perform a quick system memory range test.
143
144 This function performs a quick system memory range test. It leads to quick performance
145 but least reliability.
146
147 @param StartAddress Start address of the memory range to test.
148 @param Length Length of the memory range to test.
149 @param ErrorAddress Address of the memory where error is encountered.
150
151 @retval RETURN_SUCCESS The memory range passes test.
152 @retval RETURN_DEVICE_ERROR The memory range does not pass test.
153
154 **/
155 RETURN_STATUS
156 EFIAPI
157 QuickMemoryTest (
158 IN VOID *StartAddress,
159 IN UINT64 Length,
160 OUT VOID **ErrorAddress
161 )
162 {
163 RETURN_STATUS Status;
164
165 Status = MemoryTestWorker (
166 StartAddress,
167 Length,
168 sizeof (TestPattern) * 0x20000,
169 ErrorAddress
170 );
171
172 return Status;
173 }
174
175 /**
176 Test a system memory range with sparsely sampled memory units.
177
178 This function tests a system memory range, whose memory units
179 are sampled sparsely. It leads to relatively good performance
180 and partial reliability.
181
182 @param StartAddress Start address of the memory range to test.
183 @param Length Length of the memory range to test.
184 @param ErrorAddress Address of the memory where error is encountered.
185
186 @retval RETURN_SUCCESS The memory range passes test.
187 @retval RETURN_DEVICE_ERROR The memory range does not pass test.
188
189 **/
190 RETURN_STATUS
191 EFIAPI
192 SparseMemoryTest (
193 IN VOID *StartAddress,
194 IN UINT64 Length,
195 OUT VOID **ErrorAddress
196 )
197 {
198 RETURN_STATUS Status;
199
200 Status = MemoryTestWorker (
201 StartAddress,
202 Length,
203 sizeof (TestPattern) * 0x8000,
204 ErrorAddress
205 );
206
207 return Status;
208 }
209
210 /**
211 Test a system memory range with extensively sampled memory units.
212
213 This function tests a system memory range, whose memory units
214 are sampled extensively. Compared with SparseMemoryTest, it achieves
215 more reliability and less performance.
216
217 @param StartAddress Start address of the memory range to test.
218 @param Length Length of the memory range to test.
219 @param ErrorAddress Address of the memory where error is encountered.
220
221 @retval RETURN_SUCCESS The memory range passes test.
222 @retval RETURN_DEVICE_ERROR The memory range does not pass test.
223
224 **/
225 RETURN_STATUS
226 EFIAPI
227 ExtensiveMemoryTest (
228 IN VOID *StartAddress,
229 IN UINT64 Length,
230 OUT VOID **ErrorAddress
231 )
232 {
233 RETURN_STATUS Status;
234
235 Status = MemoryTestWorker (
236 StartAddress,
237 Length,
238 sizeof (TestPattern),
239 ErrorAddress
240 );
241
242 return Status;
243 }
244
245 /**
246 Check if soft ECC initialzation is needed for system
247
248 @retval TRUE Soft ECC initialzation is needed.
249 @retval FALSE Soft ECC initialzation is not needed.
250
251 **/
252 BOOLEAN
253 EFIAPI
254 IsSoftEccInitRequired (
255 VOID
256 )
257 {
258 return FALSE;
259 }