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