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