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