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