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