Cc: Feng Tian <feng.tian@intel.com> Cc: Star Zeng <star.zeng@intel.com> Cc: Ruiyu Ni <ruiyu.ni@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com> Reviewed-by: Star Zeng <star.zeng@intel.com> Reviewed-by: Feng Tian <feng.tian@intel.com> Reviewed-by: Jeff Fan <jeff.fan@intel.com>
		
			
				
	
	
		
			1080 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1080 lines
		
	
	
		
			36 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  The application to show the Boot Manager Menu.
 | 
						|
 | 
						|
Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
 | 
						|
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.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "BootManagerMenu.h"
 | 
						|
 | 
						|
EFI_HII_HANDLE gStringPackHandle;
 | 
						|
 | 
						|
BOOLEAN   mModeInitialized = FALSE;
 | 
						|
 | 
						|
//
 | 
						|
// Boot video resolution and text mode.
 | 
						|
//
 | 
						|
UINT32    mBootHorizontalResolution    = 0;
 | 
						|
UINT32    mBootVerticalResolution      = 0;
 | 
						|
UINT32    mBootTextModeColumn          = 0;
 | 
						|
UINT32    mBootTextModeRow             = 0;
 | 
						|
//
 | 
						|
// BIOS setup video resolution and text mode.
 | 
						|
//
 | 
						|
UINT32    mSetupTextModeColumn         = 0;
 | 
						|
UINT32    mSetupTextModeRow            = 0;
 | 
						|
UINT32    mSetupHorizontalResolution   = 0;
 | 
						|
UINT32    mSetupVerticalResolution     = 0;
 | 
						|
 | 
						|
