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