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