]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/BdsDxe/MemoryTest.c
sync comments, fix function header, rename variable name to follow coding style.
[mirror_edk2.git] / MdeModulePkg / Universal / BdsDxe / MemoryTest.c
CommitLineData
fd6a62f3 1/** @file\r
2 Perform the platform memory test\r
93e3992d 3\r
fd6a62f3 4Copyright (c) 2004 - 2008, Intel Corporation. <BR>\r
93e3992d 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
fd6a62f3 13**/\r
93e3992d 14\r
15#include "Bds.h"\r
16#include "String.h"\r
17\r
18//\r
19// BDS Platform Functions\r
20//\r
b30312ba 21/**\r
22\r
23 Show progress bar with title above it. It only works in Graphics mode.\r
24\r
25\r
26 @param TitleForeground Foreground color for Title.\r
27 @param TitleBackground Background color for Title.\r
28 @param Title Title above progress bar.\r
29 @param ProgressColor Progress bar color.\r
30 @param Progress Progress (0-100)\r
31 @param PreviousValue The previous value of the progress.\r
32\r
33 @retval EFI_STATUS Success update the progress bar\r
34\r
35**/\r
93e3992d 36EFI_STATUS\r
37PlatformBdsShowProgress (\r
38 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
39 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
40 IN CHAR16 *Title,\r
41 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
42 IN UINTN Progress,\r
43 IN UINTN PreviousValue\r
44 )\r
93e3992d 45{\r
46 EFI_STATUS Status;\r
47 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
48 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
49 UINT32 SizeOfX;\r
50 UINT32 SizeOfY;\r
51 UINT32 ColorDepth;\r
52 UINT32 RefreshRate;\r
53 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
54 UINTN BlockHeight;\r
55 UINTN BlockWidth;\r
56 UINTN BlockNum;\r
57 UINTN PosX;\r
58 UINTN PosY;\r
59 UINTN Index;\r
60\r
61 if (Progress > 100) {\r
62 return EFI_INVALID_PARAMETER;\r
63 }\r
64\r
65 UgaDraw = NULL;\r
66 Status = gBS->HandleProtocol (\r
67 gST->ConsoleOutHandle,\r
68 &gEfiGraphicsOutputProtocolGuid,\r
69 (VOID **) &GraphicsOutput\r
70 );\r
8541adab 71 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
93e3992d 72 GraphicsOutput = NULL;\r
73\r
74 Status = gBS->HandleProtocol (\r
75 gST->ConsoleOutHandle,\r
76 &gEfiUgaDrawProtocolGuid,\r
77 (VOID **) &UgaDraw\r
78 );\r
8541adab 79 }\r
80 if (EFI_ERROR (Status)) {\r
81 return EFI_UNSUPPORTED;\r
93e3992d 82 }\r
83\r
8541adab 84 SizeOfX = 0;\r
85 SizeOfY = 0;\r
93e3992d 86 if (GraphicsOutput != NULL) {\r
87 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
88 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
8541adab 89 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
93e3992d 90 Status = UgaDraw->GetMode (\r
91 UgaDraw,\r
92 &SizeOfX,\r
93 &SizeOfY,\r
94 &ColorDepth,\r
95 &RefreshRate\r
96 );\r
97 if (EFI_ERROR (Status)) {\r
98 return EFI_UNSUPPORTED;\r
99 }\r
8541adab 100 } else {\r
101 return EFI_UNSUPPORTED;\r
93e3992d 102 }\r
103\r
104 BlockWidth = SizeOfX / 100;\r
105 BlockHeight = SizeOfY / 50;\r
106\r
107 BlockNum = Progress;\r
108\r
109 PosX = 0;\r
110 PosY = SizeOfY * 48 / 50;\r
111\r
112 if (BlockNum == 0) {\r
113 //\r
114 // Clear progress area\r
115 //\r
116 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
117\r
118 if (GraphicsOutput != NULL) {\r
119 Status = GraphicsOutput->Blt (\r
120 GraphicsOutput,\r
121 &Color,\r
122 EfiBltVideoFill,\r
123 0,\r
124 0,\r
125 0,\r
391cdf43 126 PosY - EFI_GLYPH_HEIGHT - 1,\r
93e3992d 127 SizeOfX,\r
391cdf43 128 SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
93e3992d 129 SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
130 );\r
8541adab 131 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
93e3992d 132 Status = UgaDraw->Blt (\r
133 UgaDraw,\r
134 (EFI_UGA_PIXEL *) &Color,\r
135 EfiUgaVideoFill,\r
136 0,\r
137 0,\r
138 0,\r
391cdf43 139 PosY - EFI_GLYPH_HEIGHT - 1,\r
93e3992d 140 SizeOfX,\r
391cdf43 141 SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
93e3992d 142 SizeOfX * sizeof (EFI_UGA_PIXEL)\r
143 );\r
695f7e98 144 } else {\r
145 return EFI_UNSUPPORTED;\r
93e3992d 146 }\r
147 }\r
148 //\r
149 // Show progress by drawing blocks\r
150 //\r
151 for (Index = PreviousValue; Index < BlockNum; Index++) {\r
152 PosX = Index * BlockWidth;\r
153 if (GraphicsOutput != NULL) {\r
154 Status = GraphicsOutput->Blt (\r
155 GraphicsOutput,\r
156 &ProgressColor,\r
157 EfiBltVideoFill,\r
158 0,\r
159 0,\r
160 PosX,\r
161 PosY,\r
162 BlockWidth - 1,\r
163 BlockHeight,\r
164 (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
165 );\r
8541adab 166 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
93e3992d 167 Status = UgaDraw->Blt (\r
168 UgaDraw,\r
169 (EFI_UGA_PIXEL *) &ProgressColor,\r
170 EfiUgaVideoFill,\r
171 0,\r
172 0,\r
173 PosX,\r
174 PosY,\r
175 BlockWidth - 1,\r
176 BlockHeight,\r
177 (BlockWidth) * sizeof (EFI_UGA_PIXEL)\r
178 );\r
695f7e98 179 } else {\r
180 return EFI_UNSUPPORTED;\r
93e3992d 181 }\r
182 }\r
183\r
184 PrintXY (\r
391cdf43 185 (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,\r
186 PosY - EFI_GLYPH_HEIGHT - 1,\r
93e3992d 187 &TitleForeground,\r
188 &TitleBackground,\r
189 Title\r
190 );\r
191\r
192 return EFI_SUCCESS;\r
193}\r
194\r
b30312ba 195/**\r
93e3992d 196\r
197 Perform the memory test base on the memory test intensive level,\r
198 and update the memory resource.\r
199\r
93e3992d 200\r
b30312ba 201 @param Level The memory test intensive level.\r
93e3992d 202\r
b30312ba 203 @retval EFI_STATUS Success test all the system memory and update\r
204 the memory resource\r
93e3992d 205\r
b30312ba 206**/\r
207EFI_STATUS\r
208BdsMemoryTest (\r
209 IN EXTENDMEM_COVERAGE_LEVEL Level\r
210 )\r
93e3992d 211{\r
212 EFI_STATUS Status;\r
cb7cd5b0 213 EFI_STATUS KeyStatus;\r
93e3992d 214 EFI_STATUS InitStatus;\r
215 EFI_STATUS ReturnStatus;\r
216 BOOLEAN RequireSoftECCInit;\r
217 EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;\r
218 UINT64 TestedMemorySize;\r
219 UINT64 TotalMemorySize;\r
220 UINTN TestPercent;\r
221 UINT64 PreviousValue;\r
222 BOOLEAN ErrorOut;\r
223 BOOLEAN TestAbort;\r
224 EFI_INPUT_KEY Key;\r
225 CHAR16 StrPercent[16];\r
226 CHAR16 *StrTotalMemory;\r
227 CHAR16 *Pos;\r
228 CHAR16 *TmpStr;\r
229 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
230 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
231 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
232 UINT8 Value;\r
233 UINTN DataSize;\r
234 UINT32 Attributes;\r
235 UINT32 TempData;\r
236\r
237 ReturnStatus = EFI_SUCCESS;\r
238 ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
239\r
240 Pos = AllocatePool (128);\r
241\r
242 if (Pos == NULL) {\r
243 return ReturnStatus;\r
244 }\r
245\r
246 StrTotalMemory = Pos;\r
247\r
248 TestedMemorySize = 0;\r
249 TotalMemorySize = 0;\r
250 PreviousValue = 0;\r
251 ErrorOut = FALSE;\r
252 TestAbort = FALSE;\r
253\r
254 SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
255 SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
256 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
257\r
258 RequireSoftECCInit = FALSE;\r
259\r
260 gST->ConOut->ClearScreen (gST->ConOut);\r
261 gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
262 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
263\r
264 Status = gBS->LocateProtocol (\r
265 &gEfiGenericMemTestProtocolGuid,\r
266 NULL,\r
267 (VOID **) &GenMemoryTest\r
268 );\r
269 if (EFI_ERROR (Status)) {\r
270 FreePool (Pos);\r
271 return EFI_SUCCESS;\r
272 }\r
273\r
274 InitStatus = GenMemoryTest->MemoryTestInit (\r
275 GenMemoryTest,\r
276 Level,\r
277 &RequireSoftECCInit\r
278 );\r
279 if (InitStatus == EFI_NO_MEDIA) {\r
280 //\r
281 // The PEI codes also have the relevant memory test code to check the memory,\r
282 // it can select to test some range of the memory or all of them. If PEI code\r
283 // checks all the memory, this BDS memory test will has no not-test memory to\r
284 // do the test, and then the status of EFI_NO_MEDIA will be returned by\r
285 // "MemoryTestInit". So it does not need to test memory again, just return.\r
286 //\r
287 FreePool (Pos);\r
288 return EFI_SUCCESS;\r
289 }\r
290\r
291 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 2);\r
292 TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST));\r
293\r
294 if (TmpStr != NULL) {\r
295 gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
296 FreePool (TmpStr);\r
297 }\r
298\r
299 do {\r
300 Status = GenMemoryTest->PerformMemoryTest (\r
301 GenMemoryTest,\r
302 &TestedMemorySize,\r
303 &TotalMemorySize,\r
304 &ErrorOut,\r
305 TestAbort\r
306 );\r
307 if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {\r
308 TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR));\r
309 if (TmpStr != NULL) {\r
310 PrintXY (10, 10, NULL, NULL, TmpStr);\r
311 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 4);\r
312 gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
313 FreePool (TmpStr);\r
314 }\r
315\r
316 ASSERT (0);\r
317 }\r
318\r
319 TempData = (UINT32) DivU64x32 (TotalMemorySize, 16);\r
320 TestPercent = (UINTN) DivU64x32 (\r
321 DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),\r
322 TempData\r
323 );\r
324 if (TestPercent != PreviousValue) {\r
325 UnicodeValueToString (StrPercent, 0, TestPercent, 0);\r
326 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
327 TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT));\r
328 if (TmpStr != NULL) {\r
329 BdsLibOutputStrings (gST->ConOut, StrPercent, TmpStr, NULL);\r
330 FreePool (TmpStr);\r
331 }\r
332\r
333 TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
334 if (TmpStr != NULL) {\r
335 PlatformBdsShowProgress (\r
336 Foreground,\r
337 Background,\r
338 TmpStr,\r
339 Color,\r
340 TestPercent,\r
341 (UINTN) PreviousValue\r
342 );\r
343 FreePool (TmpStr);\r
344 }\r
345 }\r
346\r
347 PreviousValue = TestPercent;\r
348\r
cb7cd5b0 349 KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
350 if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) {\r
93e3992d 351 if (!RequireSoftECCInit) {\r
352 TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
353 if (TmpStr != NULL) {\r
354 PlatformBdsShowProgress (\r
355 Foreground,\r
356 Background,\r
357 TmpStr,\r
358 Color,\r
359 100,\r
360 (UINTN) PreviousValue\r
361 );\r
362 FreePool (TmpStr);\r
363 }\r
364\r
365 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
366 gST->ConOut->OutputString (gST->ConOut, L"100");\r
367 Status = GenMemoryTest->Finished (GenMemoryTest);\r
368 goto Done;\r
369 }\r
370\r
371 TestAbort = TRUE;\r
372 }\r
373 } while (Status != EFI_NOT_FOUND);\r
374\r
375 Status = GenMemoryTest->Finished (GenMemoryTest);\r
376\r
377Done:\r
378 UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0);\r
379 if (StrTotalMemory[0] == L',') {\r
380 StrTotalMemory++;\r
381 }\r
382\r
383 TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED));\r
384 if (TmpStr != NULL) {\r
385 StrCat (StrTotalMemory, TmpStr);\r
386 FreePool (TmpStr);\r
387 }\r
388\r
389 gST->ConOut->ClearScreen (gST->ConOut);\r
390 gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
391 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
392 gST->ConOut->OutputString (gST->ConOut, StrTotalMemory);\r
393 PlatformBdsShowProgress (\r
394 Foreground,\r
395 Background,\r
396 StrTotalMemory,\r
397 Color,\r
398 100,\r
399 (UINTN) PreviousValue\r
400 );\r
401\r
402 FreePool (Pos);\r
403\r
404 DataSize = sizeof (Value);\r
405 Status = gRT->GetVariable (\r
406 L"BootState",\r
407 &gEfiBootStateGuid,\r
408 &Attributes,\r
409 &DataSize,\r
410 &Value\r
411 );\r
412\r
413 if (EFI_ERROR (Status)) {\r
414 Value = 1;\r
415 gRT->SetVariable (\r
416 L"BootState",\r
417 &gEfiBootStateGuid,\r
418 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
419 sizeof (Value),\r
420 &Value\r
421 );\r
422 }\r
423\r
424 return ReturnStatus;\r
425}\r