]> git.proxmox.com Git - mirror_edk2.git/blame - EdkNt32Pkg/Dxe/PlatformBds/Generic/MemoryTest.c
Fixed EDKT419.
[mirror_edk2.git] / EdkNt32Pkg / Dxe / PlatformBds / Generic / MemoryTest.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 MemoryTest.c\r
15\r
16Abstract:\r
17\r
18 Perform the platform memory test\r
19\r
20--*/\r
21\r
22#include "bds.h"\r
23#include "BdsPlatform.h"\r
24#include "String.h"\r
25\r
26//\r
27// BDS Platform Functions\r
28//\r
29EFI_STATUS\r
30PlatformBdsShowProgress (\r
31 IN EFI_UGA_PIXEL TitleForeground,\r
32 IN EFI_UGA_PIXEL TitleBackground,\r
33 IN CHAR16 *Title,\r
34 IN EFI_UGA_PIXEL ProgressColor,\r
35 IN UINTN Progress,\r
36 IN UINTN PreviousValue\r
37 )\r
38/*++\r
39\r
40Routine Description:\r
41 \r
42 Show progress bar with title above it. It only works in UGA mode.\r
43\r
44Arguments:\r
45 \r
46 TitleForeground - Foreground color for Title.\r
47 TitleBackground - Background color for Title.\r
48 Title - Title above progress bar.\r
49 ProgressColor - Progress bar color.\r
50 Progress - Progress (0-100)\r
51\r
52Returns: \r
53 \r
54 EFI_STATUS - Success update the progress bar\r
55\r
56--*/\r
57{\r
58 EFI_STATUS Status;\r
59 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
60 UINT32 SizeOfX;\r
61 UINT32 SizeOfY;\r
62 UINT32 ColorDepth;\r
63 UINT32 RefreshRate;\r
64 EFI_UGA_PIXEL Color;\r
65 UINTN BlockHeight;\r
66 UINTN BlockWidth;\r
67 UINTN BlockNum;\r
68 UINTN PosX;\r
69 UINTN PosY;\r
70 UINTN Index;\r
71\r
72 if (Progress > 100) {\r
73 return EFI_INVALID_PARAMETER;\r
74 }\r
75\r
76 Status = gBS->HandleProtocol (\r
77 gST->ConsoleOutHandle,\r
78 &gEfiUgaDrawProtocolGuid,\r
79 &UgaDraw\r
80 );\r
81 if (EFI_ERROR (Status)) {\r
82 return EFI_UNSUPPORTED;\r
83 }\r
84\r
85 Status = UgaDraw->GetMode (\r
86 UgaDraw,\r
87 &SizeOfX,\r
88 &SizeOfY,\r
89 &ColorDepth,\r
90 &RefreshRate\r
91 );\r
92 if (EFI_ERROR (Status)) {\r
93 return EFI_UNSUPPORTED;\r
94 }\r
95\r
96 BlockWidth = SizeOfX / 100;\r
97 BlockHeight = SizeOfY / 50;\r
98\r
99 BlockNum = Progress;\r
100\r
101 PosX = 0;\r
102 PosY = SizeOfY * 48 / 50;\r
103\r
104 if (BlockNum == 0) {\r
105 //\r
106 // Clear progress area\r
107 //\r
108 SetMem (&Color, sizeof (EFI_UGA_PIXEL), 0x0);\r
109\r
110 Status = UgaDraw->Blt (\r
111 UgaDraw,\r
112 &Color,\r
113 EfiUgaVideoFill,\r
114 0,\r
115 0,\r
116 0,\r
117 PosY - GLYPH_HEIGHT - 1,\r
118 SizeOfX,\r
119 SizeOfY - (PosY - GLYPH_HEIGHT - 1),\r
120 SizeOfX * sizeof (EFI_UGA_PIXEL)\r
121 );\r
122 }\r
123 //\r
124 // Show progress by drawing blocks\r
125 //\r
126 for (Index = PreviousValue; Index < BlockNum; Index++) {\r
127 PosX = Index * BlockWidth;\r
128 Status = UgaDraw->Blt (\r
129 UgaDraw,\r
130 &ProgressColor,\r
131 EfiUgaVideoFill,\r
132 0,\r
133 0,\r
134 PosX,\r
135 PosY,\r
136 BlockWidth - 1,\r
137 BlockHeight,\r
138 (BlockWidth) * sizeof (EFI_UGA_PIXEL)\r
139 );\r
140 }\r
141\r
142 PrintXY (\r
143 (SizeOfX - StrLen (Title) * GLYPH_WIDTH) / 2,\r
144 PosY - GLYPH_HEIGHT - 1,\r
145 &TitleForeground,\r
146 &TitleBackground,\r
147 Title\r
148 );\r
149\r
150 return EFI_SUCCESS;\r
151}\r
152\r
153EFI_STATUS\r
154BdsMemoryTest (\r
155 IN EXTENDMEM_COVERAGE_LEVEL Level\r
156 )\r
157/*++\r
158\r
159Routine Description:\r
160 \r
161 Perform the memory test base on the memory test intensive level, \r
162 and update the memory resource.\r
163\r
164Arguments:\r
165 \r
166 Level - The memory test intensive level.\r
167\r
168Returns: \r
169 \r
170 EFI_STATUS - Success test all the system memory and update\r
171 the memory resource\r
172 \r
173--*/\r
174{\r
175 EFI_STATUS Status;\r
176 EFI_STATUS InitStatus;\r
177 EFI_STATUS KeyStatus;\r
178 EFI_STATUS ReturnStatus;\r
179 BOOLEAN RequireSoftECCInit;\r
180 EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;\r
181 UINT64 TestedMemorySize;\r
182 UINT64 TotalMemorySize;\r
183 UINTN TestPercent;\r
184 UINT64 PreviousValue;\r
185 BOOLEAN ErrorOut;\r
186 BOOLEAN TestAbort;\r
187 EFI_INPUT_KEY Key;\r
188 CHAR16 StrPercent[16];\r
189 CHAR16 *StrTotalMemory;\r
190 CHAR16 *Pos;\r
191 CHAR16 *TmpStr;\r
192 EFI_UGA_PIXEL Foreground;\r
193 EFI_UGA_PIXEL Background;\r
194 EFI_UGA_PIXEL Color;\r
195 UINT8 Value;\r
196 UINTN DataSize;\r
197 UINT32 Attributes;\r
198\r
199 ReturnStatus = EFI_SUCCESS;\r
200 ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
201\r
202 Pos = AllocatePool (128);\r
203\r
204 if (Pos == NULL) {\r
205 return ReturnStatus;\r
206 }\r
207\r
208 StrTotalMemory = Pos;\r
209\r
210 TestedMemorySize = 0;\r
211 TotalMemorySize = 0;\r
212 PreviousValue = 0;\r
213 ErrorOut = FALSE;\r
214 TestAbort = FALSE;\r
215\r
216 SetMem (&Foreground, sizeof (EFI_UGA_PIXEL), 0xff);\r
217 SetMem (&Background, sizeof (EFI_UGA_PIXEL), 0x0);\r
218 SetMem (&Color, sizeof (EFI_UGA_PIXEL), 0xff);\r
219\r
220 RequireSoftECCInit = FALSE;\r
221\r
222 gST->ConOut->ClearScreen (gST->ConOut);\r
223 gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
224 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
225\r
226 Status = gBS->LocateProtocol (\r
227 &gEfiGenericMemTestProtocolGuid,\r
228 NULL,\r
229 &GenMemoryTest\r
230 );\r
231 if (EFI_ERROR (Status)) {\r
232 gBS->FreePool (Pos);\r
233 return EFI_SUCCESS;\r
234 }\r
235\r
236 InitStatus = GenMemoryTest->MemoryTestInit (\r
237 GenMemoryTest,\r
238 Level,\r
239 &RequireSoftECCInit\r
240 );\r
241 if (InitStatus == EFI_NO_MEDIA) {\r
242 //\r
243 // The PEI codes also have the relevant memory test code to check the memory,\r
244 // it can select to test some range of the memory or all of them. If PEI code\r
245 // checks all the memory, this BDS memory test will has no not-test memory to\r
246 // do the test, and then the status of EFI_NO_MEDIA will be returned by\r
247 // "MemoryTestInit". So it does not need to test memory again, just return.\r
248 //\r
249 gBS->FreePool (Pos);\r
250 return EFI_SUCCESS;\r
251 }\r
252\r
253 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 2);\r
254 TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST));\r
255\r
256 if (TmpStr != NULL) {\r
257 gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
258 gBS->FreePool (TmpStr);\r
259 }\r
260\r
261 do {\r
262 Status = GenMemoryTest->PerformMemoryTest (\r
263 GenMemoryTest,\r
264 &TestedMemorySize,\r
265 &TotalMemorySize,\r
266 &ErrorOut,\r
267 TestAbort\r
268 );\r
269 if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {\r
270 TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR));\r
271 if (TmpStr != NULL) {\r
272 PrintXY (10, 10, NULL, NULL, TmpStr);\r
273 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 4);\r
274 gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
275 gBS->FreePool (TmpStr);\r
276 }\r
277\r
278 ASSERT (0);\r
279 }\r
280\r
281 TestPercent = (UINTN) DivU64x32 (\r
282 DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),\r
283 (UINTN)DivU64x32 (TotalMemorySize, 16)\r
284 );\r
285 if (TestPercent != PreviousValue) {\r
286 UnicodeValueToString (StrPercent, 0, TestPercent, 0);\r
287 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
288 TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT));\r
289 if (TmpStr != NULL) {\r
290 BdsLibOutputStrings (gST->ConOut, StrPercent, TmpStr, NULL);\r
291 gBS->FreePool (TmpStr);\r
292 }\r
293\r
294 TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
295 if (TmpStr != NULL) {\r
296 PlatformBdsShowProgress (\r
297 Foreground,\r
298 Background,\r
299 TmpStr,\r
300 Color,\r
301 TestPercent,\r
302 (UINTN) PreviousValue\r
303 );\r
304 gBS->FreePool (TmpStr);\r
305 }\r
306 }\r
307\r
308 PreviousValue = TestPercent;\r
309\r
310 KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
311 if (Key.ScanCode == SCAN_ESC) {\r
312 if (!RequireSoftECCInit) {\r
313 TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
314 if (TmpStr != NULL) {\r
315 PlatformBdsShowProgress (\r
316 Foreground,\r
317 Background,\r
318 TmpStr,\r
319 Color,\r
320 100,\r
321 (UINTN) PreviousValue\r
322 );\r
323 gBS->FreePool (TmpStr);\r
324 }\r
325\r
326 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
327 gST->ConOut->OutputString (gST->ConOut, L"100");\r
328 Status = GenMemoryTest->Finished (GenMemoryTest);\r
329 goto Done;\r
330 }\r
331\r
332 TestAbort = TRUE;\r
333 }\r
334 } while (Status != EFI_NOT_FOUND);\r
335\r
336 Status = GenMemoryTest->Finished (GenMemoryTest);\r
337\r
338Done:\r
339 UnicodeValueToString (StrTotalMemory, COMMA_TYPE, (UINTN) TotalMemorySize, 0);\r
340 if (StrTotalMemory[0] == L',') {\r
341 StrTotalMemory++;\r
342 }\r
343\r
344 TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED));\r
345 if (TmpStr != NULL) {\r
346 StrCat (StrTotalMemory, TmpStr);\r
347 gBS->FreePool (TmpStr);\r
348 }\r
349\r
350 gST->ConOut->ClearScreen (gST->ConOut);\r
351 gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
352 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
353 gST->ConOut->OutputString (gST->ConOut, StrTotalMemory);\r
354 PlatformBdsShowProgress (\r
355 Foreground,\r
356 Background,\r
357 StrTotalMemory,\r
358 Color,\r
359 100,\r
360 (UINTN) PreviousValue\r
361 );\r
362\r
363 gBS->FreePool (Pos);\r
364\r
365 DataSize = sizeof (Value);\r
366 Status = gRT->GetVariable (\r
367 L"BootState",\r
368 &gEfiBootStateGuid,\r
369 &Attributes,\r
370 &DataSize,\r
371 &Value\r
372 );\r
373\r
374 if (EFI_ERROR (Status)) {\r
375 Value = 1;\r
376 gRT->SetVariable (\r
377 L"BootState",\r
378 &gEfiBootStateGuid,\r
379 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
380 sizeof (Value),\r
381 &Value\r
382 );\r
383 }\r
384\r
385 return ReturnStatus;\r
386}\r