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