/**
 | 
						|
  Prints a unicode string to the default console, at
 | 
						|
  the supplied cursor position, using L"%s" format.
 | 
						|
 | 
						|
  @param  Column     The cursor position to print the string at.
 | 
						|
  @param  Row        The cursor position to print the string at
 | 
						|
  @param  String     String pointer.
 | 
						|
 | 
						|
  @return Length of string printed to the console
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
PrintStringAt (
 | 
						|
  IN UINTN     Column,
 | 
						|
  IN UINTN     Row,
 | 
						|
  IN CHAR16    *String
 | 
						|
  )
 | 
						|
{
 | 
						|
 | 
						|
  gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
 | 
						|
  return Print (L"%s", String);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Prints a chracter to the default console, at
 | 
						|
  the supplied cursor position, using L"%c" format.
 | 
						|
 | 
						|
  @param  Column     The cursor position to print the string at.
 | 
						|
  @param  Row        The cursor position to print the string at.
 | 
						|
  @param  Character  Character to print.
 | 
						|
 | 
						|
  @return Length of string printed to the console.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
PrintCharAt (
 | 
						|
  IN UINTN     Column,
 | 
						|
  IN UINTN     Row,
 | 
						|
  CHAR16       Character
 | 
						|
  )
 | 
						|
{
 | 
						|
  gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
 | 
						|
  return Print (L"%c", Character);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Count the storage space of a Unicode string which uses current lanaguag to get 
 | 
						|
  from input string ID.
 | 
						|
 | 
						|
  @param StringId          The input string to be counted.
 | 
						|
 | 
						|
  @return Storage space for the input string.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
GetLineWidth (
 | 
						|
  IN EFI_STRING_ID       StringId
 | 
						|
  )
 | 
						|
{  
 | 
						|
  UINTN        Index;
 | 
						|
  UINTN        IncrementValue;
 | 
						|
  EFI_STRING   String;
 | 
						|
  UINTN        LineWidth;
 | 
						|
  
 | 
						|
  LineWidth = 0;
 | 
						|
  String = HiiGetString (gStringPackHandle, StringId, NULL); 
 | 
						|
  
 | 
						|
  if (String != NULL) {
 | 
						|
    Index           = 0;
 | 
						|
    IncrementValue  = 1;
 | 
						|
    
 | 
						|
    do {
 | 
						|
      //
 | 
						|
      // Advance to the null-terminator or to the first width directive
 | 
						|
      //
 | 
						|
      for (;
 | 
						|
           (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0);
 | 
						|
           Index++, LineWidth = LineWidth + IncrementValue
 | 
						|
          )
 | 
						|
        ;
 | 
						|
    
 | 
						|
      //
 | 
						|
      // We hit the null-terminator, we now have a count
 | 
						|
      //
 | 
						|
      if (String[Index] == 0) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      //
 | 
						|
      // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed
 | 
						|
      // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2)
 | 
						|
      //
 | 
						|
      if (String[Index] == NARROW_CHAR) {
 | 
						|
        //
 | 
						|
        // Skip to the next character
 | 
						|
        //
 | 
						|
        Index++;
 | 
						|
        IncrementValue = 1;
 | 
						|
      } else {
 | 
						|
        //
 | 
						|
        // Skip to the next character
 | 
						|
        //
 | 
						|
        Index++;
 | 
						|
        IncrementValue = 2;
 | 
						|
      }
 | 
						|
    } while (String[Index] != 0);   
 | 
						|
    FreePool (String);
 | 
						|
  }
 | 
						|
  
 | 
						|
  return LineWidth;  
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function uses calculate the boot menu location, size and scroll bar information.
 | 
						|
 | 
						|
  @param  BootMenuData            The boot menu data to be proccessed.
 | 
						|
 | 
						|
  @return EFI_SUCCESS             calculate boot menu information successful.
 | 
						|
  @retval EFI_INVALID_PARAMETER   Input parameter is invalid   
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS 
 | 
						|
InitializeBootMenuScreen (
 | 
						|
  IN OUT  BOOT_MENU_POPUP_DATA  *BootMenuData
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN         MaxStrWidth;
 | 
						|
  UINTN         StrWidth;
 | 
						|
  UINTN         Index;
 | 
						|
  UINTN         Column;
 | 
						|
  UINTN         Row;
 | 
						|
  UINTN         MaxPrintRows;
 | 
						|
  UINTN         UnSelectableItmes;
 | 
						|
 | 
						|
  if (BootMenuData == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Get maximum string width
 | 
						|
  //
 | 
						|
  MaxStrWidth = 0;  
 | 
						|
  for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++) {    
 | 
						|
    StrWidth = GetLineWidth (BootMenuData->TitleToken[Index]);
 | 
						|
    MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth;
 | 
						|
  }
 | 
						|
   
 | 
						|
  for (Index = 0; Index < BootMenuData->ItemCount; Index++) {
 | 
						|
    StrWidth = GetLineWidth (BootMenuData->PtrTokens[Index]);
 | 
						|
    MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth; 
 | 
						|
  } 
 | 
						|
  
 | 
						|
  for (Index = 0; Index < HELP_TOKEN_COUNT; Index++) {    
 | 
						|
    StrWidth = GetLineWidth (BootMenuData->HelpToken[Index]);
 | 
						|
    MaxStrWidth = MaxStrWidth > StrWidth ? MaxStrWidth : StrWidth;
 | 
						|
  }  
 | 
						|
  //
 | 
						|
  // query current row and column to calculate boot menu location
 | 
						|
  //
 | 
						|
  gST->ConOut->QueryMode (
 | 
						|
                 gST->ConOut,
 | 
						|
                 gST->ConOut->Mode->Mode,
 | 
						|
                 &Column,
 | 
						|
                 &Row
 | 
						|
                 ); 
 | 
						|
                 
 | 
						|
  MaxPrintRows = Row - 6;    
 | 
						|
  UnSelectableItmes = TITLE_TOKEN_COUNT + 2 + HELP_TOKEN_COUNT + 2;           
 | 
						|
  BootMenuData->MenuScreen.Width = MaxStrWidth + 8;
 | 
						|
  if (BootMenuData->ItemCount + UnSelectableItmes > MaxPrintRows) {
 | 
						|
    BootMenuData->MenuScreen.Height = MaxPrintRows;
 | 
						|
    BootMenuData->ScrollBarControl.HasScrollBar = TRUE;
 | 
						|
    BootMenuData->ScrollBarControl.ItemCountPerScreen = MaxPrintRows - UnSelectableItmes;
 | 
						|
    BootMenuData->ScrollBarControl.FirstItem = 0;
 | 
						|
    BootMenuData->ScrollBarControl.LastItem = MaxPrintRows - UnSelectableItmes - 1;
 | 
						|
  } else {
 | 
						|
    BootMenuData->MenuScreen.Height = BootMenuData->ItemCount + UnSelectableItmes;
 | 
						|
    BootMenuData->ScrollBarControl.HasScrollBar = FALSE;
 | 
						|
    BootMenuData->ScrollBarControl.ItemCountPerScreen = BootMenuData->ItemCount;
 | 
						|
    BootMenuData->ScrollBarControl.FirstItem = 0;
 | 
						|
    BootMenuData->ScrollBarControl.LastItem = BootMenuData->ItemCount - 1;    
 | 
						|
  }
 | 
						|
  BootMenuData->MenuScreen.StartCol = (Column -  BootMenuData->MenuScreen.Width) / 2;              
 | 
						|
  BootMenuData->MenuScreen.StartRow = (Row -  BootMenuData->MenuScreen.Height) / 2;  
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
/**
 | 
						|
  This funciton uses check boot option is wheher setup application or no
 | 
						|
 | 
						|
  @param   BootOption   Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
 | 
						|
  
 | 
						|
  @retval  TRUE         This boot option is setup application.
 | 
						|
  @retval  FALSE        This boot options isn't setup application
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsBootManagerMenu (
 | 
						|
  IN  EFI_BOOT_MANAGER_LOAD_OPTION    *BootOption
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  EFI_BOOT_MANAGER_LOAD_OPTION        BootManagerMenu;
 | 
						|
 | 
						|
  Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    EfiBootManagerFreeLoadOption (&BootManagerMenu);
 | 
						|
  }
 | 
						|
 | 
						|
  return (BOOLEAN) (!EFI_ERROR (Status) && (BootOption->OptionNumber == BootManagerMenu.OptionNumber));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Return whether to ignore the boot option.
 | 
						|
 | 
						|
  @param BootOption  Pointer to EFI_BOOT_MANAGER_LOAD_OPTION to check.
 | 
						|
 | 
						|
  @retval TRUE  Ignore the boot optin.
 | 
						|
  @retval FALSE Do not ignore the boot option.
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IgnoreBootOption (
 | 
						|
  IN   EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL      *ImageDevicePath;
 | 
						|
 | 
						|
  //
 | 
						|
  // Ignore myself.
 | 
						|
  //
 | 
						|
  Status = gBS->HandleProtocol (gImageHandle, &gEfiLoadedImageDevicePathProtocolGuid, (VOID **) &ImageDevicePath);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  if (CompareMem (BootOption->FilePath, ImageDevicePath, GetDevicePathSize (ImageDevicePath)) == 0) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Do not ignore Boot Manager Menu.
 | 
						|
  //
 | 
						|
  if (IsBootManagerMenu (BootOption)) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Ignore the hidden/inactive boot option.
 | 
						|
  //
 | 
						|
  if (((BootOption->Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption->Attributes & LOAD_OPTION_ACTIVE) == 0)) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This funciton uses to initialize boot menu data
 | 
						|
 | 
						|
  @param   BootOption             Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
 | 
						|
  @param   BootOptionCount        Number of boot option.
 | 
						|
  @param   BootMenuData           The Input BootMenuData to be initialized.
 | 
						|
  
 | 
						|
  @retval  EFI_SUCCESS            Initialize boot menu data successful.
 | 
						|
  @retval  EFI_INVALID_PARAMETER  Input parameter is invalid.   
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
InitializeBootMenuData (
 | 
						|
  IN   EFI_BOOT_MANAGER_LOAD_OPTION  *BootOption,
 | 
						|
  IN   UINTN                         BootOptionCount,
 | 
						|
  OUT  BOOT_MENU_POPUP_DATA          *BootMenuData
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                         Index;
 | 
						|
  UINTN                         StrIndex;
 | 
						|
      
 | 
						|
  if (BootOption == NULL || BootMenuData == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  BootMenuData->TitleToken[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_TITLE_STRING);
 | 
						|
  BootMenuData->PtrTokens     = AllocateZeroPool (BootOptionCount * sizeof (EFI_STRING_ID));
 | 
						|
  ASSERT (BootMenuData->PtrTokens != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Skip boot option which created by BootNext Variable
 | 
						|
  //
 | 
						|
  for (StrIndex = 0, Index = 0; Index < BootOptionCount; Index++) {
 | 
						|
    if (IgnoreBootOption (&BootOption[Index])) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    ASSERT (BootOption[Index].Description != NULL);
 | 
						|
    BootMenuData->PtrTokens[StrIndex++] = HiiSetString (
 | 
						|
                                            gStringPackHandle, 
 | 
						|
                                            0,
 | 
						|
                                            BootOption[Index].Description,
 | 
						|
                                            NULL
 | 
						|
                                            );
 | 
						|
  }
 | 
						|
 | 
						|
  BootMenuData->ItemCount           = StrIndex;   
 | 
						|
  BootMenuData->HelpToken[0] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP1_STRING);
 | 
						|
  BootMenuData->HelpToken[1] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP2_STRING);
 | 
						|
  BootMenuData->HelpToken[2] = STRING_TOKEN (STR_BOOT_POPUP_MENU_HELP3_STRING);
 | 
						|
  InitializeBootMenuScreen (BootMenuData);
 | 
						|
  BootMenuData->SelectItem = 0;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}    
 | 
						|
 | 
						|
/**
 | 
						|
  This function uses input select item to highlight selected item
 | 
						|
  and set current selected item in BootMenuData
 | 
						|
 | 
						|
  @param  WantSelectItem          The user wants to select item.
 | 
						|
  @param  BootMenuData            The boot menu data to be proccessed
 | 
						|
 | 
						|
  @return EFI_SUCCESS             Highlight selected item and update current selected 
 | 
						|
                                  item successful 
 | 
						|
  @retval EFI_INVALID_PARAMETER   Input parameter is invalid   
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BootMenuSelectItem (
 | 
						|
  IN     UINTN                 WantSelectItem,
 | 
						|
  IN OUT BOOT_MENU_POPUP_DATA  *BootMenuData
 | 
						|
  )
 | 
						|
{
 | 
						|
  INT32                 SavedAttribute;
 | 
						|
  EFI_STRING            String;
 | 
						|
  UINTN                 StartCol;  
 | 
						|
  UINTN                 StartRow;
 | 
						|
  UINTN                 PrintCol;
 | 
						|
  UINTN                 PrintRow;
 | 
						|
  UINTN                 TopShadeNum;
 | 
						|
  UINTN                 LowShadeNum;
 | 
						|
  UINTN                 FirstItem;
 | 
						|
  UINTN                 LastItem;
 | 
						|
  UINTN                 ItemCountPerScreen;
 | 
						|
  UINTN                 Index;
 | 
						|
  BOOLEAN               RePaintItems;
 | 
						|
  
 | 
						|
  if (BootMenuData == NULL || WantSelectItem >= BootMenuData->ItemCount) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  SavedAttribute = gST->ConOut->Mode->Attribute;
 | 
						|
  RePaintItems = FALSE;
 | 
						|
  StartCol = BootMenuData->MenuScreen.StartCol;
 | 
						|
  StartRow = BootMenuData->MenuScreen.StartRow;
 | 
						|
  //
 | 
						|
  // print selectable items again and adjust scroll bar if need
 | 
						|
  //         
 | 
						|
  if (BootMenuData->ScrollBarControl.HasScrollBar &&
 | 
						|
      (WantSelectItem < BootMenuData->ScrollBarControl.FirstItem ||
 | 
						|
      WantSelectItem > BootMenuData->ScrollBarControl.LastItem ||
 | 
						|
      WantSelectItem == BootMenuData->SelectItem)) {          
 | 
						|
    ItemCountPerScreen   = BootMenuData->ScrollBarControl.ItemCountPerScreen;
 | 
						|
    //
 | 
						|
    // Set first item and last item
 | 
						|
    //     
 | 
						|
    if (WantSelectItem < BootMenuData->ScrollBarControl.FirstItem) {
 | 
						|
      BootMenuData->ScrollBarControl.FirstItem = WantSelectItem;
 | 
						|
      BootMenuData->ScrollBarControl.LastItem = WantSelectItem + ItemCountPerScreen - 1;  
 | 
						|
    } else if (WantSelectItem > BootMenuData->ScrollBarControl.LastItem) {
 | 
						|
      BootMenuData->ScrollBarControl.FirstItem = WantSelectItem - ItemCountPerScreen + 1; 
 | 
						|
      BootMenuData->ScrollBarControl.LastItem = WantSelectItem;
 | 
						|
    }
 | 
						|
    gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);
 | 
						|
    FirstItem = BootMenuData->ScrollBarControl.FirstItem;
 | 
						|
    LastItem  = BootMenuData->ScrollBarControl.LastItem;
 | 
						|
    TopShadeNum = 0;
 | 
						|
    if (FirstItem != 0) {
 | 
						|
      TopShadeNum = (FirstItem * ItemCountPerScreen) / BootMenuData->ItemCount;
 | 
						|
      if ((FirstItem * ItemCountPerScreen) % BootMenuData->ItemCount != 0) {
 | 
						|
        TopShadeNum++;
 | 
						|
      }
 | 
						|
      PrintCol = StartCol  + BootMenuData->MenuScreen.Width - 2;
 | 
						|
      PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;  
 | 
						|
      for (Index = 0; Index < TopShadeNum; Index++, PrintRow++) {
 | 
						|
        PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_LIGHT_SHADE);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    LowShadeNum = 0;
 | 
						|
    if (LastItem != BootMenuData->ItemCount - 1) {
 | 
						|
      LowShadeNum = ((BootMenuData->ItemCount - 1 - LastItem) * ItemCountPerScreen) / BootMenuData->ItemCount;
 | 
						|
      if (((BootMenuData->ItemCount - 1 - LastItem) * ItemCountPerScreen) % BootMenuData->ItemCount != 0) {
 | 
						|
        LowShadeNum++;
 | 
						|
      }
 | 
						|
      PrintCol = StartCol  + BootMenuData->MenuScreen.Width - 2;
 | 
						|
      PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + ItemCountPerScreen - LowShadeNum;  
 | 
						|
      for (Index = 0; Index < LowShadeNum; Index++, PrintRow++) {
 | 
						|
        PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_LIGHT_SHADE);
 | 
						|
      } 
 | 
						|
    }
 | 
						|
    PrintCol = StartCol  + BootMenuData->MenuScreen.Width - 2;
 | 
						|
    PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + TopShadeNum;  
 | 
						|
    for (Index = TopShadeNum; Index < ItemCountPerScreen - LowShadeNum; Index++, PrintRow++) {
 | 
						|
      PrintCharAt (PrintCol, PrintRow, BLOCKELEMENT_FULL_BLOCK);
 | 
						|
    }      
 | 
						|
 | 
						|
 | 
						|
    //
 | 
						|
    // Clear selectable items first
 | 
						|
    //
 | 
						|
    PrintCol = StartCol  + 1;
 | 
						|
    PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;  
 | 
						|
    String = AllocateZeroPool ((BootMenuData->MenuScreen.Width - 2) * sizeof (CHAR16));
 | 
						|
    ASSERT (String != NULL);
 | 
						|
    for (Index = 0; Index < BootMenuData->MenuScreen.Width - 3; Index++) {
 | 
						|
      String[Index] = 0x20;
 | 
						|
    }      
 | 
						|
    for (Index = 0; Index < ItemCountPerScreen; Index++) {        
 | 
						|
      PrintStringAt (PrintCol, PrintRow + Index, String); 
 | 
						|
    }
 | 
						|
    FreePool (String);
 | 
						|
    //
 | 
						|
    // print selectable items  
 | 
						|
    //
 | 
						|
    for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) {
 | 
						|
      String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index + FirstItem], NULL);
 | 
						|
      PrintStringAt (PrintCol, PrintRow, String);
 | 
						|
      FreePool (String); 
 | 
						|
    }
 | 
						|
    RePaintItems = TRUE;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Print want to select item 
 | 
						|
  //
 | 
						|
  FirstItem = BootMenuData->ScrollBarControl.FirstItem;
 | 
						|
  gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLACK);
 | 
						|
  String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[WantSelectItem], NULL);
 | 
						|
  PrintCol = StartCol  + 1;  
 | 
						|
  PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + WantSelectItem - FirstItem;  
 | 
						|
  PrintStringAt (PrintCol, PrintRow, String);
 | 
						|
  FreePool (String);
 | 
						|
  
 | 
						|
  //
 | 
						|
  // if Want Select and selected item isn't the same and doesn't re-draw selectable 
 | 
						|
  // items, clear select item
 | 
						|
  //
 | 
						|
  if (WantSelectItem != BootMenuData->SelectItem && !RePaintItems) {
 | 
						|
    gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);
 | 
						|
    String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[BootMenuData->SelectItem], NULL);
 | 
						|
    PrintCol = StartCol  + 1;  
 | 
						|
    PrintRow = StartRow + 3 + BootMenuData->SelectItem - FirstItem;  
 | 
						|
    PrintStringAt (PrintCol, PrintRow, String);
 | 
						|
    FreePool (String);    
 | 
						|
  }
 | 
						|
 | 
						|
  gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
 | 
						|
  BootMenuData->SelectItem = WantSelectItem;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This funciton uses to draw boot popup menu
 | 
						|
 | 
						|
  @param   BootMenuData           The Input BootMenuData to be processed.
 | 
						|
  
 | 
						|
  @retval  EFI_SUCCESS            Draw boot popup menu successful.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS 
 | 
						|
DrawBootPopupMenu (
 | 
						|
  IN  BOOT_MENU_POPUP_DATA  *BootMenuData
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STRING            String;
 | 
						|
  UINTN                 Index;
 | 
						|
  UINTN                 Width;  
 | 
						|
  UINTN                 StartCol;
 | 
						|
  UINTN                 StartRow;
 | 
						|
  UINTN                 PrintRow;
 | 
						|
  UINTN                 PrintCol;
 | 
						|
  UINTN                 LineWidth;
 | 
						|
  INT32                 SavedAttribute; 
 | 
						|
  UINTN                 ItemCountPerScreen;  
 | 
						|
 | 
						|
  gST->ConOut->ClearScreen (gST->ConOut);
 | 
						|
  
 | 
						|
  SavedAttribute = gST->ConOut->Mode->Attribute;
 | 
						|
  gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);
 | 
						|
  Width    = BootMenuData->MenuScreen.Width;
 | 
						|
  StartCol = BootMenuData->MenuScreen.StartCol;
 | 
						|
  StartRow = BootMenuData->MenuScreen.StartRow;
 | 
						|
  ItemCountPerScreen = BootMenuData->ScrollBarControl.ItemCountPerScreen;
 | 
						|
  PrintRow = StartRow;
 | 
						|
 
 | 
						|
  gST->ConOut->EnableCursor (gST->ConOut, FALSE);
 | 
						|
  //
 | 
						|
  // Draw Boot popup menu screen
 | 
						|
  //
 | 
						|
  PrintCharAt (StartCol, PrintRow, BOXDRAW_DOWN_RIGHT);
 | 
						|
  for (Index = 1; Index < Width - 1; Index++) {
 | 
						|
    PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); 
 | 
						|
  }
 | 
						|
  PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_DOWN_LEFT);
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Draw the screen for title
 | 
						|
  //
 | 
						|
  String = AllocateZeroPool ((Width - 1) * sizeof (CHAR16));
 | 
						|
  ASSERT (String != NULL);
 | 
						|
  for (Index = 0; Index < Width - 2; Index++) {
 | 
						|
    String[Index] = 0x20;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++) {
 | 
						|
    PrintRow++;
 | 
						|
    PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);  
 | 
						|
    PrintStringAt (StartCol + 1, PrintRow, String);
 | 
						|
    PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);
 | 
						|
  }
 | 
						|
  
 | 
						|
  PrintRow++;
 | 
						|
  PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL_RIGHT);
 | 
						|
  for (Index = 1; Index < Width - 1; Index++) {
 | 
						|
    PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); 
 | 
						|
  }
 | 
						|
  PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL_LEFT);  
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Draw screen for selectable items
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < ItemCountPerScreen; Index++) {
 | 
						|
    PrintRow++;
 | 
						|
    PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);
 | 
						|
    PrintStringAt (StartCol + 1, PrintRow, String);
 | 
						|
    PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);
 | 
						|
  }  
 | 
						|
 | 
						|
  PrintRow++;
 | 
						|
  PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL_RIGHT);
 | 
						|
  for (Index = 1; Index < Width - 1; Index++) {
 | 
						|
    PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); 
 | 
						|
  }
 | 
						|
  PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL_LEFT);
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Draw screen for Help
 | 
						|
  //
 | 
						|
  for (Index = 0; Index < HELP_TOKEN_COUNT; Index++) {
 | 
						|
    PrintRow++;
 | 
						|
    PrintCharAt (StartCol, PrintRow, BOXDRAW_VERTICAL);
 | 
						|
    PrintStringAt (StartCol + 1, PrintRow, String);
 | 
						|
    PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_VERTICAL);
 | 
						|
  }
 | 
						|
  FreePool (String);  
 | 
						|
    
 | 
						|
  PrintRow++;  
 | 
						|
  PrintCharAt (StartCol, PrintRow, BOXDRAW_UP_RIGHT);
 | 
						|
  for (Index = 1; Index < Width - 1; Index++) {
 | 
						|
    PrintCharAt (StartCol + Index, PrintRow, BOXDRAW_HORIZONTAL); 
 | 
						|
  }
 | 
						|
  PrintCharAt (StartCol + Width - 1, PrintRow, BOXDRAW_UP_LEFT);        
 | 
						|
  
 | 
						|
  
 | 
						|
  //
 | 
						|
  // print title strings
 | 
						|
  //
 | 
						|
  PrintRow = StartRow + 1;
 | 
						|
  for (Index = 0; Index < TITLE_TOKEN_COUNT; Index++, PrintRow++) {
 | 
						|
    String = HiiGetString (gStringPackHandle, BootMenuData->TitleToken[Index], NULL);
 | 
						|
    LineWidth = GetLineWidth (BootMenuData->TitleToken[Index]);      
 | 
						|
    PrintCol = StartCol + (Width - LineWidth) / 2;
 | 
						|
    PrintStringAt (PrintCol, PrintRow, String);
 | 
						|
    FreePool (String);
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // print selectable items
 | 
						|
  //
 | 
						|
  PrintCol = StartCol + 1;
 | 
						|
  PrintRow = StartRow + TITLE_TOKEN_COUNT + 2;  
 | 
						|
  for (Index = 0; Index < ItemCountPerScreen; Index++, PrintRow++) {
 | 
						|
    String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[Index], NULL);
 | 
						|
    PrintStringAt (PrintCol, PrintRow, String);
 | 
						|
    FreePool (String); 
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Print Help strings
 | 
						|
  //
 | 
						|
  PrintRow++;
 | 
						|
  for (Index = 0; Index < HELP_TOKEN_COUNT; Index++, PrintRow++) {
 | 
						|
    String = HiiGetString (gStringPackHandle, BootMenuData->HelpToken[Index], NULL);
 | 
						|
    LineWidth = GetLineWidth (BootMenuData->HelpToken[Index]);
 | 
						|
    PrintCol = StartCol + (Width - LineWidth) / 2;
 | 
						|
    PrintStringAt (PrintCol, PrintRow, String);
 | 
						|
    FreePool (String);
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Print scroll bar if has scroll bar
 | 
						|
  //
 | 
						|
  if (BootMenuData->ScrollBarControl.HasScrollBar) {
 | 
						|
    PrintCol = StartCol + Width - 2;
 | 
						|
    PrintRow = StartRow + 2; 
 | 
						|
    PrintCharAt (PrintCol, PrintRow, GEOMETRICSHAPE_UP_TRIANGLE); 
 | 
						|
    PrintCharAt (PrintCol + 1, PrintRow, BOXDRAW_VERTICAL); 
 | 
						|
    PrintRow += (ItemCountPerScreen + 1);    
 | 
						|
    PrintCharAt (PrintCol, PrintRow, GEOMETRICSHAPE_DOWN_TRIANGLE);
 | 
						|
    PrintCharAt (PrintCol + 1, PrintRow, BOXDRAW_VERTICAL); 
 | 
						|
  }  
 | 
						|
    
 | 
						|
  gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
 | 
						|
  //
 | 
						|
  // Print Selected item
 | 
						|
  //
 | 
						|
  BootMenuSelectItem (BootMenuData->SelectItem, BootMenuData);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This funciton uses to boot from selected item 
 | 
						|
 | 
						|
  @param   BootOptions            Pointer to EFI_BOOT_MANAGER_LOAD_OPTION array.
 | 
						|
  @param   BootOptionCount        Number of boot option.
 | 
						|
  @param   SelectItem             Current selected item.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
BootFromSelectOption (
 | 
						|
  IN   EFI_BOOT_MANAGER_LOAD_OPTION  *BootOptions,
 | 
						|
  IN   UINTN                         BootOptionCount, 
 | 
						|
  IN   UINTN                         SelectItem
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN                 ItemNum;
 | 
						|
  UINTN                 Index;
 | 
						|
 | 
						|
  ASSERT (BootOptions != NULL);
 | 
						|
 | 
						|
  for (ItemNum = 0, Index = 0; Index < BootOptionCount; Index++) {
 | 
						|
    if (IgnoreBootOption (&BootOptions[Index])) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (ItemNum++ == SelectItem) {
 | 
						|
      EfiBootManagerBoot (&BootOptions[Index]);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  This function will change video resolution and text mode
 | 
						|
  according to defined setup mode or defined boot mode  
 | 
						|
 | 
						|
  @param  IsSetupMode   Indicate mode is changed to setup mode or boot mode. 
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS  Mode is changed successfully.
 | 
						|
  @retval  Others             Mode failed to be changed.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BdsSetConsoleMode (
 | 
						|
  BOOLEAN  IsSetupMode
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_GRAPHICS_OUTPUT_PROTOCOL          *GraphicsOutput;
 | 
						|
  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL       *SimpleTextOut;
 | 
						|
  UINTN                                 SizeOfInfo;
 | 
						|
  EFI_GRAPHICS_OUTPUT_MODE_INFORMATION  *Info;
 | 
						|
  UINT32                                MaxGopMode;
 | 
						|
  UINT32                                MaxTextMode;
 | 
						|
  UINT32                                ModeNumber;
 | 
						|
  UINT32                                NewHorizontalResolution;
 | 
						|
  UINT32                                NewVerticalResolution;
 | 
						|
  UINT32                                NewColumns;
 | 
						|
  UINT32                                NewRows;
 | 
						|
  UINTN                                 HandleCount;
 | 
						|
  EFI_HANDLE                            *HandleBuffer;
 | 
						|
  EFI_STATUS                            Status;
 | 
						|
  UINTN                                 Index;
 | 
						|
  UINTN                                 CurrentColumn;
 | 
						|
  UINTN                                 CurrentRow;  
 | 
						|
 | 
						|
  MaxGopMode  = 0;
 | 
						|
  MaxTextMode = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get current video resolution and text mode 
 | 
						|
  //
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  gST->ConsoleOutHandle,
 | 
						|
                  &gEfiGraphicsOutputProtocolGuid,
 | 
						|
                  (VOID**)&GraphicsOutput
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    GraphicsOutput = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  gST->ConsoleOutHandle,
 | 
						|
                  &gEfiSimpleTextOutProtocolGuid,
 | 
						|
                  (VOID**)&SimpleTextOut
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    SimpleTextOut = NULL;
 | 
						|
  }  
 | 
						|
 | 
						|
  if ((GraphicsOutput == NULL) || (SimpleTextOut == NULL)) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if (IsSetupMode) {
 | 
						|
    //
 | 
						|
    // The requried resolution and text mode is setup mode.
 | 
						|
    //
 | 
						|
    NewHorizontalResolution = mSetupHorizontalResolution;
 | 
						|
    NewVerticalResolution   = mSetupVerticalResolution;
 | 
						|
    NewColumns              = mSetupTextModeColumn;
 | 
						|
    NewRows                 = mSetupTextModeRow;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // The required resolution and text mode is boot mode.
 | 
						|
    //
 | 
						|
    NewHorizontalResolution = mBootHorizontalResolution;
 | 
						|
    NewVerticalResolution   = mBootVerticalResolution;
 | 
						|
    NewColumns              = mBootTextModeColumn;
 | 
						|
    NewRows                 = mBootTextModeRow;   
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (GraphicsOutput != NULL) {
 | 
						|
    MaxGopMode  = GraphicsOutput->Mode->MaxMode;
 | 
						|
  } 
 | 
						|
 | 
						|
  if (SimpleTextOut != NULL) {
 | 
						|
    MaxTextMode = SimpleTextOut->Mode->MaxMode;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 1. If current video resolution is same with required video resolution,
 | 
						|
  //    video resolution need not be changed.
 | 
						|
  //    1.1. If current text mode is same with required text mode, text mode need not be changed.
 | 
						|
  //    1.2. If current text mode is different from required text mode, text mode need be changed.
 | 
						|
  // 2. If current video resolution is different from required video resolution, we need restart whole console drivers.
 | 
						|
  //
 | 
						|
  for (ModeNumber = 0; ModeNumber < MaxGopMode; ModeNumber++) {
 | 
						|
    Status = GraphicsOutput->QueryMode (
 | 
						|
                       GraphicsOutput,
 | 
						|
                       ModeNumber,
 | 
						|
                       &SizeOfInfo,
 | 
						|
                       &Info
 | 
						|
                       );
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      if ((Info->HorizontalResolution == NewHorizontalResolution) &&
 | 
						|
          (Info->VerticalResolution == NewVerticalResolution)) {
 | 
						|
        if ((GraphicsOutput->Mode->Info->HorizontalResolution == NewHorizontalResolution) &&
 | 
						|
            (GraphicsOutput->Mode->Info->VerticalResolution == NewVerticalResolution)) {
 | 
						|
          //
 | 
						|
          // Current resolution is same with required resolution, check if text mode need be set
 | 
						|
          //
 | 
						|
          Status = SimpleTextOut->QueryMode (SimpleTextOut, SimpleTextOut->Mode->Mode, &CurrentColumn, &CurrentRow);
 | 
						|
          ASSERT_EFI_ERROR (Status);
 | 
						|
          if (CurrentColumn == NewColumns && CurrentRow == NewRows) {
 | 
						|
            //
 | 
						|
            // If current text mode is same with required text mode. Do nothing
 | 
						|
            //
 | 
						|
            FreePool (Info);
 | 
						|
            return EFI_SUCCESS;
 | 
						|
          } else {
 | 
						|
            //
 | 
						|
            // If current text mode is different from requried text mode.  Set new video mode
 | 
						|
            //
 | 
						|
            for (Index = 0; Index < MaxTextMode; Index++) {
 | 
						|
              Status = SimpleTextOut->QueryMode (SimpleTextOut, Index, &CurrentColumn, &CurrentRow);
 | 
						|
              if (!EFI_ERROR(Status)) {
 | 
						|
                if ((CurrentColumn == NewColumns) && (CurrentRow == NewRows)) {
 | 
						|
                  //
 | 
						|
                  // Required text mode is supported, set it.
 | 
						|
                  //
 | 
						|
                  Status = SimpleTextOut->SetMode (SimpleTextOut, Index);
 | 
						|
                  ASSERT_EFI_ERROR (Status);
 | 
						|
                  //
 | 
						|
                  // Update text mode PCD.
 | 
						|
                  //
 | 
						|
                  Status = PcdSet32S (PcdConOutColumn, mSetupTextModeColumn);
 | 
						|
                  ASSERT_EFI_ERROR (Status);
 | 
						|
                  Status = PcdSet32S (PcdConOutRow, mSetupTextModeRow);
 | 
						|
                  ASSERT_EFI_ERROR (Status);
 | 
						|
                  FreePool (Info);
 | 
						|
                  return EFI_SUCCESS;
 | 
						|
                }
 | 
						|
              }
 | 
						|
            }
 | 
						|
            if (Index == MaxTextMode) {
 | 
						|
              //
 | 
						|
              // If requried text mode is not supported, return error.
 | 
						|
              //
 | 
						|
              FreePool (Info);
 | 
						|
              return EFI_UNSUPPORTED;
 | 
						|
            }
 | 
						|
          }
 | 
						|
        } else {
 | 
						|
          //
 | 
						|
          // If current video resolution is not same with the new one, set new video resolution.
 | 
						|
          // In this case, the driver which produces simple text out need be restarted.
 | 
						|
          //
 | 
						|
          Status = GraphicsOutput->SetMode (GraphicsOutput, ModeNumber);
 | 
						|
          if (!EFI_ERROR (Status)) {
 | 
						|
            FreePool (Info);
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
      FreePool (Info);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (ModeNumber == MaxGopMode) {
 | 
						|
    //
 | 
						|
    // If the resolution is not supported, return error.
 | 
						|
    //
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Set PCD to Inform GraphicsConsole to change video resolution.
 | 
						|
  // Set PCD to Inform Consplitter to change text mode.
 | 
						|
  //
 | 
						|
  Status = PcdSet32S (PcdVideoHorizontalResolution, NewHorizontalResolution);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  Status = PcdSet32S (PcdVideoVerticalResolution, NewVerticalResolution);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  Status = PcdSet32S (PcdConOutColumn, NewColumns);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  Status = PcdSet32S (PcdConOutRow, NewRows);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Video mode is changed, so restart graphics console driver and higher level driver.
 | 
						|
  // Reconnect graphics console driver and higher level driver.
 | 
						|
  // Locate all the handles with GOP protocol and reconnect it.
 | 
						|
  //
 | 
						|
  Status = gBS->LocateHandleBuffer (
 | 
						|
                   ByProtocol,
 | 
						|
                   &gEfiSimpleTextOutProtocolGuid,
 | 
						|
                   NULL,
 | 
						|
                   &HandleCount,
 | 
						|
                   &HandleBuffer
 | 
						|
                   );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    for (Index = 0; Index < HandleCount; Index++) {
 | 
						|
      gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
 | 
						|
    }
 | 
						|
    for (Index = 0; Index < HandleCount; Index++) {
 | 
						|
      gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
 | 
						|
    }
 | 
						|
    if (HandleBuffer != NULL) {
 | 
						|
      FreePool (HandleBuffer);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Display the boot popup menu and allow user select boot item.
 | 
						|
 | 
						|
  @param   ImageHandle     The image handle.
 | 
						|
  @param   SystemTable     The system table.
 | 
						|
  
 | 
						|
  @retval  EFI_SUCCESS          Boot from selected boot option, and return success from boot option
 | 
						|
  @retval  EFI_NOT_FOUND        User select to enter setup or can not find boot option
 | 
						|
  
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
BootManagerMenuEntry (
 | 
						|
  IN EFI_HANDLE                            ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE                      *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_BOOT_MANAGER_LOAD_OPTION    *BootOption;
 | 
						|
  UINTN                           BootOptionCount;  
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  BOOT_MENU_POPUP_DATA            BootMenuData;
 | 
						|
  UINTN                           Index;
 | 
						|
  EFI_INPUT_KEY                   Key;
 | 
						|
  BOOLEAN                         ExitApplication;
 | 
						|
  UINTN                           SelectItem;
 | 
						|
  EFI_BOOT_LOGO_PROTOCOL          *BootLogo;
 | 
						|
  EFI_GRAPHICS_OUTPUT_PROTOCOL    *GraphicsOutput;
 | 
						|
  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut;
 | 
						|
  UINTN                           BootTextColumn;
 | 
						|
  UINTN                           BootTextRow;
 | 
						|
 | 
						|
  //
 | 
						|
  // Set Logo status invalid when boot manager menu is launched
 | 
						|
  //
 | 
						|
  BootLogo = NULL;
 | 
						|
  Status = gBS->LocateProtocol (&gEfiBootLogoProtocolGuid, NULL, (VOID **) &BootLogo);
 | 
						|
  if (!EFI_ERROR (Status) && (BootLogo != NULL)) {
 | 
						|
    Status = BootLogo->SetBootLogo (BootLogo, NULL, 0, 0, 0, 0);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);
 | 
						|
 | 
						|
  gStringPackHandle = HiiAddPackages (
 | 
						|
                         &gEfiCallerIdGuid,
 | 
						|
                         gImageHandle,
 | 
						|
                         BootManagerMenuAppStrings,
 | 
						|
                         NULL
 | 
						|
                         );
 | 
						|
  ASSERT (gStringPackHandle != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // Connect all prior to entering the platform setup menu.
 | 
						|
  //
 | 
						|
  EfiBootManagerConnectAll ();
 | 
						|
  EfiBootManagerRefreshAllBootOption ();
 | 
						|
 | 
						|
  BootOption = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);
 | 
						|
 | 
						|
  if (!mModeInitialized) {
 | 
						|
    //
 | 
						|
    // After the console is ready, get current video resolution 
 | 
						|
    // and text mode before launching setup at first time.
 | 
						|
    //
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    gST->ConsoleOutHandle,
 | 
						|
                    &gEfiGraphicsOutputProtocolGuid,
 | 
						|
                    (VOID**)&GraphicsOutput
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      GraphicsOutput = NULL;
 | 
						|
    }
 | 
						|
    
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                    gST->ConsoleOutHandle,
 | 
						|
                    &gEfiSimpleTextOutProtocolGuid,
 | 
						|
                    (VOID**)&SimpleTextOut
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      SimpleTextOut = NULL;
 | 
						|
    }  
 | 
						|
 | 
						|
    if (GraphicsOutput != NULL) {
 | 
						|
      //
 | 
						|
      // Get current video resolution and text mode.
 | 
						|
      //
 | 
						|
      mBootHorizontalResolution = GraphicsOutput->Mode->Info->HorizontalResolution;
 | 
						|
      mBootVerticalResolution   = GraphicsOutput->Mode->Info->VerticalResolution;
 | 
						|
    }
 | 
						|
 | 
						|
    if (SimpleTextOut != NULL) {
 | 
						|
      Status = SimpleTextOut->QueryMode (
 | 
						|
                                SimpleTextOut,
 | 
						|
                                SimpleTextOut->Mode->Mode,
 | 
						|
                                &BootTextColumn,
 | 
						|
                                &BootTextRow
 | 
						|
                                );
 | 
						|
      mBootTextModeColumn = (UINT32)BootTextColumn;
 | 
						|
      mBootTextModeRow    = (UINT32)BootTextRow;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Get user defined text mode for setup.
 | 
						|
    //  
 | 
						|
    mSetupHorizontalResolution = PcdGet32 (PcdSetupVideoHorizontalResolution);
 | 
						|
    mSetupVerticalResolution   = PcdGet32 (PcdSetupVideoVerticalResolution);      
 | 
						|
    mSetupTextModeColumn       = PcdGet32 (PcdSetupConOutColumn);
 | 
						|
    mSetupTextModeRow          = PcdGet32 (PcdSetupConOutRow);
 | 
						|
    mModeInitialized           = TRUE;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Set back to conventional setup resolution
 | 
						|
  //
 | 
						|
  BdsSetConsoleMode (TRUE);
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize Boot menu data
 | 
						|
  //
 | 
						|
  Status = InitializeBootMenuData (BootOption, BootOptionCount, &BootMenuData);
 | 
						|
  //
 | 
						|
  // According to boot menu data to draw boot popup menu
 | 
						|
  //
 | 
						|
  DrawBootPopupMenu (&BootMenuData);
 | 
						|
  
 | 
						|
  //
 | 
						|
  // check user input to determine want to re-draw or boot from user selected item
 | 
						|
  //
 | 
						|
  ExitApplication = FALSE;
 | 
						|
  while (!ExitApplication) {
 | 
						|
    gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);
 | 
						|
    Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
 | 
						|
    if (!EFI_ERROR (Status)) {
 | 
						|
      switch (Key.UnicodeChar) {
 | 
						|
      
 | 
						|
      case CHAR_NULL:        
 | 
						|
        switch (Key.ScanCode) {          
 | 
						|
          
 | 
						|
        case SCAN_UP:
 | 
						|
          SelectItem = BootMenuData.SelectItem == 0 ? BootMenuData.ItemCount - 1 : BootMenuData.SelectItem - 1;
 | 
						|
          BootMenuSelectItem (SelectItem, &BootMenuData); 
 | 
						|
          break;
 | 
						|
        
 | 
						|
        case SCAN_DOWN:
 | 
						|
          SelectItem = BootMenuData.SelectItem == BootMenuData.ItemCount - 1 ? 0 : BootMenuData.SelectItem + 1;
 | 
						|
          BootMenuSelectItem (SelectItem, &BootMenuData); 
 | 
						|
          break;
 | 
						|
 | 
						|
        case SCAN_ESC:
 | 
						|
          gST->ConOut->ClearScreen (gST->ConOut);
 | 
						|
          ExitApplication = TRUE;
 | 
						|
          //
 | 
						|
          // Set boot resolution for normal boot
 | 
						|
          //
 | 
						|
          BdsSetConsoleMode (FALSE);
 | 
						|
          break;
 | 
						|
          
 | 
						|
        default:
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        break;
 | 
						|
        
 | 
						|
      case CHAR_CARRIAGE_RETURN:
 | 
						|
        gST->ConOut->ClearScreen (gST->ConOut);
 | 
						|
        //
 | 
						|
        // Set boot resolution for normal boot
 | 
						|
        //
 | 
						|
        BdsSetConsoleMode (FALSE);
 | 
						|
        BootFromSelectOption (BootOption, BootOptionCount, BootMenuData.SelectItem);
 | 
						|
        //
 | 
						|
        // Back to boot manager menu again, set back to setup resolution
 | 
						|
        //
 | 
						|
        BdsSetConsoleMode (TRUE);
 | 
						|
        DrawBootPopupMenu (&BootMenuData);
 | 
						|
        break;
 | 
						|
        
 | 
						|
      default:
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  EfiBootManagerFreeLoadOptions (BootOption, BootOptionCount);
 | 
						|
  FreePool (BootMenuData.PtrTokens);
 | 
						|
 | 
						|
  HiiRemovePackages (gStringPackHandle);
 | 
						|
 | 
						|
  return Status;
 | 
						|
  
 | 
						|
}
 |