1 /** @file
2   Perform the platform memory test
3 
4 Copyright (c) 2004 - 2015, Intel Corporation. All rights reserved.<BR>
5 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 "PlatformBootManager.h"
16 
17 EFI_HII_HANDLE gStringPackHandle                  = NULL;
18 EFI_GUID       mPlatformBootManagerStringPackGuid = {
19   0x154dd51, 0x9079, 0x4a10, { 0x89, 0x5c, 0x9c, 0x7, 0x72, 0x81, 0x57, 0x88 }
20   };
21 // extern UINT8  BdsDxeStrings[];
22 
23 //
24 // BDS Platform Functions
25 //
26 
27 /**
28   Perform the memory test base on the memory test intensive level,
29   and update the memory resource.
30 
31   @param  Level         The memory test intensive level.
32 
33   @retval EFI_STATUS    Success test all the system memory and update
34                         the memory resource
35 
36 **/
37 EFI_STATUS
PlatformBootManagerMemoryTest(IN EXTENDMEM_COVERAGE_LEVEL Level)38 PlatformBootManagerMemoryTest (
39   IN EXTENDMEM_COVERAGE_LEVEL Level
40   )
41 {
42   EFI_STATUS                        Status;
43   EFI_STATUS                        KeyStatus;
44   EFI_STATUS                        InitStatus;
45   EFI_STATUS                        ReturnStatus;
46   BOOLEAN                           RequireSoftECCInit;
47   EFI_GENERIC_MEMORY_TEST_PROTOCOL  *GenMemoryTest;
48   UINT64                            TestedMemorySize;
49   UINT64                            TotalMemorySize;
50   UINTN                             TestPercent;
51   UINT64                            PreviousValue;
52   BOOLEAN                           ErrorOut;
53   BOOLEAN                           TestAbort;
54   EFI_INPUT_KEY                     Key;
55   CHAR16                            StrPercent[80];
56   CHAR16                            *StrTotalMemory;
57   CHAR16                            *Pos;
58   CHAR16                            *TmpStr;
59   EFI_GRAPHICS_OUTPUT_BLT_PIXEL     Foreground;
60   EFI_GRAPHICS_OUTPUT_BLT_PIXEL     Background;
61   EFI_GRAPHICS_OUTPUT_BLT_PIXEL     Color;
62   UINT32                            TempData;
63   UINTN                             StrTotalMemorySize;
64 
65   ReturnStatus = EFI_SUCCESS;
66   ZeroMem (&Key, sizeof (EFI_INPUT_KEY));
67 
68   StrTotalMemorySize = 128;
69   Pos = AllocateZeroPool (StrTotalMemorySize);
70   ASSERT (Pos != NULL);
71 
72   if (gStringPackHandle == NULL) {
73     gStringPackHandle = HiiAddPackages (
74                            &mPlatformBootManagerStringPackGuid,
75                            gImageHandle,
76                            PlatformBootManagerLibStrings,
77                            NULL
78                            );
79     ASSERT (gStringPackHandle != NULL);
80   }
81 
82   StrTotalMemory    = Pos;
83 
84   TestedMemorySize  = 0;
85   TotalMemorySize   = 0;
86   PreviousValue     = 0;
87   ErrorOut          = FALSE;
88   TestAbort         = FALSE;
89 
90   SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
91   SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);
92   SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);
93 
94   RequireSoftECCInit = FALSE;
95 
96   Status = gBS->LocateProtocol (
97                   &gEfiGenericMemTestProtocolGuid,
98                   NULL,
99                   (VOID **) &GenMemoryTest
100                   );
101   if (EFI_ERROR (Status)) {
102     FreePool (Pos);
103     return EFI_SUCCESS;
104   }
105 
106   InitStatus = GenMemoryTest->MemoryTestInit (
107                                 GenMemoryTest,
108                                 Level,
109                                 &RequireSoftECCInit
110                                 );
111   if (InitStatus == EFI_NO_MEDIA) {
112     //
113     // The PEI codes also have the relevant memory test code to check the memory,
114     // it can select to test some range of the memory or all of them. If PEI code
115     // checks all the memory, this BDS memory test will has no not-test memory to
116     // do the test, and then the status of EFI_NO_MEDIA will be returned by
117     // "MemoryTestInit". So it does not need to test memory again, just return.
118     //
119     FreePool (Pos);
120     return EFI_SUCCESS;
121   }
122 
123   if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {
124     TmpStr = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST), NULL);
125 
126     if (TmpStr != NULL) {
127       PrintXY (10, 10, NULL, NULL, TmpStr);
128       FreePool (TmpStr);
129     }
130   } else {
131     DEBUG ((EFI_D_INFO, "Enter memory test.\n"));
132   }
133   do {
134     Status = GenMemoryTest->PerformMemoryTest (
135                               GenMemoryTest,
136                               &TestedMemorySize,
137                               &TotalMemorySize,
138                               &ErrorOut,
139                               TestAbort
140                               );
141     if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {
142       TmpStr = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_SYSTEM_MEM_ERROR), NULL);
143       if (TmpStr != NULL) {
144         PrintXY (10, 10, NULL, NULL, TmpStr);
145         FreePool (TmpStr);
146       }
147 
148       ASSERT (0);
149     }
150 
151     if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {
152       TempData = (UINT32) DivU64x32 (TotalMemorySize, 16);
153       TestPercent = (UINTN) DivU64x32 (
154                               DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),
155                               TempData
156                               );
157       if (TestPercent != PreviousValue) {
158         UnicodeValueToString (StrPercent, 0, TestPercent, 0);
159         TmpStr = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_MEMORY_TEST_PERCENT), NULL);
160         if (TmpStr != NULL) {
161           //
162           // TmpStr size is 64, StrPercent is reserved to 16.
163           //
164           StrnCatS (
165             StrPercent,
166             sizeof (StrPercent) / sizeof (CHAR16),
167             TmpStr,
168             sizeof (StrPercent) / sizeof (CHAR16) - StrLen (StrPercent) - 1
169             );
170           PrintXY (10, 10, NULL, NULL, StrPercent);
171           FreePool (TmpStr);
172         }
173 
174         TmpStr = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_PERFORM_MEM_TEST), NULL);
175         if (TmpStr != NULL) {
176           BootLogoUpdateProgress (
177             Foreground,
178             Background,
179             TmpStr,
180             Color,
181             TestPercent,
182             (UINTN) PreviousValue
183             );
184           FreePool (TmpStr);
185         }
186       }
187 
188       PreviousValue = TestPercent;
189     } else {
190       DEBUG ((EFI_D_INFO, "Perform memory test (ESC to skip).\n"));
191     }
192 
193     if (!PcdGetBool (PcdConInConnectOnDemand)) {
194       KeyStatus     = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
195       if (!EFI_ERROR (KeyStatus) && (Key.ScanCode == SCAN_ESC)) {
196         if (!RequireSoftECCInit) {
197           if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {
198             TmpStr = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_PERFORM_MEM_TEST), NULL);
199             if (TmpStr != NULL) {
200               BootLogoUpdateProgress (
201                 Foreground,
202                 Background,
203                 TmpStr,
204                 Color,
205                 100,
206                 (UINTN) PreviousValue
207                 );
208               FreePool (TmpStr);
209             }
210 
211             PrintXY (10, 10, NULL, NULL, L"100");
212           }
213           Status = GenMemoryTest->Finished (GenMemoryTest);
214           goto Done;
215         }
216 
217         TestAbort = TRUE;
218       }
219     }
220   } while (Status != EFI_NOT_FOUND);
221 
222   Status = GenMemoryTest->Finished (GenMemoryTest);
223 
224 Done:
225   if (!FeaturePcdGet(PcdBootlogoOnlyEnable)) {
226     UnicodeValueToString (StrTotalMemory, COMMA_TYPE, TotalMemorySize, 0);
227     if (StrTotalMemory[0] == L',') {
228       StrTotalMemory++;
229       StrTotalMemorySize -= sizeof (CHAR16);
230     }
231 
232     TmpStr = HiiGetString (gStringPackHandle, STRING_TOKEN (STR_MEM_TEST_COMPLETED), NULL);
233     if (TmpStr != NULL) {
234       StrnCatS (
235         StrTotalMemory,
236         StrTotalMemorySize / sizeof (CHAR16),
237         TmpStr,
238         StrTotalMemorySize / sizeof (CHAR16) - StrLen (StrTotalMemory) - 1
239         );
240       FreePool (TmpStr);
241     }
242 
243     PrintXY (10, 10, NULL, NULL, StrTotalMemory);
244     BootLogoUpdateProgress (
245       Foreground,
246       Background,
247       StrTotalMemory,
248       Color,
249       100,
250       (UINTN) PreviousValue
251       );
252 
253   } else {
254     DEBUG ((EFI_D_INFO, "%d bytes of system memory tested OK\r\n", TotalMemorySize));
255   }
256 
257   FreePool (Pos);
258   return ReturnStatus;
259 }
260