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