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