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