]>
Commit | Line | Data |
---|---|---|
5c08e117 | 1 | /** @file\r |
2 | Perform the platform memory test\r | |
3 | \r | |
0a6f4824 | 4 | Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r |
c0a00b14 | 5 | SPDX-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 | |
30 | EFI_STATUS\r | |
31 | PlatformBdsShowProgress (\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 | |
199 | EFI_STATUS\r | |
8861fc79 | 200 | EFIAPI\r |
5c08e117 | 201 | BdsMemoryTest (\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 | |
381 | Done:\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 |