git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			387 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			387 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| 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_UGA_PIXEL TitleForeground,
 | |
|   IN EFI_UGA_PIXEL TitleBackground,
 | |
|   IN CHAR16        *Title,
 | |
|   IN EFI_UGA_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_UGA_DRAW_PROTOCOL *UgaDraw;
 | |
|   UINT32                SizeOfX;
 | |
|   UINT32                SizeOfY;
 | |
|   UINT32                ColorDepth;
 | |
|   UINT32                RefreshRate;
 | |
|   EFI_UGA_PIXEL         Color;
 | |
|   UINTN                 BlockHeight;
 | |
|   UINTN                 BlockWidth;
 | |
|   UINTN                 BlockNum;
 | |
|   UINTN                 PosX;
 | |
|   UINTN                 PosY;
 | |
|   UINTN                 Index;
 | |
| 
 | |
|   if (Progress > 100) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status = gBS->HandleProtocol (
 | |
|                   gST->ConsoleOutHandle,
 | |
|                   &gEfiUgaDrawProtocolGuid,
 | |
|                   &UgaDraw
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   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_UGA_PIXEL), 0x0);
 | |
| 
 | |
|     Status = UgaDraw->Blt (
 | |
|                         UgaDraw,
 | |
|                         &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;
 | |
|     Status = UgaDraw->Blt (
 | |
|                         UgaDraw,
 | |
|                         &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_UGA_PIXEL                     Foreground;
 | |
|   EFI_UGA_PIXEL                     Background;
 | |
|   EFI_UGA_PIXEL                     Color;
 | |
|   UINT8                             Value;
 | |
|   UINTN                             DataSize;
 | |
|   UINT32                            Attributes;
 | |
| 
 | |
|   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_UGA_PIXEL), 0xff);
 | |
|   SetMem (&Background, sizeof (EFI_UGA_PIXEL), 0x0);
 | |
|   SetMem (&Color, sizeof (EFI_UGA_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,
 | |
|                   &Attributes,
 | |
|                   &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;
 | |
| }
 |