]> git.proxmox.com Git - mirror_edk2.git/blame - EdkNt32Pkg/Dxe/PlatformBds/Generic/MemoryTest.c
Merge GOP related code from r8->r9.
[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
243 UINT32 Attributes;\r
244\r
245 ReturnStatus = EFI_SUCCESS;\r
246 ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
247\r
248 Pos = AllocatePool (128);\r
249\r
250 if (Pos == NULL) {\r
251 return ReturnStatus;\r
252 }\r
253\r
254 StrTotalMemory = Pos;\r
255\r
256 TestedMemorySize = 0;\r
257 TotalMemorySize = 0;\r
258 PreviousValue = 0;\r
259 ErrorOut = FALSE;\r
260 TestAbort = FALSE;\r
261\r
406adcd1 262 SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
263 SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
264 SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
878ddf1f 265\r
266 RequireSoftECCInit = FALSE;\r
267\r
268 gST->ConOut->ClearScreen (gST->ConOut);\r
269 gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
270 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
271\r
272 Status = gBS->LocateProtocol (\r
273 &gEfiGenericMemTestProtocolGuid,\r
274 NULL,\r
275 &GenMemoryTest\r
276 );\r
277 if (EFI_ERROR (Status)) {\r
278 gBS->FreePool (Pos);\r
279 return EFI_SUCCESS;\r
280 }\r
281\r
282 InitStatus = GenMemoryTest->MemoryTestInit (\r
283 GenMemoryTest,\r
284 Level,\r
285 &RequireSoftECCInit\r
286 );\r
287 if (InitStatus == EFI_NO_MEDIA) {\r
288 //\r
289 // The PEI codes also have the relevant memory test code to check the memory,\r
290 // it can select to test some range of the memory or all of them. If PEI code\r
291 // checks all the memory, this BDS memory test will has no not-test memory to\r
292 // do the test, and then the status of EFI_NO_MEDIA will be returned by\r
293 // "MemoryTestInit". So it does not need to test memory again, just return.\r
294 //\r
295 gBS->FreePool (Pos);\r
296 return EFI_SUCCESS;\r
297 }\r
298\r
299 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 2);\r
300 TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST));\r
301\r
302 if (TmpStr != NULL) {\r
303 gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
304 gBS->FreePool (TmpStr);\r
305 }\r
306\r
307 do {\r
308 Status = GenMemoryTest->PerformMemoryTest (\r
309 GenMemoryTest,\r
310 &TestedMemorySize,\r
311 &TotalMemorySize,\r
312 &ErrorOut,\r
313 TestAbort\r
314 );\r
315 if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {\r
316 TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR));\r
317 if (TmpStr != NULL) {\r
318 PrintXY (10, 10, NULL, NULL, TmpStr);\r
319 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 4);\r
320 gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
321 gBS->FreePool (TmpStr);\r
322 }\r
323\r
324 ASSERT (0);\r
325 }\r
326\r
327 TestPercent = (UINTN) DivU64x32 (\r
328 DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),\r
329 (UINTN)DivU64x32 (TotalMemorySize, 16)\r
330 );\r
331 if (TestPercent != PreviousValue) {\r
332 UnicodeValueToString (StrPercent, 0, TestPercent, 0);\r
333 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
334 TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT));\r
335 if (TmpStr != NULL) {\r
336 BdsLibOutputStrings (gST->ConOut, StrPercent, TmpStr, NULL);\r
337 gBS->FreePool (TmpStr);\r
338 }\r
339\r
340 TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
341 if (TmpStr != NULL) {\r
342 PlatformBdsShowProgress (\r
343 Foreground,\r
344 Background,\r
345 TmpStr,\r
346 Color,\r
347 TestPercent,\r
348 (UINTN) PreviousValue\r
349 );\r
350 gBS->FreePool (TmpStr);\r
351 }\r
352 }\r
353\r
354 PreviousValue = TestPercent;\r
355\r
356 KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
357 if (Key.ScanCode == SCAN_ESC) {\r
358 if (!RequireSoftECCInit) {\r
359 TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
360 if (TmpStr != NULL) {\r
361 PlatformBdsShowProgress (\r
362 Foreground,\r
363 Background,\r
364 TmpStr,\r
365 Color,\r
366 100,\r
367 (UINTN) PreviousValue\r
368 );\r
369 gBS->FreePool (TmpStr);\r
370 }\r
371\r
372 gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
373 gST->ConOut->OutputString (gST->ConOut, L"100");\r
374 Status = GenMemoryTest->Finished (GenMemoryTest);\r
375 goto Done;\r
376 }\r
377\r
378 TestAbort = TRUE;\r
379 }\r
380 } while (Status != EFI_NOT_FOUND);\r
381\r
382 Status = GenMemoryTest->Finished (GenMemoryTest);\r
383\r
384Done:\r
385 UnicodeValueToString (StrTotalMemory, COMMA_TYPE, (UINTN) TotalMemorySize, 0);\r
386 if (StrTotalMemory[0] == L',') {\r
387 StrTotalMemory++;\r
388 }\r
389\r
390 TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED));\r
391 if (TmpStr != NULL) {\r
392 StrCat (StrTotalMemory, TmpStr);\r
393 gBS->FreePool (TmpStr);\r
394 }\r
395\r
396 gST->ConOut->ClearScreen (gST->ConOut);\r
397 gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
398 gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
399 gST->ConOut->OutputString (gST->ConOut, StrTotalMemory);\r
400 PlatformBdsShowProgress (\r
401 Foreground,\r
402 Background,\r
403 StrTotalMemory,\r
404 Color,\r
405 100,\r
406 (UINTN) PreviousValue\r
407 );\r
408\r
409 gBS->FreePool (Pos);\r
410\r
411 DataSize = sizeof (Value);\r
412 Status = gRT->GetVariable (\r
413 L"BootState",\r
414 &gEfiBootStateGuid,\r
415 &Attributes,\r
416 &DataSize,\r
417 &Value\r
418 );\r
419\r
420 if (EFI_ERROR (Status)) {\r
421 Value = 1;\r
422 gRT->SetVariable (\r
423 L"BootState",\r
424 &gEfiBootStateGuid,\r
425 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
426 sizeof (Value),\r
427 &Value\r
428 );\r
429 }\r
430\r
431 return ReturnStatus;\r
432}\r