1) Use FeatureFlag PcdPciBusHotplugDeviceSupport to merge LightPciLib.c with PcdLib.c.
[mirror_edk2.git] / EdkNt32Pkg / Dxe / PlatformBds / Generic / MemoryTest.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 MemoryTest.c\r
15\r
16Abstract:\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
29EFI_STATUS\r
30PlatformBdsShowProgress (\r
406adcd1 31 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
32 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
878ddf1f 33 IN CHAR16 *Title,\r
406adcd1 34 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
878ddf1f 35 IN UINTN Progress,\r
36 IN UINTN PreviousValue\r
37 )\r
38/*++\r
39\r
40Routine Description:\r
41 \r
42 Show progress bar with title above it. It only works in UGA mode.\r
43\r
44Arguments:\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
52Returns: \r
53 \r
54 EFI_STATUS - Success update the progress bar\r
55\r
56--*/\r
57{\r
58 EFI_STATUS Status;\r
406adcd1 59 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
878ddf1f 60 EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
61 UINT32 SizeOfX;\r
62 UINT32 SizeOfY;\r
63 UINT32 ColorDepth;\r
64 UINT32 RefreshRate;\r
406adcd1 65 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
878ddf1f 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
406adcd1 77 UgaDraw = NULL;\r
878ddf1f 78 Status = gBS->HandleProtocol (\r
79 gST->ConsoleOutHandle,\r
406adcd1 80 &gEfiGraphicsOutputProtocolGuid,\r
81 &GraphicsOutput\r
878ddf1f 82 );\r
83 if (EFI_ERROR (Status)) {\r
406adcd1 84 GraphicsOutput = NULL;\r
85\r
86 Status = gBS->HandleProtocol (\r
87 gST->ConsoleOutHandle,\r
88 &gEfiUgaDrawProtocolGuid,\r
89 &UgaDraw\r
90 );\r
91 if (EFI_ERROR (Status)) {\r
92 return EFI_UNSUPPORTED;\r
93 }\r
878ddf1f 94 }\r
95\r
406adcd1 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
878ddf1f 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
406adcd1 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
878ddf1f 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
406adcd1 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
878ddf1f 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
199EFI_STATUS\r
200BdsMemoryTest (\r
201 IN EXTENDMEM_COVERAGE_LEVEL Level\r
202 )\r
203/*++\r
204\r
205Routine 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
210Arguments:\r
211 \r
212 Level - The memory test intensive level.\r
213\r
214Returns: \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
406adcd1 238 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
239 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
240 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
878ddf1f 241 UINT8 Value;\r
242 UINTN DataSize;\r
878ddf1f 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
406adcd1 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
878ddf1f 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 &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
383Done:\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
6874dbd0 414 NULL,\r
878ddf1f 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