]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkUnixPkg/Dxe/PlatformBds/Generic/MemoryTest.c
Unix version of EFI emulator
[mirror_edk2.git] / EdkUnixPkg / Dxe / PlatformBds / Generic / MemoryTest.c
diff --git a/EdkUnixPkg/Dxe/PlatformBds/Generic/MemoryTest.c b/EdkUnixPkg/Dxe/PlatformBds/Generic/MemoryTest.c
new file mode 100644 (file)
index 0000000..360a26f
--- /dev/null
@@ -0,0 +1,431 @@
+/*++\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