]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/BdsDxe/MemoryTest.c
51b49abc4accfdec0d01adce5f63568cbf7003b5
[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)) {
83 GraphicsOutput = NULL;
84
85 Status = gBS->HandleProtocol (
86 gST->ConsoleOutHandle,
87 &gEfiUgaDrawProtocolGuid,
88 (VOID **) &UgaDraw
89 );
90 if (EFI_ERROR (Status)) {
91 return EFI_UNSUPPORTED;
92 }
93 }
94
95 if (GraphicsOutput != NULL) {
96 SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;
97 SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;
98 } else {
99 Status = UgaDraw->GetMode (
100 UgaDraw,
101 &SizeOfX,
102 &SizeOfY,
103 &ColorDepth,
104 &RefreshRate
105 );
106 if (EFI_ERROR (Status)) {
107 return EFI_UNSUPPORTED;
108 }
109 }
110
111 BlockWidth = SizeOfX / 100;
112 BlockHeight = SizeOfY / 50;
113
114 BlockNum = Progress;
115
116 PosX = 0;
117 PosY = SizeOfY * 48 / 50;
118
119 if (BlockNum == 0) {
120 //
121 // Clear progress area
122 //
123 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
124
125 if (GraphicsOutput != NULL) {
126 Status = GraphicsOutput->Blt (
127 GraphicsOutput,
128 &Color,
129 EfiBltVideoFill,
130 0,
131 0,
132 0,
133 PosY - GLYPH_HEIGHT - 1,
134 SizeOfX,
135 SizeOfY - (PosY - GLYPH_HEIGHT - 1),
136 SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
137 );
138 } else {
139 Status = UgaDraw->Blt (
140 UgaDraw,
141 (EFI_UGA_PIXEL *) &Color,
142 EfiUgaVideoFill,
143 0,
144 0,
145 0,
146 PosY - GLYPH_HEIGHT - 1,
147 SizeOfX,
148 SizeOfY - (PosY - GLYPH_HEIGHT - 1),
149 SizeOfX * sizeof (EFI_UGA_PIXEL)
150 );
151 }
152 }
153 //
154 // Show progress by drawing blocks
155 //
156 for (Index = PreviousValue; Index < BlockNum; Index++) {
157 PosX = Index * BlockWidth;
158 if (GraphicsOutput != NULL) {
159 Status = GraphicsOutput->Blt (
160 GraphicsOutput,
161 &ProgressColor,
162 EfiBltVideoFill,
163 0,
164 0,
165 PosX,
166 PosY,
167 BlockWidth - 1,
168 BlockHeight,
169 (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
170 );
171 } else {
172 Status = UgaDraw->Blt (
173 UgaDraw,
174 (EFI_UGA_PIXEL *) &ProgressColor,
175 EfiUgaVideoFill,
176 0,
177 0,
178 PosX,
179 PosY,
180 BlockWidth - 1,
181 BlockHeight,
182 (BlockWidth) * sizeof (EFI_UGA_PIXEL)
183 );
184 }
185 }
186
187 PrintXY (
188 (SizeOfX - StrLen (Title) * GLYPH_WIDTH) / 2,
189 PosY - GLYPH_HEIGHT - 1,
190 &TitleForeground,
191 &TitleBackground,
192 Title
193 );
194
195 return EFI_SUCCESS;
196 }
197
198 EFI_STATUS
199 BdsMemoryTest (
200 IN EXTENDMEM_COVERAGE_LEVEL Level
201 )
202 /*++
203
204 Routine Description:
205
206 Perform the memory test base on the memory test intensive level,
207 and update the memory resource.
208
209 Arguments:
210
211 Level - The memory test intensive level.
212
213 Returns:
214
215 EFI_STATUS - Success test all the system memory and update
216 the memory resource
217
218 --*/
219 {
220 EFI_STATUS Status;
221 EFI_STATUS KeyStatus;
222 EFI_STATUS InitStatus;
223 EFI_STATUS ReturnStatus;
224 BOOLEAN RequireSoftECCInit;
225 EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;
226 UINT64 TestedMemorySize;
227 UINT64 TotalMemorySize;
228 UINTN TestPercent;
229 UINT64 PreviousValue;
230 BOOLEAN ErrorOut;
231 BOOLEAN TestAbort;
232 EFI_INPUT_KEY Key;
233 CHAR16 StrPercent[16];
234 CHAR16 *StrTotalMemory;
235 CHAR16 *Pos;
236 CHAR16 *TmpStr;
237 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;
238 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;
239 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;
240 UINT8 Value;
241 UINTN DataSize;
242 UINT32 Attributes;
243 UINT32 TempData;
244
245 ReturnStatus = EFI_SUCCESS;
246 ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
247
248 Pos = AllocatePool (128);
249
250 if (Pos == NULL) {
251 return ReturnStatus;
252 }
253
254 StrTotalMemory = Pos;
255
256 TestedMemorySize = 0;
257 TotalMemorySize = 0;
258 PreviousValue = 0;
259 ErrorOut = FALSE;
260 TestAbort = FALSE;
261
262 SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
263 SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
264 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
265
266 RequireSoftECCInit = FALSE;
267
268 gST->ConOut->ClearScreen (gST->ConOut);
269 gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);
270 gST->ConOut->EnableCursor (gST->ConOut, FALSE);
271
272 Status = gBS->LocateProtocol (
273 &gEfiGenericMemTestProtocolGuid,
274 NULL,
275 (VOID **) &GenMemoryTest
276 );
277 if (EFI_ERROR (Status)) {
278 FreePool (Pos);
279 return EFI_SUCCESS;
280 }
281
282 InitStatus = GenMemoryTest->MemoryTestInit (
283 GenMemoryTest,
284 Level,
285 &RequireSoftECCInit
286 );
287 if (InitStatus == EFI_NO_MEDIA) {
288 //
289 // The PEI codes also have the relevant memory test code to check the memory,
290 // it can select to test some range of the memory or all of them. If PEI code
291 // checks all the memory, this BDS memory test will has no not-test memory to
292 // do the test, and then the status of EFI_NO_MEDIA will be returned by
293 // "MemoryTestInit". So it does not need to test memory again, just return.
294 //
295 FreePool (Pos);
296 return EFI_SUCCESS;
297 }
298
299 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 2);
300 TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST));
301
302 if (TmpStr != NULL) {
303 gST->ConOut->OutputString (gST->ConOut, TmpStr);
304 FreePool (TmpStr);
305 }
306
307 do {
308 Status = GenMemoryTest->PerformMemoryTest (
309 GenMemoryTest,
310 &TestedMemorySize,
311 &TotalMemorySize,
312 &ErrorOut,
313 TestAbort
314 );
315 if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {
316 TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR));
317 if (TmpStr != NULL) {
318 PrintXY (10, 10, NULL, NULL, TmpStr);
319 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 4);
320 gST->ConOut->OutputString (gST->ConOut, TmpStr);
321 FreePool (TmpStr);
322 }
323
324 ASSERT (0);
325 }
326
327 TempData = (UINT32) DivU64x32 (TotalMemorySize, 16);
328 TestPercent = (UINTN) DivU64x32 (
329 DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),
330 TempData
331 );
332 if (TestPercent != PreviousValue) {
333 UnicodeValueToString (StrPercent, 0, TestPercent, 0);
334 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);
335 TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT));
336 if (TmpStr != NULL) {
337 BdsLibOutputStrings (gST->ConOut, StrPercent, TmpStr, NULL);
338 FreePool (TmpStr);
339 }
340
341 TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));
342 if (TmpStr != NULL) {
343 PlatformBdsShowProgress (
344 Foreground,
345 Background,
346 TmpStr,
347 Color,
348 TestPercent,
349 (UINTN) PreviousValue
350 );
351 FreePool (TmpStr);
352 }
353 }
354
355 PreviousValue = TestPercent;
356
357 KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
358 if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) {
359 if (!RequireSoftECCInit) {
360 TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));
361 if (TmpStr != NULL) {
362 PlatformBdsShowProgress (
363 Foreground,
364 Background,
365 TmpStr,
366 Color,
367 100,
368 (UINTN) PreviousValue
369 );
370 FreePool (TmpStr);
371 }
372
373 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);
374 gST->ConOut->OutputString (gST->ConOut, L"100");
375 Status = GenMemoryTest->Finished (GenMemoryTest);
376 goto Done;
377 }
378
379 TestAbort = TRUE;
380 }
381 } while (Status != EFI_NOT_FOUND);
382
383 Status = GenMemoryTest->Finished (GenMemoryTest);
384
385 Done:
386 UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0);
387 if (StrTotalMemory[0] == L',') {
388 StrTotalMemory++;
389 }
390
391 TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED));
392 if (TmpStr != NULL) {
393 StrCat (StrTotalMemory, TmpStr);
394 FreePool (TmpStr);
395 }
396
397 gST->ConOut->ClearScreen (gST->ConOut);
398 gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);
399 gST->ConOut->EnableCursor (gST->ConOut, FALSE);
400 gST->ConOut->OutputString (gST->ConOut, StrTotalMemory);
401 PlatformBdsShowProgress (
402 Foreground,
403 Background,
404 StrTotalMemory,
405 Color,
406 100,
407 (UINTN) PreviousValue
408 );
409
410 FreePool (Pos);
411
412 DataSize = sizeof (Value);
413 Status = gRT->GetVariable (
414 L"BootState",
415 &gEfiBootStateGuid,
416 &Attributes,
417 &DataSize,
418 &Value
419 );
420
421 if (EFI_ERROR (Status)) {
422 Value = 1;
423 gRT->SetVariable (
424 L"BootState",
425 &gEfiBootStateGuid,
426 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
427 sizeof (Value),
428 &Value
429 );
430 }
431
432 return ReturnStatus;
433 }