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