--- /dev/null
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation \r
+All rights reserved. This program and the accompanying materials \r
+are licensed and made available under the terms and conditions of the BSD License \r
+which accompanies this distribution. The full text of the license may be found at \r
+http://opensource.org/licenses/bsd-license.php \r
+ \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+\r
+Module Name:\r
+\r
+ MemoryTest.c\r
+\r
+Abstract:\r
+\r
+ Perform the platform memory test\r
+\r
+--*/\r
+\r
+#include "Bds.h"\r
+#include "BdsPlatform.h"\r
+#include "String.h"\r
+\r
+//\r
+// BDS Platform Functions\r
+//\r
+EFI_STATUS\r
+PlatformBdsShowProgress (\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleForeground,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL TitleBackground,\r
+ IN CHAR16 *Title,\r
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL ProgressColor,\r
+ IN UINTN Progress,\r
+ IN UINTN PreviousValue\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Show progress bar with title above it. It only works in UGA mode.\r
+\r
+Arguments:\r
+ \r
+ TitleForeground - Foreground color for Title.\r
+ TitleBackground - Background color for Title.\r
+ Title - Title above progress bar.\r
+ ProgressColor - Progress bar color.\r
+ Progress - Progress (0-100)\r
+\r
+Returns: \r
+ \r
+ EFI_STATUS - Success update the progress bar\r
+\r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
+ EFI_UGA_DRAW_PROTOCOL *UgaDraw;\r
+ UINT32 SizeOfX;\r
+ UINT32 SizeOfY;\r
+ UINT32 ColorDepth;\r
+ UINT32 RefreshRate;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
+ UINTN BlockHeight;\r
+ UINTN BlockWidth;\r
+ UINTN BlockNum;\r
+ UINTN PosX;\r
+ UINTN PosY;\r
+ UINTN Index;\r
+\r
+ if (Progress > 100) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ UgaDraw = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ gST->ConsoleOutHandle,\r
+ &gEfiGraphicsOutputProtocolGuid,\r
+ &GraphicsOutput\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ GraphicsOutput = NULL;\r
+\r
+ Status = gBS->HandleProtocol (\r
+ gST->ConsoleOutHandle,\r
+ &gEfiUgaDrawProtocolGuid,\r
+ &UgaDraw\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ if (GraphicsOutput != NULL) {\r
+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;\r
+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;\r
+ } else {\r
+ Status = UgaDraw->GetMode (\r
+ UgaDraw,\r
+ &SizeOfX,\r
+ &SizeOfY,\r
+ &ColorDepth,\r
+ &RefreshRate\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ }\r
+\r
+ BlockWidth = SizeOfX / 100;\r
+ BlockHeight = SizeOfY / 50;\r
+\r
+ BlockNum = Progress;\r
+\r
+ PosX = 0;\r
+ PosY = SizeOfY * 48 / 50;\r
+\r
+ if (BlockNum == 0) {\r
+ //\r
+ // Clear progress area\r
+ //\r
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+\r
+ if (GraphicsOutput != NULL) {\r
+ Status = GraphicsOutput->Blt (\r
+ GraphicsOutput,\r
+ &Color,\r
+ EfiBltVideoFill,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ PosY - GLYPH_HEIGHT - 1,\r
+ SizeOfX,\r
+ SizeOfY - (PosY - GLYPH_HEIGHT - 1),\r
+ SizeOfX * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+ );\r
+ } else {\r
+ Status = UgaDraw->Blt (\r
+ UgaDraw,\r
+ (EFI_UGA_PIXEL *) &Color,\r
+ EfiUgaVideoFill,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ PosY - GLYPH_HEIGHT - 1,\r
+ SizeOfX,\r
+ SizeOfY - (PosY - GLYPH_HEIGHT - 1),\r
+ SizeOfX * sizeof (EFI_UGA_PIXEL)\r
+ );\r
+ }\r
+ }\r
+ //\r
+ // Show progress by drawing blocks\r
+ //\r
+ for (Index = PreviousValue; Index < BlockNum; Index++) {\r
+ PosX = Index * BlockWidth;\r
+ if (GraphicsOutput != NULL) {\r
+ Status = GraphicsOutput->Blt (\r
+ GraphicsOutput,\r
+ &ProgressColor,\r
+ EfiBltVideoFill,\r
+ 0,\r
+ 0,\r
+ PosX,\r
+ PosY,\r
+ BlockWidth - 1,\r
+ BlockHeight,\r
+ (BlockWidth) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)\r
+ );\r
+ } else {\r
+ Status = UgaDraw->Blt (\r
+ UgaDraw,\r
+ (EFI_UGA_PIXEL *) &ProgressColor,\r
+ EfiUgaVideoFill,\r
+ 0,\r
+ 0,\r
+ PosX,\r
+ PosY,\r
+ BlockWidth - 1,\r
+ BlockHeight,\r
+ (BlockWidth) * sizeof (EFI_UGA_PIXEL)\r
+ );\r
+ }\r
+ }\r
+\r
+ PrintXY (\r
+ (SizeOfX - StrLen (Title) * GLYPH_WIDTH) / 2,\r
+ PosY - GLYPH_HEIGHT - 1,\r
+ &TitleForeground,\r
+ &TitleBackground,\r
+ Title\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+BdsMemoryTest (\r
+ IN EXTENDMEM_COVERAGE_LEVEL Level\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+ \r
+ Perform the memory test base on the memory test intensive level, \r
+ and update the memory resource.\r
+\r
+Arguments:\r
+ \r
+ Level - The memory test intensive level.\r
+\r
+Returns: \r
+ \r
+ EFI_STATUS - Success test all the system memory and update\r
+ the memory resource\r
+ \r
+--*/\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STATUS InitStatus;\r
+ EFI_STATUS KeyStatus;\r
+ EFI_STATUS ReturnStatus;\r
+ BOOLEAN RequireSoftECCInit;\r
+ EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest;\r
+ UINT64 TestedMemorySize;\r
+ UINT64 TotalMemorySize;\r
+ UINTN TestPercent;\r
+ UINT64 PreviousValue;\r
+ BOOLEAN ErrorOut;\r
+ BOOLEAN TestAbort;\r
+ EFI_INPUT_KEY Key;\r
+ CHAR16 StrPercent[16];\r
+ CHAR16 *StrTotalMemory;\r
+ CHAR16 *Pos;\r
+ CHAR16 *TmpStr;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background;\r
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color;\r
+ UINT8 Value;\r
+ UINTN DataSize;\r
+\r
+ ReturnStatus = EFI_SUCCESS;\r
+ ZeroMem (&Key, sizeof (EFI_INPUT_KEY));\r
+\r
+ Pos = AllocatePool (128);\r
+\r
+ if (Pos == NULL) {\r
+ return ReturnStatus;\r
+ }\r
+\r
+ StrTotalMemory = Pos;\r
+\r
+ TestedMemorySize = 0;\r
+ TotalMemorySize = 0;\r
+ PreviousValue = 0;\r
+ ErrorOut = FALSE;\r
+ TestAbort = FALSE;\r
+\r
+ SetMem (&Foreground, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+ SetMem (&Background, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0x0);\r
+ SetMem (&Color, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL), 0xff);\r
+\r
+ RequireSoftECCInit = FALSE;\r
+\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiGenericMemTestProtocolGuid,\r
+ NULL,\r
+ &GenMemoryTest\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->FreePool (Pos);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ InitStatus = GenMemoryTest->MemoryTestInit (\r
+ GenMemoryTest,\r
+ Level,\r
+ &RequireSoftECCInit\r
+ );\r
+ if (InitStatus == EFI_NO_MEDIA) {\r
+ //\r
+ // The PEI codes also have the relevant memory test code to check the memory,\r
+ // it can select to test some range of the memory or all of them. If PEI code\r
+ // checks all the memory, this BDS memory test will has no not-test memory to\r
+ // do the test, and then the status of EFI_NO_MEDIA will be returned by\r
+ // "MemoryTestInit". So it does not need to test memory again, just return.\r
+ //\r
+ gBS->FreePool (Pos);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 2);\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST));\r
+\r
+ if (TmpStr != NULL) {\r
+ gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
+ gBS->FreePool (TmpStr);\r
+ }\r
+\r
+ do {\r
+ Status = GenMemoryTest->PerformMemoryTest (\r
+ GenMemoryTest,\r
+ &TestedMemorySize,\r
+ &TotalMemorySize,\r
+ &ErrorOut,\r
+ TestAbort\r
+ );\r
+ if (ErrorOut && (Status == EFI_DEVICE_ERROR)) {\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR));\r
+ if (TmpStr != NULL) {\r
+ PrintXY (10, 10, NULL, NULL, TmpStr);\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 4);\r
+ gST->ConOut->OutputString (gST->ConOut, TmpStr);\r
+ gBS->FreePool (TmpStr);\r
+ }\r
+\r
+ ASSERT (0);\r
+ }\r
+\r
+ TestPercent = (UINTN) DivU64x32 (\r
+ DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16),\r
+ (UINTN)DivU64x32 (TotalMemorySize, 16)\r
+ );\r
+ if (TestPercent != PreviousValue) {\r
+ UnicodeValueToString (StrPercent, 0, TestPercent, 0);\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT));\r
+ if (TmpStr != NULL) {\r
+ BdsLibOutputStrings (gST->ConOut, StrPercent, TmpStr, NULL);\r
+ gBS->FreePool (TmpStr);\r
+ }\r
+\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
+ if (TmpStr != NULL) {\r
+ PlatformBdsShowProgress (\r
+ Foreground,\r
+ Background,\r
+ TmpStr,\r
+ Color,\r
+ TestPercent,\r
+ (UINTN) PreviousValue\r
+ );\r
+ gBS->FreePool (TmpStr);\r
+ }\r
+ }\r
+\r
+ PreviousValue = TestPercent;\r
+\r
+ KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
+ if (Key.ScanCode == SCAN_ESC) {\r
+ if (!RequireSoftECCInit) {\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST));\r
+ if (TmpStr != NULL) {\r
+ PlatformBdsShowProgress (\r
+ Foreground,\r
+ Background,\r
+ TmpStr,\r
+ Color,\r
+ 100,\r
+ (UINTN) PreviousValue\r
+ );\r
+ gBS->FreePool (TmpStr);\r
+ }\r
+\r
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0);\r
+ gST->ConOut->OutputString (gST->ConOut, L"100");\r
+ Status = GenMemoryTest->Finished (GenMemoryTest);\r
+ goto Done;\r
+ }\r
+\r
+ TestAbort = TRUE;\r
+ }\r
+ } while (Status != EFI_NOT_FOUND);\r
+\r
+ Status = GenMemoryTest->Finished (GenMemoryTest);\r
+\r
+Done:\r
+ UnicodeValueToString (StrTotalMemory, COMMA_TYPE, (UINTN) TotalMemorySize, 0);\r
+ if (StrTotalMemory[0] == L',') {\r
+ StrTotalMemory++;\r
+ }\r
+\r
+ TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED));\r
+ if (TmpStr != NULL) {\r
+ StrCat (StrTotalMemory, TmpStr);\r
+ gBS->FreePool (TmpStr);\r
+ }\r
+\r
+ gST->ConOut->ClearScreen (gST->ConOut);\r
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT);\r
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);\r
+ gST->ConOut->OutputString (gST->ConOut, StrTotalMemory);\r
+ PlatformBdsShowProgress (\r
+ Foreground,\r
+ Background,\r
+ StrTotalMemory,\r
+ Color,\r
+ 100,\r
+ (UINTN) PreviousValue\r
+ );\r
+\r
+ gBS->FreePool (Pos);\r
+\r
+ DataSize = sizeof (Value);\r
+ Status = gRT->GetVariable (\r
+ L"BootState",\r
+ &gEfiBootStateGuid,\r
+ NULL,\r
+ &DataSize,\r
+ &Value\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Value = 1;\r
+ gRT->SetVariable (\r
+ L"BootState",\r
+ &gEfiBootStateGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+ sizeof (Value),\r
+ &Value\r
+ );\r
+ }\r
+\r
+ return ReturnStatus;\r
+}\r