]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/BdsDxe/MemoryTest.c
Add BootlogoOnly feature in BDS for BGRT
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / BdsDxe / MemoryTest.c
CommitLineData
5c08e117 1/** @file\r
2 Perform the platform memory test\r
3\r
2df686c6 4Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>\r
180a5a35 5This program and the accompanying materials\r
5c08e117 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
13**/\r
14\r
15#include "Bds.h"\r
16#include "String.h"\r
17\r
18//\r
19// BDS Platform Functions\r
20//\r
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
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
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
71 if (EFI_ERROR (Status) && FeaturePcdGet (PcdUgaConsumeSupport)) {\r
72 GraphicsOutput = NULL;\r
73\r
74 Status = gBS->HandleProtocol (\r
75 gST->ConsoleOutHandle,\r
76 &gEfiUgaDrawProtocolGuid,\r
77 (VOID **) &UgaDraw\r
78 );\r
79 }\r
80 if (EFI_ERROR (Status)) {\r
81 return EFI_UNSUPPORTED;\r
82 }\r
83\r
84 SizeOfX = 0;\r
85 SizeOfY = 0;\r
86 if (GraphicsOutput != NULL) {\r
87 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
88 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
89 } else if (UgaDraw != NULL) {\r
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
100 } else {\r
101 return EFI_UNSUPPORTED;\r
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
126 PosY - EFI_GLYPH_HEIGHT - 1,\r
127 SizeOfX,\r
128 SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
129 SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
130 );\r
131 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
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
139 PosY - EFI_GLYPH_HEIGHT - 1,\r
140 SizeOfX,\r
141 SizeOfY - (PosY - EFI_GLYPH_HEIGHT - 1),\r
142 SizeOfX * sizeof (EFI_UGA_PIXEL)\r
143 );\r
144 } else {\r
145 return EFI_UNSUPPORTED;\r
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
166 } else if (FeaturePcdGet (PcdUgaConsumeSupport)) {\r
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
179 } else {\r
180 return EFI_UNSUPPORTED;\r
181 }\r
182 }\r
183\r
184 PrintXY (\r
185 (SizeOfX - StrLen (Title) * EFI_GLYPH_WIDTH) / 2,\r
186 PosY - EFI_GLYPH_HEIGHT - 1,\r
187 &TitleForeground,\r
188 &TitleBackground,\r
189 Title\r
190 );\r
191\r
192 return EFI_SUCCESS;\r
193}\r
194\r
195/**\r
5c08e117 196 Perform the memory test base on the memory test intensive level,\r
197 and update the memory resource.\r
198\r
a798a789 199 @param Level The memory test intensive level.\r
5c08e117 200\r
a798a789 201 @retval EFI_STATUS Success test all the system memory and update\r
202 the memory resource\r
5c08e117 203\r
204**/\r
205EFI_STATUS\r
8861fc79 206EFIAPI\r
5c08e117 207BdsMemoryTest (\r
208 IN EXTENDMEM_COVERAGE_LEVEL Level\r
209 )\r
210{\r
211 EFI_STATUS Status;\r
212 EFI_STATUS KeyStatus;\r
213 EFI_STATUS InitStatus;\r
214 EFI_STATUS ReturnStatus;\r
215 BOOLEAN RequireSoftECCInit;\r
216 EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;\r
217 UINT64 TestedMemorySize;\r
218 UINT64 TotalMemorySize;\r
219 UINTN TestPercent;\r
220 UINT64 PreviousValue;\r
221 BOOLEAN ErrorOut;\r
222 BOOLEAN TestAbort;\r
223 EFI_INPUT_KEY Key;\r
5d7c1609 224 CHAR16 StrPercent[80];\r
5c08e117 225 CHAR16 *StrTotalMemory;\r
226 CHAR16 *Pos;\r
227 CHAR16 *TmpStr;\r
228 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
229 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
230 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
08c4ca5b 231 BOOLEAN IsFirstBoot;\r
5c08e117 232 UINT32 TempData;\r
233\r
234 ReturnStatus = EFI_SUCCESS;\r
235 ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
236\r
237 Pos = AllocatePool (128);\r
238\r
239 if (Pos == NULL) {\r
240 return ReturnStatus;\r
241 }\r
242\r
243 StrTotalMemory = Pos;\r
244\r
245 TestedMemorySize = 0;\r
246 TotalMemorySize = 0;\r
247 PreviousValue = 0;\r
248 ErrorOut = FALSE;\r
249 TestAbort = FALSE;\r
250\r
251 SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
252 SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
253 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
254\r
255 RequireSoftECCInit = FALSE;\r
256\r
5c08e117 257 Status = gBS->LocateProtocol (\r
258 &gEfiGenericMemTestProtocolGuid,\r
259 NULL,\r
260 (VOID **) &GenMemoryTest\r
261 );\r
262 if (EFI_ERROR (Status)) {\r
263 FreePool (Pos);\r
264 return EFI_SUCCESS;\r
265 }\r
266\r
267 InitStatus = GenMemoryTest->MemoryTestInit (\r
268 GenMemoryTest,\r
269 Level,\r
270 &RequireSoftECCInit\r
271 );\r
272 if (InitStatus == EFI_NO_MEDIA) {\r
273 //\r
274 // The PEI codes also have the relevant memory test code to check the memory,\r
275 // it can select to test some range of the memory or all of them. If PEI code\r
276 // checks all the memory, this BDS memory test will has no not-test memory to\r
277 // do the test, and then the status of EFI_NO_MEDIA will be returned by\r
278 // "MemoryTestInit". So it does not need to test memory again, just return.\r
279 //\r
280 FreePool (Pos);\r
281 return EFI_SUCCESS;\r
282 }\r
2df686c6 283 \r
284 if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {\r
285 TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST));\r
5c08e117 286\r
2df686c6 287 if (TmpStr != NULL) {\r
288 PrintXY (10, 10, NULL, NULL, TmpStr);\r
289 FreePool (TmpStr);\r
290 }\r
291 } else {\r
292 DEBUG ((EFI_D_INFO, "Enter memory test.\n"));\r
5c08e117 293 }\r
5c08e117 294 do {\r
295 Status = GenMemoryTest->PerformMemoryTest (\r
296 GenMemoryTest,\r
297 &TestedMemorySize,\r
298 &TotalMemorySize,\r
299 &ErrorOut,\r
300 TestAbort\r
301 );\r
302 if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {\r
303 TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR));\r
304 if (TmpStr != NULL) {\r
305 PrintXY (10, 10, NULL, NULL, TmpStr);\r
5c08e117 306 FreePool (TmpStr);\r
307 }\r
308\r
309 ASSERT (0);\r
310 }\r
2df686c6 311 \r
312 if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {\r
313 TempData = (UINT32) DivU64x32 (TotalMemorySize, 16);\r
314 TestPercent = (UINTN) DivU64x32 (\r
315 DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),\r
316 TempData\r
317 );\r
318 if (TestPercent != PreviousValue) {\r
319 UnicodeValueToString (StrPercent, 0, TestPercent, 0);\r
320 TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT));\r
321 if (TmpStr != NULL) {\r
322 //\r
323 // TmpStr size is 64, StrPercent is reserved to 16.\r
324 //\r
325 StrCat (StrPercent, TmpStr);\r
326 PrintXY (10, 10, NULL, NULL, StrPercent);\r
327 FreePool (TmpStr);\r
328 }\r
5c08e117 329\r
5c08e117 330 TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
331 if (TmpStr != NULL) {\r
332 PlatformBdsShowProgress (\r
333 Foreground,\r
334 Background,\r
335 TmpStr,\r
336 Color,\r
2df686c6 337 TestPercent,\r
5c08e117 338 (UINTN) PreviousValue\r
339 );\r
340 FreePool (TmpStr);\r
341 }\r
2df686c6 342 }\r
343\r
344 PreviousValue = TestPercent;\r
345 } else {\r
346 DEBUG ((EFI_D_INFO, "Perform memory test (ESC to skip).\n"));\r
347 }\r
5c08e117 348\r
2df686c6 349 KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
350 if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) {\r
351 if (!RequireSoftECCInit) {\r
352 if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {\r
353 TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
354 if (TmpStr != NULL) {\r
355 PlatformBdsShowProgress (\r
356 Foreground,\r
357 Background,\r
358 TmpStr,\r
359 Color,\r
360 100,\r
361 (UINTN) PreviousValue\r
362 );\r
363 FreePool (TmpStr);\r
364 }\r
365\r
366 PrintXY (10, 10, NULL, NULL, L"100");\r
367 }\r
5c08e117 368 Status = GenMemoryTest->Finished (GenMemoryTest);\r
369 goto Done;\r
370 }\r
371\r
372 TestAbort = TRUE;\r
373 }\r
374 } while (Status != EFI_NOT_FOUND);\r
375\r
376 Status = GenMemoryTest->Finished (GenMemoryTest);\r
377\r
378Done:\r
2df686c6 379 if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {\r
380 UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0);\r
381 if (StrTotalMemory[0] == L',') {\r
382 StrTotalMemory++;\r
383 }\r
5c08e117 384\r
2df686c6 385 TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED));\r
386 if (TmpStr != NULL) {\r
387 StrCat (StrTotalMemory, TmpStr);\r
388 FreePool (TmpStr);\r
389 }\r
5c08e117 390\r
2df686c6 391 PrintXY (10, 10, NULL, NULL, StrTotalMemory);\r
392 PlatformBdsShowProgress (\r
393 Foreground,\r
394 Background,\r
395 StrTotalMemory,\r
396 Color,\r
397 100,\r
398 (UINTN) PreviousValue\r
399 );\r
400 \r
401 } else {\r
402 DEBUG ((EFI_D_INFO, "%d bytes of system memory tested OK\r\n", TotalMemorySize));\r
403 }\r
404 \r
5c08e117 405 FreePool (Pos);\r
406\r
2df686c6 407\r
08c4ca5b 408 //\r
409 // Use a DynamicHii type pcd to save the boot status, which is used to\r
410 // control configuration mode, such as FULL/MINIMAL/NO_CHANGES configuration.\r
411 //\r
412 IsFirstBoot = PcdGetBool(PcdBootState);\r
413 if (IsFirstBoot) {\r
414 PcdSetBool(PcdBootState, FALSE);\r
5c08e117 415 }\r
416\r
417 return ReturnStatus;\r
418}\r