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